<template>
  <div class="upload">
    <el-upload v-if="hidden" :action="newAction" :headers="headers" :multiple="multiple" :data="data"
      :accept="accept" :show-file-list="showFileList" :list-type="listType" :on-progress="onProgress"
      :on-error="onError" :on-success="onSuccess" :before-upload="beforeUpload" :disabled="disabled">
      <el-button v-if="listType !== 'picture-card'" :type="btnType">{{ newTitle }}</el-button>
      <i v-else class="el-icon-plus" />
    </el-upload>
    <el-progress v-if="isShow()" type="circle" :percentage="percent" :status="isStatus" />
    <div class="upload-image" v-if="newUrl">
      <el-image :src="newUrl" />
      <i v-if="disabled === false" class="el-icon-delete" @click="getDelete" />
    </div>
  </div>
</template>

<script>
const baseUrl = process.env.VUE_APP_BASE_API
import { getToken } from "@/utils/auth";
export default {
  props: {
    action: {
      type: String,
      default: ''
    },
    // 图片
    url: String,
    // 类型
    listType: {
      type: String,
      default: 'text'
    },
    // 是否显示已上传文件列表
    showFileList: {
      type: Boolean,
      default: false
    },
    // 是否支持多选文件
    multiple: {
      type: Boolean,
      default: false
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 上传按钮文字
    title: {
      type: String,
      default: '文件上传'
    },
    // 图片尺寸
    measure: {
      type: String,
      default: ''
    },
    // 文件大小
    size: Number
  },
  data() {
    return {
      // 上传地址
      newAction: this.action,
      // 请求头
      headers: {
        Authorization: "Bearer " + getToken(),
      },
      // 附带参数
      data: {},
      // 文件字段名
      name: '',
      // 是否显示上传按钮
      hidden: true,
      // 按钮文字
      newTitle: this.title,
      // 按钮颜色
      btnType: 'primary',
      // 进度条
      percent: 0,
      // 上传失败进度条
      isStatus: null,
      // 显示图片
      newUrl: this.url,
      // 传给父级的参数
      form: {},
      // 上传图片的尺寸
      width: Number(this.measure.split('*')[0]),
      height: Number(this.measure.split('*')[1]),
      // 上传的文件格式
      accept: ''
    }
  },
  watch: {
    measure(val) {
      this.width = Number(val.split('*')[0])
      this.height = Number(val.split('*')[1])
    },
    url(val) {
      this.newUrl = val ? val : ''
      this.hidden = val ? false : true
    }
  },
  mounted() {
    if (!this.action) {
      if (this.listType === 'picture-card') {
        this.newAction = `${baseUrl}/system/file/picture/upload`
        this.accept = '.jpg, .jpeg, .png, .bmp, .icon, .gif'
      } else if (this.listType === 'text') {
        this.newAction = `${baseUrl}/system/file/file/upload`
      } else if (this.listType === 'audio') {
        this.newAction = `${baseUrl}/system/file/mp3/upload`
        this.accept = '.mp3, .wav, .aiff, .midi, .wma'
      }
    }
    this.newUrl = this.url ? this.url : ''
    this.hidden = this.url ? false : true
  },
  methods: {
    // 上传之前
    async beforeUpload(file) {
      this.btnType = 'primary'
      if (this.measure || this.size) {
        await this.measureChecked(file).then((res) => {
          if (res) {
            this.isUpload(file)
          }
        })
      } else {
        this.isUpload(file)
      }
    },

    // 上传
    isUpload(file) {
      this.data.multipartFile = file
      this.name = file.name
      if (this.listType !== 'picture-card') {
        this.form.size = file.size
      } else {
        this.hidden = false
      }
    },

    // 上传过程中
    onProgress(e) {
      this.percent = parseInt(e.percent)
      this.newTitle = `已上传${parseInt(e.percent - 1)}%`
    },
    // 上传失败
    onError() {
      this.newTitle = `上传失败`
      this.btnType = `danger`
      this.isStatus = 'exception'
    },
    // 上传成功
    onSuccess(res) {
      if (this.listType === 'picture-card') {
        // 显示图片
        this.newUrl = res.data
      } else {
        // 按钮文字
        this.newTitle = '上传成功'
        this.btnType = 'success'
      }

      // 传参
      this.form.file = res.data
      this.$emit('upload', this.form)
    },

    // 删除图片
    getDelete() {
      if (this.listType == 'picture-card') {
        this.hidden = true
        this.percent = 0
        this.newUrl = ''
      }
      this.$emit('upload', this.form = {})
    },

    // 是否显示图片进度条
    isShow() {
      if (this.listType == 'picture-card') {
        return !this.hidden && this.newUrl === '' ? true : false
      } else {
        return false
      }
    },

    // 判断图片尺寸 或 文件大小
    measureChecked(file) {
      return new Promise((resolve, reject) => {
        if (this.measure) {
          let reader = new FileReader()
          reader.readAsDataURL(file)
          reader.onload = () => {
            let img = new Image()
            img.src = reader.result
            img.onload = () => {
              if (img.width !== this.width || img.height !== this.height) {
                this.$message.error(`请上传${this.measure}尺寸的图片`)
                reject
              } else {
                resolve(true)
              }
            }
          }
        }

        if (this.size) {
          if ((file.size / 1024 / 1024) > this.size) {
            this.$message.error(`上传文件过大`)
            reject
          } else {
            resolve(true)
          }
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.upload {
  display: inline-block;

  .el-button {
    margin: 0;
  }

  .upload-image {
    position: relative;
    width: 148px;

    .el-image {
      display: block;
    }

    .el-icon-delete {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 100%;
      height: 100%;
      transform: translate(-50%, -50%);
      background: rgb(0 0 0 / 50%);
      color: #fff;
      transition: all 0.3s;
      font-size: 24px;
      opacity: 0;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    i:hover {
      opacity: 1;
      cursor: pointer;
    }
  }
}
</style>