kaoshiChengjiInfo.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. <template>
  2. <view class="phone-kaoshi-page">
  3. <customNavbarVue :title="data.name" :show-back-btn="true" @back="handleBack"></customNavbarVue>
  4. <!-- 第一行 -->
  5. <view class="kaoshi-page-title">
  6. <view v-if="activeSt" class="title-types">{{dlName}}</view>
  7. <view>100分钟</view>
  8. </view>
  9. <view class="kaoshi-shiti-content">
  10. <!-- 内容区域 -->
  11. <!-- 试题区域 -->
  12. <view v-if="activeSt">
  13. <template v-if="activeSt.stTypeId == 1">
  14. <!-- 单选 -->
  15. <danxuan :question="activeSt" :key="activeSt.stId"></danxuan>
  16. </template>
  17. <template v-if="activeSt.stTypeId == 2">
  18. <!-- 多选 -->
  19. <duoxuan :question="activeSt" :key="activeSt.stId"></duoxuan>
  20. </template>
  21. <template v-if="activeSt.stTypeId == 3">
  22. <!-- 判断 -->
  23. <panduan :question="activeSt" :key="activeSt.stId"></panduan>
  24. </template>
  25. <template v-if="activeSt.stTypeId == 4">
  26. <!-- 填空 -->
  27. <tiankong :question="activeSt" :key="activeSt.stId"></tiankong>
  28. </template>
  29. <template v-if="activeSt.stTypeId == 5">
  30. <!-- 简答 -->
  31. <jianda :question="activeSt" :key="activeSt.stId"></jianda>
  32. </template>
  33. <template v-if="activeSt.stTypeId == 6">
  34. <!-- 阅读 -->
  35. <yuedu :question="activeSt" :key="activeSt.stId" @yudu-change="onYueduChange"></yuedu>
  36. </template>
  37. </view>
  38. </view>
  39. <view class="kaoshi-bottom-box">
  40. <view @click="showAnswerCard" class="shiti-num-box">
  41. <text>
  42. {{data.userScore}} / {{data.ksScore}}分
  43. </text>
  44. <icon class="shiti-num-icon"></icon>
  45. <text
  46. class="active-num">{{activeSt ? activeSt.onlyNum: 0}}</text>/<text>{{data.StListForSearch.length}}</text>
  47. </view>
  48. </view>
  49. <template v-if="activeSt">
  50. <button type="default" size="mini" hover-class="none" class="phone-green-btn ks-btn-prev"
  51. @click="handlePrev" v-if="!isFistStId">上一题</button>
  52. <button type="default" size="mini" hover-class="none" class="phone-green-btn ks-btn-next"
  53. @click="handleNext" v-if="!isLastStId">下一题</button>
  54. </template>
  55. <uni-popup ref="popupRef" background-color="#fff" :animation="false" :is-mask-click="false" :mask-click="false">
  56. <view class="answer-card-popup">
  57. <view class="icon-title-navBar-box">
  58. <view @click="handlePopupBack" class="nav-bar-icon"> </view>
  59. <text class="nav-bar-title">答题卡</text>
  60. </view>
  61. <view class="card-content-box">
  62. <view class="answer-card-content" v-for="(paragraph,paragraphIndex) in questionData"
  63. :key="paragraphIndex">
  64. <view class="paragraph-title">
  65. {{paragraph.name}}
  66. </view>
  67. <view class="paragraph-qa" v-for="(qa,qaIndex) in paragraph.qas" :key="qaIndex"
  68. :class="getQaClass(qa)" @click="answerCardItemClick(qa)">{{qa.onlyNum}}
  69. </view>
  70. </view>
  71. </view>
  72. </view>
  73. </uni-popup>
  74. <!-- 答案解析 -->
  75. <scoreAndAnswerVue ref="scoreAnswerRef"></scoreAndAnswerVue>
  76. <scoreAndAnswerAdminTiankong ref="scoreAnswerTkRef"></scoreAndAnswerAdminTiankong>
  77. <scoreAndAnswerAdminJianda ref="scoreAnswerJdRef"></scoreAndAnswerAdminJianda>
  78. </view>
  79. </template>
  80. <script setup>
  81. import {
  82. ref,
  83. reactive,
  84. computed,
  85. watch
  86. } from "vue";
  87. import {
  88. onLoad
  89. } from "@dcloudio/uni-app";
  90. import * as cjApi from "@/api/chengji.js"
  91. import danxuan from "@/components/questionsChengji/danxuan.vue";
  92. import duoxuan from "@/components/questionsChengji/duoxuan.vue";
  93. import tiankong from "@/components/questionsChengji/tiankong.vue";
  94. import panduan from "@/components/questionsChengji/panduan.vue";
  95. import jianda from "@/components/questionsChengji/jianda.vue";
  96. import yuedu from "@/components/questionsChengji/yuedu.vue";
  97. import scoreAndAnswerVue from "@/components/scoreAndAnswer/scoreAndAnswerAdmin.vue";
  98. import scoreAndAnswerAdminTiankong from "@/components/scoreAndAnswer/scoreAndAnswerAdminTiankong.vue";
  99. import scoreAndAnswerAdminJianda from "@/components/scoreAndAnswer/scoreAndAnswerJianda.vue";
  100. import customNavbarVue from "@/components/custom-navbar/custom-navbar.vue";
  101. import { useQuestionTools } from "@/utils/useQuestionTools.js";
  102. const {
  103. checkDanxuanReply,
  104. checkDuoxuanReply,
  105. checkPanduanReply,
  106. checkTiankongReply,
  107. getLetterByIndex,
  108. checkJiandaReply,
  109. checkYueduReply
  110. } = useQuestionTools();
  111. const stTypes = {
  112. 1: '单选题',
  113. 2: '多选题',
  114. 3: '判断题',
  115. 4: '填空题',
  116. }
  117. const popupRef = ref(null)
  118. const scoreAnswerRef = ref(null)
  119. const scoreAnswerTkRef = ref(null)
  120. const startCountDown = ref(false);
  121. const scoreAnswerJdRef = ref(null);
  122. const data = reactive({
  123. hisId: null,
  124. name: '',
  125. ksScore: '',
  126. scoreData: '',
  127. stTotal: 0,
  128. stScore: 0,
  129. biaoji: null,
  130. endSecond: 0,
  131. pageSize: 0,
  132. toggleScreenFlag: 0,
  133. toggleScreenSecond: 0,
  134. zhuapai: 0,
  135. duanluo: [],
  136. markDB: [],
  137. StListForSearch: [],
  138. })
  139. const yuduIndexQa = ref(null);
  140. const questionData = ref([]);
  141. const progress = reactive({
  142. dlIndex: 0,
  143. dtIndex: 0
  144. })
  145. const dlName = computed(() => {
  146. if (data.StListForSearch && activeSt.value) {
  147. return data.StListForSearch[activeSt.value.onlyNum - 1].paragraphName
  148. } else {
  149. return ''
  150. }
  151. })
  152. watch(() => data.duanluo, (newVal) => {
  153. // 计算已答试题数量
  154. }, {
  155. deep: true
  156. })
  157. const activeSt = computed(() => {
  158. if (questionData.value.length) {
  159. return questionData.value.length && questionData.value[progress.dlIndex].qas[progress.dtIndex];
  160. } else {
  161. return null
  162. }
  163. })
  164. const isFistStId = computed(() => {
  165. if (data.StListForSearch.length) {
  166. return data.StListForSearch[0].stId == activeSt.value.stId
  167. } else {
  168. return false
  169. }
  170. });
  171. const isLastStId = computed(() => {
  172. if (data.StListForSearch.length) {
  173. return data.StListForSearch[data.StListForSearch.length - 1].stId == activeSt.value.stId
  174. } else {
  175. return false
  176. }
  177. });
  178. onLoad((option) => {
  179. data.hisId = option.hisId;
  180. data.name = option.name;
  181. data.userScore = option.userScore;
  182. data.ksScore = option.ksScore;
  183. initKaoshi();
  184. })
  185. function onTimeUp() {
  186. console.log('end')
  187. }
  188. function answerCardItemClick(qa) {
  189. const actQa = data.StListForSearch.find(item => item.stId == qa.stId);
  190. skipQuestion(actQa.dlIndex, actQa.dtIndex)
  191. }
  192. function skipQuestion(dlIndex, dtIndex) {
  193. progress.dlIndex = dlIndex;
  194. progress.dtIndex = dtIndex;
  195. handlePopupBack()
  196. // 切换试题时清空阅读提解析
  197. yuduIndexQa.value = null;
  198. }
  199. function getQaClass(qa) {
  200. if (qa.marked && qa.marked === true) {
  201. return 'paragraph-qa-block-mark';
  202. } else {
  203. if (qa.stTypeId == 1) {
  204. if (checkDanxuanReply(qa)) {
  205. return 'paragraph-qa-block-done';
  206. } else {
  207. return 'paragraph-qa-block-init';
  208. }
  209. } else if (qa.stTypeId == 2) {
  210. if (checkDuoxuanReply(qa)) {
  211. return 'paragraph-qa-block-done';
  212. } else {
  213. return 'paragraph-qa-block-init';
  214. }
  215. } else if (qa.stTypeId == 3) {
  216. if (checkPanduanReply(qa)) {
  217. return 'paragraph-qa-block-done';
  218. } else {
  219. return 'paragraph-qa-block-init';
  220. }
  221. } else if (qa.stTypeId == 4) {
  222. if (checkTiankongReply(qa)) {
  223. return 'paragraph-qa-block-done';
  224. } else {
  225. return 'paragraph-qa-block-init';
  226. }
  227. } else if (qa.stTypeId == 5) {
  228. if (checkJiandaReply(qa)) {
  229. return 'paragraph-qa-block-done';
  230. } else {
  231. return 'paragraph-qa-block-init';
  232. }
  233. } else if (qa.stTypeId == 6) {
  234. if (checkYueduReply(qa)) {
  235. return 'paragraph-qa-block-done';
  236. } else {
  237. return 'paragraph-qa-block-init';
  238. }
  239. }
  240. }
  241. }
  242. function showAnswerCard() {
  243. popupRef.value.open('top')
  244. }
  245. function handlePopupBack() {
  246. popupRef.value.close()
  247. }
  248. function handlePrev() {
  249. const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
  250. const index = qa.num - 1;
  251. if (index > 0) {
  252. const result = data.StListForSearch[index - 1];
  253. progress.dlIndex = result.dlIndex;
  254. progress.dtIndex = result.dtIndex
  255. }
  256. // 切换试题时清空阅读提解析
  257. yuduIndexQa.value = null;
  258. }
  259. function handleNext() {
  260. const qa = data.StListForSearch.find(item => item.stId == activeSt.value.stId);
  261. const index = qa.num - 1;
  262. if (index < data.StListForSearch.length) {
  263. const result = data.StListForSearch[index + 1];
  264. console.log('resultresult',result);
  265. progress.dlIndex = result.dlIndex;
  266. progress.dtIndex = result.dtIndex
  267. }
  268. // 切换试题时清空阅读提解析
  269. yuduIndexQa.value = null
  270. }
  271. function formatDuanluoList(dlData) {
  272. let uIndex = 0; // 试题num
  273. let iDuanluo = 0; // 段落num
  274. let result = [];
  275. for (const duanluo of data.duanluo) {
  276. let paragraph = {
  277. qas: [],
  278. };
  279. paragraph.name = duanluo.name;
  280. let iQa = 0; // 当前试题序号
  281. let order = 0; // 当前题型中第几题
  282. for (const iDanxuan of duanluo.danxuan) {
  283. iDanxuan.type = 'danxuan';
  284. iDanxuan.marked = false;
  285. iDanxuan.onlyNum = uIndex + 1;
  286. iDanxuan.order = order;
  287. iDanxuan.iQa = iQa;
  288. iDanxuan.reply = iDanxuan.result;
  289. paragraph.qas.push(iDanxuan);
  290. uIndex++;
  291. order++;
  292. iQa++;
  293. data.StListForSearch.push({
  294. stId: iDanxuan.stId,
  295. paragraphName: paragraph.name,
  296. dlIndex: iDuanluo,
  297. dtIndex: iDanxuan.iQa,
  298. num: iDanxuan.onlyNum
  299. })
  300. }
  301. order = 0;
  302. for (const iDuoxuan of duanluo.duoxuan) {
  303. iDuoxuan.type = 'duoxuan';
  304. iDuoxuan.marked = false;
  305. iDuoxuan.onlyNum = uIndex + 1;
  306. iDuoxuan.order = order;
  307. paragraph.qas.push(iDuoxuan);
  308. iDuoxuan.reply = iDuoxuan.result;
  309. iDuoxuan.iQa = iQa;
  310. uIndex++;
  311. order++;
  312. iQa++;
  313. data.StListForSearch.push({
  314. stId: iDuoxuan.stId,
  315. paragraphName: paragraph.name,
  316. dlIndex: iDuanluo,
  317. dtIndex: iDuoxuan.iQa,
  318. num: iDuoxuan.onlyNum
  319. })
  320. }
  321. order = 0;
  322. for (const iPanduan of duanluo.panduan) {
  323. iPanduan.type = 'panduan';
  324. iPanduan.marked = false;
  325. iPanduan.onlyNum = uIndex + 1;
  326. iPanduan.order = order;
  327. paragraph.qas.push(iPanduan);
  328. iPanduan.reply = iPanduan.result;
  329. iPanduan.iQa = iQa;
  330. uIndex++;
  331. order++;
  332. iQa++;
  333. data.StListForSearch.push({
  334. stId: iPanduan.stId,
  335. paragraphName: paragraph.name,
  336. dlIndex: iDuanluo,
  337. dtIndex: iPanduan.iQa,
  338. num: iPanduan.onlyNum
  339. })
  340. }
  341. order = 0;
  342. for (const iTiankong of duanluo.tiankong) {
  343. iTiankong.type = 'tiankong';
  344. iTiankong.marked = false;
  345. iTiankong.onlyNum = uIndex + 1;
  346. iTiankong.order = order;
  347. paragraph.qas.push(iTiankong);
  348. iTiankong.reply = iTiankong.result.map(item => item[0]);
  349. iTiankong.iQa = iQa;
  350. uIndex++;
  351. order++;
  352. iQa++;
  353. data.StListForSearch.push({
  354. stId: iTiankong.stId,
  355. paragraphName: paragraph.name,
  356. dlIndex: iDuanluo,
  357. dtIndex: iTiankong.iQa,
  358. num: iTiankong.onlyNum
  359. })
  360. }
  361. order = 0;
  362. for (const iJianda of duanluo.jianda) {
  363. iJianda.marked = false;
  364. iJianda.type = 'jianda';
  365. iJianda.onlyNum = uIndex + 1;
  366. iJianda.order = order;
  367. iJianda.iQa = iQa;
  368. paragraph.qas.push(iJianda);
  369. iJianda.reply = '';
  370. uIndex++;
  371. order++;
  372. iQa++;
  373. data.StListForSearch.push({
  374. stId: iJianda.stId,
  375. paragraphName: paragraph.name,
  376. dlIndex: iDuanluo,
  377. dtIndex: iJianda.iQa,
  378. num: iJianda.onlyNum
  379. })
  380. }
  381. order = 0;
  382. for (const iYuedu of duanluo.yuedu) {
  383. iYuedu.marked = false;
  384. iYuedu.type = 'yuedu';
  385. iYuedu.onlyNum = uIndex + 1;
  386. iYuedu.order = order;
  387. iYuedu.iQa = iQa;
  388. if (iYuedu.duoxuan && iYuedu.duoxuan.length) {
  389. iYuedu.duoxuan.map((qIt) => {
  390. qIt.reply = qIt.reply || [];
  391. return qIt
  392. })
  393. }
  394. if (iYuedu.tiankong && iYuedu.tiankong.length) {
  395. iYuedu.tiankong.map((qIt) => {
  396. qIt.reply = new Array(qIt.count).fill('');
  397. return qIt;
  398. });
  399. }
  400. paragraph.qas.push(iYuedu);
  401. iYuedu.reply = [];
  402. uIndex++;
  403. order++;
  404. iQa++;
  405. data.StListForSearch.push({
  406. stId: iYuedu.stId,
  407. paragraphName: paragraph.name,
  408. dlIndex: iDuanluo,
  409. dtIndex: iYuedu.iQa,
  410. num: iYuedu.onlyNum
  411. })
  412. }
  413. iDuanluo++;
  414. questionData.value.push(paragraph)
  415. console.log(questionData.value)
  416. console.log(paragraph)
  417. }
  418. }
  419. // 切换阅读小题时更新当前试题解析
  420. function onYueduChange(qa) {
  421. yuduIndexQa.value = qa;
  422. }
  423. // 校验阅读解析
  424. function checkYueduJiexi() {
  425. debugger
  426. let qa = yuduIndexQa.value;
  427. let score = qa.userScore;
  428. let reply = '';
  429. let result = '';
  430. let answer = qa.answer;
  431. if (qa.stTypeId == 0) {
  432. // 单选题
  433. if (qa.reply && qa.reply.trim() !== '') {
  434. reply = getLetterByIndex(qa.reply)
  435. } else {
  436. reply = '未答'
  437. }
  438. if (qa.result) {
  439. result = getLetterByIndex(qa.result)
  440. } else {
  441. result = '无答案'
  442. }
  443. scoreAnswerRef.value.showPopup({
  444. score,
  445. reply,
  446. result,
  447. answer
  448. })
  449. }
  450. if (qa.stTypeId == 2) {
  451. // 多选题
  452. if (qa.reply && qa.reply.length) {
  453. reply = qa.reply.map(item => {
  454. if (item.trim()) {
  455. return getLetterByIndex(item.trim())
  456. }
  457. }).join(',')
  458. } else {
  459. reply = '未答'
  460. }
  461. if (qa.result) {
  462. result = qa.result.map(item => {
  463. if (item.trim()) {
  464. return getLetterByIndex(item.trim())
  465. }
  466. }).join(',')
  467. } else {
  468. result = '无答案'
  469. }
  470. scoreAnswerRef.value.showPopup({
  471. score,
  472. reply,
  473. result,
  474. answer
  475. })
  476. }
  477. if (qa.stTypeId == 3) {
  478. // 判断题
  479. if (qa.reply === '') {
  480. reply = '未答'
  481. } else if (qa.reply == 0) {
  482. reply = '错误'
  483. } else if (qa.reply == 1) {
  484. reply = '正确'
  485. }
  486. if (qa.result == 0) {
  487. result = '错误'
  488. } else if (qa.result == 1) {
  489. result = '正确'
  490. }
  491. scoreAnswerRef.value.showPopup({
  492. score,
  493. reply,
  494. result,
  495. answer
  496. })
  497. }
  498. if (qa.stTypeId == 4) {
  499. let reply = qa.reply || [];
  500. let result = qa.result || [];
  501. // 填空题
  502. scoreAnswerTkRef.value.showPopup({
  503. score,
  504. reply,
  505. result,
  506. answer
  507. })
  508. }
  509. if (qa.stTypeId == 5) {
  510. // 简单题
  511. let reply = qa.reply ? '未答' : qa.reply;
  512. let result = qa.result;
  513. scoreAnswerJdRef.value.showPopup({
  514. score,
  515. reply,
  516. result,
  517. answer
  518. })
  519. }
  520. }
  521. // 获取解析
  522. function handleCheckJiexi() {
  523. const qa = activeSt.value;
  524. let score = qa.userScore;
  525. let reply = '';
  526. let result = '';
  527. let answer = qa.answer;
  528. if (qa.stTypeId == 1) {
  529. // 单选题
  530. if (qa.reply && qa.reply.trim() !== '') {
  531. reply = getLetterByIndex(qa.reply)
  532. } else {
  533. reply = '未答'
  534. }
  535. if (qa.result) {
  536. result = getLetterByIndex(qa.result)
  537. } else {
  538. result = '无答案'
  539. }
  540. scoreAnswerRef.value.showPopup({
  541. score,
  542. reply,
  543. result,
  544. answer
  545. })
  546. }
  547. if (qa.stTypeId == 2) {
  548. // 多选题
  549. if (qa.reply && qa.reply.length) {
  550. reply = qa.reply.map(item => {
  551. if (item.trim()) {
  552. return getLetterByIndex(item.trim())
  553. }
  554. }).join(',')
  555. } else {
  556. reply = '未答'
  557. }
  558. if (qa.result) {
  559. result = qa.result.map(item => {
  560. if (item.trim()) {
  561. return getLetterByIndex(item.trim())
  562. }
  563. }).join(',')
  564. } else {
  565. result = '无答案'
  566. }
  567. scoreAnswerRef.value.showPopup({
  568. score,
  569. reply,
  570. result,
  571. answer
  572. })
  573. }
  574. if (qa.stTypeId == 3) {
  575. // 判断题
  576. if (qa.reply === '') {
  577. reply = '未答'
  578. } else if (qa.reply == 0) {
  579. reply = '错误'
  580. } else if (qa.reply == 1) {
  581. reply = '正确'
  582. }
  583. if (qa.result == 0) {
  584. result = '错误'
  585. } else if (qa.result == 1) {
  586. result = '正确'
  587. }
  588. scoreAnswerRef.value.showPopup({
  589. score,
  590. reply,
  591. result,
  592. answer
  593. })
  594. }
  595. if (qa.stTypeId == 4) {
  596. let reply = qa.reply || [];
  597. let result = qa.result || [];
  598. // 填空题
  599. scoreAnswerTkRef.value.showPopup({
  600. score,
  601. reply,
  602. result,
  603. answer
  604. })
  605. }
  606. if (qa.stTypeId == 5) {
  607. // 简单题
  608. let reply = qa.reply;
  609. let result = qa.result;
  610. scoreAnswerJdRef.value.showPopup({
  611. score,
  612. reply,
  613. result,
  614. answer
  615. })
  616. }
  617. if (qa.stTypeId == 6) {
  618. // 简单题
  619. checkYueduJiexi()
  620. }
  621. }
  622. function handleBack() {
  623. // uni.redirectTo({
  624. // url: "/pages/score/index"
  625. // })
  626. uni.navigateBack()
  627. }
  628. function initKaoshi() {
  629. cjApi.lookChengjiView({
  630. hisId: data.hisId
  631. }).then(res => {
  632. const {
  633. hisId,
  634. duanluoList
  635. } = res.data;
  636. data.hisId = hisId;
  637. data.duanluo = duanluoList;
  638. formatDuanluoList(data.duanluo);
  639. uni.setNavigationBarTitle({
  640. title: data.name
  641. });
  642. })
  643. }
  644. </script>