2026-06-16-qc-work-order-tab-split-design.md 15 KB

质检工单 Tab 拆分与分型展示设计

日期:2026-06-16
状态:已确认(2026-06-16 组件边界已确认)
范围:web-admin 质检工单 + 我的质检任务;后端列表 API 补充分型过滤
关联:2026-06-12-qc-work-order-fee-summary-design.md、outbound-qc-pilot-view-sections.ts、2026-06-10-basic-experiment-design.md


1. 背景与目标

1.1 问题

【质检工单】【我的质检任务】原有三 Tab(入库 / 出库 / 临时),同一 Tab 内混用字段模板,导致:

  • 出库卡片出现入库字段(如「来源类型」receptionSource)
  • 基础实验与中试/临床共用卡片 meta,关键业务字段缺失或错位
  • 入库采集与捐赠在组头、查看弹窗混用「协议」语义

1.2 目标

将业务线拆为 6 个 Tab,每个 Tab 仅展示、仅查询 对应子类型的工单与任务;列表卡片、查看弹窗、筛选区与 Tab 一一对应。

1.3 非目标

  • 不新增工单创建入口(捐赠入库仍由样本接收自动触发)
  • 不改动质检任务执行、配置检测、物料使用逻辑
  • 不在本期做「全部工单」汇总 Tab
  • 不改动生产工单模块 Tab 结构

2. Tab 定义

2.1 Tab 配置表(权威)

Tab Key 展示标签 workOrderType receptionSource bizType 列表布局
inbound_cell_storage 采集入库 inbound cell_storage — 样本分组 inbound-grouped
inbound_research_donation 捐赠入库 inbound research_donation — 样本分组 inbound-grouped
outbound_pilot_service 中试 outbound — pilot_service 单列 standalone
outbound_basic_experiment 基础实验 outbound — basic_experiment 单列 standalone
outbound_clinical_application 临床应用 outbound — clinical_application 单列 standalone
temporary 临时 temporary — — 单列 standalone

Tab 栏视觉分组(可选 CSS): 入库 2 | 出库 3 | 临时 1,标签使用短文案。

默认 Tab: inbound_cell_storage(替换原 inbound)。

路由记忆: ?tab=<tabKey>,刷新/分享链接保持当前 Tab。

2.2 数据隔离规则(强约束)

每个 Tab 的列表 API 请求 必须同时携带 上表中的过滤参数,禁止仅传 workOrderType 后在客户端再筛:

采集入库  → workOrderType=inbound  AND receptionSource=cell_storage
捐赠入库  → workOrderType=inbound  AND receptionSource=research_donation
中试      → workOrderType=outbound AND bizType=pilot_service
基础实验  → workOrderType=outbound AND bizType=basic_experiment
临床应用  → workOrderType=outbound AND bizType=clinical_application
临时      → workOrderType=temporary

验收: 在任一 Tab 下,列表中不得出现其它子类型的工单;切换 Tab 后分页重置为第 1 页。


3. 筛选区(按 Tab)

移除原「业务类型」「来源类型」下拉(已由 Tab 固定)。

Tab 关键词 placeholder 时间筛选标签 时间字段 额外筛选
采集入库 工单号/样本编码/入库编码 创建时间 createTime 触发来源(样本接收 / 生产过程)
捐赠入库 工单号/样本编码/入库编码 创建时间 createTime 触发来源
中试 工单号/申请单号/申请单名称/患者 输注时间 infusionTime —
基础实验 工单号/申请单号/课题名称/客户 交付时间 infusionTime(schedule 提货时间) —
临床应用 工单号/申请单号/申请单名称/患者 输注时间 infusionTime —
临时 工单号 创建时间 createTime —

默认时间范围:近 30 天(出库类按输注/交付时间,入库/临时按创建时间)。


4. 组件边界(已确认)

