二次封装el-upload上传图片

203 阅读2分钟

二次封装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>