<template>
  <div id="app">
    <div style="margin: 10px 0;">
      <input type="file" @change="getFile" ref="importFile" />
      <button @click="cleanFlie">清空文件</button>
    </div>
    <div style="margin: 10px 0;">
      <!-- <el-radio v-model="compete" label="1">选拔赛</el-radio>
      <el-radio v-model="compete" label="2">决赛</el-radio> -->
      赛事编码：<input type="text" v-model="event" />
      年份：<input type="text" v-model="year" />
      (导入文件前填写，不写的话，赛事默认为YIIC，年份默认今年)
    </div>
    <div style="margin: 10px 0;">
      <el-radio v-model="radio" label="1">团队</el-radio>
      <el-radio v-model="radio" label="2">单人</el-radio>
    </div>
    <div style="margin: 10px 0;">
      <el-radio v-model="fileType" label="1">生成图片</el-radio>
      <el-radio v-model="fileType" label="2">生成压缩包</el-radio>
    </div>
    <div style="margin: 10px 0;">
      编码：<input type="text" v-model="bmText" />
      <button :disabled="isOver" @click="toBm">生成编码</button>
      <input type="text" placeholder="请输入导出的文件名" v-model="fileName">
      <button @click="exportExcel">导出列表数据表格文件</button>
      <input type="text" placeholder="请输入导出压缩包的文件名" v-model="zipName" v-show="fileType === '2'">
      <button @click="toPdf">{{ fileType === '1' ? '生成图片导出' : '生成压缩包导出' }}</button>
    </div>
    <el-table :data="datalist" border stripe @selection-change="handleSelectionChange" id="out-table" height="100%" style="flex: 1 1 auto;">
      <el-table-column type="selection" width="55">
      </el-table-column>
      <el-table-column prop="front" label="前12位编码" width="120">
      </el-table-column>
      <el-table-column prop="xh" label="序号" width="50">
      </el-table-column>
      <el-table-column prop="sdbh" label="赛队编号" width="180">
      </el-table-column>
      <el-table-column prop="zjh" label="证件号" width="180">
      </el-table-column>
      <el-table-column prop="sx" label="赛项名称" width="200">
      </el-table-column>
      <el-table-column prop="fz" label="参赛组别" width="80">
      </el-table-column>
      <el-table-column prop="xs" label="学生姓名" width="80">
      </el-table-column>
      <el-table-column prop="zdls" label="指导老师" width="80">
      </el-table-column>
      <el-table-column prop="xxmc" label="所在学校" width="200">
      </el-table-column>
      <el-table-column prop="ssdq" label="所属赛区" width="180">
      </el-table-column>
      <el-table-column prop="lx" label="类型" width="80">
      </el-table-column>
      <el-table-column prop="mc" label="奖项名次" width="100">
      </el-table-column>
      <el-table-column prop="bms" label="证书编码" width="220">
      </el-table-column>
    </el-table>
    <div style="display: inline-block;position: absolute;top: -1000px;">
      <div id="pdfDom" ref="posterWrap">
      </div>
    </div>
    <!-- <img :src="xx" > -->
  </div>
</template>

