2026-06-12-production-triggered-qc-work-order.md 18 KB

生产过程发起质检 + 质检工单统一展示 实现计划

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement task-by-task.

Goal: 生产专员在【生产工单】卡片列表中「派发质检工单」(选细胞产品 + 备注);质检专员在【质检工单】同列表看到接收/生产两种来源并按样本 Tab 展示。同时【生产工单】入库/出库/临时三个 Tab 列表由表格改为与质检侧一致的单列卡片模式。

Architecture: 扩展 biz_qc_work_order 触发来源字段;生产 API 建单;生产/质检列表均改为单列大卡片 + 内嵌任务区(生产任务沿用现有子列表逻辑并收敛紧凑样式);质检侧同样本 Tab 分组;生产侧每工单卡片操作区增加「派发质检工单」弹窗。

Tech Stack: MySQL 5.7 · FastAPI · Vue 3 · Element Plus

UI 权威 Demo: docs/mockups/qc-work-order-related-cards-prototype.html(质检侧);生产侧卡片结构对齐 QcWorkOrderCardList.vue + 现网 WorkOrderTaskSubList.vue


1. 需求结论(能否实现)

可以实现,且与现有架构兼容。

诉求 结论
生产专员派发质检(选细胞产品+备注) 生产工单卡片「派发质检工单」+ 弹窗 + API
质检工单界面可见两种来源 同表 + 样本 Tab 分组展示
生产工单三 Tab 改卡片列表 可以;新建 ProductionWorkOrderCardList,单列 + 内嵌任务

2. 业务流程(目标态)

市场专员 → 采集协议单
    ↓
质检专员 → 样本接收(结论=接收)
    ├→ 自动:入库质检工单 [trigger_source=reception]  (放行门禁)
    └→ 自动:入库生产工单
            ↓
        生产专员 → 生产任务执行 → 产出细胞产品
            ↓
        生产专员 → 【生产工单】卡片列表 → 【派发质检工单】
            (选择细胞产品 + 填写备注 → 提交)
            ↓
        新建:入库质检工单 [trigger_source=production]  (过程质检,不替代门禁)
            ↓
质检专员 → 【质检工单】列表
    同一样本编码下 Tab 切换:样本接收 | 生产过程(可多条)

3. 已确认 UI 设计

3.1 质检工单列表(Demo 定稿)

参考 docs/mockups/qc-work-order-related-cards-prototype.html:

层级 规则
列表布局 单列,一行 = 一个样本组(flex-direction: column)
同样本多条工单 顶部样本上下文条 + Tab 切换工单;下方 meta + 任务区联动
仅 1 条工单 无 Tab,结构与现网单卡一致
质检任务 三列网格;每卡 2 行融合:① 项目名 + Tag ② 任务号 · 负责人 · 操作
筛选 入库 Tab 增加「触发来源」:全部 / 样本接收 / 生产过程

3.2 生产工单列表(新增,对齐卡片模式)

现网: production-work-order/index.vue 使用 el-table + type="expand" 展开生产任务(WorkOrderTaskSubList)。

目标: 入库 / 出库 / 临时三个 Tab 均改为单列卡片,结构与质检工单大卡片一致:

┌─ 生产工单 SC202606120001 ─────────────────────────────┐
│ head:工单号 + 状态 Tag + meta 栅格 + 操作按钮          │
│  操作含:查看 | 派发任务 | 派发质检工单 | 完成 | …      │
├──────────────────────────────────────────────────────┤
│ tasks:生产任务子列表(内嵌,非表格 expand)            │
└──────────────────────────────────────────────────────┘
Tab 卡片 meta 字段 分组策略
入库 与现网表格列一致:样本编码、协议状态、样本类型、接收时间… 单列;通常 1 样本 1 生产工单,不做 Tab 分组(与质检侧不同)
出库 业务类型、申请单号、用户名称、输注时间… 单列,一工单一卡
临时 工单号、状态、备注、配置时间… 单列,一工单一卡
层级 规则
列表布局 单列 flex-direction: column(替换 minmax 多列 / 表格)
生产任务 内嵌于卡片底部 #fafafa 任务区;复用 WorkOrderTaskSubList,样式收敛为 三列 + 两行融合(与质检任务视觉统一,内容字段仍为任务名/状态/工艺类型)
工具栏 保留「已选 N 项」、新增/派发任务/完成;批量逻辑暂保留(卡片可加 checkbox 或后续迭代)
移除 el-table + expand 行

