|
|
@@ -1,4 +1,4 @@
|
|
|
-<!-- 缴退费财务确认 -->
|
|
|
+<!-- 缴费财务确认及开票(按转账笔;退费确认 Tab 已下线) -->
|
|
|
<!-- eslint-disable vue/no-v-model-argument -->
|
|
|
<template>
|
|
|
<div class="page-container">
|
|
|
@@ -18,19 +18,7 @@
|
|
|
formatTabBadgeCount(paymentPendingBadge)
|
|
|
}}</span>
|
|
|
</button>
|
|
|
- <button
|
|
|
- type="button"
|
|
|
- role="tab"
|
|
|
- class="panel-pill-tabs__btn"
|
|
|
- :class="{ 'is-active': mainTab === 'refund' }"
|
|
|
- :aria-selected="mainTab === 'refund'"
|
|
|
- @click="mainTab = 'refund'"
|
|
|
- >
|
|
|
- 退费确认
|
|
|
- <span v-if="refundPendingBadge > 0" class="panel-pill-tabs__badge">{{
|
|
|
- formatTabBadgeCount(refundPendingBadge)
|
|
|
- }}</span>
|
|
|
- </button>
|
|
|
+ <!-- TODO(P1): 开票改挂 transfer;当前仍走旧 payment_detail 开票 API -->
|
|
|
<button
|
|
|
type="button"
|
|
|
role="tab"
|
|
|
@@ -68,7 +56,7 @@
|
|
|
<el-form-item label="关键词">
|
|
|
<el-input
|
|
|
v-model="pendingSearchForm.keyword"
|
|
|
- placeholder="客户姓名/身份证号/新生儿姓名/新生儿身份证号"
|
|
|
+ placeholder="协议号/样本编码/客户姓名/身份证号"
|
|
|
clearable
|
|
|
@keyup.enter="handlePendingSearch"
|
|
|
/>
|
|
|
@@ -105,20 +93,23 @@
|
|
|
<div class="pending-card__identity">
|
|
|
<div class="pending-card__name">{{ row.motherName || '-' }}</div>
|
|
|
<div class="pending-card__sub">
|
|
|
- {{ maskIdCard(row.motherIdCard) }}
|
|
|
- <template v-if="row.newbornName"> · 新生儿 {{ row.newbornName }} </template>
|
|
|
+ {{ row.protocolNo || '-' }}
|
|
|
+ <template v-if="row.sampleCode"> · {{ row.sampleCode }}</template>
|
|
|
+ <template v-if="row.motherIdCard">
|
|
|
+ · {{ maskIdCard(row.motherIdCard) }}
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="pending-card__amount">
|
|
|
<div class="pending-card__amount-val">
|
|
|
{{ formatPaymentAmount(row.transferAmount) }}
|
|
|
</div>
|
|
|
- <div class="pending-card__amount-label">实缴金额</div>
|
|
|
+ <div class="pending-card__amount-label">转账金额</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="pending-card__grid">
|
|
|
<div class="pending-card__field">
|
|
|
- <label>期数</label>
|
|
|
+ <label>期次</label>
|
|
|
<span>第 {{ row.installmentNo ?? '-' }} 期</span>
|
|
|
</div>
|
|
|
<div class="pending-card__field">
|
|
|
@@ -126,7 +117,7 @@
|
|
|
<span>{{ formatPaymentDueDate(row.installmentDueDate) }}</span>
|
|
|
</div>
|
|
|
<div class="pending-card__field">
|
|
|
- <label>应缴金额</label>
|
|
|
+ <label>批次应缴</label>
|
|
|
<span>{{ formatPaymentAmount(row.dueAmount) }}</span>
|
|
|
</div>
|
|
|
<div class="pending-card__field">
|
|
|
@@ -141,6 +132,10 @@
|
|
|
<label>转账时间</label>
|
|
|
<span>{{ formatDisplayOrDash(row.transferTime) }}</span>
|
|
|
</div>
|
|
|
+ <div class="pending-card__field">
|
|
|
+ <label>来源</label>
|
|
|
+ <span>{{ row.source === 'presign' ? '预签约意向金' : '正式协议' }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div class="pending-card__foot">
|
|
|
<div class="pending-card__meta">
|
|
|
@@ -195,7 +190,7 @@
|
|
|
<el-form-item label="关键词">
|
|
|
<el-input
|
|
|
v-model="confirmedSearchForm.keyword"
|
|
|
- placeholder="客户姓名/身份证号/新生儿姓名/新生儿身份证号"
|
|
|
+ placeholder="协议号/样本编码/客户姓名/身份证号"
|
|
|
clearable
|
|
|
@keyup.enter="handleConfirmedSearch"
|
|
|
/>
|
|
|
@@ -244,6 +239,24 @@
|
|
|
(index) => (confirmedPagination.page - 1) * confirmedPagination.pageSize + index + 1
|
|
|
"
|
|
|
/>
|
|
|
+ <el-table-column
|
|
|
+ prop="protocolNo"
|
|
|
+ label="协议号"
|
|
|
+ min-width="140"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">{{ row.protocolNo || '-' }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ prop="sampleCode"
|
|
|
+ label="样本编码"
|
|
|
+ min-width="120"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">{{ row.sampleCode || '-' }}</template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column
|
|
|
prop="motherName"
|
|
|
label="客户姓名"
|
|
|
@@ -263,22 +276,17 @@
|
|
|
<template #default="{ row }">{{ maskIdCard(row.motherIdCard) }}</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
- prop="newbornName"
|
|
|
- label="新生儿姓名"
|
|
|
- min-width="110"
|
|
|
- align="center"
|
|
|
- header-align="center"
|
|
|
- >
|
|
|
- <template #default="{ row }">{{ row.newbornName || '-' }}</template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- prop="newbornIdCard"
|
|
|
- label="新生儿身份证号"
|
|
|
- min-width="170"
|
|
|
+ prop="source"
|
|
|
+ label="来源"
|
|
|
+ min-width="100"
|
|
|
align="center"
|
|
|
header-align="center"
|
|
|
>
|
|
|
- <template #default="{ row }">{{ maskIdCard(row.newbornIdCard) }}</template>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag size="small" :type="row.source === 'presign' ? 'warning' : 'primary'">
|
|
|
+ {{ row.source === 'presign' ? '预签约' : '正式' }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
prop="protocolStatus"
|
|
|
@@ -291,7 +299,12 @@
|
|
|
<el-tag
|
|
|
:type="protocolStatusTagType(String(row.protocolStatus || ''))"
|
|
|
size="small"
|
|
|
- >{{ protocolStatusDisplayLabel(String(row.protocolStatus || ''), String(row.voidType || '')) }}</el-tag
|
|
|
+ >{{
|
|
|
+ protocolStatusDisplayLabel(
|
|
|
+ String(row.protocolStatus || ''),
|
|
|
+ String(row.voidType || '')
|
|
|
+ )
|
|
|
+ }}</el-tag
|
|
|
>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
@@ -378,9 +391,10 @@
|
|
|
label="确认时间"
|
|
|
min-width="170"
|
|
|
align="center"
|
|
|
- header-align="center">
|
|
|
- <template #default="{ row }">{{ formatDisplayOrDash(row.updateTime) }}</template>
|
|
|
- </el-table-column>
|
|
|
+ header-align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">{{ formatDisplayOrDash(row.updateTime) }}</template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column
|
|
|
prop="financeRemark"
|
|
|
label="财务备注"
|
|
|
@@ -457,11 +471,7 @@
|
|
|
<el-icon><Close /></el-icon>
|
|
|
取消
|
|
|
</el-button>
|
|
|
- <el-button
|
|
|
- :loading="rejectLoading"
|
|
|
- :disabled="submitLoading"
|
|
|
- @click="submitReject"
|
|
|
- >
|
|
|
+ <el-button :loading="rejectLoading" :disabled="submitLoading" @click="submitReject">
|
|
|
<el-icon><RefreshLeft /></el-icon>
|
|
|
退回
|
|
|
</el-button>
|
|
|
@@ -503,7 +513,6 @@
|
|
|
</el-dialog>
|
|
|
</div>
|
|
|
|
|
|
- <RefundConfirmTab v-if="mainTab === 'refund'" @action-done="loadTabPendingCounts" />
|
|
|
<InvoiceRequestTab v-if="mainTab === 'invoice'" @action-done="loadTabPendingCounts" />
|
|
|
</section>
|
|
|
</div>
|
|
|
@@ -514,14 +523,13 @@
|
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
import { Close, Check, RefreshLeft, Search, View } from '@element-plus/icons-vue'
|
|
|
+ import { fetchProtocolInvoicePendingCount } from '@/api/collection-protocol'
|
|
|
import {
|
|
|
- fetchReceiptConfirmList,
|
|
|
- fetchReceiptConfirmedList,
|
|
|
- fetchReceiptConfirmSubmit,
|
|
|
- fetchReceiptConfirmReject,
|
|
|
- fetchRefundConfirmList,
|
|
|
- fetchProtocolInvoicePendingCount
|
|
|
- } from '@/api/collection-protocol'
|
|
|
+ fetchPaymentTransferReceiptConfirmList,
|
|
|
+ fetchPaymentTransferReceiptConfirmedList,
|
|
|
+ fetchConfirmPaymentTransfer,
|
|
|
+ fetchRejectPaymentTransfer
|
|
|
+ } from '@/api/protocol-sample-payment'
|
|
|
import ProtocolFinanceConfirmFields from '@/components/business/protocol-finance-confirm-fields/index.vue'
|
|
|
import ClinicalPaymentConfirmTimeline from '@/components/business/clinical-payment-confirm-timeline/index.vue'
|
|
|
import {
|
|
|
@@ -533,14 +541,12 @@
|
|
|
import {
|
|
|
formatPaymentDueDate,
|
|
|
payModeLabel,
|
|
|
- protocolStatusLabel,
|
|
|
protocolStatusDisplayLabel,
|
|
|
protocolStatusTagType,
|
|
|
loadTransferTypeDict,
|
|
|
transferTypeLabel
|
|
|
} from '@/utils/protocol-payment-labels'
|
|
|
import { formatMoneyDisplay } from '@/utils/money-format'
|
|
|
- import RefundConfirmTab from './RefundConfirmTab.vue'
|
|
|
import InvoiceRequestTab from './InvoiceRequestTab.vue'
|
|
|
|
|
|
defineOptions({ name: 'CellStoragePaymentConfirm' })
|
|
|
@@ -548,14 +554,12 @@
|
|
|
const route = useRoute()
|
|
|
const mainTab = ref('payment')
|
|
|
const paymentPendingBadge = ref(0)
|
|
|
- const refundPendingBadge = ref(0)
|
|
|
const invoicePendingBadge = ref(0)
|
|
|
|
|
|
function formatTabBadgeCount(count: number): string {
|
|
|
return count > 99 ? '99+' : String(count)
|
|
|
}
|
|
|
|
|
|
-
|
|
|
function formatPaymentAmount(v: unknown): string {
|
|
|
if (v == null || v === '') return '-'
|
|
|
return '¥' + formatMoneyDisplay(v)
|
|
|
@@ -591,12 +595,6 @@
|
|
|
return minioBaseUrl ? `${minioBaseUrl}/${url.replace(/^\//, '')}` : url
|
|
|
}
|
|
|
|
|
|
- function handleAttachmentPreview(file: Record<string, unknown>) {
|
|
|
- const url = String(file.fileUrl || '')
|
|
|
- if (!url) return
|
|
|
- window.open(fullFileUrl(url), '_blank')
|
|
|
- }
|
|
|
-
|
|
|
function handleAttachmentDownload(file: Record<string, unknown>) {
|
|
|
downloadAttachmentFile(file, { fullFileUrl })
|
|
|
}
|
|
|
@@ -623,13 +621,11 @@
|
|
|
|
|
|
async function loadTabPendingCounts() {
|
|
|
try {
|
|
|
- const [paymentRes, refundRes, invRes] = await Promise.all([
|
|
|
- fetchReceiptConfirmList({ page: 1, pageSize: 1 }),
|
|
|
- fetchRefundConfirmList({ page: 1, pageSize: 1 }),
|
|
|
+ const [paymentRes, invRes] = await Promise.all([
|
|
|
+ fetchPaymentTransferReceiptConfirmList({ page: 1, pageSize: 1 }),
|
|
|
fetchProtocolInvoicePendingCount()
|
|
|
])
|
|
|
paymentPendingBadge.value = paymentRes.total ?? 0
|
|
|
- refundPendingBadge.value = refundRes.total ?? 0
|
|
|
invoicePendingBadge.value = Number(invRes?.count ?? 0)
|
|
|
} catch {
|
|
|
// 角标加载失败时保留上次数值,避免干扰主流程
|
|
|
@@ -639,7 +635,7 @@
|
|
|
async function loadPending() {
|
|
|
pendingLoading.value = true
|
|
|
try {
|
|
|
- const res = await fetchReceiptConfirmList(buildPendingParams())
|
|
|
+ const res = await fetchPaymentTransferReceiptConfirmList(buildPendingParams())
|
|
|
pendingData.value = res.list || []
|
|
|
pendingPagination.total = res.total ?? 0
|
|
|
} finally {
|
|
|
@@ -650,7 +646,7 @@
|
|
|
async function loadConfirmed() {
|
|
|
confirmedLoading.value = true
|
|
|
try {
|
|
|
- const res = await fetchReceiptConfirmedList(buildConfirmedParams())
|
|
|
+ const res = await fetchPaymentTransferReceiptConfirmedList(buildConfirmedParams())
|
|
|
confirmedData.value = res.list || []
|
|
|
confirmedPagination.total = res.total ?? 0
|
|
|
} finally {
|
|
|
@@ -707,7 +703,7 @@
|
|
|
}
|
|
|
submitLoading.value = true
|
|
|
try {
|
|
|
- await fetchReceiptConfirmSubmit(currentDetailId.value, {
|
|
|
+ await fetchConfirmPaymentTransfer(currentDetailId.value, {
|
|
|
financeConfirmAttachments: financeAttachmentsToUrlString(attachments.value) || undefined,
|
|
|
financeRemark: financeRemark.value.trim() || undefined
|
|
|
})
|
|
|
@@ -730,7 +726,7 @@
|
|
|
}
|
|
|
rejectLoading.value = true
|
|
|
try {
|
|
|
- await fetchReceiptConfirmReject(currentDetailId.value)
|
|
|
+ await fetchRejectPaymentTransfer(currentDetailId.value)
|
|
|
dialogVisible.value = false
|
|
|
await loadAll()
|
|
|
await loadTabPendingCounts()
|
|
|
@@ -760,10 +756,10 @@
|
|
|
onMounted(async () => {
|
|
|
await loadTransferTypeDict()
|
|
|
const tab = route.query.tab
|
|
|
- if (tab === 'refund') {
|
|
|
- mainTab.value = 'refund'
|
|
|
- } else if (tab === 'invoice') {
|
|
|
+ if (tab === 'invoice') {
|
|
|
mainTab.value = 'invoice'
|
|
|
+ } else {
|
|
|
+ mainTab.value = 'payment'
|
|
|
}
|
|
|
loadTabPendingCounts()
|
|
|
if (mainTab.value === 'payment') {
|