<template>
  <div>
    <template v-if="uploadStyle === 'simple'">
      <a-upload
        :accept="model.accept?.join('')"
        :customRequest="uploadFiles"
        :multiple="model.acceptCount && model.acceptCount>1"
        :file-list="uploadedFileList"
        @preview="handlePreview"
        :remove="deleteFileItem"
        :show-upload-list="{
          showRemoveIcon: !readOnly,
          showPreviewIcon: true,
          showDownloadIcon: false
        }">
        <a-space>
          <a-button style="margin-top: 2%">
            <a-icon type="upload"/>
            上传
          </a-button>
          <a-button v-if="useScanner" style="margin-top: 2%" @click.stop="useScannerUpload" icon="camera">
            高拍仪
          </a-button>
        </a-space>
      </a-upload>
    </template>
    <a-upload-dragger
      v-else-if="model.type === 'file' || model.type === 'signature'"
      :accept="model.accept?.join('')"
      :customRequest="uploadFiles"
      :file-list="uploadedFileList"
      @preview="handlePreview"
      :multiple="true"
      :remove="deleteFileItem"
      :show-upload-list="{
        showRemoveIcon: !readOnly,
        showPreviewIcon: true,
        showDownloadIcon: false
      }"
      name="file">
      <p class="ant-upload-drag-icon">
        <a-icon type="inbox"/>
      </p>
      <p class="ant-upload-text">
        点击或拖动文件到该区域上传
      </p>
      <p class="ant-upload-hint">
        支持单个或多个文件
      </p>
      <a-button v-if="useScanner" style="margin-top: 2%" @click.stop="useScannerUpload" icon="camera">
        高拍仪
      </a-button>
    </a-upload-dragger>
    <a-upload
      v-else
      @preview="handlePreview"
      :accept="model.accept?.join('')"
      :multiple="model.acceptCount && model.acceptCount>1"
      :customRequest="uploadFiles"
      :file-list="uploadedFileList"
      :remove="deleteFileItem"
      :show-upload-list="{
        showRemoveIcon: !readOnly,
        showPreviewIcon: true,
        showDownloadIcon: false
      }"
      list-type="picture-card">
      <a-icon v-if="!readOnly" type="plus"/>
      <div v-if="!readOnly" class="ant-upload-text">
        上传图片
      </div>
      <a-button v-if="useScanner" style="margin-top: 2%" @click.stop="useScannerUpload" icon="camera">
        高拍仪
      </a-button>
    </a-upload>

    <height-scanner v-if="useScanner" :show="showScanner" @confirmPhoto="confirmPhoto" @cancel="handleCancelScanner" ref="heightScanner"/>

    <!-- 使用封装的图片预览组件 -->
    <image-preview-modal
      :visible="previewVisible"
      :image-url="previewImage"
      :image-name="previewImageName"
      @close="previewVisible = false"
    />
  </div>
</template>

<script>
import { mapState } from 'vuex'
import { fileDelete, fileDeleteV4, upload } from '@vue2-client/services/api/common'
import HeightScanner from '@vue2-client/components/HeightScanner/index.vue'
import ImagePreviewModal from '@vue2-client/base-client/components/common/ImagePreviewModal'
import { base64ToFile } from '@vue2-client/utils/util'
import moment from 'moment'

