+
- 查看
- 下载
+ 查看
+ 下载
删除
+
+
-
-
-
-
-
-
-
-
-
-
- {{ formatMoney(row.invoiceAmount) }}
-
-
- {{ formatMoney(row.matchedAmount) }}
-
-
-
-
- 取消
- 确认认领
-
-
+ confirm-text="确认认领"
+ multiple
+ :initial-invoice-no="String(invoiceClaimNo || '').trim()"
+ :query-api="invoicePoolQueryApi"
+ @confirm="handleInvoiceClaimConfirm"
+ />
total + Number(item.matchedAmount || 0), 0),
- 0
- );
- const existingNumbers = new Set(this.invoices.map(item => String(item.invoiceNo)));
- const mockRows = numbers
- .map((invoiceNo, index) => {
- const matchedAmount = Math.min(
- preferredMatchedAmounts[index],
- availableAmounts[index],
- remainingAmount
- );
- remainingAmount = Number((remainingAmount - matchedAmount).toFixed(2));
- return {
- invoiceNo,
- invoiceDate: this.$dayjs().subtract(index, 'day').format('YYYY-MM-DD'),
- invoiceType: index === 1 ? '增值税普通发票' : '增值税专用发票',
- taxRate: [3, 6, 9][index],
- invoiceAmount: invoiceAmounts[index],
- availableInvoiceAmount: availableAmounts[index],
- matchedAmount,
- attachmentJson: '',
- mockData: true,
- };
- })
- .filter(item => !existingNumbers.has(item.invoiceNo));
- if (!mockRows.length) {
- this.$message.warning('当前发票号码的Mock数据已认领');
- return;
- }
- this.invoices = [...this.invoices, ...mockRows];
- this.$message.success(`已生成${mockRows.length}条Mock发票数据`);
- } finally {
- this.invoiceClaimLoading = false;
- }
- },
openInvoiceClaimDialog() {
- const stamp = Date.now();
- this.invoiceClaimDialog.loading = true;
- this.invoiceClaimDialog.rows = Array.from({ length: 80 }, (_, index) => {
- const amount = Math.floor(1000 + Math.random() * 49000);
- return {
- invoiceNo: `MOCK${stamp}${String(index + 1).padStart(3, '0')}`.slice(0, 32),
- invoiceDate: this.$dayjs()
- .subtract(Math.floor(Math.random() * 90), 'day')
- .format('YYYY-MM-DD'),
- invoiceType: index % 2 ? '增值税普通发票' : '增值税专用发票',
- issuerName: this.form.payerName || 'Mock开票单位',
- receiverName: this.form.payeeName || 'Mock受票单位',
- invoiceAmount: amount,
- availableInvoiceAmount: amount,
- matchedAmount: amount,
- taxRate: [3, 6, 9, 13][index % 4],
- attachmentJson: '',
- mockData: true,
- };
- });
- this.invoiceClaimDialog.selected = [];
- this.invoiceClaimDialog.page.current = 1;
- this.invoiceClaimDialog.page.total = 80;
this.invoiceClaimDialog.visible = true;
- this.invoiceClaimDialog.loading = false;
+ },
+ invoicePoolQueryApi(params) {
+ return queryInvoicePool(params);
+ },
+ async handleInvoiceClaimConfirm(rows) {
+ // 统一票池行附件字段为复数 attachmentsJson,认领请求契约是单数 attachmentJson,中转处归一
+ this.invoiceClaimDialog.selected = rows.map(row => ({
+ ...row,
+ attachmentJson: row.attachmentJson || row.attachmentsJson,
+ }));
+ await this.confirmInvoiceClaims();
},
async confirmInvoiceClaims() {
if (!this.invoiceClaimDialog.selected.length) {
@@ -2408,7 +2356,11 @@ export default {
if (Number(this.form.settlementAmount || 0) > 0) {
remaining = Math.max(0, remaining - matchedAmount);
}
- return { ...row, matchedAmount };
+ return {
+ ...row,
+ invoiceType: row.invoiceTypeName || row.invoiceType || '',
+ matchedAmount,
+ };
})
.filter(row => row.matchedAmount > 0);
if (!invoices.length) {
@@ -2494,16 +2446,64 @@ export default {
const attachment = this.invoiceAttachment(row);
return attachment.originalName || attachment.name || `${row.invoiceNo || '发票'}.pdf`;
},
- viewInvoiceAttachment(row) {
+ async viewInvoiceAttachment(row) {
+ const attachment = this.invoiceAttachment(row);
+ // 金蝶侧附件(path 型)经后端代理 A801-2 预览,OSS 直链维持 window.open
+ if (isKingdeePathAttachment(attachment)) {
+ if (this.kingdeeAttachmentBusy) return;
+ this.kingdeeAttachmentBusy = true;
+ try {
+ await viewKingdeeInvoiceFile(row.invoiceNo, this.invoiceAttachmentName(row));
+ } finally {
+ this.kingdeeAttachmentBusy = false;
+ }
+ return;
+ }
const url = this.invoiceAttachmentUrl(row);
- if (!url) return this.$message.warning('当前Mock发票暂无可查看附件');
+ if (!url) return this.$message.warning('当前发票暂无可查看附件');
window.open(url, '_blank');
},
- downloadInvoiceAttachment(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.invoiceAttachmentUrl(row);
- if (!url) return this.$message.warning('当前Mock发票暂无可下载附件');
+ if (!url) return this.$message.warning('当前发票暂无可下载附件');
downloadFileByUrl(url, this.invoiceAttachmentName(row));
},
+ // 开票发票预览地址:数电PDF优先(OFD浏览器无法预览),退预览图、板式文件
+ issuedInvoicePreviewUrl(row) {
+ return row.invoicePdfFileUrl || row.invoiceImageUrl || row.invoiceFileUrl || '';
+ },
+ // 开票发票下载地址:数电PDF优先,退板式文件、数电XML
+ issuedInvoiceDownloadUrl(row) {
+ return row.invoicePdfFileUrl || row.invoiceFileUrl || row.invoiceXmlFileUrl || '';
+ },
+ // 下载文件名按直链扩展名推断(数电票 .pdf / 板式文件 .ofd|.pdf),缺省 .pdf
+ issuedInvoiceFileName(row, url) {
+ const match = String(url || '').split('?')[0].match(/\.([a-zA-Z0-9]+)$/);
+ const extension = match ? `.${match[1].toLowerCase()}` : '.pdf';
+ return `${row.invoiceNo || '发票'}${extension}`;
+ },
+ viewIssuedInvoice(row) {
+ const url = this.issuedInvoicePreviewUrl(row);
+ if (!url) return this.$message.warning('当前发票暂无可查看文件,可稍后重试开票结果同步');
+ window.open(url, '_blank');
+ },
+ downloadIssuedInvoice(row) {
+ const url = this.issuedInvoiceDownloadUrl(row);
+ if (!url) return this.$message.warning('当前发票暂无可下载文件,可稍后重试开票结果同步');
+ downloadFileByUrl(url, this.issuedInvoiceFileName(row, url));
+ },
buildSavePayload() {
return {
id: this.form.id,
@@ -2993,6 +2993,14 @@ export default {
.formal-editor__invoice-claim :deep(.el-input) {
width: 360px;
}
+.formal-editor__issued-invoices {
+ margin-top: 16px;
+}
+.formal-editor__issued-title {
+ margin-bottom: 8px;
+ color: var(--el-text-color-secondary);
+ font-size: 13px;
+}
.formal-editor__negative-amount {
color: var(--el-color-danger);
}
diff --git a/src/views/settlement/components/formal-settlement-table-panel.vue b/src/views/settlement/components/formal-settlement-table-panel.vue
index eb830f3..8d0d028 100644
--- a/src/views/settlement/components/formal-settlement-table-panel.vue
+++ b/src/views/settlement/components/formal-settlement-table-panel.vue
@@ -21,6 +21,7 @@
type="primary"
plain
:disabled="selection.length !== 1"
+ :loading="syncLoading"
@click="$emit('sync')"
>同步金蝶
@@ -91,6 +92,12 @@
{{
kingdeeSyncName(row.kingdeeSyncStatus)
}}
+
+
+ {{ lockTag(row).label }}
+
+ -
+
{{ displayValue(row[column.prop]) }}
@@ -137,6 +144,7 @@ export default {
rows: { type: Array, default: () => [] },
columns: { type: Array, default: () => [] },
loading: { type: Boolean, default: false },
+ syncLoading: { type: Boolean, default: false },
page: { type: Object, required: true },
hasPermission: { type: Function, required: true },
mkEnabled: { type: Boolean, default: false },
@@ -267,6 +275,28 @@ export default {
kingdeeSyncName(value) {
return kingdeeSyncStatusOptions.find(item => item.value === value)?.label || value || '-';
},
+ lockTag(row) {
+ if (row.kingdeeLockStatus === 'locked') {
+ return { show: true, type: 'danger', label: '金蝶锁定中', tip: '该单据已被金蝶锁定,不可编辑/作废' };
+ }
+ if (row.kingdeeLockStatus === 'failed') {
+ if ((row.kingdeeTryCount || 0) >= 5) {
+ return {
+ show: true,
+ type: 'danger',
+ label: '锁定失败·已达上限',
+ tip: row.kingdeeLockFailReason || '自动补偿次数已用完,请重推「同步金蝶」立即补锁',
+ };
+ }
+ return {
+ show: true,
+ type: 'warning',
+ label: '锁定失败·补偿中',
+ tip: row.kingdeeLockFailReason || '系统将自动补偿重锁',
+ };
+ }
+ return { show: false };
+ },
displayValue(value) {
return value === null || value === undefined || value === '' ? '-' : value;
},
diff --git a/src/views/settlement/components/pre-settlement-editor.vue b/src/views/settlement/components/pre-settlement-editor.vue
index 0ff982d..7a63786 100644
--- a/src/views/settlement/components/pre-settlement-editor.vue
+++ b/src/views/settlement/components/pre-settlement-editor.vue
@@ -42,7 +42,7 @@
format="YYYY-MM-DD"
:disabled="!editable || form.currency === 'RMB'"
placeholder="请选择"
- @change="recalculateLocalAmount"
+ @change="handleExchangeRateDateChange"
/>