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.

627 lines
16 KiB

5 months ago
5 months ago
4 months ago
5 months ago
4 months ago
1 month ago
4 months ago
4 months ago
1 month ago
1 month ago
1 month ago
4 months ago
1 month ago
1 month ago
1 month ago
4 months ago
3 months ago
1 month ago
3 weeks ago
3 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
3 weeks ago
1 month ago
1 month ago
1 month ago
1 month ago
4 weeks ago
1 month ago
4 weeks ago
1 month ago
2 weeks ago
1 month ago
3 weeks ago
1 month ago
3 weeks ago
1 month ago
5 months ago
1 month ago
2 weeks ago
1 month ago
3 weeks ago
1 month ago
1 month ago
3 weeks ago
1 month ago
1 month ago
1 month ago
2 weeks ago
1 month ago
2 weeks ago
1 month ago
3 weeks ago
1 month ago
1 month ago
3 weeks ago
1 month ago
1 month ago
1 month ago
2 weeks ago
3 weeks ago
1 month ago
1 month ago
1 month ago
1 month ago
4 months ago
1 month ago
1 month ago
1 month ago
2 weeks ago
1 month ago
3 weeks ago
1 month ago
1 month ago
1 month ago
4 weeks ago
1 month ago
3 weeks ago
2 weeks ago
1 month ago
1 month ago
1 month ago
1 month ago
3 weeks ago
1 month ago
2 weeks ago
1 month ago
3 weeks ago
1 month ago
3 weeks ago
1 month ago
2 weeks ago
1 month ago
2 weeks ago
1 month ago
3 weeks ago
1 month ago
3 weeks ago
1 month ago
4 months ago
4 weeks ago
5 months ago
4 months ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
4 months ago
1 month ago
1 month ago
5 months ago
4 months ago
5 months ago
4 months ago
3 months ago
1 month ago
3 months ago
1 month ago
3 months ago
4 months ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
5 months ago
4 months ago
1 month ago
2 weeks ago
1 month ago
5 months ago
  1. <template>
  2. <view class="content">
  3. <up-navbar leftText=" " title="" :safeAreaInsetTop="false" :autoBack="true">
  4. <template #center>
  5. <view class="u-nav-slot flex">
  6. <view class="btn" @click="changeNav(1)" :class="{active: currentNav==1}">答题模式</view>
  7. <view class="btn" @click="changeNav(2)" :class="{active: currentNav==2}">背题模式</view>
  8. </view>
  9. </template>
  10. </up-navbar>
  11. <view class="con padding">
  12. <view class="h1_row">
  13. <text class="tag" :class="{red: questionBank.types==2, blue: questionBank.types==3}">{{types[questionBank.types-1]}}</text>
  14. <text class="h1" @click="speak(questionBank.title)">{{ questionBank.title}}</text>
  15. </view>
  16. <view class="imgBox" style="width: 100%;padding: 0 0 30rpx 0;" v-if="questionBank.img">
  17. <image :src="questionBank.img" mode="widthFix"></image>
  18. </view>
  19. <view class="option">
  20. <view v-for="(item,index) in questionBank.optionArr" @click="chooseOption(item)">
  21. <!-- 多选题 -->
  22. <view class="optionItem flex" v-if="questionBank.types ==2&& (!curOption.answer||curOption.answer==questionBank.answer)">
  23. <up-icon name="checkmark-circle-fill" color="#55ff7f" size="20" v-if="curOption.ans?.includes(item.key)"></up-icon>
  24. <view class="icon" v-else></view>
  25. <view class="text"><text >{{item.key}}</text> {{item.text}}</view>
  26. </view>
  27. <!-- 正常答案 -->
  28. <view class="optionItem flex" v-else >
  29. <view class="icon" v-if="!curOption.key&&questionBank.types !=2"></view>
  30. <up-icon name="checkmark-circle-fill" color="#55ff7f" size="20" v-else-if="questionBank.answer.includes(item.key)"></up-icon>
  31. <up-icon name="close-circle-fill" color="#ff0000" size="20" v-else></up-icon>
  32. <view class="text"><text v-if="questionBank.types!=3">{{item.key}}</text> {{item.text}}</view>
  33. </view>
  34. <!-- ans -->
  35. </view>
  36. </view>
  37. <view class="answerCss flex" v-if="curOption.answer&&questionBank.answer!=curOption.answer">
  38. <view class="ans">正确答案是
  39. <text v-if="questionBank.types==3" >{{ questionBank.answer=='false'?'错误':'正确' }}</text>
  40. <text v-else >{{ questionBank.answer }}</text>
  41. </view>
  42. <view class="ans">您的答案是
  43. <text v-if="questionBank.types==3" class="red">{{ curOption.answer=='false'?'错误':'正确' }}</text>
  44. <text v-else class="red">{{ curOption.answer }}</text>
  45. </view>
  46. </view>
  47. <view class="btn_row flex-b">
  48. <!-- @click="$goPage('/pages/exercises/lastPage/lastPage')" -->
  49. <button class="btn border" @click="debounce(nextQuestion(-1), 500)" :class="{disable: currentIndex==0}" :disabled="currentIndex==0">上一题</button>
  50. <button class="btn bg" @click="debounce(nextQuestion(1), 500)" :class="{disable: currentIndex>=quesIdList.length-1}" :disabled="currentIndex>=quesIdList.length-1">下一题</button>
  51. </view>
  52. <view class="analysis" v-if="currentNav==2||(curOption.answer&&curOption.answer!=questionBank.answer)">
  53. <view class="tit">题目解析</view>
  54. <view class="txt">{{ questionBank.resolving }}</view>
  55. </view>
  56. </view>
  57. <view class="bottomBar">
  58. <view class="ul">
  59. <view class="li">
  60. <view class="icon" style="color: #55ff7f;">{{ yesNum }}</view>
  61. <view class="text">答对</view>
  62. </view>
  63. <view class="li">
  64. <view class="icon" style="color: #ff0000;">{{ noNum }}</view>
  65. <view class="text">答错</view>
  66. </view>
  67. <view class="li">
  68. <view class="icon">{{currentIndex+1}}/<text style="color: #999; font-size: 24rpx;">{{quesIdList.length}}</text></view>
  69. <view class="text">题目</view>
  70. </view>
  71. <view class="li" @click="showCommt=true">
  72. <view class="icon">
  73. <image src="@/static/images/theory/fankui.png" mode=""></image>
  74. </view>
  75. <view class="text">反馈</view>
  76. </view>
  77. <view class="li" @click="openPopup">
  78. <view class="icon">
  79. <image src="@/static/images/theory/dtk.png" mode=""></image>
  80. </view>
  81. <view class="text">答题卡</view>
  82. </view>
  83. <view class="li" @click="questionWrongColleFn">
  84. <view class="icon">
  85. <image src="@/static/images/theory/scActive.png" mode="" v-if="questionBank.isCollect=='1'"></image>
  86. <image src="@/static/images/theory/sc.png" mode="" v-else></image>
  87. </view>
  88. <view class="text">收藏</view>
  89. </view>
  90. </view>
  91. </view>
  92. <up-popup :show="show" @close="closePopup" mode="bottom" round="20" closeable>
  93. <view class="popupCon">
  94. <view class="h3">答题卡</view>
  95. <view class="ulRow">
  96. <view class="ul">
  97. <view class="li">
  98. <view class="icon" style="color: #55ff7f;">{{ yesNum }}</view>
  99. <view class="text">答对</view>
  100. </view>
  101. <view class="li">
  102. <view class="icon" style="color: #ff0000;">{{ noNum }}</view>
  103. <view class="text">答错</view>
  104. </view>
  105. <view class="li" style="margin-left: auto;">
  106. <view class="icon">{{currentIndex+1}}/<text style="color: #999; font-size: 24rpx;">{{quesIdList.length}}</text></view>
  107. <view class="text">题目</view>
  108. </view>
  109. </view>
  110. </view>
  111. <view class="ul2">
  112. <view class="li2" v-for="(item,index) in quesIdList" :key="index" @click="quesIdListClick(item,index)">
  113. <view class="num" :class="{active: index==currentIndex}">{{ index+1 }}</view>
  114. </view>
  115. </view>
  116. </view>
  117. </up-popup>
  118. <up-popup :show="showCommt" @close="showCommtClose" mode="bottom" round="20rpx" closeable>
  119. <view class="commtCon" style="padding: 30rpx">
  120. <up-textarea v-model.trim="contentStr" placeholder="请输入反馈内容" style="margin-top: 50rpx;" maxlength="300"></up-textarea>
  121. <up-button text="提 交" style="margin-top: 20rpx;" type="primary" @click="submitCommt"></up-button>
  122. </view>
  123. </up-popup>
  124. </view>
  125. </template>
  126. <script setup>
  127. import { nextTick } from 'vue';
  128. function speak(text) {
  129. const speech = new SpeechSynthesisUtterance(text); // 创建语音消息
  130. window.speechSynthesis.speak(speech); // 播报消息
  131. }
  132. import { startQuestionApi, submitAnswerResultApi, getQuestionApi, questionCommentAdd, questionWrongColle, findQuestionList} from '@/config/api.js'
  133. import { debounce } from '@/uni_modules/uview-plus';
  134. import {
  135. ref,
  136. reactive
  137. } from 'vue';
  138. const currentNav = ref('1')
  139. const types = ref([
  140. '单选题',
  141. '多选题',
  142. '判断题'
  143. ])
  144. const yesNum = ref(0)
  145. const noNum = ref(0)
  146. import carStore from '@/store/modules/car.js'
  147. let usecarStore = carStore()
  148. import questionStore from '@/store/modules/wrongQuestionBook.js'
  149. let usequestionStore = questionStore()
  150. import {
  151. onLoad,
  152. onReady
  153. } from "@dcloudio/uni-app"
  154. // 1:单选题,2:多选题,3:判断题
  155. function changeNav(val) {
  156. console.log(window)
  157. if(currentNav.value == val) return
  158. currentNav.value = val
  159. }
  160. function goEmam() {
  161. uni.navigateTo({
  162. // url: '/pages/exercises/exam/exam',
  163. // url: '/pages/exercises/beforeExam/beforeExam',
  164. // url: '/pages/exercises/examResults/examResults',
  165. // url: '/pages/exercises/wrongQuestion/wrongQuestion',
  166. // url: '/pages/exercises/theoryStudy/theoryStudy',
  167. url: '/pages/vip/vipEntry/vipEntry'
  168. })
  169. }
  170. function changeTabbar(val) {
  171. console.log(val)
  172. }
  173. const show = ref(false)
  174. function closePopup() {
  175. show.value = false
  176. }
  177. function openPopup() {
  178. uni.showLoading({
  179. title: '正在加载'
  180. })
  181. show.value = true
  182. setTimeout(()=>{
  183. uni.hideLoading()
  184. },1800)
  185. }
  186. let showCommt = ref(false)
  187. let contentStr = ref('')
  188. function showCommtClose() {
  189. showCommt.value = false
  190. contentStr.value = ''
  191. }
  192. // 提交反馈
  193. async function submitCommt() {
  194. if(!contentStr.value) return uni.$u.toast('请输入内容')
  195. let obj = {
  196. content: contentStr.value,
  197. questionId: questionBank.value.id
  198. }
  199. const res = await questionCommentAdd(obj)
  200. if(res.errorcode==0) {
  201. uni.$u.toast('提交成功,感谢您的反馈')
  202. showCommt.value = false
  203. }
  204. }
  205. onLoad((options)=>{
  206. if(options.wrong) {
  207. findQuestionListFn(options.wrong)
  208. }else {
  209. startQuestionFn()
  210. }
  211. })
  212. // 请求数据
  213. const questionBank = ref({})
  214. let quesIdList = ref([])
  215. let currentIndex = ref(0)
  216. async function findQuestionListFn(type) {
  217. let obj = {
  218. "carType": usecarStore.carInfo.carType,
  219. "chapter": usecarStore.carInfo.chapter,
  220. "isHigh": '',
  221. "stepType": usecarStore.carInfo.stepType,
  222. "type": type
  223. }
  224. const {data: res} = await findQuestionList(obj)
  225. }
  226. async function startQuestionFn() {
  227. try{
  228. uni.showLoading({
  229. title: '正在加载...'
  230. })
  231. let obj = {
  232. carType: usecarStore.carInfo.carType,
  233. stepType: usecarStore.carInfo.stepType,
  234. volume: usecarStore.carInfo.volume,
  235. types: usecarStore.carInfo.types,
  236. sift: usecarStore.carInfo.sift,
  237. contentType: usecarStore.carInfo.contentType,
  238. knowType: usecarStore.carInfo.knowType,
  239. chapter: usecarStore.carInfo.chapter,
  240. city: usecarStore.carInfo.city,
  241. }
  242. const {data: res} = await startQuestionApi(obj)
  243. uni.hideLoading()
  244. questionBank.value = res.questionBank
  245. initOptionArr()
  246. quesIdList.value = res.quesIdList
  247. currentIndex.value = quesIdList.value.findIndex(item=>item==questionBank.value.id)
  248. }catch(e){
  249. uni.hideLoading()
  250. }
  251. }
  252. function initOptionArr() {
  253. questionBank.value.optionArr = []
  254. let abcd = [
  255. 'a',
  256. 'b',
  257. 'c',
  258. 'd',
  259. 'e',
  260. 'f'
  261. ]
  262. abcd.forEach((k,i)=>{
  263. let option = 'option'+k
  264. if(questionBank.value[option]) {
  265. let obj = {
  266. key: k.toLocaleUpperCase(),
  267. text: questionBank.value[option],
  268. index: i+1
  269. }
  270. questionBank.value.optionArr.push(obj)
  271. // console.log(questionBank.value.optionArr)
  272. }
  273. })
  274. // 如果是判断题
  275. if(questionBank.value.types==3) {
  276. questionBank.value.optionArr[0].key = 'true'
  277. questionBank.value.optionArr[1].key = 'false'
  278. }
  279. }
  280. // 下一题
  281. async function nextQuestion(num) {
  282. // 如果是多选题,什么时候不直接请求下一题,是多选题 ,并且有答案,答错了,并且不是next
  283. if(questionBank.value.types==2 && curOption.value.ans) {
  284. // 如果没有请求就请求一下
  285. if(!curOption.value.answer) {
  286. curOption.value.answer = curOption.value.ans
  287. await submitAnswerResultFn()
  288. }
  289. // 如果答案不一样,并且是第一次请求
  290. if(questionBank.value.answer != curOption.value.ans&&curOption.value.isNext != 'next') {
  291. curOption.value.isNext = 'next'
  292. return false
  293. }
  294. }
  295. curOption.value = {}
  296. currentIndex.value = currentIndex.value + num
  297. questionBank.value.optionArr = []
  298. getQuestionFn()
  299. }
  300. // 请求下一题
  301. async function getQuestionFn() {
  302. console.log(currentIndex.value)
  303. let questionId = quesIdList.value[currentIndex.value]
  304. let obj = {
  305. "carType": usecarStore.carInfo.carType,
  306. "questionId": questionId,
  307. "sort": currentIndex.value,
  308. "stepType": usecarStore.carInfo.stepType,
  309. 'tempId': questionBank.value.questionDoTemp.id
  310. }
  311. const {data: res} = await getQuestionApi(obj)
  312. questionBank.value = res
  313. curOption.value.isNext = ''
  314. initOptionArr()
  315. }
  316. async function quesIdListClick(id, index) {
  317. curOption.value = {}
  318. currentIndex.value = index
  319. questionBank.value.optionArr = []
  320. getQuestionFn()
  321. show.value = false
  322. }
  323. // 选择答案
  324. const curOption = ref({})
  325. async function chooseOption(item) {
  326. // console.log(item)
  327. if(curOption.value.answer) return
  328. if(questionBank.value.types != 2) {
  329. item.answer = item.key
  330. curOption.value = item
  331. submitAnswerResultFn()
  332. }else if(questionBank.value.types == 2){
  333. if(!curOption.value.ans) curOption.value.ans = ''
  334. if(curOption.value.ans.includes(item.key)) {
  335. curOption.value.ans = curOption.value.ans.replace(item.key, '')
  336. return
  337. }
  338. curOption.value.ans = (curOption.value.ans + item.key).split('').sort().join('')
  339. // console.log(curOption.value.ans)
  340. }
  341. }
  342. // 提交请求
  343. async function submitAnswerResultFn() {
  344. let obj = {
  345. answer: curOption.value.answer,
  346. carType: usecarStore.carInfo.carType,
  347. questionId: questionBank.value.id,
  348. result: curOption.value.answer==questionBank.value.answer?'0':'1',
  349. stepType: usecarStore.carInfo.stepType,
  350. tempId: questionBank.value.questionDoTemp.id
  351. }
  352. const res = await submitAnswerResultApi(obj)
  353. // if(res.errorcode!=0) return
  354. if(curOption.value.answer==questionBank.value.answer) {
  355. console.log('答对了')
  356. curOption.value = {}
  357. questionBank.value.optionArr = []
  358. yesNum.value ++
  359. usequestionStore.lookList(questionBank.value.id)
  360. console.log(usequestionStore.wrongList)
  361. nextQuestion(1)
  362. }else {
  363. noNum.value ++
  364. usequestionStore.setList(questionBank.value.id)
  365. console.log(usequestionStore.wrongList)
  366. }
  367. // console.log(res)
  368. }
  369. async function questionWrongColleFn() {
  370. let isAdd = questionBank.value.isCollect==1?'0':'1'
  371. const obj = {
  372. "carType": usecarStore.carInfo.carType,
  373. "isAdd": isAdd,
  374. "questionId": questionBank.value.id,
  375. "stepType": usecarStore.carInfo.stepType
  376. }
  377. const res = await questionWrongColle(obj)
  378. questionBank.value.isCollect = isAdd
  379. console.log(questionBank.value.isCollect)
  380. }
  381. </script>
  382. <style lang="scss" scoped>
  383. image {display: block;width: 100%;height: 100%;}
  384. .bottomBar {
  385. position: fixed;
  386. bottom: 0;
  387. left: 0;
  388. width: 100%;
  389. height: 98rpx;
  390. background: #FFFFFF;
  391. border-top: 1rpx solid #F4F4F4;
  392. }
  393. .ul {
  394. display: flex;
  395. justify-content: space-between;
  396. height: 100%;
  397. align-items: center;
  398. .li {
  399. width: 16.6%;
  400. display: flex;
  401. flex-direction: column;
  402. align-items: center;
  403. justify-content: center;
  404. .icon {
  405. font-size: 30rpx;
  406. height: 30rpx;
  407. line-height: 30rpx;
  408. image {
  409. display: block;
  410. margin-top: 4rpx;
  411. width: 26rpx;
  412. height: 26rpx;
  413. }
  414. }
  415. .text {
  416. font-weight: 500;
  417. font-size: 24rpx;
  418. color: #999999;
  419. margin-top: 10rpx;
  420. }
  421. }
  422. }
  423. .content {
  424. padding: 120rpx 0;
  425. min-height: 100vh;
  426. .u-nav-slot {
  427. width: 306rpx;
  428. height: 54rpx;
  429. border-radius: 10rpx;
  430. border: 1px solid #333333;
  431. display: flex;
  432. .btn {
  433. font-size: 24rpx;
  434. color: #333333;
  435. flex: 1;
  436. text-align: center;
  437. line-height: 54rpx;
  438. &.active {
  439. background-color: #333333;
  440. color: #fff;
  441. }
  442. }
  443. }
  444. .btn_row {
  445. padding: 60rpx 0 30rpx 0;
  446. .btn {
  447. width: 44%;
  448. height: 76rpx;
  449. border-radius: 38rpx;
  450. border: 1rpx solid $themC;
  451. line-height: 76rpx;
  452. text-align: center;
  453. font-size: 28rpx;
  454. color: $themC;
  455. &.disable {
  456. opacity: 0.4;
  457. }
  458. &.bg {
  459. background: #3776FF;
  460. border-radius: 38rpx;
  461. color: #fff;
  462. }
  463. }
  464. }
  465. .con {
  466. .h1_row {
  467. margin-bottom: 50rpx;
  468. .tag {
  469. display: inline-block;
  470. // width: 66px;
  471. height: 36rpx;
  472. line-height: 36rpx;
  473. padding: 4rpx 6rpx;
  474. background: #63C168;
  475. border-radius: 6rpx;
  476. margin-top: -2rpx;
  477. margin-right: 16rpx;
  478. font-size: 28rpx;
  479. color: #fff;
  480. &.blue {
  481. background: #3776FF;
  482. }
  483. &.red {
  484. background: orangered;
  485. }
  486. }
  487. text.h1 {
  488. font-size: 36rpx;
  489. }
  490. }
  491. .option {
  492. width: 100%;
  493. .optionItem {
  494. margin-bottom: 50rpx;
  495. align-items: center;
  496. .icon {
  497. width: 36rpx;
  498. height:36rpx;
  499. border-radius: 50%;
  500. border: 1rpx solid #999;
  501. }
  502. .text {
  503. font-size: 32rpx;
  504. margin-left: 16rpx;
  505. }
  506. }
  507. }
  508. .answerCss {
  509. height: 90rpx;
  510. background: #F4F4F4;
  511. padding: 30rpx;
  512. margin-top: 20rpx;
  513. justify-content: space-around;
  514. .ans {
  515. font-size: 30rpx;
  516. text {
  517. &.red {
  518. color: red;
  519. }
  520. }
  521. }
  522. }
  523. .analysis {
  524. margin-top: 60rpx;
  525. .tit {
  526. font-weight: 700;
  527. font-size: 32rpx;
  528. position: relative;
  529. padding-left: 30rpx;
  530. &::after {
  531. content: '';
  532. position: absolute;
  533. left: 0;
  534. top: 8rpx;
  535. width: 6rpx;
  536. height: 30rpx;
  537. background: linear-gradient(0deg, #43EA80 0%, #38F8D4 100%);
  538. border-radius: 3rpx;
  539. }
  540. }
  541. .txt {
  542. margin-top: 39rpx;
  543. font-size: 32rpx;
  544. color: #333333;
  545. }
  546. }
  547. }
  548. }
  549. .popupCon {
  550. width: 100%;
  551. height: calc(100vh - 200rpx);
  552. .h3 {
  553. height: 88rpx;
  554. border-bottom: 1px solid #F4F4F4;
  555. line-height: 88rpx;
  556. font-size: 30rpx;
  557. padding: 0rpx 0 0 30rpx;
  558. }
  559. .ulRow {
  560. height: 100rpx;
  561. padding: 30rpx 0;
  562. }
  563. .ul2 {
  564. display: flex;
  565. flex-wrap: wrap;
  566. padding: 30rpx 10rpx;
  567. height: calc(100vh - 388rpx);
  568. overflow-y: auto;
  569. align-content: flex-start;
  570. .li2 {
  571. width: 16.6%;
  572. margin-bottom: 20rpx;
  573. .num {
  574. width: 100rpx;
  575. height: 100rpx;
  576. border-radius: 50%;
  577. margin: auto;
  578. background: #F6F7FA;
  579. font-size: 32rpx;
  580. line-height: 100rpx;
  581. text-align: center;
  582. &.active {
  583. border: 1px solid #63C168;
  584. background: rgba(99,193,104,0.1);
  585. color: #63C168;
  586. }
  587. }
  588. }
  589. }
  590. }
  591. </style>