2026-06-25-qc-work-order-protocol-group-design.md 11 KB

入库质检工单 · 协议单多样本 Tab 分组 — 设计文档

日期:2026-06-25
状态:已实现
范围:web-admin 【质检工单】【我的质检任务】入库类 Tab;后端列表关键词补协议号
关联:2026-06-16-qc-work-order-tab-split-design.md、2026-06-25-qc-work-order-all-tab-design.md、2026-06-25-qc-inspection-batch-design.md


1. 背景与目标

1.1 问题

细胞存储质检、科研捐赠质检的工单均来自采集协议单 / 科赠协议单。一份协议单可含多个样本,每个样本接收后各生成至少一条质检工单(生产过程可再追加)。

现网列表按 sampleCode(样本编码) 分组:同一协议下的多个样本各自占一张卡片,协议号等信息在组头副标题重复出现,用户难以「按协议一眼看全样本质检进度」。

1.2 目标

在 细胞存储质检、科研捐赠质检 两个 Tab 中,将同一协议单下的多个样本合并为一张协议组卡片,组内用 Tab 切换样本;样本内仍保留现网 触发来源 Tab(样本接收 / 生产过程)。

【质检工单】与【我的质检任务】共用同一套列表组件与分组逻辑。

1.3 非目标

  • 不改变出库、临时 Tab 的列表布局。
  • 不在 「所有」 Tab 做协议分组(沿用平铺 + 类型 Tag,见 2026-06-25-qc-work-order-all-tab-design.md §1.3)。
  • 不合并细胞存储与科研捐赠(仍分 Tab)。
  • 不把同协议多样本压成单层扁平卡片(去掉样本层级)。
  • 本期不做「按协议分页」后端改造(分页仍按工单条数;见 §5.3 边界说明)。

2. 列表信息架构

2.1 三层结构

协议组(新增外层)
  └── 样本 Tab(新增中层)
        └── 触发来源 Tab(现网 QcWorkOrderSampleGroup 内层)
              └── 工单卡片 + 检测批次 + 任务

2.2 分组键

层级 分组字段 回退
协议 collectionProtocolId (protocolNo).trim(),仍空则用首条工单 id
样本 sampleCode 工单 id
工单 同样本下按 triggerSource Tab 切换 现网逻辑

说明:科赠工单的 collectionProtocolId 存的是 research_donation_id(后端建单已如此),与细胞存储共用分组字段名。

2.3 Tab 配置

listLayout 保持 inbound-grouped(语义扩展为「入库分组列表」,实现改为协议优先分组,不再在 QcWorkOrderCardList 顶层直接使用 QcWorkOrderSampleGroup)。

受影响 Tab:

Tab Key 展示标签 列表布局(实现)
inbound_cell_storage 细胞存储质检 协议分组 + 样本 Tab
inbound_research_donation 科研捐赠质检 协议分组 + 样本 Tab

3. UI 设计

3.1 协议组头(qc-protocol-row__ctx)

视觉对齐现网 qc-sample-row__ctx(绿渐变顶栏 + 序号)。

元素 细胞存储 科研捐赠
主标题 协议号 protocolNo 捐赠单号 protocolNo
副标题 协议状态 Tag + N 个样本 + 可选进度摘要 捐赠状态 Tag + N 个样本 + 可选进度摘要
Badge 组内工单总数(如 5 条质检) 同左

进度摘要(可选展示): 如 2/3 已配置,按样本维度统计:该样本下存在 workOrderStatus !== 'dpz' 的 gate 工单(优先 triggerSource=reception,否则取组内首条)即计为「已配置样本」。无数据时不展示。

协议费用条: 仅 细胞存储 Tab、且组内存在 paymentSummary 的工单时,在协议组头下方展示 一次 QcWorkOrderProtocolPaymentPanel(compact),不要在每个样本 Tab 内重复。

3.2 样本 Tab 行(qc-protocol-sample-tabs)

  • 样式复用现网 qc-wo-indep-tabs__btn / pill Tab(与 QcWorkOrderSampleGroup 触发来源 Tab 一致)。
  • 仅当组内样本数 ≥ 2 时展示 Tab 行;单样本时隐藏 Tab 行,直接展示该样本工单区。

每个 Tab pill 文案:

部分 内容
序号 1 2 3(圆点序号,与现网一致)
主文案 样本编码(monospace)
辅助 样本类型 sampleTypeName(有值时)
状态 该样本 gate 工单 workOrderStatus 的 el-tag

Tab 排序:按样本编码字典序;同编码按 gate 工单 createTime ASC。

3.3 样本工单区

选中样本后渲染 QcWorkOrderSampleGroup,传入该样本下的 workOrders 子集,并增加 prop:

Prop 值 说明
hideContextBar true 隐藏原样本组头(协议组头 + 样本 Tab 已表达上下文)
其余 与现网一致 内层触发来源 Tab、卡片、批次、任务

单样本且仅 1 条工单时:无样本 Tab、无触发来源 Tab,直接展示 QcWorkOrderSingleCard。

3.4 线框(ASCII)

┌─ 1  XY2026001  [协议进行中]  3 个样本 · 2/3 已配置  [5 条质检] ─┐
│ [协议费用 compact — 仅细胞存储]                                    │
├─ 样本 Tab ───────────────────────────────────────────────────────┤
│ [1 A001·脐带血·待配置] [2 A002·胎盘·已配置] [3 B003·进行中]       │
├─ 触发来源 Tab(样本 A001 有 2 条工单时)───────────────────────────┤
│ [样本接收 ZJ…] [生产过程 ZJ…]                                      │
├─ 工单 meta + 检测批次 + 任务 ─────────────────────────────────────┤
└───────────────────────────────────────────────────────────────────┘

