封装el-upload上传七牛云图片

1、img-upload.vue

可以设置拖拽上传、点击上传、限制上传数量、大小、上传方法、多选、预览等

<template>
  <div>
    <!-- 拖拽上传 -->
    <div v-if="isDrag">
      <el-upload :action="uploadUrl" :file-list="imgList" class="upload-demo" list-type="picture" drag
        :show-file-list="true" :on-remove="handleRemove" :on-success="handleSuccess" :on-error="handleError"
        :on-change="changeFile" :before-upload="beforeUpload" :multiple="isMultiple" :limit="limit"
        :on-exceed="handleExceed" :class="{ dragDisabled: fileLimit }">
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
      </el-upload>
      <div class="el-upload__tip" slot="tip">只能上传{{ limit }}张图片,且不超过5M</div>
    </div>

    <!-- 点击上传 -->
    <div v-else>
      <el-upload :action="uploadUrl" :file-list="imgList" list-type="picture-card" :show-file-list="true"
        :on-preview="handlePreview" :on-remove="handleRemove" :on-success="handleSuccess" :on-error="handleError"
        :on-change="changeFile" :before-upload="beforeUpload" :limit="limit" :on-exceed="handleExceed"
        :multiple="isMultiple" :class="{ disabled: fileLimit }">
        <i class="el-icon-plus"></i>
        <div class="el-upload__tip" slot="tip">只能上传{{ limit }}张图片,且不超过5M</div>
      </el-upload>
    </div>

    <!-- 预览图片 -->
    <el-dialog :visible.sync="showDialog" title="图片预览">
      <img :src="imgUrl" alt="" style="width:100%">
    </el-dialog>
  </div>
</template>

<script>
import { uploadImg } from '@/utils/request'