模块 策略 说明
QcWorkOrderTaskSubList 共用 任务执行、填结果、物料与 Tab 无关
配置检测 / 调整检测弹窗 共用 三种工单类型逻辑相同
QcWorkOrderCardList + QcWorkOrderSampleGroup + QcWorkOrderSingleCard 共用 各 Tab 通过 props 传入卡片 meta 字段模板(组头文案、meta 列、费用条开关)
查看详情弹窗 不共用 六 Tab 各一份独立查看界面;信息区块差异大,禁止再用 Host + variant 分支
Tab 页内容(筛选 + 工具栏 + 列表) 拷贝再改 从现有入库/出库/临时 Tab 剪出/拷贝为 6 个子页面;index.vue 仅 Tab 壳

我的质检任务: 与质检工单 共用同一套 6 个 Tab 子组件(tabs/*),已确认。差异仅:

  • prop pageMode='mine'
  • 卡片操作:仅「查看」,无配置检测 / 新增 / 删除等
  • 任务区 taskListMode='mine'
  • 数据:GET /qc-tasks/mine + 与 Tab 一致的 receptionSource / bizType 过滤

维护成本: 6 个 Tab 文件 + 2 个壳页面(qc-work-order/index.vue、my-qc-task/index.vue),不是 12 份拷贝。


5. 列表卡片展示矩阵

共用 QcWorkOrderCardList / QcWorkOrderSampleGroup / QcWorkOrderSingleCard;各 Tab 子页面传入不同的 cardMetaConfig(字段 label、取值、Tag、费用条),禁止在卡片内用 activeTypeTab === 'outbound' 大包大揽。

5.1 入库 · 采集(inbound_cell_storage)

样本组头(QcWorkOrderSampleGroup)

  • 样本编码、样本类型、采集协议号、协议状态、接收时间、经手人

组内费用条(组级,已有逻辑扩展)

  • 组内存在 cell_storage 工单且 paymentSummary 时展示 QcWorkOrderProtocolPaymentPanel

卡片 meta

  • 质检对象、触发来源 Tag、关联生产工单(仅 triggerSource=production)、实验室入库编码、检测方式、创建时间、备注

卡片费用条

  • paymentSummary(QcWorkOrderProtocolPaymentPanel compact)

工具栏

  • 「新增入库质检工单」(仅本 Tab;receptionSource 固定 cell_storage)

5.2 入库 · 捐赠(inbound_research_donation)

样本组头

  • 样本编码、样本类型、捐赠单号(protocolNo 字段存捐赠编号)、捐赠状态、接收时间、经手人

卡片 meta

  • 同采集入库卡片结构;不展示协议状态、费用相关字段

工具栏

  • 无新增按钮

5.3 出库 · 中试(outbound_pilot_service)

卡片 meta

  • 申请单号、申请单名称、渠道名称、患者姓名、第 N 次 / 共 M 次、输注时间、检测方式、创建时间、备注

禁止展示

  • receptionSource、业务类型 Tag(Tab 已表达)、基础实验专属字段

费用条

  • 不展示

5.4 出库 · 基础实验(outbound_basic_experiment)

卡片 meta

  • 申请单号、课题名称、客户名称、交付时间、售卖金额(可选,来自 feeSummary.saleAmount)、检测方式、创建时间、备注

费用条

  • QcWorkOrderFeeSummaryBar(feeSummary)

5.5 出库 · 临床应用(outbound_clinical_application)

卡片 meta

  • 申请单号、申请单名称、渠道名称、患者姓名、第 N 次 / 共 M 次、输注时间、检测方式、创建时间、备注

费用条

  • QcWorkOrderFeeSummaryBar(与 2026-06-13-production-work-order-fee-summary-design.md D1=B 一致)

5.6 临时(temporary)

保持现状:产品编码/名称/类型、检测方式、创建时间;工具栏「新增临时工单」。


6. 查看弹窗(六份独立界面)

不共用 QcWorkOrderViewDialogHost、OutboundQcViewDialog 及其中 variant 分支。自现有弹窗拷贝后按 Tab 删减字段;检测任务区块(实验室/第三方/参数/附件/物料)可抽 useQcWorkOrderTaskViewSections.ts 供六弹窗 import,避免任务展示逻辑拷六份。

6.1 Tab → 弹窗组件(一一对应)

Tab Key 新建组件 拷贝来源 主要差异
inbound_cell_storage InboundCellStorageViewDialog.vue 现 QcWorkOrderViewDialogHost + useQcWorkOrderViewDialog 协议状态、协议缴费、运输、样本接收
inbound_research_donation InboundResearchDonationViewDialog.vue 上者拷贝 无协议缴费;捐赠状态;组头/基本信息用捐赠文案
outbound_pilot_service OutboundPilotViewDialog.vue 现 OutboundQcViewDialog 仅中试:申请单、患者、输注方案/计划、产品、检测任务;无缴费区块
outbound_basic_experiment OutboundBasicExperimentViewDialog.vue 出库弹窗拷贝 课题/客户/交付计划/产品/缴费;无患者、输注方案
outbound_clinical_application OutboundClinicalViewDialog.vue 出库弹窗拷贝 同中试结构 + 临床应用缴费信息(如有)
temporary TemporaryQcViewDialog.vue 入库弹窗拷贝 仅产品信息 + 检测任务;无接收/运输/协议

6.2 挂载方式

  • 各 Tab 子页面 内直接 import 对应弹窗,:visible + @view 打开;不再使用统一 openView(row) 按类型分流。
  • 旧文件 QcWorkOrderViewDialogHost.vue、OutboundQcViewDialog.vue 在六弹窗落地并切换引用后删除(或首版标记 @deprecated 再删)。

6.3 可共用的底层(非 UI 壳)

共用项 说明
SystemViewDialog 布局壳
ProtocolAttachmentReadonly 附件只读
QcWorkOrderProtocolPaymentPanel 仅采集入库弹窗使用
fetchQcWorkOrderDetail / fetchOutboundQcDetail API
useQcWorkOrderTaskViewSections(新建) 检测任务 sections + 附件 slot + 物料 slot

7. Tab 子页面结构(拷贝再改)

web-admin/src/views/quality-inspection/qc-work-order/
  index.vue                          # 6 Tab 壳 + ?tab= 路由
  tabs/
    InboundCellStorageTab.vue        # 从原 index 入库区块剪出
    InboundResearchDonationTab.vue   # 拷贝 InboundCellStorageTab 再改
    OutboundPilotTab.vue             # 从原出库区块剪出
    OutboundBasicExperimentTab.vue   # 拷贝 OutboundPilotTab 再改
    OutboundClinicalTab.vue          # 拷贝 OutboundPilotTab 再改
    TemporaryTab.vue                 # 从原临时区块剪出
  view-dialogs/
    InboundCellStorageViewDialog.vue
    InboundResearchDonationViewDialog.vue
    OutboundPilotViewDialog.vue
    OutboundBasicExperimentViewDialog.vue
    OutboundClinicalViewDialog.vue
    TemporaryQcViewDialog.vue

my-qc-task/index.vue 同样 6 Tab 壳,import 上述 tabs/* 组件,传 page-mode="mine"。


8. 我的质检任务

与质检工单 共用 tabs/* 子组件与 cardMetaConfig;差异:

  • pageMode='mine':卡片仅「查看」
  • 任务列表 taskListMode='mine'
  • 数据流:先按 Tab 参数请求 GET /qc-tasks/mine,再聚合为卡片

后端扩展 list_mine_tasks: 增加 receptionSource、bizType 过滤,与工单列表对齐,避免客户端从全量任务中筛类型。

qc-mine-task-groups.ts:

  • QcWorkOrderTypeTab 替换为 QcWorkOrderTabKey
  • resolveWorkOrderTabKey(task) 由 workOrderType + receptionSource / bizType 解析
  • filterMineEntriesByWorkOrderSearch 按 tabKey 固定过滤,移除 bizType/receptionSource 筛选项

9. 后端 API 变更

7.1 GET /qc-work-orders(列表)

新增 Query 参数:

参数 类型 说明
receptionSource string 入库分型:cell_storage / research_donation

list_work_orders() 在 work_order_type=inbound 且 reception_source 有值时:

q0 = q0.filter(BizQcWorkOrder.reception_source == rs)

出库 Tab 继续传 bizType(已有)。

7.2 GET /qc-tasks/mine

新增 Query 参数:receptionSource、bizType,在 join BizQcWorkOrder 后过滤。

7.3 列表 enrich

确认基础实验列表项含 projectTitle(课题名称)、customerName;缺则于 _enrich_outbound_list_fields 补充 join。


10. 前端模块结构(摘要)

web-admin/src/utils/qc-work-order-tabs.ts           # Tab 常量 + toListQueryParams
web-admin/src/utils/qc-work-order-card-meta.ts     # 六 Tab 的 cardMetaConfig 导出(供 CardList props)
web-admin/src/views/.../qc-work-order/tabs/        # 6 Tab 子页面(拷贝再改)
web-admin/src/views/.../qc-work-order/view-dialogs/  # 6 独立查看弹窗
web-admin/src/views/.../qc-work-order/composables/useQcWorkOrderTaskViewSections.ts  # 检测任务区块共用

共用不改业务: QcWorkOrderTaskSubList、配置检测弹窗(仍在 index.vue 或 composable)。

删除/替换: QcWorkOrderViewDialogHost.vue、OutboundQcViewDialog.vue、useQcWorkOrderViewDialog.ts(逻辑拆入六弹窗 + task composable)。


11. 验收清单

11.1 数据隔离

  • 采集入库 Tab 仅 receptionSource=cell_storage 的 inbound 工单
  • 捐赠入库 Tab 仅 research_donation 的 inbound 工单
  • 中试 / 基础实验 / 临床 Tab 各自仅对应 bizType 的 outbound 工单
  • 临时 Tab 仅 workOrderType=temporary
  • 我的质检任务六 Tab 与上相同(任务所属工单类型一致)

11.2 展示

  • 出库卡片无 receptionSource 字段
  • 基础实验卡片无患者/输注疗程字段,有课题/客户/交付时间
  • 捐赠组头为捐赠单号/捐赠状态,非协议文案
  • 采集入库查看弹窗有协议缴费;捐赠无
  • 六 Tab 各打开对应独立查看弹窗,无交叉引用 Host/variant
  • 基础实验查看弹窗无患者/输注方案;中试/临床无课题专属区块

11.3 操作

  • 仅采集入库 Tab 有「新增入库质检工单」
  • 仅临时 Tab 有「新增临时工单」
  • 配置检测 / 调整检测 / 编辑备注行为与改版前一致

11.4 回归

  • Tab 切换重置分页与筛选(保留 Tab 专属默认时间范围)
  • URL ?tab= 可深链到指定 Tab
  • 费用摘要条规则与 2026-06-12-qc-work-order-fee-summary-design.md 一致

12. 决策记录

项 决策
Tab 数量 6(入库 2 + 出库 3 + 临时 1)
Tab 标签 短标签:采集入库 / 捐赠入库 / 中试 / 基础实验 / 临床应用 / 临时
实现策略 Tab 子页面拷贝再改;index.vue 仅 Tab 壳
数据过滤 服务端 强制分型,禁止仅靠前端过滤
TaskSubList 共用
配置检测弹窗 共用
CardList + SampleGroup 共用,props 传 cardMetaConfig
查看弹窗 六份独立界面,不共用 Host / OutboundQcViewDialog
检测任务展示 composable 共用,避免六份弹窗重复任务 UI 逻辑
我的质检任务 已确认 共用 6 个 tabs/*,pageMode='mine'