소스 검색

新增新的考试

y595705120 2 년 전
부모
커밋
031ea5db4b

+ 128 - 0
src/assets/css/exam.css

@@ -0,0 +1,128 @@
+[v-cloak] {
+  display: none;
+}
+.center {
+  text-align: center;
+}
+.card-header {
+  padding: 10px;
+  margin-top: 30px;
+}
+
+
+.answer-item {
+  padding: 8px;
+  width: 100%;
+}
+
+.answer-title{
+  font-size: 15px;
+  word-wrap:break-word;
+  word-break:normal;
+  white-space:normal;
+  white-space: normal;
+}
+
+
+.el-radio, .el-radio__input{
+  word-wrap:break-word;
+  word-break:normal;
+  white-space: normal;
+}
+
+.el-radio__label{
+  font-size: 15px !important;
+  line-height:150%;
+  letter-spacing: 1px;
+}
+.mark{
+  position:absolute;
+  bottom: 70px;
+  left: 20px;
+}
+.select {
+  background-color: #7FBAE4 !important;
+}
+
+.question {
+  padding: 4px 0;
+  min-height: 100px;
+}
+.question span{
+  padding-left: 20px;
+}
+
+.exam-content {
+  margin: 0 auto;
+  font-size: 17px;
+  margin-top: 40px;
+}
+
+.exam-content .box-card {
+  position: relative;
+  padding: 10px;
+  margin: 10px;
+  min-height: 660px;
+  padding-bottom: 100px;
+}
+
+.page-ctrl{
+  position:absolute;
+  bottom: 40px;
+  right: 40px;
+  padding: 3px 0;
+}
+
+.b-grid {
+  width: 100%;
+  padding: 8px !important;
+  text-align: center !important;
+  background-color: #ffffff;
+}
+.finish {
+  background-color: #add8e6 !important;
+}
+.el-radio__inner{
+  border: 1px solid #1c1c1d;
+  border-radius: 100%;
+  background-color: #FFF;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+}
+
+.red {
+  color: red;
+}
+
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  content: "";
+}
+
+.card-select {
+  margin: 10px auto;
+  font-size: 16px;
+  font-weight: 900;
+  margin-top: 50px;
+}
+.select-item{
+  padding: 0px !important;
+  margin: 1px;
+  margin-top: 5px;
+  height: 36px;
+}
+
+.show-true{
+  font-weight: 900;
+  color: green;
+  padding: 1rem;
+}
+.show-false{
+  font-weight: 900;
+  color: red;
+  padding: 1rem;
+}
+.w130{
+  width: 130px;
+}

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

@@ -299,6 +299,9 @@ export default {
       this.questionList[ index ].marked = marked
       this.$forceUpdate()
     },
