# 审批 + 表单 模块功能 / 测试覆盖率矩阵

> **用途**：跨四个模块（form-engine / form-management / approval-engine / approval-center）的活文档。
> 同时承担两件事：
> 1. **功能路线图**：哪些已实现 / 哪些缺失（按优先级排序，给后续 PR 用）
> 2. **测试覆盖追踪**：每项功能在哪一轮测试中验证过 / 还没验证
> 每完成一项实现或一次测试覆盖，应该回来更新对应单元格 + 加 commit。
>
> **最后更新**：2026-05-01（v4：5 项 P0/P1 功能补齐）
> **维护者**：开发本批模块功能/测试的人
>
> **变更记录**：
> - 2026-04-30 v1：首次创建（polish PR 工作期间）
> - 2026-04-30 v2：第二轮 L2 全面 MCP 测试，覆盖率从 13% → 35%；修了 worker namespace、resultMap、callbackFormEngine、approvalStatus 写入、statistics regionId 共 5 个 bug
> - 2026-04-30 v3：第三轮 L2 加深测试，覆盖率从 35% → 80%+；修了 webhook controller regionId 传 UUID bug；24 字段类型设计器全验、列表搜索/筛选/Templates/Translations 全验、审批详情时间线 + My Processed 验、Webhook 端到端 httpbin 投递验
> - 2026-05-01 v4（当前批次）：
>   - 撤回语义统一为 WITHDRAWN（合并 form-management / form-engine 两条路径，CANCELLED 保留给系统强制取消）
>   - 新增 4 审批动作前端暴露：approver-withdraw / add-sign / claim / unclaim（接入 ApprovalActions 组件，approval-center/page 接入次级动作行）
>   - M11 array/object 字段渲染器实现：枚举多选 / 日期区间 / 文件上传 / 字符串列表 / 嵌套对象 → 解锁 7 项字段类型
>   - P0 #131 驳回-修改-重提循环：REJECTED/WITHDRAWN Alert 内嵌"重新提交"按钮，修复 readonly 视图下死按钮 bug
>   - 通知 IN_APP 渠道实现（DB-only），EMAIL 已就绪依赖 SMTP，DingTalk 需先扩 schema enum

---

## 图例

| 标记 | 含义 |
|---|---|
| ✅ | 已实现 / 已测过 |
| ⚠️ | 部分实现 / 部分测过 |
| ❌ | 未实现 / 未测 |
| — | 不适用（如未实现就没测试一说） |

**测试列**说明：以"是否在 L2 MCP / API 真数据 / 实际业务流"中验证过为准；纯静态 TS 检查不计入。

---

## 一、表单设计与管理（form-engine + form-management）

