@zykjcommon/questions 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/.browserslistrc +3 -0
  2. package/.env +7 -0
  3. package/.env.buildTest +9 -0
  4. package/.env.development +9 -0
  5. package/.env.production +13 -0
  6. package/.env.test +12 -0
  7. package/@types/global.d.ts +33 -0
  8. package/@types/shims-vue.d.ts +6 -0
  9. package/@types/shims-vuex.d.ts +15 -0
  10. package/auto-imports.d.ts +6 -0
  11. package/babel.config.js +5 -0
  12. package/components.d.ts +23 -0
  13. package/design/App.vue +60 -0
  14. package/design/main.js +23 -0
  15. package/design/views/dialog/contentDialog.vue +18 -0
  16. package/design/views/dialog/contentDialog2.vue +18 -0
  17. package/design/views/dialog/contentDialog3.vue +19 -0
  18. package/design/views/exam/analysis.vue +208 -0
  19. package/design/views/exam/exam.vue +355 -0
  20. package/design/views/home/illustrate.vue +45 -0
  21. package/design/views/home/login.vue +43 -0
  22. package/design/vueMapper.js +8 -0
  23. package/design/vueMapperTree.js +2 -0
  24. package/dist/demo.html +1 -0
  25. package/dist/zykjcommon-questions.common.js +12817 -0
  26. package/dist/zykjcommon-questions.css +1 -0
  27. package/dist/zykjcommon-questions.umd.js +12836 -0
  28. package/dist/zykjcommon-questions.umd.min.js +18 -0
  29. package/index.js +10 -0
  30. package/package.json +61 -0
  31. package/public/favicon.ico +0 -0
  32. package/public/index.html +19 -0
  33. package/public/static/js/jquery.html2json.js +169 -0
  34. package/public/static/js/jquery.json2html.js +137 -0
  35. package/public/static/js/jquery.min.js +2 -0
  36. package/public/static/js/json2html.js +447 -0
  37. package/readme +8 -0
  38. package/src/App.vue +37 -0
  39. package/src/assets/img/afei.jpg +0 -0
  40. package/src/assets/img/audio-ico.gif +0 -0
  41. package/src/assets/img/audio-ico.png +0 -0
  42. package/src/assets/img/bc-type-bg.png +0 -0
  43. package/src/assets/img/big-close.png +0 -0
  44. package/src/assets/img/big-next.png +0 -0
  45. package/src/assets/img/big-pre.png +0 -0
  46. package/src/assets/img/book-bg.png +0 -0
  47. package/src/assets/img/checkbox-cur.png +0 -0
  48. package/src/assets/img/checkbox.png +0 -0
  49. package/src/assets/img/cpp-bg.png +0 -0
  50. package/src/assets/img/deer-logo.png +0 -0
  51. package/src/assets/img/header-bg-2.png +0 -0
  52. package/src/assets/img/header-bg.png +0 -0
  53. package/src/assets/img/illustrate-bg.png +0 -0
  54. package/src/assets/img/loading.gif +0 -0
  55. package/src/assets/img/login-bg.png +0 -0
  56. package/src/assets/img/login-box-bg.png +0 -0
  57. package/src/assets/img/login-box-logo.png +0 -0
  58. package/src/assets/img/logo.png +0 -0
  59. package/src/assets/img/logoByText.png +0 -0
  60. package/src/assets/img/py-bg.png +0 -0
  61. package/src/assets/img/pygame-bg.png +0 -0
  62. package/src/assets/img/radio-cur.png +0 -0
  63. package/src/assets/img/radio.png +0 -0
  64. package/src/assets/img/return-top-hover.png +0 -0
  65. package/src/assets/img/return-top.png +0 -0
  66. package/src/assets/img/sb3-bg.png +0 -0
  67. package/src/assets/img/star-ico.png +0 -0
  68. package/src/assets/img/tab-mark.png +0 -0
  69. package/src/assets/img/video-play-btn.png +0 -0
  70. package/src/assets/js/arms.js +16 -0
  71. package/src/assets/js/bus.js +14 -0
  72. package/src/assets/js/fun.js +883 -0
  73. package/src/assets/js/helper.js +575 -0
  74. package/src/assets/js/http.js +219 -0
  75. package/src/assets/js/md5.js +260 -0
  76. package/src/assets/js/rem.js +33 -0
  77. package/src/assets/js/validation.js +216 -0
  78. package/src/assets/js/zykjcommon-questions.umd.min.js +18 -0
  79. package/src/assets/logo.png +0 -0
  80. package/src/assets/scss/dialog/dialog.scss +144 -0
  81. package/src/assets/scss/exam/exam.scss +256 -0
  82. package/src/assets/scss/home/home.scss +222 -0
  83. package/src/assets/scss/index.scss +80 -0
  84. package/src/assets/scss/questions/index.scss +345 -0
  85. package/src/common/const.ts +15 -0
  86. package/src/components/common/ContentDialog.vue +172 -0
  87. package/src/components/common/IframeComponent.vue +101 -0
  88. package/src/components/common/Loading.vue +45 -0
  89. package/src/components/common/MediaLooker.vue +171 -0
  90. package/src/components/common/TextAreaEditor.vue +121 -0
  91. package/src/components/exam/QuestionCard.vue +494 -0
  92. package/src/components/exam/QuestionHeader.vue +87 -0
  93. package/src/components/exam/TimeCounter.vue +107 -0
  94. package/src/components/questions/QuestionReader.js +20 -0
  95. package/src/components/questions/Question_SingleChoice.vue +208 -0
  96. package/src/components/questions/buildEntry.js +12 -0
  97. package/src/components/questions/developmentEntry.js +11 -0
  98. package/src/components/questions/mixin.js +64 -0
  99. package/src/main.ts +176 -0
  100. package/src/router/exam.ts +50 -0
  101. package/src/router/index.ts +33 -0
  102. package/src/store/exam.ts +199 -0
  103. package/src/store/index.ts +22 -0
  104. package/src/types/common/index.ts +4 -0
  105. package/src/types/exam/exam.ts +10 -0
  106. package/src/views/exam/Analysis.vue +516 -0
  107. package/src/views/exam/Default.vue +28 -0
  108. package/src/views/exam/Exam.vue +594 -0
  109. package/src/views/exam/ReviewPaper.vue +178 -0
  110. package/src/views/exam/ReviewQuestion.vue +167 -0
  111. package/tasks/vueMapper.js +37 -0
  112. package/tasks/vueMapperTree.js +42 -0
  113. package/tsconfig.json +46 -0
  114. package/tslint.json +19 -0
  115. package/vue.config.js +107 -0
