日期: 2026-06-15
状态: 已实现
关联模块: 设备管理、工艺库管理、工艺路线管理、生产工单/生产任务
【生产基础信息】→【设备管理】维护租户内设备主数据(biz_equipment)。
【工艺库管理】→【工艺列表】中「设备名称」目前为自由文本(equipment_name),与设备主数据无关联,存在录入不一致、无法校验、无法追溯等问题。
工艺还会经【工艺路线】组合,并在【生产工单】→【生产任务】中作为步骤快照执行。设备字段在三层均采用快照复制模式(与工序名称等字段一致),改造需兼顾主数据关联与历史快照完整性。
| # | 决策 | 说明 |
|---|---|---|
| 1 | 步骤级可覆盖(选项 A) | 工艺路线步骤、生产任务步骤的设备必须从设备管理选择,但允许与工艺主数据的默认设备不同 |
| 2 | 多设备逗号存储 | 三表新增 equipment_ids(逗号分隔 ID),equipment_name 扩展为逗号分隔名称快照(varchar 1000) |
| 3 | 保留名称快照 | equipment_name 保存当时设备名称列表(逗号分隔),列表/导出直接展示 |
| 4 | 不自动回写下游 | 修改工艺主数据的设备后,不自动更新已存在的路线步骤或生产任务步骤(与现有 process_name 等行为一致) |
| 5 | 设备删除约束 | 被工艺/路线步骤引用的设备禁止软删除;停用(status=0)允许,下拉中过滤或标记异常 |
| 6 | UI 控件 | 三处编辑界面:el-input 改为 el-select(filterable),数据源 fetchAllEquipments(),展示「设备编码 / 设备名称」 |
biz_equipment(设备主数据)
↑ equipment_id 引用
biz_process(工艺默认设备)
│ add_step / 拖入克隆:复制 equipment_id + equipment_name
↓
biz_process_route_step(路线步骤,可覆盖设备)
│ _clone_route_to_task:复制 equipment_id + equipment_name
↓
biz_production_task_step(任务步骤,可覆盖设备)
复制触发点(均需同步 equipment_id + equipment_name):
| 触发场景 | 后端函数 |
|---|---|
| 工艺拖入路线 | process_route.add_step() |
| 路线步骤复制 | process_route.copy_step() |
| 路线克隆新版本 | process_route 版本复制逻辑(如有) |
| 任务选路线派工 | production_task._clone_route_to_task() |
| 任务手动加工艺步骤 | production_task.add_task_step(process_id=...) |
| 任务步骤复制 | production_task.copy_task_step() |
在以下表业务字段区(description 之后或同类位置)新增:
| 表 | 新增字段 | 类型 | 说明 |
|---|---|---|---|
biz_process |
equipment_id |
VARCHAR(64) DEFAULT NULL | 关联 biz_equipment.id |
biz_process_route_step |
equipment_id |
VARCHAR(64) DEFAULT NULL | 步骤级设备,可覆盖工艺默认 |
biz_production_task_step |
equipment_id |
VARCHAR(64) DEFAULT NULL | 任务步骤级设备,可覆盖路线/工艺 |
保留现有字段: 三表 equipment_name varchar(200) 不删除,作为快照冗余。
索引(可选,建议):
idx_process_equipment(equipment_id, del_flag) — 用于删除引用检查biz_equipment — 结构不变,增加被引用校验逻辑biz_process_route、biz_production_task 及所有子表(试剂/耗材/产出/采集)— 不涉及设备ALTER TABLE biz_process
ADD COLUMN equipment_id varchar(64) DEFAULT NULL COMMENT '关联设备ID(biz_equipment.id)' AFTER description;
ALTER TABLE biz_process_route_step
ADD COLUMN equipment_id varchar(64) DEFAULT NULL COMMENT '关联设备ID(biz_equipment.id)' AFTER description;
ALTER TABLE biz_production_task_step
ADD COLUMN equipment_id varchar(64) DEFAULT NULL COMMENT '关联设备ID(biz_equipment.id)' AFTER description;
equipment_name 非空记录,按 tenant_no + 精确/trim 后匹配 biz_equipment.equipment_name 回填 equipment_idequipment_id 留 NULL,equipment_name 保留原值;列表/表单展示时提示「未关联设备(历史数据)」backend/scripts/migrate_process_equipment_id.py,可 --dry-runbackend/app/models/models.py)三个 Model 各增加:
equipment_id = Column(String(64), nullable=True, comment="关联设备ID")
写入规则(统一 helper,建议 resolve_equipment_snapshot(db, equipment_id, tenant_no) -> (id, name)):
equipment_id 时:校验设备存在、未删除、同租户;写入 equipment_id 并将 equipment_name 设为当前 biz_equipment.equipment_nameequipment_id = None,equipment_name = Noneequipment_name 字符串而不传 ID(API 层废弃纯文本写入,兼容读取旧数据)_row_to_dict 扩展字段:
equipmentIdequipmentName(快照名称,已有)equipmentCode、equipmentStatus(join 设备表,仅展示)设备删除(equipment.py soft_delete_equipment):
biz_process、biz_process_route_step 是否存在 equipment_id = ? AND del_flag = 0raise ValueError("该设备已被工艺或工艺路线引用,无法删除")backend/app/api/production.py 等)ProcessCreateBody / ProcessUpdateBody:
equipment_id: Optional[str] = Field(None, alias="equipmentId")
# equipment_name 只读出参,Create/Update 不再接受客户端直传 equipmentName
ProcessRouteStepUpdateBody、ProductionTaskStepUpdateBody:
equipmentId,服务端解析名称快照响应: 继续返回 equipmentId + equipmentName;详情可增加 equipmentCode 便于展示。
| 文件 | 函数 | 改动 |
|---|---|---|
crud/process_route.py |
add_step |
复制 proc.equipment_id + proc.equipment_name |
crud/process_route.py |
copy_step |
复制 src.equipment_id + src.equipment_name |
crud/process_route.py |
update_step |
支持 equipment_id 参数,经 helper 写快照 |
crud/production_task.py |
_clone_route_to_task |
复制 rs.equipment_id + rs.equipment_name |
crud/production_task.py |
add_task_step |
从工艺复制 equipment_id + equipment_name |
crud/production_task.py |
update_task_step |
支持 equipment_id |
crud/production_task.py |
copy_task_step |
复制 src.equipment_id + src.equipment_name |
| 页面 | 文件 | 改动 |
|---|---|---|
| 工艺列表/表单 | views/production/process/index.vue |
设备名称 → el-select,绑定 formData.equipmentId;列表列展示 equipmentName(或编码/名称) |
| 工艺路线步骤 | views/production/process/ProcessRouteTab.vue |
步骤基本信息区同样改为设备下拉,保存传 equipmentId |
| 生产任务步骤 | views/production/production-work-order/StepDetailPanel.vue |
同上 |
| 任务步骤编辑器 | useTaskStepEditor.ts |
保存 payload 改为 equipmentId;选中时本地同步 equipmentName 展示 |
fetchAllEquipments()(/web/admin/equipments/all){equipmentCode} / {equipmentName}status === '1' 正常设备可选;status === '0' 可显示但标记「异常」equipmentId 为空但 equipmentName 有值:select 显示 placeholder「历史文本:xxx」,引导用户重新选择label-position="top"| 场景 | 行为 |
|---|---|
| 新建工艺并选设备 | 写 equipment_id,冗余 equipment_name |
| 工艺改设备 | 仅更新 biz_process;已有路线/任务步骤不变 |
| 路线步骤改设备 | 仅更新该步骤;允许与来源工艺不同 |
| 任务步骤改设备 | 仅更新该步骤;执行中可改(与现有步骤编辑一致) |
| 设备改名 | 已存快照名称不变;新保存/新复制使用新名称 |
| 设备停用 | 下拉不可选或弱提示;已关联记录仍显示快照 |
| 设备删除 | 被工艺或路线步骤引用时拒绝删除 |
equipment_name 无 ID 时页面不报错,可重新关联python scripts/check_field_consistency.py