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
可以实现,且与现有架构兼容。
| 诉求 | 结论 |
|---|---|
| 生产专员派发质检(选细胞产品+备注) | 生产工单卡片「派发质检工单」+ 弹窗 + API |
| 质检工单界面可见两种来源 | 同表 + 样本 Tab 分组展示 |
| 生产工单三 Tab 改卡片列表 | 可以;新建 ProductionWorkOrderCardList,单列 + 内嵌任务 |
市场专员 → 采集协议单
↓
质检专员 → 样本接收(结论=接收)
├→ 自动:入库质检工单 [trigger_source=reception] (放行门禁)
└→ 自动:入库生产工单
↓
生产专员 → 生产任务执行 → 产出细胞产品
↓
生产专员 → 【生产工单】卡片列表 → 【派发质检工单】
(选择细胞产品 + 填写备注 → 提交)
↓
新建:入库质检工单 [trigger_source=production] (过程质检,不替代门禁)
↓
质检专员 → 【质检工单】列表
同一样本编码下 Tab 切换:样本接收 | 生产过程(可多条)
参考 docs/mockups/qc-work-order-related-cards-prototype.html:
| 层级 | 规则 |
|---|---|
| 列表布局 | 单列,一行 = 一个样本组(flex-direction: column) |
| 同样本多条工单 | 顶部样本上下文条 + Tab 切换工单;下方 meta + 任务区联动 |
| 仅 1 条工单 | 无 Tab,结构与现网单卡一致 |
| 质检任务 | 三列网格;每卡 2 行融合:① 项目名 + Tag ② 任务号 · 负责人 · 操作 |
| 筛选 | 入库 Tab 增加「触发来源」:全部 / 样本接收 / 生产过程 |
现网: 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.vueindex.vue — 表格区域替换为上述 CardList位置: 生产工单卡片 操作区 主按钮(入库 Tab 必做;出库若有关联细胞产品可二期扩展)。
交互:
Promotion / Document 类图标 + 文案,非 primary 实心,与「派发任务」并列描边按钮;每卡仅一个 primary 时仍留给「进入执行/派发任务」)DispatchQcWorkOrderDialog.vuelabel-position="top",.dialog-form-layout + .form-grid-2):
textarea,max 512POST /web/admin/production-work-orders/{id}/qc-work-ordersElMessage.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 无产出时不可派发)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)。| 规则 | 建议默认值 |
|---|---|
| 放行门禁质检 | 仅 trigger_source=reception 的那条参与入库放行 |
| 过程质检是否阻塞放行 | 否(默认) |
| 发起时机 | 细胞产品已写入 biz_cell_product(生产任务输出后) |
| 同一产品重复发起 | 允许(如 P1/P2 各一次);可选幂等:同 production_work_order_id + cell_product_id 且状态非 yzf 时不重复建 |
| 检测项目 | 与现网一致:质检专员在工单上「配置检测」时自选 |
文件: 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
文件: 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。
文件: backend/app/crud/qc_work_order.py · list_work_orders
_wo_to_dict 增加:triggerSource, triggerSourceLabel, productionWorkOrderId, productionTaskIdtriggerSource=reception|productiongroups: [{ sampleCode, sampleMeta, workOrders: [...] }],分页按样本组sampleCode 分组(改动小,分页语义弱)文件: backend/app/crud/qc_work_order.py · create_work_order_from_reception
创建时显式写 trigger_source='reception'。
文件: backend/app/crud/storage_release_review.py · _build_qc_info
查询质检工单时增加:
.filter(BizQcWorkOrder.trigger_source == 'reception')
避免多条同工单时取错;过程质检不参与放行展示。
核心文件:
| 文件 | 改动 |
|---|---|
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 单独做「发起质检」入口(统一为工单卡片「派发质检工单」,避免两处入口)。
核心文件:
| 文件 | 改动 |
|---|---|
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 不重复。
质检任务(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。
docs/sql/migrations/2026-06-12-qc-work-order-trigger-source.sqlcreate_qc_work_order_from_reception 写 trigger_source=receptioncreate_qc_work_order_from_productionlist_cell_product_options_for_production_work_orderPOST .../qc-work-orders、GET .../cell-product-options_wo_to_dict + list 筛选 triggerSource_build_qc_info 仅取 reception 工单python scripts/check_field_consistency.py(若涉及 CRUD 字段)fetchCreateQcFromProduction、fetchProductionWorkOrderCellProductOptionsDispatchQcWorkOrderDialog.vueProductionWorkOrderCardList.vue(入库/出库/临时 meta 分支)index.vue 表格 → CardList;工具栏与选择逻辑适配WorkOrderTaskSubList.vue 三列紧凑任务卡QcWorkOrderSampleGroup.vue(Tab + 样本条)QcWorkOrderCardList.vue 改单列 + 分组渲染groupWorkOrdersBySample()QcWorkOrderTaskSubList.vue 三列紧凑任务卡cellProduct*、生产工单号./scripts/update-graph.sh web-admin(若改 import/组件)| 项 | 说明 | 建议 |
|---|---|---|
| 放行门禁 | 过程质检是否影响放行 | 默认不影响,仅 reception 工单入门禁 |
| 分页语义 | 按工单分页 vs 按样本分页 | 改按样本组分页,总数展示「N 样本 · M 工单」 |
| 出库/临时 Tab | 是否同样本分组 | 质检入库 Tab 按样本 Tab;生产三 Tab 均 一工单一卡 无样本 Tab |
| 派发质检范围 | 出库生产是否派发 | 一期 入库生产工单;出库有细胞产品场景二期 |
| 生产列表批量选择 | 卡片模式多选 | 一期可保留工具栏批量按钮 + 卡片 checkbox,或暂禁批量仅单卡操作 |
| 临时质检 Tab | 与生产过程质检区别 | 临时工单无样本关联;勿与 production 触发混淆 |
| 权限 | 谁可派发质检 | 生产专员 + 生产工单相关权限 |
质检工单
生产工单
el-table 主列表。docs/mockups/qc-work-order-related-cards-prototype.htmlweb-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderCardList.vueweb-admin/src/views/production/production-work-order/index.vueweb-admin/src/views/production/production-work-order/WorkOrderTaskSubList.vueDispatchTaskDialog.vuebackend/app/crud/qc_work_order.py · create_work_order_from_receptionbackend/app/crud/sample_reception.pybiz_qc_work_order