QuestionComponent.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. <template>
  2. <div id="question">
  3. <header data-am-widget="header"
  4. class="am-header">
  5. <div class="am-header-left am-header-nav" onclick="history.go(-1)">
  6. <i class="am-icon-angle-left am-icon-md"></i>
  7. </div>
  8. <h1 class="am-header-title">
  9. <i class="am-icon-hourglass-1"></i>
  10. <span>{{shijian.text}}</span>
  11. </h1>
  12. <div class="am-header-right am-header-nav" @click="save">
  13. 交卷
  14. </div>
  15. </header>
  16. <div class="body">
  17. <div class="header">
  18. <div class="time">
  19. {{paper.name}}<span style="color: red;">({{paper.exam_time}}分钟)</span>
  20. </div>
  21. <div class="btn">
  22. {{question_id}}/{{questions.length}}
  23. </div>
  24. </div>
  25. <div class="content">
  26. <div class="title">
  27. <span class="question-id">第{{question_id}}题:</span>
  28. {{question.name}}
  29. </div>
  30. <div class="radios">
  31. <div class="am-radio" v-for="radio in question.options">
  32. <label>
  33. <input v-if="question.answers.length === 1" type="radio" name="radio" @click='select(radio)'
  34. :value="radio.name">
  35. <input v-if="question.answers.length !== 1" type="checkbox" name="radio"
  36. @click='select(radio)' :value="radio.name">
  37. {{radio.name}}:{{radio.val}}
  38. </label>
  39. </div>
  40. <input style="display:none;" id="hide-radio" type="radio" name="radio" value="">
  41. <!--<input v-if="question.answers.length !== 1" style="display:none;" id="hide-radio" type="radio" name="radio" value="">-->
  42. </div>
  43. </div>
  44. <div class="error" v-if="alertStatus">
  45. <div class=" am-warning am-icon-warning mv-error"></div>
  46. <div class="msg">请先选择答案!</div>
  47. </div>
  48. </div>
  49. <div class="footer">
  50. <div :class="{prev: true, close: question_id === 1}" @click="prev">上一题</div>
  51. <div :class="{close: question_id === questions.length}" @click="next">下一题</div>
  52. </div>
  53. </div>
  54. </template>
  55. <script>
  56. export default {
  57. props: ['questions', 'paper', 'uid'],
  58. data() {
  59. return {
  60. index: 0,
  61. question: {},
  62. answer: [],
  63. selectVal: [],
  64. alertStatus: false,
  65. shijian: {
  66. h: 0,
  67. m: 0,
  68. s: 0,
  69. text: '00:00:00'
  70. },
  71. timeInterval: ''
  72. }
  73. },
  74. methods: {
  75. prev() {
  76. if (this.question_id === 1) {
  77. return false
  78. }
  79. if (!this.saveVal()) return false
  80. this.index--
  81. this.initQuestion()
  82. },
  83. next() {
  84. if (this.question_id >= this.questions.length) {
  85. return false
  86. }
  87. if (!this.saveVal()) return false
  88. this.index++
  89. this.initQuestion()
  90. },
  91. saveVal() {
  92. if (this.question.answers.length > 1) {
  93. if (this.selectVal.length === 0) {
  94. this.alertStatus = true
  95. return false
  96. }
  97. } else {
  98. if (this.selectVal === '') {
  99. this.alertStatus = true
  100. return false
  101. }
  102. }
  103. this.answer.splice(this.index, 1, this.selectVal);
  104. this.selectVal = []
  105. $('#hide-radio').attr("checked", true);
  106. $('input[name="radio"]').attr("checked", false);
  107. return true
  108. },
  109. async save(is_v = true) {
  110. if (is_v && this.selectVal === '') {
  111. this.alertStatus = true
  112. return false
  113. }
  114. this.answer.splice(this.index, 1, this.selectVal);
  115. let res = (await axios.post('/api/answer', {
  116. answer: this.answer,
  117. 'paper': this.paper.id,
  118. 'time': this.shijian,
  119. 'questions': this.questions,
  120. uid: this.uid
  121. })).data
  122. if (res.status) {
  123. layer.open({
  124. content: '提交成功',
  125. skin: 'msg',
  126. time: 3000,
  127. end: () => {
  128. location.href = '/examHistoryContent/' + res.data.id
  129. }
  130. })
  131. }else {
  132. layer.open({
  133. content: res.msg,
  134. skin: 'msg',
  135. time: 3000,
  136. end: () => {
  137. location.href = '/examList'
  138. }
  139. })
  140. }
  141. },
  142. select(newval) {
  143. this.alertStatus = false;
  144. if (this.question.answers.length > 1) {
  145. if (this.selectVal.indexOf(newval.name) < 0) {
  146. this.selectVal[this.selectVal.length] = newval.name
  147. } else {
  148. let index = this.clocked.answer.indexOf(newval.name);
  149. this.clocked.answer.splice(index, 1)
  150. }
  151. } else {
  152. this.selectVal = newval.name
  153. }
  154. },
  155. time() {
  156. this.shijian.s++
  157. if (this.shijian.s >= 60) {
  158. this.shijian.m++
  159. this.shijian.s = 0
  160. }
  161. if (this.shijian.m >= 60) {
  162. this.shijian.h++
  163. this.shijian.m = 0
  164. }
  165. this.shijian.text = this.prefixInteger(this.shijian.h, 2) + ':' + this.prefixInteger(this.shijian.m, 2) + ':' + this.prefixInteger(this.shijian.s, 2)
  166. if (this.paper.time !== 0) {
  167. let time = this.shijian.h * 6 + this.shijian.m;
  168. if (this.paper.time <= time) {
  169. window.clearInterval(this.timeInterval)
  170. let that = this
  171. layer.open({
  172. content: '测试的时间已经到了!'
  173. , btn: ['知道了']
  174. , shadeClose: false
  175. , yes: function (index) {
  176. that.save(false);
  177. // location.href = '/questions';
  178. // layer.close(index);
  179. }
  180. });
  181. }
  182. }
  183. },
  184. prefixInteger(num, n) {
  185. return (Array(n).join(0) + num).slice(-n);
  186. },
  187. initQuestion() {
  188. this.question = this.questions[this.index]
  189. window.setTimeout(() => this.initAnswer())
  190. },
  191. initAnswer() {
  192. let val = this.answer[this.index] || false
  193. if (val) {
  194. this.selectVal = val
  195. if (this.question.answers.length > 1) {
  196. $.map(val, function (v) {
  197. $('input[value="' + v + '"]').click()
  198. })
  199. } else {
  200. $('input[value="' + val + '"]').click()
  201. }
  202. }
  203. }
  204. },
  205. mounted() {
  206. this.timeInterval = setInterval(this.time, 1000)
  207. },
  208. created() {
  209. this.initQuestion()
  210. },
  211. computed: {
  212. question_id() {
  213. return this.index + 1
  214. }
  215. }
  216. }
  217. </script>
  218. <style lang="scss" scoped>
  219. @import "../../sass/mobile";
  220. #question {
  221. .body {
  222. /*padding: 5px 15px;*/
  223. .header {
  224. padding: 10px 10px;
  225. background-color: #fff;
  226. border-bottom: 1px solid $border;
  227. color: $base;
  228. div {
  229. display: inline-block;
  230. }
  231. .btn {
  232. float: right;
  233. }
  234. }
  235. .content {
  236. padding: 5px 10px;
  237. .title {
  238. padding: 10px 0 10px;
  239. border-bottom: 1px solid $border;
  240. }
  241. .radios {
  242. padding: 0 5px;
  243. }
  244. }
  245. .error {
  246. border: 1px solid #F37B1D;
  247. padding: 5px 10px;
  248. margin: 0 10px;
  249. .mv-error {
  250. -webkit-box-sizing: border-box;
  251. box-sizing: border-box;
  252. display: inline-block;
  253. width: 30px;
  254. height: 30px;
  255. font-size: 18px;
  256. line-height: 30px;
  257. border-radius: 50%;
  258. background-color: #F37B1D;
  259. color: #fff;
  260. text-align: center;
  261. margin-right: 8px;
  262. }
  263. .msg {
  264. font-size: 16px;
  265. line-height: 30px;
  266. color: #F37B1D;
  267. }
  268. div {
  269. display: inline-block;
  270. }
  271. }
  272. }
  273. .footer {
  274. position: fixed;
  275. bottom: 0;
  276. left: 0;
  277. width: 100%;
  278. display: flex;
  279. border-top: 1px solid $border;
  280. div {
  281. width: 50%;
  282. text-align: center;
  283. margin: 8px 0;
  284. }
  285. .close {
  286. color: #999;
  287. }
  288. .prev {
  289. border-right: 1px solid $border;
  290. }
  291. }
  292. }
  293. </style>