bug:15685、15588、15575

dev
LiuJiaNan 2024-05-31 16:07:31 +08:00
parent dcbe398e58
commit 23126c74e9
7 changed files with 268 additions and 56 deletions

2
hybrid/html/hls/hls.js Normal file

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

1
hybrid/html/plyr/plyr.js Normal file

File diff suppressed because one or more lines are too long

154
hybrid/html/video.html Normal file
View File

@ -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>

View File

@ -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;
}
//appbug10退
// 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 {

View File

@ -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>