From 6d10251161b127d8e86e83ccc916053f80fd778d Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Wed, 2 Sep 2026 20:12:43 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E8=B4=A6=E5=8D=95=E6=94=B6=E6=AC=BE=E6=96=B9=E5=BC=8F=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/finance/views/FinanceBillsView.test.mjs | 2 ++ src/modules/finance/views/FinanceBillsView.vue | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/modules/finance/views/FinanceBillsView.test.mjs b/src/modules/finance/views/FinanceBillsView.test.mjs index 7ad3278..5437514 100644 --- a/src/modules/finance/views/FinanceBillsView.test.mjs +++ b/src/modules/finance/views/FinanceBillsView.test.mjs @@ -120,6 +120,8 @@ test('keeps actions first and exposes list, balance, detail, confirmation, recei for (const expected of ['未收余额', '账单详情', '确认账单', '客户确认信息', '收款记录', '暂无账单', '暂无收款记录', 'state-panel--error']) { assert.match(viewSource, new RegExp(expected)) } + assert.match(viewSource, /BANK_TRANSFER: '银行转账'/) + assert.match(viewSource, /paymentMethodLabel\(row\.method\)/) assert.match(viewSource, /auth\.hasPermission\('finance:bill:confirm'\)/) assert.match(viewSource, /row\.customerConfirmationStatus === 'PENDING_CONFIRMATION' && canConfirm/) assert.match(viewSource, /size="small" type="success" plain/) diff --git a/src/modules/finance/views/FinanceBillsView.vue b/src/modules/finance/views/FinanceBillsView.vue index 87be647..95fd113 100644 --- a/src/modules/finance/views/FinanceBillsView.vue +++ b/src/modules/finance/views/FinanceBillsView.vue @@ -49,6 +49,11 @@ function formatDateTime(value: string | null | undefined) { return value ? value.replace('T', ' ').replace(/Z$/, '').slice(0, 16) : '-' } +function paymentMethodLabel(method: string | null | undefined) { + if (!method) return '—' + return ({ BANK_TRANSFER: '银行转账', CASH: '现金', OTHER: '其他' })[method] ?? '其他' +} + function statusLabel(status: FinanceBillStatus) { return ({ DRAFT: '草稿', ISSUED: '已出账', PARTIALLY_PAID: '部分收款', PAID: '已收清', VOIDED: '作废' })[status] ?? status } @@ -207,7 +212,7 @@ onMounted(() => { void loadBills(1) })

{{ detail.billNo }}

出账 {{ formatDate(detail.issueDate) }} · 到期 {{ formatDate(detail.dueDate) }} · 未收 ¥ {{ formatAmount(detail.outstandingAmount) }}

{{ statusLabel(detail.status) }}{{ confirmationLabel(detail.customerConfirmationStatus) }}
{{ confirmationLabel(detail.customerConfirmationStatus) }}

{{ detail.customerConfirmedByName || '当前企业成员' }} · {{ formatDateTime(detail.customerConfirmedAt) }}

请核对本期金额和费用明细,确认后将记录当前登录成员与确认时间。

确认账单

费用明细

-

收款记录

暂无收款记录
+

收款记录

暂无收款记录

如对账单内容有疑问,请先线下联系平台财务,核对无误后再确认。

From 12424281c79c8b0e93eec8b59665db55bd00a542 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Wed, 2 Sep 2026 20:25:45 +0800 Subject: [PATCH 2/2] feat(finance): link bill lines to inbound details --- src/modules/finance/api/adapters.ts | 2 ++ src/modules/finance/contracts.ts | 1 + src/modules/finance/views/FinanceBillsView.test.mjs | 8 ++++++-- src/modules/finance/views/FinanceBillsView.vue | 13 ++++++++++++- src/modules/first-leg/public.ts | 1 + 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/modules/finance/api/adapters.ts b/src/modules/finance/api/adapters.ts index 33ea5c8..10aaa1a 100644 --- a/src/modules/finance/api/adapters.ts +++ b/src/modules/finance/api/adapters.ts @@ -34,6 +34,7 @@ export interface FinanceBillLineWire { sourceVersion: number orderId: WireScalar | null inboundId: WireScalar | null + inboundCode: string | null feeItemCode: string feeItemName: string amount: WireScalar @@ -89,6 +90,7 @@ function mapBillLine(line: FinanceBillLineWire): FinanceBillLine { return { id: text(line.id), orderId: line.orderId == null ? null : text(line.orderId), + inboundCode: line.inboundCode?.trim() || null, feeNo: `${line.sourceType}:${text(line.sourceId)}/v${line.sourceVersion}`, feeName: line.feeItemName, amount: text(line.amount), diff --git a/src/modules/finance/contracts.ts b/src/modules/finance/contracts.ts index 0eaafac..142ac2f 100644 --- a/src/modules/finance/contracts.ts +++ b/src/modules/finance/contracts.ts @@ -39,6 +39,7 @@ export interface FinanceCustomerConfirmationResult { export interface FinanceBillLine { id: string orderId: string | null + inboundCode: string | null feeNo: string | null feeName: string amount: string diff --git a/src/modules/finance/views/FinanceBillsView.test.mjs b/src/modules/finance/views/FinanceBillsView.test.mjs index 5437514..43818db 100644 --- a/src/modules/finance/views/FinanceBillsView.test.mjs +++ b/src/modules/finance/views/FinanceBillsView.test.mjs @@ -92,7 +92,7 @@ test('maps nested bill detail and customer-safe receipt allocations', () => { receivedAmount: '40.00', outstandingAmount: '60.00', version: 3, customerConfirmationStatus: 'PENDING_CONFIRMATION', customerConfirmedByName: null, customerConfirmedAt: null, }, - lines: [{ id: 21, sourceType: 'INBOUND_FEE', sourceId: 81, sourceVersion: 3, orderId: 31, inboundId: 41, feeItemCode: 'FREIGHT', feeItemName: '运费', amount: '100.00', currency: 'CNY' }], + lines: [{ id: 21, sourceType: 'INBOUND_FEE', sourceId: 81, sourceVersion: 3, orderId: 31, inboundId: 41, inboundCode: 'NYEXX2608180003', feeItemCode: 'FREIGHT', feeItemName: '运费', amount: '100.00', currency: 'CNY' }], }) const receipts = financeAdapters.mapFinanceReceipts([{ id: 51, receiptNo: 'RCPT-51', receivedAmount: '40.00', receivedAt: '2026-08-12T10:00:00', @@ -101,7 +101,7 @@ test('maps nested bill detail and customer-safe receipt allocations', () => { }], '2') assert.equal(detail.billNo, 'B-2') - assert.deepEqual(detail.lines[0], { id: '21', orderId: '31', feeNo: 'INBOUND_FEE:81/v3', feeName: '运费', amount: '100.00', currencyCode: 'CNY' }) + assert.deepEqual(detail.lines[0], { id: '21', orderId: '31', inboundCode: 'NYEXX2608180003', feeNo: 'INBOUND_FEE:81/v3', feeName: '运费', amount: '100.00', currencyCode: 'CNY' }) assert.deepEqual(receipts[0], { id: '51', receiptNo: 'RCPT-51', receivedAt: '2026-08-12T10:00:00', amount: '40.00', currencyCode: 'CNY', method: 'BANK_TRANSFER', allocatedAmount: '40.00' }) }) @@ -122,6 +122,10 @@ test('keeps actions first and exposes list, balance, detail, confirmation, recei } assert.match(viewSource, /BANK_TRANSFER: '银行转账'/) assert.match(viewSource, /paymentMethodLabel\(row\.method\)/) + assert.match(viewSource, /label="入仓码"/) + assert.match(viewSource, /openInboundAssociation\(row\.inboundCode\)/) + assert.match(viewSource, /InboundCodeAssociationDialog/) + assert.match(viewSource, /:inbound-code="inboundAssociationCode"/) assert.match(viewSource, /auth\.hasPermission\('finance:bill:confirm'\)/) assert.match(viewSource, /row\.customerConfirmationStatus === 'PENDING_CONFIRMATION' && canConfirm/) assert.match(viewSource, /size="small" type="success" plain/) diff --git a/src/modules/finance/views/FinanceBillsView.vue b/src/modules/finance/views/FinanceBillsView.vue index 95fd113..d4f46df 100644 --- a/src/modules/finance/views/FinanceBillsView.vue +++ b/src/modules/finance/views/FinanceBillsView.vue @@ -4,6 +4,7 @@ import { CircleDollarSign, Eye, RefreshCcw, Search } from '@lucide/vue' import { ElMessage, ElMessageBox } from 'element-plus' import { ApiError } from '@/api/http' import { useAuthStore } from '@/modules/auth/public' +import { InboundCodeAssociationDialog } from '@/modules/first-leg/public' import { confirmMerchantFinanceStatement, getMerchantFinanceBill, getMerchantFinanceBills, getMerchantFinanceReceipts } from '../api/finance' import type { FinanceBillDetail, FinanceBillQuery, FinanceBillStatus, FinanceBillSummary, FinanceCustomerConfirmationStatus } from '../contracts' @@ -16,6 +17,8 @@ const bills = ref([]) const detail = ref(null) const selectedBillId = ref('') const detailVisible = ref(false) +const inboundAssociationVisible = ref(false) +const inboundAssociationCode = ref('') const confirmingBillId = ref('') const confirmationKeys = new Map() const page = ref(1) @@ -160,6 +163,13 @@ function handlePageChange(nextPage: number) { void loadBills(nextPage) } +function openInboundAssociation(inboundCode: string | null) { + const code = inboundCode?.trim() + if (!code) return + inboundAssociationCode.value = code + inboundAssociationVisible.value = true +} + onMounted(() => { void loadBills(1) }) @@ -211,12 +221,13 @@ onMounted(() => { void loadBills(1) }) + diff --git a/src/modules/first-leg/public.ts b/src/modules/first-leg/public.ts index a7a171b..50e9e80 100644 --- a/src/modules/first-leg/public.ts +++ b/src/modules/first-leg/public.ts @@ -1,2 +1,3 @@ export { useFirstLegOrdersStore } from './store/firstLegOrders' export { getFirstLegStatusLabel, getFirstLegStatusTone } from './utils/firstLegOrder' +export { default as InboundCodeAssociationDialog } from './components/InboundCodeAssociationDialog.vue'