vue+elementui使用vuedraggable插件实现图片文件拖拽排序

安装

npm install vuedraggable

引入

import vuedraggable from 'vuedraggable'

写成组件

<template>
  <div class="upload-container">
    <vuedraggable v-model="sortImages" class="draggable-container" @change="changeImages">
      <div v-for="(image, index) in sortImages" :key="index" class="image-container" @mouseover="mouseover(index)" @mouseleave="mouseleave(index)">
        <img v-if="type === 1" class="image" :src="image">
        <template v-else>
          <div v-if="index >= 0">
            <i class="el-icon-document" />{{ image.fileName }}
          </div>
        </template>
        <i v-if="index === currentIndex" class="el-icon-close close" @click="removeImage(image)" />
      </div>
    </vuedraggable>
    <el-upload
      action="#"
      :accept="acceptConfig"
      :show-file-list="false"
      :on-change="customUpload"
      :auto-upload="false"
      :disabled="disabled"
    >
      <el-button v-if="sortImages.length < limit" size="small" :disabled="disabled">{{ type === 1 ? '添加图片' : '添加文件' }}</el-button>
      <el-button v-if="sortImages.length === limit" size="small" :disabled="disabled">{{ type === 1 ? '更换图片' : '更换文件' }}</el-button>
    </el-upload>
  </div>
</template>

<script>
import upload from '@/utils/upload'
import vuedraggable from 'vuedraggable'
import moment from 'moment'

export default {
  name: 'SortFile',
  components: { vuedraggable },
  props: {
    // eslint-disable-next-line vue/require-default-prop
    images: [String, Array],
    limit: {
      type: Number,
      default: 1
    },
    type: {
      type: Number,
      default: 1
    },
    uploadConfig: {
      type: Object,
      required: true,
      default: function() {
        return {}
      }
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      currentIndex: -1,
      sortImages: !this.images ? [] : [].concat(this.images),
      acceptConfig: 'image/jpeg,image/png,image/jpg'
    }
  },
  watch: {
    images(val) {
      this.sortImages = !this.images ? [] : [].concat(this.images)
    }
  },
  created() {
    if (this.type === 2) {
      this.acceptConfig = 'application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,.txt'
    }
  },
  methods: {
    customUpload(file) {
      const that = this
      if (that.type === 1) {
        const isLt2M = file.size / 1024 / 1024 < 2
        if (!isLt2M) {
          this.$message.error('上传图片大小不能超过2M')
          return false
        }
        if (['image/jpeg', 'image/png', 'image/jpg'].indexOf(file.raw.type) === -1) {
          this.$message.error('格式为JPG、JPEG、PNG')
          return false
        }
      }
      if (that.type === 2) {
        const isLt100M = file.size / 1024 / 1024 < 100
        if (!isLt100M) {
          this.$message.error('上传附件大小不能超过100M')
          return false
        }
      }
      const currentTime = moment(Date.now()).format('YYYYMMDDHHmmss')
      const name = file.name.split('.')[0]
      const type = file.name.split('.')[1]
      const copyFile = new File([file.raw], `${name}_${currentTime}.${type}`)
      upload(copyFile, this.uploadConfig, function(url) {
        if (url) {
          if (that.sortImages.length < that.limit) {
            if (that.type === 1) {
              that.sortImages.push(url)
            }
            if (that.type === 2) {
              that.sortImages.push({
                uri: url,
                fileName: file.name,
                fileSize: file.size / 1024 / 1024
              })
            }
          } else {
            that.sortImages.splice(that.sortImages.length - 1, 1, that.type === 1 ? url : {
              uri: url,
              fileName: file.name,
              fileSize: file.size / 1024 / 1024
            })
          }

          that.$emit('update:images', that.sortImages)
        }
      })
    },
    mouseover(index) {
      this.currentIndex = index
    },
    mouseleave(index) {
      this.currentIndex = -1
    },
    removeImage(image) {
      const index = this.sortImages.findIndex(item => {
        return item === image
      })
      this.sortImages.splice(index, 1)

      this.$emit('update:images', this.sortImages)
    },
    changeImages() {
      this.$emit('update:images', this.sortImages)
    }
  }
}
</script>

<style lang="scss" scoped>
.upload-container {
  width: 100%;
  display: flex;
  align-items: flex-end;

  .draggable-container {
    display: flex;

    .image-container {
      position: relative;
      width: 152px;
      height: 86px;
      margin-right: 17px;

      img {
        width: 100%;
        height: 100%;
      }

      .close {
        position: absolute;
        top: 4px;
        right: 4px;
        background: rgba(255, 255, 255, 1);
        border-radius: 50%;
        font-weight: 600;
      }
    }
  }

  .el-button {
    background: #EEF5FF;
    border: 1px solid #CFE3FD;
    color: #5E9FF8;
  }
}
</style>

引用组件

<SortFile :images.sync="logoUrl" :limit="1" :upload-config="uploadLogoConfig" />

参数说明

  • import upload from '@/utils/upload' 这里的upload.js在:https://blog.csdn.net/i15730384741/article/details/106300278
  • limit:当前上传限制图片张数
  • type : 默认为1,1代表上传图片,2代表上传文件
  • upload-config : 图片上传需要的config配置

你可能感兴趣的:(vue)