feat(web-admin): finance confirm by transfer and remove refund confirm tab
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
4e71a13165
commit
c404c168fe
7 files changed
+133
-81
No files matched your search
@@ -52,6 +52,8 @@ export function fetchPaymentTransferReceiptConfirmList(params?: {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
keyword?: string
|
||||
installmentDueDateStart?: string
|
||||
installmentDueDateEnd?: string
|
||||
}) {
|
||||
return request.get<PageList<Record<string, unknown>>>({
|
||||
url: '/web/admin/payment-transfers/receipt-confirm',
|
||||
@@ -63,6 +65,8 @@ export function fetchPaymentTransferReceiptConfirmedList(params?: {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
keyword?: string
|
||||
installmentDueDateStart?: string
|
||||
installmentDueDateEnd?: string
|
||||
}) {
|
||||
return request.get<PageList<Record<string, unknown>>>({
|
||||
url: '/web/admin/payment-transfers/receipt-confirmed',
|
||||
|
||||
@@ -89,7 +89,7 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
path: 'payment-confirm',
|
||||
component: '/cell-storage/payment-confirm/index',
|
||||
meta: {
|
||||
title: '缴退费财务确认及开票',
|
||||
title: '缴费财务确认及开票',
|
||||
keepAlive: true,
|
||||
menuCode: 'biz:cellStoragePaymentConfirm:list'
|
||||
}
|
||||
@@ -290,6 +290,7 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
meta: {
|
||||
title: '保险公司及险种价格',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'basic-info:insurance-company:list'
|
||||
}
|
||||
},
|
||||
@@ -398,6 +399,7 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
meta: {
|
||||
title: '体检机构及项目价格',
|
||||
keepAlive: true,
|
||||
isHide: true,
|
||||
menuCode: 'pilot-service:checkup-institution:list'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- 缴退费财务确认 · 退费 Tab -->
|
||||
<!-- 已停用:按样本缴费后退费改为协议级登记,财务页不再挂载本 Tab(保留文件供旧版对照) -->
|
||||
<!-- eslint-disable vue/no-v-model-argument -->
|
||||
<template>
|
||||
<div class="refund-confirm-tab">
|
||||
|
||||
@@ -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"
|
||||
prop="source"
|
||||
label="来源"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">{{ row.newbornName || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="newbornIdCard"
|
||||
label="新生儿身份证号"
|
||||
min-width="170"
|
||||
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') {
|
||||
|
||||
Reference in new issue
Block a user