<template>
  <div class="ai-uploader">
    <div class="imgList" v-if="type == 'image'">
      <div class="item" v-for="(item, i) in fileList" :key="i">
        <ai-image :src="item.url" :preview="preview"/>
        <u-icon v-if="!disabled" class="delBtn" color="#f46" name="close-circle-fill" size="40" @click="remove(i)"/>
      </div>
      <div v-if="!disabled&&(fileList.length == 0 || (fileList.length < limit))" class="default" @click="upload">
        <u-icon name="photo" size="64" :label="placeholder" label-pos="bottom" label-color="#89b"/>
      </div>
    </div>
    <div class="imgList" v-else-if="type == 'video'">
      <div class="item" v-for="(item, i) in fileList" :key="i">
        <video :src="item.url" :poster="item.thumb"/>
        <u-icon v-if="!disabled" class="delBtn" color="#f46" name="close-circle-fill" size="40" @click="remove(i)"/>
      </div>
      <div v-if="!disabled&&(fileList.length == 0 || (fileList.length < limit))" class="default" @click="upload">
        <u-icon name="camera" size="64" :label="placeholder" label-pos="bottom" label-color="#89b"/>
      </div>
    </div>
    <div class="fileList" v-else>
      <div class="item" v-for="(item, i) in fileList" :key="i">
        <ai-image :preview="preview" :file="item"/>
        <div class="info">
          <span>{{ item.name }} </span>
          <i>{{ item.fileSizeStr }}</i>
        </div>
        <template v-if="!disabled">
          <div class="btn" @tap="handleReUpload(i)">
            重新上传
          </div>
          <div class="btn" @tap="remove(i)">
            删除
          </div>
        </template>
      </div>
      <div v-if="!disabled&&(fileList.length == 0 || (multiple && fileList.length < limit))" class="default"
           @click="upload">
        <u-icon name="photo" size="64" :label="placeholder" label-pos="bottom" label-color="#89b"/>
      </div>
    </div>
  </div>
</template>

<script>
import {mapState} from 'vuex'
import AiImage from '../AiImage/AiImage'

