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

代码整理 二次分享的描述 JSON解析报错

上级 b93a1a7e
<template>
<div
class="pica-video"
:style="{position: isFullScreen ? 'fixed' : ''}">
<template v-if="isWechat">
<video
:id="vid"
:src="url"
:poster="poster"
preload="metadata"
webkit-playsinline
playsinline
x5-playsinline="true"
x-webkit-airplay="allow"
x5-video-player-type="h5-page"
x5-video-player-fullscreen="false"
mtt-playsinline="true"
controlsList="nodownload"
@loadedmetadata="loadedMetaData"
@timeupdate="onTimeUpdate"
@ended="onEnded"
@error="onError"
>
</video>
<div class="video-cover" @click="showControl = !showControl"></div>
<!-- 控制栏 -->
<div class="control-box" v-show="showControl">
<div class="control-bar">
<div class="btn-play" :class="{'btn-pause': isPaused}" @click="togglePlay"></div>
<div class="progress-box" @click="setProgress">
<div class="progress-inner">
<div class="progress-bar" :style="progressBar"></div>
</div>
<div
class="progress-ball"
:style="{left: `${progressBall}%`}"
@touchstart.stop="onBallStart"
@touchmove.stop="onBallMove"
@touchend.stop="onBallEnd">
</div>
</div>
<div class="time-box">{{ playTime }}/{{ totalTime }}</div>
<!-- <div class="rate-box" @click="showRate=true">
倍速
<div class="rate-list" v-show="showRate">
<div
class="rate-item"
:class="{'rate-active': rate === curtRate}"
v-for="rate in rates"
:key="rate"
@click.stop="selectRate(rate)">{{ rate }}</div>
</div>
</div> -->
<div class="btn-screen" :class="{'btn-screen-mini': isFullScreen}" @click="onFullscreen"></div>
</div>
</div>
<!-- 播放遮罩 -->
<transition name="fade">
<div v-show="isPaused" class="cover cover-play" @click="togglePlay"></div>
</transition>
<!-- 播放错误 -->
<transition name="fade">
<div v-show="showError" class="cover cover-error">
<p>播放失败,请确认网络正常或重新进入页面</p>
</div>
</transition>
<!-- 接续播放 -->
<transition name="fade">
<div v-show="showResume" class="cover cover-resume">
<p>上次观看至{{ history > 59 ? `${parseInt(history / 60)}分钟` : `${history}秒` }},正在续播</p>
</div>
</transition>
<!-- 弹窗放在外部处理 -->
<slot></slot>
<!-- 试看提示 -->
<div class="proved-box" v-show="showProved">
可试看{{ proved > 59 ? `${parseInt(proved / 60)}分钟` : `${proved}秒` }},观看完整版请来 <span @click="download">云鹊医App</span>
</div>
<!-- 重新播放,只有试看有 -->
<div class="replay-box" v-show="showReplay" @click="onReplay">重新播放</div>
</template>
<img v-else class="default-img" src="~@/images/video/course_img.png" alt="" />
</div>
</template>
<script>
/**
* 不使用参数,调用两个方法;
* switchUrl(opt)和switchUrlAndPlay(opt)
* opt: {
* url, // 视频链接
* poster, // 封面
* proved, // 试看时长,单位秒
* history, // 上次观看时长,单位秒
* enable, // 是否可看
* }
* 暴露一个回调onVideoEnd,参数:
* type => 1 播放结束,2 试看结束
*/
import { formatLeftTimeObj } from '@/utils';
export default {
name: 'pica-video',
props: {
download: {
type: Function,
default: () => {}
}
},
data() {
return {
url: '', // 视频链接
poster: '', // 封面
proved: 0, // 试看时长,单位秒
history: 0, // 上次观看时长,单位秒
enable: true, // 是否可看
vid: '', // 唯一id
playTime: '00:00', // 播放时长
totalTime: '00:00', // 总时长
isPaused: true, // 是否暂停
isFullScreen: false, // 是否全屏
showControl: true, // 显示控制栏
progressBar: {}, // 进度条
progressBall: 0, // 进度球
rates: [2, 1.5, 1, 0.5],
curtRate: 1,
showRate: false,
showProved: false, // 试看提示文字
showError: false, // 播放错误
showResume: false, // 继续播放
showReplay: false, // 显示重播
isWechat: true, // 微信环境
}
},
computed: {
logged() {
return this.$store.getters.logged;
},
},
created() {
this.vid = `video_${this._uid}`;
const ua = navigator.userAgent;
this.isWechat = ua.match(/(MicroMessenger)\/([\d.]+)/);
},
mounted() {
if (this.isWechat) {
const player = document.getElementById(this.vid);
player.addEventListener("timeupdate", this.onTimeUpdate, false);
this.player = player;
}
},
beforeDestroy() {
this.timer && clearTimeout(this.timer);
if (this.currentTime) {
this.reportLeave();
}
if (!this.isPaused && !this.finish) {
this.reportOnOff(2);
}
},
methods: {
togglePlay() {
if (!this.logged) {
this.$store.dispatch('goLogin');
return;
}
if (!this.url || !this.enable) {
return;
}
let isPaused = this.isPaused;
// 试看,且超过时间
if (this.proved && this.player.currentTime >= this.proved) {
return;
}
if (isPaused) {
this.player.play();
if (this.opts.proved > 0) {
this.showProved = true;
this.provedTimer && clearTimeout(this.provedTimer);
this.provedTimer = setTimeout(() => {
this.showProved = false;
}, 5000)
}
} else {
this.player.pause();
}
this.reportOnOff(isPaused ? 1 : 2);
this.isPaused = !isPaused;
},
// 切换视频
switchUrl(opts = {}) {
if (!this.isWechat) {
return;
}
const { url = '', poster = '', proved = 0, history = 0, enable = true } = opts;
this.loaded = false;
this.player.src = url;
this.url = url;
this.poster = poster;
this.proved = proved;
this.history = history;
this.enable = enable;
this.provedOver = false;
this.finish = false;
this.opts = opts;
this.currentTime = null;
this.duration = null;
this.showReplay = false;
if (this.showError) this.showError = false;
},
// 切换并播放
switchUrlAndPlay(opts = {}) {
if (!this.isWechat) {
return;
}
if (!this.isPaused && !this.finish) {
this.reportOnOff(2);
}
this.reportLeave();
this.switchUrl(opts);
if (!this.enable) {
return;
}
const loop = () => {
if (this.loaded) {
this.player.play();
this.isPaused = false;
this.reportOnOff(1);
return null;
} else {
return setTimeout(() => {
loop()
}, 100);
}
}
this.timer = loop();
},
// 重播
onReplay() {
this.player.currentTime = 0;
this.player.play();
this.isPaused = false;
this.reportOnOff(1);
this.$emit('onReplay')
},
// 加载完毕,获取总时长和音量。问题:移动端点击播放才会触发,且不一定会获取时长
loadedMetaData() {
let duration = this.player.duration;
if (duration) {
this.totalTime = this.formatTime(duration);
this.loaded = true;
if (this.history) {
this.player.currentTime = this.history;
this.showResume = true;
setTimeout(() => {
this.showResume = false;
}, 2000);
}
}
},
// 播放中
onTimeUpdate(e) {
if (this.provedOver) {
return
}
const { currentTime, duration } = e.target;
if (currentTime) {
this.playTime = this.formatTime(currentTime);
}
if (currentTime && duration) {
this.setBarPosition(currentTime * 100 / duration, 'progressBar');
this.currentTime = currentTime;
this.duration = duration;
}
if (currentTime < 0.1 && !this.loaded) {
this.loadedMetaData();
}
// 试看,且超过时间
if (this.proved && currentTime >= this.proved) {
this.provedEnd();
}
},
// 设置进度条位置
setBarPosition(percent, target) {
this[target] = {
transform: `translateX(${percent}%)`,
'-webkit-transform': `-webkit-translateX(${percent}%)`,
'-moz-transform': `-moz-translateX(${percent}%)`,
'-ms-transform': `-ms-translateX(${percent}%)`,
}
if (target === 'progressBar' && !this.isMoveingBall) {
this.progressBall = percent
}
},
// 点击设置进度
setProgress(e) {
if (!this.url) {
return;
}
const { offsetX } = e;
const { width } = e.target.getBoundingClientRect();
this.setProgressPosition(offsetX * 100 / width);
},
// 设置进度最终位置
setProgressPosition(percent) {
const duration = this.player.duration;
// 试看,且超过时间
if (this.proved && percent >= this.proved * 100 / duration) {
return;
}
this.setBarPosition(percent, 'progressBar');
this.player.currentTime = percent * duration / 100;
if (this.isPaused) {
this.player.play();
this.isPaused = false;
this.reportOnOff(1);
}
},
// 拖动进度条
onBallStart(e) {
this.isMoveingBall = true;
const { width } = this.$el.querySelector('.progress-inner').getBoundingClientRect();
const { pageX } = e.changedTouches[0];
this.ballPageX = pageX;
this.progressW = width;
this.oldBallPercent = this.progressBall;
},
onBallMove(e) {
const { pageX } = e.changedTouches[0];
this.progressBall = this.getNewPercent(pageX);
},
onBallEnd(e) {
this.isMoveingBall = false;
const { pageX } = e.changedTouches[0];
const newPercent = this.getNewPercent(pageX);
this.setProgressPosition(newPercent);
},
// 获取拖动百分比
getNewPercent(pageX) {
let newPercent = (pageX - this.ballPageX) * 100 / this.progressW + this.oldBallPercent;
if (newPercent <= 0) {
newPercent = 0
} else if (newPercent >= 100) {
newPercent = 100
}
return newPercent;
},
selectRate(rate) {
if (!this.url) {
return;
}
this.player.playbackRate = rate;
this.curtRate = rate;
this.showRate = false;
},
formatTime(t) {
const time = formatLeftTimeObj(t);
const h = time.h === '00' ? '' : `${time.h}:`;
return `${h}${time.f}:${time.s}`;
},
// 试看结束
provedEnd() {
this.provedOver = true;
this.player.pause();
this.$emit('onVideoEnd', { type: 2 });
this.finish = true;
this.showReplay = true;
this.reportOnOff(2);
},
// 播放结束
onEnded() {
this.$emit('onVideoEnd', { type: 1 });
this.finish = true;
this.reportOnOff(2);
},
onError() {
if (this.url) {
this.showError = true
}
},
// 全屏
onFullscreen() {
this.isFullScreen = !this.isFullScreen;
},
// 上报播放、暂停,status:1开始,2暂停
reportOnOff(status = 1) {
const { chapterId, courseId, lectureId } = this.opts;
if (!chapterId || !courseId || !lectureId) {
return;
}
this.POST('/contents/files/resourceRecord', {
fileType: 1,
resourceInfo1: courseId,
resourceInfo2: chapterId,
resourceInfo3: lectureId,
resourceType: 1,
status,
systemType: 3,
timestamp: Date.now(),
})
},
// 上报离开
reportLeave() {
if (!this.currentTime || !this.duration) {
return;
}
const { chapterId, courseId, lectureId } = this.opts;
if (!chapterId || !courseId || !lectureId) {
return;
}
this.POST('/contents/joinCourse/', {
requestList: [{
chapterId,
courseId,
lectureId,
nowTime: this.currentTime,
time: this.duration,
timeStamp: Date.now(),
}],
})
},
},
}
</script>
<style lang="less" scoped>
.pica-video{
position: relative;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #333;
overflow: hidden;
z-index: 1000;
video{
position: absolute;
left: 50%;
top: 50%;
width: 100%;
max-width: 100%;
max-height: 100%;
transform: translate3d(-50%, -50%, 0);
&::-internal-media-controls-download-button {
display: none;
}
&::-webkit-media-controls-enclosure {
overflow: hidden;
}
&::-webkit-media-controls-panel {
width: calc(100% + 30px);
}
}
.video-cover{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.control-box{
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 44px;
}
.control-bar{
position: absolute;
display: flex;
align-items: center;
justify-content: center;
left: 0;
top: 0;
width: 100%;
height: 44px;
// transform: translate3d(0, 60px, 0);
// transition: transform 0.2s;
background: linear-gradient(180deg,rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%);
}
.btn-play{
width: 44px;
height: 44px;
background-image: url('~@/images/video/play.png');
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: 24px auto;
}
.btn-pause{
background-image: url('~@/images/video/pause.png');
}
.progress-box{
position: relative;
display: flex;
align-items: center;
flex: 1;
width: 50px;
height: 44px;
margin-left: 5px;
}
.progress-inner{
position: relative;
width: 50px;
flex: 1;
height: 2px;
background: rgba(255, 255, 255, 0.4);
overflow: hidden;
}
.progress-bar{
position: absolute;
left: -100%;
top: 0;
width: 100%;
height: 100%;
background: #449284;
transform: translateX(0);
pointer-events: none;
}
.progress-ball{
position: absolute;
left: 0;
top: 50%;
width: 7px;
height: 14px;
transform: translate3d(-3px, -7px, 0);
background-color: #fff;
border-radius: 2px;
}
.time-box{
color: #fff;
font-size: 12px;
line-height: 14px;
width: 100px;
text-align: right;
}
.btn-screen{
width: 44px;
height: 44px;
background-image: url('~@/images/video/screen_full.png');
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: 20px auto;
}
.btn-screen-mini{
background-image: url('~@/images/video/screen_mini.png');
}
.rate-box{
position: relative;
color: #fff;
width: 40px;
height: 44px;
line-height: 44px;
font-size: 12px;
text-align: center;
}
.rate-list{
position: absolute;
left: 0;
bottom: 44px;
width: 100%;
background: rgba(0, 0, 0, .7);
border-radius: 2px;
}
.rate-item{
height: 30px;
line-height: 30px;
}
.rate-active{
color: #00a1d6;
}
.proved-box{
position: absolute;
color: #fff;
font-size: 12px;
left: 10px;
bottom: 44px;
height: 24px;
line-height: 24px;
padding: 0 12px;
border-radius: 12px;
background-color: rgba(0, 0, 0, .6);
span{
color: #FFA34B;
}
}
.cover-play{
background: url('~@/images/video/cover_play.png') no-repeat center center;
background-size: 50px auto;
}
.cover-error, .cover-resume{
p{
position: absolute;
left: 0;
top: 50%;
width: 100%;
color: #fff;
font-size: 15px;
text-align: center;
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{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
}
.default-img{
position: absolute;
left: 50%;
top: 50%;
min-width: 100%;
min-height: 100%;
max-width: 100%;
max-height: 100%;
transform: translate3d(-50%, -50%, 0);
}
}
</style>
<template>
<div
class="pica-video"
:style="{position: isFullScreen ? 'fixed' : ''}">
<template v-if="isWechat">
<video
:id="vid"
:src="url"
:poster="poster"
preload="metadata"
webkit-playsinline
playsinline
x5-playsinline="true"
x-webkit-airplay="allow"
x5-video-player-type="h5"
x5-video-player-fullscreen="false"
mtt-playsinline="true"
controlsList="nodownload"
@loadedmetadata="loadedMetaData"
@timeupdate="onTimeUpdate"
@ended="onEnded"
@error="onError"
>
</video>
<div class="video-cover" @click="showControl = !showControl"></div>
<!-- 控制栏 -->
<div class="control-box" v-show="showControl">
<div class="control-bar">
<div class="btn-play" :class="{'btn-pause': isPaused}" @click="togglePlay"></div>
<div class="progress-box" @click="setProgress">
<div class="progress-inner">
<div class="progress-bar" :style="progressBar"></div>
</div>
<div
class="progress-ball"
:style="{left: `${progressBall}%`}"
@touchstart.stop="onBallStart"
@touchmove.stop="onBallMove"
@touchend.stop="onBallEnd">
</div>
</div>
<div class="time-box">{{ playTime }}/{{ totalTime }}</div>
<!-- <div class="rate-box" @click="showRate=true">
倍速
<div class="rate-list" v-show="showRate">
<div
class="rate-item"
:class="{'rate-active': rate === curtRate}"
v-for="rate in rates"
:key="rate"
@click.stop="selectRate(rate)">{{ rate }}</div>
</div>
</div> -->
<div class="btn-screen" :class="{'btn-screen-mini': isFullScreen}" @click="onFullscreen"></div>
</div>
</div>
<!-- 播放遮罩 -->
<transition name="fade">
<div v-show="logged && isPaused" class="cover cover-play" @click="togglePlay"></div>
</transition>
<!-- 播放错误 -->
<transition name="fade">
<div v-show="logged && showError" class="cover cover-error">
<p>播放失败,请确认网络正常或重新进入页面</p>
</div>
</transition>
<!-- 接续播放 -->
<transition name="fade">
<div v-show="showResume" class="cover cover-resume">
<p>上次观看至{{ history > 59 ? `${parseInt(history / 60)}分钟` : `${history}秒` }},正在续播</p>
</div>
</transition>
<!-- 弹窗放在外部处理 -->
<slot></slot>
<!-- 试看提示 -->
<div class="proved-box" v-show="showProved">
可试看{{ proved > 59 ? `${parseInt(proved / 60)}分钟` : `${proved}秒` }},观看完整版请来 <span @click="download">云鹊医App</span>
</div>
<!-- 重新播放,只有试看有 -->
<div class="replay-box" v-show="showReplay" @click="onReplay">重新播放</div>
</template>
<img v-else class="default-img" src="~@/images/video/course_img.png" alt="" />
</div>
</template>
<script>
/**
* 不使用参数,调用两个方法;
* switchUrl(opt)和switchUrlAndPlay(opt)
* opt: {
* url, // 视频链接
* poster, // 封面
* proved, // 试看时长,单位秒
* history, // 上次观看时长,单位秒
* enable, // 是否可看
* }
* 暴露一个回调onVideoEnd,参数:
* type => 1 播放结束,2 试看结束
*/
import { formatLeftTimeObj } from '@/utils';
export default {
name: 'pica-video',
props: {
coverType: {
type: Number,
default: 0,
},
download: {
type: Function,
default: () => {}
}
},
data() {
return {
url: '', // 视频链接
poster: '', // 封面
proved: 0, // 试看时长,单位秒
history: 0, // 上次观看时长,单位秒
enable: true, // 是否可看
vid: '', // 唯一id
playTime: '00:00', // 播放时长
totalTime: '00:00', // 总时长
isPaused: true, // 是否暂停
isFullScreen: false, // 是否全屏
showControl: true, // 显示控制栏
progressBar: {}, // 进度条
progressBall: 0, // 进度球
rates: [2, 1.5, 1, 0.5],
curtRate: 1,
showRate: false,
showProved: false, // 试看提示文字
showError: false, // 播放错误
showResume: false, // 继续播放
showReplay: false, // 显示重播
isWechat: true, // 微信环境
}
},
computed: {
logged() {
return this.$store.getters.logged;
},
},
created() {
this.vid = `video_${this._uid}`;
this.playTime = 0;
const ua = navigator.userAgent;
this.isWechat = ua.match(/(MicroMessenger)\/([\d.]+)/);
this.isAndroid = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
},
mounted() {
if (this.isWechat) {
const player = document.getElementById(this.vid);
player.addEventListener("timeupdate", this.onTimeUpdate, false);
this.player = player;
}
},
beforeDestroy() {
this.timer && clearTimeout(this.timer);
if (this.currentTime) {
this.reportLeave();
}
if (!this.isPaused && !this.finish) {
this.reportOnOff(2);
}
},
methods: {
togglePlay() {
if (!this.logged) {
this.$store.dispatch('goLogin');
return;
}
if (!this.url || !this.enable) {
return;
}
let isPaused = this.isPaused;
// 试看,且超过时间
if (this.proved && this.player.currentTime >= this.proved) {
return;
}
this.player.style.display = 'block';
if (isPaused) {
this.player.play();
this.playTime++;
this.showProved = false;
} else {
this.player.pause();
}
this.reportOnOff(isPaused ? 1 : 2);
this.isPaused = !isPaused;
},
// 切换视频
switchUrl(opts = {}) {
if (!this.isWechat) {
return;
}
this.player.style.display = 'block';
const { url = '', poster = '', proved = 0, history = 0, enable = true } = opts;
this.loaded = false;
this.player.src = url;
this.url = url;
this.poster = poster;
this.proved = proved;
this.history = history;
this.enable = enable;
this.provedOver = false;
this.finish = false;
this.opts = opts;
this.currentTime = null;
this.duration = null;
this.showProved = proved > 0;
this.showReplay = false;
if (this.showError) this.showError = false;
},
// 切换并播放
switchUrlAndPlay(opts = {}) {
if (!this.isWechat) {
return;
}
if (!this.isPaused && !this.finish) {
this.reportOnOff(2);
}
this.reportLeave();
if (this.playTime === 0) {
this.player.play();
}
this.switchUrl(opts);
this.player.autoplay = true;
if (!this.enable) {
return;
}
const loop = () => {
if (this.loaded) {
this.player.play();
if (!this.player.paused) {
this.isPaused = false;
this.reportOnOff(1);
this.showProved = false;
}
return null;
} else {
return setTimeout(() => {
loop()
}, 100);
}
}
this.timer = loop();
},
// 重播
onReplay() {
this.player.style.display = 'block';
this.player.currentTime = 0;
this.player.play();
this.isPaused = false;
this.reportOnOff(1);
this.$emit('onReplay');
this.showReplay = false;
this.provedOver = false;
},
// 加载完毕,获取总时长和音量。问题:移动端点击播放才会触发,且不一定会获取时长
loadedMetaData() {
let duration = this.player.duration;
if (duration) {
this.totalTime = this.formatTime(duration);
this.loaded = true;
if (this.history) {
this.player.currentTime = this.history;
this.showResume = true;
setTimeout(() => {
this.showResume = false;
}, 2000);
}
}
},
// 播放中
onTimeUpdate(e) {
const { currentTime, duration } = e.target;
// 试看,且超过时间
if (this.proved && currentTime >= this.proved) {
this.provedEnd();
}
if (this.provedOver) {
return
}
if (currentTime) {
this.playTime = this.formatTime(currentTime);
}
if (currentTime && duration) {
this.setBarPosition(currentTime * 100 / duration, 'progressBar');
this.currentTime = currentTime;
this.duration = duration;
}
if (currentTime < 0.1 && !this.loaded) {
this.loadedMetaData();
}
},
// 设置进度条位置
setBarPosition(percent, target) {
this[target] = {
transform: `translateX(${percent}%)`,
'-webkit-transform': `-webkit-translateX(${percent}%)`,
'-moz-transform': `-moz-translateX(${percent}%)`,
'-ms-transform': `-ms-translateX(${percent}%)`,
}
if (target === 'progressBar' && !this.isMoveingBall) {
this.progressBall = percent
}
},
// 点击设置进度
setProgress(e) {
if (!this.url) {
return;
}
const { offsetX } = e;
const { width } = e.target.getBoundingClientRect();
this.setProgressPosition(offsetX * 100 / width);
},
// 设置进度最终位置
setProgressPosition(percent) {
const duration = this.player.duration;
// 试看,且超过时间
if (this.proved && percent >= this.proved * 100 / duration) {
return;
}
this.setBarPosition(percent, 'progressBar');
this.player.currentTime = percent * duration / 100;
if (this.isPaused) {
this.player.style.display = 'block';
this.player.play();
this.playTime++;
this.isPaused = false;
this.reportOnOff(1);
}
},
// 拖动进度条
onBallStart(e) {
this.isMoveingBall = true;
const { width } = this.$el.querySelector('.progress-inner').getBoundingClientRect();
const { pageX } = e.changedTouches[0];
this.ballPageX = pageX;
this.progressW = width;
this.oldBallPercent = this.progressBall;
},
onBallMove(e) {
const { pageX } = e.changedTouches[0];
this.progressBall = this.getNewPercent(pageX);
},
onBallEnd(e) {
this.isMoveingBall = false;
const { pageX } = e.changedTouches[0];
const newPercent = this.getNewPercent(pageX);
this.setProgressPosition(newPercent);
},
// 获取拖动百分比
getNewPercent(pageX) {
let newPercent = (pageX - this.ballPageX) * 100 / this.progressW + this.oldBallPercent;
if (newPercent <= 0) {
newPercent = 0
} else if (newPercent >= 100) {
newPercent = 100
}
return newPercent;
},
selectRate(rate) {
if (!this.url) {
return;
}
this.player.playbackRate = rate;
this.curtRate = rate;
this.showRate = false;
},
formatTime(t) {
const time = formatLeftTimeObj(t);
const h = time.h === '00' ? '' : `${time.h}:`;
return `${h}${time.f}:${time.s}`;
},
// 试看结束
provedEnd() {
this.player.pause();
this.player.currentTime = this.proved;
if (this.isAndroid) {
this.player.style.display = 'none';
}
if (!this.provedOver) {
this.$emit('onVideoEnd', { type: 2 });
this.reportOnOff(2);
}
this.finish = true;
this.showReplay = true;
this.provedOver = true;
this.isFullScreen = false;
},
// 播放结束
onEnded() {
this.$emit('onVideoEnd', { type: 1 });
this.finish = true;
if (this.isAndroid) {
this.player.style.display = 'none';
}
this.reportOnOff(2);
this.$nextTick(() => {
if (this.coverType > 0 && this.coverType !== 13) {
this.isFullScreen = false;
}
})
},
onError() {
if (this.url) {
this.showError = true
}
},
// 全屏
onFullscreen() {
this.isFullScreen = !this.isFullScreen;
},
// 上报播放、暂停,status:1开始,2暂停
reportOnOff(status = 1) {
const { chapterId, courseId, lectureId } = this.opts;
if (!chapterId || !courseId || !lectureId) {
return;
}
this.POST('/contents/files/resourceRecord', {
fileType: 1,
resourceInfo1: courseId,
resourceInfo2: chapterId,
resourceInfo3: lectureId,
resourceType: 1,
status,
systemType: 3,
timestamp: Date.now(),
})
},
// 上报离开
reportLeave() {
if (!this.currentTime || !this.duration) {
return;
}
const { chapterId, courseId, lectureId } = this.opts;
if (!chapterId || !courseId || !lectureId) {
return;
}
this.POST('/contents/joinCourse/', {
requestList: [{
chapterId,
courseId,
lectureId,
nowTime: this.currentTime,
time: this.duration,
timeStamp: Date.now(),
}],
})
},
},
}
</script>
<style lang="less" scoped>
.pica-video{
position: relative;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #333;
overflow: hidden;
z-index: 1000;
video{
position: absolute;
left: 50%;
top: 50%;
width: 100%;
max-width: 100%;
max-height: 100%;
transform: translate3d(-50%, -50%, 0);
&::-internal-media-controls-download-button {
display: none;
}
&::-webkit-media-controls-enclosure {
overflow: hidden;
}
&::-webkit-media-controls-panel {
width: calc(100% + 30px);
}
}
.video-cover{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.control-box{
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 44px;
}
.control-bar{
position: absolute;
display: flex;
align-items: center;
justify-content: center;
left: 0;
top: 0;
width: 100%;
height: 44px;
// transform: translate3d(0, 60px, 0);
// transition: transform 0.2s;
background: linear-gradient(180deg,rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%);
}
.btn-play{
width: 44px;
height: 44px;
background-image: url('~@/images/video/play.png');
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: 24px auto;
}
.btn-pause{
background-image: url('~@/images/video/pause.png');
}
.progress-box{
position: relative;
display: flex;
align-items: center;
flex: 1;
width: 50px;
height: 44px;
margin-left: 5px;
}
.progress-inner{
position: relative;
width: 50px;
flex: 1;
height: 2px;
background: rgba(255, 255, 255, 0.4);
overflow: hidden;
}
.progress-bar{
position: absolute;
left: -100%;
top: 0;
width: 100%;
height: 100%;
background: #449284;
transform: translateX(0);
pointer-events: none;
}
.progress-ball{
position: absolute;
left: 0;
top: 50%;
width: 7px;
height: 14px;
transform: translate3d(-3px, -7px, 0);
background-color: #fff;
border-radius: 2px;
}
.time-box{
color: #fff;
font-size: 12px;
line-height: 14px;
width: 100px;
text-align: right;
}
.btn-screen{
width: 44px;
height: 44px;
background-image: url('~@/images/video/screen_full.png');
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: 20px auto;
}
.btn-screen-mini{
background-image: url('~@/images/video/screen_mini.png');
}
.rate-box{
position: relative;
color: #fff;
width: 40px;
height: 44px;
line-height: 44px;
font-size: 12px;
text-align: center;
}
.rate-list{
position: absolute;
left: 0;
bottom: 44px;
width: 100%;
background: rgba(0, 0, 0, .7);
border-radius: 2px;
}
.rate-item{
height: 30px;
line-height: 30px;
}
.rate-active{
color: #00a1d6;
}
.proved-box{
position: absolute;
color: #fff;
font-size: 12px;
left: 10px;
bottom: 44px;
height: 24px;
line-height: 24px;
padding: 0 12px;
border-radius: 12px;
background-color: rgba(0, 0, 0, .6);
span{
color: #FFA34B;
}
}
.cover-play{
background: url('~@/images/video/cover_play.png') no-repeat center center;
background-size: 50px auto;
}
.cover-error, .cover-resume{
p{
position: absolute;
left: 0;
top: 50%;
width: 100%;
color: #fff;
font-size: 15px;
text-align: center;
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{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
}
.default-img{
position: absolute;
left: 50%;
top: 50%;
min-width: 100%;
min-height: 100%;
max-width: 100%;
max-height: 100%;
transform: translate3d(-50%, -50%, 0);
}
}
</style>
......@@ -73,7 +73,7 @@
<!-- 弹窗放在外部处理 -->
<slot></slot>
<!-- 试看提示 -->
<div class="proved-box" v-show="showProved">
<div class="proved-box" v-show="logged && showProved">
可试看{{ proved > 59 ? `${parseInt(proved / 60)}分钟` : `${proved}秒` }},观看完整版请来 <span @click="download">云鹊医App</span>
</div>
<!-- 重新播放,只有试看有 -->
......
<template>
<!-- 组件详情页面:模块列表及其下面的元件列表 -->
<div class="page-container-merge" :style="{'position': isShowEJDialog ? 'fixed' : 'static'}">
<CommonNavbar
id="header"
:bgColor="bgColor"
v-show="isShowNavbar"
:isBlack="isBlack"
:isShowShare="isShowShare"
:title="navTitle"
:shareTitle="project.projectName"
:shareTitleInfo="project.projectIntro"
:isFixNavbar="isFixNavbar"
:burialPoint="pointStyle"
borderStyle="0px solid #fff"
:backMethod="from"
></CommonNavbar>
<div class="page-content list-container">
<!-- banner图片 -->
<div @click="gotoCourse()" v-if="bannerType == 1" class="page-content-img-container" style="position:relative;">
<img class="banner-img" :src="attachmentUrl" />
<img v-show="project.status == 5" class="banner-img-5" src="../images/status-keep-on.png" />
<img v-show="project.status == 10" class="banner-img-10" src="../images/status-end-cme.png" />
</div>
<!-- banner视频 -->
<div class="video-box" v-if="bannerType == 2">
<pica-video ref="picaVideo" @onVideoEnd="onVideoEnd" @onReplay="onReplay">
<!-- 试看结束 -->
<div class="cover" v-if="logged && coverType === 1">
<course-covers coverTips="试看结束<br />请来云鹊医App学习完整课程" :isSingle="true" rightBtnText="学习完整课程" @btnClick="btnClick" />
</div>
<!-- 播放结束,下载App -->
<div class="cover" v-if="logged && coverType === 2">
<course-covers coverTips="播放结束<br />更多其他课程,请前往鹊医App学习" :isSingle="true" rightBtnText="去云鹊医App" @btnClick="btnClick" />
</div>
<!-- 未登录 -->
<div class="cover" v-if="!logged">
<course-covers coverTips="登录后马上学习课程" :isSingle="true" rightBtnText="去登录" @btnClick="goLogin" />
</div>
</pica-video>
</div>
<!-- 项目标题 -->
<CommonDescription
:projectName="project.projectName"
:studyNum="project.studyNum"
:subject="project.subject"
/>
<CommonAdertImg :advertInfoList="advertInfoList" position="0" />
<!-- 步骤条 -->
<div v-if="project.cmeType != 2">
<CmeStep
:currentProgress="project.currentProgress"
:studyProgress="project.studyProgress"
:credit="project.credit"
:creditId="project.creditId"
:certificateUrl="project.certificateUrl"
:inScope="project.inScope"
:projectId="projectId"
:certificateId="project.certificateId"
@applicationCredit="applicationCredit"
/>
</div>
<!-- 简介和目录 -->
<div class="intro-catalogue-container">
<div
id="content-title"
class="title"
:class="{'fixed-title-1': (fixedFlag && !isWeb), 'fixed-title-2': (fixedFlag && isWeb)}"
>
<span :class="{'focus': tabFlag}" @click="jumpIntro">简介</span>
<span :class="{'focus': !tabFlag}" @click="jumpCatalogue">目录</span>
</div>
<div v-show="fixedFlag" class="fixed-flag-height"></div>
<div id="intro-content" class="intro-content">
<BasicInfo
:projectNo="project.projectNo"
:credit="project.credit"
:level="project.level"
:scope="project.scope"
:startDate="project.startDate"
:endDate="project.endDate"
:organName="project.organName"
:remind="project.remind"
:projectCredit="project.projectCredit"
:cmeType="project.cmeType"
:projectName="project.projectName"
/>
<LearnKnow :mustKnow="project.mustKnow"></LearnKnow>
<CommonSpliteLine></CommonSpliteLine>
<ItemIntro :textContent="textContent" @itemIntroText="itemIntroText"></ItemIntro>
<ItemLeader
v-if="projectLeader"
:projectLeader="projectLeader"
:leaderText="leaderText"
@changeLeaderText="changeLeaderText"
/>
<TeacterIntro v-if="doctorList.length" :doctorList="doctorList"></TeacterIntro>
</div>
<CommonSpliteLine></CommonSpliteLine>
<div id="catalogue-content" class="catalogue-content">
<div class="catalogue-title">目录</div>
<CellListDetailShare
:projectComponent="projectComponentDTOS"
:actionList="actionList"
:detailNum="detailNum"
:courseRequire="courseRequire"
:hasBindCard="hasBindCard"
:limitTimes="limitTimes"
:cmeType="project.cmeType"
:logged="logged"
:projectId="projectId"
/>
</div>
</div>
<CommonAdertImg needPadTop :advertInfoList="advertInfoList" position="1" />
<NoMoreContent />
<div v-if="detailNum <= 9" class="no-more-bottom"></div>
</div>
<!-- 弹框 -->
<CommonDialog
:isShowDialog="isShowDialog"
:isSingle="isSingle"
:cancleBtnText="cancleBtnText"
:confirmBtnText="confirmBtnText"
:content="dialogContent"
@handlerAction="handlerAction"
/>
<!-- 弹框 -->
<ExjumperDialog
:isShowDialog="isShowEJDialog"
isSingle
needSubContent
content="请确保您已经在云鹊平台购买学员优惠学习卡"
subContent="1. 跳转后点击“购买学习”,注册登录“中华医学教育在线”平台(首次登录需用手机号注册)<br/>2. 支付方式选择 “学习卡支付”,输入在云鹊平台已购学习卡的激活码,即可参加考试申请学分"
cancleBtnText="我知道了"
@handlerAction="handlerEJAction"
/>
<ExjumperButton
@btnClick="beforeJumpToExam"
v-if="project.cmeType == 2 && hasBindCard"
:btnText="project.currentProgress > 1 ? '参加考试' : '学完全部课程,可参加考试'"
:type="project.currentProgress > 1 ? 'primary' : 'disabled'"
></ExjumperButton>
<!-- <div v-if="project.cmeType == 2 && !isWeb" style="padding-top: 30px"></div> -->
<div style="padding-top: 20px"></div>
<!-- <BindCardButton
v-if="project.cmeType == 2 && !hasBindCard && !isWeb"
:cardInfo="cardInfo"
@changeClick="changeClick"
@gotoBuy="confirm"
></BindCardButton> -->
<BindCardButtonShare
v-if="!hasBindCard"
:cardInfo="cardInfo"
@changeClick="changeClick"
@gotoBuy="confirm"
></BindCardButtonShare>
<!--去激活-->
<ChangeCard
:changeErrorMsg="changeCardErrorMsg"
:isShow="showChangeCard"
@cancle="cancleChangeCard"
@confirm="changeCardAction">
</ChangeCard>
<Loading v-show="showLoading" />
<div>
<span ref="copyLinkBtn"
data-clipboard-action="copy"
class="cobyOrderSn"
:data-clipboard-text="this.project.cardKey"
@click="copyLink"
></span>
</div>
<!-- 未登录提示 -->
<div class="course-tips" v-if="!logged">
<CourseCovers isSingle coverTips="登录后马上学习课程" rightBtnText="去登录" @btnClick="btnClick"></CourseCovers>
</div>
<!-- 试看结束 -->
<div class="course-tips" v-if="isShowSkDialog">
<CourseCovers isSingle coverTips="试看结束<br>学习完整版课程,请来云鹊医App购买" rightBtnText="APP购买更优惠" @btnClick="download(1)"></CourseCovers>
</div>
<!-- 播放结束 -->
<div class="course-tips" v-if="isShowEndDialog">
<CourseCovers isSingle coverTips="播放结束<br>更多其他课程,请前往云鹊医APP学习" rightBtnText="APP购买更优惠" @btnClick="download(1)"></CourseCovers>
</div>
<!-- 本课程为付费课程 -->
<div class="course-tips" v-if="isShowFFDialog">
<CourseCovers isSingle coverTips="本课程为付费课程<br>学习完整版课程,请来云鹊医App购买" rightBtnText="APP购买更优惠" @btnClick="download(1)"></CourseCovers>
</div>
<div class="download-abs" @click="download">
<img src="../images/cme/course/pica-icon.png" alt="">
<span :class="{'short': needShort}">{{downloadTips}}</span>
</div>
</div>
</template>
<script>
import CommonNavbar from "@/components/common/common-navbar";
import CommonDescription from "@/components/common/common-description";
import CommonSpliteLine from "@/components/common/common-splite-line";
import CellListDetailShare from "@/components/business/cell-list-detail-share";
import Loading from "@/components/common/common-loading";
import CmeStep from "@/components/cme/cme-step";
import BasicInfo from "@/components/cme/basic-info";
import LearnKnow from "@/components/cme/learn-know";
import ItemIntro from "@/components/cme/item-intro";
import ItemLeader from "@/components/cme/item-leader";
import TeacterIntro from "@/components/cme/teacter-intro";
import CommonDialog from "@/components/cme/common-dialog";
import ExjumperDialog from "@/components/cme/exjumper-dialog";
import ExjumperButton from "@/components/cme/exjumper-button";
import NoMoreContent from "@/components/business/no-more-content";
import CommonAdertImg from "@/components/common/common-advert-img";
import { getWebPageUrl, gotoPage, getAppVersion } from "@/utils/index";
import { mapGetters, mapActions } from "vuex";
import vueFilters from "@/utils/filter";
import { Toast } from "vant";
// import CardPopup from "@/components/cme/card-popup";
import BindCardButtonShare from "@/components/cme/bind-card-button-share";
import ChangeCard from "@/components/cme/change-card";
import CourseCovers from "@/components/course/course-covers";
import PicaVideo from '@/components/course/pica-video';
let cataOffsetTop = 0;
let intorOffsetTop = 0;
let titleOffsetHeight = 50;
export default {
data() {
return {
coverType: 0,
downloadTips: "打开云鹊医APP",
isWeb: window.__isWeb,
isAndroid: __isAndroid,
textContent: "",
leaderText: "",
pageTitle: "",
isShowShare: true,
premissionFlag: false,
isSingle: false,
dialogContent: "", // 弹框内容
confirmBtnText: "", // 弹框按钮
cancleBtnText: "",
isShowDialog: false,
isShowEJDialog: false,
tabFlag: false, // 显示目录还是简介
fixedFlag: false, // 目录和简介是否固定
project: {
credit: "", // 学分
creditId: 0, // 学分Id
level: "", // 项目等级
scope: "", // 申请范围
remind: "", // 在不在范围提醒
startDate: 0, // 开始时间
endDate: 0, // 结束时间
organName: "", // 发起机构
projectName: "", // 项目名称
projectNo: "", // 项目编号
currentProgress: 0, // 项目进度
projectIntro: "", // 项目介绍
mustKnow: "", // 学习须知
studyNum: 0, // 学习人数
studyProgress: "0%", // 学习进度
subject: "", // 学科
status: 0, // 项目状态 5是进行中 10是已结束
certificateUrl: "", // 证书url
inScope: 0, // 是否在范围内判断
projectCredit: "", // 学分
certificateId: "0",
cmeType: 2, // 1: 自营项目; 2: 中华医学会二类
examBtnUrl: "", // 考试按钮跳转连接
firstIntoExam: false, // true弹框,是否首次进入考试,用于首次跳转弹框提示,只跟项目和人员有关
jumpToContents: false, // 是否跳转到目录
cardStatus: 0,
cardKey: '',
// cmeType=2时不显示进度,
// projectNo为空时不显示项目编号,
// projectLeader为空时不显示项目负责人,
// inScope=0时考试按钮不显示,
// currentProgress>1时考试按钮显示并可用
},
hasBindCard: false, // 是否绑定过学习卡或激活过 没有绑定,则显示绑定按钮
limitTimes: 60,
projectLeader: {},
doctorList: [],
from: "inner",
isBlack: false,
showLoading: false,
projectId: "1",
contentList: [],
bannerType: 2, // 1 图片 2视频
videoOptions: {
mp4: "",
autoplay: false, //iOS下safari浏览器,以及大部分移动端浏览器是不开放视频自动播放这个能力的
coverpic: require("../images/video-cover.png"),
width: "415", //视频的显示宽度,请尽量使用视频分辨率宽度
height: "210", //视频的显示高度,请尽量使用视频分辨率高度
trySeeTime: "",
x5_fullscreen: false,
},
// attachmentUrl: require("../images/banner-default.png"),
attachmentUrl: require("../images/video-cover.png"),
bgColor: "none",
navTitle: "项目详情",
// compTitle: "组件名称",
isShowNavbar: true,
isFixNavbar: true,
pointStyle: "activity",
projectComponentDTOS: [],
actionList: [],
detailNum: 0,
courseRequire: 0,
clientType: 0,
// currentProgress>1时考试按钮显示并可用
btnType: "primary", // primary: 可跳转时(currentProgress = 1); disabled: 不可跳转时
btnText: "学完全部课程,可参加考试", // 参加考试(currentProgress = 1); 或者学完全部课程,可参加考试
provinceId: "",
organizationId: "",
cardInfo: {
id: 0
},
advertInfoList: [],
showChangeCard: false, //是否展示激活弹框,
changeCardErrorMsg: "",
skCourseId: 0,
isShowSkDialog: false,
isShowEndDialog: false,
isShowFFDialog: false,
needShort: false,
uuid: '',
token: ''
};
},
components: {
CommonNavbar,
CommonDescription,
CommonSpliteLine,
CellListDetailShare,
Loading,
CmeStep,
BasicInfo,
LearnKnow,
ItemIntro,
ItemLeader,
TeacterIntro,
CommonDialog,
ExjumperButton,
ExjumperDialog,
// CardPopup,
CommonAdertImg,
NoMoreContent,
BindCardButtonShare,
ChangeCard,
CourseCovers,
PicaVideo
},
computed: {
...mapGetters(["userInfo", "logged"])
},
created() {
let _this = this;
this.from = this.$route.query.from || this.from || "native";
let href = location.href;
let uuidIndex = href.indexOf('uuid') || 0;
if(uuidIndex > 0) {
this.uuid = href.substr(uuidIndex + 5, 32);
} else {
this.uuid = '07F9625472D6444EBAE4BF7D2EF83BC4'
}
if(href.indexOf('singlemessage') >= 0) {
let shareUrl = getWebPageUrl(`cme/#/sharecoop?uuid=${this.uuid}`);
location.replace(shareUrl);
}
const { token, info } = this.$store.state.user;
this.token = token;
// 如果有token,但没有用户信息,则获取用户信息
if (token && !info.id) {
this.$store.dispatch('getUserInfo');
}
this.queryByUuid(this.uuid);
// 调用广告位接口
this.getAdvertInfoList();
},
mounted() {
window.addEventListener("scroll", this.scrollFun);
},
beforeDestroyed() {
window.removeEventListener("scroll", this.scrollFun);
},
methods: {
...mapActions(["setUserInfo", "goLogin"]),
// 解析uuid
queryByUuid(uuid) {
let param = {
uuid: uuid
};
this.GET(`portal/shareParam/queryByUuid`, param).then(res => {
if (res.code == "000000") {
this.projectId = res.data;
this.getProjectParticularsV2();
console.log('queryByUuid', res);
}
});
},
// 视频播放结束
onVideoEnd(opt) {
if (opt.type === 1) {
this.coverType = 2;
} else if (opt.type === 2) { // 试看结束
this.coverType = 1;
}
},
onReplay() {
this.coverType = 0;
},
btnClick() {
this.goLogin();
},
download() {
window.location.href =
"https://a.app.qq.com/o/simple.jsp?pkgname=com.picahealth.yunque";
},
cancleChangeCard() {
this.showChangeCard = false;
},
// 激活 返回值:0绑定失败,1绑定成功
changeCardAction(cardKey) {
let _this = this;
let param = {
cardKey: cardKey,
cardType: 2,
portalProjectId: this.projectId,
setEntry: true
};
_this.changeCardErrorMsg = "";
this.POST("cme/projectCard/bind", param).then(res => {
if (res.code == "000000") {
if(res.data == 0) {
_this.changeCardErrorMsg = "请输入正确的激活码";
} else {
_this.showChangeCard = false;
Toast("激活成功,开始学习");
_this.getProjectParticularsV2();
}
} else {
}
}).catch( e => {
_this.changeCardErrorMsg = "请输入正确的激活码";
});
},
// 复制卡密
copyLink() {
let _this = this;
let clipboard = new this.clipboard(".cobyOrderSn");
clipboard.on("success", function() {
Toast("已成功复制激活码");
});
clipboard.on("error", function() {
Toast("复制激活码失败");
});
},
// 查询教培项目广告位配置信息
getAdvertInfoList() {
let param = {
setEntry: true
};
this.GET(`portal/jump/${this.projectId}/1`, param).then(res => {
if (res.code == "000000") {
this.advertInfoList = (res.data && res.data.list) || [];
console.log("advertInfoList", this.advertInfoList);
}
});
},
// 点击弹层
clickOverlay() {
console.log("clickOverlay");
},
// 点击“参与考试”
beforeJumpToExam() {
// this.$sendBuriedData({
// component_tag: `882#8824`
// });
// 如果是首次,则弹出弹框
if (this.project.firstIntoExam) {
this.isShowEJDialog = true;
} else {
this.jumpToCardList();
}
},
// 第一次跳转弹框,点击时调用相应接口
handlerEJAction() {
// this.$sendBuriedData({
// component_tag: `883#8831`
// });
this.isShowEJDialog = false;
this.jumpToCardList();
this.firstIntoExamAction();
},
// 跳转II类学习详情页面(中华医学会项目详情页面)
jumpToCardList() {
// this.$sendBuriedData({
// component_tag: `885#8851`
// });
this.showLoading = false;
// 复制卡密
this.$refs.copyLinkBtn.click();
window.location.href = this.project.examBtnUrl;
},
// 跳转前判断是否有机构,否则使用定位信息
preJumper() {
this.getCardInfoByProvinceId(this.provinceId || "");
},
// 根据省ID,获取学习卡信息
getCardInfoByProvinceId(provinceId) {
let param = {
area: provinceId + "",
cardType: 2,
pageNum: 1,
pageSize: 1
};
this.POST("trade/goods/cardList", param).then(res => {
if (res.code == "000000") {
this.showLoading = false;
this.cardInfo = (res.data && res.data[0]) || { id: 0 };
}
});
},
// 跳转到原生的购买页面
// TODO 没有购买逻辑了,直接跳转到下载页面
confirm() {
// this.$sendBuriedData({
// component_tag: `882#88203`
// });
window.location.href =
"https://a.app.qq.com/o/simple.jsp?pkgname=com.picahealth.yunque";
},
// 首次进入考试时记录(点击‘我知道了’时调用)
firstIntoExamAction() {
let _this = this;
let param = {
token: _this.token,
setEntry: true
};
this.NEW_POST(`cme/project/${_this.projectId}/firstIntoExam`, param).then(
res => {
if (res.code == "000000") {
this.project.firstIntoExam = false;
}
}
);
},
// token是否失效校验
checkToken() {
let _this = this;
let param = {
token: _this.token,
setEntry: true
};
this.GET("campaign/admin/task/checkToken", param).then(res => {
if (res.code !== "000000") {
//未登录 跳转登录页
rocNative.gotoLogin();
} else {
// if (!_this.premissionFlag) {
// _this.premissionFlag = true;
// _this.permission(); // 提示是否有机构和在申请范围内
// }
}
});
},
//(判断是否加入机构,是否为认证用户,是否在申请范围内)
permission() {
let _this = this;
let param = {
id: _this.projectId,
creditId: _this.project.creditId,
token: _this.token,
setEntry: true
};
_this.NEW_POST("cme/credit/rangeCheck", param).then(res => {
if (
_this.project.cmeType != 2 &&
(res.code == "219004" || res.code == "219012")
) {
// 未加入机构 219004 不在申请范围 219012
this.dialogContent = `该项目仅对${_this.project.scope}的用户开放`;
this.cancleBtnText = "我知道了";
this.isShowDialog = true;
this.isSingle = true;
} else {
this.isShowDialog = false;
}
});
},
// 立即申请学分
applicationCredit() {
let _this = this;
let param = {
id: _this.projectId,
creditId: _this.project.creditId,
token: _this.token,
setEntry: true
};
_this.NEW_POST("cme/credit/applyCheck", param).then(res => {
if (res.code == "000000") {
gotoPage(
_this,
`cme/#/credit-edit?creditId=${_this.project.creditId}`
);
} else if (res.code == "219004" || res.code == "219005") {
// 未加入机构 219004 未身份认证 219005 不在申请范围 219012
let params = {
__funcName: "__checkPermissions",
permCode: "009014"
};
rocNative.checkPermissions(params);
} else {
this.dialogContent = res.message;
this.cancleBtnText = "我知道了";
this.isShowDialog = true;
this.isSingle = true;
}
});
},
//去激活
changeClick(msg) {
console.log("in changeClick");
this.showChangeCard = true;
},
// 弹框按钮事件
handlerAction(data) {
this.isShowDialog = false;
},
scrollFun() {
//如果是第一次的弹框,则直接退出
if(this.isShowEJDialog) return;
let scrollTop =
document.body.scrollTop || document.documentElement.scrollTop;
let h = intorOffsetTop - 135;
// 显示头部导航
if (scrollTop > 20) {
this.isBlack = true;
this.bgColor = "#fff";
} else {
this.isBlack = false;
this.bgColor = "none";
}
if (window.__isWeb) {
h = intorOffsetTop - 88;
} else if (window.__isIOS) {
h = intorOffsetTop - 140;
}
// 如果滚动高度大于简介头部(并减去tab高度),则进行固定
if (scrollTop > h) {
this.fixedFlag = true;
} else {
this.fixedFlag = false;
}
// 如果滚动高度大于
if (scrollTop > cataOffsetTop - 600) {
this.tabFlag = false;
} else {
this.tabFlag = true;
}
},
// 锚点到简介
jumpIntro() {
if (!this.tabFlag) {
this.tabFlag = true;
}
if (!this.fixedFlag) {
this.fixedFlag = true;
}
let h;
if (this.isWeb) {
h = intorOffsetTop - 30 - titleOffsetHeight;
} else {
h = intorOffsetTop - 85 - titleOffsetHeight;
}
window.scrollTo(0, h);
this.isBlack = true;
this.bgColor = "#fff";
// this.$sendBuriedData({
// component_tag: `211#211007#${this.projectId}`
// });
},
// 锚点到目录
jumpCatalogue() {
if (this.tabFlag) {
this.tabFlag = false;
}
if (!this.fixedFlag) {
this.fixedFlag = true;
}
let h;
if (this.isWeb) {
h = cataOffsetTop - titleOffsetHeight;
} else {
h = cataOffsetTop - 100;
}
window.scrollTo(0, h);
this.isBlack = true;
this.bgColor = "#fff";
// this.$sendBuriedData({
// component_tag: `211#211008#${this.projectId}`
// });
},
// 获取项目详情
getProjectParticularsV2() {
let _this = this;
let param = {
token: _this.token,
setEntry: true
};
let videoUrl = this.$route.query.videoUrl || '';
if(videoUrl) {
param.trySeeFlag = 0;
} else {
param.trySeeFlag = 1;
}
_this.showLoading = true;
this.NEW_GET(`cme/project/${_this.projectId}/info`, param).then(res => {
if (res.code == "000000") {
// 首先使用配置中的参数中的获取视频地址及视频时间
setTimeout(() => {
this.downloadTips = '';
this.needShort = true;
}, 5000);
if(videoUrl) {
_this.limitTimes = this.$route.query.trySeeTime || 300000;
_this.videoOptions.mp4 = videoUrl;
_this.videoOptions.trySeeTime = this.$route.query.trySeeTime || 300000;
} else {
_this.limitTimes = res.data.trySeeTime;
_this.videoOptions.mp4 = res.data.attachmentUrl;
_this.videoOptions.trySeeTime = res.data.trySeeTime || 300000;
}
_this.hasBindCard = res.data.cardStatus == 0 ? false : true;
if(this.hasBindCard) {
_this.videoOptions.trySeeTime = 300000;
_this.videoOptions.autoplay = false;
}
let mp4Url = _this.videoOptions.mp4;
// 判断是否是mp4
if(mp4Url.lastIndexOf('.mp4') > 0) {
_this.bannerType = 2;
this.$nextTick( () => {
console.log('_this.$refs.picaVideo', _this.$refs.picaVideo);
_this.$refs.picaVideo.switchUrl({
url: mp4Url,
proved: _this.videoOptions.trySeeTime,
enable: true,
});
})
} else {
if (res.data.attachmentType == 2) {
_this.videoOptions.mp4 = res.data.attachmentUrl;
} else {
_this.attachmentUrl = res.data.attachmentUrl;
}
_this.bannerType = res.data.attachmentType;
}
console.log('location', location);
console.log('_this.videoOptions.mp4, trySeeTime, autoplay', _this.videoOptions.mp4, _this.videoOptions.trySeeTime, _this.videoOptions.autoplay);
// 如果绑定了卡,则提示学习下一节
_this.project = res.data;
if (_this.project.projectIntro) {
_this.textContent =
_this.project.projectIntro.length > 70
? _this.project.projectIntro.slice(0, 70) + "..."
: this.project.projectIntro;
}
_this.project.mustKnow = _this.project.mustKnow.replace(
/(\r\n)|\r|\n/g,
"<br>"
);
_this.projectLeader = res.data.projectLeader;
if (_this.projectLeader && _this.projectLeader.info) {
_this.leaderText =
_this.projectLeader.info.length > 70
? _this.projectLeader.info.slice(0, 70) + "..."
: this.projectLeader.info;
}
_this.doctorList = res.data.doctorList;
_this.projectComponentDTOS = _this.setListData(
res.data.projectComponentDTOS
);
if (!_this.isWeb && !_this.premissionFlag) {
_this.premissionFlag = true;
_this.permission(); // 提示是否有机构和在申请范围内
}
// TODO Add by Anndy Yang
if (_this.project.currentProgress == 2) {
_this.$nextTick(() => {
window.scrollTo(0, 0);
});
}
_this.provinceId = res.data.positionModel.provinceId;
_this.organizationId = res.data.positionModel.organizationId;
_this.courseRequire = res.data.courseRequire || 0;
setTimeout(() => {
cataOffsetTop = document.getElementById("catalogue-content")
.offsetTop;
intorOffsetTop = document.getElementById("intro-content").offsetTop;
console.log(
"getProjectParticularsV2",
cataOffsetTop,
intorOffsetTop
);
// if (_this.hasBindCard) {
// setTimeout(() => {
// this.jumpCatalogue();
// }, 200);
// }
}, 200);
setTimeout(() => {
_this.showLoading = false;
}, 800);
// 如果 hasBindCard 为false,则获取卡信息 0:未绑卡 1:已绑卡
if (!_this.hasBindCard) {
_this.preJumper();
}
// let shareUrl = encodeURIComponent(location.href);
let shareUrl = getWebPageUrl(`cme/#/sharecoop?uuid=${this.uuid}`);
this.wechatShare(
{
link: shareUrl,
title: this.project.projectName,
friendtitle: this.project.projectName,
desc: this.project.projectName,
imgUrl: "https://file.yunqueyi.com/logo.png"
},
() => {
console.log("share success...");
}
);
console.log('hasBindCard, limitTimes', _this.hasBindCard, _this.limitTimes);
}
});
},
// 项目负责人--详情(收起)
changeLeaderText(data) {
let _this = this;
if (_this.projectLeader.info) {
if (!data.allTextFlag) {
_this.leaderText =
_this.projectLeader.info.length > 70
? _this.projectLeader.info.slice(0, 70) + "..."
: this.projectLeader.info;
} else {
_this.leaderText = _this.projectLeader.info;
}
}
},
// 项目介绍
itemIntroText(data) {
let _this = this;
if (_this.project.projectIntro) {
if (!data.allTextFlag) {
_this.textContent =
_this.project.projectIntro.length > 70
? _this.project.projectIntro.slice(0, 70) + "..."
: this.project.projectIntro;
} else {
_this.textContent = _this.project.projectIntro;
}
}
},
setListData(data) {
let _this = this;
let list = data;
let actionList = [];
let detailNum = 0;
let hasFindCourseOrExam = false;
let item = null;
for (let i = 0; i < list.length; i++) {
for (let j = 0; j < list[i].portalModuleDTOS.length; j++) {
detailNum++;
if (list[i].portalModuleDTOS[j].status === 2) {
list[i].portalModuleDTOS[j].value =
"共" + list[i].portalModuleDTOS[j].nodeCount + "节";
} else {
list[i].portalModuleDTOS[j].value = "尚未开始";
}
list[i].portalModuleDTOS[j].disabled =
list[i].portalModuleDTOS[j].status === 2 ? false : true;
//展开项记录
if (list[i].portalModuleDTOS[j].expandStatus == 1) {
actionList.push(list[i].portalModuleDTOS[j].expandKey);
}
for (
let z = 0;
z < list[i].portalModuleDTOS[j].contentList.length;
z++
) {
list[i].portalModuleDTOS[j].contentList[z].height = _this.getHight(
list[i].portalModuleDTOS[j].contentList[z]
);
}
}
}
_this.actionList = actionList;
_this.detailNum = detailNum;
console.log("list转为:", list, actionList, detailNum);
return list;
},
getHight(data) {
let len = vueFilters.strLength(data.name);
let certificate = data.certificateFlag;
if (len > 30 && certificate == 2) {
return "2";
} else if (len > 30 && certificate != 2) {
return 2;
} else if (len <= 30 && certificate == 2) {
return "1";
} else if (len <= 30 && certificate != 2) {
return 1;
}
},
// 跳转到考试
gotoExamNew: function() {
Toast("请前往APP进行考试");
},
// 跳转到课程(H5)
gotoCourseNew: function() {
window.location.href = ""
},
}
};
</script>
<style lang="less" scoped>
.page-container-merge {
.nav-top .nav-title {
height: 0px;
// padding: 18px;
}
.banner-img {
display: inherit;
width: 375px;
height: 210px;
&-1 {
position: absolute;
left: 0;
top: 180px;
width: 76px;
height: 30px;
}
&-5 {
position: absolute;
left: 0;
top: 180px;
width: 76px;
height: 30px;
}
&-10 {
position: absolute;
left: 0;
top: 180px;
width: 76px;
height: 30px;
}
}
.video-box{
position: relative;
height: 210px;
}
.list-container {
// margin-bottom: 40px;
.sk-btn-cover {
position: absolute;
top: 82px;
left: 163px;
z-index: 100;
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
background: #fff;
color: rgba(68, 146, 132, 1);
font-size: 13px;
border-radius: 50%;
}
.sk-btn-cover-new {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 210px;
z-index: 100;
text-align: center;
// background: #fff;
font-size: 13px;
// border-radius: 50%;
background: rgba(51, 51, 51, 0.8);
span {
display: inline-block;
margin-top: 82px;
width: 100px;
height: 36px;
line-height: 36px;
font-size: 15px;
font-weight: 700;
border-radius: 20px;
color: #fff;
background: #449284;
&.android {
padding-top: 2px;
} }
// opacity: ;
}
}
.intro-catalogue-container {
.title {
height: 50px;
line-height: 30px;
padding: 0 15px;
border-bottom: 1px solid #f0f1f2;
span {
display: inline-block;
line-height: 15px;
font-size: 15px;
color: #979899;
padding-right: 35px;
}
span.focus {
position: relative;
color: #373839;
}
span.focus:after {
content: "";
position: absolute;
left: 9px;
bottom: -14px;
background: #449284;
// border-bottom: 1px solid #449284;
width: 10px;
height: 3px;
border-radius: 3px;
}
}
.title.fixed-title-1 {
position: fixed;
left: 0;
top: 60px;
background: #fff;
width: 100%;
z-index: 999;
}
.title.fixed-title-2 {
position: fixed;
left: 0;
top: 0px;
background: #fff;
width: 100%;
z-index: 999;
}
.catalogue-content {
padding: 30px 15px 0;
.catalogue-title {
font-size: 18px;
color: #373839;
font-weight: 700;
margin-bottom: 16px;
}
}
.fixed-flag-height {
height: 50px;
}
}
}
.no-more-bottom {
position: relative;
width: 100%;
height: 40px;
}
.course-tips {
width: 100%;
position: absolute;
z-index: 100;
top: 0;
left: 0;
}
.download-abs {
display: flex;
// width: 100%;
position: absolute;
z-index: 1001;
top: 15px;
right: 0;
height: 30px;
align-items: center;
img {
position: relative;
left: 15px;
width: 30px;
height: 30px;
}
span {
display: inline-block;
height: 30px;
line-height: 30px;
padding: 0 8px 0 23px;
font-size: 12px;
font-weight: 700;
color: #5BA99B;
background: #fff;
width: 120px;
&.short {
width: 10px;
transition: width 1s;
-moz-transition: width 1s; /* Firefox 4 */
-webkit-transition: width 1s; /* Safari 和 Chrome */
-o-transition: width 1s; /* Opera */
padding: 0 12px;
}
}
}
</style>
......@@ -421,8 +421,8 @@ export default {
};
this.GET(`portal/shareParam/queryByUuid`, param).then(res => {
if (res.code == "000000") {
this.shareParam = JSON.parse(res.data);
this.projectId = this.shareParam.projectId || 178;
this.shareParam = JSON.parse(res.data || "{}");
this.projectId = this.shareParam.projectId || 0; // 178
this.getProjectParticularsV2();
console.log('queryByUuid', res);
}
......
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册