From a86de6545fe414e916df1bdd07fac185801db0f6 Mon Sep 17 00:00:00 2001 From: hectorzhao Date: Wed, 24 Jun 2026 18:40:21 +0800 Subject: [PATCH] feat: complete phase2 baseline cdr quality rbac --- IMPLEMENTATION_STATUS.md | 294 +- SOFTSWITCH_PLATFORM_DESIGN_V2.md | 118 +- apps/api/src/modules/app.module.ts | 2 + apps/api/src/modules/auth/auth.e2e.spec.ts | 9 +- apps/api/src/modules/auth/auth.repository.ts | 97 +- .../api/src/modules/auth/auth.service.spec.ts | 8 +- apps/api/src/modules/auth/auth.service.ts | 2 + apps/api/src/modules/auth/auth.types.ts | 1 + .../business-prefixes.controller.ts | 58 + .../business-prefixes.module.ts | 17 + .../business-prefixes.repository.ts | 217 + .../business-prefixes.service.ts | 124 + apps/api/src/modules/cdrs/cdrs.repository.ts | 287 +- .../api/src/modules/cdrs/cdrs.service.spec.ts | 53 +- apps/api/src/modules/cdrs/cdrs.service.ts | 19 + .../customer-gateways.e2e.spec.ts | 72 +- .../customer-gateways.repository.ts | 220 +- .../customer-gateways.service.ts | 149 +- .../vendor-gateways.e2e.spec.ts | 32 +- .../vendor-gateways.repository.ts | 48 +- .../vendor-gateways.service.ts | 53 + apps/web/src/App.jsx | 3552 +---------------- apps/web/src/api.js | 52 + apps/web/src/components/layout.jsx | 209 + apps/web/src/fixtures/devFixtures.js | 153 + apps/web/src/pages/ActiveCallsPage.jsx | 123 + apps/web/src/pages/BillingPage.jsx | 56 + apps/web/src/pages/BusinessPrefixesPage.jsx | 271 ++ apps/web/src/pages/CdrPage.jsx | 392 ++ apps/web/src/pages/CustomerGatewaysPage.jsx | 529 +++ apps/web/src/pages/CustomersPage.jsx | 243 ++ apps/web/src/pages/DashboardPage.jsx | 72 + apps/web/src/pages/MonitoringPage.jsx | 27 + apps/web/src/pages/NumberLibraryPage.jsx | 307 ++ apps/web/src/pages/OperationLogsPage.jsx | 67 + apps/web/src/pages/QualityPage.jsx | 418 ++ apps/web/src/pages/RechargeRecordsPage.jsx | 56 + apps/web/src/pages/RolesPage.jsx | 117 + apps/web/src/pages/RoutesPage.jsx | 60 + apps/web/src/pages/SettingsPage.jsx | 39 + apps/web/src/pages/SipOpsPage.jsx | 25 + apps/web/src/pages/UsersPage.jsx | 131 + apps/web/src/pages/VendorGatewaysPage.jsx | 399 ++ apps/web/src/pages/VendorLineGroupsPage.jsx | 200 + apps/web/src/pages/VendorsPage.jsx | 196 + apps/web/src/permissions.js | 38 + apps/web/src/styles.css | 5 + apps/web/src/utils/formatters.js | 295 ++ apps/worker-cdr/src/rating.spec.ts | 28 +- apps/worker-cdr/src/rating.ts | 36 +- .../src/publisher.spec.ts | 50 +- apps/worker-config-publisher/src/publisher.ts | 107 +- ...SINESS_PREFIX_GATEWAY_MIGRATION_RUNBOOK.md | 191 + docs/S42_PHASE2_FREEZE_REPORT.md | 107 + infra/server-a/s28/lisglosips_hotpath.lua | 315 +- infra/server-a/s28/opensips.cfg | 44 +- packages/database/src/schema-contract.spec.ts | 28 +- packages/redis/src/cdr-stream.spec.ts | 19 + packages/redis/src/cdr-stream.ts | 24 + .../migration.sql | 2 +- .../migration.sql | 167 + prisma/schema.prisma | 216 +- scripts/phase2-gateway-migration.mjs | 285 ++ 63 files changed, 7853 insertions(+), 3678 deletions(-) create mode 100644 apps/api/src/modules/business-prefixes/business-prefixes.controller.ts create mode 100644 apps/api/src/modules/business-prefixes/business-prefixes.module.ts create mode 100644 apps/api/src/modules/business-prefixes/business-prefixes.repository.ts create mode 100644 apps/api/src/modules/business-prefixes/business-prefixes.service.ts create mode 100644 apps/web/src/components/layout.jsx create mode 100644 apps/web/src/fixtures/devFixtures.js create mode 100644 apps/web/src/pages/ActiveCallsPage.jsx create mode 100644 apps/web/src/pages/BillingPage.jsx create mode 100644 apps/web/src/pages/BusinessPrefixesPage.jsx create mode 100644 apps/web/src/pages/CdrPage.jsx create mode 100644 apps/web/src/pages/CustomerGatewaysPage.jsx create mode 100644 apps/web/src/pages/CustomersPage.jsx create mode 100644 apps/web/src/pages/DashboardPage.jsx create mode 100644 apps/web/src/pages/MonitoringPage.jsx create mode 100644 apps/web/src/pages/NumberLibraryPage.jsx create mode 100644 apps/web/src/pages/OperationLogsPage.jsx create mode 100644 apps/web/src/pages/QualityPage.jsx create mode 100644 apps/web/src/pages/RechargeRecordsPage.jsx create mode 100644 apps/web/src/pages/RolesPage.jsx create mode 100644 apps/web/src/pages/RoutesPage.jsx create mode 100644 apps/web/src/pages/SettingsPage.jsx create mode 100644 apps/web/src/pages/SipOpsPage.jsx create mode 100644 apps/web/src/pages/UsersPage.jsx create mode 100644 apps/web/src/pages/VendorGatewaysPage.jsx create mode 100644 apps/web/src/pages/VendorLineGroupsPage.jsx create mode 100644 apps/web/src/pages/VendorsPage.jsx create mode 100644 apps/web/src/permissions.js create mode 100644 apps/web/src/utils/formatters.js create mode 100644 docs/PHASE2_BUSINESS_PREFIX_GATEWAY_MIGRATION_RUNBOOK.md create mode 100644 docs/S42_PHASE2_FREEZE_REPORT.md create mode 100644 prisma/migrations/20260624121000_business_prefix_gateway_rewrite/migration.sql create mode 100644 scripts/phase2-gateway-migration.mjs diff --git a/IMPLEMENTATION_STATUS.md b/IMPLEMENTATION_STATUS.md index b40d3e8..57075a7 100644 --- a/IMPLEMENTATION_STATUS.md +++ b/IMPLEMENTATION_STATUS.md @@ -4,10 +4,11 @@ ## 当前状态 -- 当前任务:需求修改/二期变更:号码库第 6、7 步本地实现并提交 Git -- 总体状态:S30 已完成;本地 KVM 开发环境 V2 闭环原冻结 release 为 `s28-v2-20260621220924`,当前 B release 仍为 `s33-active-calls-20260623094000`,已在该 release 上覆盖发布 s41 用户/角色删除小改;A `/etc/opensips/opensips.cfg` 已将 `fr_inv_timeout` 从 30 临时调为 95 并重启;T 已新增 `/opt/lisglosips-s40/lisglosips-s40-virtual-calls.py` 并启动 10 路虚拟呼叫场景;号码库第 1-7 步已完成本地代码基线,尚未发布到 B/A、尚未执行 MySQL migration、尚未导入真实 80 万号段;阿里云迁移前需按 S30 Runbook 重新演练 -- 最后更新:2026-06-24 11:41 +08:00 -- 当前阻塞:无。遗留风险为 Redis 恢复后 OpenSIPS 热路径可能需要重启 `opensips` 才恢复,已纳入 S30 Runbook;本次发现并补齐 B `config-publisher.env`,当前 `lisglosips@config-publisher` 已 active。 +- 当前任务:需求修改/二期变更:权限驱动导航和按钮 +- 本次变更摘要:已完成登录/刷新响应透出 `user.permissions`,前端新增统一 `can(permission)` 权限封装;菜单按页面权限裁剪,核心真实 API 页面操作按钮按 manage/play 权限裁剪,无权限页面提供明确提示,并避免无权限启动时批量请求导致 403。 +- 总体状态:S30 已完成;本地 KVM 开发环境 V2 闭环原冻结 release 为 `s28-v2-20260621220924`;B 已切换并冻结到 `s42-phase2-business-prefix-20260624140000` 作为二期业务前缀小样本联调基线,MySQL 已补齐号码库 migration `20260624095000_number_library` 与业务前缀 migration `20260624121000_business_prefix_gateway_rewrite`,Prisma status 为 up to date,config-publisher 当前 active 配置版本为 `1782286812696`,上一版本为 `1782286145681`,B preflight 直接执行通过;A 已加载业务前缀 Lua SHA `0b7ee595cdcad2f38a670dd8ff3553387820039e`,OpenSIPS 配置 SHA-256 为 `ae1544e9a39d2db114e6981babac042c2ab6d399d59ba597a52b85d597aa5aa5`,最终 `dlg_list` 已清空;T 已完成冻结验收实呼 `s28-1782288889943-ckv83lce@lisglosips-t`,B CDR 入库并计费成功;当前仍未导入真实 80 万手机号段;阿里云迁移前需按 S30 Runbook 重新演练 +- 最后更新:2026-06-24 17:50 +08:00 +- 当前阻塞:无阻塞。遗留问题:真实 80 万手机号段尚未导入;OpenSIPS dialog 在测试呼叫结束后可能残留,冻结前已通过重启清空,后续应单独分析 dialog 生命周期和 `dlg_end_dlg Operation failed` 根因;本次权限裁剪使用本地 mock API 完成只读账号浏览器冒烟,真实 B 服务器浏览器登录态逐页按钮、真实录音文件播放和 Nginx/X-Accel 链路仍需后续人工复测。 - 当前环境:A/B/T 为本地 KVM 开发服务器,通过 Tailscale 联调;开发完成后再迁移阿里云 - 私密访问资料:`.codex-private/SERVER_ACCESS.md`,只在实际连接时读取,禁止回显 @@ -89,6 +90,291 @@ ## 交接记录 +### 2026-06-24 17:50 - 需求修改/二期变更:权限驱动导航和按钮 + +- 状态:已完成 +- 操作服务器:本地 +- 完成内容: + - 后端登录/刷新响应新增 `user.permissions`,从用户启用角色的 `role_permissions` 汇总去重并排序后返回;保留原 `roles` 字段。 + - 前端新增 `apps/web/src/permissions.js`,提供页面权限表、`permissionSet`、`can`、`canAll`、`canAny`。 + - `App.jsx` 根据权限裁剪菜单;启动和手动刷新时只请求当前用户有权限的全局 API,避免无权限接口产生批量 403;无权限页面显示明确“无权限访问”提示。 + - 核心页面按钮按后端真实权限 key 裁剪:当前通话挂断、客户/供应商管理、充值、客户网关、业务前缀、落地网关、落地线路组、号码库导入、话单录音播放、质检录音播放/评分/抽检规则、用户管理、角色管理。 + - 修正角色权限页 dev fixture 的权限 key,使其与后端 `RequirePermissions` 使用的真实 key 保持一致。 +- 修改文件:`apps/api/src/modules/auth/auth.types.ts`、`apps/api/src/modules/auth/auth.repository.ts`、`apps/api/src/modules/auth/auth.service.ts`、`apps/api/src/modules/auth/auth.service.spec.ts`、`apps/api/src/modules/auth/auth.e2e.spec.ts`、`apps/web/src/permissions.js`、`apps/web/src/App.jsx`、`apps/web/src/fixtures/devFixtures.js`、`apps/web/src/pages/*.jsx`、`IMPLEMENTATION_STATUS.md` +- 安装软件及固定版本:未安装新软件。 +- 执行的关键命令:`corepack pnpm@10.33.0 typecheck`、`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 exec vitest run apps/api/src/modules/auth/auth.service.spec.ts apps/api/src/modules/auth/auth.e2e.spec.ts --hookTimeout=60000 --maxWorkers=1`、`corepack pnpm@10.33.0 exec vitest run --hookTimeout=60000 --maxWorkers=1`、`corepack pnpm@10.33.0 --filter @lisglosips/web dev -- --host 127.0.0.1` +- 验证结果: + - typecheck/lint/build 均通过。 + - Auth 定向测试 2 files / 6 tests 通过,确认 login/refresh 均返回 permissions。 + - 全量 Vitest 25 files / 88 tests 通过。 + - 使用本地临时 mock API 与 in-app Browser 验证只读账号仅含 `dashboard.view/customers.view`:侧边栏只显示“概览 Dashboard”“客户管理”;“供应商管理”“质检中心”等菜单不可见;客户页可查看客户列表,但无“新增客户”“编辑”“充值”“删除”按钮;无 Vite overlay,无应用 console error/warn。 +- 回滚方式:回滚上述后端 auth 文件、前端权限/页面文件和本状态文件即可;本次未修改 Prisma schema、未执行数据库迁移、未连服务器、未重启服务。 +- 未解决问题:当前按钮级裁剪覆盖真实 API 核心页面;费率与计费、SIP 运维、监控告警、系统设置仍属于待设计/演示页面,后续接真实 API 时需继续补权限 key 和按钮裁剪。真实 B 登录态逐页按钮仍需后续人工复测。 +- 下一任务:等待用户指定。 + +### 2026-06-24 17:30 - 需求修改/二期变更:前端拆分与信息架构整理 + +- 状态:已完成 +- 操作服务器:本地 +- 完成内容: + - 将 `App.jsx` 中的页面组件拆到 `apps/web/src/pages/`:`CdrPage.jsx`、`QualityPage.jsx`、`ActiveCallsPage.jsx`、`CustomersPage.jsx`、`CustomerGatewaysPage.jsx`、`VendorsPage.jsx`、`VendorGatewaysPage.jsx`、`VendorLineGroupsPage.jsx`、`BusinessPrefixesPage.jsx`、`NumberLibraryPage.jsx`、`RechargeRecordsPage.jsx`、`RoutesPage.jsx`、`BillingPage.jsx`、`SipOpsPage.jsx`、`MonitoringPage.jsx`、`SettingsPage.jsx`、`UsersPage.jsx`、`RolesPage.jsx`、`OperationLogsPage.jsx`。 + - 将页面共享布局组件拆到 `apps/web/src/components/layout.jsx`,包含 `Icon`、`PageTitle`、`Panel`、`ApiNotice`、`Drawer`、`Modal`、`SimpleTable`、`KeyValue` 等。 + - 将格式化和 API 归一化函数拆到 `apps/web/src/utils/formatters.js`,供 App 数据刷新和页面组件复用。 + - 将残留静态演示/mock 数据集中到 `apps/web/src/fixtures/devFixtures.js`,避免继续散落在 `App.jsx`;未把这些旧 fixture 接入生产 API 流程。 + - `App.jsx` 保留应用入口、登录、导航、全局 API 刷新与页面 props 分发,体积从约 237 KB 降到约 20 KB。 +- 修改文件:`apps/web/src/App.jsx`、`apps/web/src/components/layout.jsx`、`apps/web/src/utils/formatters.js`、`apps/web/src/fixtures/devFixtures.js`、`apps/web/src/pages/*.jsx`、`IMPLEMENTATION_STATUS.md` +- 安装软件及固定版本:未安装新软件。 +- 执行的关键命令:`corepack pnpm@10.33.0 lint`、`corepack pnpm@10.33.0 typecheck`、`corepack pnpm@10.33.0 build`、`corepack pnpm@10.33.0 exec vitest run --hookTimeout=60000 --maxWorkers=1`、`corepack pnpm@10.33.0 --filter @lisglosips/web dev -- --host 127.0.0.1` +- 验证结果: + - lint/typecheck/build 均通过。 + - 全量 Vitest 25 files / 88 tests 通过。 + - 使用本地临时 mock API 与 in-app Browser 验证 `http://127.0.0.1:5173/`:登录后可切换“当前通话”“话单中心”“质检中心”“客户管理”,对应页面 `h1` 正确、root 正常挂载、无 Vite overlay、无应用 console error/warn。 + - 拆分过程中发现并修复两个运行时拆分问题:`App.jsx` 主壳补回 `Badge` 导入;`emptySamplingRuleForm` 从 `CdrPage.jsx` 挪回 `QualityPage.jsx`。 +- 回滚方式:回滚上述前端拆分文件和本状态文件即可;本次未修改 Prisma schema、未执行数据库迁移、未连服务器、未重启服务。 +- 未解决问题:`fixtures/devFixtures.js` 仍承载费率、路由、监控、系统设置等未接真实 API 的旧演示数据;后续应按页面逐步接真实 API 或加 dev-only 开关彻底隔离。真实 B 服务器浏览器登录态逐页按钮仍需后续人工复测。 +- 下一任务:等待用户指定。 + +### 2026-06-24 17:10 - 需求修改/二期变更:质检中心接真实 API + +- 状态:已完成 +- 操作服务器:本地 +- 完成内容: + - 录音列表从静态数据切换为 `api.recordings()`,接入 `GET /recordings`,支持待质检/已质检/全部筛选、条数筛选、加载中、错误提示与空状态。 + - 录音详情接入 `GET /recordings/:id`,详情抽屉展示客户、被叫、业务、录音时长、抽样状态、命中规则与既有质检结果。 + - 录音播放接入 `GET /recordings/:id/play`,以 blob URL 驱动页面内 `