@@ -0,0 +1,494 @@
1
+ <template>
2
+ <div class="question-car-box">
3
+ <div class="question-car-tit">答题卡</div>
4
+ <ul class="question-car-list clear">
5
+ <li :class="{'current':item.completed == true,'right':item.isCorrect == true,'err':item.isCorrect == false}"
6
+ @click="jump(index)"
7
+ :key="index"
8
+ v-for="(item,index) in responsiveObj.questionList">{{item.questionIndex}}</li>
9
+ </ul>
10
+ <div class="question-car-btngroud">
11
+ <button class="submit" @click="btnSubmit" v-if="route.name !== 'analysis'">提交</button>
12
+ <!-- <button class="quit" @click="btnQuit">退出</button>-->
13
+ </div>
14
+ </div>
15
+ <ContentDialog v-if="route.name === 'examIndex'" v-model:visible="submitVisible"
16
+ :cancelText="'再检查一下'"
17
+ :confirmText="'提交'"
18
+ @confirm="submitQuestion">
19
+ <template #content>
20
+ <div class="con-text-1">提交后,将无法修改。<br>请确认是否继续提交?</div>
21
+ </template>
22
+ </ContentDialog>
23
+
24
+
25
+ <ContentDialog v-if="route.name === 'examIndex'" v-model:visible="quitVisible"
26
+ :cancelText="'退出'"
27
+ :confirmText="'继续测评'"
28
+ @cancel="submitQuestion(1,true,false)">
29
+ <template #content>
30
+ <div class="con-text-1" style="margin-top: 0.2rem">测评还未结束,确定退出?</div>
31
+ </template>
32
+ </ContentDialog>
33
+
34
+
35
+ <ContentDialog v-if="route.name === 'examIndex'" v-model:visible="noCompleteVisible"
36
+ :hide-cancel="true"
37
+ :confirmText="'我知道了'">
38
+ <template #content>
39
+ <div class="con-text-1">你还有题目未作答<br>请全部作答后,再提交。</div>
40
+ </template>
41
+ </ContentDialog>
42
+
43
+ <ContentDialog v-if="route.name === 'examIndex'" v-model:visible="timeoverVisible"
44
+ @confirm="quitQuestion"
45
+ :hide-cancel="true"
46
+ :confirmText="'我知道了'">
47
+ <template #content>
48
+ <div class="con-text-1" style="font-size: 14px;line-height: 22px"><span style="font-size: 20px;font-weight: bold;display: inline-block;margin-bottom: 15px;">测评时间到!</span><br>
49
+ 测评结束,试卷已自动提交,如有疑问请联系招聘老师。
50
+ </div>
51
+ </template>
52
+ </ContentDialog>
53
+
54
+
55
+
56
+ <ContentDialog v-if="route.name === 'examIndex'" v-model:visible="initTimeoverVisible"
57
+ :hide-cancel="true"
58
+ :confirmText="'我知道了'">
59
+ <template #content>
60
+ <div class="con-text-1" style="font-size: 14px;line-height: 22px"><span style="font-size: 20px;font-weight: bold;display: inline-block;margin-bottom: 15px;">测评已结束</span><br>
61
+ 如有疑问,请联系招聘老师。
62
+ </div>
63
+ </template>
64
+ </ContentDialog>
65
+
66
+
67
+ <ContentDialog v-if="route.name === 'examIndex'" v-model:visible="nearTimeoverVisible"
68
+ :hide-cancel="true"
69
+ :confirmText="'我知道了'">
70
+ <template #content>
71
+ <div class="con-text-1" style="font-size: 14px;line-height: 22px"><span style="font-size: 20px;font-weight: bold;display: inline-block;margin-bottom: 15px;">测评即将结束</span><br>
72
+ 离自动交卷还有10分钟,请把握好时间!
73
+ </div>
74
+ </template>
75
+ </ContentDialog>
76
+
77
+
78
+ <ContentDialog v-if="route.name === 'examIndex'" v-model:visible="warnVisible"
79
+ :hide-cancel="true"
80
+ :confirmText="'我知道了'"
81
+ @confirm="quitQuestion">
82
+ <template #content>
83
+ <div class="con-text-1" style="font-size: 14px;line-height: 22px"><span style="font-size: 20px;font-weight: bold;display: inline-block;margin-bottom: 15px;">答题失败</span><br>
84
+ 该试卷已提交,请勿重复答题,如有疑<br>问请联系老师。
85
+ </div>
86
+ </template>
87
+ </ContentDialog>
88
+
89
+
90
+ <ContentDialog v-model:visible="completeVisible"
91
+ unit="px"
92
+ :width="396"
93
+ :height="195"
94
+ :hide-cancel="true">
95
+ <template #content>
96
+ <div class="con-text-1" style="font-size: 14px;line-height: 22px"><span style="font-size: 20px;font-weight: bold;display: inline-block;margin-bottom: 20px;">试卷提交成功!</span><br>
97
+ 测评结果请咨询招聘老师。
98
+ </div>
99
+ </template>
100
+ </ContentDialog>
101
+
102
+ <Loading :loading="loading"></Loading>
103
+ </template>
104
+
105
+ <script lang="ts">
106
+ import {
107
+ defineComponent,
108
+ ref,
109
+ toRef,
110
+ toRefs,
111
+ reactive,
112
+ onMounted,
113
+ watch,
114
+ nextTick,
115
+ getCurrentInstance,
116
+ computed
117
+ } from 'vue'
118
+ import fun from '@src/assets/js/fun.js'
119
+ import bus from "@/assets/js/bus";
120
+ import {useRouter,useRoute} from 'vue-router'
121
+ import {createNamespacedHelpers} from "vuex-composition-helpers";
122
+ interface dataInterface{
123
+ completeVisible:boolean,
124
+ submitVisible:boolean,
125
+ warnVisible:boolean,
126
+ quitVisible:boolean,
127
+ noCompleteVisible:boolean,
128
+ nearTimeoverVisible:boolean,
129
+ initTimeoverVisible:boolean,
130
+ timeoverVisible:boolean,
131
+ loading:boolean,
132
+ autoSubmitTimer:any,
133
+ route:any,
134
+ examInfo:any,
135
+ uploadCodingFileSuccess:boolean
136
+ }
137
+ interface responsiveData{
138
+ questionList:Array<any>
139
+ }
140
+ export default defineComponent({
141
+ props: {
142
+ questionList: {
143
+ type: Array,
144
+ default:[]
145
+ }
146
+ },
147
+ components:{
148
+ },
149
+ setup(props, context) {
150
+
151
+ const {useActions,useState} = createNamespacedHelpers('exam'); // specific module name
152
+ const {saveAnswersActions,submitExamActions} = useActions(['saveAnswersActions','submitExamActions'])
153
+ const {hasError,examInfo} = useState(['hasError','examInfo'])
154
+ let route = useRoute()
155
+ const currentInstance:any = getCurrentInstance()
156
+ let _this = currentInstance.proxy
157
+
158
+
159
+ let data:dataInterface = reactive({
160
+ completeVisible:false,
161
+ submitVisible:false,
162
+ warnVisible:false,
163
+ quitVisible:false,
164
+ noCompleteVisible:false,
165
+ nearTimeoverVisible:false,
166
+ initTimeoverVisible:false,
167
+ timeoverVisible:false,
168
+ loading:false,
169
+ autoSubmitTimer:null,
170
+ uploadCodingFileSuccess:false,
171
+ route:route,
172
+ examInfo
173
+ })
174
+
175
+ //需要响应式放里面
176
+ let responsiveObj:{value:responsiveData} = ref({
177
+ questionList:[]
178
+ })
179
+
180
+ onMounted(()=>{
181
+ watch(() => props.questionList, (nv) => {
182
+ if(nv && nv.length){
183
+ responsiveObj.value.questionList = fun.copyDeepObject(nv) as Array<any>
184
+ //考试路由才有自动提交
185
+ if(route.name === 'examIndex'){
186
+ intervalAutoSubmit()
187
+ }else if(route.name === 'analysis'){
188
+ _this.$nextTick(()=>{
189
+ let parentRefs = _this.$parent.$refs
190
+ responsiveObj.value.questionList.forEach((item,index)=>{
191
+ let questionComponent = parentRefs[`question${index}`][0]
192
+ let isCorrect = questionComponent.isCorrect ? questionComponent.isCorrect() : false
193
+ item.isCorrect = isCorrect
194
+ })
195
+ })
196
+ }
197
+
198
+
199
+ }
200
+ },{immediate:true,deep:true})
201
+
202
+ })
203
+
204
+
205
+
206
+ // questionIndex:questionInfo.questionIndex - 1,
207
+ // answered
208
+ bus.$on('questionCardChange',(obj:any)=>{
209
+ let questionIndex = obj.questionIndex
210
+ if(route.name === 'examIndex'){
211
+ let answered = obj.answered
212
+ // if(responsiveObj.value.questionList && responsiveObj.value.questionList.length){
213
+ responsiveObj.value.questionList[questionIndex].completed = answered
214
+ // }
215
+ }
216
+ })
217
+
218
+
219
+ // 考试剩下10分钟提示
220
+ bus.$on('examNearEnd',(obj:any)=>{
221
+ //关掉所有弹窗
222
+ fun.closeAllContentDialog()
223
+ data.nearTimeoverVisible = true
224
+ })
225
+
226
+
227
+
228
+ //考试倒计时结束视为手动提交,关闭所有弹窗,超时弹窗优先级最高
229
+ bus.$on('examEnd',(isInitTimeOut:any)=>{
230
+ bus.$emit('showBlur')
231
+ if(isInitTimeOut){
232
+ fun.closeAllContentDialog()
233
+ data.initTimeoverVisible = true
234
+ return
235
+ }
236
+ //关掉所有弹窗
237
+ fun.closeAllContentDialog()
238
+ data.timeoverVisible = true
239
+ let parentRefs = _this.$parent.$refs
240
+ let keys = Object.keys(parentRefs)
241
+ let codeQuestionKeys = keys.filter((key)=>{
242
+ return parentRefs[key][0].questionInfo.question_type == 16
243
+ })
244
+ let codeQuestionComponent = null
245
+ for(let i=0;i<codeQuestionKeys.length;i++){
246
+ let codeQuestionKey = codeQuestionKeys[i]
247
+ if(codeQuestionKey){
248
+ let codeQuestion = parentRefs[codeQuestionKey][0]
249
+ if(codeQuestion.showFrame){
250
+ codeQuestionComponent = codeQuestion
251
+ break
252
+ }
253
+ }
254
+ }
255
+
256
+ if(codeQuestionComponent){
257
+ codeQuestionComponent.submitCodeQuestionByTimeover()
258
+ }else{
259
+ submitQuestion(0,false)
260
+ }
261
+ })
262
+
263
+
264
+ //时间到并且开着编程题的时候,保存编程题后的回调
265
+ bus.$on('uploadCodingFileSuccess',()=>{
266
+ data.uploadCodingFileSuccess = true
267
+ submitQuestion(0,false)
268
+ })
269
+
270
+ bus.$on('submitQuestion',(obj: any )=>{
271
+ submitQuestion(obj.saveType,obj.submitRequestAutoQuit,obj.needSubmitRequest)
272
+ })
273
+
274
+
275
+ function clearAutoTimer(){
276
+ data.autoSubmitTimer && clearInterval(data.autoSubmitTimer)
277
+ }
278
+
279
+ function intervalAutoSubmit(){
280
+ let t = 1000 * 60
281
+ // let t = 1000 * 2
282
+ clearAutoTimer()
283
+ data.autoSubmitTimer = setInterval(()=>{
284
+ submitQuestion(0)
285
+ },t)
286
+ }
287
+
288
+ function btnQuit(){
289
+ if(hasError && hasError.value){
290
+ fun.postMessageByType('close')
291
+ console.log('系统异常');
292
+ return
293
+ }
294
+ if(data.loading){
295
+ fun.postMessageByType('close')
296
+ return
297
+ }
298
+ if(data.route.name === 'reviewPaper'){
299
+ fun.postMessageByType('close')
300
+ return;
301
+ }
302
+ if(data.route.name === 'analysis'){
303
+ fun.postMessageByType('close')
304
+ }else{
305
+ data.quitVisible = true
306
+ }
307
+ }
308
+
309
+
310
+ function btnSubmit(){
311
+ if(data.route.name !== 'examIndex'){
312
+ return;
313
+ }
314
+ if(data.loading){
315
+ return
316
+ }
317
+ let noComplete = false
318
+ let parentRefs = _this.$parent.$refs
319
+ let keys = Object.keys(parentRefs)
320
+ //是否完成答题校验
321
+ for(let i=0;i<keys.length;i++){
322
+ let questionItemScope = parentRefs[keys[i]][0]
323
+ // console.log(questionItemScope.isAnswered(),456);
324
+ if(!questionItemScope.isAnswered()){
325
+ noComplete = true
326
+ break
327
+ }
328
+ }
329
+ if(noComplete){
330
+ data.noCompleteVisible = true
331
+ return
332
+ }
333
+ data.submitVisible = true
334
+ }
335
+
336
+
337
+ interface examAnswerMapItemInterF{
338
+ question_id:number|string,
339
+ a:boolean,
340
+ b:number
341
+ }
342
+
343
+ interface submitExamInterF{
344
+ save_type:number,
345
+ exam_id:number|string,
346
+ exam_answer_map:{
347
+ [propName:string]:examAnswerMapItemInterF
348
+ }
349
+ }
350
+ //submitRequestAutoQuit:true 真正手动触发提交需要请求成功后退出iframe false: 考试超时提交点我知道了退出iframe
351
+ function submitQuestion(save_type:number|undefined,submitRequestAutoQuit:boolean|undefined = true,needSubmitRequest:boolean = true){
352
+ if(data.loading){
353
+ return
354
+ }
355
+ let parentRefs = _this.$parent.$refs
356
+ let keys = Object.keys(parentRefs)
357
+ //save_type 0.自动 1.手动
358
+ // let examId = route.query.examId as string | number
359
+ let examId = data.examInfo.id
360
+ let params:submitExamInterF = {
361
+ save_type:save_type===undefined?1:save_type,
362
+ exam_id:examId,
363
+ exam_answer_map:{}
364
+ }
365
+ for(let i=0;i<keys.length;i++){
366
+ let questionItemScope = parentRefs[keys[i]][0]
367
+ // console.log(questionItemScope,'questionItemScope');
368
+ if(!questionItemScope){
369
+ let msg = `可能报错但难以复现的错误:keys---${JSON.stringify(keys)},questionList---${JSON.stringify(responsiveObj.value.questionList)}`;
370
+ (fun as any).fbError(msg,window.location.href,0,0,'可能报错但难以复现的错误')
371
+ console.log(msg);
372
+ }
373
+ let question_type = responsiveObj.value.questionList[i].question_type
374
+ //阅读理解题打平小题提交
375
+ let answered = questionItemScope.isAnswered()
376
+ if(answered){
377
+ if(question_type == 11){
378
+ let answerList = questionItemScope.getAnswer()
379
+ answerList.forEach((item:any)=>{
380
+ let answer = item.answer
381
+ params.exam_answer_map[item.question_id] = {
382
+ question_id:item.question_id,
383
+ ...answer
384
+ }
385
+ })
386
+ }else{
387
+ let question_id = responsiveObj.value.questionList[i].question_id
388
+ let answer = questionItemScope.getAnswer()
389
+ params.exam_answer_map[question_id] = {
390
+ question_id,
391
+ ...answer
392
+ }
393
+ }
394
+ }
395
+
396
+ }
397
+ //一题都没做不需要调保存接口
398
+ let paramsKeys = Object.keys(params.exam_answer_map)
399
+ if(!paramsKeys.length){
400
+ //一题都没做,并且是 考试时间到视为手动提交,不需要调保存直接提交
401
+ if(params.save_type == 1 || data.timeoverVisible){
402
+ clearAutoTimer()
403
+ //手动提交需要停止倒计时
404
+ bus.$emit('stopTimeCounter')
405
+ //时间到了需要提交请求
406
+ if(needSubmitRequest){
407
+ submitRequest(examId,submitRequestAutoQuit as boolean)
408
+ }else{
409
+ //什么都没做点退出,并且还有剩余时间的情况下
410
+ submitRequestAutoQuit && quitQuestion()
411
+ }
412
+ }
413
+ return
414
+ }else{
415
+ if((params.save_type == 1 && submitRequestAutoQuit) || data.timeoverVisible){
416
+ //手动提交并且需要自动退出才需要清理自动提交定时器和倒计时定时器
417
+ clearAutoTimer()
418
+ bus.$emit('stopTimeCounter')
419
+ }
420
+ data.loading = true
421
+ saveAnswersActions(params).then((res:any) => {
422
+ data.loading = false
423
+ let {error_code} = res;
424
+ if (!error_code) {
425
+ if(params.save_type == 1 || data.timeoverVisible){
426
+ if(needSubmitRequest){
427
+ submitRequest(examId,submitRequestAutoQuit as boolean)
428
+ }else{
429
+ submitRequestAutoQuit && quitQuestion()
430
+ }
431
+ }
432
+ }else{
433
+ if(error_code === 39002){
434
+ data.warnVisible = true
435
+ }
436
+ }
437
+ },()=>{
438
+ data.loading = false
439
+ });
440
+ }
441
+ }
442
+
443
+ function submitRequest(examId:string | number,submitRequestAutoQuit:boolean){
444
+ data.loading = true
445
+ submitExamActions({exam_id:examId}).then((res:any)=>{
446
+ data.loading = false
447
+ let {error_code} = res;
448
+ if (!error_code){
449
+ //时间到了就不弹完成弹窗
450
+ if(!data.timeoverVisible){
451
+ fun.closeAllContentDialog()
452
+ data.completeVisible = true
453
+ }
454
+ bus.$emit('showBlur')
455
+ // console.log(submitRequestAutoQuit,888888888888);
456
+ submitRequestAutoQuit && quitQuestion()
457
+ }
458
+ },()=>{
459
+ data.loading = false
460
+ })
461
+ }
462
+
463
+
464
+ function quitQuestion(){
465
+ clearAutoTimer()
466
+ fun.postMessageByType('close')
467
+ }
468
+
469
+
470
+ function jump(index:number){
471
+ let idStr = `question${index}`
472
+ let jumpTarget = document.getElementById(idStr)
473
+ let header = document.querySelector('.header')
474
+ let oft = fun.offset(jumpTarget,'top')
475
+ let headerH = (header as HTMLElement).clientHeight
476
+ let scrollDistance = oft - headerH
477
+ let scrollMain:any = document.querySelector('.content-outter')
478
+ scrollMain.scrollTop = scrollDistance
479
+ }
480
+
481
+ return {
482
+ ...toRefs(data),
483
+ btnSubmit,
484
+ btnQuit,
485
+ submitQuestion,
486
+ quitQuestion,
487
+ jump,
488
+ responsiveObj
489
+ }
490
+ }
491
+ })
492
+ </script>
493
+
494
+ <!-- Add "scoped" attribute to limit CSS to this component only -->
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <div class="header" :class="{'fixed':enterCode && routeName === 'examIndex'}">
3
+ <div class="header-main">
4
+ <div class="header-left">
5
+ <div class="header-left-top">姓名:<span v-if="responsiveObj.resData.applicant_simple_info">{{ responsiveObj.resData.applicant_simple_info.applicant_name }}</span></div>
6
+ <div class="header-left-bottom">手机号:<span v-if="responsiveObj.resData.applicant_simple_info">{{ responsiveObj.resData.applicant_simple_info.phone }}</span></div>
7
+ </div>
8
+ <div class="header-title">{{responsiveObj.resData.online_exam_name}}</div>
9
+
10
+ <div class="header-right"
11
+ v-if="routeName === 'examIndex' || routeName === 'reviewPaper'">
12
+ <span>测评剩余时间</span>
13
+ <TimeCounter :time="responsiveObj.resData.remain_second"></TimeCounter>
14
+ </div>
15
+ <div class="header-right" v-if="routeName === 'analysis'">
16
+ <span>测评成绩</span>
17
+ <span class="score">{{responsiveObj.resData.user_total_score}}<span>分</span></span>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ </template>
22
+
23
+ <script lang="ts">
24
+ import {defineComponent, ref, toRefs, reactive, watch, onMounted} from 'vue'
25
+ import TimeCounter from '@src/components/exam/TimeCounter.vue'
26
+ import {useRoute} from 'vue-router'
27
+ import bus from "@/assets/js/bus";
28
+
29
+
30
+ interface dataInterface{
31
+ enterCode:boolean,
32
+ routeName:string
33
+ }
34
+
35
+ interface responsiveData{
36
+ resData:any
37
+ }
38
+
39
+
40
+ export default defineComponent({
41
+ props: {
42
+ resData: {
43
+ type: Object,
44
+ default:{}
45
+ }
46
+ },
47
+ components: {
48
+ TimeCounter
49
+ },
50
+ setup(props,context) {
51
+ let route = useRoute()
52
+ //不需要响应式或者写死的数据放里面
53
+ let data:dataInterface = reactive({
54
+ enterCode:false,
55
+ routeName:route.name as string
56
+ })
57
+
58
+ //需要响应式放里面
59
+ let responsiveObj:{value:responsiveData} = ref({
60
+ resData:{}
61
+ })
62
+
63
+
64
+ onMounted(()=>{
65
+ bus.$on('enterCode',(bol)=>{
66
+ data.enterCode = bol as boolean
67
+ })
68
+ })
69
+
70
+
71
+ watch(() => props.resData, (nv) => {
72
+ if(nv){
73
+ responsiveObj.value.resData = nv
74
+ }
75
+ },{immediate:true})
76
+
77
+
78
+ return {
79
+ ...toRefs(data),
80
+ responsiveObj
81
+ }
82
+ }
83
+ })
84
+ </script>
85
+ <style lang="scss" scoped>
86
+
87
+ </style>
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <span class="time">{{responsiveObj.examTimeStr}}</span>
3
+ </template>
4
+
5
+ <script lang="ts">
6
+ import {defineComponent, ref, toRef, toRefs, reactive, onMounted, watch, nextTick, getCurrentInstance} from 'vue'
7
+ import bus from "@/assets/js/bus";
8
+ import {useRoute} from "vue-router";
9
+ interface dataInterface{
10
+ timer:any
11
+ }
12
+ interface responsiveData{
13
+ examTime:number,
14
+ examTimeStr:string
15
+ }
16
+ export default defineComponent({
17
+ props: {
18
+ time: {
19
+ type: Number
20
+ }
21
+ },
22
+ components:{
23
+
24
+ },
25
+ setup(props, context) {
26
+ let route = useRoute()
27
+ let data:dataInterface = reactive({
28
+ timer:null
29
+ })
30
+
31
+ //需要响应式放里面
32
+ let responsiveObj:{value:responsiveData} = ref({
33
+ examTime:0,
34
+ examTimeStr:''
35
+ })
36
+
37
+
38
+ if(props.time === undefined || props.time === null){
39
+ responsiveObj.value.examTimeStr = getExamTimeStr(0)
40
+ }
41
+
42
+
43
+ watch(() => props.time, (nv) => {
44
+ responsiveObj.value.examTime = nv ? (nv < 0 ? 0: nv) : 0
45
+ // responsiveObj.value.examTime = 3000
46
+ responsiveObj.value.examTimeStr = getExamTimeStr(responsiveObj.value.examTime)
47
+ route.name === 'examIndex' && intervalGetExamTimeStr()
48
+ })
49
+
50
+ bus.$on('stopTimeCounter',()=>{
51
+ clearInterval(data.timer)
52
+ data.timer = null
53
+ })
54
+
55
+
56
+ /*function getExamTimeStr(examTime:number){
57
+ let hours = `${Math.floor(examTime / 3600000)}`
58
+ let min = `${Math.floor((examTime % 3600000) / 60000)}`
59
+ let s = `${Math.floor((examTime % 3600000 % 60000) / 1000 )}`
60
+ hours = Number(hours) < 10 ? `0${hours}` : hours
61
+ min = Number(min) < 10 ? `0${min}` : min
62
+ s = Number(s) < 10 ? `0${s}` : s
63
+ return `${hours}:${min}:${s}`
64
+ }*/
65
+ function getExamTimeStr(examTime:number){
66
+ let min = `${Math.floor(examTime / 60000)}`
67
+ let s = `${Math.floor((examTime % 60000) / 1000 )}`
68
+ min = Number(min) < 10 ? `0${min}` : min
69
+ s = Number(s) < 10 ? `0${s}` : s
70
+ return `${min}:${s}`
71
+ }
72
+ function intervalGetExamTimeStr(){
73
+ //一进来就没时间了和自然走到没时间要区分
74
+ if((props as any).time < 1000){
75
+ bus.$emit('examEnd',true)//true为是否初始化就是没时间
76
+ return
77
+ }
78
+ data.timer = setInterval(()=>{
79
+ // console.log(data.examTime);
80
+ if(responsiveObj.value.examTime < 1000){
81
+ responsiveObj.value.examTime = 0
82
+ clearInterval(data.timer)
83
+ data.timer = null
84
+ bus.$emit('examEnd')
85
+ }else{
86
+ let tenMin = 1000 * 60 * 10
87
+ if(responsiveObj.value.examTime <= tenMin && responsiveObj.value.examTime > tenMin - 1000){
88
+ bus.$emit('examNearEnd')
89
+ }
90
+ responsiveObj.value.examTime -= 1000
91
+ }
92
+ responsiveObj.value.examTimeStr = getExamTimeStr(responsiveObj.value.examTime)
93
+ },1000)
94
+ }
95
+
96
+ return {
97
+ ...toRefs(data),
98
+ responsiveObj
99
+ }
100
+ }
101
+ })
102
+ </script>
103
+
104
+ <!-- Add "scoped" attribute to limit CSS to this component only -->
105
+ <style scoped lang="scss">
106
+
107
+ </style>
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Created by Allen Liu on 2022/4/1.
3
+ */
4
+ import Question_SingleChoice from '@src/components/questions/Question_SingleChoice.vue'
5
+ import Question_MultipleChoice from '@src/components/questions/Question_MultipleChoice.vue'
6
+ import Question_Programming from '@src/components/questions/Question_Programming.vue'
7
+ import Question_BriefAnswer from '@src/components/questions/Question_BriefAnswer.vue'
8
+ import Question_Reading from '@src/components/questions/Question_Reading.vue'
9
+ import Question_FillBlank from '@src/components/questions/Question_FillBlank.vue'
10
+
11
+
12
+
13
+ export default {
14
+ Question_SingleChoice,
15
+ Question_MultipleChoice,
16
+ Question_Programming,
17
+ Question_BriefAnswer,
18
+ Question_Reading,
19
+ Question_FillBlank
20
+ }