export default {
  props: {
    isDrag: {
      type: Boolean,
      default: false
    },
    isMultiple: {
      type: Boolean,
      default: true
    },
    limit: {
      type: Number,
      default: 9
    },
    propsList: {
      type: [String, Array],
      default: () => []
    }
  },
  data() {
    return {
      uploadUrl: process.env.VUE_APP_IMG_API,
      imgList: [],
      imgUrl: '',
      showDialog: false
    }
  },
  computed: {
    // 隐藏上传按钮
    fileLimit() {
      return this.imgList.length === this.limit
    }
  },
  methods: {
    // 上传成功
    handleSuccess(response, file, fileList) {
      this.imgList.push({
        url: response.data
      })
      this.$emit('updateImg', this.imgList)
      this.$emit('handleSuccess', response)
    },
    handlePreview(file) {
      this.imgUrl = file.url
      this.showDialog = true
    },
    // 图片变更
    changeFile(file, fileList) {
      // this.fileList = [...fileList]
      // this.fileList = fileList.map(item => item)
    },
    // 删除图片
    handleRemove(file) {
      this.imgList = this.imgList.filter(item => item.uid !== file.uid)
      this.$emit('updateImg', this.imgList)
    },
    handleError(e) {
      console.log(e);
    },
    // 上传前操作
    beforeUpload(file) {

      const isImage = /\.(jpg|jpeg|png|bmp)$/i.test(file.name);
      const isLt2M = file.size / 1024 / 1024 < 5;

      if (!isImage) {
        this.$message.error('上传文件只能是jpg、jpeg、png或bmp格式!');
        return false;
      }

      if (!isLt2M) {
        this.$message.error('上传文件大小不能超过 5MB!');
        return false;
      }
      return true;
    },
    handleExceed(file, fileList) {
      this.$message.error(`只能上传${this.limit}张图片`);
    }
  },
  watch: {
    propsList(newVal) {
      if (typeof newVal === 'string' && newVal.trim().length) {
        let arr = newVal.split(',')
        arr.map(item => {
          this.fileList.push({
            url: item
          })
        })
      } else if (Array.isArray(newVal)) {
        this.fileList = newVal;
      } else {
        this.fileList = []
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.dragDisabled> :nth-child(1) {
  display: none;
}

.disabled> :nth-child(2) {
  display: none;
}
</style>

2、自定义上传方法(这里使用自己的七牛云,免费哦)

<template>
  <div>
    <!-- 拖拽上传 -->
    <div v-if="isDrag">
      <el-upload :http-request="upload" action="#" :file-list="fileList" class="upload-demo" list-type="picture" drag
        :show-file-list="true" :on-remove="handleRemove" :on-error="handleError" :before-upload="beforeUpload"
        :multiple="isMultiple" :limit="limit" :on-exceed="handleExceed" :class="{ dragDisabled: fileLimit }">
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
      </el-upload>
      <div class="el-upload__tip" slot="tip">只能上传{{ limit }}张图片,且不超过5M</div>
    </div>

    <!-- 点击上传 -->
    <div v-else>
      <el-upload :http-request="upload" action="#" :file-list="fileList" list-type="picture-card" :show-file-list="true"
        :on-preview="handlePreview" :on-remove="handleRemove" :on-error="handleError" :before-upload="beforeUpload"
        :limit="limit" :on-exceed="handleExceed" :multiple="isMultiple" :class="{ disabled: fileLimit }">
        <i class="el-icon-plus"></i>
        <div class="el-upload__tip" slot="tip">只能上传{{ limit }}张图片,且不超过5M</div>
      </el-upload>
    </div>
    <el-progress :percentage="uploadProgress" v-if="uploadProgress" :stroke-width="15" :text-inside="true"
      status="success"></el-progress>
    <!-- 预览图片 -->
    <el-dialog :visible.sync="showDialog" title="图片预览">
      <img :src="imgUrl" alt="" style="width:100%">
    </el-dialog>
  </div>
</template>

<script>
import * as qiniu from 'qiniu-js';
import { mapGetters } from 'vuex';

export default {
  props: {
    isDrag: {
      type: Boolean,
      default: false
    },
    isMultiple: {
      type: Boolean,
      default: false
    },
    limit: {
      type: Number,
      default: 9
    },
    propsList: {
      type: [String, Array],
      default: () => []
    }
  },
  data() {
    return {
      fileList: [], // 所有图片
      imgUrl: '', // 预览图片地址
      showDialog: false, // 预览图片弹框
      baseUrl: process.env.VUE_APP_IMG_API, // 七牛云地址
      uploadProgress: 0, // 进度条
      observable: null, // 上传实例
    }
  },
  computed: {
    ...mapGetters(['qiNiuToken']),
    // 隐藏上传按钮
    fileLimit() {
      return this.fileList.length === this.limit
    }
  },
  methods: {
    handlePreview(file) {
      this.imgUrl = file.url;
      this.showDialog = true;
    },
    // 删除图片
    handleRemove(file) {
      this.fileList = this.fileList.filter(item => item.uid !== file.uid)
      this.$emit('updateImg', this.fileList)
    },
    handleError(e) {
      console.log(e);
    },
    // 上传前操作
    beforeUpload(file) {
      const isImage = /\.(jpg|jpeg|png|bmp)$/i.test(file.name);
      const isLt2M = file.size / 1024 / 1024 < 10;

      if (!isImage) {
        this.$message.error('上传文件只能是jpg、jpeg、png或bmp格式!');
        return false;
      }

      if (!isLt2M) {
        this.$message.error('上传文件大小不能超过10MB!');
        return false;
      }
      return true;
    },

    handleExceed(file, fileList) {
      this.$message.error(`最多只能上传${this.limit}张图片`);
    },

    // 构建七牛云上传配置
    uploadConfig(file) {
      const config = {
        useCdnDomain: true,
        region: qiniu.region.z2 // 选择七牛云存储区域
      };
      let putExtra = {}
      // 创建七牛云上传实例
      this.observable = qiniu.upload(file, file.name, this.qiNiuToken, putExtra, config);
      
      // 返回一个Promise对象,用于处理上传成功或失败的回调
      return new Promise((resolve, reject) => {
        this.observable.subscribe({
          next: (response) => {
            // 设置上传进度
            this.uploadProgress = Number(response.total.percent.toFixed(0));
          },
          error: (err) => {
            reject(err);
          },
          complete: (response) => {
            resolve(response);
          }
        });
      });
    },
    // 自定义上传
    async upload(params) {
      let { file } = params;
      try {
        const response = await this.uploadConfig(file);
        let url = this.baseUrl + '/' + response.key;
        this.$emit('handleSuccess', { url }); // 富文本回调,只传当前上传的图片
        this.fileList.push({ url });
        this.$emit('updateImg', this.fileList); // 表单回调,回传所有图片
      } catch (error) {
        // 上传失败,可以做一些错误处理
        console.error(error);
        this.$message.error('文件上传失败!');
      } finally {
        // 清空上传进度
        setTimeout(() => {
          this.uploadProgress = 0;
        }, 1000);
      }
    },
  },
  watch: {
    propsList(newVal) {
      if (typeof newVal === 'string' && newVal.trim().length) {
        let arr = newVal.split(',')
        arr.map(item => {
          this.fileList.push({
            url: item
          })
        })
      } else if (Array.isArray(newVal)) {
        this.fileList = newVal;
      } else {
        this.fileList = []
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.dragDisabled> :nth-child(1) {
  display: none;
}

.disabled> :nth-child(2) {
  display: none;
}
</style>

3、使用方法

<ImgUpload :propsList="imgList" @updateImg="updateImg"></ImgUpload>


// 图片添加删除
    updateImg(imgList) {
      let arr = imgList.map(item => item.url)
      this.formData.images = arr.join(',')
    },

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值