<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('weightTemplate')">
                下载模板
              </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 class="count-warp" v-show="batchListSource.length > 0">
          <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="customerWeightSupplementaryData"
          :loading="customerWeightLoading"
          :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="FileName" :min-width="130" />
          <vxe-column title="补款条数" field="RowQty" :min-width="130" />
          <vxe-column title="补款金额" field="SumSupplementary" :min-width="130" />
          <vxe-column title="是否上传金额" field="ResultMessage" :min-width="130">
            <template #default="{ row }">
              <el-tag :type="row.IsPost ? 'success' : ''">
                {{ row.IsPost ? '是' : '否' }}
              </el-tag>
            </template>
          </vxe-column>
          <vxe-column title="创建时间" field="CreateTime" :min-width="180">
            <template #default="{ row }">
              {{ row.CreateTime | getDealTimeStr }}
            </template>
          </vxe-column>
          <vxe-column title="操作" :width="220">
            <template #default="{ row }">
              <el-button type="primary" size="mini" @click="onViewDetails(row)" :loading="row.detailLoading">查看明细</el-button>
              <el-button type="success" size="mini" @click="onUploadFee(row)" v-if="!row.IsPost">上传费用</el-button>
            </template>
          </vxe-column>
        </vxe-table>
        <el-pagination
          :page-sizes="[20, 50, 100, 150, 200]"
          :current-page="pagerDto.PageIndex"
          :page-size="pagerDto.PageSize"
          background
          layout="prev, pager, next ,total ,jumper,sizes,slot "
          :total="pagerDto.total"
          @current-change="pagerSerach"
          @size-change="sizeChange"
        />
      </div>
    </el-card>
    <el-dialog
      top="6vh"
      :title="getEditWeightTitle"
      width="1300px"
      :fullscreen="true"
      custom-class="batch-import-weight-form"
      :before-close="closeDialogWeight"
      :close-on-click-modal="false"
      :visible.sync="dialogWeight"
    >
      <el-form ref="costListFormRef">
        <div style="text-align: right; margin-bottom: 4px;">
          <el-button type="primary" :loading="exportLoading" @click="exportBatchWeight">导出表格</el-button>
        </div>
        <vxe-table
          border
          show-overflow
          ref="costListTableRef"
          :loading="pageWeightThrowingLoading"
          :data="pageWeightThrowingData"
          :scroll-y="{enabled: false}"
          :column-config="{ resizable: true }">
          <vxe-column field="TrackingNumber" :min-width="280" title="跟踪号" />
          <vxe-column field="ReceiverTime" :min-width="154" title="收件时间">
            <template #default="{ row }">
              {{ row.ReceiverTime | getDealTimeStr }}
            </template>
          </vxe-column>
          <vxe-column field="OldZone" :min-width="100" title="计费分区" />
          <vxe-column field="OldWeight" :min-width="100" title="原单实重" />
          <vxe-column field="OldFee" :min-width="100" title="原单派送费" />
          <vxe-column field="InputFee" :min-width="100" title="导入派送费" />
          <vxe-column field="InputFee_OldFee" :min-width="100" title="补收金额" />
          <vxe-column field="SystemFee" :min-width="100" title="计算金额" />
          <vxe-column field="SystemFee_InputFee" :min-width="100" title="计算减导入" />
          <vxe-column field="IsSuccess" :min-width="100" title="是否异常">
            <template #default="{ row }">
              <el-tag :type="!row.IsSuccess ? 'danger' : ''">
                {{ !row.IsSuccess ? '是' : '否' }}
              </el-tag>
            </template>
          </vxe-column>
          <vxe-column field="ErrorMessage" :min-width="240" title="异常信息" />
        </vxe-table>
        <div style="text-align: right;">
          <el-pagination
            background
            :page-sizes="[50, 100, 150, 200, 400]"
            :current-page="weightThrowingDataPage"
            :page-size="weightThrowingDataSize"
            layout="prev, pager, next ,total ,sizes"
            :total="totalWeightThrowing"
            @current-change="pageThrowingChange"
            @size-change="sizeThrowingChange"
          />
        </div>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeDialogWeight">
          {{ !getEditWeight ? '取 消' : '关 闭' }}
        </el-button>
        <el-button type="primary" :loading="confirmLoading" @click="hanleSubmitWeight" v-if="!getEditWeight">确定保存</el-button>
      </span>
    </el-dialog>
    <el-dialog
      title="提示"
      top="30vh"
      width="380px"
      custom-class="saveNewFee-form"
      :visible.sync="useSystemDialogVisible"
      :before-close="closeSaveNewFeeVisible">
      <div>
        <el-checkbox v-model="saveNewFeeParams.useSystem" label="是否使用系统运费"></el-checkbox>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeSaveNewFeeVisible">取 消</el-button>
        <el-button type="primary" @click="okSaveNewFee" :loading="saveNewFeeLoading">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { getToken } from '@/utils/auth'
