<template>
  <!--上传组件-->
  <el-dialog class="big-file" title="大文件上传" :close-on-click-modal="false" :modal-append-to-body="false" append-to-body :visible.sync="uploadBigVisible">
    <div class="setting-dialog">
      <div class="uploader-big">
        <uploader
          ref="uploader"
          :auto-start="false"
          :options="options"
          :file-status-text="statusText"
          @file-success="fileSuccess"
          @files-added="filesAdded"
          @file-error="onFileError"
          @file-removed="filesRemove"
        >
          <uploader-unsupport />
          <uploader-drop>
            <p>将文件拖到此处，或点击上传</p>
            <uploader-btn single>
              <slot>
                <i class="iconfont icon-tianjiawenjian upload-icon" />
              </slot>
            </uploader-btn>
            <div class="el-upload__tip">上传限制文件大小：最大10GB/个</div>
            <!-- <uploader-btn :attrs="attrs">选择图片</uploader-btn>
              <uploader-btn :directory="true">选择文件夹</uploader-btn> -->
          </uploader-drop>
          <uploader-files />
          <!-- <ul class="file-list">
            <li
              v-for="file in fileList"
              :key="file.id"
              class="file-item"
              :class="`file-${file.id}`"
            >
              <uploader-file
                ref="files"
                :class="'file_' + file.id"
                :file="file"
                :list="true"
              />
            </li>
          </ul> -->
        </uploader>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button type="text" @click="handleCloseDialog">取消</el-button>
        <el-button :loading="btnLoading" type="primary" @click="handleUploadConfirm">保存</el-button>
      </div>
    </div>
  </el-dialog>
</template>

