This commit is contained in:
2026-08-12 17:29:35 +08:00
parent 16c5ed6301
commit d2a246b122
25 changed files with 238 additions and 69 deletions
@@ -65,7 +65,7 @@ const canSettleSource = computed(() => access.can('platform:finance:fee-source:s
const stateError = computed(() => customersError.value || loadError.value)
const activeCustomers = computed(() => customers.value.filter((item) => item.status === 'ACTIVE'))
const queryFields = computed<QueryField[]>(() => [
{ key: 'customerId', type: 'select', label: '客户', width: 260, placeholder: '请选择客户', props: { 'aria-label': '客户', filterable: true, loading: customersLoading.value }, options: activeCustomers.value.map((item) => ({ label: item.tenantName, value: String(item.id) })) },
{ key: 'customerId', type: 'select', label: '客户', width: 260, placeholder: '全部客户', props: { 'aria-label': '客户', filterable: true, clearable: true, loading: customersLoading.value }, options: activeCustomers.value.map((item) => ({ label: item.tenantName, value: String(item.id) })) },
{ key: 'direction', type: 'select', label: '收付方向', width: 140, placeholder: '全部', options: [{ label: '应收', value: 'RECEIVABLE' }, { label: '应付', value: 'PAYABLE' }] },
{ key: 'status', type: 'select', label: '状态', width: 150, placeholder: '全部状态', options: financeArapStatusOptions },
{ key: 'keyword', type: 'input', label: '关键词', width: 220, placeholder: '单号/费用/来源ID', props: { 'aria-label': '关键词' } },
@@ -90,13 +90,12 @@ async function loadCustomers() {
}
async function load(model: QueryModel = filters.value) {
Object.assign(filters.value, model); page.value = 1; allRows.value = []; loadError.value = null
const customerId = String(filters.value.customerId || ''); if (!customerId) return
const customerName = customers.value.find((item) => String(item.id) === customerId)?.tenantName || `客户 ${customerId}`
const customerId = String(filters.value.customerId || '').trim()
loading.value = true
try {
const direction = String(filters.value.direction || '') as 'RECEIVABLE' | 'PAYABLE' | ''
const items = await listFinanceFeePool(customerId, direction || undefined)
allRows.value = items.map((item): ArapRow => ({ id: item.poolItemId, feeSourceId: item.feeSourceId, customerName, direction: item.direction, documentNo: item.poolItemId, sourceType: item.sourceType, sourceId: [item.inboundId ? `入库单 ${item.inboundId}` : '', item.orderId ? `订单 ${item.orderId}` : '', item.containerId ? `柜次 ${item.containerId}` : '', `来源 ${item.sourceId}/v${item.sourceVersion}`].filter(Boolean).join(' · '), orderId: item.orderId || '', inboundId: item.inboundId || '', containerId: item.containerId || '', feeName: item.feeItemName, amount: item.amount, status: item.status, occurredAt: item.createdAt }))
const items = await listFinanceFeePool(customerId || undefined, direction || undefined)
allRows.value = items.map((item): ArapRow => ({ id: item.poolItemId, feeSourceId: item.feeSourceId, customerName: customers.value.find((customer) => String(customer.id) === item.customerId)?.tenantName || `客户 ${item.customerId}`, direction: item.direction, documentNo: item.poolItemId, sourceType: item.sourceType, sourceId: [item.inboundId ? `入库单 ${item.inboundId}` : '', item.orderId ? `订单 ${item.orderId}` : '', item.containerId ? `柜次 ${item.containerId}` : '', `来源 ${item.sourceId}/v${item.sourceVersion}`].filter(Boolean).join(' · '), orderId: item.orderId || '', inboundId: item.inboundId || '', containerId: item.containerId || '', feeName: item.feeItemName, amount: item.amount, status: item.status, occurredAt: item.createdAt }))
} catch (error) { loadError.value = getApiErrorDetails(error, '客户应收应付加载失败,请重试') }
finally { loading.value = false }
}
@@ -146,7 +145,7 @@ async function submitInclusion() {
function statusLabel(status: string) { return financeStatusLabel(status) }
function money(value: unknown) { return Number(value || 0).toFixed(2) }
onMounted(() => void loadCustomers())
onMounted(async () => { await loadCustomers(); await load() })
</script>
<template>
@@ -155,7 +154,8 @@ onMounted(() => void loadCustomers())
<ListPageLayout v-else aria-label="客户应收应付">
<template #toolbar><QueryToolbar v-model="filters" class="surface-panel" ariaLabel="客户应收应付筛选" :fields="queryFields" preference-key="finance-customer-arap-query" @search="load" /></template>
<template v-if="stateError" #state><LoadErrorState title="客户应收应付加载失败" :message="stateError.message" :loading="customersLoading || loading" @retry="customersError ? loadCustomers() : load()"><template #details><ApiErrorMeta :details="stateError" /></template></LoadErrorState></template>
<section v-if="!customersError && !loadError" class="surface-panel table-panel"><DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :loading="loading" :total="filteredRows.length" preference-key="finance-customer-arap-table" aria-label="客户应收应付列表" row-key="id" empty-text="请选择客户查询应收应付">
<section v-if="!customersError && !loadError" class="surface-panel table-panel">
<DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :loading="loading" :total="filteredRows.length" preference-key="finance-customer-arap-table" aria-label="客户应收应付列表" row-key="id" empty-text="暂无客户应收应付数据">
<template #actions="{ row }"><div class="row-actions"><template v-if="row.feeSourceId"><el-button v-if="canViewSource" link type="primary" @click="openDetail(row)"><Eye :size="15" />详情</el-button><el-button v-if="canReviewSource" link type="primary" @click="openReview(row)"><FileCheck2 :size="15" />审核</el-button><el-button v-if="canSettleSource" link type="primary" @click="openInclusion(row)"><Link2 :size="15" />结算</el-button></template><span v-else class="muted-action">手工成本</span></div></template>
<template #direction="{ row }"><el-tag :type="row.direction === 'RECEIVABLE' ? 'success' : row.direction === 'PAYABLE' ? 'warning' : 'info'">{{ financeDirectionLabel(row.direction) }}</el-tag></template>
<template #status="{ row }"><el-tag :type="row.status === 'PAID' ? 'success' : row.status === 'VOIDED' ? 'info' : 'warning'">{{ statusLabel(row.status) }}</el-tag></template>