<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="分公司" prop="impUnitName">
        <el-select
          v-model="queryParams.impUnitName"
          placeholder="请选择分公司"
          clearable
          filterable
          style="width: 240px"
          @change="handleImpUnitChange"
        >
          <el-option
            v-for="item in impUnitOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="项目部" prop="departName">
        <el-select
          v-model="queryParams.departName"
          placeholder="请选择项目部"
          clearable
          filterable
          style="width: 240px"
          @change="handleDepartChange"
        >
          <el-option
            v-for="item in departOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="工程" prop="proName">
        <el-select
          v-model="queryParams.proName"
          placeholder="请选择工程"
          clearable
          filterable
          style="width: 240px"
        >
          <el-option
            v-for="item in proOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="物资名称" prop="typeName">
        <el-select
          v-model="queryParams.typeName"
          placeholder="请选择物资名称"
          clearable
          filterable
          style="width: 240px"
          @change="handleMaModel"
        >
          <el-option
            v-for="item in materialNameList"
            :key="item.value"
            :label="item.label"
            :value="item.label"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="规格型号" prop="typeModelName">
        <el-select
          v-model="queryParams.typeModelName"
          placeholder="请选择规格型号"
          clearable
          filterable
          style="width: 240px"
        >
          <el-option
            v-for="item in materialModelList"
            :key="item.value"
            :label="item.label"
            :value="item.label"
          />
        </el-select>
      </el-form-item>

      <el-form-item label="机具类型" prop="jiJuType">
        <el-select
          v-model="queryParams.jiJuType"
          placeholder="请选择机具类型"
          clearable
          style="width: 240px"
        >
          <el-option label="施工机具" :value="1" />
          <el-option label="安全工器具" :value="2" />
        </el-select>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
        <el-button
          icon="el-icon-download"
          size="mini"
          @click="handleBulkDownload"
          :disabled="!canDownload"
          :loading="isExporting">
          {{ exportButtonText }}
        </el-button>
      </el-form-item>
    </el-form>

    <!-- 进度条显示区域 -->
    <div v-if="showProgress" class="progress-container">
      <el-progress
        :percentage="progressPercentage"
        :status="progressStatus"
        :stroke-width="18"
        :text-inside="true"
        :show-text="true">
      </el-progress>
      <div class="progress-info">
        <span class="progress-text">{{ progressText }}</span>
        <span class="progress-detail">{{ currentItem }}/{{ totalItems }} {{ currentFileName }}</span>
        <span class="progress-speed" v-if="downloadSpeed > 0">
          速度: {{ formatBytes(downloadSpeed) }}/s
        </span>
      </div>
      <div class="progress-actions" v-if="showProgress">
        <el-button
          size="mini"
          @click="cancelDownload"
          :disabled="!isExporting"
          v-if="!downloadComplete">
          取消下载
        </el-button>
        <el-button
          size="mini"
          type="success"
          @click="clearProgress"
          v-if="downloadComplete">
          完成
        </el-button>
      </div>
    </div>

    <el-table v-loading="loading" :data="tableList" ref="multipleTable" row-key="id" @selection-change="handleSelectionChange" border>
      <el-table-column type="selection" width="45" :reserve-selection="true"></el-table-column>
      <el-table-column label="序号" align="center" width="60" type="index">
        <template slot-scope="scope">
          <span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
        </template>
      </el-table-column>
      <el-table-column label="分公司" align="center" prop="impUnitName" :show-overflow-tooltip="true"/>
      <el-table-column label="项目部" align="center" prop="departName" :show-overflow-tooltip="true"/>
      <el-table-column label="工程名称" align="center" prop="proName" :show-overflow-tooltip="true"/>
      <el-table-column label="物资名称" align="center" prop="typeName" :show-overflow-tooltip="true"/>
      <el-table-column label="规格型号" align="center" prop="typeModelName" :show-overflow-tooltip="true"/>
      <el-table-column label="计量单位" align="center" prop="unit" :show-overflow-tooltip="true"/>
      <el-table-column label="数量" align="center" prop="num" :show-overflow-tooltip="true"/>
      <el-table-column label="编码" align="center" prop="maCode" :show-overflow-tooltip="true">
        <template slot-scope="scope">
          <span
            v-if="scope.row.maCode"
            :style="{
              color: scope.row.qrCode ? '#3EA7F1' : '#000000',
              cursor: scope.row.qrCode ? 'pointer' : 'default'
            }"
            @click="scope.row.qrCode && handleViewQrCode(scope.row)"
          >
            {{ scope.row.maCode }}
          </span>
          <span v-else>—</span>
        </template>
      </el-table-column>

      <el-table-column label="领用日期" align="center" prop="leaseTime" :show-overflow-tooltip="true" width="100px"/>
      <el-table-column label="出库检验报告" align="center" :show-overflow-tooltip="true">
        <template #default="scope">
          <span
            @click="handleReport(scope.row)"
            style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
          >查看</span>
        </template>
      </el-table-column>
      <el-table-column label="合格证" align="center" :show-overflow-tooltip="true">
        <template #default="scope">
          <span v-if="!scope.row.qualifiedUrl">无</span>
          <span
            v-else
            @click="handleFileView(scope.row.qualifiedUrl)"
            style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
          >查看</span>
        </template>
      </el-table-column>

      <el-table-column label="型式试验报告" align="center" :show-overflow-tooltip="true">
        <template #default="scope">
          <span v-if="!scope.row.testReportUrl">无</span>
          <span
            v-else
            @click="handleFileView(scope.row.testReportUrl)"
            style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
          >查看</span>
        </template>
      </el-table-column>

      <el-table-column label="第三方检测报告" align="center" :show-overflow-tooltip="true">
        <template #default="scope">
          <span v-if="!scope.row.thirdReportUrl">无</span>
          <span
            v-else
            @click="handleFileView(scope.row.thirdReportUrl)"
            style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
          >查看</span>
        </template>
      </el-table-column>

      <el-table-column label="出厂检测报告" align="center" :show-overflow-tooltip="true">
        <template #default="scope">
          <span v-if="!scope.row.factoryReportUrl">无</span>
          <span
            v-else
            @click="handleFileView(scope.row.factoryReportUrl)"
            style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
          >查看</span>
        </template>
      </el-table-column>

      <el-table-column label="其他" align="center" :show-overflow-tooltip="true">
        <template #default="scope">
          <span v-if="!scope.row.otherReportUrl">无</span>
          <span
            v-else
            @click="handleFileView(scope.row.otherReportUrl)"
            style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
          >查看</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" width="100">
        <template slot-scope="scope">
          <el-button size="mini" type="primary" @click="handleDownload(scope.row)">下载</el-button>
        </template>
      </el-table-column>

    </el-table>

    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 验收单弹窗 -->
    <el-dialog :title="title" :visible.sync="openOutReport" width="70%" append-to-body>
      <div style="height: 600px; overflow-y: scroll; padding: 0 20px">
        <vue-easy-print tableShow ref="remarksPrintRefCheck" class="print" :printable="'checkId1'">
          <div id="checkId1">
            <div class="title" style="text-align: center; font-weight: 600; font-size: 16px">
              施工机具设备出库检验记录表
            </div>
            <div class="info" style="margin-top: 10px; display: flex; flex-wrap: wrap">
              <div class="item" style="width: 50%; flex-shrink: 0; margin-bottom: 5px; font-size: 14px">
                <span>领用工程：</span>
                {{ checkDataInfo.leaseProject }}
              </div>

              <div class="item" style="width: 50%; flex-shrink: 0; margin-bottom: 5px; font-size: 14px">
                <span>使用单位：</span>
                {{ checkDataInfo.leaseUnit }}
              </div>
            </div>
            <table
              class="print-table"
              style="margin-top: 20px; width: 100%; border-collapse: collapse"
              border="1"
            >
              <thead>
              <tr>
                <th style="text-align: center">物资名称</th>
                <th style="text-align: center">规格型号</th>
                <th style="text-align: center">单位</th>
                <th style="text-align: center">数量</th>
                <th style="text-align: center">设备编码</th>
                <th style="text-align: center">额定载荷KN</th>
                <th style="text-align: center">试验载荷KN</th>
                <th style="text-align: center">持荷时间min</th>
                <th style="text-align: center; width: 100px">试验日期</th>
                <th style="text-align: center; width: 100px">下次试验日期</th>
                <th style="text-align: center">检验结论</th>
                <th style="text-align: center">备注</th>
              </tr>
              </thead>
              <tbody>
              <tr v-for="(item, index) in printTableData" :key="index">
                <td style="text-align: center">{{ item.typeName }}</td>
                <td style="text-align: center">{{ item.typeModelName }}</td>
                <td style="text-align: center">{{ item.unit }}</td>
                <td style="text-align: center">{{ item.num }}</td>
                <td style="text-align: center">{{ item.maCode }}</td>
                <td style="text-align: center">{{ item.ratedLoad }}</td>
                <td style="text-align: center">{{ item.testLoad }}</td>
                <td style="text-align: center">{{ item.holdingTime }}</td>
                <td style="text-align: center">{{ item.testTime }}</td>
                <td style="text-align: center">{{ item.nextTestTime }}</td>
                <td style="text-align: center">{{ item.checkResult }}</td>
                <td style="text-align: center">{{ item.remark }}</td>
              </tr>
              </tbody>
            </table>

            <div
              class="fillIn"
              style="margin-top: 20px; display: flex; align-items: center; justify-content: right"
            >
              <div class="item" style="width: 30%; align-items: center; position: relative">
                <div>
                  <span>检验单位：</span>
                </div>
                <div v-if="openOutReport">
                  <canvas
                    id="canvas"
                    width="165"
                    height="165"
                    style="
                                            position: absolute;
                                            top: 180%;
                                            left: 90%;
                                            transform: translate(-100%, -50%);
                                            z-index: 9999;
                                        "
                  ></canvas>
                </div>
              </div>
            </div>
          </div>
        </vue-easy-print>
      </div>

      <div slot="footer" class="dialog-footer" style="text-align: center">
        <el-button type="primary" @click="printCheck">打 印</el-button>
        <el-button @click="closeDialogAndRefresh">关 闭</el-button>
      </div>
    </el-dialog>

    <!-- 二维码下载对话框 -->
    <el-dialog title="二维码查看" :visible.sync="uploadOpen" width="450px" append-to-body :close-on-click-modal="false">
      <div style="text-align: center" ref="codeQr" v-if="uploadOpen">
        <div class="uploadImg">
          <div id="qrcode" class="qrcode" ref="codeItem"></div>
        </div>
        <div class="boxCode">{{ rowObj.maCode }}</div>
      </div>
      <div slot="footer" class="dialog-footer" style="text-align: center">
        <el-button type="primary" @click="downloadQrCode(rowObj)">下 载</el-button>
      </div>
    </el-dialog>

  </div>
