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

<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>