You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

426 lines
19 KiB

<template>
<div class="box">
<div class="left">
<p class="title">答题卡</p>
<div class="item">
<p class="type">单选题</p>
<p class="total">{{singleCount}}合计{{singlePoint}}</p>
<div class="nums">
<span v-for="n in singleCount" :class="{active: n <= singleAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="item">
<p class="type">多选题</p>
<p class="total">(共{{multipleCount}}题,合计{{multipleChoiceScore}}分)</p>
<div class="nums">
<span v-for="n in multipleCount" :class="{active: n <= multipleAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="item">
<p class="type">判断题</p>
<p class="total">(共{{judgeCount}}题,合计{{judgeScore}}分)</p>
<div class="nums">
<span v-for="n in judgeCount" :class="{active: n <= judgeAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="item">
<p class="type">填空题</p>
<p class="total">(共{{fillBlankCount}}题,合计{{fillBlanksScore}}分)</p>
<div class="nums">
<span v-for="n in fillBlankCount" :class="{active: n <= fillBlankAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="item">
<p class="type">简答题</p>
<p class="total">(共{{briefAnswerCount}}题,合计{{briefAnswerScore}}分)</p>
<div class="nums">
<span v-for="n in briefAnswerCount" :class="{active: n <= briefAnswerAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="btn">
<el-button size="mini" type="primary" @click="save">提交考试</el-button>
</div>
</div>
<div class="middle">
<div class="ques">
<template v-for="(subject,k) in subjects">
<div class="item" v-if="subject.length" :key="k">
<p v-if="subjects[k].length" class="title">{{questionType[k]}}(共{{subjects[k].length}}题,合计{{scoreList[k]}}分)</p>
<div class="ques-wrap" v-for="(item,index) in subject" :key="index">
<div class="name-wrap">
<span class="index">{{index+1}}.</span>
<div class="name" :class="'stem' + k + index" v-html="item.questionStem"></div>
</div>
<div class="media" :id="item.mediaEleId"></div>
<div class="options">
<template v-if="item.typeId == 1 || item.typeId == 3">
<div class="option">
<el-radio-group v-model="item.val" @change.once="updateProgress">
<el-radio v-for="(option,i) in item.options" :key="i" :label="i">
{{i}}.{{item.options[i]}}
</el-radio>
</el-radio-group>
</div>
</template>
<template v-if="item.typeId == 2">
<el-checkbox-group v-model="item.val" @change="updateProgress">
<el-checkbox class="option-check" :label="i" v-for="(option,i) in item.options" :key="i">
{{i}}.{{item.options[i]}}
</el-checkbox>
</el-checkbox-group>
</template>
<template v-if="item.typeId == 4">
<el-upload
class="upload"
:before-upload="file => beforeUpload(file,item)"
:on-remove="(file, fileList) => handleRemove(file, fileList, item)"
:on-error="uploadError"
:on-success="(res, file, fileList) => uploadSuccess(res, file, fileList, item)"
:before-remove="beforeRemove"
:on-exceed="handleExceed"
:action="api.fileupload"
>
<el-button type="primary" class="ml20">上传文件</el-button>
</el-upload>
<el-input type="textarea" rows="5" v-model="item.val" @input="updateProgress"></el-input>
</template>
</div>
</div>
</div>
</template>
</div>
</div>
<div class="right">
<p class="title">剩余时间</p>
<p class="time" v-countdown="time">{{time}}</p>
<div class="ans">答题进度</div>
<el-progress :percentage="progress"></el-progress>
</div>
</div>
</template>
<script>
import { mapState,mapGetters,mapActions } from 'vuex'
import setBackground from '@/mixins/setBackground'
import examDo from '@/mixins/examDo'
import util from '@/libs/util'
export default {
mixins: [ setBackground,examDo ],
data() {
return {
subjects: [],
timer: null,
queryStateTimer: null,
singleCount: 0,
multipleCount: 0,
judgeCount: 0,
fillBlankCount: 0,
briefAnswerCount: 0,
singleAnsweredCount: 0,
multipleAnsweredCount: 0,
judgeAnsweredCount: 0,
fillBlankAnsweredCount: 0,
briefAnswerAnsweredCount: 0,
singlePoint: 0,
multipleChoiceScore: 0,
judgeScore: 0,
fillBlanksScore: 0,
briefAnswerScore: 0,
scoreList: [],
questionType: ['单选题','多选题','判断题','填空题','简答题'],
startTime: new Date().getTime(),
time: '00:00:00',
progress: 0,
isSubmit: false,
isDone: false,
totalLen: 0,
submiting: false
};
},
computed: {
...mapState('user', [
'userId'
]),
...mapState('exam', [
'testPaperId','assessmentId','teacherId','classId','duration'
]),
},
directives: {
countdown: {
bind: function(el,binding,vnode) {
let that = vnode.context
let duration = that.duration
let time = duration > 60 ? util.formateTime(Math.floor(duration / 60)) + ':' + util.formateTime(Math.floor(duration % 60)) + ':00' : `00:${duration}:00`
that.timer = setInterval(() => {
let timeList = time.split(':')
let total = Number.parseInt(timeList[0] * 60 * 60) + Number.parseInt(timeList[1] * 60) + Number.parseInt(timeList[2])
if(total > 0){
--total
let hours = Math.floor(total / (60 * 60))
let minutes = Math.floor(total % (60 * 60) / 60)
let seconds = Math.floor(total % (60 * 60) % 60)
time = `${util.formateTime(hours)}:${util.formateTime(minutes)}:${util.formateTime(seconds)}`
}else{
that.isDone = true
that.save()
clearInterval(that.timer)
}
that.time = time
},1000)
}
}
},
mounted() {
this.getData()
this.addLeaveEvent()
this.queryState()
},
beforeDestroy(){
clearInterval(this.timer)
clearInterval(this.queryStateTimer)
window.onbeforeunload = null
window.updateProgress = null
this.addRecords()
},
methods: {
getData() {
this.$get(`${this.api.enterExam}?testPaperId=${this.testPaperId}&userId=${this.userId}&assessmentId=${this.assessmentId}`)
.then(res => {
let data = res.data
this.subjects = [
[...data.singleChoiceList],
[...data.multipleChoiceList],
[...data.trueOrFalseQuestionsList],
[...data.fillInTheBlanklist],
[...data.shortAnswerList],
]
this.singleCount = data.singleChoiceList.length
this.multipleCount = data.multipleChoiceList.length
this.judgeCount = data.trueOrFalseQuestionsList.length
this.fillBlankCount = data.fillInTheBlanklist.length
this.briefAnswerCount = data.shortAnswerList.length
this.singlePoint = data.singleChoiceList.length ? data.singleChoiceList[0].singleChoiceScore : 0
this.multipleChoiceScore = data.multipleChoiceList.length ? data.multipleChoiceList[0].multipleChoiceScore : 0
this.judgeScore = data.trueOrFalseQuestionsList.length ? data.trueOrFalseQuestionsList[0].judgeScore : 0
this.fillBlanksScore = data.fillInTheBlanklist.length ? data.fillInTheBlanklist[0].fillBlanksScore : 0
this.briefAnswerScore = data.shortAnswerList.length ? data.shortAnswerList[0].briefAnswerScore : 0
this.scoreList = [this.singlePoint,this.multipleChoiceScore,this.fillBlanksScore,this.briefAnswerScore,this.briefAnswerScore]
this.handleOptions()
})
.catch(err => {})
},
getAnswer() {
this.$get(`${this.api.queryGzAnswerDetails}?userId=${this.userId}&assessmentId=${this.assessmentId}&testPaperId=${this.testPaperId}`)
.then(res => {
let records = res.data.data
let len = 0
this.subjects.map(n => len += n.length)
this.totalLen = len
this.progress = len ? Math.floor((records.length / len * 100)) : 0
this.singleAnsweredCount = records.filter(n => n.typeId == 1).length
this.multipleAnsweredCount = records.filter(n => n.typeId == 2).length
this.judgeAnsweredCount = records.filter(n => n.typeId == 3).length
this.briefAnswerAnsweredCount = records.filter(n => n.typeId == 4).length
this.fillBlankAnsweredCount = records.filter(n => n.typeId == 5).length
this.subjects.forEach((e,i) => {
e.forEach((n,k) => {
let answered = records.find(j => j.questionId == n.id)
if(answered){
if(i == 1){
n.val = answered.userAnswer.split('')
}else if(i == 3){
let answer = answered.userAnswer.split('&lt;&gt;');
[...document.querySelectorAll(`.stem${i}${k} input`)].map((n,j) => {
n.value = answer[j]
})
n.val = answered.userAnswer
}else{
n.val = answered.userAnswer
}
n.questionStatus = 1
}else{
n.questionStatus = 0
}
})
})
})
.catch(err => {})
},
handleOptions(){
let subjects = this.subjects
window.updateProgress = (item) => {
this.updateProgress(item,1)
}
let index = 0
subjects.forEach((e,i) => {
e.forEach((n,j) => {
index++
n.mediaEleId = `player${index}`
this.initMedia(n)
if(i == 1){
this.$set(n,'val',[])
}else if(i == 3){
n.questionStem = n.questionStem.replace(/\(\)\(\)\(\)/g,`<input class="input" data-index="${j}" oninput="updateProgress(this)"></input>`)
}else{
this.$set(n,'val','')
}
if(!n.options){
let options = {}
for(let i in n){
if(i.includes('option') && n[i]){
options[i.replace('option','')] = n[i]
}
}
n.options = options
}
n.video = {}
n.fileUrl = {}
})
})
this.subjects = subjects
this.getAnswer()
},
addLeaveEvent(){
window.onbeforeunload = e => {
e = e || window.event;
if (e) {
e.returnValue = '关闭提示'
}
this.addRecords()
return '关闭提示'
}
},
queryState(){
this.queryStateTimer = setInterval(() => {
this.$post(`${this.api.getStateById}?id=${this.assessmentId}`)
.then(res => {
if(res.data.state == '已结束'){
this.isDone = true
this.save()
}
})
.catch(err => {
this.$message.success('考试结束!')
this.$router.back()
})
},1000)
},
save(){
if(this.submiting) return false
this.submiting = true
let data1 = []
this.subjects.map((e,i) => {
e.map((n,k) => {
let userAnswer = ''
if(i == 1){
userAnswer = n.val.join('')
}else if(i == 3){
userAnswer = [...document.querySelectorAll(`.stem${i}${k} input`)].map(n => n.value).join('&lt;&gt;')
}else{
userAnswer = n.val
}
n.fileUrl = JSON.stringify(n.fileUrl)
n.video = JSON.stringify(n.video)
// if(userAnswer || n.fileUrl != '{}' || n.video != '{}'){
if(n.fileUrl == '{}') n.fileUrl = ''
if(n.video == '{}') n.video = ''
data1.push({
assessmentId: this.assessmentId,
questionId: n.id,
questionStatus : n.questionStatus,
testPaperId: this.testPaperId,
userAnswer,
userId: this.userId,
fileUrl: n.fileUrl,
videoAudio: n.video
})
// }
})
})
this.$post(`${this.api.coverGzAnswerDetails}?userId=${this.userId}&testPaperId=${this.testPaperId}&assessmentId=${this.assessmentId}`)
.then(res => {
this.$post(`${this.api.addGzAnswerDetails}`,data1)
.then(res => {
this.submiting = false
let timeSpent = parseInt((new Date().getTime() - this.startTime) / 1000)
let data2 = {
testPaperId: this.testPaperId,
assessmentId: this.assessmentId,
classId: this.classId,
paperId: this.testPaperId,
stuId: this.userId,
teacherId: this.teacherId,
timeSpent,
totalDuration: this.duration,
totalScore: 100
}
this.$post(`${this.api.addTestPaperRecord}`,data2)
.then(res => {
this.$post(`${this.api.calculationScore}`,data1)
.then(res => {
this.isSubmit = true
this.$message.success(this.isDone ? '考试已结束,已经自动为您提交考试!' : '提交成功')
this.$router.back()
})
.catch(err => {})
})
.catch(err => {})
})
.catch(err => {
clearInterval(this.queryStateTimer)
})
})
.catch(err => {})
},
addRecords(){
if(!this.isSubmit){
let data1 = []
this.subjects.map((e,i) => {
e.map((n,k) => {
let userAnswer = ''
if(i == 1){
userAnswer = n.val.join('')
}else if(i == 3){
userAnswer = [...document.querySelectorAll(`.stem${i}${k} input`)].map(n => n.value).join('&lt;&gt;')
}else{
userAnswer = n.val
}
if(userAnswer){
data1.push({
testPaperId: this.testPaperId,
assessmentId: this.assessmentId,
questionId: n.id,
questionStatus : n.questionStatus,
testPaperId: this.testPaperId,
userAnswer: userAnswer,
userId: this.userId
})
}
})
})
this.$post(`${this.api.coverGzAnswerDetails}?userId=${this.userId}&testPaperId=${this.testPaperId}&assessmentId=${this.assessmentId}`)
.then(res => {
this.$post(`${this.api.addGzAnswerDetails}`,data1)
.then(res => {})
.catch(err => {})
})
.catch(err => {})
}
},
},
}
</script>
<style lang="scss" scoped>
@import "@/styles/pages/exam.scss";
</style>