kaoshiChengjiInfo.vue 16 KB

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