2026-07-01-special-sample-mark.md 6.2 KB

样本特殊标记 Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 在采集/捐赠协议单样本上维护 isSpecial + specialRemark,并在 web-admin 全链路只读展示红色加粗警示。

Architecture: 字段仅存 biz_protocol_sample / biz_research_donation_sample;下游 API JOIN 源表补字段;前端 SpecialSampleDisplay 统一渲染。

Tech Stack: FastAPI + SQLAlchemy + Vue 3 + Element Plus

Spec: docs/superpowers/specs/2026-07-01-special-sample-mark-design.md


File Map

文件 职责
docs/sql/migrate-special-sample-mark.sql DDL 增量脚本
backend/app/utils/sample_special.py 校验 + dict 转换工具
backend/app/models/models.py BizProtocolSample 新列
backend/app/models/research_donation.py BizResearchDonationSample 新列
backend/app/crud/collection_protocol.py _sample_to_dict / save_samples / list sampleItems
backend/app/crud/research_donation.py 同上 + 转存储复制
backend/app/crud/qc_work_order.py _enrich_work_order_list_items 补字段
backend/app/crud/sample_reception.py 待/已接收 list item
backend/app/crud/protocol_sample_collection.py 样本采集信息 list
backend/app/crud/research_donation_sample_collection.py 捐赠样本采集 list
backend/app/crud/pre_transit_sample.py 转运前样本卡片 items
backend/app/crud/storage_release_review.py 入库审核 detail
backend/app/crud/cell_product.py 溯源链样本信息
web-admin/src/components/business/special-sample-display/index.vue 公共展示组件
web-admin/src/components/business/sample-transport-form-section/index.vue 录入
web-admin/src/views/cell-storage/protocol/ProtocolViewDialog.vue 采集查看
web-admin/src/views/research-donation/list/DonationViewDialog.vue 捐赠查看
下游 15+ vue 页面 样本编码旁 inline 展示

Task 1: 数据库与 Model

Files:

  • Create: docs/sql/migrate-special-sample-mark.sql
  • Modify: backend/app/models/models.py, backend/app/models/research_donation.py

  • [ ] Step 1: 执行 DDL(两表对称)

ALTER TABLE `biz_protocol_sample`
  ADD COLUMN `is_special` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否特殊样本:0否 1是' AFTER `storage_expire_date`,
  ADD COLUMN `special_remark` varchar(256) DEFAULT NULL COMMENT '特殊说明' AFTER `is_special`;

ALTER TABLE `biz_research_donation_sample`
  ADD COLUMN `is_special` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否特殊样本:0否 1是' AFTER `storage_expire_date`,
  ADD COLUMN `special_remark` varchar(256) DEFAULT NULL COMMENT '特殊说明' AFTER `is_special`;
  • Step 2: ORM 增加 is_special = Column(SmallInteger...) 与 special_remark = Column(String(256)...)

Task 2: 后端工具与核心 CRUD

Files:

  • Create: backend/app/utils/sample_special.py
  • Modify: backend/app/crud/collection_protocol.py, backend/app/crud/research_donation.py

  • [ ] Step 1: 创建工具函数

def sample_special_to_dict(sample) -> Dict[str, Any]: ...
def validate_sample_special_raw(raw: dict, *, index: Optional[int] = None) -> None: ...
def apply_sample_special_fields(obj, raw: dict) -> None: ...
  • [ ] Step 2: _sample_to_dict 增加 isSpecial / specialRemark

  • [ ] Step 3: save_samples / _create_samples 循环内调用 validate_sample_special_raw + apply_sample_special_fields

  • [ ] Step 4: research_donation.py 转存储复制 is_special、special_remark

  • [ ] Step 5: collection_protocol.py 列表 sampleItems 构建补字段


Task 3: 下游 CRUD API

Files: sample_reception.py, protocol_sample_collection.py, research_donation_sample_collection.py, pre_transit_sample.py, qc_work_order.py, storage_release_review.py, cell_product.py

  • [ ] Step 1: 凡已有 BizProtocolSample / BizResearchDonationSample 对象处,item.update(sample_special_to_dict(sample))

  • [ ] Step 2: qc_work_order._enrich_work_order_list_items 在 sampleTypeName 赋值后补 special 字段(覆盖质检+生产工单)


Task 4: 前端公共组件与录入

Files:

  • Create: web-admin/src/components/business/special-sample-display/index.vue
  • Modify: web-admin/src/components/business/sample-transport-form-section/index.vue

  • [ ] Step 1: 创建 SpecialSampleDisplay(v-if="isSpecial",danger 色加粗)

  • [ ] Step 2: 样本子弹窗增加 checkbox + textarea;取消勾选清空说明

  • [ ] Step 3: confirmSampleDialog 校验:isSpecial && !specialRemark.trim() → warning

  • [ ] Step 4: 列表增加「特殊样本」列;openAddSampleDialog 初始化 isSpecial: false, specialRemark: ''

  • [ ] Step 5: normalizeSampleRow 保留 isSpecial / specialRemark


Task 5: 协议查看弹窗

Files: ProtocolViewDialog.vue, DonationViewDialog.vue

  • Step 1: 样本卡片 header inline 展示 SpecialSampleDisplay

Task 6: 下游展示页面(P1 全量)

在样本编码列/标题行旁接入 SpecialSampleDisplay:

  • ProtocolAuditTab.vue, PreTransitProtocolCardList.vue
  • research-donation/audit/index.vue
  • SampleCollectionInfoTab.vue, DonationSampleCollectionInfoTab.vue
  • sample-reception/index.vue, SampleReceptionCardList.vue
  • QcWorkOrderProtocolGroup.vue, QcWorkOrderSampleGroup.vue, QcWorkOrderTaskSubList.vue
  • storage-release-review/index.vue, StorageReleaseReviewDialog.vue, StorageReleaseViewDialog.vue
  • ProductionWorkOrderCardList.vue, SampleReceptionDialog.vue, DispatchTaskDialog.vue
  • SampleCustomerViewDialog.vue

Task 7: 验证

  • 本地执行 docs/sql/migrate-special-sample-mark.sql
  • python scripts/check_field_consistency.py
  • ./scripts/update-graph.sh frontend + backend
  • 手工:协议单录入特殊样本 → 查看弹窗 → 样本接收/质检卡片可见红色标记

部署前

  1. 执行 docs/sql/migrate-special-sample-mark.sql
  2. 重启 backend
  3. 刷新 web-admin