Merge remote-tracking branch 'origin/feature/kingdee-attachment-sync' into feature/bfi-api-rate

# Conflicts:
#	src/api/payment/invoiceApplication.js
#	src/api/payment/invoiceReceipt.js
#	src/api/payment/paymentApplication.js
#	src/api/settlement/formalSettlement.js
#	src/views/payment/invoice-application.vue
#	src/views/payment/invoice-receipt.vue
#	src/views/payment/payment-application-form.vue
#	src/views/payment/payment-application.vue
#	src/views/settlement/formal-settlement.vue
This commit is contained in:
刘泉佳
2026-09-28 10:07:19 +08:00
15 changed files with 314 additions and 15 deletions
+12 -1
View File
@@ -411,7 +411,18 @@ export default {
try {
await Promise.all(rows.map(row => api.syncKingdee(row.id)));
this.$message.success(`已同步${rows.length}条开票申请`);
this.loadTable();
await this.loadTable();
// 附件联带同步提示:同步成功但附件未全部上传时追加 warning,重推即自动补传
const idSet = new Set(rows.map(row => String(row.id)));
const pendingCount = (this.rows || []).filter(row => idSet.has(String(row.id))
&& ['pending', 'partial'].includes(row.attachmentSyncStatus)).length;
if (pendingCount) {
this.$message({
type: 'warning',
message: `其中${pendingCount}单附件未全部上传,可重推补传`,
duration: 8000,
});
}
} finally {
this.batchSyncing = false;
}
+7 -2
View File
@@ -378,8 +378,13 @@ export default {
this.pushLoading = true;
try {
const summary = this.unwrapData(await api.pushKingdee(rows.map(row => row.id)));
this.$alert(summary || '推送完成', '推送结果', { confirmButtonText: '知道了' });
this.loadTable();
await this.loadTable();
// 附件联带同步提示:推送成功但附件未全部上传时在结果弹窗追加说明,重推即自动补传
const idSet = new Set(rows.map(row => String(row.id)));
const pendingCount = (this.rows || []).filter(row => idSet.has(String(row.id))
&& ['pending', 'partial'].includes(row.attachmentSyncStatus)).length;
const attachmentTip = pendingCount ? `\n其中${pendingCount}单附件未全部上传,可重推补传` : '';
this.$alert((summary || '推送完成') + attachmentTip, '推送结果', { confirmButtonText: '知道了' });
} finally {
this.pushLoading = false;
}
+45 -5
View File
@@ -281,8 +281,18 @@
<el-table-column label="操作" width="220" fixed="right" align="center">
<template #default="{ row, $index }">
<div class="payment-form-page__invoice-actions">
<el-link type="primary" @click="viewInvoiceAttachment(row)">查看</el-link>
<el-link type="primary" @click="downloadInvoiceAttachment(row)">下载</el-link>
<el-link
type="primary"
:disabled="kingdeeAttachmentBusy"
@click="viewInvoiceAttachment(row)"
>查看</el-link
>
<el-link
type="primary"
:disabled="kingdeeAttachmentBusy"
@click="downloadInvoiceAttachment(row)"
>下载</el-link
>
<el-link
v-if="!readonly"
type="danger"
@@ -663,6 +673,11 @@ import {
import { readSettlementTransfer, removeSettlementTransfer } from '@/utils/settlement-transfer';
import { downloadFileByUrl } from '@/utils/util';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import {
downloadKingdeeInvoiceFile,
isKingdeePathAttachment,
viewKingdeeInvoiceFile,
} from '@/utils/kingdee-attachment';
import PdfPreview from '@/components/pdf-preview/main.vue';
const attachmentViewerPlugins = [
@@ -743,6 +758,8 @@ export default {
form: emptyForm(),
amountSyncing: false,
transferPayload: null,
// 金蝶侧发票附件查看/下载进行中(行组级 loading 守卫)
kingdeeAttachmentBusy: false,
referenceRows: [],
paymentRecords: [],
referenceVisible: false,
@@ -1584,8 +1601,19 @@ export default {
this.attachmentFileName(this.invoiceAttachment(row)) || `${row.invoiceNo || '发票'}.pdf`
);
},
viewInvoiceAttachment(row) {
async viewInvoiceAttachment(row) {
const attachment = this.invoiceAttachment(row);
// 金蝶侧附件(path 型)经后端代理 A801-2 预览,OSS 直链维持本地预览组件
if (isKingdeePathAttachment(attachment)) {
if (this.kingdeeAttachmentBusy) return;
this.kingdeeAttachmentBusy = true;
try {
await viewKingdeeInvoiceFile(row.invoiceNo, this.invoiceAttachmentName(row));
} finally {
this.kingdeeAttachmentBusy = false;
}
return;
}
if (!this.attachmentFileUrl(attachment)) {
this.$message.warning('当前发票暂无可查看附件');
return;
@@ -1595,8 +1623,20 @@ export default {
[attachment]
);
},
downloadInvoiceAttachment(row) {
const url = this.invoiceAttachmentUrl(row);
async downloadInvoiceAttachment(row) {
const attachment = this.invoiceAttachment(row);
// 金蝶侧附件(path 型)经后端代理 A801-2 下载,OSS 直链维持前端直连下载
if (isKingdeePathAttachment(attachment)) {
if (this.kingdeeAttachmentBusy) return;
this.kingdeeAttachmentBusy = true;
try {
await downloadKingdeeInvoiceFile(row.invoiceNo, this.invoiceAttachmentName(row));
} finally {
this.kingdeeAttachmentBusy = false;
}
return;
}
const url = this.attachmentFileUrl(attachment);
if (!url) {
this.$message.warning('当前发票暂无可下载附件');
return;
+17 -2
View File
@@ -406,7 +406,8 @@ export default {
async handleSyncRow(row) {
const data = this.unwrapData(await api.syncKingdee(row.id));
this.$message.success(`已生成金蝶付款单:${data}`);
this.loadTable();
await this.loadTable();
this.warnAttachmentNotUploaded([row.id]);
},
async handleSync() {
if (this.syncLoading) return;
@@ -428,11 +429,25 @@ export default {
} else {
this.$message.success(`已同步${data.length}条付款申请`);
}
this.loadTable();
await this.loadTable();
this.warnAttachmentNotUploaded(rows.map(row => row.id));
} finally {
this.syncLoading = false;
}
},
// 附件联带同步提示:同步成功但附件未全部上传时追加 warning,重推即自动补传
warnAttachmentNotUploaded(ids) {
const idSet = new Set(ids.map(String));
const pendingCount = (this.rows || []).filter(row => idSet.has(String(row.id))
&& ['pending', 'partial'].includes(row.attachmentSyncStatus)).length;
if (pendingCount) {
this.$message({
type: 'warning',
message: `其中${pendingCount}单附件未全部上传,可重推补传`,
duration: 8000,
});
}
},
async handleSyncResult() {
if (this.resultSyncing) return;
this.resultSyncing = true;