DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>
Document
title>
<style>
* {
padding: 0;
margin: 0;
}
style>
head>
<body>
<script src="./script/vue.global.js">script>
<script src="./script/DPlayer.min.js">script>
<script src="./script/hls.min.js">script>
<script src="./script/axios.min.js">script>
<div id="app">
<div style="width: 100vw; height: 100vh">
<dplayer v-if="showVideo" :video="dplayerObj.video" ref="dplayerVideo" screenshot :loop="true" :autoplay="false"
@ended="videoFinish" @play="heartBeatApiFun(1)" @pause="heartBeatApiFun(2)" />
div>
div>
<script>
const timerObj = {
timer: null,
sec: 15000,
setTimer: function (callback) {
this.timer && this.removeTimer();
this.timer = setTimeout(() => {
this.callback && this.callback();
this.setTimer();
}, this.sec);
},
removeTimer: function () {
clearTimeout(this.timer);
this.timer = null;
},
callback: () => { },
};
function guid() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function (c) {
var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
}
);
}
function suffix(name) {
name = name.split("?")[0];
let fileName = name.lastIndexOf(".");
let fileNameLength = name.length;
let fileFormat = name.substring(fileName + 1, fileNameLength);
return fileFormat;
}
var videoBox = null;
const {
ref,
reactive,
onBeforeUnmount,
onMounted,
nextTick,
defineEmits,
defineProps,
defineExpose,
createApp,
} = Vue;
script>
<script>
const videoPlayer = {
template: `
`,
emits: ["ended", "play", "pause", "changeMaxTime"],
props: {
autoplay: {
type: Boolean,
default: false,
},
theme: {
type: String,
default: "#0093ff",
},
loop: {
type: Boolean,
default: true,
},
lang: {
type: String,
default: "zh-cn",
},
screenshot: {
type: Boolean,
default: false,
},
hotkey: {
type: Boolean,
default: true,
},
preload: {
type: String,
default: "auto",
},
volume: {
type: Number,
default: 0.7,
},
playbackSpeed: {
type: Array,
default: [0.5, 0.75, 1, 1.25, 1.5, 2],
},
disableSpeed: {
type: Boolean,
default: false,
},
disableProgress: {
type: Boolean,
default: false,
},
effMaxStudyTimes: {
type: Number,
default: 0,
},
logo: {
type: String,
default: "",
},
video: {
type: Object,
default: {
},
},
subtitle: {
type: Object,
default: {},
},
danmaku: {
type: Object,
default: {},
},
contextmenu: {
type: Array,
default: [],
},
highlight: {
type: Array,
default: [],
},
mutex: {
type: Boolean,
default: true,
},
},
setup(props, context) {
const state = reactive({
instance: null,
});
const fullscreenStatus = ref({
webfullscreen: false,
fullscreen: false,
});
onMounted(() => {
var videoRef = document.getElementById("videoRef");
let player = {
container: videoRef,
autoplay: props.autoplay,
theme: props.theme,
loop: props.loop,
lang: props.lang,
screenshot: props.screenshot,
hotkey: props.hotkey,
preload: props.preload,
volume: props.volume,
playbackSpeed: props.playbackSpeed,
video: props.video,
contextmenu: props.contextmenu,
highlight: props.highlight,
mutex: props.mutex,
};
if (props.subtitle.url) {
player.subtitle = props.subtitle;
}
console.log(player);
state.instance = new DPlayer(player);
videoBox = {
isCanPlay,
switchVideo,
seekkVideo,
getSeekTime,
setSeekTime,
play,
pause,
cancelFull,
backFull,
};
state.instance.on("ended", () => {
if (props.disableProgress) {
var duration = state.instance.video.duration;
if (Math.abs(props.effMaxStudyTimes - duration)
< 5) {
context.emit("ended");
}
} else {
context.emit("ended");
}
});
state.instance.on("play", () => {
context.emit("play");
});
state.instance.on("pause", () => {
context.emit("pause");
});
state.instance.on("fullscreen", () => {
fullscreenStatus.value.fullscreen = true;
});
state.instance.on("fullscreen_cancel", () => {
fullscreenStatus.value.fullscreen = false;
});
state.instance.on("webfullscreen", () => {
fullscreenStatus.value.webfullscreen = true;
});
state.instance.on("webfullscreen_cancel", () => {
fullscreenStatus.value.webfullscreen = false;
});
if (props.disableSpeed) {
state.instance.container.querySelector(
".dplayer-setting-speed"
).style.display = "none";
}
if (props.disableProgress) {
var videoTime = 0;
state.instance.on("timeupdate", function (e) {
var videoCurrentTime = state.instance.video.currentTime;
if (videoCurrentTime > props.effMaxStudyTimes) {
if (
videoCurrentTime - videoTime >
0.8 * state.instance.video.playbackRate
) {
state.instance.seek(videoTime);
state.instance.notice(
"最大学习时间为:" + getTime(props.effMaxStudyTimes),
2000
);
state.instance.notice("禁止快进", 2000);
} else {
if (videoCurrentTime > props.effMaxStudyTimes > 0) {
context.emit("changeMaxTime", videoCurrentTime);
}
videoTime = videoCurrentTime;
}
} else {
videoTime = videoCurrentTime;
}
});
state.instance.on("notice_show", function (e) {
if (videoTime > props.effMaxStudyTimes) {
var text = e.innerText;
if (
"禁止快进" != text &&
(text.indexOf("快进") > -1 || text.indexOf("快退") > -1)
) {
e.style.display = "none";
}
}
});
}
});
onBeforeUnmount(() => {
state.instance.destroy();
});
function switchVideo(item) {
console.log(item);
state.instance.switchVideo(item);
}
function seekkVideo(time) {
state.instance.seek(time);
}
function getSeekTime() {
return state.instance.video.currentTime;
}
function play() {
state.instance.video
.play()
.then((e) => {
console.log(e);
})
.catch((e) => {
console.log(e);
});
}
function pause() {
state.instance.pause();
}
var isCanPlayFun;
function isCanPlay(callback) {
isCanPlayFun = () => {
console.log(12121212);
callback();
};
state.instance.video.addEventListener("canplay", isCanPlayFun, {
once: true,
});
}
function setSeekTime(time, desc) {
if (time) {
state.instance.notice("上次记录:" + getTime(time), 2000);
}
return (state.instance.video.currentTime = time);
}
const fullscreenTempStatus = ref({});
function cancelFull() {
fullscreenTempStatus.value = { ...fullscreenStatus.value };
if (fullscreenStatus.value.fullscreen) {
state.instance.fullScreen.cancel("browser");
}
if (fullscreenStatus.value.webfullscreen) {
state.instance.fullScreen.cancel("web");
}
}
function backFull() {
if (fullscreenTempStatus.value.fullscreen) {
state.instance.fullScreen.request("browser");
}
if (fullscreenTempStatus.value.webfullscreen) {
state.instance.fullScreen.request("web");
}
}
context.expose({
isCanPlay,
switchVideo,
seekkVideo,
getSeekTime,
setSeekTime,
play,
pause,
cancelFull,
backFull,
});
},
};
script>
<script>
const app = createApp({
components: {
dplayer: videoPlayer,
},
setup() {
const uuid = guid();
const dplayerVideo = ref(null);
const showVideo = ref(false);
const dplayerObj = reactive({
video: {
customType: {
customHls: function (video, player) {
const hls = new Hls();
hls.loadSource(video.src);
hls.attachMedia(video);
},
},
},
});
onMounted(() => {
window.addEventListener("beforeunload", beforeunloadFun, false);
initVideo();
});
function initVideo() {
let url =
"https:\/\/******/2023\/04\/12\/100151\/100151.m3u8";
if (suffix(url) == "m3u8") {
dplayerObj.video.type = "customHls";
} else {
dplayerObj.video.type = "auto";
}
dplayerObj.video.url = url;
showVideo.value = true;
nextTick(() => {
dplayerVideo.value = videoBox;
console.log(dplayerVideo.value);
dplayerVideo.value.isCanPlay(() => {
dplayerVideo.value.play();
timerObj.callback = () => {
heartBeatApiFun(5);
};
timerObj.callback();
timerObj.setTimer();
});
});
}
function beforeunloadFun() {
heartBeatApiFun(4);
}
onBeforeUnmount(() => {
window.removeEventListener("beforeunload", beforeunloadFun, false);
heartBeatApiFun(4);
timerObj.removeTimer();
});
function videoFinish() {
heartBeatApiFun(3);
}
function heartBeatApi(data) {
return axios
.post(
"https://***************/prod-api/org/paternerStudy/heartBeat",
data
)
}
function heartBeatApiFun(type, callback = () => { }) {
const currentVideoTime = parseInt(dplayerVideo.value.getSeekTime());
heartBeatApi({
resourceId: "100151",
currentVideoTime: currentVideoTime,
type: type,
sign: uuid,
patrtnerCode: "002",
})
.then((res) => {
callback && callback(res);
})
.catch((e) => {
});
}
return {
showVideo,
dplayerObj,
videoFinish,
heartBeatApiFun,
};
},
});
app.mount("#app");
script>
body>
html>```