Explorar el Código

fix: 修复短视频模块

wenxingxing hace 4 horas
padre
commit
bfb88241de
Se han modificado 2 ficheros con 148 adiciones y 48 borrados
  1. 146 46
      pages/course/video/living-app.nvue
  2. 2 2
      pages_mall/components/GoodsNav.vue

+ 146 - 46
pages/course/video/living-app.nvue

@@ -2,14 +2,14 @@
 	<view class="es">
 		<!-- Custom Header -->
 		<view class="custom-header" :style="{paddingTop: statusBarHeight + 'px'}">
-			<view class="header-center">
+			<view v-if="false" class="header-center">
 				<text v-for="(tab, index) in headerTabs" :key="index"
 					:class="['header-tab-item', headerTabIndex === index ? 'header-tab-active' : '']"
 					@click="switchHeaderTab(index)">
 					{{ tab }}
 				</text>
 			</view>
-			<view class="header-right">
+			<view v-if="false" class="header-right">
 				<u-icon name="account" color="#ffffff" size="28" @click="navTo('/pages/expert/index')"></u-icon>
 			</view>
 		</view>
@@ -102,14 +102,14 @@
 									</view>
 									<view><text class="es-c-white es-fs-22 es-fw-500">{{item.favoriteNum}}</text></view>
 								</view>
-								<view class="item1 es es-ver es-ac es-pc es-mt-33" @tap="openShare(item)">
+								<view v-if="false" class="item1 es es-ver es-ac es-pc es-mt-33" @tap="openShare(item)">
 									<view class="es-icon-84" style="align-items: center;">
 										<image :class="animate ? 'animate-icon':'animate-scale'"
 											src="@/static/image/home1/weixin_icon.png"></image>
 									</view>
 									<view><text class="es-c-white es-fs-22 es-fw-500">{{item.shares}}</text></view>
 								</view>
-								<view class="item1 es es-ver es-ac es-pc es-mt-33" @tap="navTo('/pages/expert/index')">
+								<view v-if="false" class="item1 es es-ver es-ac es-pc es-mt-33" @tap="navTo('/pages/expert/index')">
 									<view class="es es-icon-84">
 										<image class="es-icon-84" src="/static/images/other/video/add_icon.png"></image>
 									</view>
@@ -180,7 +180,7 @@
 				<uni-search-bar radius="72" v-model="keyword"  placeholder="搜索内容" clearButton="auto" cancelButton="none" @confirm="search" />
 			</view>
 		</view> -->
-		<view class="redpacked x-c es-br-ban" v-if="!iserr && !showGuide" @click.stop="tapRedpacked">
+		<view class="redpacked x-c es-br-ban" v-if="false && !iserr && !showGuide" @click.stop="tapRedpacked">
 			<gb-progress class="es x-c es-br-ban" :radius="43" :startPosDegree="0" originalColor="#222222"
 				processColor="#FF5C03" innerbgColor="#222222" :process="process" :barWidth="5">
 				<image class="es-w-50 es-h-50" src="@/static/images/ad/redpacked.png" mode="widthFix"></image>
@@ -192,7 +192,7 @@
 			<view class="reward-popup-content">
 				<image src="/static/images/ad/integral_img.png" class="popup-gift-icon"></image>
 				<text class="popup-title">放弃太可惜啦!</text>
-				<text class="popup-desc">继续浏览广告,可获得芳华币</text>
+				<text class="popup-desc">继续浏览广告,可获得币</text>
 				<view class="popup-confirm-btn">
 					<text class="popup-confirm-title" @click="continueAd">继续观看</text>
 				</view>
@@ -231,6 +231,13 @@
 </template>
 
 <script>
+	import dayjs from 'dayjs';
+	import {
+		getPublicCourseInternetTraffic
+	} from '@/api/course'
+	import {
+		getTalentByToken
+	} from '@/api/expert.js';
 	import {
 		getVideoList,
 		doFavorite,
@@ -242,6 +249,7 @@
 	} from '@/api/integral'
 	import {
 		isAndroid,
+		isIos,
 		isLogin,
 		updateMsgDot
 	} from '@/utils/common'
@@ -286,49 +294,49 @@
 						next: '',
 					}]
 				},
