feat: add phone frequency controls and modularize codebase

This commit is contained in:
hectorzhao
2026-07-31 22:25:23 +08:00
parent 0af671b4ed
commit ca4f591a13
216 changed files with 41579 additions and 23694 deletions
@@ -1827,6 +1827,7 @@
## 运营看板与短信记录运营商筛选(2026-07-29)
- 运营看板“今日发送趋势”按 `Asia/Shanghai` 自然日固定返回 00:00 至 23:00 共 24 个小时桶,以折线图同时展示每小时业务短信提交总条数和最终状态为 `delivered` 的成功条数;无数据小时必须补零,不使用前端静态数据。
- `SmsMessageRecord.queuedAt` 为 PostgreSQL `timestamp without time zone` 且保存 UTC 时间,小时分桶必须先按 UTC 解释该字段,再转换为 `Asia/Shanghai` 提取小时;结果不得依赖 PostgreSQL 会话时区,不得把北京时间 09:00 的记录显示在 01:00。
- 运营看板“审核处理趋势”更名为“审核处理速度”。按企业认证、短信审核、模板、签名、引流信息五类展示北京时间当天已完成审核数量及平均处理时长;处理时长为同一审核事项本轮审核完成时间减本轮提交时间,无有效提交时间或出现负时长的记录不参与平均值。
- 签名通道发送质量明细的运营商概览固定按移动、联通、电信排列;未识别运营商如有数据排在三大运营商之后,数据库聚合返回顺序不得直接作为展示顺序。
- 运营端短信记录新增运营商筛选,选项为全部、移动、联通、电信、未识别。筛选必须由真实后端和 PostgreSQL 执行,并同时作用于分页总数、当前页和 CSV 导出;“未识别”包含空运营商及不属于三大运营商标准/兼容值的历史记录。
@@ -1836,3 +1837,36 @@
- 短信审核列表将“发送企业 / 企业应用”、“提交时间 / 审核来源”和“号码数量 / 状态”分别合并为三个上下分层的信息格,相关信息不得删除或改为仅在详情中展示。
- 短信内容列应设置为列表主要宽列,桌面端目标宽度不小于 440px;当可用宽度不足时由表格容器横向滚动,不得通过压缩内容列造成短信正文难以阅读。
- 号码数量继续使用真实审核任务关联短信记录数量,并保留打开真实号码分页列表的交互;本次仅调整展示布局,不改变审核查询、批量选择、通过或驳回流程。
## 号码发送频次风控(2026-07-30
- 系统内置并启用两条全局兜底规则:同一企业应用、同一手机号码在北京时间自然日内最多提交 10 条业务短信;在按北京时间时钟对齐的固定 5 分钟周期内最多提交 5 条业务短信。达到阈值的短信仍允许提交,下一条开始直接拒绝。
- 两条规则独立计数、独立命中;任一规则命中即直接拒绝该号码。首版处理动作固定为直接拒绝,不进入人工审核,也不提供放行后继续发送的自动动作。
- 隔离键固定为`applicationId + phoneNumber + ruleCode`。同一号码在不同企业应用下互不影响;同一企业的不同应用也分别计数。
- 计数单位为业务短信号码记录:一次任务向同一号码提交一条短信计 1 条,长短信分片和通道失败补发不重复计数。格式非法、黑名单命中或整个任务已被前置风控拒绝的号码不进入号码频次计数。
- 24 小时规则使用`Asia/Shanghai`自然日 00:00:00 至次日 00:00:005 分钟规则使用 00、05、10 等整 5 分钟对齐周期。进入下一周期时该周期计数自动从 0 开始,不采用命中时刻向后滚动的滑动窗口。
- 运营可分别为企业应用新增两条规则的个性化阈值;应用规则启用时覆盖同码全局兜底规则,未配置或停用时继续使用全局兜底。号码频控阈值只能是大于 0 的整数,周期、时区、对齐方式及直接拒绝动作首版不可修改。
- 命中时必须持久化企业、应用、号码、规则、阈值、触发值、周期起止、来源和触发时间。命中后的同周期提交继续拒绝,但不得重复生成相同的活跃触发记录。
- 风控规则页提供真实后端分页的号码频次触发记录,支持按当前应用范围、号码和拦截中/周期已到期/已人工解除状态查询。
- 运营可对单条触发记录执行“解除并清零”,必须填写原因并记录操作人、时间和审计日志。解除只清零该应用、号码、规则的当前计数,不删除历史记录,也不影响另一条频控规则;同周期再次超过阈值时生成新一代触发记录。
- 计数占用、首次命中记录及活跃命中关联必须由 PostgreSQL 原子完成,并能承受同一应用、同一号码的并发提交;不得使用进程内 Map、Redis 临时键、浏览器 localStorage、静态数据或 Mock 作为正式实现。
## 平台级号码频控白名单(2026-07-30)
- 运营端在风控规则页维护平台级号码频控白名单。处于启用状态的号码,在全平台所有企业及所有应用下均豁免`PHONE_FREQUENCY_24H``PHONE_FREQUENCY_5M`两类号码频控,包括企业应用个性化覆盖规则。
- 白名单不豁免号码格式校验、企业/应用黑名单、敏感词和内容审核、模板与签名审核、余额、应用日限额、路由、报备及其他风控规则;首版不提供企业级或应用级白名单。
- 白名单提供真实后端和数据库分页的增删改查,号码在平台内唯一,支持启用、停用、号码筛选和已删除历史查询。用途说明必填,备注选填;新增、修改、启停和删除均记录操作人、时间、修改前后内容及操作审计。
- 新增或恢复启用白名单时,清零该号码在所有企业应用及两类规则下的当前计数,并解除尚未到期的活跃命中;修改号码时同时清零旧号码和新号码;启停切换或删除时同样清零,确保号码退出白名单后从零开始重新计数。历史命中和白名单记录不得物理删除。
- 白名单有效期间的提交不写入号码频控状态、不增加计数、不产生号码频控命中。白名单写操作事务返回后发起的新请求必须遵循新状态;已经在写操作前进入频控事务的并发请求允许按其已读取的事务快照完成。
- 批量发送时白名单必须按号码集合分块查询,不得逐号码访问数据库;正式实现不得使用 Mock、静态数组或浏览器 localStorage。
## 客户端工作台与短信发送体验完善(2026-07-30)
- 客户端短信服务工作台的账户状态必须基于当前企业真实认证记录展示“已认证”或“未认证”,不得使用账户启停状态代替认证状态;企业主体展示真实企业名称。签名数量统计当前企业未删除、未禁用的真实签名。
- 模板状态和签名状态分别展示当前企业真实待审核数量并可进入对应菜单;“服务提醒”改为“批量任务”,展示当前企业来源为客户端且状态为`pending_review`的真实批量任务数,并可进入批量任务菜单。
- 客户端“今日发送趋势”复用真实 Dashboard 24 个北京时间小时桶,同时展示提交量和成功量;UTC 存储时间必须先按 UTC 解释再转换为`Asia/Shanghai`,不得依赖数据库或浏览器本地时区。
- 签名与引流信息页点击“重置”时,即使筛选条件已经为空,也必须回到第一页并重新请求真实后端,以获取最新签名审核、报备和引流信息状态。
- 运营端企业认证审核和短信模板审核首次打开及点击重置后,默认查询待审核状态。
- 短信发送页的字数和预计条数必须随编辑后的实际短信内容即时重新计算;单条短信不超过70个Unicode字符计1条,长短信按每67个字符计费,预计条数为单号码计费条数乘有效号码数。单价单位显示为“元/条”。
- 提交发送任务失败时使用页面中央弹窗展示真实后端错误;定时发送控件提供按北京时间计算的“今天”按钮,并以浅色背景标出北京时间当天。提交给后端的定时时间必须显式携带`+08:00`时区。
- 提交任务成功后弹窗展示真实任务编号和发送号码数。“继续发送短信”清空当前发送表单和导入内容;“查看任务进度”进入批量任务页面并按任务编号定位本次任务。