export default {
  name: 'Uploads',
  components: {
    HeightScanner,
    ImagePreviewModal
  },
  data () {
    return {
      uploadedFileList: [],
      previewVisible: false,
      previewImage: '',
      previewImageName: '',
      showScanner: false
    }
  },
  props: {
    // 表单属性
    model: {
      type: Object,
      default: () => {
        return {}
      }
    },
    files: {
      type: Array,
      default: () => {
        return []
      }
    },
    images: {
      type: Array,
      default: () => {
        return []
      }
    },
    serviceName: {
      type: String,
      default: undefined
    },
    uploadStyle: {
      type: String,
      default: undefined
    },
    // outerContainerIndex，是为了XReport，返回外侧行的Index，每一行都有可能有图片，所以要知道是哪一个Index发出的事件
    outerContainerIndex: {
      type: [String, Number],
      default: undefined
    },
    // 图片上传后添加前缀
    imgPrefix: {
      type: String,
      default: undefined
    },
    // 是否开启高拍仪
    useScanner: {
      type: Boolean,
      default: false
    },
    // 是否只读
    readOnly: {
      type: Boolean,
      default: false
    },
    // 兼容图片(新的image类型的表单项的字段名可自定义了，不再固定为Images，该属性为传入的新的图片列表)
    // 如果字段名依旧为Images，则不需要该属性，而是使用images属性（兼容旧版的代码）
    compatibleImages: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 兼容签名(PC端没有签名功能，只做展示，归属到文件上传中，该属性为传入的签名列表)
    signs: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  computed: {
    ...mapState('account', { currUser: 'user' }),
    ...mapState('setting', ['compatible'])
  },
  created () {
    // const list = this.model.type === 'file' ? [...this.files] : [...this.images]
    let list = []
    if (this.model.type === 'file') {
      list = [...this.files]
    } else if (this.model.type === 'signature') {
      list = [...this.signs]
    } else {
      if (this.model.type === 'image' && this.model.model === 'Images') {
        list = [...this.images]
      } else if (this.model.type === 'image' && this.model.model !== 'Images') {
        list = [...this.compatibleImages]
      } else {
        list = []
      }
    }

    if (this.model.useType) {
      // {uid,url,name,f_use_type?,f_form_type?}
      this.uploadedFileList = list.filter(item => item.f_use_type === this.model.useType)
    } else {
      this.uploadedFileList = list
    }
    // 第三个参数‘created’，是因为XReport，有些图片上传需要外界自己控制上传下载的逻辑
    // 如果在组件加载完成就emit的话，外侧组件会以为图片已经更新，会调用后端，造成性能浪费
    // 所以外侧需要一个标识来判断，该emit事件是不是初始化的时候发出的
    if (this.outerContainerIndex !== undefined) {
      this.$emit('setFiles', this.uploadedFileList.filter(item => item.status === 'done'), this.outerContainerIndex, 'created')
    } else {
      this.$emit('setFiles', this.uploadedFileList.filter(item => item.status === 'done').map(item => item.id), undefined, 'created')
    }
  },
  methods: {
    async handlePreview (file) {
      if (this.isImageFile(file)) {
        // 图片文件：预览
        this.previewImage = file.url
        this.previewImageName = file.name || 'preview_image'
        this.previewVisible = true
      } else {
        // 其他文件：下载
        await this.handleDownload(file)
      }
    },

    async handleDownload (file) {
      const link = document.createElement('a')
      link.href = file.url
      link.download = file.name || 'download'
      link.target = '_blank'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    },

    isImageFile (file) {
      const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
      const fileName = file.name ? file.name.toLowerCase() : ''
      return imageExtensions.some(ext => fileName.endsWith(ext))
    },

    confirmPhoto (img) {
      const fileName = `GaoPaiYi_${moment().format('YYYYMMDDHHmmss')}.png`
      const file = base64ToFile(img, fileName)
      file.uid = fileName
      const info = {
        file
      }
      this.uploadFiles(info)
    },

    useScannerUpload (e) {
      // 打开高拍仪
      this.showScanner = true
    },

    handleCancelScanner () {
      // 关闭高拍仪弹窗
      this.showScanner = false
    },

    uploadFiles (info) {
      if (this.uploadedFileList.length >= this.model.acceptCount) {
        this.$message.error(`当前表单限制仅可上传 ${this.model.acceptCount} 个文件`)
        return
      }
      // 初始化文件信息
      const fileInfo = {
        uid: info.file.uid,
        name: info.file.name,
        status: 'uploading',
        response: '',
        url: '',
      }
      // 放入上传列表中，以便于显示上传进度
      this.uploadedFileList.push(fileInfo)
      // 组装上传数据
      const headers = {
        'Content-Type': 'multipart/form-data',
      }
      const formData = new FormData()
      formData.append('avatar', info.file)
      formData.append('resUploadMode', this.model.resUploadMode ?? 'server')
      if (this.model.pathKey) {
        formData.append('pathKey', this.model.pathKey ?? 'Default')
      }
      // formData.append('stockAlias', this.model.stockAlias)
      formData.append('formType', this.model.type)
      formData.append('useType', this.model.useType ?? 'Default')
      formData.append('resUploadStock', this.model.resUploadStock ?? 1)
      formData.append('filename', info.file.name)
      formData.append('filesize', (info.file.size / 1024 / 1024).toFixed(4))
      formData.append('f_operator', this.currUser ? this.currUser.username : '')

      upload(formData, this.serviceName, { headers, timeout: 600 * 1000, dedupe: false }).then(res => {
        // 根据服务端返回的结果判断成功与否，设置文件条目的状态
        if (res.success || res.id) {
          fileInfo.status = 'done'
          let dataObj
          if (res.id) {
            dataObj = res
          } else if (typeof res.data === 'string') {
            dataObj = JSON.parse(res.data)
          } else {
            dataObj = res.data
          }
          fileInfo.response = dataObj
          fileInfo.id = dataObj.id
          // 如果新上传的图片是V4，需要携带serviceName前缀，但是同时也要回显老系统图片
          if (this.imgPrefix) {
            fileInfo.url = this.imgPrefix + dataObj.f_downloadpath
          } else {
            fileInfo.url = dataObj.f_downloadpath
          }
          if (this.outerContainerIndex !== undefined) {
            this.$emit('setFiles', this.uploadedFileList.filter(item => item.status === 'done'), this.outerContainerIndex)
          } else {
            this.$emit('setFiles', this.uploadedFileList.filter(item => item.status === 'done').map(item => item.id))
            this.$emit('setFilesAllInfo', this.uploadedFileList.filter(item => item.status === 'done').map(item => item))
          }
          this.$message.success('上传成功！')
        } else {
          fileInfo.status = 'error'
          fileInfo.response = res.data
          this.$message.error('上传失败！')
        }
      }).catch((e) => {
        fileInfo.status = 'error'
        fileInfo.response = e
      })
    },

    // 删除文件
    deleteFileItem (file) {
      const that = this
      this.$confirm({
        title: '提醒',
        content: '确定删除该文件吗?',
        okText: '删除',
        okType: 'danger',
        cancelText: '取消',
        zIndex: 2000,
        onOk () {
          //  阳春博能工单信息V4页面有时会删除V3照片, V3照片不能通过这个请求删除, 已经在外层进行删除处理
          if (file.id && !file.version) {
            switch (that.compatible) {
              case 'V3':
                fileDelete({ id: file.id, f_state: '删除' })
                  .then(res => {
                  }).catch(e => {
                })
                break
              case 'V4':
                fileDeleteV4({ id: file.id, resDeleteMode: 'server' })
                  .then(res => {
                  }).catch(e => {
                })
                break
            }
          }
          // 找到当前文件所在列表的索引
          const index = that.uploadedFileList.indexOf(file)
          // 从列表中移除该文件
          that.uploadedFileList.splice(index, 1)
          if (that.outerContainerIndex !== undefined) {
            that.$emit('setFiles', that.uploadedFileList.filter(item => item.status === 'done'), that.outerContainerIndex)
          } else {
            that.$emit('setFiles', that.uploadedFileList.filter(item => item.status === 'done').map(item => item.id))
          }
        },
        onCancel () {
          console.log('取消删除')
        },
      })
      return true
    }
  }
}
</script>
<style scoped>
</style>
