简化了在页面的使用难度,在每次加载时监控 ids 是否变化,监测到变化就重新从后台通过ids获取数据
文件上传组件完整代码:
<template>
<div>
<el-upload
class="upload-demo"
:action="upload.url"
:headers="upload.headers"
:on-change="handleUploadChange"
:on-success="handleUploadSuccess"
:on-remove="handleUploadRemove"
:on-preview="handleUploadPreview"
:before-upload="beforeUpload"
:file-list="fileList"
:disabled="disabled" >
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<el-dialog
:visible.sync="imgDialogVisible"
append-to-body
title="预览"
width="800"
>
<img
:src="dialogImageUrl"
style="display: block; max-width: 100%; margin: 0 auto"
/>
</el-dialog>
</div>
</template>
<script>
import { getFileUrl, getFileByIds } from '@/api/system/file'
import { getToken } from '@/utils/auth'
export default {
name: 'UploadCommon',
props: {
ids: {
type: String,
default: () => ""
},
disabled: {
type: Boolean,
default: () => false
},
finishUploadChange: {
type: Function
},
},
watch: {
ids(val) {
this.getFileList()
}
},
data() {
return {
// 文件上传配置
upload: {
// 是否禁用上传
isUploading: false,
// 设置上传的请求头部
headers: { Authorization: "Bearer " + getToken() },
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/common/uploadGetId",
// 上传的文件列表
fileList: []
},
form: {
layoutFileIds: null,
layoutFileIdsArr: []
},
fileList: [],
dialogImageUrl: "",
imgDialogVisible: false
}
},
methods: {
handleUploadChange(file, fileList) {
this.fileList = fileList;
},
handleUploadRemove(file, fileList, event) {
console.log(file)
this.form.layoutFileIdsArr.splice(this.form.layoutFileIdsArr.indexOf(file.id), 1)
this.form.layoutFileIds = this.form.layoutFileIdsArr.join(",")
this.finishUploadChange(this.form.layoutFileIds)
},
handleUploadSuccess(response, file, fileList) {
this.form.layoutFileIdsArr.push(response.id)
this.form.layoutFileIds = this.form.layoutFileIdsArr.join(",").toString()
this.finishUploadChange(this.form.layoutFileIds);
},
resetFileList() {
this.fileList = []
},
beforeUpload(file) {
console.log(file)
let isJPG = file.type === 'image/jpeg';
let isTxt = file.type === 'text/plain';
let isWord = ( file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|| file.type === 'application/msword' );
let isPdf = file.type === 'application/pdf';
// const isLt2M = file.size / 1024 / 1024 < 2;
if (! (isJPG || isTxt || isWord || isPdf)) {
this.$message.error('上传文件只能是 JPG、TXT、Word、PDF 格式!');
}
// if (!isLt2M) {
// this.$message.error('上传头像图片大小不能超过 2MB!');
// }
return isJPG || isTxt || isWord || isPdf;
},
handleUploadPreview(file) {
let id = file.id ? file.id : file.response.id
getFileUrl(id).then(response => {
let fileType = response.file.fileType
if (fileType === 'pdf' || fileType === 'txt') {
window.open(response.file.url)
} else if (fileType === 'docx' || fileType === 'doc') {
// window.location.href = './wordPreview?id=' + id;
window.open('/backstage/emergency/wordPreview?id=' + id)
} else if (fileType === 'jpg') {
this.dialogImageUrl = response.file.url
this.imgDialogVisible = true
}
})
},
initUpload() {
this.form.layoutFileIdsArr = []
for (let i=0; i<this.fileList.length; i++) {
this.fileList[i].name = this.fileList[i].fileName + "." + this.fileList[i].fileType
this.fileList[i].size = this.fileList[i].fileSize
this.form.layoutFileIdsArr.push(this.fileList[i].id)
}
this.form.layoutFileIds = this.form.layoutFileIdsArr.join(",")
},
getFileList() {
this.form.layoutFileIds = this.ids
if (this.ids !== "" && this.ids !== null) {
getFileByIds(this.form.layoutFileIds).then(res => {
this.fileList = res.file
this.initUpload()
})
} else {
this.fileList = []
this.initUpload()
}
},
clearData() {
this.fileList = []
}
},
created() {
this.getFileList()
}
}
</script>
<style scoped>
</style>
前端请求 js 代码
// 查询文件URL
export function getFileUrl(id) {
return request({
url: '/common/download/' + id,
method: 'get'
})
}
// 通过 ids 查询文件列表
export function getFileByIds(ids) {
return request({
url: '/common/download/list?ids=' + ids,
method: 'get'
})
}
word 文档预览组件引入 mammoth.js 实现,组件完整代码:
<template>
<div class="word-wrap">
<div id="wordView" v-html="wordText" />
</div>
</template>
<script>
// docx文档预览(只能转换.docx文档,转换过程中复杂样式被忽,居中、首行缩进等)
import mammoth from "mammoth";
import { getFileUrl } from '@/api/system/file'
export default {
name: "EnterpriseWordPreview",
data() {
return {
id: Number,
wordText: "",
wordURL: ''//文件地址
};
},
created() {
this.getWord();
this.getWordText();
},
methods: {
getWord() {
let _this = this
this.id = this.$route.query.id
getFileUrl(this.id).then(response => {
let fileType = response.file.fileType
if (fileType === 'docx' || fileType === 'doc') {
// window.location.href = './wordPreview?id=' + id;
// console.log(response.file.fileName + "." + fileType)
_this.wordURL = response.file.url
_this.getWordText()
} else {
_this.wordText = "当前文档格式不正确"
}
})
},
getWordText() {
let xhr = new XMLHttpRequest();
xhr.open("get", this.wordURL, true);
xhr.responseType = "arraybuffer";
xhr.onload = () => {
if (xhr.status === 200) {
mammoth.convertToHtml({ arrayBuffer: new Uint8Array(xhr.response) }).then((resultObject) => {
this.$nextTick(() => {
this.wordText = resultObject.value;
});
});
}
};
xhr.send();
}
},
};
</script>
<style>
.word-wrap {
padding: 15px;
}
.word-wrap img {
width: 100%;
}
</style>
后端 Controller 代码
@ApiOperation("通过文件ID获取文件URL")
@ApiImplicitParam(name = "file", value = "文件名", dataType = "String")
@GetMapping("/common/download/{id}")
public AjaxResult getFileUrl(@PathVariable("id") Long id) {
try {
SysFile sysFile = sysFileService.selectSysFileById(id);
AjaxResult ajax = AjaxResult.success();
ajax.put("file", sysFile);
return ajax;
} catch (Exception e) {
log.error("下载文件失败", e);
}
return AjaxResult.error("文件获取失败");
}
@ApiOperation("通过文件Ids获取文件列表")
@ApiImplicitParam(name = "file", value = "文件名", dataType = "String")
@GetMapping("/common/download/list")
public AjaxResult getFileByIds(String ids) {
try {
AjaxResult ajax = AjaxResult.success();
if (StringUtils.isEmpty(ids)) {
return ajax;
}
List<SysFile> sysFiles = sysFileService.selectSysFileListByIds(ids);
ajax.put("file", sysFiles);
return ajax;
} catch (Exception e) {
log.error("下载文件失败", e);
}
return AjaxResult.error("文件获取失败");
}
使用 find_in_set 方式通过 ids 查询文件列表的Mabtis代码(实体中存储的 ids 格式应该例如 6,15,78 的格式):
<select id="selectListByIds" parameterType="String" resultMap="SysFileResult">
<include refid="selectSysFileVo"/>
<where>
<if test="ids != null and ids != '' ">
find_in_set(id, #{ids})
</if>
<if test="ids == null || ids == '' ">
id = -1
</if>
</where>
</select>
实际项目中引入完整代码:
<upload-common
:disabled="disabled"
:finish-upload-change="finishUploadChange"
:ids="uploadIds"
ref="uploadCommon" >
</upload-common>
现在获取详情时只需要将实体类的 ids 传入组件即可,无需提前获取转为 JSON 格式的 文件 List,例如:
getInfo(id).then(response => {
this.form = response.data;
this.uploadIds = response.data.layoutFileIds
this.open = true;
this.title = "查看企业信息";
});
在回调函数中重新修改 form 中的 ids
finishUploadChange(ids) {
this.form.layoutFileIds = ids
},
PS:使用时需要另外定义一个变量存储 ids ,否则在组件上传后的回调函数中会重新修改 form 表单的 ids,会出现组件中文件列表重新刷新的问题,极大影响体验。
另外可能会出现组件中列表无法刷新的问题,可以采取修改自定义 ids(此处为 uploadIds) 的或者调用组件中的清除数据方法,例如:
this.$refs.uploadCommon.clearData()