index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. <template>
  2. <view class="box" @touchstart="touchStart" @touchend="touchEnd">
  3. <nav-bar :title="navTitle"> </nav-bar>
  4. <view style="text-align: center">
  5. <van-count-down :time="time"></van-count-down>
  6. </view>
  7. <view class="divider"></view>
  8. <view class="problem-box">
  9. <span class="problem-type">{{
  10. problemList[problemListIndex].questionType | questionType
  11. }}</span>
  12. <!-- <text>{{ problemListIndex + 1 }}、</text> -->
  13. <text class="problem-issue">{{
  14. problemList[problemListIndex].issue
  15. }}</text>
  16. <view v-if="problemList[problemListIndex].image" class="problem-img">
  17. <image
  18. mode="widthFix"
  19. :src="problemList[problemListIndex].image"
  20. ></image>
  21. </view>
  22. <!-- 单项选择 -->
  23. <view
  24. v-if="problemList[problemListIndex].questionType < 3"
  25. class="problem-ops"
  26. >
  27. <van-radio-group
  28. :value="problemList[problemListIndex].userAnswer"
  29. :max="1"
  30. @change="changeGroup"
  31. >
  32. <van-radio
  33. @change="changeCheckbox"
  34. :value="
  35. problemList[problemListIndex].userAnswer.includes(
  36. problemList[problemListIndex].answer
  37. )
  38. "
  39. class="problem-checkbox"
  40. use-icon-slot
  41. v-for="(item, index) in problemList[problemListIndex].optsArr"
  42. :key="index"
  43. :name="item"
  44. >
  45. <text>{{ item }}</text>
  46. <view
  47. class="problem-op"
  48. :class="{
  49. 'problem-op_selected':
  50. problemList[problemListIndex].userAnswer.includes(item),
  51. }"
  52. slot="icon"
  53. >{{ numberToLetter(index) }}</view
  54. >
  55. </van-radio>
  56. </van-radio-group>
  57. </view>
  58. <!-- 多项选择 -->
  59. <view
  60. v-if="problemList[problemListIndex].questionType == 3"
  61. class="problem-ops"
  62. >
  63. <van-checkbox-group
  64. :value="problemList[problemListIndex].userAnswer"
  65. :max="4"
  66. @change="changeGroup"
  67. >
  68. <van-checkbox
  69. @change="changeCheckbox"
  70. :value="
  71. problemList[problemListIndex].userAnswer.includes(
  72. problemList[problemListIndex].answer
  73. )
  74. "
  75. class="problem-checkbox"
  76. use-icon-slot
  77. v-for="(item, index) in problemList[problemListIndex].optsArr"
  78. :key="index"
  79. :name="item"
  80. >
  81. <text>{{ item }}</text>
  82. <view
  83. class="problem-op"
  84. :class="{
  85. 'problem-op_selected':
  86. problemList[problemListIndex].userAnswer.includes(item),
  87. }"
  88. slot="icon"
  89. >{{ numberToLetter(index) }}</view
  90. >
  91. </van-checkbox>
  92. </van-checkbox-group>
  93. </view>
  94. <view class="function-list">
  95. <div class="function-item">
  96. <van-icon name="star-o" size="25px" />
  97. <span>收藏</span>
  98. </div>
  99. <!-- <div class="function-item" @click="answerAudioPlay">
  100. <m-icon type="a-dtda" size="25px" />
  101. <span>读题+答案</span>
  102. </div> -->
  103. <div
  104. @click="readQuestion(problemList[problemListIndex].issuemp3)"
  105. class="function-item"
  106. >
  107. <van-icon name="bullhorn-o" size="25px" />
  108. <span>读题</span>
  109. </div>
  110. <!-- <div class="function-item" @click="currentAnswerIndexBack">
  111. <m-icon type="shangyiti" size="25px" />
  112. <span>上一题</span>
  113. </div>
  114. <div class="function-item" @click="skillsShow = true">
  115. <m-icon type="zongtishu" size="25px" />
  116. <span>1/100</span>
  117. </div>
  118. <div class="function-item" @click="currentAnswerIndexGo">
  119. <m-icon type="xiayiti" size="25px" />
  120. <span>下一题</span>
  121. </div> -->
  122. </view>
  123. </view>
  124. <van-tabbar>
  125. <van-tabbar-item @click="goBeforeTopics"
  126. ><van-icon
  127. slot="icon"
  128. custom-style="transform: rotate(90deg);"
  129. custom-class="last-subject"
  130. name="down"
  131. size="18px"
  132. />上一题
  133. </van-tabbar-item>
  134. <van-tabbar-item
  135. ><van-icon slot="icon" size="18px" name="description" />{{
  136. problemListIndex + 1
  137. }}/{{ problemListTotal }}
  138. </van-tabbar-item>
  139. <van-tabbar-item @click="submitExam"
  140. ><van-icon slot="icon" size="18px" name="records" />交卷
  141. </van-tabbar-item>
  142. <van-tabbar-item @click="goNextTopics"
  143. ><van-icon
  144. slot="icon"
  145. custom-style="transform: rotate(-90deg);"
  146. custom-class="last-subject"
  147. name="down"
  148. size="18px"
  149. />下一题
  150. </van-tabbar-item>
  151. </van-tabbar>
  152. </view>
  153. </template>
  154. <script>
  155. import navBar from "./components/navBar.vue";
  156. import api from "@/api/index";
  157. import utils from "@/utils/index";
  158. export default {
  159. data() {
  160. return {
  161. query: {
  162. cert: "",
  163. vehicle: "",
  164. subject: "",
  165. title: "",
  166. },
  167. examTimer: 0,
  168. examTimeUse: 0,
  169. time: 45 * 60 * 1000,
  170. problemListTotal: 1,
  171. problemList: [
  172. {
  173. answer: "×",
  174. answerkeyword: "",
  175. answermp3:
  176. "https://t1-1305573081.file.myqcloud.com/kt/answer_mp3/answer1389.mp3",
  177. classIssue: "54",
  178. classIssueName: "车内开关/装置",
  179. classSort: 16,
  180. createTime: "2022-04-21 13:33:46",
  181. excellIssue: "23",
  182. excellIssueName: "必学题三",
  183. excellSort: 4,
  184. explainGif:
  185. "https://t1-1305573081.file.myqcloud.com/kt/explain_gif/explain1389.gif",
  186. explainJq:
  187. "看图答题:红色圆圈套在杆子中间.答对;不在中间或没有圆圈的.答错。",
  188. explainJs:
  189. "图中所示为左右转向灯开关转向灯操作:上提是右转向灯亮起,下压是左转向灯。",
  190. explainMp3:
  191. "https://t1-1305573081.file.myqcloud.com/kt/explain_mp3/explain1389.mp3",
  192. explainjsmp3:
  193. "https://t1-1305573081.file.myqcloud.com/kt/explain_js_mp3/explainJS1389.mp3",
  194. id: 831,
  195. idKt: 1389,
  196. idYdt: 950,
  197. image:
  198. "https://t1-1305573081.file.myqcloud.com/kt/image/image1389.png",
  199. imageYdt:
  200. "https://t1-1305573081.file.myqcloud.com/kt/image_ydt/5eb4d75agw1e291vmniovj.jpg",
  201. issue: "将转向灯开关向上提,左转向灯亮。",
  202. issuemp3:
  203. "https://t1-1305573081.file.myqcloud.com/kt/issue_mp3/issue1389.mp3",
  204. liceBus: "1",
  205. liceCar: "1",
  206. liceMoto: null,
  207. liceTruck: "1",
  208. number: 831,
  209. opts: "√-×",
  210. optsArr: ["√", "×"],
  211. placeIssue: null,
  212. placeIssueName: null,
  213. placeSort: null,
  214. questionType: 1,
  215. sequeIssue: "7",
  216. sequeIssueName: "机械仪表",
  217. sequeSort: 25,
  218. skillkeyword: "没有圆圈-答错",
  219. subject: 1,
  220. titlekeyword: "",
  221. updateTime: "2022-04-22 13:43:07",
  222. userAnswer: [],
  223. },
  224. ],
  225. touchx: 0,
  226. touchy: 0,
  227. problemListIndex: 0,
  228. };
  229. },
  230. filters: {
  231. questionType: function (value) {
  232. let question = "";
  233. switch (value) {
  234. case 1:
  235. case "1":
  236. question = "判断题";
  237. break;
  238. case 2:
  239. case "2":
  240. question = "单选题";
  241. break;
  242. case 3:
  243. case "3":
  244. question = "多选题";
  245. break;
  246. }
  247. return question;
  248. },
  249. },
  250. methods: {
  251. touchStart(e) {
  252. var that = this;
  253. (this.touchx = e.changedTouches[0].clientX),
  254. (this.touchy = e.changedTouches[0].clientY);
  255. },
  256. touchEnd(e) {
  257. console.log(e);
  258. var that = this;
  259. let x = e.changedTouches[0].clientX;
  260. let y = e.changedTouches[0].clientY;
  261. let turn = "";
  262. if (x - that.touchx > 50 && Math.abs(y - that.touchy) < 50) {
  263. //右滑
  264. turn = "right";
  265. this.problemListIndex <= 0
  266. ? uni.showToast({
  267. title: "到底了",
  268. icon: "none",
  269. })
  270. : this.problemListIndex--;
  271. } else if (x - that.touchx < -50 && Math.abs(y - that.touchy) < 50) {
  272. //左滑
  273. turn = "left";
  274. this.problemListIndex >= this.problemList.length - 1
  275. ? uni.showToast({
  276. title: "到底了",
  277. icon: "none",
  278. })
  279. : this.problemListIndex++;
  280. }
  281. if (y - that.touchy > 50 && Math.abs(x - that.touchx) < 50) {
  282. //下滑
  283. turn = "down";
  284. } else if (y - that.touchy < -50 && Math.abs(x - that.touchx) < 50) {
  285. //上滑
  286. turn = "up";
  287. }
  288. //根据方向进行操作
  289. if (turn == "down") {
  290. //下滑触发操作
  291. }
  292. console.log(turn);
  293. },
  294. submitExam(e) {
  295. let score = 0;
  296. let query = this.query;
  297. let that = this;
  298. this.problemList.forEach((item, index) => {
  299. if (
  300. typeof item.userAnswer == "object" &&
  301. Array.isArray(item.userAnswer)
  302. ) {
  303. let answerArr = item.answer.split("-");
  304. answerArr = answerArr.sort();
  305. let userAnswer = item.userAnswer.sort();
  306. if (index > 39) {
  307. console.log(answerArr, userAnswer);
  308. }
  309. if (answerArr.join("-") === userAnswer.join("-")) {
  310. score = score + 1;
  311. }
  312. } else if (typeof item.userAnswer == "string") {
  313. item.answer === item.userAnswer ? (score = score + 1) : "";
  314. }
  315. });
  316. uni.showModal({
  317. title: "是否交卷",
  318. content: "交卷后不可再修改了",
  319. success(res) {
  320. if (res.confirm) {
  321. let useTime = "";
  322. let useTimer = new Date(that.examTimeUse);
  323. clearInterval(that.examTimer);
  324. useTime = `${useTimer.getMinutes()}:${useTimer.getSeconds()}`;
  325. uni.navigateTo({
  326. url:
  327. "/otherPages/mockExamEnd/index?" +
  328. utils.mapToUrlQuery({
  329. score,
  330. useTime,
  331. ...query,
  332. }),
  333. });
  334. }
  335. },
  336. fail() {},
  337. });
  338. },
  339. goBeforeTopics() {
  340. if (this.problemListIndex <= 0) {
  341. uni.showToast({
  342. title: "到底了",
  343. icon: "none",
  344. });
  345. return;
  346. }
  347. this.problemListIndex = this.problemListIndex - 1;
  348. },
  349. goNextTopics() {
  350. if (this.problemListIndex >= this.problemList.length - 1) {
  351. uni.showToast({
  352. title: "到底了",
  353. icon: "none",
  354. });
  355. return;
  356. }
  357. this.problemListIndex = this.problemListIndex + 1;
  358. },
  359. readQuestion(e) {
  360. let globalAudio = utils.wxUtils.getGlobAudio();
  361. if (globalAudio) {
  362. globalAudio.src = e;
  363. globalAudio.stop();
  364. globalAudio.play();
  365. }
  366. },
  367. changeGroup(e) {
  368. this.$set(
  369. this.problemList[this.problemListIndex],
  370. "userAnswer",
  371. e.detail
  372. );
  373. },
  374. changeCheckbox(e) {
  375. console.log(e);
  376. },
  377. numberToLetter(index) {
  378. index = Number(index);
  379. return String.fromCharCode(index + 65);
  380. },
  381. },
  382. onLoad(query) {
  383. let that = this;
  384. this.query = query;
  385. api.exam
  386. .studentQuestionInfoSelectTestQuestionInfo({
  387. ...this.query,
  388. })
  389. .then((res) => {
  390. res.rows.forEach((element) => {
  391. element.optsArr = element.opts.split("-");
  392. element.userAnswer = [];
  393. });
  394. that.problemListTotal = res.total;
  395. that.problemList = res.rows;
  396. });
  397. this.examTimer = setInterval(() => {
  398. this.examTimeUse = this.examTimeUse + 1000;
  399. if (this.examTimeUse > this.time) {
  400. this.submitExam();
  401. clearInterval(this.examTimer);
  402. }
  403. }, 1000);
  404. },
  405. computed: {
  406. //liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=顺序练习&sort=3
  407. navTitle() {
  408. let subjectName = this.query.subject == 1 ? "科目一" : "科目四";
  409. return `(${this.query.cert})/${subjectName}/${this.query.title}`;
  410. },
  411. },
  412. destroyed() {
  413. clearInterval(this.examTimer);
  414. },
  415. components: {
  416. navBar,
  417. },
  418. };
  419. </script>
  420. <style lang="scss" scoped>
  421. .divider {
  422. width: 100%;
  423. height: 24rpx;
  424. background-color: #f2f3f5;
  425. }
  426. .box {
  427. width: 100%;
  428. height: 100vh;
  429. background: #fff;
  430. .last-subject {
  431. transform: rotate(90deg);
  432. }
  433. .function-list {
  434. width: 100%;
  435. font-size: 13px;
  436. display: flex;
  437. justify-content: space-around;
  438. flex-wrap: wrap;
  439. padding: 15px;
  440. box-sizing: border-box;
  441. .function-item {
  442. margin-bottom: 20px;
  443. width: 30%;
  444. display: flex;
  445. flex-direction: column;
  446. align-items: center;
  447. font-size: 13px;
  448. font-weight: 400;
  449. color: #8a9099;
  450. span {
  451. margin-top: 5px;
  452. }
  453. }
  454. }
  455. .problem-box {
  456. padding: 15rpx;
  457. background: #fff;
  458. /deep/ .van-checkbox {
  459. padding-bottom: 15rpx;
  460. }
  461. /deep/ .van-radio {
  462. padding-bottom: 15rpx;
  463. }
  464. .problem-issue {
  465. font-size: 42rpx;
  466. }
  467. .problem-type {
  468. padding-left: 10rpx;
  469. padding-right: 10rpx;
  470. padding-top: 4rpx;
  471. padding-bottom: 4rpx;
  472. font-size: 24rpx;
  473. border-radius: 16rpx 16rpx 0 16rpx;
  474. background: #498ef5;
  475. margin-right: 10rpx;
  476. color: #fff;
  477. font-size: 32rpx;
  478. }
  479. .problem-ops {
  480. margin-top: 30rpx;
  481. padding-left: 30rpx;
  482. .problem-checkbox {
  483. height: 100rpx;
  484. }
  485. }
  486. .problem-op {
  487. width: 75rpx;
  488. height: 75rpx;
  489. line-height: 75rpx;
  490. border-radius: 50%;
  491. text-align: center;
  492. overflow: hidden;
  493. background: #fff;
  494. box-shadow: 0px 4rpx 12rpx rgba(0, 0, 0, 0.16);
  495. }
  496. .problem-op_selected {
  497. background: #498ef5;
  498. }
  499. .problem-img {
  500. width: 100%;
  501. margin-top: 20rpx;
  502. display: flex;
  503. justify-content: center;
  504. image {
  505. margin: 0 auto;
  506. }
  507. }
  508. }
  509. }
  510. </style>