diff --git a/src/api/payment/invoiceReceipt.js b/src/api/payment/invoiceReceipt.js index d4cf692..d4d0b3e 100644 --- a/src/api/payment/invoiceReceipt.js +++ b/src/api/payment/invoiceReceipt.js @@ -5,8 +5,10 @@ const baseUrl = '/blade-transport/invoice-receipt'; export const getList = (current, size, params) => request({ url: `${baseUrl}/list`, method: 'get', params: { current, size, ...params } }); export const getDetail = id => request({ url: `${baseUrl}/detail`, method: 'get', params: { id } }); -export const getInvoicePool = keyword => - request({ url: `${baseUrl}/invoice-pool`, method: 'get', params: { keyword } }); +export const queryInvoicePool = params => + request({ url: `${baseUrl}/invoice-pool`, method: 'get', params }); +export const fetchInvoicePoolByNo = invoiceNo => + request({ url: `${baseUrl}/invoice-pool/fetch`, method: 'post', params: { invoiceNo } }); export const getSettlementCandidates = (keyword, receiptId) => request({ url: `${baseUrl}/settlement-candidates`, @@ -27,6 +29,9 @@ export const returnBill = data => request({ url: `${baseUrl}/return`, method: 'p export const voidBill = data => request({ url: `${baseUrl}/void`, method: 'post', data }); export const syncKingdee = id => request({ url: `${baseUrl}/sync-kingdee`, method: 'post', params: { id } }); +// 手动同步为分钟级长任务,单独放宽超时(全局默认 10s 必超时) +export const syncInvoicePool = () => + request({ url: `${baseUrl}/sync-invoice-pool`, method: 'post', timeout: 300000 }); export const approvalStatusOptions = [ { label: '草稿', value: 'draft' }, diff --git a/src/api/settlement/formalSettlement.js b/src/api/settlement/formalSettlement.js index 23b280a..c1fc420 100644 --- a/src/api/settlement/formalSettlement.js +++ b/src/api/settlement/formalSettlement.js @@ -50,3 +50,5 @@ export const claimInvoices = data => request({ url: `${baseUrl}/claim-invoices`, method: 'post', data }); export const queryInvoicePool = params => request({ url: `${baseUrl}/invoice-pool`, method: 'get', params }); +export const fetchInvoicePoolByNo = invoiceNo => + request({ url: `${baseUrl}/invoice-pool/fetch`, method: 'post', params: { invoiceNo } }); diff --git a/src/components/kingdee-invoice-pool-dialog/main.vue b/src/components/kingdee-invoice-pool-dialog/main.vue new file mode 100644 index 0000000..8e311eb --- /dev/null +++ b/src/components/kingdee-invoice-pool-dialog/main.vue @@ -0,0 +1,364 @@ + + + + + diff --git a/src/views/payment/invoice-receipt-form.vue b/src/views/payment/invoice-receipt-form.vue index c74498f..e23c555 100644 --- a/src/views/payment/invoice-receipt-form.vue +++ b/src/views/payment/invoice-receipt-form.vue @@ -149,62 +149,15 @@ - - - - - - - - - - - - - - - - - - - - - - -
- -
- -
+ - Array.from({ length }, () => Math.floor(Math.random() * 10)).join(''); - -const formatMockDate = date => { - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - return `${year}-${month}-${day}`; -}; - -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, kingdeeInvoicePoolId: null, @@ -361,24 +246,17 @@ const emptyForm = () => ({ export default { name: 'InvoiceReceiptForm', components: { + KingdeeInvoicePoolDialog, VehicleAttachmentTable, }, data() { return { Search, form: emptyForm(), - invoicePoolMockRows: [], - invoicePoolMockLoaded: false, customerEmailOptions: [], departmentEmailOptions: [], invoiceDialog: { visible: false, - loading: false, - keyword: '', - sourceRows: [], - rows: [], - current: null, - page: { current: 1, size: 10, total: 0 }, }, settlementDialog: { visible: false, @@ -421,6 +299,18 @@ export default { this.initialize(); }, methods: { + apiQueryInvoicePool(params) { + return api.queryInvoicePool(params); + }, + apiFetchInvoicePool(invoiceNo) { + return api.fetchInvoicePoolByNo(invoiceNo); + }, + apiSyncInvoicePool() { + return api.syncInvoicePool(); + }, + handleInvoicePicked(rows) { + this.confirmInvoice(rows[0]); + }, hasPermission(code) { return this.permission?.[code] !== false; }, @@ -492,92 +382,11 @@ export default { } callback(); }, - async openInvoiceDialog() { + openInvoiceDialog() { this.invoiceDialog.visible = true; - this.invoiceDialog.keyword = this.form.invoiceNo || ''; - await this.loadInvoicePool(); - }, - async loadInvoicePool() { - this.invoiceDialog.loading = true; - this.invoiceDialog.page.current = 1; - this.invoiceDialog.current = null; - try { - if (!this.recordId) { - 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.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() - .toLowerCase(); - if (!normalizedKeyword) return this.invoicePoolMockRows.map(item => ({ ...item })); - return this.invoicePoolMockRows - .filter(item => - [item.invoiceNo, item.issuerName, item.receiverName].some(value => - String(value || '') - .toLowerCase() - .includes(normalizedKeyword) - ) - ) - .map(item => ({ ...item })); }, confirmInvoice(row, options = {}) { - const selected = row?.id ? row : this.invoiceDialog.current; + const selected = row; if (!selected) { this.$message.warning('请选择一张金蝶票据池发票'); return; @@ -758,16 +567,8 @@ export default { this.$message.warning('请先选择金蝶票据池发票'); return; } - const data = this.recordId - ? this.unwrapData(await api.getInvoicePool(this.form.invoiceNo)) - : this.filterInvoicePoolMockRows(this.form.invoiceNo); - const rows = Array.isArray(data) ? data : data?.records || []; - const invoice = rows.find(item => item.invoiceNo === this.form.invoiceNo); - if (!invoice) { - this.$message.warning('金蝶票据池中未查询到该发票'); - return; - } - if (!this.confirmInvoice(invoice, { preserveUserInput: true })) return; + const invoice = this.unwrapData(await api.fetchInvoicePoolByNo(this.form.invoiceNo)); + if (!invoice || !this.confirmInvoice(invoice, { preserveUserInput: true })) return; if (this.settlementIds.length) await this.loadReferenceInformation(); this.$message.success('同步成功'); }, @@ -827,11 +628,6 @@ 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; } diff --git a/src/views/settlement/components/formal-settlement-editor.vue b/src/views/settlement/components/formal-settlement-editor.vue index 589f736..1077f81 100644 --- a/src/views/settlement/components/formal-settlement-editor.vue +++ b/src/views/settlement/components/formal-settlement-editor.vue @@ -412,126 +412,16 @@ - - - - - - - - - - - - - - - - - - - - - 重置 - 查询 - - - - - - - - - - - - - - - - - -
- -
- -
+ confirm-text="确认认领" + multiple + :initial-invoice-no="String(invoiceClaimNo || '').trim()" + :query-api="invoicePoolQueryApi" + :fetch-api="invoicePoolFetchApi" + @confirm="handleInvoiceClaimConfirm" + /> ({ + ...row, + attachmentJson: row.attachmentJson || row.attachmentsJson, + })); + await this.confirmInvoiceClaims(); }, async confirmInvoiceClaims() { if (!this.invoiceClaimDialog.selected.length) {