新建组件:

  • ProductionWorkOrderCardList.vue — 对标 QcWorkOrderCardList.vue
  • index.vue — 表格区域替换为上述 CardList

3.3 派发质检工单(生产工单入口)

位置: 生产工单卡片 操作区 主按钮(入库 Tab 必做;出库若有关联细胞产品可二期扩展)。

交互:

  1. 点击 「派发质检工单」(Promotion / Document 类图标 + 文案,非 primary 实心,与「派发任务」并列描边按钮;每卡仅一个 primary 时仍留给「进入执行/派发任务」)
  2. 打开弹窗 DispatchQcWorkOrderDialog.vue
  3. 表单(label-position="top",.dialog-form-layout + .form-grid-2):
    • 细胞产品(必填):下拉,数据来自该生产工单下已产出细胞产品
    • 备注(选填):textarea,max 512
  4. 确定 → POST /web/admin/production-work-orders/{id}/qc-work-orders
  5. 成功:ElMessage.success;可选「前往质检工单」跳转 /#/quality-manage/qc-work-order?sampleCode=xxx

细胞产品选项来源(后端):

GET /web/admin/production-work-orders/{id}/cell-product-options
→ [{ id, productCode, productName, productTypeName, passage, storageSlotName, taskNo }]

从该工单下所有生产任务的 输出子表(biz_production_task_output / cell_product)去重汇总;无产出时禁用按钮并 tooltip「请先完成生产任务并录入输出细胞产品」。

前置条件:

  • 工单状态建议 jxz 或 ywc(dpz 无产出时不可派发)
  • 租户隔离、软删除一致

4. 数据模型

4.1 biz_qc_work_order 新增字段

ALTER TABLE biz_qc_work_order
  ADD COLUMN trigger_source VARCHAR(20) NOT NULL DEFAULT 'reception'
    COMMENT '触发来源 reception=样本接收 production=生产过程' AFTER qc_biz_type,
  ADD COLUMN production_work_order_id VARCHAR(64) NULL
    COMMENT '关联生产工单ID(生产过程触发时)' AFTER cell_product_id,
  ADD COLUMN production_task_id VARCHAR(64) NULL
    COMMENT '关联生产任务ID(可选)' AFTER production_work_order_id;

-- 历史数据:全部为 reception
UPDATE biz_qc_work_order SET trigger_source = 'reception' WHERE trigger_source IS NULL OR trigger_source = '';

-- 索引
CREATE INDEX idx_qc_wo_sample_trigger ON biz_qc_work_order (tenant_no, sample_code, trigger_source, del_flag);
CREATE INDEX idx_qc_wo_prod_wo ON biz_qc_work_order (production_work_order_id, del_flag);

说明:

  • uk_qc_wo_reception(reception_id, del_flag) 保留,保证接收触发仍 1:1。
  • 生产过程触发 不占用 该唯一键;同一样本可有多条 trigger_source=production 工单。
  • cell_product_id 已有;生产触发时 必填,接收触发时为空。
  • 不放 work_order_type=temporary;过程质检仍属入库链路(work_order_type=inbound)。

4.2 业务规则(需产品确认,建议默认)

规则 建议默认值
放行门禁质检 仅 trigger_source=reception 的那条参与入库放行
过程质检是否阻塞放行 否(默认)
发起时机 细胞产品已写入 biz_cell_product(生产任务输出后)
同一产品重复发起 允许(如 P1/P2 各一次);可选幂等:同 production_work_order_id + cell_product_id 且状态非 yzf 时不重复建
检测项目 与现网一致:质检专员在工单上「配置检测」时自选

5. 后端实现

5.1 新建 CRUD

文件: backend/app/crud/qc_work_order.py

def create_qc_work_order_from_production(
    db, *,
    production_work_order_id: str,
    cell_product_id: str,
    production_task_id: str | None = None,
    remark: str = "",
    tenant_no: str,
    user_id: str,
    create_dept_id: str = "",
) -> BizQcWorkOrder:
    """
    1. 校验生产工单存在、tenant、work_order_type=inbound
    2. 校验 cell_product 存在且 tenant 一致
    3. 从生产工单快照 sample_code / protocol_no / reception_id 等
    4. 插入 biz_qc_work_order:
       trigger_source=production, work_order_status=dpz
    5. flush,不 commit(由 API 层 commit)
    """

文件: backend/app/schemas/qc_work_order.py — 新增 ProductionQcWorkOrderCreateBody

5.2 API

文件: backend/app/api/production.py

