UNIVPLMDataIntegration/Web/src/views/system/file/index.vue
2024-07-11 01:32:03 +08:00

335 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="sys-file-container" v-loading="options.loading">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%">
<el-row :gutter="10">
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="文件名称" prop="fileName">
<el-input v-model="state.queryParams.fileName" placeholder="文件名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
</el-col>
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="开始时间" prop="name">
<el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="开始时间" value-format="YYYY-MM-DD HH:mm:ss" class="w100" />
</el-form-item>
</el-col>
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="结束时间" prop="code">
<el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="结束时间" value-format="YYYY-MM-DD HH:mm:ss" class="w100" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
<el-row>
<el-col>
<el-button-group>
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysFile:page'" :loading="options.loading"> 查询 </el-button>
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
</el-button-group>
</el-col>
</el-row>
</el-card>
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" v-on="gridEvents">
<template #toolbar_buttons>
<el-button type="primary" icon="ele-Plus" @click="showUpload" v-auth="'sysFile:uploadFile'"> 上传 </el-button>
</template>
<template #toolbar_tools> </template>
<template #empty>
<el-empty :image-size="200" />
</template>
<template #row_suffix="{ row }">
<el-tag round>{{ row.suffix }}</el-tag>
</template>
<template #row_url="{ row }">
<el-image
style="width: 60px; height: 60px"
:src="fetchFileUrl(row)"
alt="无法预览"
lazy
hide-on-click-modal
:preview-src-list="[fetchFileUrl(row)]"
:initial-index="0"
fit="scale-down"
preview-teleported
></el-image>
</template>
<template #row_buttons="{ row }">
<el-tooltip content="编辑" placement="top">
<el-button icon="ele-Edit" size="small" text type="primary" @click="handleEdit(row)" v-auth="'sysFile:update'" />
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button icon="ele-Delete" size="small" text type="danger" @click="handleDelete(row)" v-auth="'sysFile:delete'" />
</el-tooltip>
<el-tooltip content="预览" placement="top">
<el-button icon="ele-View" size="small" text type="primary" @click="showPreviewDialog(row)" v-auth="'sysFile:delete'" />
</el-tooltip>
<el-tooltip content="下载" placement="top">
<el-button icon="ele-Download" size="small" text type="primary" @click="handleDownload(row)" v-auth="'sysFile:downloadFile'" />
</el-tooltip>
</template>
</vxe-grid>
</el-card>
<el-dialog v-model="state.visible" :lock-scroll="false" draggable overflow destroy-on-close width="400px">
<template #header>
<div style="color: #fff">
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-UploadFilled /> </el-icon>
<span> 上传文件 </span>
</div>
</template>
<div>
<el-select v-model="state.fileType" placeholder="请选择文件类型" style="margin-bottom: 10px">
<el-option label="相关文件" value="相关文件" />
<el-option label="归档文件" value="归档文件" />
</el-select>
<el-upload ref="uploadRef" drag :auto-upload="false" :limit="1" :file-list="state.fileList" action="" :on-change="handleChange" accept=".jpg,.png,.bmp,.gif,.txt,.pdf,.xlsx,.docx">
<el-icon class="el-icon--upload">
<ele-UploadFilled />
</el-icon>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip">请上传大小不超过 10MB 的文件</div>
</template>
</el-upload>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="state.visible = false">取消</el-button>
<el-button type="primary" @click="handleUpload">确定</el-button>
</span>
</template>
</el-dialog>
<el-drawer :title="state.fileName" v-model="state.docxVisible" size="70%" destroy-on-close>
<vue-office-docx :src="state.docxUrl" style="height: calc(100vh - 37px)" @rendered="handleRendered" @error="handleError" />
</el-drawer>
<el-drawer :title="state.fileName" v-model="state.xlsxVisible" size="70%" destroy-on-close>
<vue-office-excel :src="state.excelUrl" style="height: calc(100vh - 37px)" @rendered="handleRendered" @error="handleError" />
</el-drawer>
<el-drawer :title="state.fileName" v-model="state.pdfVisible" size="70%" destroy-on-close>
<vue-office-pdf :src="state.pdfUrl" style="height: calc(100vh - 37px)" @rendered="handleRendered" @error="handleError" />
</el-drawer>
<el-image-viewer v-if="state.showViewer" :url-list="state.previewList" :hideOnClickModal="true" @close="state.showViewer = false"></el-image-viewer>
<EditFile ref="editRef" title="编辑文件" @handleQuery="handleQuery" />
</div>
</template>
<script lang="ts" setup name="sysFile">
import { onMounted, reactive, ref } from 'vue';
import { ElMessageBox, ElMessage, UploadInstance } from 'element-plus';
import { auth } from '/@/utils/authFunction';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import { downloadByUrl } from '/@/utils/download';
import VueOfficeDocx from '@vue-office/docx';
import VueOfficeExcel from '@vue-office/excel';
import VueOfficePdf from '@vue-office/pdf';
import '@vue-office/docx/lib/index.css';
import '@vue-office/excel/lib/index.css';
import EditFile from '/@/views/system/file/component/editFile.vue';
import { getAPI } from '/@/utils/axios-utils';
import { SysFileApi } from '/@/api-services/api';
import { SysFile, PageFileInput } from '/@/api-services/models';
const xGrid = ref<VxeGridInstance>();
// const baseUrl = window.__env__.VITE_API_URL;
const uploadRef = ref<UploadInstance>();
const editRef = ref<InstanceType<typeof EditFile>>();
const state = reactive({
queryParams: {
fileName: undefined,
startTime: undefined,
endTime: undefined,
},
localPageParam: {
pageSize: 50 as number,
defaultSort: { field: 'orderNo', order: 'asc', descStr: 'desc' },
},
visible: false,
diaglogEditFile: false,
fileList: [] as any,
docxVisible: false,
xlsxVisible: false,
pdfVisible: false,
showViewer: false,
docxUrl: '',
excelUrl: '',
pdfUrl: '',
fileName: '',
fileType: '',
previewList: [] as string[],
});
// 本地存储参数
const localPageParamKey = 'localPageParam:sysFile';
// 表格参数配置
const options = useVxeTable<SysFile>(
{
id: 'sysFile',
name: '文件信息',
columns: [
// { type: 'checkbox', width: 40, fixed: 'left' },
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
{ field: 'fileName', title: '名称', minWidth: 200, showOverflow: 'tooltip' },
{ field: 'suffix', title: '后缀', minWidth: 80, showOverflow: 'tooltip', slots: { default: 'row_suffix' } },
{ field: 'sizeKb', title: '大小(KB)', minWidth: 100, showOverflow: 'tooltip' },
{ field: 'url', title: '预览', minWidth: 100, slots: { default: 'row_url' } },
{ field: 'bucketName', title: '存储位置', minWidth: 180, showOverflow: 'tooltip' },
{ field: 'id', title: '存储标识', minWidth: 120, showOverflow: 'tooltip' },
{ field: 'fileType', title: '文件类型', minWidth: 140, showOverflow: 'tooltip' },
{ field: 'relationName', title: '关联对象名称', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'relationId', title: '关联对象ID', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'belongId', title: '所属ID', minWidth: 120, showOverflow: 'tooltip' },
// { field: 'userName', title: '上传者', minWidth: 150, showOverflow: 'tooltip', sortable: true },
{ field: 'createTime', title: '创建时间', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'remark', title: '备注', minWidth: 200, showOverflow: 'tooltip' },
{ title: '操作', fixed: 'right', width: 150, showOverflow: true, slots: { default: 'row_buttons' } },
],
},
// vxeGrid配置参数(此处可覆写任何参数)参考vxe-table官方文档
{
// 代理配置
proxyConfig: { autoLoad: true, ajax: { query: ({ page, sort }) => handleQueryApi(page, sort) } },
// 排序配置
sortConfig: { defaultSort: Local.get(localPageParamKey)?.defaultSort || state.localPageParam.defaultSort },
// 分页配置
pagerConfig: { pageSize: Local.get(localPageParamKey)?.pageSize || state.localPageParam.pageSize },
// 工具栏配置
toolbarConfig: { export: false },
// 行设置
rowConfig: { height: 80 },
}
);
// 页面初始化
onMounted(async () => {
await handleQuery();
});
// 查询api
const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, sort: VxeGridPropTypes.ProxyAjaxQuerySortCheckedParams) => {
const params = Object.assign(state.queryParams, { page: page.currentPage, pageSize: page.pageSize, field: sort.field, order: sort.order, descStr: 'desc' }) as PageFileInput;
return getAPI(SysFileApi).apiSysFilePagePost(params);
};
// 查询操作
const handleQuery = async () => {
await xGrid.value?.commitProxy('query');
};
// 重置操作
const resetQuery = async () => {
state.queryParams.fileName = undefined;
state.queryParams.startTime = undefined;
state.queryParams.endTime = undefined;
await xGrid.value?.commitProxy('reload');
};
// 打开上传页面
const showUpload = () => {
state.fileList = [];
state.visible = true;
};
// 通过onChanne方法获得文件列表
const handleChange = (file: any, fileList: []) => {
state.fileList = fileList;
};
// 上传
const handleUpload = async () => {
if (state.fileList.length < 1) return;
await getAPI(SysFileApi).apiSysFileUploadFilePostForm(state.fileList[0].raw, state.fileType, undefined);
handleQuery();
ElMessage.success('上传成功');
state.visible = false;
};
// 下载
const handleDownload = async (row: any) => {
// var res = await getAPI(SysFileApi).sysFileDownloadPost({ id: row.id });
var fileUrl = fetchFileUrl(row);
downloadByUrl({ url: fileUrl });
};
// 删除
const handleDelete = (row: any) => {
ElMessageBox.confirm(`确定删除文件:【${row.fileName}】?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
await getAPI(SysFileApi).apiSysFileDeletePost({ id: row.id });
handleQuery();
ElMessage.success('删除成功');
})
.catch(() => {});
};
// 表格事件
const gridEvents: VxeGridListeners<SysFile> = {
// 只对 pager-config 配置时有效,分页发生改变时会触发该事件
async pageChange({ pageSize }) {
state.localPageParam.pageSize = pageSize;
Local.set(localPageParamKey, state.localPageParam);
},
// 当排序条件发生变化时会触发该事件
async sortChange({ field, order }) {
state.localPageParam.defaultSort = { field: field, order: order!, descStr: 'desc' };
Local.set(localPageParamKey, state.localPageParam);
},
};
// 打开Pdf预览页面
const showPreviewDialog = async (row: any) => {
if (row.suffix == '.pdf') {
state.fileName = `${row.fileName}${row.suffix}`;
state.pdfUrl = fetchFileUrl(row);
state.pdfVisible = true;
} else if (row.suffix == '.docx') {
state.fileName = `${row.fileName}${row.suffix}`;
state.docxUrl = fetchFileUrl(row);
state.docxVisible = true;
} else if (row.suffix == '.xlsx') {
state.fileName = `${row.fileName}${row.suffix}`;
state.excelUrl = fetchFileUrl(row);
state.xlsxVisible = true;
} else if (['.jpg', '.png', '.jpeg', '.bmp'].findIndex((e) => e == row.suffix) > -1) {
state.previewList = [fetchFileUrl(row)];
state.showViewer = true;
} else {
ElMessage.error('此文件格式不支持预览');
}
};
// 获取文件地址
const fetchFileUrl = (row: SysFile): string => {
if (row.bucketName == 'Local') {
return `/${row.filePath}/${row.id}${row.suffix}`;
} else {
return row.url!;
}
};
// 打开编辑页面
const handleEdit = (row: any) => {
editRef.value?.openDialog(row);
};
// 文件渲染完成
const handleRendered = () => {};
// 文件渲染失败
const handleError = () => {};
</script>