<template>
  <div class="index">
    <div class="top">
      <p class="names">{{ form.name }}</p>

      <div class="count m-r-30">
        用时
        <span>{{ timeSum.day }}</span>天
        <span>{{ timeSum.hour }}</span>小时
        <span>{{ timeSum.minutes }}</span>分
        <span>{{ timeSum.seconds }}</span>秒
      </div>

      <img class="exit" src="@/assets/images/exit.svg" alt="" @click="close">
    </div>

    <div class="wrap">
      <div class="left">
        <h6 class="title">答题卡</h6>
        <div class="progress">
          <p class="fs-14">答题进度</p>
          <el-progress class="m-t-5 m-b-5" :percentage="progress" :format="progressFormat"></el-progress>
          <p>共{{ form.questionCount }}题，满分{{ form.score }}分</p>
        </div>
        <div v-if="form.paperOutline" class="type-wrap">
          <div v-for="(item, i) in form.paperOutline" :key="i" class="type">
            <h6 class="stem">{{ arabicToChinese(i + 1) }}、{{ item.outlineName }}（本题共{{ item.questionNum }}小题，共{{
              item.targetScore }}分）</h6>
            <ul class="serials">
              <template v-for="(ques, j) in item.examQuestions">
                <li
                  v-if="!sheetStatus || (sheetStatus === 1 && !ques.answered) || (sheetStatus === 2 && ques.answered) || (sheetStatus === 3 && ques.partAnswer) || (sheetStatus === 4 && ques.sign)"
                  :key="j" :class="{ answered: ques.answered, partAnswer: ques.partAnswer }"
                  @click="scrollToQues(ques, item)">
                  <img v-if="ques.sign" class="tag" src="@/assets/images/tag-active.svg" alt="">
                  {{ j + 1 }}
                </li>
              </template>
            </ul>
          </div>
        </div>
        <ul class="status-filter">
          <li :class="{ active: sheetStatus === 1 }" @click="filterStatus(1)">未作答</li>
          <li :class="{ active: sheetStatus === 2 }" @click="filterStatus(2)">已作答</li>
          <li :class="{ active: sheetStatus === 3 }" @click="filterStatus(3)">部分已作答</li>
          <li :class="{ active: sheetStatus === 4 }" @click="filterStatus(4)"><img class="tag"
              src="@/assets/images/tag-active.svg" alt=""> 已标记</li>
        </ul>
      </div>

      <ul v-if="form.paperOutline" class="ques-wrap" id="quesWrap">
        <li v-for="(item, i) in form.paperOutline" :key="i">
          <div class="outline">
            {{ arabicToChinese(i + 1) }}、{{ item.outlineName }}（本题共{{ item.questionNum }}小题，共{{
              item.targetScore }}分）
            <img :class="['shrink', { active: item.shrink }]" src="@/assets/images/shrink.svg" alt=""
              @click="item.shrink = !item.shrink">
          </div>
          <div :class="['ques', { hide: item.shrink }]">
            <div v-for="(ques, j) in item.examQuestions" :key="j"
              :class="['item', { disabled: !ques.status, del: ques.isDel, repeat: ques.repeat }]"
              :id="'ques' + ques.id">
              <div class="stem-wrap">
                <span class="label">{{ j + 1 }} / {{ item.questionNum }}</span>
                <span class="label">{{ item.questionTypeName }}</span>
                <div class="stem html-parse" :id="'stem' + ques.id" v-html="ques.stem"></div>
                <p v-if="item.questionType !== 'fill_blank'">（{{ ques.score }}分）</p>
                <img class="tag" :src="require('@/assets/images/' + (ques.sign ? 'tag-active' : 'tag') + '.svg')" alt=""
                  @click="ques.sign = ques.sign ? 0 : 1">
              </div>

              <!-- 单选、多选、判断的选项 -->
              <template
                v-if="item.questionType !== 'fill_blank' && item.questionType !== 'essay' && ques.questionAnswerVersionsList">
                <div v-for="(opt, j) in ques.questionAnswerVersionsList" :key="j" class="opt">
                  <el-checkbox v-if="item.questionType === 'multiple_choice'" v-model="opt.answer" :true-label="1"
                    @change="mulChange(ques)"></el-checkbox>
                  <el-radio v-else v-model="opt.answer" :true-label="1" :label="1"
                    @change="singleChange(ques, j)"></el-radio>

                  <span>{{ numToLetter(j) }}.&nbsp;</span>
                  <div class="text html-parse" v-html="opt.optionText"></div>
                </div>
              </template>
              <!-- 简答题需要展示题干文件及富文本 -->
              <template v-if="item.questionType === 'essay'">
                <div v-if="ques.stemAttachment" class="m-b-20">
                  <el-link class="m-r-10" type="primary" @click="preview(ques.stemAttachment)">{{ ques.fileName
                    || ques.stemAttachment
                    }}</el-link>
                  <el-button type="primary" size="mini" round
                    @click="download(ques.fileName || ques.stemAttachment, ques.stemAttachment)">下载</el-button>
                </div>
                <UeditorPlus v-if="ques.richTextStatus" :ref="'essayAnswer' + ques.id" v-model="ques.answer"
                  @ready="editor => essayAnswerReady(editor, ques)" />
                <div v-if="ques.allowAttachment" class="m-t-20">
                  <el-upload action="#">
                    <el-button size="small" type="primary">上传文件</el-button>
                  </el-upload>
                  <div v-if="ques.uploadInstructions" class="flex m-t-10 fs-12">
                    <span>上传要求说明：</span>
                    <div class="html-parse" v-html="ques.uploadInstructions"></div>
                  </div>
                </div>
              </template>
            </div>
          </div>
        </li>
      </ul>
    </div>

    <el-dialog title="图片预览" :visible.sync="previewImgVisible" width="800px" :close-on-click-modal="false">
      <el-image style="max-width: 100px; max-height: 100px" :src="previewImg" :preview-src-list="[previewImg]">
      </el-image>
    </el-dialog>
    <PdfDia :key="pdfVisible" :visible.sync="pdfVisible" :src.sync="pdfSrc" />
  </div>
