2026-10-09-protocol-audit-list-mode-design.md 8.5 KB

协议单审核(细胞存储)卡片 → 列表模式 — 实现设计

日期:2026-10-09
状态:已确认(2026-10-09)
关联:

  • 页面:/#/market/cell-storage/protocol-audit?tab=cell_storage
  • 源码:web-admin/src/views/cell-storage/protocol-audit/ProtocolAuditTab.vue
  • Demo:docs/demos/2026-10-09-protocol-audit-list-mode-demo.html
  • 模式:P02 复杂业务列表(docs/web-admin-ui-pattern-index.md)
  • 参考实现:样本运费 flatten(web-admin/src/utils/sample-freight-flatten.ts),本需求不做 rowspan

1. 背景与问题

「采集协议单」细胞存储 Tab 当前为卡片模式,一屏信息密度低、不利于按客户 Excel 习惯扫读与对照。

客户提供的 Excel 为样本粒度扁平行:一行对应一个实验室流转编号(样本);同一协议下多个样本占多行,协议级字段重复。系统中一个协议单对应 sampleItems[] 多条样本,需在列表中完整展开。


2. 已确认决策

项 结论
展示形态 纯扁平行:一行一样本;协议字段重复;不做 rowspan
年 / 月 / 日 合并为一列 采集日期(取自 sampleCollectTime 的日期部分,格式 YYYY-MM-DD)
采集时间 保留完整时间列(含时分,沿用现有 formatDisplayOrDash)
是否同存 计算列,不落库:同协议 sampleItems.length >= 2 →「是」,否则「否」;同协议各样本行显示相同值
无样本协议 仍占 1 行,样本相关列显示 —
分页 接口仍按协议条数分页;前端对当前页列表 flatten
勾选 / 批量 行可选;审核、状态变更、删除等按 protocolId 去重后执行
行内操作 审核 / 查看 / 编辑 / 删除(作用对象为协议,与现网一致)
范围 仅细胞存储 Tab(ProtocolAuditTab);科研捐赠 Tab 本轮不动
筛选 / 工具栏 / 弹窗 沿用现有;不改审核、状态变更、表单、查看、退费业务规则

3. 目标与非目标

3.1 目标

  • 卡片列表改为 el-table 列表,列对齐客户 Excel(见 §4)。
  • 正确展示一协议多样本(多行)。
  • 保留现有筛选、工具栏批量操作与各类弹窗能力。

3.2 非目标

  • 不改科研捐赠协议 Tab 的卡片/列表。
  • 不新增「是否同存」数据库字段或字典。
  • 不改为按样本分页(避免破坏现有协议列表 API 契约)。
  • 不做 Excel 导出(若后续需要另开需求)。
  • 不在本需求中扩展支付 summary 接口字段(优先用现有 paymentSummary;见 §5.3 缺口处理)。

4. UI 规格

4.1 页面骨架

与现网及 P02 一致:

  1. filter-block(关键词、协议状态、创建时间、样本采集时间)
  2. list-toolbar(已选 N 项 + 新增 + 退费登记 + 审核 + 状态变更 + 批量删除)
  3. list-body.list-wrap → el-table.list-table(stripe,无 border)
  4. pagination.list-pager-bar(total 仍为协议总数)

视觉:Fresh Mint;状态/方式类字段用 el-tag;操作列 fixed="right",min-width ≥ 260。

4.2 表格列(从左到右)

列 来源 说明
选择 — type="selection";见 §5.2 去重
序号 前端 当前页扁平行从 1 起的行号(仅展示用;翻页后重新从 1 计)
采集日期 sampleCollectTime 日期部分 YYYY-MM-DD;无则 —
实验室流转编号 sampleItems[].labStorageCode monospace;空则 —
母亲姓名 motherName
协议编号 protocolNo
样本类型 sampleItems[].sampleTypeName
是否同存 计算 el-tag:是=warning,否=info
采集地区 regionName
采集医院 hospitalName
采集时间 sampleCollectTime 完整展示
缴费方式 paymentSummary.payMode el-tag + payModeLabel / 注册表 label
首期缴费时间 paymentSummary 见 §5.3
市场专员 salesUserName
地区经理 regionManagerUserName
运输方式 sampleItems[].transport transportTypeLabel;可附简短摘要(快递公司/专线等),避免过长
操作 — 审核、查看、编辑、删除(协议级)

