This commit is contained in:
2026-08-19 09:14:35 +08:00
parent c188482c24
commit 80cfca5056
36 changed files with 854 additions and 1044 deletions
@@ -48,6 +48,8 @@ const filters = ref<QueryModel>({
settled: '', lastPaymentRange: [], createdRange: [],
})
const rows = ref<StatementRow[]>([])
const page = ref(1)
const pageSize = ref(20)
const loading = ref(false)
const error = ref<ApiErrorDetails | null>(null)
const customerError = ref<ApiErrorDetails | null>(null)
@@ -103,6 +105,7 @@ const fields = computed<QueryField[]>(() => [
const columns: DataTableColumn[] = [
{ key: 'actions', label: '操作', width: 280, fixed: 'left', slotName: 'actions' },
{ key: 'status', label: '审核状态', width: 120, slotName: 'status' },
{ key: 'customerConfirmationStatus', label: '客户确认', width: 130, slotName: 'customerConfirmationStatus' },
{ key: 'billNo', label: '对账单号', minWidth: 180 },
{ key: 'customerName', label: '客户', minWidth: 180, slotName: 'customerName' },
{ key: 'periodStart', label: '结算起始日', width: 130 },
@@ -124,6 +127,8 @@ const columns: DataTableColumn[] = [
{ key: 'submittedAt', label: '提交时间', minWidth: 170, slotName: 'submittedAt' },
{ key: 'reviewedAt', label: '审核时间', minWidth: 170, slotName: 'reviewedAt' },
{ key: 'issuedAt', label: '出账时间', minWidth: 170, slotName: 'issuedAt' },
{ key: 'customerConfirmedByName', label: '客户确认人', width: 140, slotName: 'customerConfirmedByName' },
{ key: 'customerConfirmedAt', label: '客户确认时间', minWidth: 170, slotName: 'customerConfirmedAt' },
{ key: 'updatedByName', label: '更新人', width: 130, slotName: 'updatedByName' },
{ key: 'updatedAt', label: '更新时间', minWidth: 170, slotName: 'updatedAt' },
]
@@ -215,6 +220,10 @@ const filteredRows = computed(() => rows.value.filter((row) => {
&& inDateRange(row.lastPaymentAt, 'lastPaymentRange')
&& inDateRange(row.createdAt || '', 'createdRange')
}))
const paginatedRows = computed(() => {
const start = (page.value - 1) * pageSize.value
return filteredRows.value.slice(start, start + pageSize.value)
})
async function loadCustomers() {
if (!canListCustomers.value) return
@@ -230,7 +239,10 @@ async function loadCustomers() {
async function load(model?: QueryModel) {
const hydrateDetails = model !== undefined
if (model) filters.value = { ...model }
if (model) {
filters.value = { ...model }
page.value = 1
}
rows.value = []
selectedId.value = ''
detail.value = null
@@ -462,6 +474,9 @@ watch(detailRouteId, (statementId) => {
<div class="statement-summary-item"><span>提交时间</span><strong>{{ formatDateTime(revisionTime(['SUBMIT'])) }}</strong></div>
<div class="statement-summary-item"><span>审核时间</span><strong>{{ formatDateTime(revisionTime(['APPROVE', 'REJECT'])) }}</strong></div>
<div class="statement-summary-item"><span>出账时间</span><strong>{{ formatDateTime(revisionTime(['ISSUE'])) }}</strong></div>
<div class="statement-summary-item"><span>客户确认状态</span><strong>{{ financeStatusLabel(detail.customerConfirmationStatus || 'NOT_REQUIRED') }}</strong></div>
<div class="statement-summary-item"><span>客户确认人</span><strong>{{ operatorDisplayName(detail.customerConfirmedByName) }}</strong></div>
<div class="statement-summary-item"><span>客户确认时间</span><strong>{{ formatDateTime(detail.customerConfirmedAt) }}</strong></div>
<div class="statement-summary-item"><span>更新人</span><strong>{{ operatorDisplayName(detail.updatedByName) }}</strong></div>
<div class="statement-summary-item"><span>更新时间</span><strong>{{ formatDateTime(detail.updatedAt) }}</strong></div>
<div class="statement-summary-item statement-summary-item--remark"><span>备注</span><strong>{{ detail.remark || '—' }}</strong></div>
@@ -512,7 +527,7 @@ watch(detailRouteId, (statementId) => {
<template v-if="customerError || error" #state><LoadErrorState title="客户对账单加载失败" :message="(customerError || error)?.message || ''" :loading="loading" @retry="customerError ? loadCustomers() : load()"><template #details><ApiErrorMeta :details="(customerError || error)!" /></template></LoadErrorState></template>
<template v-if="!customerError && !error">
<section class="surface-panel table-panel">
<DataTable :data="filteredRows" :columns="columns" :loading="loading" aria-label="客户对账单列表" row-key="id" empty-text="暂无客户对账单" preference-key="finance-customer-statements" @row-click="openDetail">
<DataTable v-model:page="page" v-model:page-size="pageSize" :data="paginatedRows" :columns="columns" :loading="loading" :total="filteredRows.length" aria-label="客户对账单列表" row-key="id" empty-text="暂无客户对账单" preference-key="finance-customer-statements" @row-click="openDetail">
<template #toolbar-actions>
<el-button v-if="canExport" :loading="exportBusy" :disabled="loading || exportBusy" @click="exportStatements"><Download :size="15" />导出</el-button>
<el-button v-if="canCreate" type="primary" :disabled="!canGenerate" :title="canGenerate ? '生成对账单' : '缺少客户列表权限,无法选择客户'" @click="openCreate"><Plus :size="15" />生成对账单</el-button>
@@ -533,6 +548,7 @@ watch(detailRouteId, (statementId) => {
<el-button v-if="['DRAFT','APPROVED','ISSUED'].includes(String(row.status)) && canVoid" size="small" plain type="danger" :loading="actionBusy" @click.stop="performAction(row as FinanceStatementReadModel, 'VOID')"><XCircle :size="15" />作废</el-button>
</template>
<template #status="{ row }"><el-tag :type="financeStatusTone(row.status)">{{ financeStatusLabel(row.status) }}</el-tag></template>
<template #customerConfirmationStatus="{ row }"><el-tag :type="financeStatusTone(row.customerConfirmationStatus || 'NOT_REQUIRED')">{{ financeStatusLabel(row.customerConfirmationStatus || 'NOT_REQUIRED') }}</el-tag></template>
<template #customerName="{ row }">{{ customerDisplayName(row.customerId, row.customerName) }}</template>
<template #lastPaymentAt="{ row }">{{ formatDateTime(row.lastPaymentAt) }}</template>
<template #settled="{ row }"><el-tag v-if="row.settled !== null" :type="row.settled ? 'success' : 'warning'">{{ row.settled ? '是' : '否' }}</el-tag><span v-else>—</span></template>
@@ -541,6 +557,8 @@ watch(detailRouteId, (statementId) => {
<template #submittedAt="{ row }">{{ formatDateTime(row.submittedAt) }}</template>
<template #reviewedAt="{ row }">{{ formatDateTime(row.reviewedAt) }}</template>
<template #issuedAt="{ row }">{{ formatDateTime(row.issuedAt) }}</template>
<template #customerConfirmedByName="{ row }">{{ row.customerConfirmationStatus === 'CONFIRMED' ? operatorDisplayName(row.customerConfirmedByName) : '—' }}</template>
<template #customerConfirmedAt="{ row }">{{ formatDateTime(row.customerConfirmedAt) }}</template>
<template #updatedByName="{ row }">{{ operatorDisplayName(row.updatedByName) }}</template>
<template #updatedAt="{ row }">{{ formatDateTime(row.updatedAt) }}</template>
<template #pagination-left>共 {{ filteredRows.length }} 条 · 币种:CNY</template>