提交 7b5fff92 authored 作者: lihuihui's avatar lihuihui
......@@ -28,7 +28,7 @@ export default {
},
computed: {
questionTypeName() {
const map = { 1: '单选题', 2: '多选题', 5: '案例题', 6: '判断题' }
const map = { 1: '单选题', 2: '多选题', 3: '问答题', 5: '案例题', 6: '判断题', 7: '实操题', 8: '情景题' }
return map[this.data.question_type]
}
},
......
......@@ -19,12 +19,13 @@
:index="index"
:list="questionList"
:data="currentExam"
@change="handlePageChange"
@page-change="handlePageChange"
></question-numbers>
</div>
</div>
<div class="foot" id="foot-h">
<div class="exam-btn">
<div class="confirm" @click="showResult">确认答案</div>
<div @click="prevQuestion">上一题</div>
<div @click="nextQuestion">下一题</div>
</div>
......@@ -37,8 +38,9 @@
<div :class="currentItem.sign ? 'icon active' : 'icon'"></div>
<div class="txt">{{ currentItem.sign ? '已标记' : '标记' }}</div>
</div>
<div class="del-btn" v-if="hasDeleteBtn">删除</div>
<div class="end-exam-btn">
<div class="btn" v-if="hasSubmitBtn && !disabled" @click="submitExam">交卷</div>
<div class="btn" v-if="hasSubmitBtn && !disabled" @click="submitExam">{{ submitButtonText }}</div>
</div>
</div>
</div>
......@@ -54,11 +56,14 @@ export default {
components: { questionList, questionNumbers },
props: {
title: { type: String },
hasMark: { type: Boolean, default: true },
hasCollect: { type: Boolean, default: true },
hasSubmitBtn: { type: Boolean, default: true },
hasCountDown: { type: Boolean, default: true },
data: { type: Object, default: () => {} }
hasMark: { type: Boolean, default: true }, // 标记
hasCollect: { type: Boolean, default: true }, // 收藏
hasSubmitBtn: { type: Boolean, default: true }, // 提交按钮
hasDeleteBtn: { type: Boolean, default: false }, // 删除按钮
hasCountDown: { type: Boolean, default: true }, // 计时
data: { type: Object, default: () => {} },
questionItems: { type: Array, default: () => [] },
submitButtonText: { type: String, default: '交卷' } // 提交按钮显示的文字
},
data() {
return {
......@@ -87,6 +92,10 @@ export default {
deep: true,
immediate: true,
handler(value) {
if (this.questionItems.length) {
this.questionList = this.questionItems
return
}
if (value) {
const { status } = value
this.disabled = ['1', '2'].includes(status)
......@@ -94,6 +103,9 @@ export default {
this.genQuestions(value)
}
}
},
index(value) {
this.hasResult = this.currentExam.hasResult
}
},
beforeDestroy() {
......@@ -136,14 +148,21 @@ export default {
}
return result
},
// 确认答案
showResult() {
this.hasResult = true
this.questionList[this.index].hasResult = true
},
// 下一题
nextQuestion() {
const totalNumber = this.questionList.length
if (this.index + 1 < totalNumber) this.index++
this.$emit('page-change', this.currentExam)
},
// 上一题
prevQuestion() {
if (this.index !== 0) this.index--
this.$emit('page-change', this.currentExam)
},
handlePageChange(index) {
this.index = index
......@@ -173,11 +192,10 @@ export default {
},
// 组装试题数据
genQuestions(data) {
const { questions = [], answers = {} } = data
const { questions, answers = {} } = data
if (!questions) return []
this.questionList = questions.question_items.reduce((result, question) => {
question.question_list.forEach(list => {
console.log(list)
list = list.map(item => {
let userAnswers = []
let sign = false
......@@ -316,6 +334,19 @@ export default {
.rigth-btn {
display: flex;
margin-left: auto;
.del-btn {
margin-top: 10px;
width: 100px;
height: 40px;
border-radius: 4px;
border: 1px solid #cccccc;
line-height: 40px;
font-size: 14px;
font-weight: bold;
color: #999999;
text-align: center;
margin-right: 30px;
}
.end-exam-btn {
background: #fff;
height: 62px;
......@@ -325,6 +356,7 @@ export default {
display: flex;
justify-content: center;
align-items: center;
.btn {
cursor: pointer;
width: 200px;
......
......@@ -88,7 +88,7 @@ export default {
}
},
handleClick(data) {
this.$emit('change', data.index, data)
this.$emit('page-change', data.index, data)
}
}
}
......
<template>
<div>
<div class="answer-box">
<div class="head" id="head-h">
<el-button icon="el-icon-arrow-left" circle @click="$router.back()"></el-button>
<div class="title">{{ $route.query.type == 1 ? '我的错题' : $route.query.type == 2 ? '收藏试题' : '已做试题' }}</div>
<div class="right">
<div class="count">{{ questionParams.question.sheet_time }}</div>
</div>
</div>
<div class="exam-main" :style="{height: this.contentHeight + 'px'}">
<div class="left">
<question
v-if="Object.keys(questionParams.question).length"
:contentHeight="contentHeight"
:questionParams="questionParams"
ref="confirmBtn"
></question>
</div>
<div class="right">
<answer-card
:questionParams="questionParams"
@cardChangeQuention="goAppointQuestion"
></answer-card>
</div>
</div>
<div class="foot" id="foot-h">
<div class="exam-btn">
<div class="confirm"
v-if="this.questionParams.question.answer_count > 1 && $route.query.type != 3"
@click="confirmBtn"
>
确认答案
</div>
<div
@click="changeIndex('prev')"
:class="this.questionParams.questionIndex !== 0 ? 'active' : ''"
>上一题</div>
<div
:class="questionParams.questionIndex + 1 !== questionParams.question.total_question_count ? 'active' : ''"
@click="changeIndex('next')"
>下一题</div>
</div>
<div class="rigth-btn">
<div class="sign" @click="collectQuestion" v-if="$route.query.type != 2">
<div :class="questionParams.question.is_collection ? 'icon active' : 'icon'"></div>
<div class="txt">{{ questionParams.question.is_collection ? '已收藏' : '收藏' }}</div>
</div>
<div class="del-btn" @click="deleteQuestion">删除</div>
<div class="end-exam-btn" v-if="$route.query.type != 3">
<div class="btn" @click="clearQuestion">清空记录,重新答题</div>
</div>
</div>
</div>
</div>
</div>
<exam-card
:title="title"
:questionItems="questionItems"
:hasMark="false"
:hasDeleteBtn="true"
:hasCountDown="false"
submitButtonText="清空记录,重新答题"
@submitExam="handleSubmit"
@page-change="handlePageChange"
v-if="Object.keys(data).length"
></exam-card>
</template>
<script>
import * as api from '@/api/exam.js'
import answerCard from './components/answerCard.vue'
import question from './components/question.vue'
import ExamCard from '@/components/exam/examCard.vue'
export default {
components: {
question,
answerCard
},
components: { ExamCard },
data() {
return {
// 设置页面高
contentHeight: 0,
// 原数据
questionData: [],
// 存题
container: [],
// 过滤后的数据
afterChangeData: {},
questionParams: {
// 用户选择的选项 --- 提交后台的数据
answerRecord: {},
// 所有题 和题的信息
question: {},
questionIndex: 0,
card: {}
// beforeData: {}
}
data: {},
page: 0
}
},
mounted() {
// 赋值页面高度
this.setPageHeight()
this.initData()
},
methods: {
setPageHeight() {
this.contentHeight = parseInt(document.documentElement.clientHeight - (this.getDom('head-h').offsetHeight + this.getDom('foot-h').offsetHeight))
computed: {
title() {
return this.$route.query.type === '1' ? '错题集合' : '收藏试题'
},
// 删除试题
deleteQuestion() {
this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
questionItems() {
return this.data.list.map(groups => {
const [first = {}] = groups
return { question_item_id: '', question_type: first.question_type, question_list: groups, hasResult: false }
})
const param = {
question_id: this.questionParams.question.id,
type: this.$route.query.type
}
api
.deleteQuestion(param)
.then(response => {
this.$router.go(0)
})
.finally(() => {
})
},
// 初始化
initData() {
this.getCardAll()
this.goAppointQuestion(this.$route.query.index - 1)
this.questionParams.questionIndex = 0
window.localStorage.answerRecord
? this.questionParams.answerRecord = JSON.parse(window.localStorage.answerRecord)
: this.questionParams.answerRecord = {}
},
confirmBtn() {
this.$refs.confirmBtn.answerConfirm()
},
getDom(id) {
return document.getElementById(id)
},
// 收藏试题
collectQuestion() {
const data = this.questionParams.question
console.log(data)
data.is_collection
? this.removeCall(data.id, () => {
data.is_collection = false
})
: this.addCall(data.id, () => {
data.is_collection = true
})
},
addCall(id, call) {
api
.addCollection({ question_id: id })
.then(response => {
call(response.list)
})
.finally(() => {
})
},
removeCall(id, call) {
api
.deleteCollection({ question_id: id })
.then(response => {
call(response.list)
})
.finally(() => {
})
},
// 改变数据
setData(list) {
return list.map(pList => {
return pList.map(list => {
const type = {
1: '单选题',
2: '多选题',
5: '案例题',
6: '判断题'
}
const typeTotal = {
3: 'total',
1: 'error_total',
2: 'collection_total'
}
const data = {
q_order: list.num,
question_item_type: list.question_type,
content: list.question_content,
id: list.question_id,
options: list.question_options,
question_item_title: type[parseInt(list.question_type)],
total_question_count: this.questionData[typeTotal[parseInt(this.$route.query.type)]],
question_analysis: list.question_analysis,
user_answer: list.user_answer,
is_collection: list.is_collection,
answer_count: list.answer_count,
common_content: list.common_content,
sheet_time: list.sheet_time,
rightKey: list.question_answer
}
const findAB = data.question_answer = list.question_answer.map(i => {
const findIndex = list.question_options.findIndex(opt => { return opt.id === i })
return this.A_Z()[findIndex]
})
data.question_answer = findAB.sort().toString().replace(new RegExp(',', 'g'), '')
return data
})
})
beforeMount() {
// 获取考卷
this.getTopic()
},
methods: {
// 获取考卷
getTopic(page, call) {
getTopic() {
const query = this.$route.query
const param = {
type: this.$route.query.type,
question_type: this.$route.query.qType,
page: page,
type: query.type,
question_type: query.qType,
page: this.page,
page_size: 20
}
api
.getMyQuestion(param)
.then(response => {
this.questionData = response
call(response.list)
})
.finally(() => {
api.getMyQuestion(param).then(response => {
this.data = response
})
},
// 获取答题卡所有题
getCardAll() {
const param = {
type: parseInt(this.$route.query.type) === 3 ? 0 : this.$route.query.type,
question_type: this.$route.query.qType
}
api
.getAllQuestion(param)
.then(response => {
if (response.list[0].question) {
this.questionParams.card = this.setCardData(response.list)
} else {
this.questionParams.card = response.list
}
})
.finally(() => {
})
// 缓存答案
handleCache(data) {
const params = this.genSubmitData(data)
api.setCourseCache(Object.assign(params, { status: 0 }))
},
setCardData(list) {
return list.map(item => {
item.question = JSON.parse(item.question)
return item
// 清空
handleSubmit(data) {
const params = this.genSubmitData(data)
api.setCourseCache(Object.assign(params, { status: 1 })).then(res => {
this.$router.replace({
path: '/course/chapter/result',
query: Object.assign({}, this.$route.query, { type: 2 })
})
},
// ABC
A_Z() {
const result = []
for (let i = 0; i < 26; i++) {
result.push(String.fromCharCode(65 + i))
}
return result
},
// 点击上一题下一题 答题卡序号
changeData() {
let datas = []
this.questionData.list.map(list => {
const findData = list.find(item => {
return item.q_order === this.questionParams.questionIndex + 1
})
if (findData) {
datas = list
return false
}
})
this.questionParams.question = datas
},
// 进入指定的题
goAppointQuestion(n) {
this.container = []
this.questionData.list = []
const page = parseInt(n / 20)
if (page === 0) {
this.getTopic(page + 1, data => {
this.container = this.setData(data)
this.questionData.list = this.container
this.questionParams.questionIndex = parseInt(n)
this.changeData()
})
} else {
this.getTopic(page, data => {
this.container = this.setData(data)
this.questionData.list = this.container
})
this.getTopic(page + 1, data => {
this.addCont(data, 1)
this.questionData.list = this.container
this.questionParams.questionIndex = parseInt(n)
this.changeData()
})
}
},
// 改变题序
changeIndex(type) {
if (type === 'prev') {
if (this.questionParams.questionIndex > 0) {
this.questionParams.questionIndex--
const isData = this.questionData.list.findIndex(i => { return i.q_order === this.questionParams.questionIndex + 1 })
!isData && (this.supplyRequest())
}
} else {
if (parseInt(this.questionParams.questionIndex + 1) !== parseInt(this.questionParams.question.total_question_count)) {
this.questionParams.questionIndex++
const isData = this.questionData.list.find(i => { return i.q_order === this.questionParams.questionIndex + 2 })
!isData && (this.supplyRequest(1))
}
}
},
// 加载部分试题
supplyRequest(n) {
// const loading = this.$loading({
// lock: true,
// text: 'Loading',
// spinner: 'el-icon-loading',
// background: 'rgba(0, 0, 0, 0.7)'
// })
this.getTopic(parseInt((n ? this.questionParams.questionIndex + 2 : this.questionParams.questionIndex - 2) / 20) + 1, data => {
if (this.container.length >= 40) {
n ? this.container.splice(0, 20) : this.container.splice(20, 20)
this.addCont(data, n)
} else {
this.addCont(data, n)
}
this.questionData.list = this.container
this.changeData()
// loading.close()
})
},
addCont(data, n) {
const changeData = n ? data : data.reverse()
this.setData(changeData).map(item => {
n ? this.container.push(item) : this.container.unshift(item)
})
handlePageChange(data) {
console.log(data)
},
// 缓存 提交
handlePapers(n) {
const answerData = {}
for (const data in this.questionParams.answerRecord) {
answerData[data] = this.questionParams.answerRecord[data].answer
}
const param = {
type: this.$route.query.type,
question_type: this.$route.query.qType,
answer: JSON.stringify(answerData)
// 组装提交数据
genSubmitData(questionList) {
const answers = {}
questionList.forEach(item => {
if (!answers[item.question_item_id]) {
answers[item.question_item_id] = {}
}
window.localStorage.answerRecord = JSON.stringify(this.questionParams.answerRecord)
this.chcheReq(param, () => {})
},
// 清除所有答案 重新答题
clearQuestion() {
const param = {
type: this.$route.query.type,
question_type: this.$route.query.qType,
clear: 1
item.question_list.forEach(cItem => {
answers[item.question_item_id][cItem.id] = {
sign: cItem.sign ? cItem.sign : false,
answers: cItem.user_answer
}
this.chcheReq(param, () => {
this.questionParams.questionIndex = 0
window.localStorage.removeItem('answerRecord')
this.initData()
this.$router.go(0)
})
},
chcheReq(param, call) {
api
.setMyCache(param)
.then(response => {
call()
})
.finally(() => {
})
return {
type: 1,
sheet_id: this.data.id,
status: 0,
answers: JSON.stringify(answers),
duration: 0
}
},
computed: {
changeQuestionIndex() {
return this.questionParams.questionIndex
}
},
watch: {
// 监听题的变化
changeQuestionIndex(newV, oldV) {
this.changeData()
parseInt(this.$route.query.type) !== 3 && (this.handlePapers())
}
}
}
</script>
<style lang="scss" scoped>
.answer-box{
width: 100%;
height: 100%;
// background: #f9f9f9;
.head{
border-bottom: 1px solid #ccc;
height: 80px;
background: #FFFFFF;
display: flex;
align-items: center;
padding-left: 40px;
.title{
padding-left: 20px;
font-size: 24px;
font-weight: bold;
color: #222222;
line-height: 80px;
}
.right{
width: 260px;
margin-left: auto;
display: flex;
justify-content: space-around;
align-items: center;
.count{
font-size: 18px;
font-weight: bold;
color: #222222;
}
.time{
display: flex;
.icon{
width: 23px;
height: 23px;
// background: url(../../assets/images/tick.png);
background-size:100% 100%;
}
.mun{
font-size: 18px;
font-weight: bold;
color: #222222;
line-height: 25px;
margin-left: 10px;
}
}
}
}
.exam-main{
display: flex;
.left{
background: #fff;
flex: 1;
padding: 10px 20px 0 53px;
overflow-y: scroll;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
.right{
border-left: 1px solid #ccc;
position: relative;
width: 220px;
background: #fff;
padding: 0 20px;
overflow-y: scroll;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
}
.foot{
border-top: 1px solid #ccc;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 60px;
background: #FFFFFF;
display: flex;
align-items: center;
.exam-btn{
display: flex;
padding-left: 40px;
.confirm{
width: 140px;
height: 40px;
background: #C01540;
border-radius: 4px;
font-size: 14px;
font-weight: bold;
color: #FFFFFF;
line-height: 40px;
text-align: center;
}
cursor: pointer;
div{
width: 100px;
height: 40px;
border-radius: 4px;
border: 1px solid #CCCCCC;
font-size: 14px;
font-weight: bold;
color: #999999;
line-height: 40px;
text-align: center;
margin-right: 20px;
&.active{
background: #C01540;
border-radius: 4px;
color: #fff;
}
}
}
.rigth-btn{
display: flex;
margin-left: auto;
.del-btn{
margin-top: 10px;
width: 100px;
height: 40px;
border-radius: 4px;
border: 1px solid #CCCCCC;
line-height: 40px;
font-size: 14px;
font-weight: bold;
color: #999999;
text-align: center;
margin-right: 30px;
}
.end-exam-btn{
background: #fff;
height: 62px;
margin-top: -2px;
border-left: 1px solid #ccc;
width: 260px;
display: flex;
justify-content: center;
align-items: center;
.btn{
cursor: pointer;
width: 200px;
height: 40px;
background: #c01540;
border-radius: 4px;
font-size: 14px;
font-weight: bold;
color: #fff;
line-height: 40px;
text-align: center;
}
}
.sign{
margin-right: 20px;
margin-top: 8px;
.icon{
margin: 0 auto;
width: 24px;
height: 24px;
background: url(@/assets/images/collection.png);
background-size:100% 100%;
&.active{
background: url(@/assets/images/collection2.png);
background-size:100% 100%;
}
}
.txt{
font-size: 14px;
color: #CCCCCC;
line-height: 20px;
margin-top: 2px;
}
}
}
}
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论