</template>

<script>
import vueEasyPrint from "vue-easy-print";
import {batchDownloadFileApi, downloadFileApi, getReportList} from "@/api/report/report";
import {getDepartListByImpUnitApi, getImpUnitListApi, getProListByDepartApi} from "@/api/materialsStation";
import {getMaterialTypeList} from "@/api/ma/device";
import {getCheckInfo} from "@/api/lease/apply";
import printJS from "print-js";
import QRCode from "qrcodejs2";
import axios from 'axios'
import {downloadFile} from "@/utils/download";
import request from "@/utils/request";
import {getToken} from "@/utils/auth";

export default {
  name: "ReportQuery",
  dicts: ['part_task_status'],
  components: {vueEasyPrint},
  data() {
    return {
      // 遮罩层
      loading: false,
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      showHouse: false,
      dateRange: [],
      ids: [],
      infos: [],
      // 总条数
      total: 0,
      //表格数据
      tableList: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        keyWord: undefined,
        taskStatus: undefined,
        departName: undefined,
        proName: undefined,
        impUnitName: undefined,
        typeName: undefined,
        typeModelName: undefined,
        jiJuType: undefined,
      },
      impUnitOptions: [],   // 分公司下拉
      departOptions: [],    // 项目部下拉
      proOptions: [],       // 工程下拉
      materialNameList: [],
      materialModelList: [],
      openOutReport: false,
      checkDataInfo: {},
      printTableData: [],
      uploadOpen: false,
      rowObj: {},

      // 全局选中的项，用于跨页勾选
      selectedIds: [],
      selectedData: {}, // 使用对象存储选中项数据，key为id

      // 下载进度相关数据
      isExporting: false,
      showProgress: false,
      downloadComplete: false,
      progressPercentage: 0,
      currentItem: 0,
      totalItems: 0,
      currentFileName: '',
      progressText: '准备下载...',
      progressStatus: '',
      downloadSpeed: 0,
      downloadController: null,
      retryCount: 0,
      maxRetries: 3,
      downloadStartTime: 0,
      downloadedBytes: 0,
    };
  },
  computed: {
    /** 是否可以下载 */
    canDownload() {
      const can = this.selectedIds.length > 0 && !this.isExporting;
      console.log('canDownload检查:', {
        selectedIds: this.selectedIds.length,
        isExporting: this.isExporting,
        can: can
      });
      return can;
    },

    /** 下载按钮文字 */
    exportButtonText() {
      if (this.isExporting) {
        return `下载中 ${this.progressPercentage}%`;
      }
      return `一键下载${this.selectedIds.length > 0 ? ` (${this.selectedIds.length})` : ''}`;
    }
  },
  created() {
    console.log('组件初始化');
    this.getList();
    this.getImpUnitOptions()
    this.departList()
    this.proList()
    this.getDeviceType()
  },
  beforeDestroy() {
    // 清理资源
    if (this.downloadController) {
      this.downloadController.abort();
    }
  },
  methods: {
    /** 获取分公司下拉 */
    async getImpUnitOptions() {
      try {
        const res = await getImpUnitListApi()
        this.impUnitOptions = res.data.map(item => ({
          label: item.impUnitName,
          value: item.impUnitName
        }))
      } catch (e) {
        console.error('获取分公司下拉失败:', e)
      }
    },
    /** 获取项目部下拉 */
    async departList() {
      try {
        const res = await getDepartListByImpUnitApi()
        this.departOptions = res.data.map(item => ({
          label: item.departName,
          value: item.departName
        }))
      } catch (e) {
        console.error('获取项目部下拉失败:', e)
      }
    },
    /** 获取工程下拉 */
    async proList() {
      try {
        const res = await getProListByDepartApi()
        this.proOptions = res.data.map(item => ({
          label: item.proName,
          value: item.proName
        }))
      } catch (e) {
        console.error('获取工程下拉失败:', e)
      }
    },
    /** 分公司选择变化，加载项目部 */
    async handleImpUnitChange() {
      this.queryParams.departName = null
      this.departOptions = []
      this.queryParams.proName = null
      this.proOptions = []

      try {
        const params = {
          impUnitName: this.queryParams.impUnitName,
          departName: this.queryParams.departName,
          proName: this.queryParams.proName,
          teamName: this.queryParams.teamName,
          subUnitName: this.queryParams.subUnitName,
        }
        const res = await getDepartListByImpUnitApi(params)
        this.departOptions = res.data.map(item => ({
          label: item.departName,
          value: item.departName
        }))
      } catch (e) {
        console.error('获取项目部下拉失败:', e)
      }
    },
    /** 项目部选择变化，加载工程 */
    async handleDepartChange() {
      this.queryParams.proName = null
      this.proOptions = []

      try {
        const params = {
          impUnitName: this.queryParams.impUnitName,
          departName: this.queryParams.departName,
          proName: this.queryParams.proName,
          teamName: this.queryParams.teamName,
          subUnitName: this.queryParams.subUnitName,
        }
        const res = await getProListByDepartApi(params)
        this.proOptions = res.data.map(item => ({
          label: item.proName,
          value: item.proName
        }))
      } catch (e) {
        console.error('获取工程下拉失败:', e)
      }
    },
    getDeviceType() {
      getMaterialTypeList({level: 3, skipPermission: 1}).then(response => {
        let matNameRes = response.data
        this.materialNameList = matNameRes.map((item) => {
          return {
            label: item.typeName,
            value: item.typeId
          }
        })
      })
      getMaterialTypeList({level: 4, skipPermission: 1}).then(response => {
        let matModelRes = response.data
        this.materialModelList = matModelRes.map((item) => {
          return {
            label: item.typeName,
            value: item.typeId
          }
        })
      })
    },
    // change设备类型
    handleMaModel(e) {
      this.queryParams.typeModelName = null
      this.materialModelList = []
      let typeId = null
      if (!e) {
        typeId = null
      } else {
        typeId = this.materialNameList.find(item => item.label == e).value
      }
      getMaterialTypeList({level: 4, skipPermission: 1, typeId}).then(response => {
        let matModelRes = response.data
        this.materialModelList = matModelRes.map((item) => {
          return {
            label: item.typeName,
            value: item.typeId
          }
        })
      })
    },
    /** 查询列表 */
    getList() {
      this.loading = true;
      if (this.dateRange.length > 0) {
        this.queryParams.startTime = this.dateRange[0]
        this.queryParams.endTime = this.dateRange[1]
      } else {
        this.queryParams.startTime = undefined
        this.queryParams.endTime = undefined
      }
      this.queryParams.taskStage = 3
      getReportList(this.queryParams).then(response => {
        this.tableList = response.data.rows;
        this.total = response.data.total;
        this.loading = false;

        this.$nextTick(() => {
          if (this.$refs.multipleTable) {
            // 恢复之前选中的行
            this.tableList.forEach(row => {
              if (this.selectedIds.includes(row.id)) {
                this.$refs.multipleTable.toggleRowSelection(row, true);
              }
            });
          }
        });
      });
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.dateRange = []
      this.queryParams.keyWord = null;
      this.selectedIds = [];
      this.selectedData = {};
      if (this.$refs.multipleTable) {
        this.$refs.multipleTable.clearSelection();
      }
      this.handleQuery();
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.selectedIds = [];
      this.selectedData = {};
      if (this.$refs.multipleTable) {
        this.$refs.multipleTable.clearSelection();
      }
      this.getList();
    },
    // ==== 修复关键：简化的选中状态处理 ====
    handleSelectionChange(selection) {
      console.log('选中项变化:', selection.length, '项');

      // 清空现有选中状态
      this.selectedIds = [];
      this.selectedData = {};

      // 重新构建选中状态
      selection.forEach(item => {
        this.selectedIds.push(item.id);
        this.selectedData[item.id] = item;
      });

      console.log('当前选中ID:', this.selectedIds);
      console.log('选中数据:', this.selectedData);

      // 更新其他相关数据
      this.ids = this.selectedIds;
      this.infos = selection.map(item => ({id: item.id}));
      this.single = this.ids.length !== 1;
      this.multiple = this.ids.length === 0;
    },
    //查看
    handleView(row) {
      let query = {Id: row.id, taskId: row.taskId, isView: "true"}
      this.$tab.closeOpenPage({
        path: '/part/partAcceptDetail',
        query,
      })
    },
    // 文件查看逻辑
    handleFileView(url) {
      if (!url) return;

      const fileExt = url.split('.').pop().toLowerCase();
      const imgExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
      const pdfExts = ['pdf'];
      const docExts = ['doc', 'docx', 'xls', 'xlsx'];

      if (imgExts.includes(fileExt)) {
        this.$viewerApi ? this.$viewerApi({images: [url]}) : window.open(url);
      } else if (pdfExts.includes(fileExt)) {
        window.open(url);
      } else if (docExts.includes(fileExt)) {
        this.downloadFile(url);
      } else {
        this.downloadFile(url);
      }
    },

    // 文件下载逻辑
    downloadFile(url) {
      const link = document.createElement('a');
      link.href = url;
      const fileName = url.substring(url.lastIndexOf('/') + 1);
      link.setAttribute('download', fileName);
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },
    //查看验收单
    async handleReport(row) {
      this.checkDataInfo = {
        leaseProject: row.proName,
        leaseUnit: row.departName
      }
      this.printTableData = [
        {
          typeName: row.typeName,
          typeModelName: row.typeModelName,
          unit: row.unit,
          num: row.num,
          maCode: row.maCode,
          ratedLoad: row.ratedLoad,
          testLoad: row.testLoad,
          holdingTime: row.holdingTime,
          testTime: row.testTime,
          nextTestTime: row.nextTestTime,
          checkResult: row.checkResult,
          remark: ''
        }
      ]
      setTimeout(() => {
        this.chapter('检验专用章', '安徽送变电工程有限公司机具(物流)分公司')
      }, 200)
      this.openOutReport = true
      this.title = '出库检验单'
    },
    //出库检验单打印
    printCheck() {
      this.$nextTick(() => {
        printJS({
          printable: 'checkId1',
          type: 'html',
          style: `
                        @page { size: A4; margin: 0; }
                        body { margin: 0.5cm; font-family: SimSun; }
                        #passId { font-size: 18px; padding: 0 20px; }
                    `,
          scanStyles: false
        })
      })
    },
    // 关闭弹窗
    closeDialogAndRefresh() {
      this.openOutReport = false
    },
    chapter(text, companyName) {
      let canvas = document.getElementById('canvas')
      let context = canvas.getContext('2d')
      canvas.width = canvas.width
      context.height = canvas.height

      let width = canvas.width / 2
      let height = canvas.height / 2
      context.lineWidth = 3
      context.strokeStyle = '#f00'
      context.beginPath()
      context.arc(width, height, 80, 0, Math.PI * 2)
      context.stroke()

      this.create5star(context, width, height, 20, '#f00', 0)

      context.font = '100 13px 宋体'
      context.textBaseline = 'middle'
      context.textAlign = 'center'
      context.lineWidth = 1
      context.strokeStyle = '#ff2f2f'
      context.strokeText(text, width, height + 50)

      context.translate(width, height)
      context.font = '100 13px 宋体'
      let count = companyName.length
      let angle = (4 * Math.PI) / (3 * (count - 1))
      let chars = companyName.split('')
      let c
      for (let i = 0; i < count; i++) {
        c = chars[i]
        if (i == 0) {
          context.rotate((5 * Math.PI) / 6)
        } else {
          context.rotate(angle)
        }

        context.save()
        context.translate(65, 0)
        context.rotate(Math.PI / 2)
        context.strokeStyle = '#ff5050'
        context.strokeText(c, 0, 0)
        context.restore()
      }
    },
    //绘制五角星
    create5star(context, sx, sy, radius, color, rotato) {
      context.save()
      context.fillStyle = color
      context.translate(sx, sy)
      context.rotate(Math.PI + rotato)
      context.beginPath()
      let dig = (Math.PI / 5) * 4
      for (let i = 0; i < 5; i++) {
        let x = Math.sin(i * dig)
        let y = Math.cos(i * dig)
        context.lineTo(x * radius, y * radius)
      }
      context.closePath()
      context.stroke()
      context.fill()
      context.restore()
    },
    // 二维码查看
    handleViewQrCode(row) {
      this.rowObj = row
      this.uploadOpen = true
      this.qrCode = row.qrCode
      let str = 'http://ahjj.jypxks.com:9988/imw/backstage/machine/qrCodePage?qrcode=' + row.qrCode
      this.$nextTick(() => {
        this.$refs.codeItem.innerHTML = ''
        var qrcode = new QRCode(this.$refs.codeItem, {
          text: str,
          width: 256,
          height: 256,
          colorDark: '#000000',
          colorLight: '#ffffff',
          correctLevel: QRCode.CorrectLevel.H
        })
      }, 500)

    },
    downloadQrCode(row) {
      const qrContainer = document.createElement('div')
      document.body.appendChild(qrContainer)

      const qrSize = 512
      const padding = 20
      const fontSize = 68
      const maxTextWidth = qrSize

      const qrcode = new QRCode(qrContainer, {
        text: 'http://ahjj.jypxks.com:9988/imw/backstage/machine/qrCodePage?qrcode=' + row.qrCode,
        width: qrSize,
        height: qrSize,
        colorDark: '#000000',
        colorLight: '#ffffff',
        correctLevel: QRCode.CorrectLevel.H
      })

      setTimeout(() => {
        const img = qrContainer.querySelector('img') || qrContainer.querySelector('canvas')
        const text = row.maCode || ''

        const ctxMeasure = document.createElement('canvas').getContext('2d')
        ctxMeasure.font = `${fontSize}px Arial`
        const words = text.split('')
        let line = ''
        const lines = []
        for (let i = 0; i < words.length; i++) {
          const testLine = line + words[i]
          if (ctxMeasure.measureText(testLine).width > maxTextWidth) {
            lines.push(line)
            line = words[i]
          } else {
            line = testLine
          }
        }
        lines.push(line)

        const lineHeight = fontSize + 10
        const qrCanvas = document.createElement('canvas')
        qrCanvas.width = qrSize + padding * 2
        qrCanvas.height = qrSize + padding * 2 + lines.length * lineHeight

        const ctx = qrCanvas.getContext('2d')
        ctx.fillStyle = '#fff'
        ctx.fillRect(0, 0, qrCanvas.width, qrCanvas.height)

        ctx.drawImage(img, padding, padding, qrSize, qrSize)

        ctx.fillStyle = '#000'
        ctx.font = `${fontSize}px Arial`
        ctx.textAlign = 'center'
        lines.forEach((ln, index) => {
          ctx.fillText(ln, qrCanvas.width / 2, qrSize + padding + fontSize / 1.2 + index * lineHeight)
        })

        const a = document.createElement('a')
        a.href = qrCanvas.toDataURL('image/png')
        a.download = text + '.png'
        a.click()

        document.body.removeChild(qrContainer)
      }, 500)
    },
    /** 单条下载 */
    handleDownload(row) {
      const payload = {
        items: [
          {
            proName: row.proName || '',
            departName: row.departName || '',
            typeName: row.typeName || '',
            typeModelName: row.typeModelName || '',
            qualifiedUrl: row.qualifiedUrl || null,
            testReportUrl: row.testReportUrl || null,
            thirdReportUrl: row.thirdReportUrl || null,
            factoryReportUrl: row.factoryReportUrl || null,
            otherReportUrl: row.otherReportUrl || null,
            unit: row.unit || '',
            num: row.num || '',
            maCode: row.maCode || '',
            ratedLoad: row.ratedLoad || '',
            testLoad: row.testLoad || '',
            holdingTime: row.holdingTime || '',
            testTime: row.testTime || '',
            nextTestTime: row.nextTestTime || '',
            checkResult: row.checkResult || '',
            remark: ''
          },
        ],
        zipName: row.proName || 'report',
      };

      this.downloadSingleFile(payload, `${row.proName || '文件档案下载'}.zip`);
    },

    /** 一键下载（多选） */
    async handleBulkDownload() {
      // 检查是否有选中项
      if (this.selectedIds.length === 0) {
        this.$message.warning('请先勾选要下载的行');
        return;
      }

      console.log('开始下载，选中数量:', this.selectedIds.length);

      // 确认对话框
      try {
        await this.$confirm(`确定要下载 ${this.selectedIds.length} 个选中项吗？`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning',
          center: true
        });
      } catch (cancel) {
        console.log('用户取消下载');
        return;
      }

      // 初始化下载状态
      this.initializeDownload();

      try {
        // 构建下载数据 - 直接从selectedData获取
        const items = Object.values(this.selectedData).map(item => ({
          proName: item.proName || '',
          departName: item.departName || '',
          typeName: item.typeName || '',
          typeModelName: item.typeModelName || '',
          qualifiedUrl: item.qualifiedUrl || null,
          testReportUrl: item.testReportUrl || null,
          thirdReportUrl: item.thirdReportUrl || null,
          factoryReportUrl: item.factoryReportUrl || null,
          otherReportUrl: item.otherReportUrl || null,
          unit: item.unit || '',
          num: item.num || '',
          maCode: item.maCode || '',
          ratedLoad: item.ratedLoad || '',
          testLoad: item.testLoad || '',
          holdingTime: item.holdingTime || '',
          testTime: item.testTime || '',
          nextTestTime: item.nextTestTime || '',
          checkResult: item.checkResult || '',
          remark: ''
        }));

        console.log('构建了', items.length, '个下载项');

        // 计算总文件数
        this.totalItems = this.calculateTotalFiles(items);
        console.log('总文件数:', this.totalItems);

        const taskId = null
        const payload = {
          items: items,
          taskId: null,
          zipName: `报告下载_${new Date().getTime()}`,
          stream: true
        };

        // 开始下载
        await this.streamDownload(payload);

      } catch (err) {
        console.error('一键下载失败', err);
        this.handleDownloadError(err);
      }
    },

    /** 初始化下载状态 */
    initializeDownload() {
      this.isExporting = true;
      this.showProgress = true;
      this.downloadComplete = false;
      this.progressPercentage = 0;
      this.currentItem = 0;
      this.totalItems = 0;
      this.currentFileName = '';
      this.progressText = '准备下载...';
      this.progressStatus = null;
      this.downloadSpeed = 0;
      this.retryCount = 0;
      this.downloadedBytes = 0;
      this.downloadStartTime = Date.now();
      this.downloadController = new AbortController();
    },

    /** 计算总文件数 */
    calculateTotalFiles(items) {
      let total = 0;
      items.forEach(item => {
        // 出库检验报告
        total += 1;
        // 各个附件
        if (item.qualifiedUrl) total += 1;
        if (item.testReportUrl) total += 1;
        if (item.thirdReportUrl) total += 1;
        if (item.factoryReportUrl) total += 1;
        if (item.otherReportUrl) total += 1;
      });
      return total;
    },

    /** 流式下载方法 - 使用原始的request方式 */
    async streamDownload(payload) {
      try {
        this.progressText = '正在连接服务器...';

        // 使用原始的request方法
        await this.downloadZip(
          '/material/bm_report/downloadBulkStream',
          JSON.stringify(payload),
          `${payload.zipName}.zip`,
          {
            timeout: 0,
            onDownloadProgress: (progressEvent) => {
              this.handleDownloadProgress(progressEvent);
            }
          }
        )

        this.handleDownloadComplete();

      } catch (error) {
        if (error.message && error.message.includes('canceled')) {
          this.progressText = '下载已取消';
          this.progressPercentage = 0;
          this.progressStatus = 'exception';
        } else {
          console.error('下载失败:', error);
          this.handleDownloadError(error);
        }
      }
    },


    /** 处理下载进度 */
    handleDownloadProgress(progressEvent) {
      if (progressEvent.total) {
        // ZIP 文件流阶段
        const percentage = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        this.progressPercentage = Math.min(percentage, 99);

        const elapsed = Date.now() - this.downloadStartTime;
        if (elapsed > 0) {
          this.downloadSpeed = progressEvent.loaded * 1000 / elapsed;
          this.progressText = `${this.formatBytes(progressEvent.loaded)} / ${this.formatBytes(progressEvent.total)}`;
        }
      } else {
        // 后端处理文件阶段（无进度）

        // ⭐⭐ 1. 下载中保证 currentItem 不超过总数
        if (this.totalItems > 0) {
          this.currentItem = Math.min(this.currentItem + 1, this.totalItems);
        }

        // ⭐ 2. 百分比始终不超过 100
        this.progressPercentage = Math.min(
          Math.round((this.currentItem / this.totalItems) * 100),
          100
        );

        this.progressText = `处理中：${this.currentItem}/${this.totalItems}`;
      }
    },


    /** 处理下载完成 */
    handleDownloadComplete() {
      // ⭐⭐ 2. 下载完成时补齐
      this.currentItem = this.totalItems;
      this.progressPercentage = 100;

      this.progressText = '下载完成';
      this.progressStatus = 'success';
      this.downloadComplete = true;
      this.isExporting = false;
      this.downloadSpeed = 0;

      this.$message({
        message: '下载完成！',
        type: 'success',
        duration: 3000
      });
    },


    /** 处理下载错误 */
    handleDownloadError(error) {
      console.error('下载失败:', error);

      if (this.retryCount < this.maxRetries) {
        this.retryCount++;
        this.progressText = `下载失败，正在重试 (${this.retryCount}/${this.maxRetries})...`;
        this.progressStatus = 'warning';

        // 3秒后重试
        setTimeout(() => {
          this.handleBulkDownload();
        }, 3000);
      } else {
        this.progressText = '下载失败，请重试';
        this.progressStatus = 'exception';
        this.isExporting = false;
        this.$message.error('下载失败: ' + (error.message || '未知错误'));
      }
    },

    /** 取消下载 */
    cancelDownload() {
      if (this.downloadController) {
        this.downloadController.abort();
      }
      this.isExporting = false;
      this.showProgress = false;
      this.$message.info('下载已取消');
    },

    /** 清除进度显示 */
    clearProgress() {
      this.showProgress = false;
      this.downloadComplete = false;
      this.progressPercentage = 0;
      this.currentItem = 0;
      this.totalItems = 0;
      this.downloadSpeed = 0;
      this.progressStatus = null;
      this.currentFileName = '';
    },

    /** 格式化字节大小 */
    formatBytes(bytes, decimals = 2) {
      if (bytes === 0) return '0 Bytes';
      const k = 1024;
      const dm = decimals < 0 ? 0 : decimals;
      const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
    },

    /** 单文件下载 */
    async downloadSingleFile(payload, fileName) {
      try {
        this.isExporting = true;

        const response = await request({
          url: '/material/bm_report/downloadSingle',
          method: 'post',
          data: payload,
          responseType: 'blob'
        });

        const blob = new Blob([response]);
        const downloadUrl = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = downloadUrl;
        link.download = fileName;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        window.URL.revokeObjectURL(downloadUrl);

        this.$message.success('下载成功！');

      } catch (error) {
        console.error('下载失败:', error);
        this.$message.error('下载失败');
      } finally {
        this.isExporting = false;
      }
    },
  }
};
</script>

