日期:2026-05-26 状态:待实现 方案:A — 在现有质检工单页面内新增出库 Tab
在现有质检工单页面 (quality-inspection/qc-work-order) 中新增"出库质检工单"Tab,展示由中试服务申请单/输注计划触发的出库质检工单。支持查看(含完整申请单+输注计划信息)、编辑备注、配置检测。不支持新建和删除。输注计划取消/删除时,关联的出库质检工单自动作废。
biz_type:pilot_service=中试服务、clinical_application=临床应用| 组件 | 状态 | 说明 |
|---|---|---|
biz_qc_work_order.work_order_type='outbound' |
已有 | 数据库字段已支持 |
biz_qc_work_order.qc_biz_type='outbound' |
已有 | 数据库字段已支持 |
biz_qc_work_order.infusion_schedule_id |
已有 | 关联输注计划 |
create_outbound_qc_work_order() |
已有 | 后端创建逻辑已实现 |
POST /web/admin/pilot-infusion-schedule/create-qc-work-order |
已有 | API 端点已存在 |
重要发现:
biz_qc_work_order表当前没有biz_type字段来区分"中试服务/临床应用"。biz_production_work_order已有此字段(通过2026-05-26-outbound-work-order.sql新增),但质检工单表没有。
需新增 SQL:
ALTER TABLE biz_qc_work_order
ADD COLUMN biz_type VARCHAR(20) NULL COMMENT '业务类型: pilot_service=中试服务, clinical_application=临床应用' AFTER infusion_schedule_id;
同时更新 create_outbound_qc_work_order() 函数,创建出库质检工单时写入 biz_type='pilot_service'(来自中试服务申请单触发的场景)。
在 web-admin/src/views/quality-inspection/qc-work-order/index.vue 的 el-tabs 中新增第 4 个 Tab:
┌──────────┬──────────┬──────────┬──────────┐
│ 入库质检 │ 临时质检 │ 出库质检 │ 全部工单 │
│ inbound │ temporary│ outbound │ all │
└──────────┴──────────┴──────────┴──────────┘
activeTypeTab 类型扩展为 'inbound' | 'temporary' | 'outbound' | 'all'fetchQcWorkOrderList,传入 workOrderType='outbound'| 筛选项 | 类型 | 说明 |
|---|---|---|
| 工单状态 | el-select |
待配置(dpz) / 已配置(ypz) / 已完成(ywc) / 已作废(yzf) |
| 业务类型 | el-select |
中试服务(pilot_service) / 临床应用(clinical_application) |
| 创建时间 | el-date-picker |
日期范围选择 |
| 关键词 | el-input |
搜索工单号、申请单号、申请单名称 |
| 列名 | 字段 | 宽度 | 说明 |
|---|---|---|---|
| 序号 | — | — | 分页计算 |
| 工单号 | workOrderNo |
min-width:160 | CKZJ 前缀 |
| 业务类型 | bizType |
min-width:100 | el-tag: pilot_service=primary, clinical_application=warning |
| 申请单号 | applicationNo |
min-width:160 | 从关联申请单带入 |
| 申请单名称 | applicationName |
min-width:200 | 从关联申请单带入 |
| 渠道名称 | channelName |
min-width:140 | 从关联申请单带入 |
| 输注时间 | infusionTime |
min-width:160 | 从输注计划带入 |
| 检测方式 | 计算字段 | min-width:140 | 格式化 "实验室 \ 第三方" |
| 备注 | remark |
min-width:160 | — |
| 状态 | workOrderStatus |
min-width:100 | el-tag: dpz=info, ypz=warning, ywc=success, yzf=danger |
| 创建时间 | createTime |
min-width:160 | — |
| 操作 | — | min-width:260, fixed="right" | 查看/编辑/配置检测 |
操作列按钮可见性:
| 按钮 | 显示条件 |
|---|---|
| 查看 | 所有状态 |
| 编辑(备注) | 非已完成、非已作废 |
| 配置检测 | 待配置、已配置 |
| 删除 | 不显示 |
| 新增 | 不显示 |
新建组件:web-admin/src/views/quality-inspection/qc-work-order/OutboundQcViewDialog.vue
使用 SystemViewDialog 组件,宽度 1200px,4列网格,compact 模式。
Section 1: 工单基本信息
| 字段 | 来源 |
|---|---|
| 工单号 | workOrderNo |
| 工单类型 | workOrderType → el-tag |
| 业务类型 | bizType → el-tag |
| 工单状态 | workOrderStatus → el-tag |
| 检测方式 | 计算字段(实验室/第三方) |
| 配置时间 | configuredTime |
| 配置人 | configuredBy |
| 备注 | remark |
Section 2: 中试服务申请单信息
| 字段 | 来源 |
|---|---|
| 申请单号 | application.applicationNo |
| 申请单名称 | application.applicationName |
| 申请单状态 | application.applicationStatus → el-tag |
| 渠道名称 | application.channelName |
Section 3: 患者信息
| 字段 | 来源 |
|---|---|
| 患者姓名 | patient.patientName |
| 性别 | patient.sex |
| 年龄 | patient.age |
| 联系电话 | patient.phoneNo |
| 证件号码 | patient.idCardNo |
| 紧急联系人 | patient.emergencyContact |
| 紧急联系电话 | patient.emergencyPhone |
| 临床诊断 | patient.clinicalDiagnosis(跨列) |
| 诊断附件 | patient.diagnosisAttachments(跨列,附件预览组件) |
Section 4: 输注方案信息
| 字段 | 来源 |
|---|---|
| 细胞类型 | infusionPlan.cellType |
| 规格 | infusionPlan.specText |
| 总疗程数 | infusionPlan.totalCourseCount |
| 疗程间隔 | infusionPlan.courseInterval |
| 输注途径 | infusionPlan.infusionRoute |
| 输注开始日期 | infusionPlan.infusionStartDate |
Section 5: 本次输注计划信息
| 字段 | 来源 |
|---|---|
| 输注时间 | infusionSchedule.infusionTime |
| 输注地点 | infusionSchedule.infusionLocation |
| 输注方式 | infusionSchedule.infusionMethod |
| 生产状态 | infusionSchedule.scheduleStatus → el-tag |
| 输注状态 | infusionSchedule.infusionStatus → el-tag |
| 质检状态 | infusionSchedule.qcStatus → el-tag |
| 取消原因 | infusionSchedule.cancelReason(仅已取消时显示) |
Section 6: 产品明细(表格)
| 列 | 字段 |
|---|---|
| 项目编码 | projectCode |
| 项目名称 | projectName |
| 细胞类型 | cellTypeName |
| 规格 | specText |
| 协议单价 | agreementPrice |
| 实际单价 | actualPrice |
| 份数 | quantity |
| 产品状态 | productStatus → el-tag |
Section 7+: 检测结果(动态,每个任务一个 Section)
复用现有的任务结果展示逻辑(实验室参数表 + 第三方附件),与入库质检查看对话框的检测结果 Section 一致。
GET /web/admin/qc-work-orders/{id}/outbound-detail所有状态/类型字段使用 el-tag 渲染,复用 status-tag-registry.ts 中的映射函数:
workOrderStatus: dpz=info, ypz=warning, ywc=success, yzf=dangerapplicationStatus: dks=info, jxz=warning, ywc=success, yzf=dangerscheduleStatus: dsc=info, ysc=primary, yjf=success, yqx=dangerinfusionStatus: dtz=info, yrqr=warning, yqx=danger, ywc=successqcStatus: dzc=info, yzj=success, yqx=dangerproductStatus: dtz=info, yrqr=warning, yqx=danger, ywc=success修改文件:backend/app/crud/qc_work_order.py
当 work_order_type='outbound' 时,在列表 SQL 中 LEFT JOIN 以下链路:
biz_qc_work_order
→ biz_pilot_infusion_schedule (ON infusion_schedule_id)
→ biz_pilot_infusion_plan (ON infusion_plan_id)
→ biz_pilot_application (ON pilot_application_id)
在 _row_to_dict() 中为 outbound 类型额外返回:
| 字段 | SQL 来源 |
|---|---|
bizType |
biz_qc_work_order.biz_type(新增字段,pilot_service/clinical_application) |
applicationNo |
biz_pilot_application.application_no |
applicationName |
biz_pilot_application.application_name |
channelName |
biz_pilot_application.channel_name |
infusionTime |
biz_pilot_infusion_schedule.infusion_time |
新增列表查询参数:bizType(可选),用于前端按业务类型筛选。
新增端点:GET /web/admin/qc-work-orders/{id}/outbound-detail
修改文件:
backend/app/api/qc.py — 新增路由backend/app/crud/qc_work_order.py — 新增 get_outbound_qc_detail() 函数返回数据结构:
{
"workOrder": {
"id", "workOrderNo", "workOrderType", "workOrderStatus",
"bizType", "hasLab", "hasThirdParty", "remark",
"configuredTime", "configuredBy", "createTime"
},
"application": {
"applicationNo", "applicationName", "applicationStatus", "channelName"
},
"patient": {
"patientName", "sex", "age", "phoneNo", "idCardNo",
"emergencyContact", "emergencyPhone",
"clinicalDiagnosis", "diagnosisAttachments"
},
"infusionPlan": {
"cellType", "specText", "totalCourseCount",
"courseInterval", "infusionRoute", "infusionStartDate"
},
"infusionSchedule": {
"infusionTime", "infusionLocation", "infusionMethod",
"scheduleStatus", "infusionStatus", "qcStatus", "cancelReason"
},
"products": [
{
"projectCode", "projectName", "cellTypeName", "specText",
"agreementPrice", "actualPrice", "quantity", "productStatus"
}
],
"tasks": [
{
"taskNo", "taskType", "taskStatus", "conclusion",
"results": [...],
"thirdPartyAttachments": "...",
"materialUsages": [...]
}
]
}
实现:通过工单的 infusion_schedule_id JOIN 链路一次性获取,tasks 复用现有的任务查询逻辑。
修改文件:backend/app/crud/pilot_infusion_schedule_mgmt.py
在输注计划取消/删除的状态更新逻辑中,新增:
# 当输注计划状态变更为取消时
if new_status in ('yqx',):
# 查找关联的未完成出库质检工单
pending_orders = session.query(BizQcWorkOrder).filter(
BizQcWorkOrder.infusion_schedule_id == schedule_id,
BizQcWorkOrder.work_order_status.notin_(['ywc', 'yzf']),
BizQcWorkOrder.del_flag == '0'
).all()
for order in pending_orders:
order.work_order_status = 'yzf'
| 功能 | 原因 |
|---|---|
| 配置检测 | 完全复用 configure_work_order() |
| 质检任务执行 | 复用现有任务开始/完成/填写结果流程 |
| 工单创建 | 复用 create_outbound_qc_work_order() |
| 编辑备注 | 复用现有 PUT 端点 |
| 文件 | 说明 |
|---|---|
web-admin/src/views/quality-inspection/qc-work-order/OutboundQcViewDialog.vue |
出库质检查看对话框组件 |
docs/sql/2026-05-26-qc-work-order-add-biz-type.sql |
质检工单表新增 biz_type 字段 |
| 文件 | 改动 |
|---|---|
web-admin/src/views/quality-inspection/qc-work-order/index.vue |
新增 outbound Tab、列表列、筛选条件、操作按钮 |
web-admin/src/api/qc-work-order.ts |
新增 fetchOutboundQcDetail API 函数 |
web-admin/src/utils/status-tag-registry.ts |
确保 outbound 相关状态标签映射完整 |
backend/app/api/qc.py |
新增 GET /qc-work-orders/{id}/outbound-detail 路由 |
backend/app/crud/qc_work_order.py |
扩展 _row_to_dict() outbound 字段 + 新增聚合查询函数 + 列表查询支持 bizType 筛选 |
backend/app/crud/pilot_infusion_schedule_mgmt.py |
输注计划取消时自动作废关联质检工单 |
backend/app/schemas/qc_work_order.py |
新增出库详情返回 Schema |