| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- <template>
- <div>
- <!-- -->
- <div class="v-wrap-marks"></div>
- <video-player id="myVideo" class="video-player-box" ref="videoPlayer" :playsinline="true"
- @pause="onPlayerPause($event)" @timeupdate="onPlayerTimeupdate($event)" @play="onPlayerStart($event)"
- @ready="playerReadied" @ended="onPlayerEnded($event)" @error="onPlayerError($event)"
- :globalOptions="{controls:true}" :options="options">
- </video-player>
- <div class="dialog-footer pt30">
- <el-row class="media-footer">
- <el-col :span="8" class="media-time">
- <span>{{curTimes|useTime}}</span>
- <strong>/</strong>
- <span>{{media.duration|useTime}}</span>
- </el-col>
- <el-col :span="4" class="media-center">
- <el-button class="bicon" v-if="!onPlay" type="primary" @click="doPlay" icon="el-icon-video-play"
- circle></el-button>
- <el-button class="bicon" v-else type="warning" @click="doPause" icon="el-icon-video-pause" circle></el-button>
- </el-col>
- <el-col :span="6" class="media-center">
- <span class="volume-control">
- <span class="vol-icon" @click="toggleMute">音量</span>
- <el-slider class="volume-slider" :value="volume" :min="0" :max="1" :step="0.05"
- @input="setVolume"></el-slider>
- </span>
- </el-col>
- <el-col :span="6" class="media-select">
- <el-button class="bicon" type="danger" icon="el-icon-close" @click="onClose" style="float: right;">
- </el-button>
- <div style="margin-top:0px;float: right;">
- <el-select placeholder="流畅" :value="mediaType" class="media-el-select"
- @change="(val)=>{$emit('changeMedia', val)}">
- <el-option label="流畅" value="ld"></el-option>
- <el-option label="标清" value="hls"></el-option>
- </el-select>
- </div>
- </el-col>
- </el-row>
- </div>
- </div>
- </template>
- <script>
- import {
- httpServer
- } from "@/components/httpServer/httpServer.js";
- import md5 from 'js-md5';
- import {
- videoPlayer
- } from 'vue-video-player';
- import 'video.js/dist/video-js.css'
- import {
- MessageBox
- } from "element-ui";
- export default {
- name: "Index",
- data() {
- return {
- timer: false,
- tickNum: 0,
- prevTime: 0,
- isReady: false,
- curTimes: 0,
- onPlay: false,
- volume: 0.5,
- isMuted: false
- }
- },
- components: {
- videoPlayer
- },
- watch: {
- mediaType() {
- if (!this.mediaType) return;
- },
- dialog(showDilog) {
- if (!showDilog) {
- this.doPause()
- this.isReady = false
- }
- }
- },
- props: {
- mediaType: {
- type: String,
- default: ''
- },
- media: {
- type: Object,
- default: () => {
- return {
- id: '',
- percent: 0
- }
- }
- },
- dialog: {
- type: Boolean,
- default: true
- },
- options: {
- type: Object,
- default: () => {
- return {}
- }
- }
- },
- filters: {
- useTime(val) {
- let timestr = ""
- let hour = parseInt(val / 3600);
- let min = parseInt(val / 60 % 60);
- let sec = parseInt(val % 60);
- if (hour < 10) hour = "0" + hour;
- if (min < 10) min = "0" + min;
- if (sec < 10) sec = "0" + sec;
- return hour + ":" + min + ":" + sec
- }
- },
- beforeDestroy() {
- this.stopTick()
- this.reportErr("play", 'destroy');
- },
- computed: {
- player() {
- return this.$refs.videoPlayer.player
- },
- },
- created() {
- this.startMonitor()
- },
- methods: {
- setMarks() {
- console.log("setMarks")
- if (!this.options.marks) return;
- var div = document.getElementById('myVideo')
- var div1 = div.firstChild
- var div3 = document.createElement("div");
- div3.setAttribute("class", "resize-drag");
- if (this.mediaType == 'ld') {
- div3.style.cssText =
- "position:absolute;top:52px;left:10px; background-color: #f4f4f4;width:50px; height:50px;border-radius: 50%;";
- } else {
- div3.style.cssText =
- "position:absolute;top:80px;left:18px; background-color: #f4f4f4;width:50px; height:50px;border-radius: 50%;";
- }
- div1.appendChild(div3)
- },
- startTick() {
- let tick = this.tryTick;
- if (this.timer) clearInterval(this.timer);
- this.timer = setInterval(tick, 5 * 1000);
- },
- stopTick() {
- if (this.timer) clearInterval(this.timer);
- },
- tryTick() {
- let that = this;
- try {
- that.tick()
- } catch (err) {
- that.reportErr("play", '' + err.message)
- }
- },
- playerReadied(player) {
- let that = this;
- this.isReady = true
- setTimeout(() => this.setMarks(), 600);
- if (this.media.position > 5 && this.media.position < this.media.duration) {
- setTimeout(function() {
- that.setposition(that.media.position)
- }, 300)
- }
- setTimeout(() => {
- if (that.player && that.player.volume) {
- that.player.volume(that.volume)
- that.player.muted(that.isMuted)
- }
- }, 1000)
- },
- onPlayerTimeupdate(player) {
- let myPlayer = this.$refs.videoPlayer.player;
- let curTimes = player.cache_.currentTime;
- this.curTimes = curTimes || 0
- if (this.media.isFinish) {
- return;
- }
- },
- setposition(position) {
- console.log("setposition", position)
- if (position > this.media.duration) position = this.media.duration;
- let player = this.$refs.videoPlayer.player;
- player.currentTime(position);
- if (this.media.isFinish) return;
- if (this.media.position >= this.media.duration - 10 && !this.media.isFinish) {
- this.tick(true)
- }
- // this.onPlay = true
- },
- onPlayerPause(event) {
- this.reportErr("play", 'pause');
- this.stopTick()
- this.onPlay = false
- },
- onPlayerError(event) {
- this.reportErr("play", 'error');
- },
- onPlayerEnded(event) {
- this.reportErr("play", 'end');
- this.tick(true)
- },
- onClose() {
- this.reportErr("play", 'close')
- this.doPause()
- this.$emit("close")
- },
- doPause() {
- // console.log("doPause")
- this.stopTick()
- this.onPlay = false
- let myPlayer = this.$refs.videoPlayer.player;
- myPlayer && myPlayer.pause()
- },
- doPlay() {
- this.onPlay = true
- this.startTick();
- if (!this.$refs.videoPlayer || !this.$refs.videoPlayer.player) return;
- if (!this.dialog) return this.doPause();
- let myPlayer = this.$refs.videoPlayer.player;
- let p = myPlayer && myPlayer.play()
- if (p && p.catch) p.catch(function() {})
- this.tickNum = 0
- },
- setVolume(val) {
- this.volume = val
- this.isMuted = val === 0
- if (this.player && this.player.volume) {
- this.player.volume(val)
- this.player.muted(this.isMuted)
- }
- },
- toggleMute() {
- this.isMuted = !this.isMuted
- if (this.player && this.player.volume) {
- this.player.muted(this.isMuted)
- }
- },
- onPlayerStart() {
- // console.log("onPlayerStart")
- this.reportErr("play", 'start');
- this.startTick();
- this.onPlay = true
- },
- startMonitor() {
- let that = this
- document.addEventListener("visibilitychange", function() {
- // || document.hidden
- if (document.visibilityState == "hidden") {
- // that.doPause( )
- that.reportErr("play", 'hidden');
- } else {
- that.reportErr("play", 'show');
- // that.doPlay()
- }
- });
- // 监听F12
- document.addEventListener("keydown", function(e) {
- if (e.key == "F12") {
- that.reportErr("play", 'keydownF12');
- try { e.preventDefault() } catch (err) {}
- }
- });
- // setInterval(function() { check() }, 1000);
- // var check = function() {
- // function doCheck(a) {
- // if (("" + a / a)["length"] !== 1 || a % 20 === 0) {
- // (function() {}
- // ["constructor"]("debugger")())
- // } else {
- // (function() {}
- // ["constructor"]("debugger")())
- // }
- // doCheck(++a)
- // }
- // try {
- // doCheck(0)
- // } catch (err) {}
- // };
- },
- // startMonitor() {
- // let that = this
- // window.onblur = function() {
- // that.doPause()
- // }
- // window.onfocus = function () {
- // that.doPlay()
- // }
- // },
- tickWait() {
- this.doPause()
- let that = this
- MessageBox({
- title: "连续学习超15分钟",
- message: "是否继续学习",
- showCancelButton: true,
- confirmButtonText: "确定",
- cancelButtonText: "取消",
- beforeClose: (action, instance, done) => {
- if (action === "confirm") {
- that.doPlay();
- done();
- } else {
- done();
- }
- }
- })
- },
- reportErr(action, msg) {
- httpServer("course.report", {
- action,
- msg
- })
- },
- tick(force = false) {
- let media = this.media;
- this.tickNum++
- // 已经完成
- if (this.media.isFinish) {
- console.log("finish")
- return;
- }
- // 主动暂停
- let myPlayer = this.$refs.videoPlayer.player;
- let curTimes = parseInt(myPlayer.currentTime());
- if (curTimes < 4) {
- console.log("curTimes")
- return;
- }
- let isFinish = force ? 1 : 0
- if (curTimes >= media.duration-15) isFinish = 1;
- // 拉到后面
- if (!isFinish) {
- if (!this.onPlay) return;
- if(curTimes <= media.position) return;
- }
- if(window.navigator.webdriver){
- this.reportErr("play", 'webdriver');
- this.doPause()
- return
- }
- // 强制完成
- let param = {
- id: media.id,
- position: curTimes,
- isFinish
- };
- httpServer("course.tick", param, true).then(res => {
- if (res.code == 200) {
- let {
- skip,
- position,
- pause,
- closed
- } = res.data
- if (pause || closed) {
- this.doPause();
- this.$emit("close")
- if (closed) {
- this.$message.errorMsg("禁止多处同时学习", 5);
- } else if (pause) {
- this.$message.errorMsg("禁止多处同时学习", 5);
- }
- return
- }
- if (!skip) {
- let diff = Math.abs(position - curTimes);
- if (diff > 3) {
- this.setposition(position);
- }
- }
- Object.assign(param, res.data)
- this.$emit("update", param)
- }
- })
- }
- }
- }
- </script>
- <style>
- .video-js {
- touch-action: none;
- .vjs-control-bar {
- .vjs-icon-custombutton {
- font-family: VideoJS;
- font-weight: normal;
- font-style: normal;
- }
- .vjs-icon-custombutton:before {
- content: "\f108";
- font-size: 1.8em;
- line-height: 1.67;
- }
- }
- }
- .p-process {
- width: 100%;
- margin: 20px auto;
- height: 30px;
- }
- .media-footer {
- padding: 0px 30px;
- text-align: left;
- line-height: 40px !important;
- bottom: -10px;
- }
- .media-center {
- text-align: center;
- padding: 0px;
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 8px;
- }
- .volume-control {
- display: inline-flex;
- align-items: center;
- gap: 4px;
- }
- .vol-icon {
- font-size: 12px;
- font-weight: bold;
- cursor: pointer;
- color: #606266;
- user-select: none;
- line-height: 1;
- }
- .vol-icon:hover {
- color: #409eff;
- }
- .volume-slider {
- width: 80px !important;
- }
- .volume-slider .el-slider__runway {
- height: 4px;
- }
- .volume-slider .el-slider__bar {
- height: 4px;
- }
- .volume-slider .el-slider__button {
- width: 12px;
- height: 12px;
- }
- .media-time {
- font-size: 18px;
- vertical-align: center;
- }
- .media-select {
- white-space: nowrap;
- text-align: right;
- line-height: 40px !important;
- float: right;
- margin: 0px !important;
- }
- .bicon {
- font-size: 28px !important;
- padding: 4px !important;
- }
- .media-el-select {
- font-size: 28px !important;
- width: 80px;
- padding: -4px auto !important;
- }
- </style>
|