<style lang="scss" scoped>
.uploadImg {
  padding-top: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.deviceCode {
  margin-top: 10px;
  padding-bottom: 20px;
  font-size: 18px;
}

::v-deep.el-table .fixed-width .el-button--mini {
  width: 60px !important;
  margin-bottom: 10px;
}

//隐藏图片上传框的css
::v-deep.disabled {
  .el-upload--picture-card {
    display: none;
  }
}

/* 按钮样式优化 */
.el-button {
  transition: all 0.3s ease;
}

.el-button:disabled {
  background-color: #f5f7fa;
  border-color: #e4e7ed;
  color: #c0c4cc;
  cursor: not-allowed;
}

.el-button--mini {
  padding: 7px 15px;
}

/* 下载按钮激活状态 */
.el-button:not(:disabled):hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
}

.el-button--primary:not(:disabled) {
  background-color: #409eff;
  border-color: #409eff;
}

/* 下载按钮加载状态 */
.el-button.is-loading {
  position: relative;
  pointer-events: none;
}

.el-button.is-loading:before {
  content: '';
  position: absolute;
  left: -1px;
  top: -1px;
  right: -1px;
  bottom: -1px;
  border-radius: inherit;
  background-color: rgba(255, 255, 255, 0.35);
}

/* 进度条容器样式 */
.progress-container {
  margin: 20px 0;
  padding: 20px;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  background-color: #f9f9f9;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  animation: fadeIn 0.3s ease;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.progress-info {
  margin-top: 15px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
}

