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.

566 lines
14 KiB

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