<script>
import { mapGetters } from 'vuex'
import axios from 'axios'
import SparkMD5 from 'spark-md5'
import { getToken } from '@/utils/auth'
import { getCurrentTime } from '@/utils/index'
// https://juejin.cn/post/7040817922540830728
export default {
  props: {
    selectedCategory: {
      type: Object,
      default: function() {
        return {}
      }
    },
    arcId: {
      type: String,
      default: function() {
        return ''
      }
    }
  },
  data() {
    return {
      btnLoading: false,
      uploadBigVisible: false,
      skip: false,
      options: {
        target: '/api/collect/upload',
        // 开启服务端分片校验功能
        testChunks: true, // 是否分片
        singleFile: true, // 单文件上传
        uploadMethod: 'post', // 真正上传的时候使用的 HTTP 方法,默认 POST
        allowDuplicateUploads: false, // 上传过得文件不可以再上传
        parseTimeRemaining: function(timeRemaining, parsedTimeRemaining) {
          return parsedTimeRemaining
            .replace(/\syears?/, '年')
            .replace(/\days?/, '天')
            .replace(/\shours?/, '小时')
            .replace(/\sminutes?/, '分钟')
            .replace(/\sseconds?/, '秒')
        },
        // 服务器分片校验函数
        checkChunkUploadedByResponse: (chunk, message) => {
          const result = JSON.parse(message)
          if (result.data.skipUpload) {
            this.skip = true
            return true
          }
          return (result.data.uploaded || []).indexOf(chunk.offset + 1) >= 0
        },
        headers: {
          'Authorization': getToken()
        }
      },
      attrs: {
        accept: 'image/*'
      },
      // 修改上传状态
      statusText: {
        success: '上传成功',
        error: '上传出错了',
        uploading: '上传中...',
        paused: '暂停中...',
        waiting: '等待中...',
        cmd5: '计算文件MD5中...'
      },
      fileList: [],
      nowDate: null,
      submitted: false
    }
  },
  computed: {
    ...mapGetters([
      'baseApi'
    ])
  },
  methods: {
    fileSuccess(rootFile, file, response, chunk) {
      this.chunkOffset = []
      const result = JSON.parse(response)
      console.log('result', result)
      // 是否需要合并
      // if (result.data.needMerge && !this.skip) {
      // } else {
      //   console.log('上传成功，不需要合并')
      // }
      this.fileList.push(file)
      if (result.code === 200 && this.fileList.length !== 0) {
        this.submitted = true
      } else {
        this.submitted = false
      }
      if (this.skip) {
        this.skip = false
      }
    },
    filesRemove(file, index) {
      this.fileList = []
      const uploaderInstance = this.$refs.uploader.uploader
      const temp = uploaderInstance.fileList.findIndex(e => e.uniqueIdentifier === file.uniqueIdentifier)
      if (temp > -1) {
        uploaderInstance.fileList[temp].cancel() // 这句代码是删除所选上传文件的关键
      }
    },
    handleUploadConfirm() {
      if (this.$refs.uploader.fileList.length === 0) {
        this.$message.error('请选择要上传的文件!')
        return false
      }
      this.nowDate = getCurrentTime()
      this.$refs.uploader.fileList.map(async(item, index) => {
        const json = {}
        const jsonArray = []
        const jsonString = {}
        if (item.file.type.substring(0, item.file.type.indexOf('/')) === 'image') {
          const fileBase64 = await this.getBase64(item)
          const imgRes = await this.getImgPx(fileBase64)
          item.file.px = imgRes.width + 'px*' + imgRes.height + 'px'
        } else {
          item.file.px = ''
        }
        jsonString.file_name = item.file.name
        jsonString.file_size = item.file.size
        jsonString.file_type = item.file.name.substring(item.name.lastIndexOf('.') + 1, item.file.name.length)
        // jsonString.file_path = res.data.data
        jsonString.file_path = ''
        jsonString.sequence = null
        jsonString.archive_id = this.arcId
        jsonString.file_dpi = item.file.px
        jsonString.file_thumbnail = ''
        jsonString.create_time = this.nowDate
        jsonString.id = null
        jsonArray.push(jsonString)

        json.categoryId = this.selectedCategory.id
        json.archivesId = this.arcId
        json.identifier = item.uniqueIdentifier
        json.filename = item.name
        //  chunk.offset
        json.totalChunks = item.chunks.length - 1
        json.totalSize = item.size
        json.fileJsonString = JSON.stringify(jsonArray)

        if (item.completed && this.submitted) {
          this.btnLoading = true
          this.submitted = false
          axios.post(this.baseApi + '/api/collect/merge', json, { headers: {
            'Authorization': getToken()
          }}).then((res) => {
            console.log(res)
            if (res.data.code === 200 && res.data.data !== '') {
              this.$message.success('上传成功')
            } else {
              this.$message.error('上传失败')
            }
            this.$emit('close-dialog')
            this.uploadBigVisible = false
            this.fileList = []
            this.btnLoading = false
            this.$refs.uploader.files = []
            this.$refs.uploader.fileList = []
            this.$refs.uploader.uploader.fileList = []
            this.$refs.uploader.uploader.files = []
          })
        } else {
          this.submitted = false
          this.$message.error('请耐心等待文件上传完成后再保存!')
        }
      })
    },
    onFileError(rootFile, file, message, chunk) {
      this.$message.error('上传出错：' + message)
    },
    filesAdded(file, fileList, event) {
      file.forEach((e) => {
        this.fileList.push(e)
        this.computeMD5(e)
      })
    },
    computeMD5(file) {
      const maxMessage = '上传文件大小不能超过 10GB!'
      const maxSize = 10 * 1024 * 1024 * 1024
      if (file && file.size > maxSize) {
        this.$message.warning(maxMessage)
        return false
      }
      const fileReader = new FileReader()
      const time = new Date().getTime()
      const blobSlice =
        File.prototype.slice ||
        File.prototype.mozSlice ||
        File.prototype.webkitSlice
      let currentChunk = 0
      // 文件分片大小
      const chunkSize = 10 * 1024 * 1024
      const chunks = Math.ceil(file.size / chunkSize)
      const spark = new SparkMD5.ArrayBuffer()
      // 文件状态设为"计算MD5"
      file.cmd5 = true
      file.pause()
      loadNext()
      fileReader.onload = (e) => {
        spark.append(e.target.result)
        if (currentChunk < chunks) {
          currentChunk++
          loadNext()
          // 实时展示MD5的计算进度
          console.log(
            `第${currentChunk}分片解析完成, 开始第${
              currentChunk + 1
            } / ${chunks}分片解析`
          )
        } else {
          const md5 = spark.end()
          console.log(
            `MD5计算完毕：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${
              file.size
            } 用时：${new Date().getTime() - time} ms`
          )
          spark.destroy() // 释放缓存
          file.uniqueIdentifier = md5 // 将文件md5赋值给文件唯一标识
          file.cmd5 = false // 取消计算md5状态
          file.resume() // 开始上传
        }
      }
      fileReader.onerror = function() {
        this.error(`文件${file.name}读取出错，请检查该文件`)
        file.cancel()
      }
      function loadNext() {
        const start = currentChunk * chunkSize
        const end = start + chunkSize >= file.size ? file.size : start + chunkSize
        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end))
      }
    },
    // 将上传的图片转为base64
    getBase64(file) {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      return new Promise((resolve) => {
        reader.onload = () => {
          resolve(reader.result)
        }
      })
    },
    // 获取图片的分辨率
    getImgPx(img) {
      const image = new Image()
      image.src = img
      return new Promise((resolve) => {
        image.onload = () => {
          const width = image.width
          const height = image.height
          resolve({ width, height })
        }
      })
    },
    handleCloseDialog(done) {
      this.uploadBigVisible = false
      this.fileList = []
    }
  }
}
</script>

<style lang="scss" scoped>
.uploader-big{
  width: 100%;
  .uploader{
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 100%;
    text-align: center;
    margin-bottom: 8px;
    .uploader-drop{
      display: flex;
      flex-direction: column;
      justify-content: center;
      text-align: center;
      height: 180px;
      // padding: 20px 0;
      border: none;
      .uploader-btn{
        // width: 120px;
        margin: 20px 0 20px 0;
        padding: 0;
        border: none;
        i{
          font-size: 32px;
          color: #1F55EB;
        }
        &:hover{
          background-color: transparent;
        }
      }
      .el-upload__tip{
        font-size: 12px;
        color: #A6ADB6;
      }
    }
  }
  .upload-big-button{
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    margin: 10px 0 5px 0;
  }
}
.uploader-file[status="success"] .uploader-file-remove {
  display:block
}
</style>