方法 路径 说明
POST /production-work-orders/{work_order_id}/qc-work-orders 派发质检工单 Body: { cellProductId, remark? }
GET /production-work-orders/{work_order_id}/cell-product-options 弹窗细胞产品下拉选项

权限:生产工单菜单(如 biz:productionWorkOrder:list);建单写操作可复用或新增 biz:productionWorkOrder:dispatchQc。

5.3 列表 API 扩展

文件: backend/app/crud/qc_work_order.py · list_work_orders

  • _wo_to_dict 增加:triggerSource, triggerSourceLabel, productionWorkOrderId, productionTaskId
  • 筛选参数:triggerSource=reception|production
  • 分组(二选一):
    • A(推荐) 后端返回 groups: [{ sampleCode, sampleMeta, workOrders: [...] }],分页按样本组
    • B 仍返回 flat list,前端按 sampleCode 分组(改动小,分页语义弱)

5.4 接收触发现有逻辑

文件: backend/app/crud/qc_work_order.py · create_work_order_from_reception

创建时显式写 trigger_source='reception'。

5.5 入库放行联动

文件: backend/app/crud/storage_release_review.py · _build_qc_info

查询质检工单时增加:

.filter(BizQcWorkOrder.trigger_source == 'reception')

避免多条同工单时取错;过程质检不参与放行展示。


6. 前端实现

6.1 生产侧 — 列表卡片化 + 派发质检

核心文件:

文件 改动
production-work-order/index.vue 移除 el-table;接入 ProductionWorkOrderCardList;挂载 DispatchQcWorkOrderDialog
新建 ProductionWorkOrderCardList.vue 单列卡片;head(meta+ops) + 内嵌 WorkOrderTaskSubList;三 Tab 字段分支
WorkOrderTaskSubList.vue 任务卡改为三列 + 两行融合(与质检任务样式对齐)
新建 DispatchQcWorkOrderDialog.vue 细胞产品 select + 备注 + 提交
api/production-work-order.ts fetchCreateQcFromProduction、fetchProductionWorkOrderCellProductOptions

卡片操作区按钮(入库示例,从左到右):

按钮 类型 说明
派发任务 primary(每卡唯一主色) 现有逻辑,打开 DispatchTaskDialog
派发质检工单 描边 打开 DispatchQcWorkOrderDialog
完成工单 描边 现有逻辑
查看 / 编辑 / 删除 描边 / 更多 现有逻辑

DispatchQcWorkOrderDialog.vue 要点:

<!-- 560px dialog-form-layout -->
<!-- 只读:工单号、样本编码 -->
<!-- 必填:el-select 细胞产品(filterable,option 展示 编码 · 名称 · 代次) -->
<!-- 选填:备注 textarea -->
<!-- footer:取消 Close / 确定 Check -->

不再在 TaskOutputList 单独做「发起质检」入口(统一为工单卡片「派发质检工单」,避免两处入口)。

6.2 质检侧 — 列表重构

核心文件:

文件 改动
QcWorkOrderCardList.vue 单列布局;引入样本组 + Tab 容器
新建 QcWorkOrderSampleGroup.vue 样本上下文条 + Tab + 内嵌单工单 head/tasks
QcWorkOrderTaskSubList.vue 任务卡改为三列网格 + 两行融合布局
qc-work-order/index.vue 筛选增加「触发来源」;适配分组列表数据结构
api/qc-work-order.ts 类型扩展 + 分组 list 或前端 groupBy 工具

Tab 标签: {workOrderNo} · 样本接收|生产过程 + 状态 Tag

单条工单 meta 差异:

字段 样本接收 生产过程
触发来源 样本接收 生产过程
质检对象 原始样本 / — 细胞产品编码 + 名称
关联生产工单 — 生产工单号

样本级字段(样本编码、协议、接收信息)提到 样本上下文条,Tab 内 meta 不重复。

6.3 任务卡片样式(质检 + 生产任务统一)

质检任务(QcWorkOrderTaskSubList)与生产任务(WorkOrderTaskSubList)均采用:

.qc-task-cards-grid, .production-task-cards-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
// 每卡 2 行:name+tags / code·meta·ops
// min-height ~68px

可抽公共 SCSS 片段到 web-admin/src/styles/ 或共享 class 前缀 work-order-task-cards-grid。


7. 任务分解(实施顺序)

