<template>
  <div :key="dialogKey">
    <el-dialog title="导出个性化错题手册" class="page_full_dialog" :visible.sync="showDialog" fullscreen height="100%">
      <div class="dialog_print_content">
        <div class="page_jg_20"></div>
        <div class="dialog_print_page">
          <div class="item_page">内容</div>
        </div>
        <div class="fixed_set_box">
          <div class="item_set">
            <el-radio-group v-model="radioVal">
              <el-radio :label="0">答案解析在卷底</el-radio>
              <el-radio :label="1">答案解析在每题后</el-radio>
            </el-radio-group>
          </div>
          <div class="item_set">
            <el-checkbox-group v-model="checkVal">
              <el-checkbox label="0">我的作答</el-checkbox>
              <el-checkbox label="1">答案解析</el-checkbox>
            </el-checkbox-group>
          </div>
        </div>
        <div class="dialog_close" @click="showDialog = false">关闭</div>
        <div class="dialog_print" @click="DownloadPdfs()">下载PDF文件</div>
      </div>
    </el-dialog>
    <div class="page_dialog">
      <el-dialog title="下载PDF" class="page_dialog" :visible.sync="showReportLoading" width="500px" top="15%">
        <div class="report_loading">
          <div class="report_loading_icon">
            <img src="@/assets/report/report_loading.png" />
          </div>
          <div class="report_loading_title">正在努力生成PDF中，请稍等...</div>
          <div class="report_loading_progress">
            <el-progress :text-inside="true" color="#2E64FA" text-color="#ffffff" :stroke-width="16"
              :percentage="targetProgress"></el-progress>
          </div>
        </div>
      </el-dialog>
    </div>
  </div>
</template>

