# Design:B-2a 报销审批内容工作台 ## 1. Change Boundary - 扩展 workflow context 的显式预算快照投影,但不改 Prisma schema。 - 审批页继续读取 workflow task;报销内容使用现有 reimbursement detail 只读 API。 - 新建共享展示模型、分组纯函数和响应式明细证据组件。 - PC/移动审批容器接入同一组件;审批 action API、状态机和 comment 存储不变。 ## 2. Data Flow ```text GET workflow task -> task/actions/history -> submissionSnapshot { standardViolations, budgetCheck } GET reimbursement detail -> current header/items/invoices/attachments -> current invoice amount evidence/manual review pure projection -> itemEvidenceModels -> unlinkedInvoices -> submissionCheckSummary -> currentEvidenceSummary PC/Mobile approval shell -> shared evidence component -> existing material open handlers -> existing approve/return/reject/transfer mutations ``` 两个查询任一缺少关键数据时不允许“通过”。材料单项预览失败不清空已经加载的其他证据。 ## 3. Proposed Modules - `client/src/components/reimbursements/ReimbursementItemEvidenceList.tsx`:共享响应式内容组件。 - `client/src/lib/reimbursementApprovalProjection.ts`:最小输入的分组、快照映射、实时摘要和退回引用纯函数。 - `client/src/pages/WorkflowTaskDetailPage.tsx`:PC 审批壳与右侧决策区。 - `client/src/pages/MobileApprovalsPage.tsx`:移动审批壳与底部动作层级。 - `client/src/api/workflow.ts`:显式 `budgetCheck` 类型。 - `server/src/routes/reimbursements.js`:提交时把已计算预算结果写入 context。 - `server/src/routes/workflow.js`:只投影允许的预算快照字段。 具体文件可在实施前按现有复用点微调,但不得把共享组件放进 workflow 页面目录。 ## 4. Permission Matrix | 身份/状态 | 审批页内容 | 材料原件 | 报销维护 | 审批动作 | | --- | --- | --- | --- | --- | | 当前审批人 pending | 可读 | 按现有授权/审计 | 无 | 按 allowedActions | | 已处理任务查看者 | 可读当前版本 + 历史提示 | 按现有授权/审计 | 无 | 无 | | `expense.view_all` 财务 | 可读 | 按现有授权/审计 | 无 | 仅任务允许时 | | 无任务/无查看资格 | 403 | 403 | 无 | 无 | ## 5. Offline Boundary 报销审批的完整证据不进入现有 workflow IndexedDB cache。`cacheWorkflowTaskDetail` 必须先把 task detail 投影为显式允许字段子集,只保留任务身份、业务公开摘要、节点/状态和必要历史;明确删除或拒绝明细、票据、附件、金额证据、材料访问数据及共享 component projection。不能把整个 DTO 透传给 IndexedDB。 离线时可查看已经允许缓存的摘要/历史,但报销审批的通过、退回、驳回和保存草稿全部不可用,并说明“需联网核对完整报销内容”。其他实体继续沿用当前离线草稿能力。 若未来需要离线报销审批,必须重新规划敏感数据缓存字段、过期、清除、加密/设备边界和附件不可离线预览,不得在 B-2a 实施中临时扩大缓存。 ## 6. Test Contracts - projection 纯函数覆盖:零/一/多票、未归属、snapshot itemId 找不到、manual review、amount unavailable、历史预算缺失、退回引用去 UUID。 - 后端覆盖:budgetCheck 与 workflow instance 同事务写入;null/旧 context 安全投影;不返回任意 context 字段。 - PC/移动 E2E 使用同一 fixture 工厂,fixture 字段由 API type/服务端 route contract 共同约束,避免两端测试作者各造一套形状。 - 完整流程断言必须点击真实可见的证据入口和审批动作;不能只断言 DOM 中存在文本。 - 离线测试在在线打开合成报销审批后读取 IndexedDB 原始记录,断言禁存字段不存在;再断网验证报销动作/草稿全部阻断,同时保留非报销审批离线基线。 ## 7. Rollback - 代码回滚恢复旧审批摘要和外链;workflow context 多出的 JSON 字段对旧代码无害。 - 不含 migration、seed、flag 或生产数据改写。 - 部署前/后按项目现有 build SHA、UI strict、公网 bundle 和合成审批任务流程核验。