+    reportMsg( action, msg ){
+      httpServer("course.report", {action, msg})
+    },
     getStyle: function(i) {
       let item = this.questionList[i];
       let select = getSelect( item.answer )
@@ -401,6 +404,7 @@ export default {
       this.questionList[index].answer = value;
       saveExam( this.info, this.questionList );
       this.$forceUpdate()
+      this.reportMsg( "select" , curAnswer.answerId+'|' + (cidx||0)+'|'+ getSelect(value) )
     },
     selectCheckBox(value, cidx){
       let index = this.cindex;
@@ -411,6 +415,7 @@ export default {
       this.questionList[index].answer = value;
       saveExam( this.info, this.questionList );
       this.$forceUpdate()
+      this.reportMsg( "select" , curAnswer.answerId+'|' + (cidx||0)+'|'+ getSelect(value) )
     }
   },
   destroyed(){

+ 244 - 0
src/containers/center/play/components/iCourseAnswerTest.vue

@@ -0,0 +1,244 @@
+<template>
+  <div style="display: flex;">
+
+    <ul style="width: 180px;">
+      <li class="mt10">
+        <el-button type="primary" @click="type=1" class="w130" > 判断题 {{counter[1]}}题</el-button>
+      </li>
+      <li class="mt10">
+        <el-button type="warning" @click="type=2" class="w130" >单选题 {{counter[2]}}题</el-button>
+      </li>
+      <li class="mt10">
+        <el-button type="success" @click="type=3"  class="w130">多选题 {{counter[3]}}题</el-button>
+      </li>
+      <li class="mt10">
+        <el-button type="danger" @click="type=4" class="w130">案例题 {{counter[4]}}题</el-button>
+      </li>
+    </ul>
+
+    <el-card style="width: 750px;min-height: 400px;">
+      <div slot="header" class="clearfix">
+        <span>第{{index+1}}题({{currentQuestion.type|getType}})</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,choiceIdx) in currentQuestion.choice" :label="choiceIdx+1" :key="choiceIdx">
+              <span class="answer-title">{{transformChar[choiceIdx]+'、 '+item}}</span>
+            </el-radio>
+          </el-radio-group>
+          <div class="mt10" v-if="finish">
+            <span v-html="getReult(currentQuestion)"></span>
+          </div>
+        </div>
+
+        <!-- 多选题 -->
+        <div class="answer" v-if="currentQuestion.type==3">
+          <el-checkbox-group v-model="currentQuestion.answer" @change="selectCheckBox">
+            <el-checkbox v-for="(item,choiceIdx) in currentQuestion.choice"
+              :label="choiceIdx+1" :key="choiceIdx" class="answer-item">
+              {{transformChar[choiceIdx]+'、 '+item}}
+            </el-checkbox>
+          </el-checkbox-group>
+
+
+          <div class="mt10 " v-if="finish">
+            <span v-html="getReult(currentQuestion)"></span>
+          </div>
+        </div>
+
+        <!-- 案例题 -->
+        <div class="answer" v-if="currentQuestion.type==4">
+          <div v-for="(child,cidx) in currentQuestion.child" :key="child.id">
+            {{cidx+1}}[{{child.type|getType}}]: <span v-html="child.title"></span>
+
+            <div class="answer" v-if="child.type==3">
+              <el-checkbox-group v-model="answers['answer'+cidx]" @change="(e)=>{selectCheckBox(e,cidx)}">
+                <el-checkbox v-for="(item,choiceIdx) in child.choice" :label="choiceIdx+1" :key="choiceIdx" class="answer-item">
+                  {{transformChar[choiceIdx]+'、'+item}}
+                </el-checkbox>
+              </el-checkbox-group>
+              <div class="mt10" v-if="finish">
+                <span v-html="getReult(child)"></span>
+              </div>
+            </div>
+
+            <div class="answer" v-else>
+              <el-radio-group v-model="answers['answer'+cidx]" @change="(e)=>{selectRadio(e, cidx)}">
+                <el-radio class="answer-item" v-for="(item,choiceIdx) in child.choice" :label="choiceIdx+1" :key="choiceIdx">
+                  <span class="answer-title">{{transformChar[choiceIdx]+'、 '+item}}</span>
+                </el-radio>
+              </el-radio-group>
+              <div class="mt10" v-if="finish">
+                <span v-html="getReult(child)"></span>
+              </div>
+            </div>
+
+          </div>
+        </div>
+      </div>
+      <div class="tc" v-if="!finish">
+        <el-button type="primary"  @click="submitQustion">完成</el-button>
+      </div>
+      <div class="tc" v-else>
+        <el-button type="primary" :disabled="index<1" @click="prevQuestion">上一题</el-button>
+        <el-button type="primary" :disabled="index>=counter[type]" @click="nextQuestion">下一题</el-button>
+      </div>
+    </el-card>
+
+
+  </div>
+</template>
+
+<script>
+  import { httpServer} from "@/components/httpServer/httpServer.js";
+  import { getSelect } from "@/containers/center/exam/components/util.js";
+  export default {
+    data() {
+      return {
+        index: 0,
+        groupId: 7,
+        id: 0,
+        type: 1,
+        finish: false,
+        transformChar: ["A", "B", "C", "D","E"],
+        currentQuestion: {child:[], choice:[]},
+        answers:{
+          answerlist:[],
+          answer:'',
+          answer0:'',
+          answer1:'',
+          answer2:'',
+          answer3:'',
+          answer4:'',
+        },
+        counter:{
+          1:200,
+          2:400,
+          3:100,
+          4:30
+        }
+      }
+    },
+    props: ['info', 'extraXs'],
+    mounted() {
+      this.id = this.info.id || 0;
+      this.index = this.extraXs.index1 || 0;
+      this.loadAnswer();
+    },
+    watch: {
+      type() {
+        let index = 'index' + this.type;
+        this.index = 0;
+        this.loadAnswer();
+      }
+    },
+    filters:{
+      getType( val ){
+        const d = {1:'判断题', 2:'单选题', 3:'多选题', 4:'案例题'}
+        return d[val]
+      }
+    },
+    methods: {
+      submitQustion(){
+        let param = {
+          id: this.id,
+          groupId: this.groupId,
+          type: this.type,
+          index: this.index,
+        }
+        httpServer("course.finishPaperAnswer", param).then(res => {
+          if (res.code != 200) return;
+          let extraKey = 'index'+this.type
+          if( this.index > this.extraXs[extraKey]){
+            this.$emit( "updateExtraXs", {extraKey:this.index})
+          }
+          this.finish = true
+        })
+      },
+      showResult(index){
+        let val = ''+index;
+        val = val.replaceAll('1', 'A').replaceAll('2', 'B').replaceAll('3', 'C').replaceAll('4', 'D').replaceAll('5', 'E');
+        return val.split('').join(',')
+      },
+      getReult(item){
+        let select = getSelect( item.answer);
+        let result = this.showResult( item.result )
+        if( select == item.result){
+          return `正确答案:<span class="show-true">${result}</span>`
+        }else{
+          return `正确答案:<span class="show-false">${result}</span>`
+        }
+      },
+      prevQuestion(){
+        if( this.index <1) return;
+        this.index--
+        this.loadAnswer()
+      },
+      nextQuestion(){
+        this.index++
+        this.loadAnswer()
+      },
+      selectRadio( value, cidx ){
+        if( this.currentQuestion.type == 4 ){
+          this.currentQuestion.child[cidx].answer = value;
+        }
+        this.currentQuestion.answer = value;
+        this.$forceUpdate()
+      },
+      selectCheckBox(value, cidx){
+        if( this.currentQuestion.type == 4 ){
+          this.currentQuestion.child[cidx].answer = value;
+        }
+        this.currentQuestion.answer = value;
+        this.$forceUpdate()
+      },
+      doLoadQuestion( item ){
+        item.choice = [];
+        for( let i=0;i<6;i++){
+          let mkey = "answer"+i
+          if(item[mkey] ) item.choice.push( item[mkey] );
+        }
+        item.answer = [];
+        if( item.type == 4){
+          for ( let i in item.child){
+            let child = item.child[i]
+            child.choice = [];
+            child.answer = [];
+            this.answers['answer'+i] = child.answer;
+            for( let i=0;i<6;i++){
+              let mkey = "answer"+i
+              if(child[mkey] ) child.choice.push( child[mkey] );
+            }
+          }
+        }else{
+          item.child = []
+        }
+        this.finish = false
+        console.log("ok", item)
+        this.currentQuestion = item
+      },
+      loadAnswer() {
+        let param = {
+          id: this.id,
+          groupId: this.groupId,
+          type: this.type,
+          index: this.index,
+        }
+        httpServer("course.loadPaperAnswer", param).then(res => {
+          if (res.code != 200) return;
+          if( this.index ==0 ) this.index = res.data.index;
+          this.doLoadQuestion( res.data.info || {})
+        })
+      }
+    }
+  }
+</script>
+
+<style lang="css">
+  @import url("../../../../assets/css/exam.css");
+</style>

+ 1 - 1
src/containers/center/play/components/iCourseInfo.vue

@@ -57,7 +57,7 @@
               <el-button type="primary" class="mt10" style="font-size: 14px;" @click="startExam" v-if="tpl.examGroupId>0">
                 参加考试
               </el-button>
-              <el-button type="primary" class="mt10" style="font-size: 14px;" @click="printCert">
+              <el-button type="primary" class="mt10" style="font-size: 14px;" @click="printCert" v-if="tpl.tplId>0">
                 学时证明
               </el-button>
           </div>

+ 1 - 1
src/containers/center/play/components/iCourseInfoTest.vue

@@ -76,7 +76,7 @@
 
     <el-col :span="3">
       <div>
-        <el-button type="primary" style="font-size: 14px;margin-top: ;" @click="printCert">
+        <el-button type="primary" style="font-size: 14px;margin-top: ;" @click="printCert" v-if="tpl.tplId>0">
           学时证明
         </el-button>
       </div>

+ 149 - 0
src/containers/center/play/components/iCourseInfoXsExtra.vue

@@ -0,0 +1,149 @@
+<template>
+  <el-row class="p20">
+    <el-col :span="6">
+      <img :src="tpl.tb" width="200px" style="border-radius: 20px;" />
+    </el-col>
+    <el-col :span="6">
+      <div>
+        <p style="font-size: 24px;"> 课程信息 </p>
+        <p class="mt10">岗位名称:{{tpl.name}} </p>
+        <p class="mt10" v-if="tpl.examGroupId">课程年度:
+          <strong style="color: red;">{{tpl.nd}} </strong>
+        </p>
+       <p class="mt10">学习需求:
+          <p class="mt10 ml20"> 视频学时:<strong style="color: red;">{{(tpl.xs - tpl.examXs-tpl.testXs)/10}}</strong>学时
+
+          </p>
+          <p class="ml20"> 专项练习:<strong style="color: red;">{{tpl.testXs/10}}</strong>学时</p>
+          <p class="ml20"> 模拟试卷:<strong style="color: red;">{{tpl.examXs/10}}</strong>学时</p>
+        </p>
+
+        <p class="mt10">学习情况:
+          完成 <strong style="color: red;">{{info.getXs/10}} </strong>
+          共计 <strong style="color: red;">{{info.totalXs/10}}</strong>
+        </p>
+        <p class="mt10" v-if="tpl.examGroupId">开始时间:
+          <strong style="color: red;">{{info.startDate}} </strong>
+        </p>
+
+      </div>
+    </el-col>
+
+    <el-col :span="9">
+      <div>
+        <p style="font-size: 24px;"> 考试情况 </p>
+        <p class="mt5">
+          <span style="width:240px;margin: 0px;padding: 0px;">
+            专项练习: 完成<strong style="color: red;"> {{extraXs|testCount}}</strong>题
+          </span>
+          <el-button @click="startExamTest()" type="text">开始练习</el-button>
+        </p>
+        <p class="mt5">
+          <span style="width:240px;margin: 0px;padding: 0px;">
+            模拟试卷1: 最高<strong style="color: red;"> {{extraXs.score1}}</strong>分
+          </span>
+          <el-button @click="startExam(7)" type="text">开始考试</el-button>
+        </p>
+
+        <p class="mt5">
+          <span style="width:240px;margin: 0px;padding: 0px;">
+            模拟试卷2: 最高<strong style="color: red;"> {{extraXs.score2}}</strong>分
+          </span>
+          <el-button @click="startExam(8)" type="text">开始考试</el-button>
+        </p>
+
+        <p class="mt5">
+          <span style="width:240px;margin: 0px;padding: 0px;">
+            模拟试卷3: 最高<strong style="color: red;"> {{extraXs.score3}}</strong>分
+          </span>
+          <el-button @click="startExam(9)" type="text">开始考试</el-button>
+        </p>
+        <p class="mt5">备注信息:<br>
+
+          <strong style="color: red;" class="pl20">专项练习完成100题可以获得10学时,模拟试卷三个都完成可以获得10学时</strong>
+        </p>
+      </div>
+    </el-col>
+
+    <el-col :span="3">
+      <div>
+        <el-button type="primary" style="font-size: 14px;margin-top: ;" @click="printCert" v-if="tpl.tplId>0">
+          学时证明
+        </el-button>
+      </div>
+    </el-col>
+
+  </el-row>
+</template>
+
+<script>
+  import setting from '@/setting';
+  import { getTime,packTime,toDate } from "@/utils/date";
+  export default {
+    name: "iCourseInfoTest",
+    data() {
+      return {
+        setting,
+        timer: 0,
+        end: {
+          d: 0,
+          h: 0,
+          m: 0,
+          s: 0
+        }
+      }
+    },
+    props: ['tpl', 'info', 'extraXs'],
+    destroyed(){
+      this.timer &&  window.clearInterval(this.timer)
+    },
+    created(){
+      this.initTimer()
+    },
+    filters:{
+      add80Date( date ){
+        let val = new Date(date).getTime() + 80*86400*1000;
+        return toDate( val )
+      },
+      testCount(val){
+        return val.index1+val.index2+val.index3+val.index4
+      }
+    },
+    methods: {
+      initTimer() {
+        if (this.timer) {
+          window.clearInterval(this.timer);
+        }
+        this.tickTimer();
+        this.timer = window.setInterval(() => {
+          this.tickTimer();
+        }, 1000);
+      },
+      tickTimer(  ) {
+        let nowSec = getTime();
+        let timeLast =  this.info.examTime -nowSec;
+        this.end = packTime(timeLast);
+        if (timeLast < 0) {
+          window.clearInterval(this.timer);
+        }
+      },
+      startExam(index) {
+        if( this.end.v <=0 && this.info.examTime>0 ) {
+          this.$message.errorMsg("开考超过三天,不能继续考试")
+          return;
+        }
+        if( this.tpl.isClosed ==1 ) {
+          this.$message.errorMsg("课程已经关闭", 2)
+          return;
+        }
+        this.$emit("startExam", +index)
+      },
+      startExamTest(){
+        this.$emit("startExamTest")
+      },
+      printCert() {
+        this.$emit("printCert")
+      }
+    }
+  }
+</script>

+ 23 - 2
src/containers/center/play/index.vue

@@ -1,6 +1,10 @@
 <template>
   <div class="m-right-block fr mh576">
     <ICourseInfoTest  v-if="tpl.type=='检测试验人员'" :info="info" :tpl="tpl" @printCert="printCert" @startExam="startExam"></ICourseInfoTest>
+    <ICourseInfoXsExtra v-else-if="tpl.testXs>0"
+    :extraXs="extraXs"  :info="info"
+    :tpl="tpl" @startExamTest="startExamTest" @startExam="startExam"></ICourseInfoXsExtra>
+
     <ICourseInfo v-else :info="info" :tpl="tpl" @printCert="printCert" @startExam="startExam"></ICourseInfo>
 
     <div class="right-block-bd ng-scope" ui-view="myStudyContent" style="position: relative;">
@@ -62,6 +66,12 @@
         <div v-if="show ==3" class="lwh-ul-form mt20">
           <exam-list :courseId="courseId"> </exam-list>
         </div>
+
+        <el-dialog class="previewDialog" :visible.sync="testExamDalog"
+          top="50px" width="1024px"
+          @close="testExamDalog=false">
+          <ICourseAnswerTest :info="info" :extraXs="extraXs" @updateExtraXs="updateExtraXs"> </ICourseAnswerTest>
+        </el-dialog>
       </div>
      </div>
     <el-dialog
@@ -106,6 +116,8 @@
   import ExamList from "./components/ExamList.vue";
   import ICourseInfo from "./components/iCourseInfo.vue";
   import ICourseInfoTest from "./components/iCourseInfoTest.vue";
+  import ICourseInfoXsExtra from "./components/iCourseInfoXsExtra.vue";
+  import ICourseAnswerTest from "./components/iCourseAnswerTest.vue";
   import {getPercent} from '@/utils/index.js'
   import {delExam} from '../exam/components/util.js'
   import md5 from 'js-md5';
@@ -119,9 +131,11 @@
         mediaType:'hls',
         mediaUrl:'',
         editRzcode: false,
+        testExamDalog: false,
         info: {score:0, percent:0},
         tpl:{},
         media:{},
+        extraXs:{},
         options:{
           controls:true,
           autoplay: true, // 如果true,浏览器准备好时开始回放。
@@ -154,7 +168,7 @@
         showList:[],
       };
     },
