diff --git a/docs/superpowers/specs/2026-08-17-production-pre-transit-sample-design.md b/docs/superpowers/specs/2026-08-17-production-pre-transit-sample-design.md new file mode 100644 index 00000000..64841b4d --- /dev/null +++ b/docs/superpowers/specs/2026-08-17-production-pre-transit-sample-design.md @@ -0,0 +1,166 @@ +# 生产管理 — 预产及在途样本(独立副本)功能设计 + +**日期**: 2026-08-17 +**状态**: 待实现 +**界面模式**: 与质检侧相同(P27 衍生只读看板 + 双分区) +**参考**: `docs/superpowers/specs/2026-06-23-pre-transit-sample-design.md`、`web-admin/src/views/quality-inspection/pre-transit-sample/` + +## 1. 需求背景 + +生产部门需要查看与质检相同的「预产及在途样本」看板。为便于后续两部门界面独立扩充,**不**复用质检页面组件,而是在【生产管理】下提供**完整代码副本**,并使用**独立权限码**;数据查询初期仍共用现有后端接口。 + +## 2. 已确认决策 + +| 项 | 决策 | +|----|------| +| 前端页面 | **完整复制**到 `views/production/pre-transit-sample/`,与质检目录互不引用 | +| 权限码 | **独立**:`production:preTransitSample:list`(质检仍为 `biz:preTransitSample:list`) | +| 后端业务 API | **共用**现有 `GET /web/admin/pre-transit-samples/in-transit` 与 `…/pre-delivery` | +| 菜单标题 | 「预产及在途样本」(与质检同名) | +| 菜单位置 | 【生产管理】下,位于【库位管理】**上方** | +| 角色授权 | 迁移脚本自动授予「已有生产管理(PRM)下任一有效菜单」的角色 | +| 前端 API 模块 | **共用** `web-admin/src/api/pre-transit-sample.ts`(不复制) | +| 本期非目标 | 不改列表规则/字段;不新增生产专用查询 API;不改变质检页行为 | + +## 3. 架构关系 + +``` +┌─────────────────────┐ ┌─────────────────────┐ +│ 质检管理 │ │ 生产管理 │ +│ pre-transit-sample │ │ pre-transit-sample │ +│ (独立 Vue 副本) │ │ (独立 Vue 副本) │ +│ menuCode: │ │ menuCode: │ +│ biz:preTransit… │ │ production:pre… │ +└─────────┬───────────┘ └─────────┬───────────┘ + │ │ + └─────────────┬─────────────┘ + ▼ + web-admin api/pre-transit-sample.ts + ▼ + GET /web/admin/pre-transit-samples/* + (同一 CRUD/Service;鉴权 OR 两权限码) +``` + +## 4. 前端设计 + +### 4.1 文件 + +| 动作 | 路径 | +|------|------| +| 新建(自质检复制) | `web-admin/src/views/production/pre-transit-sample/index.vue` | +| 新建(自质检复制) | `web-admin/src/views/production/pre-transit-sample/PreTransitProtocolCardList.vue` | +| 修改 | `web-admin/src/router/modules/sqxp.ts` | +| 不改(共用) | `web-admin/src/api/pre-transit-sample.ts` | +| 不改 | `web-admin/src/views/quality-inspection/pre-transit-sample/**` | + +复制后仅调整:文件头注释(标注「生产管理」)、本地组件相对 import;功能与交互保持与质检侧一致。 + +### 4.2 路由与菜单(前端静态路由) + +在 `ProductionManage`(`path: production`)的 `children` 中,于 `ProductionStorageFacility`(库位管理)**之前**插入: + +| 项 | 值 | +|----|-----| +| id | `95200000000000000000000000000001`(C 菜单;与 SQL 一致;避开已占用的 `950…` / `951…` 段) | +| name | `ProductionPreTransitSample` | +| path | `pre-transit-sample` | +| 完整 Hash | `/#/production-group/production/pre-transit-sample` | +| component | `/production/pre-transit-sample/index` | +| title | 预产及在途样本 | +| keepAlive | `true` | +| menuCode | `production:preTransitSample:list` | + +### 4.3 UI / 行为 + +与质检页相同:双分区(在途 / 预产)、筛选、分页、仅「查看」、协议/捐赠查看弹窗。本期不做差异化。 + +若 `App.vue` 的 `panelTitleBarTextRules` 已按标题文案「预产及在途样本」注册竖条,生产页同标题可复用,无需新增规则。 + +## 5. 后端设计 + +### 5.1 业务逻辑 + +不新增 Service / CRUD;继续使用 `app/crud/pre_transit_sample.py`。 + +### 5.2 鉴权 + +文件:`backend/app/api/pre_transit_sample.py` + +将两处: + +```python +Depends(require_menu_code("biz:preTransitSample:list")) +``` + +改为: + +```python +Depends(require_any_menu_code( + "biz:preTransitSample:list", + "production:preTransitSample:list", +)) +``` + +说明:当前 `menu_guard` 对 menuCode 校验为放行(仅要求运营端登录);仍应改为 OR,以便日后恢复严格校验时,仅持有生产权限码的用户可调共用 API。 + +不新增生产专用 path。 + +## 6. 数据库与权限 SQL + +### 6.1 菜单 ID 与字段 + +| 项 | 值 | +|----|-----| +| C 菜单 id | `95200000000000000000000000000001` | +| F 按钮 id | `95200000000000000000000000000002` | +| parent_id | `PRM00000000000000000000000000001`(生产管理) | +| menu_name | 预产及在途样本 | +| path | `pre-transit-sample` | +| component | `/production/pre-transit-sample/index` | +| perms(C/F) | `production:preTransitSample:list` | +| order_num(C) | `0`(库位管理当前为 `1`,故置于其上方) | +| F 按钮 menu_name | 预产及在途查询 | +| remark | 生产看板:在途样本与预产协议(协议单维度只读;与质检页代码独立) | + +### 6.2 迁移脚本 + +新建:`docs/sql/alter_sys_menu_add_production_pre_transit_sample.sql` + +内容要求: + +1. **幂等插入** C、F 菜单(不存在则 INSERT;已存在可跳过或按 id 更新 path/component/perms)。 +2. **角色授权**:对满足以下条件的角色,幂等授予 C、F,并确保祖先 `PRM000…`(生产管理)已授权(缺则补;符合「选子必带祖先」约定): + - `sys_role.del_flag = 0` 且租户匹配; + - 已存在有效 `sys_role_menu`,其 `menu_id` 对应的 `sys_menu` 满足 `parent_id = 'PRM00000000000000000000000000001'` 且 `del_flag = 0`(即已有【生产管理】下任一子菜单)。 + - 不强制补授生产顶栏 `TOP000…0002`(目标角色通常已有;若侧栏仍不可见再人工补)。 +3. 主键策略对齐现有脚本:`UPPER(MD5(CONCAT(role_id, '|', menu_id)))`;软删记录先恢复再插入。 +4. 同步更新基线 `docs/sql/zkxw.sql` 中对应 `sys_menu` 行;授权明细可由迁移脚本在环境执行,基线以菜单种子为主。 +5. 将可执行片段追加到仓库根目录 `待同步到生产的sql脚本`(若团队仍用该文件跟踪待上线 SQL)。 + +### 6.3 「生产管理相关」判定边界 + +- **包含**:已授权库位管理、细胞产品库、生产工单等任意 PRM 子菜单的角色。 +- **不包含**:仅有「生产」顶栏或其他一级分组、但从未授权 PRM 下任何子菜单的角色;此类角色需管理员在角色管理中手动勾选。 + +## 7. 验收标准 + +1. 生产侧路由 `/#/production-group/production/pre-transit-sample` 可打开,列表数据与质检侧一致(同租户、同筛选)。 +2. 质检侧原路由与行为不变。 +3. 侧栏【生产管理】中,本菜单出现在【库位管理】上方,标题为「预产及在途样本」。 +4. 仅拥有 `production:preTransitSample:list`、未拥有质检权限码的角色:可见生产侧菜单(在脚本授予后);质检侧菜单仍按原权限。 +5. 修改生产侧 Vue 文件不影响质检侧页面(无共享页面组件)。 +6. 迁移脚本可重复执行且不产生重复有效 `sys_role_menu`。 + +## 8. 实现任务清单(摘要) + +1. 复制前端页面到 `views/production/pre-transit-sample/`。 +2. 更新 `sqxp.ts` 路由。 +3. 后端 API 改为 `require_any_menu_code`。 +4. 编写并核对菜单 + 角色授权 SQL;更新 `zkxw.sql` / 待同步脚本。 +5. 手工验收上述标准。 +6. 若改动了 backend/web-admin 源码,按 AGENTS.md 执行对应 `./scripts/update-graph.sh`。 + +## 9. 后续扩展(本期不做) + +- 生产侧筛选字段、操作按钮、列表规则与质检分叉时:只改生产目录下 Vue;必要时再新增 `/web/admin/production-pre-transit-samples/*` 并收紧各自鉴权。 +- 若恢复严格 menuCode 校验,共用 API 已具备 OR 语义,无需再改路由挂载方式。