<template>
  <div v-if="isInited" class="page-exam-question-box">
    <van-nav-bar title="考试" />
    <!-- 倒计时 -->
    <div class="exam-question-countdown">
      <span>剩余考试时间：{{ timeDiff }}</span>
    </div>
    <!-- 题序盒子 -->
    <div class="exam-question-list">
      <!-- 辅助间隙，样式问题 -->
      <div class="exam-question-start">st</div>
      <!-- 题序 -->
      <div
        :class="{
          'exam-question-item': true,
          'exam-question-item-on': answerIndex === index,
          'exam-question-item-down': examQuestionList[index].userAnswer.length,
        }"
        v-for="(item, index) in examQuestionList"
        :key="index"
        @click="handleExamQuestionItemFun(item, index)"
      >
        <div>{{ index + 1 }}</div>
      </div>
      <!-- 辅助间隙，样式问题 -->
      <div class="exam-question-end">en</div>
    </div>
    <!-- 题目卡片 -->
    <div class="exam-question-div">
      <div class="exam-question-card">
        <!-- 标题、分数、题页 -->
        <div v-if="examQuestionList.length" class="exam-question-head">
          <div class="exam-question-head-left">
            <div class="exam-question-head-left-icon"></div>
            <div class="exam-question-head-left-txt">
              {{ examQuestionList[answerIndex].typeTxt || "undefind" }}
            </div>
            <span class="exam-question-head-left-txt"
              >{{ examQuestionList[answerIndex].grade || "undefind" }} 分</span
            >
          </div>
          <div class="exam-question-head-right">
            <span class="exam-question-head-right-now">{{
              answerIndex + 1
            }}</span>
            <span>/</span>
            <span>{{ examQuestionList.length }}</span>
          </div>
        </div>
        <!-- 描述 -->
        <div v-if="examQuestionList.length" class="exam-question-describe">
          {{
            examQuestionList[answerIndex].questionContent ||
            examQuestionList[answerIndex].content
          }}
        </div>
        <!-- 答题列表 -->
        <!-- 单选题、多选题的选项区域 -->
        <div
          v-if="
            examQuestionList.length &&
            (examQuestionList[answerIndex].type === questionType.singleChoice ||
              examQuestionList[answerIndex].type ===
                questionType.multipleChoice)
          "
          class="exam-question-options"
        >
          <div
            v-for="(item, index) in examQuestionList[answerIndex].answers"
            :key="index"
            :class="{
              'exam-question-options-item': true,
              'exam-question-options-item-checked': answerValue.includes(item),
            }"
            @click="handleExamQuestionOptionsItemFun(item)"
          >
            {{ formatQuestionIndex(index) }}. {{ item }}
          </div>
        </div>
        <!-- 填空题的答题区域 -->
        <div
          v-if="
            examQuestionList.length &&
            examQuestionList[answerIndex].type === questionType.gapFilling
          "
          class="exam-question-gapFilling"
        >
          <textarea
            v-for="(item, index) in examQuestionList[answerIndex]
              .questionInputNum"
            :key="index"
            :ref="'questionInputRef' + index"
            v-model="inputValue[index]"
            maxlength="200"
            rows="1"
            @change="handleExamQuestionOptionsItemFun(inputValue, index)"
          />
        </div>
        <div class="exam-question-button-box">
          <van-button
            class="exam-question-button"
            type="primary"
            color="#0088e9"
            @click="handleSureFun"
            >确定</van-button
          >
          <van-button
            v-if="answerIndex + 1 === examQuestionList.length"
            class="exam-question-button"
            type="primary"
            color="#0088e9"
            :disabled="this.timeDiff === '00:00:00'"
            @click="handleSubmitFun"
            >交卷</van-button
          >
        </div>
      </div>
    </div>
    <!-- 拍照用 -->
    <input
      ref="uploadUserInput"
      type="file"
      name="file"
      accept="image/*"
      capture="user"
      @change="startTakePhotoFUn"
      style="display: none"
    />
  </div>
</template>

