<template>
  <div class="app-container">
    <el-card>
      <div class="batch-import-weight">
        <el-divider content-position="left">批量导入实重</el-divider>
        <el-alert
          :closable="false"
          type="info"
        >
          <div class="info-text">
            <span class="font-size">根据指定模板文件进行实重导入，点击此处</span><el-link type="primary" class="font-size">
              <a href="javascript:;" @click="downloadXlsx('weightsTemplate')">
                下载模板
              </a>
            </el-link>
          </div>
        </el-alert>
        <el-form class="define-form" inline>
          <el-form-item>
            <el-upload
              ref="importUploadRef"
              action="/"
              accept=".xlsx"
              :disabled="confirmLoading"
              :multiple="false"
              :auto-upload="false"
              :show-file-list="false"
              :on-change="uploadSuccess"
            >
              <el-button type="primary" plain :loading="confirmLoading" size="small">选择文件</el-button>
            </el-upload>
          </el-form-item>
          <el-form-item>
            <el-button type="warning" size="small" :loading="confirmLoading" @click="hanleRefreshError">批量错误重试</el-button>
          </el-form-item>
        </el-form>
        <div v-show="batchListSource.length > 0" class="count-warp">
          <div v-if="countingNum.totalNum > 0">
            <div>
              批量导入实重总数量：<span class="total">{{ countingNum.totalNum }}</span>
              , 导入实重失败数量：<span class="error">{{ countingNum.errorNum }}</span>
              , 导入实重成功数量：<span class="success">{{ countingNum.successNum }}</span>
            </div>
          </div>
          <div v-else>
            <div>
              批量导入实重总数量：<span class="total">{{ countingNum.totalNum }}</span>
            </div>
          </div>
        </div>
        <vxe-table
          border
          :data="pageListSourceData"
          :row-config="{isHover: true}"
          :row-class-name="rowClassName"
          :height="tableHeight"
          :header-row-style="{
            background: '#E6F7FF',
            borderRight: '1px solid #ccc',
          }"
          :scroll-y="{enabled: false}"
          :column-config="{ resizable: true }"
        >
          <vxe-column title="提交时间" field="CreateTime" :min-width="150" />
          <vxe-column title="运单号" field="TransferNumber" :min-width="260" />
          <vxe-column title="实重(KG)" field="Weight" :min-width="100" />
          <vxe-column title="收货时间" field="ReceiverTime" :min-width="150" />
          <vxe-column title="提示内容" field="ResultMessage" :min-width="280">
            <template #default="{ row }">
              <div v-show="row.ResultMessage !== '-'">
                {{ row.ResultMessage }}
              </div>
              <el-button
                v-show="row.ResultMessage === '-'"
                type="text"
                :loading="row.ResultMessage === '-'"
              />
            </template>
          </vxe-column>
        </vxe-table>
        <el-pagination
          background
          :page-sizes="[20, 50, 100, 150, 200]"
          :current-page="listSourcePage"
          :page-size="listSourceSize"
          layout="prev, pager, next ,total ,sizes"
          :total="totalListSource"
          @current-change="pageListSourceChange"
          @size-change="sizeListSourceChange"
        />
      </div>
    </el-card>
    <el-dialog
      title="实重列表数据"
      width="820px"
      top="6vh"
      custom-class="counting-list-form"
      :before-close="closeDialogWeight"
      :close-on-click-modal="false"
      :visible.sync="dialogWeight"
    >
      <el-form ref="costListFormRef">
        <vxe-table
          ref="costListTableRef"
          border
          show-overflow
          :data="pageWeightThrowingData"
          :edit-rules="editRules"
          :edit-config="{ trigger: 'click', mode: 'row', autoClear: false }"
          :scroll-y="{enabled: false}"
          :column-config="{ resizable: true }"
        >
          <vxe-column field="TransferNumber" :min-width="240" title="运单号" :edit-render="{ autofocus: '.el-input__inner' }">
            <template #edit="r">
              <el-input v-model="r.row.TransferNumber" />
            </template>
          </vxe-column>
          <vxe-column field="Weight" :width="220" title="实重(KG)" :edit-render="{ autofocus: '.el-input__inner' }">
            <template #edit="r">
              <el-input-number v-model="r.row.Weight" :controls="false" />
            </template>
          </vxe-column>
          <vxe-column field="ReceiverTime" :width="220" title="收货时间" :edit-render="{ autofocus: '.el-input__inner' }">
            <template #edit="r">
              <el-date-picker
                v-model="r.row.ReceiverTime"
                style="width: 100%;"
                type="date"
                placeholder="收货时间"
                value-format="yyyy-MM-dd"
              />
            </template>
          </vxe-column>
        </vxe-table>
        <el-pagination
          background
          :page-sizes="[20, 50, 100, 150, 200]"
          :current-page="weightThrowingDataPage"
          :page-size="weightThrowingDataSize"
          layout="prev, pager, next ,total ,sizes"
          :total="totalWeightThrowing"
          @current-change="pageThrowingChange"
          @size-change="sizeThrowingChange"
        />
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeDialogWeight">取 消</el-button>
        <el-button type="primary" :loading="confirmLoading" @click="hanleSubmitWeight">导入实重</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { getToken } from '@/utils/auth'