.progress-text {
  font-size: 14px;
  color: #333;
  font-weight: 500;
}

.progress-detail {
  font-size: 12px;
  color: #666;
}

.progress-speed {
  font-size: 12px;
  color: #409eff;
  font-weight: 500;
}

.progress-actions {
  margin-top: 15px;
  display: flex;
  justify-content: center;
  gap: 10px;
}

/* Element UI Progress 自定义样式 */
::v-deep .el-progress-bar__inner {
  background: linear-gradient(90deg, #409eff 0%, #67c23a 100%);
  transition: width 0.3s ease;
}

::v-deep .el-progress-bar__innerText {
  color: #fff;
  font-weight: bold;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
}

/* 响应式调整 */
@media (max-width: 768px) {
  .progress-container {
    padding: 15px;
    margin: 15px 0;
  }

  .progress-text {
    font-size: 13px;
  }

  .progress-detail,
  .progress-speed {
    font-size: 11px;
  }

  .el-button--mini {
    min-width: 80px;
    padding: 5px 12px;
    font-size: 12px;
  }
}

/* 表格复选框高亮 */
::v-deep .el-table__row.selected-row {
  background-color: #f0f9ff;
}

::v-deep .el-table__row:hover {
  background-color: #f5f7fa;
}

/* 复选框样式修复 */
::v-deep .el-table .el-checkbox__input.is-checked .el-checkbox__inner {
  background-color: #409eff;
  border-color: #409eff;
}

::v-deep .el-table .el-checkbox__input.is-indeterminate .el-checkbox__inner {
  background-color: #409eff;
  border-color: #409eff;
}
</style>
