|
|
|
@@ -40,9 +40,23 @@
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column prop="uploadUserName" label="上传人" width="140" align="center" />
|
|
|
|
|
<el-table-column prop="uploadTime" label="上传时间" width="180" align="center" sortable />
|
|
|
|
|
<el-table-column v-if="!readonly" label="操作" width="100" align="center" fixed="right">
|
|
|
|
|
<template #default="{ $index }">
|
|
|
|
|
<el-link type="danger" @click="removeAttachment($index)">删除</el-link>
|
|
|
|
|
<el-table-column
|
|
|
|
|
v-if="!readonly || showViewActions"
|
|
|
|
|
label="操作"
|
|
|
|
|
:width="readonly ? 120 : 170"
|
|
|
|
|
align="center"
|
|
|
|
|
fixed="right"
|
|
|
|
|
>
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<div class="vehicle-attachment-table__actions">
|
|
|
|
|
<el-link type="primary" :disabled="kingdeeBusy" @click="previewAttachment(row)"
|
|
|
|
|
>查看</el-link
|
|
|
|
|
>
|
|
|
|
|
<el-link type="primary" :disabled="kingdeeBusy" @click="downloadAttachment(row)"
|
|
|
|
|
>下载</el-link
|
|
|
|
|
>
|
|
|
|
|
<el-link v-if="!readonly" type="danger" @click="removeAttachment($index)">删除</el-link>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
@@ -68,6 +82,7 @@
|
|
|
|
|
width="90%"
|
|
|
|
|
top="4vh"
|
|
|
|
|
class="vehicle-attachment-table__viewer-dialog"
|
|
|
|
|
@closed="handlePreviewClosed"
|
|
|
|
|
>
|
|
|
|
|
<pdf-preview
|
|
|
|
|
v-if="documentPreviewVisible && previewFile.url && previewFile.isPdf"
|
|
|
|
@@ -108,6 +123,11 @@ import '@open-file-viewer/core/style.css';
|
|
|
|
|
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
|
|
|
|
import PdfPreview from '@/components/pdf-preview/main.vue';
|
|
|
|
|
import { downloadFileByUrl } from '@/utils/util';
|
|
|
|
|
import {
|
|
|
|
|
downloadKingdeeInvoiceFile,
|
|
|
|
|
isKingdeePathAttachment,
|
|
|
|
|
requestKingdeeFile,
|
|
|
|
|
} from '@/utils/kingdee-attachment';
|
|
|
|
|
|
|
|
|
|
const attachmentFileTypes = [
|
|
|
|
|
'pdf',
|
|
|
|
@@ -153,6 +173,16 @@ export default {
|
|
|
|
|
type: Number,
|
|
|
|
|
default: 500,
|
|
|
|
|
},
|
|
|
|
|
// 金蝶侧附件(piaozone path 型)代理下载所依赖的发票号;行内自带 invoiceNo 时优先用行内值
|
|
|
|
|
kingdeeInvoiceNo: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: '',
|
|
|
|
|
},
|
|
|
|
|
// 查看态也展示「查看/下载」操作列(编辑态始终展示,含删除)
|
|
|
|
|
showViewActions: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
emits: ['update:modelValue'],
|
|
|
|
|
data() {
|
|
|
|
@@ -164,6 +194,10 @@ export default {
|
|
|
|
|
imagePreviewIndex: 0,
|
|
|
|
|
documentPreviewVisible: false,
|
|
|
|
|
previewFile: {},
|
|
|
|
|
// 金蝶侧附件代理请求进行中(行级按钮共享 loading 守卫,防重复触发)
|
|
|
|
|
kingdeeBusy: false,
|
|
|
|
|
// 金蝶附件预览用的 objectURL,弹窗关闭时回收
|
|
|
|
|
kingdeeObjectUrl: '',
|
|
|
|
|
viewerPlugins,
|
|
|
|
|
viewerToolbar: {
|
|
|
|
|
download: true,
|
|
|
|
@@ -198,6 +232,12 @@ export default {
|
|
|
|
|
attachmentUrl(row = {}) {
|
|
|
|
|
return row.url || row.link || row.fileUrl || row.downloadUrl || row.domain || row.src || '';
|
|
|
|
|
},
|
|
|
|
|
kingdeeInvoiceNoOf(row = {}) {
|
|
|
|
|
return row.invoiceNo || this.kingdeeInvoiceNo || '';
|
|
|
|
|
},
|
|
|
|
|
isKingdeeRow(row = {}) {
|
|
|
|
|
return isKingdeePathAttachment(row) && Boolean(this.kingdeeInvoiceNoOf(row));
|
|
|
|
|
},
|
|
|
|
|
attachmentExtension(row = {}) {
|
|
|
|
|
const source = String(this.attachmentName(row) || this.attachmentUrl(row)).split('?')[0];
|
|
|
|
|
const index = source.lastIndexOf('.');
|
|
|
|
@@ -245,6 +285,10 @@ export default {
|
|
|
|
|
return `${(value / 1024 / 1024).toFixed(1)}MB`;
|
|
|
|
|
},
|
|
|
|
|
downloadAttachment(row) {
|
|
|
|
|
// 金蝶侧附件(piaozone path 型)经后端代理 A801-2 下载,OSS 直链维持前端直连下载
|
|
|
|
|
if (this.isKingdeeRow(row)) {
|
|
|
|
|
return this.downloadKingdeeAttachment(row);
|
|
|
|
|
}
|
|
|
|
|
const url = this.attachmentUrl(row);
|
|
|
|
|
if (!url) {
|
|
|
|
|
this.$message.warning('附件地址为空,无法下载');
|
|
|
|
@@ -252,20 +296,47 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
downloadFileByUrl(url, this.attachmentName(row));
|
|
|
|
|
},
|
|
|
|
|
async downloadKingdeeAttachment(row) {
|
|
|
|
|
if (this.kingdeeBusy) return;
|
|
|
|
|
this.kingdeeBusy = true;
|
|
|
|
|
try {
|
|
|
|
|
await downloadKingdeeInvoiceFile(this.kingdeeInvoiceNoOf(row), this.attachmentName(row));
|
|
|
|
|
} finally {
|
|
|
|
|
this.kingdeeBusy = false;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
batchDownload() {
|
|
|
|
|
const rows = this.selectedRows.length ? this.selectedRows : this.rows;
|
|
|
|
|
const downloadableRows = rows.filter(row => 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;
|
|
|
|
|