feat: optimize routing and operations views

This commit is contained in:
hectorzhao
2026-07-29 22:32:28 +08:00
parent 500f43f673
commit c0a4317a7e
21 changed files with 718 additions and 86 deletions
@@ -1815,3 +1815,24 @@
- 企业应用列表及分页接口只能在 Prisma 查询中引用 `SmsApplication` 模型真实存在的字段;接口入参或响应别名(例如 `passwordCipher`)不得作为数据库 `select``omit` 或筛选字段。
- 企业应用列表必须排除真实敏感字段 `secretHash`,不得通过列表接口返回应用接入密码;密码只允许在既有受控的专用参数接口中按权限读取。
- 企业应用黑名单等页面加载筛选项时应使用轻量企业应用选项接口,避免依赖包含连接状态和统计信息的完整企业应用列表。
## 短信号码路由识别性能约束(2026-07-29)
- 短信发送仍以启用的 `PhoneCarrierRule` 作为运营商路由判定依据,手机号段表继续用于省份识别;不得直接用 `PhoneSegment.carrier` 替代运营商业务规则。
- 启用的运营商正则规则应在 API 进程内编译并短时缓存,默认有效期 30 秒且允许通过 `PHONE_CARRIER_RULE_CACHE_TTL_MS` 调整;并发首次加载必须合并为一次数据库查询,规则新增或删除成功后必须立即使当前进程缓存失效。
- 缓存失效期间正在执行的旧规则查询不得覆盖新一代缓存;多实例部署时允许其他实例最多保留一个 TTL 周期的旧缓存,后续扩容到多 API 实例时应升级为跨实例版本通知。
- 省份识别必须把 7 位至 3 位候选前缀放入一次真实 PostgreSQL 查询,并按前缀从长到短选择首个有省份的结果;未知号码也不得逐级产生 5 次数据库往返。
- `SmsMessageRecord` 已持久化 `carrier` 后,补发和再次选路必须同时复用该记录的 `carrier/province`,包括已确认省份未知而保存为 `null` 的情况,不得重复加载运营商规则或号码段。
## 运营看板与短信记录运营商筛选(2026-07-29)
- 运营看板“今日发送趋势”按 `Asia/Shanghai` 自然日固定返回 00:00 至 23:00 共 24 个小时桶,以折线图同时展示每小时业务短信提交总条数和最终状态为 `delivered` 的成功条数;无数据小时必须补零,不使用前端静态数据。
- 运营看板“审核处理趋势”更名为“审核处理速度”。按企业认证、短信审核、模板、签名、引流信息五类展示北京时间当天已完成审核数量及平均处理时长;处理时长为同一审核事项本轮审核完成时间减本轮提交时间,无有效提交时间或出现负时长的记录不参与平均值。
- 签名通道发送质量明细的运营商概览固定按移动、联通、电信排列;未识别运营商如有数据排在三大运营商之后,数据库聚合返回顺序不得直接作为展示顺序。
- 运营端短信记录新增运营商筛选,选项为全部、移动、联通、电信、未识别。筛选必须由真实后端和 PostgreSQL 执行,并同时作用于分页总数、当前页和 CSV 导出;“未识别”包含空运营商及不属于三大运营商标准/兼容值的历史记录。
## 短信审核列表信息密度调整(2026-07-29)
- 短信审核列表将“发送企业 / 企业应用”、“提交时间 / 审核来源”和“号码数量 / 状态”分别合并为三个上下分层的信息格,相关信息不得删除或改为仅在详情中展示。
- 短信内容列应设置为列表主要宽列,桌面端目标宽度不小于 440px;当可用宽度不足时由表格容器横向滚动,不得通过压缩内容列造成短信正文难以阅读。
- 号码数量继续使用真实审核任务关联短信记录数量,并保留打开真实号码分页列表的交互;本次仅调整展示布局,不改变审核查询、批量选择、通过或驳回流程。
+32
View File
@@ -4017,3 +4017,35 @@ npm run verify:phase8
| TC-APP-LIST-001 | 运营端打开企业应用列表并请求分页接口 | Prisma 查询仅排除真实存在的 `secretHash`;接口 HTTP 200,不因 DTO 字段 `passwordCipher` 触发 Prisma 校验错误 |
| TC-APP-LIST-002 | 运营端打开企业应用黑名单并加载企业应用筛选项 | 黑名单及筛选项均从真实后端返回;企业应用加载不触发 HTTP 500,列表响应不包含 `secretHash` |
| TC-APP-LIST-003 | 校验企业应用列表 Prisma `omit` 字段 | 所有 `omit` 键都存在于当前生成客户端的 `SmsApplication` DMMF 模型,模型字段变更或错误别名会使回归测试失败 |
## 2026-07-29 短信号码路由识别性能回归用例
| 用例编号 | 场景 | 预期结果 |
| --- | --- | --- |
| TC-PHONE-ROUTE-001 | 并发使用多个号码识别运营商 | 只查询一次全部启用规则;正则只编译一次,并按优先级返回移动、联通或电信业务路由 |
| TC-PHONE-ROUTE-002 | 运营商规则新增或删除后再次识别 | 写入成功后当前进程缓存立即失效,下一次识别读取真实新规则;正在完成的旧查询不得覆盖新缓存 |
| TC-PHONE-ROUTE-003 | 号码同时命中 7 位、5 位和 3 位号段 | 单次 `prefix IN (...)` 查询全部候选,选择最长的 7 位号段省份 |
| TC-PHONE-ROUTE-004 | 号码不命中任何号段 | 只执行一次号段查询并返回省份未知,不产生 7 位至 3 位的 5 次往返 |
| TC-PHONE-ROUTE-005 | 已完成首次识别的短信进入失败补发 | 复用短信记录持久化的运营商和省份,不再查询规则和号段;既有通道组、报备及全国/省份路由规则不变 |
## 2026-07-29 运营看板与运营商筛选用例
| 用例编号 | 场景 | 预期结果 |
| --- | --- | --- |
| TC-DASHBOARD-HOURLY-001 | 北京时间当天仅部分小时存在短信记录 | 今日发送趋势固定展示 24 个小时;有数据小时显示真实提交总条数和最终成功条数,其余小时补 0 |
| TC-DASHBOARD-HOURLY-002 | 同一小时包含成功、失败、未知短信 | 提交总条数包含全部业务短信,成功条数只包含最终状态 `delivered` 的短信,两条折线均来自后端 PostgreSQL 聚合 |
| TC-DASHBOARD-AUDIT-SPEED-003 | 当天五类审核存在不同数量和处理时长 | “审核处理速度”按企业认证、短信审核、模板、签名、引流信息展示已处理数量及审核完成时间减提交时间的平均分钟数 |
| TC-DASHBOARD-AUDIT-SPEED-004 | 某类当天无审核或历史记录缺少可配对提交时间 | 该类数量显示 0;无有效样本时平均时长为空,不使用 0 时长伪造结果,负时长不参与统计 |
| TC-ANALYTICS-CARRIER-ORDER-014 | 后端以电信、移动、联通顺序返回运营商概览 | 弹窗始终按移动、联通、电信展示,未识别项如有数据排在三大运营商之后 |
| TC-SMS-RECORD-CARRIER-007 | 分别选择移动、联通、电信并查询和翻页 | 请求携带真实 `carrier` 条件;当前页、总数和 CSV 导出均只包含所选运营商及兼容历史值 |
| TC-SMS-RECORD-CARRIER-008 | 选择未识别 | 返回运营商为空或非三大运营商标准/兼容值的真实短信记录,不把移动、联通、电信混入结果 |
| TC-SMS-RECORD-CARRIER-009 | 点击重置 | 运营商恢复“全部”,日期等既有默认条件保持原规则,并从第一页重新请求后端 |
## 2026-07-29 短信审核列表布局回归用例
| 用例编号 | 场景 | 预期结果 |
| --- | --- | --- |
| TC-SMS-AUDIT-LAYOUT-001 | 桌面端打开短信审核列表 | 每行分别以一个格子展示发送企业/企业应用、提交时间/审核来源、号码数量/状态,六列结构对齐且信息完整 |
| TC-SMS-AUDIT-LAYOUT-002 | 查看包含较长短信正文的审核任务 | 短信内容列宽不小于 440px,正文获得明显更大的展示空间,不被其他元信息列无意义挤压 |
| TC-SMS-AUDIT-LAYOUT-003 | 点击合并格中的“查看列表”并操作待审核任务 | 真实号码分页弹窗正常打开;详情、勾选、批量通过和驳回入口不受布局调整影响 |
| TC-SMS-AUDIT-LAYOUT-004 | 在窄窗口打开短信审核列表 | 表格保持信息格内部上下层级,宽度不足时允许容器横向滚动,不发生文字重叠或操作按钮遮挡 |
+38
View File
@@ -2698,3 +2698,41 @@ git diff --check
- Node.js v24.14.0 下短信配置定向 1 suite / 62 tests、API 全量 26 suites / 367 tests 全部通过;Prisma format、validate、generate、API TypeScript 正式构建、前端 TypeScript/Vite 生产构建、Gateway `go test ./...``go vet ./...`、依赖安全门禁和 `git diff --check` 均通过。Jest 仅保留既有强制结束异步句柄提示,Vite 仅保留既有大 chunk 体积事实。
- 发布前使用预生产真实 Prisma Client 和 PostgreSQL 只读执行 `SmsApplication.findMany(... omit: { secretHash: true })` 成功返回 10 条企业应用,结果中 `secretHash` 泄漏计数为 0;未写入或修改预生产数据。
- 既有 `api/tsconfig.build.tsbuildinfo``tsconfig.tsbuildinfo``outputs/` 和空文件 `=` 继续作为构建或临时产物保留,不纳入提交。
## 2026-07-29 短信号码路由查询降载(本地未提交)
- 预生产只读诊断确认手机号段 516217 条、全部为 7 位且省份完整,唯一前缀索引单次执行约 0.058ms;运营商规则 30 条,单次全量读取约 0.044ms。最近 24 小时仅 41 条短信、峰值 2 条/分钟,因此当前不是线上瓶颈,但发送 Worker 并发 50 与默认 10 个 PostgreSQL 连接组合下存在批量放大风险。
- 使用预生产真实 PostgreSQL 和最近 100 个真实号码进行只读微基准:当前每条正常号码 2 次查询,顺序总耗时约 108ms;连接池预热并发 50 时号码识别部分 100 条约 86ms、单条 P50 约 40ms;缓存规则后 100 条约 20ms。基准只覆盖号码识别,不等同于完整短信发送耗时。
- 新增共享 `PhoneRoutingLookupService`:30 条启用规则编译后默认缓存 30 秒,并发冷加载合并;规则新增和删除成功后立即失效,失效前正在执行的旧加载不会覆盖新缓存。多实例场景仍由 TTL 限定其他实例最多 30 秒陈旧窗口。
- 省份识别由最多 5 次 `findUnique` 改为一次 7 位至 3 位候选前缀 `findMany`,在内存中选择最长命中;未知号码同样只查询一次。运营商路由仍由独立 `PhoneCarrierRule` 决定,不改变广电等业务归类口径。
- 首次路由继续把运营商和省份写入真实 `SmsMessageRecord`;后续补发检测到已持久化运营商时直接复用运营商及省份(含 `province=null`),不再重复读取规则和号段。
- Node.js v24.14.0 下新增路由服务及发送链定向 3 suites / 122 tests、API 全量 27 suites / 374 tests 全部通过;Prisma format、validate、generate、API TypeScript 正式构建、前端 TypeScript/Vite 生产构建、Gateway `go test ./...``go vet ./...`、依赖安全门禁和 `git diff --check` 均通过。首次直接使用系统默认 Node.js v14.17.4 执行安全门禁因运行时过旧失败,切换到项目验证用 Node.js v24.14.0 后通过;本机 5432 未监听,因此未虚报本地数据库实测。
- 本轮按用户要求只保留本地未提交修改,不提交、不推送、不部署;既有构建缓存、`outputs/`、空文件 `=``tsconfig.tsbuildinfo` 继续原样保留。
## 2026-07-29 运营看板与短信记录运营商筛选(本地未提交)
- 运营看板“今日发送趋势”已改为上海时区 24 个小时桶的真实折线图,同时展示业务短信提交总条数和最终成功条数;后端按 `SmsMessageRecord.queuedAt/status` 聚合并为无数据小时补零。
- “审核处理趋势”已更名为“审核处理速度”,按企业认证、短信审核、模板、签名、引流信息展示北京时间当天已完成数量及平均处理时长。企业认证、短信审核、引流信息使用各业务表提交/审核时间;签名和模板使用同一对象最近一次进入 `pending` 的审计记录与审核完成审计配对,负时长和无法配对的历史数据不参与平均值。
- 签名通道发送质量详情的运营商概览已显式固定为移动、联通、电信顺序,未识别项排在其后,不依赖数据库聚合返回顺序。
- 运营端短信记录新增全部、移动、联通、电信、未识别筛选;真实后端条件同时用于数据库分页、总数和 CSV 导出。兼容 `mobile/cmcc/移动/中国移动` 等历史值,空值及非三大运营商值归入未识别。
- Node.js v24.14.0 下 Operations 定向 1 suite / 26 tests、API 全量 27 suites / 375 tests 全部通过,API TypeScript 正式构建、前端 TypeScript 检查和 Vite 生产构建通过;全量 Jest 仅保留既有强制结束异步句柄提示,Vite 仅保留既有约 1.99MB 单 chunk 提示。首次通过系统 `npm` 启动定向测试未在 120 秒内输出,终止该次遗留测试进程后改用 Node.js v24 直接运行 Jest,测试正常完成,未将超时计为通过。
- 本机 PostgreSQL 5432 未监听。预发布 PostgreSQL 只读执行等价 SQL 成功:当天小时聚合返回 6 个有数据小时;审核速度 SQL 执行成功且当天无已完成审核样本;运营商真实存量分组为移动 575、联通 138、电信 121、未识别 87。验证过程未写数据库、未发送短信、未修改通道或企业数据。
- 本轮按用户要求保持未提交、未推送、未部署。工作区中另一会话既有的号码路由优化代码和文档继续保留,本节不将其归因于本需求。
## 2026-07-29 短信审核列表信息布局调整(本地未提交)
- 短信审核列表由原 8 列压缩为 6 列:发送企业与企业应用、提交时间与审核来源、号码数量与状态分别在同一单元格内上下分层展示;短信内容列设置为 440px 主要宽列。
- 号码数量仍打开真实后端分页号码列表,审核状态、详情、勾选、批量通过和驳回逻辑均未改变;本次没有新增 mock、静态数据或 localStorage 数据路径。
- 工作区中既有号码路由优化及另一会话的运营看板、短信记录运营商筛选修改全部保留,本节不将其归因于本需求。
- 恢复 `package-lock.json` 锁定依赖后,Node.js v24.14.0 下前端 TypeScript 检查和 Vite v8.0.16 生产构建通过,2442 个模块完成转换;仅保留既有约 1.99MB 单 chunk 提示。首次误用捆绑 pnpm 触发包管理器不一致保护并生成的两个临时 pnpm 文件已精确清理,没有纳入工作区修改。
- 本地 PostgreSQL、API 和前端预览启动成功,应用内浏览器及 Chrome 均无现成的本地运营登录会话,目标路由被真实鉴权跳转至图形验证码登录页。未绕过验证码,故未把登录页冒充短信审核列表的视觉和号码弹窗交互验收;本次启动的 PostgreSQL、API 和前端进程已清理,原先已运行的 Redis 保持不变。
- 本轮按用户要求只保留本地修改,不提交、不推送、不部署。
## 2026-07-29 号码路由、运营视图与短信审核布局汇总发布门禁
- 用户已明确授权将当前工作区代码提交、推送并发布到预生产。本次汇总范围为:号码路由规则缓存和单次最长前缀查询、运营看板逐小时发送趋势和审核处理速度、短信记录运营商真实后端筛选、签名质量运营商排序,以及短信审核组合单元格布局。
- 发布前 `main`、本地 `HEAD``origin/main` 均为 `500f43f673408900c3d658051d67cf0602f6005a`。工作区中不同会话形成的上述有效源码、测试和文档统一纳入本次授权范围;`api/tsconfig.build.tsbuildinfo``tsconfig.tsbuildinfo``outputs/` 和空文件 `=` 继续作为构建缓存或临时产物排除。
- 预生产只读基线确认 `.deployed-commit=500f43f673408900c3d658051d67cf0602f6005a`76 条 migration 已应用且与源码目录一致。API、Gateway、Nginx、PostgreSQL、Redis、MinIO 均 active`12026/17890/8090/3000/6379/5432/9000` 监听,内外健康接口和首页、运营端、客户端均 HTTP 200。
- 发布前 Redis Stream `gateway.submit.commands` 消费者 1、`pending=0``lag=0`,12 个通道 TPS 配置键存在;4 条 active 供应商通道均为 `connected 1/1`,最近 120 秒活跃下游客户连接为 0,API/Gateway 近 30 分钟 error 级 journal 均为 0。
- Node.js v24.14.0 下 API 全量 27 suites / 375 tests 全部通过;Prisma format、validate、generate、API TypeScript 正式构建、前端 TypeScript/Vite v8.0.16 生产构建、Gateway `go test ./...``go vet ./...`、依赖安全门禁和 `git diff --check` 均通过。Vite 仅保留既有约 1.99MB 单 chunk 提示,Jest 仅保留既有强制结束异步句柄提示。
- 本次没有新 migration;发布过程不得发送、重投或补发真实短信,不修改供应商通道账号、密码、启停状态、企业余额或客户连接。提交、推送、备份、部署和发布后验证结果在本节后续补记。