课件学习验证/多计时器/<cover-view>使用/节流解决撞循环/video组件全屏踩坑(存档)

<template>
	<view>
		<view class="new-tab">
			<img class="new-tab-img-back" :src="backImgUrl" alt="" @click="comeBack">
		</view>
		<u-loading-icon v-if='loading' text="加载中" textSize="18"></u-loading-icon>
		<view v-else>
			<!-- 0=文档1=视频 -->
			<view v-if="data.type==1">
				<view class="content">
					<view class="landscape-container" :class="{'text-area-max':type}">
						<view class="text-area">
							<video id="myVideo" class="video-class" @error="videoErrorCallback" controls
								:autoplay='true' enable-progress-gesture='false' @play="playVideo" @ended="videoEnd"
								@pause="videoPause" :src="Url" @waiting='waitVideo' :direction='90' :initial-time='data.learnTime'
								@timeupdate="watchTimeVideo" show-fullscreen-btn='false'>

							</video>
							<cover-view class="controls">
								<cover-image v-if="type" class="controls-btn" src="@/static/hy.png" @click="check()">
								</cover-image>
								<cover-image v-else class="controls-btn" src="@/static/qp.png" @click="check()">
								</cover-image>
							</cover-view>

							<cover-view class="other-view" v-if="name == '培训'" @click="clickCountDown">
								{{countdowns}}秒
							</cover-view>
						</view>
					</view>

				</view>
				<view class="text_content">
					{{data.name || '-'}} {{data.describe || '-'}}
				</view>
				<view class="text_content">
					课件所需学习时长:{{data.schoolTime ||' -'}}分钟
				</view>
				<view class="text_content">
					观看人次:{{data.watchCount}}
				</view>

			</view>
			<!-- 文档 -->
			<view v-else>
				<view class="padding10">课件所需学习时长:{{data.schoolTime ||' -'}}分钟 ({{data.schoolTimeSeconds}}秒)</view>
				<view class="padding10">已学习:{{documentLearnTime ||' -'}}秒</view>
				<view v-for="(item,index) in pictureList">
					<img :src="item" alt="" class="fileImg">
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import {
		EducationCourseware,
		EducationExitCourseware
	} from '@/common/login.js'
	import api from '@/main.js'
	import '@/components/shoyu-xxtea/shoyu-xxtea'
	import {
		throttle
	} from "@/util"
	export default {
		data() {
			return {
				backImgUrl: require('@/static/back.png'),
				type: false,
				danmuValue: '',
				btn: 0,
				testTime: null,
				loading: true,
				schoolTime: 0,
				sumTime: 0,
				id: '',
				timestamp: 10,
				data: {
					type: 0
				},
				Url: '',
				u2: '',
				fileUrl: '',
				biz: '', //所属模块(课件中心=center,岗位必学=postLearn,我的培训=training)
				name: '',
				ti: 1,
				timer: 0,
				hour: 0,
				minutes: 0,
				seconds: 0,
				coursewareId: '',
				limitTime: '',
				remindCycle: 8,
				countdown: 8,
				urlPath: '',
				title: '',
				viewerUrl: '/hybrid/html/web/viewer.html',
				allUrl: '',
				downloadFile_onoff: false,
				reachButtom: 0, //代表是不是触底--用来判断文档
				pictureList: [],
				isPause: 0, //是否倒计时结束
				videoContext: '', //储存视频对象
				isOver: 0, //是否播放结束过--判断时长累加

				ti: 0, //实时播放进度
				nitial_time: '', //视频跳转进度 秒
				documentLearnTime: '', //文档学习时间
				countdowns: 0,
				timerCountDown: '', //倒计时实例
				numCycleTime:1, //节流时间
				playOrPause:0,//播放为0  暂停为1
			}
		},
		onLoad(e) {
			this.id = e.id || ''
			this.coursewareId = e.coursewareId || ''
			this.name = e.name
			this.value = e.value
			console.log("看课件title/value", this.name, this.value);
			if (this.name == '我的学习' || this.value == '课件中心') {
				this.biz = 'center'
			} else if (this.name == '培训') {
				this.biz = 'training'
			} else {
				//岗位必学
				this.biz = 'postLearn'
			}
			console.log("this.biz", this.biz);
			this.getData({})
			this.initial_time = '0' //视频进度


			/* 隐藏顶部状态栏 */
			// #ifndef MP-ALIPAY
			plus.navigator.setFullscreen(true);
			this.videoContext = uni.createVideoContext('myVideo')
			// #endif
			const that = this

			const landscapeOb = uni.createMediaQueryObserver(this)
			landscapeOb.observe({
				orientation: 'landscape' //屏幕方向为纵向/横向 portrait/landscape
			}, matches => {
				console.log(matches);
				that.type = matches
				this.landscape = matches
			})

		},

		methods: {
			showBtn(e) {
				this.btn = !this.btn
			},
			check() {
				const asd = this.type ? 'portrait' : 'landscape'
				plus.screen.lockOrientation(asd);
			},
			sendDanmu: function() {
				this.videoContext.sendDanmu({
					text: this.danmuValue,
					color: this.getRandomColor()
				});
				this.danmuValue = '';
			},
			getRandomColor: function() {
				const rgb = []
				for (let i = 0; i < 3; ++i) {
					let color = Math.floor(Math.random() * 256).toString(16)
					color = color.length == 1 ? '0' + color : color
					rgb.push(color)
				}
				return '#' + rgb.join('')
			},



			// 获取日常任务
			async getData(params) {
				let id = ''
				if (this.name == '我的学习') {
					id = this.coursewareId
				} else {
					id = this.id
				}
				const data = {
					id: id,
					biz: this.biz
				}
				console.log(data);
				const res = await EducationCourseware(data)
				if (res.code == 200) {
					console.log("res", res);
					this.data = res.result;
					// this.data.learnTime = 3
					this.schoolTime = (this.data.coursewareFile.schoolTime * 1 / 60).toFixed(2) //课件学习时长 分钟
					this.limitTime = this.data.videoTime * 1 //视频总秒数
					this.remindCycle = this.data.remindCycle * 1 * 60 //提醒周期 秒
					this.countdown = this.data.countdown * 1 //弹窗时间
					this.countdowns = this.data.countdown * 1 //页面显示的倒计时
					this.numCycleTime = this.remindCycle + this.countdown //节流时间
					console.log("这些时间", this.remindCycle, this.countdowns, this.numCycleTime);
					this.Url = getApp().globalData.urlApiFile + res.result.coursewareFile.filePath
					console.log("视频真正地址",this.Url);
					//文档
					if (this.data.type == 0) {
						this.documentLearnTime = this.data.learnTime || 0 //接口返回上次看到的时间--赋值
						var filePngPath = res.result.coursewareFile.filePngPath.split(',');
						var newList = []
						for (var i = 0; i < filePngPath.length; i++) {
							newList.push(getApp().globalData.urlApiFile + filePngPath[i])
						}
						this.pictureList = newList
						setInterval(() => {
							this.timer += 1
							this.documentLearnTime += 1
						}, 1000);
						console.log('newList', newList)
					}
					this.loading = false
				}
			},



			//开始
			startTimer() {},

			//暂停
			videoPause(e) {
				// console.log("暂停", e);
				this.playOrPause = 1
				clearInterval(this.timer);
				clearInterval(this.timerCountDown)
				// console.log("时间", this.ti);
			},

			//视频播放缓冲
			waitVideo() {
				clearInterval(this.timer); //暂停计时
				// this.$refs.countDown.pause() //倒计时暂停
			},

			watchTimeVideo(e) {
				let that = this;
				// videoContext.seek(that.data.learnTime);
				let videoContext = wx.createVideoContext('myVideo');
				if (this.name == '培训') {

					if (that.data.learnTime * 1 !== 0) {
						videoContext.seek(that.data.learnTime);
						that.data.learnTime = 0
						return
					}
					var isReady = 1; // 是否开启可以视频快进 1 禁止开启
					//跳转到指定播放位置 initial-time 时间为秒
					//播放的总时长
					var duration = e.detail.duration;
					//实时播放进度 秒数 
					var currentTime = parseInt(e.detail.currentTime);

					console.log("视频播放到第" + currentTime + "秒") //查看正在播放时间,以秒为单位
					if (that.ti == 0) {
						var jump_time = parseInt(that.initial_time) + parseInt(that.ti);
					} else {
						var jump_time = parseInt(that.ti);
					}
					console.log("that.data.learnTime", that.data.learnTime);

					if (isReady == 1) {

						if (currentTime > jump_time && currentTime - jump_time > 3) {

							uni.showToast({
								title: '视频不支持快进' + that.ti,
								icon: 'none',
							});
							videoContext.seek(that.ti);
						}
					}
				}
				that.ti = currentTime; //实时播放进度
			},

			playVideo(e) {
				console.log("播放1", e, this.ti);
				this.playOrPause = 0
				//开始计时
				this.timer = setInterval(this.startTimer, 1000);
				// const that = this
				if (this.name == '培训') {
					if (this.limitTime - this.ti > this.remindCycle) {
						console.log("fhr");
						this.countdowns = this.data.countdown * 1
						this.watchTime()
					}
				}

			},

			//防作弊
			watchTime() {
				const that = this
				console.log('防作弊');
				if (that.name == '培训') {
					that.test(that, that.numCycleTime)
				}
			},
			
			test: throttle((that, numCycleTime) => {
				setTimeout(function() {
					console.log("89898989", numCycleTime);
					that.timerCountDown = setInterval(() => {
						if (that.countdowns <= 0) {
							//倒计时到0的时候 暂停视频 倒计时重新赋值
							that.videoContext = uni.createVideoContext('myVideo');
							that.videoContext.pause(); //暂停
							clearInterval(that.timerCountDown)

						} else {
							that.countdowns--
						}
					}, 1000)
				}, that.remindCycle * 1000);
			}, 3000),


			//倒计时点击事件
			clickCountDown() {
				console.log("用户点击按钮");
				const that = this
				clearInterval(that.timerCountDown)
				that.countdowns = that.data.countdown * 1
				that.videoContext = uni.createVideoContext('myVideo'); //创建视频实例指向video
				//如果已经暂停了,调用播放  未暂停调用周期防作弊
				if(this.playOrPause == 1){
					console.log("已经暂停了");
					that.videoContext.play(); //播放
				}else{
					console.log("防止暂停");
					if (that.limitTime - that.ti > that.remindCycle) {
						console.log("fhr");
						that.countdowns = that.data.countdown * 1
						that.watchTime()
					}
				}
			},


			//视频播放出错
			videoErrorCallback(e) {
				clearInterval(this.timer);
				clearInterval(that.timerCountDown)
				console.log("出错", e);
			},

			//视频播放完结束
			videoEnd(e) {
				// console.log("播放完了,当前时间/总时长", this.ti,this.limitTime);
				this.sumTime = this.ti + this.sumTime
				console.log("ti/sumTime",this.ti,this.sumTime);
				clearInterval(this.sumTime);
				clearInterval(this.timer);
				clearInterval(this.timerCountDown)
				// this.ti = 0
				this.isOver = 1
			},

			//左上角返回
			comeBack() {
				clearInterval(this.timer); //计时器停止
				console.log("左上角要调用接口", this.timer, this.ti);
				let id = ''
				let ti = ''
				if (this.name == '我的学习') {
					id = this.coursewareId
				} else {
					id = this.id
				}
				if (this.data.type == 0) {
					ti = this.timer // 文档
				} else {
					// //判断用累加时长还是当前时长
					// if (this.isOver == 1) {
					// 	ti = this.sumTime
					// }
					ti = this.ti //视频
				}
				let form = {
					id: id,
					biz: this.biz,
					time: ti,
					coursewareId: '',
					isBottom: this.reachButtom
				}
				console.log('提交的数据', form);
				const res = EducationExitCourseware(Object.assign({
					id: id,
					biz: this.biz,
					time: ti,
					coursewareId: '',
					isBottom: this.reachButtom
				}))
				console.log("左上角调用接口完毕", res);
				clearInterval(this.timerCountDown)
				uni.navigateBack(-1)
			},

			//返回触发
			onBackPress(options) {
				console.log("options", options.from);
				//避免死循环
				if (options.from === 'navigateBack') return false;
				//自己的判断条件,执行自定义的返回操作
				if (options.from !== 'navigateBack') {
					clearInterval(this.timer); //计时器停止
					console.log("返回前要调用接口", this.timer, this.ti);
					let id = ''
					let ti = ''
					if (this.name == '我的学习') {
						id = this.coursewareId
					} else {
						id = this.id
					}
					if (this.data.type == 0) {
						ti = this.timer // 文档
					} else {
						//判断用累加时长还是当前时长
						if (this.isOver == 1) {
							ti = this.sumTime
						}
						ti = this.ti //视频
					}
					let form = {
						id: id,
						biz: this.biz,
						time: ti,
						coursewareId: '',
						isBottom: this.reachButtom
					}
					console.log('提交的数据', form);
					const res = EducationExitCourseware(Object.assign({
						id: id,
						biz: this.biz,
						time: ti,
						coursewareId: '',
						isBottom: this.reachButtom
					}))
					clearInterval(this.timerCountDown)
					console.log("接口调用完毕允许返回", res);
					uni.navigateBack(-1)
				}
				//返回true表示我要自定义onBackPress
				return true
			},

			//触底-用于文档验证
			onReachBottom() {
				this.reachButtom = 1
			},
		},
	}
