提交
This commit is contained in:
1 parent
e5ba8f097a
commit
62cfb8fbbf
24 files changed
+3323
-249
No files matched your search
@@ -313,6 +313,56 @@
|
||||
/>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<template
|
||||
v-for="flowCtx in [{ nodes: buildPaymentFlowNodes(detail) }]"
|
||||
:key="`${detail.id || dIdx}-flow`"
|
||||
>
|
||||
<div v-if="flowCtx.nodes.length" class="payment-flow">
|
||||
<div class="payment-flow-scroll">
|
||||
<div class="payment-flow-track">
|
||||
<div
|
||||
v-for="(node, nIdx) in flowCtx.nodes"
|
||||
:key="node.key"
|
||||
class="payment-flow-item"
|
||||
>
|
||||
<div class="payment-flow-rail">
|
||||
<span class="payment-flow-node" />
|
||||
<span
|
||||
v-if="nIdx < flowCtx.nodes.length - 1"
|
||||
class="payment-flow-line"
|
||||
/>
|
||||
</div>
|
||||
<div class="payment-flow-body">
|
||||
<div class="payment-flow-title">{{ node.title }}</div>
|
||||
<div
|
||||
v-if="node.amount != null && node.amount !== ''"
|
||||
class="payment-flow-kv"
|
||||
>
|
||||
<span class="payment-flow-kv__label">退费金额(元)</span>
|
||||
<span class="payment-flow-kv__value">{{ dash(node.amount) }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="node.remark != null && String(node.remark).trim() !== ''"
|
||||
class="payment-flow-kv payment-flow-kv--remark"
|
||||
>
|
||||
<span class="payment-flow-kv__label">{{ node.remarkLabel }}</span>
|
||||
<span class="payment-flow-kv__value">{{ dash(node.remark) }}</span>
|
||||
</div>
|
||||
<div v-if="node.attachments.length" class="payment-flow-attachments">
|
||||
<span class="payment-flow-kv__label">{{ node.attachmentLabel }}</span>
|
||||
<ProtocolAttachmentReadonly
|
||||
:files="node.attachments"
|
||||
@preview="openPreview"
|
||||
@download="downloadFile"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -494,6 +544,8 @@
|
||||
const collectorDisplay = computed(() => {
|
||||
const fromList = props.listRow?.collectorUserName
|
||||
if (fromList) return String(fromList)
|
||||
const fromBundle = protocol.value?.collectorUserName
|
||||
if (fromBundle) return String(fromBundle)
|
||||
const id = protocol.value?.collectorUserId
|
||||
const u = collectorUserOptions.value.find((x) => x.id === id)
|
||||
return u?.nickName || dash(id)
|
||||
@@ -502,6 +554,8 @@
|
||||
const salesDisplay = computed(() => {
|
||||
const fromList = props.listRow?.salesUserName
|
||||
if (fromList) return String(fromList)
|
||||
const fromBundle = collectionInfo.value?.salesUserName
|
||||
if (fromBundle) return String(fromBundle)
|
||||
const id = collectionInfo.value?.salesUserId
|
||||
const u = salesUserOptions.value.find((x) => x.id === id)
|
||||
return u?.nickName || dash(id)
|
||||
@@ -510,6 +564,8 @@
|
||||
const regionDisplay = computed(() => {
|
||||
const fromList = props.listRow?.regionName
|
||||
if (fromList) return String(fromList)
|
||||
const fromBundle = collectionInfo.value?.regionName
|
||||
if (fromBundle) return String(fromBundle)
|
||||
const id = collectionInfo.value?.regionId
|
||||
const r = regionOptions.value.find((x) => x.id === id)
|
||||
return r?.regionName || dash(id)
|
||||
@@ -518,6 +574,8 @@
|
||||
const hospitalDisplay = computed(() => {
|
||||
const fromList = props.listRow?.hospitalName
|
||||
if (fromList) return String(fromList)
|
||||
const fromBundle = collectionInfo.value?.hospitalName
|
||||
if (fromBundle) return String(fromBundle)
|
||||
const id = collectionInfo.value?.hospitalId
|
||||
const h = hospitalOptions.value.find((x) => x.id === id)
|
||||
return h?.hospitalName || dash(id)
|
||||
@@ -649,6 +707,131 @@
|
||||
return Array.isArray(detail.attachments) ? detail.attachments : []
|
||||
}
|
||||
|
||||
function financeConfirmAttachmentFiles(detail: Record<string, any>) {
|
||||
if (Array.isArray(detail.financeConfirmAttachmentFiles)) {
|
||||
return detail.financeConfirmAttachmentFiles
|
||||
}
|
||||
return urlsToAttachmentFiles(String(detail.financeConfirmAttachments || ''))
|
||||
}
|
||||
|
||||
function refundAttachmentFiles(detail: Record<string, any>) {
|
||||
if (Array.isArray(detail.refundAttachmentFiles)) {
|
||||
return detail.refundAttachmentFiles
|
||||
}
|
||||
return urlsToAttachmentFiles(String(detail.refundAttachments || ''))
|
||||
}
|
||||
|
||||
function refundFinanceConfirmAttachmentFiles(detail: Record<string, any>) {
|
||||
if (Array.isArray(detail.refundFinanceConfirmAttachmentFiles)) {
|
||||
return detail.refundFinanceConfirmAttachmentFiles
|
||||
}
|
||||
return urlsToAttachmentFiles(String(detail.refundFinanceConfirmAttachments || ''))
|
||||
}
|
||||
|
||||
function urlsToAttachmentFiles(urls: string) {
|
||||
if (!urls.trim()) return []
|
||||
return urls.split(',').map((u, i) => {
|
||||
const url = u.trim()
|
||||
if (!url) return null
|
||||
const name = url.includes('/') ? url.split('/').pop() || `附件${i + 1}` : url
|
||||
return { id: `url_${i}`, fileUrl: url, fileName: name, fileSize: 0 }
|
||||
}).filter(Boolean) as Array<Record<string, any>>
|
||||
}
|
||||
|
||||
function hasFinanceRemark(detail: Record<string, any>) {
|
||||
return String(detail.financeRemark || '').trim() !== ''
|
||||
}
|
||||
|
||||
function hasFinanceConfirmAttachments(detail: Record<string, any>) {
|
||||
return financeConfirmAttachmentFiles(detail).length > 0
|
||||
}
|
||||
|
||||
function hasRefundApplyInfo(detail: Record<string, any>) {
|
||||
const amount = detail.refundAmount
|
||||
const hasAmount = amount != null && amount !== '' && Number(amount) > 0
|
||||
return (
|
||||
hasAmount ||
|
||||
String(detail.refundRemark || '').trim() !== '' ||
|
||||
refundAttachmentFiles(detail).length > 0
|
||||
)
|
||||
}
|
||||
|
||||
/** 缴费财务确认:已缴费或退费确认中,且已有财务确认字段 */
|
||||
function showPaymentFinanceConfirm(detail: Record<string, any>) {
|
||||
const status = String(detail.payStatus || '')
|
||||
if (status === 'ytf') return false
|
||||
if (status !== 'yjf' && status !== 'tfqrz') return false
|
||||
return hasFinanceRemark(detail) || hasFinanceConfirmAttachments(detail)
|
||||
}
|
||||
|
||||
/** 退费确认申请:发起退费时填写 */
|
||||
function showRefundApply(detail: Record<string, any>) {
|
||||
const status = String(detail.payStatus || '')
|
||||
if (status !== 'tfqrz' && status !== 'ytf') return false
|
||||
return hasRefundApplyInfo(detail)
|
||||
}
|
||||
|
||||
function hasRefundFinanceRemark(detail: Record<string, any>) {
|
||||
return String(detail.refundFinanceRemark || '').trim() !== ''
|
||||
}
|
||||
|
||||
function hasRefundFinanceConfirmAttachments(detail: Record<string, any>) {
|
||||
return refundFinanceConfirmAttachmentFiles(detail).length > 0
|
||||
}
|
||||
|
||||
/** 财务退费确认:已退费时展示的财务确认信息 */
|
||||
function showRefundFinanceConfirm(detail: Record<string, any>) {
|
||||
if (String(detail.payStatus || '') !== 'ytf') return false
|
||||
return hasRefundFinanceRemark(detail) || hasRefundFinanceConfirmAttachments(detail)
|
||||
}
|
||||
|
||||
interface PaymentFlowNode {
|
||||
key: string
|
||||
title: string
|
||||
remarkLabel: string
|
||||
attachmentLabel: string
|
||||
remark?: unknown
|
||||
amount?: unknown
|
||||
attachments: Array<Record<string, any>>
|
||||
}
|
||||
|
||||
/** 缴费明细 — 财务/退费流程横向节点(按业务顺序) */
|
||||
function buildPaymentFlowNodes(detail: Record<string, any>): PaymentFlowNode[] {
|
||||
const nodes: PaymentFlowNode[] = []
|
||||
if (showPaymentFinanceConfirm(detail)) {
|
||||
nodes.push({
|
||||
key: 'receipt-finance',
|
||||
title: '缴费财务确认',
|
||||
remarkLabel: '财务备注',
|
||||
attachmentLabel: '财务附件',
|
||||
remark: detail.financeRemark,
|
||||
attachments: financeConfirmAttachmentFiles(detail)
|
||||
})
|
||||
}
|
||||
if (showRefundApply(detail)) {
|
||||
nodes.push({
|
||||
key: 'refund-apply',
|
||||
title: '退费确认申请',
|
||||
remarkLabel: '退费备注',
|
||||
attachmentLabel: '退费附件',
|
||||
remark: detail.refundRemark,
|
||||
amount: detail.refundAmount,
|
||||
attachments: refundAttachmentFiles(detail)
|
||||
})
|
||||
}
|
||||
if (showRefundFinanceConfirm(detail)) {
|
||||
nodes.push({
|
||||
key: 'refund-finance',
|
||||
title: '财务退费确认',
|
||||
remarkLabel: '财务备注',
|
||||
attachmentLabel: '财务附件',
|
||||
remark: detail.refundFinanceRemark,
|
||||
attachments: refundFinanceConfirmAttachmentFiles(detail)
|
||||
})
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
function fullFileUrl(suffix: string) {
|
||||
if (!suffix) return ''
|
||||
if (suffix.startsWith('http://') || suffix.startsWith('https://') || suffix.startsWith('/'))
|
||||
@@ -947,11 +1130,133 @@
|
||||
}
|
||||
|
||||
.payment-detail-card__attachments {
|
||||
margin-top: 8px;
|
||||
padding-top: 8px;
|
||||
margin-top: 4px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px dashed #e2e8f0;
|
||||
}
|
||||
|
||||
.payment-flow {
|
||||
margin-top: 14px;
|
||||
padding-top: 14px;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.payment-flow-scroll {
|
||||
overflow-x: auto;
|
||||
padding: 0 0 6px 4px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #d1d5db;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.payment-flow-track {
|
||||
display: inline-flex;
|
||||
min-width: 100%;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.payment-flow-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 200px;
|
||||
flex: 1 0 200px;
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
.payment-flow-rail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.payment-flow-node {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 50%;
|
||||
background: var(--primary, #10b981);
|
||||
box-shadow: 0 0 0 1px var(--primary, #10b981);
|
||||
}
|
||||
|
||||
.payment-flow-line {
|
||||
flex: 1;
|
||||
height: 2px;
|
||||
margin-left: 0;
|
||||
background: #d1d5db;
|
||||
}
|
||||
|
||||
.payment-flow-body {
|
||||
padding: 8px 12px 0 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.payment-flow-title {
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
.payment-flow-kv {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.payment-flow-kv--remark .payment-flow-kv__value {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.payment-flow-kv__label {
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.payment-flow-kv__value {
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
.payment-flow-attachments {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
|
||||
:deep(.attachment-list) {
|
||||
flex-wrap: nowrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
:deep(.attachment-item) {
|
||||
width: 88px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
:deep(.attachment-preview) {
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
:deep(.attachment-footer) {
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
:deep(.attachment-name) {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
.view-field-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in new issue
Block a user