2026-06-29-dual-sample-reception-design.md 13 KB

双部门样本接收 — 质检域与生产域拆分

日期:2026-06-29
状态:待审核
关联:2026-05-19-unified-sample-reception-design.md、2026-05-19-production-work-order-design.md、2026-06-03-sample-reception-lab-storage-code-design.md
关联模块:样本接收、入库生产工单、协议/捐赠查看弹窗、质检工单查看


1. 背景与目标

1.1 现状问题

当前 质检管理 → 样本接收 与 生产管理 → 生产工单 → 样本接收信息填写 共用同一张表 biz_sample_reception、同一套 submit/update API,两侧均可修改全部字段(含体积、净重、检查项、接收结论等)。与客户「质检登记」与「生产登记」分属不同部门、字段不同的诉求不符。

1.2 目标

  1. 质检域:仅在【质检管理 → 样本接收】填写;去掉 体积(ml)、净重(g)。
  2. 生产域:仅在【生产工单 → 样本接收信息填写】填写;字段按 来源 × 样本类型 动态展示。
  3. 互读互斥写:质检弹窗可见生产信息(只读);生产弹窗可见质检信息(只读)。
  4. 展示统一:所有展示样本接收信息的查看弹窗/详情,同时展示 质检接收 与 生产接收 两块。
  5. 历史数据(已确认):volume_ml、net_weight_g 仅从界面与读写 API 去掉;库中保留旧值,不再展示、不迁移。

2. 业务规则

2.1 填写入口与权限

入口 可写域 只读域 写权限
质检 → 样本接收(待接收/已接收/批量) 质检接收 生产接收 现网:采集接受人(经手人)、质量主管(编辑已接收)
生产工单 → 样本接收信息填写 生产接收 质检接收 实验专员(处理人候选与操作角色一致;可复用 PRODUCTION_STEP_ASSIGNEE_ROLE)

后端 必须 在 API 层拒绝跨域写入,不依赖前端 disabled。

2.2 流程依赖

  • 入库生产工单在 质检接收结论 = 接收(js) 后自动创建(现网逻辑不变)。
  • 生产接收填写 入口仅在入库类生产工单卡片展示(inbound_cell_storage / inbound_research_donation)。
  • 质检拒收(bj):生产弹窗不展示填写能力;只读展示质检结论即可。
  • 填写顺序:须已存在质检接收记录后,生产方可保存生产接收(生产 API 校验 reception_id 存在)。

2.3 样本类型匹配

与 web-admin/src/utils/sample-reception-lab-storage-code.ts 一致,按 样本类型名称 匹配:

名称 说明
围产期造血干细胞 对应需求文档编码 wcqzxgxb
脐带间充质干细胞 对应需求文档编码 qdjczgxb

未在矩阵中的类型(如 胎盘亚全能干细胞):生产弹窗仅展示公共字段(处理人、处理时间),无类型专属字段;专属字段不做必填校验。

2.4 历史字段 volume_ml / net_weight_g

  • 决策:选项 A — 停止读写与展示;biz_sample_reception 列保留,不执行数据迁移脚本。
  • _reception_to_dict 及前端类型定义 不再输出 这两字段(或输出但全链路忽略)。
  • 新生产域字段与历史体积/净重 无自动映射。

3. 字段矩阵

3.1 质检域(biz_sample_reception,现有表)

字段 变更
reception_time, handler_user_id, handler_name 保留
receive_temperature 保留
check_results(子表) 保留
accept_conclusion, lab_storage_code 保留
receive_attachments, remark 保留
volume_ml, net_weight_g 停止 API 入参/出参及 UI 展示

3.2 生产域(新表 biz_sample_production_reception)

公共字段(所有来源×类型)

字段 类型 规则
handler_user_id varchar(64) 处理人;默认当前登录用户
handler_name varchar(100) 处理人姓名快照
process_time datetime 处理时间;默认当前时间

细胞存储 + 围产期造血干细胞

字段 类型 标签
original_blood_weight_g decimal(18,4) 原血重量/g
hes_volume_ml decimal(18,4) HES用量/ml
blood_type varchar(32) 血型(文本输入,非下拉)
infectious_four_test_result varchar(16) 传染四项检测(检测卡):zc 正常 / bzc 不正常
enriched_blood_weight_g decimal(18,4) 富集后血量/g
cryopreservation_volume_ml decimal(18,4) 冻存液用量/ml

细胞存储 + 脐带间充质干细胞

