Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
L
learn-online-pc
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
learn-online-pc
Commits
be659e74
提交
be659e74
authored
6月 03, 2020
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update viewer module
上级
d69faf21
全部展开
显示空白字符变更
内嵌
并排
正在显示
22 个修改的文件
包含
685 行增加
和
168 行删除
+685
-168
CourseAction.js
client/src/action/CourseAction.js
+26
-8
api.js
client/src/modules/viewer/api.js
+24
-2
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
upload.vue
client/src/modules/viewer/components/common/upload.vue
+30
-4
layout.vue
client/src/modules/viewer/components/layout.vue
+3
-0
chapterPlayer.vue
...nt/src/modules/viewer/components/player/chapterPlayer.vue
+120
-7
pptPlayer.vue
client/src/modules/viewer/components/player/pptPlayer.vue
+18
-11
videoPlayer.vue
client/src/modules/viewer/components/player/videoPlayer.vue
+15
-1
fileList.vue
client/src/modules/viewer/components/read/fileList.vue
+1
-1
chapterExam.vue
client/src/modules/viewer/components/work/chapterExam.vue
+0
-0
chapterTest.vue
client/src/modules/viewer/components/work/chapterTest.vue
+274
-0
chapterWork.vue
client/src/modules/viewer/components/work/chapterWork.vue
+4
-4
courseExam.vue
client/src/modules/viewer/components/work/courseExam.vue
+48
-76
courseWork.vue
client/src/modules/viewer/components/work/courseWork.vue
+1
-1
examItem.vue
client/src/modules/viewer/components/work/examItem.vue
+64
-9
index.vue
client/src/modules/viewer/components/work/index.vue
+3
-3
index.vue
client/src/modules/viewer/index.vue
+11
-3
course.vue
client/src/pages/learn/course.vue
+1
-1
courseDetail.vue
client/src/pages/learn/courseDetail.vue
+0
-0
routes.js
client/src/router/routes.js
+3
-3
没有找到文件。
client/src/action/CourseAction.js
浏览文件 @
be659e74
...
...
@@ -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
)
=>
{
...
...
@@ -173,35 +187,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/modules/viewer/api.js
浏览文件 @
be659e74
...
...
@@ -35,6 +35,27 @@ 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
...
...
@@ -130,8 +151,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
浏览文件 @
be659e74
<
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
)
{
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
浏览文件 @
be659e74
...
...
@@ -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
浏览文件 @
be659e74
<
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/upload.vue
浏览文件 @
be659e74
<
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,6 +15,17 @@
<i
class=
"el-icon-document"
></i>
{{ fileUrl | fileName }}
</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>
...
...
@@ -23,6 +34,7 @@
</div>
</div>
</div>
</div>
</template>
<
script
>
...
...
@@ -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
)
{
value
:
{
immediate
:
true
,
handler
(
value
)
{
if
(
value
)
{
this
.
fileList
=
Array
.
isArray
(
value
)
?
value
:
[
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
浏览文件 @
be659e74
...
...
@@ -13,6 +13,7 @@
// components
import
ChapterPlayer
from
'./player/ChapterPlayer.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/player/chapterPlayer.vue
浏览文件 @
be659e74
...
...
@@ -7,15 +7,18 @@
:isSkip=
"isSkip"
: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 +33,8 @@
</
template
>
<
script
>
import
Cookies
from
'js-cookie'
import
{
throttle
}
from
'lodash'
// api
import
*
as
api
from
'../../api'
// components
...
...
@@ -46,11 +51,23 @@ 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
,
chatperResources
:
null
,
throttled
:
null
,
throttleWait
:
10
,
// 秒
progress
:
{
cpt
:
0
,
// 当前播放时间
mpt
:
0
,
// 视频时长
progress
:
0
,
// 进度
pt
:
0
// 累计播放时间
},
player
:
null
,
watchedTimePoint
:
[]
// 视频观看的时间点
}
},
watch
:
{
...
...
@@ -59,6 +76,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,11 +120,29 @@ 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
)
}
},
// 当前播放时间更新
onTimeupdate
(
time
)
{
const
ppts
=
this
.
chatperResources
.
ppts
||
[]
...
...
@@ -108,12 +151,29 @@ export default {
)
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 +185,66 @@ 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
=
[]
}
},
beforeMount
()
{
// 获取视频
this
.
getChapterVideo
()
// 获取视频进度
this
.
getChapterVideoProgress
()
}
}
</
script
>
...
...
@@ -148,6 +260,7 @@ export default {
.player-main
{
display
:
flex
;
flex
:
1
;
overflow
:
hidden
;
}
.player-column
{
flex
:
1
;
...
...
client/src/modules/viewer/components/player/pptPlayer.vue
浏览文件 @
be659e74
...
...
@@ -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>
<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,22 +42,23 @@ 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
)
{
if
(
this
.
isSync
)
{
this
.
currentIndex
=
value
}
}
}
},
computed
:
{
pptUrl
()
{
...
...
@@ -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
浏览文件 @
be659e74
...
...
@@ -13,13 +13,22 @@ 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
,
controlBarVisibility
:
'always'
,
components
:
[
...
...
@@ -30,6 +39,11 @@ export default {
]
},
function
(
player
)
{
player
.
on
(
'ready'
,
function
()
{
// 跳过片头
_this
.
isSkip
&&
player
.
seek
(
6
)
_this
.
$emit
(
'ready'
,
player
)
})
player
.
on
(
'sourceloaded'
,
function
(
params
)
{
const
paramData
=
params
.
paramData
const
desc
=
paramData
.
desc
...
...
client/src/modules/viewer/components/read/fileList.vue
浏览文件 @
be659e74
...
...
@@ -6,7 +6,7 @@
<i
class=
"el-icon-document"
></i>
{{
file
.
file_name
}}
</a>
<
span
v-if=
"file.file_size"
>
{{
file
.
file_size
}}
</span
>
<
!--
<span
v-if=
"file.file_size"
>
{{
file
.
file_size
}}
K
</span>
--
>
<a
:href=
"file.file_url"
:download=
"file.file_name"
target=
"_blank"
>
<el-tooltip
effect=
"dark"
content=
"下载"
>
<i
class=
"el-icon-download"
></i>
...
...
client/src/modules/viewer/components/work/chapterExam.vue
浏览文件 @
be659e74
差异被折叠。
点击展开。
client/src/modules/viewer/components/work/chapterTest.vue
0 → 100644
浏览文件 @
be659e74
<
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
.
getChapterExam
(
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
.
sbumitChapterExam
(
params
).
then
(
response
=>
{
if
(
response
.
status
)
{
this
.
getDetail
()
}
else
{
this
.
$message
.
error
(
response
.
data
.
error
)
}
})
}
},
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
浏览文件 @
be659e74
...
...
@@ -214,12 +214,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
}
...
...
client/src/modules/viewer/components/work/courseExam.vue
浏览文件 @
be659e74
<
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,32 +18,12 @@
@
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"
>
<template
v-for=
"items in questions"
>
<exam-item
v-for=
"(item, index) in question
s"
v-for=
"(item, index) in item
s"
:index=
"index"
:type=
"item.type"
:data=
"item"
...
...
@@ -50,6 +31,7 @@
: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,10 +147,11 @@ export default {
})
},
// 组装问题数据
genQue
nstions
(
data
)
{
if
(
!
data
)
{
return
genQue
stions
(
list
)
{
if
(
!
list
)
{
return
[]
}
return
list
.
map
(
data
=>
{
let
{
radioList
,
checkboxList
,
shortAnswerList
}
=
data
// 单选
radioList
=
radioList
.
map
(
item
=>
{
...
...
@@ -200,14 +176,15 @@ export default {
formModel
:
{
id
:
item
.
id
,
user_answer
:
item
.
user_answer
?
Base64
.
decode
(
item
.
user_answer
)
?
Base64
.
decode
(
item
.
user_answer
.
replace
(
/ /gi
,
'+'
)
)
:
''
,
attachments
:
[]
attachments
:
item
.
attachments
||
[]
}
}
return
Object
.
assign
({},
item
,
temp
)
})
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,13 +221,15 @@ export default {
},
// 提交校验
checkSubmit
()
{
const
quenstions
=
this
.
questions
for
(
let
i
=
0
;
i
<
quenstions
.
length
;
i
++
)
{
const
value
=
quenstions
[
i
].
formModel
.
user_answer
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
浏览文件 @
be659e74
...
...
@@ -109,7 +109,7 @@ export default {
rules
:
{
essay_name
:
[
{
required
:
true
,
message
:
'请输入主题'
,
trigger
:
'blur'
},
{
max
:
5
,
message
:
'最多输入 50 个字符'
,
trigger
:
'blur'
}
{
max
:
5
0
,
message
:
'最多输入 50 个字符'
,
trigger
:
'blur'
}
],
essay_description
:
[
{
required
:
true
,
message
:
'请输入正文'
,
trigger
:
'blur'
}
...
...
client/src/modules/viewer/components/work/examItem.vue
浏览文件 @
be659e74
...
...
@@ -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,17 +24,18 @@
<!-- 简答题 -->
<
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>
<span>
评语:
</span>
<span>
{{
data
.
check_comment
}}
</span>
</p>
</
template
>
<
template
v-else
>
<div
class=
"result"
>
<p>
<span>
学生答案:
</span>
<span
:class=
"isCorrect ? 'is-success' : 'is-error'"
>
{{
submitAnswerText
}}
</span>
...
...
@@ -40,7 +44,24 @@
<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
{
padding
:
10px
0
;
p
{
font-size
:
14px
;
margin
:
0
0
10px
0
;
}
.result
{
display
:
flex
;
justify-content
:
flex-end
;
padding
:
10px
0
;
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-left
:
20px
;
padding
:
0
;
max-width
:
100%
;
}
}
}
</
style
>
client/src/modules/viewer/components/work/index.vue
浏览文件 @
be659e74
...
...
@@ -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
浏览文件 @
be659e74
...
...
@@ -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/learn/course.vue
浏览文件 @
be659e74
...
...
@@ -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
浏览文件 @
be659e74
差异被折叠。
点击展开。
client/src/router/routes.js
浏览文件 @
be659e74
//
import viewerRoutes from '@/modules/viewer/routes.js'
import
viewerRoutes
from
'@/modules/viewer/routes.js'
export
default
[
{
path
:
'/'
,
redirect
:
'/app/learn/course'
},
...
...
@@ -291,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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论