This commit is contained in:
haomingming
2026-05-20 18:21:39 +08:00
commit 815aa04fe8
564 changed files with 82601 additions and 0 deletions
@@ -0,0 +1,35 @@
# MVP试运行与发布回滚预案
## 1. 试运行前检查
- 数据库:`schema.sql``data.sql` 已执行完成。
- 配置:`DB/OSS/JWT/SCHEDULER` 环境变量已配置。
- 服务检查:后端健康检查 `/api/system/health` 返回 `UP`
- 前端构建:`npm run build` 成功。
## 2. 核心验证用例(上线阻断项)
- 创建项目 -> 创建会议 -> 会议级提交 -> 初审/复审/终审 -> 支付确认 全链路可用。
- 越权访问接口返回 `20001/20002`
- 幂等冲突返回 `10002`
- 未终审通过支付确认返回 `40003`
- 调度任务可执行并支持失败重试。
## 3. 灰度发布策略
- 第1阶段:仅内部租户(10%流量)观察 30 分钟。
- 第2阶段:扩大到 50% 租户观察 1 小时。
- 第3阶段:全量发布。
- 监控阈值
- 5xx 错误率连续 5 分钟 > 1% 触发回滚。
- 核心接口 P95 延迟连续 10 分钟劣化 > 30% 触发回滚评估。
- 审核/支付关键失败率 > 2% 触发 P1 告警。
## 4. 回滚策略
- 应用回滚:回滚到最近稳定版本(保留最近2版)。
- 数据回滚:通过备份+binlog 恢复,禁止手工改生产数据。
- 紧急开关
- 关闭调度:`SCHEDULER_ENABLED=false`
- 暂停支付确认入口(前端隐藏+后端网关拦截)
## 5. 试运行周期建议
- 试运行 3-5 天。
- 每日输出问题清单(功能、性能、权限、财务口径)。
- 试运行结束召开上线评审,确认是否转正式运行。
@@ -0,0 +1,103 @@
# 平台超级管理员与双域鉴权开发文档
## 1. 背景与目标
当前系统采用租户内 RBAC`用户 -> 角色 -> 权限`),但“系统超级管理员”职责属于平台级,不应绑定任何租户。
本迭代目标是在不破坏现有租户业务能力的前提下,建立“平台域 + 租户域”的双域鉴权模型。
## 2. 设计原则
- 平台域与租户域严格隔离,避免越权访问。
- 平台账号不落入任何租户,不依赖 `tenant_id`
- 租户业务接口只允许租户令牌访问。
- 平台管理接口只允许平台令牌访问。
- 兼容现有租户登录接口与权限模型,按迭代逐步替换。
## 3. 总体方案
### 3.1 身份域模型
- `TENANT`:租户业务身份(必须携带 `tenantId`)。
- `PLATFORM`:平台管理身份(不携带 `tenantId`)。
### 3.2 Token 约定
- 租户令牌 claims`uid``tid``scope=TENANT`
- 平台令牌 claims`uid``scope=PLATFORM`
### 3.3 权限注解扩展
`@RequirePermission` 新增 `domain` 字段:
- `domain=TENANT`(默认)
- `domain=PLATFORM`
### 3.4 平台 RBAC 数据模型
新增表:
- `platform_user`
- `platform_role`
- `platform_permission`
- `platform_user_role`
- `platform_role_permission`
## 4. 迭代拆分
### Iteration 1(已启动)
目标:落地双域鉴权底座,打通平台登录和租户管理平台化访问。
- [x] 增加鉴权域枚举:`AuthScope``PermissionDomain`
- [x] `AuthContext` 增加 `scope` 上下文
- [x] JWT 支持租户/平台两类 token
- [x] 新增平台登录接口:`POST /api/auth/platform-login`
- [x] 拦截器按 `scope + domain` 双维度鉴权
- [x] 租户管理接口切换到平台域权限:`platform.tenant.manage`
- [x] 增加平台 RBAC 初始化迁移:`V40__platform_admin_rbac.sql`
### Iteration 2(进行中)
目标:收敛租户默认兜底逻辑,修正平台日志归属。
- [x] 清理所有 `tenantId == null ? 1L : tenantId` 兜底逻辑
- [x] 平台操作审计增加 `scope` 字段(`TENANT/PLATFORM`)并完成查询分流
- [x] 平台接口统一路由前缀(新增 `/api/platform/tenants``/api/platform/audit-logs`
- [x] 为平台接口补齐权限码与元数据校验(`domain=PLATFORM`
### Iteration 3(待开发)
目标:前后端联动与灰度上线。
- [x] 前端增加登录入口切换(平台 / 租户)
- [x] 平台工作台页面(已接入租户管理、平台审计日志基础页面)
- [x] 平台菜单动态化(`platform_menu``platform_role_menu` + `/api/platform/menus/current`
- [x] 平台菜单管理页(新增/编辑/排序/菜单绑定角色)
- [x] 平台 IAM 页面(平台用户管理、平台角色管理、平台权限查看)
- [ ] 双域登录回归测试与权限压测
- [ ] 发布灰度与回滚预案
## 5. 初始账号与权限
初始化数据(`V40`):
- 平台角色:`PLATFORM_SUPER_ADMIN`
- 平台权限:`platform.tenant.manage``platform.user.manage``platform.audit.read``platform.menu.manage``platform.role.read``platform.role.manage``platform.permission.read`
- 平台管理员账号:
- 手机号:`13900000000`
- 密码:`123456`
> 上线前必须改密,并接入密码加密存储。
## 6. 风险与注意事项
- 已完成租户默认 `1L` 兜底清理;后续仍需补齐平台独立审计模型,避免平台操作与租户审计混用。
- `tenant.manage``platform.tenant.manage` 属于不同域权限码,前后端配置需同步。
- 建议后续引入统一 `domain` 中间件拦截,禁止跨域访问。
## 7. 验收标准(Iteration 1
- 平台管理员可通过 `/api/auth/platform-login` 获取 `scope=PLATFORM` token。
- 平台管理员可访问租户管理接口(`/api/tenants`)。
- 租户 token 访问平台域接口被拒绝。
- 平台 token 访问租户域接口被拒绝。
+165
View File
@@ -0,0 +1,165 @@
-- 新租户初始化清单 SQL(按模板租户复制)
-- 用法:
-- 1) 先创建租户拿到 @target_tenant_id
-- 2) 以 tenant_id=1 作为模板租户执行
-- 3) 该脚本尽量幂等(重复执行不会重复插入)
SET @template_tenant_id := 1;
SET @target_tenant_id := 2; -- TODO: 改成目标租户ID
-- =====================================================
-- A. 必须初始化(权限与菜单链路)
-- 表:role/menu/role_permission/role_menu
-- =====================================================
-- A1) 复制模板租户角色(role_code 维度)
SET @next_role_id := (SELECT IFNULL(MAX(id), 0) FROM role);
INSERT INTO role (id, tenant_id, role_code, role_name, status, is_deleted, created_by, updated_by)
SELECT
(@next_role_id := @next_role_id + 1) AS id,
@target_tenant_id AS tenant_id,
tr.role_code,
tr.role_name,
tr.status,
0 AS is_deleted,
0 AS created_by,
0 AS updated_by
FROM role tr
LEFT JOIN role er
ON er.tenant_id=@target_tenant_id
AND er.role_code=tr.role_code
AND er.is_deleted=0
WHERE tr.tenant_id=@template_tenant_id
AND tr.is_deleted=0
AND er.id IS NULL;
-- A2) 复制模板租户菜单
INSERT INTO menu (tenant_id, menu_code, menu_name, route_path, permission_code, sort_no, status, is_deleted, created_by, updated_by)
SELECT
@target_tenant_id AS tenant_id,
tm.menu_code,
tm.menu_name,
tm.route_path,
tm.permission_code,
tm.sort_no,
tm.status,
0 AS is_deleted,
0 AS created_by,
0 AS updated_by
FROM menu tm
LEFT JOIN menu em
ON em.tenant_id=@target_tenant_id
AND em.menu_code=tm.menu_code
AND em.is_deleted=0
WHERE tm.tenant_id=@template_tenant_id
AND tm.is_deleted=0
AND em.id IS NULL;
-- A3) 复制 role_permission(按 role_code 映射)
SET @next_role_perm_id := (SELECT IFNULL(MAX(id), 0) FROM role_permission);
INSERT INTO role_permission (id, tenant_id, role_id, permission_id)
SELECT
(@next_role_perm_id := @next_role_perm_id + 1) AS id,
@target_tenant_id AS tenant_id,
target_role.id AS role_id,
rp.permission_id
FROM role_permission rp
JOIN role template_role
ON template_role.tenant_id=rp.tenant_id
AND template_role.id=rp.role_id
AND template_role.is_deleted=0
JOIN role target_role
ON target_role.tenant_id=@target_tenant_id
AND target_role.role_code=template_role.role_code
AND target_role.is_deleted=0
LEFT JOIN role_permission existing_rp
ON existing_rp.tenant_id=@target_tenant_id
AND existing_rp.role_id=target_role.id
AND existing_rp.permission_id=rp.permission_id
WHERE rp.tenant_id=@template_tenant_id
AND existing_rp.id IS NULL;
-- A4) 复制 role_menu(按 role_code + menu_code 映射)
SET @next_role_menu_id := (SELECT IFNULL(MAX(id), 0) FROM role_menu);
INSERT INTO role_menu (id, tenant_id, role_id, menu_id)
SELECT
(@next_role_menu_id := @next_role_menu_id + 1) AS id,
@target_tenant_id AS tenant_id,
target_role.id AS role_id,
target_menu.id AS menu_id
FROM role_menu rm
JOIN role template_role
ON template_role.tenant_id=rm.tenant_id
AND template_role.id=rm.role_id
AND template_role.is_deleted=0
JOIN menu template_menu
ON template_menu.tenant_id=rm.tenant_id
AND template_menu.id=rm.menu_id
AND template_menu.is_deleted=0
JOIN role target_role
ON target_role.tenant_id=@target_tenant_id
AND target_role.role_code=template_role.role_code
AND target_role.is_deleted=0
JOIN menu target_menu
ON target_menu.tenant_id=@target_tenant_id
AND target_menu.menu_code=template_menu.menu_code
AND target_menu.is_deleted=0
LEFT JOIN role_menu existing_rm
ON existing_rm.tenant_id=@target_tenant_id
AND existing_rm.role_id=target_role.id
AND existing_rm.menu_id=target_menu.id
WHERE rm.tenant_id=@template_tenant_id
AND existing_rm.id IS NULL;
-- =====================================================
-- B. 可选初始化(建议)
-- =====================================================
-- B1) 模板类型开关(template_type_option
-- 注意:type_code 是主键。若库里是“全局唯一”,目标租户可能已存在同 code。
-- 这里按 (type_code, tenant_id) 语义做幂等,重复时仅更新展示字段。
INSERT INTO template_type_option (type_code, tenant_id, type_name, status, sort_no)
SELECT
tto.type_code,
@target_tenant_id AS tenant_id,
tto.type_name,
tto.status,
tto.sort_no
FROM template_type_option tto
WHERE tto.tenant_id=@template_tenant_id
ON DUPLICATE KEY UPDATE
type_name=VALUES(type_name),
status=VALUES(status),
sort_no=VALUES(sort_no),
updated_at=CURRENT_TIMESTAMP;
-- B2) 会议字段字典(meeting_field
INSERT INTO meeting_field (tenant_id, field_code, field_name, field_values, scope_type, project_id, sort_no, status, is_deleted, created_by, updated_by)
SELECT
@target_tenant_id AS tenant_id,
mf.field_code,
mf.field_name,
mf.field_values,
mf.scope_type,
NULL AS project_id,
mf.sort_no,
mf.status,
0 AS is_deleted,
0 AS created_by,
0 AS updated_by
FROM meeting_field mf
LEFT JOIN meeting_field emf
ON emf.tenant_id=@target_tenant_id
AND emf.field_code=mf.field_code
AND emf.is_deleted=0
WHERE mf.tenant_id=@template_tenant_id
AND mf.is_deleted=0
AND emf.id IS NULL;
-- =====================================================
-- C. 不建议初始化(运行数据表,仅业务发生时产生)
-- project/meeting/audit*/finance*/notification_task/export_task/operation_audit_log 等
-- =====================================================
+558
View File
@@ -0,0 +1,558 @@
# 会议核销SaaS 未开发项迭代清单(2026-03 最新)
## 一、现状结论
- 已完成:项目/会议/审核/财务主链路、审核流配置化、用户角色增强、数据权限、模板管理(上传/发布/停用/回滚/下载留痕/类型配置)、会议资料六大模块(`BASIC_INFO``WRITE_OFF_DOCS``ONSITE_PHOTO``LABOR_PROTOCOL``INVOICE_DETAIL``EXPERT_PROFILE`)、通知策略中心、可观测性告警中心(含抑制与恢复)。
- 主要缺口:通知外部通道真实SDK接入(厂商鉴权/模板审核/限流策略)与经营分析报表(多维钻取)。
- 本清单同步维护“状态看板 + 迭代任务”,用于区分已完成、进行中与未开始项。
### 1.1 状态看板(2026-03-10
| 模块/任务 | 当前状态 | 说明 |
|---|---|---|
| T1 租户管理(C1) | 已完成(待QA执行) | 后端接口、前端页面、启停与权限控制已接通;仍需按测试单执行并回填结果。 |
| T2 企业管理(C2) | 已完成(待QA执行) | 企业主数据与项目引用联动已落地;仍需回填回归结果。 |
| T3 菜单管理(C3) | 已完成(待QA执行) | 菜单维护、角色绑定、排序与动态加载已落地;仍需补最终回归记录。 |
| T4 代理授权(C4) | 已完成(待手工QA执行) | 生命周期、鉴权继承、自动化单测与回归模板已完成;手工用例执行结果待回填。 |
| T5 账号有效期(C5) | 功能已完成(QA未闭环) | 字段迁移、登录/会话拦截、前端展示已实现;缺少任务卡级进展与QA执行记录。 |
| P2-5 通知真实SDK接入 | 未开始 | 真实供应商鉴权、模板审核、失败原因标准化仍为主要缺口。 |
| 经营分析报表(多维钻取) | 未开始 | 当前仅有运营看板汇总,未形成报表钻取能力。 |
## 二、P0(必须补齐)
### P0-1 多租户真实化改造(替换硬编码 tenant_id=1
- 范围
- 租户上下文从登录态注入,业务查询/写入全部走动态 `tenant_id`
- 新增租户管理(平台管理员):创建、启停、查询。
- 后端 API
- `GET /api/tenants`
- `POST /api/tenants`
- `POST /api/tenants/{id}/enable`
- `POST /api/tenants/{id}/disable`
- DDL
- `tenant`(若未创建)
- 业务高频表补充复合索引(`tenant_id + 业务键`
- 验收
- 同一账号跨租户不可见数据。
- 导出/下载/搜索均走租户隔离。
- 人天
- 后端 8d + 前端 2d + 测试 3d = **13d**
### P0-2 审计日志中心(关键动作可检索/导出)
- 范围
- 登录、权限变更、审核动作、支付确认、导出下载等关键操作留痕。
- 支持条件检索与导出。
- 后端 API
- `GET /api/audit-logs`
- `GET /api/audit-logs/export`
- 前端
- 新增“审计日志”页面(筛选、列表、导出)。
- DDL
- `operation_audit_log`(落表 + 索引优化)
- 验收
- 高风险动作 100% 可追溯到人/时间/对象。
- 人天
- 后端 4d + 前端 2d + 测试 2d = **8d**
## 三、P1(高优先级业务补齐)
### P1-1 会议资料四大模块补齐
- 范围
- 新增模块:`ONSITE_PHOTO``LABOR_PROTOCOL``INVOICE_DETAIL``EXPERT_PROFILE`
- 当前进度:四个新增模块已全部完成(`ONSITE_PHOTO``LABOR_PROTOCOL``INVOICE_DETAIL``EXPERT_PROFILE`)。
- 模块级保存/提交/历史/审核查看对齐现有两模块能力。
- 后端 API
- 复用现有 `/materials/{moduleCode}/save|submit|history|current`
- 扩展模块校验规则与字段结构
- 前端
- 会议资料页补齐四个模块录入与历史对比
- 审核端“查看资料”补齐结构化展示
- DDL
- 复用 `meeting_material` / `meeting_material_history`
- 验收
- 六大资料模块都支持提交前必填校验与历史可追溯。
- 人天
- 后端 5d + 前端 6d + 测试 3d = **14d**
### P1-2 审核管理增强(转审 + SLA + 批量)
- 范围
- 转审、批量催办、SLA 超时升级。
- 当前进度:已完成后端 API、DDL 与前端审核页能力(转审弹窗、批量催办、SLA 统计与超时标识)。
- 后端 API
- `POST /api/audits/tasks/{id}/transfer`
- `POST /api/audits/tasks/batch-remind`
- `GET /api/audits/tasks/sla-stat`
- 前端
- 审核页增加转审弹窗、批量催办、SLA 标识
- DDL
- `audit_task``sla_deadline_at``timeout_level`
- `audit_transfer_log`
- 验收
- 超时 4h/12h/24h 升级可见,转审链路有日志。
- 人天
- 后端 4d + 前端 3d + 测试 2d = **9d**
### P1-3 财务对账与锁账
- 范围
- 对账工单、锁账/解锁、差异追踪。
- 当前进度:已完成后端 API、DDL、支付确认拦截(锁账)与前端财务页对账/锁账记录展示。
- 后端 API
- `POST /api/finance/reconciliation`
- `POST /api/finance/lock`
- `POST /api/finance/unlock`
- `GET /api/finance/reconciliation/list`
- 前端
- 财务页补“对账结果”“锁账状态”“解锁记录”
- DDL
- `finance_reconciliation`
- `finance_lock_log`
- 验收
- 锁账期间禁止关键财务字段写入。
- 人天
- 后端 5d + 前端 3d + 测试 2d = **10d**
### P1-4 模板管理剩余闭环
- 范围
- 归档状态、版本差异追踪、水印下载、流程模板联动(通知模板/结算模板)。
- 当前进度:已完成归档、版本差异追踪、水印下载、流程模板联动(会议推荐/审核通知/结算模板绑定)。
- 后端 API
- `POST /api/templates/{id}/archive`
- `GET /api/templates/{id}/versions/diff`
- `GET /api/templates/{id}/download-watermark`
- 前端
- 模板页补“归档”“版本差异查看”
- 验收
- 已归档模板不可再发布,差异可视化可用。
- 人天
- 后端 3d + 前端 2d + 测试 1d = **6d**
## 四、P2(治理与效率)
### P2-1 专家(参会人)管理全量能力
- 范围
- 主档案、多卡、去重合并、导入导出、会议快照。
- 当前进度:已完成主档案、多卡、去重合并、导入导出与专家管理页面;会议提交已接入专家快照写入链路。
- 后端 API
- `GET/POST /api/experts`
- `POST /api/experts/{id}/merge`
- `POST /api/experts/import`
- `GET /api/experts/export`
- 前端
- 专家管理页面 + 合并记录 + 银行卡管理
- DDL
- `expert``expert_bank_card``expert_merge_log``meeting_expert_snapshot`
- 验收
- 身份证唯一校验,历史会议读快照。
- 人天
- 后端 8d + 前端 6d + 测试 4d = **18d**
### P2-2 通知策略中心
- 范围
- 事件->渠道->对象可配置,模板变量统一管理。
- 当前进度:已完成策略中心 DDL、后端 `GET/POST/PUT /api/notification-policies` 与前端通知策略页面。
- 后端 API
- `GET/POST/PUT /api/notification-policies`
- 前端
- 通知策略页面
- DDL
- `notification_policy``notification_policy_event`
- 验收
- 策略即时生效,可追溯变更。
- 人天
- 后端 4d + 前端 2d + 测试 2d = **8d**
### P2-3 可观测性与告警
- 范围
- 指标、日志、告警阈值、任务失败告警闭环。
- 当前进度:已完成指标埋点(API、异步任务、导出)与告警规则中心(规则配置、手动评估、事件查询、抑制窗口、自动恢复)。
- 交付
- 指标埋点(API、异步任务、导出)
- 告警规则(5xx、任务积压、超时率)
- 验收
- 告警可触发、可恢复、可追踪。
- 人天
- 后端 3d + 运维 2d + 测试 1d = **6d**
### P2-4 补缺闭环(文档对照新增)
- 范围
- 已完成:会议撤回提交(状态机与审计联动)
- 已完成:会议字段管理(字典配置)
- 已完成:发票管理(抬头主数据)
- 已完成:通知执行引擎(任务化发送、重试、回执)
- 已完成:导出任务中心(任务状态、下载安全)
- 已完成:可观测性自动评估与连续恢复判定
- 后端 API(建议)
- `POST /api/meetings/{id}/withdraw`
- `GET/POST/PUT /api/meeting-fields`
- `GET/POST/PUT /api/invoice-profiles`
- `POST /api/notifications/dispatch`
- `POST /api/notifications/receipts`
- `GET /api/notifications/tasks`
- `GET/POST /api/export-tasks`
- `POST /api/export-tasks/{id}/refresh-token`
- `GET /api/export-tasks/{id}/download`
- `POST /api/observability/alert-rules/evaluate/auto`
- `GET /api/operations/dashboard`
- 验收
- 文档与实现接口 1:1 对齐,新增模块可独立上线并通过回归。
- 人天
- 后端 8d + 前端 6d + 测试 4d = **18d**
### P2-5 深化治理(进行中)
- 范围
- 已完成:通知回执标准化(消息ID、回执码、回执日志)
- 已完成:导出下载鉴权与过期策略(令牌刷新、过期控制、下载计数)
- 已完成:运营看板趋势与TOP(通知/导出/告警)
- 待完成:真实供应商SDK接入与失败原因规范化字典
- 后端 API(新增)
- `POST /api/notifications/receipts`
- `POST /api/notifications/receipts/webhook`
- `POST /api/export-tasks/{id}/refresh-token`
- `GET /api/export-tasks/{id}/download`
- `GET /api/operations/dashboard`
## 五、建议迭代顺序(接下来 4 个 Sprint)
- Sprint E2周):P0-1 多租户真实化 + P0-2 审计日志中心
- Sprint F2周):P1-1 资料四模块补齐 + P1-2 审核增强
- Sprint G2周):P1-3 财务对账锁账 + P1-4 模板闭环
- Sprint H2-3周):P2-1 专家管理 + P2-2 通知策略 + P2-3 可观测性
## 六、DoD(本清单统一完成标准)
- 接口文档:请求/响应/错误码补齐。
- 数据迁移:Flyway 脚本可重复执行,预发验证通过。
- 权限校验:菜单权限 + 动作权限 + 数据权限全链路生效。
- 测试:单测 + 关键集成测试 + 最少 1 条回归脚本。
- 留痕:关键动作有审计日志(操作者、对象、前后值、时间)。
## 七、“有概念、无模块化定义”缺口补全(本轮新增)
### C1 租户管理模块化补全(平台级)
- 缺口来源
- 业务文档已有“平台超级管理员可创建/启停单位主体”概念,但缺页面与流程化定义。
- 技术文档“接口实施状态”提到已实现租户能力,但接口清单未显式列出租户分组。
- 页面定义(前端)
- 新增“租户管理”菜单与页面:列表、创建、启用、停用。
- 字段:`tenantCode``tenantName``status``createdAt`
- 后端 API
- `GET /api/tenants`
- `POST /api/tenants`
- `POST /api/tenants/{id}/enable`
- `POST /api/tenants/{id}/disable`
- 数据与约束
- `tenant_code` 唯一,状态仅允许 `ENABLED/DISABLED`
- 启停租户需写入审计日志(动作码建议:`tenant.manage`)。
- 验收
- 平台管理员可在页面完成全流程;无 `tenant.manage` 权限用户不可操作。
- 两份主文档均包含模块、接口、权限点与页面入口说明。
- 人天
- 后端 1d + 前端 1d + 测试 1d = **3d**
### C2 企业管理模块化补全(系统设置)
- 缺口来源
- 业务文档有“企业管理”字段要求,但技术文档无对应模块定义/接口清单。
- 页面定义(前端)
- 列表、详情、创建、编辑、启停(如业务确认需要)。
- 字段:企业名称、网址、Logo、状态、更新时间。
- 后端 API(建议)
- `GET /api/enterprises`
- `POST /api/enterprises`
- `PUT /api/enterprises/{id}`
- `POST /api/enterprises/{id}/enable`
- `POST /api/enterprises/{id}/disable`
- 数据与约束
- 新增 `enterprise` 主表;名称唯一,Logo 必填校验。
- 项目模块“合作企业”字段改为引用企业主数据。
- 验收
- 项目创建/编辑可引用企业主数据,禁止手填脏数据。
- 企业启停后在项目选择器实时生效。
- 人天
- 后端 3d + 前端 2d + 测试 2d = **7d**
### C3 菜单管理模块化补全(权限可见性)
- 缺口来源
- 业务文档有“菜单管理”概念,技术文档未定义菜单数据模型和权限映射策略。
- 页面定义(前端)
- 菜单列表(树形)、角色菜单绑定、菜单启停与排序。
- 后端 API(建议)
- `GET /api/menus`
- `POST /api/menus`
- `PUT /api/menus/{id}`
- `POST /api/roles/{id}/menus`
- `GET /api/roles/{id}/menus`
- 数据与约束
- `menu``role_menu` 表;菜单与 `permissionCode` 建立映射。
- 前端“可见性”与后端“动作权限”双校验,禁止只做前端隐藏。
- 验收
- 不同角色登录看到不同菜单树,且后端越权访问仍被拦截。
- 人天
- 后端 4d + 前端 3d + 测试 2d = **9d**
### C4 代理授权模块化补全(用户生命周期)
- 缺口来源
- 业务文档明确要求代理授权生效/失效与留痕,技术文档仅概念提及。
- 页面定义(前端)
- 用户详情新增“代理授权”配置:代理人、生效时间、失效时间、原因。
- 代理记录列表:状态(待生效/生效中/已失效)。
- 后端 API(建议)
- `POST /api/users/{id}/delegations`
- `GET /api/users/{id}/delegations`
- `POST /api/delegations/{id}/disable`
- 数据与约束
- 新增 `user_delegation` 表,记录授权窗口、状态、创建人与失效原因。
- 审计记录动作码建议:`user.delegation.manage`
- 验收
- 到达失效时间自动失效;代理操作可完整追溯授权链。
- 人天
- 后端 3d + 前端 2d + 测试 2d = **7d**
### C5 账号有效期模块化补全(鉴权拦截)
- 缺口来源
- 业务文档要求账号有效期必填,技术文档缺字段规范与认证拦截定义。
- 页面定义(前端)
- 用户新增/编辑增加“有效期开始/结束”。
- 到期账号列表筛选与状态提示。
- 后端 API(建议)
- 复用 `POST/PUT /api/users` 增加 `validFrom``validTo` 字段。
- 登录接口增加有效期校验失败错误码返回(建议 `11004`)。
- 数据与约束
- `sys_user` 增加 `valid_from``valid_to`
- 登录、刷新令牌、关键写操作统一做有效期检查。
- 验收
- 过期账号无法登录且返回统一错误码;在有效期内恢复正常。
- 人天
- 后端 2d + 前端 1d + 测试 1d = **4d**
## 八、缺口补全里程碑(建议)
| 里程碑 | Sprint | 交付模块 | 目标结果 |
|---|---|---|---|
| M1 | Sprint I1周) | C1 租户管理、C5 账号有效期 | 平台可创建/启停租户;账号到期拦截口径统一 |
| M2 | Sprint J2周) | C2 企业管理、C4 代理授权 | 企业主数据可维护并被项目引用;代理授权可配置并自动失效 |
| M3 | Sprint K2周) | C3 菜单管理 | 角色菜单树可配置;菜单可见性与动作权限一体化生效 |
| M4 | Sprint L1周) | 文档与验收收口 | 两份主文档与实现清单 1:1 对齐,补齐回归与审计验证 |
### 里程碑验收门槛(统一)
- 接口与页面:每个模块至少 1 条端到端回归脚本通过。
- 权限链路:登录鉴权、动作权限、数据权限、有效期校验全部生效。
- 数据治理:Flyway 脚本可重复执行,升级/回滚路径可验证。
- 审计追溯:创建、启停、授权、失效、权限变更全量留痕可检索。
## 九、开发任务卡(可直接排期)
### 9.0 任务状态总览(2026-03-10
| 任务 | 状态 | 备注 |
|---|---|---|
| T1 | 已完成(待QA执行) | 功能已落地,测试结果待回填。 |
| T2 | 已完成(待QA执行) | 功能已落地,测试结果待回填。 |
| T3 | 已完成(待QA执行) | 功能已落地,测试结果待回填。 |
| T4 | 已完成(待手工QA执行) | 自动化基线已补,手工回归待执行。 |
| T5 | 功能已完成(QA未闭环) | 缺任务卡进展说明与回归结果。 |
### T1 租户管理(平台级)
- 目标
- 提供租户列表、创建、启用、停用能力,并纳入统一权限与审计链路。
- 后端任务
- 完成 `TenantController/TenantService` 接口稳定化与参数校验。
- 增加错误码映射:重复租户编码、状态非法、无权限。
- 审计日志接入:`tenant.manage`(创建/启停分动作码)。
- 前端任务
- 新增 `TenantPage`(列表、创建弹窗、启停按钮)。
- 在菜单中增加平台入口(仅具备权限用户可见)。
- 按钮权限:`tenant.manage`
- SQL/Flyway
- 确认 `tenant` 表字段完整:`tenant_code` 唯一、`status`、审计字段。
- 历史数据修复脚本:空 `tenant_code` 回填与唯一约束检查。
- 测试用例
- 正常创建租户、重复编码拦截、启停状态切换、无权限拦截。
- 停用租户下账号登录失败验证。
- DoD
- 页面可操作、接口稳定、日志可检索、回归通过。
- 当前实现进展(2026-03-10
- 已完成:租户列表/创建/启停接口与前端页面,菜单入口与 `tenant.manage` 按钮权限控制。
- 已完成:Flyway 兼容修复与 `tenant_code` 约束补齐。
- 待完成:按 `TASK-T1-QA-01` 执行手工回归并回填结果。
### T2 企业管理(系统设置)
- 目标
- 企业主数据独立维护,并可在项目模块引用,杜绝手填脏数据。
- 后端任务
- 新增企业 CRUD 与启停接口。
- 项目创建/编辑改为企业 ID 引用校验。
- 约束:企业停用后不可被新增项目引用。
- 前端任务
- 新增企业管理页(列表、详情、创建、编辑、启停)。
- 项目页面“合作企业”改为下拉选择企业主数据。
- SQL/Flyway
- 新增 `enterprise` 表及唯一索引(企业名称/编码按最终口径确定)。
- 项目表增加 `enterprise_id`(若当前为名称存储需迁移脚本)。
- 测试用例
- 企业启停与项目引用联动、重复名称校验、历史项目兼容查询。
- DoD
- 企业数据可维护,项目联动稳定,历史数据可回溯。
- 当前实现进展(2026-03-10
- 已完成:企业表迁移、企业 CRUD/启停接口、项目绑定企业引用校验。
- 已完成:企业管理页与项目“合作企业”下拉联动。
- 待完成:按 `TASK-T2-QA-01` 执行联调回归并回填结果。
### T3 菜单管理(角色菜单树)
- 目标
- 菜单可见性可配置,且与动作权限统一治理。
- 后端任务
- 提供菜单树查询、菜单维护、角色菜单绑定接口。
- 校验角色绑定数据合法性(菜单存在、状态可用、层级正确)。
- 前端任务
- 新增菜单管理页(树形、排序、启停、角色绑定)。
- 登录后按角色加载菜单树,未授权菜单不展示。
- SQL/Flyway
- 新增 `menu``role_menu` 表,建立索引(`role_id``menu_id`)。
- 菜单与 `permission_code` 字段对齐。
- 测试用例
- 角色切换后菜单变化、越权接口后端拦截、菜单停用即时生效。
- DoD
- 菜单可配置、权限一致、越权不可达。
- 当前实现进展(2026-03-10
- 已完成:菜单管理接口、角色菜单绑定、`permission_code` 对齐与批量排序保存。
- 已完成:前端菜单管理页、角色绑菜单、登录后按权限动态加载菜单。
- 待完成:按 `TASK-T3-QA-01` 执行越权与可见性回归并回填结果。
### T4 代理授权(用户生命周期)
- 目标
- 支持代理授权时间窗配置、自动失效、全链路审计。
- 后端任务
- 提供授权创建/查询/停用接口。
- 增加定时任务:过期授权自动置为失效。
- 鉴权侧接入代理上下文判定(仅在有效窗口内生效)。
- 前端任务
- 用户详情新增代理授权配置与记录列表。
- 显示授权状态(待生效/生效中/已失效/手动停用)。
- SQL/Flyway
- 新增 `user_delegation` 表及状态索引(`status`,`effective_to`)。
- 测试用例
- 授权生效、过期自动失效、手动停用、审计记录完整。
- DoD
- 授权链路可追溯、时间窗行为正确、异常场景可控。
- 当前实现进展(2026-03-10
- 已完成:`V37__user_delegation.sql`(表结构+索引+权限种子)、授权创建/查询/停用接口、过期自动失效定时任务、用户页代理授权弹窗(新增/列表/停用)。
- 已完成:鉴权链路代理上下文生效(代理人可在有效窗口内继承被代理人权限),并补充了后端自动化测试覆盖关键路径。
- 已完成:`TASK-T4-QA-01` 回归用例模板与自动化单测基线(代理权限继承、时间窗参数校验)。
- T4-QA 回归执行清单(可直接拷贝到测试单)
| 用例ID | 场景 | 前置条件 | 操作步骤 | 预期结果 | 执行结果 |
|---|---|---|---|---|---|
| T4-QA-001 | 授权立即生效 | 用户A、用户B均启用;A具有业务权限;B不具备该权限 | 在用户页为A配置代理人B,生效时间=当前前,失效时间=未来 | 授权记录状态为`ENABLED`;B可访问A对应权限接口 | 待执行 |
| T4-QA-002 | 授权待生效 | 用户A、用户B均启用 | 配置生效时间=未来,失效时间=更未来 | 记录状态为`PENDING`B暂不可继承A权限 | 待执行 |
| T4-QA-003 | 授权自动过期 | 已存在`ENABLED`授权记录,失效时间即将到达 | 等待定时任务窗口(或手工触发任务) | 状态自动切为`EXPIRED`B失去继承权限 | 待执行 |
| T4-QA-004 | 手动停用授权 | 已存在`ENABLED``PENDING`授权记录 | 在代理授权列表点击“停用”并填写原因 | 状态切为`DISABLED`;停用原因可查询 | 待执行 |
| T4-QA-005 | 禁止自代理 | 用户A存在 | 为A创建代理,代理人也选择A | 创建失败,返回业务错误“代理人不能与被代理人相同” | 待执行 |
| T4-QA-006 | 非法时间窗拦截 | 用户A、用户B存在 | 创建授权:`effectiveTo <= effectiveFrom` | 创建失败,返回业务错误“失效时间必须晚于生效时间” | 待执行 |
| T4-QA-007 | 权限闭环审计 | 已开启操作审计 | 完成一次“创建授权->停用授权”链路 | 审计日志存在对应 API 调用记录与状态变更痕迹 | 待执行 |
- T4-QA 自动化测试映射(当前已落地)
- `PermissionServiceDelegationTest`:覆盖代理权限继承与权限集合去重。
- `UserDelegationServiceValidationTest`:覆盖自代理拦截、时间窗非法拦截。
### T5 账号有效期(统一鉴权拦截)
- 目标
- 在登录、令牌刷新、关键写操作统一校验账号有效期。
- 后端任务
- `sys_user` 引入 `valid_from/valid_to` 并在认证链路校验。
- 新增错误码(建议 `11004`)与统一错误文案。
- 前端任务
- 用户创建/编辑增加有效期字段及校验。
- 到期状态在用户列表显式标记。
- SQL/Flyway
- `sys_user` 加字段与默认值迁移;历史账号回填策略。
- 测试用例
- 有效期前不可登录、有效期内可登录、过期后自动拦截。
- 关键写接口(非登录)也进行有效期拒绝校验。
- DoD
- 各链路校验一致,错误码统一,回归通过。
- 当前实现进展(2026-03-10
- 已完成:`V33__user_account_validity.sql` 字段迁移与历史回填(`valid_from/valid_to`)。
- 已完成:登录与鉴权拦截统一有效期校验,错误码 `11004` 接入前端自动登出处理。
- 已完成:用户页面有效期录入与“已过期”状态展示。
- 待完成:补齐 `TASK-T5-QA-01` 回归执行清单与结果回填。
## 十、Jira/禅道建单模板(可导入)
### 10.1 使用说明
- 建议先创建 5 个 Epic`EPIC-T1`~`EPIC-T5`(对应 T1~T5)。
- 下面“任务导入表”可直接复制为 CSV(逗号分隔)导入。
- `依赖` 列用于排期时设置“前置任务”,避免并行冲突。
### 10.2 Epic 列表
| Epic ID | Epic 名称 | 目标 |
|---|---|---|
| EPIC-T1 | 租户管理平台化 | 完成租户创建/启停/审计全链路 |
| EPIC-T2 | 企业管理主数据化 | 企业主数据维护并联动项目引用 |
| EPIC-T3 | 菜单权限一体化 | 菜单树与动作权限统一治理 |
| EPIC-T4 | 代理授权生命周期 | 授权配置、自动失效、可审计 |
| EPIC-T5 | 账号有效期统一校验 | 登录与关键写操作统一拦截 |
### 10.3 任务导入表(CSV列头)
`IssueKey,Summary,IssueType,EpicLink,OwnerRole,EstimateDays,Priority,DependsOn,AcceptanceCriteria`
`TASK-T1-BE-01,租户管理后端接口与校验,Task,EPIC-T1,后端,1,P0,,实现GET/POST tenants与启停接口并通过单测`
`TASK-T1-FE-01,租户管理前端页面与菜单入口,Task,EPIC-T1,前端,1,P0,TASK-T1-BE-01,完成列表创建启停页面并接通权限控制`
`TASK-T1-QA-01,租户管理联调与回归,Task,EPIC-T1,测试,1,P0,TASK-T1-BE-01;TASK-T1-FE-01,覆盖创建重复编码启停无权限用例`
`TASK-T2-DB-01,企业主数据表设计与迁移脚本,Task,EPIC-T2,后端,1,P1,,新增enterprise表并完成迁移验证`
`TASK-T2-BE-01,企业管理接口与项目引用校验,Task,EPIC-T2,后端,2,P1,TASK-T2-DB-01,实现企业CRUD启停并联动项目引用约束`
`TASK-T2-FE-01,企业管理页面与项目企业下拉,Task,EPIC-T2,前端,2,P1,TASK-T2-BE-01,企业页可维护且项目页改为企业下拉`
`TASK-T2-QA-01,企业管理联调回归,Task,EPIC-T2,测试,2,P1,TASK-T2-BE-01;TASK-T2-FE-01,覆盖启停联动重复名称历史数据兼容`
`TASK-T3-DB-01,菜单与角色菜单关系表迁移,Task,EPIC-T3,后端,1,P1,,新增menu与role_menu并建索引`
`TASK-T3-BE-01,菜单树与角色绑定后端接口,Task,EPIC-T3,后端,2,P1,TASK-T3-DB-01,实现菜单树查询维护与角色绑定接口`
`TASK-T3-FE-01,菜单管理页面与动态菜单加载,Task,EPIC-T3,前端,3,P1,TASK-T3-BE-01,角色切换后菜单可见性正确生效`
`TASK-T3-QA-01,菜单权限回归与越权验证,Task,EPIC-T3,测试,2,P1,TASK-T3-BE-01;TASK-T3-FE-01,覆盖前端可见性与后端越权拦截`
`TASK-T4-DB-01,代理授权表与状态索引迁移,Task,EPIC-T4,后端,1,P1,,新增user_delegation表并通过迁移验证`
`TASK-T4-BE-01,代理授权接口与自动失效任务,Task,EPIC-T4,后端,2,P1,TASK-T4-DB-01,实现授权创建查询停用与过期自动失效`
`TASK-T4-FE-01,用户详情代理授权UI,Task,EPIC-T4,前端,2,P1,TASK-T4-BE-01,支持授权配置与状态展示`
`TASK-T4-QA-01,代理授权链路回归,Task,EPIC-T4,测试,2,P1,TASK-T4-BE-01;TASK-T4-FE-01,覆盖生效过期停用与审计追溯`
`TASK-T5-DB-01,用户有效期字段迁移,Task,EPIC-T5,后端,1,P0,,sys_user新增valid_from与valid_to并回填策略`
`TASK-T5-BE-01,认证链路有效期统一校验,Task,EPIC-T5,后端,1,P0,TASK-T5-DB-01,登录刷新关键写操作统一拦截并返回11004`
`TASK-T5-FE-01,用户有效期表单与状态展示,Task,EPIC-T5,前端,1,P0,TASK-T5-BE-01,新增有效期字段与到期标识展示`
`TASK-T5-QA-01,有效期全链路回归,Task,EPIC-T5,测试,1,P0,TASK-T5-BE-01;TASK-T5-FE-01,覆盖生效前有效期内过期后三段场景`
### 10.4 建议前置依赖图
- `T1``T5` 可并行,建议优先完成(P0)。
- `T2` 依赖企业表迁移后再做项目联动。
- `T3` 建议在 `T1/T5` 稳定后推进,避免权限链路改动冲突。
- `T4` 可与 `T2/T3` 并行,但需与鉴权改造保持分支隔离。
+131
View File
@@ -0,0 +1,131 @@
# 会议核销SaaS 未开发项开发迭代清单 V2(2026-03)
## 一、V2目标与范围
- 目标:基于 `会议核销SaaS系统_技术开发文档.md` 新增 `6.10/7.7/7.8`,完成“字段级口径 + 接口闭环 + 权限矩阵”落地。
- 范围:仅覆盖当前确认缺口,不回滚已完成能力。
- 原则:先补齐 P0 闭环,再推进 P1 增强;所有新增能力必须带审计、权限、测试。
## 二、当前迭代状态(V2启动)
| 迭代项 | 优先级 | 状态 | 说明 |
|---|---|---|---|
| V2-P0-1 字段级数据字典落库(6.10) | P0 | 已完成(待预发验证) | 已新增 `V38__v2a_field_dictionary.sql`,包含加列/新表/索引。 |
| V2-P0-2 接口缺口补齐(7.7) | P0 | 已完成(后端待QA,前端待联调) | 角色、数据权限、审计日志、资料包、会议总结、通知策略补齐。 |
| V2-P0-3 权限矩阵落地(7.8) | P0 | 进行中 | 接口三元绑定(`permissionCode/dataScopeType/auditActionCode`)统一治理。 |
| V2-P1-1 发票结构化明细全链路 | P1 | 未开始 | 明细项、附件、汇总、校验规则与财务联动。 |
| V2-P1-2 审核SLA与批量能力增强 | P1 | 未开始 | 催办、批量催办、超时升级、审计回溯增强。 |
## 三、迭代批次规划(建议 3 个 Sprint)
- Sprint V2-A(本期,1.5~2周)
- V2-P0-1、V2-P0-2、V2-P0-3 全部完成可提测版本。
- Sprint V2-B(下期,2周)
- V2-P1-1 发票结构化明细 + 财务分类费用打通。
- Sprint V2-C(下下期,1~1.5周)
- V2-P1-2 审核SLA批量能力增强 + 回归收口。
## 四、第一轮迭代(已启动)
### 4.1 V2-P0-1 字段级数据字典落库(6.10)
- 范围
- `project``meeting``meeting_material``audit_task``audit_action_log``expert``expert_bank_card``template/template_version``finance_meeting_bill` 字段补齐。
- 新增建议表:`meeting_material_invoice_item``meeting_material_invoice_file``meeting_invoice_summary`
- 后端任务
- 完成实体/DO/DTO 字段扩展与向后兼容映射。
- 对关键写接口补充字段校验(金额单位“分”、比例范围、状态枚举合法性)。
- 当前进展:已完成 `meeting_material` 发票结构化链路、`audit_task` 新字段读写链路(SLA/超时/转审扩展)、`meeting/project` 新字段基础映射、`finance_meeting_bill` 读写接口、`expert/template` 新字段映射。
- DB/Flyway任务
- 已完成:`backend/src/main/resources/db/migration/V38__v2a_field_dictionary.sql`(幂等加列 + 新表 + 索引)。
- 待完成:预发执行验证、回填策略脚本(如需)与回滚演练记录。
- 验收标准
- 新增字段不破坏现有接口。
- 发票明细可结构化保存并查询。
- 审核、财务、专家关键字段可检索可追溯。
### 4.2 V2-P0-2 接口缺口补齐(7.7
- 范围
- 角色管理、数据权限管理、审计日志查询导出、会议资料包导出、会议总结生成下载、通知策略配置侧。
- 目标接口组(本期必须交付)
- 角色:`GET/POST/PUT /api/roles``POST /api/roles/{id}/enable|disable``POST /api/roles/{id}/permissions`
- 数据权限:`GET/POST/PUT /api/data-scope-policies``POST /api/data-scope-policies/{id}/copy|assign-roles|enable|disable`
- 审计日志:`GET /api/audit-logs``GET/POST /api/audit-logs/export-tasks`
- 会议资料:`POST /api/meetings/{id}/materials/{module}/submit|resubmit``POST /api/meetings/{id}/materials/export`
- 会议总结:`POST /api/meetings/{id}/summary/generate``GET /api/meetings/{id}/summary/download`
- 通知策略配置:`GET/POST/PUT /api/notification-policies``POST /api/notification-policies/{id}/events|enable|disable`
- 验收标准
- 接口文档、权限码、错误码、审计动作码齐全。
- 前端按钮权限与后端接口权限一致。
- 导出/下载能力遵循数据权限范围。
- 当前进展
- 已补齐通知策略配置侧接口:`POST /api/notification-policies/{id}/events|enable|disable`
- 已补齐会议字段配置启停接口:`POST /api/meeting-fields/{id}/enable|disable`
- 已补齐发票抬头配置启停接口与别名路由:`POST /api/invoice-profiles/{id}/enable|disable``/api/invoice-heads`
- 前端系统设置页已接入上述能力:数据权限(复制/启停)、通知策略(绑定事件/启停)、会议字段(启停)、发票抬头(启停)。
- 审计日志页已接入导出任务能力:`GET/POST /api/audit-logs/export-tasks`
- 会议页已接入资料包导出与会议总结入口:资料包导出、总结生成、总结令牌刷新、总结下载。
### 4.3 V2-P0-3 权限矩阵落地(7.8
- 范围
- 全量接口补三元绑定:`permissionCode``dataScopeType``auditActionCode`
- 接口发布前增加权限元数据检查门禁。
- 后端任务
- 新增权限元数据校验组件(启动校验 + 单测校验)。
- 统一数据范围枚举:`TENANT/PROJECT/MEETING/MEETING_MODULE/GLOBAL_READONLY`
- 当前进展
- 已完成注解扩展:`@RequirePermission` 支持 `dataScopeType/auditActionCode` 元数据。
- 已新增启动校验门禁组件:`PermissionMetadataGuard`(支持 `writeoff.permission-metadata.strict` 严格模式)。
- 已在核心接口组补齐三元标注:通知策略、会议字段、发票抬头、数据权限、审计日志、会议资料包/会议总结接口。
- 已批量补齐存量控制器三元标注:角色/菜单/用户/租户/企业、模板、专家、审核流/审核任务、财务、导出任务、通知分发、可观测、文件下载等。
- 前端任务
- 按钮权限码与接口权限码同源配置。
- 无权限状态统一“置灰+原因提示”。
- 当前进展
- 已新增前端权限常量单源:`frontend/src/constants/permissions.ts`
- 已完成页面侧 `hasPermission("...")``hasPermission(PERMS.xxx)` 的统一替换(系统设置、审核、财务、模板、专家、导出、通知、可观测等模块)。
- 已补齐主要操作按钮的“无权限置灰 + 原因提示(title)”展示规范。
- 验收标准
- 缺权限元数据的接口不可发布。
- 越权请求稳定返回统一错误码(`20001/20002`)。
## 五、任务卡(可直接建单)
| 任务ID | 模块 | 任务 | 负责人 | 预计人天 | 状态 | 依赖 |
|---|---|---|---|---:|---|---|
| V2A-DB-01 | 字段落库 | 6.10 加列与新表迁移脚本 | 后端 | 2 | 已完成(待预发验证) | - |
| V2A-BE-01 | 字段落库 | 实体/接口字段扩展与校验 | 后端 | 3 | 已完成(待QA | V2A-DB-01 |
| V2A-QA-01 | 字段落库 | 兼容性回归(存量接口) | 测试 | 1.5 | 未开始 | V2A-BE-01 |
| V2A-BE-02 | 接口补齐 | 角色+数据权限+审计日志接口组 | 后端 | 3 | 已完成(待QA | - |
| V2A-FE-01 | 接口补齐 | 系统设置页面能力补齐 | 前端 | 3 | 已完成(待QA | V2A-BE-02 |
| V2A-BE-03 | 接口补齐 | 会议资料包/会议总结接口组 | 后端 | 2 | 已完成(待QA | - |
| V2A-FE-02 | 接口补齐 | 资料包导出与会议总结入口 | 前端 | 2 | 已完成(待QA | V2A-BE-03 |
| V2A-BE-04 | 权限矩阵 | 三元绑定校验门禁 | 后端 | 1.5 | 已完成(待QA | - |
| V2A-FE-03 | 权限矩阵 | 按钮权限同源配置改造 | 前端 | 1.5 | 已完成(待QA | V2A-BE-04 |
| V2A-QA-02 | 全链路 | 权限+审计+导出下载回归 | 测试 | 2 | 未开始 | V2A-FE-01;V2A-FE-02;V2A-FE-03 |
## 六、风险与阻塞位
- 风险1:历史数据缺失(如旧会议无结构化发票明细)导致回填不完整。
- 处理:回填脚本允许空值,前端按“旧数据兼容展示”策略处理。
- 风险2:权限码重构影响存量按钮显隐。
- 处理:灰度发布,先日志观测再全量切换。
- 风险3:导出/下载接口并发高峰导致任务堆积。
- 处理:复用导出任务中心,增加限流与重试监控。
## 七、统一DoDV2
- 文档:OpenAPI 与技术文档同步更新,接口示例可直接联调。
- 数据:Flyway 迁移可重复执行,预发演练通过。
- 安全:权限、数据范围、审计动作三链路全部生效。
- 质量:单测覆盖新增校验与状态流转;至少 1 条端到端回归通过。
- 发布:灰度策略、回滚策略、监控告警规则完成配置。
## 八、下一步(默认执行顺序)
- 第1步:先完成 `V2A-DB-01` + `V2A-BE-01`,锁定字段口径。
- 第2步:并行推进 `V2A-BE-02``V2A-BE-03``V2A-BE-04`
- 第3步:前端接入 `V2A-FE-01/02/03`,随后执行 `V2A-QA-01/02`
- 第4步:输出 Sprint V2-A 版本说明与上线检查单。
@@ -0,0 +1,420 @@
# 租户域模板管理模块优化方案清单
## 1. 适用范围
- 本清单仅针对**租户域模板管理模块**。
- 不包含平台域统一模板治理、跨租户模板审计、平台级模板库等能力。
- 目标是把租户域模板管理从“能上传、能发布”升级为“可治理、可检索、可追踪、可联动”。
## 2. 优化目标
- 提升模板管理页面的信息架构与使用效率。
- 提升模板生命周期治理能力,包括草稿、发布、停用、归档、回滚。
- 提升模板与会议、审核、结算等业务场景的联动准确性。
- 提升模板下载留痕、权限控制、时效控制和风险控制能力。
- 提升后端接口一致性、可扩展性和并发安全。
- 提升数据库模型的多租户适配性与查询性能。
## 3. 现状问题归纳
### 3.1 前端页面布局
- 一个页面同时承载模板类型开关、模板列表、流程绑定、版本回滚、版本差异、上传建版,信息密度过高。
- 缺少统一筛选区,用户只能翻表找模板。
- 创建模板时需要手填 `projectId``meetingId``objectKey`,使用门槛高。
- 模板列表缺少关键治理字段展示,例如生效时间、水印开关、下载限制、最近更新时间、维护人。
### 3.2 显示内容
- 当前列表更偏“技术字段展示”,不够业务化。
- 版本信息展示不完整,无法快速判断“当前发布版”和“历史草稿版”差异。
- 下载日志页展示维度少,问题排查效率低。
### 3.3 用户操作
- 缺少按业务对象选择模板适用范围的交互。
- 流程绑定操作没有足够的场景提示和影响提示。
- 水印下载、普通下载、发布、回滚等高风险操作缺少确认与说明。
- 缺少预览、复制模板、批量筛选、快速查看版本历史等高频能力。
### 3.4 后端逻辑
- 模板流程绑定与业务消费链路没有完全闭环。
- 模板创建和新增版本存在并发安全风险。
- 有效期、水印、下载限流等字段虽然存在,但未完整落地到业务逻辑。
- 下载日志缺少标准分页、标准筛选和关联名称字段返回。
### 3.5 数据库设计
- 模板类型配置表的主键设计与多租户语义不完全一致。
- 日志和版本表索引偏弱,后续数据量上来后容易退化。
- 模板主表、版本表、流程绑定表的约束还不够完整。
## 4. 租户域模板管理优化方案
## 4.1 前端页面布局优化
### 4.1.1 页面结构重构
- 将当前单页改为“三级结构”:
- 一级:模板管理首页
- 二级:模板详情页
- 二级:模板下载日志页
- 模板管理首页仅保留:
- 查询筛选区
- 模板列表区
- 快捷操作区
- 版本历史、版本差异、流程绑定改为详情抽屉或详情页的子区块,不与主列表混排。
### 4.1.2 首页布局建议
- 顶部操作栏:
- 新建模板
- 刷新
- 导出模板清单
- 查询筛选区:
- 模板名称
- 模板类型
- 模板状态
- 适用范围
- 业务场景
- 是否启用水印
- 生效状态
- 最近更新时间范围
- 列表区:
- 默认按“最近更新时间倒序”
- 支持分页
- 支持空态提示
### 4.1.3 详情页布局建议
- 基本信息卡片:
- 模板名称、类型、状态、业务场景、适用范围、生效时间、水印、下载限制
- 当前版本卡片:
- 当前版本号、对象文件、变更说明、创建时间、创建人
- 版本历史区:
- 版本号、状态、是否生效、变更说明、回滚原因、创建时间
- 流程联动区:
- 当前已绑定场景
- 是否允许绑定
- 绑定影响说明
- 下载记录区:
- 最近下载记录摘要
## 4.2 显示内容优化
### 4.2.1 模板列表字段建议
- 模板名称
- 模板类型
- 业务场景
- 适用范围
- 关联项目/会议名称
- 当前版本号
- 当前状态
- 生效开始时间
- 生效结束时间
- 水印开关
- 下载限流
- 最近更新时间
- 更新人
### 4.2.2 版本列表字段建议
- 版本号
- 版本状态
- 是否当前生效
- 文件名
- 对象存储路径
- 变更说明
- 回滚原因
- 创建人
- 创建时间
### 4.2.3 下载日志字段建议
- 模板名称
- 模板版本号
- 下载人姓名
- 下载人账号/手机号
- 下载时间
- IP
- User-Agent
- 下载方式
- 普通下载
- 水印下载
- 水印文案
- 关联项目/会议
## 4.3 用户操作优化
### 4.3.1 新建模板
- 取消手填 `objectKey` 为主的方式,改为:
- 选择模板类型
- 选择业务场景
- 选择适用范围
- 若为项目级,选择项目
- 若为会议级,选择会议
- 上传文件
- 填写变更说明
- 配置生效时间、水印、下载限流
- 上传成功后由系统自动回填对象存储路径。
### 4.3.2 模板列表操作
- 为每条模板提供分层操作:
- 查看详情
- 新增版本
- 发布
- 停用
- 归档
- 下载
- 水印下载
- 查看版本差异
- 查看下载记录
- 复制模板
- 对危险操作增加二次确认:
- 发布
- 回滚
- 停用
- 归档
### 4.3.3 版本管理
- 新增版本时默认继承模板基础配置,不重复填写范围与场景。
- 增加“与当前发布版对比”快捷入口。
- 回滚时必须填写回滚原因。
- 已归档模板不可新增版本。
### 4.3.4 流程联动
- 流程绑定独立为一个区块或独立弹窗。
- 绑定时只允许选择:
- 已发布
- 未停用
- 场景一致
- 当前生效
的模板。
- 显示绑定影响提示,例如:
- 绑定后将用于会议推荐
- 绑定后将用于审核通知
- 绑定后将用于结算材料
### 4.3.5 下载日志
- 支持按以下条件筛选:
- 模板名称
- 模板 ID
- 下载人
- 版本号
- 下载时间范围
- IP
- 下载方式
- 支持跳转查看“该模板全部下载记录”。
## 4.4 后端逻辑优化
### 4.4.1 查询接口
- 模板列表接口增加标准分页与筛选参数:
- `templateName`
- `templateType`
- `status`
- `scopeType`
- `bizScene`
- `watermarkEnabled`
- `effectiveStatus`
- `pageNo`
- `pageSize`
- 下载日志接口增加标准分页与筛选参数,并返回关联名称字段,不再依赖前端二次查用户和模板列表补名。
### 4.4.2 模板生命周期校验
- 发布校验:
- 当前版本文件存在
- 模板类型已启用
- 若配置有效期,开始时间不能晚于结束时间
- 停用校验:
- 若被流程联动使用,需提示影响
- 归档校验:
- 已归档模板不可再发布、不可新增版本
- 回滚校验:
- 只能回滚到本模板已有版本
- 回滚原因必填
### 4.4.3 流程联动闭环
- 流程绑定时增加强校验:
- `sceneCode` 必须与模板 `bizScene` 一致
- 模板必须为 `PUBLISHED`
- 模板必须在生效期内
- 业务消费链路按联动关系读模板,不允许页面配置和实际业务读取脱节。
- 会议推荐、审核通知、结算模板获取逻辑统一经过模板服务,不各自散落实现。
### 4.4.4 下载能力治理
- 普通下载与水印下载分开记录下载类型。
- 若模板启用下载限流,则下载前校验单位时间内下载次数。
- 若模板配置有效期,则过期后禁止下载。
- 若模板启用水印下载,则需要真正生成带水印文件或带水印预签名资源,而不是只回传文案。
### 4.4.5 并发与事务安全
- 创建模板后获取主键不要再用 `MAX(id)`,改为标准主键回填。
- 新增版本号不要再用 `MAX(version_no)+1` 裸算,改为:
- 悲观锁
- 或唯一约束重试
- 或独立版本号分配策略
- 发布、回滚、建版操作保持事务一致性,避免主表状态和版本表状态不一致。
### 4.4.6 可测试性
- 增加自动化测试覆盖:
- 创建模板
- 并发新增版本
- 发布/停用/归档/回滚
- 流程绑定场景校验
- 有效期校验
- 下载限流
- 日志分页与筛选
## 4.5 数据库设计优化
### 4.5.1 `template`
- 建议补充或强化约束:
- `tenant_id + template_name + scope_type + scope_id + biz_scene` 可考虑唯一性策略
- 状态字段增加明确枚举约束
- 建议补充索引:
- `(tenant_id, status, updated_at)`
- `(tenant_id, template_type, status)`
- `(tenant_id, biz_scene, status)`
- `(tenant_id, scope_type, scope_id)`
### 4.5.2 `template_version`
- 建议保留唯一约束:
- `(tenant_id, template_id, version_no)`
- 建议新增索引:
- `(tenant_id, template_id, is_effective)`
- `(tenant_id, template_id, created_at)`
- 建议增加字段:
- `file_name`
- `file_size`
- `content_type`
- `checksum`
### 4.5.3 `template_download_log`
- 建议新增字段:
- `download_type`
- `watermark_text`
- `project_id`
- `meeting_id`
- 建议新增索引:
- `(tenant_id, template_id, downloaded_at)`
- `(tenant_id, user_id, downloaded_at)`
- `(tenant_id, downloaded_at)`
### 4.5.4 `template_type_option`
- 现有主键建议调整为适合多租户的联合唯一约束:
- 主键独立 `id`
- 唯一键 `(tenant_id, type_code)`
- 避免 `type_code` 全局唯一导致多租户扩展受限。
### 4.5.5 `template_flow_link`
- 建议保留:
- `(tenant_id, scene_code)` 唯一
- 建议增加:
- 绑定来源
- 绑定说明
- 最近绑定人
- 最近绑定时间
## 4.6 权限与风控优化
- 继续保留租户域权限拆分:
- 查询
- 创建
- 发布
- 停用
- 归档
- 回滚
- 下载
- 流程绑定
- 补充细粒度操作审计:
- 模板创建
- 版本新增
- 发布
- 回滚
- 流程绑定
- 普通下载
- 水印下载
- 对高风险操作输出审计原因字段:
- 回滚原因
- 归档原因
- 水印下载说明
## 4.7 交互与体验优化
- 统一中文文案,避免技术字段直接暴露给业务用户。
- 统一状态文案与颜色:
- 草稿
- 已发布
- 已停用
- 已归档
- 对空数据场景增加引导:
- 暂无模板,请先创建
- 暂无下载记录
- 对失败场景返回可理解提示:
- 模板已归档,不能新增版本
- 模板未在生效期内,不能绑定流程
- 当前小时下载次数已达上限
## 5. 分期实施建议
## 5.1 P0:必须先做
- 模板列表筛选与标准分页
- 下载日志标准分页与筛选
- 创建模板交互优化,取消手填 `objectKey`
- 流程绑定强校验
- 模板创建/新增版本并发安全修复
- 发布/停用/归档/回滚状态机校验补齐
## 5.2 P1:强烈建议做
- 模板详情页与版本历史重构
- 有效期控制落地
- 水印下载真实落地
- 下载限流落地
- 下载日志返回关联名称,去掉前端补查
- 复制模板能力
## 5.3 P2:体验增强
- 模板预览
- 模板变更摘要对比优化
- 关联业务影响提示
- 模板清单导出
- 模板治理仪表盘
## 6. 验收标准建议
- 用户可以在 3 步内完成模板创建,不需要手填对象存储路径。
- 用户可以在列表中快速筛出“某场景、某状态、某范围”的模板。
- 流程绑定后,业务读取到的模板与绑定配置一致。
- 并发建版不会出现版本号冲突或串模板。
- 下载日志可分页、可筛选、可定位到具体用户与版本。
- 有效期、水印、下载限流配置能被真实执行,而不是只存库不生效。
## 7. 推荐实施顺序
1. 先改后端查询、状态机、并发安全、日志接口。
2. 再改前端页面结构与创建流程。
3. 再补流程联动闭环、水印、限流、有效期。
4. 最后补预览、复制、导出、治理报表等增强能力。