Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
L
learn-online-pc
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
learn-online-pc
Commits
5632ae6b
提交
5632ae6b
authored
6月 16, 2020
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
差异文件
merge...
上级
64bdc527
14316cb5
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
40 个修改的文件
包含
1085 行增加
和
483 行删除
+1085
-483
CourseAction.js
client/src/action/CourseAction.js
+28
-13
PlayerAction.js
client/src/action/PlayerAction.js
+87
-84
player_api.js
client/src/api/player_api.js
+1
-1
Before.js
client/src/components/beforeEnter/Before.js
+1
-1
editor.vue
client/src/components/editor.vue
+2
-2
index.html
client/src/index.html
+0
-1
api.js
client/src/modules/viewer/api.js
+39
-5
chapter.vue
client/src/modules/viewer/components/aside/chapter.vue
+28
-30
index.vue
client/src/modules/viewer/components/aside/index.vue
+9
-2
lecture.vue
client/src/modules/viewer/components/aside/lecture.vue
+2
-2
editor.vue
client/src/modules/viewer/components/common/editor.vue
+2
-3
fileList.vue
client/src/modules/viewer/components/common/fileList.vue
+0
-70
upload.vue
client/src/modules/viewer/components/common/upload.vue
+36
-10
layout.vue
client/src/modules/viewer/components/layout.vue
+4
-1
chapterLive.vue
client/src/modules/viewer/components/live/chapterLive.vue
+7
-4
chapterPlayer.vue
...nt/src/modules/viewer/components/player/chapterPlayer.vue
+150
-7
pptPlayer.vue
client/src/modules/viewer/components/player/pptPlayer.vue
+22
-15
videoPlayer.vue
client/src/modules/viewer/components/player/videoPlayer.vue
+21
-14
chapterRead.vue
client/src/modules/viewer/components/read/chapterRead.vue
+1
-1
courseRead.vue
client/src/modules/viewer/components/read/courseRead.vue
+1
-1
fileList.vue
client/src/modules/viewer/components/read/fileList.vue
+9
-2
chapterExam.vue
client/src/modules/viewer/components/work/chapterExam.vue
+0
-0
chapterTest.vue
client/src/modules/viewer/components/work/chapterTest.vue
+279
-0
chapterWork.vue
client/src/modules/viewer/components/work/chapterWork.vue
+124
-31
courseExam.vue
client/src/modules/viewer/components/work/courseExam.vue
+86
-114
courseWork.vue
client/src/modules/viewer/components/work/courseWork.vue
+24
-17
examItem.vue
client/src/modules/viewer/components/work/examItem.vue
+75
-20
index.vue
client/src/modules/viewer/components/work/index.vue
+3
-3
index.vue
client/src/modules/viewer/index.vue
+11
-3
hall.vue
client/src/pages/affairsHall/hall.vue
+4
-2
course.vue
client/src/pages/learn/course.vue
+1
-1
courseDetail.vue
client/src/pages/learn/courseDetail.vue
+0
-0
list.vue
client/src/pages/mobileLive/list.vue
+7
-11
chapterExam.vue
client/src/pages/player/chapterExam/chapterExam.vue
+1
-1
chapterExam2.vue
client/src/pages/player/chapterExam/chapterExam2.vue
+0
-0
exam.vue
client/src/pages/player/exam/exam.vue
+0
-0
index.vue
client/src/pages/player/index.vue
+6
-1
live.vue
client/src/pages/player/live/live.vue
+2
-2
sideChapterList.vue
client/src/pages/player/rightSide/sideChapterList.vue
+3
-5
routes.js
client/src/router/routes.js
+9
-3
没有找到文件。
client/src/action/CourseAction.js
浏览文件 @
5632ae6b
...
...
@@ -104,8 +104,22 @@ export default class CourseAction extends BaseACTION {
unit
:
item
.
lecturer_title
||
''
})
}
const
findChapter
=
function
(
id
,
list
)
{
for
(
const
item
of
list
)
{
if
(
item
.
resource_id
===
id
)
{
return
item
}
if
(
item
.
children
&&
item
.
children
.
length
)
{
const
found
=
findChapter
(
id
,
item
.
children
)
if
(
found
)
{
return
found
}
}
}
}
/* 课程内容 */
json
.
tabs1ChapterList
=
{
currentChapter
:
findChapter
(
cur
.
latest_play
,
data
.
chapters
),
currentChapterId
:
cur
.
latest_play
||
''
,
currentVideoProvider
:
cur
.
latest_play_type
||
'1'
,
course
:
cur
.
chapters
.
map
((
_
,
i
)
=>
{
...
...
@@ -127,9 +141,6 @@ export default class CourseAction extends BaseACTION {
case
0
:
str
=
'直播未开始'
;
break
case
1
:
str
=
'正在直播'
;
break
case
2
:
str
=
'直播结束'
;
break
case
101
:
str
=
'直播结束,视频剪辑中'
;
break
// 录制开始
case
102
:
str
=
'直播结束,视频剪辑中'
;
break
// 录制结束
case
103
:
str
=
'观看回放'
;
break
default
:
str
=
'直播未开始'
}
// 5分钟内显示“即将开始”,5~1小时内“N分钟后开始”,1~24小时内“N小时后开始”,1天以上“N天后开始”天就显示年月日
...
...
@@ -145,8 +156,8 @@ export default class CourseAction extends BaseACTION {
str
=
parseInt
(
time
/
(
24
*
60
*
60
))
+
'天后开始'
}
}
if
(
__
.
live
.
live_status
===
103
&&
__
.
live
.
enable_record
!==
undefined
&&
__
.
live
.
enable_record
!==
null
&&
!
__
.
live
.
enable_record
)
{
str
=
''
if
(
__
.
live
.
live_status
===
2
&&
__
.
live
.
enable_record
&&
__
.
live
.
record_url
)
{
str
=
'
观看回放
'
}
__
.
live
.
statusStr
=
str
}
...
...
@@ -173,35 +184,39 @@ export default class CourseAction extends BaseACTION {
title
:
'课程大作业'
,
isUp
:
true
,
chapters
:
[],
type
:
'course_work'
,
id
:
'course_work'
,
sid
:
sid
,
cid
:
cid
cid
:
cid
,
type
:
99
})
json
.
tabs1ChapterList
.
course
.
push
({
title
:
'课程资料'
,
isUp
:
true
,
chapters
:
[],
type
:
'course_info'
,
id
:
'course_info'
,
sid
:
sid
,
cid
:
cid
cid
:
cid
,
type
:
100
})
json
.
tabs1ChapterList
.
course
.
push
({
title
:
'教学评估'
,
isUp
:
true
,
chapters
:
[],
type
:
'teach_evaluation'
,
id
:
'teach_evaluation'
,
sid
:
sid
,
cid
:
cid
cid
:
cid
,
type
:
102
})
if
(
cur
.
course_examination
)
{
json
.
tabs1ChapterList
.
course
.
push
({
title
:
'课程考试'
,
isUp
:
true
,
chapters
:
[],
type
:
'
exam'
,
id
:
'course_
exam'
,
sid
:
sid
,
cid
:
cid
,
examId
:
cur
.
course_examination
examId
:
cur
.
course_examination
,
type
:
102
})
}
/* 课程考核 考核标准文案读取 */
...
...
client/src/action/PlayerAction.js
浏览文件 @
5632ae6b
...
...
@@ -93,9 +93,6 @@ export default class PlayerAction extends BaseACTION {
case
0
:
str
=
'直播未开始'
;
break
case
1
:
str
=
'正在直播'
;
break
case
2
:
str
=
'直播结束'
;
break
case
101
:
str
=
'直播结束,视频剪辑中'
;
break
// 录制开始
case
102
:
str
=
'直播结束,视频剪辑中'
;
break
// 录制结束
case
103
:
str
=
'观看回放'
;
break
default
:
str
=
'直播未开始'
}
// 5分钟内显示“即将开始”,5~1小时内“N分钟后开始”,1~24小时内“N小时后开始”,1天以上“N天后开始”天就显示年月日
...
...
@@ -111,8 +108,8 @@ export default class PlayerAction extends BaseACTION {
str
=
parseInt
(
time
/
(
24
*
60
*
60
))
+
'天后开始'
}
}
if
(
__
.
live
.
live_status
===
103
&&
__
.
live
.
enable_record
!==
undefined
&&
__
.
live
.
enable_record
!==
null
&&
!
__
.
live
.
enable_record
)
{
str
=
''
if
(
__
.
live
.
live_status
===
2
&&
__
.
live
.
enable_record
&&
__
.
live
.
record_url
)
{
str
=
'
观看回放
'
}
__
.
live
.
statusStr
=
str
}
...
...
@@ -122,6 +119,7 @@ export default class PlayerAction extends BaseACTION {
video_provider
:
(
__
.
video
&&
__
.
video
.
video_provider
)
||
''
,
time
:
(
__
.
video
&&
tools
.
convertTime
.
durationToTimeString
(
__
.
video
.
video_length
))
||
''
,
name
:
__
.
name
,
chapterId
:
__
.
id
,
// 需要chapterId 用来 提交 作业或问题 , 这个 chapterId 是 每个章节下 对应课程的 id,不是 章节id
type
:
__
.
type
,
work_type
:
(
__
.
homework
&&
__
.
homework
.
work_type
)
||
''
,
homework
:
_homework
,
...
...
@@ -164,7 +162,8 @@ export default class PlayerAction extends BaseACTION {
json
:
json
,
courseInfo
:
_res
.
files
||
[],
courseWork
:
_res
.
curriculum
||
{},
curJson
:
curJson
curJson
:
curJson
,
rawResponse
:
_res
}
})
}
...
...
@@ -291,51 +290,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 +344,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
浏览文件 @
5632ae6b
...
...
@@ -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/components/beforeEnter/Before.js
浏览文件 @
5632ae6b
...
...
@@ -14,7 +14,7 @@ export default class Before {
'studentHelp'
,
'teacherHelp'
]
this
.
isMobile
=
/android|iphone|ip
ad|ip
od/i
.
test
(
UA
)
this
.
isMobile
=
/android|iphone|ipod/i
.
test
(
UA
)
}
async
update
(
to
,
from
,
next
)
{
...
...
client/src/components/editor.vue
浏览文件 @
5632ae6b
...
...
@@ -85,8 +85,8 @@ export default {
]
}
if
(
this
.
readOnly
!==
null
)
{
config
.
readOnly
=
this
.
readOnly
if
(
this
.
disabled
!==
null
)
{
config
.
readOnly
=
this
.
disabled
}
const
editor
=
(
this
.
ckEditor
=
CKEDITOR
.
replace
(
...
...
client/src/index.html
浏览文件 @
5632ae6b
...
...
@@ -24,7 +24,6 @@
<script
type=
"text/javascript"
src=
"https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/common/runtime.js"
></script>
<!-- 直接引入aliyun播放插件 JS -->
<script
type=
"text/javascript"
charset=
"utf-8"
src=
"https://g.alicdn.com/de/prismplayer/2.8.8/aliplayer-min.js"
></script>
<script
type=
"text/javascript"
charset=
"utf-8"
src=
"https://player.alicdn.com/aliplayer/presentation/js/aliplayercomponents.min.js"
></script>
<!-- 解决iframe嵌套,CC视频在safri中打开免登陆兼容问题 -->
<script
src=
"//view.csslcloud.net/js/_fix_.js"
></script>
<script
src=
"//view.csslcloud.net/js/jquery-1.9.0.min.js"
type=
"text/javascript"
></script>
...
...
client/src/modules/viewer/api.js
浏览文件 @
5632ae6b
...
...
@@ -36,21 +36,54 @@ export function getChapterVideoAliyun(vid) {
}
/**
* 获取答题信息
* 获取章节视频播放进度
* @param {string} semesterId 学期ID
* @param {string} resourseId 章节的资源ID
* @param {Object} params
*/
export
function
getChapterVideoProgress
(
semesterId
,
resourseId
,
params
)
{
return
httpRequest
.
get
(
`/v2/education/video/
${
semesterId
}
/
${
resourseId
}
/device`
,
params
)
}
/**
* 更新章节视频播放进度
* @param {Object} params
*/
export
function
updateChapterVideoProgress
(
params
)
{
return
httpRequest
.
get
(
'/v2/analytics/upload-video'
,
params
)
}
/**
* 获取章节作业
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
* @param {string} resourseId 章节的资源ID
*/
export
function
getChapter
Exam
(
semesterId
,
courseId
,
resourseId
)
{
export
function
getChapter
Homework
(
semesterId
,
courseId
,
resourseId
)
{
return
httpRequest
.
get
(
`/v2/education/homeworks/
${
semesterId
}
/
${
courseId
}
/
${
resourseId
}
`
)
}
/**
* 获取提交作业截止时间
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
* @param {string} chapterId 章节ID
*/
export
function
getChapterHomeworkDeadline
(
semesterId
,
courseId
,
chapterId
)
{
return
httpRequest
.
get
(
`/v2/education/homeworks/
${
semesterId
}
/
${
courseId
}
/
${
chapterId
}
/deadline`
)
}
/**
* 提交考试
*/
export
function
sbumitChapter
Exam
(
params
)
{
export
function
sbumitChapter
Homework
(
params
)
{
return
httpRequest
.
post
(
'/v2/education/homeworks'
,
params
,
{
headers
:
{
'Content-Type'
:
'application/json'
}
})
...
...
@@ -130,8 +163,9 @@ export function submitCourseExam(semesterId, courseId, examId, data) {
* @param {string} courseId 课程ID
* @param {string} examId 试题ID
*/
export
function
getCourseExamResult
(
semesterId
,
courseId
,
examId
)
{
export
function
getCourseExamResult
(
semesterId
,
courseId
,
examId
,
params
)
{
return
httpRequest
.
get
(
`/v2/education/
${
semesterId
}
/
${
courseId
}
/examination/
${
examId
}
/sheet`
`/v2/education/
${
semesterId
}
/
${
courseId
}
/examination/
${
examId
}
/sheet`
,
params
)
}
client/src/modules/viewer/components/aside/chapter.vue
浏览文件 @
5632ae6b
<
template
>
<ul
class=
"chapter-list"
>
<li
class=
"chapter-item"
v-for=
"item in
data
"
:key=
"item.id"
>
<li
class=
"chapter-item"
v-for=
"item in
chapters
"
:key=
"item.id"
>
<h4>
{{
item
.
name
}}
</h4>
<ul
class=
"chapter-item-list"
>
<li
...
...
@@ -9,7 +9,7 @@
@
click=
"onClick(subItem)"
:class=
"
{'is-active': subItem.id === (active ? active.id : '')}"
>
<span
class=
"chapter-item-list__name"
>
{{
subItem
.
name
|
showName
(
subItem
.
type
)
}}
</span>
<span
class=
"chapter-item-list__name"
>
{{
subItem
.
name
|
showName
(
subItem
)
}}
</span>
<i
class=
"el-icon"
:class=
"genIconClass(subItem.type)"
></i>
</li>
</ul>
...
...
@@ -20,7 +20,14 @@
<
script
>
export
default
{
props
:
{
data
:
{
type
:
Array
,
default
:
()
=>
[]
},
// 课程详情接口返回的数据
data
:
{
type
:
Object
,
default
()
{
return
{}
}
},
chapters
:
{
type
:
Array
,
default
:
()
=>
[]
},
// 当前选中的章节
active
:
{
type
:
Object
,
...
...
@@ -30,26 +37,13 @@ export default {
}
},
data
()
{
return
{
otherList
:
[
{
name
:
'大作业及资料'
,
children
:
[
{
name
:
'课程大作业'
,
id
:
'course_work'
},
{
name
:
'课程资料'
,
id
:
'course_info'
},
{
name
:
'教学评估'
,
id
:
'teach_evaluation'
}
]
}
]
}
},
computed
:
{
list
()
{
return
this
.
data
.
concat
(
this
.
otherList
)
}
return
{}
},
filters
:
{
showName
(
name
,
type
)
{
showName
(
name
,
data
)
{
if
(
data
.
type
===
5
&&
data
.
live
)
{
return
`
${
name
}
(
${
data
.
live
.
start_time
}
)`
}
return
name
}
},
...
...
@@ -63,16 +57,20 @@ export default {
return
map
[
type
]
||
'el-icon-self-cc-book'
},
onClick
(
data
)
{
if
(
data
.
type
===
1
)
{
return
}
// 课程大作业
// if (data.id === 'course_work') {
// this.$router.push({ name: 'viewerCourseWork' })
// return
// }
// 课程资料
// if (data.id === 'course_info') {
// this.$router.push({ name: 'viewerCourseFile' })
// return
// }
if
(
data
.
id
===
'course_work'
&&
!
this
.
data
.
survey
)
{
this
.
$message
(
'请先填写教学评估,然后完成大作业。'
)
return
}
// 教学评估
if
(
data
.
id
===
'teach_evaluation'
)
{
const
{
sid
,
cid
}
=
this
.
$route
.
params
this
.
$router
.
push
({
name
:
'survey'
,
params
:
{
sid
,
cid
}
})
return
}
this
.
$router
.
push
({
name
:
'viewerCourseChapter'
,
params
:
{
id
:
data
.
id
}
...
...
client/src/modules/viewer/components/aside/index.vue
浏览文件 @
5632ae6b
...
...
@@ -3,12 +3,12 @@
<el-tabs
v-model=
"activeName"
>
<el-tab-pane
label=
"章节"
name=
"0"
>
<div
class=
"tab-pane"
>
<aside-chapter
:data=
"chapters"
:active=
"active"
></aside-chapter>
<aside-chapter
:data=
"
data"
:chapters=
"
chapters"
:active=
"active"
></aside-chapter>
</div>
</el-tab-pane>
<el-tab-pane
label=
"讲义"
name=
"1"
v-if=
"active && active.type === 2"
>
<div
class=
"tab-pane"
>
<aside-lecture
:
data
=
"ppts"
:pptIndex=
"pptIndex"
v-on=
"$listeners"
></aside-lecture>
<aside-lecture
:
ppts
=
"ppts"
:pptIndex=
"pptIndex"
v-on=
"$listeners"
></aside-lecture>
</div>
</el-tab-pane>
</el-tabs>
...
...
@@ -21,6 +21,13 @@ import AsideLecture from './lecture.vue'
export
default
{
props
:
{
// 课程详情接口返回的数据
data
:
{
type
:
Object
,
default
()
{
return
{}
}
},
// 章节
chapters
:
{
type
:
Array
,
default
:
()
=>
[]
},
// 讲义
...
...
client/src/modules/viewer/components/aside/lecture.vue
浏览文件 @
5632ae6b
<
template
>
<ul
class=
"lecture-list"
>
<li
v-for=
"(item, index) in
data
"
v-for=
"(item, index) in
ppts
"
:key=
"item.id"
@
click=
"onClick(index)"
:class=
"
{'is-active': index === activeIndex}"
...
...
@@ -16,7 +16,7 @@ export default {
props
:
{
// 当前选择的PPT
pptIndex
:
{
type
:
Number
,
default
:
0
},
data
:
{
type
:
Array
,
default
:
()
=>
[]
}
ppts
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
data
()
{
return
{
...
...
client/src/modules/viewer/components/common/editor.vue
浏览文件 @
5632ae6b
...
...
@@ -84,9 +84,8 @@ export default {
{
name
:
'insert'
,
items
:
[
'Image'
,
'Table'
,
'HorizontalRule'
]
}
]
}
if
(
this
.
readOnly
!==
null
)
{
config
.
readOnly
=
this
.
readOnly
if
(
this
.
disabled
!==
null
)
{
config
.
readOnly
=
this
.
disabled
}
const
editor
=
(
this
.
ckEditor
=
CKEDITOR
.
replace
(
...
...
client/src/modules/viewer/components/common/fileList.vue
deleted
100644 → 0
浏览文件 @
64bdc527
<
template
>
<div>
<ul
class=
"file-list"
v-if=
"files.length"
>
<li
class=
"file-list-item"
v-for=
"file in files"
:key=
"file.id"
>
<a
:href=
"file.file_url"
target=
"_blank"
>
<i
class=
"el-icon-document"
></i>
<div
v-html=
"file.file_name"
></div>
</a>
<span
v-if=
"file.file_size"
>
{{
file
.
file_size
}}
</span>
<a
:href=
"file.file_url"
:download=
"file.file_name"
target=
"_blank"
>
<el-tooltip
effect=
"dark"
content=
"下载"
>
<i
class=
"el-icon-download"
></i>
</el-tooltip>
</a>
</li>
</ul>
<div
class=
"empty"
v-else
>
<slot
name=
"empty"
>
暂无课程资料
</slot>
</div>
</div>
</
template
>
<
script
>
export
default
{
name
:
'FilePanel'
,
props
:
{
// 标题
title
:
{
type
:
String
,
default
:
'课程资料'
},
// 文件列表
files
:
{
type
:
Array
,
default
:
()
=>
[]
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.file-list
{
padding
:
0
;
}
.file-list-item
{
display
:
flex
;
font-size
:
16px
;
padding
:
20px
30px
;
margin-bottom
:
10px
;
background-color
:
#fff
;
list-style
:
none
;
border-radius
:
32px
;
justify-content
:
space-between
;
a
{
display
:
flex
;
align-items
:
center
;
text-decoration
:
none
;
color
:
#333
;
white-space
:
nowrap
;
&
:hover
{
color
:
#b49441
;
}
::v-deep
*
{
margin
:
0
;
padding
:
0
;
}
}
}
.empty
{
font-size
:
18px
;
line-height
:
80px
;
background-color
:
#fff
;
text-align
:
center
;
border-radius
:
40px
;
}
</
style
>
client/src/modules/viewer/components/common/upload.vue
浏览文件 @
5632ae6b
<
template
>
<div
class=
"upload"
>
<el-upload
action
:show-file-list=
"false"
:http-request=
"httpRequest"
>
<el-upload
action
:
disabled=
"disabled"
:
show-file-list=
"false"
:http-request=
"httpRequest"
>
<slot></slot>
<el-button
type=
"text"
icon=
"el-icon-upload"
>
点击上传
</el-button>
<template
v-slot:tip
>
...
...
@@ -15,11 +15,23 @@
<i
class=
"el-icon-document"
></i>
{{ fileUrl | fileName }}
</a>
<a
:href=
"fileUrl"
:download=
"fileUrl | fileName"
target=
"_blank"
>
<el-tooltip
effect=
"dark"
content=
"下载"
>
<i
class=
"el-icon-download"
></i>
</el-tooltip>
</a>
<div>
<a
href=
"javascript:;"
@
click=
"handleRemove(index)"
style=
"margin-right:10px;"
v-if=
"!disabled"
>
<el-tooltip
effect=
"dark"
content=
"删除"
>
<i
class=
"el-icon-delete"
></i>
</el-tooltip>
</a>
<a
:href=
"fileUrl"
:download=
"fileUrl | fileName"
target=
"_blank"
>
<el-tooltip
effect=
"dark"
content=
"下载"
>
<i
class=
"el-icon-download"
></i>
</el-tooltip>
</a>
</div>
</div>
</div>
</div>
...
...
@@ -31,7 +43,8 @@ import * as api from '../../api'
export
default
{
name
:
'VUpload'
,
props
:
{
value
:
{
type
:
[
String
,
Array
]
}
value
:
{
type
:
[
String
,
Array
]
},
disabled
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
return
{
...
...
@@ -39,9 +52,18 @@ export default {
}
},
watch
:
{
value
(
value
)
{
if
(
value
)
{
this
.
fileList
=
Array
.
isArray
(
value
)
?
value
:
[
value
]
value
:
{
immediate
:
true
,
handler
(
value
)
{
if
(
value
)
{
if
(
Array
.
isArray
(
value
))
{
this
.
fileList
=
value
.
map
(
item
=>
{
return
item
.
url
||
item
})
}
else
{
this
.
fileList
=
[
value
]
}
}
}
}
},
...
...
@@ -63,6 +85,10 @@ export default {
}
}
})
},
handleRemove
(
index
)
{
this
.
fileList
.
splice
(
index
,
1
)
this
.
$emit
(
'input'
,
Array
.
isArray
(
this
.
value
)
?
this
.
fileList
:
''
)
}
}
}
...
...
client/src/modules/viewer/components/layout.vue
浏览文件 @
5632ae6b
...
...
@@ -11,8 +11,9 @@
<
script
>
// components
import
ChapterPlayer
from
'./player/
C
hapterPlayer.vue'
// 章节视频
import
ChapterPlayer
from
'./player/
c
hapterPlayer.vue'
// 章节视频
import
ChapterWork
from
'./work/index.vue'
// 章节作业
import
ChapterExam
from
'./work/chapterExam.vue'
// 章节考试
import
ChapterRead
from
'./read/chapterRead.vue'
// 章节资料
import
ChapterLive
from
'./live/chapterLive.vue'
// 章节直播
import
CourseWork
from
'./work/courseWork.vue'
// 课程大作业
...
...
@@ -25,6 +26,7 @@ export default {
ChapterPlayer
,
ChapterWork
,
ChapterRead
,
ChapterExam
,
ChapterLive
,
CourseWork
,
CourseRead
,
...
...
@@ -45,6 +47,7 @@ export default {
3
:
'ChapterWork'
,
// 作业
4
:
'ChapterRead'
,
// 资料
5
:
'ChapterLive'
,
// 直播
9
:
'ChapterExam'
,
// 考试
99
:
'CourseWork'
,
// 课程大作业
100
:
'CourseRead'
,
// 课程资料
101
:
'CourseExam'
// 课程考试
...
...
client/src/modules/viewer/components/live/chapterLive.vue
浏览文件 @
5632ae6b
...
...
@@ -39,14 +39,17 @@ export default {
},
iframeUrl
()
{
const
live
=
this
.
chapter
.
live
const
liveStatus
=
live
.
live_status
live
.
viewer_name
=
live
.
viewer_name
||
this
.
nickName
if
(
liveStatus
===
103
&&
live
.
enable_record
===
1
)
{
if
(
live
.
live_status
===
2
&&
live
.
enable_record
===
1
&&
live
.
record_url
)
{
// enable_record 0:不启用回放 1:开启回放
// 查看回放
return
`https://view.csslcloud.net/api/view/callback?recordid=
${
live
.
record_id
}
&roomid=
${
live
.
room_id
}
&userid=
${
live
.
user_id
}
&autoLogin=true&viewername=
${
live
.
viewer_name
}
&viewertoken=
${
live
.
viewer_token
}
`
return
live
.
record_url
}
else
{
// 直播
live
.
viewer_name
=
live
.
viewer_name
||
this
.
nickName
return
`https://view.csslcloud.net/api/view/index?roomid=
${
live
.
room_id
}
&userid=
${
live
.
user_id
}
&autoLogin=true&viewername=
${
live
.
viewer_name
}
&viewertoken=
${
live
.
viewer_token
}
`
}
}
...
...
client/src/modules/viewer/components/player/chapterPlayer.vue
浏览文件 @
5632ae6b
...
...
@@ -5,17 +5,21 @@
<!-- 视频 -->
<video-player
:isSkip=
"isSkip"
:skipTime=
"skipTime"
:video=
"chatperResources.video"
@
timeupdate=
"onTimeupdate"
@
ready=
"onReady"
ref=
"videoPlayer"
></video-player>
</div>
<div
class=
"player-column"
v-if=
"pptVisible"
>
<!-- ppt -->
<ppt-player
:index=
"pptIndex"
:ppts=
"chatperResources.ppts"
@
close=
"
pptVisible = fal
se"
@
close=
"
onPPTClo
se"
@
fullscreen=
"onPPTFullscreen"
@
videoSyncTime=
"onVideoSyncTime"
></ppt-player>
</div>
</div>
...
...
@@ -30,6 +34,8 @@
</
template
>
<
script
>
import
Cookies
from
'js-cookie'
import
{
throttle
}
from
'lodash'
// api
import
*
as
api
from
'../../api'
// components
...
...
@@ -46,11 +52,26 @@ export default {
pptIndex
:
{
type
:
Number
,
default
:
0
}
},
data
()
{
// 是否跳过片头
const
isSkip
=
window
.
localStorage
.
getItem
(
'isSkip'
)
===
'true'
return
{
videoVisible
:
true
,
pptVisible
:
false
,
isSkip
:
false
,
chatperResources
:
null
isSkip
,
skipTime
:
6
,
chatperResources
:
null
,
throttled
:
null
,
throttleWait
:
5
,
// 秒
progress
:
{
cpt
:
0
,
// 当前播放时间
mpt
:
0
,
// 视频时长
progress
:
0
,
// 进度
pt
:
0
// 累计播放时间
},
player
:
null
,
watchedTimePoint
:
[],
// 视频观看的时间点
timer
:
null
,
isPlaying
:
false
}
},
watch
:
{
...
...
@@ -59,6 +80,14 @@ export default {
}
},
computed
:
{
// 学期ID
sid
()
{
return
this
.
$route
.
params
.
sid
},
// 课程ID
cid
()
{
return
this
.
$route
.
params
.
cid
},
// 视频资源ID
resourceId
()
{
return
this
.
chapter
.
resource_id
...
...
@@ -95,25 +124,63 @@ export default {
// 始终跳过片头
toggleSkip
()
{
this
.
isSkip
=
!
this
.
isSkip
window
.
localStorage
.
setItem
(
'isSkip'
,
this
.
isSkip
)
},
// 关闭PPT
onPPTClose
()
{
this
.
pptVisible
=
false
this
.
videoVisible
=
true
},
// PPT全屏
onPPTFullscreen
(
value
)
{
this
.
videoVisible
=
!
value
},
// 设置视频时间为当前PPT时间
onVideoSyncTime
(
time
)
{
this
.
player
.
seek
(
time
)
},
// 播放器ready
onReady
(
player
)
{
this
.
player
=
player
// 跳转播放进度
if
(
this
.
progress
.
cpt
)
{
this
.
player
.
seek
(
this
.
progress
.
cpt
)
}
// 更新视频观看总时长
this
.
updateWatchTime
()
},
// 当前播放时间更新
onTimeupdate
(
time
)
{
this
.
isPlaying
=
true
const
ppts
=
this
.
chatperResources
.
ppts
||
[]
let
index
=
this
.
chatperResources
.
ppts
.
findIndex
(
item
=>
item
.
ppt_point
>
time
)
index
=
index
!==
-
1
?
index
-
1
:
ppts
.
length
-
1
this
.
$emit
(
'change-ppt'
,
index
)
const
durations
=
this
.
player
.
getDuration
()
// 更新视频时间
this
.
progress
.
cpt
=
parseInt
(
time
)
// 更新视频时长
this
.
progress
.
mpt
=
parseInt
(
durations
)
const
hasTimePoint
=
this
.
watchedTimePoint
.
includes
(
this
.
progress
.
cpt
)
if
(
!
hasTimePoint
)
{
this
.
watchedTimePoint
.
push
(
this
.
progress
.
cpt
)
}
// 更新视频进度,10秒更新一次
if
(
this
.
throttled
)
{
this
.
throttled
(
time
,
durations
)
}
else
{
this
.
throttled
=
throttle
(
this
.
updateChapterVideoProgress
,
this
.
throttleWait
*
1000
)
}
},
// 更新视频当前播放时间
updateVideoCurrentTime
()
{
const
player
=
this
.
$refs
.
videoPlayer
.
player
const
ppt
=
this
.
chatperResources
.
ppts
[
this
.
pptIndex
]
ppt
&&
player
.
seek
(
ppt
.
ppt_point
)
// 增加2秒
ppt
&&
this
.
player
.
seek
(
ppt
.
ppt_point
)
// 增加2秒
},
// 获取章节视频详情
getChapterVideo
()
{
...
...
@@ -125,14 +192,89 @@ export default {
})
}
else
{
api
.
getChapterVideo
(
this
.
resourceId
).
then
(
response
=>
{
this
.
chatperResources
=
response
Array
.
isArray
(
response
.
ppts
)
&&
this
.
$emit
(
'pptupdate'
,
response
.
ppts
)
let
{
video
,
audio
,
ppts
}
=
response
video
=
video
.
reduce
(
(
result
,
item
)
=>
{
if
(
item
.
quality
===
'10'
)
{
result
.
LD
=
item
.
playurl
}
if
(
item
.
quality
===
'20'
)
{
result
.
SD
=
item
.
playurl
}
return
result
},
{
LD
:
''
,
SD
:
''
}
)
this
.
chatperResources
=
{
video
,
audio
,
ppts
}
Array
.
isArray
(
ppts
)
&&
this
.
$emit
(
'pptupdate'
,
ppts
)
})
}
},
// 获取章节视频进度
getChapterVideoProgress
()
{
api
.
getChapterVideoProgress
(
this
.
sid
,
this
.
resourceId
,
{
device_id
:
Cookies
.
get
(
'_idt'
)
})
.
then
(
response
=>
{
this
.
progress
=
response
// 跳转播放进度
if
(
this
.
player
&&
response
.
cpt
)
{
this
.
player
.
seek
(
response
.
cpt
)
}
})
},
// 更新章节视频进度
updateChapterVideoProgress
(
time
,
durations
)
{
// this.progress.pt += this.throttleWait
// 登录用户信息
const
user
=
window
.
G
.
UserInfo
const
params
=
{
sid
:
user
.
student_info
.
id
,
uid
:
user
.
uid
,
d
:
Cookies
.
get
(
'_idt'
),
i
:
Cookies
.
get
(
'_idt'
),
c
:
this
.
cid
,
// 课程ID
s
:
this
.
sid
,
// 学期ID
v
:
this
.
resourceId
,
// 视频资源ID
_p
:
this
.
progress
.
pt
,
// 累计时间
_m
:
this
.
progress
.
mpt
,
// 当前播放最大时间
_c
:
this
.
progress
.
cpt
,
// 当前播放位置
ps
:
this
.
watchedTimePoint
.
join
(
','
)
// 播放时,统计帧
}
api
.
updateChapterVideoProgress
(
params
)
// 清空已经上传过的观看时间点
this
.
watchedTimePoint
=
[]
},
// 更新观看总时长
updateWatchTime
()
{
this
.
timer
&&
clearInterval
(
this
.
timer
)
// 增加跳过片头时间
if
(
this
.
isSkip
&&
!
this
.
progress
.
pt
)
{
this
.
progress
.
pt
=
this
.
skipTime
+
this
.
throttleWait
}
// 默认增加时间
this
.
progress
.
pt
=
this
.
progress
.
pt
||
this
.
throttleWait
this
.
timer
=
setInterval
(()
=>
{
// safair 浏览器下有bug
// const status = this.player.getStatus()
if
(
this
.
isPlaying
)
{
// 播放倍速
const
speed
=
this
.
player
.
_originalPlaybackRate
||
1
this
.
progress
.
pt
=
this
.
progress
.
pt
+
1
*
speed
}
this
.
isPlaying
=
false
},
1000
)
}
},
beforeMount
()
{
// 获取视频
this
.
getChapterVideo
()
// 获取视频进度
this
.
getChapterVideoProgress
()
},
destroyed
()
{
this
.
timer
&&
clearInterval
(
this
.
timer
)
}
}
</
script
>
...
...
@@ -148,6 +290,7 @@ export default {
.player-main
{
display
:
flex
;
flex
:
1
;
overflow
:
hidden
;
}
.player-column
{
flex
:
1
;
...
...
client/src/modules/viewer/components/player/pptPlayer.vue
浏览文件 @
5632ae6b
...
...
@@ -19,10 +19,18 @@
<span>
{{ppts.length}}
</span>
页
</div>
<div
class=
"ppt-player-controls__tools"
>
<i
:class=
"['el-icon-self-xuexiao', (currentSync ? 'active' : '')]"
@
click=
"onToggleSync"
></i>
<i
class=
"el-icon-self-quanping"
@
click=
"fullscreen"
></i>
<i
class=
"el-icon-self-shipin"
@
click=
"setVideoTime"
></i>
<i
class=
"el-icon-self-guanbi"
@
click=
"$emit('close')"
></i>
<el-tooltip
content=
"PPT同步视频播放"
>
<i
:class=
"['el-icon-self-xuexiao', (isSync ? 'active' : '')]"
@
click=
"onToggleSync"
></i>
</el-tooltip>
<el-tooltip
content=
"放大PPT"
>
<i
class=
"el-icon-self-quanping"
@
click=
"fullscreen"
></i>
</el-tooltip>
<el-tooltip
content=
"切换视频到当前PPT页"
>
<i
class=
"el-icon-self-shipin"
@
click=
"setVideoTime"
></i>
</el-tooltip>
<el-tooltip
content=
"关闭PPT"
>
<i
class=
"el-icon-self-guanbi"
@
click=
"$emit('close')"
></i>
</el-tooltip>
</div>
</div>
</template>
...
...
@@ -34,20 +42,21 @@ export default {
name
:
'ppt-player'
,
props
:
{
ppts
:
{
type
:
Array
},
index
:
{
type
:
Number
,
default
:
0
},
isSync
:
{
type
:
Boolean
,
default
:
false
}
index
:
{
type
:
Number
,
default
:
0
}
},
data
()
{
return
{
currentIndex
:
this
.
index
,
currentSync
:
this
.
isSync
,
isSync
:
true
,
isFullscreen
:
false
}
},
watch
:
{
index
:
{
handler
(
value
)
{
this
.
currentIndex
=
value
if
(
this
.
isSync
)
{
this
.
currentIndex
=
value
}
}
}
},
...
...
@@ -67,20 +76,18 @@ export default {
},
prev
()
{
this
.
currentIndex
=
this
.
getIndex
(
this
.
currentIndex
-
1
)
this
.
current
Sync
=
false
this
.
is
Sync
=
false
},
next
(
e
)
{
this
.
currentIndex
=
this
.
getIndex
(
this
.
currentIndex
+
1
)
this
.
current
Sync
=
false
this
.
is
Sync
=
false
},
onToggleSync
(
e
)
{
this
.
currentSync
=
!
this
.
currentSync
this
.
currentIndex
=
this
.
currentSync
?
this
.
currentIndex
:
this
.
currentIndex
this
.
isSync
=
!
this
.
isSync
},
setVideoTime
(
e
)
{
this
.
$emit
(
'onVideoSyncTime'
,
this
.
ppts
[
this
.
currentIndex
].
ppt_point
)
this
.
isSync
=
true
this
.
$emit
(
'videoSyncTime'
,
this
.
ppts
[
this
.
currentIndex
].
ppt_point
)
},
// 全屏
fullscreen
()
{
...
...
client/src/modules/viewer/components/player/videoPlayer.vue
浏览文件 @
5632ae6b
...
...
@@ -13,34 +13,41 @@ export default {
createPlayer
()
{
const
_this
=
this
const
{
FD
,
LD
,
SD
}
=
this
.
video
/*
"OD" : "原画"
"FD" : "流畅"
"LD" : "标清"
"SD" : "高清"
"HD" : "超清"
"2K" : "2K"
"4K" : "4K"
*/
this
.
player
=
new
Aliplayer
(
{
id
:
'player'
,
source
:
JSON
.
stringify
({
FD
,
LD
,
SD
}),
width
:
'100%'
,
height
:
'100%'
,
autoplay
:
tru
e
,
autoplay
:
fals
e
,
isLive
:
false
,
preload
:
true
,
useH5Prism
:
true
,
controlBarVisibility
:
'always'
,
components
:
[
{
name
:
'QualityComponent'
,
type
:
AliPlayerComponent
.
QualityComponent
}
]
defaultDefinition
:
'SD'
,
useHlsPluginForSafari
:
true
},
function
(
player
)
{
player
.
on
(
'sourceloaded'
,
function
(
params
)
{
const
paramData
=
params
.
paramData
const
desc
=
paramData
.
desc
const
definition
=
paramData
.
definition
player
.
getComponent
(
'QualityComponent'
)
.
setCurrentQuality
(
desc
,
definition
)
player
.
on
(
'ready'
,
function
()
{
// 跳过片头
_this
.
isSkip
&&
player
.
seek
(
6
)
_this
.
$emit
(
'ready'
,
player
)
})
player
.
on
(
'timeupdate'
,
function
(
event
)
{
_this
.
$emit
(
'timeupdate'
,
player
.
getCurrentTime
())
})
player
.
on
(
'error'
,
function
(
event
)
{
console
.
log
(
event
)
})
}
)
}
...
...
client/src/modules/viewer/components/read/chapterRead.vue
浏览文件 @
5632ae6b
...
...
@@ -8,7 +8,7 @@
<
script
>
// components
import
Container
from
'../common/container.vue'
import
FileList
from
'.
./common
/fileList.vue'
import
FileList
from
'./fileList.vue'
// 章节阅读资料
export
default
{
...
...
client/src/modules/viewer/components/read/courseRead.vue
浏览文件 @
5632ae6b
...
...
@@ -8,7 +8,7 @@
<
script
>
// components
import
Container
from
'../common/container.vue'
import
FileList
from
'.
./common
/fileList.vue'
import
FileList
from
'./fileList.vue'
// 课程阅读资料
export
default
{
...
...
client/src/modules/viewer/components/read/fileList.vue
浏览文件 @
5632ae6b
...
...
@@ -4,9 +4,9 @@
<li
class=
"file-list-item"
v-for=
"file in files"
:key=
"file.id"
>
<a
:href=
"file.file_url"
target=
"_blank"
>
<i
class=
"el-icon-document"
></i>
{{
file
.
file_name
}}
<div
v-html=
"file.file_name"
></div>
</a>
<
span
v-if=
"file.file_size"
>
{{
file
.
file_size
}}
</span
>
<
!--
<span
v-if=
"file.file_size"
>
{{
file
.
file_size
}}
</span>
--
>
<a
:href=
"file.file_url"
:download=
"file.file_name"
target=
"_blank"
>
<el-tooltip
effect=
"dark"
content=
"下载"
>
<i
class=
"el-icon-download"
></i>
...
...
@@ -46,11 +46,18 @@ export default {
border-radius
:
32px
;
justify-content
:
space-between
;
a
{
display
:
flex
;
align-items
:
center
;
text-decoration
:
none
;
color
:
#333
;
white-space
:
nowrap
;
&
:hover
{
color
:
#b49441
;
}
::v-deep
*
{
margin
:
0
;
padding
:
0
;
}
}
}
.empty
{
...
...
client/src/modules/viewer/components/work/chapterExam.vue
浏览文件 @
5632ae6b
差异被折叠。
点击展开。
client/src/modules/viewer/components/work/chapterTest.vue
0 → 100644
浏览文件 @
5632ae6b
<
template
>
<container
:title=
"chapter.name"
v-loading=
"loading"
>
<template
v-slot:header-aside
v-if=
"isSubmited"
>
正确率:
{{
detail
.
score
}}
%
</
template
>
<div
class=
"exam"
>
<div
class=
"exam-form"
>
<el-form
:disabled=
"isSubmited"
>
<exam-item
v-for=
"(item, index) in unorderedQuestions"
:index=
"index"
:type=
"item.question_type"
:data=
"item"
:value=
"item.formModel"
:disabled=
"isSubmited"
:key=
"item.id"
></exam-item>
<div
class=
"exam-buttons"
>
<el-tooltip
effect=
"dark"
content=
"提交之后就不能修改了哦"
placement=
"right"
>
<el-button
type=
"primary"
@
click=
"onSubmit"
>
{{submitText}}
</el-button>
</el-tooltip>
</div>
</el-form>
</div>
</div>
</container>
</template>
<
script
>
// libs
import
{
shuffle
}
from
'lodash'
// components
import
Container
from
'../common/container.vue'
import
ExamItem
from
'./examItem.vue'
// api
import
*
as
api
from
'../../api'
// 章节测试题
export
default
{
name
:
'ChapterTest'
,
components
:
{
Container
,
ExamItem
},
props
:
{
// 当前选中的章节
chapter
:
{
type
:
Object
,
default
()
{
return
{}
}
}
},
data
()
{
return
{
loading
:
false
,
detail
:
null
,
questions
:
[],
// 问题列表
startTime
:
new
Date
().
getTime
(),
// 进入时间
messageInstance
:
null
}
},
watch
:
{
chapter
:
{
immediate
:
true
,
handler
(
data
)
{
this
.
questions
=
data
.
homework
?
this
.
genQuenstions
(
data
.
homework
.
questions
)
:
[]
}
}
},
computed
:
{
// 学期ID
sid
()
{
return
this
.
$route
.
params
.
sid
},
// 课程ID
cid
()
{
return
this
.
$route
.
params
.
cid
},
// 当前页面的ID
pid
()
{
return
this
.
$route
.
params
.
id
},
// 资源ID
resourceId
()
{
return
this
.
chapter
.
resource_id
},
// 打乱顺序的问题列表
unorderedQuestions
()
{
const
ids
=
this
.
questions
.
map
(
item
=>
item
.
id
)
const
sortIds
=
shuffle
(
ids
)
return
sortIds
.
map
(
id
=>
this
.
questions
.
find
(
item
=>
item
.
id
===
id
))
},
// 是否提交
isSubmited
()
{
return
this
.
detail
?
!!
this
.
detail
.
work_contents
:
false
},
// 提交按钮文本
submitText
()
{
return
this
.
isSubmited
?
'已提交'
:
'提交'
}
},
methods
:
{
// 获取测试答题详情
getDetail
()
{
this
.
loading
=
true
api
.
getChapterHomework
(
this
.
sid
,
this
.
cid
,
this
.
resourceId
)
.
then
(
response
=>
{
this
.
detail
=
Array
.
isArray
(
response
)
?
null
:
response
if
(
this
.
detail
)
{
const
parseAnswers
=
JSON
.
parse
(
this
.
detail
.
work_contents
)
// 设置答案
this
.
questions
=
this
.
questions
.
map
(
item
=>
{
const
found
=
parseAnswers
.
find
(
answer
=>
answer
.
question_id
===
item
.
id
)
if
(
found
)
{
const
selectedIds
=
found
.
options
.
reduce
((
result
,
item
)
=>
{
item
.
selected
&&
result
.
push
(
item
.
id
)
return
result
},
[])
item
.
user_answer
=
item
.
question_type
===
2
?
selectedIds
:
selectedIds
[
0
]
}
return
item
})
this
.
questions
=
this
.
genQuenstions
(
this
.
questions
)
}
})
.
finally
(()
=>
{
this
.
loading
=
false
})
},
// 组装问题数据
genQuenstions
(
list
)
{
if
(
!
list
)
{
return
[]
}
return
list
.
map
(
item
=>
{
let
temp
=
null
if
(
item
.
question_type
===
1
)
{
// 单选
temp
=
{
formModel
:
{
id
:
item
.
id
,
user_answer
:
item
.
user_answer
||
''
}
}
}
else
if
(
item
.
question_type
===
2
)
{
// 多选
temp
=
{
formModel
:
{
id
:
item
.
id
,
user_answer
:
item
.
user_answer
||
[]
}
}
}
else
if
(
item
.
question_type
===
3
)
{
// 简答
temp
=
{
formModel
:
{
id
:
item
.
id
,
user_answer
:
item
.
user_answer
?
Base64
.
decode
(
item
.
user_answer
)
:
''
,
attachments
:
item
.
attachments
||
''
}
}
}
return
Object
.
assign
(
{},
item
,
{
content
:
item
.
question_content
,
options
:
item
.
question_options
?
JSON
.
parse
(
item
.
question_options
)
:
[]
},
temp
)
})
},
// 提交校验
checkSubmit
()
{
const
quenstions
=
this
.
questions
for
(
let
i
=
0
;
i
<
quenstions
.
length
;
i
++
)
{
const
value
=
quenstions
[
i
].
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
(
'还有题目未做,不能提交'
)
return
}
// 计算答题时间
const
duration
=
Math
.
floor
(
(
new
Date
().
getTime
()
-
this
.
startTime
)
/
1000
)
// 答案数据
const
data
=
this
.
handleSubmitData
()
// 计算分数
const
score
=
data
.
reduce
((
result
,
item
)
=>
{
item
.
is_correct
&&
result
++
return
result
},
0
)
const
total
=
this
.
questions
.
length
const
params
=
{
semester_id
:
this
.
sid
,
course_id
:
this
.
cid
,
chapter_id
:
this
.
pid
,
work_id
:
this
.
resourceId
,
work_contents
:
JSON
.
stringify
(
data
),
duration
,
score
:
((
score
/
total
)
*
100
).
toFixed
(
1
)
}
// 请求接口
this
.
handleSubmitRequest
(
params
)
},
// 提交的答案数据
handleSubmitData
()
{
const
result
=
this
.
questions
.
map
(
item
=>
{
// 设置提交选中状态
let
isCorrect
=
true
const
options
=
item
.
options
.
map
(
option
=>
{
// 选择的项
const
answers
=
item
.
formModel
.
user_answer
// 是否选中该项
const
selected
=
Array
.
isArray
(
answers
)
?
answers
.
includes
(
option
.
id
)
:
option
.
id
===
answers
// 是否选择正确
if
(
option
.
checked
!==
selected
&&
isCorrect
)
{
isCorrect
=
false
}
return
{
id
:
option
.
id
,
checked
:
option
.
checked
,
option
:
option
.
option
,
selected
}
})
return
{
question_id
:
item
.
id
,
is_correct
:
isCorrect
?
1
:
0
,
options
}
})
return
result
},
// 请求提交接口
handleSubmitRequest
(
params
)
{
api
.
sbumitChapterHomework
(
params
)
.
then
(
response
=>
{
if
(
response
.
status
)
{
this
.
getDetail
()
}
else
{
this
.
$message
.
error
(
response
.
data
.
error
)
}
})
.
catch
(
error
=>
{
this
.
$message
.
error
(
error
.
message
)
})
}
},
beforeMount
()
{
this
.
getDetail
()
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.exam-buttons
{
padding
:
40px
0
;
text-align
:
center
;
.el-button
{
width
:
240px
;
margin
:
40px
auto
;
}
}
</
style
>
client/src/modules/viewer/components/work/chapterWork.vue
浏览文件 @
5632ae6b
<
template
>
<container
:title=
"chapter.name"
v-loading=
"loading"
>
<div
class=
"exam-form"
>
<el-form
:disabled=
"
isRevised
"
>
<el-form
:disabled=
"
disabled || !isWorkTime
"
>
<exam-item
v-for=
"(item, index) in questions"
:index=
"index"
:type=
"item.question_type"
:data=
"item"
:value=
"item.formModel"
:disabled=
"
isRevised
"
:disabled=
"
disabled || !isWorkTime
"
:key=
"item.id"
></exam-item>
</el-form>
</div>
<div
class=
"work-bottom"
v-if=
"detail"
>
<div
class=
"info"
>
<template
v-if=
"isRevised"
>
<p
style=
"color:red;"
v-if=
"deadline"
>
请于截止日期
{{
deadline
}}
前提交
</p>
<!-- 驳回状态 -->
<template
v-if=
"detail && detail.status === 1"
>
<div
class=
"work-bottom"
>
<div
class=
"info"
>
<div
class=
"paper-check"
>
<
p>
批改时间:
{{
detail
.
check_date
}}
</p
>
<
h4>
作业被驳回,点击“重新编辑”按钮重新编辑内容再次提交
</h4
>
<div
class=
"paper-check-item"
>
<b>
评分
:
</b>
{{
detail
.
score
}}
<b>
驳回时间
:
</b>
{{
detail
.
checker_time
}}
</div>
<div
class=
"paper-check-item"
>
<b>
评语
:
</b>
<b>
驳回说明
:
</b>
<div
class=
"edit_html"
v-html=
"detail.check_comments"
></div>
</div>
</div>
</
template
>
<
template
v-else-if=
"detail.created_time"
>
<p
class=
"help"
>
已于
{{
detail
.
created_time
}}
提交,等待老师批改中。
</p>
<template
v-if=
"detail.updated_time && detail.updated_time !== detail.created_time"
>
<p
class=
"help"
>
最近提交时间:
{{
detail
.
updated_time
}}
</p>
</div>
</div>
<div
class=
"buttons"
>
<el-button
type=
"primary"
@
click=
"onReEdit"
:disabled=
"!isWorkTime"
>
重新编辑
</el-button>
</div>
</
template
>
<!-- 正常状态 -->
<
template
v-else
>
<div
class=
"work-bottom"
v-if=
"detail"
>
<div
class=
"info"
>
<template
v-if=
"isRevised"
>
<div
class=
"paper-check"
>
<p>
批改时间:
{{
detail
.
checker_time
}}
</p>
<div
class=
"paper-check-item"
>
<b>
评分:
</b>
{{
detail
.
score
}}
</div>
<div
class=
"paper-check-item"
>
<b>
评语:
</b>
<div
class=
"edit_html"
v-html=
"detail.check_comments"
></div>
</div>
</div>
</
template
>
</template>
<
template
v-else-if=
"detail.created_time"
>
<p
class=
"help"
>
已于
{{
detail
.
created_time
}}
提交,等待老师批改中。
</p>
<template
v-if=
"
detail.updated_time &&
detail.updated_time !== detail.created_time
"
>
<p
class=
"help"
>
最近提交时间:
{{
detail
.
updated_time
}}
</p>
</
template
>
</template>
</div>
</div>
</div>
<div
class=
"buttons"
>
<el-tooltip
content=
"在获老师批改之前,可以多次提交,将以最后一次提交为准"
placement=
"right"
>
<el-button
type=
"primary"
@
click=
"onSubmit"
:disabled=
"isRevised"
>
{{submitText}}
</el-button>
</el-tooltip>
</div>
<div
class=
"buttons"
>
<el-tooltip
content=
"在获老师批改之前,可以多次提交,将以最后一次提交为准"
placement=
"right"
>
<el-button
type=
"primary"
@
click=
"onSubmit"
:disabled=
"disabled || !isWorkTime"
>
{{ submitText }}
</el-button>
</el-tooltip>
</div>
</template>
</container>
</template>
...
...
@@ -80,7 +113,9 @@ export default {
detail
:
null
,
questions
:
[],
// 问题列表
startTime
:
new
Date
().
getTime
(),
// 进入时间
messageInstance
:
null
messageInstance
:
null
,
deadline
:
''
,
// 截止时间
disabled
:
false
}
},
watch
:
{
...
...
@@ -112,22 +147,42 @@ export default {
},
// 是否批改
isRevised
()
{
return
this
.
detail
?
!!
this
.
detail
.
check_date
:
false
return
this
.
detail
?
this
.
detail
.
status
===
0
:
false
},
// 提交按钮文本
submitText
()
{
return
this
.
isRevised
?
'已批改'
:
'提交'
},
// 是否是提交作业时间
isWorkTime
()
{
if
(
!
this
.
deadline
)
{
return
true
}
// 大于开始时间,小于结束时间
const
endTime
=
+
new
Date
(
this
.
deadline
)
const
currentTime
=
new
Date
().
getTime
()
return
currentTime
<
endTime
}
},
methods
:
{
// 获取作业截止时间
getDeadline
()
{
api
.
getChapterHomeworkDeadline
(
this
.
sid
,
this
.
cid
,
this
.
pid
)
.
then
(
response
=>
{
this
.
deadline
=
response
.
dead_line
})
},
// 获取详情
getDetail
()
{
this
.
loading
=
true
api
.
getChapter
Exam
(
this
.
sid
,
this
.
cid
,
this
.
resourceId
)
.
getChapter
Homework
(
this
.
sid
,
this
.
cid
,
this
.
resourceId
)
.
then
(
response
=>
{
this
.
detail
=
Array
.
isArray
(
response
)
?
null
:
response
if
(
this
.
detail
)
{
// -1未处理 0已处理 1驳回
this
.
disabled
=
[
0
,
1
].
includes
(
this
.
detail
.
status
)
const
parseAnswers
=
JSON
.
parse
(
this
.
detail
.
work_contents
)
// 设置答案
this
.
questions
=
this
.
questions
.
map
(
item
=>
{
...
...
@@ -205,7 +260,9 @@ export default {
// 校验
if
(
!
this
.
checkSubmit
())
{
this
.
messageInstance
&&
this
.
messageInstance
.
close
()
this
.
messageInstance
=
this
.
$message
.
error
(
'还有题目未做,不能提交'
)
this
.
messageInstance
=
this
.
$message
.
error
(
'答题内容不能为空,请检查并输入内容'
)
return
}
// 计算答题时间
...
...
@@ -214,12 +271,12 @@ export default {
)
// 提交的答案数据
const
answers
=
this
.
questions
.
map
(
item
=>
{
if
(
item
.
question_type
===
3
)
{
item
.
formModel
.
user_answer
=
Base64
.
encode
(
item
.
formModel
.
user_answer
)
}
return
{
question_id
:
item
.
id
,
descreption
:
item
.
formModel
.
user_answer
,
descreption
:
item
.
question_type
===
3
?
Base64
.
encode
(
item
.
formModel
.
user_answer
)
:
item
.
formModel
.
user_answer
,
file_url
:
item
.
formModel
.
attachments
,
is_encoded
:
1
}
...
...
@@ -239,7 +296,7 @@ export default {
// 请求提交接口
handleSubmitRequest
(
params
)
{
api
.
sbumitChapter
Exam
(
params
)
.
sbumitChapter
Homework
(
params
)
.
then
(
response
=>
{
if
(
response
.
status
)
{
this
.
$message
.
success
(
'提交成功,等待批改'
)
...
...
@@ -251,10 +308,46 @@ export default {
.
catch
(
error
=>
{
this
.
$message
.
error
(
error
.
message
)
})
},
// 重新编辑
onReEdit
()
{
this
.
disabled
=
false
this
.
detail
.
status
=
-
1
}
},
beforeMount
()
{
this
.
getDetail
()
this
.
getDeadline
()
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.work-bottom
{
margin-top
:
20px
;
.info
{
color
:
#999
;
line-height
:
28px
;
}
}
.buttons
{
padding
:
20px
0
;
::v-deep
.el-button
{
width
:
120px
;
}
}
.paper-check
{
padding
:
10px
;
color
:
#000
;
border
:
1px
solid
#dedede
;
h4
{
margin
:
0
0
10px
;
}
}
.paper-check-item
{
display
:
flex
;
b
{
white-space
:
nowrap
;
}
}
</
style
>
client/src/modules/viewer/components/work/courseExam.vue
浏览文件 @
5632ae6b
<
template
>
<container
:title=
"detail.title"
v-loading=
"loading"
>
<template
v-slot:header-aside
v-if=
"isExamComplete"
>
分数:
{{
exam
.
score
.
total
}}
分
</
template
>
<div
class=
"exam"
>
<
template
v-if=
"status.examination_status === '00'"
>
<div
class=
"no-exam"
>
暂无考试
</div>
...
...
@@ -17,39 +18,20 @@
@
click=
"onStartExam"
>
{{
startExamButtonText
}}
</el-button>
</div>
<!-- 考试完成 -->
<div
class=
"exam-finish"
v-if=
"isExamComplete"
>
<table
class=
"exam-table"
>
<tr>
<th>
单选
</th>
<th>
多选
</th>
<th>
简答
</th>
</tr>
<tr>
<td>
{{
exam
.
score
.
radio
}}
分
</td>
<td>
{{
exam
.
score
.
checkbox
}}
分
</td>
<td>
{{
exam
.
score
.
shortAnswer
}}
分
</td>
</tr>
<tr>
<td
colspan=
"3"
>
<div
class=
"exam-total"
>
总分:
{{
exam
.
score
.
total
}}
分
</div>
</td>
</tr>
</table>
<el-button
type=
"text"
@
click=
"examVisible = !examVisible"
>
查看试卷
</el-button>
</div>
<!-- 考试试题 -->
<div
class=
"exam-form"
v-if=
"isStartExam"
v-show=
"examVisible"
>
<div
class=
"exam-form"
v-if=
"isStartExam"
>
<el-form
:disabled=
"isSubmited"
>
<exam-item
v-for=
"(item, index) in questions"
:index=
"index"
:type=
"item.type"
:data=
"item"
:value=
"item.formModel"
:disabled=
"isSubmited"
:key=
"item.id"
></exam-item>
<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=
"提交之后就不能修改了哦"
placement=
"right"
>
<el-button
type=
"primary"
@
click=
"onSubmit"
>
{{submitText}}
</el-button>
...
...
@@ -97,18 +79,11 @@ export default {
detail
:
{},
status
:
{},
questions
:
[],
values
:
[],
// 提交的答案
messageInstance
:
null
,
exam
:
{},
isStartExam
:
false
,
// 是否开始考试
autoSubmitTimer
:
null
,
// 自动提交定时器
checkStatusTimer
:
null
,
// 考试状态定时器
examVisible
:
true
}
},
watch
:
{
isExamComplete
(
value
)
{
this
.
examVisible
=
!
value
checkStatusTimer
:
null
// 考试状态定时器
}
},
computed
:
{
...
...
@@ -163,7 +138,7 @@ export default {
this
.
detail
=
Array
.
isArray
(
response
)
?
null
:
response
// 设置问题列表数据
this
.
questions
=
this
.
detail
?
this
.
genQue
n
stions
(
this
.
detail
.
examination
)
?
this
.
genQuestions
(
this
.
detail
.
examination
)
:
[]
callback
&&
callback
()
})
...
...
@@ -172,42 +147,44 @@ export default {
})
},
// 组装问题数据
genQue
nstions
(
data
)
{
if
(
!
data
)
{
return
genQue
stions
(
list
)
{
if
(
!
list
)
{
return
[]
}
let
{
radioList
,
checkboxList
,
shortAnswerList
}
=
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
)
:
''
,
attachments
:
[]
return
list
.
map
(
data
=>
{
let
{
radioList
,
checkboxList
,
shortAnswerList
}
=
data
// 单选
radioList
=
radioList
.
map
(
item
=>
{
const
temp
=
{
type
:
1
,
formModel
:
{
id
:
item
.
id
,
user_answer
:
item
.
user_answer
||
''
}
}
}
return
Object
.
assign
({},
item
,
temp
)
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
)
})
return
[...
radioList
,
...
checkboxList
,
...
shortAnswerList
]
})
return
[...
radioList
,
...
checkboxList
,
...
shortAnswerList
]
},
// 获取考试状态
getExamStatus
()
{
...
...
@@ -234,7 +211,7 @@ export default {
if
(
response
.
code
!==
8001
)
{
this
.
isStartExam
=
true
this
.
exam
=
response
this
.
questions
=
this
.
genQue
n
stions
(
response
.
sheet
)
this
.
questions
=
this
.
genQuestions
(
response
.
sheet
)
// 自动提交
if
(
this
.
isStartExam
&&
!
this
.
isSubmited
&&
!
this
.
isExamComplete
)
{
this
.
autoSubmit
()
...
...
@@ -244,11 +221,13 @@ export default {
},
// 提交校验
checkSubmit
()
{
const
quenstions
=
this
.
questions
for
(
let
i
=
0
;
i
<
quenstions
.
length
;
i
++
)
{
const
value
=
quenstions
[
i
].
formModel
.
user_answer
if
(
Array
.
isArray
(
value
)
?
!
value
.
length
:
!
value
)
{
return
false
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
...
...
@@ -262,12 +241,7 @@ export default {
return
}
// 提交的答案数据
const
answers
=
this
.
questions
.
map
(
item
=>
{
if
(
item
.
type
===
3
)
{
item
.
formModel
.
user_answer
=
Base64
.
encode
(
item
.
formModel
.
user_answer
)
}
return
item
.
formModel
})
const
answers
=
this
.
handleSubmitData
()
// 提交参数
const
params
=
{
answers
:
JSON
.
stringify
(
answers
),
type
:
1
}
// 请求接口
...
...
@@ -279,19 +253,38 @@ export default {
this
.
autoSubmitTimer
&&
clearInterval
(
this
.
autoSubmitTimer
)
this
.
autoSubmitTimer
=
setInterval
(()
=>
{
// 提交的答案数据
const
answers
=
this
.
questions
.
map
(
item
=>
{
if
(
item
.
type
===
3
)
{
item
.
formModel
.
user_answer
=
Base64
.
encode
(
item
.
formModel
.
user_answer
)
}
return
item
.
formModel
})
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
)
}
return
result
},
{
radioList
:
[],
checkboxList
:
[],
shortAnswerList
:
[]
}
)
})
},
// 请求提交接口
handleSubmitRequest
(
params
)
{
api
...
...
@@ -344,27 +337,6 @@ export default {
font-size
:
30px
;
text-align
:
center
;
}
.exam-finish
{
margin
:
40px
0
;
}
.exam-table
{
width
:
100%
;
border-collapse
:
collapse
;
th
{
background-color
:
#ccc
;
}
td
,
th
{
padding
:
10px
;
border
:
1px
solid
#999
;
text-align
:
center
;
}
}
.exam-total
{
font-size
:
18px
;
text-align
:
right
;
padding
:
0
40px
;
}
.exam-welcome
{
padding
:
40px
;
line-height
:
30px
;
...
...
client/src/modules/viewer/components/work/courseWork.vue
浏览文件 @
5632ae6b
...
...
@@ -19,7 +19,7 @@
ref=
"ruleForm"
>
<el-form-item
label=
"主题"
prop=
"essay_name"
>
<el-input
v-model=
"ruleForm.essay_name"
placeholder=
"主题"
></el-input>
<el-input
v-model=
"ruleForm.essay_name"
placeholder=
"主题"
maxlength=
"50"
></el-input>
</el-form-item>
<el-form-item
label=
"正文"
prop=
"essay_description"
>
<!-- 编辑器 -->
...
...
@@ -108,11 +108,10 @@ export default {
},
rules
:
{
essay_name
:
[
{
required
:
true
,
message
:
'请输入主题'
,
trigger
:
'blur'
},
{
max
:
5
,
message
:
'最多输入 50 个字符'
,
trigger
:
'blur'
}
{
required
:
true
,
message
:
'请输入主题'
,
trigger
:
'blur'
}
],
essay_description
:
[
{
required
:
true
,
message
:
'请输入正文'
,
trigger
:
'
blur
'
}
{
required
:
true
,
message
:
'请输入正文'
,
trigger
:
'
change
'
}
],
url
:
[{
required
:
true
,
message
:
'请上传附件'
,
trigger
:
'change'
}]
},
...
...
@@ -159,19 +158,24 @@ export default {
},
// 提交
onSubmit
()
{
this
.
$refs
.
ruleForm
.
validate
()
.
then
(
response
=>
{
const
params
=
Object
.
assign
(
this
.
ruleForm
,
{
semester_id
:
this
.
sid
,
course_id
:
this
.
cid
})
this
.
handleSubmitRequest
(
params
)
})
.
catch
(()
=>
{
this
.
messageInstance
&&
this
.
messageInstance
.
close
()
this
.
messageInstance
=
this
.
$message
.
error
(
'还有题目未做,不能提交'
)
})
this
.
messageInstance
&&
this
.
messageInstance
.
close
()
if
(
!
this
.
ruleForm
.
essay_name
)
{
this
.
messageInstance
=
this
.
$message
.
error
(
'请输入主题'
)
return
}
if
(
!
this
.
ruleForm
.
essay_description
)
{
this
.
messageInstance
=
this
.
$message
.
error
(
'请输入正文'
)
return
}
if
(
!
this
.
ruleForm
.
url
)
{
this
.
messageInstance
=
this
.
$message
.
error
(
'请上传附件'
)
return
}
const
params
=
Object
.
assign
(
this
.
ruleForm
,
{
semester_id
:
this
.
sid
,
course_id
:
this
.
cid
})
this
.
handleSubmitRequest
(
params
)
},
// 请求提交接口
handleSubmitRequest
(
params
)
{
...
...
@@ -231,5 +235,8 @@ p {
}
.paper-check-item
{
display
:
flex
;
b
{
white-space
:
nowrap
;
}
}
</
style
>
client/src/modules/viewer/components/work/examItem.vue
浏览文件 @
5632ae6b
...
...
@@ -2,8 +2,11 @@
<div
class=
"q-item"
>
<div
class=
"q-item-hd"
>
<div
class=
"q-item-num"
>
{{
index
+
1
}}
.
</div>
<div
class=
"q-item-title"
v-html=
"data.content"
>
{{
data
.
title
}}
</div>
<div
class=
"q-item-aside"
v-if=
"typeText"
>
(
{{
typeText
}}
)
</div>
<div
class=
"q-item-title"
v-html=
"data.content"
></div>
<div
class=
"q-item-aside"
>
<template
v-if=
"typeText"
>
(
{{
typeText
}}
)
</
template
>
<
template
v-if=
"data.hasOwnProperty('score')"
>
(
{{
data
.
score
}}
分)
</
template
>
</div>
</div>
<div
class=
"q-item-bd"
>
<!-- 单选 -->
...
...
@@ -21,26 +24,44 @@
<!-- 简答题 -->
<
template
v-if=
"type === 3"
>
<v-editor
v-model=
"currentValue.user_answer"
:disabled=
"disabled"
></v-editor>
<v-upload
v-model=
"currentValue.attachments"
>
请上传对应的文件附件:
</v-upload>
<v-upload
:disabled=
"disabled"
v-model=
"currentValue.attachments"
>
请上传对应的文件附件:
</v-upload>
</
template
>
</div>
<div
class=
"q-item-ft"
v-if=
"disabled"
>
<
template
v-if=
"type === 3"
>
<p>
<span>
老师
评语:
</span>
<p
v-if=
"data.check_comment"
>
<span>
评语:
</span>
<span>
{{
data
.
check_comment
}}
</span>
</p>
</
template
>
<
template
v-else
>
<p>
<span>
学生答案:
</span>
<span
:class=
"isCorrect ? 'is-success' : 'is-error'"
>
{{
submitAnswerText
}}
</span>
</p>
<p>
<span>
正确答案:
</span>
<span>
{{
correctAnswerText
}}
</span>
</p>
<div
class=
"result"
>
<p>
<span>
学生答案:
</span>
<span
:class=
"isCorrect ? 'is-success' : 'is-error'"
>
{{
submitAnswerText
}}
</span>
</p>
<p>
<span>
正确答案:
</span>
<span>
{{
correctAnswerText
}}
</span>
</p>
</div>
</
template
>
<p
v-if=
"data.hasOwnProperty('get_score')"
>
<span>
评分:
</span>
<span>
{{data.get_score}}分
</span>
</p>
<div
class=
"analyze"
v-if=
"data.analysis"
>
<span>
解析:
</span>
<div
class=
"analyze-main"
>
<span
style=
"color:blue;cursor:pointer;"
@
click=
"showAnalyze = !showAnalyze"
>
查看解析
</span>
<div
v-html=
"data.analysis"
v-if=
"data.analysis"
v-show=
"showAnalyze"
class=
"analyze-content"
></div>
</div>
</div>
</div>
</div>
</template>
...
...
@@ -77,7 +98,8 @@ export default {
},
data
()
{
return
{
currentValue
:
{}
currentValue
:
{},
showAnalyze
:
false
}
},
watch
:
{
...
...
@@ -116,6 +138,14 @@ export default {
item
.
selected
=
Array
.
isArray
(
value
)
?
value
.
includes
(
item
.
id
)
:
value
===
item
.
id
// 处理正确的选中状态
const
hasChecked
=
Object
.
prototype
.
hasOwnProperty
.
call
(
item
,
'checked'
)
const
rightAnswer
=
this
.
data
.
right_answer
||
''
if
(
!
hasChecked
&&
rightAnswer
)
{
item
.
checked
=
Array
.
isArray
(
rightAnswer
)
?
rightAnswer
.
includes
(
item
.
id
)
:
rightAnswer
===
item
.
id
}
return
item
})
},
...
...
@@ -190,14 +220,16 @@ export default {
}
.q-item-title
{
flex
:
1
;
padding
:
0
10px
;
::v-deep
img
{
max-width
:
100%
;
}
}
.q-item-aside
{
padding-left
:
20px
;
// align-self: flex-end;
}
.q-option-item
{
padding-left
:
3
0px
;
padding-left
:
2
0px
;
margin-bottom
:
14px
;
}
.is-success
{
...
...
@@ -229,13 +261,36 @@ export default {
}
}
.q-item-ft
{
display
:
flex
;
justify-content
:
flex-end
;
padding
:
10px
0
;
p
{
font-size
:
14px
;
margin
:
0
;
padding-left
:
20px
;
margin
:
0
0
10px
0
;
}
.result
{
display
:
flex
;
justify-content
:
flex-end
;
p
{
padding-left
:
20px
;
}
}
.analyze
{
display
:
flex
;
font-size
:
14px
;
}
.analyze-main
{
flex
:
1
;
overflow
:
hidden
;
}
.analyze-content
{
margin-top
:
10px
;
background-color
:
#c9c9c9
7a
;
border
:
1px
solid
#c9c9c9
7a
;
padding
:
10px
;
::v-deep
*
{
margin
:
0
;
padding
:
0
;
max-width
:
100%
;
}
}
}
</
style
>
client/src/modules/viewer/components/work/index.vue
浏览文件 @
5632ae6b
...
...
@@ -12,11 +12,11 @@
<
script
>
// componets
import
ChapterWork
from
'./chapterWork.vue'
import
Chapter
Exam
from
'./chapterExam
.vue'
import
Chapter
Test
from
'./chapterTest
.vue'
export
default
{
name
:
'ViewerWork'
,
components
:
{
ChapterWork
,
Chapter
Exam
},
components
:
{
ChapterWork
,
Chapter
Test
},
props
:
{
// 当前选中的
chapter
:
{
...
...
@@ -36,7 +36,7 @@ export default {
computed
:
{
currentCompoent
()
{
const
componentNames
=
{
1
:
'Chapter
Exam'
,
// 考试
1
:
'Chapter
Test'
,
// 课后测验
2
:
'ChapterWork'
// 作业
}
const
homework
=
this
.
chapter
.
homework
...
...
client/src/modules/viewer/index.vue
浏览文件 @
5632ae6b
...
...
@@ -9,7 +9,7 @@
<h1
class=
"course-viewer-main-hd__title"
>
{{
detail
.
course_name
}}
</h1>
<!-- 直播的时候显示帮助按钮 -->
<template
v-if=
"isLive"
>
<router-link
to=
"/app/
account/feedbackC
reate"
target=
"_blank"
>
<router-link
to=
"/app/
feedback/feedback-c
reate"
target=
"_blank"
>
<el-tooltip
effect=
"light"
content=
"意见反馈"
>
<i
class=
"el-icon-self-fankuiyijian"
></i>
</el-tooltip>
...
...
@@ -35,6 +35,7 @@
</div>
<!-- 侧边栏 -->
<v-aside
:data=
"detail"
:chapters=
"chapters"
:active=
"activeChapter"
:ppts=
"ppts"
...
...
@@ -92,10 +93,17 @@ export default {
children
:
[
{
name
:
'课程大作业'
,
id
:
'course_work'
,
type
:
99
},
{
name
:
'课程资料'
,
id
:
'course_info'
,
type
:
100
},
{
name
:
'教学评估'
,
id
:
'teach_evaluation'
,
type
:
102
},
{
name
:
'课程考试'
,
id
:
'course_exam'
,
type
:
101
}
{
name
:
'教学评估'
,
id
:
'teach_evaluation'
,
type
:
102
}
]
}
// 课程考试
if
(
this
.
detail
.
course_examination
)
{
customeChapter
.
children
.
push
({
name
:
'课程考试'
,
id
:
'course_exam'
,
type
:
101
})
}
chapters
.
push
(
customeChapter
)
return
chapters
},
...
...
client/src/pages/affairsHall/hall.vue
浏览文件 @
5632ae6b
...
...
@@ -283,7 +283,9 @@ export default {
},
// 新增
golearningAdd
(
url
)
{
this
.
$router
.
push
({
path
:
url
,
query
:
{
id
:
this
.
affairId
}
})
if
(
this
.
affairId
)
{
this
.
$router
.
push
({
path
:
url
,
query
:
{
id
:
this
.
affairId
}
})
}
},
// 列表接口请求之前
tableListbeforeRequest
(
params
)
{
...
...
@@ -291,7 +293,7 @@ export default {
return
params
}
},
beforeMount
()
{
created
()
{
this
.
getTapData
()
}
}
...
...
client/src/pages/learn/course.vue
浏览文件 @
5632ae6b
...
...
@@ -193,7 +193,7 @@ export default {
},
/* 直接进直播 */
goLive
()
{
this
.
$router
.
push
({
path
:
`/player/
${
this
.
newLiveMsg
.
semester_id
}
/
${
this
.
newLiveMsg
.
course_id
}
/live/
${
this
.
newLiveMsg
.
live
.
id
}
`
})
this
.
$router
.
push
({
name
:
'viewerCourseChapter'
,
params
:
{
sid
:
this
.
newLiveMsg
.
semester_id
,
cid
:
this
.
newLiveMsg
.
course_id
,
id
:
this
.
newLiveMsg
.
chapter_id
}
})
}
}
}
...
...
client/src/pages/learn/courseDetail.vue
浏览文件 @
5632ae6b
差异被折叠。
点击展开。
client/src/pages/mobileLive/list.vue
浏览文件 @
5632ae6b
...
...
@@ -33,7 +33,6 @@
<
div
class
=
"live-item-content__time"
>
{{
subitem
.
start_time
}}
<
/div
>
<
div
class
=
"live-item-content__status"
v
-
if
=
"!(subitem.live_status === 103 && !subitem.enable_record)"
>
{{
calcTimeText
(
subitem
.
start_time
,
subitem
.
live_status
)
}}
<
/div
>
<
/div
>
<
/div
>
...
...
@@ -133,7 +132,7 @@ export default {
start_time
:
liveTime
}
=
data
let
message
=
this
.
calcTimeText
(
liveTime
,
liveStatus
)
if
(
liveStatus
===
103
&&
data
.
enable_record
!==
1
)
{
if
(
liveStatus
===
2
&&
!
data
.
enable_record
)
{
message
=
this
.
$t
(
'live.noPlayback'
)
}
if
(
liveType
===
'cloud'
)
{
...
...
@@ -155,7 +154,7 @@ export default {
if
(
liveStatus
===
1
)
{
// 进行中
this
.
openNewWindow
(
data
.
join_url
)
}
else
if
(
liveStatus
===
103
)
{
}
else
if
(
liveStatus
===
2
)
{
// 查看回放
this
.
openNewWindow
(
data
.
record_url
)
}
else
{
...
...
@@ -173,7 +172,7 @@ export default {
// 进行中
const
url
=
`http://view.csslcloud.net/api/view/index?roomid=${data.room_id
}
&userid=${data.user_id
}
&autoLogin=true&viewername=${data.username
}
&viewertoken=${data.password
}
`
this
.
openNewWindow
(
url
)
}
else
if
(
liveStatus
===
103
)
{
}
else
if
(
liveStatus
===
2
)
{
// 查看回放
const
replayUrl
=
data
.
record_url
.
replayUrl
const
url
=
replayUrl
...
...
@@ -194,11 +193,11 @@ export default {
// 进行中
const
url
=
`https://view.csslcloud.net/api/view/index?roomid=${data.room_id
}
&userid=${data.user_id
}
&autoLogin=true&viewername=${data.viewer_name
}
&viewertoken=${data.viewer_token
}
`
this
.
openNewWindow
(
url
)
}
else
if
(
liveStatus
===
103
&&
data
.
enable_record
===
1
)
{
}
else
if
(
liveStatus
===
2
&&
data
.
enable_record
===
1
)
{
// enable_record 0:不启用回放 1:开启回放
// 查看回放
const
url
=
`https://view.csslcloud.net/api/view/callback?recordid=${data.record_id
}
&roomid=${data.room_id
}
&userid=${data.user_id
}
&autoLogin=true&viewername=${data.viewer_name
}
&viewertoken=${data.viewer_token
}
`
this
.
openNewWindow
(
url
)
//
const url = `https://view.csslcloud.net/api/view/callback?recordid=$
{
data
.
record_id
}
&
roomid
=
$
{
data
.
room_id
}
&
userid
=
$
{
data
.
user_id
}
&
autoLogin
=
true
&
viewername
=
$
{
data
.
viewer_name
}
&
viewertoken
=
$
{
data
.
viewer_token
}
`
this.openNewWindow(
data.record_
url)
}
else {
this.message && this.message.close()
this.message = this.$message({ type: 'warning', offset: 0, message
}
)
...
...
@@ -222,10 +221,7 @@ export default {
const map = {
0: this.$t('live.notStarted'),
1: this.$t('live.liveStreaming'),
2
:
this
.
$t
(
'live.liveEnd'
),
101
:
this
.
$t
(
'live.liveEndNotVideo'
),
102
:
this
.
$t
(
'live.liveEndNotVideo'
),
103
:
this
.
$t
(
'live.watchReplay'
)
2: this.$t('live.liveEnd')
}
let result = map[liveStatus] || liveTime
...
...
client/src/pages/player/chapterExam/chapterExam.vue
浏览文件 @
5632ae6b
...
...
@@ -158,7 +158,7 @@ export default {
let
str
=
''
let
stuAnswer
=
''
// 学生答案
let
stuIsCorrect
=
0
// 学生是否答对
let
_json
=
JSON
.
parse
(
_
.
question_options
)
let
_json
=
_
.
question_options
?
JSON
.
parse
(
_
.
question_options
)
:
[]
_json
.
forEach
(
function
(
__
,
j
)
{
if
(
__
.
checked
)
{
switch
(
j
)
{
...
...
client/src/pages/player/chapterExam/chapterExam2.vue
0 → 100644
浏览文件 @
5632ae6b
差异被折叠。
点击展开。
client/src/pages/player/exam/exam.vue
浏览文件 @
5632ae6b
差异被折叠。
点击展开。
client/src/pages/player/index.vue
浏览文件 @
5632ae6b
...
...
@@ -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/live/live.vue
浏览文件 @
5632ae6b
...
...
@@ -51,8 +51,8 @@ export default {
cAction
.
Player
.
getChapterList
(
this
.
cid
,
this
.
sid
,
this
.
id
).
then
(
json
=>
{
this
.
live
=
(
json
.
curJson
&&
json
.
curJson
.
live
)
||
{}
if
(
this
.
live
.
id
)
{
if
(
this
.
live
.
record_id
&&
this
.
live
.
live_status
===
103
)
{
this
.
live
.
url
=
'https://view.csslcloud.net/api/view/callback?recordid='
+
this
.
live
.
record_id
+
'&roomid='
+
this
.
live
.
room_id
+
'&userid='
+
this
.
live
.
user_id
+
'&autoLogin=true&viewername='
+
this
.
live
.
viewer_name
+
'&viewertoken='
+
this
.
live
.
viewer_token
// + '&groupid=xxx'
if
(
this
.
live
.
live_status
===
2
&&
this
.
live
.
enable_record
&&
this
.
live
.
record_url
)
{
this
.
live
.
url
=
this
.
live
.
record_url
}
else
{
this
.
$emit
(
'changeSideBar'
,
''
)
setTimeout
(()
=>
{
...
...
client/src/pages/player/rightSide/sideChapterList.vue
浏览文件 @
5632ae6b
...
...
@@ -70,16 +70,14 @@ export default {
this
.
$router
.
push
({
path
:
`/player/
${
sid
}
/
${
cid
}
/exam/
${
_id
}
`
})
}
else
if
(
_course
.
chapters
[
i2
].
type
===
5
)
{
const
status
=
_course
.
chapters
[
i2
].
live
.
live_status
if
(
status
!==
0
&&
status
!==
1
&&
status
!==
103
)
{
this
.
$message
.
error
(
_course
.
chapters
[
i2
].
live
.
statusStr
)
return
}
const
enableRecord
=
_course
.
chapters
[
i2
].
live
.
enable_record
if
(
status
===
103
&&
enableRecord
!==
undefined
&&
enableRecord
!==
null
&&
!
enableRecord
)
{
if
(
status
===
2
&&
enableRecord
)
{
this
.
$message
.
info
(
'该直播没有回放'
)
return
}
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
].
chapterId
}
`
})
}
return
}
...
...
client/src/router/routes.js
浏览文件 @
5632ae6b
//
import viewerRoutes from '@/modules/viewer/routes.js'
import
viewerRoutes
from
'@/modules/viewer/routes.js'
export
default
[
{
path
:
'/'
,
redirect
:
'/app/learn/course'
},
...
...
@@ -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'
,
...
...
@@ -285,7 +291,7 @@ export default [
// /* survey-phone 内未找到页面时 - 指向 */
// { path: '/survey-phone/*', redirect: '/learn-error/learn-error' },
/* 如果所有页面都没找到 - 指向 */
{
path
:
'*'
,
component
:
()
=>
import
(
'@/components/errorPages/404.vue'
)
}
{
path
:
'*'
,
component
:
()
=>
import
(
'@/components/errorPages/404.vue'
)
}
,
// viewer module routes
//
...viewerRoutes
...
viewerRoutes
]
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论