Phase 1 — 数据与后端建单(可独立验收)

  • 1.1 SQL 迁移写入 docs/sql/migrations/2026-06-12-qc-work-order-trigger-source.sql
  • 1.2 Model / Schema 增加字段
  • 1.3 create_qc_work_order_from_reception 写 trigger_source=reception
  • 1.4 实现 create_qc_work_order_from_production
  • 1.5 实现 list_cell_product_options_for_production_work_order
  • 1.6 生产 API:POST .../qc-work-orders、GET .../cell-product-options
  • 1.7 _wo_to_dict + list 筛选 triggerSource
  • 1.8 放行审核 _build_qc_info 仅取 reception 工单
  • 1.9 运行 python scripts/check_field_consistency.py(若涉及 CRUD 字段)

Phase 2 — 生产工单 UI(卡片化 + 派发质检)

  • 2.1 API:fetchCreateQcFromProduction、fetchProductionWorkOrderCellProductOptions
  • 2.2 新建 DispatchQcWorkOrderDialog.vue
  • 2.3 新建 ProductionWorkOrderCardList.vue(入库/出库/临时 meta 分支)
  • 2.4 index.vue 表格 → CardList;工具栏与选择逻辑适配
  • 2.5 WorkOrderTaskSubList.vue 三列紧凑任务卡
  • 2.6 卡片操作区「派发质检工单」接入弹窗
  • 2.7 权限码(如需)

Phase 3 — 质检列表 UI(Demo 落地)

  • 3.1 QcWorkOrderSampleGroup.vue(Tab + 样本条)
  • 3.2 QcWorkOrderCardList.vue 改单列 + 分组渲染
  • 3.3 列表 API 分组或前端 groupWorkOrdersBySample()
  • 3.4 筛选「触发来源」
  • 3.5 QcWorkOrderTaskSubList.vue 三列紧凑任务卡
  • 3.6 查看弹窗 / 配置检测:生产过程工单展示 cellProduct*、生产工单号

Phase 4 — 联调与文档

  • 4.1 端到端:接收 → 生产卡片 → 派发质检 → 质检列表 Tab 可见
  • 4.2 生产三 Tab 卡片列表回归:派发任务、完成工单、查看
  • 4.3 放行审核仍只认 reception 工单
  • 4.4 更新 OpenSpec / 设计 spec(可选)
  • 4.5 ./scripts/update-graph.sh web-admin(若改 import/组件)

8. 风险与待确认项

项 说明 建议
放行门禁 过程质检是否影响放行 默认不影响,仅 reception 工单入门禁
分页语义 按工单分页 vs 按样本分页 改按样本组分页,总数展示「N 样本 · M 工单」
出库/临时 Tab 是否同样本分组 质检入库 Tab 按样本 Tab;生产三 Tab 均 一工单一卡 无样本 Tab
派发质检范围 出库生产是否派发 一期 入库生产工单;出库有细胞产品场景二期
生产列表批量选择 卡片模式多选 一期可保留工具栏批量按钮 + 卡片 checkbox,或暂禁批量仅单卡操作
临时质检 Tab 与生产过程质检区别 临时工单无样本关联;勿与 production 触发混淆
权限 谁可派发质检 生产专员 + 生产工单相关权限

9. 验收标准

质检工单

  1. 样本接收后,质检列表出现 1 条「样本接收」工单(行为与现网一致)。
  2. 生产专员 派发质检工单 后,同一样本组出现新 Tab「生产过程」,状态为待配置。
  3. 质检专员 Tab 切换可分别配置检测、查看任务;任务区为三列两行融合卡片。
  4. 筛选「触发来源=生产过程」仅显示生产触发工单。
  5. 入库放行审核详情中,质检信息仍为接收触发工单。

生产工单

  1. 入库 / 出库 / 临时三个 Tab 均为 单列卡片,无 el-table 主列表。
  2. 卡片内嵌生产任务子列表,任务为紧凑三列布局。
  3. 入库生产工单卡片可点击 派发质检工单,选细胞产品 + 备注后创建成功。
  4. 无细胞产品产出时按钮不可用或有明确提示。
  5. 原有「派发任务」「完成工单」「查看」等操作在卡片模式下仍可用。

10. 参考

  • UI Demo(质检):docs/mockups/qc-work-order-related-cards-prototype.html
  • 质检卡片:web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderCardList.vue
  • 生产工单页(待改):web-admin/src/views/production/production-work-order/index.vue
  • 生产任务子列表:web-admin/src/views/production/production-work-order/WorkOrderTaskSubList.vue
  • 派发任务弹窗(表单参考):DispatchTaskDialog.vue
  • 接收建单:backend/app/crud/qc_work_order.py · create_work_order_from_reception
  • 接收事务:backend/app/crud/sample_reception.py
  • 质检工单表:biz_qc_work_order