bug:15685、15588、15575
parent
dcbe398e58
commit
23126c74e9
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,154 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<link rel="stylesheet" href="./plyr/plyr.css"/>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.plyr {
|
||||
--plyr-control-icon-size: 5vmin;
|
||||
--plyr-font-size-time: 4.5vmin;
|
||||
|
||||
.plyr__time + .plyr__time {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
#player {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div>
|
||||
<video id="player" playsinline controls data-poster="" style="width: 100vw">
|
||||
<source src="" type="video/mp4"/>
|
||||
</video>
|
||||
</div>
|
||||
</body>
|
||||
<script src="./js/hybrid_html_uni.webview.1.5.5.js"></script>
|
||||
<script src="./plyr/plyr.js"></script>
|
||||
<script src="./hls/hls.js"></script>
|
||||
<script>
|
||||
let player = null
|
||||
let hls = null
|
||||
let currentTimeTimer = null
|
||||
let isSeekEnd = false
|
||||
let src = ''
|
||||
let playTime = ''
|
||||
let poster = ''
|
||||
|
||||
function setCurrentTime(type) {
|
||||
currentTimeTimer && clearTimeout(currentTimeTimer);
|
||||
currentTimeTimer = setTimeout(() => {
|
||||
player.currentTime = playTime;
|
||||
// 如果初始没有设置上开始播放时间,递归调用直到设置上为止
|
||||
if (type === "ready" && !isSeekEnd && Math.abs(player.currentTime - playTime) > 2) {
|
||||
setCurrentTime(type);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function initVideo() {
|
||||
const video = document.querySelector("#player")
|
||||
video.setAttribute('data-poster', src)
|
||||
video.querySelector('source').setAttribute('src', poster)
|
||||
player = new Plyr(video, {
|
||||
type: "",
|
||||
autoplay: true,
|
||||
controls: [
|
||||
"play-large",
|
||||
"play",
|
||||
"current-time",
|
||||
"duration",
|
||||
"mute",
|
||||
"volume",
|
||||
"captions",
|
||||
"fullscreen",
|
||||
],
|
||||
seekTime: 0,
|
||||
ratio: "16:9",
|
||||
speed: {selected: 1, options: [1]},
|
||||
});
|
||||
hls = new Hls();
|
||||
hls.loadSource(src);
|
||||
hls.attachMedia(video);
|
||||
player.play();
|
||||
player.on("ready", () => {
|
||||
setCurrentTime("ready")
|
||||
document.title = JSON.stringify({
|
||||
eventName: 'ready',
|
||||
currentTime: player ? player.currentTime : ''
|
||||
})
|
||||
});
|
||||
player.on("seeking", () => {
|
||||
isSeekEnd = false;
|
||||
document.title = JSON.stringify({
|
||||
eventName: 'seeking',
|
||||
currentTime: player ? player.currentTime : ''
|
||||
})
|
||||
});
|
||||
player.on("seeked", () => {
|
||||
isSeekEnd = true;
|
||||
document.title = JSON.stringify({
|
||||
eventName: 'seeked',
|
||||
currentTime: player ? player.currentTime : ''
|
||||
})
|
||||
});
|
||||
player.on("play", () => {
|
||||
document.title = JSON.stringify({
|
||||
eventName: 'play',
|
||||
currentTime: player ? player.currentTime : ''
|
||||
})
|
||||
});
|
||||
player.on("pause", () => {
|
||||
document.title = JSON.stringify({
|
||||
eventName: 'pause',
|
||||
currentTime: player ? player.currentTime : ''
|
||||
})
|
||||
});
|
||||
player.on("ended", () => {
|
||||
document.title = JSON.stringify({
|
||||
eventName: 'ended',
|
||||
currentTime: player ? player.currentTime : ''
|
||||
})
|
||||
});
|
||||
player.on("timeupdate", () => {
|
||||
if (player.currentTime - playTime > 5) {
|
||||
playTime = player.currentTime;
|
||||
document.title = JSON.stringify({
|
||||
eventName: 'timeupdate',
|
||||
currentTime: player ? player.currentTime : ''
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('UniAppJSBridgeReady', function () {
|
||||
const data = plus.webview.getWebviewById("video")
|
||||
src = data.src
|
||||
poster = data.poster
|
||||
playTime = +data.playTime
|
||||
initVideo()
|
||||
});
|
||||
|
||||
function htmlMessage(event) {
|
||||
if (player) {
|
||||
switch (event) {
|
||||
case 'fullscreen.exit':
|
||||
player.fullscreen.active && player.fullscreen.exit()
|
||||
break
|
||||
default:
|
||||
player[event]()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</html>
|
|
@ -6,20 +6,30 @@
|
|||
<!-- </cu-custom>-->
|
||||
<view id="fixed">
|
||||
<view v-if="videoSrc">
|
||||
<video
|
||||
id="video"
|
||||
<web-view-video
|
||||
ref="video"
|
||||
:src="videoSrc"
|
||||
:poster="videoPoster"
|
||||
autoplay
|
||||
controls
|
||||
style="width: 100vw"
|
||||
:show-progress="false"
|
||||
:enable-progress-gesture="false"
|
||||
:play-time="serverVideoPlayTime"
|
||||
@play="fnPlay"
|
||||
@pause="fnPause"
|
||||
@ended="fnEnded"
|
||||
@timeupdate="fnTimeUpdate"
|
||||
/>
|
||||
<!-- <video-->
|
||||
<!-- id="video"-->
|
||||
<!-- :src="videoSrc"-->
|
||||
<!-- :poster="videoPoster"-->
|
||||
<!-- autoplay-->
|
||||
<!-- controls-->
|
||||
<!-- style="width: 100vw"-->
|
||||
<!-- :show-progress="false"-->
|
||||
<!-- :enable-progress-gesture="false"-->
|
||||
<!-- @play="fnPlay"-->
|
||||
<!-- @pause="fnPause"-->
|
||||
<!-- @ended="fnEnded"-->
|
||||
<!-- @timeupdate="fnTimeUpdate"-->
|
||||
<!-- />-->
|
||||
</view>
|
||||
<image
|
||||
v-if="!videoSrc"
|
||||
|
@ -110,11 +120,15 @@
|
|||
|
||||
<script>
|
||||
import {basePath, loginUser, baseImgPath} from "@/common/tool";
|
||||
import WebViewVideo from './web_view_video.vue'
|
||||
|
||||
let faceAuthTimer; // 人脸认证计时器
|
||||
let throttleTimer;
|
||||
let throttleFlag;
|
||||
export default {
|
||||
components: {
|
||||
WebViewVideo,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
baseImgPath,
|
||||
|
@ -141,7 +155,6 @@ export default {
|
|||
videoSrc: "", // 视频地址
|
||||
videoPoster: "", // 视频封面图
|
||||
scrollHeight: '0px', // scroll-view减去的高度
|
||||
videoContext: null, // 视频上下文
|
||||
submitTimeWaitForCount: 0, // 提交时间等待次数
|
||||
verification:false,// 是否人脸认证
|
||||
}
|
||||
|
@ -151,6 +164,7 @@ export default {
|
|||
this.CLASS_ID = options.CLASS_ID;
|
||||
this.STUDENT_ID = options.STUDENT_ID;
|
||||
this.ISFACE = options.ISFACE;
|
||||
// this.ISFACE = '0';
|
||||
this.fnInit();
|
||||
},
|
||||
onReady() {
|
||||
|
@ -168,6 +182,7 @@ export default {
|
|||
},
|
||||
beforeDestroy() {
|
||||
uni.$off('verification')
|
||||
this.fnClearInterval()
|
||||
},
|
||||
watch: {
|
||||
verification() {
|
||||
|
@ -326,7 +341,9 @@ export default {
|
|||
this.videoList = resData.pd.VIDEOLIST;
|
||||
},
|
||||
async fnVideoSwitching(videoData, hasNodes, index, index1) {
|
||||
this.videoContext && this.videoContext.pause();
|
||||
this.$refs.video && this.$refs.video.fn('destroy')
|
||||
this.videoSrc = "";
|
||||
this.videoPoster = "";
|
||||
this.submitTimeWaitForCount = 0;
|
||||
if (this.changeVideoPlayTime !== 0) {
|
||||
await this.fnSubmitPlayTime("0", this.changeVideoPlayTime);
|
||||
|
@ -339,8 +356,6 @@ export default {
|
|||
if (this.ISFACE === "1") {
|
||||
await this.fnNavigationFaceAuth();
|
||||
} else {
|
||||
this.videoSrc = "";
|
||||
this.videoPoster = "";
|
||||
await this.fnGetVideoPlayInfo();
|
||||
}
|
||||
},
|
||||
|
@ -349,11 +364,9 @@ export default {
|
|||
VIDEOCOURSEWARE_ID: this.videoData.VIDEOCOURSEWARE_ID,
|
||||
CURRICULUM_ID: this.videoData.CURRICULUM_ID,
|
||||
});
|
||||
this.videoSrc = resData.PLAYURLMP4 || resData.PLAYURL;
|
||||
this.videoPoster = resData.COVERURL;
|
||||
await this.fnGetVideoPlayProgress();
|
||||
await this.fnGetVideoPlayProgress(resData.PLAYURL, resData.COVERURL);
|
||||
},
|
||||
async fnGetVideoPlayProgress() {
|
||||
async fnGetVideoPlayProgress(PLAYURL, COVERURL) {
|
||||
const resData = await this.post('/app/coursestudyvideorecord/getVideoProgress',{
|
||||
VIDEOCOURSEWARE_ID: this.videoData.VIDEOCOURSEWARE_ID,
|
||||
CURRICULUM_ID: this.videoData.CURRICULUM_ID,
|
||||
|
@ -364,51 +377,23 @@ export default {
|
|||
await this.fnSubmitPlayTime("0", 0);
|
||||
}
|
||||
this.serverVideoPlayTime = Math.floor(resData.pd.RESOURCETIME) || 0
|
||||
if (this.ISFACE === "1") {
|
||||
if (this.verification) {
|
||||
this.fnCreateVideo();
|
||||
} else {
|
||||
this.fnCreateVideo();
|
||||
}
|
||||
} else {
|
||||
this.fnCreateVideo();
|
||||
}
|
||||
},
|
||||
fnCreateVideo() {
|
||||
if (!this.videoContext) {
|
||||
this.videoContext = uni.createVideoContext("video");
|
||||
}
|
||||
this.videoContext.play();
|
||||
this.serverVideoPlayTime !== 0 && this.videoContext.seek(this.serverVideoPlayTime);
|
||||
this.videoSrc = PLAYURL;
|
||||
this.videoPoster = COVERURL;
|
||||
},
|
||||
fnTimeUpdate(event) {
|
||||
this.throttle(async () => {
|
||||
const currentTime = event.detail.currentTime;
|
||||
if (currentTime - this.serverVideoPlayTime >= 10) {
|
||||
if (event - this.serverVideoPlayTime >= 10) {
|
||||
uni.navigateBack();
|
||||
return;
|
||||
}
|
||||
//app视频自带bug,判断当前视频进度与服务器进度差,如果小于10秒,则退出重新进
|
||||
// if(currentTime !== 0 && Math.abs(currentTime - this.serverVideoPlayTime) > 10) {
|
||||
// this.videoContext.pause();
|
||||
// uni.showModal({
|
||||
// title: "提示",
|
||||
// content: "app开发环境问题,偶现当前视频进度获取不准确,为了防止进度被覆盖,请退出重新进入!",
|
||||
// showCancel:false,
|
||||
// success: (res) => {
|
||||
// uni.navigateBack();
|
||||
// return;
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
this.changeVideoPlayTime = currentTime;
|
||||
if (currentTime - this.serverVideoPlayTime >= 5) {
|
||||
this.serverVideoPlayTime = currentTime;
|
||||
this.changeVideoPlayTime = event;
|
||||
if (event - this.serverVideoPlayTime >= 5) {
|
||||
this.serverVideoPlayTime = event;
|
||||
this.submitTimeWaitForCount = ++this.submitTimeWaitForCount;
|
||||
}
|
||||
if (this.submitTimeWaitForCount === 6) {
|
||||
this.submitTimeWaitForCount = 0;
|
||||
await this.fnSubmitPlayTime("0", currentTime);
|
||||
await this.fnSubmitPlayTime("0", event);
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
|
@ -462,7 +447,8 @@ export default {
|
|||
this.videoList[this.firstIndex].percent = percent;
|
||||
}
|
||||
if (resData.pd.CANEXAM === "1") {
|
||||
this.videoContext.pause();
|
||||
this.$refs.video && this.$refs.video.fn('pause')
|
||||
this.$refs.video && this.$refs.video.fn('fullscreen.exit')
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "当前班级内所有课程均已学完,是否直接参加考试?",
|
||||
|
@ -470,12 +456,11 @@ export default {
|
|||
cancelButtonText: "否",
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.videoContext && this.videoContext.exitFullScreen()
|
||||
uni.navigateTo({
|
||||
url: '/pages/application/onlinexxks/course_exam?STAGEEXAMPAPERINPUT_ID=' + resData.paper.STAGEEXAMPAPERINPUT_ID + '&STAGEEXAMPAPER_ID=' + resData.paper.STAGEEXAMPAPERINPUT_ID + '&CLASS_ID=' + this.CLASS_ID + '&POST_ID=' + resData.pd.POST_ID + '&STUDENT_ID=' + this.STUDENT_ID + '&NUMBEROFEXAMS=' + resData.pd.NUMBEROFEXAMS + '&entrySite=video_study'
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
this.videoContext.play();
|
||||
this.$refs.video && this.$refs.video.fn('play')
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -488,7 +473,6 @@ export default {
|
|||
}
|
||||
this.changeVideoPlayTime = 0;
|
||||
this.fnSubmitPlayTime("1", 0);
|
||||
this.videoContext.pause();
|
||||
this.fnClearInterval();
|
||||
},
|
||||
fnPlay() {
|
||||
|
@ -499,6 +483,10 @@ export default {
|
|||
}
|
||||
faceAuthTimer = setInterval(async () => {
|
||||
if (new Date().getTime() >= this.randomTime) {
|
||||
this.fnClearInterval();
|
||||
this.$refs.video && this.$refs.video.fn('fullscreen.exit')
|
||||
this.videoSrc = ''
|
||||
this.videoPoster = ''
|
||||
this.randomTime = 0;
|
||||
await this.fnSubmitPlayTime("0", this.changeVideoPlayTime);
|
||||
await this.fnNavigationFaceAuth();
|
||||
|
@ -522,7 +510,6 @@ export default {
|
|||
CHAPTER_ID: this.videoData.CHAPTER_ID,
|
||||
VIDEOCOURSEWARE_ID: this.videoData.VIDEOCOURSEWARE_ID,
|
||||
})
|
||||
this.videoContext && this.videoContext.exitFullScreen()
|
||||
const resData = await this.post('/app/user/getUserFace', {
|
||||
USERNAME: loginUser.NAME,
|
||||
USER_ID: loginUser.USER_ID,
|
||||
|
@ -551,7 +538,7 @@ export default {
|
|||
<style scoped lang="scss">
|
||||
.video_bg, #video {
|
||||
width: 100%;
|
||||
height: 450upx;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.title {
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<view style="height: 250px"></view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
poster: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
playTime: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
webview: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.createWebView()
|
||||
},
|
||||
beforeDestroy() {
|
||||
plus.webview.close('video')
|
||||
this.webview.removeEventListener('titleUpdate', this.handlePostMessage)
|
||||
},
|
||||
methods: {
|
||||
createWebView() {
|
||||
this.webview = plus.webview.create('/hybrid/html/video.html', 'video', {
|
||||
top: uni.getSystemInfoSync().statusBarHeight + 44 + 'px',
|
||||
height: '250px',
|
||||
videoFullscreen: "landscape"
|
||||
}, {
|
||||
src: this.src,
|
||||
poster: this.poster,
|
||||
playTime: this.playTime
|
||||
});
|
||||
this.webview.show()
|
||||
this.webview.addEventListener('titleUpdate', this.handlePostMessage)
|
||||
},
|
||||
handlePostMessage(event) {
|
||||
const {eventName, currentTime} = JSON.parse(event.title)
|
||||
const eventNameKeys = ['ready', 'seeking', 'seeked', 'play', 'pause', 'ended', 'timeupdate']
|
||||
if (eventNameKeys.includes(eventName)) {
|
||||
this.$emit(eventName, currentTime)
|
||||
}
|
||||
},
|
||||
fn(event) {
|
||||
const eventKeys = ['play', 'pause', 'destroy', 'fullscreen.exit']
|
||||
if (eventKeys.includes(event)) {
|
||||
this.webview.evalJS(`htmlMessage('${event}')`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
Loading…
Reference in New Issue