<template>
  <div class="upload">
    <el-upload v-if="isBtn()" :action="action" :headers="headers" :multiple="multiple" :data="data" :name="name"
      :show-file-list="showFileList" :drag="drag" :accept="accept" :listType="listType" :autoUpload="autoUpload"
      :disabled="disabled" :before-upload="beforeUpload" :on-progress="onProgress" :on-success="onSuccess"
      :on-error="onError">
      <el-button v-if="listType !== 'picture-card'" :type="type" ref="upload">
        <slot v-if="percentage <= 0 && !form.file">点击上传</slot>
        <span v-if="percentage > 0 && !form.file">{{ title }}</span>
        <span v-if="form.file">上传成功</span>
      </el-button>
      <div v-else>
        <i class="el-icon-plus" />
      </div>
    </el-upload>
    <el-progress v-if="isPercentage()" type="circle" :percentage="percentage" :status="status"
      @click.native="handleUpload" :width="146" />
    <div class="img" v-if="isImg()">
      <i class="el-icon-delete" v-if="!disabled" @click="onDelete" />
      <el-image :src="form.file" />
    </div>
  </div>
</template>

<script>
const baseUrl = process.env.VUE_APP_BASE_API
import { getToken } from '@/utils/auth'
export default {
  props: {
    // 回显图片
    url: String,
    // 是否支持多选文件
    multiple: {
      type: Boolean,
      default: false
    },
    // 是否显示文件列表
    showFileList: {
      type: Boolean,
      default: false
    },
    // 是否支持拖拽上传
    drag: {
      type: Boolean,
      default: false
    },
    // 上传类型
    listType: {
      type: String,
      default: 'text'
    },
    // 是否支持自动上传
    autoUpload: {
      type: Boolean,
      default: true
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 最大允许上传个数
    limit: Number,
    // 文件类型
    accept: {
      type: String,
      default: ''
    },
    // 文件名
    name: {
      type: String,
      default: 'multipartFile'
    },
    // 图片尺寸
    width: Number,
    height: Number,
    // 文件大小
    size: Number
  },
  data() {
    return {
      // 上传类型
      obj: {
        'text': `${baseUrl}/system/file/file/upload`, // 文件上传
        'picture-card': `${baseUrl}/system/file/picture/upload`, // 图片上传
        'audio': `${baseUrl}/system/file/mp3/upload`, // 音频上传
        'zip': `${baseUrl}/system/file/file/uploadFolderZip`, // 压缩包上传
        'mp3': `${baseUrl}/admin/program/batch/upload` // 歌曲批量上传
      },
      // 上传地址
      action: '#',
      // 请求头部
      headers: {
        Authorization: "Bearer " + getToken()
      },
      // 额外参数
      data: {},
      // 进度条
      percentage: 0,
      title: '',
      // 进度条状态
      status: null,
      type: 'primary',
      // 表单
      form: {
        size: 0,
        file: ''
      }
    }
  },
  watch: {
    url(val) {
      this.form.file = val
      if (!val) {
        this.percentage = 0
      }
    },
    listType(val) {
      this.action = this.obj[val]
    }
  },
  created() {
    // 根据上传类型 变更 上传地址
    this.action = this.obj[this.listType]
    // 回显图片
    this.form.file = this.url
  },
  methods: {
    // 上传之前
    beforeUpload(file) {
      if ((this.width && this.height) || this.size) {
        this.checked(file)
      }
      this.form.size = file.size
    },

    // 判断图片尺寸 或 文件大小
    checked(file) {
      return new Promise((resolve, reject) => {
        if (this.listType === 'picture-card') {
          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.width}x${this.height}尺寸的图片`)
                reject(false)
              } else {
                resolve(true)
              }
            }
          }
        }

        if (this.size !== '' && ((file.size / 1024 / 1024) > this.size)) {
          this.$message.error(`文件大小不超过${this.size}`)
          reject(false)
        } else {
          resolve(true)
        }
      })
    },

    // 上传过程中
    onProgress(file) {
      this.percentage = parseInt(file.percent - 1)
      this.title = `已上传 ${parseInt(file.percent - 1)}%`
    },

    // 上传成功
    onSuccess(file) {
      if (file.code === 0) {
        this.form.file = file.data
        this.$emit('upload', this.form)
        this.title = '上传成功'
        this.type = 'success'
      }else{
        this.onError()
      }
    },

    // 上传失败
    onError() {
      this.status = 'exception'
      this.type = 'danger'
      this.title = '上传失败'
    },

    // 删除
    onDelete() {
      this.form.file = ''
      this.percentage = 0
      this.$emit('upload', this.form)
    },

    // 如果上传失败 重新上传
    handleUpload() {
      this.percentage = 0
    },

    // 上传按钮
    isBtn() {
      return ['text', 'audio', 'zip', 'mp3'].includes(this.listType) || (this.listType === 'picture-card' && this.percentage == 0 && !this.form.file)
    },
    // 显示进度条
    isPercentage() {
      return this.listType === 'picture-card' && this.percentage !== 0 && !this.form.file
    },
    // 显示图片
    isImg() {
      return this.listType === 'picture-card' && this.form.file
    }
  }
}
</script>

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

  .el-icon-plus {
    line-height: 146px;
  }

  .img {
    position: relative;
    width: 146px;
    height: 146px;
    border-radius: 5px;

    .el-icon-delete {
      width: 100%;
      height: 100%;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      text-align: center;
      line-height: 146px;
      z-index: 99;
      opacity: 0;
      font-size: 24px;
      color: #fff;
      transition: all 0.3s;
      background: rgb(0 0 0 / 50%);
    }

    .el-icon-delete:hover {
      opacity: 1;
      cursor: pointer;
    }

    .el-image {
      width: 100%;
      height: 100%;
    }
  }
}
</style>