import { deepClone, defineThrottle, getCurrentDateTime } from '@/utils'
import XLSX from 'xlsx'
import axios from 'axios'

export default {
  name: 'BatchImportWeight',
  data() {
    const validatePositiveInteger = ({ cellValue }) => {
      if (!Number.isInteger(cellValue) || cellValue <= 0) {
        return new Error('实重(KG)必须是正整数')
      }
      return true
    }
    return {
      header: { Authorization: 'token ' + getToken() },
      loading: false,
      countingThrowingList: [],
      weightThrowingData: [],
      editRules: {
        TransferNumber: [
          {
            required: true,
            message: '运单号不能为空',
            trigger: 'blur'
          }
        ]
        // Weight: [
        //   {
        //     required: true,
        //     message: '实重(KG)不能为空',
        //     trigger: 'blur'
        //   },
        //   {
        //     validator: validatePositiveInteger,
        //     trigger: 'blur'
        //   }
        // ],
        // ReceiverTime: [
        //   {
        //     required: true,
        //     message: '收货时间不能为空',
        //     trigger: 'blur'
        //   },
        // ],
      },
      dialogWeight: false,
      batchListSource: [],
      confirmLoading: false,
      countingNum: { // 汇总数量
        totalNum: 0,
        errorNum: 0,
        successNum: 0
      },
      tableHeight: 480,
      throttledResize: null,
      saveServiceWeightUrl: 'https://wms.xingyunyi.cn/api/Order/SaveOpWeight',
      weightThrowingDataPage: 1,
      weightThrowingDataSize: 20,
      listSourcePage: 1,
      listSourceSize: 20
    }
  },
  computed: {
    totalWeightThrowing() {
      return this.weightThrowingData.length
    },
    pageWeightThrowingData() {
      const start = (this.weightThrowingDataPage - 1) * this.weightThrowingDataSize
      const end = start + this.weightThrowingDataSize
      return this.weightThrowingData.slice(start, end)
    },
    totalListSource() {
      return this.batchListSource.length
    },
    pageListSourceData() {
      const start = (this.listSourcePage - 1) * this.listSourceSize
      const end = start + this.listSourceSize
      return this.batchListSource.slice(start, end)
    }
  },
  mounted() {
    this.createThrottledResize()
    window.addEventListener('resize', this.throttledResize)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.throttledResize)
  },
  deactivated() {
    window.removeEventListener('resize', this.throttledResize)
  },
  methods: {
    // 计算表格的高度
    getTableHeight: function() {
      const tableHeight = window.innerHeight - 330
      this.tableHeight = tableHeight <= 480 ? 480 : tableHeight
    },
    createThrottledResize() {
      this.getTableHeight()
      this.throttledResize = defineThrottle(this.getTableHeight, 1000) // 使用lodash的throttle方法，设置节流的时间间隔为500ms
    },
    downloadXlsx(name) {
      const fileUrl = `/xlsx/${name}.xlsx`
      const link = document.createElement('a')
      link.href = fileUrl
      link.setAttribute('download', `${name}.xlsx`) // 设置下载属性和文件名
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link) // 点击后移除链接
    },
    // 上传xlsx文件
    uploadSuccess(file) {
      const _this = this
      // 处理文件选择的逻辑
      const excelFile = file.raw
      const isXlsx = excelFile.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      if (!isXlsx) {
        this.$message({ message: '只能上传 xlsx 文件！', type: 'error' })
        return
      }
      // 导入状态和文件信息
      _this.confirmLoading = true
      // 构建fileReader对象
      const fileReader = new FileReader()
      // 该事件为读取完成时触发
      fileReader.onload = function(ev) {
        try {
          const data = new Uint8Array(ev.target.result)
          const workbook = XLSX.read(data, { type: 'array' })
          const sheetName = workbook.SheetNames[0]
          const worksheet = workbook.Sheets[sheetName]
          const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: '' })
          // 规定这个表头
          const headers = jsonData[0]
          const isHead = _this.checkArrayHead(headers)
          if (!isHead) {
            _this.$message({ message: 'Excel表头顺序必须是（运单号、实重(克)、收货时间）！', type: 'error' })
            return false
          }
          const merges = worksheet['!merges']
          if (merges) {
            merges.forEach((mergeCell) => {
              const { s, e } = mergeCell
              const mergedCellValue = jsonData[s.r][s.c] // 获取合并单元格的值
              // 将合并单元格的值应用到所有合并的单元格中
              for (let row = s.r; row <= e.r; row++) {
                for (let col = s.c; col <= e.c; col++) {
                  jsonData[row][col] = mergedCellValue
                }
              }
            })
          }
          _this.countingThrowingList = jsonData
          const paramsCountingThrowings = deepClone(jsonData)
          paramsCountingThrowings.shift()
          if (paramsCountingThrowings.length > 1000) {
            _this.$message.error('最多上传1000条数据！')
            return
          }
          _this.weightThrowingData = _this.dealCountingThrowing(paramsCountingThrowings)
          _this.hanleOpenEditCounting()
        } catch (e) {
          _this.$message({ message: e, type: 'warning' })
        } finally {
          _this.confirmLoading = false
        }
      }
      // 读取数据
      fileReader.readAsArrayBuffer(excelFile)
    },
    // 校验表头
    checkArrayHead(arr) {
      const xlsxHead = ['运单号', '实重(KG)', '收货时间']
      if (arr && arr.length !== xlsxHead.length) return false
      if (arr.every((item, index) => item === xlsxHead[index])) {
        return true
      } else {
        return false
      }
    },
    dealCountingThrowing(array) {
      if (!Array.isArray(array) && array.length === 0) return []
      const result = []
      // 遍历原始数组
      array.forEach(arrItem => {
        const TransferNumber = arrItem[0]
        const Weight = arrItem[1]
        const ReceiverTime = arrItem[2]
        if (TransferNumber) {
          result.push({
            TransferNumber,
            Weight,
            ReceiverTime
          })
        }
      })
      return result
    },
    // 表格错误样式
    rowClassName({ row }) {
      if (row.ResultState === 500) return 'error-bg'
    },
    // 错误排序
    countingOrderSortList() {
      this.batchListSource = this.batchListSource.sort((a, b) => {
        // 根据错误排序
        if (a.ResultState === 500 && b.ResultState === 200) {
          return -1
        } else if (a.ResultState === 200 && b.ResultState === 500) {
          return 1
        } else {
          // 根据时间排序
          return new Date(b.CreateTime) - new Date(a.CreateTime)
        }
      })
      const errorList = this.batchListSource.filter(item => item.ResultState === 500)
      this.countingNum.errorNum = errorList.length
      const successList = this.batchListSource.filter(item => item.ResultState === 200)
      this.countingNum.successNum = successList.length
    },
    // 请求
    getCancelOrder(rowData, rowIndex) {
      return new Promise((resolve) => {
        if (rowData.TransferNumber) {
          // 初始化时间
          const createTime = getCurrentDateTime()
          this.$set(this.batchListSource[rowIndex], 'CreateTime', createTime)
          const currentIndex = this.batchListSource.findIndex((i) => i.id === rowData.id)
          const data = {
            TrackingNumber: rowData.TransferNumber,
            ActiveWeight: rowData.Weight,
            ReceiverTime: rowData.ReceiverTime
          }
          axios({
            method: 'post',
            url: this.saveServiceWeightUrl,
            data: JSON.stringify(data),
            headers: { 'token': getToken(), 'Content-Type': 'application/json' }
          }).then(result => {
            const res = result.data
            if (res.success && currentIndex >= 0) {
              this.$set(this.batchListSource[currentIndex], 'ResultState', 200)
              this.$set(this.batchListSource[currentIndex], 'ResultMessage', '导入成功')
            } else {
              this.$set(this.batchListSource[currentIndex], 'ResultMessage', res.message)
              this.$set(this.batchListSource[currentIndex], 'ResultState', 500)
            }
          }).catch(error => {
            const msg = error.response ? (error.response.data.message || error.response.data.errors || error.response.data) : error
            if (currentIndex >= 0) {
              this.$set(this.batchListSource[currentIndex], 'ResultMessage', msg)
              this.$set(this.batchListSource[currentIndex], 'ResultState', 500)
            }
          }).finally(() => {
            if (currentIndex >= 0) {
              // 更新时间
              const createTime = getCurrentDateTime()
              this.$set(this.batchListSource[currentIndex], 'CreateTime', createTime)
              this.countingOrderSortList()
              resolve(true)
            }
          })
        }
      })
    },
    // 错误重试
    async hanleRefreshError() {
      const isEvery = this.batchListSource.every(item => item.ResultState === 200)
      if (isEvery) {
        this.$message({
          type: 'warning',
          message: '暂无运单号重试'
        })
        return
      }
      try {
        this.confirmLoading = true
        // 同步
        for await (const [rowIndex, rowData] of this.batchListSource.entries()) {
          if (rowData.ResultState === 500) {
            await this.getCancelOrder(rowData, rowIndex)
          }
        }
      } catch (error) {
        console.error(error)
      } finally {
        this.confirmLoading = false
      }
    },
    // 批量导入实重
    async updateBatchCountingOrder() {
      if (this.batchListSource.length === 0) {
        this.$message({
          type: 'warning',
          message: '暂无运单号导入'
        })
        return
      }
      try {
        this.confirmLoading = true
        const list = this.batchListSource.map((item, index) => {
          if (item.TransferNumber) {
            item.id = `${index}_transferNumber`
            item.CreateTime = '-'
            item.ResultMessage = '-'
          }
          return item
        }) || []
        this.batchListSource = list
        // 同步
        for await (const [rowIndex, rowData] of list.entries()) {
          if (rowData.TransferNumber) {
            await this.getCancelOrder(rowData, rowIndex)
          }
        }
      } catch (error) {
        console.error(error)
      } finally {
        this.confirmLoading = false
      }
    },
    // 显示隐藏
    hanleOpenEditCounting() {
      this.dialogWeight = true
    },
    closeDialogWeight() {
      this.dialogWeight = false
    },
    // 确定
    async hanleSubmitWeight() {
      const $table = this.$refs.costListTableRef
      const isValid = await $table.validate(true).catch(errMap => errMap)
      if (!isValid) {
        this.batchListSource = this.weightThrowingData
        this.countingNum.totalNum = this.batchListSource.length
        this.closeDialogWeight()
        this.updateBatchCountingOrder()
      }
    },
    // 可编辑表格
    pageThrowingChange(page) {
      this.weightThrowingDataPage = page
    },
    sizeThrowingChange(size) {
      this.weightThrowingDataSize = size
    },
    // 不可编辑表格
    pageListSourceChange(page) {
      this.listSourcePage = page
    },
    sizeListSourceChange(size) {
      this.listSourceSize = size
    }
  }
}
</script>

<style lang="scss" scoped>
  .counting-list-form .el-input-number ::v-deep .el-input__inner {
    text-align: left !important;
  }
  .batch-import-weight {
    .info-text {
      display: inline-flex;
      padding: 6px 0;
      .font-size {
        font-size: 15px;
      }
    }
    .define-form {
      margin: 10px 0;
      .el-form-item {
        margin-bottom: 0;
      }
    }
    .count-warp {
      padding-bottom: 10px;
      line-height: 1.3;
      font-size: 14px;
      font-weight: bold;
      color: #606266;

      .total {
        font-size: 17px;
        color: #1A73E8;
      }
      .error {
        font-size: 17px;
        color: red;
      }
      .success {
        font-size: 17px;
        color: #67C23A;
      }
    }
  }
</style>
