马宇豪
2024-08-29 893ff90c6e21fa3a5241a8ae9b33836037cd5912
pages/tabBar/firstPage/exam.vue
@@ -16,10 +16,10 @@
      </view>
    </view>
    <view class="m-p-15">
      <view class="timer" v-if="viewType == 1">
      <view class="timer" v-if="viewType == 1 && bank.examPaper.limited == 1">
        <u--image :showLoading="true" :src="sandPic" width="18px" height="18px"></u--image>
        <view class="timer-b">
          <span>开考时间:</span>
          <span>剩余时间:</span>
          <span>{{ formattedTime }}</span>
        </view>
      </view>
@@ -34,12 +34,11 @@
        </view>
        <view class="content">
          <u-checkbox-group
              v-if="currentQ.questionType==2"
              v-if="viewType == 1 && currentQ.questionType==2"
              v-model="currentB"
              placement="column"
              class="myRadio"
              iconPlacement="right"
              :disabled="viewType==1?false:true"
              @change="checkboxChange"
          >
            <u-checkbox
@@ -52,7 +51,28 @@
            >
            </u-checkbox>
          </u-checkbox-group>
          <u-radio-group v-model="currentA" class="myRadio" iconPlacement="right" placement="column" @change="groupChange" v-if="currentQ.questionType==1||currentQ.questionType==3" :disabled="viewType==1?false:true">
          <u-checkbox-group
              v-if="viewType == 2 && currentQ.questionType==2"
              v-model="currentB"
              placement="column"
              class="myRadio"
              iconPlacement="right"
              disabled
              @change="checkboxChange"
          >
            <u-checkbox
                :customStyle="{marginBottom: '15px'}"
                v-for="(item, index) in currentQ.content.items"
                :key="index"
                :label="item.prefix +':'+ item.content"
                :name="item.prefix"
                :class="{'picked': currentQ.answer.includes(item.prefix),'wronged': currentB.includes(item.prefix) && !currentQ.answer.includes(item.prefix)}"
            >
            </u-checkbox>
          </u-checkbox-group>
          <u-radio-group v-model="currentA" class="myRadio" iconPlacement="right" placement="column" @change="groupChange" v-if="viewType == 1 && (currentQ.questionType==1||currentQ.questionType==3)">
            <u-radio
                :customStyle="{marginBottom: '15px'}"
                v-for="(item, index) in currentQ.content.items"
@@ -66,12 +86,29 @@
            </u-radio>
          </u-radio-group>
          <u-button style="width: 80%;margin: 30px auto"
          <u-radio-group v-model="currentA" class="myRadio" iconPlacement="right" placement="column" @change="groupChange" v-if="viewType == 2 && (currentQ.questionType==1||currentQ.questionType==3)" disabled>
            <u-radio
                :customStyle="{marginBottom: '15px'}"
                v-for="(item, index) in currentQ.content.items"
                :key="index"
                shape="square"
                :label="item.prefix +':'+ item.content"
                :name="item.prefix"
                @change="radioChange"
                :class="{'picked': currentQ.answer == item.prefix, 'wronged': currentA == item.prefix && currentA != currentQ.answer}"
            >
            </u-radio>
          </u-radio-group>
          <u--textarea v-model="currentA" v-if="viewType == 1 &&(currentQ.questionType==4)" style="margin-bottom: 15px" :maxlength="-1" placeholder="请输入答案" autoHeight @focus="openAnswer"></u--textarea>
          <u--textarea v-model="currentA" v-if="viewType == 2 &&(currentQ.questionType==4)" :class="currentQ.answer == currentA?'pickedText':'wrongText'" style="margin-bottom: 15px" :maxlength="-1" placeholder="请输入答案" autoHeight disabled></u--textarea>
          <u-button style="width: 80%;margin: 5px auto 15px"
                    v-if="currentQ.questionType==2 && currentB.length>0 && viewType ==1"
                    type="primary" shape="circle" text="确认答案" @click="confirmAnswer"></u-button>
          <view class="answers" v-if="viewType == 2 && currentQ.studentAnswer && currentQ.studentAnswer.answer">
                    type="primary" shape="circle" text="确认答案" @click="confirmAnswer(2)"></u-button>
          <view class="answers" v-if="viewType == 2">
            <view>你的答案:
              <span :class="currentQ.answer == currentQ.studentAnswer.answer?'right':'wrong'">{{currentQ.studentAnswer.answer}}</span>
              <span :class="(currentQ.studentAnswer && currentQ.studentAnswer.answer) && (currentQ.answer == currentQ.studentAnswer.answer)?'right':'wrong'">{{(currentQ.studentAnswer && currentQ.studentAnswer.answer)?currentQ.studentAnswer.answer:'暂未作答'}}</span>
