<template>
  <div class="ai-uploader">
    <div class="fileList">
      <div class="item" v-for="(item, i) in fileList" :key="i">
        <template v-if="type == 'image'">
          <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)"/>
        </template>
        <template v-else-if="type == 'video'">
          <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)"/>
        </template>
        <div class="file" v-else>
          <ai-image :preview="preview" :file="item"/>
          <div class="info">
            <span>{{ item.name }} </span>
            <i>{{ item.fileSizeStr }}</i>
          </div>
          <template v-if="!disabled">
            <div btn @tap="handleReUpload(i)">
              重新上传
            </div>
            <div btn @tap="remove(i)">
              删除
            </div>
          </template>
        </div>
      </div>
      <div v-if="!disabled&&(fileList.length == 0 || (multiple && fileList.length < limit))" class="default"
           @click="upload">
        <i class="iconfont iconfont-iconAdd"/>
        <span>{{ placeholder }}</span>
      </div>
    </div>
  </div>
</template>

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

export default {
  name: 'AiUploader',
  components: {AiImage},
  props: {
    limit: {default: 1}, //数量
    placeholder: {default: '添加图片'}, // 文字提示
    type: {default: 'image'}, // 文件类型，image还是file
    multiple: {
      type: Boolean,
      default: false,
    },
    fileId: String,
    mediaId: String,
    def: {default: () => []},
    action: String,
    preview: Boolean,
    size: {default: 10 * 1024 * 1024},
    disabled: Boolean,
    sourceType: {default: () => ['album', 'camera']}
  },
  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]
          }
        }
      },
      immediate: true,
      deep: true
    },
  },
  data() {
    return {
      fileList: [],
    }
  },
  methods: {
    remove(index) {
      this.fileList.splice(index, 1)
      this.$emit('list', this.fileList)
    },
    upload(wait) {
      typeof wait == 'function' && wait()
      let count = this.limit - (this.fileList?.length || 0)
      if (count > 0) {
        let params = {
          count,
          sizeType: ['compressed'],
          sourceType: [this.sourceType].flat(),
          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)
            }
          },
        }
        if (this.type == 'image') {
          uni.chooseImage(params)
        } else if (this.type == 'video') {
          uni.chooseVideo(params)
        } 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: '上传中'})
      let formData = new FormData()
      formData.append('file', img)
      if (this.manual) {
        this.$emit('manual', img)
        uni.hideLoading()
      } else {
        this.$http.post(this.api, formData, {
          params: {type: this.type},
        }).then((res) => {
          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 == '/app/wxcp/upload/uploadFile') {
              this.$emit('update:mediaId', res.data?.media?.mediaId)
              this.$emit('update:fileId', res.data.file.id)
              this.fileList.push(res.data.file)
            } 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("update:def", this.fileList)
            this.$emit("list", this.fileList)
          } else {
            this.$u.toast(res.msg)
          }
        }).catch(err => {
          this.$u.toast(err)
        }).finally(() => 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.fileList {
    display: flex;
    flex-wrap: wrap;

    .item {
      width: initial;
      padding: 0 10px 10px 0;
      position: relative;

      .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;
      }

      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;
      }

      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;
      }

      span {
        display: block;
        text-align: center;
        font-size: 28px;
      }
    }

    .file {
      width: 100vw;
      display: flex;
      align-items: center;
    }
  }
}
</style>