<script>
import { jsPDF } from "jspdf";
import domtoimage from "dom-to-image";
export default {
  data() {
    return {
      showDialog: false, //是否显示弹窗
      tableData: [],
      progressInterval: null,
      total: 0,
      loading: null,
      radioVal: 0,
      checkVal: ['0', '1'], //默认值
      pageInfo: {
        //794*1123
        width: 794, //595
        height: 1123, //842
      }, //成绩小条比例配置
      showReportLoading: false, //成绩小条页加载图标
      reportLoadingProgress: 0,
      targetProgress: 0, //目标进度值
      dialogKey: 1,
    };
  },
  created() {
    this.GetSlipData(); //获取成绩小条
  },
  beforeDestroy() {
    // 组件销毁前清除定时器
    if (this.progressInterval) {
      clearInterval(this.progressInterval);
      this.progressInterval = null;
    }
  },
  methods: {
    //获取总分 成绩小条数据
    GetSlipData() {
      this.dialogKey += 1;
    },
    //导出所有pdf domtoimage的方式
    async DownloadPdfs() {
      this.showReportLoading = true;

      // 创建PDF对象，使用自定义纸张尺寸
      const pdf = new jsPDF("p", "pt", "a4"); //p 为纵向布局
      const pdfWidth = pdf.internal.pageSize.getWidth();
      const pdfHeight = pdf.internal.pageSize.getHeight();

      //获取所有的area_page 元素
      const elements = document.querySelectorAll(".item_page");

      let fillCount = 0; //完成数量
      let pageCount = elements.length; //总数量
      this.targetProgress = 0;
      let oneProgress = Math.round((1 / pageCount) * 100);
      this.StartProgress(0, oneProgress);

      console.log("开始导出", this.targetProgress);

      // 遍历每个页面数据
      for (const [pageIndex, element] of Array.from(elements).entries()) {
        // 确保页面元素存在并可见
        await this.$nextTick();
        if (element) {
          // 确保元素可见并已渲染
          // 确保元素可见并已渲染，并设置为横向排列样式
          element.style.visibility = "visible";
          element.offsetHeight; // 触发重排

          // 等待元素完全渲染
          await new Promise((resolve) => setTimeout(resolve, 100));

          // 使用 dom-to-image 生成图片
          const dataUrl = await domtoimage.toJpeg(element, {
            quality: 0.8, // 降低质量以减小文件大小
            // 获取完整尺寸
            width: element.scrollWidth * 2,
            height: element.scrollHeight * 2,
            // 提高画布分辨率以获得更清晰的图像
            canvasWidth: element.scrollWidth * 2,
            canvasHeight: element.scrollHeight * 2,
            style: {
              transform: "scale(2)",
              "transform-origin": "top left",
              "background-color": "#ffffff",
              overflow: "visible",
              "white-space": "normal",
              position: "relative",
              visibility: "visible",
            },
            bgcolor: "#ffffff",
          });

          // 获取图像属性并计算缩放比例
          const imgProps = pdf.getImageProperties(dataUrl);

          const imgWidth = imgProps.width;
          const imgHeight = imgProps.height;

          // 计算缩放比例（保持宽高比）
          const ratio = Math.min(pdfWidth / imgWidth, pdfHeight / imgHeight);
          const adjustWidth = imgWidth * ratio;
          const adjustHeight = imgHeight * ratio;

          // 居中放置图像
          const xPosition = (pdfWidth - adjustWidth) / 2;
          const yPosition = (pdfHeight - adjustHeight) / 2;

          // 如果不是第一页，添加新页面
          if (pageIndex > 0) {
            pdf.addPage();
          }
          pdf.addImage(
            dataUrl,
            "JPEG",
            xPosition,
            yPosition,
            adjustWidth,
            adjustHeight,
          );
          fillCount++;
          // console.log("打印当前完成数量", fillCount);

          // 更新进度
          const progress = Math.floor((fillCount / pageCount) * 100);
          const lastProgressprogress = progress - oneProgress;
          // if(this.targetProgress<progress)
          // {
          // this.targetProgress=progress;
          // }

          this.StartProgress(lastProgressprogress, progress);

          // 页面间短暂延迟
          // await new Promise(resolve => setTimeout(resolve, 50));
        }
      }

      // 保存PDF文件
      pdf.save(this.examName + "-" + this.subjectName + "-成绩小条.pdf");

      this.showReportLoading = false; //关闭加载loading
    },
    // 开始进度条数值变化  最大增加进度值 maxIncrement
    StartProgress(currentValue, targetValue) {
      console.log("开始进度动画，目标值:", targetValue);

      // 清除已存在的定时器
      if (this.progressInterval) {
        clearInterval(this.progressInterval);
        this.progressInterval = null;
      }

      // 获取当前进度值
      if (this.targetProgress < currentValue) {
        this.targetProgress = currentValue;
      }
      const targetProgress = targetValue;
      // 如果当前值大于等于目标值，则不需要动画（进度不能递减）
      if (this.targetProgress >= targetProgress) {
        console.log("当前进度已达到或超过目标进度，无需动画");
        return;
      }

      // 计算差值
      const difference = targetProgress - currentValue;
      console.log("差值:", difference);

      // 根据差值计算时间间隔（差值越大，时间间隔越小）
      // 这里设置时间间隔在50ms到100ms之间变化
      const minInterval = 50;
      const maxInterval = 500;
      // 限制差值在1-10范围内
      // 限制差值在1-10范围内
      const clampedDifference = Math.max(1, Math.min(difference, 10));

      // 计算时间间隔：差值1->500ms，差值10->50ms
      let interval =
        maxInterval -
        (clampedDifference - 1) * ((maxInterval - minInterval) / 9);

      // 将时间间隔调整为10的倍数
      interval = Math.round(interval / 10) * 10;

      // 确保时间间隔在有效范围内
      interval = Math.max(minInterval, Math.min(interval, maxInterval));
      // 计算每次增加的步长（差值越大，步长越大）
      const step = Math.max(1, Math.floor(difference / 5)) || 1;

      console.log(
        "动画参数：当前进度=",
        currentValue,
        "目标进度=",
        targetProgress,
        "差值=",
        difference,
        "时间间隔=",
        interval,
        "步长=",
        step,
      );

      // 创建新的定时器
      this.progressInterval = setInterval(() => {
        // 只能增加，不能减少
        this.targetProgress = Math.min(
          this.targetProgress + step,
          targetProgress,
        );
        console.log("进度更新:", this.targetProgress);

        // 如果达到目标值，清除定时器
        if (this.targetProgress >= targetProgress) {
          this.targetProgress = targetProgress;
          console.log("进度动画完成，最终值:", this.targetProgress);
          clearInterval(this.progressInterval);
          this.progressInterval = null;
        }
      }, interval);
    }
  },
};
</script>
<style scoped lang="scss">
.dialog_print_content {
  width: 100%;
  height: 100vh;
  background: #f0f4fb;
  position: relative;
  overflow: hidden;

  .dialog_print_page {
    width: 100%;
    height: calc(100% - 40px);
    margin: auto;
    overflow-y: auto;

    .item_page {
      width: 595px;
      height: 842px;
      margin: auto;
      background: #fff;
      border-radius: 0px 0px 0px 0px;
      padding: 20px;
      box-sizing: border-box;
      margin-bottom: 20px;
    }
  }

  .fixed_set_box {
    position: absolute;
    top: 20px;
    left: 20px;
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  .item_set {
    width: 160px;
    background-color: #ffffff;
    border-radius: 4px;
    padding: 12px 14px 12px 12px;
    box-sizing: border-box;

    :deep(.el-radio-group) {
      display: flex;
      flex-direction: column;
      gap: 8px;

      .el-radio {
        margin-right: 0;
        line-height: 22px;
        font-weight: 400;
        font-size: 14px;
        color: #333333;

        .el-radio__input {
          &.is-checked+.el-radio__label {
            color: #333333;
          }

          &.is-checked .el-radio__inner {
            border-color: #2e64fa;
            background-color: #ffff;
          }

          .el-radio__inner {
            width: 16px;
            height: 16px;
            border-color: rgba(0, 0, 0, 0.2);

            &::after {
              width: 10px;
              height: 10px;
              background-color: #2e64fa;
            }
          }
        }

        .el-radio__label {
          padding-left: 3px;
        }
      }
    }

    :deep(.el-checkbox-group) {
      display: flex;
      flex-direction: column;
      gap: 8px;

      .el-checkbox {
        font-weight: 400;
        font-size: 14px;
        color: #333333;
        margin-right: 0;

        .el-checkbox__input {
          .el-checkbox__inner {
            width: 16px;
            height: 16px;

            &::after {
              left: 5px;
            }
          }

          &.is-checked+.el-checkbox__label {
            color: #333333;
          }
        }

        .el-checkbox__label {
          padding-left: 3px;
          line-height: 22px;
        }
      }
    }
  }

  .dialog_close {
    position: absolute;
    right: 20px;
    top: 20px;
    width: 160px;
    height: 42px;
    background: rgba(245, 108, 108, 0.1);
    border-radius: 4px 4px 4px 4px;
    border: 1px solid #f56c6c;
    line-height: 42px;
    text-align: center;
    font-weight: 500;
    font-size: 14px;
    color: #f56c6c;
    cursor: pointer;
  }

  .dialog_print {
    position: absolute;
    right: 20px;
    top: 82px;
    width: 160px;
    height: 44px;
    background: #2e64fa;
    border-radius: 4px 4px 4px 4px;
    line-height: 42px;
    font-weight: 500;
    font-size: 14px;
    color: #ffffff;
    text-align: center;
    cursor: pointer;
  }
}
</style>
