vue基于element封装图片上传组件示例
图片单个上传,支持放大
import imgUpload from '@/components/upload/imgUpload'; // 图片单个上传
<imgUpload
class="photoImage"
:showTage="DragUploadShowTag"
:picDesc="DragUploadpicDesc"
:imgUrl="photoId"
:isEdit="true"
:isDelect="true"
:imgMaxWidth="600"
:imgMaxHeight="800"
:imgMinWidth="50"
:imgMinHeight="50"
@handleSucess="handleSucess"
key="photoPath"
v-model="photoId"
>
</imgUpload>
handleSucess(response) {
// 返回文件id ,response
// ... 进行业务操作
},
handleRemove(response) {
// 返回回调的response
// ... 进行业务操作
},
已封装图片组件
<template>
<div>
<el-upload ref='upload' :id='ref' class='upload-demo' name='file' :style='bodySize' :disabled='formEdit' accept='.jpg,.jpeg,.png,.JPG,.JPEG,.png,.pdf,.PDF' drag :before-upload='beforeUpload'
action='/fa-pro-fastdfs/file/uploadFile' :auto-upload='true' :show-file-list='false' :on-success='handleSucess' :on-error='handleError' :headers='improtHeader'>
<div v-if='!showImg'>
<i class='el-icon-upload' v-if='showTage'></i>
<div class='el-upload__text' v-html='showTage'></div>
<div class='el-upload__tip' slot='tip' v-html='picDesc'></div>
</div>
<div v-else class='imgBox'>
<div class='img-option' v-if='bigImgShow' @mouseleave='mouseleaveHandle'>
<div class='btn'>
<i class='el-icon-zoom-in' @click.stop='imgClick' />
<i class='el-icon-upload2' style='margin-left: 20px' @mouseenter='formEdit = false' @mouseleave='formEdit = true' v-if='isEdit' />
<i v-if="isEdit && isDelect" class="el-icon-delete" @click="handleRemove" />
</div>
</div>
<el-image @mouseenter='mouseenterHandle' z-index='2010' class='img' :src='imgShowUrl + imgFileId' :preview-src-list='[imgShowUrl + imgFileId]' ref='elImg' />
</div>
</el-upload>
</div>
</template>
<script>
import { accMul } from '@/util/util';
import { delFile } from '@/views/admin/api/fastdfs';
export default {
name: 'imgUpload',
props: {
isEdit: {
type: Boolean,
default: true,
},
isDelect: {
type: Boolean,
default: false,
},
fileID: {
type: String,
default: '',
},
showTage: {
type: String,
default: () => `将文件拖到此处,或<em>点击上传</em>`,
},
//当前行信息
rows: {
type: Object,
default: () => {},
},
// 图片url
value: {
type: String,
default: '',
},
// 图片url
imgUrl: {
type: String,
default: '',
},
// formEdit: {
// // 是否可上传
// type: Boolean,
// default: true
// },
imgMinWidth: {
// 允许上传的图片最小宽度
type: Number,
default: 200,
},
imgMinHeight: {
// 允许上传的图片最小高度
type: Number,
default: 200,
},
imgMaxWidth: {
// 允许上传的图片最大宽度
type: Number,
default: 2000,
},
imgMaxHeight: {
// 允许上传的图片最大高度
type: Number,
default: 2000,
},
picDesc: {
// 图片上传要求说明
type: String,
default: '',
},
},
data() {
return {
loading: true, //图片压缩等待
formEdit: false,
ref: 'dragUpload' + +Math.floor(Math.random() * 9999999999999999), // 避免使用时混乱,取随机数值
showImg: false,
imgShowUrl:
'/fa-pro-fastdfs/file/downloadImage?access_token=' +
this.$store.getters.access_token +
'&id=',
improtHeader: {
'Content-Type': 'multipart/form-data; boundary=;',
Authorization: 'Bearer ' + this.$store.getters.access_token,
},
tempImgId: '',
bodySize: {
width: 428,
height: 270,
},
dialogVisible: false,
bigImgShow: false,
};
},
computed: {
imgId: {
get() {
return this.imgUrl;
},
set(val) {
//this.imgFileId = val;
},
},
imgFileId: {
get() {
if (this.imgUrl) {
return this.imgUrl;
} else {
return this.tempImgId;
}
},
set(val) {},
},
},
watch: {
imgId(val) {
if (val !== '' || val !== null) {
this.imgFileId = val;
this.showImg = true;
}
if (val === '' || val === null) {
this.showImg = false;
}
},
},
created() {
if (this.imgUrl !== '' || this.imgUrl !== null) {
this.showImg = true;
}
if (this.imgUrl === '' || this.imgUrl === null) {
this.showImg = false;
}
},
mounted() {
this.init();
},
methods: {
mouseleaveHandle(e) {
this.bigImgShow = false;
this.formEdit = false;
},
mouseenterHandle(e) {
this.bigImgShow = true;
this.formEdit = true;
},
upload() {
this.formEdit = false;
},
init() {
this.$nextTick(() => {
let node = document.getElementById(this.ref).childNodes[0]
.childNodes[0];
node.style.height = accMul(0.63, node.offsetWidth) + 'px';
});
},
imgClick() {
this.$refs.elImg.clickHandler();
this.bigImgShow = false;
this.formEdit = true;
},
//上传验证
// beforeUpload(file) {
// // 设置允许上传的文件格式
// let uploadExtend = ['jpg', 'jpeg', 'png', 'JPG', 'JPEG', 'png'];
// // 获取当前上传文件后缀名并转为小写
// let suffix = file.name
// .substr(file.name.lastIndexOf('.'))
// .substr(1)
// .toLowerCase();
// // 上传文件类型校验
// if (!uploadExtend.includes(suffix)) {
// this.$notify({
// title: '提示',
// dangerouslyUseHTMLString: true,
// type: 'warning',
// message: `<p>文件格式不正确,请上传jpg,jpeg,png,JPG,JPEG,png格式的文件</p>`
// });
// return false;
// }
// // 获取允许上传的文件大小 并由MB转为B
// let _size = 3; // 默认1MB
// let docSize = parseFloat(_size) * 1024 * 1024;
// // 上传文件大小校验
// if (file.size > docSize) {
// this.$notify({
// title: '提示',
// dangerouslyUseHTMLString: true,
// type: 'warning',
// message: `<p>文件大小过大,请上传${_size}MB以内大小的文件</p>`
// });
// return false;
// }
// // 校验上传图片的尺寸
// const isSize = new Promise((resolve, reject) => {
// let minWidth = this.imgMinWidth; // 允许上传的最小宽度
// let minHeight = this.imgMinHeight; // 允许上传的最小宽度
// let maxWidth = this.imgMaxWidth; // 允许上传的最大宽度
// let maxHeight = this.imgMaxHeight; // 允许上传的最大高度
// let _URL = window.URL || window.webkitURL;
// let img = new Image();
// img.onload = function() {
// let valid =
// img.width >= minWidth &&
// img.width <= maxWidth &&
// img.height >= minHeight &&
// img.height <= maxHeight;
// valid ? resolve() : reject();
// };
// img.src = _URL.createObjectURL(file);
// }).then(
// () => {
// return file;
// },
// () => {
// this.$notify({
// title: '提示',
// dangerouslyUseHTMLString: true,
// type: 'warning',
// message: `<p>请上传图片宽度在${this.imgMinWidth}像素-${this.imgMaxWidth}像素,高度在${this.imgMinHeight}像素-${this.imgMaxHeight}像素范围内的照片!</p>`
// });
// return Promise.reject();
// }
// );
// return isSize;
// },
//上传成功
handleSucess(response, file, fileList) {
if (response.code === 0) {
this.imgFileId = response.data.fileId;
this.tempImgId = response.data.fileId;
this.showImg = true;
this.$emit('handleSucess', response.data.fileId);
this.$notify({
title: '成功',
message: '上传成功',
type: 'success',
});
}
},
//上传失败
handleError(err, file, fileList) {
this.$emit('handleError', err, file, fileList, this.rows);
if (err.type === 'error') {
this.$notify({
title: '提示',
message: '上传失败',
type: 'error',
});
}
},
beforeUpload(file) {
console.log(file);
// 设置允许上传的文件格式
let uploadExtend = ['jpg', 'jpeg', 'png', 'JPG', 'JPEG', 'png'];
let suffix = file.name
.substr(file.name.lastIndexOf('.'))
.substr(1)
.toLowerCase();
// 上传文件类型校验
if (!uploadExtend.includes(suffix)) {
this.$notify({
title: '提示',
dangerouslyUseHTMLString: true,
type: 'warning',
message: `<p>文件格式不正确,请上传jpg,jpeg,png,JPG,JPEG,png格式的文件</p>`,
});
return false;
}
// 获取允许上传的文件大小 并由MB转为B
const isIE = !!window.ActiveXObject || 'ActiveXObject' in window;
let _size = isIE ? 5 : 20;
let docSize = parseFloat(_size) * 1024 * 1024;
// 上传文件大小校验
if (file.size > docSize) {
this.$notify({
title: '提示',
dangerouslyUseHTMLString: true,
type: 'warning',
message: `<p>文件大小过大,请上传${_size}MB以内大小的文件</p>`,
});
return false;
}
let _this = this;
return new Promise((resolve, reject) => {
let isLt2M = file.size / 1024 / 1024 < 10; // 判定图片大小是否小于10MB
if (!isLt2M) {
reject();
}
let image = new Image(),
resultBlob = '';
image.src = URL.createObjectURL(file);
if (!isIE) {
this.loading = this.$loading({
lock: true,
text: '图片压缩中请勿操作页面...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)',
});
}
image.onload = () => {
let minWidth = this.imgMinWidth; // 允许上传的最小宽度
let minHeight = this.imgMinHeight; // 允许上传的最小宽度
if (image.width < minWidth || image.height < minHeight) {
this.$notify({
title: '提示',
dangerouslyUseHTMLString: true,
type: 'warning',
message: `<p>上传图片要求宽度大于${this.imgMinWidth}像素,高度大于${this.imgMinHeight}像素!</p>`,
});
reject();
}
if (docSize > 1 && !isIE) {
this.loading = this.$loading({
lock: true,
text: '图片压缩中请勿操作页面...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)',
});
resultBlob = _this.compressUpload(image, file, 1);
}
// 调用方法获取blob格式,方法写在下边
resolve(resultBlob);
};
image.onerror = () => {
reject();
};
});
},
/* 图片压缩方法-canvas压缩 */
compressUpload(image, file, size) {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
let initSize = image.src.length;
let { width } = image,
{ height } = image;
canvas.width = width;
canvas.height = height;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(image, 0, 0, width, height);
// 初始化压缩0.6
let quality = 0.6;
let compressData = canvas.toDataURL(file.type || 'image/jpeg', quality);
console.log(compressData.length / (1024 * 1024));
console.log(size);
while (compressData.length / (1024 * 1024) > size) {
quality -= 0.06;
console.log(compressData.length / (1024 * 1024));
compressData = canvas.toDataURL('image/jpeg', quality);
}
this.loading.close();
console.log(this.loading);
// 压缩后调用方法进行base64转Blob,方法写在下边
let blobImg = this.dataURItoBlob(compressData);
return blobImg;
},
/* base64转Blob对象 */
dataURItoBlob(data) {
let byteString;
if (data.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(data.split(',')[1]);
} else {
byteString = unescape(data.split(',')[1]);
}
let mimeString = data.split(',')[0].split(':')[1].split(';')[0];
let ia = new Uint8Array(byteString.length);
for (let i = 0; i < byteString.length; i += 1) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], { type: mimeString });
},
// 删除
handleRemove() {
let fileId = this.fileID;
if (!fileId) {
return;
}
let data = {
id: fileId,
};
delFile(data).then((res) => {
if (res.code == 0) {
this.showImg = false;
this.$message.success('删除成功');
this.$emit('handleRemove', this.list);
} else {
this.$message.error(res.msg);
}
});
},
},
};
</script>
<style lang='scss' scoped>
.imgBox {
position: absolute;
top: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
.img-option {
z-index: 3;
position: absolute;
display: flex;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
align-items: center;
justify-content: center;
top: 0px;
.btn {
color: #fff;
font-size: 36px;
}
}
.img {
margin: 0 auto;
display: block;
max-width: 100%;
max-height: 100%;
width: 100%;
height: 100%;
// z-index: 2; // 20211002 by gcl edit 当一个页面使用多个imageUpload, 其他放大查看时,索引曾影响展示
}
}
/deep/ .el-upload__tip {
line-height: 18px !important;
i {
font-style: normal;
color: red;
}
}
/deep/ .el-image-viewer__wrapper {
z-index: 4;
}
.big-img {
//width: 60%;
//height: 80%;
/deep/ .el-dialog__body {
display: flex;
align-items: center;
justify-content: center;
}
}
</style>
//封装的工具类中accMul方法
// 乘法: export const accMul = function (arg1, arg2) { arg1 = arg1 ? arg1 : 0; arg2 = arg2 ? arg2 : 0; var m = 0, s1 = arg1.toString(), s2 = arg2.toString(); try { m += s1.split(".")[1].length } catch (e) { } try { m += s2.split(".")[1].length } catch (e) { } return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m) }
效果如下,目前截图缺少删除按钮,支持上传更新、放大、删除


浙公网安备 33010602011771号