提交 1a8b9f97 authored 作者: lihuihui's avatar lihuihui

知识点考试修改

上级 e4609e8c
...@@ -22,3 +22,15 @@ export function getExamStatus(data) { ...@@ -22,3 +22,15 @@ export function getExamStatus(data) {
headers: { 'Content-Type': 'multipart/form-data' } headers: { 'Content-Type': 'multipart/form-data' }
}) })
} }
/* 知识点考题获取 */
export function getExam(data) {
return httpRequest.get('/zy/v2/examination/course-papers', data)
}
/* 知识点考题缓存 */
export function cacheExam(data) {
return httpRequest.post('/zy/v2/examination/course-papers', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
<template>
<div class="exam-box">
<!-- <div class="no-swiping" v-if="countPage.noSwiping"></div> -->
<div class="topic-box">
<swiper ref="mySwiper" :options="swiperOptions">
<template v-for="item in question.list">
<template v-for="(cItem, cIndex) in item.question_list">
<swiper-slide :key="cIndex+cItem.id">
<div id="top-view">
<div class="tool-box">
<div class="time">{{time.showTime}}</div>
<div class="tag-box">
<span @click="collectQuestion(cItem)">{{ cItem.is_collection ? '已收藏' : '收藏' }}</span>
</div>
</div>
</div>
<div class="title">
<div class="type">{{other.type[cItem.question_type]}}</div>
<div class="count">{{ other.pageOrderNum + 1 }}/{{ other.totalQuestionCount }}</div>
</div>
<div class="topic-bt" v-if="cItem.question_type == '5'" v-html="cItem.common_content"></div>
<div class="topic" v-html="cItem.question_content"></div>
<ul class="option">
<template v-for="(opt, oIndex) in cItem.question_options">
<template v-if="item.question_type == 2 || (item.question_type == 5 && item.answer_count > 1)">
<li
:key="oIndex + opt.id"
:class="cItem.isConfirm
? cItem.question_answer.find(i => { return i === opt.id })
? 'active2'
: cItem.userAnswer.find(i => { return i === opt.id })
? 'active'
: ''
: cItem.userAnswer.find(i => { return i === opt.id })
? 'active'
: ''"
@click="selectOptions(item, cItem, opt)"
>
<van-icon
v-if="cItem.isConfirm && cItem.question_answer.find(i => { return i === opt.id })"
class="icon"
name="checked"
/>
<div>
<span
v-if="!cItem.isConfirm || !cItem.question_answer.find(i => { return i === opt.id })"
>{{ other.A_Z[oIndex] }}.</span>
<span>{{ opt.option }}</span>
</div>
</li>
</template>
<template v-else>
<li
:key="oIndex + opt.id"
:class="isObjKey(item, cItem)
? cItem.question_answer === opt.id
? 'active2'
: question.answers[item.question_item_id][cItem.id].answers.find(i => { return i === opt.id })
? 'active'
: ''
: ''"
@click="selectOptions(item, cItem, opt)"
>
<van-icon
v-if="isObjKey(item, cItem)
? cItem.question_answer === opt.id
? true
: false
: false"
class="icon"
name="checked"
/>
<div>
<span
v-if="isObjKey(item, cItem)
? cItem.question_answer === opt.id
? false
: true
: true
">{{ other.A_Z[oIndex] }}.</span>
<span>{{ opt.option }}</span>
</div>
</li>
</template>
</template>
</ul>
<div class="com-btn" @click="confirmSelect(item, cItem)" v-if="item.question_type == 2 || (item.question_type == 5 && item.answer_count > 1)">确认答案</div>
<div class="analy" v-if="isObjKey(item, cItem)">
<div class="tit">答案解析</div>
<div class="txt">正确答案:
<span>
{{
changeA_Z(changeArray(cItem.question_answer), cItem)
}}
</span>
</div>
<div class="txt">您的答案:
<span>
{{
isObjKey(item, cItem)
? changeA_Z(question.answers[item.question_item_id][cItem.id].answers, cItem)
: ''
}}
</span>
</div>
<div class="exp">
<p class="name">解析:</p>
<p class="nr" v-html="cItem.question_analysis"></p>
<!-- <p class="nr" v-html="dItem.question_analysis"></p> -->
</div>
</div>
</swiper-slide>
</template>
</template>
</swiper>
</div>
<div class="btn-box" id="bottom-view-btn">
<div class="padd">
<div @click="swiper.slidePrev()" class="btn left btn-w" v-show="isBtn.currentPageNum != 0">上一题</div>
<div @click="swiper.slideNext()" class="btn right btn-w" v-show="isBtn.currentPageNum != other.totalQuestionCount - 1">下一题</div>
</div>
</div>
</div>
</template>
<script>
import * as api from '@/api/courseExam.js'
import * as apiMy from '@/api/my.js'
import { Swiper, SwiperSlide, directive } from 'vue-awesome-swiper'
import { Toast, Dialog } from 'vant'
export default {
beforeDestroy() {
// window.localStorage.isCache = false
this.cacheRequest()
clearInterval(this.time.clearTime)
},
components: {
Swiper,
SwiperSlide,
[Toast.name]: Toast,
[Dialog.name]: Dialog
},
directives: {
swiper: directive
},
data() {
const _this = this
return {
isBtn: {
currentPageNum: 0
},
question: {
list: [],
answers: {}
},
time: {
count: 1,
clearTime: null,
showTime: ''
},
other: {
type: {
1: '单选题',
2: '多选题',
5: '案例题',
6: '判断题'
},
A_Z: ['A', 'B', 'C', 'D', 'E', 'F'],
totalQuestionCount: 1,
pageOrderNum: 0,
sheetId: 0
},
swiperOptions: {
observer: true,
autoHeight: true,
on: {
init() {
setTimeout(() => {
_this.isBtn.currentPageNum = this.activeIndex
}, 500)
},
slideChangeTransitionStart: function() {
_this.isBtn.currentPageNum = this.activeIndex
_this.other.pageOrderNum = this.activeIndex
},
slidePrevTransitionEnd: function() {
},
slideNextTransitionEnd: function() {
},
slideNextTransitionStart: function() {
}
}
}
}
},
mounted() {
this.init()
},
computed: {
swiper() {
return this.$refs.mySwiper.$swiper
},
changeArray() {
return function (item) {
return Array.isArray(item) ? item : [item]
}
},
isObjKey() {
return function (item, cItem) {
return this.question.answers
? this.question.answers[item.question_item_id]
? this.question.answers[item.question_item_id][cItem.id]
? 1
: 0
: 0
: 0
}
},
changeA_Z() {
return function (data, cItem) {
return data.map((i, index) => {
return this.other.A_Z[cItem.question_options.findIndex(id => { return id.id === i })]
}).toString().replace(new RegExp(',', 'g'), '')
}
}
},
methods: {
collectQuestion(item) {
item.is_collection
? this.removeColl(item.id, () => {
Toast('取消收藏')
item.is_collection = false
})
: this.addColl(item.id, () => {
Toast('收藏成功')
item.is_collection = true
})
console.log(item)
},
removeColl(id, callback) {
apiMy.deleteQuestion({ type: 2, question_id: id }).then(res => {
if (res.code === 0) {
callback()
}
})
},
addColl(id, callback) {
apiMy.collectQuestion({ question_id: id }).then(res => {
if (res.code === 0) {
callback()
}
})
},
setClock() {
clearInterval(this.time.clearTime)
this.time.clearTime = setInterval(() => {
this.time.count++
this.time.showTime = this.secondToDate(this.time.count)
}, 1000)
},
secondToDate(result) {
const h = Math.floor(result / 3600) < 10 ? '0' + Math.floor(result / 3600) : Math.floor(result / 3600)
const m = Math.floor((result / 60 % 60)) < 10 ? '0' + Math.floor((result / 60 % 60)) : Math.floor((result / 60 % 60))
const s = Math.floor((result % 60)) < 10 ? '0' + Math.floor((result % 60)) : Math.floor((result % 60))
if (h === 0) {
result = m + ':' + s
} else {
result = h + ':' + m + ':' + s
}
return result
},
init() {
api.getExam({ type: 2, tag_id: this.$route.query.tag_id }).then(res => {
const data = JSON.parse(res.data)
this.question.answers = data.sheet.answers
data.sheet.questions.question_items.map(item => {
return item.question_list.map(cItem => {
if (parseInt(cItem.question_type) === 2 || (parseInt(cItem.question_type) === 5 && cItem.answer_count > 1)) {
if (this.question.answers) {
if (this.question.answers[item.question_item_id]) {
if (this.question.answers[item.question_item_id][cItem.id]) {
cItem.isConfirm = true
cItem.userAnswer = this.question.answers[item.question_item_id][cItem.id].answers
return false
}
}
}
cItem.isConfirm = false
cItem.userAnswer = []
}
})
})
this.other.sheetId = data.sheet.id
this.question.list = data.sheet.questions.question_items
this.other.totalQuestionCount = data.sheet.questions.total_question_count
this.time.count = data.sheet.duration || 0
this.setClock()
})
},
confirmSelect(item, cItem) {
if (cItem.isConfirm) {
return false
}
cItem.isConfirm = true
const cacheData = this.question.answers
if (cacheData) {
cacheData[item.question_item_id]
? cacheData[item.question_item_id][cItem.id]
? cacheData[item.question_item_id][cItem.id].answers = cItem.userAnswer
: cacheData[item.question_item_id][cItem.id] = { answers: cItem.userAnswer }
: cacheData[item.question_item_id] = { [cItem.id]: { answers: cItem.userAnswer } }
this.$forceUpdate()
this.cacheRequest()
return false
}
this.question.answers = {
[item.question_item_id]: {
[cItem.id]: {
answers: cItem.userAnswer
}
}
}
this.cacheRequest()
},
selectOptions(item, cItem, opt) {
const qType = parseInt(item.question_type)
qType === 2 || (qType === 5 && item.answer_count > 1)
? this.checkboxSelect(item, cItem, opt)
: this.radioSelect(item, cItem, opt)
},
checkboxSelect(item, cItem, opt) {
if (cItem.isConfirm) {
return false
}
if (cItem.userAnswer) {
const index = cItem.userAnswer.findIndex(i => { return i === opt.id })
index === -1 ? cItem.userAnswer.push(opt.id) : cItem.userAnswer.splice(index, 1)
} else {
cItem.userAnswer = [opt.id]
}
this.$forceUpdate()
},
radioSelect(item, cItem, opt) {
if (this.isObjKey(item, cItem)) {
return false
}
const cacheData = this.question.answers
if (cacheData) {
cacheData[item.question_item_id]
? cacheData[item.question_item_id][cItem.id]
? cacheData[item.question_item_id][cItem.id].answers = [opt.id]
: cacheData[item.question_item_id][cItem.id] = { answers: [opt.id] }
: cacheData[item.question_item_id] = { [cItem.id]: { answers: [opt.id] } }
this.$forceUpdate()
this.cacheRequest()
return false
}
this.question.answers = {
[item.question_item_id]: {
[cItem.id]: {
answers: [opt.id]
}
}
}
this.cacheRequest()
this.$forceUpdate()
},
cacheRequest() {
let count = 0
const fKey = Object.keys(this.question.answers)
fKey.map(item => {
const cKey = Object.keys(this.question.answers[item])
for (let i = 0; i < cKey.length; i++) {
count++
}
})
const param = {
type: 2,
sheet_id: this.other.sheetId,
status: this.other.totalQuestionCount === count ? 1 : 0,
answers: JSON.stringify(this.question.answers),
duration: this.time.count
}
api.cacheExam(param).then(res => {})
}
}
}
</script>
<style lang="scss">
.no-swiping{
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 999999;
}
.exam-box{
.swiper-wrapper{
padding-bottom: env(safe-area-inset-bottom);
.swiper-slide{
padding-bottom: 1.2rem;
}
}
.head{
color: #222;
display: flex;
padding: .4rem 0;
align-items: center;
i{
font-size: .35rem;
margin-left: .28rem;
}
.title{
margin-left: .03rem;
font-size: .3rem;
}
}
.tool-box{
width: 6.7rem;
border-bottom: .01rem solid rgba(238,238,238,1);
padding: .35rem 0;
display: flex;
align-items: center;
margin: 0 auto;
color: #222;
.time{
font-size: .3rem;
}
.tag-box{
margin-left: auto;
display: flex;
span{
padding: .1rem .2rem;
font-size: .2rem;
color: #fff;
background: #F47885;
border-radius: .25rem;
margin-left: .2rem;
}
.active{
background: #FF8000;
}
}
}
.topic-box{
width: 100%;
margin: 0 auto;
font-size: .3rem;
color: #222;
overflow-y: scroll;
.title{
padding: .4rem;
display: flex;
align-items: center;
.count{
margin-left: auto;
}
}
.topic{
font-size: .26rem;
line-height: .4rem;
padding: 0 .4rem;
span{
width: 100%;
display: block;
}
img{
width: 100%;
display: block;
}
}
.topic-bt{
font-size: .26rem;
line-height: .4rem;
padding: 0 .4rem;
font-weight: bold;
margin-bottom: .2rem;
span{
width: 100%;
display: block;
}
img{
width: 100%;
display: block;
}
}
.option{
list-style: none;
margin: .35rem 0 0 0;
padding: 0 .4rem;
li{
background:rgba(247,247,247,1);
border-radius: .2rem;
font-weight: bold;
padding: .35rem .2rem;
margin-bottom: .2rem;
word-wrap:break-word;
display: flex;
align-items: center;
.icon{
margin-right: 0.1rem;
color: #5CB9A2;
}
}
.active{
color: #5F95DE;
background:#DDF1FF;
}
.active2{
color: #40A38B;
background: #E4F9ED;
}
}
.analy{
font-size: .3rem;
color: #222;
padding: 0.2rem .4rem 1.2rem .4rem;
.tit{
font-weight: bold;
line-height: 100%;
}
.txt{
line-height: 100%;
margin-top: .4rem;
span{
font-weight: bold;
}
}
.exp{
margin-top: .4rem;
overflow: hidden;
p{
float: left;
}
.nr{
width: 5.8rem;
p{
width: 100%;
}
img{
width: 100%;
}
}
}
}
}
.topic-box.hide{
overflow: hidden;
}
.btn-box{
position: fixed;
bottom: 0;
left: 0;
height: 1rem;
box-shadow:0px 0px 6px 0px rgba(0,0,0,0.05);
background: #fff;
color: #222;
font-size: .3rem;
width: 100%;
z-index: 99;
padding-bottom: env(safe-area-inset-bottom);
.padd{
display: flex;
padding: 0 .4rem;
align-items: center;
height: 100%;
}
.analysis{
white-space: nowrap;
margin-right: .3rem;
}
.btn{
width:1.97rem;
height:.7rem;
background:#C62245;
border-radius:.12rem;
text-align: center;
line-height: .7rem;
color: #fff;
}
.btn-w{
width: 2.77rem;
}
.left{
margin-right: .4rem;
}
.right{
margin-left: auto;
// background:rgba(255,103,103,1);
}
}
.exam_submit{
position: fixed;
top: 0;
left: 0;
z-index: 999999;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.6);
.pop{
width: 5.9rem;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%,-50%);
background:rgba(255,255,255,1);
border-radius:.12rem;
padding: 0.4rem 0;
.tit{
font-weight:bold;
color:rgba(34,34,34,1);
font-size:.3rem;
text-align: center;
line-height: 100%;
}
.txt{
color:rgba(34,34,34,1);
font-size:.3rem;
text-align: center;
line-height: 100%;
margin-top: .8rem;
}
.btn_box{
padding:0 0.2rem;
display: flex;
margin-top: .8rem;
.btn{
width:2.6rem;
height:.7rem;
background:#C62245;
border-radius:.12rem;
text-align: center;
line-height: .7rem;
color: #fff;
font-size: .3rem;
}
.btn2{
margin-left: auto;
}
}
}
}
.exam-end-pop{
position: fixed;
top: 0;
left: 0;
z-index: 999999;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.6);
.pop{
width: 5.9rem;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%,-50%);
background:rgba(255,255,255,1);
border-radius:.12rem;
padding: .4rem 0;
.tit{
font-size: .3rem;
color: #222;
text-align: center;
font-weight: bold;
}
img{
width: 1.59rem;
height: 1.35rem;
display: block;
margin: 0.4rem auto 0.2rem auto;
}
.txt{
color: #222;
font-size: .3rem;
line-height: 100%;
text-align: center;
}
.btn{
margin: .4rem auto 0 auto;
width:5.5rem;
height:.7rem;
background:#C62245;
border-radius:.12rem;
text-align: center;
line-height: .7rem;
color: #fff;
font-size: .3rem;
}
}
}
}
.com-btn{
width:6.7rem;
height:.7rem;
background:rgba(244,120,133,1);
border-radius:.12rem;
margin: 0 auto;
text-align: center;
line-height: .7rem;
font-size: .3rem;
color: #fff;
}
</style>
...@@ -27,13 +27,20 @@ export default [ ...@@ -27,13 +27,20 @@ export default [
component: () => import('../pages/courseExam/answerResult.vue'), component: () => import('../pages/courseExam/answerResult.vue'),
meta: { requiredLogin: true } meta: { requiredLogin: true }
}, },
/* 能力自测答题结果 */ /* 知识点详情 */
{ {
path: '/exam/courseNode', path: '/exam/courseNode',
name: 'courseNode', name: 'courseNode',
component: () => import('../pages/courseExam/courseNode.vue'), component: () => import('../pages/courseExam/courseNode.vue'),
meta: { requiredLogin: true } meta: { requiredLogin: true }
}, },
/* 知识点考试 */
{
path: '/exam/courseNodeExam',
name: 'courseNodeExam',
component: () => import('../pages/courseExam/courseNodeExam.vue'),
meta: { requiredLogin: true }
},
/* 模拟考试 */ /* 模拟考试 */
{ {
path: '/mock/index', path: '/mock/index',
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论