|
|
@@ -4,7 +4,9 @@
|
|
|
<div class="page-container">
|
|
|
<header class="page-head">
|
|
|
<h1>生产工单</h1>
|
|
|
- <p class="page-desc">管理入库与临时生产工单;入库工单关联样本接收,临时工单可独立创建并派发任务。</p>
|
|
|
+ <p class="page-desc"
|
|
|
+ >管理入库与临时生产工单;入库工单关联样本接收,临时工单可独立创建并派发任务。</p
|
|
|
+ >
|
|
|
</header>
|
|
|
|
|
|
<section class="panel">
|
|
|
@@ -12,9 +14,14 @@
|
|
|
<h2>工单列表</h2>
|
|
|
</div>
|
|
|
|
|
|
- <el-tabs v-model="activeTypeTab" class="work-order-type-tabs" @tab-change="handleTypeTabChange">
|
|
|
+ <el-tabs
|
|
|
+ v-model="activeTypeTab"
|
|
|
+ class="work-order-type-tabs"
|
|
|
+ @tab-change="handleTypeTabChange"
|
|
|
+ >
|
|
|
<el-tab-pane label="入库生产工单" name="inbound" />
|
|
|
<el-tab-pane label="临时生产工单" name="temporary" />
|
|
|
+ <el-tab-pane label="出库生产工单" name="outbound" />
|
|
|
<el-tab-pane label="全部生产工单" name="all" />
|
|
|
</el-tabs>
|
|
|
|
|
|
@@ -22,11 +29,7 @@
|
|
|
<el-form :model="searchForm" class="filter-form" @submit.prevent>
|
|
|
<div class="filter-grid">
|
|
|
<el-form-item label="关键词">
|
|
|
- <el-input
|
|
|
- v-model="searchForm.keyword"
|
|
|
- :placeholder="activeTypeTab === 'temporary' ? '工单号' : '工单号/协议号/样本编码'"
|
|
|
- clearable
|
|
|
- />
|
|
|
+ <el-input v-model="searchForm.keyword" :placeholder="searchPlaceholder" clearable />
|
|
|
</el-form-item>
|
|
|
<el-form-item label="工单状态">
|
|
|
<el-select
|
|
|
@@ -38,6 +41,7 @@
|
|
|
<el-option label="待配置" value="dpz" />
|
|
|
<el-option label="进行中" value="jxz" />
|
|
|
<el-option label="已完成" value="ywc" />
|
|
|
+ <el-option label="已作废" value="yzf" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="创建时间">
|
|
|
@@ -66,10 +70,11 @@
|
|
|
</el-form>
|
|
|
</div>
|
|
|
|
|
|
- <div v-if="activeTypeTab !== 'all'" class="list-toolbar">
|
|
|
+ <div v-if="activeTypeTab !== 'all' && activeTypeTab !== 'outbound'" class="list-toolbar">
|
|
|
<div class="list-toolbar-row">
|
|
|
<el-button class="btn-main" type="primary" @click="handleAdd">
|
|
|
- <el-icon><Plus /></el-icon>{{ activeTypeTab === 'temporary' ? '新增临时工单' : '新增生产工单' }}
|
|
|
+ <el-icon><Plus /></el-icon
|
|
|
+ >{{ activeTypeTab === 'temporary' ? '新增临时工单' : '新增生产工单' }}
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -91,30 +96,121 @@
|
|
|
:index="(i) => (pagination.page - 1) * pagination.pageSize + i + 1"
|
|
|
/>
|
|
|
<el-table-column prop="workOrderNo" label="工单号" min-width="150" align="center" />
|
|
|
- <el-table-column v-if="activeTypeTab === 'all'" prop="workOrderType" label="工单类型" min-width="100" align="center">
|
|
|
+ <el-table-column
|
|
|
+ v-if="activeTypeTab === 'all'"
|
|
|
+ prop="workOrderType"
|
|
|
+ label="工单类型"
|
|
|
+ min-width="100"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag :type="woTypeTag(row.workOrderType).type" size="small">
|
|
|
+ {{ woTypeTag(row.workOrderType).label }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <!-- 出库工单专属列 -->
|
|
|
+ <el-table-column
|
|
|
+ v-if="activeTypeTab === 'outbound'"
|
|
|
+ prop="bizTypeLabel"
|
|
|
+ label="业务类型"
|
|
|
+ min-width="110"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
<template #default="{ row }">
|
|
|
- <el-tag :type="row.workOrderType === 'temporary' ? 'warning' : 'success'" size="small">
|
|
|
- {{ row.workOrderType === 'temporary' ? '临时' : '入库' }}
|
|
|
+ <el-tag :type="row.bizType === 'pilot_service' ? 'primary' : 'success'" size="small">
|
|
|
+ {{ row.bizTypeLabel || '—' }}
|
|
|
</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column v-if="showReceptionCols" prop="protocolNo" label="协议号" min-width="140" align="center">
|
|
|
+ <el-table-column
|
|
|
+ v-if="activeTypeTab === 'outbound'"
|
|
|
+ prop="applicationNo"
|
|
|
+ label="申请单号"
|
|
|
+ min-width="150"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">{{ row.applicationNo || '—' }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ v-if="activeTypeTab === 'outbound'"
|
|
|
+ prop="cellType"
|
|
|
+ label="细胞类型"
|
|
|
+ min-width="110"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">{{ row.cellType || '—' }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ v-if="activeTypeTab === 'outbound'"
|
|
|
+ prop="specText"
|
|
|
+ label="规格"
|
|
|
+ min-width="110"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">{{ row.specText || '—' }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ v-if="activeTypeTab === 'outbound'"
|
|
|
+ prop="infusionTime"
|
|
|
+ label="输注时间"
|
|
|
+ min-width="170"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">{{ row.infusionTime || '—' }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ v-if="showReceptionCols"
|
|
|
+ prop="protocolNo"
|
|
|
+ label="协议号"
|
|
|
+ min-width="140"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
<template #default="{ row }">{{ formatTempEmptyField(row, row.protocolNo) }}</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column v-if="showReceptionCols" prop="protocolStatus" label="协议状态" min-width="100" align="center">
|
|
|
+ <el-table-column
|
|
|
+ v-if="showReceptionCols"
|
|
|
+ prop="protocolStatus"
|
|
|
+ label="协议状态"
|
|
|
+ min-width="100"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
<template #default="{ row }">
|
|
|
<span v-if="shouldShowTempEmptyField(row, row.protocolStatus)">—</span>
|
|
|
<el-tag
|
|
|
v-else
|
|
|
- :type="protocolStatusTagTypeBySource(String(row.protocolStatus || ''), row.receptionSource || 'cell_storage')"
|
|
|
+ :type="
|
|
|
+ protocolStatusTagTypeBySource(
|
|
|
+ String(row.protocolStatus || ''),
|
|
|
+ row.receptionSource || 'cell_storage'
|
|
|
+ )
|
|
|
+ "
|
|
|
size="small"
|
|
|
- >{{ protocolStatusLabelBySource(String(row.protocolStatus || ''), row.receptionSource || 'cell_storage') }}</el-tag>
|
|
|
+ >{{
|
|
|
+ protocolStatusLabelBySource(
|
|
|
+ String(row.protocolStatus || ''),
|
|
|
+ row.receptionSource || 'cell_storage'
|
|
|
+ )
|
|
|
+ }}</el-tag
|
|
|
+ >
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column v-if="showReceptionCols" prop="sampleCode" label="样本编码" min-width="120" align="center">
|
|
|
+ <el-table-column
|
|
|
+ v-if="showReceptionCols"
|
|
|
+ prop="sampleCode"
|
|
|
+ label="样本编码"
|
|
|
+ min-width="120"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
<template #default="{ row }">{{ formatTempEmptyField(row, row.sampleCode) }}</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column v-if="showReceptionCols" prop="receptionSource" label="来源类型" min-width="110" align="center">
|
|
|
+ <el-table-column
|
|
|
+ v-if="showReceptionCols"
|
|
|
+ prop="receptionSource"
|
|
|
+ label="来源类型"
|
|
|
+ min-width="110"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
<template #default="{ row }">
|
|
|
<span v-if="shouldShowTempEmptyField(row, row.receptionSource)">—</span>
|
|
|
<el-tag v-else :type="sourceTag(row.receptionSource).type" size="small">
|
|
|
@@ -122,13 +218,31 @@
|
|
|
</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column v-if="showReceptionCols" prop="sampleTypeName" label="样本类型" min-width="110" align="center">
|
|
|
+ <el-table-column
|
|
|
+ v-if="showReceptionCols"
|
|
|
+ prop="sampleTypeName"
|
|
|
+ label="样本类型"
|
|
|
+ min-width="110"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
<template #default="{ row }">{{ row.sampleTypeName || '—' }}</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column v-if="showReceptionCols" prop="handlerName" label="接收人" min-width="100" align="center">
|
|
|
+ <el-table-column
|
|
|
+ v-if="showReceptionCols"
|
|
|
+ prop="handlerName"
|
|
|
+ label="接收人"
|
|
|
+ min-width="100"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
<template #default="{ row }">{{ row.handlerName || '—' }}</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column v-if="showReceptionCols" prop="receptionTime" label="接收时间" min-width="170" align="center">
|
|
|
+ <el-table-column
|
|
|
+ v-if="showReceptionCols"
|
|
|
+ prop="receptionTime"
|
|
|
+ label="接收时间"
|
|
|
+ min-width="170"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
<template #default="{ row }">{{ row.receptionTime || '—' }}</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column prop="remark" label="备注" min-width="140" align="center">
|
|
|
@@ -143,6 +257,7 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column prop="createTime" label="创建时间" min-width="170" align="center" />
|
|
|
<el-table-column
|
|
|
+ v-if="activeTypeTab !== 'all'"
|
|
|
label="操作"
|
|
|
min-width="600"
|
|
|
fixed="right"
|
|
|
@@ -173,7 +288,12 @@
|
|
|
>
|
|
|
<el-icon><Check /></el-icon>完成工单
|
|
|
</el-button>
|
|
|
- <el-button v-if="row.workOrderStatus !== 'ywc'" class="btn-op-item" @click="handleDelete(row)">删除</el-button>
|
|
|
+ <el-button
|
|
|
+ v-if="row.workOrderStatus !== 'ywc'"
|
|
|
+ class="btn-op-item"
|
|
|
+ @click="handleDelete(row)"
|
|
|
+ >删除</el-button
|
|
|
+ >
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
@@ -302,7 +422,6 @@
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
|
|
|
-
|
|
|
<!-- 新增生产工单弹窗 -->
|
|
|
<el-dialog
|
|
|
v-model="addVisible"
|
|
|
@@ -314,10 +433,18 @@
|
|
|
:close-on-click-modal="false"
|
|
|
>
|
|
|
<el-form ref="addFormRef" :model="addForm" :rules="addRules" label-position="top">
|
|
|
- <p v-if="addMode === 'temporary'" class="hint-muted">临时工单不关联样本与协议,创建后请派发任务。</p>
|
|
|
+ <p v-if="addMode === 'temporary'" class="hint-muted"
|
|
|
+ >临时工单不关联样本与协议,创建后请派发任务。</p
|
|
|
+ >
|
|
|
<div v-if="addMode === 'temporary'" class="form-grid-2">
|
|
|
<el-form-item label="备注" class="form-col-span-2">
|
|
|
- <el-input v-model="addForm.remark" type="textarea" :rows="3" placeholder="选填" maxlength="512" />
|
|
|
+ <el-input
|
|
|
+ v-model="addForm.remark"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ placeholder="选填"
|
|
|
+ maxlength="512"
|
|
|
+ />
|
|
|
</el-form-item>
|
|
|
</div>
|
|
|
<div v-else class="form-grid-2">
|
|
|
@@ -325,7 +452,11 @@
|
|
|
<el-input v-model="addForm.protocolNo" placeholder="请输入协议号(可选)" clearable />
|
|
|
</el-form-item>
|
|
|
<el-form-item label="样本编码">
|
|
|
- <el-input v-model="addForm.sampleCode" placeholder="请输入样本编码(可选)" clearable />
|
|
|
+ <el-input
|
|
|
+ v-model="addForm.sampleCode"
|
|
|
+ placeholder="请输入样本编码(可选)"
|
|
|
+ clearable
|
|
|
+ />
|
|
|
</el-form-item>
|
|
|
<el-form-item label="来源类型" prop="receptionSource">
|
|
|
<el-select v-model="addForm.receptionSource" style="width: 100%">
|
|
|
@@ -334,7 +465,13 @@
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="备注" class="form-col-span-2">
|
|
|
- <el-input v-model="addForm.remark" type="textarea" :rows="3" placeholder="选填" maxlength="512" />
|
|
|
+ <el-input
|
|
|
+ v-model="addForm.remark"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ placeholder="选填"
|
|
|
+ maxlength="512"
|
|
|
+ />
|
|
|
</el-form-item>
|
|
|
</div>
|
|
|
</el-form>
|
|
|
@@ -392,16 +529,20 @@
|
|
|
protocolStatusLabel,
|
|
|
protocolStatusTagType,
|
|
|
donationStatusLabel,
|
|
|
- donationStatusTagType,
|
|
|
+ donationStatusTagType
|
|
|
} from '@/utils/status-tag-registry'
|
|
|
import type { TagType } from '@/utils/status-tag-registry'
|
|
|
|
|
|
/** 根据来源类型返回协议状态标签 */
|
|
|
function protocolStatusLabelBySource(status: string, source: string): string {
|
|
|
- return source === 'research_donation' ? donationStatusLabel(status) : protocolStatusLabel(status)
|
|
|
+ return source === 'research_donation'
|
|
|
+ ? donationStatusLabel(status)
|
|
|
+ : protocolStatusLabel(status)
|
|
|
}
|
|
|
function protocolStatusTagTypeBySource(status: string, source: string): TagType {
|
|
|
- return source === 'research_donation' ? donationStatusTagType(status) : protocolStatusTagType(status)
|
|
|
+ return source === 'research_donation'
|
|
|
+ ? donationStatusTagType(status)
|
|
|
+ : protocolStatusTagType(status)
|
|
|
}
|
|
|
|
|
|
/** 临时工单无关联协议/样本时,空字段展示为 — */
|
|
|
@@ -418,20 +559,21 @@
|
|
|
import DispatchTaskDialog from './DispatchTaskDialog.vue'
|
|
|
import EditTaskInfoDialog from './EditTaskInfoDialog.vue'
|
|
|
import WorkOrderRemarkDialog from '@/components/business/work-order-remark-dialog/index.vue'
|
|
|
- import {
|
|
|
- productionConclusionLabel,
|
|
|
- productionConclusionTagType
|
|
|
- } from '@/utils/production-labels'
|
|
|
- import {
|
|
|
- fetchProductionTaskList,
|
|
|
- fetchDeleteProductionTask
|
|
|
- } from '@/api/production-task'
|
|
|
+ import { productionConclusionLabel, productionConclusionTagType } from '@/utils/production-labels'
|
|
|
+ import { fetchProductionTaskList, fetchDeleteProductionTask } from '@/api/production-task'
|
|
|
|
|
|
defineOptions({ name: 'ProductionProductionWorkOrder' })
|
|
|
|
|
|
- type WorkOrderTypeTab = 'inbound' | 'temporary' | 'all'
|
|
|
+ type WorkOrderTypeTab = 'inbound' | 'temporary' | 'outbound' | 'all'
|
|
|
const activeTypeTab = ref<WorkOrderTypeTab>('inbound')
|
|
|
- const showReceptionCols = computed(() => activeTypeTab.value !== 'temporary')
|
|
|
+ const showReceptionCols = computed(
|
|
|
+ () => activeTypeTab.value !== 'temporary' && activeTypeTab.value !== 'outbound'
|
|
|
+ )
|
|
|
+ const searchPlaceholder = computed(() => {
|
|
|
+ if (activeTypeTab.value === 'temporary') return '工单号'
|
|
|
+ if (activeTypeTab.value === 'outbound') return '工单号/申请单号'
|
|
|
+ return '工单号/协议号/样本编码'
|
|
|
+ })
|
|
|
const addMode = ref<'inbound' | 'temporary'>('inbound')
|
|
|
|
|
|
// ── 新增工单 ──────────────────────────────────────────
|
|
|
@@ -485,7 +627,8 @@
|
|
|
const remarkEditLoading = ref(false)
|
|
|
const remarkEditRow = ref<{ id: string; workOrderNo?: string; remark?: string } | null>(null)
|
|
|
const remarkEditTitle = computed(
|
|
|
- () => `编辑备注${remarkEditRow.value?.workOrderNo ? ` — ${remarkEditRow.value.workOrderNo}` : ''}`
|
|
|
+ () =>
|
|
|
+ `编辑备注${remarkEditRow.value?.workOrderNo ? ` — ${remarkEditRow.value.workOrderNo}` : ''}`
|
|
|
)
|
|
|
const remarkEditInitialRemark = computed(() => remarkEditRow.value?.remark || '')
|
|
|
|
|
|
@@ -511,7 +654,8 @@
|
|
|
const map: Record<string, { label: string; type: string }> = {
|
|
|
dpz: { label: '待配置', type: 'info' },
|
|
|
jxz: { label: '进行中', type: 'warning' },
|
|
|
- ywc: { label: '已完成', type: 'success' }
|
|
|
+ ywc: { label: '已完成', type: 'success' },
|
|
|
+ yzf: { label: '已作废', type: 'danger' }
|
|
|
}
|
|
|
return map[status] || { label: status, type: 'info' }
|
|
|
}
|
|
|
@@ -530,6 +674,14 @@
|
|
|
}
|
|
|
return map[source] || { label: source, type: 'info' }
|
|
|
}
|
|
|
+ const woTypeTag = (type: string) => {
|
|
|
+ const map: Record<string, { label: string; type: string }> = {
|
|
|
+ inbound: { label: '入库', type: 'success' },
|
|
|
+ temporary: { label: '临时', type: 'warning' },
|
|
|
+ outbound: { label: '出库', type: 'primary' }
|
|
|
+ }
|
|
|
+ return map[type] || { label: type, type: 'info' }
|
|
|
+ }
|
|
|
|
|
|
function formatLocalDate(d: Date): string {
|
|
|
const y = d.getFullYear()
|
|
|
@@ -641,7 +793,122 @@
|
|
|
if (!detail.value) return []
|
|
|
const d = detail.value
|
|
|
const isTemp = d.workOrderType === 'temporary'
|
|
|
+ const isOutbound = d.workOrderType === 'outbound'
|
|
|
const r = d.reception || {}
|
|
|
+
|
|
|
+ // ── 基本信息 fields ──
|
|
|
+ const baseFields: ViewSection['fields'] = [
|
|
|
+ { label: '工单号', value: d.workOrderNo },
|
|
|
+ {
|
|
|
+ label: '工单类型',
|
|
|
+ value: isTemp ? '临时' : isOutbound ? '出库' : '入库',
|
|
|
+ tagType: isTemp ? 'warning' : isOutbound ? 'primary' : 'success'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+
|
|
|
+ // outbound 显示业务类型
|
|
|
+ if (isOutbound) {
|
|
|
+ baseFields.push({
|
|
|
+ label: '业务类型',
|
|
|
+ value:
|
|
|
+ d.bizTypeLabel ||
|
|
|
+ (d.bizType === 'pilot_service'
|
|
|
+ ? '中试服务'
|
|
|
+ : d.bizType === 'clinical_application'
|
|
|
+ ? '临床应用'
|
|
|
+ : '—'),
|
|
|
+ tagType: 'primary' as const
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // inbound 显示协议/样本字段
|
|
|
+ if (!isTemp && !isOutbound) {
|
|
|
+ baseFields.push(
|
|
|
+ { label: '协议号', value: d.protocolNo },
|
|
|
+ {
|
|
|
+ label: '协议状态',
|
|
|
+ value: protocolStatusLabelBySource(
|
|
|
+ String(d.protocolStatus || ''),
|
|
|
+ d.receptionSource || 'cell_storage'
|
|
|
+ ),
|
|
|
+ tagType: protocolStatusTagTypeBySource(
|
|
|
+ String(d.protocolStatus || ''),
|
|
|
+ d.receptionSource || 'cell_storage'
|
|
|
+ )
|
|
|
+ },
|
|
|
+ { label: '样本编码', value: d.sampleCode },
|
|
|
+ {
|
|
|
+ label: '来源类型',
|
|
|
+ value:
|
|
|
+ r.sourceTypeLabel ||
|
|
|
+ d.receptionSourceLabel ||
|
|
|
+ receptionSourceLabel(d.receptionSource || ''),
|
|
|
+ tagType: 'primary' as const
|
|
|
+ },
|
|
|
+ { label: '样本类型', value: r.sampleTypeName || d.sampleTypeName || '—' }
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ baseFields.push(
|
|
|
+ {
|
|
|
+ label: '工单状态',
|
|
|
+ value: woStatusTag(d.workOrderStatus).label,
|
|
|
+ tagType: woStatusTag(d.workOrderStatus).type as any
|
|
|
+ },
|
|
|
+ { label: '备注', value: d.remark || '—', span: true },
|
|
|
+ { label: '创建时间', value: d.createTime || '—' }
|
|
|
+ )
|
|
|
+
|
|
|
+ const sections: ViewSection[] = [{ title: '基本信息', fields: baseFields }]
|
|
|
+
|
|
|
+ // outbound: 申请单 + 输注计划
|
|
|
+ if (isOutbound) {
|
|
|
+ const pa = d.pilotApplication || {}
|
|
|
+ const sched = d.infusionSchedule || {}
|
|
|
+ const appStatusLabel = (s: string) => {
|
|
|
+ const m: Record<string, string> = {
|
|
|
+ dks: '待开始',
|
|
|
+ jxz: '进行中',
|
|
|
+ ywc: '已完成',
|
|
|
+ yzf: '已作废'
|
|
|
+ }
|
|
|
+ return m[s] || s || '—'
|
|
|
+ }
|
|
|
+ const appStatusTagType = (s: string) => {
|
|
|
+ const m: Record<string, string> = {
|
|
|
+ dks: 'info',
|
|
|
+ jxz: 'warning',
|
|
|
+ ywc: 'success',
|
|
|
+ yzf: 'danger'
|
|
|
+ }
|
|
|
+ return m[s] || 'info'
|
|
|
+ }
|
|
|
+ sections.push({
|
|
|
+ title: '中试申请信息',
|
|
|
+ fields: [
|
|
|
+ { label: '申请单号', value: pa.applicationNo || '—' },
|
|
|
+ { label: '申请名称', value: pa.applicationName || '—' },
|
|
|
+ {
|
|
|
+ label: '申请状态',
|
|
|
+ value: appStatusLabel(pa.applicationStatus),
|
|
|
+ tagType: appStatusTagType(pa.applicationStatus) as any
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ })
|
|
|
+ sections.push({
|
|
|
+ title: '输注计划信息',
|
|
|
+ fields: [
|
|
|
+ { label: '细胞类型', value: sched.cellType || '—' },
|
|
|
+ { label: '规格', value: sched.specText || '—' },
|
|
|
+ { label: '输注时间', value: sched.infusionTime || '—' },
|
|
|
+ { label: '输注地点', value: sched.infusionLocation || '—' },
|
|
|
+ { label: '输注方式', value: sched.infusionMethod || '—' }
|
|
|
+ ]
|
|
|
+ })
|
|
|
+ return sections
|
|
|
+ }
|
|
|
+
|
|
|
+ // inbound: 运输 + 样本接收
|
|
|
const transportFields: ViewSection['fields'] = [
|
|
|
{ label: '运输方式', value: transportTypeLabel(String(r.transportType || '')) }
|
|
|
]
|
|
|
@@ -661,62 +928,29 @@
|
|
|
transportFields.length > 1 || r.transportType
|
|
|
? [{ title: '运输信息', fields: transportFields }]
|
|
|
: []
|
|
|
+
|
|
|
return [
|
|
|
- {
|
|
|
- title: '基本信息',
|
|
|
- fields: [
|
|
|
- { label: '工单号', value: d.workOrderNo },
|
|
|
- {
|
|
|
- label: '工单类型',
|
|
|
- value: isTemp ? '临时' : '入库',
|
|
|
- tagType: isTemp ? 'warning' : 'success'
|
|
|
- },
|
|
|
- ...(isTemp
|
|
|
- ? []
|
|
|
- : [
|
|
|
- { label: '协议号', value: d.protocolNo },
|
|
|
- {
|
|
|
- label: '协议状态',
|
|
|
- value: protocolStatusLabelBySource(String(d.protocolStatus || ''), d.receptionSource || 'cell_storage'),
|
|
|
- tagType: protocolStatusTagTypeBySource(String(d.protocolStatus || ''), d.receptionSource || 'cell_storage')
|
|
|
- },
|
|
|
- { label: '样本编码', value: d.sampleCode },
|
|
|
- {
|
|
|
- label: '来源类型',
|
|
|
- value:
|
|
|
- r.sourceTypeLabel ||
|
|
|
- d.receptionSourceLabel ||
|
|
|
- receptionSourceLabel(d.receptionSource || ''),
|
|
|
- tagType: 'primary' as const
|
|
|
- },
|
|
|
- { label: '样本类型', value: r.sampleTypeName || d.sampleTypeName || '—' }
|
|
|
- ]),
|
|
|
- {
|
|
|
- label: '工单状态',
|
|
|
- value: woStatusTag(d.workOrderStatus).label,
|
|
|
- tagType: woStatusTag(d.workOrderStatus).type as any
|
|
|
- },
|
|
|
- { label: '备注', value: d.remark || '—', span: true },
|
|
|
- { label: '创建时间', value: d.createTime || '—' }
|
|
|
- ]
|
|
|
- },
|
|
|
- ...(isTemp ? [] : transportSection),
|
|
|
- ...(isTemp
|
|
|
- ? []
|
|
|
- : [
|
|
|
+ { title: '基本信息', fields: baseFields },
|
|
|
+ ...transportSection,
|
|
|
+ ...(!isTemp
|
|
|
+ ? [
|
|
|
{
|
|
|
title: '样本接收',
|
|
|
slot: 'reception-extra',
|
|
|
fields: [
|
|
|
{ label: '接收时间', value: r.receptionTime || d.receptionTime || '—' },
|
|
|
{ label: '接收经手人', value: r.handlerName || d.handlerName || '—' },
|
|
|
- { label: '接收温度(℃)', value: r.receiveTemperature ? `${r.receiveTemperature}℃` : '—' },
|
|
|
+ {
|
|
|
+ label: '接收温度(℃)',
|
|
|
+ value: r.receiveTemperature ? `${r.receiveTemperature}℃` : '—'
|
|
|
+ },
|
|
|
{ label: '体积(ml)', value: formatMetric(r.volumeMl) },
|
|
|
{ label: '净重(g)', value: formatMetric(r.netWeightG) },
|
|
|
{
|
|
|
label: '结论',
|
|
|
value:
|
|
|
- r.acceptConclusionLabel || acceptConclusionLabel(String(r.acceptConclusion || '')),
|
|
|
+ r.acceptConclusionLabel ||
|
|
|
+ acceptConclusionLabel(String(r.acceptConclusion || '')),
|
|
|
tagType:
|
|
|
r.acceptConclusion === 'js'
|
|
|
? 'success'
|
|
|
@@ -728,7 +962,8 @@
|
|
|
{ label: '备注', value: r.remark || '—', span: true }
|
|
|
]
|
|
|
}
|
|
|
- ])
|
|
|
+ ]
|
|
|
+ : [])
|
|
|
]
|
|
|
})
|
|
|
|