diff --git a/docs/superpowers/specs/2026-10-15-mp-webview-crm-contract-design.md b/docs/superpowers/specs/2026-10-15-mp-webview-crm-contract-design.md new file mode 100644 index 000000000..84a314051 --- /dev/null +++ b/docs/superpowers/specs/2026-10-15-mp-webview-crm-contract-design.md @@ -0,0 +1,225 @@ +# 小程序 WebView · CRM 合同 — 设计文档 + +> **日期**: 2026-10-15 +> **状态**: 待实现 +> **方案**: 复用运输计划 / CRM 产品·报价 WebView 模板;在 `web-admin` 新增 `/#/m/crm/contract*`;工作台开放「合同管理」「合同审批」 +> **权威接入清单**: `docs/web-admin-mp-webview-modules.md` +> **样式参考**: `/#/m/pl/plan*`、`/#/m/crm/product*`、`/#/m/crm/quote*`(三墙 Token,`mp-webview.scss`) +> **前置**: 报价 WebView 已落地;`MINI_CRM_ROOT` 已存在 + +## 1. 目标 + +在微信小程序「CRM管理」下提供与 Web 端 **合同管理**、**合同审批** 同等的管理闭环能力,以 **WebView 加载 H5** 落地: + +- 业务改动优先只发 `web-admin` 静态资源 +- 不复制鉴权、不新建第二个 `web-view` 壳页 +- 移动端视觉对齐运输计划 / 产品 / 报价 H5,不套桌面 Fresh Mint + +**Web 对照** + +| 能力 | 桌面 | 权限 | +|------|------|------| +| 合同管理 | `src/views/crm/contract/index.vue`(`ContractListPage mode=manage`) | `crm:contract:list` | +| 合同审批 | `src/views/crm/contract/approval/index.vue`(`mode=approve`) | `crm:contract:approve` | +| 表单/详情 | `components/ContractFormDialog`、`ContractDetailDialog` 等 | — | + +**本期不做调价函**(`crm/price-letter`)。 + +## 2. 已确认决策 + +| # | 项 | 决策 | +|---|-----|------| +| D1 | 接入方式 | **方案 1:嵌套 H5**,不写原生 `pages/crm/contract*` | +| D2 | 管理能力 | 列表 / 详情 / 新增编辑 / 删除 + **提交审批** + **合同复制** + **作废** + **作废恢复** + **上传扫描件** | +| D3 | 明确不做 | 调价函;执行管理;续签;打印;导出 PDF / Excel;列 facet / 列显隐 / 日期快捷 / 统计条;工作台「合同审批人设置」 | +| D4 | 双入口 | 管理 `/#/m/crm/contract`;审批 `/#/m/crm/contract/approval`;管理页不做审批操作,审批页不改单 | +| D5 | 粒度 | **支持单条与批量**提交审批、通过/驳回 | +| D6 | 表单字段 | **全字段对齐 Web**;`variant="page"` 复用校验与提交;布局移动端化 | +| D7 | 提交审批 | 选审批人(多选、有序)+ 备注;可预填桌面 `getContractApproverSetting`;不挂移动端审批人设置菜单 | +| D8 | 列表 | 管理 Tab:全部 / 待审批 / 已审批;审批 Tab:待审批(默认)/ 已审批;顶部 `keyword` | +| D9 | H5 落点 | `web-admin` `/#/m/crm/contract*`,复用现有合同 API | +| D10 | 视觉 | 三墙绿 `#0a9f6d` / `#087f57`(`mp-webview.scss`) | +| D11 | 菜单 | `MINI_CRM_ROOT` 下挂「合同管理」「合同审批」;工作台两项 + `WORKBENCH_ROUTE_MAP` | +| D12 | 角色绑定 | 有 Web `crm:contract:list` → 补绑管理入口;有 `crm:contract:approve` → 补绑审批入口;均补绑移动端根与 `MINI_CRM_ROOT` | +| D13 | 双权限 | 入口 `mini:crm:contract:list` / `mini:crm:contract:approve`;业务 API 仍校验 Web `crm:contract:*` | + +## 3. 非目标 + +- 不做调价函管理及相关 API / 菜单 +- 不把桌面 `ContractListPage` 的导出 / 打印 / 执行 / 续签原样塞进 WebView +- 不改合同后端业务规则、租户隔离与数据权限语义 +- 不新建独立 `mobile-h5`、不新增第二个 `mp-webview`、不输出独立 HTML Demo + +## 4. 架构 + +```text +工作台「合同管理」→ pages/common/mp-webview?path=/m/crm/contract +工作台「合同审批」→ pages/common/mp-webview?path=/m/crm/contract/approval + 1) POST /api/web/auth/mp-webview-ticket + 2) web-view src = {WEB_ORIGIN}/?mpTicket=…#/m/crm/contract…?mpTicket=… + 3) H5:MpWebviewShell → POST /api/web/auth/mp-webview-exchange + 4) 之后与桌面同账号调用现有 CRM 合同 API +``` + +| 单元 | 职责 | +|------|------| +| `pages/common/mp-webview` | 已有壳,不改协议 | +| `MpWebviewShell` | 已有 | +| `/#/m/crm/contract*` | 新建移动端 UI | +| 工作台 + SQL | 两叶子 + 角色补绑 | + +## 5. H5 路由与页面 + +### 5.1 静态路由 + +在 `staticRoutes.ts` catch-all 之前,`meta: { isHideTab: true, isMpWebview: true }`: + +| 路径 | 文件(建议) | 用途 | +|------|--------------|------| +| `/m/crm/contract` | `views/m/crm/contract/index.vue` | 管理列表 | +| `/m/crm/contract/approval` | `views/m/crm/contract/approval.vue` | 审批列表 | +| `/m/crm/contract/new` | `form.vue` | 新增;复制 `?copyFrom=` | +| `/m/crm/contract/:id/edit` | `form.vue` | 编辑 | +| `/m/crm/contract/:id` | `detail.vue` | 详情 | + +顺序:`/approval`、`/new`、`/:id/edit` 须在 `/:id` 之前。 + +列表宜抽共享组件 `MpContractList.vue`(`mode=manage|approve`)。 + +### 5.2 查询语义 + +| mode | view | 请求要点 | +|------|------|----------| +| manage | `all` | `excludeStatus=invalid` | +| manage | `approving`(UI「待审批」) | `status=approving`;不传 pending/approved 用户过滤 | +| manage | `approved`(UI「已审批」) | `status=approved`;不传 approvedByUserId | +| approve | `submitted`(待审批) | `pendingApprovalUserId=当前用户`(与桌面审批 Tab 一致) | +| approve | `approved`(已审批) | `approvedByUserId=当前用户` | + +分页字段对齐 `ContractQuery`(实现时打开 types 核对 `pageNum`/`page`)。 + +### 5.3 管理列表 + +- Header:回工作台 +「合同管理」+ keyword(主题/客户/单号,与 list API 一致) +- Tab + 卡片流;**多选**;Speed Dial「新增合同」 +- 批量栏:提交审批(仅草稿)、作废等(按桌面可操作集合过滤,跳过提示) +- 不做:导出、打印、facet、日期快捷、执行/续签 + +### 5.4 审批列表 + +- 标题「合同审批」;Tab 待审批(默认)/ 已审批 +- 多选 + 批量通过/驳回;无新增 Speed Dial + +### 5.5 详情 + +- 只读全字段(主表 + 明细 + 审批流 + 扫描件展示) +- **管理底栏**:按状态 — 提交审批 / 编辑 / 删除(`canDeleteByCreator`)/ 作废 / 作废恢复 / 复制 / 上传扫描件;**不出现**执行、续签、打印、审批通过驳回 +- **审批底栏**:待我审 → 通过 / 驳回;**不出现**改单类按钮 +- 提交 Sheet:审批人多选有序 + 备注;预填默认审批人 + +### 5.6 表单 + +- `ContractFormDialog`(或 Panel)`variant="page"`,全字段;单列/卡片化;禁止桌面多列原样塞手机 + +### 5.7 批量 + +- 列表选择模式;底栏「已选 N」+ 主操作 +- 批量提交:共用一组审批人+备注;仅草稿;跳过非草稿并提示 +- 批量审批:仅当前用户 pending 节点;驳回意见必填;跳过无权/非待审并提示 + +## 6. 小程序工作台 + +### 6.1 `workbench-menus.js` + +| name | code | perms | +|------|------|-------| +| 合同管理 | `crm-contract-webview` | `mini:crm:contract:list` | +| 合同审批 | `crm-contract-approval-webview` | `mini:crm:contract:approve` | + +不挂调价函。模块 `desc` 可含「合同」。 + +### 6.2 `WORKBENCH_ROUTE_MAP` + +```text +'crm-contract-webview' → mp-webview?path=/m/crm/contract +'crm-contract-approval-webview' → mp-webview?path=/m/crm/contract/approval +``` + +## 7. 菜单与权限(SQL) + +### 7.1 菜单树 + +```text +MINI_CRM_ROOT +├─ …产品 / 报价… +├─ MINI_CRM_CONTRACT mini:crm:contract:list +└─ MINI_CRM_CONTRACT_APPROVAL mini:crm:contract:approve +``` + +脚本:`docs/sql/migrations/2026-10-15-mini-crm-contract-webview-menus.sql`(幂等;`MINI_CRM_ROOT` 不存在则插入)。 + +### 7.2 角色补绑 + +| Web menu id | perms | 补绑 | +|-------------|-------|------| +| `CRM3000000000000000000000000020` | `crm:contract:list` | `1`、`MINI_CRM_ROOT`、`MINI_CRM_CONTRACT` | +| `CRM3000000000000000000000000021` | `crm:contract:approve` | `1`、`MINI_CRM_ROOT`、`MINI_CRM_CONTRACT_APPROVAL` | + +### 7.3 双权限 + +入口看 `mini:crm:contract:*`;H5 内业务看 Web `crm:contract:*`。 + +## 8. 数据流与 API + +**不新建业务 API。** 复用: + +| 能力 | API | +|------|-----| +| 列表 | `listContract` | +| 详情 | `getContract` + `listContractApproval` | +| 增改删 | `addContract` / `updateContract` / `delContract` | +| 复制 | 预填后 `addContract` | +| 提交 | `submitApproval` / `batchSubmitApproval` + `getContractApproverSetting` | +| 审批 | `approvePass` / `approveReject`(或桌面同源封装;批量逐条) | +| 作废/恢复 | `invalidContract` / `restoreContract` | +| 扫描件 | `uploadFile` / `uploadAttachments` | + +**不调用**:`exportContract`、模板/打印、`startExecute`/`finishContract`/`renewContract`、统计、`saveContractApproverSetting`、调价函 API。 + +## 9. 错误处理与发版 + +| 场景 | 行为 | +|------|------| +| 无对应 `mini:crm:contract:*` | 工作台不显示该入口 | +| H5 403 | 页内「无权限」 | +| 401 | 回小程序,不进 `/#/auth/login` | +| ticket 二次 exchange 失败 | 提示从工作台重进 | + +发版:H5→web-admin;工作台→小程序包;菜单→目标库执行 SQL。 + +## 10. 测试要点 + +- 换票后管理/审批列表与桌面同账号一致 +- Tab、keyword、多选批量提交/审批;跳过提示正确 +- 详情单条:提交、复制、作废/恢复、上传扫描件;管理无审批、审批无改单 +- 全字段表单保存回显 +- 无打印/PDF/导出/执行/续签/调价函入口 +- 桌面 `/#/crm/contract*` 默认行为不变 + +## 11. 实现清单(供 plan 拆任务) + +1. 列表查询纯函数 + 单测 +2. 菜单 SQL + 角色补绑 +3. 静态路由 + 路径常量 + 空壳 +4. 共享列表(含多选批量) +5. 详情 + 提交/审批 Sheet + 作废/恢复/上传 +6. 表单 `variant="page"` + form 壳 +7. 工作台两项 + route map +8. 更新 `docs/web-admin-mp-webview-modules.md` + 回归 + +## 12. 参考 + +- `docs/superpowers/specs/2026-10-15-mp-webview-crm-quote-design.md` +- `docs/web-admin-mp-webview-modules.md` +- Web:`web-admin/src/views/crm/contract/*`、`src/api/crm/contract/*` +- 报价 H5:`web-admin/src/views/m/crm/quote/*`