4. 前端实现要点

4.1 新增工具(web-admin/src/utils/qc-work-order-groups.ts)

export type QcWorkOrderProtocolGroupModel = {
  groupKey: string
  protocolId: string
  protocolNo: string
  receptionSource: 'cell_storage' | 'research_donation'
  sampleGroups: QcWorkOrderSampleGroupModel[]
  workOrders: QcWorkOrder[] // 组内全部工单(扁平)
}

export function groupInboundQcWorkOrdersByProtocol(
  rows: QcWorkOrder[]
): QcWorkOrderProtocolGroupModel[]

实现步骤:

  1. 按 collectionProtocolId(及回退键)聚合工单。
  2. 每组内调用现有 groupInboundQcWorkOrders 得到 sampleGroups。
  3. 协议组排序:组内最新工单 createTime DESC(与列表默认排序一致)。

4.2 新增组件

QcWorkOrderProtocolGroup.vue

  • Props / Emits 与 QcWorkOrderSampleGroup 对齐(configure / view / command / tasks-changed)。
  • 内含样本 Tab 状态 activeSampleKey(sampleCode 或回退 id)。
  • 渲染选中样本的 QcWorkOrderSampleGroup(hideContextBar=true)。

4.3 修改组件

文件 变更
QcWorkOrderSampleGroup.vue 新增 hideContextBar?: boolean,为 true 时不渲染 qc-sample-row__ctx
QcWorkOrderCardList.vue cardMetaUsesInboundGroups 时渲染 QcWorkOrderProtocolGroup 而非直接 QcWorkOrderSampleGroup
qc-work-order-card-meta.ts 新增 buildProtocolGroupContextSubtitle(group);细胞存储/捐赠分别用协议/捐赠文案

4.4 「所有」Tab

不变。 buildAllTabListItems 中 inbound 仍可按样本合并(或维持现状);本需求不修改 all Tab 布局。

4.5 我的质检任务

与 manage 共用 QcWorkOrderCardList + 协议分组;pageMode='mine' 时卡片仅查看、任务区 taskListMode='mine'。

前端 mine 关键词过滤补充 protocolNo 字段(qc-mine-task-groups.ts → keywordMatchesWorkOrder,inbound 组)。


5. 后端变更

5.1 列表关键词 — 协议号(必须)

list_work_orders 在现有关键词 OR 条件中增加:

BizQcWorkOrder.protocol_no.like(like)

适用于入库类及「所有」Tab 跨类型搜索。

5.2 筛选 placeholder

入库 Tab 关键词 placeholder 更新为:

工单号/协议号/样本编码/入库编码

(细胞存储写「协议号」,科研捐赠写「捐赠单号」——按 Tab 文案区分。)

5.3 分页边界

  • 分页单位仍为 工单条数(pageSize 默认 100)。
  • 同一协议多样本可能跨页:当前页仅展示本页工单所属的样本 Tab;未出现在本页的样本不出 Tab。可接受,二期可选「按协议 ID 拉全量样本工单再分组」(非本期)。

6. 与检测批次的关系

检测批次在 工单卡片内部(QcWorkOrderBatchSubList),与协议/样本分组正交:

协议 → 样本 Tab → 触发来源 Tab → 工单 → 批次 → 任务

本需求不修改批次配置 API 与 UI。


7. 验收标准

  1. 【质检工单】细胞存储 / 科研捐赠 Tab:同一 collectionProtocolId 下多样本合并为 一张协议组卡片。
  2. 协议组内 样本 Tab 可切换;切换后展示对应样本工单与任务。
  3. 同样本多工单(接收 + 生产)仍显示 触发来源 Tab,行为与改动前一致。
  4. 单样本协议组 不显示 样本 Tab 行,直接展示工单区。
  5. 细胞存储协议组 协议费用条 组级展示一次;科研捐赠不展示费用条。
  6. 【我的质检任务】同上,且仅查看 + 任务操作。
  7. 关键词输入协议号 / 捐赠单号可筛出该协议下全部相关工单。
  8. 「所有」Tab、出库 Tab、临时 Tab 列表行为 回归不变。
  9. 配置检测 / 调整检测 / 查看弹窗 回归不变。

8. 已确认决策

问题 决策
是否按协议合并多样本? 是
样本切换交互? Tab(pill),复用现网触发来源 Tab 样式
单样本是否仍显示 Tab? 否,隐藏样本 Tab 行
两页是否一致? 是
「所有」Tab 是否协议分组? 否
分页是否改为按协议? 否(本期)
协议费用条位置? 协议组头一次(仅细胞存储)

9. 实现阶段建议

阶段 内容 预估
P1 groupInboundQcWorkOrdersByProtocol + QcWorkOrderProtocolGroup + SampleGroup hideContextBar 1~1.5 人天
P2 CardList 接入 + card-meta 协议组头 + placeholder 0.5 人天
P3 后端 protocol_no 关键词 + mine 前端关键词 0.5 人天
P4 两页联调、回归六 Tab + 所有 Tab 0.5~1 人天
合计 2.5~3.5 人天

10. 下一步

  1. 评审本文档 — 无遗漏后进入实现计划(writing-plans → docs/superpowers/plans/)。
  2. 可选:同步 OpenSpec capability qc-work-order-protocol-group(与 ui-conventions 卡片分组约定对齐)。