-				dataList: [], //用于数据循环的列表🌟💗
-				wHeight: 0, //获取的屏幕高度🌟💗
-				boxStyle: { //视频父视图样式🌟💗
+				dataList: [], //用于数据循环的列表
+				wHeight: 0, //获取的屏幕高度
+				boxStyle: { //视频父视图样式
 					'height': 0,
 					'width': 0,
 				},
-				videoStyle: { //视频,图片封面样式🌟💗
+				videoStyle: { //视频,图片封面样式
 					'height': 0,
 					'width': 0,
 					'marginTop': 0
 				},
 				Heights: 0,
-				k: 0, //默认为0🌟💗
-				playIngIds: [], //正在播放的视频id列队,列队用于处理滑动过快导致的跳频问题🌟💗
+				k: 0, //默认为0
+				playIngIds: [], //正在播放的视频id列队,列队用于处理滑动过快导致的跳频问题
 				ready: false, //可忽略
-				isDragging: false, //false代表停止滑动🌟💗
-				refreshing: false, //用于下拉刷新🌟💗
-				windowWidth: 0, //获取屏幕宽度🌟💗
+				isDragging: false, //false代表停止滑动
+				refreshing: false, //用于下拉刷新
+				windowWidth: 0, //获取屏幕宽度
 				windowHeight: 0,
 				dex: [0, 0], //用于判断是上滑还是下滑,第一个存旧值,第二个存新值【目前在1.0.7已经废弃】
-				currents: 0, //用于左右滑动,0代表视频界面,1代表右滑界面🌟💗
-				platform: '', //用于获取操作系统:ios、android🌟💗
-				playIng: false, //用于视频初始化时是否播放,默认不播放🌟💗
-				videoTime: '', //视频总时长,这个主要用来截取时间数值💗
-				videoTimes: '', //视频时长,用这个来获取时间值,例如:00:30这个时间值💗
-				changeTime: '', //显示滑动进度条时变化的时间💗
+				currents: 0, //用于左右滑动,0代表视频界面,1代表右滑界面
+				platform: '', //用于获取操作系统:ios、android
+				playIng: false, //用于视频初始化时是否播放,默认不播放
+				videoTime: '', //视频总时长,这个主要用来截取时间数值
+				videoTimes: '', //视频时长,用这个来获取时间值,例如:00:30这个时间值
+				changeTime: '', //显示滑动进度条时变化的时间
 				isShowimage: false, //是否显示封面【1.0.4已废弃,但是意思需要记住】
-				currenttimes: 0, //当前时间💗
+				currenttimes: 0, //当前时间
 				isShowProgressBarTime: false, //是否拖动进度条,如果拖动(true)则显示进度条时间,否则不显示(false)【1.0.4已废弃,但是意思需要记住】
-				ProgressBarOpacity: 0.7, //进度条不拖动时的默认值,就是透明的💗
-				dotWidth: 0, //播放的小圆点,默认没有💗
-				deleteHeight: 0, //测试高度🌟💗
+				ProgressBarOpacity: 0.7, //进度条不拖动时的默认值,就是透明的
+				dotWidth: 0, //播放的小圆点,默认没有
+				deleteHeight: 0, //测试高度
 				statusBarHeight: 0,
-				percent: 0, //百分小数💗
-				currentPosition: 0, //滑块当前位置💗//2.0已弃用,现已用于后端参数
-				currentPositions: 0, //滑块当前位置的副本💗//2.0已弃用,现已用于后端参数
-				newTime: 0, //跟手滑动后的最新时间💗
-				timeNumber: 0, //🌟💗
-				ProgressBarBottom: 20, //进度条离底部的距离💗
-				object_fit: 'contain', //视频样式默认包含🌟💗   contain :包含  fill:填充 cover:覆盖
-				mode: 'aspectFit', //图片封面样式🌟💗
-				timeout: "", //🌟用来阻止 setTimeout()方法
-				voice: "", //🌟用来阻止 setTimeout()方法
+				percent: 0, //百分小数
+				currentPosition: 0, //滑块当前位置//2.0已弃用,现已用于后端参数
+				currentPositions: 0, //滑块当前位置的副本//2.0已弃用,现已用于后端参数
+				newTime: 0, //跟手滑动后的最新时间
+				timeNumber: 0, //
+				ProgressBarBottom: 20, //进度条离底部的距离
+				object_fit: 'contain', //视频样式默认包含   contain :包含  fill:填充 cover:覆盖
+				mode: 'aspectFit', //图片封面样式
+				timeout: "", //用来阻止 setTimeout()方法
+				voice: "", //用来阻止 setTimeout()方法
 				oldVideo: "",
 				isAutoplay: false, //是否开启自动播放(默认不开启)
 				autoplayText: "开启自动播放",
@@ -410,9 +418,15 @@
 				guideTimer: null,
 				currentVideoId: null, // 当前播放的视频 ID
 				isAdShowing: false, // 广告是否正在显示
-				headerTabs: ['', '', '推荐', '热门', '关注'], //'直播',
+				headerTabs: ['推荐', '热门', '关注'], //'直播',
 				headerTabIndex: 0,
-				sortType: ''
+				sortType: '',
+
+				currentTrafficData: "",
+				videoCurrentTime: 0,
+				videoTotalDuration: 0,
+				lastReportMinute: 0,
+				uuId: "",
 			}
 		},
 		created: function() {
@@ -470,8 +484,9 @@
 			}, 900)
 		},
 		onShow() {
+			this.uuId = this.generateRandomString(16)
 			uni.showTabBar();
-			if (!isLogin()) {
+			if (!isLogin() && !this.isIos()) {
 				uni.navigateTo({
 					url: '/pages/auth/loginIndex'
 				})
@@ -489,7 +504,7 @@
 				this.currentVideoId = this.dataList[this.k].id; // 记录当前视频ID
 				//getVideoContext(this.dataList[this.k].id,this).play();
 				const videoContext = getVideoContext(this.dataList[this.k].id, this);
-				// videoContext.play(); // 开始播放
+				videoContext.play(); // 开始播放
 			}
 		},
 		onHide() {
@@ -520,6 +535,11 @@
 				// 2.0版本已经去掉了下面这一句,视频不用暂停,只需要把声音禁止就行
 				// getVideoContext(this.dataList[old_k].id + '' + old_k,this).stop()//如果视频暂停,那么旧视频停止,这里的this.dataList[old_k].id + '' + old_k,后面加 old_k 是为了每一个视频的 id 值不同,这样就可以大程度的避免串音问题
 				this.currentVideoId = this.dataList[k].id; // 更新当前视频ID
+				this.currentTrafficData = this.dataList[k];
+				this.videoCurrentTime = 0;
+				this.videoTotalDuration = 0;
+				this.lastReportMinute = 0;
+
 				this.dataList[k].state = 'play'
 				this.dataList[k].muted = false; // 取消静音
 				this.dataList[k].showCover = true; // 确保切回来时先显示封面
@@ -581,6 +601,32 @@
 			}
 		},
 		methods: {
+			generateRandomString(length) {
+				let result = '';
+				const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+				const charactersLength = characters.length;
+
+				for (let i = 0; i < length; i++) {
+					result += characters.charAt(Math.floor(Math.random() * charactersLength));
+				}
+				return result;
+			},
+			// 缓冲
+			getInternetTraffic() {
+				if (!this.currentTrafficData) return;
+
+				const playVideoTime = this.videoTotalDuration > 0 ? Math.ceil(this.videoCurrentTime / this
+					.videoTotalDuration * 100) : 0; // 播放百分比
+
+				const param = {
+					uuId: dayjs().format('YYYYMMDD') + this.uuId,
+					duration: Math.floor(this.videoCurrentTime),
+					bufferRate: playVideoTime,
+					videoId: this.currentTrafficData.videoIds,
+					isPublic: 0,
+				}
+				getPublicCourseInternetTraffic(param).then(res => {})
+			},
 			videoPause() {
 				this.animateInterval = null;
 				if (this.dataList.length > 0) {
@@ -591,23 +637,40 @@
 					videoContext.pause(); // 暂停播放
 				}
 			},
-			switchHeaderTab(index) {
+			async switchHeaderTab(index) {
 				this.headerTabIndex = index;
 				switch (index) {
 					// case 0:
 					// 	return this.navTo('/pages/course/video/live')
-					case 2:
+					case 0:
+						// 停止当前播放的视频
+						if (this.dataList.length > 0 && this.dataList[this.k]) {
+							const currentVideoId = this.dataList[this.k].id;
+							const videoContext = getVideoContext(currentVideoId, this);
+							videoContext.pause();
+						}
 						this.pageNum = 1
 						this.sortType = 'play'
 						this.getData();
 						return
-					case 3:
+					case 1:
+						// 停止当前播放的视频
+						if (this.dataList.length > 0 && this.dataList[this.k]) {
+							const currentVideoId = this.dataList[this.k].id;
+							const videoContext = getVideoContext(currentVideoId, this);
+							videoContext.pause();
+						}
 						this.pageNum = 1
 						this.sortType = 'hot'
 						this.getData();
 						return
-					case 4:
-						return this.navTo('/pages/expert/friendsList')
+					case 2:
+						this.headerTabIndex = 0
+						const user = JSON.parse(uni.getStorageSync('userInfo'))
+						const res = await getTalentByToken()
+						return this.navTo(
+							`/pages/expert/friendsList?current=0&userId=${user.userId || ''}&talentId=${res.data.fsUserTalent.talentId || ''}`
+							)
 				}
 			},
 			navTo(url) {
@@ -679,7 +742,7 @@
 				// 广告正常播放结束,且满足奖励条件
 				if (detail && detail.isEnded) {
 					this.showRewardPopup = false;
-					// 发放芳华币奖励(调用接口)
+					// 发放币奖励(调用接口)
 					this.giveAdReward()
 
 					// 广告关闭后,继续播放原视频
@@ -787,6 +850,7 @@
 				const params = {
 					"keyword": this.keyword,
 					isRandom: 1,
+					isIos: this.isIos(),
 					sortType: this.sortType
 				};
 				if (flag == 'showLoading') {
@@ -799,10 +863,14 @@
 						this.refreshing = false;
 						this.isShowTab = true;
 						if (res.code == 200 && res.data && res.data.list && res.data.list.length > 0) {
+							if (this.pageNum == 1) {
+								this.dataList = [];
+							}
 							const datas = res.data.list;
 							this.isLastPage = res.data.isLastPage;
 							datas.forEach(e => {
 								e.videoId = e.id;
+								e.videoIds = e.id * 1;
 								e.id = 'A' + e.id + '' + parseInt(Math.random() * 1000);
 								e.muted = false; // 初始化静音状态为 false
 								e.showCover = true; // 初始化显示封面
@@ -811,9 +879,20 @@
 								this.dataList.push(e);
 							});
 							if (this.pageNum == 1) {
+								this.k = 0;
 								setTimeout(e => {
 									this.tapVideoHover("reset");
 									this.checkTextLines(0);
+									// 确保第一个视频开始播放
+									const videoContext = getVideoContext(this.dataList[0].id, this);
+									videoContext.seek(0);
+									that.currentTrafficData = that.dataList[0]
+									that.videoCurrentTime = 0
+									that.videoTotalDuration = 0
+									that.lastReportMinute = 0
+									setTimeout(() => {
+										videoContext.play();
+									}, 100);
 								}, 100)
 								this.leftTimers = setTimeout(e => {
 									this.dataList[0].isShowGoods = true;
@@ -1166,7 +1245,7 @@
 				}
 			},
 			onProgress() {
-				//console.log("------qxj onProgress");
+
 			},
 			timeupdate(e, index) {
 				//console.log("------qxj onTimeupdate");
@@ -1174,6 +1253,19 @@
 				if (e.detail.currentTime > 0.1 && this.dataList[index].showCover) {
 					this.dataList[index].showCover = false;
 				}
+				if (index !== this.k) return; // 只处理当前播放的视频
+
+				let currentTime = e.detail.currentTime; // 当前播放秒数
+				let totalDuration = e.detail.duration; // 视频总时长
+
+				this.videoCurrentTime = currentTime
+				this.videoTotalDuration = totalDuration
+				let currentMinute = Math.floor(currentTime / 60);
+				
+				if (currentMinute > 0 && currentMinute > this.lastReportMinute) {
+					this.lastReportMinute = currentMinute;
+					this.getInternetTraffic();
+				}
 			},
 			onLoadeddata() {
 				console.log('------qxj 视频缓冲完成');
@@ -1232,9 +1324,17 @@
 
 			},
 			navTo(url) {
+				if (!isLogin()) {
+					return uni.navigateTo({
+						url: '/pages/auth/loginIndex'
+					})
+				}
 				uni.navigateTo({
 					url: url
 				})
+			},
+			isIos() {
+				return uni.getSystemInfoSync().platform == 'ios';
 			}
 		}
 	}

+ 2 - 2
pages_mall/components/GoodsNav.vue

@@ -1,7 +1,7 @@
 <template>
 	<view class="goods-nav" v-if="navList && navList.length > 0">
 		<view class="nav-row">
-			<view class="nav-all" :class="{ active: activeId === 'all' || activeId === 0 || activeId === '0' }" @tap.stop="onSelectAll" @click.stop="onSelectAll">
+			<view class="nav-all" :class="{ active: activeId === 'all' || activeId === 0 || activeId === '0' }" @tap.stop="onSelectAll">
 				<text>全部</text>
 			</view>
 			<scroll-view scroll-x class="nav-scroll" :show-scrollbar="false">
@@ -73,7 +73,6 @@ export default {
 .nav-inner {
 	display: inline-flex;
 	padding:0;
-	gap: 30rpx;
 }
 .nav-item {
 	flex-shrink: 0;
@@ -82,6 +81,7 @@ export default {
 	font-size: 40rpx;
 	color: rgba(0,0,0,0.85);
 	line-height: 56rpx;
+	margin-left: 30rpx;
 }
 .nav-item.active {
 	color: #FF233C;