feat: 文件归档功能改为弹窗显示文件列表
- 新增 FileArchiveDialog.vue 弹窗组件,显示项目所有文件 - 弹窗顶部增加下载按钮,点击可打包下载全部文件 - 修改 handleArchive 方法,改为打开弹窗而非直接下载 - 新增 listDownloadUrls API 获取文件列表
This commit is contained in:
@@ -347,3 +347,15 @@ export function downloadFileById(fileId: string) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取文件下载地址列表
|
||||
* @param purchaseId 采购申请ID
|
||||
*/
|
||||
export function listDownloadUrls(purchaseId: string | number) {
|
||||
return request({
|
||||
url: '/purchase/purchasingfiles/listDownloadUrls',
|
||||
method: 'get',
|
||||
params: { purchaseId }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
185
src/views/purchase/purchasingrequisition/FileArchiveDialog.vue
Normal file
185
src/views/purchase/purchasingrequisition/FileArchiveDialog.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
title="文件归档"
|
||||
width="900px"
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
>
|
||||
<template #header>
|
||||
<div class="dialog-header">
|
||||
<span class="dialog-title">
|
||||
<el-icon><FolderOpened /></el-icon>
|
||||
文件归档 - {{ purchaseNo || purchaseId }}
|
||||
</span>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="downloading"
|
||||
@click="handleDownloadAll"
|
||||
>
|
||||
<el-icon><Download /></el-icon>
|
||||
下载全部文件
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="fileList"
|
||||
stripe
|
||||
border
|
||||
max-height="500px"
|
||||
class="file-table"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="fileTitle" label="文件名称" min-width="250" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<div class="file-name">
|
||||
<el-icon class="file-icon"><Document /></el-icon>
|
||||
<span>{{ row.fileTitle }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fileTypeDesc" label="文件类型" width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="info">{{ row.fileTypeDesc || '未知类型' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Download"
|
||||
@click="handleDownloadFile(row)"
|
||||
>
|
||||
下载
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div v-if="!loading && fileList.length === 0" class="empty-tip">
|
||||
<el-empty description="暂无文件" />
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { FolderOpened, Download, Document } from '@element-plus/icons-vue'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { listDownloadUrls, getArchiveDownloadUrl } from '/@/api/purchase/purchasingrequisition'
|
||||
import other from '/@/utils/other'
|
||||
|
||||
interface FileItem {
|
||||
id: string
|
||||
fileTitle: string
|
||||
fileType: string
|
||||
fileTypeDesc: string
|
||||
downloadUrl: string
|
||||
}
|
||||
|
||||
const visible = ref(false)
|
||||
const loading = ref(false)
|
||||
const downloading = ref(false)
|
||||
const purchaseId = ref('')
|
||||
const purchaseNo = ref('')
|
||||
const fileList = ref<FileItem[]>([])
|
||||
|
||||
const open = async (id: string, no?: string) => {
|
||||
purchaseId.value = id || ''
|
||||
purchaseNo.value = no || ''
|
||||
visible.value = true
|
||||
await loadFileList()
|
||||
}
|
||||
|
||||
const loadFileList = async () => {
|
||||
if (!purchaseId.value) {
|
||||
useMessage().warning('无法获取采购申请ID')
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await listDownloadUrls(purchaseId.value)
|
||||
if (res && res.data) {
|
||||
fileList.value = res.data as FileItem[]
|
||||
} else {
|
||||
fileList.value = []
|
||||
}
|
||||
} catch (err: any) {
|
||||
useMessage().error(err?.msg || '获取文件列表失败')
|
||||
fileList.value = []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleDownloadFile = (row: FileItem) => {
|
||||
if (row.downloadUrl) {
|
||||
window.open(row.downloadUrl, '_blank')
|
||||
} else {
|
||||
useMessage().warning('文件下载地址不存在')
|
||||
}
|
||||
}
|
||||
|
||||
const handleDownloadAll = () => {
|
||||
if (!purchaseId.value) {
|
||||
useMessage().warning('无法获取采购申请ID')
|
||||
return
|
||||
}
|
||||
downloading.value = true
|
||||
try {
|
||||
const url = getArchiveDownloadUrl(purchaseId.value)
|
||||
const fileName = `归档_${purchaseNo.value || purchaseId.value}.zip`
|
||||
other.downBlobFile(url, {}, fileName)
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
downloading.value = false
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
.file-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
padding: 40px 0;
|
||||
}
|
||||
</style>
|
||||
@@ -289,9 +289,12 @@
|
||||
<FlowCommentTimeline v-if="currFlowJob" :key="String(currFlowJob.flowInstId) + currFlowCommentType" :curr-job="currFlowJob" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 实施采购:iframe 嵌入 implement.vue,供列表与流程页面使用 -->
|
||||
<!-- 实施采购:iframe 嵌入 implement.vue,供列表与流程页面使用 -->
|
||||
<ImplementForm ref="implementFormRef" @refresh="getDataList" />
|
||||
|
||||
<!-- 文件归档弹窗 -->
|
||||
<FileArchiveDialog ref="fileArchiveDialogRef" />
|
||||
|
||||
<!-- 招标文件审核弹窗 -->
|
||||
<!-- <DocAuditDialog ref="docAuditDialogRef" @refresh="getDataList" />-->
|
||||
|
||||
@@ -345,7 +348,7 @@
|
||||
import { ref, reactive, defineAsyncComponent, onMounted, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { getPage, delObj, submitObj, getArchiveDownloadUrl, getApplyTemplateDownloadUrl, getFileApplyTemplateDownloadUrl, getDeptMembers, saveRepresentor } from "/@/api/purchase/purchasingrequisition";
|
||||
import { getPage, delObj, submitObj, getApplyTemplateDownloadUrl, getFileApplyTemplateDownloadUrl, getDeptMembers, saveRepresentor, listDownloadUrls } from "/@/api/purchase/purchasingrequisition";
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||
import { useAuth } from '/@/hooks/auth';
|
||||
import { getDicts } from '/@/api/admin/dict';
|
||||
@@ -365,6 +368,7 @@ const ImplementForm = defineAsyncComponent(() => import('./implementForm.vue'));
|
||||
const ActionDropdown = defineAsyncComponent(() => import('/@/components/tools/action-dropdown.vue'));
|
||||
const PurchasingAcceptModal = defineAsyncComponent(() => import('./accept/PurchasingAcceptModal.vue'));
|
||||
const FlowCommentTimeline = defineAsyncComponent(() => import('/@/views/jsonflow/comment/timeline.vue'));
|
||||
const FileArchiveDialog = defineAsyncComponent(() => import('./FileArchiveDialog.vue'));
|
||||
// const DocAuditDialog = defineAsyncComponent(() => import('./docAudit/DocAuditDialog.vue'));
|
||||
|
||||
// 字典数据和品目树数据
|
||||
@@ -393,6 +397,7 @@ const currFlowJob = ref<{ id?: number; flowInstId?: number } | null>(null)
|
||||
const currFlowCommentType = ref<'apply' | 'file'>('apply')
|
||||
|
||||
const implementFormRef = ref()
|
||||
const fileArchiveDialogRef = ref()
|
||||
|
||||
/** 采购代表弹窗 */
|
||||
const representorDialogVisible = ref(false)
|
||||
@@ -713,16 +718,14 @@ const handleDownloadFileApply = (row: any) => {
|
||||
other.downBlobFile(url, {}, fileName);
|
||||
};
|
||||
|
||||
/** 文件归档:按文件类型打包下载该申请单下所有附件 */
|
||||
/** 文件归档:打开弹窗查看文件列表,支持打包下载 */
|
||||
const handleArchive = (row: any) => {
|
||||
const id = row?.id ?? row?.purchaseId;
|
||||
if (id == null || id === '') {
|
||||
useMessage().warning('无法获取申请单ID');
|
||||
return;
|
||||
}
|
||||
const url = getArchiveDownloadUrl(id);
|
||||
const fileName = `归档_${row?.purchaseNo || id}.zip`;
|
||||
other.downBlobFile(url, {}, fileName);
|
||||
fileArchiveDialogRef.value?.open(String(id), row?.purchaseNo);
|
||||
};
|
||||
|
||||
// 获取字典数据和品目树数据
|
||||
|
||||
Reference in New Issue
Block a user