import { deepClone, defineThrottle, getCurrentDateTime } from '@/utils';
import XLSX from 'xlsx';
import { _GetCustomerWeightSupplementary, _GetDetail, _GetNewFee, _SaveNewFee, _UpdateSupplementaryGroup, _DoloadUpdateWeightViewFile } from '@/api/order'
import axios from 'axios';

export default {
  name: 'BatchImportWeight',
  filters: {
    getDealTimeStr(timerStr) {
      if (!timerStr) return ''
      return timerStr.replace('T', ' ')
    }
  },
  data() {
    const validatePositiveInteger = ({ cellValue }) => {
      if (!Number.isInteger(cellValue) || cellValue <= 0) {
        return new Error('实重(克)必须是正整数');
      }
      return true;
    }
    return {
      header: { Authorization: 'token ' + getToken() },
      loading: false,
      countingThrowingList: [],
      weightThrowingData: [],
      editRules: {
        TrackingNumber: [
          {
            required: true,
            message: '运单号不能为空',
            trigger: 'blur'
          },
        ],
        ActiveWeight: [
          {
            required: true,
            message: '实重(克)不能为空',
            trigger: 'blur'
          },
          {
            validator: validatePositiveInteger,
            trigger: 'blur'
          }
        ]
      },
      dialogWeight: false,
      editWeightId: undefined,
      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,
      pageWeightThrowingLoading: false,
      saveNewFeeParams: {
        fileName: '',
        useSystem: false,
        serviceWeightResult: []
      },
      useSystemDialogVisible: false,
      saveNewFeeLoading: false,
      customerWeightSupplementaryData: [],
      customerWeightLoading: false,
      pagerDto: {
        PageIndex: 1,
        PageSize: 20,
        total: 0
      },
      exportLoading: false
    }
  },
  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);
    },
    getEditWeight() {
      return this.editWeightId >= 0 ? true : false
    },
    getEditWeightTitle() {
      return this.getEditWeight ? '查看实重数据' : '上传实重数据'
    }
  },
  mounted() {
    this.initSaveNewFeeList();
    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
      this.saveNewFeeParams.fileName = file.name
      // 处理文件选择的逻辑
      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
          }
          const weightThrowingData = _this.dealCountingThrowing(paramsCountingThrowings)
          _this.getNewFeeList(weightThrowingData)
          _this.hanleOpenEditWeight()
        } catch (e) {
          _this.$message({ message: e, type: 'warning' })
        } finally {
          _this.confirmLoading = false
        }
      }
      // 读取数据
      fileReader.readAsArrayBuffer(excelFile)
    },
    // 校验表头
    checkArrayHead(arr) {
      const xlsxHead = ["运单号", "实重(克)", "运费"]
      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 TrackingNumber = arrItem[0];
        const ActiveWeight = arrItem[1];
        const Fee = arrItem[2];
        if (TrackingNumber && ActiveWeight && Number(Fee) >= 0 ) {
          result.push({
            TrackingNumber,
            ActiveWeight,
            Fee
          })
        }
      });
      return result
    },
    // 获取上传文件后的数据
    getNewFeeList(list) {
      const newsList = list.map(item => ({ TrackingNumber: item.TrackingNumber, ActiveWeight: item.ActiveWeight, Fee: item.Fee }))
      this.pageWeightThrowingLoading = true
      _GetNewFee(newsList).then((res) => {
        this.weightThrowingData = res
      }).finally(() => {
        this.pageWeightThrowingLoading = false
      })
      // const weightThrowingData = [
      //   {
      //     "TrackingNumber": "4209894092001903608804663394184958",
      //     "IsSuccess": true,
      //     "ErrorMessage": null,
      //     "ReceiverTime": "2024-05-31T11:13:50",
      //     "OldWeight": 0.500,
      //     "OldFee": 9.18,
      //     "oldZone": "5",
      //     "SystemFee": 9.18,
      //     "NewWeight": 0.5,
      //     "InputFee": 7.87,
      //     "InputFee_OldFee": -1.31,
      //     "SystemFee_OldFee": 0.00
      //   }
      // ]
      // this.weightThrowingData = weightThrowingData
    },
    // 表格错误样式
    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.TrackingNumber) {
          // 初始化时间
          const createTime = getCurrentDateTime()
          this.$set(this.batchListSource[rowIndex], 'CreateTime', createTime);
          const currentIndex = this.batchListSource.findIndex((i) => i.id === rowData.id)
          const data = {
            TrackingNumber: rowData.TrackingNumber,
            ActiveWeight: rowData.ActiveWeight,
          }
          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.TrackingNumber) {
            item.id = `${index}_transferNumber`
            item.CreateTime = '-'
            item.ResultMessage = '-'
          }
          return item
        }) || []
        this.batchListSource = list
        // 同步
        for await (const [rowIndex, rowData] of list.entries()) {
          if (rowData.TrackingNumber) {
            await this.getCancelOrder(rowData, rowIndex)
          }
        }
      } catch (error) {
        console.error(error);
      } finally {
        this.confirmLoading = false
      }
    },
    // 显示隐藏
    hanleOpenEditWeight() {
      this.dialogWeight = true
    },
    closeDialogWeight() {
      this.dialogWeight = false
      this.editWeightId = undefined
      this.weightThrowingData = []
    },
    // 确定保存
    async hanleSubmitWeight() {
      this.useSystemDialogVisible = true
      const list = this.weightThrowingData.map(item => {
        const { _X_ROW_KEY, ...rest } = item;
        return rest;
      });
      this.saveNewFeeParams.serviceWeightResult = list
      // 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()
      // }
    },
    initSaveNewFeeList() {
      this.customerWeightLoading = true
      _GetCustomerWeightSupplementary(this.pagerDto).then((res) => {
        this.customerWeightSupplementaryData = res.Result
        this.pagerDto.total = res.TotalCount
      }).finally(() => {
        this.customerWeightLoading = false
      })
      // this.batchListSource = [
      //   {
      //     "FileName":"1.xlsx", /*文件名*/
      //     "RowQty":100,/*补款条数*/
      //     "SumSupplementary":1000,/*补款金额*/
      //     "IsPost":"true"/*是否上传金额*/
      //   }
      // ]
      // this.countingNum.totalNum = this.batchListSource.length
    },
    closeSaveNewFeeVisible() {
      this.useSystemDialogVisible = false
    },
    closeSaveNewFee() {
      this.closeSaveNewFeeVisible()
      this.saveNewFeeParams.useSystem = false
      this.saveNewFeeParams.fileName = ''
    },
    okSaveNewFee() {
      const useSystem = this.saveNewFeeParams.useSystem ? true : undefined
      const params = {
        ...this.saveNewFeeParams,
        useSystem
      }
      this.saveNewFeeLoading = true
      _SaveNewFee(params).then((res) => {
        this.$message({ type: 'success', message: '保存成功' })
        this.closeSaveNewFee()
        this.closeDialogWeight()
        this.initSaveNewFeeList()
      }).finally(() => {
        this.saveNewFeeLoading = false
      })
    },
    // 查看明细
    onViewDetails(row) {
      if (!row.Id) return
      this.editWeightId = row.Id
      this.$set(row, 'detailLoading', true)
      _GetDetail(row.Id).then((res) => {
        this.weightThrowingData = res
        this.hanleOpenEditWeight()
      }).finally(() => {
        this.$set(row, 'detailLoading', false)
      })
    },
    // 上传费用
    onUploadFee(row) {
      if (!row.Id) return
      const that = this
      that.$confirm('是否继续上传费用?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        _UpdateSupplementaryGroup(row.Id).then(() => {
          this.$message({
            type: 'success',
            message: '操作成功'
          });
          that.initSaveNewFeeList()
        }).finally(() => {
        })
      })
    },
    // 明细分页-前度
    pageThrowingChange(page) {
      this.weightThrowingDataPage = page;
    },
    sizeThrowingChange(size) {
      this.weightThrowingDataSize = size;
    },
    // 外层分页-后端
    pagerSerach(p) {
      this.pagerDto.PageIndex = p
      this.initSaveNewFeeList()
    },
    sizeChange(s) {
      this.pagerDto.PageIndex = 1
      this.pagerDto.PageSize = s
      this.initSaveNewFeeList()
    },
    // 导出
    async exportBatchWeight() {
      const pageWeightThrowingData = deepClone(this.pageWeightThrowingData)
      const list = pageWeightThrowingData.map(obj => {
        delete obj['_X_ROW_KEY'];
        return obj;
      });
      this.exportLoading = true
      _DoloadUpdateWeightViewFile(list).finally(() => {
        this.exportLoading = false
      })
      // const currentDate = getCurrentDateTime('-')
      // const filename = '实重列表数据' + currentDate
      // this.exportLoading = true
      // if (this.$refs.costListTableRef) {
      //   await this.$refs.costListTableRef.exportData({ type: 'csv', filename })
      // }
      // this.exportLoading = false
    }
  }
}
</script>

<style lang="scss" scoped>
  .batch-import-weight-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>
