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
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('<>'); |
|
[...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('<>') |
|
}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('<>') |
|
}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> |