Browse Source

新的考试

y595705120 2 năm trước cách đây
mục cha
commit
68caf2900b

+ 1 - 0
src/containers/center/exam/components/util.js

@@ -49,6 +49,7 @@ export function getExam(){
 }
 
 export function getSelect( answers ){
+  if(!answers) return 0;
   let select = 0;
   if(answers>=0 && answers < 10 ) return answers
   for( let i =0; i < answers.length; i++){

+ 6 - 1
src/containers/center/exam/index.css

@@ -12,6 +12,7 @@
 
 .answer-item {
   padding: 8px;
+  width: 100%;
 }
 
 .answer-title{
@@ -39,6 +40,9 @@
   bottom: 70px;
   left: 20px;
 }
+.select {
+  background-color: #7FBAE4 !important;
+}
 
 .question {
   padding: 4px 0;
@@ -59,6 +63,7 @@
   padding: 10px;
   margin: 10px;
   min-height: 660px;
+  padding-bottom: 100px;
 }
 
 .page-ctrl{
@@ -96,7 +101,7 @@
 }
 
 .card-select {
-  margin: 50px auto;
+  margin: 10px auto;
   font-size: 16px;
   font-weight: 900;
   margin-top: 50px;

+ 446 - 0
src/containers/center/exam/indexTest.vue

@@ -0,0 +1,446 @@
+<template lang="html">
+  <div class="m-right-block fr">
+    <div class="exam-card">
+        <el-row :gutter="20">
+          <el-col :span="16"  :loading="loading">
+            <div class="exam-content">
+              <el-card class="box-card" v-for="(currentQuestion, aindex) in questionList" :key="aindex" v-show="aindex==cindex">
+                <div slot="header" class="clearfix">
+                  <span>第{{aindex+1}}题({{currentQuestion.type|getType}})</span>
+
+                  <span style="float: right;">
+                    <span> 剩余时间: <span class="ltime">{{end.h}}: {{end.m}}:{{end.s}}</span> </span>
+
+                    <el-button type="danger" @click="submitPaper" class="ml20">交卷</el-button>
+
+                  </span>
+                </div>
+
+                <div class="q-single">
+                  <div class="question">
+                    题目 : <span v-html="currentQuestion.title"></span>
+                  </div>
+                  <!-- 当选题 -->
+                  <div class="answer" v-if="currentQuestion.type<3">
+                    <el-radio-group v-model="currentQuestion.answer"  @change="selectRadio">
+                      <el-radio class="answer-item" v-for="(item,index) in currentQuestion.choice"
+                       :label="index+1"
+                       :key="index">
+                        <span class="answer-title">{{transformChar[index]+'、 '+item}}</span>
+                      </el-radio>
+                    </el-radio-group>
+                  </div>
+
+                  <!-- 多选题 -->
+                  <div class="answer" v-if="currentQuestion.type==3">
+                    <el-checkbox-group v-model="currentQuestion.answer"  @change="selectCheckBox">
+                       <el-checkbox
+                       :label="index"
+                        v-for="(item,index) in currentQuestion.choice"
+                        :key="index"
+                       class="answer-item">
+                       {{transformChar[index]+'、 '+item}}
+                       </el-checkbox>
+                    </el-checkbox-group >
+                  </div>
+
+                  <!-- 案例题 -->
+                  <div class="answer" v-if="currentQuestion.type==4">
+                    <div v-for="(child,cidx) in currentQuestion.child" :key="child.id">
+                      {{cidx+1}}小题: <span v-html="child.title"></span>
+
+                      <div class="answer" v-if="child.type==3">
+                        <el-checkbox-group v-model="currentQuestion.child[cidx].answer"  @change="(e)=>{selectCheckBox(e,cidx)}">
+                           <el-checkbox
+                           :label="index"
+                            v-for="(item,index) in child.choice"
+                            :key="index"
+                           class="answer-item">
+                           {{transformChar[index]+'、 '+item}}
+                           </el-checkbox>
+                        </el-checkbox-group >
+                      </div>
+
+                      <div class="answer" v-else>
+                        <el-radio-group v-model="currentQuestion.child[cidx].answer"  @change="(e)=>{selectRadio(e, cidx)}">
+                          <el-radio class="answer-item" v-for="(item,index) in child.choice"
+                           :label="index+1"
+                           :key="index">
+                            <span class="answer-title">{{transformChar[index]+'、 '+item}}</span>
+                          </el-radio>
+                        </el-radio-group>
+                      </div>
+
+                    </div>
+                  </div>
+
+                  <div class="mark" >
+                    <el-checkbox v-model="currentQuestion.marked" @change="changeMark" :checked="currentQuestion.marked">
+                      <span class="red">*</span> 题目标注
+                    </el-checkbox>
+                  </div>
+                </div>
+
+                <div class="page-ctrl">
+                  <el-button  type="primary" :disabled="currentQuestion.index<1" @click="prevQuestion">上一题</el-button>
+                  <el-button  type="primary" :disabled="currentQuestion.index>48" @click="nextQuestion">下一题</el-button>
+                </div>
+              </el-card>
+            </div>
+          </el-col>
+
+          <el-col :span="8" >
+            <div class="card-select">
+              <div>
+                <h3 class="p5">单项选择题</h3>
+                <el-row :gutter="24" class="ml20">
+                  <el-col :span="3" v-for="(item,index) in info.answers" :key="index" class="select-item" v-if="item.type==2">
+                    <el-button :class="'b-grid '+getStyle(index)" @click="gotoQuestion(index)" >
+                       {{index+1}}
+                       <span class="red">
+                        {{isMarked(index)}}
+                       </span>
+                    </el-button>
+                  </el-col>
+                </el-row>
+
+               <h3 class="p5">多选题</h3>
+                <el-row :gutter="24" class="ml20">
+                  <el-col :span="3" v-for="(item,index) in info.answers"   :key="index" class="select-item" v-if="item.type==3">
+                    <el-button :class="'b-grid '+getStyle(index)" @click="gotoQuestion(index)" >
+                       {{index+1}}
+                       <span class="red">
+                        {{isMarked(index)}}
+                       </span>
+                    </el-button>
+                  </el-col>
+                </el-row>
+
+                <h3 class="p5">判断题</h3>
+                <el-row :gutter="24" class="ml20">
+                  <el-col :span="3" v-for="(item,index) in info.answers"  :key="index" class="select-item" v-if="item.type==1">
+                    <el-button :class="'b-grid '+getStyle(index)" @click="gotoQuestion(index)" >
+                       {{index+1}}
+                       <span class="red">
+                        {{isMarked(index)}}
+                       </span>
+                    </el-button>
+                  </el-col>
+                </el-row>
+
+                <h3 class="p10" v-if="isAnli">案例题</h3>
+                <el-row :gutter="24" class="ml20">
+                  <el-col :span="3" v-for="(item,index) in info.answers"  :key="index" class="select-item" v-if="item.type==4">
+                    <el-button :class="'b-grid '+getStyle(index)" @click="gotoQuestion(index)" >
+                       {{index+1}}
+                       <span class="red">
+                        {{isMarked(index)}}
+                       </span>
+                    </el-button>
+                  </el-col>
+                </el-row>
+              </div>
+            </div>
+          </el-col>
+        </el-row>
+     </div>
+
+    <my-dialog style="margin-top:20vh" :dialogVisible="dialogVisible" :info="info" :start="start" :end="end" @leavePage="leavePage" >
+
+
+    </my-dialog>
+  </div>
+</template>
+
+<script>
+import { Message, MessageBox } from "element-ui";
+import {httpServer } from "@/components/httpServer/httpServer.js";
+import md5 from 'js-md5';
+import { getTime, packTime, time2str, saveExam, getExam,getSelect,delExam } from "./components/util.js";
+import headline from "./components/headline.vue";
+import myDialog from "./components/my-dialog.vue";
+const defAnswer = [false,false,false,false,false];
+
+export default {
+  components:{
+    headline,
+    myDialog
+  },
+  filters:{
+    getType( val ){
+      const d = {1:'判断题', 2:'单选题', 3:'多选题', 4:'案例题'}
+      return d[val]
+    }
+  },
+  data() {
+    return {
+      uuid:0,
+      examId:0,
+      groupId:0,
+      startExam: false,
+      dialogVisible: false,
+      info: {},
+      id:'',
+      index:0,
+      cindex:0,
+      loading: false,
+      isAnli: false,
+      questionList: [],
+      answers:{},
+      questionLen: 0,
+      questionType: '单选题',
+      textarea: "",
+      radio: "",
+      checked:defAnswer,
+      getSelect,
+      time2str,
+      questionId: 0,
+      startTime: "",
+      endTime: "",
+      transformChar: ["A", "B", "C", "D","E"],
+      start: { h: 0, m: 0, s: 0 },
+      end: { h: 0, m: 0, s: 0 },
+      timer: 0,
+      commitMap:{},
+      loadCache:{ },
+      onblurTime: 0
+    };
+  },
+  methods: {
+    isMarked(val){
+      if( val>= this.questionList.length || val < 0 ) return '';
+      return this.questionList[val].marked?'*':'';
+    },
+    initTimer() {
+      let courseId = this.info.courseId;
+      let leftTime =  this.info.startTime +this.info.duration -getTime();
+      if (leftTime < 0) return;
+      if (this.timer) {
+        window.clearInterval(this.timer);
+      }
+      this.tickTimer( courseId );
+      this.timer = window.setInterval(() => {
+        this.tickTimer( courseId );
+      }, 1000);
+    },
+    tickTimer( courseId ) {
+      let nowSec = getTime();
+      let {startTime, duration} = this.info;
+      let timeLast =  startTime+duration -nowSec;
+      this.end = packTime(timeLast);
+      this.start = packTime( startTime );
+      if (timeLast < 0) {
+        window.clearInterval(this.timer);
+        this.dosubmit(answer);
+        return;
+      }
+    },
+
+    doLoadQuestion( index, item ){
+      item.choice = [];
+      this.cindex = index;
+      for( let i=0;i<6;i++){
+        let mkey = "answer"+i
+        if(item[mkey] ) item.choice.push( item[mkey] );
+      }
+      if( item.type == 4){
+        for ( let i in item.child){
+          let child = item.child[i]
+          child.choice = [];
+          for( let i=0;i<6;i++){
+            let mkey = "answer"+i
+            if(child[mkey] ) child.choice.push( child[mkey] );
+          }
+        }
+      }else{
+        item.child = []
+      }
+      console.log("index", index, item.type, item.radio, item.answer)
+      this.questionList[index] = item
+    },
+    loadQuestion( index ) {
+      let item = this.questionList[index];
+      item.index = index;
+      if( !item.title ){
+        let {id} = item;
+        this.loading= true;
+        httpServer("course.loadAnswer", {id} ).then(res => {
+          this.loading= false;
+          if( res.code != 200) return;
+          item = Object.assign( item, res.data )
+          let childs = res.data.child;
+          if( item.type == 4){
+            item.child = childs.map( v=>{
+              if( v.type == 3){ v.answer = [false,false,false,false,false]
+              }else{ v.answer=0 }
+              return v
+            })
+          }else if(item.type == 3){
+            item.answer= [false,false,false,false,false];
+          }else{
+            item.answer = 0;
+          }
+          this.doLoadQuestion( index, item )
+        })
+      }else{
+        this.doLoadQuestion( index, item )
+      }
+    },
+    changeMark(marked){
+      let index = this.currentQuestion.index
+      this.questionList[ index ].marked = marked
+      this.$forceUpdate()
+    },
+    getStyle: function(i) {
+      let item = this.questionList[i];
+      let select = getSelect( item.answer )
+      let cls = ""
+      if( i == this.cindex) cls+='select '
+      cls+=(select ? "finish" : "unfinish");
+      return cls
+    },
+    leavePage(){
+      let courseId = this.info.courseId
+      this.timer &&  window.clearInterval(this.timer);
+      delExam( )
+      this.$router.push(`/center/play/${courseId}`);
+    },
+    submitPaper() {
+      let that = this
+      MessageBox({
+        title: "确认交卷",
+        message: "是否确认交卷",
+        showCancelButton: true,
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        beforeClose: (action, instance, done) => {
+          if (action === "confirm") {
+            instance.confirmButtonLoading = true;
+            instance.confirmButtonText = '提交中...';
+            that.dosubmit(done);
+            done();
+            instance.confirmButtonLoading = false;
+            that.dialogVisible = true;
+
+          } else{
+            done();
+          }
+
+        }
+      })
+    },
+    dosubmit( cb ) {
+      let param = { examId: this.info.examId, result: { }};
+      for( let i in this.questionList){
+        let item = this.questionList[i];
+        if(item.type!= 4){
+          let select = getSelect(item.answer);
+          if( select) param.result[item.id] =select ;
+        }else{
+          for( let j in item.child){
+            if(!item.child[j] || !item.child[j].id) continue;
+            let select = getSelect(item.child[j].answer);
+            if(select) param.result[item.child[j].id] = select;
+          }
+        }
+      }
+      httpServer("course.FinishExamTest", param).then(res => {
+        if (res.code == 200) {
+          let { score, useTime } = res.data;
+          this.info.score = score;
+          this.info.useTime = useTime;
+          this.info.isFinish = 1;
+          this.timer &&  window.clearInterval(this.timer);
+        }
+      });
+    },
+    prevQuestion() {
+      let index = this.cindex
+      if( index <1) return
+      this.loadQuestion(index-1);
+    },
+    nextQuestion() {
+      let index = this.cindex
+      if( index >= this.questionList.length - 1) return
+      this.loadQuestion(index+1);
+    },
+    gotoQuestion( index ) {
+      index = parseInt(index);
+      this.loadQuestion(index);
+    },
+    doStartExam( info ){
+      info.groupId = this.groupId||0;
+      this.info = info
+      this.questionList = info.answers||[];
+      this.isAnli = false;
+      for( let i in this.questionList){
+         if( this.questionList[i].type == 4){
+           this.isAnli = true;
+         }
+      }
+
+      this.loadQuestion(0);
+      this.startTime = info.startTime;
+      saveExam( this.info, this.questionList );
+      // this.initTimer();
+    },
+    selectRadio( value, cidx ){
+      let index = this.index;
+      let curAnswer = this.questionList[index];
+      if( curAnswer.type == 4 ){
+        this.questionList[index].child[cidx].answer = value;
+      }
+      this.questionList[index].answer = value;
+      saveExam( this.info, this.questionList );
+      this.$forceUpdate()
+    },
+    selectCheckBox(value, cidx){
+      let index = this.index;
+      let curAnswer= this.questionList[index];
+      if( curAnswer.type == 4 ){
+        this.questionList[index].child[cidx].answer = value;
+      }
+      this.questionList[index].answer = value;
+      saveExam( this.info, this.questionList );
+      this.$forceUpdate()
+    }
+  },
+  destroyed(){
+    this.timer &&  window.clearInterval(this.timer)
+    saveExam( this.info, this.questionList );
+  },
+
+  beforeMount() {
+    let courseId = +this.$route.params.courseId
+    let groupId = +this.$route.query.groupId;
+    this.groupId = groupId;
+    this.courseId = courseId;
+    let info = getExam()
+    let nowSec = getTime()
+
+    if( info.courseId == courseId &&  info.groupId == groupId&&
+    info.questionList.length>0 &&info.startTime + info.duration > nowSec){
+      this.doStartExam( info )
+      return;
+    }
+    let that = this;
+    //
+    httpServer("course.StartExamTest", {courseId, groupId} ).then(res => {
+      if( res.code != 200) return;
+      let info = res.data||{}
+      info.questionList = info.answers.map( v =>{
+        v.marked = false
+        v.answer = 0
+        if(v.type==3) v.answer = [false,false,false,false,false];
+        return v;
+      });
+      that.doStartExam( info );
+    });
+  }
+};
+</script>
+
+<style lang="css">
+  @import url("./index.css");
+  @import url("../../../assets/css/base.css");
+</style>

+ 6 - 1
src/router/index.js

@@ -35,6 +35,7 @@ import PublicSign from '@/containers/sign/index'
 
 import CenterMarket from '@/containers/center/market/index'
 import CenterExam from '@/containers/center/exam/index'
+import CenterExamTest from '@/containers/center/exam/indexTest'
 
 import CenterUserSeat from '@/containers/center/userSeat/index'
 
@@ -146,9 +147,13 @@ export default new Router({
           component: CenterMessage,
         },
         {
-          path: 'exam/:courseId',
+          path: 'examTest/:courseId',
           component: CenterExam,
         },
+        {
+          path: 'exam/:courseId',
+          component: CenterExamTest,
+        },
         {
           path: 'market',
           component: CenterMarket,