提交
This commit is contained in:
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(
|
||||
|
||||
Reference in new issue
Block a user