<!--              <span v-else :class="currentQ.answer == currentQ.studentAnswer.answer?'right':'wrong'">{{currentQ.studentAnswer.answer}}</span>-->
            </view>
            <view>正确答案:<span class="right">{{currentQ.answer}}</span></view>
@@ -85,11 +122,22 @@
      <u-button v-if="curTotalIndex < idList.length - 1" style="width: 30%" type="error" shape="circle" size="small" text="下一题" @click="nextQ"></u-button>
      <u-button v-if="curTotalIndex == idList.length - 1 && viewType == 2" style="width: 30%" type="primary" shape="circle" size="small" text="退出" @click="goBack"></u-button>
    </view>
    <u-popup :show="showPanel" :round="40" mode="right" @close="close" @open="open">
      <view class="panel">
    <u-popup :show="showPanel" :round="40" mode="bottom" @close="close" @open="open">
      <view class="panel" v-if="viewType == 1">
        <view :class="item.state==1?'right-a':''" v-for="(item,index) in idList" @click="toQuestion(item,index)">
          {{index + 1}}
        </view>
      </view>
      <view class="panel" v-else>
        <view :class="item.passed==1?'right-a':item.passed==0?'wrong-a':''" v-for="(item,index) in idList" @click="toQuestion(item,index)">
          {{index + 1}}
        </view>
      </view>
    </u-popup>
    <u-popup :show="showInput" :round="40" mode="bottom" @close="closeInput" @open="openInput">
      <view class="panelTwo">
        <u--textarea v-model="currentA" :maxlength="-1" placeholder="请输入答案"></u--textarea>
        <u-button shape="circle" type="primary" style="width: 80%;margin-top: 20px" text="确认答案" @click="confirmAnswer(1)"></u-button>
      </view>
    </u-popup>
   </view>
@@ -129,7 +177,9 @@
      startTime: null,
      elapsedTime: 0,
      timerInterval: null,
      showPanel: false
      showPanel: false,
      showInput: false,
      limitTime: 0
      }
   },
  onReady(){
@@ -140,25 +190,27 @@
    this.viewType = e.type && JSON.parse(decodeURIComponent(e.type))
    this.startTime = this.bank.startTime?this.bank.startTime:0
    this.getQuestionIds(this.bank.paperId)
    this.limitTime = this.bank.examPaper.limited == 1?this.bank.examPaper.limitTime:0
    if(this.viewType == 1){
      this.startTimer()
    }
   },
   onShow(){
   },
   mounted() {
    if(this.viewType == 1){
      this.startTimer()
    }
   },
  computed: {
    formattedTime() {
      const totalSeconds = Math.floor(this.elapsedTime / 1000);
      const totalSeconds = Math.floor((this.limitTime * 60) - this.elapsedTime / 1000);
      const hours = Math.floor(totalSeconds / 3600);
      const minutes = Math.floor((totalSeconds % 3600) / 60);
      const seconds = totalSeconds % 60;
      return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
    }
  },
   beforeUnmount() {
  },
