恢复账单明细入口并完善采购状态展示

This commit is contained in:
2026-10-30 18:50:56 +08:00
parent 119b4d6d66
commit 63193d04de
6 changed files with 52 additions and 12 deletions
@@ -55,12 +55,18 @@ test('adapts the Finance Java DTO contract and filters nested receipt allocation
assert.doesNotMatch(adapterSource, /bill_no|customer_name|bill_date|total_amount|outstanding_amount|receipt_no|bill_id|applied_amount/)
assert.doesNotMatch(adapterSource, /receipt\.billId|receipt\.appliedAmount/)
assert.doesNotMatch(adapterSource, /voucherNo|voucher_no/)
assert.match(viewSource, /name: 'finance-bill-detail', params: \{ billNo: row\.billNo \}/)
assert.doesNotMatch(viewSource, /key: 'detail'|label: '查看'/)
assert.match(detailViewSource, /getMerchantFinanceBill\(summary\.id\)/)
assert.match(detailViewSource, /getMerchantFinanceReceipts\(summary\.id\)/)
assert.doesNotMatch(detailViewSource, /getMerchantFinanceBill\(billNo\.value\)/)
})
test('keeps bill numbers linked to business-number details independently of confirmation actions', () => {
assert.match(viewSource, /label: '账单编号',\s*prop: 'billNo',\s*slotName: 'billNo'/)
assert.match(viewSource, /<template #billNo="\{ row \}">\s*<RouterLink[^>]*:to="\{ name: 'finance-bill-detail', params: \{ billNo: row\.billNo \} \}"[^>]*>\{\{ row\.billNo \}\}<\/RouterLink>\s*<\/template>/)
assert.doesNotMatch(viewSource.match(/<template #billNo[^]*?<\/template>/)?.[0] || '', /canConfirm|confirmationStatus|row\.id/)
})
test('does not expose draft or voided bills returned by the server', () => {
const bill = (id, status) => ({
id,
@@ -2,7 +2,7 @@
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { RefreshCcw } from '@lucide/vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRouter } from 'vue-router'
import { RouterLink } from 'vue-router'
import { ApiError } from '@/api/http'
import QueryToolbar, { type QueryField, type QueryModel } from '@/components/common/QueryToolbar.vue'
import DataTable, { type DataTableColumn } from '@/components/common/DataTable.vue'
@@ -13,7 +13,6 @@ import type { FinanceBillQuery, FinanceBillStatus, FinanceBillSummary, FinanceCu
const loading = ref(false)
const auth = useAuthStore()
const router = useRouter()
const errorMessage = ref('')
const bills = ref<FinanceBillSummary[]>([])
const confirmingBillId = ref('')
@@ -38,7 +37,7 @@ const queryFields: QueryField[] = [
]
const tableColumns: DataTableColumn[] = [
{ label: '操作', slotName: 'actions', width: 190, fixed: 'left' },
{ label: '账单编号', prop: 'billNo', minWidth: 160 },
{ label: '账单编号', prop: 'billNo', slotName: 'billNo', minWidth: 160 },
{ label: '出账日期', slotName: 'issueDate', width: 120 },
{ label: '到期日', slotName: 'dueDate', width: 120 },
{ label: '账单金额', slotName: 'totalAmount', width: 145, align: 'right' },
@@ -104,11 +103,9 @@ async function loadBills(nextPage = page.value) {
}
}
function openDetail(row: FinanceBillSummary) { void router.push({ name: 'finance-bill-detail', params: { billNo: row.billNo } }) }
function rowActions(row: object): TableAction[] {
const statement = row as FinanceBillSummary
const actions: TableAction[] = [{ key: 'detail', label: '查看', run: () => openDetail(statement) }]
const actions: TableAction[] = []
if (statement.customerConfirmationStatus === 'PENDING_CONFIRMATION' && canConfirm.value) {
actions.push({
key: 'confirm',
@@ -181,6 +178,7 @@ onMounted(() => { void loadBills(1) })
<section class="content-card">
<DataTable v-model:page="page" v-model:page-size="pageSize" :data="bills" :columns="tableColumns" :loading="loading" :total="total" :page-sizes="[20, 50, 100]" :row-actions="rowActions" row-key="billNo" empty-text="暂无账单">
<template v-if="errorMessage" #error><div class="state-panel state-panel--error" role="alert"><p>{{ errorMessage }}</p><el-button @click="loadBills(1)"><RefreshCcw :size="15" />重试</el-button></div></template>
<template #billNo="{ row }"><RouterLink class="bill-number-link" :to="{ name: 'finance-bill-detail', params: { billNo: row.billNo } }">{{ row.billNo }}</RouterLink></template>
<template #issueDate="{ row }">{{ formatDate(row.issueDate) }}</template>
<template #dueDate="{ row }">{{ formatDate(row.dueDate) }}</template>
<template #totalAmount="{ row }">¥ {{ formatAmount(row.totalAmount) }}</template>
@@ -196,6 +194,8 @@ onMounted(() => { void loadBills(1) })
<style scoped>
.finance-bills-page { display: flex; flex-direction: column; gap: 12px; }
.bill-number-link { color: var(--primary); text-decoration: none; }
.bill-number-link:hover { text-decoration: underline; }
.finance-summary { display: flex; flex-wrap: wrap; gap: 8px 26px; color: var(--muted); font-size: 13px; }.finance-summary strong { margin-left: 6px; color: var(--navy); font-size: 18px; }.amount-warning, .amount-warning strong { color: #b45309; }
.content-card { min-width: 0; overflow: hidden; border: 1px solid var(--client-border); border-radius: var(--client-radius); background: var(--surface, #fff); }
.state-panel { display: flex; min-height: 180px; align-items: center; justify-content: center; gap: 12px; flex-direction: column; color: var(--muted); text-align: center; }.state-panel p { margin: 0; }.state-panel--error { color: #b42318; background: #fff8f7; border: 1px solid #f5c2bd; border-radius: 6px; }