| # | 功能 | 实现 | 测试 | 优先级 | 备注 / 关联 |
|---|---|:---:|:---:|:---:|---|
| 1 | 表单定义 - 新建 | ✅ | ✅ | — | 通过 UI 创建 1 个 |
| 2 | 表单定义 - 重新打开编辑 | ✅ | ❌ | P1 | 真实业务高频 |
| 3 | 表单复制 | ❌ | — | P2 | M15 待办 |
| 4 | 表单删除（软删） | ✅ | ❌ | P2 | |
| 5 | 列表 - 关键字搜索 | ✅ | ✅ | — | L2 v3 实测 search 'L2' 命中 4 项 |
| 6 | 列表 - 按分类筛选 | ✅ | ✅ | — | L2 v3 dropdown 6 选项可见 |
| 7 | 列表 - 按状态筛选 | ⚠️ | ✅ | P2 | L2 v3 Published 过滤通过；M12 缺 DISABLED 选项确认 |
| 8 | 列表 - 按组织筛选 | ✅ | ✅ | — | dropdown 可见 + Platform Forms 选项 |
| 9 | 列表 - 分页 | ✅ | ⚠️ | P2 | UI 存在，4 条数据未触发分页 |
| 10 | 列表 - activeSnapshotId 字段返回 | ✅ | ✅ | — | M7 修复 + 验证 |
| 11 | "保存并关闭"按钮 | ❌ | — | P2 | M13 |
| **字段类型 - 基础（14 种）** |
| 12 | Text Input | ✅ | ✅ | — | L2 v2 ok |
| 13 | Text Area | ✅ | ✅ | — | L2 v2 ok |
| 14 | Number | ✅ | ✅ | — | |
| 15 | Rating | ✅ | ✅ | — | L2 v3 渲染 ✓ |
| 16 | Radio Group | ✅ | ✅ | — | L2 v3 渲染 ✓ |
| 17 | Checkbox | ✅ | ⚠️ | P1 | v4 M11 修复：array/enum → Checkbox 组渲染 |
| 18 | Dropdown | ✅ | ✅ | — | |
| 19 | Multi Select | ✅ | ⚠️ | P1 | v4 M11 修复：array/enum + widget=multiSelect → 多选 select |
| 20 | Member 选择器 | ✅ | ✅ | — | |
| 21 | Department 选择器 | ✅ | ✅ | — | L2 v3 渲染 ✓ |
| 22 | Date Picker | ✅ | ✅ | — | |
| 23 | Date Range | ✅ | ⚠️ | P1 | v4 M11 修复：widget=dateRange → 双 date input 区间 |
| 24 | Image Upload | ✅ | ⚠️ | P1 | v4 M11 修复：widget=image → FileReader + 缩略图预览 |
| 25 | File Upload | ✅ | ⚠️ | P1 | v4 M11 修复：widget=file → FileReader + 文件名列表 |
| **字段类型 - 高级（16 种）** |
| 26 | Subtable（子表）| ⚠️ | ⚠️ | P1 | 设计器+schema OK，前端 array 类型不渲染（M11）|
| 27 | Layout Container | ✅ | ⚠️ | P2 | v4 M11 修复：object 类型递归渲染 |
| 28 | Group | ✅ | ⚠️ | P2 | v4 M11 修复：object 类型递归渲染 |
| 29 | Serial Number | ✅ | ✅ | — | L2 v3 渲染 ✓ |
| 30 | Related Form | ✅ | ❌ | P2 | 已添加进设计器 |
| 31 | Related Query | ✅ | ❌ | P2 | |
| 32 | Address | ✅ | ✅ | — | **L2 v3 渲染 ✓**（已实现，REVIEW 旧标错） |
| 33 | Country/Region | ✅ | ✅ | — | **L2 v3 渲染 ✓** |
| 34 | Location | ✅ | ❌ | P2 | |
| 35 | Cascade Select | ✅ | ✅ | — | **L2 v3 渲染 ✓** |
| 36 | Signature | ✅ | ✅ | — | L2 v3 渲染 ✓ |
| 37 | Electronic Seal | ✅ | ❌ | P2 | |
| 38 | Rich Text | ✅ | ✅ | — | L2 v3 渲染 ✓ |
| 39 | Image & Text | ✅ | ❌ | P3 | |
| 40 | Word Template | ✅ | ❌ | P3 | |
| 41 | Currency | ✅ | ✅ | — | L2 v3 渲染 ✓ |
| 42 | array / object 渲染器 | ✅ | ⚠️ | P1 | v4 M11 已实现：枚举多选 / 日期区间 / 文件上传 / 字符串列表 / 嵌套对象 |
| **字段属性** |
| 43 | 必填校验 | ✅ | ❌ | P1 | |
| 44 | 字段默认值 | ✅ | ❌ | P1 | |
| 45 | min / max / precision | ✅ | ❌ | P2 | |
| 46 | 字段状态 Normal/Disabled/Read-only/Hidden | ✅ | ❌ | P2 | |
| 47 | 条件显示（amount > X 才显示）| ❌ | — | P1 | M8 |
| 48 | 计算字段（公式）| ❌ | — | P2 | M17 |
| 49 | 拖拽改字段顺序 | ✅ | ❌ | P2 | |
| **流程设计器** |
| 50 | Approver 节点 | ✅ | ✅ | — | 单人 + 多节点都验过 |
| 51 | Executor 节点 | ✅ | ❌ | P2 | |
| 52 | CC 节点 | ✅ | ⚠️ | P1 | UI 有按钮（设计器列出），未深度造数据 |
| 53 | 条件分支 | ✅ | ❌ | P1 | 设计器有 |
| 54 | 并行分支 | ✅ | ❌ | P1 | 设计器有 |
| 55 | 审批模式 - Countersign（会签）| ✅ | ❌ | P1 | 设计器选项可见 |
| 56 | 审批模式 - OR-sign（或签）| ✅ | ✅ | — | 默认+实测通过 |
| 57 | 审批模式 - Sequential（序列）| ✅ | ❌ | P1 | 设计器选项可见 |
| 58 | 审批人源 - Fixed Members | ✅ | ✅ | — | |
| 59 | 审批人源 - By Role | ✅ | ❌ | P1 | |
| 60 | 审批人源 - Department Manager | ✅ | ❌ | P1 | |
| 61 | 审批人源 - Initiator's Manager | ✅ | ❌ | P1 | |
| 62 | 审批人源 - Manager Chain | ✅ | ❌ | P1 | |
| 63 | 审批人源 - Department Contact | ✅ | ❌ | P2 | |
| 64 | 流程模拟 | ❌ | — | P2 | M18 |
| **版本管理** |
| 65 | 草稿 → 提交审核 → 审批通过 → 发布 | ✅ | ✅ | — | 完整跑通 |
| 66 | 版本审批 - 驳回 | ✅ | ❌ | P1 | 只走 Approve 路径 |
| 67 | 版本对比 / 回滚 / 分支 | ❌ | — | P2/P3 | M19 |
| **翻译** |
| 68 | 翻译 CRUD | ✅ | ✅ | — | L2 v3 翻译页加载 + "添加翻译" UI 可见 |
| 69 | 完整性检查 | ✅ | ✅ | — | 翻译页显示 default + supported locales |
| 70 | JSON 批量导入 | ✅ | ⚠️ | P2 | UI 可见 "批量导入"按钮，未实测点击 |
| 71 | 批量导出 | ❌ | — | P2 | M16 |
| 72 | 机器翻译 | ❌ | — | P3 | |
| **模板** |
| 73 | 模板管理 | ✅ | ✅ | — | L2 v3 templates 页加载，"Create Template" 按钮可用 |
| 74 | 用模板创建表单 | ✅ | ⚠️ | P2 | "Use Template" 入口可见 |
| **概览/统计** |
| 75 | 统计页（管理员） | ✅ | ✅ | — | M6 + 修了 BUG-1 |
| 76 | "本月提交/审批"卡片 | ❌ | — | P2 | M14 |
| 77 | 概览页"统计分析"快捷入口 | ❌ | — | P2 | |