字段 类型 标签
inoculation_amount decimal(18,4) 接种量
cryopreservation_time datetime 冻存时间
storage_total_tubes int 储存总量(管)
available_cell_count_1e7 decimal(18,4) 可提供细胞数量/*10E7

科研捐赠 + 脐带间充质干细胞

字段 类型 标签
inoculation_amount decimal(18,4) 接种量
cryopreservation_time datetime 冻存时间

科研捐赠 + 围产期造血干细胞

字段 类型 标签
original_blood_volume_ml decimal(18,4) 原血体积/ml
nucleated_cell_count_1e8 decimal(18,4) 有核细胞数/10E8

必填规则:对当前样本命中的类型专属字段 + 公共字段做前后端必填校验;未命中类型的专属列保持 NULL。


4. 数据库设计

4.1 新表

-- docs/sql/migrate_sample_production_reception.sql

CREATE TABLE `biz_sample_production_reception` (
  `id` varchar(64) NOT NULL COMMENT '主键ID',
  `reception_id` varchar(64) NOT NULL COMMENT '关联 biz_sample_reception.id',
  `sample_code` varchar(32) DEFAULT NULL COMMENT '样本编码快照',
  `reception_source` varchar(20) NOT NULL DEFAULT 'cell_storage' COMMENT '来源 cell_storage/research_donation',
  `sample_type_name` varchar(100) DEFAULT NULL COMMENT '样本类型名称快照',
  `handler_user_id` varchar(64) DEFAULT NULL COMMENT '处理人用户ID',
  `handler_name` varchar(100) DEFAULT NULL COMMENT '处理人姓名',
  `process_time` datetime NOT NULL COMMENT '处理时间',
  `original_blood_weight_g` decimal(18,4) DEFAULT NULL COMMENT '原血重量/g',
  `hes_volume_ml` decimal(18,4) DEFAULT NULL COMMENT 'HES用量/ml',
  `blood_type` varchar(32) DEFAULT NULL COMMENT '血型',
  `infectious_four_test_result` varchar(16) DEFAULT NULL COMMENT '传染四项 zc正常 bzc不正常',
  `enriched_blood_weight_g` decimal(18,4) DEFAULT NULL COMMENT '富集后血量/g',
  `cryopreservation_volume_ml` decimal(18,4) DEFAULT NULL COMMENT '冻存液用量/ml',
  `inoculation_amount` decimal(18,4) DEFAULT NULL COMMENT '接种量',
  `cryopreservation_time` datetime DEFAULT NULL COMMENT '冻存时间',
  `storage_total_tubes` int DEFAULT NULL COMMENT '储存总量(管)',
  `available_cell_count_1e7` decimal(18,4) DEFAULT NULL COMMENT '可提供细胞数量/*10E7',
  `original_blood_volume_ml` decimal(18,4) DEFAULT NULL COMMENT '原血体积/ml',
  `nucleated_cell_count_1e8` decimal(18,4) DEFAULT NULL COMMENT '有核细胞数/10E8',
  `tenant_no` varchar(64) NOT NULL DEFAULT 'zkxw',
  `order_num` int DEFAULT NULL,
  `remark` varchar(512) DEFAULT NULL,
  `create_by` varchar(64) DEFAULT NULL,
  `create_dept_id` varchar(64) NOT NULL DEFAULT '',
  `create_time` datetime NOT NULL,
  `update_by` varchar(64) DEFAULT NULL,
  `update_time` datetime NOT NULL,
  `del_flag` smallint NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_reception_id` (`reception_id`,`del_flag`),
  KEY `idx_sample_code` (`tenant_no`,`sample_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='生产部门样本接收登记';

关系:与 biz_sample_reception 1:1(reception_id 唯一);软删除遵循 del_flag。

4.2 现有表

  • biz_sample_reception.volume_ml、net_weight_g:不删列;应用层停用。

5. API 设计

5.1 质检 API(调整现有 /web/admin/sample-receptions)

  • POST / PUT:请求体 移除 volumeMl、netWeightG。
  • GET 详情 / 列表 / by-sample-code:响应增加 productionReception(对象或 null);响应 移除 volumeMl、netWeightG。
  • 写接口 拒绝 任何生产域字段(若误传则忽略或 400)。

5.2 生产 API(新增)

前缀建议:/web/admin/production-sample-receptions

方法 路径 说明
GET /by-sample-code?sampleCode=&sourceType= 返回 { receptionId, qcReception, productionReception, sampleInfo }
GET /{id} 生产接收详情
POST / 创建(body 含 receptionId 或 sampleCode+sourceType)
PUT /{id} 更新生产域字段
  • 校验:关联质检记录存在;accept_conclusion !== 'bj';当前用户具备实验专员角色或等于处理人(编辑策略与质检对称,首版:实验专员可写)。
  • 写接口 禁止 修改 biz_sample_reception 任意字段。

5.3 聚合读

以下详情接口的 reception 或等价字段扩展为:

{
  "qcReception": { "...质检字段..." },
  "productionReception": { "...生产字段..." }
}

或保持扁平 reception 为质检数据,另增 productionReception。实现时 _row_to_dict 为单一真相源。

影响面:生产工单详情、质检工单入库查看、协议/捐赠样本卡片接口(若内嵌 sampleReception)。


6. 前端设计

6.1 可写表单

组件 改造
quality-inspection/sample-reception/index.vue 去掉体积/净重;表单下增加 生产接收信息(只读) 区块;拉取聚合详情
production-work-order/SampleReceptionDialog.vue 重写:上为质检只读,下为生产可编辑(按类型字段模板);不再 调用质检 submit/update
production/sample-reception-completion/index.vue 废弃或改为跳转生产工单;菜单保持隐藏

6.2 公共只读组件(新建)

建议:web-admin/src/components/business/sample-reception-dual-readonly-panel/

  • Props:qcReception、productionReception、sourceType、sampleTypeName
  • 内置 4 套类型字段展示模板 + 空态(「生产尚未登记」/「暂未接收」)
  • 供协议查看、捐赠查看、工单查看、质检任务查看等复用

6.3 只读展示改造清单

文件 改造
ProtocolViewDialog.vue 样本卡片拆「质检接收」「生产接收」
DonationViewDialog.vue 同上
production-view-sections.ts 拆两段 section
inbound-view-sections.ts 同上
QcTaskViewDialog 同上
QcWorkOrderTaskSubList 同上
StorageReleaseViewDialog 同上
质检样本接收「接收详情」弹窗 增加生产只读块

6.4 生产处理人下拉

复用 fetchProductionStepAssigneeUsers(角色 实验专员);打开弹窗时默认选中当前登录用户(若在列表中)。

6.5 UI 规范

  • 弹窗:dialog-form-layout、label-position="top"、只读块用 readonly-grid / data-grid 与现网样本接收弹窗一致。
  • 质检块标题:质检接收信息;生产块:生产接收信息。
  • 传染四项:el-select,选项「正常」「不正常」。

7. 后端模块

路径 职责
backend/app/models/models.py BizSampleProductionReception
backend/app/crud/sample_production_reception.py CRUD、类型校验、_row_to_dict
backend/app/api/sample_production_reception.py 路由
backend/app/crud/sample_reception.py 去掉 volume/netWeight 出参;详情挂载 production
backend/app/api/__init__.py + main.py 注册新路由

字段一致性:运行 python scripts/check_field_consistency.py(若纳入检查范围)。


8. 权限与菜单

  • 新增按钮权限(建议):production:sample-reception:add、production:sample-reception:edit,挂在生产工单或生产管理菜单下。
  • 质检权限不变:biz:sampleReception:*。

9. 测试要点

  1. 质检接收(js) → 生产工单出现 → 生产填写 4 种类型组合字段 → 质检页只读可见。
  2. 质检编辑后 → 生产页只读更新;生产编辑后 → 质检页只读更新;双方 API 互不能改对方域。
  3. 质检拒收 → 生产无填写入口。
  4. 历史记录:volume_ml/net_weight_g 有值的旧数据,界面与 API 均不出现。
  5. 未覆盖样本类型:仅公共字段可保存。
  6. 实验专员/非实验专员写权限边界。

10. 实施顺序

  1. SQL + Model + 生产 CRUD/API
  2. 质检 API 瘦身 + 聚合读
  3. SampleReceptionDialog 重写 + 质检页调整
  4. sample-reception-dual-readonly-panel + 各查看弹窗接入
  5. 权限 SQL + 回归

11. 不在本次范围

  • 隐藏菜单「样本接收信息完善」路由删除(可后续清理)。
  • 小程序端样本接收(若有)不同步,除非另行立项。
  • volume_ml/net_weight_g 列的数据库物理删除。

12. 已确认决策

议题 决策
历史体积/净重 A — 库保留,界面与 API 去掉,不展示不迁移
数据模型 新表 biz_sample_production_reception,1:1 关联质检接收
未覆盖样本类型 仅公共字段,无专属必填