diff --git a/docs/superpowers/specs/2026-10-10-market-miniapp-role-features-design.md b/docs/superpowers/specs/2026-10-10-market-miniapp-role-features-design.md index 9fdb1000..7b330d47 100644 --- a/docs/superpowers/specs/2026-10-10-market-miniapp-role-features-design.md +++ b/docs/superpowers/specs/2026-10-10-market-miniapp-role-features-design.md @@ -2,7 +2,7 @@ **日期:** 2026-10-10 **状态:** 待审阅 -**范围:** 市场现场侧小程序(存储业务子集);角色能力与数据范围,不含 UI 线框与实现排期 +**范围:** 市场现场侧能力(存储业务子集);角色菜单、承载工程、数据范围与运费脱敏;不含完整实现排期与视觉稿 ## 1. 背景与目标 @@ -10,7 +10,7 @@ Web 管理端「市场 → 存储服务」已形成面向市场部客服的后台能力:预签约订单、采集协议单(细胞存储 / 科研捐赠)、缴费信息、催缴信息、样本信息、运费信息等。 -医院现场的**市场专员**与**地区经理**平时不在电脑前,需要通过小程序操作系统。二者操作能力对齐,差异仅在**数据可见/可改范围**;运费批次对市场专员另有跨专员脱敏。 +医院现场的**市场专员**与**地区经理**平时不在电脑前,需要通过小程序入口操作系统。二者业务模块类似,但须**分菜单、分页面**,便于角色菜单授权与后续各自拓展;业务界面放在 **`mobile-oa-h5`**,小程序首页只挂菜单链接(`web-view`),功能升级以发布 H5 为主,避免每次改业务都发版微信小程序。 相关 Web 用语与主数据(已落地): @@ -21,151 +21,192 @@ Web 管理端「市场 → 存储服务」已形成面向市场部客服的后 协议 / 预签单据字段:`sales_user_id`(市场专员)、`region_manager_user_id`(地区经理)、采集地区。 +现有移动端模式可复用: + +- 菜单:`sys_menu`「移动端菜单」根下种子 + `GET /api/mini/menus`(见 [`backend/app/api/mini_menu.py`](../../../backend/app/api/mini_menu.py)) +- 小程序壳:`mobile-h5` 首页宫格 + 通用 `web-view` +- H5 业务:`mobile-oa-h5`(OA 已采用「列表可原生 / 表单在 H5」;**本需求业务页一律进 H5**,便于免发版升级) + ### 1.2 目标 -1. 明确小程序要上线的业务模块清单(对齐 Web 存储服务子集)。 -2. 明确市场专员、地区经理的数据范围与操作能力。 -3. 明确运费批次对市场专员的脱敏规则。 -4. 明确非目标(继续留在 Web 或非本角色)。 -5. 为后续实现计划预留「市场现场数据范围」过滤层要求(Web 现有部门/创建人 `apply_data_scope` 不覆盖本规则)。 +1. 明确市场专员、地区经理各自的小程序菜单与 H5 页面清单(分树、分路由)。 +2. 菜单注册在 `sys_menu` 的「移动端菜单」下,走角色-菜单授权。 +3. 业务界面落在 `mobile-oa-h5`;小程序仅配置入口 path → 打开 H5。 +4. 明确数据范围与运费脱敏;专员页只用专员 scope,经理页只用经理 scope。 +5. 明确非目标。 ### 1.3 已确认决策 | 项 | 选择 | |----|------| -| 产品形态 | 同一小程序、同一套业务菜单;角色只影响数据范围与运费脱敏 | +| 产品形态 | **两套菜单 + 两套页面**(专员 / 经理分开),不共用同一业务页靠角色切换 | +| 菜单配置 | 挂在 `sys_menu` **「移动端菜单」** 根下;角色勾选授权 | +| 业务承载 | **`mobile-oa-h5`**;小程序首页只挂链接,经 `web-view` 打开 | +| 发版策略 | 业务迭代优先发 H5;小程序仅在新增入口/改壳时发版 | | 市场专员数据范围 | 单据 `sales_user_id` = 当前用户(不以 `create_by`) | | 地区经理数据范围 | **C**:主数据负责地区(`is_leader=1`) **∪** 单据 `region_manager_user_id` = 当前用户 | -| 市场专员操作能力 | 与地区经理同权:范围内预签/协议/催缴/缴费/样本/运费均可建改查(运费另有脱敏) | -| 地区经理操作能力 | 分管范围内可读可建可改 | -| 一人兼两职 | 数据范围取**并集**(自己名下 ∪ 分管地区) | +| 操作能力 | 各自菜单下:预签/协议/催缴/缴费/样本/运费均可建改查(专员运费另有脱敏) | +| 一人兼两职 | 角色勾选两套菜单则首页两套入口都出现;**进入哪套页用哪套 scope**(不做单页并集) | | 本期 Demo | 不做 HTML Demo | -## 2. 角色与数据范围 +## 2. 信息架构与承载 -### 2.1 市场专员 +### 2.1 总体链路 + +```mermaid +flowchart LR + Home[mobile-h5_首页宫格] + MenusAPI["GET_/api/mini/menus"] + WV[web-view壳] + H5[mobile-oa-h5业务页] + API[业务API_含现场scope] + Home --> MenusAPI + Home -->|"点击菜单"| WV + WV --> H5 + H5 --> API +``` + +1. 用户打开小程序首页 → 拉「移动端菜单」授权项展示宫格。 +2. 点击「市场专员·xxx」或「地区经理·xxx」→ 小程序打开通用 `web-view`,URL 指向 `mobile-oa-h5` 对应路由(带 token,对齐现有 OA H5 拼法)。 +3. 列表 / 表单 / 详情均在 H5 内完成;升级业务只发 H5 静态资源。 + +### 2.2 工程边界 + +| 工程 | 职责 | +|------|------| +| `mobile-h5` | 登录、首页宫格、通用 `web-view`、菜单 path→H5 URL 映射;**不实现**本需求业务列表/表单页 | +| `mobile-oa-h5` | 市场专员、地区经理全部业务路由与页面(可与 OA 路由并列,建议 `/market/...` 前缀) | +| `backend` | 菜单种子 SQL;业务 API 按入口角色施加现场 scope;扩展 `/api/mini/menus` 图标映射(若需) | +| `web-admin` | 角色管理勾选移动端菜单;不强制同步 Web「存储服务」菜单树 | + +### 2.3 菜单树(`sys_menu` · 移动端菜单下) + +建议两级目录 + 叶子(名称可微调,**专员与经理叶子必须分离**): + +``` +移动端菜单 +├── 市场专员(目录) +│ ├── 预签约订单 +│ ├── 协议单 +│ ├── 催缴信息 +│ ├── 缴费信息 +│ ├── 样本信息 +│ └── 运费信息 +└── 地区经理(目录) + ├── 预签约订单 + ├── 协议单 + ├── 催缴信息 + ├── 缴费信息 + ├── 样本信息 + └── 运费信息 +``` + +约定: + +- 目录与叶子均落在「移动端菜单」根的子孙中;种子 SQL 幂等 INSERT(对齐既有 OA 移动端菜单写法)。 +- 叶子 `path` 指向小程序壳路由或约定协议(如 `/pages/oa/webview/index` + query,或专用 `/pages/market/webview`),**component / 扩展字段**需能解析出 H5 path(实现计划写死一种与 OA 一致的拼法)。 +- 角色授权:市场专员角色勾选「市场专员」子树;地区经理角色勾选「地区经理」子树;兼岗勾选两套。 +- 协议单叶子在 H5 内可用 Tab 区分细胞存储 / 科研捐赠(仍属该角色自己的页面实例,不与另一角色共用组件路由)。 + +### 2.4 H5 路由命名(建议) + +| 角色 | 前缀 | 示例 | +|------|------|------| +| 市场专员 | `/market/specialist/` | `/market/specialist/presign`、`.../protocol`、`.../payment-chase`、`.../payment`、`.../sample`、`.../freight` | +| 地区经理 | `/market/manager/` | `/market/manager/presign`、… 同上六模块 | + +专员页与经理页**禁止共用同一路由**;可抽共享业务组件,但页面入口、菜单 path、权限码分离。 + +## 3. 角色与数据范围 + +### 3.1 市场专员页(`/market/specialist/*`) - **范围键:** 协议 / 预签等主单据的 `sales_user_id` = 当前登录用户。 -- **下游模块(催缴、缴费、样本):** 经所属协议关联过滤,同样落在「自己是市场专员」的协议下。 -- **运费:** 见第 4 节脱敏规则。 +- **下游(催缴、缴费、样本):** 经所属协议关联,仅上述协议。 +- **运费:** 见第 5 节脱敏。 +- API 入参或服务端上下文固定 `fieldScope=specialist`,**即使**该用户同时是地区经理,本页也不扩大到分管地区。 -### 2.2 地区经理 +### 3.2 地区经理页(`/market/manager/*`) 满足以下任一即可纳入范围: -1. **主数据:** 当前用户在 `biz_collection_region_staff`(`del_flag=0`)中为某采集地区的负责人(`is_leader=1`),且该地区 `del_flag=0`;协议(或预签)的采集地区属于这些地区之一。 -2. **单据字段:** 协议 / 预签上的 `region_manager_user_id` = 当前用户。 +1. **主数据:** 当前用户在 `biz_collection_region_staff`(`del_flag=0`)中为某采集地区负责人(`is_leader=1`),协议/预签采集地区属于这些地区。 +2. **单据字段:** `region_manager_user_id` = 当前用户。 -下游模块经协议关联过滤,规则同上。 +下游经协议关联。API 固定 `fieldScope=manager`,不混入「仅自己是市场专员、但不在分管范围」的单据(那些只在专员菜单可见)。 -### 2.3 兼岗并集 +### 3.3 兼岗 -同一用户既是若干单据的市场专员,又是若干地区的负责人(或单据地区经理)时: +| 维度 | 行为 | +|------|------| +| 菜单 | 两套目录叶子均可出现在首页(取决于角色-菜单) | +| 数据 | 进专员页 → 仅专员 scope;进经理页 → 仅经理 scope | +| 写校验 | 按当前页面 scope 校验;禁止用专员入口改经理范围外单据 | -``` -可见可改集合 = 专员范围 ∪ 经理范围 -``` - -列表与详情、写操作均按并集校验;写操作目标单据必须落在并集内。 - -### 2.4 与现有 Web 数据权限的关系 +### 3.4 与现有 Web 数据权限的关系 | 层级 | 机制 | 是否满足本设计 | |------|------|----------------| | 租户 | `tenant_no` | 必须继续生效 | -| 角色数据权限 | `apply_data_scope`(部门 / 创建人等) | **不替代**本设计的专员/地区范围 | -| 本设计 | 市场现场 scope(`sales_user_id` / 负责地区 ∪ `region_manager_user_id`) | 小程序 API **必须**实现 | +| 角色菜单 | 移动端菜单勾选 | 控制入口可见 | +| 角色数据权限 | `apply_data_scope`(部门/创建人) | **不替代**现场 scope | +| 本设计 | 按页面角色的 `sales_user_id` / 地区∪单据经理 | 市场 H5 对应 API **必须**实现 | -实现阶段应在小程序(或专用)API 上增加「市场现场数据范围」过滤,可与租户隔离叠加;是否回写到 Web 端同一套 scope **不在本文范围**,另行决策。 +## 4. 功能矩阵 -## 3. 功能矩阵 +模块能力对齐 Web「存储服务」子集;**专员与经理各有独立菜单与页面**,能力列相同、范围不同。 -两端菜单一致,模块对齐 Web「存储服务」子集。 +| 模块 | 市场专员菜单/页 | 地区经理菜单/页 | Web 对照 | +|------|-----------------|-----------------|----------| +| 预签约订单 | 建 / 改 / 查;预签转正式 | 同能力,范围=分管 | `presign-order` | +| 协议单(细胞存储 + 科研捐赠) | 建 / 改 / 查 | 同能力,范围=分管 | 采集协议单双来源 | +| 催缴信息 | 查 / 改 | 同能力,范围=分管 | `payment-chase` | +| 缴费信息 | 查 / 改(含登记转账等) | 同能力,范围=分管 | `payment-info` | +| 样本信息 | 查 / 改(Web 统一样本轻量子集) | 同能力,范围=分管 | `sample-info` | +| 运费信息 | 见第 5 节 | 分管内完整可见可改 | `sample-freight` | -| 模块 | 市场专员 | 地区经理 | Web 对照 | -|------|----------|----------|----------| -| 预签约订单 | 建 / 改 / 查;预签转正式协议 | 同权,范围=分管(含并集) | `/market/cell-storage/presign-order` | -| 协议单(细胞存储) | 建 / 改 / 查 | 同权,范围=分管 | 采集协议单 · 细胞存储 | -| 协议单(科研捐赠) | 建 / 改 / 查 | 同权,范围=分管 | 采集协议单 · 科研捐赠 | -| 催缴信息 | 查 / 改(范围内) | 同权,范围=分管 | `/market/cell-storage/payment-chase` | -| 缴费信息 | 查 / 改(含登记转账等) | 同权,范围=分管 | `/market/cell-storage/payment-info` | -| 样本信息 | 查 / 改(轻量能力按 Web 统一样本信息子集) | 同权,范围=分管 | `/market/cell-storage/sample-info` | -| 运费信息 | 见第 4 节 | 分管范围内完整可见可改 | `/market/cell-storage/sample-freight` | +口径: -### 3.1 模块口径说明 +- **催缴:** 未来 30 天应缴未清 ∪ 已逾期未清(对齐 Web)。 +- **缴费:** 市场侧登记/查看;**不含**财务确认开票。 +- **样本:** 进度与轻量办理子集;非实验室/生产。 +- **预签转正式:** 沿用现有后端人员映射,不另造规则。 -- **催缴信息:** 口径对齐 Web——未来 30 天内应缴未清 ∪ 已逾期未清;行与筛选可移动端瘦身,业务集合不变。 -- **缴费信息:** 支持查看与登记转账等市场侧改写;**不含**财务确认收款、开票。 -- **样本信息:** 对齐统一样本信息的进度查看与 Web 已提供的轻量办理能力子集;实验室/生产操作不在此列。 -- **预签转正式:** 人员映射继续遵循现有后端约定(正式单市场专员以采集专员为准等),小程序不另造规则。 +## 5. 运费批次脱敏(仅市场专员页) -```mermaid -flowchart TB - subgraph roles [角色] - Spec[市场专员] - Mgr[地区经理] - end - subgraph modules [小程序模块] - Presign[预签约订单] - Protocol[协议单] - Chase[催缴信息] - Pay[缴费信息] - Sample[样本信息] - Freight[运费信息] - end - Spec --> Presign - Spec --> Protocol - Spec --> Chase - Spec --> Pay - Spec --> Sample - Spec --> Freight - Mgr --> Presign - Mgr --> Protocol - Mgr --> Chase - Mgr --> Pay - Mgr --> Sample - Mgr --> Freight -``` +| 场景 | 市场专员页 | 地区经理页(分管内) | +|------|------------|----------------------| +| 批次含自己为市场专员的样本/协议 | 可见批次;可操作**自己相关**明细 | 完整可见可改 | +| 同批次含其他专员协议/样本 | **可看**运单号等批次级信息;**不返回**他专员明细行 | 完整可见可改 | +| 批次与自己无关且不在经理范围 | 不可见 | 地区不在分管则不可见 | -## 4. 运费批次脱敏(仅市场专员) +- 专员批次详情:仅批次头 + 自己的明细行;不暴露「他人明细条数」等可推断信息。 +- 写操作:专员仅改自己明细;经理改分管范围内全部明细。 -适用:当前请求仅以**市场专员**身份命中某运费批次,或以并集进入但明细行归属其他专员时。 - -| 场景 | 市场专员 | 地区经理(分管内) | -|------|----------|-------------------| -| 批次含自己为市场专员的样本/协议 | 可见批次;可查看并操作**自己相关**明细 | 完整可见可改 | -| 同批次含其他市场专员的协议/样本 | **可看**运单号等批次级信息;**不可看**他专员协议/样本详情 | 完整可见可改 | -| 批次仅含其他专员且自己无明细、也不在经理范围 | 不可见该批次 | 若地区不在分管则不可见 | - -实现要点(后续计划展开): - -- 批次列表:专员侧「批次可见」当且仅当批次内至少一条明细关联到自己 `sales_user_id` 的协议/样本,**或**兼岗并集下经理范围命中。 -- 批次详情:明细行按专员过滤;**他专员明细行不返回**(专员仅见批次头字段 + 自己的明细行;不提供「有 N 条他人明细」之类的可推断详情)。 -- 写操作:专员仅能改自己明细;经理可改分管范围内全部明细。 - -## 5. 非目标 - -以下**不在**本小程序角色首期范围: +## 6. 非目标 - 缴费财务确认及开票、退费财务确认 -- 采集地区及医院主数据配置、细胞样本类型等基础资料维护 -- 市场物料库全量管理(「我的领用」若需要,单独立项) -- 质检 / 生产 / 入库放行等非市场现场链路 -- HTML Demo、完整小程序视觉稿(另文) +- 采集地区及医院、细胞样本类型等主数据维护 +- 市场物料库全量管理(「我的领用」另立项) +- 质检 / 生产 / 入库放行 +- 在 `mobile-h5` 内实现本需求业务列表/表单(与免发版策略冲突) +- 专员/经理共用同一 H5 路由、靠前端隐藏区分 +- HTML Demo、完整视觉稿(另文) - 将本 scope 强制推广到 Web 全部菜单(另决策) -## 6. 数据范围实现要点(供后续实现计划) +## 7. 数据范围与菜单实现要点(供后续实现计划) -1. **专员:** 协议及下游均经 `sales_user_id` 过滤;预签同字段语义。 -2. **经理:** 采集地区 ∈ 负责地区列表,**或** `region_manager_user_id` = 本人;下游经协议关联。 -3. **兼岗:** 查询 OR 合并;写前校验目标落在并集。 -4. **运费:** 批次可见性 + 明细级专员脱敏,独立查询策略。 -5. **租户:** 所有查询/写操作继续 `tenant_no` 隔离。 +1. SQL 种子:在「移动端菜单」下插入专员/经理两目录及各 6 个叶子;角色在 Web 勾选。 +2. `mobile-h5`:首页已有菜单拉取则复用;点击市场类 path 时拼 `OA_H5_ORIGIN` + `/market/{specialist|manager}/...` + `token`。 +3. `mobile-oa-h5`:注册两套路由与页面;共享组件可抽,入口不可合并。 +4. API:按 path 或显式 `fieldScope` 施加专员/经理过滤;写前二次校验。 +5. 运费:批次可见性 + 明细级专员脱敏,独立查询策略。 +6. 租户隔离始终生效。 -## 7. 与 Web 菜单对照(摘要) +## 8. 与 Web 菜单对照(业务能力,非同一菜单树) -| 小程序模块 | Web Hash(参考) | -|------------|------------------| +| 能力 | Web Hash(参考) | +|------|------------------| | 预签约订单 | `/#/market/cell-storage/presign-order` | | 协议单 | `/#/market/cell-storage/protocol-audit` | | 催缴信息 | `/#/market/cell-storage/payment-chase` | @@ -173,14 +214,18 @@ flowchart TB | 样本信息 | `/#/market/cell-storage/sample-info` | | 运费信息 | `/#/market/cell-storage/sample-freight` | -## 8. 验收标准(产品级) +移动端为两套叶子,不与 Web 侧栏菜单 id 共用。 -1. 市场专员登录后,仅能看到/操作 `sales_user_id` 为自己的预签、协议及下游;运费批次对他人明细脱敏符合第 4 节。 -2. 地区经理登录后,能看到/操作:负责地区内全部相关单据 **加上** 单据上挂自己为地区经理的单据。 -3. 兼岗用户看到并集,且可对并集内单据执行与矩阵一致的建改查。 -4. 财务确认开票、主数据配置等不出现在该小程序菜单中。 +## 9. 验收标准(产品级) -## 9. 后续 +1. 「移动端菜单」下可区分市场专员 / 地区经理两套菜单;角色只勾专员时首页不出现经理入口,反之亦然。 +2. 点击菜单打开 `mobile-oa-h5` 对应页,而非小程序原生业务页。 +3. 专员页仅 `sales_user_id` 自己的数据;运费脱敏符合第 5 节。 +4. 经理页可见可改分管地区 ∪ 单据地区经理为自己的数据。 +5. 兼岗用户两套入口均可用,且各自 scope 不串。 +6. 更新 H5 业务页后,无需因该业务改动而重新发布微信小程序(壳与菜单 path 未变的前提下)。 -- 本文审阅通过后,再编写实现计划(`docs/superpowers/plans/`),拆分:鉴权与 scope 中间层、各模块 API/页面瘦身、运费脱敏、测试用例。 -- 小程序工程载体(新建 uni-app 工程 vs 扩展现有 `mobile-h5`)在实现计划中选定,本文不绑定。 +## 10. 后续 + +- 本文审阅通过后编写实现计划:菜单 SQL、H5 路由脚手架、scope 中间层、分模块页面、运费脱敏、联调与测试。 +- 实现计划中写死:菜单 `path` 与 `web-view` URL 拼装规则(对齐现有 OA)。