RuoYi 框架本身对于图片上传功能,在
ElementUI
的<el-upload>
组件的基础装封装了@/components/ImageUpload/index.vue
组件。本组件就是在 RuoYi 自定义的<ImageUpload>
组件的基础上进行改造,将图片的信息在上传之前处理成 base64 格式,用于提交到后端接口,以及前端图片相应的预览展示。
自定义组件 ImageUploadBase64
组件目录 :
@/components/ImageUploadBase64/index.vue
html
<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>
表单中引用如下
html
<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>
接收图片的信息并进行后续的处理。