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.
577 lines
17 KiB
577 lines
17 KiB
<template>
|
|
|
|
<BaseContainer class="honor-list-page">
|
|
<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/question_sheet?test_id=${test_id}&record_id=${e_id}&index=${activeIndex}&is_analysis=${is_analysis}&txamination_time=${txamination_time}&exam_time=${duration}`"
|
|
>答题卡</navigator
|
|
>
|
|
<view v-if="!is_analysis">{{ duration | formatTime }}</view>
|
|
</view>
|
|
</view>
|
|
<view class="swiper-container pos">
|
|
<view
|
|
v-for="(item, idx) of questions"
|
|
:key="item.id"
|
|
class="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.user_answer.includes(option.code) &&
|
|
is_analysis,
|
|
no:
|
|
!option.right &&
|
|
item.user_answer.includes(option.code) &&
|
|
is_analysis,
|
|
}"
|
|
>
|
|
<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 && is_analysis" class="analysis">
|
|
<view :class="{ no: item.is_correct === 1 }">
|
|
回答{{ item.is_correct === 2 ? "正确" : "错误" }}
|
|
</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 {
|
|
submitQuestions,
|
|
getSituation,
|
|
getQuestion,
|
|
getAnswerAgain,
|
|
getAnswerContinue,
|
|
getQuestionDetail,
|
|
getAnswer
|
|
} from "@/api/topic";
|
|
|
|
export default {
|
|
components: {
|
|
QuestionGuide,
|
|
mpHtml,
|
|
},
|
|
filters: {
|
|
formatTime(time) {
|
|
let hour = Math.floor(time / 3600000);
|
|
let minute = Math.floor((time - hour * 3600000) / 60000);
|
|
let second = Math.floor((time - hour * 3600000 - minute * 60000) / 1000);
|
|
|
|
if (hour < 10) {
|
|
hour = "0" + hour;
|
|
}
|
|
if (minute < 10) {
|
|
minute = "0" + minute;
|
|
}
|
|
if (second < 10) {
|
|
second = "0" + second;
|
|
}
|
|
|
|
return hour + ":" + minute + ":" + second;
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
questions: [], // 考题列表
|
|
test_id: "",
|
|
e_id: "",
|
|
isWechat: false,
|
|
is_analysis: 0,
|
|
activeIndex: 0,
|
|
virtualData: {
|
|
slides: [],
|
|
},
|
|
questionSwiper: null,
|
|
startTime: new Date(),
|
|
duration: 0,
|
|
txamination_time: 0,
|
|
guideVisible: false,
|
|
submitProblem: {},
|
|
};
|
|
},
|
|
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);
|
|
|
|
const task = this.getData();
|
|
|
|
const exam_time = this.$util.getStorage(`exam_time${this.test_id}`);
|
|
if (exam_time) {
|
|
if (Number.isNaN(parseInt(exam_time))) {
|
|
this.exam_time = 0;
|
|
} else {
|
|
this.exam_time = parseInt(exam_time);
|
|
}
|
|
} else {
|
|
this.exam_time = 0;
|
|
}
|
|
if (parseInt(is_analysis)) {
|
|
this.is_analysis = 1;
|
|
}
|
|
if (e_id) {
|
|
this.e_id = e_id || '';
|
|
this.getQuestions();
|
|
} else {
|
|
this.getSituation();
|
|
task.then(this.setTimer);
|
|
}
|
|
},
|
|
onHide(){
|
|
// 清除定时器
|
|
clearTimeout(this.timer);
|
|
},
|
|
onUnload(){
|
|
// 清除定时器
|
|
clearTimeout(this.timer);
|
|
},
|
|
methods: {
|
|
getData() {
|
|
return getQuestionDetail(this.test_id).then(({ data }) => {
|
|
const { titles, txamination_time } = data;
|
|
Object.assign(this, {
|
|
titles,
|
|
txamination_time,
|
|
});
|
|
});
|
|
},
|
|
setTimer() {
|
|
this.timer = setInterval(() => {
|
|
this.duration = new Date() - this.startTime + this.exam_time;
|
|
this.$util.setStorage(`exam_time${this.test_id}`, this.duration);
|
|
if (this.txamination_time * 60000 <= this.duration) {
|
|
clearInterval(timer);
|
|
this.$util.showMsg("考试时间已到");
|
|
this.submit();
|
|
}
|
|
}, 1000);
|
|
},
|
|
async submit() {
|
|
const submitProblem = this.questions[this.activeIndex];
|
|
if (submitProblem.user_answer.length) {
|
|
const question = submitProblem;
|
|
const data = {
|
|
e_id: this.e_id,
|
|
questions_id: question.questions_id,
|
|
answer: question.answer,
|
|
score: question.score,
|
|
type: 2,
|
|
};
|
|
|
|
if (typeof question.user_answer === "string") {
|
|
data.user_answer = question.user_answer;
|
|
data.is_correct = question.answer === question.user_answer ? 2 : 1;
|
|
} else {
|
|
const answer = question.answer.split(",");
|
|
|
|
if (answer.length === question.user_answer.length) {
|
|
if (answer.toString() === question.user_answer.toString()) {
|
|
data.is_correct = 2;
|
|
} else {
|
|
data.is_correct =
|
|
answer.sort().toString() === question.user_answer.sort().toString()
|
|
? 2
|
|
: 1;
|
|
}
|
|
} else {
|
|
data.is_correct = 1;
|
|
}
|
|
|
|
data.user_answer = question.user_answer.sort().toString();
|
|
}
|
|
|
|
uni.showLoading({ mask: true });
|
|
try {
|
|
const resData = await submitQuestions(data);
|
|
uni.hideLoading();
|
|
if (resData.code === 200) {
|
|
question.is_correct = data.is_correct;
|
|
|
|
uni.navigateTo({
|
|
url:
|
|
"/pages/topic/question_sheet?" +
|
|
this.$util.objToParam({
|
|
test_id: this.test_id,
|
|
record_id: this.e_id,
|
|
index: this.activeIndex,
|
|
is_analysis: this.is_analysis,
|
|
txamination_time: this.txamination_time,
|
|
}),
|
|
});
|
|
} else {
|
|
this.$util.showMsg(resData.msg);
|
|
}
|
|
} catch (err) {
|
|
uni.hideLoading();
|
|
this.$util.showMsg(err.msg);
|
|
}
|
|
} else {
|
|
uni.navigateTo({
|
|
url:
|
|
"/pages/topic/question_sheet?" +
|
|
this.$util.objToParam({
|
|
test_id: this.test_id,
|
|
record_id: this.e_id,
|
|
index: this.activeIndex,
|
|
is_analysis: this.is_analysis,
|
|
txamination_time: this.txamination_time,
|
|
}),
|
|
});
|
|
}
|
|
},
|
|
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);
|
|
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: 2,
|
|
}).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=2",
|
|
});
|
|
}
|
|
});
|
|
},
|
|
// 再次答题
|
|
getAnswerAgain() {
|
|
getAnswerAgain({
|
|
test_id: this.test_id,
|
|
type: 2,
|
|
})
|
|
.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=2",
|
|
});
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
this.$util.showMsg(err.msg);
|
|
setTimeout(() => {
|
|
uni.navigateBack({
|
|
delta: 2
|
|
});
|
|
}, 2000);
|
|
|
|
});
|
|
},
|
|
// 继续答题
|
|
getAnswerContinue() {
|
|
getAnswerContinue({
|
|
test_id: this.test_id,
|
|
type: 2,
|
|
}).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=2",
|
|
});
|
|
}
|
|
});
|
|
},
|
|
// 获取练习题
|
|
async getQuestions() {
|
|
uni.showLoading({ mask: true });
|
|
try {
|
|
const { data: questions } = await getQuestion({
|
|
test_id: this.test_id,
|
|
record_id: this.e_id,
|
|
type: 2,
|
|
});
|
|
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];
|
|
if (!!question.is_correct) return;
|
|
let data = {
|
|
e_id: this.e_id,
|
|
questions_id: question.questions_id,
|
|
answer: question.answer,
|
|
score: question.score,
|
|
type: 2,
|
|
};
|
|
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>
|
|
|