实现 B-2b 统一报销工作台迁移(reimbursement-form-shared-component-migration)
这个提交包含在:
@@ -1,21 +1,164 @@
|
||||
# Design:B-2b 报销填写态共享组件迁移
|
||||
# Design:B-2b 统一报销工作台迁移
|
||||
|
||||
## Current Decision Boundary
|
||||
## 1. Architecture Decision
|
||||
|
||||
B-2b 不重新定义业务内容组件,而是采用 B-2a 已验证的展示模型、字段顺序和快照/实时标签;本阶段增加 edit capability、票据抽屉和提交前检查,并删除旧重复布局。
|
||||
采用“任务路由分派 + 唯一报销工作台内容合同 + PC/移动布局壳 + 三个模式适配器”。不把审批模式继续塞进现有大型详情页,也不让通用 workflow 页面继续拥有报销业务布局。
|
||||
|
||||
详细交互在 B-2a 真人反馈后收敛,但以下架构边界已经冻结:
|
||||
```text
|
||||
/workflow/tasks/:taskId /mobile/approvals/:taskId
|
||||
│ │
|
||||
└──── authorized task route dispatcher ┘
|
||||
│
|
||||
entityType=reimbursement
|
||||
│
|
||||
ReimbursementApprovalAdapter
|
||||
│
|
||||
ReimbursementDesktopWorkspaceShell
|
||||
(共享内容合同)
|
||||
|
||||
- 共享组件不直接拥有 API 查询或 mutation;填写页通过显式能力和回调注入新增、编辑、删除、票据关联与恢复动作。
|
||||
- review/readonly 模式不接收 edit capability,不能靠 CSS 隐藏维护动作。
|
||||
- PC/移动复用同一 projection 与语义 DOM;响应式容器决定抽屉/底部 sheet 形态。
|
||||
- 服务端 B2 门禁仍是提交权威,前端检查只做同合同的提前反馈。
|
||||
- 旧布局在迁移验证通过后删除,不保留永久 feature flag 双实现。
|
||||
/reimbursements/:reimbursementId
|
||||
│
|
||||
reimbursement route selector
|
||||
├─ participant + draft/rejected -> ReimbursementEditAdapter
|
||||
└─ otherwise authorized -> ReimbursementReadonlyAdapter
|
||||
│
|
||||
Desktop / Mobile WorkspaceShell
|
||||
(共享内容合同)
|
||||
```
|
||||
|
||||
## Deferred Until Entry Conditions Are Met
|
||||
任务分派器通过唯一一次已授权 task detail 查询选择实体渲染器,并把同一份 query result(含受控 refetch 能力)移交给所选渲染器。它不重复查询、不渲染报销摘要、不计算报销检查、不持有审批表单状态。非报销实体继续进入现有通用详情。
|
||||
|
||||
- 票据抽屉在 PC 使用侧栏还是对话框、移动使用 bottom sheet 还是全屏层。
|
||||
- 编辑入口的最终密度、明细卡片折叠规则和提交摘要的视觉权重。
|
||||
- B-2a 真人反馈要求的字段顺序微调。
|
||||
## 2. Shell Contract
|
||||
|
||||
这些是 B-2b 启动前要补齐的设计细节,不改变本 PRD 的迁移承诺和验收结果。
|
||||
PC/移动布局壳都是纯组合组件,共享模型和 capability 合同,但不强求同一份 DOM,也不接收 `mode` 用于业务判断:
|
||||
|
||||
```ts
|
||||
type ReimbursementWorkspaceModel = {
|
||||
header: ReimbursementWorkspaceHeaderModel;
|
||||
evidence: ReimbursementWorkspaceEvidenceProjection;
|
||||
issueSummary: ReimbursementWorkspaceIssueSummary | null;
|
||||
timeline: ReimbursementWorkspaceTimelineModel;
|
||||
};
|
||||
|
||||
type ReimbursementWorkspaceCapabilities = {
|
||||
item?: ReimbursementEvidenceItemCapabilities;
|
||||
invoice?: ReimbursementEvidenceInvoiceCapabilities;
|
||||
attachment?: ReimbursementEvidenceAttachmentCapabilities;
|
||||
decision?: ReimbursementDecisionCapabilities;
|
||||
};
|
||||
|
||||
type ReimbursementWorkspaceShellProps = {
|
||||
model: ReimbursementWorkspaceModel;
|
||||
capabilities: ReimbursementWorkspaceCapabilities;
|
||||
primaryActions?: ReactNode;
|
||||
secondaryActions?: ReactNode;
|
||||
statusSummary?: ReactNode;
|
||||
transientFeedback?: ReactNode;
|
||||
};
|
||||
```
|
||||
|
||||
`ReimbursementDesktopWorkspaceShell` 与 `ReimbursementMobileWorkspaceShell` 可以根据数据是否存在组合区块,也可以渲染注入的 slot;两者必须保持同一业务内容顺序和语义子组件,但可分别实现 PC 右栏与移动卡片/底部安全区布局。它们不能根据角色、permission、workflow 状态、报销状态或模式推导能力,不能用 `isMobile` 业务分支互相模拟。壳内禁止 `useQuery`、`useMutation`、API client 和业务 mutation state。纯视觉展开优先使用语义 HTML;确需本地视觉状态时不得承载业务事实。
|
||||
|
||||
## 3. Adapter Responsibilities
|
||||
|
||||
### Edit Adapter
|
||||
|
||||
- 获取/刷新报销详情、费用类型、项目、票据候选和 participant precheck。
|
||||
- 拥有表头、明细、票据、附件、提交、删除、OCR 状态与错误恢复 mutation/state。
|
||||
- 将可用动作投影为 capabilities;状态或权限不允许时不注入,不让壳二次判断。
|
||||
- 服务端提交/B2 结果覆盖客户端乐观判断。
|
||||
|
||||
### Approval Adapter
|
||||
|
||||
- 消费路由边界移交的 workflow task detail/query result,不为同一 task 再发一份分派查询;另行获取实时报销详情。
|
||||
- 拥有 task detail 的业务解释和刷新策略、allowedActions、提交快照、处理历史、审批 mutation、退回引用、材料查看、联网状态和 fail-closed。
|
||||
- 只注入证据查看、引用和审批决策能力;编辑/关联/解绑 capability 必须不存在。
|
||||
- 任务、快照、实时报销内容任一关键部分未就绪时,输出不可决策模型和原因。
|
||||
|
||||
### Readonly Adapter
|
||||
|
||||
- 只获取既有授权允许的报销详情、处理进度和材料查看能力。
|
||||
- 不请求参与人专用 precheck,不持有任何业务 mutation。
|
||||
- 不注入编辑、提交或 workflow 决策能力。
|
||||
|
||||
共享查询键、材料打开 helper、展示投影和格式化函数可以复用;适配器不能通过一个巨大 hook 返回所有模式的 mutation 再由页面隐藏。
|
||||
|
||||
## 4. Information Architecture
|
||||
|
||||
### PC
|
||||
|
||||
```text
|
||||
报销单号 + 状态
|
||||
报销人 · 日期 · 合计
|
||||
事由
|
||||
┌────────────────────────────────────┬────────────────────┐
|
||||
│ 明细及所属票据 │ 当前节点/状态 │
|
||||
│ 未归属票据(仅有时) │ 可决策状态 │
|
||||
│ 补充附件 │ 异常锚点(仅有时) │
|
||||
│ 异常/快照差异(仅有时) │ 审批/提交动作 │
|
||||
│ 处理历史/进度 │ sticky │
|
||||
└────────────────────────────────────┴────────────────────┘
|
||||
```
|
||||
|
||||
### Mobile
|
||||
|
||||
标题/状态 → 报销人/日期/合计 → 事由 → 明细/票据 → 未归属(仅有时)→ 附件 → 异常/差异(仅有时)→ 历史/进度 → 底部动作。
|
||||
|
||||
正常检查不生成卡片。异常模型必须带对象引用和锚点:
|
||||
|
||||
```ts
|
||||
type ReimbursementWorkspaceIssue = {
|
||||
key: string;
|
||||
target: { kind: "item" | "invoice" | "submission"; displayLabel: string };
|
||||
severity: "blocking" | "review" | "info";
|
||||
reason: string;
|
||||
impact: string;
|
||||
nextStep?: string;
|
||||
anchorId: string;
|
||||
};
|
||||
```
|
||||
|
||||
右栏只投影非零、可定位的问题。快照缺失是 `info`,视觉低于 blocking/review;快照与实时事实一致时不生成独立差异区。
|
||||
|
||||
## 5. Route and Navigation
|
||||
|
||||
- PC `/workflow/tasks/:taskId` 与移动 `/mobile/approvals/:taskId` 保持不变,避免破坏通知、待办、刷新和深链。
|
||||
- 分派期间显示统一加载骨架;不得先挂载 `WorkflowTaskDetailPage`/通用移动详情再切换报销工作台。
|
||||
- `/reimbursements/:id` 继续是报销记录入口。返回目标由合法、受限的 navigation state/source helper 解析;审批工作台不再提供“返回审批详情”的自循环外链。
|
||||
- 新增或重分类路由时同步 `scripts/qa/route-manifest.json`;如果只是同一路由内分派,也要为 reimbursement renderer 增加行为证据。
|
||||
|
||||
## 6. Legacy Removal
|
||||
|
||||
最终候选删除:
|
||||
|
||||
- `WorkflowTaskDetailPage` 的报销 DetailField、报销证据/检查区、报销右栏摘要与报销专用动作分支。
|
||||
- `MobileApprovalsPage` 的报销内容、报销检查、报销离线解释和报销动作业务分支;通用列表/非报销详情可保留。
|
||||
- `ReimbursementDetailPage`/`MobileReimbursementDetailPage` 中被工作台替代的旧明细表格和旧材料分组。
|
||||
- 旧报销专用文案、测试 fixture 与只为休眠路径服务的 helper/import。
|
||||
|
||||
允许在实现过程的未提交工作区短暂双接线;业务候选提交前必须用结构测试/`rg` allowlist 证明旧分支为 0。不得保留 feature flag 双轨。
|
||||
|
||||
上述壳层禁用项与通用审批旧分支清零必须实现为 `scripts/qa/check-ui-design-rules.mjs` 的 error 规则,并通过既有 `--strict` 部署 preflight;单元测试只补行为和类型证据,不能替代该门禁。
|
||||
|
||||
## 7. Data and Permission Contracts
|
||||
|
||||
- 不改后端 schema。现有 reimbursement detail、workflow detail、材料预览和动作 API 保持权威。
|
||||
- 提交时费用标准/预算来自 workflow context 快照;当前票据/附件来自 reimbursement detail。
|
||||
- approval adapter 复用 B-2a IndexedDB 白名单投影;工作台 model/evidence 不进入 cache。
|
||||
- edit adapter 继续要求参与人 + `draft/rejected` + 现有 permission;readonly/approval 不因 UI 复用获得写能力。
|
||||
- 材料 URL、访问参数和原始 payload 不进入 task、日志、浏览器持久缓存或错误文案。
|
||||
|
||||
## 8. Print Boundary
|
||||
|
||||
`/reimbursements/:id/print` 继续作为专用打印/PDF 视图,允许独立的纸面布局。它不参与三模式交互工作台,不持有工作台 mutation,也不作为审批取得核心内容的入口。本轮只做回归,避免字段删除误伤打印;不迁移或重新设计打印结构。
|
||||
|
||||
## 9. Rollout and Rollback
|
||||
|
||||
- 单一独立候选上线,不新增 migration、seed、flag 或生产数据写入。
|
||||
- 切换前必须完成 PC/移动三模式和非报销回归;上线后使用公网真实 bundle + 合成 API 验收,不操作真人单据。
|
||||
- 回滚是完整回到 B-2a 已部署版本;不保留运行时双壳开关。
|
||||
- 真实三张 rejected 单据可与开发并行,任何反馈只通过新的规划修订进入本任务,不直接现场改产品代码。
|
||||
|
||||
## 10. UI/UX Basis
|
||||
|
||||
本任务不引入新视觉系统。采用 `ui-ux-pro-max` 对本场景适用的通用原则:一致标题层级、组合优于模式继承、异常不只靠颜色、反馈明确、触控目标至少 44×44、渐进披露避免把所有解释预先铺开。其数据库没有命中特定“审批工作台”React 模板,因此不采用不存在的模板结论,继续以项目现有组件和 `docs/产品设计规则.md` 的信息架构为基线。
|
||||
|
||||
@@ -1,22 +1,68 @@
|
||||
# Implementation Plan:B-2b 报销填写态共享组件迁移
|
||||
# Implementation Plan:B-2b 统一报销工作台迁移
|
||||
|
||||
## Entry Gate
|
||||
## Before Development
|
||||
|
||||
- [ ] B-2a 已部署并取得至少一次真人审批反馈。
|
||||
- [ ] 回填本任务最终 drawer/sheet 交互与字段顺序。
|
||||
- [ ] 用户重新批准更新后的 B-2b planning summary。
|
||||
- [x] 用户批准最新 `prd.md`、`design.md`、`implement.md`。
|
||||
- [x] 切换当前 Trellis task 到 B-2b 并运行 `task.py start`;实施前加载 `trellis-before-dev`。
|
||||
- [x] 读取 frontend、approval workflow、reimbursement/OCR、security/privacy、code reuse 与 route manifest 规约。
|
||||
- [x] 冻结现有 PC/移动三模式、权限/状态、路由/返回和打印页回归矩阵。
|
||||
- [x] 记录 B-2a 当前 DOM/test-id、公共 projection、IndexedDB 投影与可回滚提交基线。
|
||||
|
||||
## Planned Sequence
|
||||
## Implementation Order
|
||||
|
||||
1. [ ] 为 B-2a 共享组件接入 edit capability,保持 review/readonly 零维护动作。
|
||||
2. [ ] PC 填写态迁移明细、票据和就近检查。
|
||||
3. [ ] 移动填写态迁移相同语义结构与安全区操作。
|
||||
4. [ ] 接入票据抽屉和未归属票据恢复。
|
||||
5. [ ] 接入提交前摘要与服务端错误就近定位。
|
||||
6. [ ] 删除被替代的旧明细/材料/只读展示分支。
|
||||
7. [ ] 完成状态/权限矩阵、全量前端门禁和独立部署验证。
|
||||
1. [x] 先在 `scripts/qa/check-ui-design-rules.mjs` 建立 error 级结构门禁:PC/移动布局壳禁止 query/mutation/API/role/status/mode 请求分支;通用审批页最终禁止报销业务渲染;旧分支允许清单仅覆盖分派器,并补 self-test。
|
||||
2. [x] 抽取统一报销头、异常模型、快照/实时差异和三模式共享展示 projection 纯函数;补正常/异常/缺失边界测试。
|
||||
3. [x] 建立无业务状态的 PC/移动布局壳,共享模型、区块顺序、`ReimbursementItemEvidenceList` 与 capability 合同;PC 实现右栏 sticky,移动实现卡片 + 底部安全区,不复用同一 DOM 或引入 `isMobile` 业务分支。
|
||||
4. [x] 在 PC/移动 task route 建立唯一 task detail 查询和授权后实体分派;把同一 query result/refetch 入口移交渲染器,报销进入 approval adapter,非报销继续通用详情;避免重复 task 查询和通用页闪现。
|
||||
5. [x] 建立 approval adapter:消费已移交的 task detail,另取实时报销 detail,迁移 allowedActions、快照、task 刷新策略、fail-closed、退回引用、材料查看与 IndexedDB/离线合同。
|
||||
6. [x] 删除 `WorkflowTaskDetailPage` 与 `MobileApprovalsPage` 的报销业务内容、检查、右栏摘要和休眠兜底;立即跑非报销审批回归。
|
||||
7. [x] 建立 readonly adapter,把获准只读报销详情、材料查看和处理进度接入同一工作台,不请求参与人 precheck,不注入 mutation。
|
||||
8. [x] 建立 edit adapter,迁移表头/明细/票据/附件维护、票据抽屉、未归属恢复、提交前检查和 B2 阻断后再次提交;所有能力通过 capability 注入。
|
||||
9. [x] 删除 PC/移动旧明细表格、旧报销材料分组和被替代 helper/test fixture;确保最终候选无双实现或 feature flag 兜底。
|
||||
10. [x] 落实七条信息收敛:紧凑头、唯一事由、正常项隐藏、异常就近、差异条件显示、右栏去重、动作解释按需;补可访问性和锚点/focus 回归。
|
||||
11. [x] 回归 `/reimbursements/:id/print`,证明打印页未被工作台拆分误伤且没有获得交互 mutation。
|
||||
12. [x] 更新与新合同冲突的父任务、frontend/approval/reimbursement spec 或产品事实源;不顺带处理无关治理债。
|
||||
|
||||
## Rollback
|
||||
## Verification Matrix
|
||||
|
||||
- 独立于 B-2a 形成候选与回滚点。
|
||||
- 不改变 B2 服务端门禁或既有票据关联数据;代码回滚恢复旧填写 UI,不删除业务数据。
|
||||
### Structural
|
||||
|
||||
- [x] `check-ui-design-rules.mjs --strict` 对 PC/移动壳中的 `useQuery|useMutation|api/|roleCodes|hasPermission|workflow status|reimbursement status|mode ===` 命中报 error(仅显式视觉 allowlist 可例外),并由 self-test 证明规则有效。
|
||||
- [x] task route 每次详情加载只发一份授权 task detail 查询;approval adapter 复用该结果和 refetch 入口,不产生同 key 重复请求。
|
||||
- [x] 三适配器 capability 快照准确:edit 有维护/提交、approval 有查看/引用/决策、readonly 只有查看。
|
||||
- [x] 通用 PC/移动审批详情不再导入报销证据组件或包含报销摘要/检查文案;唯一 `reimbursement` 判断位于授权分派层允许清单。
|
||||
- [x] 旧明细表/材料布局与休眠测试 fixture 删除,没有双实现 flag。
|
||||
|
||||
### Behavior
|
||||
|
||||
- [x] PC/移动 edit:draft/rejected 新增/编辑/删除明细、PDF 发票上传/选择、关联/解绑、未归属恢复、附件维护、提交预检、B2 阻断、修复后再次提交。
|
||||
- [x] PC/移动 readonly:参与人 reviewing 与非参与人获准查看;无维护、无审批能力;材料权限/审计不变。
|
||||
- [x] PC/移动 approval:pending/已处理、快照 ready/missing/invalid、detail failure、材料单项 failure、退回引用、approve/return/reject/transfer 和联网 fail-closed。
|
||||
- [x] 非报销 workflow:请假、补卡、采购、差旅通用详情和移动离线草稿保持基线。
|
||||
- [x] 路由:列表进入、通知深链、刷新、后退、移动分流、无权 403/不泄露、无返回循环。
|
||||
- [x] 信息:正常 fixture 无“0 条”检查/常驻动作解释;异常 fixture 每项都有对象、原因、影响、下一步和可聚焦锚点;只有快照/实时不一致时出现差异。
|
||||
|
||||
### Commands
|
||||
|
||||
- [x] 相关前端单元/组件/Playwright;`cd client && npm run typecheck && npm run build`。
|
||||
- [x] `node scripts/qa/check-ui-design-rules.mjs --strict` 与 `--self-test`。
|
||||
- [x] route manifest/candidate gate、相关后端 B2/workflow/detail/material tests、`cd server && npm run prisma:validate`。
|
||||
- [x] `python3 ./.trellis/scripts/task.py validate 09-01-reimbursement-form-shared-component-migration`。
|
||||
- [x] `node scripts/qa/check-process-contract.mjs --baseline --json`、`node scripts/qa/check-trellis-governance.mjs`、敏感内容检查、docs registry(如需)、`git diff --check`。
|
||||
- [x] 因涉及 workflow 分派、权限/状态和报销动作,实施后执行只读 review;inline 模式由主会话完成,不派发 implement/check 子代理。
|
||||
|
||||
验证说明:移动离线专项的默认 iPhone 设备配置会选择本机未安装的 WebKit;本轮按既有口径改用 Chromium + iPhone 视口执行,3/3 通过。该结果验证 IndexedDB、离线分流和 fail-closed 合同,不替代 Safari/WebView 渲染验收。
|
||||
|
||||
## Commit and Deployment Boundary
|
||||
|
||||
- [ ] 代码检查通过后按中文 task 引用提交;task 元数据回填独立提交,不 amend。
|
||||
- [ ] 未经明确授权不 push、不部署、不写生产数据。
|
||||
- [ ] 部署候选无 migration/schema/flag/seed;使用既有生产入口与独立回滚基线。
|
||||
- [ ] 公网用合成三模式任务验证,不碰 `0016/0017/0018` 或其他真人单据。
|
||||
- [ ] 部署与真人反馈完成前,B-2b 和父任务都不得归档。
|
||||
|
||||
## Rollback Points
|
||||
|
||||
- 适配器接线或非报销回归失败:停止在本地,不删除旧分支,修正后重新验证。
|
||||
- 最终旧分支删除后检查失败:回到本任务候选前提交,不引入运行时双轨 flag。
|
||||
- 公网验收失败:回滚到 B-2a 生产基线,保留数据库与业务数据不变。
|
||||
|
||||
@@ -1,71 +1,139 @@
|
||||
# B-2b 报销填写态共享组件迁移
|
||||
# B-2b 统一报销工作台迁移
|
||||
|
||||
## Goal
|
||||
|
||||
在 B-2a 共享内容组件经真实审批使用验证后,把 PC/移动报销填写态迁入同一业务结构,消除旧填写态、新审批态和旧只读态长期并存,并完成此前延期的票据抽屉与提交前检查体验。
|
||||
把报销从“填写详情页、审批详情页、旧只读详情页分别组织同一业务对象”收敛为唯一的交互式报销工作台。工作台以报销内容为主体,通过 `edit`、`readonly`、`approval` 三个模式适配器注入数据、状态和能力;审批只是叠加在报销对象上的流程与决策能力,不再复制一套报销页面壳。
|
||||
|
||||
本任务优先服务当前唯一有真实流转的“报销 → 审批 → 付款”链路。请假/补卡继续以企业微信为主,采购/差旅保持冻结的低频能力,不因追求形式一致而同步重构。
|
||||
|
||||
## Background and Confirmed Facts
|
||||
|
||||
- B-2a 已部署到生产并通过公网真实 bundle 的 PC/移动合成验收,解决了审批人必须跳转才能取得明细、票据和附件的问题。
|
||||
- B-2a 是经批准的过渡交付:先恢复核心内容可达性并产出 `ReimbursementItemEvidenceList`、快照投影、离线白名单与 fail-closed 合同;B-2b 负责根据真人目视反馈收敛页面结构。
|
||||
- 真人目视反馈确认:通用审批壳的流程摘要、报销六字段摘要、新证据区和右侧检查计数存在重复;解释性文字按系统内部状态平铺,审批人需要的“哪条明细、什么问题、是否阻断、如何处理”反而不突出。
|
||||
- `ReimbursementDetailPage.tsx` 与 `MobileReimbursementDetailPage.tsx` 已是高状态、高 mutation 的大型页面。继续在其中加入 `if (approvalMode)` 会把查询、权限、编辑和审批职责耦合成更难维护的巨型组件。
|
||||
- 项目定位决定采用方案 A:只有报销任务进入业务对象工作台的审批模式;其他 workflow 实体继续使用通用审批详情。
|
||||
- `/workflow/tasks/:taskId` 与 `/mobile/approvals/:taskId` 仍是审批深链和任务身份入口;报销任务在任务元数据解析后交给报销审批适配器,不要求用户再跳到另一业务路由。
|
||||
- B-2a 的提交时费用标准/预算快照与当前票据事实仍是两类不同时间语义,不因页面合并而混用。
|
||||
|
||||
## Entry Conditions
|
||||
|
||||
- B-2a 已部署并通过 PC/移动公网核验。
|
||||
- 至少取得一次真实报销审批反馈,确认审批人能理解明细—票据对应、快照/实时标签和退回引用。
|
||||
- B-2a 共享组件 API 已冻结;若真实反馈要求改字段顺序,先回写 B-2a 组件合同再启动迁移。
|
||||
- B-2a 已部署并通过生产 `/ready`、公网 bundle 与合成业务验收。
|
||||
- 已取得一次真人目视反馈,并据此冻结方案 A、信息收敛规则和壳/适配器边界。
|
||||
- 本 PRD、`design.md` 与 `implement.md` 经用户复核批准后,B-2b 才可进入实施。
|
||||
- 三张真实 `rejected` 单据的员工修改与反馈可以并行推进,不是本任务启动或完成的阻塞条件;反馈如改变已批准产品行为,必须回到规划阶段修订。
|
||||
|
||||
## Scope
|
||||
|
||||
- PC `ReimbursementDetailPage` 与移动 `MobileReimbursementDetailPage` 的 draft/rejected 填写态及非参与人只读内容投影。
|
||||
- B-2a 共享组件的 edit 能力、票据抽屉、提交前检查和错误恢复。
|
||||
- 删除被共享组件替代的旧明细/材料展示分支,并保持现有 API、权限和 B2 服务端门禁权威。
|
||||
- 建立 PC/移动共享内容合同的唯一交互式报销工作台;PC 与移动允许使用各自布局壳,但必须消费同一展示模型、区块顺序、语义组件和 capability 契约。
|
||||
- 建立 `edit`、`readonly`、`approval` 三类模式适配器;查询、业务状态、权限判断、mutation、错误恢复和 fail-closed 均归适配器。
|
||||
- `/reimbursements/:reimbursementId` 的参与人填写态和非参与人只读态迁入工作台。
|
||||
- `/workflow/tasks/:taskId` 与 `/mobile/approvals/:taskId` 的报销任务进入同一工作台的审批适配器;其他实体继续走通用审批详情。
|
||||
- 复用并扩展 B-2a 的明细—票据证据组件、票据抽屉、提交前检查和未归属恢复。
|
||||
- 删除 PC/移动通用审批页中的报销业务分支,以及被工作台替代的旧报销明细/材料布局。
|
||||
- 收敛顶部摘要、检查提示、右侧动作摘要和退回/驳回解释。
|
||||
|
||||
## Requirements
|
||||
## Product Requirements
|
||||
|
||||
### R1 填写态采用同一业务内容组件
|
||||
### R1 一个业务对象只保留一个交互式工作台
|
||||
|
||||
- PC/移动填写态、审批态和非参与人只读态共享同一“明细 + 所属票据”组件及字段顺序。
|
||||
- 填写态的新增、编辑、删除、关联和恢复动作通过显式能力与回调注入;审批/只读模式不渲染这些能力。
|
||||
- 删除被共享组件替代的旧明细表格、旧材料对应展示或重复只读布局,不保留永久双实现兜底。
|
||||
- 报销详情的主内容顺序在 `edit`、`readonly`、`approval` 三种模式中一致:紧凑报销头 → 明细及所属票据 → 未归属票据 → 补充附件 → 必要检查/差异 → 处理历史或处理进度。
|
||||
- PC 宽屏使用主列证据 + 右侧单一 sticky 动作区;窄屏和移动采用同一内容顺序的卡片/分区详情布局,动作区转到底部且不遮挡内容。PC 与移动不强求同一份 DOM,不得用密集的 `isMobile` 业务分支把两种布局重新耦合成巨型壳。
|
||||
- `/workflow/tasks/:taskId` 保留为审批入口和浏览器地址。任务解析为 `reimbursement` 后由报销审批适配器渲染工作台;不得先渲染通用报销摘要再嵌入工作台,也不得要求用户点击“查看报销单”才能取得核心内容。
|
||||
- `/reimbursements/:reimbursementId` 使用同一工作台。参与人处于 `draft/rejected` 时获得编辑能力;其他获准查看者只得到只读能力。
|
||||
- “打开完整原始表单”不再作为独立核心内容页面入口;打印/PDF 仍通过专用打印路由提供。
|
||||
|
||||
### R2 票据抽屉围绕当前明细工作
|
||||
### R2 壳与模式适配器必须严格分层
|
||||
|
||||
- 员工可从明细就近添加/选择 PDF 发票,查看已关联票据和解除自己可维护状态下的关联。
|
||||
- 整单补充附件仍独立,不伪装成明细票据。
|
||||
- 未归属票据有明确恢复入口;不得要求员工依赖操作顺序或跳到另一大区寻找。
|
||||
- PC/移动布局壳只接收同一份已经计算完成的展示模型、区块内容和 capability/action slots,分别负责各端布局、响应式结构和语义标题;内容顺序和业务组件合同不得分叉。
|
||||
- 工作台壳不得调用 `useQuery`、`useMutation` 或 API;不得持有编辑、审批、权限、状态机、票据上传或错误恢复等业务状态;不得根据 `mode` 决定是否发请求。
|
||||
- 壳内不以 `roleCodes`、permission code、workflow 状态、报销状态或 `if (mode === ...)` 推导业务能力。模式差异由适配器注入了什么数据、capability 和 action slot 体现。
|
||||
- `edit` 适配器拥有参与人判断、`draft/rejected` 状态、表头/明细/票据/附件维护状态和 mutation、提交前检查及 B2 错误恢复。
|
||||
- 任务路由边界唯一获取用于授权和实体分派的 workflow task detail,并把同一份查询结果及受控刷新入口移交给 `approval` 适配器;不得为分派和审批内容各发一次相同 task detail 请求。
|
||||
- `approval` 适配器拥有 workflow task detail 的业务解释、allowed actions、提交快照、审批 mutation、刷新策略、fail-closed、退回引用、处理历史与联网要求;不得获得报销维护 mutation。
|
||||
- `readonly` 适配器只执行获准的只读查询和材料查看,不注入新增、编辑、删除、关联、解绑、提交或审批能力。
|
||||
- 共享投影和展示组件接收显式最小字段或纯展示模型,不接收完整 Prisma/API 记录,也不在组件内部判断角色。
|
||||
|
||||
### R3 提交前检查进入填写路径
|
||||
### R3 通用审批页的报销旧分支必须删除
|
||||
|
||||
- 在填写过程中持续显示明细完整性、票据关联、票面金额证据和需人工核对摘要。
|
||||
- 提交动作前展示与服务端 B2 一致的检查结果;服务端仍为权威,前端不得自行放宽。
|
||||
- 错误就近落到明细/票据,汇总区只告诉员工还有几项及如何到达,不只在页面顶部报错。
|
||||
- PC `WorkflowTaskDetailPage` 中报销专用的六字段 `DetailField`、报销证据区、提交/当前检查区、报销右栏计数和报销审批动作接线,在新工作台路由生效后全部删除。
|
||||
- 移动 `MobileApprovalsPage` 中对应的报销详情、证据、检查和报销 fail-closed UI 分支迁入审批适配器后删除。
|
||||
- 通用审批页只保留请假、补卡、采购、差旅等现有实体的通用投影与动作,不保留休眠报销路径、隐藏兜底或复制文案“以防万一”。
|
||||
- 最终结构检查必须证明通用审批页不再导入报销证据组件、不再包含报销检查文案,也不再根据 `entityType === "reimbursement"` 渲染业务内容。该检查与壳层禁用 API/权限/模式判断的检查必须实现于 `scripts/qa/check-ui-design-rules.mjs`,由部署 preflight 的 `--strict` 门禁执行,不得仅存在于单测。
|
||||
- 任务类型分派层可以识别 `reimbursement` 并选择适配器;它只负责路由,不得重新实现报销摘要或决策逻辑。
|
||||
|
||||
### R4 填写与审批语义一致
|
||||
### R4 信息必须按审批人决策需要收敛
|
||||
|
||||
- 发生日期不默认等于发票日期;跨天/跨期同一业务可作为一条明细并写明起止日期。
|
||||
- 系统不自动判断明细是否应拆分,页面把它表达为填报要求和财务复核项。
|
||||
- 需票明细、无票补助、manual review 和金额不可用继续遵守现有业务事实源及 B2 合同。
|
||||
1. 顶部只显示报销单号、状态、报销人、日期、合计;事由作为紧接标题的正文展示。不得再用六张字段卡重复下面已经出现的信息,也不显示“业务类型=报销”等自明字段。
|
||||
2. 主列直接进入明细和所属票据;附件随后展示。相同报销头、事由、票据或检查事实不得在不同区块重复完整表达。
|
||||
3. 正常项不解释、不计数。只有存在异常或人工决策需要时才显示提示,并就近说明“对象、原因、影响、下一步”;不得默认平铺“0 条”状态或仅显示无法定位对象的总数。
|
||||
4. 提交时快照与当前票据事实一致时,不并排展示两个“检查摘要”;只有出现异常、快照缺失或时间语义差异时才显示必要内容。
|
||||
5. 历史提交缺少预算快照时,以低强调度说明“该次提交未留存预算快照”;它不得使用告警视觉冒充当前业务异常,也不得用实时预算结果补写历史。
|
||||
6. PC 右栏只保留当前节点/状态、是否可决策、异常锚点和审批动作。报销合计如已在顶部清晰可见,不在右栏重复;创建/发起/完成等时间进入处理历史或按需展开,不平铺为决策摘要。
|
||||
7. “退回”和“驳回”的后果说明只在用户展开相应动作或进入确认时出现;默认右栏不常驻解释卡。错误和提交结果继续提供明确反馈,不能为了降噪删除必要恢复信息。
|
||||
- 警告不得只依赖颜色;标题层级、DOM 顺序和读屏顺序必须与视觉顺序一致。
|
||||
|
||||
### R5 编辑态围绕明细完成票据维护与提交恢复
|
||||
|
||||
- `edit` 适配器向同一明细—票据组件注入新增、编辑、删除、上传/选择 PDF 发票、关联、解绑和未归属恢复能力。
|
||||
- 员工可在当前明细上下文内查看和维护所属票据;未归属票据直接提供选择明细的恢复入口,不依赖口头操作顺序或跳到独立材料区。
|
||||
- 整单补充附件继续作为独立证据,不伪造与某条明细的结构化关系。
|
||||
- 填写过程中持续计算可解释的提交前检查;汇总区只提示仍有多少可操作问题并提供锚点,具体错误就近落到明细或票据。
|
||||
- 服务端 B2 门禁继续为权威。前端不得因工作台迁移放宽 `ocr_failed`、manual review、金额超票面、缺票或未归属合同。
|
||||
- 发生日期不取发票日期;系统不自动决定业务是否应拆分,页面继续按既有业务事实源提示员工和财务人工复核。
|
||||
|
||||
### R6 审批态保留快照、实时事实与 fail-closed
|
||||
|
||||
- 费用标准/预算使用 workflow 提交快照;票据归属、金额证据和附件使用当前实时报销详情。两者不得互相替代。
|
||||
- 完整报销内容、关键当前检查或提交快照解析未就绪时,通过、退回、驳回、转审和报销离线草稿均不可执行;动作入口除禁用外仍有中文原因。
|
||||
- 审批适配器只注入查看原件、查看附件、引用到退回意见及 workflow 决策能力,不注入报销维护能力。
|
||||
- 报销证据继续排除在移动 IndexedDB workflow cache 之外;其他审批类型的离线草稿能力保持不变。
|
||||
- 已处理任务查看当前报销版本时保留时间语义提示;历史意见和提交快照不被当前内容覆盖。
|
||||
|
||||
### R7 路由、权限与回退必须保持稳定
|
||||
|
||||
- 通用任务路由以一次已授权 task detail 查询选择报销或非报销渲染器,并把该查询结果移交所选渲染器继续使用。非参与人不能从分派错误、报销加载状态或材料错误推断无权对象信息。
|
||||
- 报销详情、票据、附件、短时材料 URL 和审批动作继续使用既有后端授权、用途审计和状态机;本任务不以纯前端隐藏替代服务端校验。
|
||||
- PC/移动从待办列表进入、刷新、浏览器返回、深链打开和已处理任务查看均保持可预测;工作台返回目标由入口上下文决定,不形成“返回审批详情 → 又回到同一工作台”的循环。
|
||||
- 页面级加载失败显示重试和安全返回;单个材料加载失败只影响该材料,不清空已加载证据。
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] PC/移动填写态使用 B-2a 同一业务内容组件,审批/只读/编辑模式只在能力和动作上不同。
|
||||
- [ ] 员工可在明细上下文内完成票据添加、归属查看和错误恢复,不再依赖“先明细、后整单材料区”的隐含顺序。
|
||||
- [ ] 提交前检查与服务端 B2 结果一致,错误就近显示且再次提交链路可完成。
|
||||
- [ ] 旧重复布局和不再使用的展示分支被删除;父任务不存在三套并行内容结构。
|
||||
- [ ] PC/移动、参与人/非参与人、draft/rejected/reviewing 状态矩阵通过,既有票据/附件权限无回归。
|
||||
- [ ] 公网部署和真实员工重提反馈通过后,父任务才可归档。
|
||||
- [ ] AC1:PC 与移动的 `edit`、`readonly`、`approval` 使用同一展示模型、区块顺序、明细—票据语义组件和 capability 契约;PC 可使用右栏 sticky 布局壳,移动可使用卡片 + 底部动作布局壳,不要求同一份 DOM,模式差异只来自适配器注入的数据与能力。
|
||||
- [ ] AC2:PC/移动布局壳中 `useQuery`、`useMutation`、API 调用、角色/权限判断、workflow/报销状态机判断和 `if (mode === ...)` 业务分支均为 0;`scripts/qa/check-ui-design-rules.mjs --strict` 静态扫描并报 error,且该命令作为部署 preflight 执行。
|
||||
- [ ] AC3:`WorkflowTaskDetailPage` 与 `MobileApprovalsPage` 的报销业务渲染分支、六字段摘要、重复检查区和休眠兜底全部删除;通用审批页仍通过非报销回归。
|
||||
- [ ] AC4:报销审批首屏只有一套紧凑报销头;事由、明细、所属票据、附件、异常和历史各有唯一主展示位置,不再出现两套摘要或四处检查计数。
|
||||
- [ ] AC5:无异常时不显示“0 条”检查卡或常驻退回/驳回解释;异常时每条提示可定位到具体明细/票据,包含原因、影响和下一步。快照/实时不一致时才额外显示差异。
|
||||
- [ ] AC6:PC 右栏只含决策所需状态、异常锚点和单一动作区;窄屏/移动动作区不遮挡内容,触控区域不小于 44×44,键盘和读屏顺序正确。
|
||||
- [ ] AC7:员工可在明细上下文完成新增/编辑/删除、PDF 发票添加、关联/解绑、未归属恢复、提交阻断修复和再次提交;服务端 B2 结果仍为最终权威。
|
||||
- [ ] AC8:审批内容或快照失败时所有报销决策 fail-closed;审批适配器没有任何报销维护能力;readonly 适配器没有编辑或审批能力。
|
||||
- [ ] AC9:报销证据不进入 IndexedDB;非报销审批离线草稿基线、PC/移动非报销详情和 workflow 状态机均无回归。
|
||||
- [ ] AC10:参与人/非参与人、`draft/rejected/reviewing`、pending/已处理任务和材料权限矩阵通过;没有新增 schema、migration、flag、seed 或生产数据改写。
|
||||
- [ ] AC11:生产部署后使用公网真实 bundle + 合成 API 完成三模式、失败关闭和离线验收;真实员工重提反馈记录后,父任务才允许归档。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- 自动从票据推断发生日期或业务拆分正确性。
|
||||
- 结构化退回原因和统计模型。
|
||||
- 财务代员工编辑、批量改票或新审批状态。
|
||||
- 与 B-2a 同批部署;本任务必须是独立候选、独立回滚点。
|
||||
- 请假、补卡、采购、差旅改造成“业务对象页 + 审批模式”;它们继续使用通用审批详情。
|
||||
- `/reimbursements/:id/print` 打印/PDF 页面重构。该页面是格式化交付视图,不是交互式工作台;本任务有意保留其独立布局,但不得把它当作编辑/只读/审批的第四套交互实现,也不得向其中复制工作台 mutation。
|
||||
- 自动从发票推断发生日期、自动判断业务拆分正确性或替财务作真实性结论。
|
||||
- 结构化退回原因、统计模型、财务代员工编辑、批量改票或新审批状态。
|
||||
- 修改 workflow 状态机、B2 flag、付款流程、数据库 schema、生产配置或真人单据。
|
||||
- 为当前冗余页面单独发布临时删减版;信息收敛随 B-2b 独立候选一次交付。
|
||||
|
||||
## Test Plan
|
||||
|
||||
- 组件/纯函数:review/readonly/edit 三模式字段顺序一致,能力注入不向只读视角泄漏维护动作。
|
||||
- Playwright:PC/移动 participant 与 nonparticipant 的 draft/rejected/reviewing 矩阵,覆盖票据抽屉、未归属恢复、提交阻断和再次提交。
|
||||
- 后端:复跑 B2 票据门禁、报销参与人授权、票据 bind/unbind/link 与材料预览聚焦套件;本任务原则上不改后端合同。
|
||||
- 前端:typecheck/build、UI strict/self-test、代表性视口、键盘/读屏焦点和固定操作区遮挡检查。
|
||||
- 治理:task validate、process contract、Trellis governance、敏感内容检查、`git diff --check`;部署和公网验证另行批准。
|
||||
- 结构边界:`check-ui-design-rules.mjs --strict` 扫描 PC/移动布局壳,禁止 query/mutation/API/角色/状态机/mode 请求分支,并扫描通用审批页报销分支和旧文案为 0;三适配器能力集合另做组件/类型验证。
|
||||
- 纯函数/组件:统一报销头、明细—票据投影、异常过滤、快照/实时差异、异常锚点和 capability 注入覆盖正常/异常/缺失边界。
|
||||
- PC/移动 Playwright:三模式内容顺序;无异常降噪;异常就近文案;右栏/底部动作;票据抽屉;未归属恢复;B2 阻断后修复并再次提交;退回引用;深链/返回。
|
||||
- 权限/状态:participant/nonparticipant × draft/rejected/reviewing;pending/已处理审批;无权 task、跨单材料、无维护能力和并发关联回归。
|
||||
- 离线:直接读取 IndexedDB 禁存字段/哨兵值;报销动作和草稿 fail-closed;非报销审批离线草稿仍可形成和同步。
|
||||
- 后端:原则上不改合同;复跑 B2 门禁、报销详情只读投影、workflow task detail、材料查看审计、票据 bind/unbind/link 和审批动作聚焦测试。
|
||||
- 前端/治理:typecheck、build、UI strict/self-test、route manifest、相关 Playwright、process contract、Trellis governance、敏感内容检查、docs registry(如改事实源)和 `git diff --check`。
|
||||
- 部署:另行批准独立候选;切换前 UI strict;部署后核 `/ready`、bundle marker、公网文案、三模式合成路径、B2 状态和真人单据状态不变。
|
||||
|
||||
## Planning Note
|
||||
## Risks and Deferred Items
|
||||
|
||||
本子任务当前只冻结迁移承诺和验收边界。详细 `design.md` / `implement.md` 在 B-2a 真人反馈回填后编写,避免在共享组件尚未验证前固化票据抽屉交互。
|
||||
- 大型旧页面拆分容易在中间阶段形成双实现;允许在开发分支短暂并存,但最终候选必须通过旧分支为 0 的结构门禁。
|
||||
- task 路由先取元数据再分派可能产生加载闪烁;设计必须用稳定骨架而不是先渲染通用页再切换。
|
||||
- 打印页继续独立,未来如字段语义漂移可另建“打印投影复用”任务;本轮不扩大交付面。
|
||||
- 全局错误色 token、部署脚本 `--no-deps`、`.claude` gitignore 和其他治理债不并入本任务。
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"id": "reimbursement-form-shared-component-migration",
|
||||
"name": "reimbursement-form-shared-component-migration",
|
||||
"title": "B-2b 报销填写态共享组件迁移",
|
||||
"description": "在 B-2a 真人反馈后,把 PC/移动填写态迁入同一明细票据组件并删除重复旧布局。",
|
||||
"status": "planning",
|
||||
"title": "B-2b 统一报销工作台迁移",
|
||||
"description": "把 PC/移动报销编辑、只读、审批收敛为一个工作台壳和三个能力适配器,并删除通用审批页的报销旧分支。",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": "client,spec",
|
||||
"scope": "client,workflow,spec",
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "shunli",
|
||||
@@ -21,6 +21,6 @@
|
||||
"children": [],
|
||||
"parent": "09-01-reimbursement-one-page-approval-workbench",
|
||||
"relatedFiles": [],
|
||||
"notes": "父任务第二阶段;B-2a 部署和真人反馈是启动条件,当前只冻结迁移承诺与验收边界。",
|
||||
"notes": "父任务第二阶段;B-2a 已部署并取得真人目视反馈。规划采用方案 A:仅报销进入业务对象工作台审批模式,其他 workflow 实体保持通用详情。实现与本地全量门禁已完成,待用户最终 diff 复核后提交;尚未 push、部署或触碰真人单据。",
|
||||
"meta": {}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,16 @@ Workflow task shell
|
||||
+ approval decision panel
|
||||
|
||||
B-2b
|
||||
Existing reimbursement form shell
|
||||
+ same shared item/evidence component (edit mode)
|
||||
+ invoice drawer
|
||||
+ submit preflight summary
|
||||
Authorized task/reimbursement route dispatch
|
||||
-> edit / readonly / approval adapters
|
||||
-> one stateless reimbursement workspace shell
|
||||
+ same shared item/evidence component
|
||||
+ invoice drawer + submit preflight
|
||||
- generic workflow reimbursement branches
|
||||
- retired legacy item/material duplication
|
||||
```
|
||||
|
||||
共享边界选在“明细 + 挂在明细下的票据”,而不是复用整个旧 `ReimbursementDetailPage`。旧页面混有填写 mutation、权限判断、材料上传、处理进度和操作面板,直接嵌入审批页会把报销人维护能力与审批职责再次耦合。
|
||||
共享边界在 B-2a 先选为“明细 + 挂在明细下的票据”;真人目视反馈后,B-2b 把它上升为唯一交互式报销工作台。旧 `ReimbursementDetailPage` 的查询、mutation、权限判断和编辑状态进入 edit adapter,workflow task、审批 mutation 与 fail-closed 进入 approval adapter,只读查询进入 readonly adapter;工作台壳只负责编排已经计算好的展示模型和 capability/action slots。
|
||||
|
||||
## 2. Data Authority Matrix
|
||||
|
||||
@@ -50,14 +52,13 @@ type ReimbursementItemEvidenceModel = {
|
||||
type ReimbursementItemEvidenceListProps = {
|
||||
models: ReimbursementItemEvidenceModel[];
|
||||
unlinkedInvoices: ReimbursementInvoiceEvidence[];
|
||||
mode: "review" | "edit" | "readonly";
|
||||
onOpenInvoice: (invoiceId: string) => void;
|
||||
onReferenceReturn?: (reference: ReturnReference) => void;
|
||||
editCapabilities?: ReimbursementEvidenceEditCapabilities;
|
||||
};
|
||||
```
|
||||
|
||||
分组、文案和检查映射由纯函数完成,页面容器只负责查询、mutation、导航和动作面板。`editCapabilities` 在 B-2a 不启用,B-2b 再接入,避免审批页出现维护分支。
|
||||
分组、文案和检查映射由纯函数完成。B-2a 页面容器暂时负责查询、mutation、导航和动作面板;B-2b 将这些职责迁入三种适配器,唯一工作台壳不得拥有 query/mutation/角色/状态机判断。`editCapabilities` 在 B-2a 不启用,B-2b 只由 edit adapter 接入,避免审批/只读视角出现维护分支。
|
||||
|
||||
## 4. Responsive Page Structure
|
||||
|
||||
@@ -118,7 +119,8 @@ B-2a 客户端在 workflow task 已授权后读取现有报销详情 API,复
|
||||
|
||||
- B-2a 保留完整原始表单入口作为降级路径;核心核验不得依赖它。
|
||||
- B-2a 不删除旧填写组件,只新增共享组件的 review/readonly 能力。
|
||||
- B-2b 接入 edit 能力后删除被替代布局;不长期维护双实现。
|
||||
- B-2b 接入三种适配器后删除被替代布局,并删除 PC/移动通用审批页的报销业务分支;不长期维护双实现或运行时 feature flag。
|
||||
- `/reimbursements/:id/print` 保持专用打印布局,不纳入三模式交互壳,只做不误伤回归。
|
||||
- 旧 workflow 无预算快照兼容为 null。
|
||||
- 当前已处理任务展示实时内容时加版本提示,避免历史误读。
|
||||
|
||||
|
||||
@@ -20,15 +20,15 @@
|
||||
采用“先审批、后填写迁移”的 B 路线,并拆成两次可独立验收的交付:
|
||||
|
||||
1. **B-2a 报销审批内容工作台**:建立共享的“明细 + 所属票据”只读/核验组件,先接入 PC 和移动审批页;审批人无需跳转即可取得决策所需内容。
|
||||
2. **B-2b 报销填写态共享组件迁移**:在 B-2a 真人使用反馈稳定后,把 PC/移动填写态迁移到同一组件,并完成票据抽屉、提交前检查和旧只读布局收口。
|
||||
2. **B-2b 统一报销工作台迁移**:根据 B-2a 真人目视反馈,把 PC/移动编辑、只读、审批收敛为一个纯布局工作台壳和三个能力适配器,并完成票据抽屉、提交前检查、信息降噪及旧页面分支删除。
|
||||
|
||||
B-2a 完成时允许旧填写态暂时存在;B-2b 是本父任务的必交子任务,不得以“以后优化”关闭父任务。父任务只有在填写态迁移完成、旧重复内容布局被删除或明确退役后才能归档为完成。
|
||||
B-2a 完成时允许两套交互式页面壳暂时存在;B-2b 是本父任务的必交子任务,不得以“以后优化”关闭父任务。父任务只有在三种模式使用唯一报销工作台、通用审批页报销分支和旧重复布局均被删除后才能归档为完成。专用打印/PDF 页面是有意排除的格式化交付视图,不计作第四种交互模式。
|
||||
|
||||
## Scope
|
||||
|
||||
- 父任务负责两阶段交付合同、共享组件边界、快照/实时数据口径、跨子任务验收和最终旧布局收口。
|
||||
- 父任务负责两阶段交付合同、唯一工作台边界、快照/实时数据口径、跨子任务验收和最终旧布局收口。
|
||||
- B-2a 负责 PC/移动审批一页式内容工作台与共享组件 review/readonly 能力。
|
||||
- B-2b 负责 PC/移动填写态迁移、票据抽屉、提交前检查和重复布局删除。
|
||||
- B-2b 负责唯一工作台壳、edit/readonly/approval 适配器、票据抽屉、提交前检查、通用审批页报销分支删除和信息收敛。
|
||||
- 两个子任务分别形成候选、部署和回滚点;父任务不直接承载业务代码实施。
|
||||
|
||||
## Product Requirements
|
||||
@@ -39,12 +39,13 @@ B-2a 完成时允许旧填写态暂时存在;B-2b 是本父任务的必交子
|
||||
- “查看报销单”降级为“打开完整原始表单/打印视图”的次要入口,用于少见的完整字段追溯,不再承担核心内容可达性。
|
||||
- 非报销审批类型保持当前各自投影,本父任务不借机重构请假、采购、差旅或考勤审批。
|
||||
|
||||
### R2 共享内容组件必须有明确迁移终点
|
||||
### R2 共享内容组件必须收敛为唯一工作台
|
||||
|
||||
- B-2a 建立的共享件以业务数据和交互能力为边界,不依赖 `WorkflowTaskDetailPage` 或审批状态;至少覆盖“明细 + 关联票据 + 行内核验提示”。
|
||||
- PC 与移动审批使用同一语义组件和字段顺序,只允许响应式布局和操作容器不同。
|
||||
- B-2b 必须让 PC/移动填写态采用同一组件;编辑、删除、关联等维护动作通过显式能力/回调注入,不复制一套填写专用展示结构。
|
||||
- B-2b 完成后,不得继续保留“旧填写态、新审批态、旧只读态”三套并行布局。
|
||||
- B-2b 必须让 PC/移动编辑、只读、审批采用同一纯布局工作台壳和同一业务内容顺序;查询、状态、mutation、权限和 fail-closed 全部归各模式适配器。
|
||||
- 工作台壳不得根据 mode、角色、权限或业务状态发请求或推导能力;编辑、删除、关联、审批等动作只通过显式 capability/action slot 注入。
|
||||
- B-2b 完成后,不得继续保留“旧填写态、新审批态、旧只读态”三套并行布局,也不得在 PC/移动通用审批页保留休眠报销业务分支。
|
||||
|
||||
### R3 快照事实与实时事实分层展示
|
||||
|
||||
@@ -93,13 +94,14 @@ B-2a 完成时允许旧填写态暂时存在;B-2b 是本父任务的必交子
|
||||
- [ ] 退回可以引用具体明细/票据到现有自由文本意见;本父任务不新增结构化退回原因数据模型。
|
||||
- [ ] PC 只有右侧单一审批动作面板,完整流程/历史位于主列靠后;窄屏和移动才把同一动作面板转到底部,多个动作不竖向铺卡片。
|
||||
- [ ] 报销审批离线时不能形成任何审批动作或草稿,且离线缓存中不存在明细、票据、附件或材料访问证据;其他审批类型离线合同不变。
|
||||
- [ ] B-2b 完成后,填写态、审批态和只读态共享同一业务内容组件,不再保留三套漂移布局。
|
||||
- [ ] B-2b 完成后,编辑、审批和只读共享同一无业务状态的工作台壳;通用 PC/移动审批页报销分支和旧重复布局为 0。
|
||||
- [ ] 两次交付分别通过各自的前后端、PC/移动、无障碍、文案、权限和部署验证;生产部署与真人数据写入仍需单独批准。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- 一次性同时重写审批态和填写态。
|
||||
- 把已上线的 B-2a 与 B-2b 合并成一次候选或一次回滚点;B-2b 仍必须独立规划、验证和部署。
|
||||
- 请假、采购、差旅申请、考勤等其他业务的审批内容重构。
|
||||
- `/reimbursements/:id/print` 打印/PDF 视图重构;它保持独立纸面布局,但不得承担交互式工作台职责。
|
||||
- 结构化退回原因 schema、统计报表、数据库 migration。
|
||||
- 修改审批角色、审批规则、状态机、B2 flag 或付款流程。
|
||||
- 自动判断明细日期粒度、业务是否应拆分或费用是否真实合理。
|
||||
|
||||
在新工单中引用
屏蔽一个用户