Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
L
learn-online-pc
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
learn-online-pc
Commits
1eb19f81
提交
1eb19f81
authored
5月 25, 2020
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
修改课程考试模块
上级
7854fc18
隐藏空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
1031 行增加
和
463 行删除
+1031
-463
PlayerAction.js
client/src/action/PlayerAction.js
+84
-79
player_api.js
client/src/api/player_api.js
+1
-1
courseDetail.vue
client/src/pages/learn/courseDetail.vue
+2
-0
chapterExam2.vue
client/src/pages/player/chapterExam/chapterExam2.vue
+770
-0
exam.vue
client/src/pages/player/exam/exam.vue
+160
-382
index.vue
client/src/pages/player/index.vue
+6
-1
sideChapterList.vue
client/src/pages/player/rightSide/sideChapterList.vue
+2
-0
routes.js
client/src/router/routes.js
+6
-0
没有找到文件。
client/src/action/PlayerAction.js
浏览文件 @
1eb19f81
...
...
@@ -164,7 +164,8 @@ export default class PlayerAction extends BaseACTION {
json
:
json
,
courseInfo
:
_res
.
files
||
[],
courseWork
:
_res
.
curriculum
||
{},
curJson
:
curJson
curJson
:
curJson
,
rawResponse
:
_res
}
})
}
...
...
@@ -291,51 +292,51 @@ export default class PlayerAction extends BaseACTION {
exam
.
id
=
_res
.
id
exam
.
title
=
_res
.
title
exam
.
score
=
{}
exam
.
radioList
=
_res
.
examination
.
radioList
for
(
let
i
=
0
;
i
<
exam
.
radioList
.
length
;
i
++
)
{
exam
.
radioList
[
i
].
user_answer
=
''
exam
.
radioList
[
i
].
right_answer
=
''
exam
.
radioList
[
i
].
get_score
=
-
1
}
exam
.
checkboxList
=
_res
.
examination
.
checkboxList
for
(
let
i
=
0
;
i
<
exam
.
checkboxList
.
length
;
i
++
)
{
exam
.
checkboxList
[
i
].
user_answer
=
[]
exam
.
checkboxList
[
i
].
right_answer
=
[]
exam
.
checkboxList
[
i
].
get_score
=
-
1
}
exam
.
shortAnswerList
=
_res
.
examination
.
shortAnswerList
for
(
let
i
=
0
;
i
<
exam
.
shortAnswerList
.
length
;
i
++
)
{
exam
.
shortAnswerList
[
i
].
user_answer
=
''
exam
.
shortAnswerList
[
i
].
get_score
=
-
1
exam
.
shortAnswerList
[
i
].
attachments
=
[]
exam
.
shortAnswerList
[
i
].
upload
=
{
type
:
'upload-form'
,
label
:
'附件上传:'
,
model
:
'attachments'
,
action
:
webConf
.
apiBaseURL
+
'/util/upload-file'
,
data
:
{
special
:
'exam'
},
attrs
:
{
multiple
:
true
,
headers
:
{
tenant
:
'sofia'
}
},
html
:
`
<div style="color: #72818c; font-size: 14px;">
<p style="margin: 0;">支持doc,docx,ppt,xls,txt,rar,zip,pdf,jpg,pic,png格式的文件,文件小于30M。</p>
</div>
`
exam
.
examination
=
_res
.
examination
.
map
(
exam
=>
{
for
(
let
i
=
0
;
i
<
exam
.
radioList
.
length
;
i
++
)
{
exam
.
radioList
[
i
].
user_answer
=
''
exam
.
radioList
[
i
].
right_answer
=
''
exam
.
radioList
[
i
].
get_score
=
-
1
}
}
for
(
let
i
=
0
;
i
<
exam
.
checkboxList
.
length
;
i
++
)
{
exam
.
checkboxList
[
i
].
user_answer
=
[]
exam
.
checkboxList
[
i
].
right_answer
=
[]
exam
.
checkboxList
[
i
].
get_score
=
-
1
}
for
(
let
i
=
0
;
i
<
exam
.
shortAnswerList
.
length
;
i
++
)
{
exam
.
shortAnswerList
[
i
].
user_answer
=
''
exam
.
shortAnswerList
[
i
].
get_score
=
-
1
exam
.
shortAnswerList
[
i
].
attachments
=
[]
exam
.
shortAnswerList
[
i
].
upload
=
{
type
:
'upload-form'
,
label
:
'附件上传:'
,
model
:
'attachments'
,
action
:
webConf
.
apiBaseURL
+
'/util/upload-file'
,
data
:
{
special
:
'exam'
},
attrs
:
{
multiple
:
true
,
headers
:
{
tenant
:
'sofia'
}
},
html
:
`
<div style="color: #72818c; font-size: 14px;">
<p style="margin: 0;">支持doc,docx,ppt,xls,txt,rar,zip,pdf,jpg,pic,png格式的文件,文件小于30M。</p>
</div>
`
}
}
return
exam
})
return
exam
})
}
/* 获取考卷结果 */
getExamAnswer
(
cid
,
sid
,
eid
)
{
return
Player
.
getExamAnswer
(
cid
,
sid
,
eid
).
then
(
_res
=>
{
getExamAnswer
(
cid
,
sid
,
eid
,
obj
)
{
return
Player
.
getExamAnswer
(
cid
,
sid
,
eid
,
obj
).
then
(
_res
=>
{
if
(
_res
.
code
)
{
return
_res
}
const
exam
=
{}
let
tmp
=
null
...
...
@@ -345,46 +346,50 @@ export default class PlayerAction extends BaseACTION {
exam
.
score
=
_res
.
score
exam
.
isPublished
=
_res
.
is_published
||
''
exam
.
submitted_time
=
_res
.
submitted_time
exam
.
radioList
=
_res
.
sheet
.
radioList
for
(
let
i
=
0
;
i
<
exam
.
radioList
.
length
;
i
++
)
{
tmp
=
exam
.
radioList
[
i
]
if
(
!
tmp
.
user_answer
)
tmp
.
user_answer
=
''
if
(
!
tmp
.
right_answer
)
tmp
.
right_answer
=
''
if
(
!
tmp
.
get_score
)
tmp
.
get_score
=
-
1
}
exam
.
checkboxList
=
_res
.
sheet
.
checkboxList
for
(
let
i
=
0
;
i
<
exam
.
checkboxList
.
length
;
i
++
)
{
tmp
=
exam
.
checkboxList
[
i
]
if
(
!
tmp
.
user_answer
||
!
tmp
.
user_answer
.
length
)
tmp
.
user_answer
=
[]
if
(
!
tmp
.
right_answer
||
!
tmp
.
right_answer
.
length
)
tmp
.
right_answer
=
[]
if
(
!
tmp
.
get_score
)
tmp
.
get_score
=
-
1
}
exam
.
shortAnswerList
=
_res
.
sheet
.
shortAnswerList
for
(
let
i
=
0
;
i
<
exam
.
shortAnswerList
.
length
;
i
++
)
{
tmp
=
exam
.
shortAnswerList
[
i
]
tmp
.
user_answer
=
Base64
.
decode
(
tmp
.
user_answer
.
replace
(
/ /gi
,
'+'
))
if
(
!
tmp
.
attachments
||
!
tmp
.
attachments
.
length
)
tmp
.
attachments
=
[]
tmp
.
upload
=
{
type
:
'upload-form'
,
label
:
'附件上传:'
,
model
:
'attachments'
,
action
:
webConf
.
apiBaseURL
+
'/util/upload-file'
,
data
:
{
special
:
'exam'
},
attrs
:
{
multiple
:
true
,
headers
:
{
tenant
:
'sofia'
}
},
html
:
`
<div style="color: #72818c; font-size: 14px;">
<p style="margin: 0;">支持doc,docx,ppt,xls,txt,rar,zip,pdf,jpg,pic,png格式的文件,文件小于30M。</p>
</div>
`
exam
.
examination
=
_res
.
sheet
.
map
(
exam
=>
{
exam
.
radioList
=
exam
.
radioList
||
[]
for
(
let
i
=
0
;
i
<
exam
.
radioList
.
length
;
i
++
)
{
tmp
=
exam
.
radioList
[
i
]
if
(
!
tmp
.
user_answer
)
tmp
.
user_answer
=
''
if
(
!
tmp
.
right_answer
)
tmp
.
right_answer
=
''
if
(
!
tmp
.
get_score
)
tmp
.
get_score
=
-
1
}
}
exam
.
checkboxList
=
exam
.
checkboxList
||
[]
for
(
let
i
=
0
;
i
<
exam
.
checkboxList
.
length
;
i
++
)
{
tmp
=
exam
.
checkboxList
[
i
]
if
(
!
tmp
.
user_answer
||
!
tmp
.
user_answer
.
length
)
tmp
.
user_answer
=
[]
// if (!tmp.right_answer || !tmp.right_answer.length) tmp.right_answer = []
tmp
.
right_answer
=
tmp
.
right_answer
||
[]
if
(
!
tmp
.
get_score
)
tmp
.
get_score
=
-
1
}
exam
.
shortAnswerList
=
exam
.
shortAnswerList
||
[]
for
(
let
i
=
0
;
i
<
exam
.
shortAnswerList
.
length
;
i
++
)
{
tmp
=
exam
.
shortAnswerList
[
i
]
tmp
.
user_answer
=
tmp
.
user_answer
?
Base64
.
decode
(
tmp
.
user_answer
.
replace
(
/ /gi
,
'+'
))
:
''
if
(
!
tmp
.
attachments
||
!
tmp
.
attachments
.
length
)
tmp
.
attachments
=
[]
tmp
.
upload
=
{
type
:
'upload-form'
,
label
:
'附件上传:'
,
model
:
'attachments'
,
action
:
webConf
.
apiBaseURL
+
'/util/upload-file'
,
data
:
{
special
:
'exam'
},
attrs
:
{
multiple
:
true
,
headers
:
{
tenant
:
'sofia'
}
},
html
:
`
<div style="color: #72818c; font-size: 14px;">
<p style="margin: 0;">支持doc,docx,ppt,xls,txt,rar,zip,pdf,jpg,pic,png格式的文件,文件小于30M。</p>
</div>
`
}
}
return
exam
})
return
exam
})
}
...
...
client/src/api/player_api.js
浏览文件 @
1eb19f81
...
...
@@ -113,7 +113,7 @@ export default class PlayerAPI extends BaseAPI {
* @param {[string]} semester_id -> sid
* @param {[string]} exam_id -> eid
*/
getExamAnswer
=
(
cid
,
sid
,
eid
)
=>
this
.
get
(
`/v2/education/
${
sid
}
/
${
cid
}
/examination/
${
eid
}
/sheet`
,
{}
)
getExamAnswer
=
(
cid
,
sid
,
eid
,
obj
=
{})
=>
this
.
get
(
`/v2/education/
${
sid
}
/
${
cid
}
/examination/
${
eid
}
/sheet`
,
obj
)
/**
* 获取考试状态
* @param {[string]} course_id -> cid
...
...
client/src/pages/learn/courseDetail.vue
浏览文件 @
1eb19f81
...
...
@@ -618,6 +618,8 @@ export default {
}
else
{
this
.
$router
.
push
({
path
:
`/player/
${
sid
}
/
${
cid
}
/live/
${
_id
}
`
})
}
}
else
if
(
_course
.
chapters
[
i2
].
type
===
9
)
{
this
.
$router
.
push
({
path
:
`/player/
${
sid
}
/
${
cid
}
/chapter-exam2/
${
_course
.
chapters
[
i2
].
id
}
`
})
}
return
}
...
...
client/src/pages/player/chapterExam/chapterExam2.vue
0 → 100644
浏览文件 @
1eb19f81
<
template
>
<div
class=
"play-paper"
>
<div
class=
"play-paper-body"
>
<div
class=
"play-paper-title"
>
<div>
<h3>
{{
exam
.
title
}}
</h3>
</div>
</div>
<template
v-if=
"exam.type !== 3"
>
<div
class=
"play-paper-content play-chapter-exam"
>
<template
v-if=
"exam.id"
>
<div
class=
"exam"
>
<!--
<div
style=
'text-align: center;'
>
-->
<!--
<div
class=
'topic'
>
-->
<!--
<div
class=
'tit'
>
{{
exam
.
title
}}
</div>
-->
<template
v-if=
"exam.type === 2"
>
<template
v-if=
"exam.score"
>
<div
style=
"font-size: 18px;"
>
总分:
{{
exam
.
score
.
total
}}
分
</div>
</
template
>
</template>
<
template
v-else-if=
"exam.type === 1"
>
<div
class=
"no-exam"
>
试卷批改中,请耐心等待
</div>
</
template
>
<!-- </div> -->
<!-- </div> -->
<
template
v-if=
"(exam.type !== 1 && exam.type !== 2)"
>
<div
style=
"text-align: center;"
v-if=
"exam.paper_deadline"
>
考试截止时间为:
{{
exam
.
paper_deadline
}}
</div>
<template
v-for=
"exam in exam.examination"
>
<!-- 单选题 -->
<template
v-if=
"exam.radioList.length"
>
<template
v-for=
"(item, index) in exam.radioList"
>
<div
v-bind:key=
"item.id"
class=
"q-group"
:data-index=
"index"
>
<div
class=
"q-num"
>
{{
index
+
1
}}
.
</div>
<div
class=
"q-title"
v-html=
"item.content"
></div>
<div
class=
"q-type"
>
(单选题)
</div>
<el-radio-group
class=
"radio-group"
v-model=
"item.user_answer"
>
<template
v-for=
"(item1, index1) in item.options"
>
<el-radio
v-bind:key=
"item1.id"
:label=
"item1.id"
:disabled=
"!!item.right_answer && !!exam.type"
:class=
"['radio', ((item.right_answer && !!exam.type) ? (item1.id === item.right_answer ? 'success' : 'error') : '')]"
>
{{
index1
|
getLetter
()
}}
.
{{
item1
.
option
}}
</el-radio>
</
template
>
</el-radio-group>
<
template
v-if=
"item.right_answer && !!exam.type"
>
<div
class=
"result"
>
学生答案:
<div
:class=
"['stu', (item.right_answer === item.user_answer ? 'success' : 'error')]"
>
{{
item
.
user_answer
|
getRadioAnswer
(
item
.
options
)
}}
</div>
正确答案:
{{
item
.
right_answer
|
getRadioAnswer
(
item
.
options
)
}}
</div>
</
template
>
</div>
</template>
</template>
<!-- 多选题 -->
<
template
v-if=
"exam.checkboxList.length"
>
<template
v-for=
"(item, index) in exam.checkboxList"
>
<div
v-bind:key=
"item.id"
class=
"q-group"
:data-index=
"index"
>
<div
class=
"q-num"
>
{{
exam
.
radioList
.
length
+
index
+
1
}}
.
</div>
<div
class=
"q-title"
v-html=
"item.content"
></div>
<div
class=
"q-type"
>
(多选题)
</div>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"item.user_answer"
>
<template
v-for=
"(item1, index1) in item.options"
>
<el-checkbox
v-bind:key=
"item1.id"
:label=
"item1.id"
:disabled=
"!!item.right_answer.length && !!exam.type"
:class=
"['checkbox', ((item.right_answer.length && !!exam.type) ? (isCheckboxChecked(item1.id, item.right_answer) ? 'success' : 'error') : '')]"
>
{{
index1
|
getLetter
()
}}
.
{{
item1
.
option
}}
</el-checkbox>
</
template
>
</el-checkbox-group>
<
template
v-if=
"item.right_answer.length && !!exam.type"
>
<div
class=
"result"
>
学生答案:
<div
:class=
"['stu', ((item.right_answer.length && isCheckboxRight(item.user_answer, item.right_answer)) ? 'success' : 'error')]"
>
{{
item
.
user_answer
|
getCheckboxAnswer
(
item
.
options
)
}}
</div>
正确答案:
{{
item
.
right_answer
|
getCheckboxAnswer
(
item
.
options
)
}}
</div>
</
template
>
</div>
</template>
</template>
<!-- 简答题 -->
<
template
v-if=
"exam.shortAnswerList.length"
>
<template
v-for=
"(item, index) in exam.shortAnswerList"
>
<div
class=
"q-group"
:key=
"index"
>
<div
class=
"q-sa-title"
>
{{
exam
.
radioList
.
length
+
exam
.
checkboxList
.
length
+
index
+
1
}}
.
简答题
</div>
<div
class=
"edit_html"
v-html=
"item.content || ''"
></div>
<v-editor
v-model=
"item.user_answer"
></v-editor>
<div
style=
"height: 10px;"
></div>
<!-- 利用key值自动更新组件 -->
<component
:is=
"item.upload.type"
v-bind:key=
"item.upload.id + new Date().getTime()"
:item=
"item.upload"
:formData=
"item"
:isUpload=
"!exam.type"
></component>
</div>
</
template
>
</template>
</template>
<div
:class=
"['btn', (exam.type && 'on')]"
@
click=
"submitExam"
:data-submit=
"!!exam.type"
@
mousedown=
"_SubmitMouseLeftDown()"
>
{{exam.type ? "已提交" : "提交"}}
</div>
<div
class=
"care"
>
(注意:考试只有一次提交机会)
</div>
<!-- <div :class='["btn"]' @click='repeatExam($event, true)' v-if="exam.work_contents">重做</div> -->
</template>
</div>
</template>
</div>
</template>
<
template
v-else
>
<div
class=
"exam"
>
<!--
<p>
考试须知:
</p>
-->
<div
style=
"text-align: left;"
v-if=
"exam.paper_deadline"
>
考试截止时间为:
{{
exam
.
paper_deadline
}}
</div>
<template
v-if=
"isExamTime"
>
<div
style=
"width: 25%;"
:class=
"['btn']"
@
click=
"beginExam(true)"
@
mousedown=
"beginExam(true)"
>
开始考试
</div>
</
template
>
</div>
</template>
</div>
</div>
</template>
<
script
>
import
cAction
from
'@action'
import
Base64
from
'Base64'
import
VEditor
from
'@/components/editor.vue'
var
getLetter
=
val
=>
{
switch
(
val
)
{
case
0
:
return
'A'
case
1
:
return
'B'
case
2
:
return
'C'
case
3
:
return
'D'
case
4
:
return
'E'
case
5
:
return
'F'
case
6
:
return
'G'
case
7
:
return
'H'
case
8
:
return
'I'
case
9
:
return
'J'
case
10
:
return
'K'
case
11
:
return
'L'
case
12
:
return
'M'
}
}
export
default
{
props
:
{
chapters
:
{
type
:
Array
,
default
()
{
return
[]
}
},
sid
:
{
type
:
String
,
require
:
false
},
cid
:
{
type
:
String
,
require
:
false
},
id
:
{
type
:
String
,
require
:
false
}
},
components
:
{
VEditor
},
filters
:
{
getLetter
:
getLetter
,
getRadioAnswer
:
(
val
,
arr
)
=>
{
for
(
let
i
=
0
;
i
<
arr
.
length
;
i
++
)
{
if
(
arr
[
i
].
id
===
val
)
{
return
getLetter
(
i
)
}
}
},
getCheckboxAnswer
:
(
val
,
arr
)
=>
{
let
str
=
''
for
(
let
i
=
0
;
i
<
val
.
length
;
i
++
)
{
const
tmpId
=
val
[
i
]
for
(
let
j
=
0
;
j
<
arr
.
length
;
j
++
)
{
if
(
arr
[
j
].
id
===
tmpId
)
{
str
+=
getLetter
(
j
)
+
','
break
}
}
}
return
str
.
substr
(
0
,
str
.
length
-
1
)
}
},
data
()
{
return
{
_time
:
null
,
// 定时器,自动化提交
exam
:
{},
status
:
{
isStart
:
false
,
startTime
:
''
,
terminateTime
:
''
,
serverTime
:
''
,
examinationStatus
:
''
,
type
:
0
,
isPublished
:
0
}
}
},
computed
:
{
// 当前章节
activeChatper
()
{
for
(
const
item
of
this
.
chapters
)
{
return
item
.
children
.
find
(
subItem
=>
subItem
.
id
===
this
.
id
)
}
},
// 是否是考试时间
isExamTime
()
{
if
(
!
this
.
exam
.
paper_deadline
)
{
return
true
}
// 大于开始时间,小于结束时间
const
endTime
=
+
new
Date
(
this
.
exam
.
paper_deadline
)
const
currentTime
=
new
Date
().
getTime
()
return
currentTime
<
endTime
},
// 考试完成
isExamComplete
()
{
// 考试完成,批改完成并且公布成绩
return
this
.
exam
.
is_published
===
1
&&
this
.
exam
.
type
===
2
},
// 是否提交
isSubmited
()
{
return
this
.
exam
.
type
===
1
||
this
.
exam
.
type
===
2
}
},
watch
:
{
id
:
{
handler
()
{
this
.
init
()
}
}
},
mounted
()
{
this
.
init
()
this
.
$emit
(
'changeSideBar'
,
''
)
setTimeout
(()
=>
{
if
(
window
.
document
.
getElementById
(
'switch-btn'
))
{
window
.
document
.
getElementById
(
'switch-btn'
).
style
.
display
=
'none'
}
},
500
)
},
destroyed
()
{
if
(
this
.
_time
)
{
clearInterval
(
this
.
_time
)
this
.
_time
=
null
}
if
(
window
.
document
.
getElementById
(
'switch-btn'
))
{
window
.
document
.
getElementById
(
'switch-btn'
).
style
.
display
=
'block'
}
},
methods
:
{
isCheckboxRight
:
(
val
,
arr
)
=>
{
let
flag
=
true
for
(
let
i
=
0
;
i
<
arr
.
length
;
i
++
)
{
const
tmpId
=
arr
[
i
]
let
j
=
0
for
(;
j
<
val
.
length
;
j
++
)
{
if
(
val
[
j
]
===
tmpId
)
{
break
}
}
if
(
j
===
val
.
length
)
{
flag
=
false
break
}
}
return
flag
},
isCheckboxChecked
:
(
val
,
arr
)
=>
{
let
i
=
0
for
(;
i
<
arr
.
length
;
i
++
)
{
if
(
arr
[
i
].
id
===
val
||
arr
[
i
]
===
val
)
{
return
true
}
}
return
false
},
init
()
{
const
data
=
this
.
activeChatper
.
paper
this
.
exam
=
data
this
.
exam
.
id
=
data
.
id
this
.
exam
.
title
=
data
.
paper_title
this
.
exam
.
score
=
{}
this
.
exam
.
examination
=
data
.
examination
.
map
(
exam
=>
{
for
(
let
i
=
0
;
i
<
exam
.
radioList
.
length
;
i
++
)
{
exam
.
radioList
[
i
].
user_answer
=
''
exam
.
radioList
[
i
].
right_answer
=
''
exam
.
radioList
[
i
].
get_score
=
-
1
}
for
(
let
i
=
0
;
i
<
exam
.
checkboxList
.
length
;
i
++
)
{
exam
.
checkboxList
[
i
].
user_answer
=
[]
exam
.
checkboxList
[
i
].
right_answer
=
[]
exam
.
checkboxList
[
i
].
get_score
=
-
1
}
for
(
let
i
=
0
;
i
<
exam
.
shortAnswerList
.
length
;
i
++
)
{
exam
.
shortAnswerList
[
i
].
user_answer
=
''
exam
.
shortAnswerList
[
i
].
get_score
=
-
1
exam
.
shortAnswerList
[
i
].
attachments
=
[]
exam
.
shortAnswerList
[
i
].
upload
=
{
type
:
'upload-form'
,
label
:
'附件上传:'
,
model
:
'attachments'
,
action
:
webConf
.
apiBaseURL
+
'/util/upload-file'
,
data
:
{
special
:
'exam'
},
attrs
:
{
multiple
:
true
,
headers
:
{
tenant
:
'sofia'
}
},
html
:
`
<div style="color: #72818c; font-size: 14px;">
<p style="margin: 0;">支持doc,docx,ppt,xls,txt,rar,zip,pdf,jpg,pic,png格式的文件,文件小于30M。</p>
</div>
`
}
}
return
exam
})
this
.
exam
.
paper_deadline
=
data
.
paper_deadline
// this.loadExamStatus()
// this.loadExamInfo()
this
.
loadAjax
()
// if (this._time) {
// clearInterval(this._time)
// this._time = null
// }
// this._time = setInterval(() => {
// // this.loadExamStatus()
// if (!this.exam.type && this.status.isStart) {
// // console.log(11, '暂存')
// this.submitExam({ submitType: true }) // 暂存, submitType: true 暂存;其他或不填为提交
// }
// /* 到时间 自动提交 */
// if (
// !this.exam.type &&
// this.status.isStart &&
// new Date(this.status.terminateTime).getTime() -
// new Date(this.status.serverTime).getTime()
<=
// 5000
// ) {
// this.submitExam({ submitType: false, currentTarget: { dataset: {} } })
// }
// }, 3000)
},
/* 定时调用 - 考试状态 */
loadExamStatus
()
{
cAction
.
Player
.
getExamStatus
(
this
.
cid
,
this
.
sid
,
this
.
id
)
.
then
(
_data
=>
{
if
(
_data
.
status
&&
_data
.
status
===
200
)
{
this
.
status
.
startTime
=
this
.
setTime
(
_data
.
start_time
)
this
.
status
.
terminateTime
=
_data
.
terminate_time
this
.
status
.
serverTime
=
this
.
setTime
(
_data
.
server_time
)
this
.
status
.
examinationStatus
=
_data
.
examination_status
}
else
{
this
.
$message
.
error
(
'数据异常,请联系管理员'
)
}
})
.
catch
(
e
=>
{
this
.
$message
.
error
(
e
.
message
)
})
.
finally
(()
=>
{})
},
/* 时间格式化(解决safari时间兼容问题); */
setTime
(
time
)
{
return
time
.
replace
(
/-/g
,
'/'
)
},
/* 开始考试 */
beginExam
(
flag
)
{
this
.
status
.
isStart
=
true
// this.loadAjax(flag)
},
/* 加载题库基本数据 */
loadExamInfo
()
{
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
''
,
spinner
:
''
,
background
:
'rgba(255, 255, 255, 0.9)'
})
cAction
.
Player
.
getExamInfo
(
this
.
cid
,
this
.
sid
)
.
then
(
_data
=>
{
this
.
exam
=
_data
this
.
exam
.
id
=
this
.
id
})
.
catch
(
e
=>
{
this
.
$message
.
error
(
e
.
message
)
})
.
finally
(()
=>
{
loading
.
close
()
/* 正在考试,考试结束 */
this
.
beginExam
()
})
},
/**
* 生命周期函数--监听页面加载
* @param flag 通过该字段 判别是点击进入考试 还是 自动调用
*/
loadAjax
(
flag
)
{
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
''
,
spinner
:
''
,
background
:
'rgba(255, 255, 255, 0.9)'
})
cAction
.
Player
.
getExamAnswer
(
this
.
cid
,
this
.
sid
,
this
.
id
,
{
paper_type
:
0
})
.
then
(
_data
=>
{
if
(
_data
.
code
===
8001
)
{
console
.
log
(
'没有考试内容,认为是第一次答题,并且在答题期间,所以显示考试开始页面'
)
if
(
!
flag
)
{
this
.
status
.
isStart
=
false
}
}
else
{
// this.exam.id = _data.id
this
.
exam
.
title
=
_data
.
title
this
.
exam
.
type
=
_data
.
type
this
.
exam
.
score
=
_data
.
score
this
.
exam
.
submitted_time
=
_data
.
submitted_time
this
.
exam
.
isPublished
=
_data
.
isPublished
this
.
status
.
type
=
_data
.
type
this
.
status
.
isPublished
=
_data
.
isPublished
this
.
exam
.
examination
=
this
.
exam
.
examination
.
map
((
exam
,
index
)
=>
{
const
rawExam
=
_data
.
examination
[
index
]
if
(
!
rawExam
)
{
return
exam
}
for
(
let
i
=
0
;
i
<
exam
.
radioList
.
length
;
i
++
)
{
for
(
let
j
=
0
;
j
<
rawExam
.
radioList
.
length
;
j
++
)
{
if
(
rawExam
.
radioList
[
j
].
id
===
exam
.
radioList
[
i
].
id
)
{
for
(
const
k
in
rawExam
.
radioList
[
j
])
{
exam
.
radioList
[
i
][
k
]
=
rawExam
.
radioList
[
j
][
k
]
}
}
}
}
for
(
let
i
=
0
;
i
<
exam
.
checkboxList
.
length
;
i
++
)
{
for
(
let
j
=
0
;
j
<
rawExam
.
checkboxList
.
length
;
j
++
)
{
if
(
rawExam
.
checkboxList
[
j
].
id
===
exam
.
checkboxList
[
i
].
id
)
{
for
(
const
k
in
rawExam
.
checkboxList
[
j
])
{
exam
.
checkboxList
[
i
][
k
]
=
rawExam
.
checkboxList
[
j
][
k
]
}
}
}
}
for
(
let
i
=
0
;
i
<
exam
.
shortAnswerList
.
length
;
i
++
)
{
for
(
let
j
=
0
;
j
<
rawExam
.
shortAnswerList
.
length
;
j
++
)
{
if
(
rawExam
.
shortAnswerList
[
j
].
id
===
exam
.
shortAnswerList
[
i
].
id
)
{
for
(
const
k
in
rawExam
.
shortAnswerList
[
j
])
{
exam
.
shortAnswerList
[
i
][
k
]
=
rawExam
.
shortAnswerList
[
j
][
k
]
}
}
}
}
return
exam
})
}
})
.
catch
(
e
=>
{
this
.
$message
.
error
(
e
.
message
)
})
.
finally
(()
=>
{
// console.log(this.exam.type, this.exam.isPublished)
loading
.
close
()
if
(
this
.
status
.
isStart
&&
this
.
exam
.
type
!==
1
&&
this
.
exam
.
type
!==
2
)
{
/* 滚动到头部 */
document
.
querySelector
(
'.play-paper'
).
scrollTop
=
0
}
})
},
/**
* 提交试题
*/
submitExam
(
e
)
{
if
(
!
e
.
submitType
&&
e
.
currentTarget
.
dataset
.
submit
)
{
this
.
$message
.
error
(
'已做过,不能再提交'
)
return
}
const
body
=
{
answers
:
[],
type
:
!
e
.
submitType
?
1
:
0
,
paper_type
:
0
}
// type: 0 缓存;type: 1 提交
for
(
let
k
=
0
;
k
<
this
.
exam
.
examination
.
length
;
k
++
)
{
const
exam
=
this
.
exam
.
examination
[
k
]
const
radioList
=
[]
for
(
let
i
=
0
;
i
<
exam
.
radioList
.
length
;
i
++
)
{
const
tmp
=
exam
.
radioList
[
i
]
if
(
!
tmp
.
user_answer
&&
!
e
.
submitType
)
{
this
.
$message
.
error
(
'还有单选题未做,不能提交'
)
return
}
radioList
.
push
({
id
:
tmp
.
id
,
user_answer
:
tmp
.
user_answer
})
}
const
checkboxList
=
[]
for
(
let
i
=
0
;
i
<
exam
.
checkboxList
.
length
;
i
++
)
{
const
tmp
=
exam
.
checkboxList
[
i
]
if
(
!
tmp
.
user_answer
.
length
&&
!
e
.
submitType
)
{
this
.
$message
.
error
(
'还有多选题未做,不能提交'
)
return
}
checkboxList
.
push
({
id
:
tmp
.
id
,
user_answer
:
tmp
.
user_answer
})
}
const
shortAnswerList
=
[]
for
(
let
i
=
0
;
i
<
exam
.
shortAnswerList
.
length
;
i
++
)
{
const
tmp
=
exam
.
shortAnswerList
[
i
]
if
(
!
tmp
.
user_answer
&&
!
e
.
submitType
)
{
this
.
$message
.
error
(
'还有简答题未做,不能提交'
)
return
}
shortAnswerList
.
push
({
id
:
tmp
.
id
,
user_answer
:
Base64
.
encode
(
tmp
.
user_answer
),
attachments
:
tmp
.
attachments
})
}
body
.
answers
[
k
]
=
{
radioList
,
checkboxList
,
shortAnswerList
}
}
body
.
answers
=
JSON
.
stringify
(
body
.
answers
)
let
loading
=
null
if
(
!
e
.
submitType
)
{
loading
=
this
.
$loading
({
lock
:
true
,
text
:
''
,
spinner
:
''
,
background
:
'rgba(255, 255, 255, 0.9)'
})
}
cAction
.
Player
.
submitExam
(
this
.
cid
,
this
.
sid
,
this
.
exam
.
id
,
body
)
.
then
(
_res
=>
{
if
(
e
.
submitType
)
{
// this.$message.success('暂存成功')
console
.
log
(
'暂存成功'
)
return
}
if
(
_res
.
code
===
200
)
{
this
.
$message
.
success
(
'考试答卷提交成功'
)
// this.exam.type = 1
this
.
init
()
console
.
log
(
111
,
'this.loadAjax()'
)
}
else
{
this
.
$message
.
error
(
_res
.
data
.
error
)
}
})
.
catch
(
e
=>
{
this
.
$message
.
error
(
e
.
message
)
})
.
finally
(()
=>
{
if
(
!
e
.
submitType
)
{
loading
.
close
()
}
})
},
_SubmitMouseLeftDown
()
{
const
_fn1
=
this
.
repeatExam
.
bind
(
this
,
false
)
document
.
addEventListener
(
'keydown'
,
_fn1
,
false
)
const
_fn3
=
function
()
{
document
.
removeEventListener
(
'keydown'
,
_fn1
)
document
.
removeEventListener
(
'mouseup'
,
_fn3
)
}
document
.
addEventListener
(
'mouseup'
,
_fn3
,
false
)
},
/**
* 重做
*/
repeatExam
(
e
,
flag
)
{
let
_flag
=
flag
/* 字母 f */
if
(
e
.
keyCode
===
70
)
{
_flag
=
true
}
if
(
!
_flag
)
{
return
}
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
''
,
spinner
:
''
,
background
:
'rgba(255, 255, 255, 0.9)'
})
cAction
.
chapterAction
.
getExamDetail
(
this
.
sid
,
this
.
cid
,
this
.
id
)
.
then
(
_data
=>
{
this
.
exam
=
{}
})
.
catch
(
e
=>
{
this
.
$message
.
error
(
e
.
message
)
})
.
finally
(()
=>
{
loading
.
close
()
})
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.play
{
.exam
{
padding
:
0
;
}
.exam
.topic
{
display
:
inline-block
;
margin-bottom
:
0
.1rem
;
}
.exam
.topic
.tit
{
margin
:
0
auto
;
padding
:
0
0
.2rem
;
text-align
:
center
;
font-size
:
0
.24rem
;
color
:
#313131
;
background
:
#fff
;
box-sizing
:
border-box
;
-webkit-box-sizing
:
border-box
;
}
.exam
.topic
.cur
{
text-align
:
center
;
font-size
:
0
.18rem
;
color
:
#313131
;
line-height
:
0
.4rem
;
}
/* 循环 所有选择题 */
.exam
.q-group
{
padding
:
0
.1rem
0
.1rem
;
border-bottom
:
1px
solid
#c9c9c9
7a
;
overflow
:
hidden
;
}
.exam
.q-group
.q-num
{
float
:
left
;
margin-right
:
0
.1rem
;
font-size
:
0
.16rem
;
color
:
#676a6c
;
}
.exam
.q-group
.q-title
{
float
:
left
;
width
:
90%
;
font-size
:
0
.16rem
;
color
:
#676a6c
;
text-align
:
justify
;
}
.exam
.q-group
.q-type
{
float
:
right
;
font-size
:
0
.16rem
;
color
:
#676a6c
;
}
.exam
.q-group
.radio-group
{
float
:
left
;
margin-top
:
0
.1rem
;
width
:
100%
;
}
.exam
.q-group
.radio-group
.radio
{
display
:
block
;
font-size
:
0
.18rem
;
color
:
#3f3b3a
;
line-height
:
0
.3rem
;
margin-bottom
:
0
.1rem
;
}
.exam
.q-group
.checkbox-group
{
float
:
left
;
margin-top
:
0
.1rem
;
width
:
100%
;
}
.exam
.q-group
.checkbox-group
.checkbox
{
display
:
block
;
font-size
:
0
.18rem
;
color
:
#3f3b3a
;
line-height
:
0
.3rem
;
margin-bottom
:
0
.1rem
;
}
.exam
.q-group
.radio-group
.radio.error
,
.exam
.q-group
.checkbox-group
.checkbox.error
{
color
:
#d80000
;
}
.exam
.q-group
.radio-group
.radio.success
,
.exam
.q-group
.checkbox-group
.checkbox.success
{
color
:
#090
;
}
.exam
.q-group
.result
{
float
:
right
;
font-size
:
0
.18rem
;
color
:
#3f3b3a
;
margin-right
:
0
;
}
.exam
.q-group
.result
.stu
{
display
:
inline-block
;
}
.exam
.q-group
.result
.stu.error
{
color
:
#d80000
;
}
.exam
.q-group
.result
.stu.success
{
color
:
#090
;
}
.exam
.q-group
:last-child
{
border-bottom
:
none
;
}
.exam
.btn
{
margin
:
0
.2rem
auto
;
width
:
60%
;
height
:
0
.5rem
;
line-height
:
0
.5rem
;
font-size
:
0
.16rem
;
text-align
:
center
;
font-weight
:
300
;
color
:
#fff
;
border-radius
:
0
.1rem
;
background
:
#b49441
;
cursor
:
pointer
;
}
.exam
.btn.on
{
opacity
:
0
.5
;
}
.exam
.care
{
font-size
:
0
.16rem
;
color
:
#d80000
;
text-align
:
center
;
}
.exam
.q-sa-title
{
float
:
left
;
width
:
100%
;
font-size
:
0
.16rem
;
color
:
#676a6c
;
text-align
:
justify
;
}
}
.no-exam
{
font-size
:
0
.24rem
;
line-height
:
19
;
text-align
:
center
;
}
</
style
>
client/src/pages/player/exam/exam.vue
浏览文件 @
1eb19f81
...
...
@@ -13,22 +13,7 @@
<template
v-if=
"status.type === 2 && status.isPublished === 1"
>
<template
v-if=
"exam.score.total !== undefined"
>
<div
style=
"font-size: 18px;"
>
得分:单选:
{{
exam
.
score
.
radio
}}
分,多选:
{{
exam
.
score
.
checkbox
}}
分,简答:
{{
exam
.
score
.
shortAnswer
}}
分,总分:
{{
exam
.
score
.
total
}}
分
</div>
</
template
>
<
template
v-if=
"exam.shortAnswerList.length"
>
<template
v-for=
"(item, index) in exam.shortAnswerList"
>
<template
v-if=
"item.check_comment"
>
<div
style=
"font-size: 18px; margin-top: 10px;"
:key=
"index"
>
<div>
简答题
{{
index
+
1
}}
</div>
<div>
老师评语:
<div
style=
"display: inline-block"
v-html=
"item.check_comment || ''"
></div>
</div>
</div>
</
template
>
</template>
<div
style=
"font-size: 18px;"
>
总分:
{{
exam
.
score
.
total
}}
分
</div>
</
template
>
</template>
<
template
v-else-if=
"status.type === 0"
>
...
...
@@ -53,22 +38,7 @@
<!--
<div
class=
'tit'
>
{{
exam
.
title
}}
</div>
-->
<template
v-if=
"exam.type === 2 && exam.isPublished === 1"
>
<template
v-if=
"exam.score.total !== undefined"
>
<div
style=
"font-size: 18px;"
>
得分:单选:
{{
exam
.
score
.
radio
}}
分,多选:
{{
exam
.
score
.
checkbox
}}
分,简答:
{{
exam
.
score
.
shortAnswer
}}
分,总分:
{{
exam
.
score
.
total
}}
分
</div>
</
template
>
<
template
v-if=
"exam.shortAnswerList.length"
>
<template
v-for=
"(item, index) in exam.shortAnswerList"
>
<template
v-if=
"item.check_comment"
>
<div
style=
"font-size: 18px; margin-top: 10px;"
:key=
"index"
>
<div>
简答题
{{
index
+
1
}}
</div>
<div>
老师评语:
<div
style=
"display: inline-block"
v-html=
"item.check_comment || ''"
></div>
</div>
</div>
</
template
>
</template>
<div
style=
"font-size: 18px;"
>
总分:
{{
exam
.
score
.
total
}}
分
</div>
</
template
>
</template>
<
template
v-else-if=
"exam.type === 1 || exam.type === 2"
>
...
...
@@ -78,86 +48,87 @@
<!-- </div> -->
<
template
v-if=
"(exam.type !== 1 && exam.type !== 2)"
>
<div
style=
"text-align: center;"
>
考试截止时间为:
{{
status
.
terminateTime
}}
</div>
<!-- 单选题 -->
<template
v-if=
"exam.radioList.length"
>
<template
v-for=
"(item, index) in exam.radioList"
>
<div
v-bind:key=
"item.id"
class=
"q-group"
:data-index=
"index"
>
<div
class=
"q-num"
>
{{
index
+
1
}}
.
</div>
<div
class=
"q-title"
v-html=
"item.content"
></div>
<div
class=
"q-type"
>
(单选题)
</div>
<el-radio-group
class=
"radio-group"
v-model=
"item.user_answer"
>
<template
v-for=
"(item1, index1) in item.options"
>
<el-radio
v-bind:key=
"item1.id"
:label=
"item1.id"
:disabled=
"!!item.right_answer && !!exam.type"
:class=
"['radio', ((item.right_answer && !!exam.type) ? (item1.id === item.right_answer ? 'success' : 'error') : '')]"
>
{{
index1
|
getLetter
()
}}
.
{{
item1
.
option
}}
</el-radio>
<template
v-for=
"exam in exam.examination"
>
<!-- 单选题 -->
<template
v-if=
"exam.radioList.length"
>
<template
v-for=
"(item, index) in exam.radioList"
>
<div
v-bind:key=
"item.id"
class=
"q-group"
:data-index=
"index"
>
<div
class=
"q-num"
>
{{
index
+
1
}}
.
</div>
<div
class=
"q-title"
v-html=
"item.content"
></div>
<div
class=
"q-type"
>
(单选题)
</div>
<el-radio-group
class=
"radio-group"
v-model=
"item.user_answer"
>
<template
v-for=
"(item1, index1) in item.options"
>
<el-radio
v-bind:key=
"item1.id"
:label=
"item1.id"
:disabled=
"!!item.right_answer && !!exam.type"
:class=
"['radio', ((item.right_answer && !!exam.type) ? (item1.id === item.right_answer ? 'success' : 'error') : '')]"
>
{{
index1
|
getLetter
()
}}
.
{{
item1
.
option
}}
</el-radio>
</
template
>
</el-radio-group>
<
template
v-if=
"item.right_answer && !!exam.type"
>
<div
class=
"result"
>
学生答案:
<div
:class=
"['stu', (item.right_answer === item.user_answer ? 'success' : 'error')]"
>
{{
item
.
user_answer
|
getRadioAnswer
(
item
.
options
)
}}
</div>
正确答案:
{{
item
.
right_answer
|
getRadioAnswer
(
item
.
options
)
}}
</div>
</
template
>
</el-radio-group>
<
template
v-if=
"item.right_answer && !!exam.type"
>
<div
class=
"result"
>
学生答案:
<div
:class=
"['stu', (item.right_answer === item.user_answer ? 'success' : 'error')]"
>
{{
item
.
user_answer
|
getRadioAnswer
(
item
.
options
)
}}
</div>
正确答案:
{{
item
.
right_answer
|
getRadioAnswer
(
item
.
options
)
}}
</div>
</
template
>
</div>
</div>
</template>
</template>
</template>
<!-- 多选题 -->
<
template
v-if=
"exam.checkboxList.length"
>
<template
v-for=
"(item, index) in exam.checkboxList"
>
<div
v-bind:key=
"item.id"
class=
"q-group"
:data-index=
"index"
>
<div
class=
"q-num"
>
{{
exam
.
radioList
.
length
+
index
+
1
}}
.
</div>
<div
class=
"q-title"
v-html=
"item.content"
></div>
<div
class=
"q-type"
>
(多选题)
</div>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"item.user_answer"
>
<template
v-for=
"(item1, index1) in item.options"
>
<el-checkbox
v-bind:key=
"item1.id"
:label=
"item1.id"
:disabled=
"!!item.right_answer.length && !!exam.type"
:class=
"['checkbox', ((item.right_answer.length && !!exam.type) ? (isCheckboxChecked(item1.id, item.right_answer) ? 'success' : 'error') : '')]"
>
{{
index1
|
getLetter
()
}}
.
{{
item1
.
option
}}
</el-checkbox>
<!-- 多选题 -->
<
template
v-if=
"exam.checkboxList.length"
>
<template
v-for=
"(item, index) in exam.checkboxList"
>
<div
v-bind:key=
"item.id"
class=
"q-group"
:data-index=
"index"
>
<div
class=
"q-num"
>
{{
exam
.
radioList
.
length
+
index
+
1
}}
.
</div>
<div
class=
"q-title"
v-html=
"item.content"
></div>
<div
class=
"q-type"
>
(多选题)
</div>
<el-checkbox-group
class=
"checkbox-group"
v-model=
"item.user_answer"
>
<template
v-for=
"(item1, index1) in item.options"
>
<el-checkbox
v-bind:key=
"item1.id"
:label=
"item1.id"
:disabled=
"!!item.right_answer.length && !!exam.type"
:class=
"['checkbox', ((item.right_answer.length && !!exam.type) ? (isCheckboxChecked(item1.id, item.right_answer) ? 'success' : 'error') : '')]"
>
{{
index1
|
getLetter
()
}}
.
{{
item1
.
option
}}
</el-checkbox>
</
template
>
</el-checkbox-group>
<
template
v-if=
"item.right_answer.length && !!exam.type"
>
<div
class=
"result"
>
学生答案:
<div
:class=
"['stu', ((item.right_answer.length && isCheckboxRight(item.user_answer, item.right_answer)) ? 'success' : 'error')]"
>
{{
item
.
user_answer
|
getCheckboxAnswer
(
item
.
options
)
}}
</div>
正确答案:
{{
item
.
right_answer
|
getCheckboxAnswer
(
item
.
options
)
}}
</div>
</
template
>
</el-checkbox-group>
<
template
v-if=
"item.right_answer.length && !!exam.type"
>
<div
class=
"result"
>
学生答案:
<div
:class=
"['stu', ((item.right_answer.length && isCheckboxRight(item.user_answer, item.right_answer)) ? 'success' : 'error')]"
>
{{
item
.
user_answer
|
getCheckboxAnswer
(
item
.
options
)
}}
</div>
正确答案:
{{
item
.
right_answer
|
getCheckboxAnswer
(
item
.
options
)
}}
</div>
</
template
>
</div>
</div>
</template>
</template>
</template
>
<!-- 简答题 --
>
<
template
v-if=
"exam.shortAnswerList.length
"
>
<template
v-for=
"(item, index) in exam.shortAnswerList
"
>
<div
class=
"q-group"
:key=
"index"
>
<div
class=
"q-sa-title"
>
{{
exam
.
radioList
.
length
+
exam
.
checkboxList
.
length
+
index
+
1
}}
.
简答题
</div>
<div
class=
"edit_html"
v-html=
"item.content || ''"
></div
>
<textarea
:id=
"('editor-exam' + index)"
v-model=
"item.user_answer"
></textarea
>
<div
style=
"height: 10px;"
></div
>
<!-- 利用key值自动更新组件 -->
<component
:is=
"item.upload.type
"
v-bind:key=
"item.upload.id + new Date().getTime()
"
:item=
"item.upload
"
:formData=
"item
"
:isUpload=
"!exam.type"
></component
>
</
div
>
<!-- 简答题 --
>
<
template
v-if=
"exam.shortAnswerList.length"
>
<template
v-for=
"(item, index) in exam.shortAnswerList
"
>
<div
class=
"q-group"
:key=
"index
"
>
<div
class=
"q-sa-title"
>
{{
exam
.
radioList
.
length
+
exam
.
checkboxList
.
length
+
index
+
1
}}
.
简答题
</div>
<div
class=
"edit_html"
v-html=
"item.content || ''"
>
</div>
<v-editor
v-model=
"item.user_answer"
></v-editor
>
<div
style=
"height: 10px;"
></div
>
<!-- 利用key值自动更新组件 --
>
<component
:is=
"item.upload.type"
v-bind:key=
"item.upload.id + new Date().getTime()
"
:item=
"item.upload
"
:formData=
"item
"
:isUpload=
"!exam.type
"
></component>
</div
>
</
template
>
</template>
</template>
<div
:class=
"['btn', (exam.type && 'on')]"
@
click=
"submitExam"
...
...
@@ -197,7 +168,7 @@
import
cAction
from
'@action'
import
Base64
from
'Base64'
import
CKEDITOR
from
'CKEDITOR
'
import
VEditor
from
'@/components/editor.vue
'
var
getLetter
=
val
=>
{
switch
(
val
)
{
...
...
@@ -236,6 +207,7 @@ export default {
cid
:
{
type
:
String
,
require
:
false
},
id
:
{
type
:
String
,
require
:
false
}
},
components
:
{
VEditor
},
filters
:
{
getLetter
:
getLetter
,
getRadioAnswer
:
(
val
,
arr
)
=>
{
...
...
@@ -262,131 +234,7 @@ export default {
data
()
{
return
{
_time
:
null
,
// 定时器,自动化提交
exam
:
{
// id: '1',
// title: '标题',
// type: 0, // 0: 暂存,可以继续答题;1: 提交,不能再继续答题(等待批改) 2: 已批改(这时候有分数)
// radioList: [
// {
// id: '6622309081933676544',
// content: '\u5047\u8bbe\u8d27\u5e01\u9700\u6c42\u4e3aL=ky-hr\uff0c\u8d27\u5e01\u4f9b\u7ed9\u589e\u52a010\u4ebf\u7f8e\u5143\u800c\u5176\u5b83\u6761\u4ef6\u4e0d\u53d8\uff0c\u5219\u4f1a\u4f7fLM \u66f2\u7ebf( )',
// options: [
// {
// id: '6622310260604403712',
// option: '\u53f3\u79fb10\u4ebf\u7f8e\u5143'
// },
// {
// id: '6622310260604403713',
// option: '\u53f3\u79fb k\u4e58\u4ee510\u4ebf\u7f8e\u5143'
// },
// {
// id: '6622310260604403714',
// option: '\u53f3\u79fb10\u4ebf\u7f8e\u5143\u9664\u4ee5k'
// },
// {
// id: '6622310260604403715',
// option: '\u53f3\u79fb k\u9664\u4ee510\u4ebf\u7f8e\u5143'
// }
// ],
// user_answer: '6622310260604403714',
// right_answer: '6622310260604403714',
// get_score: 30,
// score: 30
// }
// ],
// checkboxList: [
// {
// id: '6622310510798831616',
// content: '\u51ef\u6069\u65af\u5b8f\u89c2\u7ecf\u6d4e\u7406\u8bba\u7684\u4e3b\u8981\u524d\u63d0\u5305\u62ec\uff08\uff09',
// options: [
// {
// id: '6622310872641437696',
// option: '\u8fb9\u9645\u6d88\u8d39\u503e\u5411\u9012\u51cf'
// },
// {
// id: '6622310872641437697',
// option: '\u8d44\u672c\u8fb9\u9645\u6548\u7387\u9012\u51cf'
// },
// {
// id: '6622310872641437698',
// option: '\u4e0d\u786e\u5b9a\u6027\u4e0e\u6d41\u52a8\u6027\u504f\u597d'
// },
// {
// id: '6622310872641437699',
// option: '\u540d\u4e49\u5de5\u8d44\u521a\u6027'
// }
// ],
// user_answer: [
// '6622310872641437697',
// '6622310872641437698',
// '6622310872641437699'
// ],
// right_answer: [
// '6622310872641437697',
// '6622310872641437698'
// ],
// get_score: 30,
// score: 30
// }
// ],
// shortAnswerList: [
// {
// id: '6622311487476072448',
// content: '\u8bba\u8ff01929\u5e74\u7f8e\u56fd\u4e3a\u4ec0\u4e48\u4f1a\u51fa\u73b0\u5927\u8427\u6761\u3002',
// user_answer: '2018\u5e74\u79ef\u6781\u7684\u8d22\u653f\u653f\u7b56\u5bf9\u4f9b\u7ed9\u6027\u7ed3\u6784\u6027\u6539\u9769\u6709\u4e00\u5b9a\u7684\u63a8\u52a8\u4f5c\u7528\u3002\u623f\u5730\u4ea7\u5e02\u573a\u5f97\u5230\u4e00\u5b9a\u7a0b\u5ea6\u6291\u5236\u3002\u7ecf\u6d4e\u53d1\u5c55\u5e73\u7a33\uff0c\u7ecf\u6d4e\u8fd0\u884c\u5728\u5408\u7406\u533a\u95f4\u3002\u964d\u7a0e\u4e3e\u52a8\u53d6\u5f97\u6210\u6548\uff0c\u5168\u5e74\u56fd\u5185\u589e\u503c\u7a0e\u3001\u4f01\u4e1a\u6240\u5f97\u7a0e\u3001\u4e2a\u4eba\u6240\u5f97\u7a0e\u540c\u6bd4\u5206\u522b\u589e\u957f9.1%\u300110%\u300115.9%\uff0c\u5206\u522b\u62c9\u9ad8\u5168\u56fd\u8d22\u653f\u6536\u5165\u589e\u5e453\u4e2a\u30011.9\u4e2a\u30011.1\u4e2a\u767e\u5206\u70b9\uff0c\u6709\u53d1\u6325\u51fa\u5b8f\u89c2\u8c03\u63a7\u7684\u4f5c\u7528\u3002\u4ece2018\u5e74\u8d27\u5e01\u653f\u7b56\u6574\u4f53\u6765\u770b\uff0c\u8f83\u597d\u5730\u628a\u63e1\u4e86\u652f\u6301\u5b9e\u4f53\u7ecf\u6d4e\u548c\u517c\u987e\u5185\u5916\u90e8\u5747\u8861\u4e4b\u95f4\u7684\u5e73\u8861\uff0c\u53d6\u5f97\u4e86\u79ef\u6781\u6210\u6548\uff0c\u4e5f\u5f88\u597d\u5730\u9632\u8303\u4e86\u91d1\u878d\u98ce\u9669\u30022018\u5e74\u603b\u4f53\u4fdd\u6301\u4e86\u9002\u5b9c\u7684\u8d27\u5e01\u91d1\u878d\u73af\u5883\uff0c\u65e0\u8bba\u662f\u5404\u9879\u8d37\u6b3e\u8fd8\u662f\u666e\u60e0\u53e3\u5f84\u5c0f\u5fae\u8d37\u6b3e\u90fd\u540c\u6bd4\u5927\u5e45\u591a\u589e\uff0cM2\u548c\u793e\u4f1a\u878d\u8d44\u89c4\u6a21\u5b58\u91cf\u540c\u6bd4\u589e\u901f\u4e0e\u540d\u4e49GDP\u589e\u901f\u57fa\u672c\u5339\u914d\uff0c\u6709\u529b\u4fc3\u8fdb\u4e86\u6211\u56fd\u7ecf\u6d4e\u6301\u7eed\u5065\u5eb7\u53d1\u5c55\u3002\u6211\u56fd\u5b9e\u65bd\u79ef\u6781\u7684\u8d22\u653f\u653f\u7b56\u548c\u7a33\u5065\u7684\u8d27\u5e01\u653f\u7b56\uff0c\u4e00\u65b9\u9762\u80fd\u4ee5\u653f\u7b56\u7684\u7a33\u5b9a\u6765\u5e94\u5bf9\u5916\u90e8\u73af\u5883\u7684\u4e0d\u7a33\u5b9a\uff0c\u5728\u9762\u5bf9\u4e16\u754c\u73af\u5883\u53d8\u5316\u65f6\u80fd\u968f\u65f6\u628a\u63e1\u4f4f\u6218\u7565\u4e3b\u52a8\u6027\uff1b\u540c\u65f6\u80fd\u591f\u79ef\u6781\u4fc3\u8fdb\u6211\u56fd\u4f9b\u7ed9\u4fa7\u7ed3\u6784\u6027\u6539\u9769\u8fdb\u7a0b\uff0c\u652f\u6301\u89e3\u51b3\u7ecf\u6d4e\u53d1\u5c55\u4e2d\u7684\u6df1\u5c42\u6b21\u7ed3\u6784\u6027\u95ee\u9898\uff0c\u63d0\u5347\u6211\u56fd\u7ecf\u6d4e\u53d1\u5c55\u8d28\u91cf\u548c\u6548\u7387\u3002\u5b8f\u89c2\u653f\u7b56\u7684\u5b9e\u65bd\u4e5f\u5de9\u56fa\u4e86\u6211\u56fd\u5e73\u7a33\u53d1\u5c55\u7684\u7ecf\u6d4e\u57fa\u7840\uff0c\u4e3a\u5168\u9762\u5efa\u6210\u5c0f\u5eb7\u793e\u4f1a\u63d0\u4f9b\u4e86\u575a\u5f3a\u6709\u529b\u7684\u7ecf\u6d4e\u63aa\u65bd\u4fdd\u969c\u3002',
// check_comment: '\u5361\u5c3c\u66fc\u8ba4\u4e3a\u4eba\u7684\u5927\u8111\u5b58\u5728\u4e24\u4e2a\u7cfb\u7edf\uff0c\u4e24\u4e2a\u7cfb\u7edf\u5206\u522b\u6709\u5feb\u4e0e\u6162\u4e24\u79cd\u4f5c\u51b3\u5b9a\u7684\u65b9\u5f0f\u611f\u6027\u8ba4\u8bc6\u548c\u7406\u6027\u8ba4\u8bc6\u662f\u540c\u4e00\u8ba4\u8bc6\u8fc7\u7a0b\u7684\u4e24\u4e2a\u9636\u6bb5\u3002\u4e8c\u8005\u65e2\u76f8\u4e92\u5bf9\u7acb\u53c8\u76f8\u4e92\u7edf\u4e00\u3002\u6211\u4eec\u79f0\u4f5c\u7cfb\u7edf1\u548c\u7cfb\u7edf2\uff0c\u4ed6\u7684\u7406\u8bba\u4e0e\u6211\u4eec\u719f\u77e5\u7684\u611f\u6027\u8ba4\u8bc6\u548c\u7406\u6027\u8ba4\u8bc6\u7684\u8fc7\u7a0b\u7684\u4e24\u4e2a\u9636\u6bb5\u6709\u5f88\u76f8\u4f3c\u7684\u7406\u8bba\u6216\u8005\u8bf4\u662f\u4e0d\u662f\u5c5e\u4e8e\u540c\u4e00\u4e2a\u7406\u8bba\u57fa\u7840\u3002',
// get_score: 30,
// score: 40,
// attachments: [],
// upload: {
// type: 'upload-form',
// label: '附件上传:',
// model: 'attachments',
// action: webConf.apiBaseURL + '/util/upload-file',
// data: {
// special: 'exam'
// },
// attrs: {
// multiple: true,
// headers: {
// 'tenant': 'sofia'
// }
// },
// html: `
//
<
div
style
=
"color: #72818c; font-size: 14px;"
>
//
<
p
style
=
"margin: 0;"
>
支持
doc
,
docx
,
ppt
,
xls
,
txt
,
rar
,
zip
,
pdf
,
jpg
,
pic
,
png
格式的文件,文件小于
30
M
。
<
/p
>
//
<
/div
>
// `
// }
// },
// {
// id: '6622311487476072448',
// content: '\u8bba\u8ff01929\u5e74\u7f8e\u56fd\u4e3a\u4ec0\u4e48\u4f1a\u51fa\u73b0\u5927\u8427\u6761\u3002',
// user_answer: '2018\u5e74\u79ef\u6781\u7684\u8d22\u653f\u653f\u7b56\u5bf9\u4f9b\u7ed9\u6027\u7ed3\u6784\u6027\u6539\u9769\u6709\u4e00\u5b9a\u7684\u63a8\u52a8\u4f5c\u7528\u3002\u623f\u5730\u4ea7\u5e02\u573a\u5f97\u5230\u4e00\u5b9a\u7a0b\u5ea6\u6291\u5236\u3002\u7ecf\u6d4e\u53d1\u5c55\u5e73\u7a33\uff0c\u7ecf\u6d4e\u8fd0\u884c\u5728\u5408\u7406\u533a\u95f4\u3002\u964d\u7a0e\u4e3e\u52a8\u53d6\u5f97\u6210\u6548\uff0c\u5168\u5e74\u56fd\u5185\u589e\u503c\u7a0e\u3001\u4f01\u4e1a\u6240\u5f97\u7a0e\u3001\u4e2a\u4eba\u6240\u5f97\u7a0e\u540c\u6bd4\u5206\u522b\u589e\u957f9.1%\u300110%\u300115.9%\uff0c\u5206\u522b\u62c9\u9ad8\u5168\u56fd\u8d22\u653f\u6536\u5165\u589e\u5e453\u4e2a\u30011.9\u4e2a\u30011.1\u4e2a\u767e\u5206\u70b9\uff0c\u6709\u53d1\u6325\u51fa\u5b8f\u89c2\u8c03\u63a7\u7684\u4f5c\u7528\u3002\u4ece2018\u5e74\u8d27\u5e01\u653f\u7b56\u6574\u4f53\u6765\u770b\uff0c\u8f83\u597d\u5730\u628a\u63e1\u4e86\u652f\u6301\u5b9e\u4f53\u7ecf\u6d4e\u548c\u517c\u987e\u5185\u5916\u90e8\u5747\u8861\u4e4b\u95f4\u7684\u5e73\u8861\uff0c\u53d6\u5f97\u4e86\u79ef\u6781\u6210\u6548\uff0c\u4e5f\u5f88\u597d\u5730\u9632\u8303\u4e86\u91d1\u878d\u98ce\u9669\u30022018\u5e74\u603b\u4f53\u4fdd\u6301\u4e86\u9002\u5b9c\u7684\u8d27\u5e01\u91d1\u878d\u73af\u5883\uff0c\u65e0\u8bba\u662f\u5404\u9879\u8d37\u6b3e\u8fd8\u662f\u666e\u60e0\u53e3\u5f84\u5c0f\u5fae\u8d37\u6b3e\u90fd\u540c\u6bd4\u5927\u5e45\u591a\u589e\uff0cM2\u548c\u793e\u4f1a\u878d\u8d44\u89c4\u6a21\u5b58\u91cf\u540c\u6bd4\u589e\u901f\u4e0e\u540d\u4e49GDP\u589e\u901f\u57fa\u672c\u5339\u914d\uff0c\u6709\u529b\u4fc3\u8fdb\u4e86\u6211\u56fd\u7ecf\u6d4e\u6301\u7eed\u5065\u5eb7\u53d1\u5c55\u3002\u6211\u56fd\u5b9e\u65bd\u79ef\u6781\u7684\u8d22\u653f\u653f\u7b56\u548c\u7a33\u5065\u7684\u8d27\u5e01\u653f\u7b56\uff0c\u4e00\u65b9\u9762\u80fd\u4ee5\u653f\u7b56\u7684\u7a33\u5b9a\u6765\u5e94\u5bf9\u5916\u90e8\u73af\u5883\u7684\u4e0d\u7a33\u5b9a\uff0c\u5728\u9762\u5bf9\u4e16\u754c\u73af\u5883\u53d8\u5316\u65f6\u80fd\u968f\u65f6\u628a\u63e1\u4f4f\u6218\u7565\u4e3b\u52a8\u6027\uff1b\u540c\u65f6\u80fd\u591f\u79ef\u6781\u4fc3\u8fdb\u6211\u56fd\u4f9b\u7ed9\u4fa7\u7ed3\u6784\u6027\u6539\u9769\u8fdb\u7a0b\uff0c\u652f\u6301\u89e3\u51b3\u7ecf\u6d4e\u53d1\u5c55\u4e2d\u7684\u6df1\u5c42\u6b21\u7ed3\u6784\u6027\u95ee\u9898\uff0c\u63d0\u5347\u6211\u56fd\u7ecf\u6d4e\u53d1\u5c55\u8d28\u91cf\u548c\u6548\u7387\u3002\u5b8f\u89c2\u653f\u7b56\u7684\u5b9e\u65bd\u4e5f\u5de9\u56fa\u4e86\u6211\u56fd\u5e73\u7a33\u53d1\u5c55\u7684\u7ecf\u6d4e\u57fa\u7840\uff0c\u4e3a\u5168\u9762\u5efa\u6210\u5c0f\u5eb7\u793e\u4f1a\u63d0\u4f9b\u4e86\u575a\u5f3a\u6709\u529b\u7684\u7ecf\u6d4e\u63aa\u65bd\u4fdd\u969c\u3002',
// check_comment: '\u5361\u5c3c\u66fc\u8ba4\u4e3a\u4eba\u7684\u5927\u8111\u5b58\u5728\u4e24\u4e2a\u7cfb\u7edf\uff0c\u4e24\u4e2a\u7cfb\u7edf\u5206\u522b\u6709\u5feb\u4e0e\u6162\u4e24\u79cd\u4f5c\u51b3\u5b9a\u7684\u65b9\u5f0f\u611f\u6027\u8ba4\u8bc6\u548c\u7406\u6027\u8ba4\u8bc6\u662f\u540c\u4e00\u8ba4\u8bc6\u8fc7\u7a0b\u7684\u4e24\u4e2a\u9636\u6bb5\u3002\u4e8c\u8005\u65e2\u76f8\u4e92\u5bf9\u7acb\u53c8\u76f8\u4e92\u7edf\u4e00\u3002\u6211\u4eec\u79f0\u4f5c\u7cfb\u7edf1\u548c\u7cfb\u7edf2\uff0c\u4ed6\u7684\u7406\u8bba\u4e0e\u6211\u4eec\u719f\u77e5\u7684\u611f\u6027\u8ba4\u8bc6\u548c\u7406\u6027\u8ba4\u8bc6\u7684\u8fc7\u7a0b\u7684\u4e24\u4e2a\u9636\u6bb5\u6709\u5f88\u76f8\u4f3c\u7684\u7406\u8bba\u6216\u8005\u8bf4\u662f\u4e0d\u662f\u5c5e\u4e8e\u540c\u4e00\u4e2a\u7406\u8bba\u57fa\u7840\u3002',
// get_score: 30,
// score: 40,
// attachments: [],
// upload: {
// type: 'upload-form',
// label: '附件上传:',
// model: 'attachments',
// action: webConf.apiBaseURL + '/util/upload-file',
// data: {
// special: 'exam'
// },
// attrs: {
// multiple: true
// },
// html: `
//
<
div
style
=
"color: #72818c; font-size: 14px;"
>
//
<
p
style
=
"margin: 0;"
>
支持
doc
,
docx
,
ppt
,
xls
,
txt
,
rar
,
zip
,
pdf
,
jpg
,
pic
,
png
格式的文件,文件小于
30
M
。
<
/p
>
//
<
/div
>
// `
// }
// }
// ]
},
exam
:
{},
status
:
{
isStart
:
false
,
startTime
:
''
,
...
...
@@ -443,100 +291,30 @@ export default {
}
return
false
},
initckeditor
()
{
if
(
!
this
.
exam
.
shortAnswerList
)
{
return
}
/* 删除所有 ckeditor 实例 */
const
instances
=
CKEDITOR
.
instances
for
(
const
name
in
instances
)
{
instances
[
name
].
destroy
()
}
for
(
let
i
=
0
;
i
<
this
.
exam
.
shortAnswerList
.
length
;
i
++
)
{
if
(
!
instances
[
'editor-exam'
+
i
])
{
CKEDITOR
.
replace
(
'editor-exam'
+
i
,
{
height
:
300
,
uiColor
:
'#eeeeee'
,
filebrowserImageUploadUrl
:
'/api/ckeditor/img/upload'
,
// resize_enabled: typeof this.props.resizable === 'boolean' ? this.props.resizable : true,
toolbar
:
[
// { name: 'document', items: [ 'Source', '-', 'Save', 'NewPage', 'Preview' ] },
{
name
:
'styles'
,
items
:
[
'Styles'
,
'Format'
,
'Font'
,
'FontSize'
]
},
{
name
:
'colors'
,
items
:
[
'TextColor'
,
'BGColor'
]
},
{
name
:
'tools'
,
items
:
[
'Maximize'
,
'ShowBlocks'
]
},
// { name: 'clipboard', items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
{
name
:
'editing'
,
items
:
[
'Find'
,
'Replace'
]
},
// { name: 'forms', items: [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ] },
'/'
,
{
name
:
'basicstyles'
,
items
:
[
'Bold'
,
'Italic'
,
'Underline'
,
'Strike'
,
'Subscript'
,
'Superscript'
,
'-'
,
'RemoveFormat'
]
},
{
name
:
'paragraph'
,
items
:
[
'NumberedList'
,
'BulletedList'
,
'-'
,
'Outdent'
,
'Indent'
,
'-'
,
'Blockquote'
,
'CreateDiv'
,
'-'
,
'JustifyLeft'
,
'JustifyCenter'
,
'JustifyRight'
,
'JustifyBlock'
,
'-'
,
'BidiLtr'
,
'BidiRtl'
]
},
{
name
:
'links'
,
items
:
[
'Link'
,
'Unlink'
,
'Anchor'
]
},
{
name
:
'insert'
,
items
:
[
'Image'
,
'Table'
,
'HorizontalRule'
]
}
]
})
}
this
.
exam
.
shortAnswerList
[
i
].
ckeditor
=
instances
[
'editor-exam'
+
i
]
}
},
init
()
{
this
.
loadExamStatus
()
this
.
loadExamInfo
()
if
(
this
.
_time
)
{
clearInterval
(
this
.
_time
)
this
.
_time
=
null
}
this
.
_time
=
setInterval
(()
=>
{
this
.
loadExamStatus
()
if
(
!
this
.
exam
.
type
&&
this
.
status
.
isStart
)
{
// console.log(11, '暂存')
this
.
submitExam
({
submitType
:
true
})
// 暂存, submitType: true 暂存;其他或不填为提交
}
/* 到时间 自动提交 */
if
(
!
this
.
exam
.
type
&&
this
.
status
.
isStart
&&
new
Date
(
this
.
status
.
terminateTime
).
getTime
()
-
new
Date
(
this
.
status
.
serverTime
).
getTime
()
<=
5000
)
{
this
.
submitExam
({
submitType
:
false
,
currentTarget
:
{
dataset
:
{}
}
})
}
},
3000
)
//
if (this._time) {
//
clearInterval(this._time)
//
this._time = null
//
}
//
this._time = setInterval(() => {
//
this.loadExamStatus()
//
if (!this.exam.type && this.status.isStart) {
//
// console.log(11, '暂存')
//
this.submitExam({ submitType: true }) // 暂存, submitType: true 暂存;其他或不填为提交
//
}
//
/* 到时间 自动提交 */
//
if (
//
!this.exam.type &&
//
this.status.isStart &&
//
new Date(this.status.terminateTime).getTime() -
//
new Date(this.status.serverTime).getTime()
<=
//
5000
//
) {
//
this.submitExam({ submitType: false, currentTarget: { dataset: {} } })
//
}
//
}, 3000)
},
/* 定时调用 - 考试状态 */
loadExamStatus
()
{
...
...
@@ -621,38 +399,42 @@ export default {
this
.
exam
.
isPublished
=
_data
.
isPublished
this
.
status
.
type
=
_data
.
type
this
.
status
.
isPublished
=
_data
.
isPublished
for
(
let
i
=
0
;
i
<
this
.
exam
.
radioList
.
length
;
i
++
)
{
for
(
let
j
=
0
;
j
<
_data
.
radioList
.
length
;
j
++
)
{
if
(
_data
.
radioList
[
j
].
id
===
this
.
exam
.
radioList
[
i
].
id
)
{
for
(
const
k
in
_data
.
radioList
[
j
])
{
this
.
exam
.
radioList
[
i
][
k
]
=
_data
.
radioList
[
j
][
k
]
this
.
exam
.
examination
=
this
.
exam
.
examination
.
map
((
exam
,
index
)
=>
{
const
rawExam
=
_data
.
examination
[
index
]
if
(
!
rawExam
)
{
return
exam
}
for
(
let
i
=
0
;
i
<
exam
.
radioList
.
length
;
i
++
)
{
for
(
let
j
=
0
;
j
<
rawExam
.
radioList
.
length
;
j
++
)
{
if
(
rawExam
.
radioList
[
j
].
id
===
exam
.
radioList
[
i
].
id
)
{
for
(
const
k
in
rawExam
.
radioList
[
j
])
{
exam
.
radioList
[
i
][
k
]
=
rawExam
.
radioList
[
j
][
k
]
}
}
}
}
}
for
(
let
i
=
0
;
i
<
this
.
exam
.
checkboxList
.
length
;
i
++
)
{
for
(
let
j
=
0
;
j
<
_data
.
checkboxList
.
length
;
j
++
)
{
if
(
_data
.
checkboxList
[
j
].
id
===
this
.
exam
.
checkboxList
[
i
].
id
)
{
for
(
const
k
in
_data
.
checkboxList
[
j
])
{
this
.
exam
.
checkboxList
[
i
][
k
]
=
_data
.
checkboxList
[
j
][
k
]
for
(
let
i
=
0
;
i
<
exam
.
checkboxList
.
length
;
i
++
)
{
for
(
let
j
=
0
;
j
<
rawExam
.
checkboxList
.
length
;
j
++
)
{
if
(
rawExam
.
checkboxList
[
j
].
id
===
exam
.
checkboxList
[
i
].
id
)
{
for
(
const
k
in
rawExam
.
checkboxList
[
j
]
)
{
exam
.
checkboxList
[
i
][
k
]
=
rawExam
.
checkboxList
[
j
][
k
]
}
}
}
}
}
for
(
let
i
=
0
;
i
<
this
.
exam
.
shortAnswerList
.
length
;
i
++
)
{
for
(
let
j
=
0
;
j
<
_data
.
shortAnswerList
.
length
;
j
++
)
{
if
(
_data
.
shortAnswerList
[
j
].
id
===
this
.
exam
.
shortAnswerList
[
i
].
id
)
{
for
(
const
k
in
_data
.
shortAnswerList
[
j
])
{
this
.
exam
.
shortAnswerList
[
i
][
k
]
=
_data
.
shortAnswerList
[
j
][
k
]
for
(
let
i
=
0
;
i
<
exam
.
shortAnswerList
.
length
;
i
++
)
{
for
(
let
j
=
0
;
j
<
rawExam
.
shortAnswerList
.
length
;
j
++
)
{
if
(
rawExam
.
shortAnswerList
[
j
].
id
===
exam
.
shortAnswerList
[
i
].
id
)
{
for
(
const
k
in
rawExam
.
shortAnswerList
[
j
])
{
exam
.
shortAnswerList
[
i
][
k
]
=
rawExam
.
shortAnswerList
[
j
][
k
]
}
}
}
}
}
return
exam
})
}
})
.
catch
(
e
=>
{
...
...
@@ -668,7 +450,6 @@ export default {
)
{
/* 滚动到头部 */
document
.
querySelector
(
'.play-paper'
).
scrollTop
=
0
this
.
initckeditor
()
}
})
},
...
...
@@ -680,44 +461,41 @@ export default {
this
.
$message
.
error
(
'已做过,不能再提交'
)
return
}
const
body
=
{
answers
:
{},
type
:
!
e
.
submitType
?
1
:
0
}
// type: 0 缓存;type: 1 提交
body
.
answers
.
radioList
=
[]
for
(
let
i
=
0
;
i
<
this
.
exam
.
radioList
.
length
;
i
++
)
{
const
tmp
=
this
.
exam
.
radioList
[
i
]
if
(
!
tmp
.
user_answer
&&
!
e
.
submitType
)
{
this
.
$message
.
error
(
'还有单选题未做,不能提交'
)
return
const
body
=
{
answers
:
[],
type
:
!
e
.
submitType
?
1
:
0
}
// type: 0 缓存;type: 1 提交
for
(
let
k
=
0
;
k
<
this
.
exam
.
examination
.
length
;
k
++
)
{
const
exam
=
this
.
exam
.
examination
[
k
]
const
radioList
=
[]
for
(
let
i
=
0
;
i
<
exam
.
radioList
.
length
;
i
++
)
{
const
tmp
=
exam
.
radioList
[
i
]
if
(
!
tmp
.
user_answer
&&
!
e
.
submitType
)
{
this
.
$message
.
error
(
'还有单选题未做,不能提交'
)
return
}
radioList
.
push
({
id
:
tmp
.
id
,
user_answer
:
tmp
.
user_answer
})
}
body
.
answers
.
radioList
.
push
({
id
:
tmp
.
id
,
user_answer
:
tmp
.
user_answer
})
}
body
.
answers
.
checkboxList
=
[]
for
(
let
i
=
0
;
i
<
this
.
exam
.
checkboxList
.
length
;
i
++
)
{
const
tmp
=
this
.
exam
.
checkboxList
[
i
]
if
(
!
tmp
.
user_answer
.
length
&&
!
e
.
submitType
)
{
this
.
$message
.
error
(
'还有多选题未做,不能提交'
)
return
const
checkboxList
=
[]
for
(
let
i
=
0
;
i
<
exam
.
checkboxList
.
length
;
i
++
)
{
const
tmp
=
exam
.
checkboxList
[
i
]
if
(
!
tmp
.
user_answer
.
length
&&
!
e
.
submitType
)
{
this
.
$message
.
error
(
'还有多选题未做,不能提交'
)
return
}
checkboxList
.
push
({
id
:
tmp
.
id
,
user_answer
:
tmp
.
user_answer
})
}
body
.
answers
.
checkboxList
.
push
({
id
:
tmp
.
id
,
user_answer
:
tmp
.
user_answer
})
}
body
.
answers
.
shortAnswerList
=
[]
for
(
let
i
=
0
;
i
<
this
.
exam
.
shortAnswerList
.
length
;
i
++
)
{
const
tmp
=
this
.
exam
.
shortAnswerList
[
i
]
tmp
.
user_answer
=
tmp
.
ckeditor
.
getData
()
if
(
!
tmp
.
user_answer
&&
!
e
.
submitType
)
{
this
.
$message
.
error
(
'还有简答题未做,不能提交'
)
return
const
shortAnswerList
=
[]
for
(
let
i
=
0
;
i
<
exam
.
shortAnswerList
.
length
;
i
++
)
{
const
tmp
=
exam
.
shortAnswerList
[
i
]
if
(
!
tmp
.
user_answer
&&
!
e
.
submitType
)
{
this
.
$message
.
error
(
'还有简答题未做,不能提交'
)
return
}
shortAnswerList
.
push
({
id
:
tmp
.
id
,
user_answer
:
Base64
.
encode
(
tmp
.
user_answer
),
attachments
:
tmp
.
attachments
})
}
body
.
answers
.
shortAnswerList
.
push
({
id
:
tmp
.
id
,
user_answer
:
Base64
.
encode
(
tmp
.
user_answer
),
attachments
:
tmp
.
attachments
})
body
.
answers
[
k
]
=
{
radioList
,
checkboxList
,
shortAnswerList
}
}
body
.
answers
=
JSON
.
stringify
(
body
.
answers
)
let
loading
=
null
...
...
client/src/pages/player/index.vue
浏览文件 @
1eb19f81
...
...
@@ -18,6 +18,7 @@
<div
class=
"play-content"
>
<router-view
ref=
"comTotalChapter"
:chapters=
"rawResponse.chapters"
:chapterName=
"curChapterName"
:chapterId=
"chapterId"
:courseInfo=
"courseInfo"
...
...
@@ -33,6 +34,7 @@
@
updateProgress=
"updateProgress"
@
changeSideBar=
"changeSideBar"
:key=
"id"
v-if=
"rawResponse.chapters"
></router-view>
</div>
</div>
...
...
@@ -151,7 +153,8 @@ export default {
chapterExam
:
{},
/* 章节视频 */
chapterVideo
:
{},
chapterPpts
:
[]
chapterPpts
:
[],
rawResponse
:
{}
// 接口返回的数据
}
},
beforeRouteUpdate
(
to
,
from
,
next
)
{
...
...
@@ -178,6 +181,7 @@ export default {
return
}
cAction
.
Player
.
getChapterList
(
to
.
params
.
cid
,
to
.
params
.
sid
,
to
.
params
.
id
).
then
(
json
=>
{
this
.
rawResponse
=
json
.
rawResponse
this
.
chapterList
=
json
.
json
this
.
courseInfo
=
json
.
courseInfo
this
.
courseWork
=
json
.
courseWork
...
...
@@ -219,6 +223,7 @@ export default {
return
}
cAction
.
Player
.
getChapterList
(
this
.
cid
,
this
.
sid
,
this
.
id
).
then
(
json
=>
{
this
.
rawResponse
=
json
.
rawResponse
this
.
chapterList
=
json
.
json
this
.
courseInfo
=
json
.
courseInfo
this
.
courseWork
=
json
.
courseWork
...
...
client/src/pages/player/rightSide/sideChapterList.vue
浏览文件 @
1eb19f81
...
...
@@ -80,6 +80,8 @@ export default {
return
}
this
.
$router
.
push
({
path
:
`/player/
${
sid
}
/
${
cid
}
/live/
${
_id
}
`
})
}
else
if
(
_course
.
chapters
[
i2
].
type
===
5
)
{
this
.
$router
.
push
({
path
:
`/player/
${
sid
}
/
${
cid
}
/chapter-exam2/
${
_course
.
chapters
[
i2
].
id
}
`
})
}
return
}
...
...
client/src/router/routes.js
浏览文件 @
1eb19f81
...
...
@@ -201,6 +201,12 @@ export default [
component
:
()
=>
import
(
'@/pages/player/chapterExam/chapterExam.vue'
),
props
:
true
},
{
path
:
'chapter-exam2/:id'
,
name
:
'chapterExam2'
,
component
:
()
=>
import
(
'@/pages/player/chapterExam/chapterExam2.vue'
),
props
:
true
},
{
path
:
'chapter-read/:id'
,
name
:
'chapterRead'
,
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论