feat: 质检工单结论、库位批量/筛选与协议样本接收质检摘要

落库并展示质检工单级结论(可编辑/任务派生),库位树支持批量新增子节点与货架格子检索,协议/捐赠列表补充接收与门禁质检摘要,并同步生产物料与工单卡片展示优化。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-07-28 18:46:24 +08:00
1 parent f554d77e59
commit a3af039e74
54 files changed
+42429 -35006

No files matched your search

@@ -51,7 +51,7 @@ function keywordMatchesWorkOrder(
const tab = getProductionWorkOrderTab(tabKey)!
const fields =
tabKey === 'temporary'
? [row.workOrderNo]
? [row.remark]
: tabKey === 'outbound_basic_experiment'
? [
row.workOrderNo,
@@ -1,6 +1,6 @@
import { formatDisplayOrDash } from '@/utils/datetime-display'
import type { ProductionWorkOrderItem } from '@/api/production-work-order'
import { receptionSourceLabel } from '@/utils/qc-labels'
import { receptionSourceLabel, receptionSourceTagType } from '@/utils/qc-labels'
import {
donationStatusDisplayLabel,
donationStatusTagType,
@@ -78,18 +78,19 @@ function protocolStatusTagTypeForTab(
}
function buildInboundMetaFields(tabKey: ProductionWorkOrderTabKey): CardMetaField[] {
const fields: CardMetaField[] = []
if (tabKey === 'inbound_cell_storage') {
fields.push({
const defaultSource = tabKey === 'inbound_research_donation' ? 'research_donation' : 'cell_storage'
return [
{ label: '实验室入库编码', getValue: (row) => row.labStorageCode || '—' },
{ label: '样本类型', getValue: (row) => row.sampleTypeName || '—' },
{ label: '接收经手人', getValue: (row) => row.handlerName || '—' },
{ label: '接收时间', getValue: (row) => formatDisplayOrDash(row.receptionTime) },
{
label: '来源类型',
kind: 'tag',
getValue: (row) => row.receptionSourceLabel || receptionSourceLabel(row.receptionSource || 'cell_storage'),
getTagType: () => 'success'
})
}
fields.push(
{ label: '母亲姓名', getValue: (row) => row.motherName || '—' },
{ label: '新生儿姓名', getValue: (row) => row.newbornName || '—' },
getValue: (row) =>
row.receptionSourceLabel || receptionSourceLabel(row.receptionSource || defaultSource),
getTagType: (row) => receptionSourceTagType(row.receptionSource || defaultSource)
},
{
label: tabKey === 'inbound_research_donation' ? '捐赠状态' : '协议状态',
kind: 'tag',
@@ -97,21 +98,24 @@ function buildInboundMetaFields(tabKey: ProductionWorkOrderTabKey): CardMetaFiel
getTagType: (row) => protocolStatusTagTypeForTab(row, tabKey),
visible: (row) => !!String(row.protocolStatus || '').trim()
},
{ label: '样本类型', getValue: (row) => row.sampleTypeName || '—' },
{ label: '接收经手人', getValue: (row) => row.handlerName || '—' },
{ label: '接收时间', getValue: (row) => formatDisplayOrDash(row.receptionTime) },
plannedStartTimeRangeField,
{ label: '工单号', getValue: (row) => row.workOrderNo || '—' },
{ label: '样本编码', getValue: (row) => row.sampleCode || '—' },
{ label: '实验室入库编码', getValue: (row) => row.labStorageCode || '—' },
{
label: '备注',
getValue: (row) => row.remark || '—',
visible: (row) => !!row.remark,
wide: true
label: '质检结论',
kind: 'tag',
getValue: (row) =>
row.qcConclusionLabel ||
(row.qcConclusion === 'tg'
? '合格'
: row.qcConclusion === 'btg'
? '不合格'
: '—'),
getTagType: (row) => {
const c = String(row.qcConclusion || '').trim()
if (c === 'tg') return 'success'
if (c === 'btg') return 'danger'
return 'info'
}
}
)
return fields
]
}
const outboundPilotClinicalFields: CardMetaField[] = [
@@ -157,10 +161,7 @@ const outboundBasicExperimentFields: CardMetaField[] = [
}
]
const temporaryFields: CardMetaField[] = [
{ label: '工单号', getValue: (row) => row.workOrderNo || '—' },
plannedStartTimeRangeField
]
const temporaryFields: CardMetaField[] = []
const CARD_META_BY_TAB: Record<ProductionWorkOrderTabKey, ProductionWorkOrderCardMetaConfig> = {
all: {
@@ -137,7 +137,7 @@ export function resolveTabKeyFromWorkOrder(row: {
export function keywordPlaceholderForTab(tab: ProductionWorkOrderTabConfig): string {
if (tab.key === 'all') return '工单号 / 样本编码 / 申请单号 / 产品名称等'
if (tab.key === 'temporary') return '工单号'
if (tab.key === 'temporary') return '备注'
if (tab.key === 'outbound_basic_experiment') {
return '工单号/申请单号/课题名称/客户'
}
+2
View File
@@ -15,6 +15,8 @@ export {
qcTaskConclusionTagType,
qcConclusionDisplayLabel,
qcConclusionDisplayTagType,
qcWorkOrderConclusionLabel,
qcWorkOrderConclusionTagType,
taskStatusLabel,
taskStatusTagType
} from './status-tag-registry'
@@ -250,6 +250,14 @@ export const qcConclusion: StatusRegistry = {
export const qcTaskConclusionLabel = createLabelGetter(qcConclusion)
export const qcTaskConclusionTagType = createTagTypeGetter(qcConclusion)
/** 工单级质检结论(列表卡片):合格 / 不合格;无结论返回空串 */
export const qcWorkOrderConclusionLabelMap: StatusRegistry = {
tg: { label: '合格', tagType: 'success' },
btg: { label: '不合格', tagType: 'danger' }
}
export const qcWorkOrderConclusionLabel = createLabelGetter(qcWorkOrderConclusionLabelMap)
export const qcWorkOrderConclusionTagType = createTagTypeGetter(qcWorkOrderConclusionLabelMap)
/** 无 tg/btg 时展示「待结论」(待办醒目,用 danger) */
export function qcConclusionDisplayLabel(code?: string | null): string {
const c = (code || '').trim()