<script>
import { mapState } from "vuex";
import { Dialog, Toast } from "vant";
export default {
  name: "page-exam-item-doing",
  components: {},
  data() {
    return {
      questionType: {
        singleChoice: "DanXuan", // 单选题
        multipleChoice: "DuoXuan", // 多选题
        gapFilling: "TianKong" // 填空题
      }, // 试题类型
      examEndTimeSeconds: null, // 考试结束时的毫秒秒数
      examBeforeHalfEndTimeSeconds: null, // 开始考试一半时间的毫秒秒数
      startTimeSeconds: 0, // 当前开始考试的毫秒秒数时长
      timeDiff: "00:00:00", // 距离考试结束的时间
      interval: null, // 计时器
      examQuestionList: [], // 试题列表
      answerIndex: null, // 当前试题的下标索引
      answerValue: [], // 当前试题的所答
      inputValue: [], // 填空题时输入框的值
      isInited: false, // 是否已初始化完毕
      isOverHalfTime: false, // 是否已超过1/3的考试时间
      answerTime: {
        startTime: 0,
        endTime: 0
      } // 答题的开始、结束时间
    };
  },
  mounted() {
    // window.onbeforeunload = function() {
    //   return "正在考试，无法退出";
    // };
    // history.pushState(null, null, document.URL);
    // window.addEventListener("popstate", function() {
    //   Toast("正在考试中，无法退出");
    //   history.pushState(null, null, document.URL);
    // });

    this.initDataFun(); // 初始化数据信息
  },
  beforeDestroy() {
    console.log("in");
    if (this.interval) {
      clearInterval(this.interval); // 销毁前清空计时器
    }
  },
  watch: {},
  computed: {
    ...mapState({
      examItem: state => state.exam.examItem,
      userInfo: state => state.user.userInfo
    })
  },
  methods: {
    // 初始化数据信息
    initDataFun() {
      if (!this.examItem) {
        Dialog.alert({
          message: "试题信息有误，请重新进入当前页面",
          theme: "round-button"
        }).then(() => {
          // window.removeEventListener("popstate", function() {
          //   Toast("正在考试中，无法退出");
          //   history.pushState(null, null, document.URL);
          // });
          this.$router.back();
        });
        return;
      }
      this.examStartFun(); // 方法：开始考试
    },
    // 方法：开始考试
    examStartFun() {
      this.$store.commit("toggleLoading", true);
      //   let params = {
      //     type: "aaaaaaaa"
      //   };
      this.$_http
        .post(
          this.$pathParams(this.$_API.POST_JTXT_GET_EXAMS_START, {
            examId: this.examItem.id
          }),
          this.userInfo
          //   { params }
        )
        .then(res => {
          if (res.data) {
            let httpResultData = [];
            res.data.forEach((item, index) => {
              this.getExamQuestionsListFun(
                item,
                httpResultData,
                index === res.data.length - 1
              );
            });
          }
        })
        .catch(() => {
          this.$store.commit("toggleLoading", false);
        });
    },
    // 查询：试题信息
    async getExamQuestionsListFun(questionId, httpResultData, isLast) {
      this.$_http
        .get(
          this.$pathParams(this.$_API.GET_JTXT_GET_EXAMS_ONE_QUESTIONS_LIST, {
            questionId: questionId
          })
        )
        .then(res => {
          let resData = { ...res.data };
          httpResultData.push(this.setPersonDataFun(resData));
          if (isLast) {
            this.examQuestionList = httpResultData;
            this.handleExamQuestionItemFun(this.examQuestionList[0], 0); // 设置第一题开始
            this.isInited = true;
            this.getExamTimeFun(); // 获取：当前时间及考试限时
            this.setIntervalFun(); // 设置：倒计时定时器
            this.$store.commit("toggleLoading", false);
          }
        })
        .catch(() => {
          this.$store.commit("toggleLoading", false);
        });
    },
    // 方法：过滤试题的类型，添加用户作答的字段
    setPersonDataFun(httpResultDataItme) {
      let results = this.formatQuestionType(
        httpResultDataItme.type,
        httpResultDataItme.content
      );
      httpResultDataItme.typeTxt = results.typeTxt;
      httpResultDataItme.questionContent = results.questionContent;
      httpResultDataItme.questionInputNum = results.questionInputNum;
      httpResultDataItme.userAnswer = [];
      return httpResultDataItme;
    },
    // 获取：考试限定的时间点
    getExamTimeFun() {
      let tarTime = this.getTimeHoursMinuteSecondsTogetherFun(
        this.examItem.examTimeMins
      );
      let curTime = new Date();
      this.answerTime.startTime = curTime; // 赋值开始时间
      // 在当前时间curTime变量上加上小时
      let addHour = curTime.setHours(curTime.getHours() + tarTime.hours);
      curTime = new Date(addHour);
      // 在当前时间curTime变量上加上分钟
      let addMinute = new Date(
        curTime.setMinutes(curTime.getMinutes() + tarTime.minute)
      );
      curTime = new Date(addMinute);
      // 在当前时间curTime变量上加上秒
      let addSeconds = new Date(
        curTime.setSeconds(curTime.getSeconds() + tarTime.seconds + 1)
      );
      curTime = new Date(addSeconds);
      this.answerTime.endTime = curTime; // 赋值结束时间-标准时间格式
      this.examEndTimeSeconds = curTime.getTime(); // 赋值结束时间的毫秒秒数
    },
    // 方法：分别获取时 分 秒
    getTimeHoursMinuteSecondsTogetherFun(e) {
      let time = e;
      let len = time.split(":");
      if (len.length === 3) {
        let hour = time.split(":")[0];
        let min = time.split(":")[1];
        let sec = time.split(":")[2];
        return {
          hours: Number(hour),
          minute: Number(min),
          seconds: Number(sec)
        };
      }
      if (len.length === 2) {
        let min = time.split(":")[0];
        let sec = time.split(":")[1];
        return { hours: 0, minute: Number(min), seconds: Number(sec) };
      }
      if (len.length === 1) {
        let sec = time.split(":")[0];
        return { hours: 0, minute: 0, seconds: Number(sec) };
      }
      return { hours: 0, minute: 0, seconds: 0 };
    },
    // 设置：倒计时定时器
    setIntervalFun() {
      let _self = this;
      let isStart = false;
      // 获取距离目标时间的毫秒时间戳
      this.interval = setInterval(() => {
        let curTime = Date.now(); // 获取当前时间的毫秒时间戳
        if (!isStart) {
          this.examBeforeHalfEndTimeSeconds = this.examEndTimeSeconds - curTime; // 获取当前开始考试的时间的毫秒秒数
          console.log(
            "examBeforeHalfEndTimeSeconds：",
            this.examBeforeHalfEndTimeSeconds
          );
          isStart = true;
        }
        let diffTime = this.examEndTimeSeconds - curTime; // 计算出当前时间距离目标时间的时间差
        // 判断倒计时是否完成，成立则清除定时器，关闭函数执行
        if (diffTime <= 0) {
          Dialog.close(); // 关闭弹框提示框
          clearInterval(_self.interval);
          _self.timeDiff = "00:00:00";
          this.examsEndFun(true); // 自动交卷
          return;
        }
        this.startTimeSeconds = this.startTimeSeconds + 1000; // 新增开始进行了考试的时长
        console.log(this.startTimeSeconds);
        if (
          this.examBeforeHalfEndTimeSeconds / 2 > diffTime &&
          !this.isOverHalfTime
        ) {
          console.log("超过一半考试时间了");
          // this.$nextTick(() => {
          //   this.$refs.uploadUserInput.click(); // 调用拍照工具
          // });
          this.isOverHalfTime = true;
        }
        let hours = Math.floor(diffTime / (1000 * 60 * 60));
        let minutes = Math.floor(
          (diffTime - hours * 60 * 60 * 1000) / (1000 * 60)
        );
        let seconds = Math.floor(
          (diffTime - hours * 60 * 60 * 1000 - minutes * 60 * 1000) / 1000
        );
        let timeDiff = zero(hours) + ":" + zero(minutes) + ":" + zero(seconds);
        _self.timeDiff = timeDiff;
        // 数字补零
        function zero(num) {
          return num < 10 ? "0" + num : num;
        }
      }, 1000);
    },
    // 方法：过滤试题的类型、填空题的题目、填空题的回答框个数
    formatQuestionType(type, content) {
      let typeTxt = "";
      let questionContent = "";
      let questionInputNum = 0;
      switch (type) {
        case this.questionType.singleChoice:
          typeTxt = "单选题";
          break;
        case this.questionType.multipleChoice:
          typeTxt = "多选题";
          break;
        case this.questionType.gapFilling:
          typeTxt = "填空题";
          console.log(content);
          questionInputNum = this.getPlaceholderCount(content);
          questionContent = content.replace("$PH$", "()");
          console.log(questionContent, questionInputNum);
          break;
        default:
          break;
      }
      return {
        typeTxt: typeTxt,
        questionContent: questionContent,
        questionInputNum: questionInputNum
      };
    },
    // 方法：统计字符串中包含的特定字符个数
    getPlaceholderCount(strSource) {
      // 统计字符串中包含{}或{xxXX}的个数
      let thisCount = 0;
      strSource.replace("$PH$", function(m, i) {
        // m为找到的{xx}元素、i为索引
        thisCount++;
      });
      return thisCount;
    },
    // 操作：点击了某个题序
    handleExamQuestionItemFun(item, index) {
      if (this.answerIndex === index || !this.examQuestionList.length) {
        return;
      }
      this.answerIndex = index;
      switch (item.type) {
        case this.questionType.singleChoice:
        case this.questionType.multipleChoice:
          this.answerValue = [...new Set(item.userAnswer)];
          break;
        case this.questionType.gapFilling:
          this.answerValue = [...new Set(item.userAnswer)];
          this.inputValue = this.answerValue || [];
          break;
        default:
          break;
      }
    },
    // 操作：作答了某个选项
    handleExamQuestionOptionsItemFun(value, index) {
      let answerQuestionType = this.examQuestionList[this.answerIndex].type;
      switch (answerQuestionType) {
        // 单选题
        case this.questionType.singleChoice:
          this.answerValue = [value];
          break;
        // 多选题
        case this.questionType.multipleChoice:
          // 遍历所答的数组，看是否有重复的
          let repetitiveIndex = null;
          for (let i = 0; i < this.answerValue.length; i++) {
            let it = this.answerValue[i];
            if (value === it) {
              repetitiveIndex = i;
              break;
            }
          }
          // 如果有重复的就移除
          if (repetitiveIndex !== null) {
            this.answerValue.splice(repetitiveIndex, 1);
          } else {
            this.answerValue.push(value);
          }
          break;
        // 填空题
        case this.questionType.gapFilling:
          this.$refs["questionInputRef" + index][0].blur(); // 清除input的焦点
          this.answerValue = value;
          break;
        default:
          break;
      }
    },
    // 方法：下一题
    handleNextFun() {
      let nextIndex = this.answerIndex + 1;
      if (nextIndex >= this.examQuestionList.length) {
        return;
      }
      this.handleExamQuestionItemFun(
        this.examQuestionList[nextIndex],
        nextIndex
      );
    },
    // 操作：确定
    handleSureFun() {
      if (!this.examQuestionList.length) {
        return;
      }
      this.examQuestionList[this.answerIndex].userAnswer = this.answerValue;
      this.handleNextFun();
      // 若超过了了考试时间的1/3，则需要调用拍照
      if (this.isOverHalfTime) {
        this.$refs.uploadUserInput.click(); // 调用拍照工具
      }
    },
    // 操作：交卷 isAuto：true（时间到了的自动交卷）  false（手动交卷）
    handleSubmitFun() {
      let isAuto = this.timeDiff === "00:00:00";
      if (isAuto) {
        this.examsEndFun(isAuto);
      } else {
        Dialog.confirm({
          title: "温馨提示",
          message: "确认交卷？"
        })
          .then(() => {
            clearInterval(this.interval); // 销毁前清空计时器
            this.answerTime.endTime = new Date();
            this.examsEndFun(isAuto);
          })
          .catch(() => {});
      }
    },
    // 方法：结束考试
    examsEndFun(isAuto) {
      if (isAuto) {
        Dialog({ message: "考试时间已到，该考试已结束，并自动交卷" });
      }
      // window.removeEventListener("popstate", function() {
      //   Toast("正在考试中，无法退出");
      //   history.pushState(null, null, document.URL);
      // });
      this.$store.commit("toggleLoading", true);
      let grades = this.getUserExamAllPointsFun(); // 方法：计算成绩
      let answers = this.getUserExamAllAnswersFun(); // 方法：获取当前用户所有题目作答的答案
      let params = {
        userId: this.userInfo.id,
        examId: this.answerRecruitId,
        points: grades, // 成绩：分数
        startTime: this.answerTime.startTime,
        endTime: this.answerTime.endTime,
        userAnswers: answers
      };
      this.$_http
        .post(
          this.$pathParams(this.$_API.POST_JTXT_GET_EXAMS_END, {
            examId: this.examItem.id
          }),
          params
        )
        .then(res => {
          this.$store.commit("toggleLoading", false);
          this.$router.replace({
            name: "ExamResult",
            params: { grades: grades }
          });
        })
        .catch(() => {
          this.$store.commit("toggleLoading", false);
          Dialog.close();
          Dialog({ message: "结束考试异常，请联系系统管理员" });
          this.$router.back();
        });
    },
    // 方法：计算成绩
    getUserExamAllPointsFun() {
      let grades = 0;
      this.examQuestionList.forEach((item, index) => {
        let sureNum = 0;
        item.finalAnswer.forEach(it => {
          item.userAnswer.forEach(answerItem => {
            if (it === answerItem) {
              sureNum++;
            }
          });
        });
        if (sureNum === item.finalAnswer.length) {
          grades++; // 默认每题一分
        }
      });
      return grades;
    },
    // 方法：获取题目的答案
    getUserExamAllAnswersFun() {
      let answers = [];
      this.examQuestionList.forEach((item, index) => {
        // answers[index] = item.userAnswer;
        answers[index] = item.userAnswer.join("||");
      });
      return answers;
    },
    // 方法：开始考试
    startTakePhotoFUn(event) {
      let file = event.target.files[0]; // 获取文件对象
      if (file) {
        // let fd = new FormData(); // 构造formdata对象
        // fd.append("file", file); // 向formdata里面存放键值对存放图片文件
        // fd.append("userId", this.userInfo.id); // 向formdata里面存放用户的ID
        // console.log(fd);
        this.$router.replace({ name: "Exam" });
      } else {
        Toast("请完成拍照后，再进行考试");
      }
    }
  }
};
</script>

