RuoYi 框架本身对于图片上传功能,在ElementUI
的 <el-upload>
组件的基础装封装了 @/components/ImageUpload/index.vue
组件。本组件就是在 RuoYi 自定义的 <ImageUpload>
组件的基础上进行改造,将图片的信息在上传之前处理成 base64 格式,用于提交到后端接口,以及前端图片相应的预览展示。
自定义组件 ImageUploadBase64
组件目录 : @/components/ImageUploadBase64/index.vue
<template> <div class="component-upload-image"> <el-upload ref="imageUploadRef" action="#" list-type="picture-card" accept=".png, .jpeg, .jpg" :limit="limit" :on-change="handleChange" :on-remove="handleRemove" :on-preview="handlePictureCardPreview" :on-exceed="handleExceed" :file-list="fileList" :class="{hide: this.fileList.length >= this.limit}" :show-file-list="true" :auto-upload="false"> <i class="el-icon-plus"></i> </el-upload> <el-dialog :visible.sync="previewDialogVisible" title="图片预览" width="800" append-to-body> <el-image style="display: block; max-width: 100%; margin: 0 auto" :src="previewDialogImageUrl" alt=""></el-image> </el-dialog> </div></template><script>export default { props: { // 对应父组件 v-model绑定,对应本组件 this.$emit("input",参数)绑定 value: [String, Object, Array], // 图片数量限制 limit: { type: Number, default: 5, }, // 大小限制(MB) fileSize: { type: Number, default: 5, }, // 文件类型, 例如['png', 'jpg', 'jpeg'] fileType: { type: Array, default: () => ["png", "jpg", "jpeg"], }, }, data() { return { // 图片预览弹窗 显隐 previewDialogVisible: false, // 图片预览 url previewDialogImageUrl: '', // 待上传的图片集合 是转化完base64 后的结果 fileList: [ /*{ name:'', url:'' }*/ ] } }, watch: { value: { handler(val) { if (val) { // 首先将值转为数组 const list = Array.isArray(val) ? val : this.value.split(','); // 然后将数组转为对象数组 this.fileList = list.map(item => { if (typeof item === "string") { item = {name: item, url: item}; } return item; }); } else { this.fileList = []; return []; } }, deep: true, immediate: true } }, methods: { /** * 校验文件尺寸是否符合要求 和类型是否是图片 * @param file * @returns {boolean} */ handleFileValidate(file) { // 上传文件的类型 let type = file.raw.type || file.type; let isImg = type.indexOf("image") > -1; if (isImg) { if (this.fileSize) { const isLt = file.size / 1024 / 1024 < this.fileSize; if (!isLt) { this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`); return false; } else { return true; } } } else { this.$message.error( `文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!` ); // 不是图片格式 return false; } }, /* 添加文件、上传成功和上传失败时都会被调用 */ handleChange(file, fileList) { if (this.handleFileValidate(file)) { this.fileToBase64(file); } else { // 删除尺寸大的图片 或者非图片类型的文件 let lastIndex = fileList.length - 1; if (lastIndex > -1) { fileList.splice(lastIndex, 1); } } }, /** * 删除图片 * @param file 被删除的图片 * @param fileList 剩余的文件信息列表 */ handleRemove(file, fileList) { const findex = this.fileList.map(f => f.url).indexOf(file.url); if (findex > -1) { // 删除对应的 文件数据 this.fileList.splice(findex, 1); this.$emit("input", this.listToArray(this.fileList)); } }, /*预览图片*/ handlePictureCardPreview(file) { this.previewDialogImageUrl = file.url; this.previewDialogVisible = true; }, /** * 文件个数超出 * @param files 超出的文件信息 * @param fileList 原来已经添加的文件信息 */ handleExceed(files, fileList) { this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`); }, /** * 将el-upload组件上传的文件转为base64 * @param file */ fileToBase64(file) { var reader = new FileReader(); reader.readAsDataURL(file.raw); // 转换为Base64 reader.onload = e => { // 当转换完成后,e.target.result就是Base64字符串 const base64 = e.target.result; this.fileList.push({name: base64, url: base64}); this.$emit("input", this.listToArray(this.fileList)); }; }, // list中的元素{name:'',url:''} 转 url字符串 listToArray(list) { let arr = []; for (let i in list) { arr.push(list[i].url); } return arr; } }}</script><style scoped lang="scss">// .el-upload--picture-card 控制加号部分::v-deep.hide .el-upload--picture-card { display: none;}// 去掉动画效果::v-deep .el-list-enter-active,::v-deep .el-list-leave-active { transition: all 0s;}::v-deep .el-list-enter, .el-list-leave-active { opacity: 0; transform: translateY(0);}</style>
表单中引用如下
<template> <div class="app-container"> <!-- 添加或修改对话框 --> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-form ref="form" :model="form" :rules="rules" :show-message="false" label-width="80px"> <el-col :span="24"> <el-form-item label="上传图片"> <ImageUploadBase64 v-model="form.base64DataList" :file-size="10" @input="handleImageInput"></ImageUploadBase64> </el-form-item> </el-col> </el-row> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitForm()">保 存</el-button> <el-button @click="cancel">取 消</el-button> </div> </el-dialog> </div></template><script>import ImageUploadBase64 from "@/components/ImageUploadBase64/index.vue";import {listWorkInfo, getWorkInfo, delWorkInfo, addWorkInfo, updateWorkInfo} from "@/api/basic/work";export default { name: "Work", components: {ImageUploadBase64}, data() { return { // 弹出层标题 title: "", // 是否显示弹出层 open: false, // 表单参数 form: {}, }; }, created() { this.getList(); }, methods: { /** * 子组件 this.$emit("input", this.listToArray(this.fileList)); 返回的数据 * @param fileList */ handleImageInput(fileList){ // 这里返回的就是base64字符串的数组,可以直接提交后端接口,也可以根据业务做其他处理 console.log("handleImageInput-----:", fileList) }, // 取消按钮 cancel() { this.open = false; this.reset(); }, // 表单重置 reset() { this.form = { id: null base64DataList:[] }; this.resetForm("form"); }, /** 新增按钮操作 */ handleAdd() { this.reset(); this.title = "添加工作信息"; this.open = true; }, /** 修改按钮操作 */ handleUpdate(row) { this.reset(); const id = row.id || this.ids getWorkInfo(id).then(response => { this.form = response.data; this.open = true; this.title = "修改工作信息"; }); }, /** 提交按钮 */ submitForm: function () { this.$refs["form"].validate(valid => { if (valid) { if (this.form.id != undefined) { updateWorkInfo(this.form).then(response => { this.$modal.msgSuccess("修改成功"); this.open = false; this.getList(); }); } else { addWorkInfo(this.form).then(response => { this.$modal.msgSuccess("新增成功"); this.open = false; this.getList(); }); } } }); } }};</script>
这个组件将图片信息直接在前端转化成 base64格式的字符串数字,后端可以直接使用List<String>
接收图片的信息并进行后续的处理。