This commit is contained in:
吴红兵
2026-03-07 12:35:45 +08:00
parent 271710e870
commit b997b3ba48
423 changed files with 79612 additions and 91574 deletions

View File

@@ -1,280 +1,236 @@
<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-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="220" 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="160" align="center">
<template #default="{ row }">
<el-tag type="info">{{ row.fileTypeDesc || '未知类型' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="{ row }">
<el-button
type="primary"
link
icon="View"
@click="handlePreview(row)"
>
预览
</el-button>
<el-button
type="primary"
link
icon="Download"
@click="handleDownloadFile(row)"
>
下载
</el-button>
</template>
</el-table-column>
</el-table>
<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="220" 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="160" align="center">
<template #default="{ row }">
<el-tag type="info">{{ row.fileTypeDesc || '未知类型' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="{ row }">
<el-button type="primary" link icon="View" @click="handlePreview(row)"> 预览 </el-button>
<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>
<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 #footer>
<el-button @click="visible = false">关闭</el-button>
</template>
</el-dialog>
<!-- PDF预览弹窗 -->
<el-dialog
v-model="previewVisible"
title="文件预览"
width="90%"
top="5vh"
destroy-on-close
append-to-body
class="preview-dialog"
>
<div class="preview-container">
<iframe
v-if="previewUrl"
:src="previewUrl"
class="preview-iframe"
frameborder="0"
/>
</div>
</el-dialog>
<!-- PDF预览弹窗 -->
<el-dialog v-model="previewVisible" title="文件预览" width="90%" top="5vh" destroy-on-close append-to-body class="preview-dialog">
<div class="preview-container">
<iframe v-if="previewUrl" :src="previewUrl" class="preview-iframe" frameborder="0" />
</div>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, computed, onUnmounted } from 'vue'
import { FolderOpened, Download, Document } from '@element-plus/icons-vue'
import { useMessage } from '/@/hooks/message'
import { listDownloadUrls, getArchiveDownloadUrl, downloadFileById, previewFileById } from '/@/api/purchase/purchasingrequisition'
import other from '/@/utils/other'
import { ref, computed, onUnmounted } from 'vue';
import { FolderOpened, Download, Document } from '@element-plus/icons-vue';
import { useMessage } from '/@/hooks/message';
import { listDownloadUrls, getArchiveDownloadUrl, downloadFileById, previewFileById } from '/@/api/purchase/purchasingrequisition';
import other from '/@/utils/other';
interface FileItem {
id: string
fileTitle: string
fileType: string
fileTypeDesc: string
downloadUrl: string
id: string;
fileTitle: string;
fileType: string;
fileTypeDesc: string;
downloadUrl: string;
}
const visible = ref(false)
const loading = ref(false)
const downloading = ref(false)
const previewVisible = ref(false)
const previewUrl = ref('')
const previewLoading = ref(false)
const purchaseId = ref('')
const purchaseNo = ref('')
const fileList = ref<FileItem[]>([])
const visible = ref(false);
const loading = ref(false);
const downloading = ref(false);
const previewVisible = ref(false);
const previewUrl = ref('');
const previewLoading = 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()
}
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
}
}
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 isPdfFile = (fileName: string): boolean => {
if (!fileName) return false
const ext = fileName.toLowerCase().split('.').pop()
return ext === 'pdf'
}
if (!fileName) return false;
const ext = fileName.toLowerCase().split('.').pop();
return ext === 'pdf';
};
const handlePreview = async (row: FileItem) => {
if (!row.id) {
useMessage().warning('文件ID不存在')
return
}
if (!row.id) {
useMessage().warning('文件ID不存在');
return;
}
if (!isPdfFile(row.fileTitle)) {
useMessage().info('仅支持PDF格式文件预览将为您下载文件')
handleDownloadFile(row)
return
}
if (!isPdfFile(row.fileTitle)) {
useMessage().info('仅支持PDF格式文件预览将为您下载文件');
handleDownloadFile(row);
return;
}
previewLoading.value = true
previewVisible.value = true
previewUrl.value = ''
previewLoading.value = true;
previewVisible.value = true;
previewUrl.value = '';
try {
const res = await previewFileById(row.id)
const blob = res as unknown as Blob
const url = window.URL.createObjectURL(blob)
previewUrl.value = url
} catch (err: any) {
useMessage().error(err?.msg || '预览失败')
previewVisible.value = false
} finally {
previewLoading.value = false
}
}
try {
const res = await previewFileById(row.id);
const blob = res as unknown as Blob;
const url = window.URL.createObjectURL(blob);
previewUrl.value = url;
} catch (err: any) {
useMessage().error(err?.msg || '预览失败');
previewVisible.value = false;
} finally {
previewLoading.value = false;
}
};
const handleDownloadFile = async (row: FileItem) => {
if (!row.id) {
useMessage().warning('文件ID不存在')
return
}
try {
const res = await downloadFileById(row.id)
const blob = res as unknown as Blob
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = row.fileTitle || 'download'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
} catch (err: any) {
useMessage().error(err?.msg || '下载失败')
}
}
if (!row.id) {
useMessage().warning('文件ID不存在');
return;
}
try {
const res = await downloadFileById(row.id);
const blob = res as unknown as Blob;
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = row.fileTitle || 'download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
} catch (err: any) {
useMessage().error(err?.msg || '下载失败');
}
};
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)
}
}
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);
}
};
onUnmounted(() => {
if (previewUrl.value) {
window.URL.revokeObjectURL(previewUrl.value)
}
})
if (previewUrl.value) {
window.URL.revokeObjectURL(previewUrl.value);
}
});
defineExpose({
open
})
open,
});
</script>
<style scoped lang="scss">
.dialog-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
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;
display: flex;
align-items: center;
gap: 8px;
font-size: 16px;
font-weight: 500;
}
.file-table {
width: 100%;
width: 100%;
}
.file-name {
display: flex;
align-items: center;
gap: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.file-icon {
color: #409eff;
color: #409eff;
}
.empty-tip {
padding: 40px 0;
padding: 40px 0;
}
.preview-container {
width: 100%;
height: calc(90vh - 120px);
width: 100%;
height: calc(90vh - 120px);
}
.preview-iframe {
width: 100%;
height: 100%;
width: 100%;
height: 100%;
}
</style>