This commit is contained in:
zlwu committed 2026-10-17 11:46:53 +08:00
1 parent 48dcf991dc
commit be2226e4ca
100 files changed
+61340 -40975

No files matched your search

@@ -52,6 +52,10 @@
></div
></div
>
<div class="data-item"
><div class="data-label">母亲姓名</div
><div class="data-value">{{ basicMotherNameDisplay }}</div></div
>
<div class="data-item"
><div class="data-label">登记日期</div
><div class="data-value">{{ formatYmd(protocol?.registerDate) }}</div></div
@@ -786,6 +790,23 @@
align="center"
show-overflow-tooltip
/>
<el-table-column
label="附件"
min-width="280"
align="left"
header-align="center"
>
<template #default="{ row }">
<ProtocolAttachmentReadonly
v-if="refundRecordAttachments(row).length"
:files="refundRecordAttachments(row)"
size="compact"
@preview="openPreview"
@download="downloadFile"
/>
<span v-else class="muted-dash">—</span>
</template>
</el-table-column>
</el-table>
<el-empty v-else description="暂无退费登记" :image-size="40" />
</template>
@@ -1099,62 +1120,47 @@
<!-- 状态变更记录(置底) -->
<div id="view-section-status-change" class="section-card section-card--white">
<div class="section-title section-title--banner"><h3>状态变更记录</h3></div>
<el-empty v-if="!hasAnyStatusChange" description="暂无状态变更记录" :image-size="64" />
<div v-else class="data-grid data-grid--4">
<template v-if="protocol?.effectiveTime">
<div class="data-item"
><div class="data-label">协议生效时间</div
><div class="data-value">{{ dash(protocol.effectiveTime) }}</div></div
<div class="list-body list-wrap view-inner-table-wrap">
<el-table
v-loading="statusChangeLoading"
class="list-table inner-table"
:data="statusChangeRecords"
stripe
empty-text="暂无状态变更记录"
>
<el-table-column
type="index"
label="序号"
min-width="68"
align="center"
header-align="center"
/>
<el-table-column label="变更类型" min-width="110" align="center" header-align="center">
<template #default="{ row }">
<el-tag :type="statusChangeTagType(String(row.changeType || ''))" size="small">
{{ statusChangeTypeLabel(String(row.changeType || '')) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="变更时间" min-width="170" align="center" header-align="center">
<template #default="{ row }">{{ dash(row.changeTime) }}</template>
</el-table-column>
<el-table-column label="状态流转" min-width="160" align="center" header-align="center">
<template #default="{ row }">{{ statusChangeFlow(row) }}</template>
</el-table-column>
<el-table-column
label="变更说明"
min-width="200"
align="center"
header-align="center"
show-overflow-tooltip
>
<div class="data-item"
><div class="data-label">协议生效描述</div
><div class="data-value data-value--muted">{{
dash(protocol.effectiveDesc)
}}</div></div
>
</template>
<template v-if="protocol?.expireTime">
<div class="data-item"
><div class="data-label">协议过期时间</div
><div class="data-value">{{ dash(protocol.expireTime) }}</div></div
>
<div class="data-item"
><div class="data-label">协议过期描述</div
><div class="data-value data-value--muted">{{
dash(protocol.expireDesc)
}}</div></div
>
</template>
<template v-if="protocol?.voidTime">
<div class="data-item"
><div class="data-label">作废类型</div
><div class="data-value">{{
voidTypeLabel(String(protocol?.voidType || '')) || '—'
}}</div></div
>
<div class="data-item"
><div class="data-label">协议作废时间</div
><div class="data-value">{{ dash(protocol.voidTime) }}</div></div
>
<div class="data-item"
><div class="data-label">协议作废描述</div
><div class="data-value data-value--muted">{{
dash(protocol.voidDesc)
}}</div></div
>
</template>
<template v-if="protocol?.toResearchTime">
<div class="data-item"
><div class="data-label">协议转科研时间</div
><div class="data-value">{{ dash(protocol.toResearchTime) }}</div></div
>
<div class="data-item"
><div class="data-label">协议转科研描述</div
><div class="data-value data-value--muted">{{
dash(protocol.toResearchDesc)
}}</div></div
>
</template>
<template #default="{ row }">{{ statusChangeDesc(row) }}</template>
</el-table-column>
<el-table-column label="操作人" min-width="120" align="center" header-align="center">
<template #default="{ row }">{{ dash(row.operatorUserName) }}</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
@@ -1208,6 +1214,7 @@
import {
fetchCollectionProtocolAuditList,
fetchCollectionProtocolDetail,
fetchCollectionProtocolStatusChanges,
type CollectionProtocolRow
} from '@/api/collection-protocol'
import {
@@ -1305,8 +1312,52 @@
const detailLoading = ref(false)
const lookupLoading = ref(false)
const auditLoading = ref(false)
const statusChangeLoading = ref(false)
const bundle = ref<Record<string, any> | null>(null)
const auditRecords = ref<Array<Record<string, unknown>>>([])
const statusChangeRecords = ref<Array<Record<string, unknown>>>([])
const STATUS_CHANGE_TYPE_LABEL: Record<string, string> = {
activate: '生效',
expire: '过期',
void: '作废',
to_research: '转科研',
to_storage: '转细胞存储'
}
const STATUS_CHANGE_TAG: Record<string, 'success' | 'warning' | 'danger' | 'primary' | 'info'> = {
activate: 'success',
expire: 'warning',
void: 'danger',
to_research: 'primary',
to_storage: 'primary'
}
function statusChangeTypeLabel(changeType: string) {
return STATUS_CHANGE_TYPE_LABEL[changeType] || changeType || '—'
}
function statusChangeTagType(changeType: string) {
return STATUS_CHANGE_TAG[changeType] || 'info'
}
function statusChangeFlow(row: Record<string, unknown>) {
const from = String(row.fromStatus || '')
const to = String(row.toStatus || '')
const voidType = String(row.voidType || '')
const toLabel = protocolStatusDisplayLabel(to, to === 'yzf' ? voidType : '')
if (!from) return toLabel || '—'
return `${protocolStatusDisplayLabel(from)} → ${toLabel}`
}
function statusChangeDesc(row: Record<string, unknown>) {
const desc = String(row.changeDesc || '').trim()
if (String(row.changeType || '') === 'void') {
const vt = voidTypeLabel(String(row.voidType || ''))
if (vt && desc) return `作废类型:${vt};${desc}`
if (vt) return `作废类型:${vt}`
}
return desc || '—'
}
const activeTab = ref('basic')
const sampleTypeOptions = ref<Array<{ id: string; typeName: string }>>([])
@@ -1520,25 +1571,21 @@
/** 金额只读展示:千分位 + ¥ 前缀,null 显示 — */
function fmtMoney(v: unknown): string {
if (v == null || v === '') return '—'
return '¥' + formatMoneyDisplay(v)
return '¥' + formatMoneyDisplay(v as string | number)
}
const basicMotherNameDisplay = computed(() =>
dash(
partyCustomer.value?.motherName || props.listRow?.motherName || protocol.value?.motherName
)
)
const dialogTitle = computed(() => {
const name =
partyCustomer.value?.motherName || props.listRow?.motherName || protocol.value?.motherName
return `查看 — ${formatProtocolDocSubject('cell_storage', { motherName: name })}`
})
const hasAnyStatusChange = computed(() => {
if (!protocol.value) return false
return !!(
protocol.value.effectiveTime ||
protocol.value.expireTime ||
protocol.value.voidTime ||
protocol.value.toResearchTime
)
})
const collectorDisplay = computed(() => {
const fromList = props.listRow?.collectorUserName
if (fromList) return String(fromList)
@@ -1892,6 +1939,13 @@
return urlsToAttachmentFiles(String(detail.financeConfirmAttachments || ''))
}
function refundRecordAttachments(row: Record<string, any>) {
if (Array.isArray(row.refundAttachmentFiles) && row.refundAttachmentFiles.length) {
return row.refundAttachmentFiles
}
return urlsToAttachmentFiles(String(row.refundAttachments || ''))
}
function refundAttachmentFiles(detail: Record<string, any>) {
if (Array.isArray(detail.refundAttachmentFiles)) {
return detail.refundAttachmentFiles
@@ -2007,6 +2061,22 @@
}
}
async function loadStatusChangeRecords() {
if (!props.protocolId) {
statusChangeRecords.value = []
return
}
statusChangeLoading.value = true
try {
const res = await fetchCollectionProtocolStatusChanges(props.protocolId)
statusChangeRecords.value = res.list || []
} catch {
statusChangeRecords.value = []
} finally {
statusChangeLoading.value = false
}
}
async function loadAuditRecords() {
if (!props.showAuditHistory || !props.protocolId) {
auditRecords.value = []
@@ -2033,9 +2103,11 @@
lookupLoading.value = true
bundle.value = null
auditRecords.value = []
statusChangeRecords.value = []
const baseLookupsPromise = loadBaseLookups().catch(() => {})
const auditPromise = props.showAuditHistory ? loadAuditRecords() : null
const statusChangePromise = loadStatusChangeRecords()
let data: Record<string, any> | null = null
try {
@@ -2052,6 +2124,7 @@
void finishLookups(data, baseLookupsPromise)
void auditPromise
void statusChangePromise
if (props.highlightSampleCode) {
nextTick(() => {
document
@@ -2074,10 +2147,12 @@
function handleClosed() {
bundle.value = null
auditRecords.value = []
statusChangeRecords.value = []
activeTab.value = 'basic'
detailLoading.value = false
lookupLoading.value = false
auditLoading.value = false
statusChangeLoading.value = false
}
watch(