提交 dc6a4b8d 编写于 作者: guangjun.yang's avatar guangjun.yang

Merge branch 'dev-coursedetail-0817' of...

Merge branch 'dev-coursedetail-0817' of http://192.168.110.53/com.pica.cloud.education.frontend/pica-professional-exam into dev-coursedetail-0817

* 'dev-coursedetail-0817' of http://192.168.110.53/com.pica.cloud.education.frontend/pica-professional-exam:
  排查冲突
  逻辑对接

# Conflicts:
#	src/store/modules/user.js
...@@ -2674,12 +2674,14 @@ ...@@ -2674,12 +2674,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
...@@ -2694,17 +2696,20 @@ ...@@ -2694,17 +2696,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
...@@ -2821,7 +2826,8 @@ ...@@ -2821,7 +2826,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
...@@ -2833,6 +2839,7 @@ ...@@ -2833,6 +2839,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
...@@ -2847,6 +2854,7 @@ ...@@ -2847,6 +2854,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
...@@ -2854,12 +2862,14 @@ ...@@ -2854,12 +2862,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
...@@ -2878,6 +2888,7 @@ ...@@ -2878,6 +2888,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
...@@ -2958,7 +2969,8 @@ ...@@ -2958,7 +2969,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
...@@ -2970,6 +2982,7 @@ ...@@ -2970,6 +2982,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
...@@ -3091,6 +3104,7 @@ ...@@ -3091,6 +3104,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
......
<template> <template>
<div class="course-catalog"> <div class="course-catalog">
<div class="chapter-box"> <div class="chapter-box" v-for="(chapter, index) in list" :key="index">
<div class="head"> <div class="head">
<div class="name ellipsis">1.糖尿病的诊断与分型</div> <div class="name ellipsis">{{ chapter.chapterNameText }}</div>
<div class="total"> <div class="total" @click="onToggle(index)">
4 {{ chapter.lectureNum }}
<img class="arrow" src="~@/images/course/arrow_down.png" /> <img class="arrow" :class="{'arrow-active': chapter.showAll}" src="~@/images/course/arrow_down.png" />
</div> </div>
</div> </div>
<div class="lecture-box"> <div class="lecture-box" v-show="chapter.showAll">
<div class="item"> <div class="item"
<img class="icon" src="~@/images/course/array-right.png" /> :class="{'item-active': curtId === lecture.lectureId}"
<div class="info line"> v-for="lecture in chapter.lectures"
<p class="subname ellipsis">1.糖尿病的诊断</p> :key="lecture.lectureId"
<p class="time">时长: 03:56</p> @click="onSelect(lecture, 1)">
<img class="icon" src="~@/images/course/icon_play.png" />
<div class="info-box line">
<div class="info">
<p class="subname ellipsis">{{ lecture.lectureNameText }}</p>
<p class="time">
时长: {{ lecture.totalTimeText }}
<span>{{ lecture.statusText }}</span>
</p>
</div>
<div class="btn" v-if="lecture.btnText">{{ lecture.btnText }}</div>
<img v-else class="lock" src="~@/images/course/lock.png" alt="" />
</div> </div>
<div class="btn">学习</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -31,14 +41,18 @@ export default { ...@@ -31,14 +41,18 @@ export default {
default() { default() {
return [] return []
} }
},
curtId: {
type: Number,
default: 0,
},
onToggle: {
type: Function
},
onSelect: {
type: Function
} }
}, },
mounted() {
},
methods: {
}
}; };
</script> </script>
...@@ -82,24 +96,37 @@ export default { ...@@ -82,24 +96,37 @@ export default {
height: 12px; height: 12px;
transition: all 0.3s; transition: all 0.3s;
} }
.arrow-active{
transform: rotate(180deg);
}
} }
.lecture-box{ .lecture-box{
.item{ .item{
position: relative; position: relative;
display: flex; padding: 15px 0 0 25px;
padding: 15px 0 15px 30px; }
align-items: center; .item-active{
.subname, .time{
color: #449284;
}
} }
.icon{ .icon{
position: absolute; position: absolute;
left: 0; left: 0;
top: 18px; top: 20px;
width: 12px; width: 12px;
} }
.info-box{
position: relative;
display: flex;
align-items: center;
padding-bottom: 15px;
}
.info{ .info{
position: relative; position: relative;
flex: 1; flex: 1;
width: 100px; width: 100px;
padding-right: 5px;
} }
.line{ .line{
&::after{ &::after{
...@@ -125,8 +152,8 @@ export default { ...@@ -125,8 +152,8 @@ export default {
&::after{ &::after{
position: absolute; position: absolute;
content: ""; content: "";
left: 0; left: -1px;
top: 0; top: -1px;
width: 200%; width: 200%;
height: 200%; height: 200%;
border: 1px solid #449284; border: 1px solid #449284;
...@@ -135,6 +162,11 @@ export default { ...@@ -135,6 +162,11 @@ export default {
border-radius: 26px; border-radius: 26px;
} }
} }
.lock{
display: block;
width: 16px;
margin: 0 22px;
}
.subname{ .subname{
color: #676869; color: #676869;
font-size: 15px; font-size: 15px;
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
</div> </div>
</div> </div>
</div> </div>
<div class="go-app" @click="download">
<span>打开App,查看更多讨论内容</span>
</div>
</div> </div>
</template> </template>
...@@ -34,6 +37,9 @@ export default { ...@@ -34,6 +37,9 @@ export default {
default() { default() {
return [] return []
} }
},
download: {
type: Function
} }
}, },
data() { data() {
...@@ -151,5 +157,18 @@ export default { ...@@ -151,5 +157,18 @@ export default {
.show-arrow-up{ .show-arrow-up{
transform: rotate(180deg); transform: rotate(180deg);
} }
.go-app{
color: #449284;
font-size: 14px;
line-height: 14px;
text-align: center;
padding: 20px 0;
span{
display: inline-block;
padding-right: 20px;
background: url('~@/images/course/array-right.png') no-repeat right center;
background-size: 14px auto;
}
}
} }
</style> </style>
<template> <template>
<div class="course-covers-wrapper"> <div class="course-covers-wrapper">
<span class="tips" v-html="coverTips"></span> <div class="tips" v-html="coverTips"></div>
<div v-if="isShowBtn" class="course-button-group"> <div v-if="isShowBtn" class="course-button-group">
<CourseButton v-if="!isSingle" type="plain" @btnClick="btnClick(1)" :btnText="leftBtnText"></CourseButton> <CourseButton v-if="!isSingle" type="plain" @btnClick="btnClick(1)" :btnText="leftBtnText"></CourseButton>
<CourseButton @btnClick="btnClick(2)" :btnText="rightBtnText"></CourseButton> <CourseButton @btnClick="btnClick(2)" :btnText="rightBtnText"></CourseButton>
......
...@@ -16,6 +16,10 @@ export default { ...@@ -16,6 +16,10 @@ export default {
url: { url: {
type: String, type: String,
default: "" default: ""
},
visible: {
type: Boolean,
default: true,
} }
}, },
watch: { watch: {
...@@ -64,6 +68,18 @@ export default { ...@@ -64,6 +68,18 @@ export default {
viewport: viewport, viewport: viewport,
}); });
box.appendChild(canvas); box.appendChild(canvas);
if (!this.visible) {
let cover = document.createElement("div");
cover.className = 'canvas-cover';
cover.onclick = () => {
if (!this.$store.getter.logged) {
this.$store.dispatch('goLogin');
return;
}
this.$toast('前往APP购买查看')
}
box.appendChild(cover);
}
this.$el.appendChild(box); this.$el.appendChild(box);
} }
} }
...@@ -76,7 +92,17 @@ export default { ...@@ -76,7 +92,17 @@ export default {
overflow: hidden; overflow: hidden;
/deep/ .canvas-box{ /deep/ .canvas-box{
position: relative; position: relative;
padding-bottom: 30px; margin-bottom: 30px;
}
/deep/ .canvas-cover{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: url('~@/images/course/lock-big.png') no-repeat center center;
background-size: 50px auto;
background-color: rgba(255, 255, 255, .2);
} }
/deep/ canvas{ /deep/ canvas{
display: block; display: block;
......
...@@ -21,9 +21,9 @@ ...@@ -21,9 +21,9 @@
@error="onError" @error="onError"
> >
</video> </video>
<div class="video-cover"></div> <div class="video-cover" @click="showControl = !showControl"></div>
<!-- 控制栏 --> <!-- 控制栏 -->
<div class="control-box"> <div class="control-box" v-show="showControl">
<div class="control-bar"> <div class="control-bar">
<div class="btn-play" :class="{'btn-pause': isPaused}" @click="togglePlay"></div> <div class="btn-play" :class="{'btn-pause': isPaused}" @click="togglePlay"></div>
<div class="progress-box" @click="setProgress"> <div class="progress-box" @click="setProgress">
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
</div> </div>
</div> </div>
<div class="time-box">{{ playTime }}/{{ totalTime }}</div> <div class="time-box">{{ playTime }}/{{ totalTime }}</div>
<div class="rate-box" @click="showRate=true"> <!-- <div class="rate-box" @click="showRate=true">
倍速 倍速
<div class="rate-list" v-show="showRate"> <div class="rate-list" v-show="showRate">
<div <div
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
:key="rate" :key="rate"
@click.stop="selectRate(rate)">{{ rate }}</div> @click.stop="selectRate(rate)">{{ rate }}</div>
</div> </div>
</div> </div> -->
<div class="btn-screen" :class="{'btn-screen-mini': isFullScreen}" @click="onFullscreen"></div> <div class="btn-screen" :class="{'btn-screen-mini': isFullScreen}" @click="onFullscreen"></div>
</div> </div>
</div> </div>
...@@ -73,9 +73,10 @@ ...@@ -73,9 +73,10 @@
<slot></slot> <slot></slot>
<!-- 试看提示 --> <!-- 试看提示 -->
<div class="proved-box" v-show="showProved"> <div class="proved-box" v-show="showProved">
可试看{{ proved > 59 ? `${parseInt(proved / 60)}分钟` : `${proved}秒` }},激活/购买后可看完整课程 可试看{{ proved > 59 ? `${parseInt(proved / 60)}分钟` : `${proved}秒` }},观看完整版请来 <span @click="download">云鹊医App</span>
<div class="proved-close" @click="showProved=false"></div>
</div> </div>
<!-- 重新播放,只有试看有 -->
<div class="replay-box" v-show="showReplay" @click="onReplay">重新播放</div>
</div> </div>
</template> </template>
...@@ -97,6 +98,12 @@ import { formatLeftTimeObj } from '@/utils'; ...@@ -97,6 +98,12 @@ import { formatLeftTimeObj } from '@/utils';
export default { export default {
name: 'pica-video', name: 'pica-video',
props: {
download: {
type: Function,
default: () => {}
}
},
data() { data() {
return { return {
url: '', // 视频链接 url: '', // 视频链接
...@@ -109,6 +116,7 @@ export default { ...@@ -109,6 +116,7 @@ export default {
totalTime: '00:00', // 总时长 totalTime: '00:00', // 总时长
isPaused: true, // 是否暂停 isPaused: true, // 是否暂停
isFullScreen: false, // 是否全屏 isFullScreen: false, // 是否全屏
showControl: true, // 显示控制栏
progressBar: {}, // 进度条 progressBar: {}, // 进度条
progressBall: 0, // 进度球 progressBall: 0, // 进度球
rates: [2, 1.5, 1, 0.5], rates: [2, 1.5, 1, 0.5],
...@@ -117,6 +125,7 @@ export default { ...@@ -117,6 +125,7 @@ export default {
showProved: false, // 试看提示文字 showProved: false, // 试看提示文字
showError: false, // 播放错误 showError: false, // 播放错误
showResume: false, // 继续播放 showResume: false, // 继续播放
showReplay: false, // 显示重播
} }
}, },
computed: { computed: {
...@@ -157,10 +166,17 @@ export default { ...@@ -157,10 +166,17 @@ export default {
} }
if (isPaused) { if (isPaused) {
this.player.play(); this.player.play();
if (this.opts.proved > 0) {
this.showProved = true;
this.provedTimer && clearTimeout(this.provedTimer);
this.provedTimer = setTimeout(() => {
this.showProved = false;
}, 5000)
}
} else { } else {
this.player.pause(); this.player.pause();
} }
// this.reportOnOff(isPaused ? 1 : 2); this.reportOnOff(isPaused ? 1 : 2);
this.isPaused = !isPaused; this.isPaused = !isPaused;
}, },
// 切换视频 // 切换视频
...@@ -173,12 +189,12 @@ export default { ...@@ -173,12 +189,12 @@ export default {
this.proved = proved; this.proved = proved;
this.history = history; this.history = history;
this.enable = enable; this.enable = enable;
this.showProved = proved > 0;
this.provedOver = false; this.provedOver = false;
this.finish = false; this.finish = false;
this.opts = opts; this.opts = opts;
this.currentTime = null; this.currentTime = null;
this.duration = null; this.duration = null;
this.showReplay = false;
if (this.showError) this.showError = false; if (this.showError) this.showError = false;
}, },
// 切换并播放 // 切换并播放
...@@ -205,6 +221,14 @@ export default { ...@@ -205,6 +221,14 @@ export default {
} }
this.timer = loop(); this.timer = loop();
}, },
// 重播
onReplay() {
this.player.currentTime = 0;
this.player.play();
this.isPaused = false;
this.reportOnOff(1);
this.$emit('onReplay')
},
// 加载完毕,获取总时长和音量。问题:移动端点击播放才会触发,且不一定会获取时长 // 加载完毕,获取总时长和音量。问题:移动端点击播放才会触发,且不一定会获取时长
loadedMetaData() { loadedMetaData() {
let duration = this.player.duration; let duration = this.player.duration;
...@@ -275,7 +299,7 @@ export default { ...@@ -275,7 +299,7 @@ export default {
if (this.isPaused) { if (this.isPaused) {
this.player.play(); this.player.play();
this.isPaused = false; this.isPaused = false;
// this.reportOnOff(1); this.reportOnOff(1);
} }
}, },
// 拖动进度条 // 拖动进度条
...@@ -323,10 +347,10 @@ export default { ...@@ -323,10 +347,10 @@ export default {
// 试看结束 // 试看结束
provedEnd() { provedEnd() {
this.provedOver = true; this.provedOver = true;
this.showProved = false;
this.player.pause(); this.player.pause();
this.$emit('onVideoEnd', { type: 2 }); this.$emit('onVideoEnd', { type: 2 });
this.finish = true; this.finish = true;
this.showReplay = true;
this.reportOnOff(2); this.reportOnOff(2);
}, },
// 播放结束 // 播放结束
...@@ -347,7 +371,10 @@ export default { ...@@ -347,7 +371,10 @@ export default {
// 上报播放、暂停,status:1开始,2暂停 // 上报播放、暂停,status:1开始,2暂停
reportOnOff(status = 1) { reportOnOff(status = 1) {
const { chapterId, courseId, lectureId } = this.opts; const { chapterId, courseId, lectureId } = this.opts;
this.$api.pauseCourse({ if (!chapterId || !courseId || !lectureId) {
return;
}
this.POST('/contents/files/resourceRecord', {
fileType: 1, fileType: 1,
resourceInfo1: courseId, resourceInfo1: courseId,
resourceInfo2: chapterId, resourceInfo2: chapterId,
...@@ -356,7 +383,6 @@ export default { ...@@ -356,7 +383,6 @@ export default {
status, status,
systemType: 3, systemType: 3,
timestamp: Date.now(), timestamp: Date.now(),
showError: false,
}) })
}, },
// 上报离开 // 上报离开
...@@ -365,7 +391,10 @@ export default { ...@@ -365,7 +391,10 @@ export default {
return; return;
} }
const { chapterId, courseId, lectureId } = this.opts; const { chapterId, courseId, lectureId } = this.opts;
this.$api.joinCourse({ if (!chapterId || !courseId || !lectureId) {
return;
}
this.POST('/contents/joinCourse/', {
requestList: [{ requestList: [{
chapterId, chapterId,
courseId, courseId,
...@@ -374,7 +403,6 @@ export default { ...@@ -374,7 +403,6 @@ export default {
time: this.duration, time: this.duration,
timeStamp: Date.now(), timeStamp: Date.now(),
}], }],
showError: false,
}) })
}, },
}, },
...@@ -530,24 +558,16 @@ export default { ...@@ -530,24 +558,16 @@ export default {
position: absolute; position: absolute;
color: #fff; color: #fff;
font-size: 12px; font-size: 12px;
left: 20px; left: 10px;
bottom: 70px; bottom: 44px;
height: 30px; height: 24px;
line-height: 30px; line-height: 24px;
padding: 0 27px 0 31px; padding: 0 12px;
border-radius: 15px; border-radius: 12px;
background: url('~@/images/video/tip.png') no-repeat 12px center; background-color: rgba(0, 0, 0, .6);
background-size: 14px auto; span{
background-color: #373839; color: #FFA34B;
} }
.proved-close{
position: absolute;
right: 0;
top: 0;
width: 30px;
height: 30px;
background: url('~@/images/video/close.png') no-repeat 10px center;
background-size: 10px auto;
} }
.cover-play{ .cover-play{
background: url('~@/images/video/cover_play.png') no-repeat center center; background: url('~@/images/video/cover_play.png') no-repeat center center;
...@@ -565,6 +585,20 @@ export default { ...@@ -565,6 +585,20 @@ export default {
transform: translate3d(0, -50%, 0); transform: translate3d(0, -50%, 0);
} }
} }
.replay-box{
position: absolute;
color: #fff;
font-size: 12px;
right: 10px;
bottom: 44px;
height: 24px;
line-height: 24px;
padding: 0 12px 0 22px;
border-radius: 12px;
background: url('~@/images/video/replay.png') no-repeat left center;
background-size: 23px auto;
background-color: rgba(0, 0, 0, .6);
}
.cover{ .cover{
position: absolute; position: absolute;
left: 0; left: 0;
......
...@@ -53,13 +53,30 @@ const router = new VueRouter({ ...@@ -53,13 +53,30 @@ const router = new VueRouter({
} }
}) })
router.beforeEach((to, from, next) => { // 过滤路由
let query = { ...to.query }; function fliterRoute(query, path) {
let has = false;
// 登录token保存并替换路径 // 登录token保存并替换路径
if (query.token && query.token != 'undefined') { if (query.token && query.token != 'undefined') {
store.dispatch('setToken', query.token); store.dispatch('setToken', query.token);
delete query.token; delete query.token;
next({ path: to.path, query: query, replace: true }); has = true;
}
// 课程详情页去掉projectId
if (path === '/course-detail' && query.projectId) {
sessionStorage.setItem('projectId', query.projectId);
delete query.projectId;
has = true;
}
return [query, has];
}
router.beforeEach((to, from, next) => {
let query = { ...to.query };
// 登录token保存并替换路径
let [newQuery, has] = fliterRoute(query, to.path);
if (has) {
next({ path: to.path, query: newQuery, replace: true });
return; return;
} }
next(); next();
......
...@@ -42,16 +42,16 @@ const user = { ...@@ -42,16 +42,16 @@ const user = {
const { certifyDoc, isExist } = res.data; const { certifyDoc, isExist } = res.data;
const picapDoctor = res.data.picapDoctor || {}; const picapDoctor = res.data.picapDoctor || {};
if (picapDoctor.id) { if (picapDoctor.id) {
let avatar = picapDoctor.avatar_image_url || ''; // let avatar = picapDoctor.avatar_image_url || '';
let avatarUrl = ''; let avatarUrl = '';
const img1 = await preLoadImg(`https://test-file.yunqueyi.com${avatar}`).catch(err => console.error(err)); // const img1 = await preLoadImg(`https://test-file.yunqueyi.com${avatar}`).catch(err => console.log(err));
const img2 = await preLoadImg(`https://file.yunqueyi.com${avatar}`).catch(err => console.error(err)); // const img2 = await preLoadImg(`https://file.yunqueyi.com${avatar}`).catch(err => console.log(err));
if (img1) { // if (img1) {
avatarUrl = img1.src; // avatarUrl = img1.src;
} // }
if (img2) { // if (img2) {
avatarUrl = img2.src; // avatarUrl = img2.src;
} // }
picapDoctor.avatar = avatarUrl || 'https://file.yunqueyi.com/File/doctor_default.png'; picapDoctor.avatar = avatarUrl || 'https://file.yunqueyi.com/File/doctor_default.png';
commit('SET_USER_INFO', { ...picapDoctor, isExist, certifyDoc }); commit('SET_USER_INFO', { ...picapDoctor, isExist, certifyDoc });
} }
......
此差异已折叠。
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册