上传图片或者视频进度条

这个博客展示了如何在Vue.js中创建一个图片上传组件,该组件支持预览图片、删除已上传图片、显示上传进度,并通过Vuex管理全局的上传进度。在上传过程中,组件监听上传进度变化并实时更新,同时提供了上传成功后的回调处理。用户可以通过点击按钮添加图片,最多可上传9张。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.上传图片组件

<template>
  <view class="basicUploadImage flex flex-wrap">
    <slot name="before"></slot>
    <!-- 已经上传过的图片 -->
    <view
      class="imageWrap"
      :style="imageStyle"
      v-for="(item, index) in imageList"
      :key="index"
    >
      <image
        class="image"
        :src="item.url"
        @click="$common.previewImage([item])"
      ></image>
      <image
        @click.stop="delImage(index, 'cur')"
        class="delIcon"
        :src="imgPrefixUrl && imgPrefixUrl + 'pic_del@2x.png'"
      ></image>
    </view>
    <!-- 当前正在上传的图片 -->
    <view class="imageWrap" :style="imageStyle" v-if="curImageUrl">
      <image
        class="image"
        :src="item"
        @click="$common.previewImage([{ url: item }])"
      ></image>
      <view class="progressLine">
        <view
          v-if="imageProgressPercent && imageProgressPercent !== 1"
          class="line"
          :style="'width:' + progressWidth + 'rpx'"
        ></view>
      </view>
    </view>
    <!-- 等待上传的图片列表 -->
    <block v-if="waitImageList.length">
      <view
        class="imageWrap"
        :style="imageStyle"
        v-for="(item, index) in waitImageList"
        :key="index"
      >
        <image
          class="image"
          :src="item"
          @click="$common.previewImage([{ url: item }])"
        ></image>
        <image
          @click.stop="delImage(index, 'wait')"
          class="delIcon"
          :src="imgPrefixUrl && imgPrefixUrl + 'pic_del@2x.png'"
        ></image>
        <view class="progressLine">
          <view class="line" style="width: 2rpx"></view>
        </view>
      </view>
    </block>
    <view
      v-if="imageList.length + waitImageList.length < maxNum"
      class="uploadImage imageWrap"
      :style="imageStyle"
      @click="onUploadClick"
    >
      <image
        :src="imgPrefixUrl && imgPrefixUrl + 'upload_pic%402x.png'"
      ></image>
      <view class="add">上传图片</view>
    </view>
    <slot name="after"></slot>
  </view>
