test.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. <template>
  2. <view>
  3. <Headers></Headers>
  4. <view class="project">
  5. <view style="width: 1200px;margin: auto;">二手车评估师考试</view>
  6. </view>
  7. <view class="project-content ddflex">
  8. <!-- 考试区域 -->
  9. <view class="test-box">
  10. <view class="test-box-title">
  11. <text style="font-weight: bold;margin-right: 10px;">考试题目</text>
  12. <text>{{ cIndex + 1 }}</text><text style="color: #999999;">/{{questTotal}}</text>
  13. </view>
  14. <view class="test-question-box">
  15. <view class="test-question ddflex">
  16. <view>{{ cIndex + 1 }}</view>
  17. <view>【{{getQuestType()}}】</view>
  18. <view>
  19. <rich-text class="hh" :nodes="addTitleType(quest.title,quest.qtype)"></rich-text>
  20. </view>
  21. </view>
  22. <!-- 简答题 -->
  23. <view class="short" v-if="quest.qtype == 4 || quest.qtype == 5">
  24. <textarea
  25. v-model="quest.answerTxt"
  26. maxlength="-1"
  27. ref="inputText"
  28. placeholder="在此输入答案"
  29. placeholder-class="placeholder"
  30. class="text-ans"
  31. @click="intAnswer(qitem, idx)"
  32. ></textarea>
  33. </view>
  34. <view class="test-question-answer" v-else-if="quest.qtype == 1 || quest.qtype == 2 || quest.qtype == 3">
  35. <view class="answer-item ddflex" v-for="(qitem, idx) in quest.questJson" :key="idx" @click="setAnswer(qitem, idx)">
  36. <!-- answer-checked -->
  37. <view :class="qitem.cssStr ? 'answer-checked' : 'answer-unchecked'"></view>
  38. <view class="answer-text ddflex">
  39. <view style="margin-right: 10px;">{{ qitem.num }} </view>
  40. <rich-text class="hh" :nodes="qitem.title"></rich-text>
  41. </view>
  42. </view>
  43. </view>
  44. </view>
  45. <view style="height: 82px;width: 100%;"> </view>
  46. <view class="test-btn-group ddflex">
  47. <view v-if="cIndex != 0" class="test-btn" @click="prev()">上一题</view>
  48. <view v-if="cIndex + 1 != questTotal" class="test-btn" @click="next()">下一题</view>
  49. </view>
  50. </view>
  51. <!-- 答题卡区域 -->
  52. <view class="test-info ddflex">
  53. <view class="test-people ddflex">
  54. <image></image>
  55. <view class="test-people-info ddflex">
  56. <view class="ddflex">
  57. <view class="test-people-label">考生姓名</view>
  58. <view class="fflex">李田</view>
  59. </view>
  60. <view class="ddflex">
  61. <view class="test-people-label">准考证号</view>
  62. <view class="fflex" style="word-break: break-all;">4512541244</view>
  63. </view>
  64. <view class="ddflex">
  65. <view class="test-people-label">考试科目</view>
  66. <view class="fflex">二手车评估师</view>
  67. </view>
  68. </view>
  69. </view>
  70. <view class="test-date">
  71. <view class="test-date-title">距考试结束还有</view>
  72. <view class="test-date-group ddflex">
  73. <view class="test-date-item">{{times.hour}}</view>
  74. <text class="test-date-symbol">:</text>
  75. <view class="test-date-item">{{times.minutes}}</view>
  76. <text class="test-date-symbol">:</text>
  77. <view class="test-date-item">{{times.seconds}}</view>
  78. </view>
  79. </view>
  80. <view class="test-answer fflex">
  81. <view class="test-answer-title">答题卡</view>
  82. <view class="test-answer-info ddflex">
  83. <view class="">共 {{quests.length}} 题</view>
  84. <view class="test-answer-info-symbol"></view>
  85. <view class="">总计 100 分</view>
  86. </view>
  87. <view class="test-answer-box ddflex">
  88. <view :class="'test-answer-item '+(cIndex == index?'test-answer-item-curActive':item.isSubmit?'test-answer-item-active':'')" v-for="item,index in quests"
  89. @click="toQuestTip(index)">
  90. {{index+1}}
  91. </view>
  92. </view>
  93. <view class="test-answer-number ddflex">
  94. <view class="ddflex">
  95. <view class="test-isanswer"></view>
  96. <view>已做 {{quests.filter(item=>{return item.isSubmit}).length}}</view>
  97. </view>
  98. <view class="ddflex">
  99. <view class="test-unanswer"></view>
  100. <view>未做 {{quests.filter(item=>{return !item.isSubmit}).length}}</view>
  101. </view>
  102. </view>
  103. <view style="height: 82px;"></view>
  104. <view class="submit-btn" @click="open">交 卷</view>
  105. </view>
  106. </view>
  107. </view>
  108. <uni-popup ref="popup" type="bottom" :is-mask-click='false'>
  109. <view class="popup-box" v-if="state==1">
  110. <view class="popup-top ddflex">
  111. <view>您正在结束作答</view>
  112. <image src="/static/images/close.png" @click="close()"></image>
  113. </view>
  114. <view class="popup-content">您已完成全部考题,是否确定交卷?</view>
  115. <view class="popup-bottom ddflex">
  116. <view class="popup-btn1" @click="close()">继续考试</view>
  117. <view class="popup-btn2" @click="submit">确定交卷</view>
  118. </view>
  119. </view>
  120. <view class="popup-box" v-if="state==2">
  121. <view class="popup-top ddflex">
  122. <view>考试结果</view>
  123. <image src="/static/images/close.png" @click="close()"></image>
  124. </view>
  125. <view class="popup-content" style="margin-top: 23px;">
  126. <view class="chufen-title">二手车评估师考试</view>
  127. <view class="chufen-number">
  128. 84<text style="font-size: 18px;margin-left: 10px;">分</text>
  129. <view style="font-size: 16px;">考试不合格</view>
  130. </view>
  131. </view>
  132. <view class="popup-bottom ddflex" style="margin-top: 30px;margin-bottom: 60px;padding-left: 30px">
  133. <view>
  134. <view class="popup-bottom-label">总题数</view>
  135. <view class="popup-bottom-value">23</view>
  136. </view>
  137. <view class="line"></view>
  138. <view>
  139. <view class="popup-bottom-label">考试用时</view>
  140. <view class="popup-bottom-value">20:42:14</view>
  141. </view>
  142. </view>
  143. </view>
  144. </uni-popup>
  145. <Foot></Foot>
  146. </view>
  147. </template>
  148. <script>
  149. const app = getApp();
  150. const req = require('../../utils/request.js');
  151. const utils = require('../../utils/util.js');
  152. export default {
  153. data() {
  154. return {
  155. state:1,
  156. paperId: '', //考试题目
  157. paperTitle: '', //考试标题
  158. paperType: '', //1每日一练 2模拟试题 3大厂真题 5企业真题
  159. type: '', //标识类型 1试卷 2章节 3热门考点 4错题集 5高频错题
  160. systems: {},
  161. isMockExam: true, //是否是模拟考试
  162. isShowTip: false, //是否展示温馨提示
  163. isShowSheet: false, //
  164. paper: '', //试卷详情
  165. time: 0, //允许做题的时间
  166. times: 0, //做题时分秒倒计时
  167. quest: '', //当前选中的题目
  168. quests: [], //题目数据
  169. questTotal: 0, //题目条数
  170. cIndex: 0, //当前做题下标
  171. answerTxt: '', //填空题、简答题答案
  172. isGoBack: false,
  173. isShowView: false
  174. }
  175. },
  176. onReady() {},
  177. onLoad() {
  178. this.getQuests()
  179. },
  180. methods: {
  181. getQuestType() {
  182. // <!-- 1单选 2多选 3 判断 4 填空 5 简答', -->
  183. var text = '';
  184. switch (this.quest.qtype) {
  185. case 1:
  186. text = '单选题';
  187. break;
  188. case 2:
  189. text = '多选题';
  190. break;
  191. case 3:
  192. text = '判断题';
  193. break;
  194. case 4:
  195. text = '填空题';
  196. break;
  197. case 5:
  198. text = '简答题';
  199. break;
  200. default:
  201. break;
  202. }
  203. return text;
  204. },
  205. stylesText(text){
  206. return utils.preText(text);
  207. },
  208. addTitleType(title, qtype) {
  209. var stitle=this.stylesText(title);
  210. return stitle;
  211. },
  212. //获取考试对象
  213. getPaper() {
  214. var _ts = this;
  215. req.getRequest(api.paper_detail + _ts.paperId, {}, res => {
  216. if (res) {
  217. if (res.time > 0 && _ts.paperType != 3 && _ts.paperType != 5) {
  218. _ts.time = res.time * 60;
  219. _ts.setTime();
  220. }
  221. _ts.paperType = res.paperType * 1;
  222. _ts.paper = res;
  223. }
  224. });
  225. },
  226. getQuests(){
  227. let _ts = this
  228. req.getRequest('https://mock.apifox.cn/m1/2171629-0-default/api/paper/quest/init/2834',{},quests=>{
  229. console.log(quests)
  230. if (quests && quests.length > 0) {
  231. _ts.questTotal = quests.length;
  232. for (var k = 0; k < quests.length; k++) {
  233. var quest = quests[k];
  234. quest.eitype = _ts.etype;
  235. quest.title = quest.title.replace(/<code class="(.*?)"/gi, '<code class="Java" ');
  236. }
  237. if (_ts.questTotal > 0) {
  238. _ts.quest = _ts.setQuest(quests[0]);
  239. }
  240. _ts.quests = quests;
  241. }
  242. })
  243. },
  244. //考试时间倒计时
  245. setTime() {
  246. var _ts = this;
  247. var time = _ts.time;
  248. if (time <= 0) {
  249. //考试时间到,交卷
  250. if (_ts.ptime) {
  251. clearTimeout(_ts.ptime);
  252. }
  253. _ts.submitTest();
  254. return;
  255. }
  256. var times = {};
  257. times.hour = _ts.cut22(Math.floor(time / 3600));
  258. var leave2 = time % 3600;
  259. times.minutes = _ts.cut22(Math.floor(leave2 / 60));
  260. var leave3 = leave2 % 60;
  261. times.seconds = _ts.cut22(Math.round(leave3));
  262. _ts.times = times;
  263. _ts.ptime = setTimeout(function() {
  264. _ts.time = time - 1;
  265. _ts.setTime();
  266. }, 1000);
  267. }, //下次继续
  268. cut22(n) {
  269. n = n.toString();
  270. return n[1] ? n : '0' + n;
  271. },
  272. //将答案和问题转成数组或对象
  273. setQuest(quest) {
  274. console.log('quest.iscv==', quest.iscv);
  275. if (quest.iscv) {
  276. return quest;
  277. }
  278. quest.iscv = true;
  279. var answers = [];
  280. var qjs = [];
  281. try {
  282. var qJsons = JSON.parse(quest.questJson);
  283. if (quest.qtype == 1 || quest.qtype == 3) {
  284. //'单选题'
  285. answers = quest.answerJson ? [quest.answerJson] : [];
  286. } else if (quest.qtype == 2) {
  287. if (quest.answerJson) {
  288. answers = JSON.parse(quest.answerJson);
  289. }
  290. }
  291. for (var m = 0; m < qJsons.length; m++) {
  292. var num = this.getNum(m);
  293. qjs.push({
  294. num: num,
  295. title: qJsons[m],
  296. cssStr: ''
  297. });
  298. }
  299. } catch (e) {}
  300. quest.answerJson = answers;
  301. quest.questJson = qjs;
  302. console.log('下一题中');
  303. quest.answerTxt = '';
  304. this.answerTxt = '';
  305. return quest;
  306. },
  307. getNum: function(ix) {
  308. var keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N'];
  309. return keys[ix];
  310. },
  311. intAnswer(item, idx) {
  312. var _ts = this;
  313. var qes = this.quest;
  314. qes.isSubmit = true;
  315. _ts.quest = qes;
  316. },
  317. setAnswer(item, idx) {
  318. // <!-- 1单选 2多选 3 判断 4 填空 5 简答', -->
  319. var _ts = this;
  320. idx = idx + 1;
  321. var qes = this.quest;
  322. /*修改答案选中项*/
  323. var sItems = qes.sItems;
  324. if (qes.qtype == 2) {
  325. var isflg = false;
  326. if (sItems && sItems.length > 0) {
  327. var cidx = sItems.indexOf(idx);
  328. if (cidx > -1) {
  329. sItems.splice(cidx, 1);
  330. isflg = true;
  331. }
  332. } else {
  333. sItems = [];
  334. }
  335. if (!isflg) {
  336. sItems.push(idx);
  337. }
  338. } else if (qes.qtype == 1 || qes.qtype == 3) {
  339. sItems = [idx];
  340. }
  341. qes.sItems = sItems.sort();
  342. qes.isSubmit = true;
  343. //修改Css
  344. qes = _ts.setCss(qes);
  345. _ts.quest = qes;
  346. _ts.quests[_ts.cIndex] = qes;
  347. },
  348. //设置页面选中样式
  349. setCss(qes) {
  350. var qjson = qes.questJson;
  351. var answers = qes.answerJson; //答案
  352. var sItems = qes.sItems;
  353. if (!sItems) {
  354. sItems = [];
  355. }
  356. for (var m = 0; m < qjson.length; m++) {
  357. var qitem = qjson[m];
  358. var cidx = sItems.indexOf(m + 1);
  359. if (cidx > -1) {
  360. qitem.cssStr = ' active';
  361. } else {
  362. qitem.cssStr = '';
  363. }
  364. }
  365. qes.questJson = qjson;
  366. qes.cssStr = ' active';
  367. return qes;
  368. },
  369. //上一题
  370. prev() {
  371. var _ts = this;
  372. var cIndex = _ts.cIndex;
  373. if (cIndex <= 0) {
  374. return;
  375. }
  376. _ts.cIndex = cIndex - 1;
  377. _ts.quest = _ts.setQuest(_ts.quests[_ts.cIndex]);
  378. }, //下一题
  379. next() {
  380. var _ts = this;
  381. var cIndex = _ts.cIndex;
  382. if (cIndex >= _ts.questTotal - 1) {
  383. return;
  384. }
  385. _ts.cIndex = cIndex + 1;
  386. console.log('下一题');
  387. _ts.quest = _ts.setQuest(_ts.quests[_ts.cIndex]);
  388. console.log('下一题后');
  389. console.log('_ts.quest==', _ts.quest);
  390. console.log('_ts.quest.answerTxt==', _ts.quest.answerTxt);
  391. _ts.$forceUpdate();
  392. console.log('quests==', _ts.quests);
  393. },
  394. toQuestTip(index) {
  395. var _ts = this;
  396. var _ts = this;
  397. _ts.cIndex = index;
  398. _ts.quest = _ts.setQuest(_ts.quests[_ts.cIndex]);
  399. _ts.closeCeng();
  400. // });
  401. },
  402. //提交
  403. submitQuest() {
  404. var msg = '';
  405. if (this.paperType == 2) {
  406. if (this.times.hour > 0) {
  407. msg = '距离考试结束还剩' + this.times.hour + '小时' + this.times.minutes + '分钟,确定要结束考试吗?';
  408. } else {
  409. if (this.times.minutes > 0) {
  410. msg = '距离考试结束还剩' + this.times.minutes + '分钟,确定要结束考试吗?';
  411. } else {
  412. msg = '确定要交卷结束考试吗?';
  413. }
  414. }
  415. } else {
  416. msg = '确定要交卷结束做题吗?';
  417. }
  418. this.$showModal({ title: '温馨提示', content: msg, cancelText: '继续作答', confirmText: '交卷' })
  419. .then(res => {
  420. this.submitTest();
  421. })
  422. .catch(err => {
  423. // 点击取消按钮的操作
  424. });
  425. },
  426. async submitTest(){
  427. if (!this.paper.isScore) {//手动阅卷
  428. //订阅成绩通知
  429. await requsetmessage.resultsTest().then(res => {});
  430. }
  431. this.submit();
  432. },
  433. //提交考试+答案
  434. submit() {
  435. uni.redirectTo({
  436. url:'/pages/scoreQuery/scoreQuery'
  437. })
  438. return
  439. var _ts = this;
  440. if (_ts.ptime) {
  441. clearTimeout(_ts.ptime);
  442. }
  443. var dataP = {
  444. uniqueId: _ts.paperId,
  445. uniqueType: _ts.type
  446. };
  447. //组装考试题目
  448. dataP.questionList = this.quests.map(it => {
  449. // <!-- 1单选 2多选 3 判断 4 填空 5 简答', -->
  450. var data = {
  451. id: it.id, //记录ID
  452. paperQuestionId: it.pqId, //试卷题目ID
  453. questionId: it.questId //题目ID
  454. };
  455. var answerJson = '';
  456. if (it.qtype == 1 || it.qtype == 3) {
  457. answerJson = it.sItems ? it.sItems.join('') : '';
  458. } else if (it.qtype == 2) {
  459. answerJson = it.sItems ? JSON.stringify(it.sItems) : '';
  460. } else if (it.qtype == 4) {
  461. var list = [];
  462. list.push(it.answerTxt ? it.answerTxt : '');
  463. answerJson = JSON.stringify(list);
  464. } else if (it.qtype == 5) {
  465. answerJson = it.answerTxt ? it.answerTxt : '';
  466. }
  467. data.answerJson = answerJson;
  468. return data;
  469. });
  470. console.log(dataP);
  471. req.postRequest(
  472. api.complete_exam,
  473. dataP,
  474. res => {
  475. if (!_ts.paper.isScore) {//手动阅卷
  476. uni.redirectTo({
  477. url: '/learn/marking/index?id=' + res.id
  478. });
  479. } else {//自动阅卷
  480. uni.redirectTo({
  481. url: '/learn/result/index?id=' + res.id
  482. });
  483. }
  484. },
  485. true
  486. );
  487. },
  488. open() {
  489. this.$refs.popup.open('center')
  490. },
  491. close() {
  492. this.$refs.popup.close()
  493. },
  494. }
  495. }
  496. </script>
  497. <style>
  498. @import url('./test.css');
  499. </style>