Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
L
learn-online-pc
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
learn-online-pc
Commits
e90db39f
提交
e90db39f
authored
11月 29, 2022
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 章节考试支持多次考试
上级
fb4b247e
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
361 行增加
和
0 行删除
+361
-0
api.js
src/modules/viewer/api.js
+24
-0
layout.vue
src/modules/viewer/components/layout.vue
+3
-0
chapterMultipleExam.vue
src/modules/viewer/components/work/chapterMultipleExam.vue
+334
-0
没有找到文件。
src/modules/viewer/api.js
浏览文件 @
e90db39f
...
@@ -196,3 +196,27 @@ export function addChapterHomeworkComment(data) {
...
@@ -196,3 +196,27 @@ export function addChapterHomeworkComment(data) {
export
function
getChapterHomeworkComment
(
params
)
{
export
function
getChapterHomeworkComment
(
params
)
{
return
httpRequest
.
get
(
'/api/lms/v2/education/homeworks/fmcomment'
,
params
)
return
httpRequest
.
get
(
'/api/lms/v2/education/homeworks/fmcomment'
,
params
)
}
}
/**
* 获取章节多次考试信息
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
* @param {string} chapterId 章节ID
*/
export
function
getChapterMultipleExams
(
semesterId
,
courseId
,
chapterId
,
params
)
{
return
httpRequest
.
get
(
`/api/lms/v3/education/chapter-examination/
${
semesterId
}
/
${
courseId
}
/
${
chapterId
}
`
,
params
)
}
/**
* 提交章节多次考试信息
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
* @param {string} chapterId 章节ID
* @param {string} examId 试题ID
*/
export
function
submitChapterMultipleExams
(
semesterId
,
courseId
,
chapterId
,
examId
,
params
)
{
return
httpRequest
.
post
(
`/api/lms/v3/education/chapter-examination/
${
semesterId
}
/
${
courseId
}
/
${
chapterId
}
/
${
examId
}
`
,
params
)
}
src/modules/viewer/components/layout.vue
浏览文件 @
e90db39f
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
import
ChapterPlayer
from
'./player/chapterPlayer.vue'
// 章节视频
import
ChapterPlayer
from
'./player/chapterPlayer.vue'
// 章节视频
import
ChapterWork
from
'./work/index.vue'
// 章节作业
import
ChapterWork
from
'./work/index.vue'
// 章节作业
import
ChapterExam
from
'./work/chapterExam.vue'
// 章节考试
import
ChapterExam
from
'./work/chapterExam.vue'
// 章节考试
import
ChapterMultipleExam
from
'./work/ChapterMultipleExam.vue'
// 章节多次考试
import
ChapterRead
from
'./read/chapterRead.vue'
// 章节资料
import
ChapterRead
from
'./read/chapterRead.vue'
// 章节资料
import
ChapterLive
from
'./live/chapterLive.vue'
// 章节直播
import
ChapterLive
from
'./live/chapterLive.vue'
// 章节直播
import
CourseWork
from
'./work/courseWork.vue'
// 课程大作业
import
CourseWork
from
'./work/courseWork.vue'
// 课程大作业
...
@@ -20,6 +21,7 @@ export default {
...
@@ -20,6 +21,7 @@ export default {
ChapterWork
,
ChapterWork
,
ChapterRead
,
ChapterRead
,
ChapterExam
,
ChapterExam
,
ChapterMultipleExam
,
ChapterLive
,
ChapterLive
,
CourseWork
,
CourseWork
,
CourseRead
,
CourseRead
,
...
@@ -42,6 +44,7 @@ export default {
...
@@ -42,6 +44,7 @@ export default {
5
:
'ChapterLive'
,
// CC直播
5
:
'ChapterLive'
,
// CC直播
8
:
'ChapterLive'
,
// CC直播
8
:
'ChapterLive'
,
// CC直播
9
:
'ChapterExam'
,
// 考试
9
:
'ChapterExam'
,
// 考试
10
:
'ChapterMultipleExam'
,
// 多次考试
99
:
'CourseWork'
,
// 课程大作业
99
:
'CourseWork'
,
// 课程大作业
100
:
'CourseRead'
,
// 课程资料
100
:
'CourseRead'
,
// 课程资料
101
:
'CourseExam'
// 课程考试
101
:
'CourseExam'
// 课程考试
...
...
src/modules/viewer/components/work/chapterMultipleExam.vue
0 → 100644
浏览文件 @
e90db39f
<
template
>
<div
class=
"multiple-exam"
>
<div
class=
"multiple-exam-header"
v-if=
"exam.can_more"
>
<div
class=
"multiple-exam-header__history"
v-if=
"historyScoreText"
>
历史分数:
{{
historyScoreText
}}
</div>
<el-button
type=
"primary"
plain
:disabled=
"!exam.can_next"
@
click=
"onNextExam"
>
再次考试
</el-button>
<el-button
plain
:disabled=
"!maxScoreExamId"
@
click=
"onViewMaxScoreExam"
>
查看历史最高分数试卷
</el-button>
</div>
<container
:title=
"exam.title"
v-loading=
"loading"
>
<template
v-slot:header-aside
v-if=
"isExamComplete"
>
{{
$t
(
'viewerWork.fraction'
)
}}
:
{{
exam
.
score
.
total
}}{{
$t
(
'viewerWork.fractionUnit'
)
}}
</
template
>
<div
class=
"exam"
>
<!-- 批改中 -->
<div
class=
"no-exam"
v-if=
"isSubmited && !isExamComplete"
>
{{ $t('viewerWork.examSubmitedTips') }}
</div>
<!-- 考试试题 -->
<div
class=
"exam-form"
v-else
>
<el-form
:disabled=
"isSubmited"
>
<
template
v-for=
"items in questions"
>
<exam-item
v-for=
"(item, index) in items"
:index=
"index"
:type=
"item.type"
:data=
"item"
:value=
"item.formModel"
:disabled=
"isSubmited"
:key=
"item.id"
></exam-item>
</
template
>
<div
class=
"exam-buttons"
>
<el-tooltip
effect=
"dark"
:content=
"$t('viewerWork.examSubmitButtonTips')"
placement=
"right"
>
<el-button
type=
"primary"
:loading=
"submitLoading"
@
click=
"onSubmit"
>
{{ submitText }}
</el-button>
</el-tooltip>
</div>
</el-form>
</div>
</div>
</container>
</div>
</template>
<
script
>
import
Base64
from
'Base64'
// components
import
Container
from
'../common/container.vue'
import
ExamItem
from
'./examItem.vue'
// api
import
*
as
api
from
'../../api'
// 章节测试题
export
default
{
name
:
'ChapterMultipleExam'
,
components
:
{
Container
,
ExamItem
},
props
:
{
// 当前选中的章节
chapter
:
{
type
:
Object
,
default
:
()
=>
({})
},
// 课程详情接口返回的数据
data
:
{
type
:
Object
,
default
:
()
=>
({})
}
},
data
()
{
return
{
loading
:
false
,
exam
:
{},
questions
:
[],
autoSubmitTimer
:
null
,
// 自动提交定时器
submitLoading
:
false
,
messageInstance
:
null
}
},
computed
:
{
// 学期ID
sid
()
{
return
this
.
$route
.
params
.
sid
},
// 课程ID
cid
()
{
return
this
.
$route
.
params
.
cid
},
// 当前页面的ID
pid
()
{
return
this
.
$route
.
params
.
id
},
// 是否是考试时间
isExamTime
()
{
if
(
!
this
.
exam
.
dead_line
)
return
true
// 大于开始时间,小于结束时间
const
endTime
=
+
new
Date
(
this
.
exam
.
dead_line
)
const
currentTime
=
new
Date
().
getTime
()
return
currentTime
<
endTime
},
// 考试按钮
startExamButtonText
()
{
return
this
.
isExamTime
?
this
.
$t
(
'viewerWork.examStartButtonText'
)
:
this
.
$t
(
'viewerWork.examEndButtonText'
)
},
// 考试完成
isExamComplete
()
{
// 考试完成,批改完成并且公布成绩
return
this
.
exam
.
is_published
===
1
&&
this
.
exam
.
type
===
2
},
// 是否提交
isSubmited
()
{
return
this
.
exam
.
type
===
1
||
this
.
exam
.
type
===
2
},
// 提交按钮文本
submitText
()
{
return
this
.
isSubmited
?
this
.
$t
(
'viewerWork.submitedText'
)
:
this
.
$t
(
'viewerWork.submitText'
)
},
// 历史分数
historyScoreText
()
{
if
(
!
this
.
exam
.
history
)
return
return
this
.
exam
.
history
.
map
(
item
=>
item
.
score
).
join
(
'、'
)
},
// 最高分试卷ID
maxScoreExamId
()
{
if
(
!
this
.
exam
.
history
)
return
let
maxScore
=
0
let
maxItem
=
null
this
.
exam
.
history
.
forEach
(
item
=>
{
if
(
item
.
score
>=
maxScore
)
{
maxScore
=
item
.
score
maxItem
=
item
}
})
return
maxItem
?
maxItem
.
sheet_id
:
''
}
},
methods
:
{
// 组装问题数据
genQuestions
(
list
)
{
if
(
!
list
)
return
[]
return
list
.
map
(
data
=>
{
let
{
radioList
=
[],
checkboxList
=
[],
shortAnswerList
=
[],
judgeList
=
[]
}
=
data
// 单选
radioList
=
radioList
.
map
(
item
=>
{
const
temp
=
{
type
:
1
,
formModel
:
{
id
:
item
.
id
,
user_answer
:
item
.
user_answer
||
''
}
}
return
Object
.
assign
({},
item
,
temp
)
})
// 多选
checkboxList
=
checkboxList
.
map
(
item
=>
{
const
temp
=
{
type
:
2
,
formModel
:
{
id
:
item
.
id
,
user_answer
:
item
.
user_answer
||
[]
}
}
return
Object
.
assign
({},
item
,
temp
)
})
// 问答
shortAnswerList
=
shortAnswerList
.
map
(
item
=>
{
const
temp
=
{
type
:
3
,
formModel
:
{
id
:
item
.
id
,
user_answer
:
item
.
user_answer
?
Base64
.
decode
(
item
.
user_answer
.
replace
(
/ /gi
,
'+'
))
:
''
,
attachments
:
item
.
attachments
||
[]
}
}
return
Object
.
assign
({},
item
,
temp
)
})
// 判断题
judgeList
=
judgeList
.
map
(
item
=>
{
const
temp
=
{
type
:
4
,
formModel
:
{
id
:
item
.
id
,
user_answer
:
item
.
user_answer
||
''
}
}
return
Object
.
assign
({},
item
,
temp
)
})
return
[...
radioList
,
...
checkboxList
,
...
judgeList
,
...
shortAnswerList
]
})
},
// 获取考试结果
getExamResult
(
params
=
{})
{
this
.
loading
=
true
api
.
getChapterMultipleExams
(
this
.
sid
,
this
.
cid
,
this
.
pid
,
params
)
.
then
(
response
=>
{
// 设置问题列表数据
if
(
response
.
code
!==
8001
)
{
this
.
exam
=
response
this
.
questions
=
this
.
genQuestions
(
response
.
sheet
)
// 自动提交
!
this
.
isSubmited
&&
this
.
autoSubmit
()
}
})
.
finally
(()
=>
{
this
.
loading
=
false
})
},
// 再考一次
onNextExam
()
{
this
.
getExamResult
({
is_new
:
1
})
},
// 查看最高分试卷
onViewMaxScoreExam
()
{
this
.
getExamResult
({
sheet_id
:
this
.
maxScoreExamId
})
},
// 提交校验
checkSubmit
()
{
if
(
!
this
.
questions
.
length
)
{
return
}
for
(
let
i
=
0
;
i
<
this
.
questions
.
length
;
i
++
)
{
const
questions
=
this
.
questions
[
i
]
for
(
let
k
=
0
;
k
<
questions
.
length
;
k
++
)
{
const
value
=
questions
[
k
].
formModel
.
user_answer
if
(
Array
.
isArray
(
value
)
?
!
value
.
length
:
!
value
)
{
return
false
}
}
}
return
true
},
// 提交
onSubmit
()
{
// 校验
if
(
!
this
.
checkSubmit
())
{
this
.
messageInstance
&&
this
.
messageInstance
.
close
()
this
.
messageInstance
=
this
.
$message
.
error
(
this
.
$t
(
'viewerWork.examSubmitError'
))
return
}
// 提交的答案数据
const
answers
=
this
.
handleSubmitData
()
// 提交参数
const
params
=
{
answers
:
JSON
.
stringify
(
answers
),
type
:
1
}
// 请求接口
this
.
submitLoading
=
true
this
.
handleSubmitRequest
(
params
)
},
// 自动提交,10秒提交一次
autoSubmit
()
{
this
.
autoSubmitTimer
&&
clearInterval
(
this
.
autoSubmitTimer
)
this
.
autoSubmitTimer
=
setInterval
(()
=>
{
// 提交的答案数据
const
answers
=
this
.
handleSubmitData
()
const
params
=
{
answers
:
JSON
.
stringify
(
answers
),
type
:
0
}
// 请求接口
this
.
handleSubmitRequest
(
params
)
},
10000
)
},
// 处理请求接口答案数据
handleSubmitData
()
{
return
this
.
questions
.
map
(
questions
=>
{
return
questions
.
reduce
(
(
result
,
item
)
=>
{
// 单选题
if
(
item
.
type
===
1
)
{
result
.
radioList
.
push
(
item
.
formModel
)
}
// 多选题
if
(
item
.
type
===
2
)
{
result
.
checkboxList
.
push
(
item
.
formModel
)
}
// 简答题
if
(
item
.
type
===
3
)
{
const
formModel
=
Object
.
assign
({},
item
.
formModel
,
{
user_answer
:
Base64
.
encode
(
item
.
formModel
.
user_answer
)
})
result
.
shortAnswerList
.
push
(
formModel
)
}
// 判断题
if
(
item
.
type
===
4
)
{
result
.
judgeList
.
push
(
item
.
formModel
)
}
return
result
},
{
radioList
:
[],
checkboxList
:
[],
shortAnswerList
:
[],
judgeList
:
[]
}
)
})
},
// 请求提交接口
handleSubmitRequest
(
params
)
{
params
.
paper_type
=
0
api
.
submitChapterMultipleExams
(
this
.
sid
,
this
.
cid
,
this
.
pid
,
this
.
exam
.
id
,
params
)
.
then
(
response
=>
{
if
(
params
.
type
===
0
)
{
console
.
log
(
'暂存成功'
)
return
}
if
(
response
.
code
===
200
)
{
this
.
$message
.
success
(
this
.
$t
(
'viewerWork.examSubmitSuccess'
))
this
.
autoSubmitTimer
&&
clearInterval
(
this
.
autoSubmitTimer
)
this
.
getExamResult
()
}
else
{
this
.
$message
.
error
(
response
.
data
.
error
)
}
})
.
catch
(
error
=>
{
this
.
$message
.
error
(
error
.
message
)
})
.
finally
(()
=>
{
this
.
submitLoading
=
false
})
}
},
beforeMount
()
{
// 获取考试结果
this
.
getExamResult
()
},
destroyed
()
{
this
.
autoSubmitTimer
&&
clearInterval
(
this
.
autoSubmitTimer
)
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.multiple-exam
{
max-width
:
900px
;
margin
:
0
auto
;
}
.multiple-exam-header
{
display
:
flex
;
align-items
:
center
;
justify-content
:
flex-end
;
margin
:
40px
0
;
padding
:
40px
;
background-color
:
#f2f2f2
;
}
.multiple-exam-header__history
{
flex
:
1
;
}
.exam-buttons
{
padding
:
40px
0
;
text-align
:
center
;
.el-button
{
width
:
240px
;
margin
:
40px
auto
;
}
}
.no-exam
{
padding
:
100px
;
font-size
:
30px
;
text-align
:
center
;
}
.exam-welcome
{
padding
:
40px
;
line-height
:
30px
;
text-align
:
center
;
::v-deep
.el-button
{
margin-top
:
30px
;
}
}
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论