提交 be659e74 authored 作者: 王鹏飞's avatar 王鹏飞

update viewer module

上级 d69faf21
...@@ -104,8 +104,22 @@ export default class CourseAction extends BaseACTION { ...@@ -104,8 +104,22 @@ export default class CourseAction extends BaseACTION {
unit: item.lecturer_title || '' 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 = { json.tabs1ChapterList = {
currentChapter: findChapter(cur.latest_play, data.chapters),
currentChapterId: cur.latest_play || '', currentChapterId: cur.latest_play || '',
currentVideoProvider: cur.latest_play_type || '1', currentVideoProvider: cur.latest_play_type || '1',
course: cur.chapters.map((_, i) => { course: cur.chapters.map((_, i) => {
...@@ -173,35 +187,39 @@ export default class CourseAction extends BaseACTION { ...@@ -173,35 +187,39 @@ export default class CourseAction extends BaseACTION {
title: '课程大作业', title: '课程大作业',
isUp: true, isUp: true,
chapters: [], chapters: [],
type: 'course_work', id: 'course_work',
sid: sid, sid: sid,
cid: cid cid: cid,
type: 99
}) })
json.tabs1ChapterList.course.push({ json.tabs1ChapterList.course.push({
title: '课程资料', title: '课程资料',
isUp: true, isUp: true,
chapters: [], chapters: [],
type: 'course_info', id: 'course_info',
sid: sid, sid: sid,
cid: cid cid: cid,
type: 100
}) })
json.tabs1ChapterList.course.push({ json.tabs1ChapterList.course.push({
title: '教学评估', title: '教学评估',
isUp: true, isUp: true,
chapters: [], chapters: [],
type: 'teach_evaluation', id: 'teach_evaluation',
sid: sid, sid: sid,
cid: cid cid: cid,
type: 102
}) })
if (cur.course_examination) { if (cur.course_examination) {
json.tabs1ChapterList.course.push({ json.tabs1ChapterList.course.push({
title: '课程考试', title: '课程考试',
isUp: true, isUp: true,
chapters: [], chapters: [],
type: 'exam', id: 'course_exam',
sid: sid, sid: sid,
cid: cid, cid: cid,
examId: cur.course_examination examId: cur.course_examination,
type: 102
}) })
} }
/* 课程考核 考核标准文案读取 */ /* 课程考核 考核标准文案读取 */
......
...@@ -35,6 +35,27 @@ export function getChapterVideoAliyun(vid) { ...@@ -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 * @param {string} semesterId 学期ID
...@@ -130,8 +151,9 @@ export function submitCourseExam(semesterId, courseId, examId, data) { ...@@ -130,8 +151,9 @@ export function submitCourseExam(semesterId, courseId, examId, data) {
* @param {string} courseId 课程ID * @param {string} courseId 课程ID
* @param {string} examId 试题ID * @param {string} examId 试题ID
*/ */
export function getCourseExamResult(semesterId, courseId, examId) { export function getCourseExamResult(semesterId, courseId, examId, params) {
return httpRequest.get( return httpRequest.get(
`/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet` `/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`,
params
) )
} }
<template> <template>
<ul class="chapter-list"> <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> <h4>{{item.name}}</h4>
<ul class="chapter-item-list"> <ul class="chapter-item-list">
<li <li
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
@click="onClick(subItem)" @click="onClick(subItem)"
:class="{'is-active': subItem.id === (active ? active.id : '')}" :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> <i class="el-icon" :class="genIconClass(subItem.type)"></i>
</li> </li>
</ul> </ul>
...@@ -20,7 +20,14 @@ ...@@ -20,7 +20,14 @@
<script> <script>
export default { export default {
props: { props: {
data: { type: Array, default: () => [] }, // 课程详情接口返回的数据
data: {
type: Object,
default() {
return {}
}
},
chapters: { type: Array, default: () => [] },
// 当前选中的章节 // 当前选中的章节
active: { active: {
type: Object, type: Object,
...@@ -30,26 +37,13 @@ export default { ...@@ -30,26 +37,13 @@ export default {
} }
}, },
data() { data() {
return { return {}
otherList: [
{
name: '大作业及资料',
children: [
{ name: '课程大作业', id: 'course_work' },
{ name: '课程资料', id: 'course_info' },
{ name: '教学评估', id: 'teach_evaluation' }
]
}
]
}
},
computed: {
list() {
return this.data.concat(this.otherList)
}
}, },
filters: { filters: {
showName(name, type) { showName(name, data) {
if (data.type === 5) {
return `${name}(${data.live.start_time})`
}
return name return name
} }
}, },
...@@ -63,16 +57,20 @@ export default { ...@@ -63,16 +57,20 @@ export default {
return map[type] || 'el-icon-self-cc-book' return map[type] || 'el-icon-self-cc-book'
}, },
onClick(data) { onClick(data) {
if (data.type === 1) {
return
}
// 课程大作业 // 课程大作业
// if (data.id === 'course_work') { if (data.id === 'course_work' && !this.data.survey) {
// this.$router.push({ name: 'viewerCourseWork' }) this.$message('请先填写教学评估,然后完成大作业。')
// return return
// } }
// 课程资料 // 教学评估
// if (data.id === 'course_info') { if (data.id === 'teach_evaluation') {
// this.$router.push({ name: 'viewerCourseFile' }) const { sid, cid } = this.$route.params
// return this.$router.push({ name: 'survey', params: { sid, cid } })
// } return
}
this.$router.push({ this.$router.push({
name: 'viewerCourseChapter', name: 'viewerCourseChapter',
params: { id: data.id } params: { id: data.id }
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
<el-tabs v-model="activeName"> <el-tabs v-model="activeName">
<el-tab-pane label="章节" name="0"> <el-tab-pane label="章节" name="0">
<div class="tab-pane"> <div class="tab-pane">
<aside-chapter :data="chapters" :active="active"></aside-chapter> <aside-chapter :data="data" :chapters="chapters" :active="active"></aside-chapter>
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="讲义" name="1" v-if="active && active.type === 2"> <el-tab-pane label="讲义" name="1" v-if="active && active.type === 2">
<div class="tab-pane"> <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> </div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
...@@ -21,6 +21,13 @@ import AsideLecture from './lecture.vue' ...@@ -21,6 +21,13 @@ import AsideLecture from './lecture.vue'
export default { export default {
props: { props: {
// 课程详情接口返回的数据
data: {
type: Object,
default() {
return {}
}
},
// 章节 // 章节
chapters: { type: Array, default: () => [] }, chapters: { type: Array, default: () => [] },
// 讲义 // 讲义
......
<template> <template>
<ul class="lecture-list"> <ul class="lecture-list">
<li <li
v-for="(item, index) in data" v-for="(item, index) in ppts"
:key="item.id" :key="item.id"
@click="onClick(index)" @click="onClick(index)"
:class="{'is-active': index === activeIndex}" :class="{'is-active': index === activeIndex}"
...@@ -16,7 +16,7 @@ export default { ...@@ -16,7 +16,7 @@ export default {
props: { props: {
// 当前选择的PPT // 当前选择的PPT
pptIndex: { type: Number, default: 0 }, pptIndex: { type: Number, default: 0 },
data: { type: Array, default: () => [] } ppts: { type: Array, default: () => [] }
}, },
data() { data() {
return { return {
......
<template> <template>
<div class="upload"> <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> <slot></slot>
<el-button type="text" icon="el-icon-upload">点击上传</el-button> <el-button type="text" icon="el-icon-upload">点击上传</el-button>
<template v-slot:tip> <template v-slot:tip>
...@@ -15,11 +15,23 @@ ...@@ -15,11 +15,23 @@
<i class="el-icon-document"></i> <i class="el-icon-document"></i>
{{ fileUrl | fileName }} {{ fileUrl | fileName }}
</a> </a>
<a :href="fileUrl" :download="fileUrl | fileName" target="_blank"> <div>
<el-tooltip effect="dark" content="下载"> <a
<i class="el-icon-download"></i> href="javascript:;"
</el-tooltip> @click="handleRemove(index)"
</a> 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> </div>
</div> </div>
...@@ -31,7 +43,8 @@ import * as api from '../../api' ...@@ -31,7 +43,8 @@ import * as api from '../../api'
export default { export default {
name: 'VUpload', name: 'VUpload',
props: { props: {
value: { type: [String, Array] } value: { type: [String, Array] },
disabled: { type: Boolean, default: false }
}, },
data() { data() {
return { return {
...@@ -39,9 +52,18 @@ export default { ...@@ -39,9 +52,18 @@ export default {
} }
}, },
watch: { watch: {
value(value) { value: {
if (value) { immediate: true,
this.fileList = Array.isArray(value) ? value : [value] 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 { ...@@ -63,6 +85,10 @@ export default {
} }
} }
}) })
},
handleRemove(index) {
this.fileList.splice(index, 1)
this.$emit('input', Array.isArray(this.value) ? this.fileList : '')
} }
} }
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
// components // components
import ChapterPlayer from './player/ChapterPlayer.vue' // 章节视频 import ChapterPlayer from './player/ChapterPlayer.vue' // 章节视频
import ChapterWork from './work/index.vue' // 章节作业 import ChapterWork from './work/index.vue' // 章节作业
import ChapterExam from './work/chapterExam.vue' // 章节考试
import ChapterRead from './read/chapterRead.vue' // 章节资料 import ChapterRead from './read/chapterRead.vue' // 章节资料
import ChapterLive from './live/chapterLive.vue' // 章节直播 import ChapterLive from './live/chapterLive.vue' // 章节直播
import CourseWork from './work/courseWork.vue' // 课程大作业 import CourseWork from './work/courseWork.vue' // 课程大作业
...@@ -25,6 +26,7 @@ export default { ...@@ -25,6 +26,7 @@ export default {
ChapterPlayer, ChapterPlayer,
ChapterWork, ChapterWork,
ChapterRead, ChapterRead,
ChapterExam,
ChapterLive, ChapterLive,
CourseWork, CourseWork,
CourseRead, CourseRead,
...@@ -45,6 +47,7 @@ export default { ...@@ -45,6 +47,7 @@ export default {
3: 'ChapterWork', // 作业 3: 'ChapterWork', // 作业
4: 'ChapterRead', // 资料 4: 'ChapterRead', // 资料
5: 'ChapterLive', // 直播 5: 'ChapterLive', // 直播
9: 'ChapterExam', // 考试
99: 'CourseWork', // 课程大作业 99: 'CourseWork', // 课程大作业
100: 'CourseRead', // 课程资料 100: 'CourseRead', // 课程资料
101: 'CourseExam' // 课程考试 101: 'CourseExam' // 课程考试
......
...@@ -7,15 +7,18 @@ ...@@ -7,15 +7,18 @@
:isSkip="isSkip" :isSkip="isSkip"
:video="chatperResources.video" :video="chatperResources.video"
@timeupdate="onTimeupdate" @timeupdate="onTimeupdate"
@ready="onReady"
ref="videoPlayer" ref="videoPlayer"
></video-player> ></video-player>
</div> </div>
<div class="player-column" v-if="pptVisible"> <div class="player-column" v-if="pptVisible">
<!-- ppt --> <!-- ppt -->
<ppt-player <ppt-player
:index="pptIndex"
:ppts="chatperResources.ppts" :ppts="chatperResources.ppts"
@close="pptVisible = false" @close="onPPTClose"
@fullscreen="onPPTFullscreen" @fullscreen="onPPTFullscreen"
@videoSyncTime="onVideoSyncTime"
></ppt-player> ></ppt-player>
</div> </div>
</div> </div>
...@@ -30,6 +33,8 @@ ...@@ -30,6 +33,8 @@
</template> </template>
<script> <script>
import Cookies from 'js-cookie'
import { throttle } from 'lodash'
// api // api
import * as api from '../../api' import * as api from '../../api'
// components // components
...@@ -46,11 +51,23 @@ export default { ...@@ -46,11 +51,23 @@ export default {
pptIndex: { type: Number, default: 0 } pptIndex: { type: Number, default: 0 }
}, },
data() { data() {
// 是否跳过片头
const isSkip = window.localStorage.getItem('isSkip') === 'true'
return { return {
videoVisible: true, videoVisible: true,
pptVisible: false, pptVisible: false,
isSkip: false, isSkip,
chatperResources: null chatperResources: null,
throttled: null,
throttleWait: 10, // 秒
progress: {
cpt: 0, // 当前播放时间
mpt: 0, // 视频时长
progress: 0, // 进度
pt: 0 // 累计播放时间
},
player: null,
watchedTimePoint: [] // 视频观看的时间点
} }
}, },
watch: { watch: {
...@@ -59,6 +76,14 @@ export default { ...@@ -59,6 +76,14 @@ export default {
} }
}, },
computed: { computed: {
// 学期ID
sid() {
return this.$route.params.sid
},
// 课程ID
cid() {
return this.$route.params.cid
},
// 视频资源ID // 视频资源ID
resourceId() { resourceId() {
return this.chapter.resource_id return this.chapter.resource_id
...@@ -95,11 +120,29 @@ export default { ...@@ -95,11 +120,29 @@ export default {
// 始终跳过片头 // 始终跳过片头
toggleSkip() { toggleSkip() {
this.isSkip = !this.isSkip this.isSkip = !this.isSkip
window.localStorage.setItem('isSkip', this.isSkip)
},
// 关闭PPT
onPPTClose() {
this.pptVisible = false
this.videoVisible = true
}, },
// PPT全屏 // PPT全屏
onPPTFullscreen(value) { onPPTFullscreen(value) {
this.videoVisible = !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) { onTimeupdate(time) {
const ppts = this.chatperResources.ppts || [] const ppts = this.chatperResources.ppts || []
...@@ -108,12 +151,29 @@ export default { ...@@ -108,12 +151,29 @@ export default {
) )
index = index !== -1 ? index - 1 : ppts.length - 1 index = index !== -1 ? index - 1 : ppts.length - 1
this.$emit('change-ppt', index) 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() { updateVideoCurrentTime() {
const player = this.$refs.videoPlayer.player
const ppt = this.chatperResources.ppts[this.pptIndex] const ppt = this.chatperResources.ppts[this.pptIndex]
ppt && player.seek(ppt.ppt_point) // 增加2秒 ppt && this.player.seek(ppt.ppt_point) // 增加2秒
}, },
// 获取章节视频详情 // 获取章节视频详情
getChapterVideo() { getChapterVideo() {
...@@ -125,14 +185,66 @@ export default { ...@@ -125,14 +185,66 @@ export default {
}) })
} else { } else {
api.getChapterVideo(this.resourceId).then(response => { api.getChapterVideo(this.resourceId).then(response => {
this.chatperResources = response let { video, audio, ppts } = response
Array.isArray(response.ppts) && this.$emit('pptupdate', response.ppts) 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() { beforeMount() {
// 获取视频
this.getChapterVideo() this.getChapterVideo()
// 获取视频进度
this.getChapterVideoProgress()
} }
} }
</script> </script>
...@@ -148,6 +260,7 @@ export default { ...@@ -148,6 +260,7 @@ export default {
.player-main { .player-main {
display: flex; display: flex;
flex: 1; flex: 1;
overflow: hidden;
} }
.player-column { .player-column {
flex: 1; flex: 1;
......
...@@ -19,10 +19,18 @@ ...@@ -19,10 +19,18 @@
<span>{{ppts.length}}</span> <span>{{ppts.length}}</span>
</div> </div>
<div class="ppt-player-controls__tools"> <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-quanping" @click="fullscreen"></i> <i :class="['el-icon-self-xuexiao', (isSync ? 'active' : '')]" @click="onToggleSync"></i>
<i class="el-icon-self-shipin" @click="setVideoTime"></i> </el-tooltip>
<i class="el-icon-self-guanbi" @click="$emit('close')"></i> <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>
</div> </div>
</template> </template>
...@@ -34,20 +42,21 @@ export default { ...@@ -34,20 +42,21 @@ export default {
name: 'ppt-player', name: 'ppt-player',
props: { props: {
ppts: { type: Array }, ppts: { type: Array },
index: { type: Number, default: 0 }, index: { type: Number, default: 0 }
isSync: { type: Boolean, default: false }
}, },
data() { data() {
return { return {
currentIndex: this.index, currentIndex: this.index,
currentSync: this.isSync, isSync: true,
isFullscreen: false isFullscreen: false
} }
}, },
watch: { watch: {
index: { index: {
handler(value) { handler(value) {
this.currentIndex = value if (this.isSync) {
this.currentIndex = value
}
} }
} }
}, },
...@@ -67,20 +76,18 @@ export default { ...@@ -67,20 +76,18 @@ export default {
}, },
prev() { prev() {
this.currentIndex = this.getIndex(this.currentIndex - 1) this.currentIndex = this.getIndex(this.currentIndex - 1)
this.currentSync = false this.isSync = false
}, },
next(e) { next(e) {
this.currentIndex = this.getIndex(this.currentIndex + 1) this.currentIndex = this.getIndex(this.currentIndex + 1)
this.currentSync = false this.isSync = false
}, },
onToggleSync(e) { onToggleSync(e) {
this.currentSync = !this.currentSync this.isSync = !this.isSync
this.currentIndex = this.currentSync
? this.currentIndex
: this.currentIndex
}, },
setVideoTime(e) { setVideoTime(e) {
this.$emit('onVideoSyncTime', this.ppts[this.currentIndex].ppt_point) this.isSync = true
this.$emit('videoSyncTime', this.ppts[this.currentIndex].ppt_point)
}, },
// 全屏 // 全屏
fullscreen() { fullscreen() {
......
...@@ -13,13 +13,22 @@ export default { ...@@ -13,13 +13,22 @@ export default {
createPlayer() { createPlayer() {
const _this = this const _this = this
const { FD, LD, SD } = this.video const { FD, LD, SD } = this.video
/*
"OD" : "原画"
"FD" : "流畅"
"LD" : "标清"
"SD" : "高清"
"HD" : "超清"
"2K" : "2K"
"4K" : "4K"
*/
this.player = new Aliplayer( this.player = new Aliplayer(
{ {
id: 'player', id: 'player',
source: JSON.stringify({ FD, LD, SD }), source: JSON.stringify({ FD, LD, SD }),
width: '100%', width: '100%',
height: '100%', height: '100%',
autoplay: true, autoplay: false,
isLive: false, isLive: false,
controlBarVisibility: 'always', controlBarVisibility: 'always',
components: [ components: [
...@@ -30,6 +39,11 @@ export default { ...@@ -30,6 +39,11 @@ export default {
] ]
}, },
function(player) { function(player) {
player.on('ready', function() {
// 跳过片头
_this.isSkip && player.seek(6)
_this.$emit('ready', player)
})
player.on('sourceloaded', function(params) { player.on('sourceloaded', function(params) {
const paramData = params.paramData const paramData = params.paramData
const desc = paramData.desc const desc = paramData.desc
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<i class="el-icon-document"></i> <i class="el-icon-document"></i>
{{ file.file_name }} {{ file.file_name }}
</a> </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"> <a :href="file.file_url" :download="file.file_name" target="_blank">
<el-tooltip effect="dark" content="下载"> <el-tooltip effect="dark" content="下载">
<i class="el-icon-download"></i> <i class="el-icon-download"></i>
......
<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>
...@@ -214,12 +214,12 @@ export default { ...@@ -214,12 +214,12 @@ export default {
) )
// 提交的答案数据 // 提交的答案数据
const answers = this.questions.map(item => { const answers = this.questions.map(item => {
if (item.question_type === 3) {
item.formModel.user_answer = Base64.encode(item.formModel.user_answer)
}
return { return {
question_id: item.id, 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, file_url: item.formModel.attachments,
is_encoded: 1 is_encoded: 1
} }
......
<template> <template>
<container :title="detail.title" v-loading="loading"> <container :title="detail.title" v-loading="loading">
<template v-slot:header-aside v-if="isExamComplete">分数:{{exam.score.total}}</template>
<div class="exam"> <div class="exam">
<template v-if="status.examination_status === '00'"> <template v-if="status.examination_status === '00'">
<div class="no-exam">暂无考试</div> <div class="no-exam">暂无考试</div>
...@@ -17,39 +18,20 @@ ...@@ -17,39 +18,20 @@
@click="onStartExam" @click="onStartExam"
>{{startExamButtonText}}</el-button> >{{startExamButtonText}}</el-button>
</div> </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"> <el-form :disabled="isSubmited">
<exam-item <template v-for="items in questions">
v-for="(item, index) in questions" <exam-item
:index="index" v-for="(item, index) in items"
:type="item.type" :index="index"
:data="item" :type="item.type"
:value="item.formModel" :data="item"
:disabled="isSubmited" :value="item.formModel"
:key="item.id" :disabled="isSubmited"
></exam-item> :key="item.id"
></exam-item>
</template>
<div class="exam-buttons"> <div class="exam-buttons">
<el-tooltip effect="dark" content="提交之后就不能修改了哦" placement="right"> <el-tooltip effect="dark" content="提交之后就不能修改了哦" placement="right">
<el-button type="primary" @click="onSubmit">{{submitText}}</el-button> <el-button type="primary" @click="onSubmit">{{submitText}}</el-button>
...@@ -97,18 +79,11 @@ export default { ...@@ -97,18 +79,11 @@ export default {
detail: {}, detail: {},
status: {}, status: {},
questions: [], questions: [],
values: [], // 提交的答案
messageInstance: null, messageInstance: null,
exam: {}, exam: {},
isStartExam: false, // 是否开始考试 isStartExam: false, // 是否开始考试
autoSubmitTimer: null, // 自动提交定时器 autoSubmitTimer: null, // 自动提交定时器
checkStatusTimer: null, // 考试状态定时器 checkStatusTimer: null // 考试状态定时器
examVisible: true
}
},
watch: {
isExamComplete(value) {
this.examVisible = !value
} }
}, },
computed: { computed: {
...@@ -163,7 +138,7 @@ export default { ...@@ -163,7 +138,7 @@ export default {
this.detail = Array.isArray(response) ? null : response this.detail = Array.isArray(response) ? null : response
// 设置问题列表数据 // 设置问题列表数据
this.questions = this.detail this.questions = this.detail
? this.genQuenstions(this.detail.examination) ? this.genQuestions(this.detail.examination)
: [] : []
callback && callback() callback && callback()
}) })
...@@ -172,42 +147,44 @@ export default { ...@@ -172,42 +147,44 @@ export default {
}) })
}, },
// 组装问题数据 // 组装问题数据
genQuenstions(data) { genQuestions(list) {
if (!data) { if (!list) {
return return []
} }
let { radioList, checkboxList, shortAnswerList } = data return list.map(data => {
// 单选 let { radioList, checkboxList, shortAnswerList } = data
radioList = radioList.map(item => { // 单选
const temp = { radioList = radioList.map(item => {
type: 1, const temp = {
formModel: { id: item.id, user_answer: item.user_answer || '' } 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 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() { getExamStatus() {
...@@ -234,7 +211,7 @@ export default { ...@@ -234,7 +211,7 @@ export default {
if (response.code !== 8001) { if (response.code !== 8001) {
this.isStartExam = true this.isStartExam = true
this.exam = response this.exam = response
this.questions = this.genQuenstions(response.sheet) this.questions = this.genQuestions(response.sheet)
// 自动提交 // 自动提交
if (this.isStartExam && !this.isSubmited && !this.isExamComplete) { if (this.isStartExam && !this.isSubmited && !this.isExamComplete) {
this.autoSubmit() this.autoSubmit()
...@@ -244,11 +221,13 @@ export default { ...@@ -244,11 +221,13 @@ export default {
}, },
// 提交校验 // 提交校验
checkSubmit() { checkSubmit() {
const quenstions = this.questions for (let i = 0; i < this.questions.length; i++) {
for (let i = 0; i < quenstions.length; i++) { const questions = this.questions[i]
const value = quenstions[i].formModel.user_answer for (let k = 0; k < questions.length; k++) {
if (Array.isArray(value) ? !value.length : !value) { const value = questions[k].formModel.user_answer
return false if (Array.isArray(value) ? !value.length : !value) {
return false
}
} }
} }
return true return true
...@@ -262,12 +241,7 @@ export default { ...@@ -262,12 +241,7 @@ export default {
return return
} }
// 提交的答案数据 // 提交的答案数据
const answers = this.questions.map(item => { const answers = this.handleSubmitData()
if (item.type === 3) {
item.formModel.user_answer = Base64.encode(item.formModel.user_answer)
}
return item.formModel
})
// 提交参数 // 提交参数
const params = { answers: JSON.stringify(answers), type: 1 } const params = { answers: JSON.stringify(answers), type: 1 }
// 请求接口 // 请求接口
...@@ -279,19 +253,38 @@ export default { ...@@ -279,19 +253,38 @@ export default {
this.autoSubmitTimer && clearInterval(this.autoSubmitTimer) this.autoSubmitTimer && clearInterval(this.autoSubmitTimer)
this.autoSubmitTimer = setInterval(() => { this.autoSubmitTimer = setInterval(() => {
// 提交的答案数据 // 提交的答案数据
const answers = this.questions.map(item => { const answers = this.handleSubmitData()
if (item.type === 3) {
item.formModel.user_answer = Base64.encode(
item.formModel.user_answer
)
}
return item.formModel
})
const params = { answers: JSON.stringify(answers), type: 0 } const params = { answers: JSON.stringify(answers), type: 0 }
// 请求接口 // 请求接口
this.handleSubmitRequest(params) this.handleSubmitRequest(params)
}, 10000) }, 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) { handleSubmitRequest(params) {
api api
...@@ -344,27 +337,6 @@ export default { ...@@ -344,27 +337,6 @@ export default {
font-size: 30px; font-size: 30px;
text-align: center; 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 { .exam-welcome {
padding: 40px; padding: 40px;
line-height: 30px; line-height: 30px;
......
...@@ -109,7 +109,7 @@ export default { ...@@ -109,7 +109,7 @@ export default {
rules: { rules: {
essay_name: [ essay_name: [
{ required: true, message: '请输入主题', trigger: 'blur' }, { required: true, message: '请输入主题', trigger: 'blur' },
{ max: 5, message: '最多输入 50 个字符', trigger: 'blur' } { max: 50, message: '最多输入 50 个字符', trigger: 'blur' }
], ],
essay_description: [ essay_description: [
{ required: true, message: '请输入正文', trigger: 'blur' } { required: true, message: '请输入正文', trigger: 'blur' }
......
...@@ -2,8 +2,11 @@ ...@@ -2,8 +2,11 @@
<div class="q-item"> <div class="q-item">
<div class="q-item-hd"> <div class="q-item-hd">
<div class="q-item-num">{{index + 1}}.</div> <div class="q-item-num">{{index + 1}}.</div>
<div class="q-item-title" v-html="data.content">{{data.title}}</div> <div class="q-item-title" v-html="data.content"></div>
<div class="q-item-aside" v-if="typeText">({{typeText}})</div> <div class="q-item-aside">
<template v-if="typeText">({{typeText}})</template>
<template v-if="data.hasOwnProperty('score')">({{data.score}}分)</template>
</div>
</div> </div>
<div class="q-item-bd"> <div class="q-item-bd">
<!-- 单选 --> <!-- 单选 -->
...@@ -21,26 +24,44 @@ ...@@ -21,26 +24,44 @@
<!-- 简答题 --> <!-- 简答题 -->
<template v-if="type === 3"> <template v-if="type === 3">
<v-editor v-model="currentValue.user_answer" :disabled="disabled"></v-editor> <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> </template>
</div> </div>
<div class="q-item-ft" v-if="disabled"> <div class="q-item-ft" v-if="disabled">
<template v-if="type === 3"> <template v-if="type === 3">
<p> <p>
<span>老师评语:</span> <span>评语:</span>
<span>{{data.check_comment}}</span> <span>{{data.check_comment}}</span>
</p> </p>
</template> </template>
<template v-else> <template v-else>
<p> <div class="result">
<span>学生答案:</span> <p>
<span :class="isCorrect ? 'is-success' : 'is-error'">{{submitAnswerText}}</span> <span>学生答案:</span>
</p> <span :class="isCorrect ? 'is-success' : 'is-error'">{{submitAnswerText}}</span>
<p> </p>
<span>正确答案:</span> <p>
<span>{{correctAnswerText}}</span> <span>正确答案:</span>
</p> <span>{{correctAnswerText}}</span>
</p>
</div>
</template> </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>
</div> </div>
</template> </template>
...@@ -77,7 +98,8 @@ export default { ...@@ -77,7 +98,8 @@ export default {
}, },
data() { data() {
return { return {
currentValue: {} currentValue: {},
showAnalyze: false
} }
}, },
watch: { watch: {
...@@ -116,6 +138,14 @@ export default { ...@@ -116,6 +138,14 @@ export default {
item.selected = Array.isArray(value) item.selected = Array.isArray(value)
? value.includes(item.id) ? value.includes(item.id)
: value === 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 return item
}) })
}, },
...@@ -190,14 +220,16 @@ export default { ...@@ -190,14 +220,16 @@ export default {
} }
.q-item-title { .q-item-title {
flex: 1; flex: 1;
padding: 0 10px; ::v-deep img {
max-width: 100%;
}
} }
.q-item-aside { .q-item-aside {
padding-left: 20px; padding-left: 20px;
// align-self: flex-end; // align-self: flex-end;
} }
.q-option-item { .q-option-item {
padding-left: 30px; padding-left: 20px;
margin-bottom: 14px; margin-bottom: 14px;
} }
.is-success { .is-success {
...@@ -229,13 +261,36 @@ export default { ...@@ -229,13 +261,36 @@ export default {
} }
} }
.q-item-ft { .q-item-ft {
display: flex;
justify-content: flex-end;
padding: 10px 0; padding: 10px 0;
p { p {
font-size: 14px; font-size: 14px;
margin: 0; margin: 0 0 10px 0;
padding-left: 20px; }
.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: #c9c9c97a;
border: 1px solid #c9c9c97a;
padding: 10px;
::v-deep * {
margin: 0;
padding: 0;
max-width: 100%;
}
} }
} }
</style> </style>
...@@ -12,11 +12,11 @@ ...@@ -12,11 +12,11 @@
<script> <script>
// componets // componets
import ChapterWork from './chapterWork.vue' import ChapterWork from './chapterWork.vue'
import ChapterExam from './chapterExam.vue' import ChapterTest from './ChapterTest.vue'
export default { export default {
name: 'ViewerWork', name: 'ViewerWork',
components: { ChapterWork, ChapterExam }, components: { ChapterWork, ChapterTest },
props: { props: {
// 当前选中的 // 当前选中的
chapter: { chapter: {
...@@ -36,7 +36,7 @@ export default { ...@@ -36,7 +36,7 @@ export default {
computed: { computed: {
currentCompoent() { currentCompoent() {
const componentNames = { const componentNames = {
1: 'ChapterExam', // 考试 1: 'ChapterTest', // 课后测验
2: 'ChapterWork' // 作业 2: 'ChapterWork' // 作业
} }
const homework = this.chapter.homework const homework = this.chapter.homework
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<h1 class="course-viewer-main-hd__title">{{ detail.course_name }}</h1> <h1 class="course-viewer-main-hd__title">{{ detail.course_name }}</h1>
<!-- 直播的时候显示帮助按钮 --> <!-- 直播的时候显示帮助按钮 -->
<template v-if="isLive"> <template v-if="isLive">
<router-link to="/app/account/feedbackCreate" target="_blank"> <router-link to="/app/feedback/feedback-create" target="_blank">
<el-tooltip effect="light" content="意见反馈"> <el-tooltip effect="light" content="意见反馈">
<i class="el-icon-self-fankuiyijian"></i> <i class="el-icon-self-fankuiyijian"></i>
</el-tooltip> </el-tooltip>
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
</div> </div>
<!-- 侧边栏 --> <!-- 侧边栏 -->
<v-aside <v-aside
:data="detail"
:chapters="chapters" :chapters="chapters"
:active="activeChapter" :active="activeChapter"
:ppts="ppts" :ppts="ppts"
...@@ -92,10 +93,17 @@ export default { ...@@ -92,10 +93,17 @@ export default {
children: [ children: [
{ name: '课程大作业', id: 'course_work', type: 99 }, { name: '课程大作业', id: 'course_work', type: 99 },
{ name: '课程资料', id: 'course_info', type: 100 }, { name: '课程资料', id: 'course_info', type: 100 },
{ name: '教学评估', id: 'teach_evaluation', type: 102 }, { name: '教学评估', id: 'teach_evaluation', type: 102 }
{ name: '课程考试', id: 'course_exam', type: 101 }
] ]
} }
// 课程考试
if (this.detail.course_examination) {
customeChapter.children.push({
name: '课程考试',
id: 'course_exam',
type: 101
})
}
chapters.push(customeChapter) chapters.push(customeChapter)
return chapters return chapters
}, },
......
...@@ -193,7 +193,7 @@ export default { ...@@ -193,7 +193,7 @@ export default {
}, },
/* 直接进直播 */ /* 直接进直播 */
goLive () { 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 } })
} }
} }
} }
......
// import viewerRoutes from '@/modules/viewer/routes.js' import viewerRoutes from '@/modules/viewer/routes.js'
export default [ export default [
{ path: '/', redirect: '/app/learn/course' }, { path: '/', redirect: '/app/learn/course' },
...@@ -291,7 +291,7 @@ export default [ ...@@ -291,7 +291,7 @@ export default [
// /* survey-phone 内未找到页面时 - 指向 */ // /* survey-phone 内未找到页面时 - 指向 */
// { path: '/survey-phone/*', redirect: '/learn-error/learn-error' }, // { 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 // viewer module routes
// ...viewerRoutes ...viewerRoutes
] ]
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论