<template>
  <div class="bbsl-common-page">
    <div class="bbsl-table-search">
      <el-form ref="searchForm" v-model="queryParam.querys" :inline="true">
        <el-form-item label="年度：">
          <el-date-picker
            v-model="queryParam.querys[1].value"
            placeholder="请选择年度"
            style="width: 100%;"
            type="year"
            value-format="yyyy"
          >
          </el-date-picker>
        </el-form-item>
        <el-form-item label="计划状态：">
          <el-select
            v-model="queryParam.querys[5].value"
            placeholder="请选择计划状态"
            style="width: 100%;"
          >
            <el-option
              :label="item.name"
              :value="item.value"
              v-for="(item, i) in getDictionaryByCode('planStatus')"
              :key="i"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button icon="el-icon-search" type="primary" @click="handleSearch"
            >搜索
          </el-button>
          <el-button icon="el-icon-refresh" @click="resetSearch">
            重置
          </el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="page-content">
      <div ref="contentPanel" class="bbsl-table-content">
        <div ref="btnPanel" class="bbsl-btn-content">
          <el-button
            v-charge
            icon="el-icon-plus"
            type="success"
            @click="showDialog('addEdit')"
          >
            新增
          </el-button>
          <el-popconfirm title="确定删除选中数据吗？" @confirm="handleDelete">
            <template v-slot:reference>
              <el-button
                v-charge
                :disabled="!multipleSelection.length"
                icon="el-icon-delete"
                style="margin-left: 10px"
                type="danger"
              >
                删除
              </el-button>
            </template>
          </el-popconfirm>
          <el-upload
            ref="upload"
            :action="actionUrl"
            :before-upload="beforeUpload"
            :headers="headers"
            :multiple="false"
            :on-error="handleError"
            :on-success="handleSuccess"
            :show-file-list="false"
            class="avatar-uploader"
          >
            <el-button
              v-charge
              :loading="uploadLoading"
              icon="el-icon-download"
              style="margin-right: 10px;"
              type="primary"
              >导入
            </el-button>
          </el-upload>
          <el-button icon="el-icon-upload2" type="warning" @click="exportFile"
            >导出
          </el-button>
          <el-button
            v-charge
            icon="el-icon-document"
            type="info"
            @click="templateDownload"
          >
            模板下载
          </el-button>
        </div>
        <el-table
          ref="multipleSelection"
          v-loading="loading"
          :cell-style="{'text-align': 'center'}"
          :data="tableData"
          :default-sort="getSorterDirection(queryParam, true)"
          :header-cell-style="{'text-align': 'center'}"
          :max-height="tableMaxHeight"
          :style="{width: '100%'}"
          size="mini"
          @selection-change="handleSelectionChange"
          @sort-change="sortChange"
          @row-dblclick="row => isCharge && menuClick('addEdit', row)"
        >
          <el-table-column type="selection" width="55"></el-table-column>
          <el-table-column
            :index="
              index =>
                index +
                1 +
                (queryParam.pageBean.page - 1) * queryParam.pageBean.pageSize
            "
            fixed
            label="序号"
            type="index"
            width="55"
          />

          <el-table-column
            label="年度"
            prop="year"
            width="100"
          ></el-table-column>
          <el-table-column
            label="月份"
            prop="month"
            width="100"
            :formatter="({month}) => month + '月'"
          ></el-table-column>
          <el-table-column label="周" prop="week" width="100"></el-table-column>

          <el-table-column
            label="训练日期"
            prop="subjectName"
            show-overflow-tooltip
          >
            <template v-slot="{row}">
              {{ row.startTime + '-' + row.endTime }}
            </template>
          </el-table-column>

          <el-table-column
            :formatter="
              ({planStatus}) => dictionaryEscape('planStatus', planStatus)
            "
            label="计划状态"
            prop="planStatus"
            show-overflow-tooltip
          ></el-table-column>
          <el-table-column
            :formatter="({createTime}) => createTime || '-'"
            label="创建时间"
            prop="createTime"
            show-overflow-tooltip
            sortable="custom"
          />
          <el-table-column v-if="isCharge === 1" label="操作" min-width="100">
            <template v-slot="{row}">
              <el-dropdown
                size="small"
                split-button
                v-charge
                @click="() => menuClick('info', row)"
                @command="command => menuClick(command, row)"
              >
                详情
                <template v-slot:dropdown>
                  <el-dropdown-menu>
                    <!-- <el-dropdown-item
                      v-if="row.planStatus !== '0'"
                      command="attendanceRecord"
                    >
                      考勤记录
                    </el-dropdown-item> -->
                    <el-dropdown-item
                      v-if="+row.planStatus < 1"
                      command="planIssuance"
                    >
                      计划下发
                    </el-dropdown-item>
                    <!-- <el-dropdown-item v-else command="trainingDetails">
                      训练明细
                    </el-dropdown-item> -->
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
          ref="paginationPanel"
          :current-page="queryParam.pageBean.page"
          :page-size="queryParam.pageBean.pageSize"
          :page-sizes="[20, 30, 40, 50]"
          :total="queryParam.pageBean.total"
          align="right"
          background
          class="bbsl-pagination"
          layout="prev, pager, next,total, sizes, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        >
        </el-pagination>
      </div>
    </div>

    <!--  新增修改弹层  -->
    <AddEditDialog
      :row-info="rowInfo"
      :value.sync="dialogs.addEditDialog"
      @submit="dialogSubmit"
    />

    <!--  训练明细  -->
    <training-details-dialog
      v-model="dialogs.trainingDetailsDialog"
      :row-details="rowInfo"
      @submit="dialogSubmit"
    />

    <!-- 考勤记录 -->
    <el-dialog
      :visible.sync="showRecord"
      custom-class="new-edition-dialog"
      title="考勤记录"
      top="3vh"
      width="80%"
      @close="close"
    >
      <div style="display: flex;align-items: center;margin-bottom: 10px;">
        <el-date-picker
          value-format="yyyy-MM-dd"
          v-model="recordInfo.querys[0].value"
          placeholder="请选择日期"
          type="date"
        ></el-date-picker>
        <el-upload
          ref="upload"
          :action="actionUrls"
          :before-upload="beforeUploads"
          :headers="headers"
          :multiple="false"
          :on-error="handleErrors"
          :on-success="handleEnd"
          :show-file-list="false"
          class="avatar-uploader"
          :data="{planId: this.recordInfo.querys[1].value}"
        >
          <el-button
            :loading="uploadLoading"
            icon="el-icon-download"
            size="small"
            style="margin-right: 10px;"
            type="warning"
          >
            导入
          </el-button>
        </el-upload>

        <el-button
          icon="el-icon-download"
          size="small"
          type="primary"
          @click="exportFiles"
          >导出
        </el-button>
        <el-button
          v-charge
          icon="el-icon-document"
          type="info"
          size="small"
          @click="templateDownloads"
        >
          模板下载
        </el-button>
        <el-button
          @click="search"
          size="small"
          style="margin-left: 10px;"
          type="primary"
        >
          查询
        </el-button>
      </div>
      <el-table :data="attendanceRecordList" border>
        <el-table-column
          label="单位"
          show-overflow-tooltip
          prop="orgName"
        ></el-table-column>
        <el-table-column
          label="考生姓名"
          show-overflow-tooltip
          prop="userName"
        ></el-table-column>
        <el-table-column
          label="训练课目"
          show-overflow-tooltip
          prop="subjectName"
        ></el-table-column>

        <el-table-column
          label="考勤日期"
          show-overflow-tooltip
          prop="lastTime"
        ></el-table-column>

        <el-table-column label="考勤状态" show-overflow-tooltip prop="status">
          <template v-slot="{row}">
            {{ row.status == '0' ? '未考勤' : '已考勤' }}
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template v-slot="{row}">
            <el-link type="primary" @click="attendanceRecord(row)"
              >{{ row.status == '0' ? '考勤' : '编辑' }}
            </el-link>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        ref="paginationPanel"
        :current-page="recordInfo.pageBean.page"
        :page-size="recordInfo.pageBean.pageSize"
        :page-sizes="[20, 30, 40, 50]"
        :total="recordInfo.pageBean.total"
        align="right"
        background
        layout="prev, pager, next,total, sizes, jumper"
        style="margin-top: 10px;"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      >
      </el-pagination>
      <el-dialog
        :visible.sync="showAttendance"
        append-to-body
        custom-class="new-edition-dialog"
        title="考勤记录"
        top="3vh"
        width="75%"
      >
        <el-form :model="form">
          <el-col :span="24">
            <el-form-item
              :rules="[
                {
                  required: true,
                  message: '装备知识附件不能为空',
                  trigger: 'change'
                }
              ]"
              label=""
              prop="fileList"
            >
              <el-button size="small" type="primary" @click="selectFile">
                附件 +
              </el-button>
              <el-button
                v-show="form.fileList && form.fileList.length"
                :disabled="!currentDataDel.length"
                size="small"
                type="danger"
                @click="deleteFile()"
              >
                附件 -
              </el-button>
              <div class="attachment-tips-text">
                只能上传
                <span>
                  <template v-for="(item, index) in typeRegularArr"
                    >{{ item
                    }}{{
                      typeRegularArr.length - 1 === index ? '' : '/'
                    }}</template
                  >
                </span>
                文件
              </div>
            </el-form-item>
            <uploader
              v-show="false"
              ref="uploader"
              :options="uploadOption"
              @file-added="onFileAdded"
              @file-error="uploadError"
              @file-progress="onFileProgress"
              @file-success="onFileSuccess"
            >
              <uploader-unsupport></uploader-unsupport>
              <uploader-btn ref="uploaderBtn"></uploader-btn>
              <uploader-list> </uploader-list>
            </uploader>
          </el-col>
          <el-col :span="24">
            <el-table
              v-show="form.fileList && form.fileList.length"
              ref="multipleSelection"
              :data="form.fileList"
              border
              class="table-list"
              row-key="id"
              stripe
              @selection-change="handleSelectionChanges"
            >
              <el-table-column align="center" type="selection" width="55" />
              <el-table-column
                :index="index => index + 1"
                align="center"
                label="序号"
                type="index"
                width="70"
              />
              <el-table-column
                align="center"
                label="附件名称"
                min-width="140"
                prop="fileName"
                show-overflow-tooltip
              >
                <template v-slot="{row}">
                  <template v-if="row.status !== 'success'">
                    {{ row.fileName }}
                  </template>
                  <el-link v-else type="primary" @click="previewFile(row)">
                    {{ row.fileName }}
                  </el-link>
                </template>
              </el-table-column>
              <el-table-column
                align="center"
                class-name="is-required"
                label="附件别名"
                min-width="170"
                prop="name"
                show-overflow-tooltip
              >
                <template v-slot="{row, $index}">
                  <el-form-item
                    :prop="`fileList.${$index}.name`"
                    :rules="rules.fileList.name"
                    class="table-form-item"
                  >
                    <el-input
                      v-model="row.name"
                      :autosize="{minRows: 1, maxRows: 4}"
                      placeholder="请输入附件名称"
                      size="small"
                      type="textarea"
                    ></el-input>
                  </el-form-item>
                </template>
              </el-table-column>
              <el-table-column
                :formatter="
                  ({fileType}) => dictionaryEscape('wjlx', fileType) || '-'
                "
                align="center"
                label="资料类型"
                min-width="70"
                prop="name"
                show-overflow-tooltip
              />
              <el-table-column
                :formatter="({size}) => formatFileSize(size)"
                align="center"
                label="附件大小"
                min-width="70"
                prop="size"
              />
              <el-table-column
                align="center"
                label="上传进度"
                min-width="110"
                prop="progress"
              >
                <template v-slot="{row}">
                  <template
                    v-if="row.status === 'error' || row.status === 'mergeError'"
                  >
                    <el-progress :percentage="0" status="exception" />
                  </template>
                  <template v-else-if="row.status === 'success'">
                    <el-progress :percentage="100" status="success" />
                  </template>
                  <template v-else-if="row.status === 'pause'">
                    <el-progress
                      :percentage="+(row._prevProgress * 100).toFixed(2)"
                      status="warning"
                    />
                  </template>
                  <template
                    v-else-if="
                      row.status === 'upload' || row.status === 'initialization'
                    "
                  >
                    <el-progress
                      :percentage="
                        +(row._prevProgress * 100).toFixed(2) >= 90
                          ? 90
                          : +(row._prevProgress * 100).toFixed(2)
                      "
                    />
                  </template>
                  <template v-else-if="row.status === 'merge'">
                    <el-progress :percentage="90" />
                  </template>
                </template>
              </el-table-column>
              <el-table-column
                align="center"
                label="上传速度"
                min-width="80"
                prop="size"
                show-overflow-tooltip
              >
                <template v-slot="{row}">
                  {{ `${formatFileSize(row.currentSpeed)} / S` }}
                </template>
              </el-table-column>
              <el-table-column
                align="center"
                label="预计上传时长"
                min-width="100"
                prop="size"
                show-overflow-tooltip
              >
                <template v-slot="{row}">
                  {{
                    !Number.isFinite(row.timeRemaining()) ||
                    row.timeRemaining() === 0
                      ? '-'
                      : formatTime(row.timeRemaining())
                  }}
                </template>
              </el-table-column>
              <el-table-column
                align="center"
                label="上传状态"
                min-width="90"
                prop="status"
                show-overflow-tooltip
              >
                <template v-slot="{row}">
                  <template v-if="row.status === 'initialization'">
                    <el-tag size="medium" type="warning">文件初始化中..</el-tag>
                  </template>
                  <template v-else-if="row.status === 'error'">
                    <el-tag size="medium" type="danger">文件上传失败</el-tag>
                  </template>
                  <template v-else-if="row.status === 'mergeError'">
                    <el-tag size="medium" type="danger">文件合并失败</el-tag>
                  </template>
                  <template v-else-if="row.status === 'success'">
                    <el-tag size="medium" type="success">文件上传成功</el-tag>
                  </template>
                  <template v-else-if="row.status === 'pause'">
                    <el-tag size="medium" type="warning">文件上传暂停</el-tag>
                  </template>
                  <template v-else-if="row.status === 'upload'">
                    <el-tag size="medium" type="primary">文件上传中...</el-tag>
                  </template>
                  <template v-else-if="row.status === 'merge'">
                    <el-tag size="medium" type="primary">文件合并中...</el-tag>
                  </template>
                </template>
              </el-table-column>
              <el-table-column
                align="center"
                label="操作"
                min-width="130"
                show-overflow-tooltip
              >
                <template v-slot="{row}">
                  <template
                    v-if="
                      row.status !== 'initialization' &&
                        (!row.isComplete() || row.status === 'mergeError') &&
                        row.status !== 'success'
                    "
                  >
                    <el-link
                      v-if="
                        row.status === 'error' || row.status === 'mergeError'
                      "
                      :underline="false"
                      style="margin-right: 10px"
                      type="primary"
                      @click="reUpload(row)"
                    >
                      重新上传
                    </el-link>
                    <el-link
                      v-else
                      :type="row.paused ? 'primary' : 'warning'"
                      :underline="false"
                      style="margin-right: 10px"
                      @click="filePauseUpload(row)"
                    >
                      {{ row.paused ? '继续' : '暂停' }}上传
                    </el-link>
                  </template>
                  <el-link
                    v-if="row.status === 'success'"
                    :underline="false"
                    style="margin-right: 10px"
                    type="primary"
                    @click="downloadFile(row)"
                  >
                    文件下载
                  </el-link>
                  <el-link
                    :underline="false"
                    style="margin-right: 10px"
                    type="danger"
                    @click="deleteFile(row)"
                  >
                    {{ row.status === 'success' ? '删除附件' : '取消上传' }}
                  </el-link>
                </template>
              </el-table-column>
            </el-table>
          </el-col>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button :loading="saveLoad" type="primary" @click="handleSave">
            确 认
          </el-button>
          <el-button @click="showAttendance = false">取 消</el-button>
        </span>
      </el-dialog>
    </el-dialog>
  </div>
