<template>
  <div class="question-import-edit">
    <el-dialog
      custom-class="question-import-edit-dialog"
      :visible.sync="modalIsShow"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      append-to-body
      fullscreen
      destroy-on-close
      :show-close="false"
      @opened="visibleChange"
      @closed="initData"
    >
      <el-dialog
        title="录入说明"
        :visible.sync="showIframeDialog"
        append-to-body
        width="900px"
        top="30px"
      >
        <div
          style="width: 100%; height: calc(100vh - 250px); overflow: auto"
          id="doc-box"
        ></div>
        <span slot="footer" class="dialog-footer">
          <el-button type="primary" @click="showIframeDialog = false"
            >关闭</el-button
          >
        </span>
      </el-dialog>
      <div slot="title" class="box-justify">
        <div>
          <h2>文件上传</h2>
        </div>
        <div style="display: flex; align-items: center">
          <upload-button
            btn-content="重新上传文件"
            btn-icon="icon icon-import"
            :disabled="loading"
            :upload-data="uploadData"
            :upload-url="uploadUrl"
            :format="importFileTypes"
            @valid-error="validError"
            @upload-success="uploaded"
            :auto-upload="false"
          ></upload-button>
          <el-button
            style="margin-left: 10px"
            size="small"
            type="danger"
            @click="cancel"
            >返回</el-button
          >
        </div>
      </div>
      <div class="qe-body">
        <div class="qe-part qe-part-edit">
          <div class="qe-part-main">
            <div class="qe-part-head">
              <h3>
                题目编辑
                <div
                  style="color: #9a9dab; font-size: 14px; font-weight: normal"
                >
                  <i class="icon icon-tips"></i>
                  提示：若识别有误，可点击左侧题目按格式进行修改后重新识别
                </div>
              </h3>
              <el-button
                size="small"
                type="primary"
                plain
                icon="icon icon-edit-warning"
                @click="showDocx"
                >录入说明</el-button
              >
            </div>
            <div class="qe-part-body">
              <div id="qe-part-richtext-list">
                <div
                  class="qe-part-richtext"
                  v-for="(richJsonItem, rindex) in paperRichJsonGroup"
                  :key="rindex"
                >
                  <v-editor
                    ref="RichTextEditor"
                    :value="richJsonItem"
                    :show-menu="false"
                    custom-emit-input
                    :custom-render-action="renderRichText"
                    :custom-tojson-action="richTextToJSON"
                    @focus="() => richTextFocus(richJsonItem)"
                  ></v-editor>
                  <div
                    v-if="richJsonItem.exceptions.length"
                    class="qe-part-richtext-error"
                  >
                    <p
                      class="tips-info tips-error"
                      v-for="(exception, index) in richJsonItem.exceptions"
                      :key="index"
                      @click="highLightErrorText(exception)"
                      :class="{ hide: inHasIgnore(exception.indexs) }"
                    >
                      {{ exception.message }}
                    </p>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="qe-part qe-part-view">
          <div class="qe-part-main">
            <div class="qe-part-head">
              <h3>题目阅览</h3>
              <div>
                <el-button
                  size="small"
                  type="primary"
                  plain
                  icon="icon icon-export-answer"
                  @click="toImportAnswer"
                  >导入答案属性</el-button
                >
                <el-button
                  size="small"
                  type="primary"
                  icon="icon icon-save-white"
                  :loading="loading"
                  :disabled="!paperData.length || hasErrorTips"
                  @click="confirm"
                  >识别无误，加入题库</el-button
                >
              </div>
            </div>
            <div id="qe-part-paper" class="qe-part-body">
              <question-import-paper-edit
                v-if="paperData.length"
                ref="QuestionImportPaperEdit"
                :key="questionKey"
                :paper="paperData"
                :course-id="data.importData.courseId"
              ></question-import-paper-edit>
            </div>
          </div>
        </div>
        <div class="qe-middle">
          <div class="qe-middle-arrow"></div>
          <el-button
            size="small"
            type="primary"
            :loading="loading"
            @click="toParse"
            >识别</el-button
          >
        </div>
      </div>
    </el-dialog>

    <!-- 上传答案文件 -->
    <import-file-dialog
      ref="ImportAnswerDialog"
      dialog-title="导入答案"
      :template-download-handle="answerTemplateDownload"
      :upload-url="uploadAnswerUrl"
      :upload-data="uploadAnswerData"
      add-file-param="dataFile"
      @uploaded="answerUploaded"
    ></import-file-dialog>
  </div>