<style lang="scss" scoped>
@import "~@/styles/mixin";
.page-exam-question-box {
  width: 100%;
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  font-size: 0.6rem;
  .exam-question-countdown {
    height: 2rem;
    background-color: #f4f7ff;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding: 0 0.5rem;
    font-size: 0.65rem;
    span {
      color: #666;
    }
  }
  .exam-question-list {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: scroll;
    overflow-y: hidden;
    padding: 0.25rem 0;
    background-color: #fff;
    .exam-question-start {
      width: 0.2rem;
      height: 100%;
      color: #fff;
    }
    .exam-question-end {
      width: 1em;
      height: 1.5rem;
      color: #fff;
    }
    .exam-question-item {
      margin-left: 0.3rem;
      background-color: #f3f3f3;
      border: 1px solid transparent;
      > div {
        width: 1.25rem;
        height: 1.5rem;
        text-align: center;
        line-height: 1.5rem;
      }
    }
    .exam-question-item-down {
      background-color: #f4f7ff;
    }
    .exam-question-item-on {
      border-color: #0088e9;
      color: #0088e9;
    }
  }
  .exam-question-div {
    padding: 0.5rem 0.5rem;
    .exam-question-card {
      padding: 0.5rem 0.5rem;
      background-color: #fff;
      border-radius: 4px;
      box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
      .exam-question-head {
        display: flex;
        justify-content: space-between;
        align-items: center;
        flex-wrap: nowrap;
        border-bottom: 1px solid #0088e9;
        padding-bottom: 0.25rem;
        height: 1.25rem;
        font-size: 0.65rem;
        .exam-question-head-left {
          display: flex;
          align-items: center;
          flex-wrap: nowrap;
          .exam-question-head-left-icon {
            width: 0.25rem;
            height: 1rem;
            background-color: #0088e9;
          }
          .exam-question-head-left-txt {
            margin-left: 0.25rem;
            font-weight: bold;
          }
        }
        .exam-question-head-right {
          span {
            color: #666;
          }
          .exam-question-head-right-now {
            font-weight: bold;
            color: #000;
          }
        }
      }
      .exam-question-describe {
        padding: 0.5rem 0;
        font-size: 0.65rem;
      }
      .exam-question-options {
        .exam-question-options-item {
          width: 100%;
          padding: 0.5rem 0.25rem;
          background-color: #f3f3f3;
          margin-bottom: 0.5rem;
          border: 1px solid transparent;
        }
        .exam-question-options-item-checked {
          border-color: #0088e9;
          color: #0088e9;
        }
      }
      .exam-question-gapFilling {
        padding-top: 0.5rem;
        textarea {
          width: 100%;
          padding: 0.25rem 0.25rem;
          background-color: #f3f3f3;
          margin-bottom: 0.5rem;
          border: 1px solid transparent;
          &:active,
          &:focus {
            border-color: #0088e9;
          }
        }
      }
      .exam-question-button-box {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        .exam-question-button {
          width: 6rem;
          height: auto;
          padding: 0.5rem 0.5rem;
          font-size: 0.65rem;
          margin-top: 0.75rem;
        }
      }
    }
  }
}
</style>