export default {
  name: 'AiUploader',
  components: {AiImage},
  model: {
    prop: 'def', // :def.sync才可以回显，v-model不能回显(bug)
    event: 'input'
  },
  props: {
    limit: {default: 1}, //数量
    placeholder: {default: '添加图片'}, // 文字提示
    type: {default: 'image'}, // 文件类型:image,file,video
    multiple: {
      type: Boolean,
      default: false,
    },
    fileId: String,
    mediaId: String,
    def: {default: () => []},
    action: String,
    preview: Boolean,
    size: {default: 10 * 1024 * 1024},
    disabled: Boolean,
  },
  computed: {
    ...mapState(['token']),
    errorImage: v => v.$cdn + 'file.png',
    api() {
      if (this.action) return this.action
      else return {
        image: '/admin/file/add',
        file: '/admin/file/add',
        video: '/admin/file/addVideo',
      }[this.type]
    }
  },
  watch: {
    def: {
      handler(v) {
        if (!!v?.toString()) {
          if (this.multiple) {
            this.fileList = v
          } else if (v?.url) {
            this.fileList = [v]
          } else if (v?.length > 0) {
            this.fileList = v
          }
        }
      },
      immediate: true,
      deep: true
    },
  },
  data() {
    return {
      fileList: [],
    }
  },
  methods: {
    remove(index) {
      this.fileList.splice(index, 1)
      this.$emit('input', this.fileList)
    },
    upload(wait) {
      let count = this.limit - (this.fileList?.length || 0)
      if (count > 0) {
        const params = {
          count,
          sizeType: ['compressed'],
          sourceType: ['album', 'camera'],
          success: res => {
            let count = this.fileList?.length + (res.tempFiles?.length || res.tempFile ? 1 : 0)
            if (count > this.limit && this.limit !== 1) {
              return this.$u.toast(`不能超过${this.limit}个`)
            }
            if (res.tempFiles?.length > 0) {
              res.tempFiles.map(this.uploadFile)
            } else if (res?.tempFile) {
              this.uploadFile(res.tempFile)
            }
          },
        }
        typeof wait == 'function' && wait()
        if (this.type == 'image') {
          uni.chooseMedia({...params, mediaType: ['image']})
        } else if (this.type == 'video') {
          uni.chooseMedia({...params, mediaType: ['video']})
        } else {
          uni.chooseFile(params)
        }
      } else {
        this.$u.toast(`不能超过${this.limit}个`)
      }
    },
    uploadFile(img) {
      if (this.size > 0 && img.size > this.size) {
        return this.$u.toast(`不能超过${Math.ceil(this.size / 1024 / 1024)}MB`)
      }
      uni.showLoading({title: '上传中'})
      if (this.manual) {
        this.$emit('manual', img)
        uni.hideLoading()
      } else {
        const filePath = img.path || img.tempFilePath
        uni.uploadFile({
          url: this.$instance.defaults.baseURL + this.api,
          filePath,
          name: 'file',
          header: {
            'Content-Type': 'multipart/form-data',
            Authorization: this.token,
          },
          success: response => {
            const res = JSON.parse(response.data)
            if (res?.data) {
              this.$emit('data', res.data)
              this.$u.toast('上传成功!')
              if (!this.action) {//默认组件接口
                if (this.type == 'image') {
                  const [image = "",] = res.data
                  this.fileList.push({url: image.split(";")[0], id: image.split(";")?.[1]})
                } else if (this.type == 'video') {
                  const [video = "", thumb = ""] = res.data
                  this.fileList.push({url: video.split(";")[0], id: video.split(";")?.[1], thumb: thumb.split(";")[0]})
                }
              } else if (this.api == '/admin/file/add2') {
                let info = res.data
                this.$emit('update:fileId', info?.id)
                this.fileList.push(res.data)
              } else if (this.api == '/admin/file/add-portrait') {
                this.fileList.push({url: res.data?.split(";")?.[0], id: res.data?.split(";")?.[1]})
              }
              this.$emit("input", this.fileList)
              this.$emit("update:def", this.fileList)
            } else {
              this.$u.toast(res.msg)
            }
          },
          fail: console.error,
          complete: uni.hideLoading
        })
      }

    },
    handleReUpload(i) {
      this.upload(() => this.remove(i))
    },
  },
}
</script>

<style lang="scss" scoped>
.ai-uploader {
  width: 100%;
  line-height: normal;
  margin-bottom: 16px;

  ::v-deep.imgList {
    display: flex;
    flex-wrap: wrap;

    .item {
      width: 30vw;
      height: 30vw;
      position: relative;
      padding: 0 2pt 2pt 0;
      box-sizing: border-box;

      .delBtn {
        position: absolute;
        right: -8px;
        top: -8px;
        z-index: 2;
        border-radius: 50%;
        overflow: hidden;
        background-color: #fff;
        height: 40px;
      }

      image,video {
        width: 29vw;
        height: 29vw;
      }
    }
  }

  .fileList {
    .item {
      display: flex;
      align-items: center;
      margin-bottom: 10px;

      image {
        width: 160px;
        height: 160px;
      }

      i {
        font-style: normal;
        color: #9b9b9b;
      }

      .info {
        flex: 1;
        min-width: 0;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        overflow: hidden;
        text-overflow: ellipsis;

        & > span {
          flex: 1;
          min-width: 0;
        }
      }

      div.btn {
        color: $uni-color-primary;
        margin-right: 16px;

      }

      div:nth-child(4) {
        color: #f72c27;
      }

      & > * + * {
        margin-left: 20px;
      }
    }


  }

  .default {
    width: 30vw;
    height: 30vw;
    box-sizing: border-box;
    border-radius: 8px;
    background: #f3f4f7;
    color: #89b;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;

    .iconfont-iconAdd {
      font-size: 64px;
    }
  }
}
</style>
