el-upload in vue combines vuedraggable to realize the functions of uploading, sorting, deleting and previewing pictures

Realize the needs of image upload, sorting, deletion, preview and other functions, as well as the echo during editing

Vuedraggable can refer to the implementation of drag and drop function: drag and drop preview function implementation

1. First show the effect of implementing the function.

insert image description here

2. Echo of pictures during editing

insert image description here

3. Function realization

3.1 To realize the drag and drop function of pictures, you first need to install the vuedraggable library

npm install vuedraggable --save

3.2 Import the component in the component and register it

import draggable from 'vuedraggable';
insert image description here

3.3 Use the el-upload component of element ui, combined with vuedraggable to realize the image upload and sorting function, the code in it is as follows:

 <el-form-item label="上传图片:">
      <ul class="image-upload">
        <draggable v-model="imageListArr" @update="dataDragEnd">  //拖拽排序
          <transition-group>                                      //过渡动画                                           
            <li v-for="(item, index) of imageListArr" :key="item.imgUrl">
              <img v-if="item.imgUrl" style="width:100% ;height: 90px" :src="item.imgUrl">
              <div class="icon-container">
                <span v-if="item.imgUrl" @click="handleRemove(index)">  //删除上传的图片
                  <i class="el-icon-delete" style="margin-right:15px"></i>
                </span>
                <span v-if="item.imgUrl" class="el-upload-list__item-preview" @click="handlePreview(index)">          //预览上传的图片
                  <i class="el-icon-zoom-in"></i>
                </span>
              </div>
            </li>
          </transition-group>

        </draggable>
      </ul>
      //图片上传部分
      <el-upload ref="upload" accept=".jpeg, .png, .gif" action="#" :multiple="true" list-type="picture-card"
        :show-file-list="false" :on-change="handleChange" :auto-upload="false">
        <i class="el-icon-plus avatar-uploader-icon"></i>
      </el-upload>

      <!-- 图片回显预览 -->
      <el-dialog title="图片预览" :visible.sync="previewVisible" width="50%" append-to-body>
        <img :src="previewPath" alt="" style="width:100%;height:100%" />
      </el-dialog>
    </el-form-item>

Open the edit pop-up window to obtain the base64 file stream containing the image. When the data structure of the base64 file stream obtained from the backend is in the form of an object array, such as: image:[{url:“xxxxx”},{url:“xxxxx”}] , we first need to echo the image, this part of the code is implemented as follows:

 methods: {
    
    
   editProject(projectInfos) {
    
       //projectInfos为当前行信息
      this.dialogVisible = true; //打开弹窗
      this.title = "编辑零部件";
      this.tempPic = []
      //由于此处共享了信息,需要进行深拷贝
      let infos = JSON.parse(JSON.stringify(projectInfos))
      this.addProjectForm = infos;
      /**
       * 假如当前行infos数据结构为:
       * {
       * projectId: 1,
       * uploadTime: 'xxx',
       * images:[{url: 'http://xxx', name: 'xxx'}, {url: 'http://xxx', name: 'xxx'}]
       * }
       */
//后端获取的是url地址需要先将url地址转成base64
       /**
       * 假如当前行infos数据结构为:
       * {
       * projectId: 1,
       * uploadTime: 'xxx',
       * images:[{url: base64, name: 'xxx'}, {url: base64, name: 'xxx'}]//图片为base64
       * }
       */
      this.imageListArr = [] //清空图片列表,防止图片重复
      //将数据结构拼成回显时所需的格式
      if (infos.images && infos.images.length > 0) {
    
    
        infos.images.map((item, index) => {
    
    
          // 将 Base64 编码转换成 Blob 对象
          let byteString = window.atob(singlePic.split(',')[1]);
          let mimeString = singlePic.split(',')[0].split(':')[1].split(';')[0];
          let ab = new ArrayBuffer(byteString.length);
          let ia = new Uint8Array(ab);
          for (let i = 0; i < byteString.length; i++) {
    
    
            ia[i] = byteString.charCodeAt(i);
          }
          let blob = new Blob([ab], {
    
     type: mimeString });
          // 转换成文件对象(File)
          let file = new File([blob], `pic${
      
      index}.png`, {
    
     type: mimeString, lastModified: Date.now() });
          //将其转换成url
          let url = URL.createObjectURL(file);
          //将其转换成临时文件对象,fileList中的文件对象包含name、size、type、lastModified、lastModifiedDate、uid、url等属性
          let tempFile = {
    
    
            name: file.name,
            size: file.size,
            type: file.type,
            raw: file,
            lastModified: file.lastModified,
            lastModifiedDate: file.lastModifiedDate,
            uid: file.lastModified,
            url
          }
          this.imageListArr.push({
    
    
            raw: tempFile.raw, //由于后续提交表单时需要用到file对象,所以这里需要拼接获取
            imgUrl: tempFile.url,
            sortNum: index + 1  //添加序号为了图片排序
          })
        })
      }
      //过滤一下imgUrl为空的数据,防止出现空白图片,并按照sortNum排序,sortNum为1开始
      //(注:开发过程中发现,如果不过滤空白图片,会出现空白图片,原因不明)
      this.imageListArr = this.imageListArr.filter(item => {
    
    
        return item.imgUrl != ''
      });
      //按照sortNum排序
      this.imageListArr.sort((a, b) => {
    
    
        return a.sortNum - b.sortNum  //升序
      })
    },
    //拖拽图片
    dataDragEnd() {
    
    
      // 拖拽图片更换位置 并重新从1开始排序
      this.imageListArr.forEach((item, index) => {
    
    
        item.sortNum = index + 1
      })
      //过滤一下imgUrl为空的数据
      this.imageListArr = this.imageListArr.filter(item => {
    
    
        return item.imgUrl != ''
      });
    },
  }