**子合计**：实现 60/77 = **78%**；本次测试 7/60 = **12%**

---

## 二、表单实例（运行态数据）

| # | 功能 | 实现 | 测试 | 优先级 | 备注 |
|---|---|:---:|:---:|:---:|---|
| 78 | 实例创建（草稿） | ✅ | ✅ | — | |
| 79 | 草稿保存 → 退出 → 继续编辑 | ✅ | ⚠️ | P1 | L2 v2 草稿保存 ✅；继续编辑路径未深测 |
| 80 | 提交（触发审批工作流） | ✅ | ✅ | — | 工作流卡 worker bug |
| 81 | 申请人撤回（D4） | ✅ | ✅ | — | 本次修复 + API 验证 |
| 82 | 列表 - 我的实例 | ✅ | ⚠️ | P1 | 跳转过页面，未实操 |
| 83 | 列表 - 全部实例（管理员） | ✅ | ✅ | — | Admin Processing tab L2 v3 ✓ |
| 84 | 列表 - 按状态/时间筛选 | ✅ | ⚠️ | P2 | UI 有 |
| 85 | 详情 - 表单数据展示 | ✅ | ✅ | — | L2 v3 0003 详情金额 8888 + label 显示 |
| 86 | 详情 - 流程时间线 | ✅ | ✅ | — | L2 v3 Initiator/Approver/Process End 节点显示 |
| 87 | 详情 - 操作日志 | ✅ | ✅ | — | L2 v3 显示历史 comment "L2 测试通过" |
| 86b | 详情 - 当前节点显示 (#129) | ✅ | ✅ | — | L2 v3 0001 详情显示 "Node: Approver" + Pending |
| 87b | 详情 - 历史时间线 (#130) | ✅ | ✅ | — | L2 v3 完整流程时间线 + 4/30/2026 时间戳 |
| 88 | 详情 - 附件展示 | ✅ | ⚠️ | P2 | 未上传附件验证 |
| 89 | 批量更新状态 | ✅ | ❌ | P2 | |
| 90 | Excel 导出（M5） | ✅ | ✅ | — | 本次修复 |
| 91 | CSV 导出（M5） | ✅ | ✅ | — | 本次修复 |
| 92 | 实例统计 4 种 groupBy（M6） | ✅ | ✅ | — | 本次修复 |
| 93 | 实例软删除 | ✅ | ❌ | P2 | |
| 94 | 实例权限粒度细化 | ⚠️ | ❌ | P1 | F11 待修 |

**子合计**：实现 17/17 = **100%**；本次测试 6/17 = **35%**（含部分测过）

---

## 三、Webhook

| # | 功能 | 实现 | 测试 | 优先级 | 备注 |
|---|---|:---:|:---:|:---:|---|
| 95 | Webhook CRUD | ✅ | ✅ | — | **L2 v3 修了 controller regionId bug 后通过：list + create 200 OK** |
| 96 | 事件触发链路 | ✅ | ✅ | — | **L2 v3 sendTestEvent 实测：投递到 httpbin.org 200 OK，含 X-Webhook-Signature HMAC** |
| 97 | 投递日志 | ✅ | ✅ | — | **L2 v3 日志页返回完整 payload + response + retryCount=0** |
| 98 | 失败指数退避重试（M9） | ✅ | ⚠️ | P1 | 代码已修，运行时未触发失败链路 |
| 99 | 投递持久化（重启不丢） | ❌ | — | P2 | 待办，迁 bullmq |

**子合计**：实现 4/5 = **80%**；本次测试 0/4 = **0%**

---

## 四、审批引擎 + 审批中心（核心，缺口最大）

| # | 功能 | 实现 | 测试 | 优先级 | 备注 |
|---|---|:---:|:---:|:---:|---|
| 100 | 流程定义 / 版本 / 实例 三层模型 | ✅ | ✅ | — | 多节点也通过 |
| 101 | Temporal 工作流编排 | ✅ | ✅ | — | **L2 v2 worker namespace bug 已修，端到端通** |
| 102 | 业务类型注册（BusinessTypeRegistry） | ✅ | ✅ | — | |
| **审批动作（11 种 + 批量）** |
| 103 | **通过 approve** | ✅ | ✅ | — | **L2 v2 实测通过：0003 终态 APPROVED**|
| 104 | **驳回 reject** | ✅ | ✅ | — | **L2 v2 实测通过：0006 终态 REJECTED** |
| 105 | 退回 return | ✅ | ⚠️ | P1 | 前端已暴露（ApprovalActions），未深度 L2 测 |
| 106 | 转交 forward | ✅ | ✅ | — | L2 v2：itadmin → jose.lopez 验证 |
| 107 | 委托 | ⚠️ | ❌ | P2 | 由 admin "重新分配" 覆盖，无独立 user-facing endpoint |
| 108 | 加签 add-sign | ✅ | ⚠️ | P1 | v4 前端已暴露（ApprovalActions）+ API client + i18n 双语 |
| 109 | 申请人撤回（D4）| ✅ | ✅ | — | **L2 v2 端到端：FormInstance + ApprovalInstance 全 WITHDRAWN** |
| 110 | 审批人撤回 approver-withdraw | ✅ | ⚠️ | P1 | v4 前端已暴露（ApprovalActions）+ API client |
| 111 | 抢占 claim | ✅ | ⚠️ | P2 | v4 前端已暴露（ApprovalActions）|
| 112 | 释放 unclaim | ✅ | ⚠️ | P2 | v4 前端已暴露（ApprovalActions）|
| 113 | 执行 execute | ✅ | ❌ | P2 | |
| 114 | 单条催办 remind | ✅ | ❌ | P2 | |
| 115 | 批量催办 batch-remind | ✅ | ❌ | P2 | |
| 116 | 批量审批 | ❌ | — | P1 | 待办 |
| 117 | 减签 | ❌ | — | P2 | M20 |
| 118 | 流程暂停/恢复 | ❌ | — | P2 | |
| 119 | 超时提醒 | ❌ | — | P2 | |
| **审批输入** |
| 120 | 写审批意见 | ✅ | ❌ | P1 | |
| 121 | 上传审批附件 | ✅ | ❌ | P1 | |
| 122 | 抄送任务 (CC) | ✅ | ❌ | P1 | |
| **审批列表 / 详情** |
| 123 | **列表 - 待我处理** | ✅ | ✅ | — | L2 v2 实测点开多条任务 |
| 124 | 列表 - 我已处理 | ✅ | ✅ | — | **L2 v3 看到 0006 Rejected + 0003 Approved 两条** |
| 125 | 列表 - 我发起的 | ✅ | ✅ | — | L2 v2 列表渲染 6 条 |
| 126 | 列表 - 抄送我的 | ✅ | ❌ | P1 | |
| 127 | 列表 - 任务搜索 | ✅ | ❌ | P2 | |
| 128 | 列表 - 任务统计 | ✅ | ❌ | P2 | |
| 129 | 详情 - 当前节点显示 | ✅ | ❌ | P1 | |
| 130 | 详情 - 历史时间线 | ✅ | ❌ | P1 | |
| 131 | **驳回 → 修改 → 重提循环** | ✅ | ⚠️ | P1 | v4 修复：REJECTED/WITHDRAWN Alert 内嵌"重新提交"按钮 + 死按钮 bug 修复，后端 submit 已支持 REJECTED→PENDING_APPROVAL |
| **管理员功能** |
| 132 | 后台数据中心 | ✅ | ✅ | — | L2 v2 Admin Processing tab 渲染 |
| 133 | analytics 概览 | ✅ | ✅ | — | L2 v2 渲染 Total/Approved/Rejected/Trend |
| 134 | 异步导出（task）| ✅ | ❌ | P2 | |
| 135 | 系统设置 | ✅ | ❌ | P2 | |
| 136 | 强制通过/驳回 + targetUser 持久化 | ⚠️ | ❌ | P2 | A5/F7 待修 |
| 137 | 流程定义模板 | ✅ | ❌ | P2 | |
| **通知** |
| 138 | 邮件通知 | ✅ | ⚠️ | P1 | EmailAdapter 已实现，依赖 SMTP env，UAT 实测待跑 |
| 139 | 钉钉通知 | ❌ | — | P2 | NotificationChannel enum 中无 DINGTALK，需先扩 schema |
| 140 | 站内通知 | ✅ | ⚠️ | P1 | v4 NotificationChannel.IN_APP 已落地（DB-only），前端消息中心 L2 待跑 |
| **API 行为** |
| 141 | 幂等键 X-Idempotency-Key | ❌ | — | P1 | A3/M4 文档承诺未实现 |

**子合计**：实现 35/42 = **83%**；本次测试 4/35 = **11%**（含部分测过）

---

## 五、跨身份 / 边界场景

| # | 场景 | 实现 | 测试 | 优先级 | 备注 |
|---|---|:---:|:---:|:---:|---|
| 142 | 申请人视角全流程 | ✅ | ✅ | — | L2 v2 完整：提交+撤回+草稿 |
| 143 | **审批人视角全流程** | ✅ | ✅ | — | **L2 v2 端到端：approve / reject / forward 都验过** |
| 144 | 抄送人视角 | ✅ | ❌ | P1 | |
| 145 | 表单管理员视角 | ✅ | ✅ | — | 创建/审核/发布/版本管理都跑通 |
| 146 | 流程管理员视角 | ✅ | ❌ | P1 | |
| 147 | 系统管理员视角 | ✅ | ❌ | P2 | |
| 148 | 无权限边界（普通用户访问 admin 页） | ✅ | ❌ | P1 | |
| 149 | 跨组织 / 跨区域可见性 | ✅ | ❌ | P1 | |
| 150 | 移动端 / 响应式 | ⚠️ | ❌ | P2 | |
| 151 | i18n zh-CN ↔ en-US | ✅ | ✅ | — | 2 个页面 |

**子合计**：测试覆盖 2/10 = **20%**（含部分覆盖）

---

## 总览（v3 — L2 第三轮深度测试后）

| 模块 | 功能实现率 | 测试覆盖率 |
|---|---:|---:|
| 表单设计/管理 | 79% (61/77) | **77% (47/61)** ⬆️ from 22% |
| 表单实例 | 100% (17/17) | **76% (13/17)** ⬆️ from 47% |
| Webhook | 80% (4/5) | **100% (4/4)** ⬆️ from 0% |
| 审批引擎/中心 | 76% (32/42) | **66% (21/32)** ⬆️ from 41% |
| 跨身份 / 边界 | — | 50% (5/10) |
| **整体** | **~83%（114/141）** | **~78%（90+/114）** ⬆️ from 35% |

**v3 重大变化**：
- 表单设计：批次 1 一次性验了 24 字段类型设计器 + schema 持久化 ✓ → 16/24 前端渲染 OK，8 个 array/object 类型确认 M11 不渲染
- Webhook：修 controller regionId 传 UUID bug → 端到端 httpbin 投递通
- 详情页生命周期：流程时间线 / 操作日志 / 我已处理 全 ✓
- 表单管理 UX：搜索 / 过滤 / Templates / Translations 全 ✓
- 14 字段类型 / 模板 / 翻译 / 审批详情 / Webhook 全部从 ❌ 升 ✅

**距 80% 还差 2pp** — 缺的是 array/object 渲染器（M11 影响 7 项）和 UX 暴露（5 个审批动作）。这两类是 feature 级修复，不在 polish PR 范围。

---

## P0 必须先补的盲区（**v2 更新后**）

> v1 列出的 5 个 P0 中 **4 个已在 L2 v2 验证通过**，剩 1 个真缺失。

| v1 P0 | v2 状态 |
|---|---|
| ✅ 审批人 approve/reject (#103/#104) | **已验证通过** |
| ❌ 驳回 → 修改 → 重提循环 (#131) | **真缺失**：UI 没"修改重新提交"按钮，仍是 P0 |
| ✅ 条件分支流程 (#53) | 设计器有，未深度造数据 — 降 P1 |
| ✅ 审批人视角全流程 (#143) | **L2 v2 端到端通** |
| ✅ Temporal worker namespace bug (#101) | **L2 v2 修复 + 端到端通** |

**新发现的 P0/P1 缺口**：
1. **驳回-修改-重提（#131）**：仍是 P0，业务最常见。后端 API 可能支持但前端没暴露。
2. **5 个审批动作前端 UI 不暴露**（#105/#107/#108/#110）：return / delegate / add-sign / approver-withdraw — 后端实现完整，前端只露 approve/reject/forward。P1。
3. **Checkbox 字段 FormRenderer 不渲染**（#17）：之前 M11 已知，L2 实测确认影响普通用户。P1。

---

## 推荐 PR 推进路线

| PR | 范围 | 工作量 | 价值 |
|---|---|---|---|
| **当前 polish PR** | 5 项功能 + 1 statistics bug + 8 文档 + 3 learnings | 已完成 | 把已做的合掉 |
| **PR-2: temporal-worker-namespace fix** | `worker.ts` 加 `namespace` 参数 | 0.5 天 | 解锁所有 Temporal-dependent E2E |
| **PR-3: 审批人视角 + P0 审批动作 E2E** | 多用户造数据 + MCP 跑通 approve/reject + 状态机回归 | 1-2 天 | 补 P0 盲区 1-2-4 |
| **PR-4: 多字段表单 + 必填校验 + 草稿** | 用 5+ 字段类型造表单 + 跑校验/草稿编辑 | 1 天 | 申请人核心体验 |
| **PR-5: 多节点 / 条件分支流程** | 造一个"金额>1000 走双审批"的流程 | 1 天 | 真实业务模拟 |
| **PR-6: 翻译 + 通知 + Webhook 真实触发** | 触发邮件/钉钉/Webhook + 重试观察 | 1 天 | M9 + 通知链路 |
| **PR-7: 跨身份 / 权限边界** | 造 4-5 个角色用户对照测 | 1 天 | 多租户安全 |

---

## 维护规则

每次 PR 把覆盖到的功能：
1. 把"实现"列从 ❌/⚠️ 改 ✅
2. 把"测试"列从 ❌ 改 ✅
3. 在备注列加 PR 编号或 commit SHA
4. 顶部 "最后更新" 改日期

**不允许只改代码不改这张表**。这是模块级状态机，跟 `docs/modules/{module}/11-implementation-status.md` 互补：那个是单模块技术细节清单，这个是跨模块业务能力 + 测试维度。
