From b4ecc90470a39702f9ab1bef0d903ec1201979da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com>
Date: Thu, 1 Oct 2026 18:32:22 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=B6=E7=A5=A8=E7=99=BB=E8=AE=B0?=
=?UTF-8?q?=E5=8F=91=E7=A5=A8=E9=99=84=E4=BB=B6=E6=9F=A5=E7=9C=8B=E4=B8=8B?=
=?UTF-8?q?=E8=BD=BD=E4=B8=8E=E6=9F=A5=E7=9C=8B=E6=80=81=E6=93=8D=E4=BD=9C?=
=?UTF-8?q?=E5=88=97=EF=BC=88=E9=87=91=E8=9D=B6piaozone=20path=E9=99=84?=
=?UTF-8?q?=E4=BB=B6=E4=BB=A3=E7=90=86=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- vehicle-attachment-table 新增 kingdee-invoice-no/show-view-actions props:piaozone path 型附件查看经 A801-2 代理取流进弹窗预览(objectURL 弹窗关闭回收),下载/批量下载走金蝶代理串行触发
- 查看态展示查看/下载操作列,编辑态为查看/下载/删除;未传 props 的页面行为不变
- 收票登记表单页接入(编辑/查看态均生效),kingdee-attachment.js 导出 requestKingdeeFile 供组件复用
---
.../vehicle-attachment-table/main.vue | 125 +++++++++++++++++-
src/utils/kingdee-attachment.js | 7 +-
src/views/payment/invoice-receipt-form.vue | 8 +-
3 files changed, 130 insertions(+), 10 deletions(-)
diff --git a/src/components/vehicle-attachment-table/main.vue b/src/components/vehicle-attachment-table/main.vue
index f725c49..fc43c86 100644
--- a/src/components/vehicle-attachment-table/main.vue
+++ b/src/components/vehicle-attachment-table/main.vue
@@ -40,9 +40,23 @@
-
-
- 删除
+
+
+
+ 查看
+ 下载
+ 删除
+
@@ -68,6 +82,7 @@
width="90%"
top="4vh"
class="vehicle-attachment-table__viewer-dialog"
+ @closed="handlePreviewClosed"
>
this.attachmentUrl(row));
- if (!downloadableRows.length) {
+ const kingdeeRows = rows.filter(row => this.isKingdeeRow(row));
+ const urlRows = rows.filter(row => !this.isKingdeeRow(row) && this.attachmentUrl(row));
+ if (!kingdeeRows.length && !urlRows.length) {
this.$message.warning(
this.selectedRows.length ? '所选附件暂无可下载地址' : '暂无可下载附件'
);
return;
}
- downloadableRows.forEach((row, index) => {
+ urlRows.forEach((row, index) => {
window.setTimeout(() => this.downloadAttachment(row), index * 500);
});
+ // 金蝶侧附件走代理接口,串行触发避免并发重复回源
+ this.downloadKingdeeRows(kingdeeRows);
+ },
+ async downloadKingdeeRows(rows) {
+ if (this.kingdeeBusy) return;
+ this.kingdeeBusy = true;
+ try {
+ for (const row of rows) {
+ await downloadKingdeeInvoiceFile(this.kingdeeInvoiceNoOf(row), this.attachmentName(row));
+ }
+ } finally {
+ this.kingdeeBusy = false;
+ }
},
previewAttachment(row) {
+ // 金蝶侧附件经 A801-2 代理取流后进弹窗预览,OSS 直链维持原逻辑
+ if (this.isKingdeeRow(row)) {
+ return this.previewKingdeeAttachment(row);
+ }
const url = this.attachmentUrl(row);
if (!url) {
this.$message.warning('附件地址为空,无法预览');
@@ -288,6 +359,37 @@ export default {
};
this.documentPreviewVisible = true;
},
+ async previewKingdeeAttachment(row) {
+ if (this.kingdeeBusy) return;
+ this.kingdeeBusy = true;
+ try {
+ const blob = await requestKingdeeFile(this.kingdeeInvoiceNoOf(row));
+ this.releaseKingdeeObjectUrl();
+ const isPdf = this.isPdf(row) || String(blob.type || '').includes('application/pdf');
+ this.kingdeeObjectUrl = URL.createObjectURL(blob);
+ this.previewFile = {
+ name: this.attachmentName(row),
+ url: this.kingdeeObjectUrl,
+ mimeType: isPdf ? 'application/pdf' : blob.type || '',
+ isPdf,
+ };
+ this.documentPreviewVisible = true;
+ } catch (error) {
+ if (!error?.silent) this.$message.error(error?.message || '附件预览失败');
+ } finally {
+ this.kingdeeBusy = false;
+ }
+ },
+ handlePreviewClosed() {
+ this.releaseKingdeeObjectUrl();
+ this.previewFile = {};
+ },
+ releaseKingdeeObjectUrl() {
+ if (this.kingdeeObjectUrl) {
+ URL.revokeObjectURL(this.kingdeeObjectUrl);
+ this.kingdeeObjectUrl = '';
+ }
+ },
handlePreviewUnsupported() {
this.$message.warning('当前文件暂不支持在线预览');
},
@@ -318,6 +420,17 @@ export default {
text-decoration: underline;
}
+ &__actions {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 12px;
+
+ :deep(.el-link) {
+ font-size: 13px;
+ }
+ }
+
&__upload {
display: flex;
justify-content: flex-start;
diff --git a/src/utils/kingdee-attachment.js b/src/utils/kingdee-attachment.js
index c66a970..a7ac977 100644
--- a/src/utils/kingdee-attachment.js
+++ b/src/utils/kingdee-attachment.js
@@ -3,7 +3,7 @@
*
* 票池发票附件为 {source:'piaozone', path, name}:path 是金蝶侧文件 id(非 http 直链),
* 须由后端代理 A801-2 流式回源;OSS 直链附件(url/link/fileUrl)仍由前端直连下载/预览。
- * 三处入口共用:票池弹窗、正式结算认领发票行、付款申请发票附件行。
+ * 入口共用:票池弹窗、正式结算认领发票行、付款申请发票附件行、收票登记附件表。
*/
import { ElMessage } from 'element-plus';
import { downloadFile } from '@/utils/util';
@@ -22,11 +22,12 @@ export const isKingdeePathAttachment = attachment => {
/**
* 请求金蝶文件流:成功返回 Blob;业务失败为 HTTP 200 + R.fail JSON(响应通道未写流时后端即失败),
- * 按 Content-Type 识别并抛出带 msg 的错误;网络级失败拦截器已提示,标记 silent 避免重复提示
+ * 按 Content-Type 识别并抛出带 msg 的错误;网络级失败拦截器已提示,标记 silent 避免重复提示。
+ * 供查看(弹窗内预览)/下载两类入口复用
* @param {String} invoiceNo 发票号码
* @returns {Promise}
*/
-const requestKingdeeFile = async invoiceNo => {
+export const requestKingdeeFile = async invoiceNo => {
let res;
try {
res = await downloadInvoicePoolAttachment(invoiceNo);
diff --git a/src/views/payment/invoice-receipt-form.vue b/src/views/payment/invoice-receipt-form.vue
index 144ca1c..6a5b524 100644
--- a/src/views/payment/invoice-receipt-form.vue
+++ b/src/views/payment/invoice-receipt-form.vue
@@ -118,7 +118,13 @@
-
+
+