</template>
<script>
import { mapGetters, mapState } from "vuex";
export default {
  props: {
    //图片样式
    imageStyle: {
      default: "",
      type: String,
    },
    //最大上传数量
    maxNum: {
      default: 9,
      type: Number || String,
    },
    //图片列表
    imageList: {
      default: function () {
        return [];
      },
      type: Array,
    },
    //是否
  },
  data() {
    return {
      curImageUrl: "", //正在上传的图片
      waitImageList: [], //等待上传的图片列表
    };
  },
  computed: {
     //  imageProgressPercent  全局上传图片的进度
    ...mapState(["imgPrefixUrl", "imageProgressPercent"]),
    /**
     * @author: yaoxueke
     * @description: 设置视频进度条
     * @param {*}
     * @return {*}
     */
    progressWidth() {
      let totalWidth = 192; //进度条完成时宽度
      let lineWidth = (totalWidth * (this.imageProgressPercent / 100)).toFixed(
        2
      );
      return lineWidth;
    },
  },
  methods: {
    /**
     * @author: yaoxueke
     * @description: 删除图片
     * @param {*} index  索引
     * @param {*} type cur 删除当前的视频  wait删除等待的视频
     * @return {*}
     */
    delImage(index, type) {
      if (type === "wait") {
        this.waitImageList.splice(index, 1);
      } else {
        this.$emit("delImage", index);
      }
    },
    /**
     * @author: yaoxueke
     * @description: 上传视频
     * @param {*}
     * @return {*}
     */
    uploadImage() {
      this.$common.uploadImageFun(0, [this.curImageUrl], (imgInfo) => {
        this.curImageUrl = "";
        this.$emit("updateImage", imgInfo);
        if (this.waitImageList.length) {
          this.curImageUrl = this.waitImageList[0];
          this.waitImageList.splice(0, 1);
          this.uploadImage();
        }
      });
    },
    /**
     * @author: yaoxueke
     * @description: 上传图片
     * @param {*}
     * @return {*}
     */
    onUploadClick() {
      let num = this.curImageUrl
        ? this.maxNum - this.imageList.length - this.waitImageList.length - 1
        : this.maxNum - this.imageList.length - this.waitImageList.length;
      this.$common.chooseImage(num).then((res) => {
        let data = res;
        if (!this.curImageUrl) {
          //等待列表没有图片,说明是第一次选择图片,从选择的第一张开始上传
          this.curImageUrl = data[0];
          data.splice(0, 1); //删除第一张,如果还有,其他加入等待上传的图片列表
          if (data.length) {
            data.forEach((item) => {
              this.waitImageList.push(item);
            });
          }
          this.uploadImage();
        } else {
          //等待列表有图片,就把所有的图片添加到等待列表
          res.forEach((item) => {
            this.waitImageList.push(item);
          });
        }
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.basicUploadImage {
  .imageWrap {
    position: relative;
    margin: 14rpx 12rpx 0 0;
    .image {
      width: 100%;
      height: 100%;
      border-radius: 14rpx;
      border: 2rpx dashed rgba(0, 0, 0, 0.15);
    }
    .progressLine {
      position: absolute;
      left: 0;
      bottom: 0;
      width: 100%;
      height: 12rpx;
      border-radius: 8rpx;
      border: 1px solid #0feada;
      .line {
        border-radius: 10rpx;
        background: #0feada;
        width: 0;
        height: 100%;
      }
    }
    .delIcon {
      width: 30rpx;
      height: 30rpx;
      position: absolute;
      right: -10rpx;
      top: -10rpx;
      z-index: 9;
    }
  }

  .uploadImage {
    // text-align:center;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    // margin:0 auto;
    border-radius: 20rpx;
    border: 2rpx dashed rgba(0, 0, 0, 0.15);
    background: rgba(0, 0, 0, 0.02);
    margin-top: 16rpx;
    image {
      width: 72rpx;
      height: 72rpx;
    }
    .add {
      font-size: 24rpx;
      color: #4e4e4e;
      margin-top: 18rpx;
    }
  }
}
</style>

2.全局设置一个进度字段(在此设置在vuex中)

   

state:{
  imageProgressPercent:0,
},
mutations:{
 setImageProgressPercent(state,data){
    state.imageProgressPercent = data
 }
},

3.上传请求中监听上传进度变化并更新全局进度值

Vue.prototype.$store.commit('setImageProgressPercent',0)  //每次上传前进度置0
return new Promise((resolve,reject) => {
    let uploadTask = uni.uploadFile({
        url,
        name: "file",
        header,
        formData:args.formData || {},
        filePath: args.path,
        // #ifdef MP-ALIPAY
        fileType:args.fileType || '',
        // #endif
        success:function(res){
            if(res.statusCode === 200 && JSON.parse(res.data).code === '000000'){
              Vue.prototype.$store.commit('setImageProgressPercent',100) //上传成功后进度设置100
              resolve(JSON.parse(res.data).resData)
            }else{
                console.error(res,'上传图片返回错误信息')
                uni.showToast({
                    title: res && res.msg,
                    icon: 'none',
                    mask: true
                })
                reject(res)
            }
        },
        fail:function(err){
            console.error(err,'上传图片返回错误信息')
            uni.showToast({
                title: err && err.msg,
                icon: 'none',
                mask: true
            })
            reject(err)
        }
    });
    //监听上传进度
    uploadTask.onProgressUpdate((res) => {
      let progress = Number(res.progress) > 92 ? 92 : Number(res.progress)
      Vue.prototype.$store.commit('setImageProgressPercent',progress)
      if(res.progress == 100){
        uploadTask.offProgressUpdate(() => {
          console.log('取消监听')
        })
        uploadTask = ''
      }
    });
  })

4.在页面

 <basicUploadImage
            ref="basicUploadImage"
            :maxNum="9"
            imageStyle="width:184rpx;height:184rpx;"
            :imageList="picUrl"
            @updateImage="updateImageHandle"
            @delImage="delImageHandle"
          >
          </basicUploadImage>


picUrl:[{url:‘’}]
updateImageHandle(imgInfo){
    console.log(imgInfo,'上传图片服务器返回数据')
}
//删除图片 index 索引
delImageHandle(index){
    picUrl.splice(0,index)
    
}

中使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值