日期:2026-07-29
状态:已确认(brainstorming)
方案:A(后端聚合接口 + 独立只读弹窗)
入口:出库放行审核 → 出库物料准备 → 出库细胞列表
在「出库物料准备」弹窗的「出库细胞」列表中,用户可通过行操作查看所选细胞产品相关的质检信息,用于放行前核对。
必须展示:
数据策略:实时查询,不写入出库台账快照;质检事后变更后再次打开可见最新结果。
交互:主列表保持简洁;行上「查看质检」打开独立弹窗(非行内展开)。
| 项 | 选择 |
|---|---|
| 父级范围 | B:整条来源链(祖先细胞产品 + 上游样本) |
| 任务状态 | B:全部状态 |
| 检测材料 | 质检任务附件(非出库 qcMaterials 库存扣减,非实验室物料使用明细) |
| 交互 | B:行按钮 → 独立弹窗 |
| 数据 | A:实时查询 |
| 实现路径 | A:后端聚合 API + 只读弹窗 |
/chain 可视化)biz_cell_product 无 parent_id。父子关系来自生产任务投入/产出:
get_product_chain → _build_ancestor_chain(backend/app/crud/cell_product.py)fetchCellProductChain → GET /web/admin/cell-products/{id}/chaindocs/superpowers/specs/2026-05-24-cell-product-source-chain-design.md本需求只消费 current + ancestors,不取 descendants。
BizQcWorkOrder.cell_product_idlist_work_orders_by_sample(sample_code + reception_source,work_order_type=inbound)results(参数)、conclusion / remark、attachmentFiles(由附件 URL 解析)web-admin/.../QcWorkOrderTaskResultPanel.vueOutboundReleaseMaterialDialog.vuecellProductId 等台账字段;保存逻辑不因本需求变更出库细胞行 [查看质检]
│
▼
GET /web/admin/cell-products/{id}/lineage-qc
│
├─ get_product_chain(复用)→ current + ancestors
├─ 展平节点(根→叶,当前最后;按 nodeType+id 去重)
├─ cell_product 节点:按 cell_product_id 查工单(不限 work_order_type)
├─ sample 节点:按 sampleCode + receptionSource 查入库质检
└─ 工单批量拉任务详情(参数/结论/备注/附件;不过滤状态)
│
▼
el-dialog「来源链质检」只读展示
GET /web/admin/cell-products/{product_id}/lineage-qc/chain 同域(backend/app/api/production.py)get_product_lineage_qc(建议在 cell_product.py,内部复用 qc CRUD,禁止复制序列化逻辑){
"productId": "...",
"productCode": "...",
"productName": "...",
"nodes": [
{
"nodeType": "sample | cell_product",
"id": "...",
"label": "样本编码或产品编码",
"productName": "...",
"passage": "P1",
"receptionSource": "cell_storage | research_donation | null",
"isCurrent": false,
"workOrders": [
{
"id": "...",
"workOrderNo": "...",
"workOrderType": "...",
"workOrderStatus": "...",
"workOrderStatusLabel": "...",
"tasks": [
{
"id": "...",
"taskNo": "...",
"itemName": "...",
"itemCode": "...",
"taskType": "...",
"taskStatus": "...",
"conclusion": "...",
"conclusionLabel": "...",
"remark": "...",
"completedTime": "...",
"results": [
{ "paramName": "", "paramValue": "", "paramUnit": "" }
],
"attachmentFiles": [
{ "fileName": "", "fileUrl": "", "fileType": "" }
]
}
]
}
]
}
]
}
字段命名与现有质检详情 camelCase 对齐,便于前端复用 Tag/附件组件。
get_product_chain;展平 nested ancestor parent;深度上限沿用 _MAX_CHAIN_DEPTH。cell_product_id = node.id,del_flag=0,租户过滤;不限 work_order_type。list_work_orders_by_sample;reception_source 缺失时该节点 workOrders: [],不 500。get_work_order_detail;全量一次返回。二期可按节点懒加载。| 情况 | 行为 |
|---|---|
| 产品不存在 / 跨租户 | 业务 400/404,文案明确 |
| 无祖先(如手动录入) | nodes 仅含 current |
| 节点无工单 | 仍返回节点,workOrders: [] |
| 单节点加载异常 | 该节点空列表 + 可选 loadError,不拖垮整响应 |
| 附件 URL 坏项 | 跳过该项 |
require_any_menu_code:任一匹配即可——出库放行相关菜单码,或质检工单列表码,或细胞产品查看码(具体码表在实现计划中对照菜单 SQL 写死)。tenant_no 过滤;若套用质检 data scope 会导致「能准备出库物料却看不到质检」则本期对放行入口放宽为租户内只读(实现计划写明最终策略)。OutboundReleaseMaterialDialog.vue(及若共用的 outbound-material-form-sections,以实现时是否共用为准;至少出库放行物料弹窗落地)View 图标 + 文案);保留「删除」min-width 约 ≥ 180pxcellProductId 时可点CellProductLineageQcDialog.vue(建议 components/business/ 或 outbound-release-review/)el-dialog + dialog-form-layout,宽约 960–1120px,append-to-body,无 backdrop blur来源链质检;副信息:当前产品编码 / 名称lineage-qc;v-loading;失败 ElMessage.error自上而下:
nodes 分区(可折叠;默认均展开)
QcWorkOrderTaskResultPanel 只读结构
节点顺序:上游 → 下游(当前产品在最后)。
web-admin/src/api/cell-product.ts 增加 fetchCellProductLineageQc(productId)el-tag + status-tag-registryget_product_lineage_qc + 路由 + 单测(展平/样本键/批量)CellProductLineageQcDialogOutboundReleaseMaterialDialog 操作列docs/sql 菜单)components/business vs 业务目录)outbound-material-form-sections 与放行弹窗分叉,是否两边都接入口(默认:放行物料弹窗必做;共用组件则一并改)