<template>
|
|
<el-row class="morpheus-box">
|
<el-col :span="24">
|
<el-card>
|
|
<div class="exam-card-body">
|
|
<div class="subject-box">
|
<el-row :gutter="30">
|
<el-col :span="5">
|
<div class="tool-bar">
|
<div class="time-remain">
|
剩余时间:
|
<div class="time">
|
<count-down v-on:start_callback="countDownS_cb(1)"
|
v-on:end_callback="countDownE_cb(1)"
|
:current-time="currentTime"
|
:start-time="startTime"
|
:end-time="endTime"
|
:tip-text="'距离考试开始'"
|
:tip-text-end="'距离考试结束'"
|
:end-text="'考试结束'"
|
:hourTxt="':'"
|
:minutesTxt="':'"
|
:secondsTxt="''">
|
</count-down>
|
</div>
|
</div>
|
<div class="current-progress">
|
当前进度: {{subjectIndex}}/{{subjectIds.length}}
|
</div>
|
<div class="answer-card">
|
<el-button type="text"
|
icon="el-icon-date"
|
@click="answerCard">答题卡</el-button>
|
</div>
|
<el-button type="success"
|
icon="el-icon-date"
|
@click="submitExam"
|
v-bind:disabled="disableSubmit">提交</el-button>
|
</div>
|
</el-col>
|
<el-col :span="18">
|
<div class="subject-box-card">
|
<div class="subject-exam-title">{{exam.examinationName}}(共{{subjectIds.length}}题,合计{{exam.totalScore}}分)</div>
|
<!-- 题目内容 -->
|
<choices ref="choices"
|
v-show="this.query.type === 0" />
|
|
<multiple-choices ref="multipleChoices"
|
v-show="this.query.type === 1" />
|
|
<judgement ref="judgement"
|
v-show="this.query.type === 2" />
|
|
<practical-operation ref="practicalOperation"
|
v-show="this.query.type === 3" />
|
|
<short-answer ref="shortAnswer"
|
v-show="this.query.type === 4" />
|
|
<div class="subject-buttons"
|
v-if="query.subjectId !== ''">
|
|
<el-button plain
|
@click="last"
|
:loading="loadingLast">上一题</el-button>
|
<el-button plain
|
@click="next"
|
:loading="loadingNext">下一题</el-button>
|
<el-button type="success"
|
@click="submitExam"
|
v-bind:disabled="disableSubmit">提交</el-button>
|
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
<el-dialog title="答题卡"
|
:visible.sync="dialogVisible"
|
width="50%"
|
top="10vh"
|
:modal='false'
|
center>
|
<div class="answer-card-title">{{exam.examinationName}}(共{{subjectIds.length}}题,合计{{exam.totalScore}}分)</div>
|
<div class="answer-card-split"></div>
|
<el-row class="answer-card-content">
|
<el-button :class="{ 'answered': subjectIds[index].answered }"
|
circle
|
v-for="(value, index) in subjectIds"
|
:key="index"
|
@click="toSubject(value.everyID, value.type, index)"> {{index + 1}} </el-button>
|
</el-row>
|
</el-dialog>
|
</div>
|
|
</div>
|
|
</el-card>
|
</el-col>
|
</el-row>
|
|
</template>
|
<script>
|
import { mapState } from 'vuex'
|
import CountDown from 'vue2-countdown'
|
import { saveAndNext } from '@/api/exam/answer'
|
import { getSubjectIds } from '@/api/exam/exam'
|
import { getCurrentTime } from '@/api/exam/examRecord'
|
import { getSubjectAnswer } from '@/api/exam/subject'
|
|
import moment from 'moment'
|
import { messageSuccess, messageFail, messageWarn, isNotEmpty } from '@/util/util'
|
import Tinymce from '@/components/Tinymce'
|
import Choices from '@/components/Subjects/Choices'
|
|
import MultipleChoices from '@/components/Subjects/MultipleChoices'
|
import PracticalOperation from '@/components/Subjects/PracticalOperation'
|
|
|
|
|
// import ShortAnswer from '@/components/Subjects/ShortAnswer'
|
import Judgement from '@/components/Subjects/Judgement'
|
|
import { nextSubjectType } from '@/const/constant'
|
|
export default {
|
components: {
|
CountDown,
|
Tinymce,
|
Choices,
|
MultipleChoices,
|
PracticalOperation,
|
Judgement,
|
// ShortAnswer,
|
},
|
data () {
|
return {
|
loadingLast: false,
|
loadingNext: false,
|
|
currentTime: 0,
|
startTime: 0,
|
endTime: 0,
|
disableSubmit: true,
|
subjectIndex: 1,
|
query: {
|
examinationId: undefined,
|
examRecordId: undefined,
|
subjectId: undefined,
|
userId: undefined,
|
type: 0
|
},
|
subject: {},
|
answer: '',
|
dialogVisible: false,
|
subjectIds: [],
|
subjectStartTime: undefined,
|
exam: {
|
id: '590969316204220416',
|
creator: 'admin',
|
createDate: 1560939664000,
|
modifier: 'preview',
|
modifyDate: 1609835214000,
|
|
delFlag: 0,
|
|
examinationName: '',
|
|
startTime: null,
|
endTime: null,
|
|
totalScore: 50,
|
|
status: 0,
|
|
|
remark: '全国计算机统考练习题10道',
|
|
newRecord: false
|
},
|
firstFlag: true
|
}
|
},
|
computed: {
|
...mapState({
|
userInfo: state => state.user.userInfo
|
})
|
},
|
created () {
|
|
const examInfo = this.$route.params.id
|
|
if (isNotEmpty(examInfo)) {
|
// 试卷ID
|
this.query.examinationId = this.$route.params.id
|
|
// 考场ID
|
this.query.examRecordId = this.userInfo.user_id
|
|
this.query.userId = this.userInfo.user_id
|
|
this.exam.id = this.userInfo.user_id + '' + this.$route.params.id
|
|
this.exam.examinationName = this.$route.query.examName
|
this.exam.startTime = this.$route.query.startTime
|
this.exam.endTime = this.$route.query.endTime
|
this.exam.totalScore = this.$route.query.totalScore
|
this.exam.status = this.$route.query.examStatus
|
this.exam.remark = this.$route.query.remark
|
|
this.validateExamTime()
|
}
|
},
|
methods: {
|
countDownS_cb: function () {
|
messageSuccess(this, '考试开始')
|
},
|
validateExamTime () {
|
getCurrentTime().then(response => {
|
const currentTime = moment(response.data.data)
|
if (currentTime.isAfter(this.exam.endTime)) {
|
messageWarn(this, '考试已结束')
|
} else if (currentTime.isBefore(this.exam.startTime)) {
|
messageWarn(this, '考试未开始')
|
} else {
|
this.startExam()
|
const current = currentTime.valueOf()
|
this.currentTime = current
|
this.startTime = current
|
this.subjectStartTime = current
|
this.endTime = moment(this.exam.endTime).valueOf()
|
this.disableSubmit = false
|
}
|
}).catch(() => {
|
messageFail(this, '开始考试失败!15')
|
})
|
},
|
startExam () {
|
// 获取题目ID列表
|
getSubjectIds().then(subjectResponse => {
|
const subjectData = subjectResponse.data.data
|
if (subjectData.length > 0) {
|
for (let i = 0; i < subjectData.length; i++) {
|
this.subjectIds.push({
|
subjectId: 1,
|
everyID: subjectData[i].id,
|
type: subjectData[i].choicesType,
|
index: i + 1,
|
answered: false,
|
answer: subjectData[i].answer,
|
score: subjectData[i].score
|
})
|
}
|
|
this.query.type = parseInt(this.subjectIds[0].type)
|
|
// 准考证号
|
this.query.subjectId = this.subjectIds[0].everyID
|
|
this.updateSubjectIndex()
|
// 获取当前题目信息
|
getSubjectAnswer({
|
id: this.subjectIds[0].everyID,
|
}).then(response => {
|
if (isNotEmpty(response.data.data)) {
|
this.setSubjectInfo(response.data.data)
|
}
|
}).catch(() => {
|
messageFail(this, '获取题目失败!')
|
})
|
}
|
}).catch(() => {
|
messageFail(this, '开始考试失败!4646549888*8*')
|
})
|
},
|
countDownE_cb: function () {
|
messageWarn(this, '考试结束')
|
this.disableSubmit = true
|
},
|
last () {
|
|
for (let i = 0; i < this.subjectIds.length; i++) {
|
|
if (this.subjectIds[i].everyID == this.query.subjectId) {
|
|
this.subjectIds[i].answer = this.getAnswer()
|
|
this.markAnswered(this.subjectIds[i].answer, i)
|
|
if (i === 0) {
|
messageSuccess(this, '已经是第一题了')
|
break
|
}
|
|
let { everyID, type, index } = this.subjectIds[--i]
|
|
this.subjectIndex = index
|
|
this.saveCurrentSubjectAndGetNextSubject(nextSubjectType.last, everyID, type)
|
|
break
|
|
}
|
|
}
|
|
},
|
next () {
|
|
for (let i = 0; i < this.subjectIds.length; i++) {
|
|
if (this.subjectIds[i].everyID == this.query.subjectId) {
|
|
this.subjectIds[i].answer = this.getAnswer()
|
|
this.markAnswered(this.subjectIds[i].answer, i)
|
|
if (i === this.subjectIds.length - 1) {
|
messageSuccess(this, '已经是最后一题了')
|
break
|
}
|
|
let { everyID, index } = this.subjectIds[++i]
|
|
this.subjectIndex = index
|
|
this.saveCurrentSubjectAndGetNextSubject(nextSubjectType.next, everyID)
|
|
break
|
|
}
|
|
}
|
|
},
|
// 保存当前题目,同时根据序号加载下一题
|
saveCurrentSubjectAndGetNextSubject (nextType, nextSubjectId) {
|
|
|
this.startLoading(nextType)
|
|
getSubjectAnswer({ id: nextSubjectId }).then(response => {
|
|
if (response.data.data !== null) {
|
|
// 保存成功后更新答题卡状态
|
const subject = response.data.data
|
const { id, choicesType } = subject
|
|
this.query.subjectId = id
|
|
this.query.type = choicesType
|
|
for (let i = 0; i < this.subjectIds.length; i++) {
|
|
if (this.subjectIds[i].everyID == nextSubjectId) {
|
|
subject.answer = this.subjectIds[i].answer
|
|
break
|
|
}
|
|
}
|
|
|
|
this.setSubjectInfo(subject)
|
|
// store.dispatch('SetSubjectInfo', subject).then(() => { })
|
|
}
|
// 更新时间
|
getCurrentTime().then(response => {
|
this.subjectStartTime = moment(response.data.data)
|
})
|
this.endLoading(nextType)
|
}).catch((error) => {
|
console.log(error)
|
messageFail(this, '获取题目失败')
|
this.endLoading(nextType)
|
})
|
},
|
markAnswered (answer, index) {
|
if (answer && answer !== null) {
|
this.subjectIds[index].answered = true
|
}
|
},
|
// 答题卡
|
answerCard () {
|
this.dialogVisible = true
|
},
|
// 跳转题目
|
toSubject (everyID, type, index) {
|
|
var ind = this.subjectIndex;
|
|
if (this.firstFlag == false) {
|
ind = this.subjectIndex;
|
} else {
|
ind = this.subjectIndex - 1;
|
}
|
|
|
this.subjectIds[ind].answer = this.getAnswer()
|
|
this.markAnswered(this.subjectIds[ind].answer, ind)
|
|
this.subjectIndex = index + 1
|
this.firstFlag = true;
|
// 保存当前题目,同时加载下一题
|
this.saveCurrentSubjectAndGetNextSubject(nextSubjectType.next, everyID, type)
|
|
this.dialogVisible = false
|
},
|
// 提交
|
submitExam () {
|
|
var ind = this.subjectIndex;
|
|
if (this.firstFlag == false) {
|
ind = this.subjectIndex;
|
} else {
|
ind = this.subjectIndex - 1;
|
}
|
|
|
this.subjectIds[ind].answer = this.getAnswer()
|
|
this.markAnswered(this.subjectIds[ind].answer, ind)
|
|
this.$confirm('确定要提交吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
this.disableSubmit = true
|
this.doSubmitExam()
|
}).catch(() => {
|
})
|
},
|
doSubmitExam () {
|
var obj = {
|
examName: this.$route.query.examName,
|
securityName: this.userInfo.user_name,
|
userId: this.userInfo.user_id,
|
allScore: this.$route.query.totalScore,
|
company: this.userInfo.dept_id,
|
examTime: this.$route.query.startTime,
|
papersId: this.$route.query.id,
|
examEndTime: this.$route.query.endTime,
|
examResultVOS: null
|
|
}
|
|
var arr = []
|
|
|
this.subjectIds.forEach((item) => {
|
|
|
if (item.type == 3) {
|
|
var str = ''
|
|
if (item.answer.length > 0) {
|
item.answer.forEach(it => {
|
|
if (it.value != '') {
|
str += it.value + ','
|
}
|
|
})
|
|
var a = str.substr(0, str.length - 1);
|
|
|
arr.push(
|
{
|
"subjectChoicesId": item.everyID,
|
"value": a,
|
"grade": item.score
|
}
|
|
)
|
}
|
} else {
|
arr.push(
|
{
|
"subjectChoicesId": item.everyID,
|
"value": item.answer,
|
"grade": item.score
|
}
|
|
)
|
}
|
|
})
|
|
obj.examResultVOS = arr
|
|
saveAndNext(obj).then(response => {
|
messageSuccess(this, '提交成功')
|
if (response) {
|
this.$store.commit("DEL_TAG", this.$store.state.tags.tag);
|
this.$router.push({
|
path: `/singleperformance/index`,
|
});
|
}
|
|
}).catch(() => {
|
this.disableSubmit = false
|
messageFail(this, '提交题目失败')
|
})
|
},
|
// 选中选项
|
toggleOption (answer) {
|
this.answer = answer
|
},
|
// 根据题目类型返回填写的答案
|
getAnswer () {
|
const ref = this.getSubjectRef()
|
if (isNotEmpty(ref)) {
|
const answer = ref.getAnswer()
|
this.answer = answer
|
return answer
|
// {
|
// id: answerId,
|
// userId: this.userInfo.id,
|
// examinationId: this.query.examinationId,
|
// examRecordId: this.query.examRecordId,
|
// subjectId: this.query.subjectId,
|
// answer: answer,
|
// type: this.query.type,
|
// startTime: this.subjectStartTime
|
// }
|
}
|
return {}
|
},
|
// 获取题目索引
|
getSubjectIndex (targetId) {
|
for (let subject of this.subjectIds) {
|
let { subjectId, index } = subject
|
if (subjectId === targetId) {
|
return index
|
}
|
}
|
return 1
|
},
|
// 更新题目索引
|
updateSubjectIndex () {
|
this.subjectIndex = this.getSubjectIndex(this.query.subjectId)
|
},
|
startLoading (nextType) {
|
if (nextType === nextSubjectType.next) {
|
this.loadingNext = true
|
} else if (nextType === nextSubjectType.last) {
|
this.loadingLast = true
|
} else {
|
this.loadingNext = true
|
}
|
},
|
endLoading (nextType) {
|
if (nextType === nextSubjectType.next) {
|
this.loadingNext = false
|
} else if (nextType === nextSubjectType.last) {
|
this.loadingLast = false
|
} else {
|
this.loadingNext = false
|
}
|
},
|
getSubjectRef () {
|
let ref
|
|
switch (this.query.type) {
|
case 0:
|
ref = this.$refs.choices
|
break
|
case 1:
|
ref = this.$refs.multipleChoices
|
|
break
|
case 2:
|
ref = this.$refs.judgement
|
break
|
case 3:
|
ref = this.$refs.practicalOperation
|
break
|
case 4:
|
ref = this.$refs.shortAnswer
|
break
|
}
|
return ref
|
},
|
setSubjectInfo (subject) {
|
|
const ref = this.getSubjectRef()
|
|
if (isNotEmpty(ref)) {
|
try {
|
ref.setSubjectInfo(subject, this.subjectIds.length, this.subjectIndex)
|
} catch (error) {
|
console.error(error)
|
}
|
}
|
}
|
}
|
}
|
</script>
|
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
<style lang="scss" rel="stylesheet/scss" scoped>
|
.subject-box {
|
margin-top: 50px;
|
margin-left: 20px;
|
}
|
.subject-box-card {
|
width: 80%;
|
margin-bottom: 30px;
|
min-height: 400px;
|
}
|
.subject-buttons {
|
text-align: right;
|
}
|
.tool-bar {
|
margin-left: 20px;
|
}
|
.time-remain .time {
|
display: inline-block;
|
font-size: 18px;
|
line-height: 22px;
|
color: #ff0000;
|
font-weight: 400;
|
}
|
|
/* 答题卡 */
|
.answer-card-title {
|
font-size: 13px;
|
color: #3a3e51;
|
line-height: 17px;
|
padding: 10px 0;
|
}
|
.answer-card-split {
|
width: 100%;
|
border-bottom: 1px solid #e6e6e6;
|
}
|
.answer-card-content {
|
padding-bottom: 10px;
|
font-size: 0;
|
margin-right: -15px;
|
> button {
|
margin-top: 5px;
|
}
|
}
|
.answered {
|
background-color: greenyellow;
|
}
|
</style>
|