二次封装el-upload,可单个、多个图片上传
<template>
<div class="uploadImg">
<div class="imgList_box" :class="{ maxHidden: hideUploadImg }">
<div
v-for="(item, index) in imgfileList"
:key="item.imageUrl + index"
class="imgItem"
:style="{ width: width + 'px', height: height + 'px' }"
>
<el-image
:z-index="3000"
:src="baseUrl + item.imageUrl"
:preview-src-list="[baseUrl + item.imageUrl]"
></el-image>
<div class="shadow" @click="handleRemove(index)">
<i class="el-icon-delete"></i>
</div>
</div>
<el-upload
:action="uploadImgUrl"
list-type="picture-card"
:show-file-list="false"
:headers="importHeaders"
:limit="limit"
:multiple="isMultiple"
:file-list="fileList"
:before-upload="handleBeforeUpload"
:on-success="handleSuccess"
:on-exceed="handleExceedLength"
:on-progress="uploadImgProcess"
:style="{ width: width + 'px', height: height + 'px' }"
ref="uploadImgRef"
class="uploadImgBox"
>
<el-progress
v-if="showProgress"
type="circle"
:percentage="uploadPercent"
></el-progress>
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
<p style="color: #b8b8b8" v-if="showTip">
仅支持上传jpg/png/jpeg格式文件,单个图片大小不超过100M,最多上传{{
limit
}}张。
</p>
</div>
</template>
<script>
import { domain, common } from "@/utls.js";
export default {
name: "uploadImg",
props: {
// 图片显示的宽度(px)
width: {
type: Number,
default: 100
},
// 图片显示的高度(px)
height: {
type: Number,
default: 100
},
// 限制上传图片数量
limit: {
type: Number,
default: 1
},
// 是否多选
isMultiple: {
type: Boolean,
default: false
},
// 图片数据 [{id:'', imageUrl: 'xxx.jpg'}]
imgValue: {
type: Array,
default: () => []
},
showTip:{
type:Boolean,
default:true
}
},
data() {
return {
baseUrl:domain.Base_M1_URL,
uploadImgUrl: domain.Base_M1_URL + common.UPLOAD_IMAGE,
uploadVideoUrl: domain.Base_M1_URL + common.UPLOAD_VIDEO,
importHeaders: { token: localStorage.userToken },
showProgress: false, //是否显示进度条
uploadPercent: 0, //进度条的进度
fileList:[]
};
},
computed: {
imgfileList: {
get() {
return this.imgValue;
},
set(val) {
if (val.length < this.imgfileList.length) {
// 判断是删除图片,同步el-upload
this.syncUploadImg(val);
}
this.$emit("update:imgValue", val);
},
},
//超出上传限数隐藏上传按钮
hideUploadImg() {
return this.imgfileList.length >= this.limit
}
},
methods: {
createUniqueString() {
const timestamp = +new Date() + ''
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
return (+(randomNum + timestamp)).toString(32)
},
//上传前处理函数:限制上传大小以及格式
handleBeforeUpload(file) {
const imgType = ["image/png", "image/jpg", "image/jpeg", "image/gif"];
const isLtMaxSize = file.size / 1024 / 1024;
if (imgType.indexOf(file.type) === -1) {
this.$message.error("上传图片格式错误!");
return false;
}
if (isLtMaxSize > 100) {
this.$message.error("上传图片不能超过100M!");
return false;
}
},
//上传图片成功处理函数:
handleSuccess(res, file, fileList) {
if (res.code === 200) {
if (this.imgfileList.length < this.limit) {
// 未超限时,把接口返回的图片url地址添加到imgfileList
this.imgfileList.push({imageUrl:res.data})
const imgfileList = [].concat(this.imgfileList)
this.imgfileList = imgfileList
if(fileList.every(item => item.status == "success")) {
fileList.map(item => {
this.fileList.push({
name:item.name,
url:item.response && item.response.data,
status:item.status,
uid:item.uid
})
})
}
}
this.showProgress = false;
this.uploadPercent = 0
this.$emit('changeUploadSuccess',this.imgfileList)
} else {
// 上传失败,进度条关闭
this.syncUploadImg()
this.$message.error(res.msg || "上传失败,请重新上传文件!");
this.showProgress = false;
this.uploadPercent = 0
}
},
// 同步el-upload数据
syncUploadImg(val) {
// 注意新增上传图片时,只有图片地址,编辑时还有图片id
const imgList = val || this.imgfileList;
this.fileList = imgList.map((item, i) => {
return {
name: "pic" + i,
url: item.imageUrl,
status: "success",
uid: this.createUniqueString(),
id:item.id ? item.id : ""
};
});
},
// 超限上传
handleExceedLength() {
this.syncUploadImg()
this.$refs.uploadImgRef.abort(); // 取消剩余接口请求
this.$message.warning(`图片超限,最多可上传${this.limit}图片`);
},
// 上传进度
uploadImgProcess(event, file, fileList) {
this.showProgress = true;
this.uploadPercent = file ? file.percentage.toFixed(0) * 1 : 0;
},
handleRemove(index) {
this.$confirm('确定删除该图片?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
this.imgfileList.splice(index,1)
this.syncUploadImg(this.imgfileList)
})
.catch(() => {})
},
},
};
</script>
<style lang="less" scoped>
.uploadImg {
.maxHidden{
.uploadImgBox{
display: none;
}
}
.imgList_box {
display: flex;
flex-wrap: wrap;
/deep/.el-icon-circle-close{
color: #179bfe;
}
/deep/ .el-upload {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
/deep/ .el-progress-circle {
width: 80px !important;
height: 80px !important;
}
.imgItem {
margin: 0 5px 5px 0;
border: 1px solid #ddd;
border-radius: 6px;
position: relative;
overflow: hidden;
.el-image {
width: 100%;
height: 100%;
}
.shadow {
position: absolute;
top: 50%;
right: 50%;
opacity: 0;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: opacity 0.3s;
color: #fff;
font-size: 20px;
line-height: 20px;
padding: 2px;
cursor: pointer;
transform: translate(50%,-50%);
}
&:hover {
.shadow {
opacity: 1;
}
}
}
}
}
</style>
使用封装的上传图片组件
<template>
<upload-img :imgValue.sync="parameterFrom.imageUrl" />
</template>
<script>
import uploadImg from "@/components/uploadImg.vue";
export default {
components: { uploadImg },
data() {
return {
parameterFrom: {
imageUrl: []
}
}
}
}
</script>