<script>
import * as XLSX from 'xlsx/xlsx.mjs'
import html2Canvas from 'html2canvas'
import JSZip from 'jszip'
import FileSaver from 'file-saver'
export default {
  name: 'App',
  data () {
    return {
      a: 1,
      fileType: '2',
      compete: '1',
      datalist: [],
      bmText: '',
      isOver: false,
      url: require('./assets/one.jpg'),
      urlTwo: require('./assets/two.jpg'),
      urlThree: require('./assets/three.jpg'),
      urlFour: require('./assets/youxiu.jpg'),
      oUrl: require('./assets/oOne.jpg'),
      oUrlTwo: require('./assets/oTwo.jpg'),
      oUrlThree: require('./assets/oThree.jpg'),
      oUrlFour: require('./assets/oYouxiu.jpg'),
      multipleSelection: [],
      radio: '1',
      fileName: '',
      sourceList: [],
      flag: 1,
      zipName: '',
      event: '', // 赛事编写
      year: '', // 年份,
      load: null
      // xx: ''
    }
  },
  methods: {
    // 上传文件后处理excel内容，展示在页面中
    getFile (e) {
      const that = this
      const files = e.target.files[0]
      const fileReader = new FileReader()
      // debugger
      let workbook
      let persons
      fileReader.onload = function (e) {
        const data = e.target.result
        workbook = XLSX.read(data, {
          type: 'binary'
        })
        persons = []
        // 表格的表格范围，可用于判断表头是否数量是否正确
        let fromTo = ''
        // 遍历每张表读取
        for (const sheet in workbook.Sheets) {
          // if (workbook.Sheets.hasOwnProperty(sheet)) {
          //   fromTo = workbook.Sheets[sheet]['!ref']
          //   console.log(fromTo)
          //   persons = persons.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]))
          //   // break; // 如果只取第一张表，就取消注释这行
          // }
          fromTo = workbook.Sheets[sheet]['!ref']
          persons = persons.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]))
        }
        console.log(fromTo, 1)
        // console.log(persons)
        let Data = that.handleFzbm(persons)
        Data = that.handleBm(Data)
        that.datalist = that.autoCode(Data)
        console.log(that.datalist, 89)
      }

      // 以二进制方式打开文件
      fileReader.readAsBinaryString(files)
    },
    // 导入文件后先处理证书编码
    handleFzbm (data) {
      if (this.radio === '2') {
        let one = 1
        let two = 1
        let three = 1
        let four = 1
        data.forEach((item) => {
          if (item.mc === '一等奖') {
            item.bm = one
            one++
          } else if (item.mc === '二等奖') {
            item.bm = two
            two++
          } else if (item.mc === '三等奖') {
            item.bm = three
            three++
          } else if (item.mc === '优秀奖') {
            item.bm = four
            four++
          }
          // item.bm = index + 1
        })
        return data
      } else {
        let flag = 1
        let one = 1
        let two = 1
        let three = 1
        let four = 1
        for (let i = 0; i < data.length; i++) {
          if (i === 0) {
            data[i].fzbm = flag
            flag++
            // 要判断
            if (data[i].mc === '一等奖') {
              data[i].bm = one
              one++
            } else if (data[i].mc === '二等奖') {
              data[i].bm = two
              two++
            } else if (data[i].mc === '三等奖') {
              data[i].bm = three
              three++
            } else if (data[i].mc === '优秀奖') {
              data[i].bm = four
              four++
            }
            continue
          }
          if (data[i].sdbh === data[i - 1].sdbh) {
            data[i].bm = data[i - 1].bm
          } else {
            if (data[i].mc === '一等奖') {
              data[i].bm = one
              one++
            } else if (data[i].mc === '二等奖') {
              data[i].bm = two
              two++
            } else if (data[i].mc === '三等奖') {
              data[i].bm = three
              three++
            } else if (data[i].mc === '优秀奖') {
              data[i].bm = four
              four++
            }
          }
          // data[i].bm = data[i].sdbh === data[i - 1].sdbh ? data[i - 1].bm : data[i - 1].bm + 1
          if (data[i].sdbh === data[i - 1].sdbh) {
            data[i].fzbm = flag
            flag++
          } else {
            flag = 1
            data[i].fzbm = flag
            flag++
          }
        }
        // console.log(data)
        return data
      }
    },
    // 根据名次选择对应证书图片
    handleBm (data) {
      if (!this.isOver) {
        data.forEach(element => {
          // element.bms = this.bmText + element.bm.toString().padStart(5, '0') + (element.fzbm === undefined ? '' : '-' + element.fzbm)
          if (element.lx === '地市') {
            console.log('地市')
            if (element.mc === '一等奖') {
              element.num = 1
              element.url = this.url
            } else if (element.mc === '二等奖') {
              element.num = 2
              element.url = this.urlTwo
            } else if (element.mc === '三等奖') {
              element.num = 3
              element.url = this.urlThree
            } else if (element.mc === '优秀奖') {
              element.num = 4
              element.url = this.urlFour
            }
          } else {
            console.log('省赛')
            if (element.mc === '一等奖') {
              element.num = 1
              element.url = this.oUrl
            } else if (element.mc === '二等奖') {
              element.num = 2
              element.url = this.oUrlTwo
            } else if (element.mc === '三等奖') {
              element.num = 3
              element.url = this.oUrlThree
            } else if (element.mc === '优秀奖') {
              element.num = 4
              element.url = this.oUrlFour
            }
          }
          console.log(this.compete, element)
          element.bms = this.bmText + element.num + element.bm.toString().padStart(5, '0') + (element.fzbm === undefined ? '' : '-' + element.fzbm)
        })
      }
      return data
    },
    // 自动生成编码
    autoCode (data) {
      data.forEach(item => {
        item.front = this.generateEncode(this.event, this.year, item.lx, item.ssdq);
        item.bms = this.generateEncode(this.event, this.year, item.lx, item.ssdq) + item.bms;
      });
      return data;
    },
    // 生成导出的图片或者压缩包
    async toPdf () {
      this.load = this.$loading({
        lock: true, // lock的修改符--默认是false
        text: 'Loading', // 显示在加载图标下方的加载文案
        spinner: 'el-icon-loading', // 自定义加载图标类名
        background: 'rgba(0, 0, 0, 0.7)', // 遮罩层颜色
        target: document.querySelector('#table') // loadin覆盖的dom元素节点
      })
      if (this.zipName === '') {
        // alert('请输入文件名')
        // return
        this.zipName = 'sheet'
      }
      const batchSize = 20
      const totalData = this.multipleSelection.length
      const batchedElements = []
      for (let i = 0; i < totalData; i += batchSize) {
        const batchElements = this.multipleSelection.slice(i, i + batchSize).map(data => this.createPdfElement(data))
        batchedElements.push(...batchElements)
      }
      await this.processBatchedElements(batchedElements)
      // debugger
      // console.log(this.sourceList, 8989)
      // this.downloadZip(this.sourceList, this.fileName)
    },
    // 生成html
    createPdfElement (data) {
      // console.log(data, 9090)
      const div = document.createElement('div')
      div.className = 'proBox'
      // const url = window.URL.createObjectURL(data.url)
      // 根据类型不同生成不同的html，选拔赛的图片多了一个地区
      if (data.lx === '地市') {
        div.innerHTML = `
        <img class="proBox-img" src="${data.url}">
        <p class="zs-bm">${data.bms}</p>
        <div class="zs-msg">
          <p class="zs-sxmc">${data.sx}</p>
          <p class="zs-cszb">${data.fz}</p>
          <p class="zs-xm">${data.xs}</p>
          <p class="zs-zdls">${data.zdls ? data.zdls : ''}</p>
          <p class="zs-xx" style="width:${data.xxmc.length < 16 ? 'max-content' : '192px'};min-width: 192px;">${data.xxmc}</p>
          <p class="zs-ssdq">${data.ssdq}</p>
        </div>`
      } else {
        div.innerHTML = `
        <img class="proBox-img" src="${data.url}">
        <p class="zs-bm">${data.bms}</p>
        <div class="zs-msg">
          <p class="zs-sxmc">${data.sx}</p>
          <p class="zs-cszb">${data.fz}</p>
          <p class="zs-xm">${data.xs}</p>
          <p class="zs-zdls">${data.zdls ? data.zdls : ''}</p>
          <p class="zs-xx" style="width:${data.xxmc.length < 16 ? 'max-content' : '192px'};min-width: 192px;">${data.xxmc}</p>
        </div>`
      }
      return div
    },
    processBatchedElements (batchedElements) {
      let index = 0
      const processNext = () => {
        if (index < batchedElements.length) {
          this.dataToPdf(batchedElements[index], () => {
            index++
            processNext()
          })
        } else {
          if (this.fileType === '2') {
            this.downloadZip(this.sourceList, this.zipName)
          }
        }
      }
      processNext()
    },
    // 根据选择下载的文件类型导出文件
    dataToPdf (element, callback) {
      const that = this
      document.body.appendChild(element)
      html2Canvas(element, {
        allowTaint: false,
        dpi: 300,
        scale: 4,
        useCORS: true
      }).then(canvas => {
        if (that.fileType === '1') {
          // const f = canvas.toDataURL('image/png', 1)
          // console.log(f, 2)
          canvas.toBlob(blob => {
            FileSaver.saveAs(blob, `${element.querySelector('.zs-bm').textContent}.jpg`)
            document.body.removeChild(element)
            if (typeof callback === 'function') {
              that.load.close()
              callback()
            }
          })
        } else {
          const d = canvas.toDataURL('image/png', 1)
          that.sourceList.push({
            id: this.flag,
            qrCode: d,
            picName: `${element.querySelector('.zs-bm').textContent}.jpg`
          })
          this.flag++
          document.body.removeChild(element)
          if (typeof callback === 'function') {
            callback()
          }
        }
      })
    },
    handleSelectionChange (val) {
      this.multipleSelection = val
    },
    // 输入证书编码统一部分，处理证书编码
    toBm () {
      if (this.bmText === '') {
        return
      }
      if (this.datalist.length === 0) {
        return
      }
      this.datalist.forEach(item => {
        item.bms = item.front + this.bmText + item.num + item.bm.toString().padStart(5, '0') + (item.fzbm === undefined ? '' : '-' + item.fzbm)
      })
    },
    // 生成并导出excel文件
    exportExcel () {
      /* 从表生成工作簿对象 */
      const that = this
      that.load = this.$loading({
        lock: true, // lock的修改符--默认是false
        text: 'Loading', // 显示在加载图标下方的加载文案
        spinner: 'el-icon-loading', // 自定义加载图标类名
        background: 'rgba(0, 0, 0, 0.7)', // 遮罩层颜色
        target: document.querySelector('#table') // loadin覆盖的dom元素节点
      })
      const wb = XLSX.utils.table_to_book(document.querySelector('#out-table'))
      /* 将每一个t属性为n（number）的改成s 文本 */
      for (let key in wb.Sheets.Sheet1) {
        if (wb.Sheets.Sheet1[key].t && wb.Sheets.Sheet1[key].t === 'n') {
          wb.Sheets.Sheet1[key].t = 's'
          wb.Sheets.Sheet1[key].v = '' + wb.Sheets.Sheet1[key].v
        }
      }
      const wbout = XLSX.write(wb, {
        bookType: 'xlsx',
        bookSST: true,
        type: 'array'
      })
      try {
        FileSaver.saveAs(
          // Blob 对象表示一个不可变、原始数据的类文件对象。
          // Blob 表示的不一定是JavaScript原生格式的数据。
          // File 接口基于Blob，继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
          // 返回一个新创建的 Blob 对象，其内容由参数中给定的数组串联组成。
          new Blob([wbout], { type: 'application/octet-stream' }),
          // 设置导出文件名称
          `${that.fileName === '' ? 'sheet' : that.fileName}.xlsx`
        )
        that.load.close()
      } catch (e) {
        if (typeof console !== 'undefined') console.log(e, wbout)
      }
      // that.show = true
      return wbout
    },
    // 清空上传的文件
    cleanFlie () {
      this.$refs.importFile.value = ''
    },
    // 下载压缩包
    downloadZip (sourceList, zipName = '文件夹名称') {
      const zip = new JSZip()
      const fileFolder = zip.folder(zipName) // 创建 zipName 文件夹
      const fileList = []
      for (let i = 0; i < sourceList.length; i++) {
        const name = sourceList[i].picName // 注意: 每张图片的名称--需要对数据属性进行转换
        fileList.push({ name: name, img: sourceList[i].qrCode })
        if (fileList.length === sourceList.length) {
          if (fileList.length) {
            for (let k = 0; k < fileList.length; k++) {
              // 往文件夹中，添加每张图片数据
              fileFolder.file(fileList[k].name, fileList[k].img.replace(/^data:image\/(png|jpg);base64,/, ''), {
                base64: true
              })
            }
            zip.generateAsync({ type: 'blob' }).then(content => {
              FileSaver.saveAs(content, zipName + '.zip')
            })
          }
        }
      }
      this.load.close()
    },
    // 没用到，将图片转成base64
    getImageBase64 (image) {
      const canvas = document.createElement('canvas')
      canvas.width = image.width
      canvas.height = image.height
      const ctx = canvas.getContext('2d')
      ctx.drawImage(image, 0, 0, image.width, image.height)
      // 获取图片后缀名
      const extension = image.src
        .substring(image.src.lastIndexOf('.') + 1)
        .toLowerCase()
      // 某些图片 url 可能没有后缀名，默认是 png
      return canvas.toDataURL('image/' + extension, 1)
    },
    //  生成编码：
    //  赛事编码（4位） + 年份（4位） + 赛事级别（2位） + 地区编码（2位）
    //  YIIC + 2024 + -A(决赛)/-B(选拔赛) + 00（决赛）/ 行政代码（选拔赛）
    //  选拔赛:
    //  1.广州XX区的，前12位为“YIIC2024-B01”,
    //  2.韶关的，前12位为“YIIC2024-B02”,
    //  3.澳门的，前12位为“YIIC2024-B82”
    //  总决赛:
    //  前12位编码为：“YIIC2024-A00”开头
    //  event 赛事编写 year 年份 level 赛事级别 region 地区
    generateEncode (event, year, level, region) {
      let Level;
      let Region;
      if (level === '省赛') {
        Level = '-A'
        Region = '00'
      } else {
        Level = '-B'
        Region = this.getAdministrativeCode(region)
      }
      const Event = event === '' ? 'YIIC' : event;
      const Year = year === '' ? new Date().getUTCFullYear() : year;
      return Event + Year + Level + Region;
    },
    //  获取行政代码
    getAdministrativeCode (region) {
      let code;
      if (region.indexOf('广州') !== -1) {
        code = '01'
      } else if (region.indexOf('韶关') !== -1) {
        code = '02'
      } else if (region.indexOf('深圳') !== -1) {
        code = '03'
      } else if (region.indexOf('珠海') !== -1) {
        code = '04'
      } else if (region.indexOf('汕头') !== -1) {
        code = '05'
      } else if (region.indexOf('佛山') !== -1) {
        code = '06'
      } else if (region.indexOf('江门') !== -1) {
        code = '07'
      } else if (region.indexOf('湛江') !== -1) {
        code = '08'
      } else if (region.indexOf('茂名') !== -1) {
        code = '09'
      } else if (region.indexOf('肇庆') !== -1) {
        code = '12'
      } else if (region.indexOf('惠州') !== -1) {
        code = '13'
      } else if (region.indexOf('梅州') !== -1) {
        code = '14'
      } else if (region.indexOf('汕尾') !== -1) {
        code = '15'
      } else if (region.indexOf('河源') !== -1) {
        code = '16'
      } else if (region.indexOf('阳江') !== -1) {
        code = '17'
      } else if (region.indexOf('清远') !== -1) {
        code = '18'
      } else if (region.indexOf('东莞') !== -1) {
        code = '19'
      } else if (region.indexOf('中山') !== -1) {
        code = '20'
      } else if (region.indexOf('潮州') !== -1) {
        code = '51'
      } else if (region.indexOf('揭阳') !== -1) {
        code = '52'
      } else if (region.indexOf('云浮') !== -1) {
        code = '53'
      } else if (region.indexOf('香港') !== -1) {
        code = '81'
      } else if (region.indexOf('澳门') !== -1) {
        code = '82'
      }
      return code;
    }
    // async init () {
    //   const image = document.createElement('img');
    //   image.src = this.url
    //   console.log(image.src, 2)
    //   let blob = new Blob([image.src], { type: 'image/png' });
    //   const c = URL.createObjectURL(blob)
    //   localStorage.setItem('url', blob);
    //   const b = await this.blobToBase64(blob)
    //   console.log(c, b)
    //   this.url = await this.blobToBase64(blob)
    //   image.src = this.urlTwo
    //   blob = new Blob([image.src], { type: 'image/png' })
    //   localStorage.setItem('urlTwo', blob);
    //   this.urlTwo = await this.blobToBase64(blob)
    //   image.src = this.urlThree
    //   blob = new Blob([image.src], { type: 'image/png' })
    //   localStorage.setItem('urlThree', blob);
    //   this.urlThree = await this.blobToBase64(blob)
    //   image.src = this.urlFour
    //   blob = new Blob([image.src], { type: 'image/png' })
    //   localStorage.setItem('urlFour', blob);
    //   this.urlFour = await this.blobToBase64(blob)
    //   image.src = this.oUrl
    //   blob = new Blob([image.src], { type: 'image/png' })
    //   localStorage.setItem('oUrl', blob);
    //   this.oUrl = await this.blobToBase64(blob)
    //   image.src = this.oUrlTwo
    //   blob = new Blob([image.src], { type: 'image/png' })
    //   localStorage.setItem('oUrlTwo', blob);
    //   // this.oUrlTwo = await this.blobToBase64(blob)
    //   image.src = this.oUrlThree
    //   blob = new Blob([image.src], { type: 'image/png' })
    //   // localStorage.setItem('oUrlThree', blob);
    //   this.oUrlThree = await this.blobToBase64(blob)
    //   image.src = this.oUrlFour
    //   blob = new Blob([image.src], { type: 'image/png' })
    //   localStorage.setItem('oUrlFour', blob);
    //   // this.oUrlFour = await this.blobToBase64(blob)
    // },
    // blobToBase64 (blob) {
    //   return new Promise((resolve, reject) => {
    //     const fileReader = new FileReader()
    //     fileReader.onload = (e) => {
    //       resolve(e.target.result)
    //     }
    //     // readAsDataURL
    //     fileReader.readAsDataURL(blob)
    //     fileReader.onerror = () => {
    //       reject(new Error('blobToBase64 error'))
    //     }
    //   })
    // }
  }
}
</script>

