index copy.vue 6.86 KB
<template>
  <div class="component-upload-image">
    <div v-if="false" class="imgBox">
      <div v-for="item in fileList" :key="item.url" class="imgItem">
        <div class="dot">X</div>
        <img :src="item.url">
      </div>
    </div>
    <el-upload multiple :action="uploadFileUrl" list-type="picture-card" :on-success="handleUploadSuccess"
      :before-upload="handleBeforeUpload" :limit="limit" :on-error="handleUploadError" :on-exceed="handleExceed"
      name="file" :on-remove="handleRemove" :show-file-list="true" :headers="headers" :file-list="fileList"
      :on-preview="handlePictureCardPreview" :class="{hide: this.fileList.length >= this.limit}">
      <i class="el-icon-plus" />
    </el-upload>

    <!-- 上传提示 -->
    <div v-if="showTip" slot="tip" class="el-upload__tip">
      请上传
      <template v-if="fileSize"> 大小不超过 <b style="color: #3F9B6A">{{ fileSize }}MB</b></template>
      <template v-if="fileType"> 格式为 <b style="color: #3F9B6A">{{ fileType.join('/') }}</b></template>
      的文件
    </div>

    <el-dialog :visible.sync="dialogVisible" title="预览" width="800" append-to-body>
      <!--    <img
        :src="dialogImageUrl"
        style="display: block; width:200px; margin: 0 auto"
      > -->
      <el-image style="width: 200px; height: 200px" :src="dialogImageUrl" fit="fill"></el-image>
    </el-dialog>
  </div>
</template>

<script>
  // import { getAccessToken } from '@/utils/auth'
  import {
    uploadUrl
  } from '@/utils/request'
  export default {
    props: {
      value: [String, Object, Array],
      // 图片数量限制
      limit: {
        type: Number,
        default: 5
      },
      // 大小限制(MB)
      fileSize: {
        type: Number,
        default: 5
      },
      // 文件类型, 例如['png', 'jpg', 'jpeg']
      fileType: {
        type: Array,
        default: () => ['png', 'jpg', 'jpeg']
      },
      // 是否显示提示
      isShowTip: {
        type: Boolean,
        default: true
      }
    },
    data() {
      return {
        host: '',
        number: 0,
        uploadList: [],
        dialogImageUrl: '',
        dialogVisible: false,
        hideUpload: false,
        uploadFileUrl: uploadUrl, // 请求地址
        headers: {
          Authorization: ''
        }, // 设置上传的请求头部
        fileList: []
      }
    },
    computed: {
      // 是否显示提示
      showTip() {
        return this.isShowTip && (this.fileType || this.fileSize)
      }
    },
    watch: {
      value: {
        handler(val) {
          if (val) {
            // 首先将值转为数组
            const list = Array.isArray(val) ? val : this.value.split(',')
            // 然后将数组转为对象数组
            this.fileList = list.map(item => {
              if (typeof item === 'string') {
                item = {
                  name: item,
                  url: item
                }
              }
              return item
            })
          } else {
            this.fileList = []
            return []
          }
        },
        deep: true,
        immediate: true
      }
    },
    onload() {
      this.host = window.location.host
    },
    methods: {
      // 删除图片
      handleRemove(file, fileList) {
        const findex = this.fileList.map(f => f.name).indexOf(file.name)
        if (findex > -1) {
          this.fileList.splice(findex, 1)
          this.$emit('input', this.listToString(this.fileList))
        }
      },
      // 上传成功回调
      handleUploadSuccess(res) {
        this.uploadList.push({
          name: res.data.url,
          url: res.data.url
        })
        console.log(this.uploadList)
        if (this.uploadList.length === this.number) {
          this.fileList = this.fileList.concat(this.uploadList)
          this.uploadList = []
          this.number = 0
          this.$emit('input', this.listToString(this.fileList))
          // this.$modal.closeLoading()
        }
      },
      // 上传前loading加载
      handleBeforeUpload(file) {
        let isImg = false
        if (this.fileType.length) {
          let fileExtension = ''
          if (file.name.lastIndexOf('.') > -1) {
            fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
          }
          isImg = this.fileType.some(type => {
            if (file.type.indexOf(type) > -1) return true
            if (fileExtension && fileExtension.indexOf(type) > -1) return true
            return false
          })
        } else {
          isImg = file.type.indexOf('image') > -1
        }

        if (!isImg) {
          this.$message.error(`文件格式不正确, 请上传${this.fileType.join('/')}图片格式文件!`)
          return false
        }
        if (this.fileSize) {
          const isLt = file.size / 1024 / 1024 < this.fileSize
          if (!isLt) {
            this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`)
            return false
          }
        }
        this.$message.warning('正在上传图片,请稍候...')
        this.number++
      },
      // 文件个数超出
      handleExceed() {
        this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`)
      },
      // 上传失败
      handleUploadError() {
        this.$message.error('上传图片失败,请重试')
        // this.$modal.closeLoading()
      },
      // 预览
      handlePictureCardPreview(file) {
        this.dialogImageUrl = file.url
        this.dialogVisible = true
      },
      // 对象转成指定字符串分隔
      listToString(list, separator) {
        let strs = ''
        separator = separator || ','
        for (const i in list) {
          strs += list[i].url.replace(this.baseUrl, '') + separator
        }
        return strs !== '' ? strs.substr(0, strs.length - 1) : ''
      }
    }
  }
</script>
<style scoped lang="scss">
  // .el-upload--picture-card 控制加号部分
  ::v-deep.hide .el-upload--picture-card {
    display: none;
  }

  // 去掉动画效果
  ::v-deep .el-list-enter-active,
  ::v-deep .el-list-leave-active {
    transition: all 0s;
  }

  ::v-deep .el-list-enter,
  .el-list-leave-active {
    opacity: 0;
    transform: translateY(0);
  }

  .imgBox {
    display: flex;
    flex-wrap: wrap;

    .imgItem {
      position: relative;
      width: 100px;
      height: 100px;

      .dot {
        position: absolute;
        right: -10px;
        top: -10px;
        width: 20px;
        height: 20px;
        color: #fff;
        background-color: red;
        text-align: center;
        line-height: 20px;
        border-radius: 50%;
        cursor: pointer;
      }

      img {
        width: 100%;
        height: 100%;
        margin-right: 5px;
        margin-bottom: 5px;
        display: inline-block;
      }
    }
  }

  ::v-deep .el-upload--picture-card:hover,
  .el-upload:focus {
    border-color: #3F9B6A;
    color: #3F9B6A;
  }

  .el-upload__tip {}
</style>