双击行:打开协议查看弹窗(与现卡片 dblclick 一致)。

4.3 不在首期列表展示的卡片字段(刻意收缩)

卡片上的新生儿、接收结论、质检结论、缴费面板详情等不进入首期列表列,以免列宽失控;详情仍通过「查看」弹窗获取。若业务后续要求加列,另开变更。


5. 数据与交互

5.1 Flatten

前端将 CollectionProtocolRow[] 展开为扁平行,建议工具函数(可新建 utils/protocol-audit-flatten.ts,风格对齐 sample-freight-flatten.ts):

type ProtocolAuditFlatRow = {
  rowKey: string           // `${protocolId}|${sampleCode||idx}`
  protocolId: string
  protocol: CollectionProtocolRow
  isCoStored: boolean      // sampleCount >= 2
  sampleCount: number
  sampleIndex: number      // 0-based within protocol
  sampleTypeName: string
  sampleCode: string
  labStorageCode: string
  transportType?: string
  transportSummary: string
  collectDate: string      // YYYY-MM-DD
  // …展示所需其它从 protocol / sample 拷贝的字段
}

规则:

  • sampleItems 非空:每个 item 一行。
  • sampleItems 空:仍一行,样本字段空串 / —,isCoStored = false。
  • 是否同存:基于该协议展开前的样本条数(空样本计 0 → 否)。

5.2 选择与批量

  • 表格 @selection-change 得到扁平行集合。
  • 「已选 N 项」:N = 去重后的协议数(与批量语义一致),避免「选了 2 个样本显示已选 2 项但只对应 1 个协议」的歧义。
  • 批量审核 / 状态变更 / 删除:unique protocols by protocolId。
  • 退费登记:仍要求恰好 1 个协议(去重后长度为 1)。

5.3 缴费方式与首期缴费时间

  • 缴费方式:paymentSummary.payMode + label(payModeLabel 或 payModeLabel())。
  • 首期缴费时间:现有 list enrichment 的 paymentDetails 含 installmentDueDate,明细表有 transfer_time 但 summary 尚未透出。
    • 首期实现(最小):展示首期(installmentNo === 1 或排序后第一条)的 installmentDueDate;多条已付/多期时,若仅有 dueDate,可多行叠展示 dueDate(与 Demo 中多行时间类似)。
    • 优选增强(同需求内若改动面小):在 build_protocol_payment_summary / _payment_detail_row 增加 transferTime,列表优先展示已转账时间,否则回退 dueDate。无 summary 时显示 —。

本设计允许「仅前端用现有字段」或「顺带透出 transferTime」;实现计划中二选一,优先小改动透出 transferTime 若触及后端文件很少。

5.4 运输方式

优先 transportType → transportTypeLabel;无运输信息显示 —。不强制拼完整运单摘要(列宽有限);完整信息在查看弹窗。


6. 后端

  • 默认不改列表 API 契约:继续 GET 协议分页 + 已有 sampleItems / paymentSummary enrichment。
  • 可选小改:paymentDetails[] 增加 transferTime(见 §5.3),需同步 TS 类型与(若有)单测。
  • 不新增「是否同存」存储字段。

7. 测试要点

  • 0 / 1 / 2+ 样本协议:行数、是否同存、空样本行。
  • 采集日期与采集时间均来自同一 sampleCollectTime,空值显示 —。
  • 勾选同一协议两行样本 → 已选 1 项;批量删除只调一次该协议。
  • 筛选、分页、新增/编辑/查看/审核/状态变更/退费回归通过。
  • 列使用 min-width;操作列固定右侧不被裁切。

8. 文件影响(预期)

区域 文件
主改 web-admin/src/views/cell-storage/protocol-audit/ProtocolAuditTab.vue
新增 web-admin/src/utils/protocol-audit-flatten.ts(及可选 *.test.ts)
可选 backend/app/services/qc_work_order_fee_summary.py、web-admin/src/api/qc-work-order.ts(transferTime)
文档 本设计;Demo 已存在

9. 验收标准

  1. 细胞存储协议审核页为表格列表,不再使用协议卡片流。
  2. 一协议多样本时,列表出现多行,协议字段重复,是否同存均为「是」。
  3. 列包含 §4.2 所列字段;年/月/日不以三列出现,而为「采集日期」。
  4. 现有工具栏与弹窗行为可用,批量操作按协议去重正确。