The above code implements the drag and drop function, and the code for deleting and previewing pictures is as follows:

//删除图片
    handleRemove(index) {
    
    
      this.imageListArr.splice(index, 1)
    },
    // 处理图片预览效果
    handlePreview(index) {
    
    
      this.previewPath = this.imageListArr[index].imgUrl
      this.previewVisible = true
    },

3.4 Upload pictures through el-upload, first limit the type and size of pictures

//上传前对图片的大小和类型进行限制
    handleChange(file) {
    
    
      const isJPG = file.raw.type === 'image/jpeg';
      const isPNG = file.raw.type === 'image/png';
      const isGIF = file.raw.type === 'image/gif';
      if (!isJPG && !isPNG && !isGIF) {
    
    
        this.$message.error('上传图片只能是 JPG/PNG/GIF 格式!');
        return false;
      }
      const isLt2M = file.size / 1024 / 1024 < 2; // 上传图片大小限制2M
      if (!isLt2M) {
    
    
        this.$message.error('上传图片大小不能超过 2MB!');
        return false;
      }
      let url = URL.createObjectURL(file.raw);
      let obj = {
    
    
        raw: file.raw, //点击确定按钮,将图片上传给后端时后端需要的参数
        imgUrl: url
      }
      this.imageListArr.push(obj)
      //过滤一下imgUrl为空的数据
      this.imageListArr = this.imageListArr.filter(item => {
    
    
        return item.imgUrl != ''
      });
      //上传的图片和回显的图片进行重新排序
      this.imageListArr.map((item, index) =>
        item.sortNum = index + 1
      )
    },

3.5 Submit the picture to the server when the confirm button is clicked

//提交编辑的设备信息
    submitDeviceInfo() {
    
    
      let formData = new FormData(); //创建form对象,用于上传图片
      this.imageListArr.forEach((file) => {
    
    
        formData.append('files', file.raw); //添加图片信息的参数,所以3.4中拼接时添加了raw参数
      });
      //上传图片
      const header = {
    
    
        'Content-Type': 'multipart/form-data',
      }
      //提交时调用后端上传接口
      fileUpload(formData, header).then(response => {
    
    
        if (response.Code === 20000) {
    
    
          this.picUrl = response.Data.files
          //提交表单,创建或编辑设备信息,传入图片地址,后台进行保存,
          //返回成功后,关闭弹窗,刷新列表,重置表单
          this.$refs.projectForm.validate((valid) => {
    
    
            if (valid) {
    
    
              let params = {
    
    
                name: this.addProjectForm.name,
                serial_number: this.addProjectForm.serial_number,
                supplier: this.addProjectForm.supplier,
                memo: this.addProjectForm.memo,
                pic_addr: this.picUrl
              }
              editDeviceList(this.partId, params).then(response => {
    
    
                if (response.Code === 20000) {
    
    
                  this.handleClose()
                  this.getList()
                }
              }).catch(() => {
    
     })
            } else {
    
    
              this.$message.error('请输入必填项')
            }
          })
        }
      }).catch(() => {
    
     })
    },

Guess you like

Origin blog.csdn.net/qq_36660135/article/details/130425390