实现需求文档 2.3.8 节「工艺路线配置」。在生产管理菜单下的「工艺库管理」之后新增「工艺路线管理」菜单。
核心功能:维护工艺路线基础信息(路线编码、名称、产品类型、版本号),支持同编码多版本管理(轻量版:is_current 标记当前版本),并通过拖拽式三栏弹窗配置路线中的工艺步骤和子表数据。
| 决策项 | 选择 | 理由 |
|---|---|---|
| 版本号 | 同编码多版本 + is_current 标记当前版本 | 轻量版:同 route_code 可有多条记录,仅一个可标记为当前版本。无发布/草稿状态机 |
| 子表范围 | 完整复刻4张子表(试剂/耗材/产出物/数据采集) | 从工艺库拖入时克隆默认数据,用户可覆盖编辑 |
| 排列模式 | 线性排列(A→B→C→D) | 卡片从上到下,无需分支逻辑 |
| 可编辑范围 | 全部字段可编辑(基础信息+4张子表) | 右侧面板展示完整工艺信息供修改 |
| 保存方式 | 实时保存,拖入即创建后端记录 | 每步操作即时持久化,弹窗关闭无需额外保存 |
| UI方案 | 方案A:单弹窗 + vue-draggable-plus | 项目中已有3处成熟用法,跨栏拖拽通过HTML5 Drag API组合实现 |
| 步骤删除 | 支持删除,软删除步骤+级联软删除子表 | 中栏卡片上有删除按钮,确认后删除 |
| 依赖模块 | 用途 | 状态 |
|---|---|---|
| 细胞产品类型管理(biz_cell_product_type) | 产品类型下拉 | 已实现 |
| 工艺工序分类(biz_process_category) | 工艺分组展示 | 已实现 |
| 工艺库(biz_process + 4张子表) | 拖入时的数据源和克隆来源 | 已实现 |
| SOP文档(biz_sop_document) | 步骤关联SOP | 已实现 |
| vue-draggable-plus@0.6.0 | 卡片排序拖拽 | 已安装 |
| sortablejs@1.15.7 | vue-draggable-plus 底层引擎 | 已安装 |
所有表遵循项目公共字段规范:id VARCHAR(64) UUID → 业务字段 → tenant_no → order_num → remark → create_by → create_dept_id → create_time → update_by → update_time → del_flag。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | VARCHAR(64) PK | UUID |
| route_code | VARCHAR(64) NOT NULL | 路线编码 |
| route_name | VARCHAR(100) NOT NULL | 路线名称 |
| product_type_id | VARCHAR(64) DEFAULT NULL | 细胞产品类型ID(引用 biz_cell_product_type) |
| version | VARCHAR(50) DEFAULT NULL | 版本号(用户手填文本,如 V1.0、V2.0) |
| is_current | CHAR(1) DEFAULT '0' | 是否当前版本(0-否 1-是)。同 route_code 下仅一条记录 is_current=1 |
| + 公共字段 |
索引:idx_route_tenant(tenant_no, del_flag)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | VARCHAR(64) PK | UUID |
| route_id | VARCHAR(64) NOT NULL | 所属路线ID |
| process_id | VARCHAR(64) DEFAULT NULL | 来源工艺库工艺ID(工艺被删时可null) |
| step_order | INT DEFAULT NULL | 步骤顺序(拖拽排序时自动计算) |
| process_code | VARCHAR(64) DEFAULT NULL | 工序代码(从工艺库克隆,可编辑) |
| category_id | VARCHAR(64) DEFAULT NULL | 工序分类ID(可编辑) |
| process_name | VARCHAR(100) DEFAULT NULL | 工序名称(可编辑) |
| description | VARCHAR(500) DEFAULT NULL | 描述(可编辑) |
| equipment_name | VARCHAR(200) DEFAULT NULL | 预计使用设备(可编辑) |
| estimated_duration | VARCHAR(100) DEFAULT NULL | 预估耗时(可编辑) |
| sop_ids | VARCHAR(1000) DEFAULT NULL | 关联SOP文档ID(可编辑,逗号分隔) |
| + 公共字段 |
索引:idx_prs_route(route_id, del_flag)、idx_prs_tenant(tenant_no, del_flag)
字段完全镜像 biz_process_reagent,但外键改为 step_id(关联 biz_process_route_step.id):
| 字段 | 类型 | 说明 |
|---|---|---|
| id | VARCHAR(64) PK | UUID |
| step_id | VARCHAR(64) NOT NULL | 所属步骤ID |
| reagent_code | VARCHAR(64) DEFAULT NULL | 试剂编码 |
| reagent_name | VARCHAR(100) DEFAULT NULL | 试剂名称 |
| spec | VARCHAR(200) DEFAULT NULL | 规格 |
| standard_usage | VARCHAR(100) DEFAULT NULL | 标准用量 |
| unit | VARCHAR(64) DEFAULT NULL | 单位 |
| is_key_material | CHAR(1) DEFAULT '0' | 是否关键物料(0-否 1-是) |
| + 公共字段 |
索引:idx_prsr_step(step_id, del_flag)
字段完全镜像 biz_process_consumable,外键改为 step_id:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | VARCHAR(64) PK | UUID |
| step_id | VARCHAR(64) NOT NULL | 所属步骤ID |
| consumable_code | VARCHAR(64) DEFAULT NULL | 耗材编码 |
| consumable_name | VARCHAR(100) DEFAULT NULL | 耗材名称 |
| spec_model | VARCHAR(200) DEFAULT NULL | 规格型号 |
| standard_usage | VARCHAR(100) DEFAULT NULL | 标准用量 |
| unit | VARCHAR(64) DEFAULT NULL | 单位 |
| is_required | CHAR(1) DEFAULT '1' | 是否必需(1-必须 0-可选) |
| remark | VARCHAR(512) DEFAULT NULL | 备注 |
| + 公共字段(不含 remark) |
索引:idx_prsc_step(step_id, del_flag)
字段完全镜像 biz_process_output,外键改为 step_id:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | VARCHAR(64) PK | UUID |
| step_id | VARCHAR(64) NOT NULL | 所属步骤ID |
| output_type_id | VARCHAR(64) DEFAULT NULL | 产出类型ID |
| output_name | VARCHAR(200) DEFAULT NULL | 产出物名称 |
| output_barcode | VARCHAR(200) DEFAULT NULL | 产出物条码 |
| + 公共字段 |
索引:idx_prso_step(step_id, del_flag)
字段完全镜像 biz_process_data_collection,外键改为 step_id:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | VARCHAR(64) PK | UUID |
| step_id | VARCHAR(64) NOT NULL | 所属步骤ID |
| collection_name | VARCHAR(100) DEFAULT NULL | 采集信息名称 |
| unit | VARCHAR(64) DEFAULT NULL | 单位 |
| + 公共字段 |
索引:idx_prsdc_step(step_id, del_flag)
在「工艺库管理」(order_num=6)之后、「SOP文档」(order_num=7)之前插入,SOP 文档 order_num 改为 8:
INSERT INTO sys_menu (id, menu_name, parent_id, menu_type, path, component, perms, is_frame, visible, status, tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag)
VALUES ('90000000000000000000000000000010', '工艺路线管理', '90000000000000000000000000000001', 'C', 'process-route', '/production/process-route/index', 'production:process-route:list', 1, '1', '1', 'zkxw', 7, NULL, NULL, '', '2026-05-19 00:00:00', NULL, '2026-05-19 00:00:00', 0);
-- SOP文档 order_num 从 7 改为 8
UPDATE sys_menu SET order_num = 8 WHERE id = '90000000000000000000000000000004';
路由前缀:/api/admin/production/route/
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /list |
路线分页列表。支持筛选:route_name(模糊)、route_code(精确)、product_type_id。排序:order_num ASC, create_time DESC。带 tenant_no 隔离。 |
| POST | /create |
创建路线主表。必填:route_code, route_name。自动填充 tenant_no。默认 is_current=0。 |
| PUT | /update |
更新路线主表信息(编码、名称、产品类型、版本号、备注)。 |
| PUT | /set-current |
设置指定路线为当前版本。逻辑:先将同 route_code + tenant_no 下所有记录 is_current 置 0,再将目标记录 is_current 置 1。 |
| DELETE | /delete/{id} |
软删除路线(del_flag=1)+ 级联软删除所有步骤及步骤子表。 |
| GET | /detail/{id} |
获取路线详情:主表 + 步骤列表(按 step_order ASC)+ 每个步骤的4张子表数据。 |
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /step/add |
从工艺库拖入创建步骤。入参:route_id, process_id, step_order。后端读取 biz_process 基础信息克隆到 step 表,读取4张子表数据批量克隆到 routestep* 子表。返回完整 step 对象(含子表)。 |
| PUT | /step/update |
更新步骤基础信息(右侧面板字段修改时触发)。 |
| PUT | /step/reorder |
批量重排步骤顺序。入参:route_id, step_ids[](新顺序数组)。遍历更新 step_order。 |
| DELETE | /step/delete/{id} |
软删除步骤(del_flag=1)+ 级联软删除该步骤的4张子表数据。 |
| PUT | /step/reagent/update |
更新步骤试剂子表。入参:step_id, items[](完整替换)。 |
| PUT | /step/consumable/update |
更新步骤耗材子表。入参:step_id, items[](完整替换)。 |
| PUT | /step/output/update |
更新步骤产出子表。入参:step_id, items[](完整替换)。 |
| PUT | /step/data-collection/update |
更新步骤数据采集子表。入参:step_id, items[](完整替换)。 |
拖入克隆(step/add):
biz_process 读取工艺基础信息biz_process_route_step(克隆字段:process_code, category_id, process_name, description, equipment_name, estimated_duration, sop_ids)biz_process_reagent 等4张子表批量读取并插入对应 biz_process_route_step_*级联软删除:
子表更新(完整替换策略):
| 文件 | 操作 | 说明 |
|---|---|---|
web-admin/src/views/production/process-route/index.vue |
新建 | 路线列表页 + 路线图配置弹窗 |
web-admin/src/api/production.ts |
追加 | route 相关 API 函数 |
web-admin/src/router/modules/sqxp.ts |
追加 | process-route 路由条目 |
遵循标准列表模板(参考 src/views/system/unit/index.vue):
el-tag 标签)、备注、创建时间弹窗属性:width="90vw",destroy-on-close,标题显示路线名称和版本号
三栏布局(flex):
┌──────────────────────────────────────────────────────────────┐
│ 路线图配置 - {路线名称} v{版本号} [关闭] │
├────────────┬──────────────────────┬──────────────────────────┤
│ 工艺库 │ 工艺流程布局 │ 工艺详情 │
│ (240px) │ (flex:1) │ (360px) │
│ │ │ │
│ [分类折叠] │ ┌────────────┐ │ 工序名称: [___] │
│ > 细胞培养 │ │ 步骤1: xxx │ ←拖 │ 工序分类: [下拉] │
│ [卡片] │ └────────────┘ │ 描述: [___] │
│ [卡片] │ ┌────────────┐ │ 设备: [___] │
│ > 病毒转染 │ │ 步骤2: xxx │ │ 预估耗时: [___] │
│ [卡片] │ └────────────┘ │ SOP: [选择] │
│ > ... │ │ ────────────── │
│ │ [+ 拖入工艺卡片] │ [试剂][耗材][产出][采集] │
│ │ │ (子表tab切换编辑) │
└────────────┴──────────────────────┴──────────────────────────┘
左栏 — 工艺库面板(240px 固定宽度):
el-collapse 按工序分类(biz_process_category)分组展示draggable="true" + @dragstart 传递 process_id中栏 — 流程布局区(flex:1 自适应):
vue-draggable-plus(VueDraggable 组件)包裹步骤卡片列表<el-icon><Rank /></el-icon>)@dragover.prevent + @drop 接收从左栏拖入的工艺卡片POST /step/add,即时创建后端记录PUT /step/reorderDELETE /step/delete/{id} → 从列表移除右栏 — 工艺详情编辑面板(360px 固定宽度):
@change 触发 PUT /step/update 实时保存PUT /step/reagent/update拖入流程:
左栏卡片 dragstart(process_id)
→ 中栏 drop 事件
→ POST /step/add {route_id, process_id, step_order: list.length + 1}
→ 后端克隆工艺+子表 → 返回完整 step
→ 前端追加到步骤列表
排序流程:
中栏内 vue-draggable-plus 拖拽排序
→ @end 回调
→ PUT /step/reorder {route_id, step_ids: [...]}
编辑流程:
右栏字段 @change
→ PUT /step/update {step_id, ...fields}
右栏子表增删改
→ PUT /step/{sub-table}/update {step_id, items: [...]}
删除步骤:
卡片删除按钮 → ElMessageBox.confirm
→ DELETE /step/delete/{step_id}
→ 前端从列表移除
点击步骤:
中栏卡片 click
→ 设置 selectedStepId
→ 右栏加载该步骤详情(从列表数据中取,无需额外 API)
| 层 | 文件 | 操作 |
|---|---|---|
| SQL | docs/sql/production_process_route.sql |
新建:6张表DDL + 菜单INSERT + SOP order_num UPDATE |
| Model | backend/app/models/models.py |
追加 6 个 SQLAlchemy Model 类 |
| Model | backend/app/models/__init__.py |
追加 6 个 export |
| CRUD | backend/app/crud/process_route.py |
新建:路线CRUD + 步骤CRUD + 子表CRUD + 克隆逻辑 |
| API | backend/app/api/production.py |
追加 route 子路由(挂载到 production router 下) |
| Schema | backend/app/schemas/process_route.py |
新建:Pydantic v2 schemas |
| 前端 API | web-admin/src/api/production.ts |
追加 route 相关函数(~15个 API 函数) |
| 前端页面 | web-admin/src/views/production/process-route/index.vue |
新建:列表页 + 三栏拖拽配置弹窗 |
| 路由 | web-admin/src/router/modules/sqxp.ts |
追加 process-route 路由条目 |