docs(P21PWA2-4,P21PWA2-5): PWA-2矩阵边界回归清单收口

这个提交包含在:
2026-03-12 12:34:56 +08:00
父节点 9112383d23
当前提交 6ec091eed3
共修改 4 个文件,包含 98 行新增和 39 行删除
+11 -4
查看文件
@@ -1,8 +1,8 @@
# hyb-oa 实现状态矩阵(P5-P19+IM-1+ERP-3+R10+MCP-1+AI-1+TRAVEL-1+TRAVEL-2+TRAVEL-3+PWA-1)
# hyb-oa 实现状态矩阵(P5-P19+IM-1+ERP-3+R10+MCP-1+AI-1+TRAVEL-1+TRAVEL-2+TRAVEL-3+PWA-1+PWA-2)
**快照日期**:2026-03-11
**范围**:`F1-F42`(含 `F19b/F19c/F19d`)+ `R1-S2` + `P9A1-P9D1` + `P10E1-P10G1` + `G0-G6` + `H1` + `M1-M4` + `P13-0-P13-8` + `P14-0-P14-8` + `P15A-0-P15A-5` + `P15B-0-P15B-6` + `P16A-0-P16A-6` + `P16B-0-P16B-6` + `P16C-0-P16C-6` + `R9-0-R9-3` + `G2-0-G2-6` + `P17A-0-P17A-6` + `P17B-0-P17B-6` + `P18A-0-P18A-6` + `P18B-0-P18B-6` + `P19-0-P19-6` + `P19IM1-0-P19IM1-6` + `P19ERP1-0-P19ERP1-6` + `P19ERP2-0-P19ERP2-6` + `P19ERP3-0-P19ERP3-6` + `R10-0-R10-4` + `P19MCP1-0-P19MCP1-4` + `P19AI1-0-P19AI1-5` + `P20TRAVEL1-0-P20TRAVEL1-5` + `P20TRAVEL2-0-P20TRAVEL2-5` + `P20TRAVEL3-0-P20TRAVEL3-5` + `P21PWA1-0-P21PWA1-5`,共 260 项。
**事实源**:`issues/2026-02-09_13-39-02-p5-blueprint-v3.csv` + `issues/2026-02-09_23-30-00-p6-p8-remaining-work-master.csv` + `issues/2026-02-10_09-42-31-p9-maintenance-performance-matrix.csv` + `issues/2026-02-10_10-35-30-p10-production-hardening.csv` + `issues/2026-02-11-p11-p12-governance-mobile.csv` + `issues/2026-02-12_01-09-41-p13-l5-governance.csv` + `issues/2026-02-13_00-11-56-p14-l5-operationalization.csv` + `issues/2026-03-06_14-30-00-p15a-l5-permission-decouple.csv` + `issues/2026-03-06_14-30-00-p15b-l5-leave-v1.csv` + `issues/2026-03-07_13-47-05-p16a-l5-master-data-core.csv` + `issues/2026-03-07_16-22-07-p16b-l5-holiday-calendar.csv` + `issues/2026-03-07_17-14-39-p16c-l5-suppliers.csv` + `issues/2026-03-07_18-15-03-r9-g2-p19-roadmap-refresh.csv` + `issues/2026-03-07_18-16-00-g2-l5-cross-domain-bridge.csv` + `issues/2026-03-07_19-33-09-p17a-l5-procurement-core.csv` + `issues/2026-03-07_21-00-37-p17b-l5-procurement-budget-archive.csv` + `issues/2026-03-07_22-02-09-p18a-l5-asset-registry-core.csv` + `issues/2026-03-07_22-34-03-p18b-l5-asset-movements-inventory.csv` + `issues/2026-03-07_23-22-00-p19-l4-integration-readiness.csv` + `issues/2026-03-08_12-18-10-p19-im-1-l5-collaboration-adapter.csv` + `issues/2026-03-08_14-10-53-p19-erp-1-l5-masterdata-journal-bridge.csv` + `issues/2026-03-08_22-46-51-p19-erp-2-l5-procurement-commitment-archive.csv` + `issues/2026-03-09_00-10-00-p19-erp-3-l5-asset-ledger-summary.csv` + `issues/2026-03-09_10-15-00-r10-post-erp3-roadmap-refresh.csv` + `issues/2026-03-09_10-25-00-p19-mcp-1-l4-readonly-tools-baseline.csv` + `issues/2026-03-10_12-54-30-p19-ai-1-l5-suggestion-workbench-refresh.csv` + `issues/2026-03-10_17-32-21-p20-travel-1-l5-request-intake-refresh.csv` + `issues/2026-03-10_21-05-59-p20-travel-2-l5-corporate-payments-refresh.csv` + `issues/2026-03-11_09-57-28-p20-travel-3-l5-reconciliation-erp-bridge-refresh.csv` + `issues/2026-03-11_17-50-39-p21-pwa-1-l5-asset-scan-refresh.csv`(执行合同)
**快照日期**:2026-03-12
**范围**:`F1-F42`(含 `F19b/F19c/F19d`)+ `R1-S2` + `P9A1-P9D1` + `P10E1-P10G1` + `G0-G6` + `H1` + `M1-M4` + `P13-0-P13-8` + `P14-0-P14-8` + `P15A-0-P15A-5` + `P15B-0-P15B-6` + `P16A-0-P16A-6` + `P16B-0-P16B-6` + `P16C-0-P16C-6` + `R9-0-R9-3` + `G2-0-G2-6` + `P17A-0-P17A-6` + `P17B-0-P17B-6` + `P18A-0-P18A-6` + `P18B-0-P18B-6` + `P19-0-P19-6` + `P19IM1-0-P19IM1-6` + `P19ERP1-0-P19ERP1-6` + `P19ERP2-0-P19ERP2-6` + `P19ERP3-0-P19ERP3-6` + `R10-0-R10-4` + `P19MCP1-0-P19MCP1-4` + `P19AI1-0-P19AI1-5` + `P20TRAVEL1-0-P20TRAVEL1-5` + `P20TRAVEL2-0-P20TRAVEL2-5` + `P20TRAVEL3-0-P20TRAVEL3-5` + `P21PWA1-0-P21PWA1-5` + `P21PWA2-0-P21PWA2-5`,共 266 项。
**事实源**:`issues/2026-02-09_13-39-02-p5-blueprint-v3.csv` + `issues/2026-02-09_23-30-00-p6-p8-remaining-work-master.csv` + `issues/2026-02-10_09-42-31-p9-maintenance-performance-matrix.csv` + `issues/2026-02-10_10-35-30-p10-production-hardening.csv` + `issues/2026-02-11-p11-p12-governance-mobile.csv` + `issues/2026-02-12_01-09-41-p13-l5-governance.csv` + `issues/2026-02-13_00-11-56-p14-l5-operationalization.csv` + `issues/2026-03-06_14-30-00-p15a-l5-permission-decouple.csv` + `issues/2026-03-06_14-30-00-p15b-l5-leave-v1.csv` + `issues/2026-03-07_13-47-05-p16a-l5-master-data-core.csv` + `issues/2026-03-07_16-22-07-p16b-l5-holiday-calendar.csv` + `issues/2026-03-07_17-14-39-p16c-l5-suppliers.csv` + `issues/2026-03-07_18-15-03-r9-g2-p19-roadmap-refresh.csv` + `issues/2026-03-07_18-16-00-g2-l5-cross-domain-bridge.csv` + `issues/2026-03-07_19-33-09-p17a-l5-procurement-core.csv` + `issues/2026-03-07_21-00-37-p17b-l5-procurement-budget-archive.csv` + `issues/2026-03-07_22-02-09-p18a-l5-asset-registry-core.csv` + `issues/2026-03-07_22-34-03-p18b-l5-asset-movements-inventory.csv` + `issues/2026-03-07_23-22-00-p19-l4-integration-readiness.csv` + `issues/2026-03-08_12-18-10-p19-im-1-l5-collaboration-adapter.csv` + `issues/2026-03-08_14-10-53-p19-erp-1-l5-masterdata-journal-bridge.csv` + `issues/2026-03-08_22-46-51-p19-erp-2-l5-procurement-commitment-archive.csv` + `issues/2026-03-09_00-10-00-p19-erp-3-l5-asset-ledger-summary.csv` + `issues/2026-03-09_10-15-00-r10-post-erp3-roadmap-refresh.csv` + `issues/2026-03-09_10-25-00-p19-mcp-1-l4-readonly-tools-baseline.csv` + `issues/2026-03-10_12-54-30-p19-ai-1-l5-suggestion-workbench-refresh.csv` + `issues/2026-03-10_17-32-21-p20-travel-1-l5-request-intake-refresh.csv` + `issues/2026-03-10_21-05-59-p20-travel-2-l5-corporate-payments-refresh.csv` + `issues/2026-03-11_09-57-28-p20-travel-3-l5-reconciliation-erp-bridge-refresh.csv` + `issues/2026-03-11_17-50-39-p21-pwa-1-l5-asset-scan-refresh.csv` + `issues/2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv`(执行合同)
**说明**:
- 本矩阵用于全局读图(审计/交接/回归覆盖追踪),不替代 `issues/*.csv` 的执行合同职责。
@@ -302,3 +302,10 @@
| P21PWA1-3 | 盘点录入模式与离线队列联动 | N/A | 2026-03-09_11-15-00-p21-pwa-1-l5-asset-scan.csv | 2026-03-11_17-50-39-p21-pwa-1-l5-asset-scan-refresh.csv | 2026-03-11 | DONE | server:test + client:typecheck/build | `inventoryCheckId` 模式支持 draft 启动、counting 录入、completed 只读,以及 IndexedDB 离线队列 last-write-wins 重放 |
| P21PWA1-4 | PWA一期文档边界与矩阵同步 | N/A | 2026-03-09_11-15-00-p21-pwa-1-l5-asset-scan.csv | 2026-03-11_17-50-39-p21-pwa-1-l5-asset-scan-refresh.csv | 2026-03-11 | DONE | validate-feature-matrix | 集成边界、PWA 回归清单、Feature Matrix 与事实源校验器同步到 `...+PWA-1`,并明确不做原生壳 / 深链 / 完整离线同步 |
| P21PWA1-5 | P21PWA1回归与验收收口 | N/A | 2026-03-09_11-15-00-p21-pwa-1-l5-asset-scan.csv | 2026-03-11_17-50-39-p21-pwa-1-l5-asset-scan-refresh.csv | 2026-03-11 | DONE | server:test + regression-all + client:typecheck/build + validate-feature-matrix | 移动扫码、盘点录入、离线重放与权限边界回归通过,矩阵推进到 260 并为 `P21+PWA-2` 留出干净合同起点 |
| P21PWA2-0 | P21PWA2执行合同刷新与主线最终冻结 | N/A | 2026-03-09_11-25-00-p21-pwa-2-l5-offline-deeplink.csv | 2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv | 2026-03-12 | DONE | CSV 校验 | 以 superseding CSV 刷新 PWA-2 执行合同,冻结 canonical workflow deep link、离线守卫、本地草稿与 R10 主线最终里程碑 |
| P21PWA2-1 | 移动审批深链入口与离线守卫快照 | N/A | 2026-03-09_11-25-00-p21-pwa-2-l5-offline-deeplink.csv | 2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv | 2026-03-12 | DONE | client:typecheck/build | `/workflow/tasks/:taskId` 保持 canonical,客户端在移动 / PWA / IM WebView 下自动分流到 `/mobile/approvals?taskId=<id>`,并引入仅含 `me + permissions` 的 24h 离线快照 |
| P21PWA2-2 | 移动审批approve/reject离线草稿队列 | N/A | 2026-03-09_11-25-00-p21-pwa-2-l5-offline-deeplink.csv | 2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv | 2026-03-12 | DONE | client:typecheck/build | `MobileApprovalsPage` 支持 `taskId` deep link、已缓存详情离线查看与 `approve/reject` 草稿 last-write-wins 重放,`already_processed` / 403 / 404 明确进入冲突态 |
| P21PWA2-3 | PWA缓存策略升级与IndexedDB helper收口 | N/A | 2026-03-09_11-25-00-p21-pwa-2-l5-offline-deeplink.csv | 2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv | 2026-03-12 | DONE | client:typecheck/build | `vite-plugin-pwa` runtime cache 升级为静态资源 `StaleWhileRevalidate` + 审批 GET `NetworkFirst`,并新增共享 IndexedDB helper 供上传 / 盘点 / 审批队列复用 |
| P21PWA2-4 | PWA二期文档矩阵与主线闭环同步 | N/A | 2026-03-09_11-25-00-p21-pwa-2-l5-offline-deeplink.csv | 2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv | 2026-03-12 | DONE | validate-feature-matrix | 集成边界、PWA 回归清单、Feature Matrix 与事实源校验器同步到 `...+PWA-2`,矩阵总数推进到 266 并明确 R10 主线闭环 |
| P21PWA2-5 | P21PWA2回归与R10主线最终验收 | N/A | 2026-03-09_11-25-00-p21-pwa-2-l5-offline-deeplink.csv | 2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv | 2026-03-12 | DONE | server:test + regression-all + client:typecheck/build + validate-feature-matrix | 移动 deep link、离线审批草稿、联网重放、权限拒绝、缓存回退与既有 PWA-1 / workflow 主流程回归全部通过,R10 主线正式闭环 |
+20 -13
查看文件
@@ -1,8 +1,8 @@
# 集成边界冻结(P19 / P19+IM-1 / P19+ERP-3 / R10 / P19+MCP-1 / P19+AI-1 / P20+TRAVEL-1 / P20+TRAVEL-2 / P20+TRAVEL-3 / P21+PWA-1)
# 集成边界冻结(P19 / P19+IM-1 / P19+ERP-3 / R10 / P19+MCP-1 / P19+AI-1 / P20+TRAVEL-1 / P20+TRAVEL-2 / P20+TRAVEL-3 / P21+PWA-1 / P21+PWA-2)
**快照日期**:2026-03-11
**当前基线**:`P19+IM-1`、`P19+ERP-1`、`P19+ERP-2`、`P19+ERP-3`、`P19+MCP-1`、`P19+AI-1`、`P20+TRAVEL-1`、`P20+TRAVEL-2`、`P20+TRAVEL-3` 与 `P21+PWA-1` 已完成;当前运行时已落地企微群机器人 + 深链 + Outbox 异步派发的一期协同适配,以及 ERP 主数据 Pull、报销付款凭证切片、采购双阶段 journal / 归档摘要出站、资产台账摘要出站、Postgres MCP 只读工具基线、报销 / 采购 / 资产详情页 AI 只读建议挂件、差旅申请主单 / 行程段 / 审批预算锁定 / `travel_orders` 关联入站、混合双轨对公支付闭环与批次级对账摘要桥的三期差旅基线,以及浏览器 PWA 下的移动资产扫码、盘点快捷录入与离线队列重放。
**目标**:在保持核心域稳定的前提下,冻结 ERP / IM / AI / MCP / TRAVEL / PWA 的长期边界,并记录 IM 一期、ERP 三期、AI 一期、差旅三期与 PWA 一期的已实现范围、禁入规则以及 R10 之后的固定主线顺序。
**快照日期**:2026-03-12
**当前基线**:`P19+IM-1`、`P19+ERP-1`、`P19+ERP-2`、`P19+ERP-3`、`P19+MCP-1`、`P19+AI-1`、`P20+TRAVEL-1`、`P20+TRAVEL-2`、`P20+TRAVEL-3`、`P21+PWA-1` 与 `P21+PWA-2` 已完成;当前运行时已落地企微群机器人 + 深链 + Outbox 异步派发的一期协同适配,以及 ERP 主数据 Pull、报销付款凭证切片、采购双阶段 journal / 归档摘要出站、资产台账摘要出站、Postgres MCP 只读工具基线、报销 / 采购 / 资产详情页 AI 只读建议挂件、差旅申请主单 / 行程段 / 审批预算锁定 / `travel_orders` 关联入站、混合双轨对公支付闭环与批次级对账摘要桥的三期差旅基线,以及浏览器 PWA 下的移动资产扫码、盘点快捷录入与离线队列重放、移动审批 deep link 直达、本地会话快照离线守卫与审批草稿重放。
**目标**:在保持核心域稳定的前提下,冻结 ERP / IM / AI / MCP / TRAVEL / PWA 的长期边界,并记录 IM 一期、ERP 三期、AI 一期、差旅三期与 PWA 两期的已实现范围、禁入规则以及 R10 主线闭环后的固定收口结论。
## 1. 总体原则
@@ -190,11 +190,18 @@
- 已把盘点录入固定在 `inventoryCheckId` 上下文内复用现有 `fetchInventoryChecks / startInventoryCheck / recordInventoryItems`,实现 `draft -> start`、`counting -> record`、`completed -> readonly` 三态,不新增移动专用后端协议。
- 已新增 `IndexedDB` 离线队列,仅缓存“已解析出 `assetId` 的盘点结果”;联网后自动或手动重放,且以 `inventoryCheckId + assetId` 做 last-write-wins 去重。
### 5.8 PWA 一期明确不做
- 不做原生 App、小程序、双栈移动壳,也不接企微 / 钉钉 / 浏览器私有扫码 SDK。
- 不做 NFC、蓝牙、RFID、资产主数据全量离线镜像或完整离线盘点引擎。
- 不做企微 / 钉钉深链直达、后台持续同步、复杂冲突合并;这些能力继续留给 `P21+PWA-2`。
- 不改写现有资产台账详情路由,不新增 `/api/assets/lookup` 或其他移动专用后端路由。
### 5.8 P21+PWA-2 已实现范围
- 已保持 `workflow.task_assigned` 的 canonical `targetPath = /workflow/tasks/:taskId` 不变,并在客户端补齐移动 / PWA / IM WebView 环境下的自动兜底跳转:命中移动规则时统一落到 `/mobile/approvals?taskId=<id>`。
- 已为移动审批补齐 `taskId` deep link 模式:待办即使不在第一页列表中,也可单独拉取详情;离线时若该待办曾被本地缓存,则允许直接在移动审批页内查看与起草草稿。
- 已新增仅含 `me + permissions + savedAt` 的本地会话快照,不持久化 access token;离线冷启动时只允许 `/mobile/approvals` 与 `/workflow/tasks/:taskId` 两类路径进入壳页面。
- 已新增 `approve / reject` 审批草稿队列,采用 `taskId` 级 last-write-wins 去重;恢复联网后支持自动或手动重放,并把 `already_processed` / 403 / 404 明确标记为冲突态。
- 已升级 `vite-plugin-pwa` 的 runtime cache:静态资源使用 `StaleWhileRevalidate`,审批相关 GET API 使用 `NetworkFirst`,导航仍通过 `navigateFallback=/index.html` 回到 SPA 壳。
### 5.9 PWA 二期明确不做
- 不做钉钉 / 企微真实消息适配器、JS-SDK、开放平台回调审批;本期仅承接同源 H5 deep link 打开体验。
- 不做 Background Sync、Push、原生 App、小程序、双栈移动壳,也不把审批动作 POST 请求交给 Service Worker 代理。
- 不做完整离线登录、全量待办镜像、复杂冲突合并或离线自动修复;未缓存的待办详情离线仍要求联网重试。
- 不改写现有 workflow 动作 API,不给 `approve` 新增 comment,也不把 `return / transfer` 纳入离线草稿范围。
## 6. 事件与通知交付规范
@@ -254,8 +261,8 @@
## 9. R10 后续路线冻结
### 9.1 固定主线顺序
- `P21+PWA-1` 已完成后,当前固定后续主线顺序为:`P21+PWA-2`。
- 历史主线顺序仍保持:`P19+MCP-1 -> P19+AI-1 -> P20+TRAVEL-1 -> P20+TRAVEL-2 -> P20+TRAVEL-3 -> P21+PWA-1 -> P21+PWA-2`。
- `P21+PWA-2` 已完成后,`R10` 主线正式闭环;后续若进入新阶段,必须通过新的路线合同显式启动。
- 历史主线顺序保持为:`P19+MCP-1 -> P19+AI-1 -> P20+TRAVEL-1 -> P20+TRAVEL-2 -> P20+TRAVEL-3 -> P21+PWA-1 -> P21+PWA-2`。
- 后续阶段继续遵循“先治理,再工具,再建议,再业务,再移动”的总顺序,不并行开启两个重业务 phase。
- 每个 phase 固定遵循:`执行合同 CSV -> 方案批准 -> 开发 -> 测试 -> 文档矩阵收口 -> 合并 main`。
@@ -272,8 +279,8 @@
### 9.4 PWA 兑现顺序
- `P21+PWA-1` 已完成移动资产扫码与盘点增强,优先兑现一线资产作业的生产价值,并固定采用浏览器 PWA + 离线队列重放路线。
- `P21+PWA-2` 固定后做离线动作队列增强与企微深链增强,继续复用现有 `APP_ORIGIN + targetPath` 深链规范。
- PWA 路线继续限定在浏览器 / PWA 栈内,不引入原生 App、小程序或双栈移动壳。
- `P21+PWA-2` 已完成移动审批 deep link、离线守卫、本地草稿重放与缓存策略升级,继续复用现有 `APP_ORIGIN + targetPath` 深链规范且不改写服务端通知协议。
- PWA 路线已按浏览器 / PWA 栈闭环,不引入原生 App、小程序或双栈移动壳。
### 9.5 后置 backlog
- `P19+IM-2 / IM-3 / IM-4`、`P22+VEH-1`、`P22+ASSET-FIN-1` 明确列为后置 backlog,本轮不进入主线。
+65 -21
查看文件
@@ -1,9 +1,10 @@
# PWA 回归清单(P12 + P21PWA1)
# PWA 回归清单(P12 + P21PWA1 + P21PWA2)
## 前置条件
- `client` 已完成构建:`cd client && npm run build`
- 浏览器支持 PWA(Chrome/Safari 最新版)
- 浏览器支持 PWA(Chrome / Safari 最新版,含移动端)
- 服务端 API 可用
- 离线相关场景优先在真实设备、企微 / 钉钉容器或移动浏览器中手工验证
## 场景 A:安装与离线壳
1. 打开系统首页,确认可出现安装入口(浏览器原生 UI)。
@@ -21,24 +22,7 @@
期望:离线缓存成功,联网可重放成功。
## 场景 C:移动审批快捷动作
1. 使用审批角色访问 `移动审批` 页面。
2. 选择待办任务,依次测试 `通过` / `驳回` / `退回` / `转审`。
3. 返回待办列表与详情页确认状态同步刷新。
期望:动作闭环,错误提示可读。
## 场景 D:权限与边界
1. 非审批角色访问 `移动审批`,应被拒绝(403页)。
2. 非上传角色访问 `移动拍照`,应被拒绝(403页)。
期望:权限守卫生效。
## 备注
- iOS 场景仅保证前台恢复后的重放,不承诺后台持续同步。
## 场景 E:移动资产扫码
## 场景 C:移动资产扫码
1. 使用具备资产读取权限的账号访问 `资产扫码` 页面。
2. 在支持 `BarcodeDetector` 的浏览器中点击“开始扫码”,扫描资产条码或二维码。
3. 若浏览器不支持 `BarcodeDetector`,确认页面自动回退到 ZXing 并可继续扫码。
@@ -47,7 +31,7 @@
期望:扫码与手工输入都能完成资产查找,且不要求新增原生壳。
## 场景 F:移动盘点录入与离线重放
## 场景 D:移动盘点录入与离线重放
1. 使用具备 `asset.inventory` 权限的账号,从 `资产盘点` 页面进入 `移动扫码盘点`。
2. 选择或打开一个 `draft` 盘点任务,点击“开始并扫码”,确认任务进入 `counting`。
3. 扫码定位资产后提交盘点结果,确认桌面盘点页同步看到新增 item。
@@ -56,3 +40,63 @@
6. 用无 `asset.inventory` 权限账号访问同一路径,确认只能查看资产结果,不能录入盘点。
期望:离线只缓存已解析盘点结果,联网可重放成功,权限边界不回退。
## 场景 E:移动审批在线动作
1. 使用审批角色访问 `移动审批` 页面。
2. 选择待办任务,依次测试在线 `通过` / `驳回` / `退回` / `转审`。
3. 返回待办列表与详情页确认状态同步刷新。
期望:在线动作闭环不回归,错误提示可读。
## 场景 F:workflow canonical deep link 落点
1. 生成待办通知,其 canonical URL 为 `/workflow/tasks/<taskId>`。
2. 在企微 / 钉钉容器或移动浏览器打开链接。
3. 确认 PWA 壳成功打开并自动跳转到 `/mobile/approvals?taskId=<taskId>`。
4. 确认待办详情正确展开;若该任务不在第一页列表中,也能单独查看详情。
期望:服务端 canonical deep link 不变,移动端自动落到移动审批页,桌面链接不回归。
## 场景 G:deep link 登录回跳
1. 未登录状态下直接打开 `/workflow/tasks/<taskId>`。
2. 守卫跳转到 `/login?redirect=...`。
3. 登录成功后返回原始 deep link。
4. 再次命中移动兜底跳转并进入 `/mobile/approvals?taskId=<taskId>`。
期望:登录回跳完整保留 deep link,上线后仍进入移动审批详情。
## 场景 H:离线审批草稿与联网重放
1. 在线进入移动审批页并成功加载某个待办详情。
2. 断网后选择 `通过` 或填写 comment 后 `驳回`。
3. 页面提示“已加入待同步审批草稿”。
4. 恢复联网后等待自动重放或手动点击“同步草稿队列”。
5. 确认成功项从队列移除,列表 / 详情刷新到最新状态。
期望:离线仅排队 `approve / reject`,联网可自动或手动重放成功。
## 场景 I:离线冷启动与未缓存待办
1. 设备先在线登录成功并写入本地会话快照。
2. 完全关闭页面后断网,直接打开 `/workflow/tasks/<taskId>` 或 `/mobile/approvals?taskId=<taskId>`。
3. 若该待办曾在线加载过,确认可进入移动审批壳并看到缓存详情。
4. 若该待办从未缓存过,确认页面只显示 taskId 与“离线未缓存该待办,请联网后重试”提示。
期望:离线冷启动仅依赖本地会话快照进入壳页面,不伪造未缓存详情。
## 场景 J:草稿冲突与失败重试
1. 离线起草一条 `驳回` 草稿。
2. 在恢复联网前,由其他审批人在线处理同一待办。
3. 自动重放返回 `409 already_processed`、`403` 或 `404`。
4. 确认草稿进入“存在冲突”状态,而不是静默视为成功。
5. 对 `5xx` 或临时网络异常场景,确认草稿进入“同步失败”状态并可手动重试。
期望:冲突与失败语义区分明确,用户可查看任务、重试失败项或丢弃草稿。
## 场景 K:权限与边界
1. 非审批角色访问 `移动审批` 或 deep link,确认被拒绝到 `403`。
2. 无在线会话且无本地快照时,离线冷启动不得绕过守卫。
3. 离线状态下确认 `退回` / `转审` 按钮统一置灰,并提示“需联网执行”。
期望:PWA-2 只放开移动审批壳的离线守卫,不扩散到其他受保护页面。
## 备注
- iOS 场景仅保证前台恢复后的重放,不承诺后台持续同步。
- `PWA-2` 不校验真实钉钉 / 企微 JS-SDK,只校验同源 H5 deep link 打开体验。
+1
查看文件
@@ -49,6 +49,7 @@ CSV_FACT_SOURCES = [
ROOT / "issues" / "2026-03-10_21-05-59-p20-travel-2-l5-corporate-payments-refresh.csv",
ROOT / "issues" / "2026-03-11_09-57-28-p20-travel-3-l5-reconciliation-erp-bridge-refresh.csv",
ROOT / "issues" / "2026-03-11_17-50-39-p21-pwa-1-l5-asset-scan-refresh.csv",
ROOT / "issues" / "2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv",
]
ID_PATTERN = re.compile(r"^[A-Z][0-9][0-9A-Za-z-]*$")