<style>
* {
  padding: 0;
  margin: 0;
}
body,
html {
  height: 100vh;
  overflow: hidden;
}
#app {
  font-family: 黑体, simhei;
  /* Avenir, Helvetica, Arial, sans-serif */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  padding: 20px 20px 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}

p {
  margin: 0;
}

.proBox {
  background-size: cover;
  width: 595px;
  height: 842px;
  box-sizing: border-box;
  margin: 0 auto;
  position: relative;
  color: #000;
  font-size: 16px;
  background-color: aquamarine;
}

.proBox img {
  width: 595px;
  height: 842px;
  position: absolute;
  top: 0;
  left: 0;
}

.zs-bm {
  position: absolute;
  margin: 0;
  font-size: 10px;
  top: 45px;
  /* top: 46px; */
  left: 114px;
}

.zs-msg {
  position: absolute;
  text-align: center;
  width: 192px;
  top: 354px;
  margin: 0;
  left: 238px;
  font-size: 13px;
  height: 220px;
}

.zs-sxmc {
  position: absolute;
  left: 0;
  bottom: 197px;
  width: 192px;
}

.zs-cszb {
  position: absolute;
  left: 0;
  bottom: 157px;
  width: 192px;
}

.zs-xm {
  position: absolute;
  left: 0;
  bottom: 120px;
  width: 192px;
}

.zs-zdls {

  position: absolute;
  left: 0;
  bottom: 83px;
  width: 192px;
}

.zs-xx {
  position: absolute;
  left: 0;
  bottom: 45px;
  width: 192px
}
.zs-ssdq{
  position: absolute;
  left: 0;
  bottom: 7px;
  width: 192px
}
.zs-sq {
  position: absolute;
  left: 0;
  bottom: 7px;
  width: 192px;
}

button {
  margin: 0 10px;
}
</style>