@@ -174,7 +226,8 @@
      if(res.code == 200){
        let list = res.data || []
        if(list.length>0){
          t.idList = list.sort((a, b) => a.id - b.id)
          // t.idList = list.sort((a, b) => a.id - b.id)
          this.idList = list
        }else{
          t.idList = []
          uni.showToast({
@@ -186,13 +239,16 @@
        uni.$u.toast(res.message)
      }
    },
    openAnswer(){
      const t = this
      t.showInput = true
    },
    async toQuestion(item,index){
      this.curTotalIndex = index
      const curIdList = this.idList.slice(this.curTotalIndex,this.curTotalIndex + 20)
      this.currentId = this.idList[this.curTotalIndex].id
      await this.getQuestionsByIds(curIdList)
      this.currentQ = this.questionList[0]
      this.currentQ = this.questionList.find(i=>i.id == this.currentId)
      this.showAnswer()
      this.showPanel = false
    },
@@ -203,6 +259,13 @@
    close() {
      this.showPanel = false
      // console.log('close');
    },
    openInput() {
      // console.log('open');
    },
    closeInput(){
      this.showInput = false
    },
    updateTimer() {
@@ -219,12 +282,13 @@
      if(res.code == 200){
        let list = res.data || []
        if(list.length>0){
          this.idList = list.sort((a, b) => a.id - b.id)
          // this.idList = list.sort((a, b) => a.id - b.id)
          this.idList = list
          this.curTotalIndex = this.bank.questionId ? this.idList.findIndex(i=>i.id == this.bank.questionId):0
          const curIdList = this.idList.slice(this.curTotalIndex,this.curTotalIndex + 20)
          this.currentId = this.idList[this.curTotalIndex].id
          await this.getQuestionsByIds(curIdList)
          this.currentQ = this.questionList[0]
          this.currentQ = this.questionList.find(i=>i.id == this.currentId)
          this.showAnswer()
        }else{
          this.idList = []
@@ -243,12 +307,13 @@
      if(res.code == 200){
        let list = res.data || []
        if(list.length>0){
          this.idList = list.sort((a, b) => a - b)
          // this.idList = list.sort((a, b) => a - b)
          this.idList = list
          this.curTotalIndex = 0
          const curIdList = this.idList.slice(0,20)
          this.currentId = this.idList[0].id
          await this.getQuestionsByIds(curIdList)
          this.currentQ = this.questionList[0]
          this.currentQ = this.questionList.find(i=>i.id == this.currentId)
          this.showAnswer()
        }else{
          this.idList = []
@@ -279,14 +344,18 @@
    },
    groupChange(n) {
      if(this.currentA !== ''){
        this.confirmAnswer()
        this.confirmAnswer(1)
      }
    },
    radioChange(n) {
      console.log('radioChange', n);
    },
    confirmAnswer(){
    confirmAnswer(type){
      if(type == 1 && this.currentA == ''){
        uni.$u.toast('答案为空,请先作答')
        return
      }
      const data = {
        answer: this.currentQ.questionType==2?this.currentB.join(','):this.currentA,
        paperId: this.bank.paperId,
@@ -296,8 +365,16 @@
      postExamAnswer(data).then(res=>{
        if(res.code == 200){
          this.currentQ.passed = res.data
          // this.currentQ.exExerciseAnswer.passed = res.data.passed
          this.currentQ.studentAnswer.answer = res.data.answer
          if (!this.currentQ.studentAnswer) {
            Vue.set(this.currentQ, 'studentAnswer', {});
          }
          Vue.set(this.currentQ.studentAnswer, 'answer', data.answer);
          if(type == 2){
            this.nextQ()
          }
          if(this.showInput == true){
            this.showInput = false
          }
          // uni.$u.toast('答案已提交')
        }else{
          uni.$u.toast(res.message)
@@ -308,13 +385,13 @@
    prevQ(){
      if(this.curTotalIndex - 1>=0){
        this.curTotalIndex--
        if(this.curTotalIndex == 0){
          this.getQuestionsByIds([this.idList[0]]).then(()=>{
            // this.currentQ = this.questionList[this.questionList.length-1]
            this.$set(this, 'currentQ', this.questionList[this.questionList.length-1])
            this.showAnswer()
          })
        }else{
        // if(this.curTotalIndex == 0){
        //   this.getQuestionsByIds([this.idList[0]]).then(()=>{
        //     // this.currentQ = this.questionList[this.questionList.length-1]
        //     this.$set(this, 'currentQ', this.questionList[this.questionList.length-1])
        //     this.showAnswer()
        //   })
        // }else{
          this.currentId = this.idList[this.curTotalIndex].id
          if(this.questionList.find(i=>i.id == this.currentId)){
            this.$set(this, 'currentQ', this.questionList.find(i=>i.id == this.currentId))
@@ -324,11 +401,11 @@
            const curIdList = this.idList.slice(startIndex, this.curTotalIndex+1);
            this.getQuestionsByIds(curIdList).then(()=>{
              // this.currentQ = this.questionList[this.questionList.length-1]
              this.$set(this, 'currentQ', this.questionList[this.questionList.length-1])
              this.$set(this, 'currentQ', this.questionList.find(i=>i.id == this.currentId))
              this.showAnswer()
            })
          }
        }
        // }
      }else{
        uni.showToast({
          title: '已经是第一题了',
@@ -347,8 +424,8 @@
        }else{
          const curIdList = this.idList.slice(this.curTotalIndex,this.curTotalIndex + 20)
          this.getQuestionsByIds(curIdList).then(()=>{
            this.$set(this, 'currentQ', this.questionList[0])
            // this.currentQ = this.questionList[0]
            this.$set(this, 'currentQ', this.questionList.find(i=>i.id == this.currentId))
            // this.$set(this, 'currentQ', this.questionList[0])
            this.showAnswer()
          })
        }
@@ -405,6 +482,7 @@
                  title: '本次考试结束',
                  duration: 1500
                })
                clearInterval(this.timerInterval)
                setTimeout(()=>{
                  const url = uni.getStorageSync("prevPage");
                  if(url){
@@ -464,8 +542,7 @@
}
.panel{
  height: 100vh;
  width: 60vw;
  height: 60vh;
  background: #f2f2f2;
  overflow-y: auto;
  padding: 15px;
@@ -477,7 +554,8 @@
  &>view{
    padding: 5px;
    min-width: calc(20% - 12px);
    box-sizing: border-box;
    min-width: 33px;
    border-radius: 4px;
    text-align: center;
    background: rgba(41,121,255,0);
@@ -485,7 +563,7 @@
    color: #333;
    background: #f2f2f2;
    transition: all 100ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
    box-shadow: 0px -6px 10px rgba(255, 255, 255, 1), 0px 4px 15px rgba(0, 0, 0, 0.15);
    box-shadow: 0px -6px 10px rgba(255, 255, 255, 1), 0px 4px 15px rgba(0, 0, 0, 0.1);
    cursor: pointer;
    &:active {
@@ -508,6 +586,17 @@
    background: rgba(237,100,100,.1);
    border: 1px solid #ed6464;
    color: #ed6464;
  }
}
.panelTwo{
  height: 60vh;
  background: #f2f2f2;
  padding: 15px;
  box-sizing: border-box;
  /deep/ .u-textarea__field{
    height: calc(60vh - 110px) !important;
  }
}
@@ -558,7 +647,7 @@
      border-radius: 4px;
      color: #2979ff;
      background: #f5f7fa;
      border: 1px solid rgba(41,121,255,.4);
      border: 1px solid rgba(41,121,255,.2);
      box-shadow: 0px -6px 10px rgba(255, 255, 255, 1), 0px 4px 15px rgba(0, 0, 0, 0.1);
      transition: box-shadow .25s ease !important;
    }
@@ -571,13 +660,24 @@
  .questions{
    width: 100%;
    margin-top: 40px;
    margin-top: 40rpx;
    .title{
      font-size: 16px;
      margin-bottom: 20px;
    }
    .content{
      padding-left: 10rpx;
      .pickedText{
        border: 1.5px solid #2979ff !important;
      }
      .wrongText{
        border: 1.5px solid #ed6464 !important;
      }
      /deep/ .u-textarea__field{
        min-height: 80px;
      }
      .answers{
        background: #ecf5ff;
@@ -587,7 +687,11 @@
        }
        span{
          width: 100%;
          display: block;
          white-space: pre-wrap;
          font-weight: bolder;
          word-break: break-word;
        }
        .right{
          color: #3c9cff
@@ -606,7 +710,7 @@
  align-items: center;
  justify-content: space-around;
  z-index: 99;
  bottom: 60px;
  bottom: 20px;
  left: 0;
}
@@ -622,14 +726,14 @@
  box-sizing: border-box;
  border-radius: 8px;
  background: #f5f7fa;
  border: 1px solid #fff;
  border: 1.5px solid #fff;
  box-shadow: 0px -6px 10px rgba(255, 255, 255, 1), 0px 4px 15px rgba(0, 0, 0, 0.1);
  transition: box-shadow .25s ease !important;
}
.myRadio{
  /deep/ .picked{
    border: 2px solid #2979ff;
    border: 1.5px solid #2979ff;
    .u-radio__icon-wrap,.u-checkbox__icon-wrap{
      border-color: #fff !important;
@@ -641,6 +745,19 @@
      color: #2979ff
    }
  }
  /deep/ .wronged{
    border: 1.5px solid #ed6464;
    .u-radio__icon-wrap,.u-checkbox__icon-wrap{
      border-color: #fff !important;
      span{
        color: #fff !important;
      }
    }
    span{
      color: #ed6464
    }
  }
}
/deep/ .u-checkbox:active {