feat(standardDocument): 添加文档上传功能和文件预览功能

- 新增附件上传组件,支持文档/PDF/压缩包上传,最大50MB
- 添加文档路径字段用于存储上传的文件路径
- 添加文档大小格式化显示功能,以B/KB/MB/GB单位显示
- 实现文件预览功能,点击附件链接可在新窗口打开文档
- 添加文件上传验证和错误处理机制
- 支持回车键搜索功能,在输入框中按Enter键触发搜索
- 优化表单按钮权限指令位置,提升代码可读性
- 添加文件列表管理和文件移除功能
- 实现上传进度提示和文件大小限制检查
master
zangch@mesnac.com 5 days ago
parent 6c83fb8d52
commit 9bb92479e2

@ -1,11 +1,11 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80">
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="80">
<el-form-item label="文档编号" prop="documentCode">
<el-input v-model="queryParams.documentCode" placeholder="请输入文档编号" clearable />
<el-input v-model="queryParams.documentCode" placeholder="请输入文档编号" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="文档名称" prop="documentName">
<el-input v-model="queryParams.documentName" placeholder="请输入文档名称" clearable />
<el-input v-model="queryParams.documentName" placeholder="请输入文档名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
@ -15,16 +15,16 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['base:standardDocument:add']"></el-button>
<el-button v-hasPermi="['base:standardDocument:add']" type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['base:standardDocument:edit']"></el-button>
<el-button v-hasPermi="['base:standardDocument:edit']" type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['base:standardDocument:remove']"></el-button>
<el-button v-hasPermi="['base:standardDocument:remove']" type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['base:standardDocument:export']"></el-button>
<el-button v-hasPermi="['base:standardDocument:export']" type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"></el-button>
</el-col>
</el-row>
@ -36,13 +36,26 @@
<el-table-column label="产品编号" align="center" prop="productCode" />
<el-table-column label="产品名称" align="center" prop="productName" />
<el-table-column label="版本号" align="center" prop="versionNo" />
<el-table-column label="文档大小" align="center" prop="documentSize" />
<el-table-column label="附件" align="center" min-width="180">
<template slot-scope="scope">
<el-link v-if="scope.row.documentPath" type="primary" :underline="false" @click="handlePreview(scope.row)">
{{ getFileName(scope.row.documentPath) }}
</el-link>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="文档大小" align="center" min-width="110">
<template slot-scope="scope">
<span>{{ formatFileSize(scope.row.documentSize) }}</span>
</template>
</el-table-column>
<el-table-column label="上传人" align="center" prop="uploader" />
<el-table-column label="状态" align="center" prop="status" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['base:standardDocument:edit']"></el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['base:standardDocument:remove']"></el-button>
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)"></el-button>
<el-button v-hasPermi="['base:standardDocument:edit']" size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"></el-button>
<el-button v-hasPermi="['base:standardDocument:remove']" size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
@ -69,17 +82,28 @@
<el-form-item label="版本号" prop="versionNo">
<el-input v-model="form.versionNo" placeholder="请输入版本号" />
</el-form-item>
<el-form-item label="文档路径" prop="documentPath">
<el-input v-model="form.documentPath" placeholder="请输入文档路径" />
</el-form-item>
<el-form-item label="文档大小" prop="documentSize">
<el-input-number v-model="form.documentSize" :min="0" />
<el-form-item label="附件上传" prop="documentPath">
<el-upload
:action="uploadUrl"
:headers="uploadHeaders"
:file-list="fileList"
:limit="1"
:before-upload="beforeUpload"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
:on-remove="handleFileRemove"
:on-exceed="handleExceed"
>
<el-button size="small" type="primary">选取文件</el-button>
<div slot="tip" class="el-upload__tip">支持常见文档/PDF/压缩包大小不超过50MB</div>
</el-upload>
<div v-if="form.documentSize" class="upload-size-tip">{{ formatFileSize(form.documentSize) }}</div>
</el-form-item>
<el-form-item label="生效日期" prop="effectiveDate">
<el-date-picker clearable v-model="form.effectiveDate" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择生效日期" />
<el-date-picker v-model="form.effectiveDate" clearable type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择生效日期" />
</el-form-item>
<el-form-item label="失效日期" prop="expiryDate">
<el-date-picker clearable v-model="form.expiryDate" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择失效日期" />
<el-date-picker v-model="form.expiryDate" clearable type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择失效日期" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-input v-model="form.status" placeholder="请输入状态" />
@ -97,10 +121,11 @@
</template>
<script>
import { listStandardDocument, getStandardDocument, delStandardDocument, addStandardDocument, updateStandardDocument } from "@/api/base/standardDocument";
import { listStandardDocument, getStandardDocument, delStandardDocument, addStandardDocument, updateStandardDocument } from '@/api/base/standardDocument'
import { getToken } from '@/utils/auth'
export default {
name: "StandardDocument",
name: 'StandardDocument',
data() {
return {
loading: true,
@ -110,8 +135,11 @@ export default {
showSearch: true,
total: 0,
standardDocumentList: [],
title: "",
title: '',
open: false,
fileList: [],
uploadUrl: process.env.VUE_APP_BASE_API + '/common/upload',
uploadHeaders: { Authorization: 'Bearer ' + getToken() },
queryParams: {
pageNum: 1,
pageSize: 10,
@ -124,26 +152,26 @@ export default {
},
form: {},
rules: {
documentCode: [{ required: true, message: "文档编号不能为空", trigger: "blur" }],
documentName: [{ required: true, message: "文档名称不能为空", trigger: "blur" }]
documentCode: [{ required: true, message: '文档编号不能为空', trigger: 'blur' }],
documentName: [{ required: true, message: '文档名称不能为空', trigger: 'blur' }]
}
};
}
},
created() {
this.getList();
this.getList()
},
methods: {
getList() {
this.loading = true;
this.loading = true
listStandardDocument(this.queryParams).then(response => {
this.standardDocumentList = response.rows;
this.total = response.total;
this.loading = false;
});
this.standardDocumentList = response.rows
this.total = response.total
this.loading = false
})
},
cancel() {
this.open = false;
this.reset();
this.open = false
this.reset()
},
reset() {
this.form = {
@ -156,73 +184,152 @@ export default {
versionNo: null,
documentPath: null,
documentSize: null,
fileChanged: false,
uploader: null,
uploadTime: null,
effectiveDate: null,
expiryDate: null,
status: null,
remark: null
};
this.resetForm("form");
}
this.fileList = []
this.resetForm('form')
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
this.queryParams.pageNum = 1
this.getList()
},
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
this.resetForm('queryForm')
this.handleQuery()
},
handleSelectionChange(selection) {
this.ids = selection.map(item => item.objId);
this.single = selection.length !== 1;
this.multiple = !selection.length;
this.ids = selection.map(item => item.objId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
handleAdd() {
this.reset();
this.open = true;
this.title = "添加标准文档";
this.reset()
this.open = true
this.title = '添加标准文档'
},
handleUpdate(row) {
this.reset();
const objId = row.objId || this.ids;
this.reset()
const objId = row.objId || this.ids
getStandardDocument(objId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改标准文档";
});
this.form = response.data
this.form.fileChanged = false
this.fileList = this.buildFileList(this.form.documentPath)
this.open = true
this.title = '修改标准文档'
})
},
submitForm() {
this.$refs["form"].validate(valid => {
this.$refs['form'].validate(valid => {
if (valid) {
if (this.form.objId != null) {
updateStandardDocument(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
this.$modal.msgSuccess('修改成功')
this.open = false
this.getList()
})
} else {
addStandardDocument(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
this.$modal.msgSuccess('新增成功')
this.open = false
this.getList()
})
}
}
});
})
},
handlePreview(row) {
if (!row.documentPath) {
this.$modal.msgWarning('暂无文件可查看')
return
}
window.open(process.env.VUE_APP_BASE_API + row.documentPath, '_blank')
},
handleDelete(row) {
const objIds = row.objId || this.ids;
const objIds = row.objId || this.ids
this.$modal.confirm('是否确认删除标准文档编号为"' + objIds + '"的数据项?').then(function() {
return delStandardDocument(objIds);
return delStandardDocument(objIds)
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
this.getList()
this.$modal.msgSuccess('删除成功')
}).catch(() => {})
},
handleExport() {
this.download('base/standardDocument/export', { ...this.queryParams }, `standardDocument_${new Date().getTime()}.xlsx`);
this.download('base/standardDocument/export', { ...this.queryParams }, `standardDocument_${new Date().getTime()}.xlsx`)
},
handleUploadSuccess(res, file) {
if (res.code !== 200) {
this.$modal.msgError(res.msg || '上传失败')
this.fileList = []
return
}
//
this.form.documentPath = res.fileName
this.form.documentSize = file.size
this.form.fileChanged = true
this.fileList = [{ name: res.originalFilename || file.name, url: res.fileName }]
this.$modal.msgSuccess('上传成功')
},
handleUploadError() {
this.$modal.msgError('上传失败,请重试')
this.fileList = this.buildFileList(this.form.documentPath)
},
handleFileRemove() {
//
this.form.documentPath = null
this.form.documentSize = null
this.form.fileChanged = true
this.fileList = []
},
handleExceed() {
this.$modal.msgWarning('只能上传一个文件')
},
beforeUpload(file) {
const isLt50M = file.size / 1024 / 1024 < 50
if (!isLt50M) {
this.$modal.msgError('上传文件大小不能超过 50MB!')
}
return isLt50M
},
buildFileList(path) {
if (!path) {
return []
}
return [{ name: this.getFileName(path), url: path }]
},
getFileName(path) {
if (!path) {
return ''
}
return path.lastIndexOf('/') > -1 ? path.slice(path.lastIndexOf('/') + 1) : path
},
formatFileSize(size) {
if (size === null || size === undefined || size === '') {
return '-'
}
if (size < 1024) {
return size + ' B'
}
if (size < 1024 * 1024) {
return (size / 1024).toFixed(2) + ' KB'
}
if (size < 1024 * 1024 * 1024) {
return (size / 1024 / 1024).toFixed(2) + ' MB'
}
return (size / 1024 / 1024 / 1024).toFixed(2) + ' GB'
}
}
};
}
</script>
<style scoped>
.upload-size-tip {
color: #909399;
line-height: 1.6;
}
</style>

Loading…
Cancel
Save