</template>

<script>
import Util from '@/libs/util'
import Setting from "@/setting"
import QuesConst from '@/const/ques'
import TestPaperConst from '@/const/testPaper'
import _ from 'lodash'
import Oss from '@/components/upload/upload.js'
import Upload from '@/components/upload'
import UeditorPlus from '@/components/ueditorPlus'
import PdfDia from '@/components/pdf'

export default {
  components: {
    Upload, UeditorPlus, PdfDia
  },
  data () {
    return {
      questionTypes: QuesConst.questionTypes,
      numToLetter: Util.numToLetter,
      arabicToChinese: Util.arabicToChinese,
      id: +this.$route.query.id,
      entryTime: '',
      counterTimer: null, // 获取setInterval对象值
      timeSumVal: 0,
      // 用时
      timeSum: {
        day: 0,
        seconds: 0,
        minutes: 0,
        hour: 0,
      },
      totalAnswered: 0,
      progress: 0,
      sheetStatus: '',
      form: {
        questionCount: 0,
      },
      previewImgVisible: false,
      previewImg: '',
      pdfVisible: false,
      pdfSrc: '',
    };
  },
  mounted () {
    this.$once('hook:beforeDestroy', function () {
      clearInterval(this.counterTimer)
    })

    this.getPaper()
  },
  methods: {
    // 获取试卷详情
    async getPaper (now) {
      try {
        this.entryTime = await Util.getNow()
        const { id } = this
        if (id) {
          // 试卷详情
          const { examPaper } = await this.$get(this.api.examPaperDetails, { id })

          this.startCount()

          const r = examPaper
          const paper = r.paperOutline
          const types = this.questionTypes
          paper.map(e => {
            const type = e.questionType
            e.questionTypeName = types.find(n => n.id === type).name
            e.shrink = false
            e.examQuestions.map(n => {
              Object.assign(n, n.question)
              n.sign = 0
              const opts = n.questionAnswerVersionsList
              if (type !== 'fill_blank' && type !== 'essay' && opts) { // 选择题
                opts.map(m => {
                  m.answer = 0
                })
              } else if (type === 'fill_blank') { // 填空题
                n.stem = this.getQuesStem(n)
              } else { // 简答题
                n.answer = ''
                // 附件
                n.uploadList = []
              }
            })
          })
          this.form = r

          // 给填空题的每个空监听input事件，用以显示已作答状态
          this.$nextTick(() => {
            paper.map(e => {
              e.examQuestions.map(n => {
                if (e.questionType === 'fill_blank') {
                  const stem = document.querySelector(`#stem` + n.id)
                  if (stem) {
                    const inputs = stem.querySelectorAll('.fill-input')
                    if (inputs) {
                      for (const e of inputs) {
                        e.addEventListener('input', () => {
                          const answers = []
                          for (const e of inputs) {
                            e.value && answers.push(e.value)
                          }
                          n.answered = answers.length === inputs.length ? 1 : 0
                          n.partAnswer = answers.length && answers.length !== inputs.length ? 1 : 0
                        })
                      }
                    }
                  }
                }
              })
            })
            this.calcProgress()
          })
        }
      } catch (e) { }
    },
    // 计时器
    handleCounter (counterTime, isCount) {
      let leave1 = counterTime % (24 * 3600) //计算天数后剩余的毫秒数
      let leave2 = leave1 % 3600 //计算小时数后剩余的毫秒数
      let leave3 = leave2 % 60 //计算分钟数后剩余的毫秒数
      let day = Math.floor(counterTime / (24 * 3600)) //计算相差天数
      let hour = Math.floor(leave1 / 3600) //计算相差小时
      let minutes = Math.floor(leave2 / 60) //计算相差分钟
      let seconds = Math.round(leave3) //计算相差秒
      day = this.timeFormat(day)
      hour = this.timeFormat(hour)
      minutes = this.timeFormat(minutes)
      seconds = this.timeFormat(seconds)
      const count = this[isCount ? 'counterVal' : 'timeSum']
      count.day = day
      count.hour = hour
      count.minutes = minutes
      count.seconds = seconds
    },
    // 启动倒计时
    startCount () {
      clearInterval(this.counterTimer)
      this.counterTimer = setInterval(() => {
        this.timeSumVal >= 0 && this.handleCounter(this.timeSumVal++)
      }, 1000)
    },
    timeFormat (param) {
      return param < 10 ? '0' + param : param
    },
    // 计算答题进度
    calcProgress () {
      let answered = 0
      this.form.paperOutline.map(e => {
        answered += e.examQuestions.filter(n => n.answered).length
      })
      this.totalAnswered = answered
      this.progress = +(answered / this.form.questionCount * 100).toFixed(1)
    },
    // 答题进度格式
    progressFormat (e) {
      return this.totalAnswered + '/' + this.form.questionCount
    },
    scrollToSmooth (position, duration) {
      let startTime = Date.now()

      function scroll () {
        let now = Date.now()
        let progress = Math.min(1, (now - startTime) / duration)
        document.querySelector('#quesWrap').scrollTo(0, position * progress)

        if (progress < 1) {
          window.requestAnimationFrame(scroll)
        }
      }

      window.requestAnimationFrame(scroll)
    },
    // 答题卡题目点击滚动
    scrollToQues (e, item) {
      item.shrink = false
      const el = document.querySelector('#ques' + e.id)
      this.$nextTick(() => {
        el && this.scrollToSmooth(el.offsetTop - document.querySelector('#quesWrap').offsetTop, 200)
      })
    },
    // 答题卡筛选
    filterStatus (e) {
      this.sheetStatus = this.sheetStatus === e ? '' : e
    },
    // 处理题干显示
    getQuesStem (ques) {
      let { stem } = ques
      if (ques.questionType === 'fill_blank') { // 填空题
        let { fills } = ques

        const regex = /<span class="gapfilling-span" data-id="(.*?)">______<\/span>/g
        let match
        let index = 0 // 用于跟踪索引
        let result = stem

        while ((match = regex.exec(stem)) !== null) {
          const newInput = `<span contenteditable placeholder="(${index + 1})" class="fill-input">${fills && fills.length ? fills[index] : ''}</span>`
          result = result.replace(match[0], newInput)
          index++
        }
        return result
      } else {
        return stem
      }
    },
    // 单选题回调
    singleChange (ques, j) {
      ques.questionAnswerVersionsList.map(e => {
        e.answer = 0
      })
      ques.questionAnswerVersionsList[j].answer = 1

      ques.answered = 1
      this.calcProgress()
    },
    // 多选题回调
    mulChange (ques) {
      ques.answered = ques.questionAnswerVersionsList.some(e => e.answer)
      this.calcProgress()
    },

    // 简答题富文本加载完毕回调
    essayAnswerReady (editor, ques) {
      editor.ques = ques
      editor.addListener('contentChange', () => {
        ques.answered = editor.getContent() ? 1 : 0
        this.calcProgress()
      })
      ques.answer && editor.setContent(ques.answer)
    },
    // 预览附件
    preview (url) {
      const ext = url.split('.').pop()
      if (Util.isDoc(ext)) {
        window.open('https://view.officeapps.live.com/op/view.aspx?src=' + url)
      } else if (Util.isImg(ext)) {
        this.previewImgVisible = true
        this.previewImg = url
      } else if (ext === 'pdf') {
        this.pdfVisible = true
        this.pdfSrc = url
      }
    },
    // 下载附件
    download (name, url) {
      Util.downloadFile(name, url)
    },
    handleRemove (ques) {
      Oss.del(ques.attachmentUrl)
      ques.attachmentName = ''
      ques.attachmentUrl = ''
    },
    uploadSuccess (file, ques) {
      ques.attachmentName = file.name
      ques.attachmentUrl = file.url
    },
    // 解析富文本加载完毕回调
    answerAnalysisReady (editor) {
      this.answerAnalysis && editor.setContent(this.answerAnalysis)
    },
    close () {
      window.close()
    }
  }
};
</script>