</template>

<script>
import {TableMixin} from '@/mixins/tableMixin'
import {getSorterDirection, refineRequestBody} from '@/utils/requestWrappers'
import * as userCheck from '@/api/examDataMenu/examActivityData/userCheckData'
import AddEditDialog from './components/AddEditDialog.vue'
import {mapState} from 'vuex'
import {completeUpload, initFile} from '@/api/systemInterface'
import * as api from '@/api/examDataMenu/examManagerData/examPlanAll.js'
import {dictionaryEscape, getDictionaryByCode} from '@/utils/dictionary'
import moment from 'moment'
import SparkMD5 from 'spark-md5'

import TrainingDetailsDialog from './components/TrainingDetailsDialog/index.vue'

export default {
  name: 'ExamYearPlan',
  components: {
    TrainingDetailsDialog,
    AddEditDialog
  },
  mixins: [TableMixin],
  data() {
    return {
      form: {},
      rules: {
        name: [{required: true, message: '请输入名称', trigger: 'blur'}],
        fileList: {
          name: [{required: true, message: '附件名称不能为空', trigger: 'blur'}]
        }
      },
      tableData: [], // 表格数据

      currentDataDel: [],
      currentDataDels: [],

      recordInfo: {
        pageBean: {pageSize: 20, page: 1, total: 0},
        querys: [
          {
            operation: 'EQUAL',
            property: 'checkDate',
            value: moment().format('YYYY-MM-DD')
          },
          {
            operation: 'EQUAL',
            property: 'plan_id_'
          }
        ]
      },
      showRecord: false,
      showAttendance: false,
      attendanceRecordList: [],

      // 查询对象
      queryParam: {
        pageBean: {pageSize: 20, page: 1, total: 0},
        querys: [
          {operation: 'LIKE', property: 'orgName'},
          {
            operation: 'EQUAL',
            property: 'year',
            value: moment().format('YYYY')
          },
          {operation: 'LIKE', property: 'post'},
          {operation: 'LIKE', property: 'majorName'},
          {operation: 'EQUAL', property: 'planType', value: '4'},
          {operation: 'EQUAL', property: 'planStatus'}
        ],
        sorter: [{direction: 'DESC', property: 'createTime'}]
      },
      // 统一管理多个弹层
      dialogs: {
        addEditDialog: false, // 新增修改弹层
        trainingDetailsDialog: false // 训练明细弹层
      },
      rowInfo: {}, // 保存行信息
      uploadLoading: false,
      typeRegularArr: [
        // 视频格式
        ...[
          'mp4',
          'mov',
          'avi',
          'mkv',
          'wmv',
          'flv',
          'mpeg',
          'mpg',
          '3gp',
          'webm',
          'mts'
        ],
        // 文档格式
        // ...['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'rtf', 'pdf'],
        // 图像文件
        ...['jpg', 'png', 'bmp', 'gif']
      ],

      saveLoad: false
    }
  },
  computed: {
    actionUrl: _ => window.context.portal + '/biz/exam/plan/importExcel/3',
    actionUrls: _ => window.context.portal + '/biz/userCheck/importExcel',
    actionPick: _ => window.context.portal,
    ...mapState({
      headers: state => ({
        Authorization: `Bearer ${state.login.currentUser.token}`
      })
    }),
    uploadOption() {
      return {
        target: `${this.actionPick}/file/v1/chunkUpload`,
        autoUpload: false, // 设置为手动上传，以便先检查类型和请求分片ID
        testChunks: true, // 关闭自动分片检查
        checkChunkUploadedByResponse: this.checkChunkUploadedByResponse,
        singleFile: false, // 确保每个组件只处理单文件上传
        forceChunkSize: true, // 是否强制所有的块都是小于等于 chunkSize 的值
        chunkSize: 10 * 1024 * 1024, // 设置分片大小为10MB
        simultaneousUploads: 10, // 并发数
        maxChunkRetries: 3, // 设置最大重试次数
        chunkRetryInterval: 2000, // 设置重试间隔时间，单位为毫秒
        headers: this.headers,
        onFileAdded: this.onFileAdded, // 文件添加时的钩子
        processParams: this.processParams // 加工分片上传请求体
      }
    }
  },
  created() {},
  methods: {
    dictionaryEscape,
    getDictionaryByCode,
    close() {
      this.$refs.uploader?.uploader?.cancel()
    },
    attendanceRecord(row) {
      this.form = JSON.parse(JSON.stringify(row))

      this.$set(this.form, 'fileList', [])
      this.showAttendance = true
    },
    // 提交考勤
    async handleSave() {
      this.saveLoad = true
      try {
        console.log(this.form)
        let {fileList} = this.form
        let {state} = await api.saveUserCheck({
          ...this.form,
          trainFile: JSON.stringify(
            fileList.flatMap(file => {
              if (file.fileType !== '3') return []
              return {
                fileSizes: file.fileSizes,
                fileExt: file.fileExt,
                fileId: file.fileId,
                fileType: file.fileType,
                fileName: file.fileName,
                name: file.name,
                id: file.fileId
              }
            })
          )
        })

        if (state) {
          this.$message.success(`考勤成功`)
          this.showAttendance = false
          this.getUserList()
        }
        console.log(res)
      } finally {
        this.saveLoad = false
      }
    },
    //表格选中
    handleSelectionChanges(val) {
      this.currentDataDels = val.map(item => item.id)
    },
    // 格式化文件大小
    formatFileSize(bytes) {
      const k = 1024
      const sizes = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
      if (bytes < k) return '0 KB' // 最小单位为 kb
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      const size = bytes / Math.pow(k, i)
      const formattedSize = parseFloat(size.toFixed(2))
      return `${formattedSize} ${sizes[i - 1]}` // i-1 因为 kb 是最小单位
    },
    // 文件重新上传
    reUpload(file) {
      file.retry()
      this.initializeFile(file)
    },

    // 文件继续/暂停上传
    filePauseUpload(file) {
      if (file.paused) {
        file.status = 'upload'
        file.resume()
      } else {
        file.status = 'pause'
        file.pause()
      }
    },
    // 导出考勤数据
    async exportFiles() {
      await api.attendanceExport(
        refineRequestBody({
          querys: this.recordInfo.querys,
          pageBean: {
            pageSize: -1
          }
        })
      )
    },
    // 考勤模板下载
    async templateDownloads() {
      await api.attendanceDownload()
    },
    //  导入文件上传前
    beforeUploads(file) {
      return new Promise((resolve, reject) => {
        this.uploadLoading = true
        const {size, name} = file
        let passedOrNot = true // 是否通过验证
        const maxSize = 500 * 1024 * 1024 // 20MB
        const typeRegular = /\.(xls|xlsx)$/i
        const verification = [
          {
            condition: !typeRegular.test(name),
            result: () => this.$message.error('只能上传xls或xlsx文件类型')
          }
        ]
        verification.forEach(item => {
          if (item.condition) {
            item.result()
            passedOrNot = false
            this.uploadLoading = false
          }
        })

        passedOrNot ? resolve() : reject()
      })
    },

    // 导入文件上传成功
    async handleEnd() {
      this.$message.success('考勤数据导入成功')
      this.uploadLoading = false
      await this.loadData()
    },

    // 导入文件上传失败
    handleErrors() {
      this.$message.error('考勤数据导入失败，请重试')
      this.uploadLoading = false
    },

    //  可选的函数用于根据 XHR 响应内容检测每个块是否上传成功了
    checkChunkUploadedByResponse(chunk) {
      const successChunk = chunk.file.successChunk || []
      return successChunk.includes(chunk.offset)
    },

    /**
     * 生成文件的 MD5 哈希值
     * @param {File} file - 要加密的文件对象
     * @returns {Promise} - 返回包含MD5哈希值的Promise
     */
    generateMd5(file) {
      return new Promise((resolve, reject) => {
        const chunkSize = 2 * 1024 * 1024 // 2MB
        const chunks = Math.ceil(file.size / chunkSize)
        let currentChunk = 0
        const spark = new SparkMD5.ArrayBuffer()
        const fileReader = new FileReader()

        fileReader.onload = e => {
          spark.append(e.target.result)
          currentChunk += 1
          if (currentChunk < chunks) {
            loadNext()
          } else {
            // 在文件内容加密完成后，追加文件名进行加密
            const nameBuffer = new TextEncoder().encode(file.name) // 将文件名转换为 ArrayBuffer
            spark.append(nameBuffer)
            const hash = spark.end()
            resolve(hash)
          }
        }

        fileReader.onerror = () => {
          reject(new Error('Error reading file'))
        }

        function loadNext() {
          const start = currentChunk * chunkSize
          const end = Math.min(start + chunkSize, file.size)
          if (start < file.size) {
            const blob = file.slice(start, end)
            fileReader.readAsArrayBuffer(blob)
          }
        }

        loadNext()
      })
    },
    // 文件添加后（验证文件类型）
    onFileAdded(file) {
      this.saveLoading = true
      const {size, name} = file
      const maxSize = 500 * 1024 * 1024 // 20MB
      const typeRegular = new RegExp(
        `\\.(${this.typeRegularArr.join('|')})$`,
        'i'
      )
      const verification = [
        {
          condition: !typeRegular.test(name),
          result: () =>
            setTimeout(() =>
              this.$message.warning('只能上传视频 / 图片格式文件')
            )
        }
        // {
        //   condition: size > maxSize,,
        //   result: () => this.$message.warning('附件大小不能超过500MB')
        // }
      ]
      const findItem = verification.find(i => i.condition)
      if (findItem) {
        findItem.result && findItem.result()
        this.saveLoading = this.form.fileList.some(i => i.status !== 'success')
        file.ignored = true //文件校验，不符规则的文件过滤掉
      } else {
        file.ignored = false //文件校验，不符规则的文件过滤掉
        const addProps = {
          status: 'initialization',
          uploadId: '',
          fileName: file.name
        }
        Object.keys(addProps).forEach(key => {
          this.$set(file, key, addProps[key])
        })

        this.form.fileList.push(file)
        this.initializeFile(file)
      }
    },
    // 整个文件预处理
    async initializeFile(file) {
      file.pause()
      file.status = 'initialization'
      const fileObject = file.file // 源文件对象
      try {
        const md5 = await this.generateMd5(fileObject)

        // 请求分片信息

        try {
          let {
            state = false,
            value: {uploadId = '', uploadResult = {}, successChunk = ''} = {}
          } = await initFile({
            md5,
            filename: file.name,
            size: file.size,
            partSize: this.uploadOption.chunkSize
          })

          if (state && uploadResult.mergeStatus === '1') {
            file.status = 'success'
            const addProps = {
              fileName: file.fileName,
              fileSizes: uploadResult.size,
              fileExt: uploadResult.fileExt,
              fileId: uploadResult.fileId,
              fileType: uploadResult.fileType,
              id: uploadResult.fileId,
              successChunk
            }
            Object.keys(addProps).forEach(key => {
              this.$set(file, key, addProps[key])
            })
            setTimeout(_ => {
              this.saveLoading = this.form.fileList.some(
                i => i.status !== 'success'
              )
            })
          } else if (state && uploadId) {
            file.status = 'upload'
            file.uploadId = uploadId
            if (typeof successChunk === 'string' && successChunk) {
              // 前缀并转换为数字数组
              successChunk = successChunk
                .split(',')
                .map(chunk => +chunk.replace('chunk_', ''))
                .sort((a, b) => a - b)
            } else {
              successChunk = []
            }
            const addProps = {
              fileName: file.fileName,
              fileSizes: uploadResult.size,
              fileExt: uploadResult.fileExt,
              fileId: uploadResult.fileId,
              fileType: uploadResult.fileType,
              id: uploadResult.fileId,
              successChunk
            }
            Object.keys(addProps).forEach(key => {
              this.$set(file, key, addProps[key])
            })
            file.resume()
          } else {
            file.status = 'error'
          }
        } catch (error) {
          file.status = 'error'
        }
      } catch {
        file.status = 'error'
        this.$message.error('文件初始化错误，请重新上传')
      }
    },
    // 加工分片上传请求体
    processParams(params, file, check) {
      return {
        chunk: `chunk_${params.chunkNumber - 1}`,
        uploadId: file.uploadId
      }
    },
    // 文件上传中
    onFileProgress(rootFile, file, chunk) {
      rootFile.status = 'upload'
    },
    // 文件上传失败
    uploadError(rootFile, file, message, chunk) {
      rootFile.status = 'error'
      this.$message.error(`"${file.name}"上传失败`)
    },

    // 选择文件
    selectFile() {
      // 查找uploaderBtn组件内部的input元素，并模拟点击
      const inputElement = this.$refs.uploaderBtn.$el.querySelector(
        'input[type="file"]'
      )
      if (inputElement) {
        inputElement.click()
      }
    },

    // 文件删除
    deleteFile(file) {
      this.$confirm('确定删除选中附件吗？', '提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async () => {
          if (file) {
            const index = this.form.fileList.findIndex(i => i.id === file.id)
            file.cancel && file.cancel()
            if (index !== -1) {
              this.form.fileList.splice(index, 1)
            }
          } else {
            this.currentDataDel.forEach(id => {
              const index = this.form.fileList.findIndex(i => i.id === id)
              if (index !== -1) {
                this.form.fileList[index]?.cancel()
                this.form.fileList.splice(index, 1)
              }
            })
          }
          this.saveLoading = this.form.fileList.some(
            i => i.status !== 'success'
          )
        })
        .catch(_ => _)
    },

    // 文件上传成功
    async onFileSuccess(rootFile, file, response) {
      try {
        file.status = 'merge'
        // 合并文件
        const {value = {}} = await completeUpload(rootFile.uploadId)
        if (value.mergeStatus === '1') {
          file.status = 'success'
          const addProps = {
            fileSizes: file.size,
            fileExt: value.fileExt,
            fileId: value.fileId,
            fileType: value.fileType
          }

          Object.keys(addProps).forEach(key => {
            this.$set(file, key, addProps[key])
          })

          setTimeout(_ => {
            this.saveLoading = this.form.fileList.some(
              i => i.status !== 'success'
            )
          })
        } else {
          file.bootstrap()
          file.status = 'mergeError'
        }
      } catch {
        file.bootstrap()
        file.status = 'mergeError'
      }
    },
    search() {
      this.recordInfo.pageBean.page = 1
      this.getUserList()
    },
    async getUserList() {
      try {
        let {rows, total} = await userCheck.tableData(
          refineRequestBody(this.recordInfo)
        )
        this.attendanceRecordList = rows
        this.recordInfo.pageBean.total = total
      } finally {
      }
    },
    // 考勤记录
    openAttendanceRecord(row) {
      this.recordInfo.querys[1].value = row.id

      this.getUserList()
      this.showRecord = true
    },

    // 获取表格数据
    async loadData() {
      try {
        this.loading = true
        const {total = 0, rows = []} = await api.tableData(
          refineRequestBody(this.queryParam)
        )
        this.queryParam.pageBean.total = total
        this.tableData = rows
      } finally {
        this.loading = false
      }
    },

    // 重置搜索
    resetSearch() {
      this.queryParam = this.$options.data().queryParam

      this.loadData()
    },

    // 删除
    async handleDelete(row) {
      console.log(1111111111, row)

      let ids = row ? row.id : this.multipleSelection.join()
      const {state} = await api.tableDelete(ids)
      if (state) {
        this.$message.success(`周训练计划删除成功`)
        const {page, pageSize, total} = this.queryParam.pageBean
        const totalPages = Math.ceil(total / pageSize) // 计算总页数
        if (totalPages > 1 && page === totalPages) {
          if (this.tableData.length === 1) {
            // 当前页只有一条数据
            this.queryParam.pageBean.page -= 1 // 返回前一页
          }
        }
        await this.loadData()
      }
    },

    //  导入文件上传前
    beforeUpload(file) {
      return new Promise((resolve, reject) => {
        this.uploadLoading = true
        const {size, name} = file
        let passedOrNot = true // 是否通过验证
        const maxSize = 500 * 1024 * 1024 // 20MB
        const typeRegular = /\.(xls|xlsx)$/i
        const verification = [
          {
            condition: !typeRegular.test(name),
            result: () => this.$message.error('只能上传xls或xlsx文件类型')
          }
        ]
        verification.forEach(item => {
          if (item.condition) {
            item.result()
            passedOrNot = false
            this.uploadLoading = false
          }
        })

        passedOrNot ? resolve() : reject()
      })
    },

    // 导入文件上传成功
    async handleSuccess() {
      this.$message.success('周训练计划导入成功')
      this.uploadLoading = false
      await this.loadData()
    },

    // 导入文件上传失败
    handleError() {
      this.$message.error('周训练计划导入失败，请重试')
      this.uploadLoading = false
    },

    // 导出数据
    async exportFile() {
      await api.exportData(
        refineRequestBody({
          querys: this.queryParam.querys,
          pageBean: {
            pageSize: -1
          }
        }),
        '4'
      )
    },

    // 模板下载
    async templateDownload() {
      await api.downModel('4')
    },

    // 修改计划状态
    async changeType(row) {
      this.$confirm('是否确认计划下发？', '提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async () => {
          const {state} = await api.updateStatus(row.id)
          if (state) {
            this.$message.success(`计划下发成功`)
            this.loadData()
          } else {
            this.$message.error(`计划下发失败`)
          }
        })
        .catch(_ => _)
    },

    // 新增修改弹层提交成功后
    dialogSubmit(type) {
      switch (type) {
        case 'add':
          this.queryParam.pageBean.page = 1
          break
        case 'edit':
          break
        case 'trainingDetails':
          break
      }
      this.loadData()
    },

    // 功能菜单点击
    menuClick(command, row) {
      switch (command) {
        // 编辑
        case 'addEdit':
          if (row.planStatus !== '0')
            return this.$message.warning(`已下发的计划不能进行编辑`)
          this.showDialog(command, row)
          break
        // 考勤记录
        case 'attendanceRecord':
          this.openAttendanceRecord(row)
          break
        // 计划下发
        case 'planIssuance':
          this.changeType(row)
          break
        // 训练明细
        case 'trainingDetails':
          this.showDialog(command, row)
          break
        // 详情
        case 'info':
          this.showDialog('addEdit', {...row, type: '详情'})
          break
      }
    },

    getSorterDirection
  }
}
</script>
<style lang="scss" scoped>
.type-tag {
  margin: 0 2px;
}

.bbsl-common-page {
  display: flex;
  flex-direction: column;
  row-gap: 10px;

  .page-content {
    display: flex;
    height: calc(100% - 70px);
    column-gap: 10px;

    .tree-container {
      height: 100%;
      min-width: 300px;
      background: #fff;
      border-radius: 20px;
      padding: 20px 20px;
      box-shadow: 0px 0px 12px 0 rgba($color: #000000, $alpha: 0.1);
      box-sizing: border-box;
    }

    .bbsl-table-content {
      height: 100%;
      flex: 1;
      margin-top: 0;
      box-sizing: border-box;
    }
  }
}

a {
  text-decoration: none;
  color: #ffffff;
}

.title {
  width: 100%;
  margin-bottom: 10px;

  i {
    color: #1289fe;
    font-size: 25px;
  }

  span {
    font-size: 25px;
  }
}

::v-deep .el-tree {
  border: none;
}

.avatar-uploader {
  display: inline-block;
  margin-left: 10px;
}

::v-deep .el-tree-node__content {
  padding: 5px 0;
}
</style>
