detail.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. <template>
  2. <view :class="{ yejian: if_theme_dark }">
  3. <!--#ifdef APP-PLUS-->
  4. <view class="lz-status_bar">
  5. <view class="lz-top_view"></view>
  6. </view>
  7. <!--#endif-->
  8. <view class="kaoshi-head">
  9. <view class="kaoshi-head-top">
  10. <view class="kaoshi-head-left" @tap="$navigateBack">
  11. <view class="iconfont icon-zuojiantou"></view>
  12. </view>
  13. <view class="kaoshi-head-m">
  14. {{ pages_params.title }}
  15. </view>
  16. <view class="kaoshi-head-right"></view>
  17. </view>
  18. </view>
  19. <view scroll-y style="height: 100%;">
  20. <view style="height: 10px;"></view>
  21. <view class="questionBankAnswer" v-if="current_timu && current_timu.id">
  22. <question-type :current_timu="current_timu" :timu_order="timu_order" :total_num="total_num"
  23. :over_time="over_time" @timeup="timeup"></question-type>
  24. </view>
  25. <view class="questionBankAnswer-content" v-if="current_timu && current_timu.answers">
  26. <question-title :node="current_timu.question_name"></question-title>
  27. <block v-for="(item, index) in current_timu.answers" :key="index">
  28. <question-option :show_beiti="false" :ref="'questionOption_' + index" :item="item" :index="index"
  29. :current_timu="current_timu" :copy_user_answer="copy_user_answer" :timu_index="timu_order - 1"
  30. :copy_post_status="copy_post_status" @post_answer_req="post_answer_req"
  31. @set_copy_user_answer="set_copy_user_answer" @set_sub_button_style="set_sub_button_style"
  32. question_type="exam"></question-option>
  33. </block>
  34. <template v-if="current_timu.type == 4">
  35. <question-tiankong :show_beiti="false" :current_timu="current_timu"
  36. :is_tiankong_sub="is_tiankong_sub" @set_current_timu="set_current_timu"
  37. @post_answer_req="post_answer_req" @set_sub_button_style="set_sub_button_style">
  38. </question-tiankong>
  39. </template>
  40. <template v-else-if="current_timu.type == 5">
  41. <question-jianda :show_beiti="false" :current_timu="current_timu" :is_jianda_sub="is_jianda_sub"
  42. @set_current_timu="set_current_timu" @post_answer_req="post_answer_req"
  43. @set_sub_button_style="set_sub_button_style"></question-jianda>
  44. </template>
  45. <view v-if="current_timu.answers && current_timu.type == 2">
  46. <button :class="is_duoxuan_sub ? 'duoxuan_checked' : 'duoxuan'" type="" @tap="post_answer_req">
  47. {{ is_duoxuan_sub ? "提交成功" : "确认答案" }}
  48. </button>
  49. </view>
  50. <question-pre-next v-if="timu_list.length > 0" :total_num="total_num" :timu_order="timu_order"
  51. :timu_list="timu_list" @choice_timu_by_id="choice_timu_by_id" @tap_handler="jiaojuan"
  52. confirmText="交卷" class="questionBankAnswer-contentbtnbox"></question-pre-next>
  53. </view>
  54. <view v-if="current_timu.type == 5" class="jdttishi">温馨提示:简答题不记入错题,默认为正确</view>
  55. <view style="height: 50px;"></view>
  56. </view>
  57. <view class="order-pay">
  58. <view class="questionBankAnswer-bottom-flex" @tap="jiaojuan1">
  59. <view class="iconfont icon-bianjisekuai"></view>
  60. <view>交卷</view>
  61. </view>
  62. <question-answer-sheet class="questionBankAnswer-bottom-flex"
  63. @show_choice_timu_list="show_choice_timu_list = true"></question-answer-sheet>
  64. <view class="questionBankAnswer-bottom-flex" @tap="show_change_moshi = true">
  65. <view class="iconfont icon-shezhi"></view>
  66. <view>设置</view>
  67. </view>
  68. </view>
  69. <question-answer-sheet-1 v-if="show_choice_timu_list" question_type="exam"
  70. @show_choice_timu_list="show_choice_timu_list = false" :timu_order="timu_order" :timu_list="timu_list"
  71. :total_num="total_num" @choice_timu_by_id="choice_timu_by_id" @jiaojuan1="jiaojuan1">
  72. </question-answer-sheet-1>
  73. <question-set :show_change_moshi="show_change_moshi" :if_theme_dark="if_theme_dark"
  74. @set_if_theme_dark="set_if_theme_dark" @hide_change_moshi="show_change_moshi = false"></question-set>
  75. <overtimu v-if="show_over_dati" :timuinfo="over_dati_info" @tap_handler="jiaojuan"></overtimu>
  76. </view>
  77. </template>
  78. <script>
  79. import overtimu from "@/components/overtimu/index";
  80. import {
  81. mapState
  82. } from "vuex";
  83. export default {
  84. data() {
  85. return {
  86. exam_id: 0, //考试id
  87. total_num: 0, //试题总数
  88. // 上次答到第几题
  89. timu_order: -1,
  90. //区分多选题是否点击提交按钮
  91. is_duoxuan_sub: false,
  92. is_tiankong_sub: false,
  93. is_jianda_sub: false,
  94. // 当前题目
  95. current_timu: {},
  96. // 用户输入的答案
  97. copy_user_answer: {},
  98. copy_right_answer_code: {},
  99. copy_post_status: {},
  100. // 是否显示退出答题弹框
  101. show_over_dati: false,
  102. over_dati_info: {},
  103. // 答题开始时间
  104. start_time: 0,
  105. end_time: 0,
  106. // 页面参数
  107. pages_params: {},
  108. // 显示答题卡
  109. show_choice_timu_list: false,
  110. // 答题卡
  111. timu_list: [],
  112. // 字号大小
  113. show_change_moshi: false,
  114. if_theme_dark: false // 黑夜模式
  115. };
  116. },
  117. onShow() {},
  118. onLoad(opts) {
  119. this.pages_params = opts;
  120. this.exam_id = this.pages_params.id
  121. this.end_time = this.pages_params.end_time
  122. if (this.userinfo.token) {
  123. this.init()
  124. }
  125. },
  126. onReady() {},
  127. computed: {
  128. ...mapState(["subject", "userinfo"]),
  129. over_time() {
  130. if (this.end_time > 0) {
  131. let end = parseInt(new Date().getTime() / 1000);
  132. let sec = parseInt(this.end_time - end);
  133. let hour = parseInt(sec / 3600);
  134. let miu = parseInt((sec - hour * 3600) / 60);
  135. let s = sec - hour * 3600 - miu * 60;
  136. return {
  137. hour: parseInt(hour),
  138. minute: parseInt(miu),
  139. second: parseInt(s)
  140. };
  141. }
  142. return {};
  143. }
  144. },
  145. onBackPress() {
  146. this.over_dati();
  147. return true;
  148. },
  149. components: {
  150. overtimu,
  151. },
  152. methods: {
  153. async init() {
  154. const info = await this.$myUserLogin.getExamVipInfo(this.exam_id);
  155. if(info.is_vip == 0 || info.owned_vip == 1){
  156. this.get_timu_list();
  157. }else{
  158. //需要vip但还不是vip
  159. uni.showToast({
  160. title: '暂无权限',
  161. icon: 'none'
  162. })
  163. setTimeout(() => {
  164. uni.reLaunch({
  165. url: '/pages/index/index'
  166. })
  167. }, 1500)
  168. }
  169. },
  170. set_sub_button_style(type, value) {
  171. console.log(type, value)
  172. this[type] = value
  173. },
  174. set_current_timu(data) {
  175. this.current_timu = JSON.parse(JSON.stringify(data))
  176. let copy_user_answer_this = this.copy_user_answer;
  177. if (copy_user_answer_this[this.current_timu.id]) {
  178. copy_user_answer_this[this.current_timu.id] = this.current_timu.my_answer_arr
  179. }
  180. },
  181. set_copy_user_answer(data) {
  182. this.copy_user_answer = JSON.parse(JSON.stringify(data))
  183. this.setAnswerStyle(this.current_timu);
  184. // this.setMyAnswer();
  185. },
  186. //单选多选判断,选项正确错误
  187. setAnswerStyle(timu) {
  188. this.$nextTick(() => {
  189. timu.answers.forEach((item, index) => {
  190. this.$refs['questionOption_' + index][0].setAnswerStyle(this.copy_user_answer);
  191. })
  192. })
  193. },
  194. timeup() {
  195. this.jiaojuan();
  196. },
  197. // 获取答题卡
  198. //2020年2月1日——创建一个答题卡数组 is_dati 1已答 0未答
  199. async get_timu_list() {
  200. let res = await this.$myHttp.post({
  201. url: this.$myHttp.urlMap.examCard,
  202. data: {
  203. exam_id: this.exam_id // 考试id
  204. },
  205. needLogin: true
  206. });
  207. if (res.code == 1) {
  208. this.timu_order = res.data.position
  209. this.timu_list = res.data.card;
  210. this.total_num = this.timu_list.length;
  211. this.isChangeTimu = false
  212. if (res.data.curr_question != []) {
  213. this.current_timu = res.data.curr_question;
  214. this.save_user_answer(this.current_timu);
  215. }else{
  216. this.current_timu = null
  217. }
  218. this.is_duoxuan_sub = false
  219. this.is_tiankong_sub = false
  220. this.is_jianda_sub = false
  221. // this.get_timu_order();
  222. }
  223. },
  224. // 获取用户答到第几题
  225. // async get_timu_order() {
  226. // let res = await this.$myHttp.post({
  227. // url: this.$myHttp.urlMap.examPosition,
  228. // data: {
  229. // exam_id: this.exam_id
  230. // },
  231. // needLogin: true
  232. // });
  233. // if (res.code == 1) {
  234. // this.timu_order = res.data
  235. // this.get_timu_info();
  236. // }
  237. // },
  238. async get_timu_info() {
  239. let res = await this.$myHttp.post({
  240. url: this.$myHttp.urlMap.exam_timu_details,
  241. data: {
  242. exam_id: this.exam_id,
  243. question_id: this.timu_list[this.timu_order - 1].id
  244. },
  245. needLogin: true
  246. });
  247. if (res.code == 1) {
  248. if (res.data != []) {
  249. this.isChangeTimu = false
  250. this.current_timu = res.data;
  251. this.save_user_answer(this.current_timu);
  252. this.is_duoxuan_sub = false
  253. this.is_tiankong_sub = false
  254. this.is_jianda_sub = false
  255. } else {
  256. this.current_timu = null;
  257. }
  258. } else {
  259. uni.navigateBack({});
  260. }
  261. },
  262. // 根据答题卡获取题目
  263. choice_timu_by_id(index) {
  264. this.timu_order = index + 1
  265. this.isChangeTimu = true
  266. // this.current_timu = {}
  267. uni.pageScrollTo({
  268. scrollTop: 0,
  269. duration: 200
  270. });
  271. this.get_timu_info()
  272. },
  273. // 本地存储用户答案 考试页面
  274. save_user_answer(timu) {
  275. if (timu.type <= 3) {
  276. if (timu && timu.answers) {
  277. if (!(this.copy_user_answer[timu.id])) {
  278. this.copy_user_answer = Object.assign({}, this.copy_user_answer, {
  279. [timu.id]: []
  280. });
  281. this.copy_post_status = Object.assign({}, this.copy_post_status, {
  282. [timu.id]: false
  283. });
  284. for (let i = 0, leng = timu.answers.length; i < leng; i++) {
  285. this.copy_user_answer[timu.id].push({
  286. answer_code: timu.answers[i].answer_code,
  287. active: false
  288. })
  289. }
  290. if (timu.my_answer !== '' && timu.my_answer !== null) {
  291. this.setUserAnswer(timu)
  292. } else {
  293. this.setAnswerStyle(timu);
  294. }
  295. } else {
  296. this.setAnswerStyle(timu);
  297. }
  298. }
  299. } else {
  300. let right_answer_arr = timu.right_answer.split('|');
  301. this.$set(timu, 'right_answer_arr', right_answer_arr)
  302. this.$set(timu, 'show_right_answer', false)
  303. if (!(this.copy_user_answer[timu.id])) {
  304. //本地没有记录呢,如果my_answer有值,写进去
  305. this.copy_user_answer = Object.assign({}, this.copy_user_answer, {
  306. [timu.id]: []
  307. });
  308. this.copy_post_status = Object.assign({}, this.copy_post_status, {
  309. [timu.id]: false
  310. });
  311. if (timu.my_answer == '' || timu.my_answer == null) {
  312. //之前没有答过题
  313. let arr = [];
  314. arr.length = right_answer_arr.length;
  315. this.$set(timu, 'my_answer_arr', arr)
  316. this.$set(timu, 'my_answer', '')
  317. this.setAnswerStyle(timu);
  318. } else {
  319. //之前答过题了
  320. this.setUserAnswer(timu)
  321. }
  322. } else {
  323. //本地有答题记录 答过题了
  324. this.setUserAnswer(timu)
  325. }
  326. }
  327. },
  328. //获取题目信息后,如果答过题了,设置到本地
  329. setUserAnswer(timu) {
  330. this.copy_post_status = Object.assign({}, this.copy_post_status, {
  331. [timu.id]: true
  332. });
  333. let id = this.current_timu.id,
  334. answer = this.current_timu.my_answer;
  335. // 如果是判断和单选。执行以下处理
  336. if (timu.type == 1 || timu.type == 3) {
  337. for (let i = 0, leng = this.copy_user_answer[id].length; i < leng; i++) {
  338. if (this.copy_user_answer[id][i].answer_code.toString().toLowerCase().replace(/\s/g, "") ==
  339. answer.toString().toLowerCase().replace(/\s/g, "")) {
  340. this.copy_user_answer[id][i].active = true;
  341. } else {
  342. this.copy_user_answer[id][i].active = false;
  343. }
  344. }
  345. } else if (timu.type == 2) {
  346. // 如果是多选。执行以下处理
  347. for (let i = 0, leng = answer.length; i < leng; i++) {
  348. for (let j = 0, len = this.copy_user_answer[id].length; j < len; j++) {
  349. if (this.copy_user_answer[id][j].answer_code.toString().toLowerCase().replace(/\s/g, "") ==
  350. answer[i].toString().toLowerCase().replace(/\s/g, "")) {
  351. this.copy_user_answer[id][j].active = true;
  352. }
  353. }
  354. }
  355. } else {
  356. // 如果是填空,简答
  357. this.$set(timu, 'my_answer_arr', timu.my_answer.split('|'))
  358. this.$set(timu, 'my_answer', timu.my_answer)
  359. this.$set(timu, 'show_right_answer', true)
  360. this.copy_user_answer = Object.assign({}, this.copy_user_answer, {
  361. [timu.id]: []
  362. });
  363. this.copy_user_answer[timu.id].push(...timu.my_answer_arr)
  364. }
  365. this.setAnswerStyle(timu);
  366. },
  367. // 提交答案
  368. async post_answer_req() {
  369. this.is_duoxuan_sub = true;
  370. this.is_tiankong_sub = true
  371. this.is_jianda_sub = true
  372. let timu_index = this.timu_order - 1;
  373. let answer = "";
  374. if (this.current_timu.type <= 3) {
  375. let answers = this.copy_user_answer[this.current_timu.id];
  376. for (let i = 0, leng = answers.length; i < leng; i++) {
  377. if (answers[i].active) {
  378. answer += answers[i].answer_code;
  379. }
  380. }
  381. this.copy_post_status = Object.assign({}, this.copy_post_status, {
  382. [this.current_timu.id]: true
  383. });
  384. }
  385. let res = await this.$myHttp.post({
  386. url: this.$myHttp.urlMap.exam_answer,
  387. data: {
  388. question_id: this.current_timu.id,
  389. exam_id: this.exam_id,
  390. answer: this.current_timu.type <= 3 ? answer : this.current_timu.my_answer
  391. },
  392. needLogin: true
  393. });
  394. if (res.code == 1 && res.msg) {
  395. this.timu_list[timu_index].state = 1;
  396. }
  397. },
  398. jiaojuan1() {
  399. uni.showModal({
  400. title: '提示',
  401. content: '是否立即交卷',
  402. showCancel: true,
  403. cancelText: '继续答题',
  404. confirmText: '立即交卷',
  405. success: res => {
  406. if (res.confirm) {
  407. this.jiaojuan();
  408. }
  409. },
  410. fail: () => {},
  411. complete: () => {}
  412. });
  413. },
  414. async jiaojuan() {
  415. if (this.exam_id) {
  416. let res = await this.$myHttp.post({
  417. url: this.$myHttp.urlMap.exam_end,
  418. data: {
  419. exam_id: this.exam_id
  420. },
  421. needLogin: true
  422. });
  423. if (res.code == 1) {
  424. this.$myCatch.setItem("jiaojuan_info", res.msg);
  425. this.tap_handler();
  426. } else {
  427. uni.navigateBack({
  428. delta: 1
  429. });
  430. }
  431. } else {
  432. uni.navigateBack({
  433. delta: 1
  434. });
  435. }
  436. },
  437. // 中途退出
  438. over_dati() {
  439. let that = this;
  440. that.$myUtils.$prompt.showModal({
  441. title: "提示",
  442. content: "是否交卷",
  443. confirmText: "交卷",
  444. success: function(res) {
  445. if (res.confirm) {
  446. that.jiaojuan();
  447. } else if (res.cancel) {
  448. console.log("用户点击取消");
  449. }
  450. }
  451. });
  452. },
  453. // 设置是否黑夜模式
  454. set_if_theme_dark(data) {
  455. this.if_theme_dark = data
  456. },
  457. tap_handler(type) {
  458. if (type == 0) {
  459. this.show_over_dati = false;
  460. } else {
  461. this.$redirectTo("/pages/examination/examOver/index");
  462. }
  463. },
  464. }
  465. };
  466. </script>
  467. <style>
  468. @import "~@/static/css/tiku.css";
  469. .questionBankAnswer-content-menu .active {
  470. background: #3c7bfc !important;
  471. }
  472. </style>