</template>

<script>
// import paperRichTextJson from "../datas/paperRichText.json";
// import paperParseData from "../datas/paperParseData.json";

import { calcSum, deepCopy, objTypeOf, randomCode } from "@/plugins/utils";
import QuestionImportPaperEdit from "./QuestionImportPaperEdit.vue";
import UploadButton from "@/components/UploadButton.vue";
import { getRichTextAnswerPointCount, isAnEmptyRichText } from "@/utils/utils";
import {
  questionImportPaperSave,
  questionImportParseRichText,
  questionImportDownloadTemplate,
} from "../api";
import ImportFileDialog from "@/components/ImportFileDialog.vue";
import { QUESTION_API } from "@/constants/constants";
import { propertyNameQueryApi } from "@/modules/question/api";
import { downloadByApi } from "@/plugins/download";
import { richTextToJSON, renderRichText } from "./import-edit/richText";
import scrollMixins from "./import-edit/scrollMixins";
import timeMixin from "@/mixins/timeMixin";
import { renderAsync } from "docx-preview";

const questionInfoField = [
  "courseId",
  "difficulty",
  "quesProperties",
  "score",
  "publicity",
  "control",
  "answerAnalysis",
  "quesAnswer",
];

export default {
  name: "QuestionImportEdit",
  components: { QuestionImportPaperEdit, ImportFileDialog, UploadButton },
  mixins: [scrollMixins, timeMixin],
  computed: {
    hasErrorTips() {
      // return (this.paperRichJsonGroup || []).some((item) => {
      //   return item?.exceptions?.length;
      // });
      let detailInfo = this.paperData;
      if (!Array.isArray(detailInfo)) {
        return false;
      }
      return detailInfo.some((detail) => {
        return detail?.questions?.some((item) => {
          let questionExceptions = item.questionExceptions;
          let arr = item.ignoreOptionRepeat
            ? questionExceptions.filter(
                (v) => !v.cause.includes("选项内容相同")
              )
            : questionExceptions;
          if (!item.subQuestions?.length) {
            return !!arr.length;
          } else {
            return item.subQuestions.some((sub) => {
              let { questionExceptions = [] } = sub;
              let ar = sub.ignoreOptionRepeat
                ? questionExceptions.filter(
                    (v) => !v.cause.includes("选项内容相同")
                  )
                : questionExceptions;
              return !!ar.length;
            });
          }
        });
      });
    },
  },
  props: {
    data: {
      type: Object,
      default() {
        return {
          richText: { sections: [] },
          detailInfo: [],
          importData: {
            courseId: "",
            courseName: "",
            name: "",
            checkTotalScore: false,
            useOriginalPaper: false,
            totalScore: 0,
          },
        };
      },
    },
  },
  data() {
    return {
      ignoreRepeatExceptionIndexArr: [],
      modalIsShow: false,
      loading: false,
      questionKey: "",
      paperData: [],
      paperRichJson: { sections: [] },
      paperRichJsonGroup: [],
      richTextToJSON,
      renderRichText,
      lastPaperScrollTop: 0,
      lastRichTextScrollTop: 0,
      richTextIndexList: [],
      scrollType: "",
      curException: null,
      // upload answer
      uploadAnswerUrl: `${QUESTION_API}/word/parse/import`,
      uploadAnswerData: {},
      // word upload
      importFileTypes: ["docx", "doc"],
      uploadData: {},
      uploadUrl: `${QUESTION_API}/word/parse/struct`,
      showIframeDialog: false,
    };
  },
  created() {
    this.$bus.on("markIgnoreRepeatQuestion", this.markIgnoreRepeat);
  },
  methods: {
    inHasIgnore(indexes) {
      return this.ignoreRepeatExceptionIndexArr.includes(indexes.toString());
    },
    markIgnoreRepeat(exceptionIndex, bool) {
      this.paperData.forEach((detail) => {
        detail.questions.forEach((question) => {
          if (
            question.questionExceptions?.length &&
            question.questionExceptions.find(
              (v) => v.exceptionIndex.toString() == exceptionIndex
            )
          ) {
            question.ignoreOptionRepeat = bool;
          }
          if (question.subQuestions?.length) {
            question.subQuestions.forEach((sub) => {
              if (
                sub.questionExceptions?.length &&
                sub.questionExceptions.find(
                  (v) => v.exceptionIndex.toString() == exceptionIndex
                )
              ) {
                sub.ignoreOptionRepeat = bool;
              }
            });
          }
        });
      });
      this.paperData = JSON.parse(JSON.stringify(this.paperData));
      this.paperRichJsonGroup = this.getRichTextGroup();
      this.ignoreRepeatExceptionIndexArr.push(exceptionIndex);
    },
    urlToBlob(url, callback) {
      let xhr = new XMLHttpRequest();
      xhr.open("GET", url, true);
      xhr.responseType = "blob";
      xhr.onload = function () {
        if (xhr.status == 200) {
          callback(xhr.response);
        }
      };
      xhr.send();
    },
    showDocx() {
      this.showIframeDialog = true;
      this.$nextTick(() => {
        this.urlToBlob("/admin/inputDesc.docx", (data) => {
          let box = document.getElementById("doc-box");
          renderAsync(data, box);
        });
      });
    },
    async visibleChange() {
      this.ignoreRepeatExceptionIndexArr = [];
      await this.getCourseProperty();

      // this.resetData({
      //   richText: paperRichTextJson,
      //   detailInfo: paperParseData,
      // });
      this.resetData(this.data);

      this.$nextTick(() => {
        this.registScrollEvent();
      });
    },
    resetData({ richText, detailInfo }) {
      this.paperData = deepCopy(detailInfo);
      this.paperRichJson = this.buildRichText(deepCopy(richText));
      this.transformDataInfo();
      this.paperRichJsonGroup = this.getRichTextGroup();

      this.uploadData = { courseId: this.data.importData.courseId };
      this.questionKey = randomCode();

      this.$nextTick(() => {
        this.getRichTextIndexList();
      });
    },
    getRichTextIndexList() {
      const richTextListDom = document.getElementById("qe-part-richtext-list");
      const elPos = richTextListDom.getBoundingClientRect();
      let richTextIndexList = [];
      const richTextBodyDoms =
        richTextListDom.querySelectorAll(".v-editor-body");
      richTextBodyDoms.forEach((richTextBodyDom) => {
        richTextBodyDom.childNodes.forEach((sectionNode) => {
          const id = sectionNode.getAttribute("id");
          if (!id) return;
          if (
            sectionNode.className &&
            sectionNode.className.includes("section-error")
          )
            return;

          const index = id.replace("section-", "") * 1;
          const sectionPos = sectionNode.getBoundingClientRect();

          richTextIndexList.push([index, sectionPos.y - elPos.y]);
        });
      });
      this.richTextIndexList = richTextIndexList;
    },
    async getCourseProperty() {
      const res = await propertyNameQueryApi(this.data.importData.courseId, "");
      const optionList = res.data || [];
      window.sessionStorage.setItem(
        "coursePropertys",
        JSON.stringify({ optionList, courseId: this.data.importData.courseId })
      );
    },
    buildRichText(richText) {
      let nsections = [];
      richText.sections.forEach((section) => {
        nsections.push({
          ...section,
          attributes: { id: `section-${section.remark.index}` },
        });
      });
      return { sections: nsections };
    },
    transformDataInfo() {
      this.transformRichImg(this.paperRichJson);
      this.paperData.forEach((detail) => {
        detail.questions.forEach((question) => {
          this.transformQuestion(question);
          if (question.subQuestions && question.subQuestions.length) {
            question.subQuestions.forEach((subq) => {
              this.transformQuestion(subq);
            });
          }
        });
      });
    },
    transformQuestion(question) {
      this.transformRichImg(question.body);
      this.transformRichImg(question.answerRichTexts);
      if (question.options && question.options.length) {
        question.options.forEach((item) => {
          this.transformRichImg(item.body);
        });
      }
      question.quesAnswer = this.transformQuestionAnser(question.quesAnswer);
    },
    transformRichImg(richText) {
      if (isAnEmptyRichText(richText)) return;

      const rate = 96 / 600;
      richText.sections.forEach((section) => {
        section.blocks.forEach((block) => {
          if (block.type !== "image" || !block.param) return;
          block.param.width = block.param.width * rate;
          block.param.height = block.param.height * rate;
        });
      });
    },
    transformQuestionAnser(quesAnswer) {
      let qAnswer = null;
      try {
        qAnswer = quesAnswer ? JSON.parse(quesAnswer) : null;
      } catch (error) {
        console.log(error);
      }
      if (!qAnswer || objTypeOf(qAnswer) !== "array") return quesAnswer;

      qAnswer.forEach((item) => {
        this.transformRichImg(item);
      });
      return JSON.stringify(qAnswer);
    },
    getRichTextGroup() {
      let groupSetList = [];
      this.paperData.forEach((detail) => {
        groupSetList.push({
          id: randomCode(),
          indexs: detail.detailIndex,
        });
        detail.questions.forEach((question) => {
          groupSetList.push({
            id: randomCode(),
            indexs: question.integralIndex,
          });
          if (question.subQuestions && question.subQuestions.length) {
            question.subQuestions.forEach((subq) => {
              groupSetList.push({
                id: randomCode(),
                indexs: subq.integralIndex,
              });
            });
          }
        });
      });

      let groups = [];
      let curGroupId = 0;
      let curGroup = [];
      const findGroupId = (ind) => {
        let data = groupSetList.find((item) => item.indexs.includes(ind));
        return data ? data.id : null;
      };
      this.paperRichJson.sections.forEach((section) => {
        const sectionGroupId = findGroupId(section.remark.index);
        if (sectionGroupId !== curGroupId) {
          if (curGroup.length) {
            groups.push({ sections: curGroup, exceptions: [] });
            curGroup = [];
          }
        }
        curGroupId = sectionGroupId;
        curGroup.push(section);
      });
      if (curGroup.length) {
        groups.push({ sections: curGroup, exceptions: [] });
        curGroup = [];
      }

      const getExceptions = (sections) => {
        let cause = {};
        sections.forEach((section) => {
          if (section.remark.status) return;
          if (!cause[section.remark.cause]) {
            cause[section.remark.cause] = [];
          }
          cause[section.remark.cause].push(section.remark.index);
        });
        const causeList = Object.keys(cause).map((key) => {
          return {
            message: key,
            indexs: cause[key],
          };
        });
        causeList.sort((a, b) => a.indexs[0] - b.indexs[0]);
        return causeList;
      };

      groups.forEach((group) => {
        group.indexs = group.sections.map((item) => item.remark.index);
        group.exceptions = getExceptions(group.sections);
      });
      return groups;
    },
    highLightErrorText(exception) {
      if (this.curException) {
        this.curException.indexs.forEach((ind) => {
          const sectionDoms = document.querySelectorAll(`#section-${ind}`);
          if (!sectionDoms.length) return;
          sectionDoms.forEach((sectionDom) => {
            sectionDom.style = null;
          });
        });
      }
      this.clearSetTs();

      this.curException = exception;
      let firstSectionDom = null;
      exception.indexs.forEach((ind) => {
        const sectionDom = document.getElementById(`section-${ind}`);
        if (!sectionDom) return;
        if (!firstSectionDom) firstSectionDom = sectionDom;
        sectionDom.style.background = "#fef0f0";
      });

      if (!firstSectionDom) return;

      const richTextListDom = document.getElementById("qe-part-richtext-list");
      const elPos = richTextListDom.getBoundingClientRect();
      const sectionOffsetTop =
        firstSectionDom.getBoundingClientRect().y - elPos.y - 100;
      if (sectionOffsetTop < richTextListDom.parentNode.scrollTop) {
        richTextListDom.parentNode.scrollTop = sectionOffsetTop;
        this.scrollType = "rich-text";
        setTimeout(() => {
          this.scrollType = "";
        }, 100);
      }

      this.addSetTime(() => {
        this.curException.indexs.forEach((ind) => {
          const sectionDoms = document.querySelectorAll(`#section-${ind}`);
          if (!sectionDoms.length) return;
          sectionDoms.forEach((sectionDom) => {
            sectionDom.style = null;
          });
        });
        this.curException = null;
      }, 5000);
    },
    initData() {
      this.paperData = [];
      this.paperRichJson = { sections: [] };
      window.sessionStorage.removeItem("coursePropertys");
      this.$message.closeAll();
      this.removeScrollEvent();
    },
    cancel() {
      this.modalIsShow = false;
    },
    open() {
      this.modalIsShow = true;
    },
    getRichTextJsons() {
      let sections = [];
      this.$refs.RichTextEditor.forEach((item) => {
        const itemRichJson = item.emitJsonAction();
        sections.push(...itemRichJson.sections);
      });
      return { sections };
    },
    async toParse() {
      if (isAnEmptyRichText(this.paperRichJson)) {
        this.$message.error("请输入试卷内容！");
        return;
      }

      if (this.loading) return;
      this.loading = true;

      let richText = this.getRichTextJsons();
      const res = await questionImportParseRichText({
        richText,
        courseId: this.data.importData.courseId,
      }).catch(() => {});
      this.loading = false;
      if (!res) return;

      const cacheData = this.getCachePaperInfo(
        this.getImportPaperData(),
        questionInfoField
      );
      // console.log(cacheData);
      this.paperData = this.assignCachePaperData(
        res.data.detailInfo,
        cacheData
      );
      this.paperRichJson = this.buildRichText(deepCopy(res.data.richText));
      this.paperRichJsonGroup = this.getRichTextGroup();
      this.questionKey = randomCode();

      this.$nextTick(() => {
        this.getRichTextIndexList();
      });
    },
    getCachePaperInfo(paperData, cacheFields = []) {
      let cachePaperInfo = {};
      paperData.forEach((detail, dIndex) => {
        detail.questionInfo.forEach((question, qIndex) => {
          let info = {};
          let k = `${dIndex + 1}_${qIndex + 1}`;
          if (cacheFields.length) {
            cacheFields.forEach((field) => {
              info[field] = question[field];
            });
          } else {
            info = { ...question };
          }

          cachePaperInfo[k] = info;

          if (question.subQuestions && question.subQuestions.length) {
            question.subQuestions.forEach((subq, subqIndex) => {
              let info = {};
              let k = `${dIndex + 1}_${qIndex + 1}_${subqIndex + 1}`;
              if (cacheFields.length) {
                cacheFields.forEach((field) => {
                  info[field] = subq[field];
                });
              } else {
                info = { ...subq };
              }

              cachePaperInfo[k] = info;
            });
          }
        });
      });
      // console.log(cachePaperInfo);
      return cachePaperInfo;
    },
    assignCachePaperData(paperData, cacheData, mergeReverse = false) {
      return paperData.map((detail, dIndex) => {
        detail.questions = detail.questions.map((question, qIndex) => {
          let k = `${dIndex + 1}_${qIndex + 1}`;
          let nq = this.mergeObjData(
            question,
            cacheData[k] || {},
            mergeReverse
          );
          if (question.subQuestions && question.subQuestions.length) {
            nq.subQuestions = question.subQuestions.map((subq, subqIndex) => {
              let k = `${dIndex + 1}_${qIndex + 1}_${subqIndex + 1}`;
              return this.mergeObjData(subq, cacheData[k] || {}, mergeReverse);
            });
          }
          return nq;
        });
        return detail;
      });
    },
    isNull(val) {
      if (val) {
        if (val === "[]") return true;
        if (objTypeOf(val) === "array" && !val.length) return true;
      }
      return val === null || val === "" || val === undefined;
    },
    mergeObjData(targetObj, cacheObj, mergeReverse) {
      let data = { ...targetObj };
      Object.keys(cacheObj).forEach((k) => {
        if (mergeReverse) {
          data[k] = this.isNull(cacheObj[k]) ? targetObj[k] : cacheObj[k];
        } else {
          data[k] = this.isNull(targetObj[k]) ? cacheObj[k] : targetObj[k];
        }
      });
      return data;
    },
    getImportPaperData() {
      if (!this.$refs.QuestionImportPaperEdit) return [];
      let paperData = deepCopy(this.$refs.QuestionImportPaperEdit.getData());
      const transformFieldMap = { body: "quesBody", options: "quesOptions" };
      const fields = Object.keys(transformFieldMap);
      const course = {
        id: this.data.importData.courseId,
        name: this.data.importData.courseName,
      };

      const transformQuestion = (question) => {
        question.id = null;
        question.course = course;
        fields.forEach((field) => {
          question[transformFieldMap[field]] = question[field];
          delete question[field];
        });
        if (question.quesOptions && question.quesOptions.length) {
          question.quesOptions = question.quesOptions.map((option) => {
            option.optionBody = option.body;
            delete option.body;
            return option;
          });
        }
        return question;
      };

      const detailInfo = paperData.map((detail) => {
        const questionInfo = detail.questions.map((question) => {
          transformQuestion(question);

          if (question.subQuestions && question.subQuestions.length) {
            question.subQuestions = question.subQuestions.map((subq) =>
              transformQuestion(subq)
            );
            question.score = calcSum(
              question.subQuestions.map((q) => q.score || 0)
            );
          }
          return question;
        });

        return {
          name: detail.name,
          number: detail.number,
          questionCount: questionInfo.length,
          questionInfo,
          questionScore: detail.questionScore,
          totalScore: calcSum(questionInfo.map((q) => q.score || 0)),
        };
      });
      // console.log(detailInfo);
      return detailInfo;
    },
    checkImportPaperData(paperData) {
      this.$message.closeAll();

      // 题目内容校验
      const MATCHING_QUESTION = ["PARAGRAPH_MATCHING", "BANKED_CLOZE"];
      const SELECT_QUESTION = [
        "SINGLE_ANSWER_QUESTION",
        "MULTIPLE_ANSWER_QUESTION",
        ...MATCHING_QUESTION,
      ];
      const NESTED_QUESTION = [
        ...MATCHING_QUESTION,
        "READING_COMPREHENSION",
        "CLOZE",
        "LISTENING_QUESTION",
      ];
      const ALLOW_EMPTY_BODY_QUESTION = [
        "LISTENING_QUESTION",
        ...MATCHING_QUESTION,
      ];
      let errInfos = [];
      paperData.forEach((detail) => {
        detail.questionInfo.forEach((question) => {
          const { questionType, quesBody } = question;
          const questionTitle = `第${detail.number}大题第${question.number}小题`;
          let qErrInfo = [];
          // 题干
          if (
            !ALLOW_EMPTY_BODY_QUESTION.includes(questionType) &&
            (!quesBody || isAnEmptyRichText(quesBody))
          ) {
            qErrInfo.push(`没有题干`);
          }

          // 选项
          if (SELECT_QUESTION.includes(questionType)) {
            if (question.quesOptions.length < 2) {
              qErrInfo.push(`选项少于2个`);
            }
            if (
              question.quesOptions.some((option) =>
                isAnEmptyRichText(option.optionBody)
              )
            ) {
              qErrInfo.push(`有选择内容为空`);
            }
          }

          // 小题数
          if (
            NESTED_QUESTION.includes(questionType) &&
            !question.subQuestions.length
          ) {
            qErrInfo.push(`没有小题`);
          }

          if (qErrInfo.length) {
            errInfos.push(`${questionTitle}${qErrInfo.join("、")}`);
            qErrInfo = [];
          }

          // 完形填空
          if (questionType === "CLOZE") {
            const answerPointCount = getRichTextAnswerPointCount(quesBody);
            if (answerPointCount !== question.subQuestions.length) {
              errInfos.push(
                `第${detail.number}大题题干答题点数量与选项数不匹配`
              );
            }
            if (
              question.subQuestions.some(
                (q) => q.questionType !== "SINGLE_ANSWER_QUESTION"
              )
            ) {
              errInfos.push(`第${detail.number}大题存在不是单选题的子题`);
            }
          }

          // 听力题
          if (questionType === "LISTENING_QUESTION") {
            if (
              question.subQuestions.some(
                (q) => q.questionType !== "SINGLE_ANSWER_QUESTION"
              )
            ) {
              errInfos.push(`第${detail.number}大题存在不是单选题的子题`);
            }
          }

          // 选词填空、段落匹配，单用模式时校验输入答案是否重复
          if (
            MATCHING_QUESTION.includes(questionType) &&
            question.quesParam.matchingMode === 1
          ) {
            // 选词填空
            if (questionType === "BANKED_CLOZE") {
              const answerPointCount = getRichTextAnswerPointCount(quesBody);
              if (answerPointCount > question.quesOptions.length) {
                errInfos.push(`第${detail.number}大题题干答题点数量超过选项数`);
              }
            } else {
              if (question.subQuestions.length > question.quesOptions.length) {
                errInfos.push(`第${detail.number}大题小题数量超过选项数`);
              }
            }

            let selectedAnswer = [],
              errorQuestionIndexs = [];
            question.subQuestions.forEach((subq, sindex) => {
              if (selectedAnswer.includes(subq.quesAnswer)) {
                errorQuestionIndexs.push(`${question.number}-${sindex + 1}`);
              } else {
                if (subq.quesAnswer !== "[]")
                  selectedAnswer.push(subq.quesAnswer);
              }
            });
            if (errorQuestionIndexs.length) {
              errInfos.push(
                `第${
                  detail.number
                }大题${errorQuestionIndexs.join()}小题答案重复`
              );
            }
          }

          if (!NESTED_QUESTION.includes(questionType)) return;

          // 套题小题校验
          question.subQuestions.forEach((subq, sindex) => {
            const subqTitle = `第${detail.number}大题第${question.number}-${
              sindex + 1
            }小题`;
            if (
              questionType === "READING_COMPREHENSION" &&
              (!subq.quesBody || isAnEmptyRichText(subq.quesBody))
            ) {
              qErrInfo.push(`没有题干`);
            }
            if (
              SELECT_QUESTION.includes(subq.questionType) &&
              !MATCHING_QUESTION.includes(questionType)
            ) {
              if (subq.quesOptions.length < 2) {
                qErrInfo.push(`选项少于2个`);
              }
              if (
                subq.quesOptions.some((option) =>
                  isAnEmptyRichText(option.optionBody)
                )
              ) {
                qErrInfo.push(`有选择内容为空`);
              }
            }

            if (qErrInfo.length) {
              errInfos.push(`${subqTitle}${qErrInfo.join("、")}`);
              qErrInfo = [];
            }
          });
        });
      });
      if (errInfos.length) {
        this.$message({
          showClose: true,
          message: errInfos.join("。"),
          type: "error",
          duration: 0,
        });
        return;
      }

      if (!this.data.importData.useOriginalPaper) return true;

      let detailNumbers = paperData.map((detail) => detail.number);
      // 大题号重复性校验
      let repeatDetaiNumbers = [];
      let detailNums = [];
      for (let i = 0; i < detailNumbers.length; i++) {
        const num = detailNumbers[i];
        if (detailNums.includes(num)) {
          if (!repeatDetaiNumbers.includes(num)) repeatDetaiNumbers.push(num);
        } else {
          detailNums.push(num);
        }
      }
      if (repeatDetaiNumbers.length) {
        this.$message({
          showClose: true,
          message: `大题号${repeatDetaiNumbers.join("、")}重复`,
          type: "error",
          duration: 0,
        });
        return;
      }
      // 大题号连续性校验
      for (let i = 0; i < detailNumbers.length; i++) {
        if (detailNumbers[i] - 1 !== i) {
          this.$message({
            showClose: true,
            message: "大题号不连续",
            type: "error",
            duration: 0,
          });
          return;
        }
      }

      // 答案、分数校验
      let totalScore = calcSum(paperData.map((d) => d.totalScore));
      let errQuestions = [];
      paperData.forEach((detail) => {
        detail.questionInfo.forEach((question) => {
          if (question.subQuestions && question.subQuestions.length) {
            let subIndexs = [];
            question.subQuestions.forEach((subq, sind) => {
              if (!subq.score)
                subIndexs.push(question.number + "-" + (sind + 1));
            });
            if (subIndexs.length)
              errQuestions.push(
                `第${detail.number}大题第${subIndexs.join()}小题`
              );
          } else {
            if (!question.score) {
              errQuestions.push(
                `第${detail.number}大题第${question.number}小题`
              );
            }
          }
        });
      });
      if (errQuestions.length) {
        this.$message({
          showClose: true,
          message: `请设置如下试题的分值：${errQuestions.join("、")}。`,
          type: "error",
          duration: 0,
        });
        return;
      }

      if (
        this.data.importData.checkTotalScore &&
        totalScore !== this.data.importData.totalScore
      ) {
        this.$message({
          showClose: true,
          message: `试卷总分与导入设置的总分不一致！`,
          type: "error",
          duration: 0,
        });
        return;
      }

      return true;
    },
    async confirm() {
      const confirm = await this.$confirm("确认加入题库吗?", "提示", {
        type: "warning",
      }).catch(() => {});
      if (confirm !== "confirm") return;

      const detailInfo = this.getImportPaperData();
      if (!this.checkImportPaperData(detailInfo)) return;

      if (this.loading) return;
      this.loading = true;
      console.log("detailInfo", detailInfo);
      const res = await questionImportPaperSave({
        ...this.data.importData,
        detailInfo,
      }).catch(() => {});

      this.loading = false;
      if (!res) return;
      if (res.data) {
        this.$confirm(
          "系统正在计算试题情况，请在后续检查试题查重与试题审核数据。",
          "系统通知",
          {
            type: "warning",
          }
        );
      }
      this.$message.success("提交成功！");
      this.$emit("modified");
      this.cancel();
    },
    // 导入答案属性
    toImportAnswer() {
      const detailInfo = this.getImportPaperData();
      this.uploadAnswerData = {
        detailInfo: JSON.stringify(detailInfo),
        ...this.data.importData,
      };
      this.$refs.ImportAnswerDialog.open();
    },
    async answerTemplateDownload() {
      const detailInfo = this.getImportPaperData();

      const res = await downloadByApi(() => {
        return questionImportDownloadTemplate({
          detailInfo,
          ...this.data.importData,
        });
      }).catch((e) => {
        this.$message.error(e || "下载失败，请重新尝试！");
      });

      if (!res) return;
      this.$message.success("下载成功！");
    },
    answerUploaded(res) {
      const cacheData = this.getCachePaperInfo(
        res.data.detailInfo,
        questionInfoField
      );
      this.paperData = this.assignCachePaperData(
        this.paperData,
        cacheData,
        true
      );
      this.questionKey = randomCode();
    },
    // word upload
    uploaded(res) {
      this.$message.success("上传成功！");
      this.resetData({
        richText: res.data.richText,
        detailInfo: res.data.detailInfo,
      });
    },
    validError(error) {
      console.log("err", error);
      this.$message.error(error.message);
    },
    // rich test editor
    richTextFocus(richTextGroup) {
      this.$refs.QuestionImportPaperEdit.scrollToContentByIndex(
        richTextGroup.indexs
      );
      this.scrollType = "rich-text";
      setTimeout(() => {
        this.scrollType = "";
      }, 100);
    },
  },
};
</script>