-    components:{Media,ExamList,ICourseInfo,ICourseInfoTest},
+    components:{Media,ExamList,ICourseInfo,ICourseInfoTest,ICourseAnswerTest,ICourseInfoXsExtra},
     beforeMount() {
       this.courseId = +this.$route.params.courseId
       this.getData()
@@ -203,6 +217,9 @@
         this.options.autoplay = this.options.playtimes>0;
         this.mediaDialog = true;
       },
+      startExamTest(){
+        this.testExamDalog = true;
+      },
       startExam( groupId ){
         let courseId = this.courseId
         let endDate = new Date( )
@@ -265,9 +282,10 @@
         let param = { courseId: this.courseId }
         httpServer("course.getCourse", param).then(res => {
           if (res.code == 200) {
-            let {info, extra, list, tpl} = res.data;
+            let {info, extra, list, tpl, extraXs} = res.data;
             this.info =  Object.assign( info, extra||{});
             this.tpl = tpl||{};
+            this.extraXs = extraXs||{};
             this.list = list.map( (item)=>{
               item.percent = getPercent(item)||0;
               return item;
@@ -304,6 +322,9 @@
       updateOption( param ){
         this.options = Object.assign( this.options, param);
       },
+      updateExtraXs( param ){
+        this.extraXs = Object.assign( this.extraXs, param);
+      },
       //
       update( item ){
         if( item.position> this.media.position) {