fix
This commit is contained in:
@@ -392,3 +392,27 @@ export function updateFiles(data: { purchaseId: string; fileIds: string[] }) {
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function tempStoreSupplement(applyId: string, fileIds: string[]) {
|
||||
return request({
|
||||
url: '/purchase/purchasingapply/supplement/temp-store',
|
||||
method: 'post',
|
||||
data: { applyId, fileIds },
|
||||
});
|
||||
}
|
||||
|
||||
export function submitSupplement(applyId: string) {
|
||||
return request({
|
||||
url: '/purchase/purchasingapply/supplement/submit',
|
||||
method: 'post',
|
||||
data: { id: applyId },
|
||||
});
|
||||
}
|
||||
|
||||
export function getSupplementFileType(purchaseType: string) {
|
||||
return request({
|
||||
url: '/purchase/purchasingapply/supplement/file-type',
|
||||
method: 'get',
|
||||
params: { purchaseType },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="补充材料" width="900px" destroy-on-close append-to-body :close-on-click-modal="false">
|
||||
<template #header>
|
||||
<div class="dialog-header">
|
||||
<span class="dialog-title">
|
||||
<el-icon><Upload /></el-icon>
|
||||
补充材料 - {{ applyData.purchaseNo || applyId }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-descriptions :column="2" border class="apply-info">
|
||||
<el-descriptions-item label="采购编号">{{ applyData.purchaseNo || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购项目名称">{{ applyData.projectName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购金额">{{ applyData.budget ? Number(applyData.budget).toLocaleString() + ' 元' : '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购方式">{{ purchaseTypeLabelComputed || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购内容" :span="2">{{ applyData.projectContent || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-divider content-position="left">采购相关文件补充上传</el-divider>
|
||||
|
||||
<el-alert
|
||||
:type="fileTypeAlertType"
|
||||
:closable="false"
|
||||
style="margin-bottom: 16px"
|
||||
>
|
||||
<template #title>
|
||||
<span v-if="requiredFileType">{{ requiredFileTypeName }}必传</span>
|
||||
<span v-else>当前采购方式无需补充材料</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
|
||||
<el-form v-if="requiredFileType" label-width="140px">
|
||||
<el-form-item :label="requiredFileTypeName" required>
|
||||
<upload-file
|
||||
v-model="fileList"
|
||||
:limit="1"
|
||||
:file-type="['pdf']"
|
||||
:data="{ fileType: requiredFileType, purchaseId: applyId }"
|
||||
upload-file-url="/purchase/purchasingfiles/upload"
|
||||
/>
|
||||
<div class="file-tips">{{ fileTips }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-empty v-else description="当前采购方式无需补充材料" />
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" :disabled="!requiredFileType" @click="handleTempStore">暂存</el-button>
|
||||
<el-button type="success" :loading="submitting" :disabled="!canSubmit" @click="handleSubmit">提交</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { Upload } from '@element-plus/icons-vue';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import { getObj, tempStoreSupplement, submitSupplement, getSupplementFileType, getApplyFiles } from '/@/api/purchase/purchasingrequisition';
|
||||
import { getDicts } from '/@/api/admin/dict';
|
||||
|
||||
interface FileItem {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
const visible = ref(false);
|
||||
const submitting = ref(false);
|
||||
const applyId = ref('');
|
||||
const applyData = ref<any>({});
|
||||
const requiredFileType = ref('');
|
||||
const fileList = ref<FileItem[]>([]);
|
||||
const purchaseTypeDeptList = ref<any[]>([]);
|
||||
|
||||
const PURCHASE_TYPE_DEPT_MAP: Record<string, string> = {
|
||||
'1': '网上商城',
|
||||
'2': '市场采购',
|
||||
'3': '商务洽谈',
|
||||
'5': '询价',
|
||||
};
|
||||
|
||||
const purchaseTypeLabelComputed = computed(() => {
|
||||
if (applyData.value.purchaseTypeLabel) {
|
||||
return applyData.value.purchaseTypeLabel;
|
||||
}
|
||||
if (applyData.value.purchaseType) {
|
||||
const found = purchaseTypeDeptList.value.find((item: any) => item.value === applyData.value.purchaseType);
|
||||
if (found) {
|
||||
return found.label;
|
||||
}
|
||||
return PURCHASE_TYPE_DEPT_MAP[applyData.value.purchaseType] || applyData.value.purchaseType;
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
const fileTypeMap: Record<string, { name: string; tips: string }> = {
|
||||
'10': { name: '商务洽谈纪要', tips: '请上传商务洽谈相关纪要文件(PDF格式)' },
|
||||
'20': { name: '市场采购纪要', tips: '请上传市场采购相关纪要文件(PDF格式)' },
|
||||
'30': { name: '网上商城采购材料', tips: '请上传网上商城采购相关材料(PDF格式)' },
|
||||
'150': { name: '部门采购询价表', tips: '请上传部门采购询价表(PDF格式)' },
|
||||
};
|
||||
|
||||
const requiredFileTypeName = computed(() => {
|
||||
if (!requiredFileType.value) return '';
|
||||
return fileTypeMap[requiredFileType.value]?.name || '补充材料';
|
||||
});
|
||||
|
||||
const fileTips = computed(() => {
|
||||
if (!requiredFileType.value) return '';
|
||||
return fileTypeMap[requiredFileType.value]?.tips || '请上传PDF格式文件';
|
||||
});
|
||||
|
||||
const fileTypeAlertType = computed(() => {
|
||||
return requiredFileType.value ? 'warning' : 'info';
|
||||
});
|
||||
|
||||
const canSubmit = computed(() => {
|
||||
return requiredFileType.value && fileList.value.length > 0;
|
||||
});
|
||||
|
||||
const loadDictData = async () => {
|
||||
try {
|
||||
const res = await getDicts('PURCHASE_TYPE_DEPT');
|
||||
if (res.data && Array.isArray(res.data)) {
|
||||
purchaseTypeDeptList.value = res.data.map((item: any) => ({
|
||||
label: item.label || item.dictLabel || item.name,
|
||||
value: item.value || item.dictValue || item.code,
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载字典数据失败', e);
|
||||
}
|
||||
};
|
||||
|
||||
const open = async (id: string) => {
|
||||
applyId.value = id || '';
|
||||
visible.value = true;
|
||||
fileList.value = [];
|
||||
requiredFileType.value = '';
|
||||
applyData.value = {};
|
||||
|
||||
await loadDictData();
|
||||
|
||||
try {
|
||||
const res = await getObj(id);
|
||||
const data = res?.data || {};
|
||||
applyData.value = data;
|
||||
|
||||
if (data.purchaseType) {
|
||||
const fileTypeRes = await getSupplementFileType(data.purchaseType);
|
||||
requiredFileType.value = fileTypeRes?.data || '';
|
||||
}
|
||||
|
||||
if (requiredFileType.value) {
|
||||
const filesRes = await getApplyFiles(id);
|
||||
const files = filesRes?.data || [];
|
||||
const matchingFiles = files.filter((f: any) => String(f.fileType) === requiredFileType.value);
|
||||
if (matchingFiles.length > 0) {
|
||||
fileList.value = matchingFiles.map((f: any) => ({
|
||||
id: f.id,
|
||||
name: f.fileTitle || f.fileName || '附件',
|
||||
url: f.fileUrl,
|
||||
}));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取采购申请详情失败', e);
|
||||
useMessage().error('获取采购申请详情失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleTempStore = async () => {
|
||||
if (!applyId.value) {
|
||||
useMessage().warning('无法获取采购申请ID');
|
||||
return;
|
||||
}
|
||||
|
||||
const fileIds = fileList.value.filter((f) => f.id).map((f) => f.id);
|
||||
if (fileIds.length === 0) {
|
||||
useMessage().warning('请先上传补充材料');
|
||||
return;
|
||||
}
|
||||
|
||||
submitting.value = true;
|
||||
try {
|
||||
await tempStoreSupplement(applyId.value, fileIds);
|
||||
useMessage().success('暂存成功');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err?.msg || '暂存失败');
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!applyId.value) {
|
||||
useMessage().warning('无法获取采购申请ID');
|
||||
return;
|
||||
}
|
||||
|
||||
submitting.value = true;
|
||||
try {
|
||||
await submitSupplement(applyId.value);
|
||||
useMessage().success('提交成功,流程已启动');
|
||||
visible.value = false;
|
||||
emit('refresh');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err?.msg || '提交失败');
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'refresh'): void;
|
||||
}>();
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.dialog-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.apply-info {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.file-tips {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
@@ -292,6 +292,9 @@
|
||||
<!-- 合同弹窗 -->
|
||||
<ContractDialog ref="contractDialogRef" @refresh="getDataList" />
|
||||
|
||||
<!-- 补充材料弹窗 -->
|
||||
<SupplementFilesDialog ref="supplementFilesDialogRef" @refresh="getDataList" />
|
||||
|
||||
<!-- 招标文件审核弹窗 -->
|
||||
<!-- <DocAuditDialog ref="docAuditDialogRef" @refresh="getDataList" />-->
|
||||
|
||||
@@ -405,6 +408,7 @@ const FlowCommentTimeline = defineAsyncComponent(() => import('/@/views/jsonflow
|
||||
const FileArchiveDialog = defineAsyncComponent(() => import('./FileArchiveDialog.vue'));
|
||||
const UpdateFilesDialog = defineAsyncComponent(() => import('./UpdateFilesDialog.vue'));
|
||||
const ContractDialog = defineAsyncComponent(() => import('./contract/ContractDialog.vue'));
|
||||
const SupplementFilesDialog = defineAsyncComponent(() => import('./SupplementFilesDialog.vue'));
|
||||
// const DocAuditDialog = defineAsyncComponent(() => import('./docAudit/DocAuditDialog.vue'));
|
||||
|
||||
// 字典数据和品目树数据
|
||||
@@ -436,6 +440,7 @@ const implementFormRef = ref();
|
||||
const fileArchiveDialogRef = ref();
|
||||
const updateFilesDialogRef = ref();
|
||||
const contractDialogRef = ref();
|
||||
const supplementFilesDialogRef = ref();
|
||||
|
||||
/** 采购代表弹窗 */
|
||||
const representorDialogVisible = ref(false);
|
||||
@@ -712,6 +717,18 @@ const getActionMenuItems = (row: any) => {
|
||||
icon: DocumentChecked,
|
||||
visible: () => isCompleted,
|
||||
},
|
||||
{
|
||||
command: 'supplementFiles',
|
||||
label: '补充材料',
|
||||
icon: Upload,
|
||||
visible: () => isCompleted && row?.purchaseMode === '1' && row?.purchaseChannel === '1' && hasAuth('purchase_supplement'),
|
||||
},
|
||||
{
|
||||
command: 'submitSupplementFiles',
|
||||
label: '提交补充材料',
|
||||
icon: Upload,
|
||||
visible: () => isCompleted && row?.purchaseMode === '1' && row?.purchaseChannel === '1' && row?.supplementFlowStatus === '-1' && hasAuth('purchase_supplement'),
|
||||
},
|
||||
// {
|
||||
// command: 'downloadFileApply',
|
||||
// label: '下载文件审批表',
|
||||
@@ -773,6 +790,12 @@ const handleMoreCommand = (command: string, row: any) => {
|
||||
case 'contract':
|
||||
handleContract(row);
|
||||
break;
|
||||
case 'supplementFiles':
|
||||
handleSupplementFiles(row);
|
||||
break;
|
||||
case 'submitSupplementFiles':
|
||||
handleSubmitSupplementFiles(row);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -801,6 +824,26 @@ const handleContract = async (row: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
/** 补充材料 */
|
||||
const handleSupplementFiles = (row: any) => {
|
||||
const id = row?.id ?? row?.purchaseId;
|
||||
if (!id) {
|
||||
useMessage().warning('无法获取采购申请ID');
|
||||
return;
|
||||
}
|
||||
supplementFilesDialogRef.value?.open(String(id));
|
||||
};
|
||||
|
||||
/** 提交补充材料 */
|
||||
const handleSubmitSupplementFiles = async (row: any) => {
|
||||
const id = row?.id ?? row?.purchaseId;
|
||||
if (!id) {
|
||||
useMessage().warning('无法获取采购申请ID');
|
||||
return;
|
||||
}
|
||||
supplementFilesDialogRef.value?.open(String(id));
|
||||
};
|
||||
|
||||
/** 下载审批表 */
|
||||
const handleDownloadApply = (row: any) => {
|
||||
const id = row?.id ?? row?.purchaseId;
|
||||
|
||||
277
src/views/purchase/purchasingrequisition/supplement-view.vue
Normal file
277
src/views/purchase/purchasingrequisition/supplement-view.vue
Normal file
@@ -0,0 +1,277 @@
|
||||
<template>
|
||||
<div class="supplement-view-container">
|
||||
<el-card shadow="never" class="info-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon><Document /></el-icon>
|
||||
采购申请基本信息
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="采购编号">{{ applyData.purchaseNo || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购项目名称">{{ applyData.projectName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购金额">{{ applyData.budget ? Number(applyData.budget).toLocaleString() + ' 元' : '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购方式">{{ purchaseTypeLabel || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购内容" :span="2">{{ applyData.projectContent || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请人">{{ applyData.createByName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请部门">{{ applyData.deptName || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" class="file-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">
|
||||
<el-icon><FolderOpened /></el-icon>
|
||||
补充材料文件
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-alert
|
||||
v-if="requiredFileTypeName"
|
||||
type="info"
|
||||
:closable="false"
|
||||
style="margin-bottom: 16px"
|
||||
>
|
||||
<template #title>
|
||||
<span>{{ requiredFileTypeName }}</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
<el-table :data="fileList" border stripe v-if="fileList.length > 0">
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="name" label="文件名称" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link icon="View" @click="handlePreview(scope.row)">预览</el-button>
|
||||
<el-button type="success" link icon="Download" @click="handleDownload(scope.row)">下载</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-else description="暂无补充材料文件" />
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="previewVisible" :title="previewTitle" width="80%" top="5vh" destroy-on-close append-to-body>
|
||||
<div class="preview-container">
|
||||
<iframe v-if="previewUrl" :src="previewUrl" class="preview-iframe" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { Document, FolderOpened, Download } from '@element-plus/icons-vue';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import { getDicts } from '/@/api/admin/dict';
|
||||
import { previewFileById, downloadFileById } from '/@/api/purchase/purchasingrequisition';
|
||||
import { currElTabIsSave } from '/@/api/order/order-key-vue';
|
||||
import request from '/@/utils/request';
|
||||
|
||||
interface FileInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
currJob: { type: Object, default: null },
|
||||
currElTab: { type: Object, default: null },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['handleJob']);
|
||||
|
||||
const route = useRoute();
|
||||
const loading = ref(false);
|
||||
const applyData = ref<any>({});
|
||||
const fileList = ref<FileInfo[]>([]);
|
||||
const purchaseTypeLabel = ref('');
|
||||
const requiredFileTypeName = ref('');
|
||||
const previewVisible = ref(false);
|
||||
const previewTitle = ref('');
|
||||
const previewUrl = ref('');
|
||||
|
||||
const PURCHASE_TYPE_DEPT_MAP: Record<string, string> = {
|
||||
'1': '网上商城',
|
||||
'2': '市场采购',
|
||||
'3': '商务洽谈',
|
||||
'5': '询价',
|
||||
};
|
||||
|
||||
const FILE_TYPE_MAP: Record<string, string> = {
|
||||
'10': '商务洽谈纪要',
|
||||
'20': '市场采购纪要',
|
||||
'30': '网上商城采购材料',
|
||||
'150': '部门采购询价表',
|
||||
};
|
||||
|
||||
const loadDictData = async () => {
|
||||
try {
|
||||
const res = await getDicts('PURCHASE_TYPE_DEPT');
|
||||
if (res.data && Array.isArray(res.data)) {
|
||||
const list = res.data.map((item: any) => ({
|
||||
label: item.label || item.dictLabel || item.name,
|
||||
value: item.value || item.dictValue || item.code,
|
||||
}));
|
||||
if (applyData.value.purchaseType) {
|
||||
const found = list.find((item: any) => item.value === applyData.value.purchaseType);
|
||||
if (found) {
|
||||
purchaseTypeLabel.value = found.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载字典数据失败', e);
|
||||
}
|
||||
};
|
||||
|
||||
const getPurchaseTypeLabel = () => {
|
||||
if (applyData.value.purchaseType) {
|
||||
purchaseTypeLabel.value = PURCHASE_TYPE_DEPT_MAP[applyData.value.purchaseType] || applyData.value.purchaseType;
|
||||
}
|
||||
};
|
||||
|
||||
const getRequiredFileTypeName = () => {
|
||||
const purchaseType = applyData.value.purchaseType;
|
||||
let fileTypeCode = '';
|
||||
if (purchaseType === '3') {
|
||||
fileTypeCode = '10';
|
||||
} else if (purchaseType === '2') {
|
||||
fileTypeCode = '20';
|
||||
} else if (purchaseType === '1') {
|
||||
fileTypeCode = '30';
|
||||
} else if (purchaseType === '5') {
|
||||
fileTypeCode = '150';
|
||||
}
|
||||
if (fileTypeCode) {
|
||||
requiredFileTypeName.value = FILE_TYPE_MAP[fileTypeCode] || '补充材料';
|
||||
}
|
||||
return fileTypeCode;
|
||||
};
|
||||
|
||||
const loadData = async () => {
|
||||
const flowInstId = route.query.flowInstId as string;
|
||||
if (!flowInstId) {
|
||||
useMessage().warning('缺少流程实例ID');
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/purchase/purchasingapply/supplement/getByFlowInstId',
|
||||
method: 'get',
|
||||
params: { flowInstId },
|
||||
});
|
||||
applyData.value = res?.data || {};
|
||||
|
||||
await loadDictData();
|
||||
getPurchaseTypeLabel();
|
||||
const fileTypeCode = getRequiredFileTypeName();
|
||||
|
||||
if (applyData.value.id && fileTypeCode) {
|
||||
const filesRes = await request({
|
||||
url: '/purchase/purchasingfiles/listByType',
|
||||
method: 'get',
|
||||
params: { purchaseId: applyData.value.id, fileType: fileTypeCode },
|
||||
});
|
||||
const files = filesRes?.data || [];
|
||||
fileList.value = files.map((f: any) => ({
|
||||
id: f.id,
|
||||
name: f.fileTitle || f.fileName || '附件',
|
||||
url: f.fileUrl,
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取数据失败', e);
|
||||
useMessage().error('获取采购申请信息失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handlePreview = async (row: FileInfo) => {
|
||||
if (!row.id) {
|
||||
useMessage().warning('文件ID不存在');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const blob = await previewFileById(row.id);
|
||||
previewUrl.value = window.URL.createObjectURL(blob);
|
||||
previewTitle.value = row.name || '文件预览';
|
||||
previewVisible.value = true;
|
||||
} catch (e) {
|
||||
console.error('预览失败', e);
|
||||
useMessage().error('预览失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownload = async (row: FileInfo) => {
|
||||
if (!row.id) {
|
||||
useMessage().warning('文件ID不存在');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const blob = await downloadFileById(row.id);
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = row.name || '附件.pdf';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
} catch (e) {
|
||||
console.error('下载失败', e);
|
||||
useMessage().error('下载失败');
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadData();
|
||||
if (props.currJob && props.currElTab?.id) {
|
||||
currElTabIsSave(props.currJob, props.currElTab.id, true, emit);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.supplement-view-container {
|
||||
padding: 16px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.info-card,
|
||||
.file-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
width: 100%;
|
||||
height: 75vh;
|
||||
}
|
||||
|
||||
.preview-iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user