</script>
<style>
	page {
		background-color: #EFF1F5;
	}

	.new-tab {
		width: 100%;
		height: 100px;
		background-color: #556585;
	}

	.new-tab-img-back {
		width: 25px;
		height: 25px;
		margin-top: 60px;
		margin-left: 20px;
	}

	.text_content {
		padding: 30upx;
		color: #333333;
		font-size: 30upx;
	}

	.shijian {
		font-size: 16px;
		text-align: center;
		color: white;
		z-index: 999999;
	}

	.count-down {
		width: 80px;
		height: 30px;
		color: white !important;
		background-color: steelblue;
		text-align: center;
		line-height: 30px !important;
		position: absolute;
		z-index: 999999;
		right: 0;
	}

	.count-down-son {
		width: 80px;
		height: 30px;
		z-index: 9999999;
	}

	.padding10 {
		padding: 10px;
	}

	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.landscape-container {
		height: 300px;
	}

	.text-area {
		position: relative;
		width: 100vw;
		height: 100%;
		display: flex;
		justify-content: center;
	}

	.text-area-max {
		position: absolute;
		top: 0;
		left: 0;
		width: 100vw;
		height: 100vh;
		background: #000;
		display: flex;
		align-items: center;
	}

	.video-class {
		width: 100%;
		height: 100%;
	}

	.other-view {
		position: absolute;
		color: white;
		font-size: 16px;
		text-align: center;
		top: 0;
		right: 0;
		width: 100px;
		height: 30px;
		background-color: #556585;
	}

	.controls {
		position: absolute;
		bottom: 2%;
		right: 2%;
		/* background: #ff; */
		color: #000;
		text-align: center;
	}


	.controls-btn {
		width: 15px;
		height: 15px;
		padding: 10px;
	}


	.bottom-list {
		border: 1px solid;
	}
</style>
<style lang="scss" scoped>
	.u-tabs {
		background-color: #ffffff;
	}

	.fileImg {
		width: 750upx;
		height: 1440upx;
	}

	.task-list {
		.content {
			color: #00000073;
		}



		.left {
			margin-left: 40rpx;
		}

		.green {
			color: #45CEA1;
		}

		.red {
			color: #FF5F56;
		}
	}

	.u-input {
		width: 400rpx;
	}
</style>

节流重点代码:

export const  throttle =(fn, wait = 3000) => {
	    let flag = true
	    return function () {
	        if (!flag) return
	        flag = false
			fn.apply(this, arguments)
	        setTimeout(() => {
	            flag = true
	        }, wait)
	    }
	}

效果图:(顶部导航栏自己写的,屏蔽了原生的,不然视频全屏会受影响)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值