文字文件预览和删除

This commit is contained in:
砂糖
2025-08-01 14:46:43 +08:00
parent 8a75ab2dba
commit 21e354258e
2 changed files with 272 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
import request from '@/utils/request'
// 模拟获取文件列表
export function listFile() {
return request({
url: '/wms/file/list',
method: 'get'
})
}
export function getFileStats() {
return request({
url: `/wms/file/stats`,
method: 'get'
})
}
export function deleteFile(fileName) {
return request({
url: `/wms/file/delete/${fileName}`,
method: 'delete'
})
}
export function getFileContent(fileName) {
return request({
url: `/wms/file/content/${fileName}`,
method: 'get',
})
}
// 清除三个月的内的文件
export function clearUp() {
return request({
url: `/wms/file/cleanup`,
method: 'delete'
})
}
// 批量删除文件
export function batchDeleteFile(fileNames) {
return request({
url: `/wms/file/batch-delete`,
method: 'post',
data: fileNames
})
}

View File

@@ -0,0 +1,225 @@
<template>
<div style="display: flex; height: calc(100vh - 84px);">
<!-- 左侧文件列表 -->
<div style="width: 250px; border-right: 1px solid #eee; overflow-y: auto;">
<div style="padding: 8px 16px; border-bottom: 1px solid #eee; display: flex; gap: 8px; align-items: center;">
<button @click="handleClearAll" style="background: #f56c6c; color: #fff; border: none; border-radius: 3px; padding: 4px 10px; cursor: pointer;">清空全部</button>
</div>
<div v-if="loadingList" style="padding: 24px; color: #888; text-align: center;">文件列表加载中...</div>
<ul v-else style="list-style: none; padding: 0; margin: 0;">
<template v-for="(group, groupName) in groupedFiles">
<li style="background:#f5f5f5; color:#888; font-weight:bold; padding:8px 16px; display: flex; align-items: center; justify-content: space-between;">
<span>{{ groupName }}</span>
<button @click.stop="handleClearGroup(groupName)" style="background: #e6a23c; color: #fff; border: none; border-radius: 3px; padding: 2px 8px; font-size: 12px; cursor: pointer;">清空分组</button>
</li>
<li v-for="file in group" :key="file.fileName"
:style="{padding: '12px 16px', cursor: 'pointer', background: file.fileName === selectedFileName ? '#f0f0f0' : ''}"
@click="selectFile(file)">
{{ file.fileName }}
<span style="float: right; color: #f56c6c; cursor: pointer;" @click.stop="handleDeleteFile(file)">删除</span>
</li>
</template>
</ul>
</div>
<!-- 右侧文件预览 -->
<div style="flex: 1; padding: 24px; overflow-y: auto;">
<div v-if="loadingContent" style="color: #888;">内容加载中...</div>
<div v-else-if="selectedFile">
<h3>{{ selectedFile.fileName }}</h3>
<template v-if="selectedFile.fileType === 'text'">
<pre style="background: #fafafa; padding: 16px; border-radius: 4px; min-height: 300px;">{{ selectedFile.fileContent }}</pre>
</template>
<!-- <template v-else-if="selectedFile.fileType === 'image'">
<div style="padding: 16px; background: #fafafa; border-radius: 4px; min-height: 300px; display: flex; align-items: center; justify-content: center;">
<img :src="selectedFile.fileContent" alt="图片预览" style="max-width: 100%; max-height: 600px;" />
</div>
</template> -->
<template v-else>
<div style="background: #fafafa; padding: 16px; border-radius: 4px; min-height: 300px; color: #f56c6c;">{{ selectedFile.fileContent }}</div>
</template>
</div>
<div v-else style="color: #888;">请选择左侧文件进行预览</div>
</div>
</div>
</template>
<script>
import { listFile, getFileStats, deleteFile, getFileContent, clearUp, batchDeleteFile } from '@/api/mes/qc/files';
export default {
name: 'FilePreview',
data() {
return {
files: [],
selectedFile: null,
selectedFileName: '',
loadingList: false,
loadingContent: false,
};
},
created() {
this.fetchFileList();
getFileStats()
},
computed: {
groupedFiles() {
// 分组规则
const groups = {
'今天': [],
'昨天': [],
'一周内': [],
'本月': [],
'近三个月': [],
'更久': [],
};
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const yesterday = new Date(today);
yesterday.setDate(today.getDate() - 1);
const weekAgo = new Date(today);
weekAgo.setDate(today.getDate() - 6);
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
const threeMonthsAgo = new Date(now.getFullYear(), now.getMonth() - 2, 1);
(this.files || []).forEach(file => {
const d = file.lastModified ? new Date(file.lastModified) : null;
if (!d) {
groups['更久'].push(file);
return;
}
if (d >= today) {
groups['今天'].push(file);
} else if (d >= yesterday) {
groups['昨天'].push(file);
} else if (d >= weekAgo) {
groups['一周内'].push(file);
} else if (d >= monthStart) {
groups['本月'].push(file);
} else if (d >= threeMonthsAgo) {
groups['近三个月'].push(file);
} else {
groups['更久'].push(file);
}
});
// 只返回有文件的分组
return Object.fromEntries(Object.entries(groups).filter(([k, v]) => v.length));
}
},
methods: {
// 清空全部文件
async handleClearAll() {
if (!this.files.length) return this.$message.info('没有可删除的文件');
this.$confirm('确定要清空全部文件吗?此操作不可恢复!', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
const names = this.files.map(f => f.fileName);
await this.batchDelete(names);
}).catch(() => {});
},
// 清空某个分组
async handleClearGroup(groupName) {
const group = this.groupedFiles[groupName] || [];
if (!group.length) return this.$message.info('该分组没有可删除的文件');
this.$confirm(`确定要清空分组“${groupName}”下的所有文件吗?`, '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
const names = group.map(f => f.fileName);
await this.batchDelete(names);
}).catch(() => {});
},
// 批量删除
async batchDelete(names) {
if (!names.length) return;
this.loadingList = true;
try {
if (typeof this.$api?.mes?.qc?.files?.batchDeleteFile === 'function') {
await this.$api.mes.qc.files.batchDeleteFile(names);
} else if (typeof batchDeleteFile === 'function') {
await batchDeleteFile(names);
} else {
// fallback: 单个删除
for (const name of names) {
await deleteFile(name);
}
}
this.$message.success('删除成功');
this.fetchFileList();
} catch (e) {
this.$message.error('批量删除失败: ' + (e.message || '未知错误'));
} finally {
this.loadingList = false;
}
},
async fetchFileList() {
this.loadingList = true;
this.files = [];
this.selectedFile = null;
this.selectedFileName = '';
try {
const res = await listFile();
console.log('文件列表:', res);
this.files = res.data || [];
} finally {
this.loadingList = false;
}
},
async selectFile(file) {
this.selectedFileName = file.fileName;
this.selectedFile = null;
this.loadingContent = true;
try {
const isText = /\.(txt|md|json|js|ts|log|csv|xml|html|css)$/i.test(file.fileName);
const isImage = /\.(png|jpe?g|gif|bmp|webp|svg)$/i.test(file.fileName);
if (isText) {
const textResult = await getFileContent(file.fileName)
this.selectedFile = {...textResult.data, fileType: 'text'};
}
// else if (isImage) {
// // 图片文件
// let blob = null;
// if (typeof this.$options.components?.getFileContent === 'function') {
// blob = await this.$options.components.getFileContent(file.fileName);
// } else if (typeof window.getFileContent === 'function') {
// blob = await window.getFileContent(file.fileName);
// }
// // blob 可能是base64字符串或Blob对象需适配
// let imgUrl = '';
// if (blob instanceof Blob) {
// imgUrl = URL.createObjectURL(blob);
// } else if (typeof blob === 'string' && blob.startsWith('data:image')) {
// imgUrl = blob;
// } else if (typeof blob === 'string') {
// // 假设后端返回base64
// imgUrl = 'data:image/*;base64,' + blob;
// }
// this.selectedFile = { fileName: file.fileName, fileContent: imgUrl, fileType: 'image' };
// }
else {
this.selectedFile = { fileName: file.fileName, fileContent: '不支持的文件类型', fileType: 'other' };
}
} finally {
this.loadingContent = false;
}
},
handleDeleteFile(file) {
deleteFile(file.fileName)
.then(() => {
this.$message.success('文件删除成功');
this.fetchFileList(); // 重新加载文件列表
})
.catch(err => {
this.$message.error('删除文件失败: ' + (err.message || '未知错误'));
});
}
},
};
</script>
<style scoped>
/* 可根据需要自定义样式 */
</style>