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.
589 lines
15 KiB
589 lines
15 KiB
<template>
|
|
<view class="content">
|
|
<up-navbar leftText=" " title="" :safeAreaInsetTop="false" :autoBack="true">
|
|
<template #center>
|
|
<view class="u-nav-slot flex">
|
|
<view class="btn" @click="changeNav(1)" :class="{active: currentNav==1}">答题模式</view>
|
|
<view class="btn" @click="changeNav(2)" :class="{active: currentNav==2}">背题模式</view>
|
|
</view>
|
|
</template>
|
|
</up-navbar>
|
|
|
|
|
|
<view class="con padding">
|
|
<view class="h1_row">
|
|
<text class="tag" :class="{red: questionBank.types==2, blue: questionBank.types==3}">{{types[questionBank.types-1]}}</text>
|
|
<text class="h1" @click="speak(questionBank.title)">{{ questionBank.title}}</text>
|
|
</view>
|
|
<view class="imgBox" style="width: 100%;padding: 0 0 30rpx 0;" v-if="questionBank.img">
|
|
<image :src="questionBank.img" mode="widthFix"></image>
|
|
</view>
|
|
<view class="option">
|
|
<view v-for="(item,index) in questionBank.optionArr" @click="chooseOption(item)">
|
|
<!-- 多选题 -->
|
|
<view class="optionItem flex" v-if="questionBank.types ==2&& (!curOption.answer||curOption.answer==questionBank.answer)">
|
|
<up-icon name="checkmark-circle-fill" color="#55ff7f" size="20" v-if="curOption.ans?.includes(item.key)"></up-icon>
|
|
<view class="icon" v-else></view>
|
|
<view class="text"><text >{{item.key}}</text> {{item.text}}</view>
|
|
</view>
|
|
<!-- 正常答案 -->
|
|
<view class="optionItem flex" v-else >
|
|
<view class="icon" v-if="!curOption.key&&questionBank.types !=2"></view>
|
|
<up-icon name="checkmark-circle-fill" color="#55ff7f" size="20" v-else-if="questionBank.answer.includes(item.key)"></up-icon>
|
|
<up-icon name="close-circle-fill" color="#ff0000" size="20" v-else></up-icon>
|
|
<view class="text"><text v-if="questionBank.types!=3">{{item.key}}</text> {{item.text}}</view>
|
|
</view>
|
|
<!-- ans -->
|
|
</view>
|
|
</view>
|
|
<view class="answerCss flex" v-if="curOption.answer&&questionBank.answer!=curOption.answer">
|
|
<view class="ans">正确答案是
|
|
<text v-if="questionBank.types==3" >{{ questionBank.answer=='false'?'错误':'正确' }}</text>
|
|
<text v-else >{{ questionBank.answer }}</text>
|
|
</view>
|
|
<view class="ans">您的答案是
|
|
<text v-if="questionBank.types==3" class="red">{{ curOption.answer=='false'?'错误':'正确' }}</text>
|
|
<text v-else class="red">{{ curOption.answer }}</text>
|
|
</view>
|
|
</view>
|
|
<view class="btn_row flex-b">
|
|
<!-- @click="$goPage('/pages/exercises/lastPage/lastPage')" -->
|
|
<button class="btn border" @click="debounce(nextQuestion(-1), 500)" :class="{disable: currentIndex==1}" :disabled="currentIndex==1">上一题</button>
|
|
<button class="btn bg" @click="debounce(nextQuestion(1), 500)" :class="{disable: currentIndex>=quesIdList.length}" :disabled="currentIndex>=quesIdList.length">下一题</button>
|
|
</view>
|
|
<view class="analysis" v-if="currentNav==2||(curOption.answer&&curOption.answer!=questionBank.answer)">
|
|
<view class="tit">题目解析</view>
|
|
<view class="txt">{{ questionBank.resolving }}</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="bottomBar">
|
|
|
|
<view class="ul">
|
|
<view class="li">
|
|
<view class="icon" style="color: #55ff7f;">{{ yesNum }}</view>
|
|
<view class="text">答对</view>
|
|
</view>
|
|
<view class="li">
|
|
<view class="icon" style="color: #ff0000;">{{ noNum }}</view>
|
|
<view class="text">答错</view>
|
|
</view>
|
|
<view class="li">
|
|
<view class="icon">{{currentIndex}}/<text style="color: #999; font-size: 24rpx;">{{quesIdList.length}}</text></view>
|
|
<view class="text">题目</view>
|
|
</view>
|
|
<view class="li" @click="showCommt=true">
|
|
<view class="icon">
|
|
<image src="@/static/images/theory/fankui.png" mode=""></image>
|
|
</view>
|
|
<view class="text">反馈</view>
|
|
</view>
|
|
<view class="li" @click="openPopup">
|
|
<view class="icon">
|
|
<image src="@/static/images/theory/dtk.png" mode=""></image>
|
|
</view>
|
|
<view class="text">答题卡</view>
|
|
</view>
|
|
<view class="li" @click="questionWrongColleFn">
|
|
<view class="icon">
|
|
<image src="@/static/images/theory/scActive.png" mode="" v-if="questionBank.isCollect=='1'"></image>
|
|
<image src="@/static/images/theory/sc.png" mode="" v-else></image>
|
|
</view>
|
|
<view class="text">收藏</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<up-popup :show="show" @close="closePopup" @open="openPopup" mode="bottom" round="20" closeable>
|
|
<view class="popupCon">
|
|
<view class="h3">答题卡</view>
|
|
<view class="ulRow">
|
|
<view class="ul">
|
|
<view class="li">
|
|
<view class="icon" style="color: #55ff7f;">{{ yesNum }}</view>
|
|
<view class="text">答对</view>
|
|
</view>
|
|
<view class="li">
|
|
<view class="icon" style="color: #ff0000;">{{ noNum }}</view>
|
|
<view class="text">答错</view>
|
|
</view>
|
|
<view class="li" style="margin-left: auto;">
|
|
<view class="icon">{{currentIndex}}/<text style="color: #999; font-size: 24rpx;">{{quesIdList.length}}</text></view>
|
|
<view class="text">题目</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="ul2">
|
|
<view class="li2" v-for="(item,index) in quesIdList" :key="index" @click="quesIdListClick(item,index)">
|
|
<view class="num" :class="{active: index+1==currentIndex}">{{ index+1 }}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</up-popup>
|
|
|
|
<up-popup :show="showCommt" @close="showCommtClose" mode="bottom" round="20rpx" closeable>
|
|
<view class="commtCon" style="padding: 30rpx">
|
|
<up-textarea v-model.trim="contentStr" placeholder="请输入反馈内容" style="margin-top: 50rpx;" maxlength="300"></up-textarea>
|
|
<up-button text="提 交" style="margin-top: 20rpx;" type="primary" @click="submitCommt"></up-button>
|
|
</view>
|
|
</up-popup>
|
|
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
function speak(text) {
|
|
const speech = new SpeechSynthesisUtterance(text); // 创建语音消息
|
|
window.speechSynthesis.speak(speech); // 播报消息
|
|
}
|
|
|
|
import { startQuestionApi, submitAnswerResultApi, getQuestionApi, questionCommentAdd, questionWrongColle} from '@/config/api.js'
|
|
import { debounce } from '@/uni_modules/uview-plus';
|
|
import {
|
|
ref,
|
|
reactive
|
|
} from 'vue';
|
|
const currentNav = ref('1')
|
|
const types = ref([
|
|
'单选题',
|
|
'多选题',
|
|
'判断题'
|
|
])
|
|
const yesNum = ref(0)
|
|
const noNum = ref(0)
|
|
|
|
import carStore from '@/store/modules/car.js'
|
|
let usecarStore = carStore()
|
|
|
|
import {
|
|
onLoad,
|
|
onReady
|
|
} from "@dcloudio/uni-app"
|
|
// 1:单选题,2:多选题,3:判断题
|
|
function changeNav(val) {
|
|
console.log(window)
|
|
if(currentNav.value == val) return
|
|
currentNav.value = val
|
|
}
|
|
function goEmam() {
|
|
uni.navigateTo({
|
|
// url: '/pages/exercises/exam/exam',
|
|
// url: '/pages/exercises/beforeExam/beforeExam',
|
|
// url: '/pages/exercises/examResults/examResults',
|
|
// url: '/pages/exercises/wrongQuestion/wrongQuestion',
|
|
// url: '/pages/exercises/theoryStudy/theoryStudy',
|
|
url: '/pages/vip/vipEntry/vipEntry'
|
|
|
|
})
|
|
}
|
|
function changeTabbar(val) {
|
|
console.log(val)
|
|
}
|
|
const show = ref(false)
|
|
function closePopup() {
|
|
show.value = false
|
|
}
|
|
function openPopup() {
|
|
show.value = true
|
|
}
|
|
|
|
let showCommt = ref(false)
|
|
let contentStr = ref('')
|
|
function showCommtClose() {
|
|
showCommt.value = false
|
|
contentStr.value = ''
|
|
}
|
|
// 提交反馈
|
|
async function submitCommt() {
|
|
if(!contentStr.value) return uni.$u.toast('请输入内容')
|
|
let obj = {
|
|
content: contentStr.value,
|
|
questionId: questionBank.value.id
|
|
}
|
|
const res = await questionCommentAdd(obj)
|
|
if(res.errorcode==0) {
|
|
uni.$u.toast('提交成功,感谢您的反馈')
|
|
showCommt.value = false
|
|
}
|
|
}
|
|
// 请求数据
|
|
const questionBank = ref({})
|
|
let quesIdList = ref([])
|
|
let currentIndex = ref(1)
|
|
async function startQuestionFn() {
|
|
try{
|
|
uni.showLoading({
|
|
title: '正在加载...'
|
|
})
|
|
let obj = {
|
|
carType: usecarStore.carInfo.carType,
|
|
stepType: usecarStore.carInfo.stepType,
|
|
volume: usecarStore.carInfo.volume,
|
|
types: usecarStore.carInfo.types,
|
|
sift: usecarStore.carInfo.sift,
|
|
contentType: usecarStore.carInfo.contentType,
|
|
knowType: usecarStore.carInfo.knowType,
|
|
chapter: usecarStore.carInfo.chapter,
|
|
}
|
|
const {data: res} = await startQuestionApi(obj)
|
|
uni.hideLoading()
|
|
questionBank.value = res.questionBank
|
|
initOptionArr()
|
|
quesIdList.value = res.quesIdList
|
|
}catch(e){
|
|
uni.hideLoading()
|
|
}
|
|
}
|
|
startQuestionFn()
|
|
|
|
function initOptionArr() {
|
|
questionBank.value.optionArr = []
|
|
let abcd = [
|
|
'a',
|
|
'b',
|
|
'c',
|
|
'd',
|
|
'e',
|
|
'f'
|
|
]
|
|
abcd.forEach((k,i)=>{
|
|
let option = 'option'+k
|
|
if(questionBank.value[option]) {
|
|
let obj = {
|
|
key: k.toLocaleUpperCase(),
|
|
text: questionBank.value[option],
|
|
index: i+1
|
|
}
|
|
questionBank.value.optionArr.push(obj)
|
|
// console.log(questionBank.value.optionArr)
|
|
}
|
|
})
|
|
|
|
// 如果是判断题
|
|
if(questionBank.value.types==3) {
|
|
questionBank.value.optionArr[0].key = 'true'
|
|
questionBank.value.optionArr[1].key = 'false'
|
|
}
|
|
|
|
}
|
|
|
|
// 下一题
|
|
async function nextQuestion(num) {
|
|
// 如果是多选题,什么时候不直接请求下一题,是多选题 ,并且有答案,答错了,并且不是next
|
|
if(questionBank.value.types==2 && curOption.value.ans) {
|
|
// 如果没有请求就请求一下
|
|
if(!curOption.value.answer) {
|
|
curOption.value.answer = curOption.value.ans
|
|
await submitAnswerResultFn()
|
|
}
|
|
// 如果答案不一样,并且是第一次请求
|
|
if(questionBank.value.answer != curOption.value.ans&&curOption.value.isNext != 'next') {
|
|
curOption.value.isNext = 'next'
|
|
return false
|
|
}
|
|
}
|
|
curOption.value = {}
|
|
currentIndex.value = currentIndex.value + num
|
|
getQuestionFn()
|
|
|
|
}
|
|
// 请求下一题
|
|
async function getQuestionFn() {
|
|
console.log(currentIndex.value)
|
|
let questionId = quesIdList.value[currentIndex.value-1]
|
|
let obj = {
|
|
"carType": usecarStore.carInfo.carType,
|
|
"questionId": questionId,
|
|
"sort": currentIndex.value,
|
|
"stepType": usecarStore.carInfo.stepType,
|
|
'tempId': questionBank.value.questionDoTemp.id
|
|
}
|
|
const {data: res} = await getQuestionApi(obj)
|
|
questionBank.value = res
|
|
curOption.value.isNext = ''
|
|
initOptionArr()
|
|
}
|
|
async function quesIdListClick(id, index) {
|
|
curOption.value = {}
|
|
currentIndex.value = index + 1
|
|
getQuestionFn()
|
|
show.value = false
|
|
}
|
|
|
|
// 选择答案
|
|
const curOption = ref({})
|
|
async function chooseOption(item) {
|
|
// console.log(item)
|
|
if(curOption.value.answer) return
|
|
if(questionBank.value.types != 2) {
|
|
item.answer = item.key
|
|
curOption.value = item
|
|
submitAnswerResultFn()
|
|
}else if(questionBank.value.types == 2){
|
|
if(!curOption.value.ans) curOption.value.ans = ''
|
|
if(curOption.value.ans.includes(item.key)) {
|
|
curOption.value.ans = curOption.value.ans.replace(item.key, '')
|
|
return
|
|
}
|
|
curOption.value.ans = (curOption.value.ans + item.key).split('').sort().join('')
|
|
// console.log(curOption.value.ans)
|
|
}
|
|
}
|
|
// 提交请求
|
|
async function submitAnswerResultFn() {
|
|
let obj = {
|
|
answer: curOption.value.answer,
|
|
carType: 'car',
|
|
questionId: questionBank.value.id,
|
|
result: '0',
|
|
stepType: 1,
|
|
tempId: questionBank.value.questionDoTemp.id
|
|
}
|
|
const res = await submitAnswerResultApi(obj)
|
|
if(res.errorcode!=0) return
|
|
if(curOption.value.answer==questionBank.value.answer) {
|
|
console.log('答对了')
|
|
curOption.value = {}
|
|
yesNum.value ++
|
|
nextQuestion(1)
|
|
}else {
|
|
noNum.value ++
|
|
}
|
|
// console.log(res)
|
|
}
|
|
|
|
async function questionWrongColleFn() {
|
|
let isAdd = questionBank.value.isCollect==1?'0':'1'
|
|
const obj = {
|
|
"carType": usecarStore.carInfo.carType,
|
|
"isAdd": isAdd,
|
|
"questionId": questionBank.value.id,
|
|
"stepType": usecarStore.carInfo.stepType
|
|
}
|
|
const res = await questionWrongColle(obj)
|
|
questionBank.value.isCollect = isAdd
|
|
console.log(questionBank.value.isCollect)
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
image {display: block;width: 100%;height: 100%;}
|
|
.bottomBar {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 98rpx;
|
|
background: #FFFFFF;
|
|
border-top: 1rpx solid #F4F4F4;
|
|
|
|
}
|
|
.ul {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
height: 100%;
|
|
align-items: center;
|
|
.li {
|
|
width: 16.6%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
.icon {
|
|
font-size: 30rpx;
|
|
height: 30rpx;
|
|
line-height: 30rpx;
|
|
image {
|
|
display: block;
|
|
margin-top: 4rpx;
|
|
width: 26rpx;
|
|
height: 26rpx;
|
|
}
|
|
}
|
|
.text {
|
|
font-weight: 500;
|
|
font-size: 24rpx;
|
|
color: #999999;
|
|
margin-top: 10rpx;
|
|
}
|
|
}
|
|
}
|
|
.content {
|
|
padding: 120rpx 0;
|
|
min-height: 100vh;
|
|
.u-nav-slot {
|
|
width: 306rpx;
|
|
height: 54rpx;
|
|
border-radius: 10rpx;
|
|
border: 1px solid #333333;
|
|
display: flex;
|
|
|
|
.btn {
|
|
font-size: 24rpx;
|
|
color: #333333;
|
|
flex: 1;
|
|
text-align: center;
|
|
line-height: 54rpx;
|
|
|
|
&.active {
|
|
background-color: #333333;
|
|
color: #fff;
|
|
}
|
|
}
|
|
}
|
|
.btn_row {
|
|
padding: 60rpx 0 30rpx 0;
|
|
.btn {
|
|
width: 44%;
|
|
height: 76rpx;
|
|
border-radius: 38rpx;
|
|
border: 1rpx solid $themC;
|
|
line-height: 76rpx;
|
|
text-align: center;
|
|
font-size: 28rpx;
|
|
color: $themC;
|
|
&.disable {
|
|
opacity: 0.4;
|
|
}
|
|
&.bg {
|
|
background: #3776FF;
|
|
border-radius: 38rpx;
|
|
color: #fff;
|
|
}
|
|
|
|
}
|
|
}
|
|
.con {
|
|
.h1_row {
|
|
margin-bottom: 50rpx;
|
|
.tag {
|
|
display: inline-block;
|
|
// width: 66px;
|
|
height: 36rpx;
|
|
line-height: 36rpx;
|
|
padding: 4rpx 6rpx;
|
|
background: #63C168;
|
|
border-radius: 6rpx;
|
|
margin-top: -2rpx;
|
|
margin-right: 16rpx;
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
&.blue {
|
|
background: #3776FF;
|
|
}
|
|
&.red {
|
|
background: orangered;
|
|
}
|
|
}
|
|
|
|
text.h1 {
|
|
font-size: 36rpx;
|
|
}
|
|
}
|
|
|
|
.option {
|
|
width: 100%;
|
|
.optionItem {
|
|
margin-bottom: 50rpx;
|
|
align-items: center;
|
|
.icon {
|
|
width: 36rpx;
|
|
height:36rpx;
|
|
border-radius: 50%;
|
|
border: 1rpx solid #999;
|
|
}
|
|
|
|
.text {
|
|
font-size: 32rpx;
|
|
margin-left: 16rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.answerCss {
|
|
height: 90rpx;
|
|
background: #F4F4F4;
|
|
padding: 30rpx;
|
|
margin-top: 20rpx;
|
|
justify-content: space-around;
|
|
.ans {
|
|
font-size: 30rpx;
|
|
text {
|
|
&.red {
|
|
color: red;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
.analysis {
|
|
margin-top: 60rpx;
|
|
.tit {
|
|
font-weight: 700;
|
|
font-size: 32rpx;
|
|
position: relative;
|
|
padding-left: 30rpx;
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: 8rpx;
|
|
width: 6rpx;
|
|
height: 30rpx;
|
|
background: linear-gradient(0deg, #43EA80 0%, #38F8D4 100%);
|
|
border-radius: 3rpx;
|
|
}
|
|
}
|
|
|
|
.txt {
|
|
margin-top: 39rpx;
|
|
font-size: 32rpx;
|
|
color: #333333;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.popupCon {
|
|
width: 100%;
|
|
height: calc(100vh - 200rpx);
|
|
.h3 {
|
|
height: 88rpx;
|
|
border-bottom: 1px solid #F4F4F4;
|
|
line-height: 88rpx;
|
|
font-size: 30rpx;
|
|
padding: 0rpx 0 0 30rpx;
|
|
}
|
|
.ulRow {
|
|
height: 100rpx;
|
|
padding: 30rpx 0;
|
|
}
|
|
.ul2 {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
padding: 30rpx 10rpx;
|
|
height: calc(100vh - 388rpx);
|
|
overflow-y: auto;
|
|
.li2 {
|
|
width: 16.6%;
|
|
margin-bottom: 20rpx;
|
|
.num {
|
|
width: 100rpx;
|
|
height: 100rpx;
|
|
border-radius: 50%;
|
|
margin: auto;
|
|
background: #F6F7FA;
|
|
font-size: 32rpx;
|
|
line-height: 100rpx;
|
|
text-align: center;
|
|
&.active {
|
|
border: 1px solid #63C168;
|
|
background: rgba(99,193,104,0.1);
|
|
color: #63C168;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|