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.
419 lines
12 KiB
419 lines
12 KiB
<template>
|
|
|
|
<BaseContainer>
|
|
<NavBar title="练习答题" />
|
|
<view class="question-paper" v-if="questions.length">
|
|
<view class="header">
|
|
<div class="message">温馨提示:请点击“答题卡”前去提交考试哦!</div>
|
|
<view class="header-bd">
|
|
<navigator
|
|
open-type="redirect"
|
|
:url="`/pages/topic/problem_sheet?test_id=${test_id}&record_id=${e_id}&index=${activeIndex}`"
|
|
>答题卡</navigator
|
|
>
|
|
</view>
|
|
</view>
|
|
<view class="pos" >
|
|
<view
|
|
v-for="(item, idx) of questions"
|
|
:key="item.id"
|
|
class="swiper-container swiper-slide abs"
|
|
:class="activeIndex == idx ? '' : 'on'"
|
|
:style="{ left: `${(activeIndex - idx) * -100}vw` }"
|
|
>
|
|
<view class="type">{{ item.questionType }}</view>
|
|
<view class="question" >
|
|
<view>{{ item.stem }}</view>
|
|
<image mode="widthFix" v-if="item.image" :src="item.image" />
|
|
<view
|
|
:class="{ image: item.is_img }"
|
|
class="label-group"
|
|
@click="handleClickOptions"
|
|
>
|
|
<template v-for="(option, idx) in item.options">
|
|
<view class="label" v-if="option.value" :key="option.code">
|
|
<view
|
|
:data-idx="idx"
|
|
class="label-item"
|
|
:class="{
|
|
checked: item.user_answer.includes(option.code),
|
|
ok:
|
|
option.right &&
|
|
item.is_correct &&
|
|
item.user_answer.includes(option.code),
|
|
no:
|
|
!option.right &&
|
|
item.is_correct &&
|
|
item.user_answer.includes(option.code),
|
|
}"
|
|
>
|
|
<image v-if="option.is_img" :src="option.value" />
|
|
<template v-else>{{ option.value }}</template>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
</view>
|
|
</view>
|
|
<view v-if="item.is_correct" class="analysis">
|
|
<view :class="{ no: item.is_correct === 1 }">
|
|
回答{{ item.is_correct === 1 ? "错误" : "正确" }}
|
|
</view>
|
|
<view>
|
|
<view>
|
|
正确答案:
|
|
<view>{{ item.answer }}</view>
|
|
</view>
|
|
<view>
|
|
您的答案:
|
|
<view>{{ item.user_answer.toString() }}</view>
|
|
</view>
|
|
</view>
|
|
<view>
|
|
试题难度:<span
|
|
v-for="star in 5"
|
|
:key="star"
|
|
:class="{ on: item.difficulty >= star }"
|
|
class="iconfont iconxing"
|
|
></span>
|
|
</view>
|
|
<view>答案解析:</view>
|
|
<mpHtml container-style="background: #ffffff;" :content="item.analysis"></mpHtml>
|
|
<view v-if="item.special.length">关联知识点:</view>
|
|
<navigator
|
|
open-type="redirect"
|
|
v-for="special in item.special"
|
|
:key="special.id"
|
|
:url="`/pages/special/${
|
|
special.is_light ? 'single_details' : 'details'
|
|
}?id=${special.id}`"
|
|
>{{ special.title }}</navigator
|
|
>
|
|
</view>
|
|
<view class="pl_per"></view>
|
|
</view>
|
|
<view class="swiper-pagination abs">
|
|
<text class="swiper-pagination-current">{{ activeIndex + 1 }}</text>
|
|
<text class="swiper-pagination-line"> / </text>
|
|
<text class="swiper-pagination-total">{{ questions.length }}</text>
|
|
</view>
|
|
</view>
|
|
<view class="footer">
|
|
<view
|
|
class="button flex flex-column flex-center"
|
|
:class="{ disabled: !activeIndex }"
|
|
@click="slidePrev"
|
|
>
|
|
<i class="iconfont iconshangyige"></i>
|
|
<view class="tips">上一题</view>
|
|
</view>
|
|
<view
|
|
class="button flex flex-column flex-center"
|
|
:class="{ disabled: !!questions[activeIndex].is_correct }"
|
|
@click="submitQuestion"
|
|
>
|
|
<i class="iconfont icontijiao"></i>
|
|
<view class="tips">确认提交</view>
|
|
</view>
|
|
<view
|
|
class="button flex flex-column flex-center"
|
|
:class="{ disabled: activeIndex === questions.length - 1 }"
|
|
@click="slideNext"
|
|
>
|
|
<i class="iconfont iconxiayige"></i>
|
|
<view class="tips">下一题</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<QuestionGuide :visible.sync="guideVisible"></QuestionGuide>
|
|
</BaseContainer>
|
|
</template>
|
|
|
|
<script>
|
|
import QuestionGuide from "@/components/QuestionGuide/index.vue";
|
|
import mpHtml from "mp-html/dist/uni-app/components/mp-html/mp-html.vue";
|
|
import { PROBLEM_GUIDE } from "@/constants/storage-keys";
|
|
import {
|
|
getAnswer,
|
|
getAnswerAgain,
|
|
getAnswerContinue,
|
|
getQuestion,
|
|
getSituation,
|
|
submitQuestions,
|
|
} from "@/api/topic";
|
|
export default {
|
|
components: {
|
|
QuestionGuide,
|
|
mpHtml,
|
|
},
|
|
data() {
|
|
return {
|
|
questions: [],
|
|
test_id: "",
|
|
e_id: "",
|
|
is_analysis: 0,
|
|
activeIndex: 0,
|
|
guideVisible: false,
|
|
};
|
|
},
|
|
watch: {
|
|
guideVisible(value) {
|
|
if (!value) {
|
|
this.$util.setStorage(PROBLEM_GUIDE, new Date());
|
|
}
|
|
},
|
|
},
|
|
onLoad({ test_id, type, index = 0, e_id, is_analysis }) {
|
|
this.test_id = test_id;
|
|
this.activeIndex = Number(index);
|
|
|
|
if (e_id && parseInt(is_analysis)) {
|
|
this.is_analysis = 1;
|
|
this.e_id = e_id;
|
|
this.getQuestions();
|
|
} else {
|
|
this.getSituation();
|
|
}
|
|
},
|
|
methods: {
|
|
handleClickOptions({ target }) {
|
|
const { idx } = target.dataset;
|
|
if (idx === undefined) return;
|
|
const item = this.questions[this.activeIndex];
|
|
const option = item.options[idx];
|
|
|
|
if (!item || !option) return;
|
|
if (!!item.is_correct) return;
|
|
if (item.question_type === 2) {
|
|
const existIdx = item.user_answer.findIndex((i) => i === option.code);
|
|
console.log(existIdx);
|
|
if (existIdx === -1) {
|
|
item.user_answer.push(option.code);
|
|
} else {
|
|
item.user_answer.splice(existIdx, 1);
|
|
}
|
|
} else {
|
|
if (item.user_answer.includes(option.code)) {
|
|
item.user_answer = "";
|
|
} else {
|
|
item.user_answer = option.code;
|
|
}
|
|
}
|
|
},
|
|
// 获取状态
|
|
getSituation() {
|
|
getSituation(this.test_id).then(({ code, msg, data }) => {
|
|
if (code === 400) {
|
|
return this.$util.showMsg(msg);
|
|
}
|
|
switch (data) {
|
|
case 0:
|
|
this.getAnswer();
|
|
break;
|
|
case 1:
|
|
this.getAnswerAgain();
|
|
break;
|
|
case 2:
|
|
this.getAnswerContinue();
|
|
break;
|
|
}
|
|
});
|
|
},
|
|
// 开始答题
|
|
getAnswer() {
|
|
getAnswer({
|
|
test_id: this.test_id,
|
|
type: 1,
|
|
}).then(({ code, msg, data }) => {
|
|
if (code === 200) {
|
|
this.e_id = data;
|
|
this.$util.setCookie("e_id", this.e_id);
|
|
this.getQuestions();
|
|
} else {
|
|
this.$util.showMsg(msg);
|
|
uni.navigateTo({
|
|
url: "/pages/topic/question_user?type=1",
|
|
});
|
|
}
|
|
});
|
|
},
|
|
// 再次答题
|
|
getAnswerAgain() {
|
|
getAnswerAgain({
|
|
test_id: this.test_id,
|
|
type: 1,
|
|
}).then(({ code, data, msg }) => {
|
|
if (code === 200) {
|
|
this.e_id = data;
|
|
this.$util.setCookie("e_id", this.e_id);
|
|
this.getQuestions();
|
|
} else {
|
|
this.$util.showMsg(msg);
|
|
uni.navigateTo({
|
|
url: "/pages/topic/question_user?type=1",
|
|
});
|
|
}
|
|
});
|
|
},
|
|
// 继续答题
|
|
getAnswerContinue() {
|
|
getAnswerContinue({
|
|
test_id: this.test_id,
|
|
type: 1,
|
|
}).then(({ code, data, msg }) => {
|
|
if (code === 200) {
|
|
this.e_id = data;
|
|
this.$util.setCookie("e_id", this.e_id);
|
|
this.getQuestions();
|
|
} else {
|
|
this.$util.showMsg(msg);
|
|
uni.navigateTo({
|
|
url: "/pages/topic/question_user?type=1",
|
|
});
|
|
}
|
|
});
|
|
},
|
|
// 获取练习题
|
|
async getQuestions() {
|
|
uni.showLoading({ mask: true });
|
|
try {
|
|
const { data: questions } = await getQuestion({
|
|
test_id: this.test_id,
|
|
record_id: this.e_id,
|
|
type: 1,
|
|
});
|
|
uni.hideLoading();
|
|
questions.forEach((question) => {
|
|
question.options = [];
|
|
if (Array.isArray(question.option)) {
|
|
question.option.forEach((option, index) => {
|
|
let code = String.fromCharCode(index + 65);
|
|
question.options.push({
|
|
code,
|
|
value: option,
|
|
right: question.answer.includes(code),
|
|
});
|
|
});
|
|
} else {
|
|
for (let key in question.option) {
|
|
if (Object.hasOwnProperty.call(question.option, key)) {
|
|
question.options.push({
|
|
code: key,
|
|
value: question.option[key],
|
|
right: question.answer.includes(key),
|
|
});
|
|
}
|
|
}
|
|
}
|
|
if (!Array.isArray(question.userAnswer)) {
|
|
Object.assign(question, question.userAnswer);
|
|
}
|
|
if (!("is_correct" in question)) {
|
|
question.is_correct = 0;
|
|
}
|
|
if (!("user_answer" in question)) {
|
|
question.user_answer = "";
|
|
}
|
|
if (question.question_type === 2) {
|
|
question.user_answer = question.user_answer
|
|
? question.user_answer.split(",")
|
|
: [];
|
|
}
|
|
switch (question.question_type) {
|
|
case 1:
|
|
question.questionType = "单选题";
|
|
break;
|
|
case 2:
|
|
question.questionType = "多选题";
|
|
break;
|
|
case 3:
|
|
question.questionType = "判断题";
|
|
break;
|
|
}
|
|
});
|
|
this.questions = questions;
|
|
} catch (err) {
|
|
uni.hideLoading();
|
|
this.$util.showMsg(err);
|
|
}
|
|
},
|
|
// 提交本题
|
|
async submitQuestion() {
|
|
let question = this.questions[this.activeIndex];
|
|
let data = {
|
|
e_id: this.e_id,
|
|
questions_id: question.questions_id,
|
|
answer: question.answer,
|
|
score: question.score,
|
|
type: 1,
|
|
};
|
|
if (!question.user_answer.length) {
|
|
return this.$util.showMsg("请作答后提交本题");
|
|
}
|
|
if (question.question_type === 2) {
|
|
question.user_answer.sort();
|
|
data.user_answer = question.user_answer.toString();
|
|
} else {
|
|
data.user_answer = question.user_answer;
|
|
}
|
|
data.is_correct = data.user_answer === question.answer ? 2 : 1;
|
|
|
|
uni.showLoading({ mask: true });
|
|
try {
|
|
const { code, msg } = await submitQuestions(data);
|
|
uni.hideLoading();
|
|
if (code === 200) {
|
|
question.is_correct = data.is_correct;
|
|
} else {
|
|
this.$util.showMsg(msg);
|
|
}
|
|
} catch (err) {
|
|
uni.hideLoading();
|
|
this.$util.showMsg(err);
|
|
}
|
|
},
|
|
// 上一题
|
|
slidePrev() {
|
|
if (this.activeIndex) {
|
|
this.activeIndex--;
|
|
}
|
|
},
|
|
// 下一题
|
|
slideNext() {
|
|
if (this.activeIndex !== this.questions.length - 1) {
|
|
this.activeIndex++;
|
|
|
|
if (this.activeIndex === this.questions.length - 1) {
|
|
this.$util.showMsg("答完全部考题后\n点击左上角“答题卡”前去提交练习");
|
|
}
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
page {
|
|
background-color: #f5f5f5;
|
|
}
|
|
.pl_per{
|
|
/* #ifdef MP-WEIXIN */
|
|
height:100rpx;
|
|
/* #endif */
|
|
}
|
|
</style>
|
|
|
|
<style scoped lang="scss">
|
|
@import "@/static/style/question.scss";
|
|
.message{
|
|
height:80rpx;
|
|
border-radius: 12rpx 12rpx 0 0;
|
|
background-color: #FFF0E5;
|
|
text-align: center;
|
|
font-size: 24rpx;
|
|
line-height: 80rpx;
|
|
color: #FF6B00;
|
|
}
|
|
.abs.on{
|
|
display: none;
|
|
}
|
|
</style>
|
|
|