调整收付款问题

This commit is contained in:
2026-08-31 12:40:35 +08:00
parent 2451efdfcb
commit dea760ea1c
12 changed files with 544 additions and 164 deletions
+136 -85
View File
@@ -163,6 +163,7 @@
v-loading="invoiceDialog.loading"
:data="invoiceDialog.rows"
border
empty-text="暂无票据数据"
highlight-current-row
@current-change="invoiceDialog.current = $event"
@row-dblclick="confirmInvoice"
@@ -188,6 +189,17 @@
</template>
</el-table-column>
</el-table>
<div class="receipt-form-page__dialog-pagination">
<el-pagination
v-model:current-page="invoiceDialog.page.current"
v-model:page-size="invoiceDialog.page.size"
:total="invoiceDialog.page.total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@current-change="refreshInvoicePoolPage"
@size-change="handleInvoicePoolSizeChange"
/>
</div>
<template #footer>
<el-button @click="invoiceDialog.visible = false">取消</el-button>
<el-button type="primary" @click="confirmInvoice()">确定</el-button>
@@ -247,67 +259,12 @@
import { Search } from '@element-plus/icons-vue';
import { mapGetters } from 'vuex';
import * as api from '@/api/payment/invoiceReceipt';
import { getList as getCustomerList } from '@/api/vehicle/customer-archive';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
const invoicePoolMockTemplates = [
{
id: 90000001,
invoiceNo: '25312000000000000101',
invoiceDate: '2026-08-25',
invoiceType: '增值税专用发票',
taxRate: 9,
invoiceAmount: 109000,
taxAmount: 9000,
receiverName: '华东供应链管理有限公司',
issuerName: '上海安捷运输有限公司',
bankName: '中国工商银行上海分行',
bankAccount: '1001000100000000019',
issuingBank: '中国工商银行上海分行营业部',
phone: '021-66880001',
customerEmails: 'finance@huadong.example.com',
departmentEmails: 'transport@huadong.example.com',
attachmentsJson: '[]',
kingdeeBillNo: 'KD-FP-20260825001',
},
{
id: 90000002,
invoiceNo: '25312000000000000102',
invoiceDate: '2026-08-26',
invoiceType: '增值税普通发票',
taxRate: 6,
invoiceAmount: 53000,
taxAmount: 3000,
receiverName: '华东供应链管理有限公司',
issuerName: '江苏联运物流有限公司',
bankName: '中国建设银行南京分行',
bankAccount: '3201000100000000026',
issuingBank: '中国建设银行南京城南支行',
phone: '025-66880002',
customerEmails: 'finance@huadong.example.com',
departmentEmails: 'logistics@huadong.example.com',
attachmentsJson: '[]',
kingdeeBillNo: 'KD-FP-20260826002',
},
{
id: 90000003,
invoiceNo: '25312000000000000103',
invoiceDate: '2026-08-27',
invoiceType: '增值税专用发票',
taxRate: 3,
invoiceAmount: 20600,
taxAmount: 600,
receiverName: '华东供应链管理有限公司',
issuerName: '浙江通达物流有限公司',
bankName: '招商银行杭州分行',
bankAccount: '5719000100000000033',
issuingBank: '招商银行杭州高新支行',
phone: '0571-66880003',
customerEmails: 'finance@huadong.example.com',
departmentEmails: 'settlement@huadong.example.com',
attachmentsJson: '[]',
kingdeeBillNo: 'KD-FP-20260827003',
},
];
const mockInvoiceTypes = ['增值税专用发票', '增值税普通发票'];
const mockTaxRates = [3, 6, 9, 13];
const mockBankNames = ['中国工商银行', '中国农业银行', '中国银行', '中国建设银行', '招商银行'];
const randomDigits = length =>
Array.from({ length }, () => Math.floor(Math.random() * 10)).join('');
@@ -319,28 +276,59 @@ const formatMockDate = date => {
return `${year}-${month}-${day}`;
};
const createInvoicePoolMockRows = () =>
invoicePoolMockTemplates.map((template, index) => {
const invoiceDateValue = new Date();
invoiceDateValue.setDate(invoiceDateValue.getDate() - Math.floor(Math.random() * 15));
const invoiceDate = formatMockDate(invoiceDateValue);
const invoiceAmount = Math.floor(10000 + Math.random() * 190000);
const taxAmount = Number(
(
(invoiceAmount * Number(template.taxRate || 0)) /
(100 + Number(template.taxRate || 0))
).toFixed(2)
);
return {
...template,
id: Date.now() + index * 100 + Math.floor(Math.random() * 100),
invoiceNo: `25${randomDigits(18)}`,
invoiceDate,
invoiceAmount,
taxAmount,
kingdeeBillNo: `KD-FP-${invoiceDate.replaceAll('-', '')}${randomDigits(3)}`,
};
const customerName = customer =>
customer.fullName || customer.shortName || customer.customerCode || `客商${customer.id}`;
const customerEmail = (customer, index) => {
const prefix = String(customer.customerCode || customer.id || `customer${index + 1}`)
.replace(/[^a-zA-Z0-9_-]/g, '')
.toLowerCase();
return `finance@${prefix || `customer${index + 1}`}.example.com`;
};
const createInvoicePoolMockRows = (customers, counterpartyName, departmentEmail) => {
const rows = [];
const baseId = Date.now();
customers.forEach((customer, customerIndex) => {
const name = customerName(customer);
['issuer', 'receiver'].forEach((role, roleIndex) => {
const count = 3 + Math.floor(Math.random() * 5);
for (let index = 0; index < count; index += 1) {
const rowIndex = rows.length;
const invoiceDateValue = new Date();
invoiceDateValue.setDate(invoiceDateValue.getDate() - Math.floor(Math.random() * 90));
const invoiceDate = formatMockDate(invoiceDateValue);
const taxRate = mockTaxRates[(customerIndex + roleIndex + index) % mockTaxRates.length];
const invoiceAmount = Math.floor(10000 + Math.random() * 190000);
const taxAmount = Number(
((invoiceAmount * Number(taxRate)) / (100 + Number(taxRate))).toFixed(2)
);
const bankName = mockBankNames[(customerIndex + index) % mockBankNames.length];
rows.push({
id: baseId + rowIndex,
invoiceNo: `25${randomDigits(18)}`,
invoiceDate,
invoiceType: mockInvoiceTypes[(customerIndex + index) % mockInvoiceTypes.length],
taxRate,
invoiceAmount,
taxAmount,
receiverName: role === 'receiver' ? name : counterpartyName,
issuerName: role === 'issuer' ? name : counterpartyName,
bankName,
bankAccount: randomDigits(19),
issuingBank: `${bankName}营业部`,
phone: customer.contactPhone || '',
customerEmails: customerEmail(customer, customerIndex),
departmentEmails: departmentEmail || '',
attachmentsJson: '[]',
kingdeeBillNo: `KD-FP-${invoiceDate.replaceAll('-', '')}${randomDigits(5)}`,
kingdeeStatus: 'unsynced',
});
}
});
});
return rows;
};
const emptyForm = () => ({
id: null,
@@ -380,9 +368,18 @@ export default {
Search,
form: emptyForm(),
invoicePoolMockRows: [],
invoicePoolMockLoaded: false,
customerEmailOptions: [],
departmentEmailOptions: [],
invoiceDialog: { visible: false, loading: false, keyword: '', rows: [], current: null },
invoiceDialog: {
visible: false,
loading: false,
keyword: '',
sourceRows: [],
rows: [],
current: null,
page: { current: 1, size: 10, total: 0 },
},
settlementDialog: {
visible: false,
loading: false,
@@ -447,7 +444,6 @@ export default {
.filter(Boolean);
},
async initialize() {
this.invoicePoolMockRows = createInvoicePoolMockRows();
const userInfo = this.$store.getters.userInfo || {};
const userEmail = userInfo.email || '';
this.departmentEmailOptions = userEmail ? [userEmail] : [];
@@ -499,22 +495,72 @@ export default {
async openInvoiceDialog() {
this.invoiceDialog.visible = true;
this.invoiceDialog.keyword = this.form.invoiceNo || '';
if (!this.recordId) this.invoicePoolMockRows = createInvoicePoolMockRows();
await this.loadInvoicePool();
},
async loadInvoicePool() {
this.invoiceDialog.loading = true;
this.invoiceDialog.page.current = 1;
this.invoiceDialog.current = null;
try {
if (!this.recordId) {
this.invoiceDialog.rows = this.filterInvoicePoolMockRows(this.invoiceDialog.keyword);
if (!this.invoicePoolMockLoaded) await this.loadInvoicePoolMockRows();
this.invoiceDialog.sourceRows = this.filterInvoicePoolMockRows(
this.invoiceDialog.keyword
);
this.refreshInvoicePoolPage();
return;
}
const data = this.unwrapData(await api.getInvoicePool(this.invoiceDialog.keyword));
this.invoiceDialog.rows = Array.isArray(data) ? data : data?.records || [];
this.invoiceDialog.sourceRows = Array.isArray(data) ? data : data?.records || [];
this.refreshInvoicePoolPage();
} finally {
this.invoiceDialog.loading = false;
}
},
async loadInvoicePoolMockRows() {
const pageSize = 500;
const firstData = this.unwrapData(await getCustomerList(1, pageSize, {}));
const firstRows = Array.isArray(firstData) ? firstData : firstData?.records || [];
const total = Number(firstData?.total || firstRows.length);
const pageCount = Math.ceil(total / pageSize);
const remainingPages = await Promise.all(
Array.from({ length: Math.max(pageCount - 1, 0) }, (_, index) =>
getCustomerList(index + 2, pageSize, {})
)
);
const customers = [
...firstRows,
...remainingPages.flatMap(response => {
const data = this.unwrapData(response);
return Array.isArray(data) ? data : data?.records || [];
}),
].filter(
(customer, index, rows) =>
rows.findIndex(item => String(item.id) === String(customer.id)) === index
);
const userInfo = this.$store.getters.userInfo || {};
const counterpartyName = userInfo.deptName || userInfo.dept_name || '本企业';
this.invoicePoolMockRows = createInvoicePoolMockRows(
customers,
counterpartyName,
userInfo.email || ''
);
this.invoicePoolMockLoaded = true;
},
refreshInvoicePoolPage() {
const page = this.invoiceDialog.page;
const total = this.invoiceDialog.sourceRows.length;
const maxPage = Math.max(Math.ceil(total / page.size), 1);
if (page.current > maxPage) page.current = maxPage;
const start = (page.current - 1) * page.size;
page.total = total;
this.invoiceDialog.current = null;
this.invoiceDialog.rows = this.invoiceDialog.sourceRows.slice(start, start + page.size);
},
handleInvoicePoolSizeChange() {
this.invoiceDialog.page.current = 1;
this.refreshInvoicePoolPage();
},
filterInvoicePoolMockRows(keyword) {
const normalizedKeyword = String(keyword || '')
.trim()
@@ -781,6 +827,11 @@ export default {
.receipt-form-page__dialog-search .el-input {
width: 360px;
}
.receipt-form-page__dialog-pagination {
display: flex;
justify-content: flex-end;
margin-top: 12px;
}
.receipt-form-page :deep(.el-table) {
--el-table-border-color: #eff1f7;
}