<style lang="scss" scoped>
.top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 20px;
  color: #fff;
  background-color: #5786fc;

  .item {
    display: inline-flex;
    align-items: center;
  }

  .names {
    font-size: 18px;
    font-weight: 600;
  }

  .submit {
    width: 106px;
    font-size: 15px;
  }

  .exit {
    margin-left: 20px;
    cursor: pointer;

    &:hover {
      opacity: .9;
    }
  }
}

/deep/.wrap {
  display: flex;
  padding: 15px;

  .left {
    width: 300px;
    margin-right: 15px;
    background-color: #fff;

    .title {
      padding: 10px 0;
      font-size: 16px;
      text-align: center;
      color: #333;
    }

    .progress {
      padding: 10px;
      color: #5a5a5a;
      background-color: #d4e9ff;
    }

    .type-wrap {
      max-height: calc(100vh - 248px);
      padding: 10px;
      overflow: auto;

      .type {
        margin-bottom: 20px;
      }

      .stem {
        font-size: 15px;
        color: #333;
      }
    }

    .serials {
      display: flex;
      flex-wrap: wrap;
      margin-top: 5px;

      li {
        position: relative;
        width: 35px;
        margin: 7px 9px;
        font-size: 13px;
        text-align: center;
        line-height: 35px;
        color: #505050;
        border: 1px solid #d3d3d3;
        cursor: pointer;

        &:hover {
          opacity: .9;
        }

        &.answered {
          color: #fff;
          background-color: #66b2ff;
          border-color: #66b2ff;
        }

        &.partAnswer {
          border-color: #66b2ff;
        }
      }

      .tag {
        position: absolute;
        top: -2px;
        left: -4px;
      }
    }

    .status-filter {
      display: flex;
      justify-content: space-between;
      padding: 10px;
      border-top: 1px solid #e5e5e5;

      li {
        display: inline-flex;
        align-items: center;
        padding: 0 3px;
        font-size: 12px;
        color: #333;
        cursor: pointer;
        border: 1px solid transparent;

        &:not(:last-child):before {
          content: '';
          width: 13px;
          height: 13px;
          margin-right: 5px;
          border: 1px solid #ccc;
        }

        &:nth-child(2):before {
          background-color: #56aaff;
          border: 0;
        }

        &:nth-child(3):before {
          border-color: #56aaff;
        }

        &.active {
          font-weight: 600;
          color: #007eff;
          border-color: #007eff;

          &:last-child {
            color: #d81e06;
            border-color: #d81e06;
          }
        }
      }
    }
  }

  .ques-wrap {
    width: calc(100% - 315px);
    height: calc(100vh - 80px);
    background-color: #fff;
    overflow: auto;

    &>li {
      margin-bottom: 15px;
    }

    .outline {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 10px 15px;
      font-size: 15px;
      font-weight: 600;
      color: #333;
      background-color: #e8f0ff;
    }

    .shrink {
      cursor: pointer;
      transition: .5s;

      &.active {
        transform: rotate(180deg);
      }
    }

    .ques {
      max-height: none;
      padding: 15px;
      margin-bottom: 15px;
      transition: all 1.5s;
      overflow: hidden;

      &.hide {
        max-height: 10px;
      }
    }

    .item {
      position: relative;
      overflow: hidden;

      &:not(:last-child) {
        padding-bottom: 15px;
        margin-bottom: 15px;
        border-bottom: 1px dashed #e1e1e1;
      }


      &.disabled,
      &.del,
      &.repeat {
        border-color: #f00;

        &:after {
          content: '已 禁 用';
          position: absolute;
          top: 17px;
          right: -33px;
          padding: 5px 36px;
          font-size: 14px;
          color: #fff;
          background-color: #f00;
          transform: rotate(45deg);
          opacity: .6;
        }
      }

      &.del {
        &:after {
          content: '已 删 除';
        }
      }

      &.repeat {
        border-color: #ff962a;

        &:after {
          content: '存在重复题';
          background-color: #ff962a;
        }
      }
    }


    .stem-wrap {
      display: flex;
      align-items: baseline;
      margin-bottom: 10px;
    }

    .tag {
      margin-left: 10px;
      cursor: pointer;

      &:hover {
        opacity: .9;
      }
    }

    .label {
      padding: 3px 5px;
      margin-right: 10px;
      font-size: 12px;
      line-height: 1;
      color: $main-color;
      white-space: nowrap;
      border: 1px solid;
      border-radius: 2px;
    }

    .stem {
      max-width: calc(100% - 191px);
    }

    img {
      max-width: 100%;
    }

    .fill-input {
      position: relative;
      display: inline;
      min-width: 50px;
      height: 28px;
      padding: 3px;
      margin: 0 10px;
      font-size: 14px;
      line-height: 28px;
      color: #333;
      border: 0;
      border-bottom: 1px solid #DCDEE0;
      outline: none;

      &:empty {
        display: inline-block;
        width: 3em;
      }
    }

    .opt {
      display: flex;
      flex-wrap: wrap;
      align-items: baseline;
      padding-left: 10px;
      margin-bottom: 5px;
      font-size: 14px;
      color: #707070;
      line-height: 1.6;

      .el-radio,
      .el-checkbox {
        margin-right: 15px;
      }

      .el-radio__label {
        display: none;
      }

      .text {
        max-width: calc(100% - 48px);
      }
    }
  }
}
</style>