qxj 1 неделя назад
Родитель
Сommit
7d6177a7c1

+ 0 - 19
App.vue

@@ -13,25 +13,6 @@
 		},
 		onLaunch: function() {
 			this.checkUpdate();
-			// uni.hideTabBar({ animation: true })
-			// uni.$TUIKit = TIM.create({
-			// 	SDKAppID: 1400693126
-			// });
-			// uni.$TUIKit.registerPlugin({
-			// 	'cos-wx-sdk': COS
-			// });
-			// uni.$TUIKitTIM = TIM;
-			// uni.$TUIKitEvent = TIM.EVENT;
-			// uni.$TUIKitVersion = TIM.VERSION;
-			// uni.$TUIKitTypes = TIM.TYPES; // 监听系统级事件
-			// uni.$resetLoginData = this.resetLoginData();
-			// uni.$TUIKit.on(uni.$TUIKitEvent.SDK_READY, this.onSDKReady);
-			// uni.$TUIKit.on(uni.$TUIKitEvent.SDK_NOT_READY, this.onSdkNotReady);
-			// uni.$TUIKit.on(uni.$TUIKitEvent.KICKED_OUT, this.onKickedOut);
-			// uni.$TUIKit.on(uni.$TUIKitEvent.ERROR, this.onTIMError);
-			// uni.$TUIKit.on(uni.$TUIKitEvent.NET_STATE_CHANGE, this.onNetStateChange);
-			// uni.$TUIKit.on(uni.$TUIKitEvent.SDK_RELOAD, this.onSDKReload);
-			// console.log('IM')
 			// 看课题目字体跟随系统变化
 			const systemInfo = uni.getSystemInfoSync();
 			const baseFontSize = 14; // 标准字体大小(你可以自定义)

+ 1 - 1
api/integral.js

@@ -83,7 +83,7 @@ export function payment(data) {
  }
  // 用户领取看课积分(传入直播间id)
  export function receivePoints(data) {
-  	return request('/app/live/completion/receive-points',data,'POST','application/json;charset=UTF-8');
+  	return request('/app/live/completion/receive-points?liveId='+data.liveId,null,'POST','application/json;charset=UTF-8');
  }
  // 查询用户自己的积分记录
  export function integrallogs(data) {

+ 8 - 10
common/request.js

@@ -10,17 +10,15 @@ export default class Request {
 		// let path = 'https://test.userapp.store.cdwjyyh.com';
 		// let path = 'https://user.test.ylrztop.com/api';
 
-		// let path = 'https://userapp.klbycp.com/store'; //百域承品
-		// let path2 = 'https://userapp.klbycp.com'; //百域承品
-
-
-		// let path = 'http://j26df4a4.natappfree.cc/store'; //百域承品 夏伟
-		// let path2 = 'http://j26df4a4.natappfree.cc'; //百域承品 夏伟
-
-		let path = 'http://d499966b.natappfree.cc/store'; //本地
-		let path2 = 'http://d499966b.natappfree.cc'; //本地
+		let path = 'https://userapp.klbycp.com/store'; //百域承品
+		let path2 = 'https://userapp.klbycp.com'; //百域承品
 
+		//let path = 'http://e895a54d.natappfree.cc/store'; //百域承品 夏伟
+		//let path2 = 'http://e895a54d.natappfree.cc'; //百域承品 夏伟
 
+		//let path = 'http://d499966b.natappfree.cc/store'; //本地
+		//let path2 = 'http://d499966b.natappfree.cc'; //本地
+		
 		let type = 0
 		uni.setStorageSync('requestPath', path2)
 		// uni.showLoading({
@@ -96,7 +94,7 @@ export default class Request {
 				httpContentType = contentType;
 			}
 			var routers = router;
-			console.log("---qxj request url:"+`${path}${router}`+" params:"+JSON.stringify(data)+" \n AppToken:"+token);
+			//console.log("---qxj request url:"+`${path}${router}`+" params:"+JSON.stringify(data)+" \n AppToken:"+token);
 			// 请求
 			uni.request({
 				header: {

+ 2 - 2
components/Server.vue

@@ -11,7 +11,7 @@
 				<image class="w130 h130"
 					src="/static/images/server.png"
 					mode="aspectFit"></image>
-				<text class="text">官方客服</text>
+				<text class="text">客服投诉</text>
 				<button class="contact-btn" open-type="contact"></button>
 			</view>
 		</view>
@@ -205,7 +205,7 @@
 	.text{
 		margin-top: 8rpx;
 		font-weight: 500;
-		font-size: 24rpx;
+		font-size: 28rpx;
 		color: #333;
 		background: rgba(255, 255, 255, 0.9);
 		padding: 6rpx 12rpx;

+ 3 - 2
manifest.json

@@ -1,5 +1,5 @@
 {
-    "name" : "联志甄选",
+    "name" : "百域承品",
     "appid" : "__UNI__A8490FA",
     "description" : "",
     "versionName" : "1.0.0",
@@ -52,7 +52,7 @@
     "quickapp" : {},
     /* 小程序特有相关 */
     "mp-weixin" : {
-        "appid" : "wx44beed5640bcb1ba",
+        "appid" : "wxd791d5933ed42218",
         "setting" : {
             "urlCheck" : false
         },
@@ -62,6 +62,7 @@
                 "desc" : "用于显示用户昵称和头像"
             }
         }
+		
     },
     "mp-alipay" : {
         "usingComponents" : true

+ 1 - 1
package.json

@@ -1,5 +1,5 @@
 {
-  "name": "zhongkmall_user_app",
+  "name": "baiyu_user_app",
   "version": "1.0.0",
   "main": "main.js",
   "scripts": {

+ 12 - 5
pages/user/index.vue

@@ -151,6 +151,7 @@
 								<text class="text">资质证书</text>
 							</view> -->
 							<!-- v-if="user.bindCompanyUserId" -->
+							
 							<!-- <view class="item no-marin-bottom" @click="navgetTo('/pages_shopping/live/order')">
 								<image
 									src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/shop/images/live.png"
@@ -293,17 +294,23 @@
 			},
 		},
 		methods: {
+			/**
+			 * 获取当前环境版本,控制 Version 变量
+			 * 开发版(develop)或体验版(trial)时 Version 为 true
+			 * 正式版(release)时 Version 为 false
+			 */
 			yincang(){
-				    const accountInfo = wx.getAccountInfoSync();
-				    const { envVersion } = accountInfo.miniProgram;
-					// || envVersion === 'trial'
-				   this.Version=envVersion === 'develop' ;
+				// #ifdef MP-WEIXIN
+				const accountInfo = uni.getAccountInfoSync();
+				const { envVersion } = accountInfo.miniProgram;
+				this.Version = (envVersion === 'develop' || envVersion === 'trial');
+				// #endif
 			},
 			callService() {
 				let orderKey = '5d81cf01-6f8d-4e1a-ae7a-dbc26c965b01';
 				uni.navigateTo({
 					url: '/pages_company/order/confirmOrder?orderKey=' + orderKey
-				})
+				});
 				return;
 
 				uni.makePhoneCall({

+ 65 - 0
pages_course/components/courseExpiration.vue

@@ -0,0 +1,65 @@
+<template>
+	<view class="container-body">
+		<text class="user" v-if="userId">#{{userId}}</text>
+		<image class="kfqrcode" v-if="qrcode" :src="qrcode" show-menu-by-longpress="true"></image>
+		<image v-else src="/static/course_expiration_img.png" mode="aspectFill"></image>
+		<view class="title">{{msg}}</view>
+		<view style="margin-bottom: 10vh;" v-show="code">状态码:{{code}}</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props:['code','qrcode','msg','userId'],
+		data() {
+			return {
+			
+			}
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+	.kfqrcode {
+		height: 460rpx;
+		width: 460rpx;
+	}
+	.container-body {
+		background-color: #fff;
+		position: fixed;
+		top: 0;
+		right: 0;
+		z-index: 9998;
+		justify-content: center;
+		font-family: PingFang SC, PingFang SC;
+		font-weight: 400;
+		font-size: 32rpx;
+		color: #757575;
+		line-height: 48rpx;
+		text-align: center;
+		height: 100vh;
+		width: 100vw;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		.title {
+			font-weight: bold;
+			font-size: 40rpx;
+			color: #1E2F67;
+			margin-bottom: 24rpx;
+			padding: 0 60rpx;
+		}
+		image {
+			width: 428rpx;
+			height: 360rpx;
+			margin-bottom: 30rpx;
+		}
+		.user {
+			position: absolute;
+			right: 24rpx;
+			top: 124rpx;
+			z-index: 9999;
+		}
+	}
+</style>

+ 1 - 1
pages_course/components/like.vue

@@ -1,6 +1,6 @@
 <template>
 	<view class="like-container">
-		<image class="image" @click="handleLike" src="/static/images/like.png" ref="likeBtn"></image>
+		<image class="image" @click="handleLike" src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/fs/20251231/dc4eccf12e3b45ec9a2a9b523f42300f.png" ref="likeBtn"></image>
 		<view v-for="(icon, index) in icons" :key="icon.id" class="animated-icon" :style="{
         top: icon.top + 'rpx',
         left: icon.left + 'rpx',  // 补充left属性的单位

+ 36 - 0
pages_course/images/zb_like_icon24.svg

@@ -0,0 +1,36 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="zb_like_icon24">
+<g id="Union" filter="url(#filter0_i_217_11517)">
+<path d="M12.6138 4.78201C14.9895 2.40625 18.8415 2.40637 21.2173 4.78201C23.5931 7.15784 23.5931 11.0097 21.2173 13.3855L14.8276 19.7752C14.2906 20.3122 13.6392 20.665 12.9517 20.8328C12.8267 20.8633 12.7006 20.8877 12.5737 20.906C12.1931 20.9609 11.8059 20.961 11.4253 20.906C11.2985 20.8877 11.1723 20.8633 11.0474 20.8328C10.3598 20.665 9.70839 20.3122 9.17139 19.7752L2.78174 13.3855C0.405956 11.0097 0.406001 7.15784 2.78174 4.78201C5.15754 2.40619 9.00945 2.40619 11.3853 4.78201V4.78201C11.7245 5.12126 12.2745 5.12126 12.6138 4.78201V4.78201Z" fill="url(#paint0_linear_217_11517)"/>
+</g>
+<g id="Union_2" filter="url(#filter1_i_217_11517)">
+<path d="M5.21478 7.19141C6.83464 5.60285 9.46095 5.60288 11.0808 7.19141C11.3122 7.41829 11.6876 7.41811 11.9191 7.19141C13.539 5.60294 16.1653 5.60294 17.7851 7.19141C19.405 8.77994 19.4049 11.3555 17.7851 12.944L13.4286 17.2164C13.3952 17.2491 13.3613 17.2811 13.3267 17.3117C13.2922 17.3423 13.2572 17.372 13.2215 17.4006C13.0788 17.5147 12.9269 17.6122 12.7687 17.6937C12.729 17.7142 12.6887 17.7334 12.6482 17.7518C12.1641 17.9721 11.6278 18.0459 11.1088 17.9726C11.0654 17.9664 11.0221 17.9592 10.9789 17.951C10.9359 17.9428 10.8931 17.9338 10.8504 17.9236C10.4245 17.8216 10.0185 17.6176 9.67324 17.3117C9.63869 17.2811 9.60466 17.2491 9.57137 17.2164L5.21478 12.944C3.59504 11.3555 3.59511 8.77997 5.21478 7.19141Z" fill="#FFE4F9"/>
+</g>
+</g>
+<defs>
+<filter id="filter0_i_217_11517" x="1" y="3.00015" width="21.999" height="18.9471" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="1"/>
+<feGaussianBlur stdDeviation="1"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.649038 0 0 0 0 0.694692 0 0 0 0.8 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_217_11517"/>
+</filter>
+<filter id="filter1_i_217_11517" x="4" y="4" width="15" height="14" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="-2"/>
+<feGaussianBlur stdDeviation="1"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.514423 0 0 0 0 0.655316 0 0 0 1 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_217_11517"/>
+</filter>
+<linearGradient id="paint0_linear_217_11517" x1="0.999512" y1="14.5909" x2="22.9995" y2="14.5909" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FB687D"/>
+<stop offset="1" stop-color="#FE3370"/>
+</linearGradient>
+</defs>
+</svg>

+ 24 - 0
pages_course/images/zb_share_icon24.svg

@@ -0,0 +1,24 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="zb_share_icon24">
+<g id="Ellipse 368" filter="url(#filter0_i_217_11495)">
+<circle cx="12" cy="12" r="12" fill="url(#paint0_linear_217_11495)"/>
+</g>
+<path id="Vector (Stroke)" d="M11.3398 6.6465C11.3398 5.4942 12.6855 4.71713 13.6406 5.51857L13.7314 5.6006L13.7334 5.60255L18.3652 10.1387L18.3691 10.1426C18.6474 10.4192 18.8003 10.7956 18.7998 11.1836V11.1846C18.7988 11.5727 18.6441 11.9481 18.3643 12.2236L18.3516 12.2363L18.3389 12.2481L13.7061 16.4209C12.7483 17.3197 11.3369 16.5334 11.3369 15.3535V14.042C9.60754 14.1397 8.1591 15.0005 7.39551 16.1797L7.39454 16.1826C6.75348 17.1645 5.34789 16.7124 5.23633 15.6484L5.23731 15.6475C5.21283 15.4197 5.19993 15.1902 5.2002 14.96C5.20069 11.5488 7.88831 8.81466 11.3398 8.07618V6.6465ZM12.9395 9.45118L12.2441 9.54298C9.32009 9.92969 7.16218 11.9485 6.8418 14.3428C8.03801 13.1574 9.76999 12.4327 11.666 12.4326H11.668C11.8443 12.4329 12.0214 12.4397 12.1982 12.4531L12.9375 12.5098V14.96L17.1377 11.1758L12.9395 7.06447V9.45118Z" fill="white"/>
+</g>
+<defs>
+<filter id="filter0_i_217_11495" x="0" y="0" width="26" height="25" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dx="3" dy="1"/>
+<feGaussianBlur stdDeviation="1"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.723321 0 0 0 0 1 0 0 0 0 0.427885 0 0 0 0.5 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_217_11495"/>
+</filter>
+<linearGradient id="paint0_linear_217_11495" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
+<stop stop-color="#9DDF81"/>
+<stop offset="1" stop-color="#16A27E"/>
+</linearGradient>
+</defs>
+</svg>

+ 66 - 0
pages_course/images/zb_shopping_car_icon24.svg

@@ -0,0 +1,66 @@
+<svg width="25" height="30" viewBox="0 0 25 30" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="zb_shopping_car_icon24">
+<g id="Group 9020" filter="url(#filter0_d_217_11499)">
+<g id="Rectangle 638" filter="url(#filter1_i_217_11499)">
+<path d="M7.09985 6.56668L7.90886 6.92113L8.43225 6.20967L9.24126 6.56412L9.76465 5.85265L10.5737 6.2071L11.097 5.49564L11.9061 5.85009L12.4294 5.13862L14.7143 13.666L9.38475 15.094L7.09985 6.56668Z" fill="#FF443A"/>
+</g>
+<path id="Subtract" d="M14.7143 13.6662L12.0495 14.3802L9.76465 5.85287L10.5734 6.20739L11.0975 5.49573L11.9063 5.85025L12.4294 5.13885L14.7143 13.6662Z" fill="#FF1406"/>
+</g>
+<g id="Star 2" filter="url(#filter2_i_217_11499)">
+<path d="M13.3252 6.86899C13.3041 6.4613 13.754 6.20151 14.0966 6.42364L15.1532 7.10888C15.2873 7.19585 15.4549 7.21346 15.6042 7.15628L16.7802 6.7057C17.1614 6.55964 17.5475 6.90731 17.4421 7.30171L17.117 8.51841C17.0757 8.67282 17.1107 8.83765 17.2112 8.96192L18.0032 9.94117C18.2599 10.2586 18.0486 10.7333 17.6409 10.7549L16.3832 10.8216C16.2236 10.8301 16.0777 10.9143 15.9906 11.0483L15.304 12.1041C15.0814 12.4463 14.5647 12.392 14.4181 12.011L13.966 10.8355C13.9087 10.6864 13.7834 10.5736 13.6291 10.5321L12.4128 10.2054C12.0185 10.0995 11.9105 9.59126 12.2276 9.33414L13.2059 8.54094C13.33 8.44028 13.3985 8.28633 13.3903 8.12672L13.3252 6.86899Z" fill="url(#paint0_linear_217_11499)"/>
+</g>
+<circle id="Ellipse 369" cx="19" cy="9" r="2" fill="url(#paint1_linear_217_11499)"/>
+<path id="Union" d="M9.7666 24.3C10.8712 24.3 11.7666 25.1954 11.7666 26.3C11.7666 27.4046 10.8712 28.3 9.7666 28.3C8.66203 28.3 7.7666 27.4046 7.7666 26.3C7.7666 25.1954 8.66203 24.3 9.7666 24.3ZM19.7666 24.3C20.8712 24.3 21.7666 25.1954 21.7666 26.3C21.7666 27.4046 20.8712 28.3 19.7666 28.3C18.662 28.3 17.7666 27.4046 17.7666 26.3C17.7666 25.1954 18.662 24.3 19.7666 24.3Z" fill="url(#paint2_linear_217_11499)"/>
+<path id="Union_2" d="M1.93823 8C3.59767 8.00002 5.09012 8.71301 6.12731 9.84894C6.33718 10.0788 6.62662 10.2275 6.93787 10.2275H21.7019C22.9878 10.2275 23.9398 11.4237 23.6511 12.6768L21.6384 21.4131C21.4292 22.3207 20.6207 22.9639 19.6892 22.9639H8.34937C7.3621 22.9639 6.5218 22.2434 6.37183 21.2676L5.05762 12.7147C5.04578 12.6376 5.02564 12.5618 4.99345 12.4908C4.47572 11.3483 3.24838 10.543 1.93823 10.543C1.23606 10.543 0.666779 9.97365 0.666748 9.27148C0.666748 8.56929 1.23604 8 1.93823 8Z" fill="url(#paint3_linear_217_11499)"/>
+<path id="Union_3" d="M16.8669 18C17.3086 18.0001 17.6666 18.3581 17.6667 18.7998C17.6667 19.2416 17.3087 19.5995 16.8669 19.5996H11.4666C11.0248 19.5995 10.6667 19.2416 10.6667 18.7998C10.6669 18.3581 11.0249 18.0001 11.4666 18H16.8669ZM16.8669 14C17.3086 14.0001 17.6666 14.3581 17.6667 14.7998C17.6667 15.2416 17.3087 15.5995 16.8669 15.5996H11.4666C11.0248 15.5995 10.6667 15.2416 10.6667 14.7998C10.6669 14.3581 11.0249 14.0001 11.4666 14H16.8669Z" fill="#FFFCE0"/>
+</g>
+<defs>
+<filter id="filter0_d_217_11499" x="2.69985" y="0.738611" width="16.4145" height="18.7554" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset/>
+<feGaussianBlur stdDeviation="2.2"/>
+<feComposite in2="hardAlpha" operator="out"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.9375 0 0 0 0 0.00390625 0 0 0 0 0.00390625 0 0 0 0.8 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_217_11499"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_217_11499" result="shape"/>
+</filter>
+<filter id="filter1_i_217_11499" x="7.09985" y="5.13861" width="7.6145" height="10.9554" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="1"/>
+<feGaussianBlur stdDeviation="2"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.988235 0 0 0 0 0.929412 0 0 0 0 0.890196 0 0 0 0.2 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_217_11499"/>
+</filter>
+<filter id="filter2_i_217_11499" x="12.0422" y="6.34216" width="6.573" height="6.48941" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dx="0.5" dy="0.5"/>
+<feGaussianBlur stdDeviation="1"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.972549 0 0 0 0 0.917647 0 0 0 0.7 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_217_11499"/>
+</filter>
+<linearGradient id="paint0_linear_217_11499" x1="13.3085" y1="7.30846" x2="17.0556" y2="12.4396" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FEEBAE"/>
+<stop offset="1" stop-color="#FFB160"/>
+</linearGradient>
+<linearGradient id="paint1_linear_217_11499" x1="18" y1="7" x2="21" y2="11" gradientUnits="userSpaceOnUse">
+<stop stop-color="#87EB8F"/>
+<stop offset="1" stop-color="#5AC1D4"/>
+</linearGradient>
+<linearGradient id="paint2_linear_217_11499" x1="11.6666" y1="24.5" x2="11.6666" y2="28" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FFD553"/>
+<stop offset="1" stop-color="#FB7830"/>
+</linearGradient>
+<linearGradient id="paint3_linear_217_11499" x1="0.666748" y1="16.5001" x2="23.7148" y2="16.5001" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FFDC49"/>
+<stop offset="0.49" stop-color="#FF8E33"/>
+<stop offset="1" stop-color="#FFA02B"/>
+</linearGradient>
+</defs>
+</svg>

Разница между файлами не показана из-за своего большого размера
+ 371 - 197
pages_course/living.vue


+ 2 - 12
pages_course/livingList.vue

@@ -15,9 +15,7 @@
 </template>
 
 <script>
-	import {
-		liveList
-	} from '@/api/living.js'
+	import {liveList} from '@/api/living.js'
 	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
 	export default {
 		mixins: [MescrollMixin],
@@ -43,7 +41,6 @@
 			}
 		},
 		onLoad() {
-			
 			// if (!uni.getStorageSync("AppToken")) {
 			// 	uni.navigateTo({
 			// 		url: '/pages/auth/login'
@@ -54,22 +51,18 @@
 
 		},
 		methods: {
-
 			mescrollInit(mescroll) {
 				this.mescroll = mescroll;
 			},
-
 			// 下拉刷新回调
 			downCallback(mescroll) {
 				this.list = [];
 				mescroll.resetUpScroll();
 			},
-
 			// 上拉加载回调
 			upCallback(mescroll) {
 				const pageNum = mescroll.num;
 				const pageSize = mescroll.size;
-
 				let data = {
 					pageSize: pageSize,
 					pageNum: pageNum,
@@ -86,7 +79,6 @@
 							this.list = [];
 						}
 						this.list = this.list.concat(curPageData);
-
 						mescroll.endBySize(curPageData.length, totalSize);
 					} else {
 						mescroll.endErr();
@@ -99,10 +91,9 @@
 					mescroll.endErr();
 				});
 			},
-
 			goLive(item) {
 				uni.navigateTo({
-					// &immediate=true
+					//url: `./living?liveId=1195`
 					url: `./living?liveId=${item.liveId}`
 				});
 			}
@@ -115,7 +106,6 @@
 		background-color: #111;
 		min-height: 100vh;
 		padding: 24rpx;
-
 		.list {
 			display: flex;
 			justify-content: space-between;

+ 7619 - 0
pages_course/livingQj.vue

@@ -0,0 +1,7619 @@
+<template>
+	<view class="swiper-wrapper" :class="liveItem.showType == 1 ? 'horizontal' : ''">
+		<view class="container">
+			<!-- 预告直播状态 -->
+			<view :class="liveItem.previewUrl?'trailer-box':'trailer-box2'" v-if="liveItem.status == 1">
+				<view class="video-container2"
+					:style="{ paddingBottom:liveItem.previewUrl?videoRatio + '%':'' ,height:auto,width:'100%'}">
+					<video v-if="liveItem.previewUrl" :id="`myVideo_${liveId}`" class="trailer-video"
+						:src="liveItem.previewUrl" :autoplay="true" :loop="false"
+						:object-fit="isHeight?'contain':'fill'" :custom-cache="false" :enable-progress-gesture="false"
+						vslide-gesture-in-fullscreen="false" :show-center-play-btn="false" :http-cache="false"
+						@error="videoError" @loadedmetadata="onVideoMetaLoaded" @pause="onVideoPause"
+						@play="onVideoPlay" :disable-progress="true" :enable-play-gesture="true"
+						@waiting="onVideoWaiting" preload="auto" type="application/x-mpegURL" :controls="false"></video>
+				</view>
+				<image v-if="liveItem.status == 1 && !liveItem.previewUrl" class="trailer-placeholder"
+					src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/readyStart.png">
+				</image>
+				<view class="countdown-container" v-if="liveItem.status == 1 && liveCountdown">
+					<view class="live-name" v-if="liveItem.previewUrl">{{ liveItem.liveName }}</view>
+					<view class="countdown-display">
+						<text class="countdown-label">距离开播还有</text>
+						<view class="countdown-unit">
+							{{ liveCountdown.hours || '00' }}
+						</view>
+						<view class="countdown-separator">:</view>
+						<view class="countdown-unit">
+							{{ liveCountdown.minutes || '00' }}
+						</view>
+						<view class="countdown-separator">:</view>
+						<view class="countdown-unit">
+							{{ liveCountdown.seconds || '00' }}
+						</view>
+					</view>
+				</view>
+				<view class="trailer-actions">
+					<button open-type="share" class="button-reset share-button">
+						<view class="action-button mr24" @click="handleAgreement">
+							<text>分享给好友</text>
+						</view>
+					</button>
+					<view class="action-button reserve-button" @click="handleAgreement">
+						<text>{{ hasSubscribed ? '已预约' : '预约直播'}}</text>
+					</view>
+				</view>
+			</view>
+
+			<!-- 无直播状态 -->
+			<view class="trailer-box" v-if="!liveItem">
+				<image class="trailer-placeholder"
+					src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/no_live.png">
+				</image>
+				<view class="no-live-title">暂无直播</view>
+			</view>
+
+			<!-- 主要内容区域 -->
+			<view class="content"
+				:class="{ 'horizontal-content': isFocus==1, 'trailer-content': liveItem.status==1,  'fullscreen-mode': isFullscreen   }">
+				<!-- 顶部信息栏 -->
+				<view class="top-info-bar" v-if="!isFullscreen"
+					:class="{'horizontal-top': liveItem.showType == 1,'hidden-on-fullscreen': isFullscreen}"
+					:style="{marginTop: menuButtonInfo.top}">
+					<view class="user-info-section">
+						<image v-if="!scene&&liveItem.showType==2" @click="goBack" class="back-icon mr4"
+							src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/return3.png" />
+						<image v-if="!scene&&liveItem.showType==1" @click="goBack" class="w42 h42 mr4"
+							src="/static/images/return_black.png" />
+						<view class="user-avatar-container">
+							<u-avatar
+								:src="liveItem.liveImgUrl || 'https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/avatar.png'"
+								:size="32"></u-avatar>
+							<view class="user-name ml10 mr6">
+								<view>{{ liveItem.liveName ? truncateString(liveItem.liveName, 8) : '未命名' }}</view>
+							</view>
+						</view>
+					</view>
+
+					<!-- 观众头像列表 -->
+					<!-- @click="toggleViewerList" -->
+					<view v-if="Array.isArray(filteredViewers)" class="viewers-section">
+						<view style="display: flex;align-items: center;">
+							<view v-for="(item, index) in (filteredViewers ||[])" :key="index">
+								<image v-if="item" class="viewer-avatar mr4" :src="item" />
+							</view>
+							<view class="viewer-count ">{{formattedWatchCount || 0 }}</view>
+						</view>
+					</view>
+				</view>
+
+				<!-- 视频区域 -->
+				<view class="videolist" v-if="liveItem.status == 2" :class="isFullscreen ? 'screen' : ''">
+					<view class="video-container"
+						:style="{ paddingBottom: liveItem.showType==2||isFullscreen?'':videoRatio + '%',height:liveItem.showType==2?'100vh':isFullscreen?'auto':'400rpx',width:isFullscreen?'0':'100%'}"
+						:class="{'horizontal-layout': liveItem.showType == 1,'fullscreen-mode': isFullscreen}">
+						<video v-if="liveItem.videoUrl && liveItem.liveType == 2 && !generating"
+							:id="`myVideo_${liveId}`" :autoplay="true" class="video-player" :src="liveItem.videoUrl"
+							:style="{transform:liveItem.showType!==2?`scale(${scale})`:'', transformOrigin: 'center center', bottom:isFullscreen?'0':''}"
+							:object-fit="liveItem.showType==2||isFullscreen?'contain':'fill'" :custom-cache="false"
+							:enable-progress-gesture="false" vslide-gesture-in-fullscreen="false"
+							:show-center-play-btn="false" :http-cache="false" loop @error="videoError"
+							@timeupdate="onVideoTimeUpdate" @loadedmetadata="onVideoMetaLoaded" @pause="onVideoPause"
+							@play="onVideoPlay" @waiting="onVideoWaiting" :enable-play-gesture="false"
+							:play-strategy="1" @dblclick="preventDoubleClick" preload="auto"
+							:enable-stash-buffer="false" :stash-initial-size="0" :stash-max-size="0" :stash-time="0"
+							type="application/x-mpegURL" :controls="false" :show-fullscreen-btn="false" show-play-btn
+							show-mute-btn enable-play-gesture="true" @fullscreenchange="onFullscreenChange"
+							x5-video-player-fullscreen="false" x5-video-player-type="h5"
+							x5-video-orientation="landscape" :webkit-playsinline="true" playsinline="true"
+							:x5-playsinline="true">
+						</video>
+						<view v-else class="txt">回放生成中...</view>
+						<view v-if="showCustomControls && liveItem.showType==1 && !isFullscreen" class="custom-controls"
+							@click.stop="toggleFullscreen">
+							<image src="/static/images/full_screen.png" class="control-icon" />
+						</view>
+
+						<!-- 全屏返回按钮 - 只在全屏状态下显示 -->
+						<view v-if="isFullscreen" class="fullscreen-exit-btn" @click="exitFullscreen">
+							<image src="/static/images/half_screen.png" class="exit-fullscreen-icon" />
+							<text class="exit-text">退出全屏</text>
+						</view>
+
+
+						<!-- 投诉按钮 -->
+						<view v-if="liveItem.showType==2||isFullscreen" class="complaint-box"
+							:class="isFullscreen ? 'complaint-full' : ''"
+							:style="{top:isFullscreen?'':'15%',bottom:isFullscreen?'86vw':''}"
+							@click="navgetTo('/pages_shopping/live/complaintList') ">
+							<image class="image w32 h32 mr10" src="/static/images/complaint.png" mode="widthFix" />
+							<view class="fs26">投诉</view>
+						</view>
+
+						<!-- 回放标签 -->
+						<view v-if="isPlayback" class="replay-label"
+							:style="{top:liveItem.showType === 2?'22%':isFullscreen?'':'10%',bottom:isFullscreen?'75vw':''}"
+							:class="isFullscreen? 'replay-full' : ''">回放
+						</view>
+
+						<!-- 观看时间 -->
+						<view class="look-time" v-if="isPlayback&&liveItem.showType==1"
+							:class="isFullscreen ? 'look-full' : '' ">{{playbackTime}}</view>
+					</view>
+				</view>
+				<!-- 直播结束状态 -->
+				<!-- v-if="liveItem.status == 3" -->
+				<view class="videolist" v-if="liveItem.status == 3">
+					<view class="video-container" style="height: 500rpx;"
+						:class="{'horizontal-layout': liveItem.showType == 1, 'fullscreen-mode': isFullscreen}">
+						<view class="live-end-message" :style="{marginTop:liveItem.showType === 2?'50%':''}">直播已结束
+						</view>
+					</view>
+				</view>
+
+				<!-- 直播回放 -->
+				<view class="videolist" v-if="liveItem.status == 4">
+					<view class="video-container" :class="liveItem.showType == 1 ? 'horizontal-layout' : ''">
+						<video v-if="liveItem.videoUrl && liveItem.liveType == 3" :id="`myVideo_${liveId}`"
+							class="video-player" :src="liveItem.videoUrl" :autoplay="true" :controls="true"
+							:object-fit="isFullscreen?'contain':'contain'" :custom-cache="false"
+							:enable-progress-gesture="liveItem.isSpeedAllowed" vslide-gesture-in-fullscreen="true"
+							:show-center-play-btn="true" :http-cache="false" loop @error="videoError"
+							@timeupdate="onVideoTimeUpdate" @loadedmetadata="onVideoMetaLoaded" @pause="onVideoPause"
+							@play="onVideoPlay" :enable-play-gesture="true" preload="auto" @waiting="onVideoWaiting"
+							type="application/x-mpegURL"></video>
+						<view v-if="liveItem.videoUrl && liveItem.liveType == 3" class="replay-label">直播回放</view>
+					</view>
+				</view>
+				<!-- v-if="!hasReachedTarget" -->
+				<!-- &&liveItem.completionPointsEnabled -->
+				
+				<view class="progress-countdown end" :class="liveItem.showType==2?' progress-vertical':''" :style="{ 'display':isFocus?'none':''}"
+					v-if="countdownPercentage!=100&&liveItem.completionPointsEnabled&&!receiveStatus&&liveItem.status==2&&!hasReceived&&!isPreview">
+					<image class="title" src="/static/images/points_title.png"></image>
+					<view class="progress-bar-bg">
+						<view class="progress-bar-fill" :style="{ width: countdownPercentage + '%' }"></view>
+					</view>
+					<view class="progress-text">
+						倒计时{{ formattedCountdown.hours||'00' }}:{{ formattedCountdown.minutes||'00' }}:{{ formattedCountdown.seconds||"00" }}
+					</view>
+				</view>
+				
+				<view class="slide-group" v-if="!isFocus && !isFullscreen">
+					<view class="action-button-group end">
+						<view :class="[liveItem.showType === 1 ? 'horizontal' : 'vertical','icon-button','ml20']">
+							<button open-type="share" class="action-icon button-reset">
+								<image class="action-icon"
+									src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/weixin.png"
+									mode="widthFix" />
+							</button>
+						</view>
+					</view>
+					<view class="action-button-group end">
+						<view
+							:class="[liveItem.showType === 1 ? 'horizontal' : 'vertical','icon-button','ml20','like-container']"
+							@click="onLike">
+							<LikeButton :initialCount="100" :heartsPerClick="5" @like="onLike" />
+							<view class="like-count">{{formattedLikeCount||0 }}</view>
+						</view>
+					</view>
+
+				</view>
+
+				<!-- 底部聊天区域 -->
+				<view class="chat-area-container" :class="{
+								    'chat-area-container2': liveItem.showType == 1,
+									'chat-area-container3': liveItem.status == 1 && !liveItem.previewUrl && liveItem.showType == 1,
+									'chat-area-container4': liveItem.status == 1 && liveItem.previewUrl && liveItem.showType == 1,
+								    'chat-area-focused': isFocus
+								  }" :style="{ '--keyboard-height': keyboardHeight + 'rpx' ,'display':isFullscreen?'none':''}">
+					<view class="tabs_bg" v-if="liveItem.showType == 1">
+						<u-tabs :list="listTabs" @click="clickTabs" lineColor="#02B176"
+							:activeStyle="{color: '#02B176',fontWeight: 'bold',transform: 'scale(1.05)'}">
+						</u-tabs>
+						<!-- 投诉 -->
+						<view v-if="liveItem.showType==1" class="complaint-box"
+							@click="navgetTo('/pages_shopping/live/complaintList') ">
+							<image class="image w32 h32 mr10" src="/static/images/complaint2.png" mode="widthFix" />
+							<view class="fs26">投诉</view>
+						</view>
+					</view>
+					<view class="chat-content-wrapper"
+						:style="{ 'height':liveItem.status == 1 && !liveItem.previewUrl && liveItem.showType == 2?'48vh':''}"
+						:class="{ 'chat-content-focused': isFocus }">
+						<view class="notice-message" v-if="isShowNotice"
+							:style="{ 'display':isFocus&&liveItem.showType == 2?'none':''}"
+							:class="liveItem.showType == 1 ? 'horizontal-notice' : 'horizontal-notice2'">
+							公告消息: {{notice.msg}}
+						</view>
+						<scroll-view id="msgScroll" v-if="Array.isArray(talklist)" enable-flex scroll-y="true"
+							:style="{ height: liveItem.showType === 1 || liveItem.showType == 2 && !isFocus?`calc(100% - ${commonViewHeight}px)`:'',
+											marginTop:liveItem.showType === 1?commonViewHeight+'px':liveItem.showType == 2 && !isFocus?`calc(${commonViewHeight}px + 20rpx)`:'' }" :enhanced="true" :bounces="false"
+							:show-scrollbar="false" :fast-deceleration="false" :enable-back-to-top="false"
+							class="message-scroll-view" :scroll-top="scrollTop" :scroll-into-view="scrollIntoView"
+							@scroll="onScroll" ref="scrollView">
+
+							<view class="message-list" v-for="(item, talkIndex) in (talklist || [])"
+								:key="item.uniqueId " :id="`list_${item.uniqueId }`" v-show="item.cmd != 'red' ">
+								<view class="message-item">
+									<view class="message-content">
+										<text class="user-nickname">{{ item.nickName || '未命名' }}
+											<text v-if="item.cmd != 'entry'">:</text>
+										</text>
+										<text class="message-text ml8">{{ item.msg }}</text>
+									</view>
+								</view>
+							</view>
+						</scroll-view>
+					</view>
+
+					<!-- 底部输入和操作区域 -->
+					<view class="input-actions-container" :class="{ 'input-actions-focused': isFocus }">
+						<view v-if="liveItem.status!=3&&!isPlayback" class="input-container" :class="{ 
+													'input-container-focused': isFocus,
+													'input-container-normal': !isFocus
+												}">
+							<input v-if="isIOS" type="text" :placeholder="placeholderText" v-model="value"
+								:placeholder-style="liveItem.showType == 1 ? 'color:#999999;' : 'color:#e7e7e7;'"
+								placeholder-class="placeholder-style" class="chat-input"
+								:class="{ 'input-focused': isFocus }" @focus="inputFocus" @blur="inputBlur"
+								cursor-spacing="100" :adjust-position="false" :disabled="isEnd" @confirm="sendMsg"
+								:confirm-type="value?'send':'done'" />
+
+							<input v-else :placeholder="placeholderText" v-model="value" type="text"
+								:placeholder-style="liveItem.showType == 1 ? 'color:#999999;' : 'color:#e7e7e7;'"
+								placeholder-class="placeholder-style" class="chat-input"
+								:class="{ 'input-focused': isFocus }" @focus="inputFocus" @blur="inputBlur"
+								cursor-spacing="100" :adjust-position="false" :disabled="isEnd" @confirm="sendMsg"
+								:confirm-type="value?'send':'done'" />
+							<view class="send-button" v-if="!isIOS" :class="liveItem.showType == 1 ? 'send2' : ''"
+								@click="sendMsg()">
+								发送</view>
+						</view>
+						<!--  :class="{ 'action-buttons-hidden': isFocus }" -->
+						<view class="action-buttons" v-if="!isFocus">
+							<view class="action-button-group" v-if="!isFocus">
+								<view
+									:class="[liveItem.showType === 1 ? 'horizontal' : 'vertical','icon-button','mr40']"
+									@click="isMore=true,shopping=false">
+									<!-- <image
+														src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/more-icon.png"
+														class="action-icon" /> -->
+
+									<image :src="liveItem.showType == 1 
+														    ? '/static/images/more2.png' 
+														    :'https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/more-icon.png'"
+										class="action-icon" />
+								</view>
+							</view>
+
+							<view class="icon-button mr20" @tap="openCart()">
+								<image
+									src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/shopping.png"
+									class="cart-icon" />
+							</view>
+
+						</view>
+					</view>
+				</view>
+			</view>
+
+			<!-- 商品卡片 -->
+			<view class="goods-card" v-if="isShowGoods&&!isFullscreen"
+				@click.stop="goShop(goodsCard.productId, goodsCard.goodsId)">
+				<view class="goods-card-header">
+					<view class="goods-status">
+						<image class="status-icon mr8"
+							src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/signal.png" />
+						主播讲解中
+					</view>
+					<image @click.stop="isShowGoods = false" class="close-icon" src="/static/images/close_w.png" />
+				</view>
+				<image class="goods-image" :src="goodsCard.imgUrl" />
+				<view class="goods-info">
+
+					<view class="goods-title oneline-hide">{{ goodsCard.productName }}</view>
+					<view class="goods-action">
+						<view class="goods-price">
+							<text class="price-symbol">¥<text class="price-integer">{{ goodsCard.price }}</text> <text
+									class="price-decimal"></text></text>
+						</view>
+						<image class="shop-icon" src="/static/images/shop.png"></image>
+					</view>
+				</view>
+			</view>
+
+			<!-- :show="userlogo" -->
+			<u-popup :show="userlogo" mode="bottom" round='12'>
+				<view class="userlogo column">
+					<view class="bold fs36 mt42">授权你的昵称信息</view>
+					<view class=" justify-between align-center  mt42">
+						<view class="button-container">
+							<input type="nickname" class="hidden-input"
+								placeholder-style="color:#ffffff; font-size:32rpx;" @blur="onNickNameInput"
+								placeholder="请点击授权微信昵称" @input="onNickNameInput" />
+						</view>
+					</view>
+					<view class="submitname" @click="confimrname">确定</view>
+				</view>
+			</u-popup>
+
+			<!-- 抽奖弹窗 -->
+			<u-popup :show="isShowLotteryPop && countdown" round="40rpx">
+				<view class="lottery-popup">
+					<image class="lottery-header-image"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/red_head.png"
+						mode="widthFix" />
+					<image class="lottery-background-image"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/red_bg.png" />
+					<view class="lottery-content">
+						<view class="lottery-close-section">
+							<view class="close-button-wrapper">
+								<view class="close-button" @click="isShowLotteryPop = false">
+									<u-icon class="close-icon" name="close" color="#fff" size="20"></u-icon>
+								</view>
+							</view>
+						</view>
+						<view class="lottery-main-content">
+							<image class="lottery-title-image"
+								src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/red_title.png" />
+							<view class="lottery-countdown-section">
+								<view class="countdown-label">开奖倒计时</view>
+								<view class="countdown-timer">
+									<view class="countdown-number">
+										{{ countdown.hours || '00' }}
+									</view>
+									<view class="countdown-number">
+										{{ countdown.minutes || '00' }}
+									</view>
+									<view class="countdown-number">
+										{{ countdown.seconds || '00' }}
+									</view>
+								</view>
+							</view>
+							<view class="lottery-products-section">
+								<ThreeItemSwiper :products="lotteryProducts"></ThreeItemSwiper>
+							</view>
+							<view class="lottery-indicators">
+								<view class="indicator-point" v-for="(item, index) in (lotteryProducts || [])"
+									:key="index"></view>
+							</view>
+							<view class="lottery-tip">观看直播参与抽奖</view>
+							<view class="lottery-action-button" @click="onClaim">参与抽奖</view>
+						</view>
+					</view>
+				</view>
+			</u-popup>
+			
+			<!-- 积分弹窗(完课) -->
+			<!-- showPoints -->
+			<!-- :show="!!integral.status" -->
+			<!-- :show="showPoints"  -->
+			<!-- :show="shouldShowIntegralPopup" -->
+			<u-popup :show="shouldShowIntegralPopup" round="20rpx" mode="center" bgColor="#ffffff" zIndex="10076">
+				<view class="integral-popup color9">
+					<view class="integral-header">
+						<view class="integral-title">观看视频领积分</view>
+						<image class="integral-background-image"
+							src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/integral_bg.png" mode="widthFix" />
+					</view>
+					<view class="integral-content">
+						<view class="integral-message">积分领取成功</view>
+						<view class="integral-confirm-button" @click="showPoints = false">确认</view>
+					</view>
+					
+					<!-- <view class="integral-content">
+						<view class="integral-item" v-for="(item,index ) in receiveList" :key="index">
+							<view class="integral-message">连续签到{{item.continuousDays}}天</view>
+							<view class="integral-message">获取{{item.pointsAwarded}}积分</view>
+							<view class="integral-confirm-button" @click="completionReceive(item)">领取</view>
+						</view>
+					</view> -->
+				</view>
+			</u-popup>
+
+			<!-- 积分弹窗(时长) -->
+			<u-popup :show="!!integral.status" round="20rpx" mode="center" bgColor="#ffffff" zIndex="10076">
+				<view class="integral-popup color9">
+					<view class="integral-header">
+						<view class="integral-title">观看视频领积分</view>
+						<image class="integral-background-image"
+							src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/integral_bg.png"
+							mode="widthFix" />
+					</view>
+					<view class="integral-content">
+						<view class="integral-message">{{ integral.msg }}</view>
+						<view class="integral-confirm-button" @click="integral.status = false">确认</view>
+					</view>
+				</view>
+			</u-popup>
+			
+			<!-- 红包弹窗 -->
+			<u-popup :show="isShowRed" round="20rpx" mode="center" zIndex="10076" bgColor="transparent">
+				<view class="red-envelope-popup" @click="onRed()">
+					<image class="red-envelope-close-button"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/close_white.png"
+						@click.stop="isShowRed=false"></image>
+					<image class="red-envelope-background"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/pop1.png">
+					</image>
+					<view class="red-envelope-content">
+						<view class="red-envelope-header">
+							<image class="header-decoration-left"
+								src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/top_left.png"
+								mode="widthFix" />
+							<view class="header-title">恭喜您可以</view>
+							<image class="header-decoration-right"
+								src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/top_right.png"
+								mode="widthFix" />
+						</view>
+						<view class="red-envelope-text">领红包</view>
+						<view class="red-envelope-open-text">开</view>
+					</view>
+				</view>
+			</u-popup>
+
+			<!-- 抽奖弹窗2 -->
+			<u-popup :show="isShowLottery&&countdown" round="20rpx" mode="center" zIndex="10076" bgColor="transparent">
+				<view class="lottery-popup-v2">
+					<image class="lottery-close-button-v2"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/close_white.png"
+						@click.stop="isShowLottery=false">
+					</image>
+					<image class="lottery-top-image"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/pop_top.png"
+						mode="widthFix"></image>
+					<image class="lottery-background-v2"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/pop2.png">
+					</image>
+					<view class="lottery-content-v2">
+						<view class="lottery-header-v2">
+							<image class="lottery-header-decoration-left"
+								src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/top_left.png"
+								mode="widthFix" />
+							<view class="lottery-header-title">恭喜您可以</view>
+							<image class="lottery-header-decoration-right"
+								src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/top_right.png"
+								mode="widthFix" />
+						</view>
+						<view class="lottery-text-v2">参与抽奖</view>
+						<view class="lottery-text-v2">赢好礼</view>
+						<view class="lottery-action-button-v2" @click="onLottery()">确认</view>
+					</view>
+				</view>
+			</u-popup>
+
+			<!-- 红包卡片弹窗 -->
+			<u-popup :show="isShowRedCard" round="20rpx" mode="center" bgColor="transparent" zIndex="10076">
+				<view class="red-card-popup">
+					<image class="red-card-image"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/red_card.png" />
+					<view class="red-card-content">
+						<view class="red-card-message">{{ redCard.msg }}</view>
+						<view class="red-card-tip">直播惊喜积分</view>
+						<view class="red-card-confirm-button" @click="isShowRedCard = false">确认</view>
+					</view>
+				</view>
+			</u-popup>
+
+			<!-- 消息弹窗 -->
+			<u-popup :show="isShowPopMsg" round="20rpx" mode="center" zIndex="10076">
+				<view class="message-popup">
+					<image class="message-close-icon" src="/static/images/message_icon.png" />
+					<view class="message-title">消息通知</view>
+					<view class="message-content">{{popMsg}}</view>
+					<view class="message-confirm-button" @click="isShowPopMsg = false">确认</view>
+					<image src="/static/images/close_white_icon.png" class="close" @click="isShowPopMsg = false">
+					</image>
+				</view>
+			</u-popup>
+
+
+			<!-- 中奖和未中奖 -->
+			<u-popup :show="isShowPrize && havePrize" round="20rpx" mode="center" bgColor="#fff" zIndex="10076">
+				<view class="prize-popup" v-if="isCurrentUserWon">
+					<image class="prize-header-image"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/red_head.png"
+						mode="widthFix" />
+					<view class="prize-title">恭喜您 中奖啦!</view>
+					<view class="prize-info-section" v-for="(item, index) in (prizeInfo || [])" :key="index">
+						<view class="prize-info-item">{{ item.userName }}</view>
+						<view class="prize-info-item">{{ item.userId }}</view>
+						<view class="prize-level item">{{ item.prizeLevel }}等奖</view>
+					</view>
+					<view class="prize-tip">请填写收货地址,主播将会将奖品发给您</view>
+					<view class="prize-action-button"
+						@click="navgetTo('/pages_shopping/live/confirmCreateOrder?type=win&productId='+getCurrentUserPrizeProductId+'&liveId='+liveId+'&recordId='+getCurrentUserPrizeRecordId),confirm()">
+						填写地址</view>
+				</view>
+				<view class="no-prize-popup" v-else>
+					<image class="no-prize-image"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/no-prize.png"
+						mode="widthFix" />
+					<view class="no-prize-tip">很遗憾 您未中奖</view>
+					<view class="no-prize-confirm-button" @click="confirm">确认</view>
+				</view>
+			</u-popup>
+
+			<!-- 中奖记录弹窗 -->
+			<u-popup :show="winning" @close="closeWin" round="20rpx" bgColor="#f3f5f9" zIndex="10076">
+				<view class="winning-record-popup">
+					<image class="winning-record-header-bg"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/red_head.png"
+						mode="widthFix"></image>
+					<image class="winning-record-background"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/red_bg.png">
+					</image>
+					<view class="winning-record-content">
+						<view class="winning-record-title">我的中奖记录</view>
+						<view class="winning-record-header">
+							<view class="header-column time-column">时间</view>
+							<view class="header-column status-column">状态</view>
+							<view class="header-column prize-column">奖品</view>
+						</view>
+						<scroll-view v-if="prizeAll" enable-flex scroll-y class="winning-record-list">
+							<view class="winning-record-item" v-for="(item, index) in (prizeAll||[])" :key="index">
+								<view class="record-time">{{ item.createTime }}</view>
+								<view class="record-status-button" v-if="item.orderStatus=='-9'||!item.orderStatus"
+									@click="navgetTo('/pages_shopping/live/confirmCreateOrder?type=win&productId='+item.productId+'&liveId='+liveId+'&recordId='+item.id),winning=false">
+									<text>填地址</text>
+								</view>
+								<view class="record-status" v-else>
+									<text v-if="item.orderStatus=='1'">待支付</text>
+									<text v-if="item.orderStatus=='2'">待发货</text>
+									<text v-if="item.orderStatus=='3'">待收货</text>
+									<text v-if="item.orderStatus=='4'">已完成</text>
+									<text v-if="item.orderStatus=='-3'">已取消</text>
+								</view>
+								<view class="record-prize">
+									{{ item.productName ? truncateString(item.productName, 6) : '' }}
+								</view>
+							</view>
+						</scroll-view>
+						<view v-else class="no-winning-records">暂无中奖信息</view>
+					</view>
+				</view>
+			</u-popup>
+			
+			<!-- 更多操作弹窗 -->
+			<u-popup :show="isMore" @close="closeMore" round="20rpx" bgColor="#f3f5f9" zIndex="10076">
+				<view class="more-actions-popup">
+					<view class="more-action-item"
+						@click="navgetTo('/pages_shopping/live/integral?liveId'+liveId), (isMore = false)">
+						<image class="action-icon"
+							src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/order.png" />
+						<view class="action-label">积分</view>
+					</view>
+					<!-- <view class="more-action-item"
+						@click="navgetTo('/pages_shopping/live/storeOrderRefundList?liveId=' + liveId), (isMore = false)">
+						<image class="action-icon"
+							src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/after_sales.png" />
+						<view class="action-label">售后订单</view>
+					</view> -->
+					<view class="more-action-item" @click="goMiniProgram(), (isMore = false)">
+						<image class="action-icon"
+							src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/points.png" />
+						<view class="action-label">兑换好礼</view>
+					</view>
+					<view class="more-action-item" @click="getMyLottery(), (isMore = false), (winning = true)">
+						<image class="action-icon"
+							src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/health_sel.png" />
+						<view class="action-label">中奖记录</view>
+					</view>
+				</view>
+			</u-popup>
+
+			<!-- 商品弹窗 -->
+			<u-popup :show="shopping" @close="closeShop" round="20rpx" bgColor="#f3f5f9" zIndex="10075">
+				<view class="shopping-popup">
+					<view class="shopping-header">
+						<view class="search-input-container">
+							<image class="search-icon"
+								src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/search.png"
+								mode="widthFix" />
+							<input placeholder="请搜索商品" v-model="inputInfo" @input="handleSearchInput" />
+						</view>
+						<view class="x-f">
+							<view class="shopping-action-button mr30" @click="navgetTo('/pages_shopping/live/order')">
+								<image class="action-button-icon"
+									src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/carts.png" />
+								<view class="action-button-label">订单</view>
+							</view>
+							<view class="shopping-action-button" @click="(isMore = true), (shopping = false)">
+								<image class="action-button-icon"
+									src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/search2.png" />
+								<view class="action-button-label">更多</view>
+							</view>
+						</view>
+					</view>
+
+					<scroll-view enable-flex scroll-y class="products-list">
+						<view v-for="(item, index) in products" :key="index" class="product-item">
+							<view class="product-image-container">
+								<image class="product-image" :src="item.imgUrl" mode="widthFix" />
+								<view class="product-index-label">{{ index + 1 }}</view>
+							</view>
+							<view class="product-info">
+								<view class="product-name">{{ item.productName }}</view>
+								<view class="product-sales">{{ item.sales }} 人已购</view>
+								<view class="product-action-section">
+									<text class="product-price">
+										<text class="price-symbol">¥</text>
+										<text class="price-integer">{{ Math.trunc(item.price) }}</text>
+										.{{ getPureDecimal(item.price) ? getPureDecimal(item.price) : '00' }}
+									</text>
+									<view class="product-action-buttons">
+										<view class="collect-button">
+											<image v-if="item.isFavorite" @click="onGoodsCollect(item)"
+												class="collect-icon"
+												src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/collect_select.png" />
+											<image v-else @click="onGoodsCollect(item)" class="collect-icon"
+												src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/collect.png" />
+										</view>
+										<view v-if="item.status == 1" class="buy-button"
+											@click="goShop(item.productId, item.goodsId)">去购买</view>
+										<view v-else-if="item.status == 0" class="buy-button disabled">已下架</view>
+									</view>
+								</view>
+							</view>
+						</view>
+					</scroll-view>
+				</view>
+			</u-popup>
+
+			<!-- 优惠券弹窗 -->
+			<view class="coupon-popup" v-if="isShowCoupon">
+				<view class="coupon-container">
+					<image class="coupon-background"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/coupon_bg.png" />
+					<image class="coupon-header"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/coupon_top.png" />
+					<image @click="isShowCoupon = false" class="coupon-close-button"
+						src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/close_white.png" />
+					<view class="coupon-content">
+						<view class="coupon-name">{{ couponInfo.couponName }}</view>
+						<view class="coupon-price">
+							¥
+							<text class="coupon-price-integer">{{ couponInfo.couponPrice }}</text>
+						</view>
+						<view class="coupon-condition">满{{ couponInfo.useMinPrice }}元可用</view>
+						<view class="coupon-description">指定商品可用</view>
+						<view class="coupon-validity">自领取起{{ couponInfo.couponTime }}天内有效</view>
+						<view class="coupon-get-button" @click="onCoupon()">立即领券</view>
+					</view>
+				</view>
+			</view>
+			<view v-if="liveItem.status == 1" class="ash_bg"></view>
+			
+		</view>
+	</view>
+</template>
+
+<script>
+	import LikeButton from '@/pages_course/components/like.vue';
+	import ThreeItemSwiper from '@/pages_course/components/ThreeItemSwiper.vue';
+	import CryptoJS from 'crypto-js';
+	import {
+		myLiveMsg,
+		myLottery, // 我的中奖明细
+		coupon, //领取优惠券
+		liveLottery, // 抽奖查询
+		claim, //抽奖
+		liveRed, // 点击领红包
+		liveDataLike, // 点赞
+		collectStore, // 店铺收藏/取消收藏
+		collectGoods, // 商品收藏/取消收藏
+		watchUserList, //获取直播间用户(展示在线用户)
+		liveMsg, //获取最近聊天记录
+		// 小黄车
+		liveStore, //店铺展示,
+		liveOrderUser, //正在购买
+		getLiveInfo, //获取直播间信息接口
+		getLiveViewData, //直播间点赞、关注、在线人数数据
+		currentActivities, //红包 卡片 抽奖
+		getlive,
+		subNotifyLive,
+		internetTraffic, // 流量(缓冲百分比),
+		liveInternetTraffic, // 直播流量(缓冲百分比),
+		loginByMp,
+		getUserInfo,
+		getIsAddKf,
+		liveWatchUser
+	} from '@/api/living.js';
+	import {
+		editUser
+	} from '@/api/user'
+	import {
+		nextTick
+	} from 'vue';
+
+	import {
+		mapGetters
+	} from 'vuex';
+	import {
+		TOKEN_KEYAuto,
+		generateRandomString
+	} from '@/utils/courseTool.js'
+	import {
+		completionRecords,
+		completionReceive,
+		completionUnreceived,
+
+		remainingTime,
+		updateWatchDuration,
+		receivePoints,
+		
+		integrallogs
+	} from '@/api/integral.js'
+	import dayjs from 'dayjs';
+	var isSocketOpen = false;
+	var socket = null;
+
+	export default {
+		components: {
+			ThreeItemSwiper,
+			LikeButton
+		},
+		data() {
+			return {
+				videoDuration:0,//要看的时长
+				pointsRemainingTime: 0,
+				hasReceived: false,
+				receiveStatus: false,
+				completionRate: 0,
+				playbackTime: '00:00:00', //用户观看回放时间
+				// 观看时长统计变量
+				watchStartTime: 0, // 开始观看时间戳
+				accumulatedWatchDuration: 0, // 累计观看时长(秒)
+				isPageVisible: true, // 页面是否可见
+				lastPauseTime: 0,
+				qwCode: false,
+				hasReachedTarget: false,
+				receiveList: [],
+				recordId: null, //完课积分记录ID
+				showPoints: false,
+				remainingTime: 0, // 剩余时间(秒)
+				watchProgressKey: '', // 存储键
+				isCountdownActive: false, // 倒计时是否激活
+				countdownTimer: null, // 倒计时定时器
+				lastUpdateTime: 0, // 上次更新时间
+
+				totalWatchTime: 0, // 累计观看时间(秒)
+				watchTimeStorageKey: '', // 存储键
+				lastSaveTime: 0, // 上次保存时间
+				watchTimeTimer: null, // 观看时间定时器
+				hasSubscribed: false, // 已成功订阅(永久禁用)
+				urlOption: {},
+
+				menuButtonInfo: {}, // 胶囊按钮布局信息
+				isHeight: false,
+				isFullscreen: false,
+				isVideoRotated: false,
+				showNonVideoElementsFlag: true,
+				videoRatio: 56.25, // 默认16:9比例
+				scale: 1,
+				isMuted: false,
+				showCustomControls: true,
+				videoContext: null,
+				isNow: false,
+				fakeAvatar: Array.from({
+						length: 11
+					}, (_, i) =>
+					`https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/avatar${i + 1}.jpg`),
+				virtualHuman: null,
+				userlogo: false,
+				listTabs: [{
+					name: '讨论',
+				}],
+				generating: false,
+				hasPlayback: false,
+				isPlayback: false, //是否是回放
+				isIOS: false,
+				myselfFlag: false, // yhq
+				isEnd: false,
+				popMsg: null,
+				// barrageList: ['支持你!', '谢谢你!', '平台真好!', '666', '欢迎回家!'], //一键弹幕列表
+				uuId: '',
+				totalTraffic: 0, // 总流量(字节)
+				bitrate: 800, // 录播默认码率 0.16Mbps
+				bitrateLive: 1600, // 直播默认码率 0.16Mbps
+				videoLoaded: false, // 视频是否加载成功
+				trafficStartTime: 0, // 流量计算开始时间
+				liveBeginWatchTime:0,//开始观看的时间点 不包含预告
+				//定时器
+				trafficTimer: null,
+				pingTimeoutTimer: null, // 心跳超时定时器
+				heartBeatTimer: null, // 心跳定时器
+				liveViewDataTimer: null,
+				reconnectTimer: null, // 重连定时器
+				scrollTimer: null, // 滚动防抖定时器
+				lastScrollTime: 0, // 上次滚动时间
+				scrollDebounceDelay: 200, // 滚动防抖延迟(毫秒)
+				searchTimer: null, //搜索
+				purchasePromptTimer: null, //购买提示
+				welcomeTimer: null, //进入离开直播间定时器
+				redTimer: null,
+				liveStartTimer: null,
+				lotteryTimer: null,
+				memoryMonitorTimer: null, // 内存监控定时器
+				networkStatusTimer: null, // 网络状态检测定时器
+				networkRetryTimer: null, // 网络重试定时器
+				lastHeartBeatTime: 0, // 上次心跳时间
+
+				// 性能监控
+				connectionStartTime: 0, // 连接开始时间
+				connectionLatency: 0, // 连接延迟
+				messageCount: 0, // 消息计数
+				errorCount: 0, // 错误计数
+				lastPerformanceCheck: 0, // 上次性能检查时间
+				stayTime: 0,
+				startTime: 0,
+				scrollTop: 0,
+				currentScrollTop: 0, // 当前实际滚动位置
+				scrollIntoView: '', // scroll-into-view属性
+				messageIdCounter: 0, // 消息ID计数器,确保每个消息有唯一ID
+				scrollPending: false, // 滚动操作是否正在等待执行
+				isOnload: false,
+				isConnecting: false, // 是否正在连接中
+				hasInitialized: false,
+				// 请求状态标记,防止重复请求
+				isLoadingLiveInfo: false, // 是否正在加载直播间信息
+				isLoadingVideo: false, // 是否正在加载视频资源
+				hasCheckedLogin: false, // 是否已检查登录状态
+				hasLoadedLocation: false, // 是否已加载位置信息
+
+				liveViewersData: [],
+				liveUserCalled: false, //调用过watchUserList没
+				userRandomColors: Object.create(null), // 缓存用户ID -> 随机色的映射
+
+				heartBeatRetryCount: 0, // 心跳发送重试次数(避免一次失败就重连)
+				maxHeartBeatRetries: 3, // 心跳最大重试次数(增加到3次)
+				pingTimeout: 25000, // 心跳超时时间(25秒,适应移动网络)
+				shownEntryUsers: new Set(), // 存储已显示过「进入提示」的用户ID
+
+				socket: null, // WebSocket 实例
+				isSocketOpen: false, // 连接是否已打开
+				heartBeatInterval: 15000, // 心跳发送间隔(15秒)
+				adaptiveHeartBeatInterval: 15000, // 自适应心跳间隔
+				reconnectCount: 0, // 当前重连次数f
+				maxReconnectAttempts: 5, // 最大重连次数(增加到5次)
+				isManualClose: false, // 是否手动关闭(用于区分主动关闭和异常断开)
+				networkType: 'unknown', // 当前网络类型
+				isNetworkAvailable: true, // 网络是否可用
+
+				templateId: '_4qtxmcaXRsTe96wBKtx7VvRuxeF5ln4l27KL-L57Zs', //百域承品
+				isAgreement: false,
+
+				wsNewUrl: 'wss://api.fhhx.runtzh.com/ws/app/webSocket',
+				// wsNewUrl: 'ws://192.168.10.166:7114/ws/app/webSocket',
+				qrFrom: null,
+				scene: '',
+
+				liveCountdown: {}, //直播倒计时
+				countdown: {}, //抽奖倒计时
+				liveViewData: {},
+
+				keyboardHeight: 0,
+				videoCurrentTime: 0, // 当前视频播放时间
+				videoProgressKey: '', // 存储进度的key
+				inAndOut: {},
+				winning: false,
+				isShowPrize: false,
+				isShowCoupon: false,
+				prizeInfo: [],
+				havePrize: uni.getStorageSync('havePrize') || false, //是否参与抽奖
+				countDownKey: 0,
+				lotteryProducts: [],
+				lotteryList: [],
+				talklist: [],
+				isShowLotteryPop: false,
+				liveItem: {},
+				isSending: false,
+				isMore: false,
+
+				value: '',
+				placeholderText: '说点什么...',
+
+				prizeAll: [],
+				isShowLottery: false,
+				isShowRedCard: false,
+				isShowPopMsg: false,
+				isShowNotice: false,
+				notice: [],
+				redCard: null, //点击红包出现弹窗
+				integral: {},
+				lotteryInfo: {},
+				goodsCard: {},
+				couponInfo: {},
+				redInfo: {},
+				storeId: null,
+				isFocus: false,
+				shopping: false,
+				systemInfo: null, // 缓存系统信息,避免重复调用同步API
+				generatingTimer: null, //回访生成中
+				getlivingTimer: null, // getliving 防抖定时器
+				inputInfo: '',
+				showWelcomeMessage: false,
+				isShowGoods: false,
+				isShowRed: false,
+				lastClickTime: 0,
+				videoRetryCounts: Object.create(null), // 记录每个直播间的视频重试次数,格式: { liveId: 次数 }
+				clickDelay: 300, // 300ms内只响应一次点击
+				liveUserTotal: 0,
+				viewPageSize: 10, // 每页数量
+				viewPageNum: 1, // 当前页码
+				viewLoading: false, // 是否正在加载
+				scrollHeight: 0,
+				showPurchasePrompt: false,
+				prevOrderCount: 0, // 用于记录上一次的购买人数
+				videoUrl: null,
+				showType: 1, //横屏1 竖屏2
+				boxHeight: 300, //小黄车高度
+				liveViewers: [], //观众
+				livingUrl: '',
+				products: [],
+				loadingProducts: false, // 商品加载状态
+				orderUser: {}, //正在购买
+				userType: 0,
+				timestamp: '',
+				showadd: false,
+				liveId: null,
+				userInfo: {}, //用户信息
+				userData: {},
+				diffTotalTime: '',
+				address: '',
+				commonViewHeight: '',
+				user: {},
+				watchDuration:0,
+				liveFlag:-1,//0 回放   1 直播
+				isPreview:true, //是否预告
+				hasReplayGeneration:false, //是否经历回放生成
+				diffLiveStartTime:0,  //距离直播开始时间差值
+				diffLiveEndTime:0, //距离直播结束时间差值
+				diffReplayGenerationSeconds:0, //经历回放生成的秒速
+				completionTime:0, //领取积分所需时间
+				hasLiveEnd:false, //是否经历过首播结束
+				isPageLoadFirst:true, //是否首次加载直播间
+				pointsRetryTimer: null, // 积分领取重试定时器
+			};
+		},
+		async onLoad(options) {
+
+			this.getMenuButtonInfo(); // 初始化获取胶囊信息
+			this.initTime()
+
+			// 解析参数
+			if (options.liveId) {
+				this.liveId = options.liveId;
+			}
+			if (options.qwUserId) {
+				this.urlOption.companyId = options.companyId
+				this.urlOption.companyUserId = options.companyUserId
+				this.urlOption.corpId = options.corpId
+				this.urlOption.liveId = options.liveId
+				this.urlOption.qwUserId = options.qwUserId
+				this.urlOption.qwExternalId = options.externalId
+				this.urlOption.chatId = options.chatId
+			}
+			// 扫码传来的参数
+			if (options.scene) {
+				this.scene = options.scene;
+				const decodedScene = decodeURIComponent(this.scene);
+				const params = {};
+				decodedScene.split('&').forEach((item) => {
+					const [key, value] = item.split('=');
+					params[key] = value;
+					this.liveId = params.a;
+				});
+				if (params.b && params.c) {
+					console.log("扫码参数", params)
+					this.qrFrom = `&companyId=${params.b}&companyUserId=${params.c}`;
+				}
+			}
+			if (options.companyId && options.companyUserId) {
+				this.qrFrom = `&companyId=${options.companyId}&companyUserId=${options.companyUserId}`;
+			}
+			this.userinfo = uni.getStorageSync('userinfo');
+			this.hasSubscribed = uni.getStorageSync('subscribe_status_' + this.liveId) || false;
+			console.log('全部参数', options);
+			// 优先判断登录状态,然后加载数据
+			// this.userData = uni.getStorageSync('userData');
+			try {
+				const isLogin = await this.utils.checkLiveToken();
+				this.hasCheckedLogin = true;
+				if (isLogin) {
+					// 登录后:优先加载直播间信息,然后加载视频资源
+					await this.haveLogin();
+				} else {
+					// 未登录:先登录,登录成功后再加载数据
+					this.goLogin();
+				}
+
+			} catch (error) {
+				console.error('初始化失败:', error);
+				this.hasCheckedLogin = true;
+			}
+
+			// 异步加载位置信息(不阻塞主流程)
+			if (!this.hasLoadedLocation) {
+				this.getLocationByIP();
+			}
+			//获取键盘高度 - 针对iPhone优化(使用缓存的系统信息)
+			uni.onKeyboardHeightChange((res) => {
+				console.log('键盘高度变化:', res.height, '平台:', this.systemInfo.platform);
+				if (this.systemInfo.platform === 'ios') {
+					// iPhone特殊处理
+					if (res.height > 0) {
+						// 键盘弹出
+						this.isKeyboardShow = true;
+						// iPhone键盘高度计算优化
+						let calculatedHeight = res.height * 2;
+						// 根据iPhone型号进行微调
+						if (this.systemInfo.model) {
+							if (this.systemInfo.model.includes('iPhone X') ||
+								this.systemInfo.model.includes('iPhone 11') ||
+								this.systemInfo.model.includes('iPhone 12') ||
+								this.systemInfo.model.includes('iPhone 13') ||
+								this.systemInfo.model.includes('iPhone 14') ||
+								this.systemInfo.model.includes('iPhone 15') ||
+								this.systemInfo.model.includes('iPhone 16') ||
+								this.systemInfo.model.includes('iPhone 17')) {
+								// 刘海屏设备需要额外调整
+								calculatedHeight = calculatedHeight + 20; // 增加20rpx补偿
+							}
+						}
+
+						// 减去底部安全区域,避免过高
+						const safeAreaBottom = this.systemInfo.safeAreaInsets ? this.systemInfo.safeAreaInsets
+							.bottom : 0;
+						if (safeAreaBottom > 0) {
+							calculatedHeight = calculatedHeight - (safeAreaBottom * 2.0); // 微调10rpx
+						}
+						this.keyboardHeight = Math.max(400, calculatedHeight);
+					} else {
+						// 键盘隐藏
+						this.isKeyboardShow = false;
+						this.keyboardHeight = 0;
+					}
+				} else {
+					console.log("手机型号是>>>>", this.systemInfo.model)
+					// Android处理保持原有逻辑
+					if (res.height > 0) {
+						this.isKeyboardShow = true;
+						const safeAreaBottom = this.systemInfo.safeAreaInsets ? this.systemInfo.safeAreaInsets
+							.bottom : 0;
+						// this.keyboardHeight = (res.height * 2)-50;
+						// this.keyboardHeight = res.height * 2;
+						if (this.systemInfo.brand == 'vivo') {
+							this.keyboardHeight = res.height * 2;
+						} else {
+							// this.keyboardHeight = (res.height * 1.78) + 20;''
+							this.keyboardHeight = (res.height * 1.88) + 20;
+						}
+						console.log("高度是", this.keyboardHeight)
+					} else {
+						this.isKeyboardShow = false;
+						this.keyboardHeight = 0;
+					}
+				}
+			});
+
+			// 初始化网络状态监听
+			this.initNetworkStatusListener();
+		},
+		async onPullDownRefresh() {
+			// 下拉刷新时,重新加载数据
+			if (this.liveId) {
+				// 重置加载状态,允许重新加载
+				this.isLoadingLiveInfo = false;
+				//await this.getliving(this.liveId);
+				await this.getLiveMsg(this.liveItem);
+			}
+			setTimeout(() => {
+				uni.stopPullDownRefresh();
+			}, 1000);
+			this.getliving(this.liveId);
+		},
+		mounted() {
+			// 获取 video 上下文
+			// 监听视频全屏事件
+			setTimeout(() => {
+				this.videoContext = uni.createVideoContext(`myVideo_${this.liveId}`, this);
+				// 添加全屏状态变化监听(更可靠的方式)
+				if (this.videoContext) {
+					// 使用 uni.onUserCaptureScreen 作为备选方案
+					uni.onUserCaptureScreen(() => {
+						console.log('用户截屏,可能是全屏状态');
+					});
+				}
+			}, 1000);
+
+			const systemInfo = uni.getSystemInfoSync();
+			this.isIOS = systemInfo.platform === 'ios';
+		},
+		async onShow() {
+			setTimeout(()=>{
+				this.startCountdown();
+			},500);
+			if (!this.hasCheckedLogin) {
+				try {
+					const isLogin = await this.utils.checkLiveToken();
+					this.hasCheckedLogin = true;
+					if (isLogin) {
+						await this.haveLogin();
+						if (this.urlOption.qwUserId) {
+							this.getIsAddKf()
+						}
+					} else {
+						this.goLogin();
+					}
+				} catch (error) {
+					console.error('初始化失败:', error);
+					this.hasCheckedLogin = true;
+				}
+			}
+			// 位置信息只加载一次
+			if (!this.hasLoadedLocation) {
+				this.getLocationByIP();
+			}
+			this.uuId = generateRandomString(16);
+			const isLiveLogin = uni.getStorageSync('isLiveLogin');
+			this.share = uni.getStorageSync('share');
+			this.scene = uni.getStorageSync('scene');
+			if (this.share && this.share.length > 0) {
+				this.liveId = this.share.liveId;
+				this.qrFrom =`&companyId=${this.share.companyId}&companyUserId=${this.share.companyUserId}`;
+				uni.removeStorageSync('share');
+			}
+			if (this.scene) {
+				const decodedScene = decodeURIComponent(this.scene);
+				const params = {};
+				decodedScene.split('&').forEach((item) => {
+					const [key, value] = item.split('=');
+					params[key] = value;
+					this.liveId = params.a;
+				});
+				if (params.b && params.c) {
+					this.qrFrom = `&companyId=${params.b}&companyUserId=${params.c}`;
+				}
+				uni.removeStorageSync('scene');
+			}
+
+			// 恢复播放和连接
+			await this.resumePageActivity();
+
+			// 恢复观看时长统计(如果之前已经开始统计)
+			if (this.watchStartTime > 0 || this.accumulatedWatchDuration > 0) {
+				this.resumeWatchDurationTracking();
+			}
+
+			// this.userinfo = JSON.parse(uni.getStorageSync('userInfo'));
+			this.userinfo = uni.getStorageSync('userinfo');
+			this.isAgreement = uni.getStorageSync('isAgreement');
+
+			this.$nextTick(() => {
+				this.setVideoProgress();
+			});
+			if (this.lookTimer) {
+				clearInterval(this.lookTimer);
+				this.lookTimer = null;
+				this.stayTime = 0;
+				this.startTime = 0;
+			}
+
+			// 启动内存监控,定期清理
+			this.startMemoryMonitor();
+			if (this.trafficTimer) {
+				clearInterval(this.trafficTimer);
+				this.trafficTimer = null;
+				this.startTime = 0;
+				this.totalTraffic = 0;
+			}
+			// 重置视频加载状态和流量计算开始时间
+			this.videoLoaded = false;
+			this.trafficStartTime = 0;
+			this.startTimer();
+			this.$nextTick(() => {
+				console.log(444, this.userInfo);
+				if (!this.userInfo || !this.userInfo.nickname) {
+					console.log('用户信息不完整,显示授权弹窗');
+					this.userlogo = true;
+					return;
+				}
+
+				// // 重新计算 isNow
+				// const isNowCalculated = dayjs(this.userInfo.updateTime).isSame(dayjs(), 'day');
+				// console.log('重新计算 isNow:', isNowCalculated);
+				// if (!isNowCalculated) {
+				//    console.log('不是今天更新过,显示授权弹窗');
+				// 	  this.userlogo = true;
+				// }
+				
+				setTimeout(() => {
+					this.videoContext = uni.createVideoContext(`myVideo_${this.liveId}`,
+						this);
+					console.log('videoContext 初始化完成:', this.videoContext);
+				}, 1000);
+			});
+		
+		},
+		//分享给好友
+		onShareAppMessage() {
+			return {
+				title: '邀请你来观看直播:' + this.liveItem.liveName,
+				path: '/pages_course/living?companyId=-2&companyUserId=' + this.userInfo.userId +
+					'&liveId=' + this.liveId,
+				imageUrl: '/static/logo.png',
+				success(res) {
+					console.log('分享成功', res);
+				},
+				fail(err) {
+					console.error('分享失败', err);
+				}
+			};
+		},
+
+		// 分享到朋友圈
+		onShareTimeline() {
+			return {
+				title: '邀请你来观看直播:' + this.liveItem.liveName,
+				query: 'companyId=-2&companyUserId=' + this.userInfo.userId + '&liveId=' + this.liveId
+			};
+		},
+		computed: {
+			shouldShowIntegralPopup() {
+				//只有当 showPoints 为 true 且 receiveList 有数据时才显示
+				return this.showPoints;
+			},
+			// 格式化后的倒计时
+			formattedCountdown() {
+				return this.formatCountdown(this.pointsRemainingTime);
+			},
+
+			// 倒计时百分比
+			countdownPercentage() {
+				return this.getCountdownPercentage();
+			},
+
+			// 环形进度条样式
+			circularStyle() {
+				const percentage = this.getCountdownPercentage();
+				const strokeDashoffset = 314 - (314 * percentage) / 100; // 2 * π * 50 = 314
+				return {
+					'--percentage': percentage + '%',
+					'--stroke-dashoffset': strokeDashoffset
+				};
+			},
+
+			// 是否显示倒计时
+			showCountdown() {
+				return !this.hasReachedTarget &&
+					this.liveItem?.liveType === 2 && // 只对录播显示
+					this.pointsRemainingTime > 0 && // 还有剩余时间
+					this.pointsRemainingTime < this.liveItem.duration * this.completionRate; // 已经开始计时
+			},
+		
+			// 控制是否显示非视频元素
+			shouldShowNonVideoElements() {
+				return !this.isFullscreen && this.showNonVideoElementsFlag;
+			},
+
+			// 控制是否显示全屏按钮
+			shouldShowFullscreenButton() {
+				return this.liveItem.showType == 1 && !this.isFullscreen;
+			},
+			...mapGetters(['coureLogin']),
+			appid() {
+				return this.$store.state.appid
+			},
+			// 观看人数
+			formattedWatchCount() {
+				return this.formatNumber(this.virtualHuman || 0);
+			},
+			//点赞人数
+			formattedLikeCount() {
+				return this.formatNumber(this.liveViewData.like || 0);
+			},
+			filteredViewers() {
+				// 获取3个随机假头像,而不是显示真实观众
+				const avatarCount = 3; // 需要显示的假头像数量
+
+				// 如果fakeAvatar数组为空或不存在,返回空数组
+				if (!this.fakeAvatar || !Array.isArray(this.fakeAvatar) || this.fakeAvatar.length === 0) {
+					return [];
+				}
+
+				// 从fakeAvatar中随机选择3个不同的头像
+				const randomAvatars = [];
+				const availableAvatars = [...this.fakeAvatar]; // 创建副本避免修改原数组
+
+				// 确保有足够的头像可选
+				if (availableAvatars.length < avatarCount) {
+					// 如果头像数量不足,可以重复使用
+					for (let i = 0; i < avatarCount; i++) {
+						const randomIndex = Math.floor(Math.random() * availableAvatars.length);
+						randomAvatars.push(availableAvatars[randomIndex]);
+					}
+				} else {
+					// 随机选择不重复的头像
+					for (let i = 0; i < avatarCount; i++) {
+						const randomIndex = Math.floor(Math.random() * availableAvatars.length);
+						randomAvatars.push(availableAvatars[randomIndex]);
+						availableAvatars.splice(randomIndex, 1); // 移除已选的头像,避免重复
+					}
+				}
+
+				console.log("随机选择的头像:", randomAvatars);
+				return randomAvatars;
+			},
+			isCurrentUserWon() {
+				if (!Array.isArray(this.prizeInfo) || !this.userInfo?.userId) {
+					return false;
+				}
+				return this.prizeInfo.some((item) => {
+					return String(item.userId) === String(this.userInfo.userId);
+				});
+			},
+			getCurrentUserPrizeProductId() {
+				if (!Array.isArray(this.prizeInfo) || !this.userInfo?.userId) {
+					return null;
+				}
+				// 在 prizeInfo 中查找当前用户的中奖记录
+				const userPrize = this.prizeInfo.find(item => {
+					return String(item.userId) == String(this.userInfo.userId);
+				});
+
+				// 返回商品ID,如果没有找到则返回null
+				return userPrize ? userPrize.productId : null;
+			},
+			getCurrentUserPrizeRecordId() {
+				if (!Array.isArray(this.prizeInfo) || !this.userInfo?.userId) {
+					console.log('条件不满足,返回null');
+					return null;
+				}
+				const userPrize = this.prizeInfo.find(item => {
+					const match = String(item.userId) == String(this.userInfo.userId);
+					return match;
+				});
+				return userPrize ? userPrize.recordId : null;
+			},
+			nameuser() {
+				return this.userInfo.nickname
+			},
+		},
+		onHide() {
+			this.updateWatchDuration(); //更新用户的看课时长
+			this.stopCountdown();
+			if (this.watchTimeTimer) {
+				clearInterval(this.watchTimeTimer);
+				this.watchTimeTimer = null;
+			}
+			this.saveWatchTime();
+			//  清除所有定时器
+			// this.clearAllTimersEnhanced();
+			// this.stopHeartBeat();
+			// 页面隐藏时,提交当前流量数据
+			if (this.videoLoaded && this.trafficStartTime && this.trafficTimer) {
+				const watchDuration = Math.floor((Date.now() - this.trafficStartTime) / 1000);
+				this.submitTraffic(watchDuration);
+			}
+			if (this.trafficTimer) {
+				clearInterval(this.trafficTimer);
+				this.trafficTimer = null;
+			}
+			// 暂停观看时长统计
+			this.pauseWatchDurationTracking();
+			// 页面隐藏时清理部分数据,减少内存占用
+			if (this.talklist && this.talklist.length > 20) {
+				// 只保留最新的20条消息
+				this.talklist = this.talklist.slice(-20);
+			}
+			// 触发垃圾回收
+			// this.triggerGarbageCollection();
+		},
+		onVideoStateChange(e) {  //废弃
+			// 这里可以根据视频状态控制倒计时
+			if (e.detail.code === 2004) { // 视频开始播放
+				//this.startCountdown();
+			} else if (e.detail.code === 2006) { // 视频播放结束
+				this.stopCountdown();
+			}
+		},
+		onUnload() {
+			
+			this.stopCountdown();
+			if (this.watchTimeTimer) {
+				clearInterval(this.watchTimeTimer);
+				this.watchTimeTimer = null;
+			}
+			this.saveWatchTime();
+			// 保存视频进度
+			this.saveVideoProgress();
+			// 停止观看时长统计
+			this.stopWatchDurationTracking();
+			// 用户退出时,再次请求一次10s流量接口
+			if (this.videoLoaded && this.trafficStartTime) {
+				const watchDuration = Math.floor((Date.now() - this.trafficStartTime) / 1000);
+				// 提交最后一次流量数据(至少10秒)
+				const finalDuration = Math.max(watchDuration, 10);
+				this.submitTraffic(finalDuration);
+			}
+			// 清理直播相关定时器
+			if (this.liveItem) {
+				this.pauseVideo();
+				// 清除直播间的时间定时器
+				if (this.liveItem.timeTimer) {
+					clearInterval(this.liveItem.timeTimer);
+					this.liveItem.timeTimer = null;
+				}
+			}
+
+			// 关闭WebSocket连接(会自动清理相关资源)
+			this.closeWebSocket(true);
+
+			// 清除 getliving 防抖定时器
+			if (this.getlivingTimer) {
+				clearTimeout(this.getlivingTimer);
+				this.getlivingTimer = null;
+			}
+
+			// 清除所有定时器(使用增强清理)
+			this.clearAllTimersEnhanced();
+
+			// 暂停视频
+			const videoId = `myVideo_${this.liveId}`;
+			const videoContext = uni.createVideoContext(videoId, this);
+			if (videoContext) {
+				videoContext.pause();
+			}
+			// 移除网络状态监听
+			try {
+				uni.offNetworkStatusChange();
+			} catch (err) {
+				console.warn('移除网络状态监听失败:', err);
+			}
+			// 清理大数据和状态
+			this.clearBigData();
+			this.resetAllStates();
+			// 解锁屏幕方向
+			this.unlockOrientation();
+			// 强制退出全屏
+			this.isFullscreen = false;
+			this.showCustomControls = true;
+		},
+
+		mounted() {
+			// 初始化系统信息缓存,避免在键盘监听器中重复调用同步API
+			this.systemInfo = uni.getSystemInfoSync();
+			console.log('系统信息:', this.systemInfo.platform, this.systemInfo.model);
+
+			this.getCurrentActivities();
+			this.getliveOrder();
+		},
+		watch: {
+			coureLogin: {
+				immediate: true, // 页面一进入就检查一次
+				handler(val) {
+					if (val == 2 && this.isLogin) {
+						this.isLogin = false
+						this.goLogin();
+					}
+				}
+			},
+			// 监听liveItem.status的变化
+			'liveItem.status': {
+				handler(newStatus, oldStatus) {
+					if (newStatus === undefined || oldStatus === undefined) return;
+					if (newStatus === oldStatus) return;
+					if (!this.liveId) {
+						console.warn('liveId不存在,无法触发getliving请求');
+						return;
+					}
+					// 状态变化时,调用getliving更新直播间数据
+					// 添加防抖,避免频繁请求
+					if (this.getlivingTimer) {
+						clearTimeout(this.getlivingTimer);
+					}
+					this.getlivingTimer = setTimeout(() => {
+						this.getliving(this.liveId);
+					}, 500); // 500ms 防抖
+				},
+				deep: true
+			},
+			// 监听orderUser.count的变化
+			'orderUser.count': {
+				handler(newVal, oldVal) {
+					if (newVal !== this.prevOrderCount) {
+						this.prevOrderCount = newVal;
+						this.showPurchaseMessage();
+					}
+				},
+				immediate: true
+			},
+			'isShowNotice': {
+				handler(newVal, oldVal) {
+					setTimeout(() => {
+						this.noticeHeightFun()
+					}, 800)
+				},
+				immediate: true
+			},
+			'notice.msg': {
+				handler(newVal, oldVal) {
+					// 添加空值检查
+					const newLength = newVal ? newVal.length : 0;
+					const oldLength = oldVal ? oldVal.length : 0;
+
+					if (newLength !== oldLength) {
+						setTimeout(() => {
+							this.noticeHeightFun()
+						}, 800)
+					}
+				},
+				deep: true
+			},
+		},
+		methods: {
+			// 查询当前用户当前直播间领取积分的剩余时长
+			getRemainingTime() {
+				if (!this.liveId) return;
+				const data = {liveId: this.liveId}
+				remainingTime(data).then((res) => {
+					if (res.code == 200) {
+						//this.pointsRemainingTime = res.data.remainingTime;
+						this.hasReceived = res.data.hasReceived;
+						this.videoDuration = res.data.videoDuration;
+						this.watchDuration = res.data.watchDuration; //停留时长
+						//this.completionRate= res.data.completionRate*0.01;//完课比例
+						console.log("查询当前用户当前直播间领取积分的剩余时长", res)
+					}
+				}).catch((error) => {
+
+				});
+			},
+
+			// 更新用户的看课时长 (传入直播间id和看课时长)
+			updateWatchDuration() {
+				if (!this.liveId) return;
+				if (this.isPreview) return;
+				//const watchDuration = Math.floor((Date.now() - this.liveBeginWatchTime) / 1000)
+				const watchDuration = this.totalWatchTime-this.watchDuration;
+				updateWatchDuration(this.liveId, watchDuration).then((res) => {
+					if (res.code == 200) {
+						console.log("更新用户的看课时长", res);
+						this.receivePoints();
+					}
+				}).catch((error) => {
+
+				});
+			},
+		
+			// 用户领取看课积分 (传入直播间id)
+			receivePoints(retryCount = 0) {
+				if (!this.liveId) return;
+				const data = {
+					liveId: this.liveId
+				}
+				receivePoints(data).then((res) => {
+					if (res.code == 200) {
+						console.log("用户领取看课积分", res);
+						//清除重试定时器
+						if (this.pointsRetryTimer) {
+							clearTimeout(this.pointsRetryTimer);
+							this.pointsRetryTimer = null;
+						}
+					}
+				}).catch((error) => {
+					console.log("用户领取积分失败error", error);
+					// 增加重试机制:最多重试3次
+					if (retryCount < 3) {
+						const delay = (retryCount + 1) * 2000; // 递增延迟: 2s, 4s, 6s
+						console.log(`领取积分失败,${delay}ms后进行第${retryCount + 1}次重试`);
+						if (this.pointsRetryTimer) {
+							clearTimeout(this.pointsRetryTimer);
+						}
+						this.pointsRetryTimer = setTimeout(() => {
+							this.receivePoints(retryCount + 1);
+						}, delay);
+					}
+				});
+			},
+
+			// ======================== 观看时长统计相关方法 ========================
+			/**
+			 * 开始观看时长统计
+			 * WebSocket连接成功后调用
+			 */
+			startWatchDurationTracking() {
+				// 防止重复启动
+				if (this.watchStartTime > 0) {
+					console.log('观看时长统计已启动,跳过');
+					return;
+				}
+				this.watchStartTime = Date.now();
+				this.isPageVisible = true;
+				console.log('开始观看时长统计', new Date(this.watchStartTime).toLocaleString());
+
+				// 启动页面可见性监听
+				this.initPageVisibilityListener();
+			},
+
+			/**
+			 * 获取当前累计观看时长(秒)
+			 * @returns {number} 观看时长(秒)
+			 */
+			getCurrentWatchDuration() {
+				if (this.watchStartTime === 0) {
+					return this.accumulatedWatchDuration;
+				}
+				// 如果页面可见,计算当前时段的时长
+				if (this.isPageVisible) {
+					const currentDuration = Math.floor((Date.now() - this.watchStartTime) / 1000);
+					return this.accumulatedWatchDuration + currentDuration;
+				}
+				// 页面不可见,返回累计时长
+				return this.accumulatedWatchDuration;
+			},
+
+			/**
+			 * 暂停观看时长统计(页面隐藏/后台时)
+			 */
+			pauseWatchDurationTracking() {
+				if (!this.isPageVisible || this.watchStartTime === 0) {
+					return;
+				}
+				// 累加本次观看的时长
+				const currentSessionDuration = Math.floor((Date.now() - this.watchStartTime) / 1000);
+				this.accumulatedWatchDuration += currentSessionDuration;
+				this.lastPauseTime = Date.now();
+				this.isPageVisible = false;
+				console.log(`暂停观看统计: 本次=${currentSessionDuration}秒, 累计=${this.accumulatedWatchDuration}秒`);
+			},
+
+			/**
+			 * 恢复观看时长统计(页面显示/前台时)
+			 */
+			resumeWatchDurationTracking() {
+				if (this.isPageVisible) {
+					return;
+				}
+				// 重新记录开始时间
+				this.watchStartTime = Date.now();
+				this.isPageVisible = true;
+				const pauseDuration = this.lastPauseTime > 0 ? Math.floor((Date.now() - this.lastPauseTime) /
+					1000) : 0;
+				console.log(`恢夏观看统计: 暂停了${pauseDuration}秒, 当前累计=${this.accumulatedWatchDuration}秒`);
+			},
+
+			/**
+			 * 停止观看时长统计
+			 */
+			stopWatchDurationTracking() {
+				if (this.isPageVisible && this.watchStartTime > 0) {
+					const currentSessionDuration = Math.floor((Date.now() - this.watchStartTime) / 1000);
+					this.accumulatedWatchDuration += currentSessionDuration;
+				}
+				console.log(`停止观看统计: 总时长=${this.accumulatedWatchDuration}秒`);
+				// 重置状态
+				this.watchStartTime = 0;
+				this.isPageVisible = true;
+				this.lastPauseTime = 0;
+				// 移除监听
+				this.removePageVisibilityListener();
+			},
+
+			/**
+			 * 初始化页面可见性监听
+			 */
+			initPageVisibilityListener() {
+				// uni-app 的页面生命周期已经在 onShow/onHide 中处理
+				// 这里主要监听小程序的前后台切换
+				uni.onAppShow(() => {
+					console.log('小程序回到前台');
+					this.resumeWatchDurationTracking();
+				});
+
+				uni.onAppHide(() => {
+					console.log('小程序切换到后台');
+					this.pauseWatchDurationTracking();
+				});
+			},
+
+			/**
+			 * 移除页面可见性监听
+			 */
+			removePageVisibilityListener() {
+				// uni-app 不需要手动移除监听,生命周期自动管理
+				console.log('页面可见性监听已移除');
+			},
+			/**
+			 * 计算当前时间与目标时间的差值(秒)
+			 */
+			calculateLiveTimeDiff(timeStr) {
+				  // 0. 安全校验:防止 undefined/null 导致 crash
+				  if (!timeStr) {
+					  return 0;
+				  }
+				  // 1. 获取当前时间戳(毫秒)
+				  const now = Date.now();
+				  // 3. 【关键】解决 iOS 兼容性问题
+				  // iOS 系统不支持 "2025-12-25" 这种带横杠的格式,需要替换为斜杠 "2025/12/25"
+				  const safeTimeStr = String(timeStr).replace(/-/g, '/');
+				  // 4. 解析目标时间戳(毫秒)
+				  const liveStartTime = Date.parse(safeTimeStr);
+				  // 5. 计算差值(毫秒 -> 秒)
+				  // 结果为:当前时间 - 直播开始时间
+				  const diffInSeconds = Math.floor((now - liveStartTime) / 1000);
+				  return diffInSeconds;
+			},
+			// 根据开始时间和时长计算结束时间
+			calculateLiveEndTime(startTime, duration) {
+				if (!startTime) return '';
+				// 兼容 iOS 时间格式
+				const safeStartTime = String(startTime).replace(/-/g, '/');
+				const startDate = new Date(safeStartTime);
+				if (isNaN(startDate.getTime())) return '';
+				// 计算结束时间戳
+				const endTimeMs = startDate.getTime() + (Number(duration) * 1000);
+				const endDate = new Date(endTimeMs);
+				// 格式化
+				const year = endDate.getFullYear();
+				const month = this.padZero(endDate.getMonth() + 1);
+				const day = this.padZero(endDate.getDate());
+				const hours = this.padZero(endDate.getHours());
+				const minutes = this.padZero(endDate.getMinutes());
+				const seconds = this.padZero(endDate.getSeconds());
+				return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+			},
+			// 开始倒计时
+			startCountdown() {
+				this.isCountdownActive = true;
+				this.countdownTimer = setInterval(() => {
+					this.updateCountdown();
+				}, 1000); // 每秒更新一次
+			},
+			// 更新倒计时
+			updateCountdown() {
+				if(!this.liveItem){
+					return;
+				}
+				this.completionTime=this.liveItem.duration * this.completionRate;
+				//console.log("qxj watchDuration:"+this.watchDuration+" completionTime:"+this.completionTime+" pointsRemainingTime:"+this.pointsRemainingTime);
+				//console.log(`qxj countdownPercentage=${this.countdownPercentage} completionPointsEnabled=${this.liveItem.completionPointsEnabled} receiveStatus=${this.receiveStatus} liveItemStatus=${this.liveItem.status} hasReceived=${this.hasReceived} isPreview=${this.isPreview}`);
+				if(this.watchDuration>this.completionTime){  //已达成观看时间
+					if (this.countdownTimer) {
+						clearInterval(this.countdownTimer);
+						this.countdownTimer = null;
+						this.isPreview=true;
+						return;
+					}
+				}
+				if (this.pointsRemainingTime <0) {
+					this.stopCountdown();
+					return;
+				}
+				this.showPoints=false;
+				this.diffLiveStartTime=this.calculateLiveTimeDiff(this.liveItem.startTime);
+				this.diffLiveEndTime=this.calculateLiveTimeDiff(this.liveItem.startTime)-this.liveItem.duration;
+				if(!this.liveItem.finishTime){
+					this.liveItem.finishTime=this.calculateLiveEndTime(this.liveItem.startTime,this.liveItem.duration); //得出首播结束时间
+				}
+			    //console.log("qxj updateCountdown diffLiveStartTime:"+this.diffLiveStartTime+" diffLiveEndTime:"+this.diffLiveEndTime+" liveBeginWatchTime:"+this.liveBeginWatchTime+" diffReplayGenerationSeconds:"+this.diffReplayGenerationSeconds);
+				if(this.diffLiveStartTime<0){  //预告状态
+				    this.isPreview=true;
+					return;
+				}
+				if(this.diffLiveStartTime>=0){   
+				    if(this.diffLiveEndTime>=0){   //回放文件生成中
+						if(this.diffLiveEndTime<=180){
+							this.isPreview=false;
+							this.pointsRemainingTime = Math.max(0, this.completionTime - this.totalWatchTime);
+							this.diffReplayGenerationSeconds++; //经历回放生成的秒数
+							this.hasReplayGeneration=true;
+							return;
+						}
+						else{  
+						    if(this.hasReplayGeneration){  //经历过回放生成 回放生成后扣减掉经历回放生成的时间
+								this.totalWatchTime=this.watchDuration+Math.floor((Date.now() - this.liveBeginWatchTime) / 1000)-this.diffReplayGenerationSeconds;//累计观看的总时长
+							}else{ //进入直播间时已过回放生成中
+								this.totalWatchTime=this.watchDuration+Math.floor((Date.now() - this.liveBeginWatchTime) / 1000);//累计观看的总时长
+							}
+						}	 
+					}else{
+						this.totalWatchTime=this.watchDuration+Math.floor((Date.now() - this.liveBeginWatchTime) / 1000); //累计观看的总时长
+					}
+				}
+				//console.log("qxj直播中 completionTime:"+this.completionTime+" totalWatchTime:"+this.totalWatchTime+" pointsRemainingTime:"+this.pointsRemainingTime+" watchDuration:"+this.watchDuration+", liveBeginWatchTime:"+this.liveBeginWatchTime);
+				if(this.totalWatchTime>=this.completionTime){  //积分领取满足条件
+					if (this.countdownTimer) {
+						clearInterval(this.countdownTimer);
+						this.countdownTimer=null;
+						this.onCountdownComplete();
+						return;
+					}
+				}
+				
+				if(this.diffLiveStartTime>=0){ 
+					 this.isPreview=false;
+					 if(this.diffLiveEndTime<0){    //直播中状态
+					     this.pointsRemainingTime = Math.max(0, this.completionTime - this.totalWatchTime);
+					 }
+					 if(this.diffLiveEndTime>180){    //直播回放中
+					 	this.pointsRemainingTime = Math.max(0, this.completionTime - this.totalWatchTime);			 	  
+					 }
+				}
+				// 更新显示
+				this.updateCountdownDisplay();
+			},
+
+			// 停止倒计时
+			stopCountdown() {
+				if (this.countdownTimer) {
+					clearInterval(this.countdownTimer);
+					this.countdownTimer = null;
+				}
+				this.isCountdownActive = false;
+				this.updateWatchDuration();
+				//this.saveWatchProgress(); // 立即保存
+			},
+
+			// 倒计时完成
+			onCountdownComplete() {
+				console.log('倒计时完成!');
+				this.stopCountdown();
+				this.pointsRemainingTime = -1;
+				this.updateCountdownDisplay();
+				this.triggerWatchComplete();
+				uni.showToast({title:"完课积分已到账",duration:5000,icon:"none"});
+				//this.showPoints=true;
+			},
+
+			// 触发观看完成事件
+			async triggerWatchComplete() {
+				if (!this.userInfo?.userId || !this.liveId) return;
+				try {
+					// 这里可以调用API通知服务器用户已完成观看
+					console.log('用户已完成观看');
+					// 清空进度,防止重复计算
+					uni.removeStorageSync(this.watchProgressKey);
+				} catch (error) {
+					console.error('触发观看完成事件失败:', error);
+				}
+			},
+			
+			// 补零函数
+			padZero(num) {
+				return num < 10 ? `0${num}` : num.toString();
+			},
+			
+			// 倒计时格式化函数
+			formatCountdown(seconds) {
+				// 1. 先校验输入:确保是有效正整数,避免负数/非数字导致计算错误
+				const totalSeconds = Math.max(0, Math.floor(Number(seconds) || 0));
+				// 2. 重新梳理计算逻辑(核心修复)
+				const hours = Math.floor(totalSeconds / 3600);
+				const remainingAfterHours = totalSeconds % 3600; // 小时取余后剩余的秒数
+				const minutes = Math.floor(remainingAfterHours / 60);
+				const secs = remainingAfterHours % 60;
+				// 3. 返回格式化结果(补零+原始值)
+				return {
+					hours: this.padZero(hours),
+					minutes: this.padZero(minutes),
+					seconds: this.padZero(secs),
+					total: totalSeconds // 确保total是处理后的有效数值
+				};
+			},
+			getCountdownPercentage() {
+				// 1. 使用倒计时的 remainingTime 计算进度
+				if (!this.getRemainingTime) {
+					console.log('进度条计算:liveItem.duration无效', this.liveItem?.duration);
+					return 0;
+				}
+				// 2. 计算目标观看时间(90%的总时长)
+				// const targetWatchTime = this.liveItem.duration * this.completionRate;
+				// 3. 如果已经达到目标,直接返回100%
+				if (this.hasReachedTarget || this.pointsRemainingTime <= 0) {
+					return 100;
+				}
+				// remainingTime = 剩余需要观看的时间
+				// 已观看时间 = 总目标时间 - 剩余时间
+				const watchedTime = this.videoDuration - this.pointsRemainingTime;
+				// 5. 确保数值有效
+				if (watchedTime <= 0) {
+					return 0;
+				}
+				// 6. 计算百分比(已观看时间 / 目标时间)
+				const percentage = (watchedTime / this.videoDuration) * 100;
+				// 7. 限制在 0-100 范围内
+				return Math.min(100, Math.max(0, percentage));
+			},
+			// 更新倒计时显示(如果需要强制更新视图)
+			updateCountdownDisplay() {
+				// 如果需要,可以在这里触发视图更新
+				this.$forceUpdate();
+			},
+			// 初始化观看时间
+			initWatchTime() {
+				// 创建基于用户ID和直播ID的存储键
+				const userId = this.userInfo?.userId || 'anonymous';
+				this.watchTimeStorageKey = `watchTime_${userId}_${this.liveId}`;
+				// 从本地存储加载累计观看时间
+				try {
+					const storedTime = uni.getStorageSync(this.watchTimeStorageKey);
+					this.totalWatchTime = storedTime ? parseInt(storedTime) : 0;
+					console.log(`加载累计观看时间: ${this.totalWatchTime}秒`);
+				} catch (error) {
+					console.error('加载观看时间失败:', error);
+					this.totalWatchTime = 0;
+				}
+			},
+
+			//保存观看时间到本地存储
+			saveWatchTime() {
+				if (!this.watchTimeStorageKey) return;
+				try {
+					uni.setStorageSync(this.watchTimeStorageKey, this.totalWatchTime);
+					console.log(`保存观看时间: ${this.totalWatchTime}秒`);
+				} catch (error) {
+					console.error('保存观看时间失败:', error);
+				}
+			},
+
+			// 格式化显示时间
+			formatWatchTime(seconds) {
+				const hours = Math.floor(seconds / 3600);
+				const minutes = Math.floor((seconds % 3600) / 60);
+				const secs = seconds % 60;
+				return {
+					hours: this.padZero(hours),
+					minutes: this.padZero(minutes),
+					seconds: this.padZero(secs),
+					total: seconds
+				};
+			},
+
+			// // 获取用户未领取的积分列表
+			// completionUnreceived() {
+			// 	if (!this.liveId) return;
+			// 	const data = {
+			// 		liveId: this.liveId
+			// 	}
+			// 	completionUnreceived(data).then((res) => {
+			// 		if (res.code == 200) {
+			// 			console.log("获取用户未领取的积分列表", res)
+			// 			if (res.data) {
+			// 				this.receiveList = res.data
+			// 				this.showPoints = true
+			// 			}
+			// 		}
+			// 	}).catch((error) => {});
+			// },
+
+			// 领取完课积分
+			// completionReceive(item) {
+			// 	if (!item.id) return;
+			// 	completionReceive(item.id).then((res) => {
+			// 		if (res.code == 200) {
+			// 			this.showPoints = false
+			// 			console.log("领取完课积分", res)
+			// 			uni.showToast({
+			// 				title: '领取积分成功',
+			// 				icon: 'none'
+			// 			});
+			// 		}
+			// 	}).catch((error) => {});
+			// },
+
+			noticeHeightFun() {
+				const query = uni.createSelectorQuery().in(this);
+				query.select('.notice-message').boundingClientRect(rect => {
+					if (rect) {
+						this.commonViewHeight = rect.height;
+						this.forceScrollToBottomOnSend();
+					} else {
+						this.commonViewHeight = ''
+					}
+				}).exec();
+			},
+			// 获取胶囊按钮布局参数
+			getMenuButtonInfo() {
+				// 微信小程序API(Uniapp可直接用uni.getMenuButtonBoundingClientRect)
+				const menuBtn = uni.getMenuButtonBoundingClientRect();
+				if (menuBtn) {
+					this.menuButtonInfo = {
+						top: menuBtn.top + 'px', // 胶囊顶部距离
+						height: menuBtn.height + 'px', // 胶囊高度
+						centerY: (menuBtn.top + menuBtn.height / 2) + 'px', // 胶囊垂直居中Y坐标
+						right: menuBtn.right + 'px' // 胶囊右侧距离
+					};
+				}
+			},
+			// 退出全屏
+			exitFullscreen() {
+				console.log('执行退出全屏');
+				this.isFullscreen = false;
+
+				// 恢复竖屏样式
+				this.restoreVideoList();
+
+				// 显示非videolist元素
+				this.showNonVideoElements();
+
+				// 强制页面重排
+				this.$forceUpdate();
+			},
+			// 添加屏幕方向变化监听
+			addOrientationChangeListener() {
+				if (window.addEventListener) {
+					window.addEventListener('orientationchange', this.handleOrientationChange);
+				}
+			},
+
+			// 移除屏幕方向变化监听
+			removeOrientationChangeListener() {
+				if (window.removeEventListener) {
+					window.removeEventListener('orientationchange', this.handleOrientationChange);
+				}
+			}, // 处理屏幕方向变化
+			handleOrientationChange() {
+				uni.onWindowResize((res) => {
+					const windowWidth = res.size.windowWidth;
+					const windowHeight = res.size.windowHeight;
+					const isLandscape = windowWidth > windowHeight;
+
+					if (this.isFullscreen && !isLandscape) {
+						console.log('全屏状态下屏幕方向不正确,尝试退出全屏');
+						if (this.videoContext) {
+							this.videoContext.exitFullScreen();
+						}
+					}
+				});
+			}, // 恢复videolist盒子
+			restoreVideoList() {
+				this.isVideoRotated = false;
+				this.isFullscreen = false;
+				console.log('恢复视频容器竖屏状态');
+			},
+			// 强制横屏全屏(备用方案)
+			forceLandscapeFullscreen() {
+				// 尝试多种全屏方式
+				try {
+					// 方案1: 使用video的requestFullScreen
+					if (this.videoContext) {
+						this.videoContext.requestFullScreen({
+							direction: 90
+						});
+						return true;
+					}
+				} catch (e) {
+					console.log('方案1失败:', e);
+				}
+
+				try {
+					// 方案2: 尝试DOM全屏API
+					const videoElement = document.getElementById(`myVideo_${this.liveId}`);
+					if (videoElement && videoElement.requestFullscreen) {
+						videoElement.requestFullscreen();
+						return true;
+					}
+				} catch (e) {
+					console.log('方案2失败:', e);
+				}
+
+				try {
+					// 方案3: 使用Web API全屏
+					if (document.documentElement.requestFullscreen) {
+						document.documentElement.requestFullscreen();
+						return true;
+					}
+				} catch (e) {
+					console.log('方案3失败:', e);
+				}
+
+				console.log('所有全屏方案都失败了');
+				uni.showToast({
+					title: '无法全屏播放,请尝试手动横屏',
+					icon: 'none'
+				});
+				return false;
+			},
+			// 切换全屏
+			toggleFullscreen() {
+				console.log('自定义全屏按钮被点击');
+				if (this.isFullscreen) {
+					// 退出全屏
+					this.exitFullscreen();
+				} else {
+					// 进入全屏
+					this.enterFullscreen();
+				}
+			}, // 进入全屏
+			enterFullscreen() {
+				console.log('执行进入全屏');
+				this.isFullscreen = true;
+				// 设置横屏样式
+				this.rotateVideoList();
+
+				// 隐藏非videolist元素
+				this.hideNonVideoElements();
+
+				// 强制页面重排
+				this.$forceUpdate();
+			},
+			// 强制全屏的备用方案
+			forceFullscreen() {
+				console.log('使用备用方案进入全屏');
+				const videoId = `myVideo_${this.liveId}`;
+				// 在小程序中,只能使用 videoContext
+				if (this.videoContext) {
+					try {
+						this.videoContext.requestFullScreen({
+							direction: 90 // 横屏方向
+						});
+					} catch (error) {
+						console.error('请求全屏失败:', error);
+						uni.showToast({
+							title: '无法全屏播放,请尝试手动横屏',
+							icon: 'none'
+						});
+					}
+				}
+			}, // 隐藏非videolist元素
+			hideNonVideoElements() {
+				this.showNonVideoElementsFlag = false;
+				console.log('隐藏非视频元素');
+			},
+			// 显示非videolist元素
+			showNonVideoElements() {
+				this.showNonVideoElementsFlag = true;
+				console.log('显示非视频元素');
+			},
+			// 旋转videolist盒子
+			rotateVideoList() {
+				// 在小程序中,通过设置CSS类名来控制样式,而不是直接操作DOM
+				this.isVideoRotated = true;
+				this.isFullscreen = true;
+				console.log('视频容器旋转到横屏状态');
+			},
+			// 全屏状态变化监听
+			onFullscreenChange(e) {
+				console.log('全屏状态变化事件详情:', e);
+				// 方法1:通过事件参数获取(小程序主要方式)
+				let fullScreen = false;
+				// 视频组件的全屏事件参数
+				if (e.detail && typeof e.detail.fullScreen !== 'undefined') {
+					fullScreen = e.detail.fullScreen;
+					console.log('通过e.detail.fullScreen获取全屏状态:', fullScreen);
+				}
+				// 其他可能的参数名
+				else if (e.detail && typeof e.detail.fullscreen !== 'undefined') {
+					fullScreen = e.detail.fullscreen;
+					console.log('通过e.detail.fullscreen获取全屏状态:', fullScreen);
+				} else {
+					// 在小程序环境中,可以通过屏幕方向判断
+					try {
+						const systemInfo = uni.getSystemInfoSync();
+						fullScreen = systemInfo.windowWidth > systemInfo.windowHeight;
+						console.log('通过屏幕方向判断全屏状态:', fullScreen);
+					} catch (err) {
+						console.error('获取系统信息失败:', err);
+						// 默认使用事件参数
+						fullScreen = e.detail || false;
+					}
+				}
+
+				this.isFullscreen = fullScreen;
+				console.log('最终设置isFullscreen为:', this.isFullscreen);
+
+				// 根据全屏状态显示/隐藏自定义控件
+				this.showCustomControls = !this.isFullscreen;
+
+				// 强制UI更新
+				this.$forceUpdate();
+
+				// 全屏时锁定横屏
+				if (this.isFullscreen) {
+					this.lockOrientation();
+				} else {
+					this.unlockOrientation();
+				}
+			},
+			// 锁定屏幕方向为横屏
+			lockOrientation() {
+				// 设置屏幕方向为横屏
+				try {
+					// 尝试锁定横屏
+					plus.screen.lockOrientation('landscape-primary');
+				} catch (e) {
+					console.log('锁定屏幕方向失败:', e);
+					// 备用方案
+					try {
+						// 使用 Web API(如果支持)
+						if (screen.orientation && screen.orientation.lock) {
+							screen.orientation.lock('landscape');
+						}
+					} catch (err) {
+						console.log('备用方案也失败了:', err);
+					}
+				}
+			}, // 解锁屏幕方向
+			unlockOrientation() {
+				try {
+					if (screen.orientation && screen.orientation.unlock) {
+						screen.orientation.unlock();
+					}
+				} catch (err) {
+					console.log('备用解锁方案也失败了:', err);
+				}
+			},
+
+			shouquan() {
+				if (this.user.nickname == '') {
+					uni.showToast({
+						icon: 'none',
+						title: "请先授权微信昵称",
+					});
+				}
+			},
+			confimrname() {
+				if (this.user.nickname == '') {
+					uni.showToast({
+						icon: 'none',
+						title: "请授权微信昵称",
+					});
+					return
+				}
+				this.editUser();
+				uni.setStorageSync('userInfo', this.userInfo);
+				this.userlogo = false;
+			},
+
+			editUser() {
+				this.user.nickName = this.user.nickname;
+				editUser(this.user).then(
+					res => {
+						if (res.code == 200) {
+							uni.showToast({
+								icon: 'success',
+								title: "修改成功",
+							});
+							this.getUserInfo()
+						} else {
+							uni.showToast({
+								icon: 'none',
+								title: res.msg,
+							});
+						}
+					},
+					rej => {}
+				);
+			},
+
+			onNickNameInput(e) {
+				console.log(e)
+				this.user.nickname = e.detail.value
+			},
+			async haveLogin() {
+				// 防止重复执行
+				if (this.isOnload) {
+					return;
+				}
+				this.userInfo = uni.getStorageSync('userInfo');
+				if (this.userInfo) {
+					await this.getUserInfo();
+				}
+				if (this.liveId) {
+					// 优先加载直播间信息(包含视频资源URL)
+					this.isOnload = true;
+					await this.getliving(this.liveId);
+					// await this.getLiveMsg(this.liveItem);
+					// await this.getliveViewData();
+					// 然后加载其他数据(并行执行,不阻塞视频加载)
+					Promise.all([
+						this.getLiveMsg(this.liveItem),
+						this.getliveViewData()
+					]).catch(err => {
+						console.error('加载数据失败:', err);
+					});
+					// 其他非关键数据异步加载
+					this.getCurrentActivities();
+					this.getliveOrder();
+					this.initSocket();
+				}
+			},
+			// 静默登录
+			goLogin(data) {
+				let provider = 'weixin'
+				uni.login({
+					provider: provider,
+					success: async loginRes => {
+						uni.getUserInfo({
+							provider: provider,
+							success: (infoRes) => {
+								uni.showToast({
+									title: '登录中...',
+									icon: 'loading'
+								});
+								loginByMp({
+									code: loginRes.code,
+									encryptedData: infoRes.encryptedData,
+									iv: infoRes.iv,
+									appId: this.appid
+								}).then(res => {
+									uni.hideLoading();
+									if (res.code == 200) {
+										uni.setStorageSync('AppToken', res
+											.token);
+										uni.setStorageSync('userInfo', JSON
+											.stringify(res
+												.user));
+										this.userInfo = uni.getStorageSync(
+											'userInfo');
+										// uni.setStorageSync('auto_userInfo', JSON.stringify(res.user));
+										// this.user = res.user
+										this.$store.commit('setCoureLogin', 1);
+										this.isLogin = true
+										this.haveLogin()
+										this.userlogo = true
+										// console.log("TOKEN_KEYAuto",TOKEN_KEYAuto)
+										if (this.urlOption.qwUserId) {
+											this.getIsAddKf() //this.getIsAddKf()
+										}
+									} else {
+										uni.showToast({
+											title: res.msg,
+											icon: 'none'
+										});
+									}
+								}).catch(err => {
+									uni.hideLoading();
+									uni.showToast({
+										icon: 'none',
+										title: "登录失败,请重新登录",
+									});
+								});
+							}
+						});
+					}
+				})
+			},
+			// liveWatchUser(){
+			// 	var data={
+			// 		qwUserId:this.urlOption.qwUserId,
+			// 		liveId:this.urlOption.liveId,
+			// 		userId:this.userInfo.userId,
+			// 		corpId:this.urlOption.corpId,
+			// 		companyUserId:this.urlOption.companyUserId,
+			// 		qwExternalId:this.urlOption.qwExternalId,
+			// 		companyId:this.urlOption.companyId,
+			// 		chatId:this.urlOption.chatId,
+			// 	}
+			// 	liveWatchUser(data).then(
+			// 		res => {
+			// 			if (res.code == 200) {
+
+			// 			} else {
+			// 				uni.showToast({
+			// 					icon: 'none',
+			// 					title: res.msg,
+			// 				});
+			// 			}
+			// 		},
+			// 		rej => {}
+			// 	);
+			// },
+			// 客服
+			getIsAddKf() {
+				// {videoId: this.videoId,qwUserId: this.qwUserId,corpId: this.corpId}
+				getIsAddKf(this.urlOption).then(res => {
+						if (res.code == 200) {
+							this.isAddKf = 1
+							this.qwCode = true
+							//this.getH5CourseVideoDetails()
+						} else if (res.code == 401) {
+							this.isAddKf = 0
+							this.goLogin();
+						} else {
+							this.qwCode = false
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+						}
+					},
+					err => {}
+				);
+			},
+			clickTabs(item) {},
+			getLocationByIP() {
+				// 防止重复请求
+				if (this.hasLoadedLocation) {
+					return;
+				}
+				this.hasLoadedLocation = true;
+				// 高德IP定位API,需要替换成你的key
+				const key = '4e13632be0cc278f56825919603c07cf';
+				uni.request({
+					url: `https://restapi.amap.com/v3/ip?key=${key}`,
+					method: 'GET',
+					success: (res) => {
+						if (res.data && res.data.status === '1') {
+							// 返回数据格式:{ province: '广东省', city: '深圳市', ... }
+							// ${res.data.city}
+							this.location = `${res.data.province} `;
+							this.address = this.location
+							console.log('用户所在地:', this.location);
+						} else {
+							console.error('获取位置失败:', res.data);
+							this.hasLoadedLocation = false; // 失败后允许重试
+						}
+					},
+					fail: (err) => {
+						console.error('请求失败:', err);
+						this.hasLoadedLocation = false; // 失败后允许重试
+					}
+				});
+			},
+			formatNumber(num) {
+				if (typeof num !== 'number') {
+					num = Number(num) || 0;
+				}
+				if (num < 10000) {
+					return num.toString();
+				}
+				// 处理万以上的数字
+				const wan = num / 10000;
+				if (wan < 10) {
+					// 1万-10万之间,保留2位小数
+					const rounded = Math.round(wan * 100) / 100;
+					return rounded.toFixed(2).replace(/\.?0+$/, '') + 'w';
+				} else if (wan < 10000) {
+					// 10万-1亿之间,保留1位小数
+					const rounded = Math.round(wan * 10) / 10;
+					return rounded.toFixed(1).replace(/\.0$/, '') + 'w';
+				} else {
+					// 1亿以上,转换为亿单位
+					const yi = wan / 10000;
+					const rounded = Math.round(yi * 100) / 100;
+					return rounded.toFixed(2).replace(/\.?0+$/, '') + '亿';
+				}
+			},
+			// 重置所有状态
+			resetAllStates() {
+				this.liveUserCalled = false;
+				this.talklist = [];
+				this.liveViewersData = [];
+				this.liveViewers = [];
+				this.products = [];
+				this.liveItem = [];
+
+				// 重置WebSocket相关状态
+				this.isSocketOpen = false;
+				this.isConnecting = false;
+				this.isManualClose = true;
+				this.reconnectCount = 0;
+				this.heartBeatRetryCount = 0;
+				this.lastHeartBeatTime = 0;
+				this.adaptiveHeartBeatInterval = this.heartBeatInterval;
+				this.isNetworkAvailable = true;
+				this.networkType = 'unknown';
+
+				// 重置性能监控数据
+				this.connectionStartTime = 0;
+				this.connectionLatency = 0;
+				this.messageCount = 0;
+				this.errorCount = 0;
+				this.lastPerformanceCheck = 0;
+			},
+
+			// 获取WebSocket性能统计
+			getWebSocketPerformanceStats() {
+				const now = Date.now();
+				const uptime = this.connectionStartTime > 0 ? now - this.connectionStartTime : 0;
+				return {
+					connectionLatency: this.connectionLatency,
+					uptime: uptime,
+					messageCount: this.messageCount,
+					errorCount: this.errorCount,
+					errorRate: this.messageCount > 0 ? (this.errorCount / this.messageCount * 100).toFixed(2) : 0,
+					messagesPerSecond: uptime > 0 ? (this.messageCount / (uptime / 1000)).toFixed(2) : 0,
+					networkType: this.networkType,
+					isConnected: this.isSocketAvailable(),
+					reconnectCount: this.reconnectCount
+				};
+			},
+
+			// 定期检查性能并输出统计信息
+			performanceCheck() {
+				const now = Date.now();
+				// 每5分钟输出一次性能统计
+				if (now - this.lastPerformanceCheck > 300000) { // 5分钟
+					const stats = this.getWebSocketPerformanceStats();
+					console.log('WebSocket性能统计:', stats);
+					this.lastPerformanceCheck = now;
+					// 如果错误率过高,记录警告
+					if (stats.errorRate > 10) {
+						console.warn(`WebSocket错误率过高: ${stats.errorRate}%`);
+					}
+					// 如果连接延迟过高,记录警告
+					if (stats.connectionLatency > 5000) {
+						console.warn(`WebSocket连接延迟过高: ${stats.connectionLatency}ms`);
+					}
+				}
+			},
+			// 定期清理视频缓存
+			startVideoCacheCleanup() {
+				if (this.videoCleanupTimer) {
+					clearInterval(this.videoCleanupTimer);
+				}
+				// 每30秒清理一次视频缓存
+				this.videoCleanupTimer = setInterval(() => {
+					this.cleanupVideoCache();
+				}, 30000);
+			},
+			// 清理视频缓存
+			cleanupVideoCache() {
+				if (!this.liveItem || !this.liveId) return;
+
+				// 只对录播视频进行清理
+				if (this.liveItem.liveType === 2 && this.liveItem.videoUrl) {
+					this.reloadVideoPlayer();
+				}
+			},
+			// 重新加载视频播放器
+			reloadVideoPlayer() {
+				const videoId = `myVideo_${this.liveId}`;
+				const videoContext = uni.createVideoContext(videoId, this);
+
+				if (videoContext) {
+					const currentTime = this.videoCurrentTime;
+					// 暂停视频
+					videoContext.pause();
+					// 延迟重新加载
+					setTimeout(() => {
+						// 重新设置视频源,强制清理缓存
+						this.$set(this.liveItem, 'videoUrl', this.liveItem.videoUrl + '&t=' + Date.now());
+
+						// 恢复播放位置
+						setTimeout(() => {
+							if (videoContext.seek) {
+								videoContext.seek(currentTime);
+							}
+							videoContext.play();
+						}, 500);
+					}, 100);
+				}
+			},
+			// 启动内存监控
+			startMemoryMonitoring() {
+				if (this.memoryMonitorTimer) {
+					clearInterval(this.memoryMonitorTimer);
+				}
+				this.memoryMonitorTimer = setInterval(() => {
+					this.checkMemoryUsage();
+				}, 15000); // 每15秒检查一次
+			},
+
+
+			// 检查内存使用情况
+			checkMemoryUsage() {
+				try {
+					// 检查定时器数量
+					const timerCount = this.getActiveTimerCount();
+					if (timerCount > 10) {
+						console.warn(`检测到过多定时器: ${timerCount}个,可能存在内存泄漏`);
+						this.cleanupUnusedTimers();
+					}
+
+					// 检查消息队列长度
+					if (this.messageQueue && this.messageQueue.length > 100) {
+						console.warn(`消息队列过长: ${this.messageQueue.length}条,清理旧消息`);
+						this.messageQueue = this.messageQueue.slice(-50); // 只保留最新50条
+					}
+
+					// 检查用户颜色缓存
+					if (this.userRandomColors && Object.keys(this.userRandomColors).length > 500) {
+						console.warn('用户颜色缓存过大,清理部分缓存');
+						const keys = Object.keys(this.userRandomColors);
+						const keysToRemove = keys.slice(0, keys.length - 200); // 只保留最新200个
+						keysToRemove.forEach(key => delete this.userRandomColors[key]);
+					}
+
+					// 定期触发垃圾回收
+					if (Date.now() - this.lastPerformanceCheck > 60000) { // 每分钟一次
+						this.triggerGarbageCollection();
+						this.lastPerformanceCheck = Date.now();
+					}
+				} catch (error) {
+					console.error('内存检查失败:', error);
+				}
+			},
+
+
+
+			// 强制内存清理
+			forceMemoryCleanup() {
+				console.log('执行强制内存清理');
+
+				// 1. 清理视频播放器
+				this.cleanupVideoPlayer();
+
+				// 2. 清理大数据
+				this.clearBigData();
+
+				// 3. 强制垃圾回收(在支持的环境下)
+				this.triggerGarbageCollection();
+			},
+			// 清理视频播放器
+			cleanupVideoPlayer() {
+				const videoId = `myVideo_${this.liveId}`;
+				const videoContext = uni.createVideoContext(videoId, this);
+				if (videoContext) {
+					// 停止播放
+					videoContext.stop();
+					// 重置视频源
+					setTimeout(() => {
+						this.$set(this.liveItem, 'videoUrl', '');
+						setTimeout(() => {
+							this.$set(this.liveItem, 'videoUrl', this.getFreshVideoUrl());
+							this.playVideo();
+						}, 500);
+					}, 100);
+				}
+			},
+			// 获取带时间戳的新视频URL
+			getFreshVideoUrl() {
+				if (!this.liveItem.originalVideoUrl) {
+					this.liveItem.originalVideoUrl = this.liveItem.videoUrl;
+				}
+				// 添加时间戳参数,避免缓存
+				const separator = this.liveItem.originalVideoUrl.includes('?') ? '&' : '?';
+				return this.liveItem.originalVideoUrl + separator + 't=' + Date.now();
+			},
+			// 清理大数据
+			clearBigData() {
+				// 清理聊天记录,只保留最近50条
+				if (this.talklist.length > 50) {
+					this.talklist = this.talklist.slice(-50);
+				}
+				// 清理虚拟数据
+				if (this.liveViewers.length > 100) {
+					this.liveViewers = this.liveViewers.slice(-100);
+				}
+				// 清理商品数据
+				if (this.products.length > 50) {
+					this.products = this.products.slice(0, 50);
+				}
+
+				// 强制垃圾回收(如果支持)
+				if (typeof gc === 'function') {
+					gc();
+				}
+			},
+
+
+			// 触发垃圾回收(在支持的环境下)
+			triggerGarbageCollection() {
+				if (wx && wx.triggerGC) {
+					wx.triggerGC();
+				}
+			},
+
+			// 强制滚动到底部(备用方案)
+			forceScrollToBottom() {
+				// console.log('执行强制滚动到底部');
+
+				// 方案1:直接设置一个很大的scrollTop值
+				this.scrollTop = 999999;
+
+				// 方案2:使用scroll-into-view滚动到最后一个元素
+				this.$nextTick(() => {
+					if (this.talklist && this.talklist.length > 0) {
+						const lastMessage = this.talklist[this.talklist.length - 1];
+						const targetId = `list_${lastMessage.uniqueId || (this.talklist.length - 1)}`;
+						console.log(
+							`尝试滚动到元素: ${targetId}, 当前消息数量: ${this.talklist.length}, 最后消息ID: ${lastMessage.uniqueId}`
+						);
+
+						this.scrollIntoView = targetId;
+
+						// 清除scroll-into-view,避免影响后续滚动
+						setTimeout(() => {
+							this.scrollIntoView = '';
+						}, 200);
+					}
+
+					// 方案3:使用更大的延迟再次设置scrollTop
+					setTimeout(() => {
+						this.scrollTop = 999999;
+						console.log('延迟设置scrollTop为999999');
+					}, 100);
+
+					// 方案4:300ms后使用原生API作为最终备用方案
+					setTimeout(() => {
+						this.nativeScrollToBottom();
+					}, 300);
+				});
+			},
+			// 强制滚动到底部(用于发送消息,绕过防抖限制)
+			forceScrollToBottomOnSend() {
+				//console.log('执行强制滚动到底部(发送消息专用)');
+				// 清理之前的定时器
+				if (this.scrollTimer) {
+					clearTimeout(this.scrollTimer);
+					this.scrollTimer = null;
+				}
+				// 强制更新滚动时间,确保不被防抖阻止
+				this.lastScrollTime = Date.now();
+				// 清除scroll-into-view,避免冲突
+				this.scrollIntoView = '';
+				// 方案1:立即使用scroll-into-view滚动到最后一条消息
+				if (this.talklist.length > 0) {
+					const lastMessage = this.talklist[this.talklist.length - 1];
+					if (lastMessage && lastMessage.uniqueId) {
+						this.scrollIntoView = `list_${lastMessage.uniqueId}`;
+						//console.log(`强制滚动方案1: 设置scrollIntoView为list_${lastMessage.uniqueId}`);
+					}
+				}
+				// 方案2:同时设置scrollTop为一个非常大的值
+				const targetScrollTop = Date.now(); // 使用时间戳确保每次都不同
+				this.scrollTop = targetScrollTop;
+				//console.log('强制滚动方案2: 设置scrollTop为', targetScrollTop);
+				// 方案3:立即尝试原生滚动
+				this.nativeScrollToBottom();
+				// 方案4:使用nextTick确保DOM更新后再次滚动
+				this.$nextTick(() => {
+					// 清除scroll-into-view后重新设置scrollTop
+					this.scrollIntoView = '';
+					this.scrollTop = targetScrollTop + 1;
+					//console.log('强制滚动方案3: nextTick后重新设置scrollTop');
+					// 再次尝试原生滚动
+					setTimeout(() => {
+						this.nativeScrollToBottom();
+					}, 50);
+				});
+				// 方案5:延迟检查和强制滚动(最终保障)
+				this.scrollTimer = setTimeout(() => {
+					this.checkAndForceScroll(targetScrollTop);
+					this.scrollTimer = null;
+				}, 200);
+			},
+
+			// 检查并强制滚动
+			checkAndForceScroll(targetScrollTop) {
+				//console.log(`检查滚动状态: 当前位置=${this.currentScrollTop}, 目标位置=${targetScrollTop}`);
+				// 无论当前位置如何,都尝试强制滚动到底部
+				// 使用scroll-into-view滚动到最后一条消息
+				if (this.talklist.length > 0) {
+					const lastMessage = this.talklist[this.talklist.length - 1];
+					if (lastMessage && lastMessage.uniqueId) {
+						this.scrollIntoView = `list_${lastMessage.uniqueId}`;
+						//console.log(`最终检查: 设置scrollIntoView为list_${lastMessage.uniqueId}`);
+					}
+				}
+				// 设置一个新的scrollTop值
+				this.scrollTop = Date.now() + Math.random() * 1000;
+				//console.log('最终检查: 设置新的scrollTop值');
+				// 多次尝试原生滚动
+				this.nativeScrollToBottom();
+				setTimeout(() => {
+					this.nativeScrollToBottom();
+				}, 100);
+			},
+
+			// 使用原生API强制滚动(最终备用方案)
+			nativeScrollToBottom() {
+				try {
+					// 方案1:使用uni.createSelectorQuery直接操作DOM
+					const query = uni.createSelectorQuery().in(this);
+					query.select('#msgScroll').node((res) => {
+						if (res && res.node) {
+							// console.log('找到msgScroll节点,执行原生滚动');
+							const scrollHeight = res.node.scrollHeight;
+							res.node.scrollTop = scrollHeight;
+							// 确保滚动生效,延迟再次设置
+							setTimeout(() => {
+								res.node.scrollTop = scrollHeight + 100;
+							}, 50);
+						}
+					}).exec();
+				} catch (error) {
+					console.error('原生滚动失败:', error);
+				}
+			},
+
+			// 监听滚动事件
+			onScroll(e) {
+				this.currentScrollTop = e.detail.scrollTop;
+				//console.log('当前滚动位置:', this.currentScrollTop);
+			},
+			// 停止内存监控
+			stopMemoryMonitor() {
+				if (this.memoryMonitorTimer) {
+					clearInterval(this.memoryMonitorTimer);
+					this.memoryMonitorTimer = null;
+				}
+			},
+			// 获取活跃定时器数量
+			getActiveTimerCount() {
+				const timers = [
+					'trafficTimer', 'pingTimeoutTimer', 'heartBeatTimer', 'liveViewDataTimer',
+					'reconnectTimer', 'scrollTimer', 'searchTimer', 'purchasePromptTimer',
+					'welcomeTimer', 'redTimer', 'liveStartTimer', 'lotteryTimer',
+					'memoryMonitorTimer', 'networkStatusTimer', 'networkRetryTimer', 'generatingTimer',
+					'videoCleanupTimer', 'countdownTimer', 'watchTimeTimer', 'pointsRetryTimer'
+				];
+				return timers.filter(timer => this[timer] !== null).length;
+			},
+
+			// 清理未使用的定时器
+			cleanupUnusedTimers() {
+				// 检查并清理可能泄漏的定时器
+				const timers = [
+					'trafficTimer', 'pingTimeoutTimer', 'heartBeatTimer', 'liveViewDataTimer',
+					'reconnectTimer', 'scrollTimer', 'searchTimer', 'purchasePromptTimer',
+					'welcomeTimer', 'redTimer', 'liveStartTimer', 'lotteryTimer', 'noticeTimer',
+					'networkStatusTimer', 'networkRetryTimer', 'generatingTimer',
+					'videoCleanupTimer', 'countdownTimer', 'watchTimeTimer', 'memoryMonitorTimer',
+					'pointsRetryTimer'
+				];
+
+				timers.forEach(timerName => {
+					if (this[timerName] && typeof this[timerName] === 'number') {
+						// 检查定时器是否还在运行
+						if (timerName.includes('Interval') || timerName.includes('Timer')) {
+							clearInterval(this[timerName]);
+						} else {
+							clearTimeout(this[timerName]);
+						}
+						this[timerName] = null;
+						console.log(`清理了可能泄漏的定时器: ${timerName}`);
+					}
+				});
+			},
+
+			// 增强的定时器清理方法
+			clearAllTimersEnhanced() {
+				// 先调用原有的清理方法
+				this.clearAllTimers();
+
+				// 额外清理新增的定时器
+				if (this.networkRetryTimer) {
+					clearTimeout(this.networkRetryTimer);
+					this.networkRetryTimer = null;
+				}
+
+				// 停止内存监控
+				this.stopMemoryMonitor();
+
+				// 清理缓存数据
+				this.userRandomColors = Object.create(null);
+				this.shownEntryUsers.clear();
+
+				// 重置性能监控数据
+				this.messageCount = 0;
+				this.errorCount = 0;
+				this.connectionLatency = 0;
+				this.lastPerformanceCheck = 0;
+
+				console.log('增强清理完成:所有定时器和缓存已清理');
+			},
+
+			goMiniProgram() {
+				uni.navigateTo({
+					url: '/pages_user/user/integralGoodsList'
+				})
+			},
+			// 阻止双击事件
+			preventDoubleClick(e) {
+				e.preventDefault();
+				e.stopPropagation();
+				return false;
+			},
+
+			// 清理所有定时器和内存
+			clearAllTimers() {
+				// 清理所有定时器
+				const timers = [
+					'scrollTimer',
+					'liveViewDataTimer',
+					'redTimer',
+					'liveStartTimer',
+					'lotteryTimer',
+					'noticeTimer',
+					'welcomeTimer',
+					'trafficInterval',
+					'lookTimer',
+					'trafficTimer',
+					'intervalId',
+					'reconnectTimer',
+					'searchTimer',
+					'purchasePromptTimer',
+					'heartBeatTimer',
+					'pingTimeoutTimer',
+					'generatingTimer',
+					'videoCleanupTimer',
+					'countdownTimer',
+					'watchTimeTimer',
+					'memoryMonitorTimer',
+					'networkStatusTimer',
+					'networkRetryTimer',
+					'pointsRetryTimer'
+				];
+				timers.forEach((timer) => {
+					if (this[timer]) {
+						if (timer.includes('Interval') || timer.includes('Timer')) {
+							clearInterval(this[timer]);
+						} else {
+							clearTimeout(this[timer]);
+						}
+						this[timer] = null;
+					}
+				});
+
+				// 重置相关状态
+				this.stayTime = 0;
+				this.startTime = 0;
+				this.totalTraffic = 0;
+				this.scrollPending = false;
+				this.reconnectCount = 0;
+				this.heartBeatRetryCount = 0;
+			},
+			//直播计算流量
+			// startTrafficCalculation() {
+			// 	if (this.trafficTimer) {
+			// 		clearInterval(this.trafficTimer);
+			// 		this.trafficTimer = null;
+			// 	}
+
+			// 	this.startTime = Date.now();
+			// 	var that = this;
+
+			// 	// 计算码率
+			// 	let bitrate = this.calculateBitrate();
+
+			// 	this.trafficTimer = setInterval(() => {
+			// 		that.calculateTraffic(bitrate);
+			// 	}, 10000); // 每10秒计算一次
+			// },
+			//直播计算流量
+			startTrafficCalculation() {
+				// 检查必要数据
+				if (!this.liveItem || !this.liveItem.videoFileSize) {
+					console.warn('视频文件大小数据不完整,无法启动流量计算');
+					return;
+				}
+				
+				// 检查视频总时长
+				const totalDuration = this.liveItem.videoDuration || this.liveItem.duration;
+				if (!totalDuration) {
+					console.warn('视频总时长数据不完整,无法启动流量计算');
+					return;
+				}
+
+				// 清除已有定时器
+				if (this.trafficTimer) {
+					clearInterval(this.trafficTimer);
+					this.trafficTimer = null;
+				}
+
+				// 记录流量计算开始时间
+				this.trafficStartTime = Date.now();
+				var that = this;
+
+				// 立即提交一次10s流量(模拟10秒观看)
+				setTimeout(() => {
+					that.submitTraffic(10);
+				}, 100); // 延迟100ms确保数据已准备好
+
+				// 启动定时器,每10秒计算并提交一次流量
+				this.trafficTimer = setInterval(() => {
+					that.calculateAndSubmitTraffic();
+				}, 10000); // 每10秒计算一次
+			},
+			// 计算流量
+			// calculateTraffic(bitrate) {
+			// 	const currentTime = Date.now();
+			// 	const duration = (currentTime - this.startTime) / 1000; // 持续时间(秒)
+			// 	// 流量 = 码率 × 时间
+			// 	// 码率单位: bps, 时间单位: 秒, 流量单位: 比特
+			// 	const trafficBits = bitrate * duration;
+			// 	// 转换为字节
+			// 	this.totalTraffic = trafficBits / 8;
+			// 	this.getLiveInternetTraffic();
+			// },
+			// calculateBitrate() {
+			// 	// 如果接口返回了视频文件大小和时长,使用这些数据计算码率
+			// 	if (this.liveItem.videoFileSize && this.liveItem.videoDuration) {
+			// 		// 码率 = 文件大小(字节) / 时长(秒) × 8 (转换为bps) × 5
+			// 		const calculatedBitrate = (this.liveItem.videoFileSize / this.liveItem.videoDuration) * 8 * 5;
+			// 		console.log(
+			// 			`使用接口数据计算码率: ${calculatedBitrate} bps (文件大小: ${this.liveItem.videoFileSize} 字节, 时长: ${this.liveItem.videoDuration} 秒)`
+			// 		);
+			// 		return calculatedBitrate;
+			// 	} else {
+			// 		// 如果任一字段为空,使用默认码率 1500 bps
+			// 		console.log('接口数据不完整,使用默认码率: 1500 bps');
+			// 		return 1500;
+			// 	}
+			// },
+			// calculateTraffic(bitrate) {
+			// 	const currentTime = Date.now();
+			// 	const duration = (currentTime - this.startTime) / 1000; // 持续时间(秒)
+
+			// 	// 流量 = 码率 × 时间
+			// 	// 码率单位: bps, 时间单位: 秒, 流量单位: 比特
+			// 	const trafficBits = bitrate * duration;
+
+			// 	// 转换为字节
+			// 	this.totalTraffic = trafficBits / 8;
+
+			// 	// 调用流量上报接口
+			// 	this.getLiveInternetTraffic();
+			// },
+			// 计算并提交流量
+			calculateAndSubmitTraffic() {
+				if (!this.liveItem || !this.liveItem.videoFileSize) {
+					const totalDuration = this.liveItem.videoDuration || this.liveItem.duration;
+					if (!totalDuration) {
+						return;
+					}
+				}
+				// 计算用户观看视频时长(秒)
+				const watchDuration = Math.floor((Date.now() - this.trafficStartTime) / 1000);
+				// 获取视频总时长(秒)
+				const totalDuration = this.liveItem.videoDuration || this.liveItem.duration || 0;
+
+				// 获取视频文件大小(字节)
+				const videoFileSize = this.liveItem.videoFileSize || 0;
+
+				if (totalDuration <= 0 || videoFileSize <= 0) {
+					console.warn('视频总时长或文件大小无效,无法计算流量');
+					return;
+				}
+
+				// 流量计算方法:用户观看视频时长/视频总时长*视频文件大小
+				const calculatedTraffic = (watchDuration / totalDuration) * videoFileSize;
+
+				// 更新总流量
+				this.totalTraffic = calculatedTraffic;
+
+				// 提交流量数据
+				this.submitTraffic(watchDuration);
+			},
+			// 提交流量数据到后端
+			submitTraffic(watchDuration) {
+				if (!this.liveId || !this.userInfo || !this.userInfo.userId) {
+					return;
+				}
+
+				// 计算当前观看时长对应的流量
+				const totalDuration = this.liveItem.videoDuration || this.liveItem.duration || 0;
+				const videoFileSize = this.liveItem.videoFileSize || 0;
+
+				if (totalDuration <= 0 || videoFileSize <= 0) {
+					console.warn('视频总时长或文件大小无效,无法提交流量', {
+						totalDuration,
+						videoFileSize,
+						videoDuration: this.liveItem.videoDuration,
+						duration: this.liveItem.duration
+					});
+					return;
+				}
+
+				// 流量 = 用户观看视频时长/视频总时长*视频文件大小
+				const traffic = (watchDuration / totalDuration) * videoFileSize;
+
+				const param = {
+					userId: this.userInfo.userId || '',
+					liveId: this.liveId || '',
+					uuId: dayjs().format('YYYYMMDD') + this.uuId,
+					internetTraffic: Math.round(traffic), // 四舍五入到整数
+					watchDuration: watchDuration, // 观看时长(秒)
+					totalDuration: totalDuration, // 视频总时长(秒)
+					videoFileSize: videoFileSize // 视频文件大小(字节)
+				};
+
+				//console.log('提交流量数据:', param);
+				liveInternetTraffic(param).catch(err => {
+					console.error('流量数据提交失败:', err);
+				});
+			},
+			startTimer() {
+				this.startTime = Date.now();
+				this.lookTimer = setInterval(() => {
+					this.stayTime = Math.floor((Date.now() - this.startTime) / 1000);
+				}, 1000);
+			},
+
+			//直播、录播缓冲
+			getLiveInternetTraffic() {
+				if (!this.liveId) return;
+				const currentTime = (this.stayTime / this.liveItem.duration) * 100;
+				const param = {
+					userId: this.userInfo.userId || '',
+					liveId: this.liveId || '',
+					uuId: dayjs().format('YYYYMMDD') + this.uuId,
+					internetTraffic: this.totalTraffic
+				};
+				liveInternetTraffic(param);
+			},
+			// 回放、预告缓冲
+			getInternetTraffic() {
+				if (!this.liveId || !this.liveId || !this.userInfo.userId || !this.uuId) return;
+				const currentTime = (this.stayTime / this.liveItem.duration) * 100;
+				const param = {
+					videoType: this.liveItem.videoType,
+					videoId: this.liveItem.videoId,
+					userId: this.userInfo.userId,
+					liveId: this.liveId,
+					uuId: dayjs().format('YYYYMMDD') + this.uuId,
+					duration: this.liveItem.duration,
+					bufferRate: currentTime
+				};
+				if (this.liveItem.status == 1) {
+					param.videoType = this.liveItem.previewVideoType || '';
+					param.videoId = this.liveItem.previewVideoId || '';
+				}
+				if (this.liveItem.liveType == 1) {
+					param.bufferRate = this.totalTraffic;
+				}
+				internetTraffic(param);
+			},
+			scrollToBottom() {
+				const now = Date.now();
+				// 防抖检查:如果距离上次滚动时间太短,则忽略
+				if (now - this.lastScrollTime < this.scrollDebounceDelay) {
+					return;
+				}
+				this.lastScrollTime = now;
+				// 清理之前的定时器
+				if (this.scrollTimer) {
+					clearTimeout(this.scrollTimer);
+					this.scrollTimer = null;
+				}
+				// 直接设置滚动位置
+				this.scrollTop = 999999999;
+
+			},
+
+			// 启动内存监控
+			startMemoryMonitor() {
+				// 清理之前的监控
+				if (this.memoryMonitorTimer) {
+					clearInterval(this.memoryMonitorTimer);
+				}
+				// 每5分钟检查一次内存使用情况
+				this.memoryMonitorTimer = setInterval(() => {
+					this.checkAndCleanMemory();
+				}, 5 * 60 * 1000); // 5分钟
+			},
+
+			// 检查并清理内存
+			checkAndCleanMemory() {
+				try {
+					// 清理过多的聊天消息
+					if (this.talklist && this.talklist.length > 25) {
+						const keepCount = 20;
+						this.talklist.splice(0, this.talklist.length - keepCount);
+					}
+
+					// 清理用户颜色缓存(保留最近的50个)
+					if (this.userRandomColors && Object.keys(this.userRandomColors).length > 50) {
+						const entries = Object.entries(this.userRandomColors);
+						const keepEntries = entries.slice(-50);
+						this.userRandomColors = Object.fromEntries(keepEntries);
+					}
+					// 清理已显示用户集合(保留最近的100个)
+					if (this.shownEntryUsers && this.shownEntryUsers.size > 100) {
+						const array = Array.from(this.shownEntryUsers);
+						this.shownEntryUsers.clear();
+						array.slice(-100).forEach((id) => this.shownEntryUsers.add(id));
+					}
+
+					console.log('内存清理完成');
+				} catch (error) {
+					console.error('内存清理失败:', error);
+				}
+			},
+			// 恢复页面活动
+			async resumePageActivity() {
+				if (this.liveItem) {
+					await this.getliving(this.liveId);
+					this.startTimeTimer(this.liveItem);
+				}
+				if (!this.isSocketAvailable()) {
+					this.initSocket();
+				}
+			},
+			// 获取用户专属随机色(缓存机制:同一用户始终用同一颜色)
+			getUserRandomColor(userId) {
+				if (!userId) {
+					return '#8978e2'; // 默认颜色
+				}
+				//如果缓存中已有该用户的颜色,直接返回
+				if (this.userRandomColors[userId]) {
+					return this.userRandomColors[userId];
+				}
+				//为新用户生成固定颜色(基于用户ID生成,不是完全随机)
+				const color = this.generateStableColor(userId);
+				this.userRandomColors[userId] = color;
+				// 存储到本地缓存,确保页面刷新后颜色不变
+				this.saveUserColorsToStorage();
+				return color;
+			}, // 基于用户ID生成稳定颜色(不是完全随机)
+			generateStableColor(userId) {
+				// 将用户ID转换为数字种子
+				let seed = 0;
+				for (let i = 0; i < userId.length; i++) {
+					seed = (seed * 31 + userId.charCodeAt(i)) % 1000000;
+				}
+				const colorPool = [
+					'#FF6B6B',
+					'#4ECDC4',
+					'#45B7D1',
+					'#96CEB4',
+					'#FFEAA7',
+					'#DDA0DD',
+					'#98D8C8',
+					'#F7DC6F',
+					'#BB8FCE',
+					'#85C1E9',
+					'#F8C471',
+					'#82E0AA',
+					'#F1948A',
+					'#85C1E9',
+					'#D7BDE2'
+				];
+				return colorPool[seed % colorPool.length];
+			},
+			// 保存颜色映射到本地存储
+			saveUserColorsToStorage() {
+				try {
+					uni.setStorageSync('userRandomColors', this.userRandomColors);
+				} catch (e) {
+					console.warn('保存用户颜色缓存失败:', e);
+				}
+			},
+			// 从本地存储加载颜色映射
+			loadUserColorsFromStorage() {
+				try {
+					const cached = uni.getStorageSync('userRandomColors');
+					if (cached) {
+						this.userRandomColors = cached;
+					}
+				} catch (e) {
+					console.warn('加载用户颜色缓存失败:', e);
+				}
+			},
+			//头像名字
+			getNicknameInitial(nickName) {
+				if (!nickName || typeof nickName !== 'string') return '未';
+				if (/^[\u4e00-\u9fa5]/.test(nickName[0])) {
+					return nickName[0];
+				}
+				return nickName[0].toUpperCase();
+			},
+			async getUserInfo() {
+				await getUserInfo().then(
+					(res) => {
+						if (res.code == 200) {
+							this.userInfo = res.user;
+							this.isNow = dayjs(this.userInfo.updateTime).isSame(dayjs(), 'day')
+						} else {
+							uni.showToast({
+								icon: 'none',
+								title: '请求失败'
+							});
+						}
+					},
+					(rej) => {}
+				);
+			},
+
+			//订阅消息
+			handleAgreement() {
+				const templateId = this.templateId;
+				if (this.hasSubscribed) return;
+				uni.requestSubscribeMessage({
+					tmplIds: [templateId],
+					success: (res) => {
+						if (res[templateId] === 'accept') {
+							uni.showToast({
+								title: '订阅成功,开播将提醒您',
+								icon: 'none',
+								duration: 2500 // 成功提示延长到2.5秒
+							});
+							// 订阅成功时
+							this.hasSubscribed = true;
+							uni.setStorageSync('subscribe_status_' + this.liveId, true);
+							this.callSendMessageApi();
+						} else if (res[templateId] === 'reject') {
+							uni.showToast({
+								title: '您已拒绝订阅,将无法收到提醒',
+								icon: 'none',
+								duration: 2500 // 成功提示延长到2.5秒
+							});
+						} else if (res[templateId] === 'ban') {
+							uni.showToast({
+								title: '您已关闭所有订阅权限,请在设置中开启',
+								icon: 'none',
+								duration: 2500 // 成功提示延长到2.5秒
+							});
+						}
+					},
+					fail: (err) => {
+						console.error('订阅消息失败', err);
+						uni.showToast({
+							title: '订阅失败,请重试',
+							icon: 'none',
+							duration: 2500 // 成功提示延长到2.5秒
+						});
+					}
+				});
+			},
+			async callSendMessageApi() {
+				if (!this.userInfo.userId) return;
+				const templateData = {
+					liveId: this.liveId,
+					userId: this.userInfo.userId,
+					templateId: this.templateId, // 模板ID
+					maOpenId: this.userInfo.maOpenId,
+					appId: this.appid,
+					data: {
+						thing2: this.liveItem.liveName,
+						time4: this.liveItem.startTime,
+						date7: this.liveItem.startTime
+					}
+				};
+				subNotifyLive(templateData).then(
+					(res) => {
+						if (res.code == 200) {
+							this.isAgreement = true;
+							uni.setStorageSync('isAgreement', true);
+						} else {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+						}
+					},
+					(rej) => {}
+				);
+			},
+
+			//发送心跳
+			sendHeartBeat() {
+				if (!this.isSocketAvailable() || !this.isNetworkAvailable) {
+					console.warn('网络不可用或Socket连接异常,跳过心跳发送');
+					return;
+				}
+				this.lastHeartBeatTime = Date.now();
+				// 计算当前累计观看时长
+				const currentWatchDuration = this.getCurrentWatchDuration();
+
+				try {
+					const heartBeatMsg = JSON.stringify({
+						cmd: 'heartbeat',
+						msg: 'ping',
+						userId: this.userInfo.userId || '',
+						liveId: this.liveId,
+						timestamp: this.lastHeartBeatTime,
+						networkType: this.networkType,
+						data: String(currentWatchDuration)
+					});
+					this.socket.send({
+						data: heartBeatMsg,
+						success: () => {
+							this.heartBeatRetryCount = 0; // 成功后重置重试次数
+							this.adjustHeartBeatInterval(true); // 网络良好,可适当延长间隔
+							this.startPingTimeout(); // 启动超时检测
+						},
+						fail: (err) => {
+							console.error('心跳包发送失败:', err);
+							this.heartBeatRetryCount++;
+							this.adjustHeartBeatInterval(false); // 网络不稳定,缩短间隔
+
+							// 根据网络类型调整重试策略
+							const retryDelay = this.getRetryDelay();
+
+							if (this.heartBeatRetryCount < this.maxHeartBeatRetries) {
+								setTimeout(() => this.sendHeartBeat(), retryDelay);
+							} else {
+								this.heartBeatRetryCount = 0;
+								this.handleReconnect(); // 重试用完才重连
+							}
+						}
+					});
+				} catch (err) {
+					console.error('心跳发送异常:', err);
+					this.heartBeatRetryCount++;
+
+					const retryDelay = this.getRetryDelay();
+					if (this.heartBeatRetryCount < this.maxHeartBeatRetries) {
+						setTimeout(() => this.sendHeartBeat(), retryDelay);
+					} else {
+						this.heartBeatRetryCount = 0;
+						this.handleReconnect();
+					}
+				}
+			},
+
+			// 根据网络状态获取重试延迟
+			getRetryDelay() {
+				const baseDelay = 2000;
+				const retryMultiplier = Math.pow(1.5, this.heartBeatRetryCount); // 指数退避
+
+				// 根据网络类型调整延迟
+				let networkMultiplier = 1;
+				switch (this.networkType) {
+					case '2g':
+						networkMultiplier = 3;
+						break;
+					case '3g':
+						networkMultiplier = 2;
+						break;
+					case '4g':
+					case '5g':
+						networkMultiplier = 1;
+						break;
+					case 'wifi':
+						networkMultiplier = 0.8;
+						break;
+					default:
+						networkMultiplier = 1.5;
+				}
+				return Math.min(baseDelay * retryMultiplier * networkMultiplier, 10000); // 最大10秒
+			},
+
+			// 自适应调整心跳间隔
+			adjustHeartBeatInterval(isSuccess) {
+				if (isSuccess) {
+					// 连接稳定,可适当延长间隔(最大30秒)
+					this.adaptiveHeartBeatInterval = Math.min(this.adaptiveHeartBeatInterval * 1.1, 30000);
+				} else {
+					// 连接不稳定,缩短间隔(最小10秒)
+					this.adaptiveHeartBeatInterval = Math.max(this.adaptiveHeartBeatInterval * 0.9, 10000);
+				}
+			},
+			// 启动心跳超时检测
+			startPingTimeout() {
+				// 清除现有的ping超时定时器
+				if (this.pingTimeoutTimer) {
+					clearTimeout(this.pingTimeoutTimer);
+					this.pingTimeoutTimer = null;
+				}
+				// 启动新的ping超时定时器
+				this.pingTimeoutTimer = setTimeout(() => {
+					console.warn('心跳超时,触发重连');
+					// 清理当前定时器引用
+					this.pingTimeoutTimer = null;
+					// 增加心跳重试次数
+					this.heartBeatRetryCount++;
+					// 如果重试次数未达到上限,先尝试重发心跳
+					if (this.heartBeatRetryCount < this.maxHeartBeatRetries) {
+						console.log(
+							`心跳超时,尝试重发 (${this.heartBeatRetryCount}/${this.maxHeartBeatRetries})`);
+						setTimeout(() => this.sendHeartBeat(), 1000);
+					} else {
+						console.log('心跳重试次数用尽,触发重连');
+						this.heartBeatRetryCount = 0;
+						this.handleReconnect();
+					}
+				}, this.pingTimeout);
+			},
+			stopHeartBeat() {
+				if (this.heartBeatTimer) {
+					clearInterval(this.heartBeatTimer);
+					this.heartBeatTimer = null;
+				}
+				if (this.pingTimeoutTimer) {
+					clearTimeout(this.pingTimeoutTimer);
+					this.pingTimeoutTimer = null;
+				}
+			}, // 封装通用的连接状态校验方法
+			isSocketAvailable() {
+				// WebSocket readyState:0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED
+				return this.socket && this.isSocketOpen && this.socket.readyState === 1;
+			},
+			// 处理重连逻辑
+			handleReconnect() {
+				if (this.isManualClose) {
+					console.log('手动关闭连接,不进行重连');
+					return;
+				}
+				// 防止重复重连
+				if (this.reconnectTimer) {
+					console.log('重连已在进行中,跳过重复重连');
+					return;
+				}
+				this.stopHeartBeat();
+				// 检查网络状态
+				if (!this.isNetworkAvailable) {
+					console.warn('网络不可用,延迟重连');
+					this.reconnectTimer = setTimeout(() => {
+						this.reconnectTimer = null;
+						this.handleReconnect();
+					}, 5000);
+					return;
+				}
+				if (this.reconnectCount < this.maxReconnectAttempts) {
+					this.reconnectCount++;
+					// 指数退避算法:基础延迟 * 2^(重连次数-1) + 随机抖动
+					const baseDelay = 1000;
+					const exponentialDelay = baseDelay * Math.pow(2, this.reconnectCount - 1);
+					const jitter = Math.random() * 1000; // 随机抖动,避免同时重连
+					const totalDelay = Math.min(exponentialDelay + jitter, 30000); // 最大30秒
+					console.log(
+						`第${this.reconnectCount}次重连,延迟${Math.round(totalDelay)}ms,网络类型:${this.networkType}`
+					);
+					this.reconnectTimer = setTimeout(() => {
+						this.reconnectTimer = null; // 清理定时器引用
+						// 重连前再次检查网络状态和连接状态
+						if (this.isNetworkAvailable && !this.isManualClose && !this
+							.isSocketAvailable()) {
+							console.log('开始执行重连...');
+							this.initSocket();
+						} else if (this.isSocketAvailable()) {
+							console.log('连接已恢复,取消重连');
+							this.reconnectCount = 0; // 重置重连计数
+						} else {
+							console.warn('重连时网络不可用或已手动关闭');
+							this.handleReconnect(); // 递归重试
+						}
+					}, totalDelay);
+				} else {
+					console.log(`已达最大重连次数(${this.maxReconnectAttempts}),停止重连`);
+					this.showReconnectFailedMessage();
+				}
+			},
+
+			// 显示重连失败提示
+			showReconnectFailedMessage() {
+				uni.showToast({
+					title: '网络连接异常,请检查网络后重新进入',
+					icon: 'none',
+					duration: 3000
+				});
+			},
+
+			// 统一处理连接错误
+			handleConnectionError(errorType, error) {
+				console.error(`WebSocket ${errorType}:`, error);
+
+				// 根据错误类型进行不同处理
+				if (errorType === '连接请求失败') {
+					// 连接请求失败,可能是网络问题或服务器问题
+					if (!this.isNetworkAvailable) {
+						console.warn('网络不可用,等待网络恢复后重连');
+						return;
+					}
+				}
+				// 触发重连
+				this.handleReconnect();
+			},
+			// 重置重连状态
+			resetReconnectState() {
+				this.reconnectCount = 0;
+				this.heartBeatRetryCount = 0;
+				// 清理重连定时器
+				if (this.reconnectTimer) {
+					clearTimeout(this.reconnectTimer);
+					this.reconnectTimer = null;
+				}
+				// 重置自适应心跳间隔
+				this.adaptiveHeartBeatInterval = this.heartBeatInterval;
+			},
+
+			// 初始化网络状态监听
+			initNetworkStatusListener() {
+				// 获取当前网络状态
+				uni.getNetworkType({
+					success: (res) => {
+						this.networkType = res.networkType;
+						this.isNetworkAvailable = res.networkType !== 'none';
+						console.log('当前网络类型:', res.networkType);
+					}
+				});
+
+				// 监听网络状态变化
+				uni.onNetworkStatusChange((res) => {
+					const oldNetworkType = this.networkType;
+					const oldNetworkAvailable = this.isNetworkAvailable;
+
+					this.networkType = res.networkType;
+					this.isNetworkAvailable = res.isConnected;
+
+					console.log(
+						`网络状态变化: ${oldNetworkType} -> ${res.networkType}, 连接状态: ${res.isConnected}`
+					);
+
+					// 网络从不可用变为可用时,尝试重连
+					if (!oldNetworkAvailable && res.isConnected) {
+						console.log('网络恢复,尝试重连WebSocket');
+						this.resetReconnectState();
+						setTimeout(() => {
+							if (!this.isSocketAvailable()) {
+								this.initSocket();
+							}
+						}, 1000);
+					}
+
+					// 网络类型变化时,调整心跳策略
+					if (oldNetworkType !== res.networkType && res.isConnected) {
+						this.adjustHeartBeatForNetworkType(res.networkType);
+					}
+
+					// 网络断开时停止心跳
+					if (!res.isConnected) {
+						console.warn('网络断开,停止心跳');
+						this.stopHeartBeat();
+					}
+				});
+			},
+
+			// 根据网络类型调整心跳策略
+			adjustHeartBeatForNetworkType(networkType) {
+				let newInterval = this.heartBeatInterval;
+				switch (networkType) {
+					case '2g':
+						newInterval = 30000; // 2G网络,30秒间隔
+						break;
+					case '3g':
+						newInterval = 20000; // 3G网络,20秒间隔
+						break;
+					case '4g':
+					case '5g':
+						newInterval = 15000; // 4G/5G网络,15秒间隔
+						break;
+					case 'wifi':
+						newInterval = 10000; // WiFi网络,10秒间隔
+						break;
+					default:
+						newInterval = 15000; // 默认15秒
+				}
+
+				if (newInterval !== this.adaptiveHeartBeatInterval) {
+					this.adaptiveHeartBeatInterval = newInterval;
+					console.log(`根据网络类型(${networkType})调整心跳间隔为${newInterval}ms`);
+
+					// 如果当前有心跳在运行,重启心跳以应用新间隔
+					if (this.heartBeatTimer && this.isSocketAvailable()) {
+						this.startHeartBeat();
+					}
+				}
+			},
+
+			//输入框
+			inputFocus() {
+				// 立即更新状态,确保UI零延迟响应
+				this.isFocus = true;
+				this.isKeyboardShow = true;
+				this.scrollTop = 9999999
+			},
+			inputBlur() {
+				this.isFocus = false;
+			},
+			getTimeDifferenceInSeconds(createTimeStr) {
+				if (!createTimeStr) return;
+				const createTime = new Date(createTimeStr.replace(/-/g, '/'));
+				const now = new Date();
+				const timeDiffMs = now - createTime;
+				const timeDiffSeconds = Math.floor(timeDiffMs / 1000);
+				return Math.max(0, timeDiffSeconds);
+			},
+			// 录播时间点
+			onVideoMetaLoaded(e) {
+				console.log("录播时间点", e)
+				const width = e.detail.width;
+				const height = e.detail.height;
+				const res = uni.getSystemInfoSync();
+				const winH = res.windowHeight;
+				const winW = res.windowWidth;
+				//横屏
+				const wW = (winW / winH) * 100;
+				//竖屏
+				if (height > width) {
+					this.isHeight = true
+				}
+				const wH = (winH / winW) * 100;
+				// this.scale = wW / this.videoRatio;
+				// if (this.liveItem.showType == 2) {
+				// 	const videoRatio = (height / width) * 100;
+				// 	this.scale = wH / videoRatio;
+				// 	console.log("比例", this.videoRatio, width, height)
+				// } else if (this.isFullscreen) {
+				// }
+				this.videoProgressKey = `videoProgress_${this.liveId}`;
+				this.setVideoProgress();
+
+				// 视频加载成功后,启动流量计算
+				if (!this.videoLoaded) {
+					this.videoLoaded = true;
+					// 延迟一下确保数据已加载
+					setTimeout(() => {
+						this.startTrafficCalculation();
+					}, 500);
+				}
+			},
+			setVideoProgress() {
+				// 只有录播和回放需要设置进度
+				if (this.liveItem.liveType !== 2 && this.liveItem.liveType !== 3) {
+					return;
+				}
+				let currentTime = 0;
+				if (this.liveItem.liveType === 2) {
+					// 录播:计算当前时间与开始时间的差值,对视频总时长取模
+					const diff = this.getTimeDifferenceInSeconds(this.liveItem.startTime);
+					if (diff > this.liveItem.duration) {
+						const storedProgress = uni.getStorageSync(this.videoProgressKey) || 0;
+						currentTime = storedProgress >= this.liveItem.duration ? 0 : storedProgress || 0;
+						this.isPlayback = true;
+						this.hasPlayback = true;
+					} else {
+						currentTime = diff % this.liveItem.duration;
+					}
+				} else if (this.liveItem.liveType === 3) {
+					// 回放:从存储中获取进度
+					const storedProgress = uni.getStorageSync(this.videoProgressKey);
+					currentTime = storedProgress || 0;
+				}
+				const videoId = `myVideo_${this.liveId}`;
+				const videoContext = uni.createVideoContext(videoId, this);
+				if (videoContext) {
+					videoContext.seek(currentTime);
+				}
+			},
+
+			// onVideoWaiting(e) {
+			// 	// console.log('视频等待加载', e);
+			// 	if (this.liveItem.liveType == 2) {
+			// 		this.startTrafficCalculation(this.bitrate);
+			// 	} else {
+			// 		let that = this;
+			// 		if (this.trafficInterval) {
+			// 			clearInterval(this.trafficInterval);
+			// 			this.trafficInterval = null;
+			// 		}
+			// 		this.trafficInterval = setInterval(function() {
+			// 			that.getInternetTraffic();
+			// 		}, 10000);
+			// 	}
+			// },
+			onVideoWaiting(e) {
+				// console.log('视频等待加载', e);
+				if (this.liveItem.liveType == 2) {
+					// 修改这里:不再传入固定码率,而是在方法内部计算
+					this.startTrafficCalculation();
+				} else {
+					let that = this;
+					if (this.trafficInterval) {
+						clearInterval(this.trafficInterval);
+						this.trafficInterval = null;
+					}
+					this.trafficInterval = setInterval(function() {
+						that.getInternetTraffic();
+					}, 10000);
+				}
+			},
+
+			// 视频时间更新
+			onVideoTimeUpdate(e) {
+				// 获取当前播放时间
+				this.videoCurrentTime = e.detail.currentTime;
+				// 每隔1秒保存一次进度(避免频繁存储)
+				if (Math.floor(this.videoCurrentTime) % 1 === 0) {
+					this.saveVideoProgress();
+				}
+				const diff = this.getTimeDifferenceInSeconds(this.liveItem.startTime)
+				if (diff >= this.liveItem.duration) {
+					if (!this.hasPlayback) {
+						this.generating = true;
+						this.pauseVideo();
+						setTimeout(() => {
+							this.playVideo();
+							this.generating = false;
+							this.hasPlayback = true;
+
+						}, 180000);
+						this.isEnd = true;
+					}
+				}
+
+				// 观看时间 ljx
+				let currentTime = ''
+				const storedProgress = uni.getStorageSync(this.videoProgressKey) || 0;
+				currentTime = storedProgress >= this.liveItem.duration ? 0 : storedProgress || 0;
+				this.$nextTick(() => {
+					const difPlayback = currentTime;
+					const totalSeconds = Math.floor(difPlayback);
+					const hours = this.padZero(Math.floor(totalSeconds / 3600));
+					const minutes = this.padZero(Math.floor((totalSeconds % 3600) / 60));
+					const seconds = this.padZero(totalSeconds % 60);
+					this.playbackTime = `${hours}:${minutes}:${seconds}`;
+				});
+			},
+
+			// 视频暂停
+			onVideoPause(e) {
+				
+				if (this.liveItem.liveType === 2) {
+					const videoId = `myVideo_${this.liveId}`;
+					const videoContext = uni.createVideoContext(videoId, this);
+					setTimeout(() => {
+						videoContext.play();
+					}, 100);
+				}
+				// 暂停时保存进度
+				this.saveVideoProgress();
+			},
+			// 视频播放
+			onVideoPlay(e) {
+				//console.log("qxj onVideoPlay");
+				if (this.liveItem.status == 2) {
+					//this.startCountdown();
+					// 启动观看时长统计
+					//this.startWatchDurationTracking();
+				}
+				if (this.watchTimeTimer) {
+					clearInterval(this.watchTimeTimer);
+					this.watchTimeTimer = null;
+					this.saveWatchTime();
+					console.log("视频开始播放")
+				}
+			},
+			// 保存视频进度
+			saveVideoProgress() {
+				if (this.videoProgressKey) {
+					uni.setStorage({
+						key: this.videoProgressKey,
+						data: this.videoCurrentTime,
+						success: () => {},
+						fail: (err) => {
+							console.error('保存视频进度失败:', err);
+						}
+					});
+				}
+			},
+
+			// 点击红包
+			onRed() {
+				if (!this.liveId) return;
+				if (!this.redInfo?.redId) return;
+				if (this.redTimer) {
+					clearInterval(this.redTimer);
+					this.redTimer = null;
+				}
+				let data = {
+					liveId: this.liveId,
+					userId: this.userInfo.userId,
+					redId: this.redInfo.redId
+				};
+				liveRed(data).then((res) => {
+						this.isShowRed = false;
+						this.redCard = res;
+						this.isShowRedCard = true;
+					},
+					(rej) => {}
+				);
+			},
+			//领取优惠券
+			onCoupon() {
+				if (!this.couponInfo.couponIssueId) return;
+				let data = {
+					goodsId: this.couponInfo.goodsId,
+					couponIssueId: this.couponInfo.couponIssueId,
+					liveId: this.liveId
+				};
+				coupon(data).then((res) => {
+						this.isShowCoupon = false;
+						if (res.code == 200) {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+						} else {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+						}
+					})
+					.catch((rej) => {});
+			},
+
+			// 我的中奖名单
+			getMyLottery() {
+				this.winning = true;
+				myLottery()
+					.then((res) => {
+						if (res.code == 200) {
+							// console.log("我的中奖名单", res)
+							this.prizeAll = res.data.list || {};
+						} else {}
+					})
+					.catch((rej) => {});
+			},
+			// 抽奖
+			onLottery() {
+				if (!this.lotteryInfo) return;
+				this.isShowLottery = false
+				let data = {
+					lotteryId: this.lotteryInfo.lotteryId
+				};
+
+				liveLottery(data)
+					.then((res) => {
+						if (res.code == 200) {
+							const resData = res.data || {};
+							this.lotteryList = Array.isArray(resData) ? resData : [];
+							this.lotteryProducts = Array.isArray(resData.products) ? resData.products : [];
+
+							if (resData.duration) {
+								this.isShowLotteryPop = true;
+							}
+						} else {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+							this.lotteryList = [];
+							this.lotteryProducts = [];
+						}
+					})
+					.catch((rej) => {
+						uni.showToast({
+							title: '获取抽奖信息失败',
+							icon: 'none'
+						});
+						// 失败时强制重置为数组
+						this.lotteryList = [];
+						this.lotteryProducts = [];
+					});
+			},
+			// 参与抽奖
+			onClaim() {
+				let data = {
+					liveId: this.liveId,
+					lotteryId: this.lotteryInfo.lotteryId
+				};
+				claim(data).then(
+					(res) => {
+						if (res.code == 200) {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+							this.isShowLotteryPop = false;
+							this.havePrize = true;
+							uni.setStorageSync('havePrize', this.havePrize);
+						} else {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+						}
+					},
+					(rej) => {}
+				);
+			},
+			confirm() {
+				this.isShowPrize = false;
+				this.havePrize = false;
+				uni.setStorageSync('havePrize', this.havePrize);
+			},
+			// 商品收藏
+			onGoodsCollect(item) {
+				if (!item || item.length === 0 || !item.goodsId) {
+					return;
+				}
+				collectGoods(item.goodsId).then(
+					(res) => {
+						if (res.code == 200) {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+							item.isFavorite = !item.isFavorite;
+						} else {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+						}
+					},
+					(rej) => {}
+				);
+			},
+
+			//正在购买
+			getliveOrder(item) {
+				if (!this.liveId) {
+					return;
+				}
+				liveOrderUser(this.liveId).then(
+					(res) => {
+						if (res.code == 200) {
+							this.orderUser = res;
+						} else {
+							console.log('获取正在购买用户失败');
+						}
+					},
+					(rej) => {}
+				);
+			},
+			onLiveStateChange(e, liveItem) {
+				// 可以根据状态码处理不同的直播状态
+				const stateCode = e.detail.code;
+				if (e.detail.code == -2301 || e.detail.code == -2302) {
+					this.playVideo();
+				} else if (e.detail.code == 2004) {
+					this.calculateTimeDiff(this.liveItem);
+					// this.startTrafficCalculation(this.bitrateLive);
+					this.startTrafficCalculation();
+				}
+				// 2001: 已经连接服务器
+				// 2002: 已经连接服务器,开始拉流
+				// 2003: 网络接收到首个视频数据包(IDR)
+				// 2004: 视频播放开始
+				// 2005: 视频播放进度
+				// 2006: 视频播放结束
+				// 2007: 视频播放Loading
+				// 2008: 解码器启动
+				// -2301: 网络断连,且经多次重连抢救无效,更多重试请自行重启播放
+				// -2302: 获取加速拉流地址失败
+			}, // 直播错误事件
+			onLiveError(e, liveItem) {
+				this.videoError(e, liveItem);
+				console.log('错误');
+			},
+			//  红包 卡片 抽奖
+			getCurrentActivities() {
+				if (!this.liveId) return;
+				currentActivities(this.liveId).then(
+					(res) => {
+						if (res.code === 200) {
+							// 提取数据(默认空数组/对象避免报错)
+							this.redInfo = (Array.isArray(res.red) ? res.red : [])[0] || {};
+							this.lotteryInfo = (Array.isArray(res.lottery) ? res.lottery : [])[0] || {};
+							this.goodsCard = res.goods || {};
+							this.notice = res.topMsg || {};
+
+							this.isShowGoods = this.goodsCard && this.goodsCard.status == 1;
+							this.isShowRed = this.redInfo && this.redInfo.redStatus == 1;
+							this.isShowLottery = this.lotteryInfo && this.lotteryInfo.lotteryStatus == 1;
+
+							if (this.notice.msg) {
+								this.noticeTimer = setInterval(() => {
+									const noticeCountdown = this.handleTime(this.notice.endTime, 0);
+									if (!noticeCountdown) {
+										this.isShowNotice = false;
+										clearInterval(this.noticeTimer);
+									} else {
+										this.isShowNotice = true
+									}
+								}, 1000);
+							}
+							// if(this.notice.msg&&this.notice){
+							// 	this.isShowNotice = true
+							// }else{
+							// 	this.isShowNotice = false
+							// }
+							if (this.isShowRed) {
+								this.redTimer = setInterval(() => {
+									const redCountdown = this.handleTime(this.redInfo.updateTime, this
+										.redInfo
+										.duration);
+									if (!redCountdown) {
+										this.isShowRed = false;
+										clearInterval(this.redTimer);
+									}
+								}, 1000);
+							}
+							// 处理抽奖定时器
+							if (this.isShowLottery) {
+								this.lotteryTimer = setInterval(() => {
+									this.countdown = this.handleTime(this.lotteryInfo.updateTime, this
+										.lotteryInfo.duration);
+								}, 1000);
+							}
+						} else {
+							uni.showToast({
+								title: res.msg,
+								icon: 'none'
+							});
+						}
+					},
+					(rej) => {}
+				);
+			},
+
+			// 计算当前时间与 liveItem.startTime 的差值,并更新 totalTime
+			calculateTimeDiff(item, type) {
+				if (!item.startTime) return;
+				// 提取对应场景的时间字符串(直播用startTime,抽奖用updateTime)
+				let timeStr = item.startTime;
+
+				// 转换时间格式(适配iOS,将 "-" 替换为 "/")
+				const time = new Date(timeStr.replace(/-/g, '/'));
+
+				if (isNaN(time.getTime())) {
+					return;
+				}
+				const now = new Date();
+				let diffMs = Math.max(0, now.getTime() - time.getTime());
+				// 转换为 时:分:秒(补零处理)
+				const totalSeconds = Math.floor(diffMs / 1000);
+				const hours = this.padZero(Math.floor(totalSeconds / 3600));
+				const minutes = this.padZero(Math.floor((totalSeconds % 3600) / 60));
+				const seconds = this.padZero(totalSeconds % 60);
+				this.diffTotalTime = `${hours}:${minutes}:${seconds}`;
+				if (type) {
+					return `${hours}:${minutes}:${seconds}`;
+				}
+			},
+
+
+			// 启动当前直播间的时间差值定时器
+			startTimeTimer(item) {
+				if (!item) return;
+				// 立即计算一次(避免等待1秒才显示)
+				const totalTime = this.calculateTimeDiff(item);
+				item.timeTimer = setInterval(() => {
+					const totalTime = this.calculateTimeDiff(item);
+				}, 1000);
+			},
+
+			// toggleViewerList() {
+			// 	const now = Date.now();
+			// 	if (now - this.lastClickTime > this.clickDelay) {
+			// 		this.showadd = !this.showadd;
+			// 		if (this.showadd) {
+			// 			this.getliveUser(false); // 加载第一页观众
+			// 		}
+			// 		this.lastClickTime = now;
+			// 	}
+			// },
+			// 播放视频
+			playVideo() {
+				if (!this.liveItem) {
+					console.log('liveItem 为空,无法播放视频');
+					return;
+				}
+				try {
+					if (this.liveItem.liveType === 1 && this.liveItem.livingUrl && this.liveItem.status == 2) {
+
+					} else if (this.liveItem.status == 1 && this.liveItem.previewUrl) {
+						const videoId = `myVideo_${this.liveId}`;
+						const videoContext = uni.createVideoContext(videoId, this);
+
+						if (videoContext) {
+							videoContext.play();
+						}
+					} else if (this.liveItem.liveType === 2 && this.liveItem.videoUrl && this.liveItem.status ==
+						2) {
+						const videoId = `myVideo_${this.liveId}`;
+						const videoContext = uni.createVideoContext(videoId, this);
+						// console.log("录播")
+						if (videoContext) {
+							videoContext.play();
+						}
+					} // 回放视频使用video
+					else if (this.liveItem.liveType === 3 && this.liveItem.videoUrl && this.liveItem.status == 4) {
+						const videoId = `myVideo_${this.liveId}`;
+						const videoContext = uni.createVideoContext(videoId, this);
+						// console.log("回放")
+						if (videoContext) {
+							videoContext.play();
+						}
+					}
+				} catch (error) {
+					console.error('播放视频失败:', error);
+				}
+			},
+
+			pauseVideo() {
+				if (!this.liveItem) return;
+
+				try {
+					if (this.liveItem.status == 1) {
+						const videoId = `myVideo_${this.liveId}`;
+						const videoContext = uni.createVideoContext(videoId, this);
+						if (videoContext) {
+							videoContext.pause();
+						}
+					} else if (this.liveItem.status == 2) {
+						if (this.liveItem.liveType === 1) {
+							const livePlayerId = `myLivePlayer_${this.liveId}`;
+							const livePlayerContext = uni.createLivePlayerContext(livePlayerId, this);
+							if (livePlayerContext) {
+								livePlayerContext.pause();
+							}
+						} else if (this.liveItem.liveType === 2) {
+							const videoId = `myVideo_${this.liveId}`;
+							const videoContext = uni.createVideoContext(videoId, this);
+							if (videoContext) {
+								videoContext.pause();
+							}
+						}
+					}
+				} catch (error) {
+					console.error('暂停视频失败:', error);
+				}
+			},
+			// 视频错误处理
+			videoError(e, liveItem) {
+				if (!liveItem || !this.liveId) return;
+				// 初始化重试计数
+				if (this.videoRetryCounts[liveItem.liveId] === undefined) {
+					this.videoRetryCounts[liveItem.liveId] = 0;
+				}
+				// 限制重试次数
+				if (this.videoRetryCounts[liveItem.liveId] >= 3) {
+					console.error(`直播间 ${this.liveId} 视频加载失败,停止重试`);
+					// 显示错误提示
+					uni.showToast({
+						title: '视频加载失败,请检查网络',
+						icon: 'none',
+						duration: 2000
+					});
+					return;
+				}
+
+				this.videoRetryCounts[this.liveId]++;
+
+				// 延迟重试
+				setTimeout(() => {
+					if (this.liveId === this.liveId) {
+						console.log(`第${this.videoRetryCounts[this.liveId]}次重试播放视频`);
+						this.playVideo();
+					}
+				}, 2000);
+			},
+
+			openViews() {
+				// 计算scroll-view高度
+				this.$nextTick(() => {
+					const query = uni.createSelectorQuery().in(this);
+					query
+						.select('.view-box')
+						.boundingClientRect((data) => {
+							if (data) {
+								this.scrollHeight = data.height - 80; // 80是标题高度,120是底部高度
+							}
+						})
+						.exec();
+				});
+			},
+			// 滚动到底部触发
+			handleScrollToLower() {
+				// 清除上一次未执行的定时器,避免重复请求
+				if (this.scrollTimer) {
+					clearTimeout(this.scrollTimer);
+				}
+				// 延迟1秒执行接口请求
+				this.scrollTimer = setTimeout(() => {
+					this.getliveUser(true);
+				}, 1000);
+			},
+
+			async getMyLiveMsg(liveItem) {
+				console.log("不可见了")
+				if (!liveItem || !this.liveId) {
+					console.error('getLiveMsg 错误:无效的 liveItem');
+					return;
+				}
+				try {
+					const res = await myLiveMsg(this.liveId, 30, 1);
+					if (res.code == 200) {
+						const rows = Array.isArray(res.rows) ? res.rows : [];
+						const reversedTalkList = [...rows].reverse();
+						this.talklist = Array.isArray(reversedTalkList) ? reversedTalkList : [];
+						// 获取历史消息后也滚动到底部
+						this.$nextTick(() => {
+							this.scrollToBottom();
+						});
+					} else {
+						this.talklist = [];
+					}
+				} catch (error) {
+					this.talklist = [];
+					console.error('获取聊天记录失败:', error);
+				}
+			},
+			async getLiveMsg(liveItem) {
+				if (!liveItem || !this.liveId) {
+					console.error('getLiveMsg 错误:无效的 liveItem');
+					return;
+				}
+				try {
+					const res = await liveMsg(this.liveId, 30, 1);
+					if (res.code == 200) {
+						const rows = Array.isArray(res.rows) ? res.rows : [];
+						const reversedTalkList = [...rows].reverse();
+						this.talklist = Array.isArray(reversedTalkList) ? reversedTalkList : [];
+						// 获取历史消息后也滚动到底部
+						this.$nextTick(() => {
+							this.scrollToBottom();
+						});
+					} else {
+						this.talklist = [];
+					}
+				} catch (error) {
+					this.talklist = [];
+					console.error('获取聊天记录失败:', error);
+				}
+			},
+
+			//小黄车搜索商品
+			handleSearchInput() {
+				// 使用防抖优化性能,避免频繁请求
+				clearTimeout(this.searchTimer);
+				this.searchTimer = setTimeout(() => {
+					this.queryCollect();
+				}, 500); // 500毫秒延迟
+			},
+
+			// 显示购买提示信息
+			showPurchaseMessage() {
+				// 清除之前的定时器
+				if (this.purchasePromptTimer) {
+					clearTimeout(this.purchasePromptTimer);
+				}
+
+				// 显示提示
+				this.showPurchasePrompt = true;
+
+				// 2秒后自动隐藏
+				this.purchasePromptTimer = setTimeout(() => {
+					this.showPurchasePrompt = false;
+				}, 2000);
+			},
+
+			//名字超过省略
+			truncateString(str, maxLength) {
+				if (typeof str !== 'string' || str.length <= maxLength) {
+					return str;
+				}
+				return str.slice(0, maxLength) + '...'; // 截断后加省略号
+			},
+			// 跳转页面
+			navgetTo(url) {
+				uni.navigateTo({
+					url: url
+				});
+			},
+			// 查询用户积分领取记录
+			completionRecords() {
+				if (!this.liveId) return;
+				const data = {
+					liveId: this.liveId
+				}
+				completionRecords(data).then((res) => {
+					if (res.code == 200) {
+						const targetData = res.data.find(item => item.liveId == this.liveId);
+						if (targetData) {
+							// 找到匹配的数据
+							const receiveStatus = targetData.receiveStatus;
+							this.receiveStatus = receiveStatus;
+						} else {
+							console.log('未找到liveId为', this.liveId, '的数据');
+							this.receiveStatus = false; // 或其他默认值
+						}
+						console.log("查询用户积分领取记录", res)
+					}
+				}).catch((error) => {
+
+				});
+			},
+
+			// 修改获取直播信息方法
+			async getliving(liveId) {
+				if (!liveId) return;
+				// 防止重复请求
+				if (this.isLoadingLiveInfo) {
+					console.log('正在加载直播间信息,跳过重复请求');
+					return;
+				}
+				this.isLoadingLiveInfo = true;
+				const param = {id: liveId};
+				try {
+					const res = await getlive(param);
+					this.isLoadingLiveInfo = false;
+					if (res.code !== 200) {
+						uni.showToast({
+							title: res.msg,
+							icon: 'none'
+						});
+						return;
+					}
+					this.liveItem = Object.assign({}, this.liveItem, res.data);
+					if (res.data.globalVisible || res.data.singleVisible) {
+						this.myselfFlag = true;
+					}
+					//this.talklist = Array.isArray((res.data || {}).talklist) ? res.data.talklist : [];
+					//this.startTimeTimer(this.liveItem);
+				
+					// 清除旧定时器(如预告倒计时)
+					if (this.liveStartTimer) {
+						clearInterval(this.liveStartTimer);
+						this.liveStartTimer = null;
+					}
+					if (res.data.status == 1) {
+						// 直播预告
+						this.liveStartTimer = setInterval(async () => {
+							this.liveCountdown = this.handleTime(res.data.startTime, 0);
+							if (!this.liveCountdown) {
+								uni.removeStorageSync('isAgreement');
+								await this.getliving(this.liveId);
+								clearInterval(this.liveStartTimer);
+							}
+						}, 1000);
+						this.$set(this.liveItem, 'previewUrl', res.data.previewUrl);
+						this.$set(this.liveItem, 'livingUrl', ''); // 清空直播流
+						this.$set(this.liveItem, 'videoUrl', ''); // 清空回放视频
+					} else if (res.data.status == 2) {
+						if (res.data.liveType == 1) {  // 直播流
+							let cTime = Math.floor(Math.random() * 10000) + 1;
+							let livingUrl = res.data.flvHlsUrl + '&t=' + cTime;
+							console.log('地址在', this.liveItem.livingUrl);
+							this.$set(this.liveItem, 'livingUrl', livingUrl);
+							this.$set(this.liveItem, 'videoUrl', ''); // 清空回放视频
+						} else if (res.data.liveType === 2) {
+							// 回放视频   2录播 3直播回放
+							// let urlStr = 'https://fs-1319721001.cos.ap-chongqing.myqcloud.com/10%E6%9C%8820%E6%97%A5%20%281%29.m3u8'
+							// this.$set(this.liveItem, 'videoUrl', urlStr);
+							this.$set(this.liveItem, 'videoUrl', res.data.videoUrl);
+							this.$set(this.liveItem, 'livingUrl', '');
+						}
+					} else if (res.data.status == 4 && res.data.liveType == 3) {
+						this.$set(this.liveItem, 'videoUrl', res.data.videoUrl);
+						this.$set(this.liveItem, 'livingUrl', '');
+					} else {
+						// 未开播
+						this.$set(this.liveItem, 'livingUrl', '');
+						this.$set(this.liveItem, 'videoUrl', '');
+					}
+					if (this.liveItem.configJson) {
+						this.completionRate = JSON.parse(this.liveItem.configJson).completionRate *0.01
+					}
+					console.log("查询当前用户当前直播间领取积分的剩余时长", this.liveId)
+					this.getRemainingTime(); //查询当前用户当前直播间领取积分的剩余时长
+
+					this.$set(this.liveItem, 'autoplay', res.data.liveType !== 0);
+					this.$set(this.liveItem, 'showType', res.data.showType);
+					this.storeId = res.storeId;
+					
+					console.log("qxj living",this.liveItem);
+					
+					this.diffLiveStartTime=this.calculateLiveTimeDiff(this.liveItem.startTime);
+					if(this.diffLiveStartTime<0){ //预告
+						this.isPreview=true;
+						this.liveBeginWatchTime=Date.now();  
+					}else{
+						if(!this.hasLiveEnd){ //没经历过直播结束
+							this.liveBeginWatchTime=Date.now();  
+						}
+					}
+					this.startLiveViewDataTimer();
+					this.completionRecords();
+					// 初始化观看时间统计
+					this.initWatchTime();
+					const diff = this.getTimeDifferenceInSeconds(this.liveItem.startTime)
+					if (diff >= this.liveItem.duration) {
+						const diffTime = diff - this.liveItem.duration
+						if (diffTime < 180) {
+							this.generating = true;
+							this.pauseWatchDurationTracking()
+							// 计算剩余等待时间
+							const remainingTime = Math.max(0, 180 - diffTime) * 1000;
+							if (this.generatingTimer) {
+								clearTimeout(this.generatingTimer);
+							}
+							this.generatingTimer = setTimeout(() => {
+								this.generating = false;
+								this.hasPlayback = true;
+								this.playVideo();
+								// this.closeWebSocket(true);
+								this.isEnd = true;
+							}, remainingTime);
+
+						} else {
+
+							// 已经超过18秒,应该直接播放
+							this.generating = false;
+							this.hasPlayback = true;
+							this.playVideo();
+							this.resumeWatchDurationTracking()
+							// this.closeWebSocket(true);
+							this.isEnd = true;
+						}
+					} else {
+						// 直播还未结束,正常播放
+						this.playVideo();
+					}
+				} catch (err) {
+					this.isLoadingLiveInfo = false;
+					console.error('获取直播信息失败:', err);
+					uni.showToast({
+						title: '获取直播信息失败',
+						icon: 'none'
+					});
+				}
+			},
+
+			getPureDecimal(num, precision = 6) {
+				const decimalPart = Math.abs(num).toFixed(precision).split('.')[1];
+				return decimalPart?.replace(/0+$/, '') || ''; // 移除末尾多余的0
+			},
+
+			goBack() {
+				// 暂停当前视频
+				if (this.liveItem) {
+					this.pauseVideo();
+				}
+				// 关闭WebSocket连接
+				this.closeWebSocket(true);
+				
+				// 导航返回
+				// const pages = getCurrentPages();
+				// if (pages.length > 1) {
+				// 	uni.navigateBack();
+				// } else {
+				// 	uni.reLaunch({
+				// 		url: '/pages_course/livingList'
+				// 	});
+				// }
+
+				const pages = getCurrentPages();
+				uni.reLaunch({ url: '/pages/home/index'});
+			},
+			// 点赞
+			async onLike() {
+				if (!this.liveId) return;
+				try {
+					const res = await liveDataLike(this.liveId);
+					if (res?.like) {
+						this.liveViewData.like++; //只更新当前直播间的点赞数
+					} else {
+						uni.showToast({
+							title: res.msg,
+							icon: 'none'
+						});
+					}
+				} catch (error) {
+					console.error('点赞失败:', error);
+				}
+			},
+
+			//直播间点赞、关注、在线人数数据
+			getliveViewData() {
+				if (!this.liveId) return;
+
+				// 使用 Promise 包装,支持 await
+				return getLiveViewData(this.liveId).then((res) => {
+					if (res.code == 200) {
+						// 强制响应式更新,确保数据实时显示
+						this.liveViewData = res;
+					}
+					return res;
+				}).catch((error) => {
+					console.error('获取直播间数据失败:', error);
+					// 失败时兜底,避免显示异常
+					this.liveViewData = {
+						like: 0,
+						watchCount: 0
+					};
+					throw error;
+				});
+			},
+			// 30秒刷新一下直播间点赞数
+			startLiveViewDataTimer() {
+				// 先清除旧定时器(防止重复创建)
+				if (this.liveViewDataTimer) {
+					clearInterval(this.liveViewDataTimer);
+					this.liveViewDataTimer = null;
+				}
+				this.getliveViewData();
+				this.liveViewDataTimer = setInterval(() => {
+					// 安全校验:确保liveItem和liveId存在(避免无效请求)
+					if (this.liveId) {
+						this.getliveViewData();
+					}
+				}, 20000);
+			},
+			// 去购买,跳商品详情
+			goShop(productId, goodsId) {
+				if (!this.liveId) return;
+				uni.navigateTo({
+					url: '/pages_shopping/live/goods?productId=' + productId + '&liveId=' +
+						this.liveId +
+						'&goodsId=' + goodsId + '&storeId=' + this.storeId
+				});
+			},
+
+			// 查询店铺
+			async queryCollect() {
+				this.loadingProducts = true;
+				if (!this.liveId) return;
+				if (this.inputInfo == null) this.inputInfo = '';
+				uni.showLoading({title: '加载中'});
+				try {
+					const res = await liveStore(this.liveId, this.inputInfo);
+					uni.hideLoading();
+					this.shopping = true;
+					if (res.code === 200) {
+						// 数据绑定到当前 liveItem,避免全局污染
+						this.products = Array.isArray(res.data) ? res.data : [];
+					}
+				} catch (error) {
+					console.error('获取小黄车商品失败:', error);
+				} finally {
+					this.loadingProducts = false;
+				}
+			},
+			// 时间戳
+			initTime() {
+				const now = new Date();
+				this.timestamp = now.getTime();
+			},
+
+			openCart() {
+				this.queryCollect();
+			},
+			close() {
+				this.showadd = false;
+			},
+
+			// 关闭小黄车
+			closeShop() {
+				this.shopping = false;
+			},
+			closeMore() {
+				this.isMore = false;
+			},
+			closeWin() {
+				this.winning = false;
+			},
+			// 关闭WebSocket连接(isManual:是否手动关闭)
+			closeWebSocket(isManual = true) {
+				if (!this.socket || !this.isSocketOpen) {
+					// console.warn('WebSocket 任务不存在或未打开,无需关闭');
+					return;
+				}
+
+				console.log(`WebSocket连接关闭 - ${isManual ? '手动' : '自动'}`);
+				this.isManualClose = isManual;
+
+				// 清理所有定时器和状态
+				this.cleanupAllResources();
+
+				try {
+					// 先保存引用,避免在关闭过程中被置为null
+					const socketToClose = this.socket;
+					this.socket = null;
+					this.isSocketOpen = false;
+					this.isConnecting = false;
+
+					socketToClose.close({
+						code: 1000,
+						reason: isManual ? '主动关闭' : '异常关闭'
+					});
+					console.log('WebSocket连接已发起关闭');
+				} catch (err) {
+					console.error('关闭WebSocket失败:', err);
+					// 即使关闭失败,也要重置状态
+					this.socket = null;
+					this.isSocketOpen = false;
+					this.isConnecting = false;
+				}
+			},
+
+			// 清理所有资源
+			cleanupAllResources() {
+				// 停止心跳相关
+				this.stopHeartBeat();
+
+				// 清理ping超时定时器
+				if (this.pingTimeoutTimer) {
+					clearTimeout(this.pingTimeoutTimer);
+					this.pingTimeoutTimer = null;
+				}
+
+				// 清理网络状态定时器
+				if (this.networkStatusTimer) {
+					clearTimeout(this.networkStatusTimer);
+					this.networkStatusTimer = null;
+				}
+
+				// 重置重连状态
+				this.resetReconnectState();
+
+				// 重置心跳相关状态
+				this.heartBeatRetryCount = 0;
+				this.lastHeartBeatTime = 0;
+				this.adaptiveHeartBeatInterval = this.heartBeatInterval;
+			},
+			startHeartBeat() {
+				this.stopHeartBeat(); // 先停止现有心跳,防止重复
+				// 使用自适应间隔循环发送心跳
+				this.heartBeatTimer = setInterval(() => {
+					this.sendHeartBeat();
+				}, this.adaptiveHeartBeatInterval);
+			},
+			initSocket() {
+				// 检查是否正在连接中
+				if (this.isConnecting) {
+					console.log('WebSocket正在连接中,跳过重复连接');
+					return;
+				}
+
+				// 检查网络状态
+				if (!this.isNetworkAvailable) {
+					console.warn('网络不可用,延迟WebSocket连接');
+					// 使用定时器而不是递归调用,避免内存泄漏
+					if (!this.networkRetryTimer) {
+						this.networkRetryTimer = setTimeout(() => {
+							this.networkRetryTimer = null;
+							this.initSocket();
+						}, 3000);
+					}
+					return;
+				}
+
+				// 如果已经存在连接且状态为open,则退出
+				if (this.socket && this.socket.readyState === 1) {
+					console.log('WebSocket连接已存在且正常,无需重新连接');
+					// 重置重连计数
+					this.reconnectCount = 0;
+					return;
+				}
+
+				// 关闭现有连接
+				if (this.socket && (this.socket.readyState === 0 || this.socket.readyState ===
+						1)) {
+					console.log('关闭现有WebSocket连接,创建新连接');
+					this.closeWebSocket(false); // 非手动关闭
+					// 等待一小段时间确保连接完全关闭
+					setTimeout(() => {
+						this.createWebSocketConnection();
+					}, 100);
+					return;
+				}
+
+				this.createWebSocketConnection();
+			},
+			createWebSocketConnection() {
+				// 校验必要参数
+				if (!this.liveId) {
+					console.error('缺失直播间ID,无法初始化WebSocket');
+					return;
+				}
+				if (!this.userInfo || !this.userInfo.userId) {
+					console.error('用户信息缺失,无法初始化WebSocket');
+					return;
+				}
+
+				// 设置连接状态
+				this.isConnecting = true;
+				this.isSocketOpen = false;
+
+				// 记录连接开始时间(性能监控)
+				this.connectionStartTime = Date.now();
+
+				// 清除之前的重连定时器
+				this.resetReconnectState();
+
+				const now = new Date();
+				this.timestamp = now.getTime(); // 生成签名
+				const signature = CryptoJS.HmacSHA256(
+					`${this.liveId}${this.userInfo.userId}${this.userType}${this.timestamp}`,
+					this.timestamp.toString()
+				).toString(CryptoJS.enc.Hex);
+
+				try {
+					const baseWsUrl = 'wss://ws.klbycp.com/ws/app/webSocket';
+					// const baseWsUrl = 'wss://api.fhhx.runtzh.com/ws/app/webSocket';
+					// const baseWsUrl = 'ws://d6998672.natappfree.cc/ws/app/webSocket';
+					// const baseWsUrl = 'ws://nd967d83.natappfree.cc/ws/app/webSocket';
+					let wsUrl =
+						`${baseWsUrl}?userId=${this.userInfo.userId}&liveId=${this.liveId}&userType=${this.userType}&timestamp=${this.timestamp}&signature=${signature}`;
+
+					// let wsUrl =
+					// 	'ws://q96d9752.natappfree.cc/ws/app/webSocket?liveId=128&userId=9769&userType=1&timestamp=1762501143712&signature=0498c66c3fca64ab009586200c04d51312ce44e36d5639e99b22e34f3bac8d13';
+					if (this.qrFrom) {
+						wsUrl += this.qrFrom;
+					}
+					if (this.urlOption.qwUserId) {
+						wsUrl += `&qwUserId=${this.urlOption.qwUserId}`;
+					}
+					if (this.urlOption.qwExternalId) {
+						wsUrl += `&externalContactId=${this.urlOption.qwExternalId}`;
+					}
+					// if(this.address){
+					// console.log("this.address是什么>>>", this.address)
+					wsUrl += `&location=${this.address}`;
+					// wsUrl += `&location=${encodeURIComponent(liveWatchUser)}`;
+					// }
+					console.log("qxj wsUrl", wsUrl);
+					console.log(
+						`尝试连接WebSocket: ${wsUrl.replace(/signature=[^&]+/, 'signature=***')}`
+					);
+					const socketTask = uni.connectSocket({
+						url: wsUrl,
+						success: () => {
+							console.log("WebSocket连接请求发送成功");
+						},
+						fail: (err) => {
+							console.error('WebSocket连接请求失败:', err);
+							this.isConnecting = false;
+							this.handleConnectionError('连接请求失败', err);
+						}
+					});
+
+					// 连接打开事件
+					socketTask.onOpen((res) => {
+						console.log("WebSocket连接已打开");
+						this.socket = socketTask;
+						this.isConnecting = false;
+						this.isSocketOpen = true;
+
+						// 计算连接延迟(性能监控)
+						if (this.connectionStartTime > 0) {
+							this.connectionLatency = Date.now() - this
+								.connectionStartTime;
+							console.log(`WebSocket连接延迟: ${this.connectionLatency}ms`);
+						}
+
+						this.reconnectCount = 0;
+						this.resetReconnectState();
+						this.heartBeatRetryCount = 0; // 重置心跳重试次数
+						this.shownEntryUsers.clear(); // 重连后重置进入提示记录
+
+						// 连接成功后显示提示(仅首次连接)
+						if (this.reconnectCount === 0) {
+							console.log('WebSocket连接建立成功');
+						} else {
+							console.log(`WebSocket重连成功(第${this.reconnectCount}次尝试)`);
+						}
+						this.startHeartBeat();
+						// 启动观看时长统计
+						//this.startWatchDurationTracking();
+					});
+
+					// 消息接收事件
+					socketTask.onMessage((res) => {
+						// 消息计数(性能监控)
+						this.messageCount++;
+						try {
+							//console.log("qxj onMessage handleSocketMessage",res);
+							const data = JSON.parse(res.data);
+							// 处理服务端心跳响应 - 修复:后端返回的是heartBeat而不是heartBeatAck
+							if (!!data.data && data.data.cmd === 'heartbeat') {
+								// console.log('收到心跳响应:', data.data);
+								// 清除ping超时定时器
+								if (this.pingTimeoutTimer) {
+									clearTimeout(this.pingTimeoutTimer);
+									this.pingTimeoutTimer = null;
+								}
+								// 重置心跳重试次数
+								this.heartBeatRetryCount = 0;
+								// 更新网络状态为良好
+								this.adjustHeartBeatInterval(true);
+								return;
+							}
+							this.handleSocketMessage(res);
+
+						} catch (err) {
+							console.error('消息解析异常:', err);
+							this.errorCount++; // 错误计数
+						}
+					});
+					// 连接错误事件
+					socketTask.onError((err) => {
+						console.error('WebSocket连接错误:', err);
+						this.errorCount++; // 错误计数
+						this.isSocketOpen = false;
+						this.isConnecting = false;
+						this.stopHeartBeat();
+						this.handleConnectionError('连接错误', err);
+					});
+
+					// 连接关闭事件
+					socketTask.onClose((res) => {
+						console.log('WebSocket连接关闭:', res);
+						this.isSocketOpen = false;
+						this.isConnecting = false;
+						this.stopHeartBeat(); // 清除心跳定时器
+						// 暂停观看时长统计
+						this.pauseWatchDurationTracking();
+
+						// 根据关闭原因决定是否重连
+						if (!this.isManualClose) {
+							if (res.code === 1000) {
+								console.log('WebSocket正常关闭,不进行重连');
+							} else {
+								console.warn(
+									`WebSocket异常关闭 (code: ${res.code}, reason: ${res.reason})`
+								);
+								this.handleReconnect();
+							}
+						} else {
+							console.log('WebSocket手动关闭,不进行重连');
+						}
+					});
+				} catch (e) {
+					console.error('创建WebSocket异常:', e);
+					this.handleReconnect();
+				}
+			},
+			handleTime(time, duration) {
+				let timeStamp;
+
+				if (typeof time === 'number' && time > 0 && time < 9999999999999) {
+					timeStamp = time;
+				} else if (typeof time === 'string' && time.trim() !== '') {
+					// 手动解析 CST 时间字符串
+					const match = time.match(
+						/^(\w{3}) (\w{3}) (\d{1,2}) (\d{1,2}):(\d{2}):(\d{2}) CST (\d{4})$/
+					);
+
+					if (match) {
+						const [, day, month, date, hours, minutes, seconds, year] = match;
+
+						// 月份映射
+						const monthMap = {
+							'Jan': 0,
+							'Feb': 1,
+							'Mar': 2,
+							'Apr': 3,
+							'May': 4,
+							'Jun': 5,
+							'Jul': 6,
+							'Aug': 7,
+							'Sep': 8,
+							'Oct': 9,
+							'Nov': 10,
+							'Dec': 11
+						};
+
+						// 创建日期对象(CST 是 UTC+8,与中国时区一致)
+						const jsDate = new Date(
+							parseInt(year),
+							monthMap[month],
+							parseInt(date),
+							parseInt(hours),
+							parseInt(minutes),
+							parseInt(seconds)
+						);
+						timeStamp = jsDate.getTime();
+					} else {
+						// 如果不是预期格式,回退到普通解析
+						const date = new Date(time);
+						if (!isNaN(date.getTime())) {
+							timeStamp = date.getTime();
+						} else {
+							console.error('无效的日期格式:', time);
+							return false;
+						}
+					}
+				} else {
+					console.error('time参数必须是有效的时间戳(数字)或日期字符串');
+					return false;
+				}
+
+				const targetTimestamp = timeStamp + duration * 60 * 1000;
+				const currentTimestamp = Date.now();
+				const timeDiffMs = targetTimestamp - currentTimestamp;
+
+				if (timeDiffMs <= 0) {
+					return false;
+				}
+
+				const hours = Math.floor(timeDiffMs / (1000 * 60 * 60));
+				const minutes = Math.floor((timeDiffMs % (1000 * 60 * 60)) / (1000 * 60));
+				const seconds = Math.floor((timeDiffMs % (1000 * 60)) / 1000);
+
+				const formatNum = (num) => num.toString().padStart(2, '0');
+				return {
+					hours: formatNum(hours),
+					minutes: formatNum(minutes),
+					seconds: formatNum(seconds)
+				};
+			},
+			// 限制聊天消息数量,防止内存泄漏
+			addToTalkList(message) {
+				// console.log("修改后的message>>", message)
+				// 减少最大消息数量,提升iPhone性能
+				const MAX_TALK_ITEMS = 30;
+
+				// 直接操作数组,避免创建新数组
+				if (!Array.isArray(this.talklist)) {
+					this.talklist = [];
+				}
+
+				const wasAtLimit = this.talklist.length >= MAX_TALK_ITEMS;
+				//console.log(`添加消息前: 当前消息数量=${this.talklist.length}, 是否达到限制=${wasAtLimit}`);
+
+				// 检查是否是自己发送的消息
+				const isMyMessage = message.userId === this.userInfo.userId;
+				//console.log(`消息来源: ${isMyMessage ? '自己' : '他人'}, userId=${message.userId}`);
+
+				// 给消息添加唯一ID
+				message.uniqueId = ++this.messageIdCounter;
+				let msgdata = JSON.parse(message.data);
+				message.msgId = msgdata.msgId;
+				this.talklist.push(message);
+
+				// 当消息超过限制时,批量删除旧消息
+				if (this.talklist.length > MAX_TALK_ITEMS) {
+					const removeCount = this.talklist.length - MAX_TALK_ITEMS;
+					//console.log(`消息超过限制,删除前${removeCount}条旧消息`);
+					this.talklist.splice(0, removeCount);
+				}
+				//console.log(`添加消息后: 当前消息数量=${this.talklist.length}`);
+
+				// 强制触发视图更新
+				this.$forceUpdate();
+
+				// 使用单次nextTick确保DOM更新后再滚动
+				this.$nextTick(() => {
+					this.forceScrollToBottomOnSend();
+				});
+			},
+			// 处理Socket消息
+			async handleSocketMessage(message) {
+				try {
+					let data = JSON.parse(message.data);
+					const socketMessage = data.data; // 服务端返回的消息体
+					//console.log("qxj handleSocketMessage socketMessage",socketMessage);
+					if (data.code == 200) {
+						const messageData = {
+							...socketMessage,
+							cmd: socketMessage.cmd || '', // 确保cmd字段存在
+							ts: Date.now() // 时间戳
+						};
+						// 处理服务端返回的sendMsg消息,加入本地列表
+						if (socketMessage.cmd == 'sendMsg') {
+							if (!this.isSocketAvailable()) {
+								uni.showToast({
+									title: '连接已断开,正在重试...',
+									icon: 'none'
+								});
+								this.handleReconnect();
+								return;
+							}
+							this.addToTalkList(messageData);
+						} else if (socketMessage.cmd == 'red') {
+							const redData = socketMessage.data ? JSON.parse(socketMessage.data) : {};
+							this.redInfo = redData || {};
+							this.isShowRed = socketMessage.status === 1;
+							if (this.isShowRed) {
+								this.redTimer = setInterval(() => {
+									const redCountdown = this.handleTime(this
+										.redInfo.updateTime, this.redInfo
+										.duration);
+									if (!redCountdown) {
+										this.isShowRed = false;
+										clearInterval(this.redTimer);
+									}
+								}, 1000);
+							}
+						} else if (socketMessage.cmd == 'goods') {
+							const goodsData = socketMessage.data ? JSON.parse(socketMessage
+								.data) : {};
+							this.goodsCard = goodsData || {};
+							this.isShowGoods = socketMessage.status == 1;
+						} else if (socketMessage.cmd == 'coupon') {
+							const couponData = socketMessage.data ? JSON.parse(
+								socketMessage.data) : {};
+							this.couponInfo = couponData || {};
+							this.isShowCoupon = socketMessage.status === 1;
+							if (this.isShowCoupon) {}
+						} else if (socketMessage.cmd == 'likeDetail') {
+							this.liveViewData.like = socketMessage.data;
+						} else if (socketMessage.cmd == 'lottery') {
+							const lotteryData = socketMessage.data ? JSON.parse(
+								socketMessage.data) : {};
+							this.lotteryInfo = lotteryData || {};
+							this.isShowLottery = socketMessage.status === 1;
+							if (socketMessage.status != 1) {
+								this.isShowLotteryPop = false;
+							}
+							// 清除已有定时器(无论状态是否为1,先清掉旧的)
+							clearInterval(this.lotteryTimer);
+							if (this.isShowLottery) {
+								this.lotteryTimer = setInterval(() => {
+									this.countdown = this.handleTime(this
+										.lotteryInfo.updateTime, this
+										.lotteryInfo.duration);
+									if (!this.countdown) {
+										console.log('倒计时', this.countdown);
+										this.isShowLottery = false;
+										this.isShowLotteryPop = false;
+										clearInterval(this.lotteryTimer);
+									}
+								}, 1000);
+							} else {
+								this.isShowLottery = false;
+							}
+						} else if (socketMessage.cmd == 'globalVisible' || socketMessage
+							.cmd == 'singleVisible') {
+							//  status = 1的时候,用户消息自可见,其他消息丢失}
+							if (socketMessage.status == 1) {
+								this.myselfFlag = true;
+							} else {
+								this.myselfFlag = false;
+							}
+
+						} else if (socketMessage.cmd == 'sendPopMsg') {
+							this.popMsg = socketMessage.msg
+							this.isShowPopMsg = true
+						} else if (socketMessage.cmd == 'sendTopMsg') {
+							clearInterval(this.noticeTimer);
+							const noticeData = socketMessage.data ? JSON.parse(
+								socketMessage.data) : {};
+							this.notice = noticeData || {};
+							this.isShowNotice = true
+							if (this.isShowNotice) {
+								this.noticeTimer = setInterval(() => {
+									const noticeCountdown = this.handleTime(this
+										.notice.endTime, 0);
+									if (!noticeCountdown) {
+										this.isShowNotice = false;
+										clearInterval(this.noticeTimer);
+									}
+								}, 1000);
+							}
+
+						} else if (socketMessage.cmd == 'entry') {
+							try {
+								if (!this.liveUserCalled) {
+									this.liveUserCalled = true;
+								}
+								const userIdToEntry = socketMessage.userId;
+								const existingIndex = this.liveViewersData.findIndex((
+										item) => item.userId ===
+									userIdToEntry);
+
+								if (existingIndex === -1) {
+									const liveViewers = {
+										userId: socketMessage.userId,
+										nickName: socketMessage.nickName,
+										avatar: socketMessage.avatar
+									};
+									this.liveViewersData.push(liveViewers);
+									this.liveUserTotal++;
+								}
+
+								// 解析用户ID(根据实际接口字段调整,此处假设data含userId)
+								const userInfo = JSON.parse(socketMessage.data || '{}');
+								const userId = userInfo.userId || socketMessage
+									.userId; // 兼容不同字段
+								if (!userId) return; // 无用户ID不处理
+
+								// 仅新用户(未显示过)才触发提示
+								if (!this.shownEntryUsers.has(userId)) {
+									this.inAndOut = socketMessage;
+									this.showWelcomeMessage = true;
+									this.shownEntryUsers.add(userId); // 加入已显示集合
+									messageData.msg = '来了'
+									this.addToTalkList(messageData);
+
+									// 3秒后隐藏提示(可调整时长)
+									if (this.welcomeTimer) clearTimeout(this.welcomeTimer);
+									this.welcomeTimer = setTimeout(() => {
+										this.showWelcomeMessage = false;
+									}, 3000);
+								}
+							} catch (err) {
+								console.error('解析entry用户数据失败:', err);
+							}
+						} else if (socketMessage.cmd == 'out') {
+							if (this.liveUserTotal > 0) {
+								const userIdToRemove = socketMessage.userId;
+								const index = this.liveViewersData.findIndex((item) => item
+									.userId === userIdToRemove);
+								if (index !== -1) {
+									this.liveViewersData.splice(index, 1);
+									this.liveUserTotal--; // 根据userId删除对应的用户数据
+								}
+							}
+							this.inAndOut = socketMessage;
+							this.showWelcomeMessage = true;
+
+							// 3秒后隐藏提示
+							if (this.welcomeTimer) clearTimeout(this.welcomeTimer);
+							this.welcomeTimer = setTimeout(() => {
+								this.showWelcomeMessage = false;
+							}, 3000);
+						} else if (socketMessage.cmd == 'live_start' || socketMessage.cmd == 'live_end') {
+							// 开始直播,关闭直播
+							if (this.liveStartTimer) {
+								clearInterval(this.liveStartTimer);
+								this.liveStartTimer = null;
+							}
+							if (this.redTimer) {
+								clearInterval(this.redTimer);
+								this.redTimer = null;
+							}
+							if(socketMessage.cmd == 'live_start'){
+								this.liveBeginWatchTime=Date.now();
+							}
+							if(socketMessage.cmd == 'live_end'){
+								this.hasLiveEnd=true;
+							}
+							//  请求最新直播间数据
+							this.$nextTick(() => {
+								this.getliving(this.liveId);
+							});
+							
+						} else if (socketMessage.cmd == 'Integral') {
+							this.integral = {
+								msg: socketMessage.msg,
+								status: true
+							};
+						}
+						// else if (socketMessage.cmd == 'completionPoints') {
+						// 	uni.showToast({
+						// 		title: socketMessage.msg,
+						// 		icon: 'none',
+						// 		duration: 3000
+						// 	});
+						// 	this.completionUnreceived()
+						// } 
+						// else if (socketMessage.cmd == 'completionPoints') {
+						// 	// 先显示toast
+						// 	uni.showToast({
+						// 		title: socketMessage.msg,
+						// 		icon: 'none',
+						// 		duration: 3000
+						// 	});
+
+						// 	// 1秒后关闭弹窗并执行completionUnreceived
+						// 	setTimeout(() => {
+						// 		// 如果需要手动关闭toast(虽然设置了3秒自动关闭,但这里提前关闭)
+						// 		uni.hideToast();
+
+						// 		// 执行completionUnreceived方法
+						// 		this.completionUnreceived();
+						// 	}, 1000); // 1000毫秒 = 1秒
+						// } 
+						else if (socketMessage.cmd == 'userCount') {
+							// 广播在线人数
+							this.virtualHuman = socketMessage.data * 10
+
+						} else if (socketMessage.cmd == 'deleteMsg') {
+							const index = this.talklist.findIndex(item => item.msgId ==
+								socketMessage.msg);
+							if (index !== -1) {
+								this.talklist.splice(index, 1);
+							}
+						} else if (socketMessage.cmd == 'LotteryDetail') {
+							try {
+								this.prizeInfo = Array.isArray(JSON.parse(socketMessage
+									.data || '[]')) ? JSON.parse(
+									socketMessage.data || '[]') : [];
+							} catch (err) {
+								console.error('解析抽奖结果失败:', err);
+								this.prizeInfo = [];
+							}
+							this.isShowPrize = true;
+							this.isShowLottery = false;
+							this.isShowLotteryPop = false;
+						} else if (socketMessage.cmd == 'blockUser') {
+							uni.removeStorage({
+								key: 'AppToken',
+								success: () => {
+									uni.reLaunch({
+										url: '/pages/auth/login'
+									});
+								}
+							});
+						}
+					} else {
+						uni.showToast({
+							title: data.msg,
+							icon: 'none'
+						});
+					}
+				} catch (error) {
+					console.error('Socket消息处理失败:', error);
+				}
+			},
+
+			sendMsg(retries = 1) {
+				// 防止连续点击发送两次(800ms短时锁定)
+				if (this.isSending) return;
+				this.isSending = true;
+				setTimeout(() => {
+					this.isSending = false;
+				}, 800);
+				const text = (this.value || '').trim();
+				if (!text) {
+					uni.showToast({
+						title: '不能发送空消息',
+						icon: 'none'
+					});
+					return;
+				}
+				if (!this.isSocketAvailable()) {
+					if (retries > 0) {
+						uni.showToast({
+							title: `连接不稳定,正在重试(${retries}次)...`,
+							icon: 'none'
+						});
+						// 延迟500ms重试,重试次数减1
+						setTimeout(() => this.sendMsg(retries - 1), 500);
+					} else {
+						uni.showToast({
+							title: '连接已断开,发送失败',
+							icon: 'none'
+						});
+						this.value = text; // 恢复输入框内容
+					}
+					return;
+				}
+				const liveId = this.liveId;
+				this.value = ''; // 立即清空输入框
+				// 构造发送给服务端的消息数据
+				const data = {
+					liveId,
+					userId: this.userInfo.userId,
+					userType: 0,
+					cmd: 'sendMsg',
+					msg: text,
+					nickName: this.userInfo.nickname || '未命名',
+					avatar: this.userInfo.avatar ||
+						'https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/avatar.png'
+				};
+				// 发送socket消息
+				try {
+					if (this.myselfFlag) {
+						this.addToTalkList(data);
+						this.forceScrollToBottomOnSend();
+					} else {
+						this.socket.send({
+							data: JSON.stringify(data),
+							success: () => {
+								this.value = '';
+								// 发送成功后强制滚动到底部,无论当前滚动位置如何
+								this.forceScrollToBottomOnSend();
+							},
+							fail: (err) => {
+								console.error('消息发送失败:', err);
+								if (retries > 0) {
+									uni.showToast({
+										title: `发送失败,正在重试(${retries}次)`,
+										icon: 'none'
+									});
+									setTimeout(() => this.sendMsg(retries - 1),
+										500);
+								} else {
+									uni.showToast({
+										title: '发送失败,请稍后再试',
+										icon: 'none'
+									});
+									this.value = text; // 恢复输入框内容
+								}
+							}
+						});
+					}
+
+				} catch (err) {
+					console.error('发送消息异常:', err);
+					if (retries > 0) {
+						setTimeout(() => this.sendMsg(retries - 1), 500);
+					} else {
+						uni.showToast({
+							title: '发送失败,请稍后再试',
+							icon: 'none'
+						});
+						this.value = text;
+					}
+				}
+			},
+			formatUserNum() {
+
+				let userTotal = 0;
+				if (!this.liveUserTotal) {
+					this.liveUserTotal = 0;
+				}
+				if (this.liveUserTotal > 0) {
+					userTotal = this.liveUserTotal = 0;
+				}
+				if (this.liveUserTotal > 10000) {
+					userTotal = (this.liveUserTotal / 10000.0).toFixed(1);
+					userTotal = userTotal + "万";
+				}
+				console.log("qxj userTotal", userTotal);
+				return userTotal;
+
+
+			},
+		}
+
+	};
+</script>
+
+<style scoped lang="scss">
+	/* 退出全屏按钮 */
+	.fullscreen-exit-btn {
+		position: fixed;
+		bottom: 40rpx;
+		left: 82vh;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		z-index: 100001;
+		background: rgba(57, 57, 57, 0.6);
+		border-radius: 40rpx;
+		padding: 20rpx 24rpx;
+		transition: all 0.3s ease;
+
+		&:active {
+			transform: scale(0.95);
+			background: rgba(50, 50, 50, 0.6);
+		}
+
+		.exit-fullscreen-icon {
+			width: 40rpx;
+			height: 40rpx;
+			margin-bottom: 10rpx;
+		}
+
+		.exit-text {
+			color: #ffffff;
+			font-size: 22rpx;
+			white-space: nowrap;
+		}
+	}
+
+	.video-container.fullscreen-mode .fullscreen-exit-btn {
+		z-index: 999999 !important;
+	}
+
+	.fullscreen-mode {
+		background-color: #000 !important;
+	}
+
+	/* 全屏模式样式 */
+	.video-container.fullscreen-mode {
+		// width: auto !important;
+		// height: auto !important;
+		z-index: 99999 !important;
+		background-color: #000 !important;
+		transform: rotate(90deg) !important;
+		transform-origin: center center !important;
+
+		.video-player {
+			width: 100vh !important;
+			height: 100vw !important;
+			// object-fit: contain !important;
+		}
+	}
+
+	/* 全屏时隐藏其他元素 */
+	.video-container.fullscreen-mode~* {
+		display: none !important;
+	}
+
+	.video-container {
+		position: relative;
+		bottom: -1px;
+		transition: all 0.3s ease;
+	}
+
+	.video-container2 {
+		position: relative;
+		bottom: -1px;
+		transition: all 0.3s ease;
+	}
+
+	.video-player.fullscreen {
+		width: 100vh !important;
+		height: 100vw !important;
+		object-fit: contain !important;
+	}
+
+
+
+	/* 全屏按钮样式优化 */
+	.custom-controls {
+		position: absolute;
+		bottom: 24rpx;
+		right: 40rpx;
+		z-index: 9999;
+		background: rgba(0, 0, 0, 0.6);
+		border-radius: 50%;
+		width: 80rpx;
+		height: 80rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		transition: all 0.3s ease;
+
+		&:active {
+			transform: scale(0.95);
+			background: rgba(0, 0, 0, 0.8);
+		}
+	}
+
+	.control-icon {
+		width: 46rpx;
+		height: 46rpx;
+	}
+
+
+
+	@media screen and (orientation: landscape) {
+		.video-container.horizontal-layout {
+			width: 100%;
+			height: 100%;
+		}
+
+		// .video-player {
+		// 	width: 100vh !important;
+		// 	height: 100vw !important;
+		// }
+	}
+
+
+
+
+	// 重置按钮样式
+	.button-reset {
+		background-color: transparent !important;
+		padding: 0 !important;
+		line-height: 1 !important;
+		margin: 0 !important;
+		width: auto !important;
+		// font-weight: 500 !important;
+		border-radius: none !important;
+
+		&::after {
+			border: none !important;
+			padding: 0 !important;
+			margin: 0 !important;
+		}
+	}
+
+	// :deep(.u-tabs__wrapper__nav) {
+	// 	background-color: #fff !important;
+	// }
+
+	.swiper-wrapper {
+		/* 深色主题变量 */
+		--bottom-color: transparent;
+		--bg-color: #242424;
+		--text-color: #ffffff;
+		--name-color: #8CE7FF;
+		--normal-bg: rgba(0, 0, 0, 0.3);
+		--input-bg: rgba(0, 0, 0, 0.3);
+		--chat-bg: transparent;
+		--video-height: 100vh;
+		--chat-height: 30vh;
+		--pop-bg: #333333;
+		--notice-bg: rgba(9, 9, 9, 0.4);
+	}
+
+	.swiper-wrapper.horizontal {
+		--notice-bg: #fefae8;
+		--pop-bg: #ECF5F4;
+		/* 默认变量(浅色主题) */
+		--bottom-color: #fff;
+		--name-color: #666666;
+		--bg-color: #ffffff;
+		--text-color: #333333;
+		--normal-bg: #fff;
+		--input-bg: #F5F7FA;
+		--chat-bg: #ECF5F4; //对话聊天
+		--video-height: 500rpx;
+		--chat-height: clac(100% - 650rpx);
+	}
+
+
+
+	// 主容器
+	.swiper-wrapper {
+		position: relative;
+		width: 100%;
+		height: 100vh;
+		overflow: hidden;
+		/* 应用变量 */
+		background: var(--bg-color);
+		color: var(--text-color);
+
+		.container {
+			width: 100%;
+			height: 100%;
+			position: relative;
+			transition: opacity 0.3s ease;
+			transform: translateZ(0);
+			will-change: opacity;
+
+			// 预告直播盒子
+			.trailer-box {
+				width: calc(100% - 80rpx);
+				background: var(--pop-bg);
+				border-radius: 24rpx;
+				position: absolute;
+				top: 16%;
+				left: 50%;
+				transform: translateX(-50%);
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				color: var(--text-color);
+				padding: 20rpx;
+				z-index: 999;
+				box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.12);
+				transition: box-shadow 0.3s ease;
+
+				.trailer-video {
+					width: 100%;
+					height: 100%;
+					position: absolute;
+					z-index: 1;
+					border-radius: 20rpx;
+				}
+
+				.trailer-placeholder {
+					margin-bottom: 40rpx;
+					width: 240rpx;
+					height: 240rpx;
+				}
+
+				.countdown-container {
+					margin: 20rpx 0;
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+
+					.live-name {
+						font-weight: 600;
+						font-size: 36rpx;
+					}
+
+					.countdown-display {
+						display: flex;
+						align-items: center;
+						margin: 30rpx 0;
+
+						.countdown-label {
+							font-size: 24rpx;
+							color: #999999;
+						}
+
+						.countdown-separator {
+							font-size: 24rpx;
+							color: #999999;
+						}
+
+						.countdown-unit {
+							width: 40rpx;
+							height: 40rpx;
+							background: #4D4D4D;
+							border-radius: 8rpx;
+							text-align: center;
+							overflow: hidden;
+							margin: 0 8rpx;
+							font-weight: 500;
+							font-size: 28rpx;
+							color: #FFFFFF;
+							line-height: 40rpx;
+						}
+					}
+				}
+
+				.trailer-actions {
+					display: flex;
+					justify-content: center;
+					align-items: center;
+
+					.action-button {
+						width: 280rpx;
+						height: 72rpx;
+						border-radius: 36rpx;
+						line-height: 72rpx;
+						text-align: center;
+						color: #fff;
+
+						&.reserve-button {
+							background: linear-gradient(136deg, #38D97D 0%, #02B176 100%);
+						}
+
+						&:not(.reserve-button) {
+							background: #F4A007;
+						}
+
+						.button-icon {
+							width: 32rpx;
+							height: 32rpx;
+						}
+					}
+				}
+
+				.no-live-title {
+					margin-top: 30rpx;
+					font-size: 42rpx;
+					font-weight: 500;
+				}
+			}
+
+			// 新预告直播盒子
+			.trailer-box2 {
+				width: 100%;
+				position: absolute;
+				top: 16%;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				z-index: 999;
+				transition: box-shadow 0.3s ease;
+				height: 400rpx;
+
+				.trailer-video {
+					width: 100%;
+					height: 100%;
+					position: absolute;
+					z-index: 1;
+				}
+
+				.trailer-placeholder {
+
+					position: absolute;
+					top: 0;
+					left: 0;
+					width: 100%;
+					height: 100%;
+					z-index: -1;
+					/* 置于内容下方 */
+				}
+
+				.countdown-container {
+					padding-top: 15%;
+					margin: 20rpx 0;
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+
+					.live-name {
+						font-weight: 600;
+						font-size: 36rpx;
+					}
+
+					.countdown-display {
+						display: flex;
+						align-items: center;
+						margin: 30rpx 0;
+
+						.countdown-label {
+							font-size: 32rpx;
+							color: rgba(250, 214, 176, 1);
+						}
+
+						.countdown-separator {
+							font-size: 24rpx;
+							color: #999999;
+						}
+
+						.countdown-unit {
+							width: 60rpx;
+							height: 60rpx;
+							background: rgba(255, 246, 214, 1);
+							border-radius: 8rpx;
+							text-align: center;
+							overflow: hidden;
+							margin: 0 8rpx;
+							font-weight: 500;
+							font-size: 36rpx;
+							color: rgba(0, 75, 59, 1);
+							line-height: 60rpx;
+						}
+					}
+				}
+
+				.trailer-actions {
+					display: flex;
+					justify-content: center;
+					align-items: center;
+
+					.action-button {
+						width: 280rpx;
+						height: 72rpx;
+						border-radius: 36rpx;
+						display: flex;
+						justify-content: center;
+						align-items: center;
+						text-align: center;
+						border: 1px solid rgba(151, 151, 151, 1);
+						font-size: 36rpx;
+						font-weight: bold;
+
+						&.reserve-button {
+							color: rgba(0, 110, 80, 1);
+							background: linear-gradient(231.51deg, rgba(249, 215, 178, 1) 0%, rgba(255, 255, 191, 1) 47.83%, rgba(255, 250, 229, 1) 65.77%, rgba(248, 214, 178, 1) 100%);
+
+						}
+
+						&:not(.reserve-button) {
+							color: rgba(255, 246, 214, 1);
+							background: rgba(0, 110, 80, 1);
+						}
+
+						.button-icon {
+							width: 32rpx;
+							height: 32rpx;
+						}
+					}
+				}
+
+				.no-live-title {
+					margin-top: 30rpx;
+					font-size: 42rpx;
+					font-weight: 500;
+				}
+			}
+
+			// 主要内容区域
+			.content {
+				position: relative;
+				z-index: 2;
+				height: 100%;
+				width: 100%;
+				top: 0;
+				left: 0;
+				display: flex;
+				flex-direction: column;
+
+
+				&.horizontal-content {
+					z-index: 999;
+				}
+
+				&.trailer-content {
+					justify-content: space-between;
+				}
+
+				// 顶部信息栏
+				.top-info-bar {
+					position: fixed;
+					top: 0;
+					z-index: 5;
+					width: 100%;
+					padding: 0 24rpx;
+					box-sizing: border-box;
+					// margin-top:calc(var(--status-bar-height) + 10rpx);
+					display: flex;
+					justify-content: space-between;
+					flex-direction: column;
+
+					&.horizontal-top {
+						position: static;
+						margin-bottom: 30rpx;
+
+					}
+
+					.user-info-section {
+						display: flex;
+						align-items: center;
+
+						.back-icon {
+							width: 60rpx;
+							height: 64rpx;
+						}
+
+						.user-avatar-container {
+							padding: 6rpx 8rpx;
+							height: 64rpx;
+							background: var(--normal-bg);
+							border-radius: 32rpx;
+							display: flex;
+							align-items: center;
+
+							.user-name {
+								color: var(--text-color);
+							}
+						}
+					}
+
+					.viewers-section {
+						display: flex;
+						justify-content: flex-end;
+						align-items: center;
+						margin-top: 30rpx;
+
+						.viewer-avatar {
+							width: 52rpx;
+							height: 52rpx;
+							border-radius: 26rpx;
+						}
+
+						.viewer-avatar-placeholder {
+							width: 52rpx;
+							height: 52rpx;
+							border-radius: 50%;
+							display: flex;
+							align-items: center;
+							justify-content: center;
+
+							.avatar-initial {
+								color: var(--text-color);
+								font-size: 18rpx;
+							}
+						}
+
+						.viewer-count {
+							width: 80rpx;
+							height: 52rpx;
+							background: var(--normal-bg);
+							border-radius: 26rpx;
+							font-size: 30rpx;
+							color: var(--text-color);
+							text-align: center;
+							line-height: 52rpx;
+						}
+					}
+				}
+
+				// 购买提示
+				.purchase-prompt {
+					position: absolute;
+					bottom: 750rpx;
+					left: 24rpx;
+					padding: 6rpx 20rpx;
+					background: rgba(230, 154, 34, 0.7);
+					border-radius: 24rpx;
+					z-index: 9;
+					font-weight: 500;
+					color: #ffffff;
+					transition: opacity 0.3s ease;
+					font-size: 30rpx;
+					display: flex;
+					align-items: center;
+
+					.prompt-icon {
+						width: 32rpx;
+						height: 32rpx;
+					}
+				}
+
+				// 视频区域
+				.videolist {
+					position: relative;
+					// height: var(--video-height);
+					width: 100%;
+
+					&.screen {
+						width: 100%;
+						height: 100%;
+						//height: 100vh;
+					}
+
+					.video-container {
+						//height: var(--video-height);
+						width: 100%;
+						transform: translateZ(0);
+						backface-visibility: hidden;
+						perspective: 1000;
+
+						&.horizontal-layout {
+							// position: absolute;
+							// top: 20%;
+							// max-height: 450rpx;
+							// z-index: 99;
+						}
+
+						.complaint-box {
+							position: absolute;
+							// top: 20%;
+							right: 20rpx;
+							width: 140rpx;
+							margin-top: 20rpx;
+							display: flex;
+							align-items: center;
+							justify-content: center;
+							background-color: rgba(57, 57, 57, 0.6);
+							padding: 16rpx 0;
+							color: #fff;
+							border-radius: 28rpx;
+							z-index: 999999 !important;
+
+							&.complaint-full {
+								// top: 10rpx;
+								left: 82vh;
+							}
+
+							&:active {
+								transform: scale(0.95);
+								background: rgba(50, 50, 50, 0.6);
+							}
+						}
+
+						.txt {
+							text-align: center;
+							font-weight: 500;
+							font-size: 40rpx;
+							line-height: var(--video-height);
+						}
+
+						.video-player {
+							width: 100%;
+							height: 100%;
+							position: absolute;
+							z-index: 1;
+						}
+
+						.live-end-message {
+							position: absolute;
+							top: 50%;
+							left: 50%;
+							transform: translate(-50%, -50%);
+							font-size: 36rpx;
+							color: var(--text-color);
+						}
+
+						.replay-label {
+							position: absolute;
+							// top: 10%;
+							right: 24rpx;
+							background-color: rgba(57, 57, 57, 0.6);
+							width: 100rpx;
+							height: 70rpx;
+							line-height: 70rpx;
+							text-align: center;
+							color: #fff;
+							border-radius: 15rpx;
+							z-index: 999999 !important;
+
+							&.replay-full {
+								left: 82vh;
+								// top: 16% !important;
+							}
+						}
+
+						.look-time {
+							position: absolute;
+							left: 24rpx;
+							bottom: 24rpx;
+							font-size: 20rpx;
+							background-color: rgba(57, 57, 57, 0.6);
+							border-radius: 15rpx;
+							z-index: 999999 !important;
+							padding: 10rpx 16rpx;
+							color: #fff;
+
+							&.look-full {
+								left: 10vh;
+							}
+						}
+					}
+				}
+			}
+
+			// 侧边
+			.slide-group {
+				position: absolute;
+				right: 20rpx;
+				top: 60%;
+				z-index: 9000;
+
+				.action-button-group {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					margin-top: 50rpx;
+				}
+
+				.action-icon {
+					width: 88rpx;
+					height: 88rpx;
+				}
+
+				.icon-button {
+					// background: var(--normal-bg);
+					// border-radius: 50%;
+					width: 88rpx;
+					height: 88rpx;
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					transition: transform 0.2s ease;
+
+					// margin-left: 10rpx;
+
+					&.like-container {
+						display: flex;
+						flex-direction: column;
+						justify-content: center;
+						align-items: center;
+
+						.like-count {
+							position: absolute;
+							bottom: -40rpx;
+							font-size: 24rpx;
+							color: #FA341E;
+							padding: 6rpx 16rpx;
+							background: #FFFFFF;
+							border-radius: 30rpx;
+						}
+					}
+
+
+				}
+			}
+
+			// 聊天区域
+			.chat-area-container {
+				background: var(--chat-bg);
+				position: fixed;
+				width: 100%;
+				bottom: 0;
+				z-index: 999;
+				transform: translateZ(0);
+				will-change: transform;
+				backface-visibility: hidden;
+
+				&.chat-area-container2 {
+					flex: 1;
+					min-height: 0; // 重要:允许收缩到0
+					position: relative;
+					transform: none; // 移除之前的变换
+					will-change: auto;
+					display: flex;
+					flex-direction: column;
+				}
+
+				&.chat-area-container3 {
+					height: calc(85% - 420rpx);
+					flex: 1;
+					transform: none; // 移除之前的变换
+					will-change: auto;
+					display: flex;
+					flex-direction: column;
+					position: absolute;
+				}
+
+				&.chat-area-container4 {
+					height: calc(85% - 680rpx);
+					flex: 1;
+					transform: none; // 移除之前的变换
+					will-change: auto;
+					display: flex;
+					flex-direction: column;
+					position: absolute;
+					// max-height: 40%;
+					// flex: 1;
+					// min-height: 0; // 重要:允许收缩到0
+					// // position: relative;
+					// transform: none; // 移除之前的变换
+					// will-change: auto;
+					// display: flex;
+					// flex-direction: column;
+					// position: absolute;
+				}
+
+				&.chat-area-container5 {
+					height: calc(85% - 450rpx);
+					flex: 1;
+					transform: none; // 移除之前的变换
+					will-change: auto;
+					display: flex;
+					flex-direction: column;
+					position: absolute;
+					// max-height: 40%;
+					// flex: 1;
+					// min-height: 0; // 重要:允许收缩到0
+					// // position: relative;
+					// transform: none; // 移除之前的变换
+					// will-change: auto;
+					// display: flex;
+					// flex-direction: column;
+					// position: absolute;
+				}
+
+				&.chat-area-focused {
+					transform: translateY(calc(-1 * var(--keyboard-height, 0rpx))) translateZ(0);
+					z-index: 1000;
+				}
+
+				.tabs_bg {
+					background-color: #fff;
+					padding: 0 40rpx;
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					height: 96rpx;
+
+					.complaint-box {
+						width: 120rpx;
+						height: 48rpx;
+						background: #FFFFFF;
+						border-radius: 24rpx 24rpx 24rpx 24rpx;
+						border: 2rpx solid #EEEEEE;
+						display: flex;
+						justify-content: center;
+						align-items: center;
+					}
+				}
+
+				.chat-content-wrapper {
+					flex: 1;
+					height: 400rpx;
+					padding: 20rpx 0;
+					transform: translateZ(0);
+					will-change: height;
+					position: relative;
+
+					&.chat-content-focused {
+						height: 100rpx !important;
+					}
+
+					.notice-message {
+						font-size: 36rpx;
+						position: absolute;
+						bottom: 388rpx;
+						max-width: 80%;
+						padding: 24rpx;
+						background-color: var(--notice-bg);
+						margin: 0 0 20rpx 20rpx;
+						border-radius: 20rpx;
+						color: #0d0b05;
+						font-weight: 500;
+						overflow: hidden;
+
+						&.horizontal-notice {
+							top: 12rpx;
+							height: fit-content;
+							z-index: 2;
+						}
+
+						&.horizontal-notice2 {
+							color: #fff !important;
+							top: 12rpx;
+							height: fit-content;
+							z-index: 2;
+						}
+					}
+
+					.message-scroll-view {
+						width: calc(100% - 20rpx);
+						height: 100%;
+						padding-left: 20rpx;
+						display: flex;
+						flex: 1;
+						flex-direction: column;
+						-webkit-overflow-scrolling: touch;
+
+						&.message-scroll2 {
+							height: 300rpx;
+						}
+					}
+
+					.message-list {
+						width: 80%;
+						margin-bottom: 16rpx;
+						animation: simpleFade 0.2s;
+
+						.message-item {
+							display: flex;
+							justify-content: flex-start;
+
+							.message-content {
+								font-size: 30rpx;
+								max-width: 100%;
+								border-radius: 30rpx;
+								background: var(--normal-bg);
+								padding: 10rpx 30rpx;
+								line-height: 1.4;
+								word-break: break-all;
+								word-wrap: break-word;
+								overflow-wrap: break-word;
+
+								.user-nickname {
+									color: var(--name-color);
+								}
+
+								.message-text {
+									color: var(--text-color);
+								}
+							}
+						}
+					}
+				}
+
+
+				// 输入和操作区域
+				.input-actions-container {
+					position: relative;
+					z-index: 999999;
+					background-color: var(--bottom-color);
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					padding: 24rpx;
+
+					&.input-actions-focused {
+						justify-content: flex-start !important;
+						align-items: stretch !important;
+						width: 100% !important;
+						display: flex !important;
+					}
+
+					.input-container {
+						background: var(--input-bg);
+						box-sizing: border-box;
+						border-radius: 36rpx;
+						display: flex;
+						align-items: center;
+						transform: translateZ(0);
+						will-change: transform;
+						backface-visibility: hidden;
+						perspective: 1000px;
+
+						&.input-container-normal {
+							padding: 18rpx 20rpx;
+							width: auto;
+							max-width: auto;
+							margin-right: 0;
+							justify-content: space-between;
+						}
+
+						&.input-container-focused {
+							padding: 10rpx 10rpx 10rpx 20rpx;
+							width: 100%;
+							max-width: calc(100% - 20rpx);
+							margin-right: 20rpx;
+							// flex: 1;
+							justify-content: flex-start;
+						}
+
+						.chat-input {
+							border: none !important;
+							font-size: 32rpx !important;
+							color: var(--text-color) !important;
+							background: transparent !important;
+							width: 70% !important;
+							transform: translateZ(0);
+							will-change: contents, width;
+							backface-visibility: hidden;
+							margin-left: 20rpx;
+
+							&.input-focused {
+								width: 100% !important;
+								flex: 1 !important;
+								min-width: 0 !important;
+								margin-left: 10rpx !important;
+								max-width: none !important;
+							}
+						}
+
+						.send-button {
+							background-color: #ffffff;
+							border-radius: 28rpx;
+							padding: 14rpx 16rpx;
+							color: #181818;
+							font-weight: 500;
+							min-width: 80rpx;
+							text-align: center;
+							flex-shrink: 0;
+
+							&.send2 {
+								background-color: #2fa9f1;
+								color: #ffffff;
+							}
+						}
+
+					}
+
+					.action-buttons {
+						display: flex;
+						justify-content: space-between;
+						align-items: center;
+						flex: auto;
+						// margin-right: 15rpx;
+						transform: translateZ(0);
+						justify-content: flex-end;
+
+						&.action-buttons-hidden {
+							opacity: 0;
+							visibility: hidden;
+						}
+
+						.action-icon {
+							width: 48rpx;
+							height: 48rpx;
+						}
+
+						.cart-icon {
+							width: 58rpx;
+							height: 58rpx;
+						}
+
+
+					}
+				}
+			}
+
+			// 商品卡片
+			.goods-card {
+				position: fixed;
+				bottom: 140rpx;
+				right: 24rpx;
+				z-index: 5;
+				background-color: #fff;
+				border-radius: 20rpx;
+				overflow: hidden;
+				width: 224rpx;
+				padding: 4rpx;
+
+				.goods-card-header {
+					position: absolute;
+					top: 4rpx;
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					color: #fff;
+					width: 100%;
+					padding-right: 10rpx;
+					box-sizing: border-box;
+
+					.goods-status {
+						background: rgba(0, 0, 0, 0.4);
+						padding: 12rpx;
+						font-size: 22rpx;
+						display: flex;
+						justify-content: space-between;
+						align-items: center;
+						border-radius: 10rpx;
+
+						.status-icon {
+							width: 30rpx;
+							height: 30rpx;
+						}
+					}
+
+					.close-icon {
+						width: 24rpx;
+						height: 24rpx;
+					}
+				}
+
+				.goods-image {
+					width: 100%;
+					height: 224rpx;
+					border-radius: 16rpx 16rpx 0 0;
+					overflow: hidden;
+				}
+
+				.goods-info {
+					padding: 4rpx;
+
+					.goods-title {
+						font-weight: 500;
+						font-size: 24rpx;
+						margin: 10rpx 0 12rpx;
+						color: #111111;
+					}
+
+					.goods-action {
+						color: #fff;
+						text-align: center;
+						font-weight: 500;
+						font-size: 30rpx;
+						position: relative;
+
+						.goods-price {
+							left: 10rpx;
+							position: absolute;
+							top: 40%;
+							transform: translateY(-50%);
+							font-size: 30rpx;
+							z-index: 999;
+
+							.price-symbol {
+								font-weight: 600;
+								font-size: 20rpx;
+								color: #FFFFFF;
+							}
+
+							.price-integer {
+								font-size: 36rpx;
+								margin-right: 10rpx;
+							}
+						}
+
+						.shop-icon {
+							width: 204rpx;
+							height: 52rpx;
+						}
+					}
+				}
+			}
+
+			// 动画
+			@keyframes simpleFade {
+				from {
+					opacity: 0;
+				}
+
+				to {
+					opacity: 1;
+				}
+			}
+
+			.userlogo {
+				padding: 36rpx 40rpx;
+				color: #000000;
+
+				.mt42 {
+					margin-top: 42rpx;
+				}
+
+				.boxweixin {
+					width: 44rpx;
+					height: 44rpx;
+					border-radius: 50%;
+					text-align: center;
+					line-height: 34rpx;
+					color: #0a0;
+				}
+
+				.button-container {
+					position: relative;
+					margin: auto;
+
+					.hidden-input {
+						width: calc(100vw - 80rpx);
+						text-align: center;
+						height: 104rpx;
+						background: #07C160;
+						padding: 30rpx 0;
+						box-sizing: border-box;
+						border-radius: 12rpx;
+						font-size: 32rpx !important;
+						color: #FFFFFF !important;
+						/* 输入文字大小 */
+					}
+
+					/* 针对 placeholder 的样式 */
+					.hidden-input::placeholder {
+						font-size: 44rpx !important;
+						color: #FFFFFF !important;
+					}
+
+					/* 兼容微信小程序的 placeholder 样式 */
+					.hidden-input .placeholder {
+						font-size: 44rpx !important;
+						color: #FFFFFF !important;
+					}
+				}
+
+				.submitname {
+					height: 104rpx;
+					line-height: 104rpx;
+					background: #F2F2F2;
+					border-radius: 12rpx;
+					font-size: 32rpx;
+					color: #07C160;
+					margin-top: 32rpx;
+					text-align: center;
+				}
+			}
+
+			// 抽奖弹窗1
+			.lottery-popup {
+				position: relative;
+				border-radius: 40rpx;
+				height: fit-content;
+
+				.lottery-header-image {
+					width: 311rpx;
+					position: absolute;
+					top: -122rpx;
+					left: 50%;
+					transform: translateX(-50%);
+				}
+
+				.lottery-background-image {
+					position: absolute;
+					top: 0;
+					left: 0;
+					width: 100%;
+					height: 100%;
+					z-index: 1;
+				}
+
+				.lottery-content {
+					position: relative;
+					z-index: 2;
+					padding: 24rpx 0 68rpx;
+
+					.lottery-close-section {
+						display: flex;
+						justify-content: flex-end;
+						margin-right: 20rpx;
+
+						.close-button-wrapper {
+							.close-button {
+								width: 80rpx;
+								height: 80rpx;
+								display: flex;
+								justify-content: center;
+								align-items: center;
+							}
+						}
+					}
+
+					.lottery-main-content {
+						display: flex;
+						flex-direction: column;
+						align-items: center;
+
+						.lottery-title-image {
+							width: 446rpx;
+							height: 80rpx;
+						}
+
+						.lottery-countdown-section {
+							font-size: 24rpx;
+							color: #fff;
+							display: flex;
+							align-items: center;
+							margin: 30rpx 0;
+
+							.countdown-label {
+								margin-right: 10rpx;
+							}
+
+							.countdown-timer {
+								display: flex;
+								align-items: center;
+
+								.countdown-number {
+									width: 40rpx;
+									height: 40rpx;
+									text-align: center;
+									overflow: hidden;
+									background: #ffffff;
+									box-shadow: inset 0rpx 2rpx 8rpx 0rpx #ffebb2;
+									border-radius: 8rpx;
+									margin: 4rpx;
+									font-weight: 600;
+									font-size: 24rpx;
+									color: #f85d22;
+									line-height: 40rpx;
+								}
+							}
+						}
+
+						.lottery-products-section {
+							width: 100%;
+						}
+
+						.lottery-indicators {
+							margin: 20rpx 0 50rpx;
+							display: flex;
+							gap: 6rpx;
+
+							.indicator-point {
+								width: 20rpx;
+								height: 8rpx;
+								background: rgba(255, 255, 255, 0.5);
+								border-radius: 4rpx;
+
+								&.selected {
+									background: #ffeb66;
+								}
+							}
+						}
+
+						.lottery-tip {
+							color: #fff;
+							font-size: 28rpx;
+						}
+
+						.lottery-action-button {
+							margin-top: 30rpx;
+							width: 520rpx;
+							height: 88rpx;
+							line-height: 88rpx;
+							background: linear-gradient(180deg, #fff4d6 0%, #ffeb66 100%);
+							box-shadow: 0rpx 10rpx 8rpx 4rpx rgba(246, 82, 25, 0.5);
+							border-radius: 44rpx;
+							font-weight: 500;
+							font-size: 36rpx;
+							color: #f4410b;
+							text-align: center;
+						}
+					}
+				}
+			}
+
+			// 积分弹窗
+			.integral-popup {
+				min-width: 400rpx;
+				max-width: 600rpx;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				border-radius: 20rpx;
+				overflow: hidden;
+
+				.integral-header {
+					width: 100%;
+					position: relative;
+
+					.integral-title {
+						width: 100%;
+						font-weight: 600;
+						font-size: 40rpx;
+						color: #ffffff;
+						text-shadow: 0px 4rpx 8rpx rgba(255, 89, 2, 0.8);
+						position: absolute;
+						top: 50rpx;
+						text-align: center;
+					}
+
+					.integral-background-image {
+						width: 100%;
+					}
+				}
+
+				.integral-content {
+					padding: 20rpx;
+
+					.integral-message {
+						font-weight: 500;
+						font-size: 32rpx;
+						text-align: center;
+					}
+
+					.integral-confirm-button {
+						font-size: 32rpx;
+						margin-top: 20rpx;
+						background: linear-gradient(270deg, #ff4702 0%, #fe6304 100%);
+						color: #fff;
+						text-align: center;
+						padding: 18rpx 60rpx;
+						border-radius: 10rpx;
+						font-weight: 500;
+					}
+				}
+			}
+
+			// 红包弹窗
+			.red-envelope-popup {
+				width: 504rpx;
+				position: relative;
+				text-align: center;
+				height: 610rpx;
+				display: flex;
+				align-items: center;
+
+				.red-envelope-close-button {
+					position: absolute;
+					right: 0;
+					top: -180rpx;
+					width: 64rpx;
+					height: 64rpx;
+				}
+
+
+				.red-envelope-background {
+					width: 100%;
+					height: 100%;
+				}
+
+				.red-envelope-content {
+					position: absolute;
+					top: 0;
+					left: 50%;
+					transform: translateX(-50%);
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+					height: auto;
+
+					.red-envelope-header {
+						margin-top: 68rpx;
+						display: flex;
+						align-items: center;
+
+						.header-decoration-left,
+						.header-decoration-right {
+							width: 44rpx;
+							height: 20rpx;
+						}
+
+						.header-title {
+							margin: 0 12rpx;
+							font-size: 28rpx;
+							color: #FFF1BC;
+						}
+					}
+
+					.red-envelope-text {
+						font-weight: 600;
+						font-size: 80rpx;
+						color: #FFF1BC;
+						margin-top: 42rpx;
+					}
+
+					.red-envelope-open-text {
+						font-weight: 800;
+						font-size: 110rpx;
+						color: #F41420;
+						margin-top: 70rpx;
+					}
+				}
+			}
+
+			// 抽奖弹窗2
+			.lottery-popup-v2 {
+				width: 504rpx;
+				position: relative;
+				text-align: center;
+				height: 556rpx;
+				display: flex;
+				align-items: center;
+
+				.lottery-close-button-v2 {
+					position: absolute;
+					right: 0;
+					top: -180rpx;
+					width: 64rpx;
+					height: 64rpx;
+					z-index: 9;
+				}
+
+				.lottery-top-image {
+					position: absolute;
+					top: -214rpx;
+					width: 100%;
+				}
+
+				.lottery-background-v2 {
+					width: 100%;
+					height: 100%;
+				}
+
+				.lottery-content-v2 {
+					position: absolute;
+					top: 0;
+					left: 50%;
+					transform: translateX(-50%);
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+					height: auto;
+
+					.lottery-header-v2 {
+						margin-top: 68rpx;
+						display: flex;
+						align-items: center;
+
+						.lottery-header-decoration-left,
+						.lottery-header-decoration-right {
+							width: 44rpx;
+							height: 20rpx;
+						}
+
+						.lottery-header-title {
+							margin: 0 12rpx;
+							font-size: 28rpx;
+							color: #FFF1BC;
+							margin-top: 22rpx;
+						}
+					}
+
+					.lottery-text-v2 {
+						font-weight: 600;
+						font-size: 80rpx;
+						color: #FFF1BC;
+
+						&:last-of-type {
+							margin-bottom: 56rpx;
+						}
+					}
+
+					.lottery-action-button-v2 {
+						width: 424rpx;
+						height: 96rpx;
+						line-height: 96rpx;
+						background: linear-gradient(180deg, #FBF1CA 0%, #FFD684 100%);
+						border-radius: 48rpx;
+						font-weight: 600;
+						font-size: 36rpx;
+						color: #F12E2C;
+						margin-bottom: 52rpx;
+					}
+				}
+			}
+
+			// 红包卡片弹窗
+			.red-card-popup {
+				width: 550rpx;
+				height: 636rpx;
+				position: relative;
+
+				.red-card-image {
+					position: absolute;
+					width: 100%;
+					height: 100%;
+				}
+
+				.red-card-content {
+					position: relative;
+					z-index: 5;
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+
+					.red-card-message {
+						font-size: 36rpx;
+						color: #ff3a1e;
+						margin: 180rpx 0 90rpx;
+					}
+
+					.red-card-tip {
+						font-size: 28rpx;
+						color: #ffecc3;
+						margin: 80rpx 0 40rpx;
+					}
+
+					.red-card-confirm-button {
+						width: 392rpx;
+						height: 96rpx;
+						line-height: 96rpx;
+						background: linear-gradient(180deg, #fff4d5 0%, #ffe5b1 100%);
+						border-radius: 48rpx;
+						font-weight: 600;
+						font-size: 36rpx;
+						color: #c32008;
+						text-align: center;
+					}
+				}
+			}
+
+			// 消息弹窗
+			.message-popup {
+				display: flex;
+				flex-direction: column;
+				position: relative;
+				align-items: center;
+				padding: 126rpx 48rpx 0;
+				width: 554rpx;
+				box-sizing: border-box;
+				background: linear-gradient(180deg, #E2FCEF 0%, rgba(226, 252, 239, 0) 100%);
+				border-radius: 62rpx 62rpx 0rpx 0rpx;
+
+				.message-close-icon {
+					position: absolute;
+					z-index: 9;
+					top: -74rpx;
+					width: 176rpx;
+					height: 176rpx;
+				}
+
+				.message-title {
+					font-weight: 600;
+					font-size: 36rpx;
+					color: #333333;
+					margin: 24rpx 0 28rpx;
+				}
+
+				.message-content {
+					margin-bottom: 52rpx;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #333333;
+				}
+
+				.message-confirm-button {
+					width: 358rpx;
+					height: 88rpx;
+					line-height: 88rpx;
+					background: linear-gradient(136deg, #38D97D 0%, #02B176 100%);
+					border-radius: 44rpx 44rpx 44rpx 44rpx;
+					font-weight: 600;
+					font-size: 32rpx;
+					text-align: center;
+					color: #FFFFFF;
+				}
+
+				.close {
+					position: absolute;
+					z-index: 9;
+					bottom: -168rpx;
+					width: 64rpx;
+					height: 64rpx;
+				}
+			}
+
+			// 中奖弹窗
+			.prize-popup {
+				width: 504rpx;
+				padding: 40rpx 40rpx 30rpx;
+				box-sizing: border-box;
+				display: flex;
+				flex-direction: column;
+				border-radius: 20rpx;
+				align-items: center;
+				background: linear-gradient(180deg, #f7823f 0%, #ffd4be 27%, #ffffff 100%);
+				position: relative;
+
+				.prize-header-image {
+					width: 311rpx;
+					position: absolute;
+					top: -122rpx;
+					left: 50%;
+					transform: translateX(-50%);
+				}
+
+				.prize-title {
+					color: #c32008;
+					font-size: 34rpx;
+					font-weight: 600;
+					margin: 20rpx 0 40rpx;
+				}
+
+				.prize-info-section {
+					width: 100%;
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					font-size: 28rpx;
+					margin: 10rpx 0;
+
+					.prize-level {
+						font-weight: 600;
+					}
+				}
+
+				.prize-tip {
+					font-size: 28rpx;
+					color: #414141;
+					margin: 40rpx 0;
+				}
+
+				.prize-action-button {
+					width: 200rpx;
+					height: 70rpx;
+					line-height: 70rpx;
+					background: linear-gradient(180deg, #ff7c30 0%, #ff3a1e 100%);
+					border-radius: 28rpx;
+					font-weight: 500;
+					font-size: 32rpx;
+					color: #ffffff;
+					text-align: center;
+				}
+			}
+
+			// 未中奖弹窗
+			.no-prize-popup {
+				width: 504rpx;
+				padding: 40rpx 40rpx 30rpx;
+				box-sizing: border-box;
+				display: flex;
+				flex-direction: column;
+				border-radius: 20rpx;
+				align-items: center;
+				position: relative;
+
+				.no-prize-image {
+					margin-top: 40rpx;
+					width: 300rpx;
+					height: 300rpx;
+				}
+
+				.no-prize-tip {
+					font-size: 36rpx;
+					color: #414141;
+					margin: 40rpx 0;
+				}
+
+				.no-prize-confirm-button {
+					width: 220rpx;
+					height: 80rpx;
+					line-height: 80rpx;
+					background: linear-gradient(180deg, #fdfbb8 0%, #b79243 100%);
+					border-radius: 28rpx;
+					font-weight: 500;
+					font-size: 32rpx;
+					color: #ffffff;
+					text-align: center;
+				}
+			}
+
+			// 中奖记录弹窗
+			.winning-record-popup {
+				position: relative;
+				height: 800rpx;
+
+				.winning-record-header-bg {
+					position: absolute;
+					top: -125rpx;
+					left: 50%;
+					width: 311rpx;
+					transform: translateX(-50%);
+				}
+
+				.winning-record-background {
+					width: 100%;
+					height: 100%;
+				}
+
+				.winning-record-content {
+					position: absolute;
+					top: 50rpx;
+					color: #fff;
+					width: 100%;
+					padding: 0 36rpx;
+					box-sizing: border-box;
+
+					.winning-record-title {
+						text-align: center;
+						font-size: 40rpx;
+						font-weight: 500;
+						margin-bottom: 40rpx;
+					}
+
+					.winning-record-header {
+						display: flex;
+						justify-content: space-between;
+						text-align: center;
+						font-size: 34rpx;
+						margin-bottom: 40rpx;
+
+						.header-column {
+							&.time-column {
+								width: 45%;
+							}
+
+							&.status-column {
+								width: 20%;
+							}
+
+							&.prize-column {
+								width: 35%;
+							}
+						}
+					}
+
+					.winning-record-list {
+						height: 500rpx;
+
+						.winning-record-item {
+							display: flex;
+							justify-content: space-between;
+							text-align: center;
+							font-size: 34rpx;
+							margin-bottom: 20rpx;
+
+							.record-time {
+								width: 45%;
+								font-size: 30rpx;
+							}
+
+							.record-status-button {
+								width: 20%;
+								background-color: #fff;
+								border-radius: 20rpx;
+								color: #f4410b;
+							}
+
+							.record-status {
+								width: 20%;
+							}
+
+							.record-prize {
+								width: 35%;
+							}
+						}
+					}
+
+					.no-winning-records {
+						font-size: 36rpx;
+						margin-top: 150rpx;
+						text-align: center;
+					}
+				}
+			}
+
+			// 观众列表弹窗
+			.viewers-list-popup {
+				position: relative;
+				height: 40vh;
+				padding: 40rpx 0rpx;
+				box-sizing: border-box;
+				display: flex;
+				flex-direction: column;
+
+				.viewers-list-title {
+					font-size: 32rpx;
+					text-align: center;
+				}
+
+				.viewers-scroll-list {
+					flex: 1;
+					margin-top: 50rpx;
+					overflow-y: auto;
+					padding: 0 40rpx;
+
+					.viewer-list-item {
+						display: flex;
+						align-items: center;
+						font-size: 28rpx;
+						margin: 20rpx 0;
+
+						.rank-number {
+							width: 50rpx;
+							margin-right: 10rpx;
+							font-weight: normal;
+
+							&.rank-1 {
+								color: #FF3B30;
+								font-weight: bold;
+							}
+
+							&.rank-2 {
+								color: #FF9500;
+								font-weight: bold;
+							}
+
+							&.rank-3 {
+								color: #FFCC00;
+								font-weight: bold;
+							}
+
+							&:not(.rank-1):not(.rank-2):not(.rank-3) {
+								color: #8E8E93;
+							}
+						}
+
+						.viewer-avatar-placeholder {
+							width: 72rpx;
+							height: 72rpx;
+							border-radius: 50%;
+							display: flex;
+							align-items: center;
+							justify-content: center;
+							background-color: #8978e2;
+
+							.avatar-initial {
+								color: #ffffff;
+								font-size: 24rpx;
+							}
+						}
+
+						.viewer-name {
+							margin-left: 16rpx;
+							font-size: 30rpx;
+						}
+					}
+				}
+			}
+
+			// 更多操作弹窗
+			.more-actions-popup {
+				border-radius: 20rpx 0 0 20rpx;
+				padding: 70rpx 30rpx;
+				display: flex;
+				justify-content: space-between;
+
+				.more-action-item {
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+
+					.action-icon {
+						width: 48rpx;
+						height: 48rpx;
+					}
+
+					.action-label {
+						color: #1e1e1e;
+						text-align: center;
+						margin-top: 10rpx;
+					}
+				}
+			}
+
+			// 商品弹窗
+			.shopping-popup {
+				padding: 22rpx 16rpx;
+
+				.shopping-header {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					padding: 0 16rpx 22rpx;
+
+					.search-input-container {
+						width: 414rpx;
+						height: 76rpx;
+						background: #ffffff;
+						border-radius: 36rpx;
+						margin-left: 20rpx;
+						padding: 0 32rpx;
+						box-sizing: border-box;
+						font-size: 24rpx;
+						margin-right: 24rpx;
+						display: flex;
+						align-items: center;
+						color: #000;
+
+						.search-icon {
+							width: 24rpx;
+							margin-right: 16rpx;
+						}
+					}
+
+					.shopping-action-button {
+						display: flex;
+						flex-direction: column;
+						align-items: center;
+						font-size: 20rpx;
+						color: #222222;
+
+						.action-button-icon {
+							width: 48rpx;
+							height: 48rpx;
+						}
+
+						.action-button-label {
+							text-align: center;
+						}
+					}
+				}
+
+				.products-list {
+					height: 30vh;
+					overflow: hidden;
+
+					.product-item {
+						display: flex;
+						align-items: center;
+						padding: 20rpx 16rpx;
+						background: #ffffff;
+						border-radius: 16rpx;
+						margin-bottom: 16rpx;
+
+						.product-image-container {
+							width: 200rpx;
+							height: 200rpx;
+							border-radius: 16rpx;
+							overflow: hidden;
+							position: relative;
+							margin-right: 24rpx;
+
+							.product-image {
+								width: 100%;
+								height: 100%;
+							}
+
+							.product-index-label {
+								position: absolute;
+								top: 0;
+								width: 64rpx;
+								height: 40rpx;
+								background: var(--normal-bg);
+								border-radius: 16rpx 0rpx 16rpx 0rpx;
+								text-align: center;
+								font-weight: 500;
+								font-size: 28rpx;
+								color: var(--text-color);
+							}
+						}
+
+						.product-info {
+							flex: 1;
+
+							.product-name {
+								font-weight: 500;
+								font-size: 30rpx;
+								color: #000000;
+								margin-bottom: 10rpx;
+							}
+
+							.product-sales {
+								font-size: 22rpx;
+								color: #e69a22;
+								height: 56rpx;
+							}
+
+							.product-action-section {
+								display: flex;
+								justify-content: space-between;
+								align-items: center;
+
+								.product-price {
+									color: #ff5c03;
+									font-size: 22rpx;
+									font-weight: 500;
+
+									.price-symbol {
+										font-size: 20rpx;
+										font-weight: 600;
+									}
+
+									.price-integer {
+										font-size: 36rpx;
+										font-weight: bold;
+									}
+								}
+
+								.product-action-buttons {
+									display: flex;
+									align-items: center;
+									text-align: center;
+									line-height: 56rpx;
+
+									.collect-button {
+										width: 72rpx;
+										height: 100%;
+										background: #f5f7fa;
+										border-radius: 8rpx 0rpx 0rpx 8rpx;
+
+										.collect-icon {
+											width: 36rpx;
+											height: 36rpx;
+											vertical-align: middle;
+										}
+									}
+
+									.buy-button {
+										width: 152rpx;
+										background: linear-gradient(270deg, #ff5c03 0%, #ffac64 100%);
+										border-radius: 0rpx 8rpx 8rpx 0rpx;
+										font-weight: 500;
+										font-size: 30rpx;
+										color: #ffffff;
+
+										&.disabled {
+											background: #cccccc;
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+
+			.end {
+				justify-content: flex-end;
+			}
+
+			.progress-countdown {
+				position: absolute;
+				right: 20rpx;
+				top: calc(60% - 128rpx);
+				z-index: 9000;
+				width: 180rpx;
+				background: rgba(0, 0, 0, 0.3);
+				border-radius: 16rpx;
+				padding: 16rpx;
+				flex-direction: column;
+				&.progress-vertical {
+					top: 15%;
+					left: 24rpx;
+				}
+
+				.title {
+					width: 148rpx;
+					height: 28rpx;
+				}
+
+				.progress-bar-bg {
+					width: 148rpx;
+					height: 8rpx;
+					margin-top: 16rpx;
+					background: #FFFFFF;
+					border-radius: 6rpx 6rpx 6rpx 6rpx;
+					overflow: hidden;
+					margin-bottom: 16rpx;
+
+					.progress-bar-fill {
+						height: 100%;
+						// background: linear-gradient(90deg, #4CAF50, #8BC34A);
+						background: #FACE15;
+						border-radius: 6rpx 6rpx 6rpx 6rpx;
+						transition: width 1s linear;
+					}
+				}
+
+				.progress-text {
+					color: #fff;
+					font-size: 20rpx;
+				}
+			}
+
+			// 优惠券弹窗
+			.coupon-popup {
+				position: fixed;
+				bottom: 140rpx;
+				right: 100rpx;
+				z-index: 5;
+				border-radius: 20rpx;
+				width: 320rpx;
+				.coupon-container {
+					width: 100%;
+					position: relative;
+					.coupon-background {
+						height: 452rpx;
+						width: 100%;
+					}
+					.coupon-header {
+						position: absolute;
+						height: 120rpx;
+						top: -120rpx;
+						left: 0;
+						width: 100%;
+						z-index: 6;
+					}
+					.coupon-close-button {
+						position: absolute;
+						right: 10rpx;
+						top: 10rpx;
+						width: 40rpx;
+						height: 40rpx;
+						z-index: 99;
+					}
+
+					.coupon-content {
+						width: 100%;
+						position: absolute;
+						top: 20rpx;
+						display: flex;
+						flex-direction: column;
+						align-items: center;
+						color: #fff;
+
+						.coupon-name {
+							font-weight: 500;
+							font-size: 30rpx;
+							margin: 16rpx 0 12rpx;
+						}
+
+						.coupon-price {
+							font-size: 40rpx;
+
+							.coupon-price-integer {
+								font-size: 56rpx;
+								font-weight: 600;
+							}
+						}
+
+						.coupon-condition,
+						.coupon-description,
+						.coupon-validity {
+							font-weight: 500;
+							font-size: 30rpx;
+							margin: 5rpx 0;
+						}
+
+						.coupon-description {
+							margin-top: 26rpx;
+						}
+
+						.coupon-get-button {
+							background: linear-gradient(270deg, #fffce1 0%, #ffeaaf 100%);
+							color: #ff0004;
+							text-align: center;
+							padding: 16rpx 0;
+							border-radius: 40rpx;
+							font-weight: 500;
+							font-size: 30rpx;
+							width: 70%;
+							margin-top: 26rpx;
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 30 - 63
pages_course/video.vue

@@ -48,6 +48,9 @@
 				</cover-view>
 				<cover-image v-if="courseLogo" :class="isfull?'logo-full':'logo'" :src="courseLogo" mode="widthFix"></cover-image>
 			</video>
+			
+			
+			
 		</view>
 		<!-- 弹幕方法 -->
 		<commentBox
@@ -249,7 +252,6 @@
 				<view>阅读并同意<text style="color: #ff5c03;" @click.stop="goWeb(0)">《用户协议》</text>和<text
 						style="color: #ff5c03;" @click.stop="goWeb(1)">《隐私协议》</text></view>
 			</view> -->
-			<!-- <view class="footer-tips">重庆云联融智提供技术支持</view> -->
 		</view>
 		<view v-show="currentTab==2">
 			<view class="chatinput" :style="{bottom:danmuboxHeight>0?danmuboxHeight+'px':'calc(var(--window-bottom) + 24rpx)'}">
@@ -257,6 +259,9 @@
 				<button class="send" @click="handleChatInput">发送</button>
 			</view>
 		</view>
+		<ykscreenRecord></ykscreenRecord>
+		<courseExpiration v-if="showExpiration" :code="resCode" :msg="resMsg" :qrcode="qrcode"
+		:userId="user && user.userId ? user.userId : ''"></courseExpiration>
 	</view>
 </template>
 
@@ -281,16 +286,17 @@
 		loginByMp,
 		getRealLink
 	} from "@/api/courseAuto.js"
-	import {
-		getConfigByKey
-	} from "@/api/user.js"
 	import {handleFsUserWx} from '@/api/courseLook.js'
+	import ykscreenRecord from './yk-screenRecord/yk-screenRecord.vue'
+	import courseExpiration from './components/courseExpiration.vue'
 	export default {
 		components: {
 			descInfoNav,
 			descInfo,
 			commentBox,
 			ques,
+			ykscreenRecord,
+			courseExpiration
 		},
 		data() {
 			return {
@@ -427,6 +433,9 @@
 				videoitem:null,
 				// 是否公开课
 				isOpen: 0,
+				resMsg:'',
+				resCode:"",
+				showExpiration:false
 			}
 		},
 		//发送给朋友
@@ -470,7 +479,6 @@
 		    }
 		},
 		onLoad(option) {
-			this.getWebviewUrl()
 			if(option.videoitem){
 				this.isOpen = 1
 				this.urlOption=JSON.parse(option.videoitem)
@@ -480,9 +488,7 @@
 				}
 			}else {
 				this.isOpen = 0
-				console.log(option)
 				this.urlOption = option.course ? JSON.parse(option.course) : {}
-				console.log(this.urlOption)
 			}
 			uni.$on('usercode',(data)=>{
 				if(this.isSpare == 1&&data) {
@@ -535,10 +541,6 @@
 			if (this.player) {
 				this.player.pause()
 			}
-			// if (this.interval != null) {
-			// 	clearInterval(this.interval)
-			// 	this.interval = null
-			// }
 		},
 		onUnload() {
 			uni.$off('usercode')
@@ -568,23 +570,6 @@
 			// #endif
 		},
 		methods: {
-			getWebviewUrl() {
-				var data = {
-					key: 'course.config'
-				}
-					getConfigByKey(data).then(res => {
-						if (res.code == 200) {
-							console.log("getConfigByKey====", JSON.parse(res.data))
-							let data = JSON.parse(res.data,)
-							uni.setStorageSync('setWebviewUrl',data.userCourseAuthDomain)
-						}else{
-							uni.showToast({
-								icon:'none',
-								title: res.msg,
-							});
-						}
-					})
-			},
 			numberToChinese(number) {
 				if (number) {
 					const chineseNumber = ['一', '二', '三', '四', '五', '六', '七', '八', '九'];
@@ -800,11 +785,6 @@
 								this.lineIndex = this.config.defaultLine
 								this.videoUrl = lineList[this.lineIndex]
 								this.poster= res.course && res.course.imgUrl ? res.course.imgUrl : ''
-								// this.options.sources = [{
-								// 	src: this.videoUrl
-								// }]
-								// this.options.poster = res.course && res.course.imgUrl ? res.course.imgUrl : ''
-								// this.initVideo()
 								this.playTime = this.playDuration >= this.duration ? 0 : this.playDuration
 								this.playDurationSeek = this.playTime
 								setTimeout(()=>{
@@ -813,14 +793,6 @@
 									this.player.play();
 								},500);
 							} else {
-								// let div = document.querySelector(".vjs-progress-control");
-								// if(div) {
-								// 	if (this.isFinish == 1 || this.isEnded || this.videolinkType == 1) {
-								// 		div.style.pointerEvents = "auto";
-								// 	} else {
-								// 		div.style.pointerEvents = "none"; //禁止所有事件
-								// 	}
-								// }
 								this.playTime = this.playTime > this.playDuration ? this.playTime : this.playDuration >= this.duration ? 0 : this.playDuration
 								this.playDurationSeek = this.playTime
 								this.player.seek(this.playTime)
@@ -833,6 +805,11 @@
 									questionOption: JSON.parse(item.question),
 									answer: ''
 								}))
+						}else{
+							uni.showToast({
+								title: res.msg,
+								icon: "none"
+							})
 						}
 						this.getHeight()
 						this.$nextTick(()=>{
@@ -908,8 +885,7 @@
 					res => {
 						if(res){
 							if (this.isAddKf == 1) {
-								// 答题
-								// 您已提交过答案,请领取红包
+								//答题  您已提交过答案,请领取红包
 								this.courseAnswer()
 							} else {
 								// 添加客服
@@ -1083,14 +1059,6 @@
 					this.close()
 					return
 				} else {
-					// let div = document.querySelector(".vjs-progress-control");
-					// if(div) {
-					// 	if (this.isFinish == 1 || this.isEnded || this.videolinkType == 1) {
-					// 		div.style.pointerEvents = "auto";
-					// 	} else {
-					// 		div.style.pointerEvents = "none"; //禁止所有事件
-					// 	}
-					// }
 					this.lineIndex = index
 					this.videoUrl = this.lineList[index]
 					this.tipsOpen = false
@@ -1100,11 +1068,6 @@
 						that.player.seek(that.playDurationSeek)
 						that.player.play();
 					},500);
-					// this.player.src(this.lineList[index])
-					// this.player.one('loadedmetadata', () => {
-					// 	this.player.currentTime(this.playDurationSeek);
-					// 	this.player.play();
-					// });
 					this.close()
 				}
 
@@ -1123,7 +1086,6 @@
 				this.qrcode = ''
 				this.qrcodeMsg = ''
 				this.isAddKf = 0
-				// {videoId: this.videoId,qwUserId: this.qwUserId,corpId: this.corpId}
 				getIsAddKf(this.urlOption).then(res => {
 						if (res.code == 200) {
 							this.isAddKf = 1
@@ -1133,9 +1095,7 @@
 							this.qrcode = res.qrcode
 							this.qrcodeMsg = res.msg
 							this.$refs.kfPopup.open()
-						} else if (res.code == 504) {
-							// 登录
-							// this.goLogin()
+							this.initExpiration(res.msg,res.code)
 						} else if (res.code == 566) {
 							// 官方群发通用链接
 							const url = res.courseLink.realLink.split('?course=')[1]
@@ -1146,7 +1106,7 @@
 							// 群聊通用链接
 							this.urlOption = {
 								...this.urlOption,
-								qwExternalId: res.qwExternalId
+								qwExternalId:res.qwExternalId
 							}
 							this.isAddKf = 1
 							this.getH5CourseVideoDetails()
@@ -1156,17 +1116,23 @@
 								title: res.msg,
 								icon: 'none'
 							});
+							this.initExpiration(res.msg,res.code)
 						}
 					},
 					err => {}
 				);
 			},
+			initExpiration(resMsg,resCode) {
+				if(resCode==401) return;
+				this.resMsg = resMsg
+				this.resCode = resCode
+				this.showExpiration = true
+			},
 			closeKFPop() {
 				this.$refs.kfPopup.close()
 			},
 			getFinishCourseVideo() {
 				if (!this.playTime || this.isAddKf!=1 ||!this.isLogin) return
-				// {videoId: this.videoId,duration:this.playTime}
 				const param = {
 					duration: this.playTime,
 					...this.urlOption
@@ -1222,7 +1188,7 @@
 				})
 			},
 			goLogin(data) {
-				if(data || this.isSpare==1) {
+				if(data || (this.isSpare==1&&this.isOpen!=1)) {
 					this.loginFsUserWx(data)
 					return
 				}
@@ -1246,6 +1212,7 @@
 								}).then(res=>{
 									 uni.hideLoading();
 									 if (res.code == 200) {
+										this.$store.commit('setCoureLogin', 1);
 										uni.setStorageSync(TOKEN_KEYAuto, res.token);
 										uni.setStorageSync('auto_userInfo', JSON.stringify(res.user));
 										this.user = res.user

+ 163 - 0
pages_course/yk-screenRecord/yk-screenRecord.vue

@@ -0,0 +1,163 @@
+<template>
+	<view class="zzc_mol" v-if="isRecording"></view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				isRecording: false
+			}
+		},
+		created() {
+			this.screenInit();
+		},
+		onUnload() {
+			this.AllowScreenshots()
+		},
+		beforeDestroy() {
+			this.AllowScreenshots()
+		},
+		methods: {
+			screenInit() {
+				let _this = this;
+				// #ifdef H5
+				uni.showToast({
+					title: '请在APP或者小程序环境下操作',
+					icon: 'error'
+				})
+				// #endif
+				// #ifndef H5
+				uni.getSystemInfo({
+					success: function(e) {
+						// #ifdef APP-PLUS
+						if (e.platform == 'android') {
+							//注意:一旦开启禁止截屏/录屏后将会全局生效,关闭页面时记得放开允许截屏/录屏
+							_this.NoscreenCapture();
+						} else {
+							//在APP IOS端截屏、录屏暂时没办法实现,可以寻求原生解决
+						}
+						// #endif
+
+						// #ifdef MP-WEIXIN
+						if (e.platform == 'android') {
+							//微信小程序在安卓手机上 禁止截屏/录屏(注意:禁止后录屏动作还是会进行,但录屏后的视频是黑屏的)
+							wx.setVisualEffectOnCapture({
+								visualEffect: 'hidden', //传入 hidden 则表示在截屏/录屏时隐藏屏幕
+								success: (res) => {
+									console.log(res)
+								},
+								fail: (err) => {
+									console.log(err)
+								},
+								complete: (res) => {
+									console.log(res)
+								}
+							})
+						} else {
+							//微信小程序在IOS手机上,注意:目前微信小程序在ios上也只能通过监听录屏状态,然后通过添加view层来进行阻止,截屏暂时无法实现
+							//监听用户录屏事件
+							wx.onScreenRecordingStateChanged(function(res) {
+								if (res.state == 'start') {
+									_this.isRecording = true
+								} else {
+									_this.isRecording = false
+								}
+							})
+							//查询用户是否在录屏
+							wx.getScreenRecordingState({
+								success: (res) => {
+									if (res.state == 'on') {
+										_this.isRecording = true
+									} else if (res.state == 'off') {
+										_this.isRecording = false
+									}
+								},
+								fail: (err) => {
+									_this.isRecording = false
+								}
+							})
+						}
+						// #endif
+					}
+				})
+				// #endif
+			},
+			//安卓端禁止截屏
+			NoscreenCapture() {
+				let osname = plus.os.name;
+				if (osname == "Android") {
+					var activity = plus.android.runtimeMainActivity();
+					plus.android.invoke(plus.android.invoke(activity, "getWindow"), "addFlags", 0x00002000);
+				}
+			},
+			//安卓端允许截屏  
+			AllowScreenshots() {
+				let _this = this;
+				uni.getSystemInfo({
+					success: function(e) {
+						// #ifdef MP-WEIXIN
+						if (e.platform == 'android') {
+							//微信小程序在安卓手机上 禁止截屏/录屏(注意:禁止后录屏动作还是会进行,但录屏后的视频是黑屏的)
+							wx.setVisualEffectOnCapture({
+								visualEffect: 'none', //传入 hidden 则表示在截屏/录屏时隐藏屏幕
+								success: (res) => {
+									console.log(res)
+								},
+								fail: (err) => {
+									console.log(err)
+								},
+								complete: (res) => {
+									console.log(res)
+								}
+							})
+						} else {
+							//微信小程序在IOS手机上,注意:目前微信小程序在ios上也只能通过监听录屏状态,然后通过添加view层来进行阻止,截屏暂时无法实现
+							//监听用户录屏事件
+							wx.onScreenRecordingStateChanged(function(res) {
+								if (res.state == 'start') {
+									_this.isRecording = false
+								} else {
+									_this.isRecording = false
+								}
+							})
+							//查询用户是否在录屏
+							wx.getScreenRecordingState({
+								success: (res) => {
+									if (res.state == 'on') {
+										_this.isRecording = false
+									} else if (res.state == 'off') {
+										_this.isRecording = false
+									}
+								},
+								fail: (err) => {
+									_this.isRecording = false
+								}
+							})
+						}
+						// #endif
+					}
+				})
+				// #ifdef APP-PLUS
+				let osname = plus.os.name;
+				if (osname == "Android") {
+					var activity = plus.android.runtimeMainActivity();
+					plus.android.invoke(plus.android.invoke(activity, "getWindow"), "clearFlags", 0x00002000);
+				}
+				// #endif
+			}
+		}
+	}
+</script>
+
+<style>
+	.zzc_mol {
+		background: #000;
+		width: 100%;
+		height: 100%;
+		position: fixed;
+		z-index: 99999;
+		top: 0;
+		left: 0;
+	}
+</style>

+ 606 - 645
pages_shopping/live/integral.vue

@@ -1,646 +1,607 @@
-<template>
-	<view>
-		<view class="top-cont">
-			<!-- 背景图片 -->
-			<image class="bg"
-				src="https://fs-1319721001.cos.ap-chongqing.myqcloud.com/fs/20240229/ed4a8ff0406747a68e40988b210d1c78.png"
-				mode=""></image>
-			<view class="top-inner">
-				<!-- 这里是状态栏 -->
-				<view class="fixed-top-box" :style="{ background: bg }">
-					<view class="status_bar" :style="{height: statusBarHeight}"></view>
-					<view class="back-box" @click="back">
-						<text class="title">我的积分</text>
-						<text></text>
-					</view>
-				</view>
-				<!-- 顶部固定后站位元素 -->
-				<view style="padding-bottom: 88upx;">
-					<view :style="{height: statusBarHeight}"></view>
-				</view>
-				<!-- 可用积分 -->
-				<view class="available-points">
-					<text class="label">可用积分</text>
-					<text class="num">{{integral}}</text>
-				</view>
-
-				<!-- 签到 -->
-				<!-- <view class="singn-content">
-					<view class="sign-in-box">
-						<view class="inner">
-							<view class="title-box">已连续签到<text class="num">{{totalDays}}</text>天</view>
-							<view class="sign-list">
-								<view v-for="(item,index) in records" :key="index"
-									:class="totalDays >= index+ 1?'item active':'item'">
-									<view class="line"></view>
-									<view class="right">
-										<image v-if="totalDays >= index+ 1"
-											src="https://fs-1319721001.cos.ap-chongqing.myqcloud.com/fs/20240229/f3bdd5d388854e9a8f365904840c3b32.png"
-											mode=""></image>
-										<image v-else
-											src="https://fs-1319721001.cos.ap-chongqing.myqcloud.com/fs/20240229/c593e551e4b246b981aaa58deb1fe725.png"
-											mode=""></image>
-										<text class="text">第{{ item.continuousDays}}天</text>
-									</view>
-								</view>
-							</view>
-						</view>
-						<view class="sign-btn-box">
-							<view class="btn" v-if="isDaySign==false" @click="doSign()">
-								<image
-									src="https://fs-1319721001.cos.ap-chongqing.myqcloud.com/fs/20240229/295aa046433d4feb95b467c83f8b4096.png"
-									mode=""></image>
-								<text class="text">签到</text>
-							</view>
-							<view class="btn" v-else>
-								<image
-									src="https://fs-1319721001.cos.ap-chongqing.myqcloud.com/fs/20240229/295aa046433d4feb95b467c83f8b4096.png"
-									mode=""></image>
-								<text class="text">签到</text>
-							</view>
-						</view>
-					</view>
-				</view> -->
-				<view class="content">
-					<!-- 积分列表 -->
-					<view class="points-cont">
-						<!-- tab切换 -->
-						<!-- <view class="pub-tab-box">
-							<view class="tab-inner">
-								<view 
-									v-for="(item,index) in tags" 
-									:key="index"
-									:class="tabIndex == item.value?'item active':'item'"
-									@click="tabChange(item)">
-									<view class="text">
-										{{ item.lable }}
-										<image v-show="tabIndex == item.value" class="tab-bg" src="https://fs-1319721001.cos.ap-chongqing.myqcloud.com/fs/20240229/1828ea6b3b124b5f84e3556267a8d9ef.png" mode=""></image>
-									</view>
-								</view>
-							</view>
-						</view> -->
-
-						<!-- 列表 -->
-						<view class="point-list">
-							<view v-for="(item,index) in list" :key="index" class="item">
-								<view class="left">
-									<text class="title">
-										<!-- {{item.logTypeName}} -->
-										直播间完课积分
-									</text>
-									<view class="time">{{item.createTime}}</view>
-								</view>
-								<view class="right">
-									<text v-if="item.integral<0" class="less">{{item.integral}}</text>
-									<text v-else class="add">+{{item.pointsAwarded}}</text>
-								</view>
-							</view>
-						</view>
-					</view>
-				</view>
-
-			</view>
-		</view>
-
-	</view>
-</template>
-
-<script>
-	import {
-		getUserIntegralInfo
-	} from '@/api/living.js' // 积分
-	import {
-		completionRecords,
-		completionInfo,doSign
-	} from '@/api/integral.js'
-
-
-	// import {getDictByKey} from '@/api/common.js'
-	// import {getUserSign,getUserIntegralLogsList,doSign} from '@/api/integral';
-	// import {
-	// 	doSign
-	// } from '@/api/integral';
-	export default {
-		comments() {
-			Loading
-		},
-		data() {
-			return {
-				totalDays: null,
-				records: null,
-				liveId: 712,
-				signNum: 0,
-				typeOptions: [],
-				top: 0,
-				integral: 0,
-				sign: [],
-				// 状态栏的高度
-				statusBarHeight: uni.getStorageSync('menuInfo').statusBarHeight,
-				// tab切换
-				// {lable:'获得',value:1},{lable:'消耗',value:2}
-				// tags: [{lable:'最近十条',value:0},],
-				// 选中的tab
-				tabIndex: 0,
-				current: 0,
-				page: {
-					type: 0,
-					page: 1,
-					pageSize: 10
-				},
-				list: [],
-				loaded: false,
-				loading: false
-			};
-		},
-		onLoad(option) {
-			if (option.liveId) {
-				this.liveId = option.liveId
-			}
-			console.log("进入积分页面了")
-			// this.getUserIntegralInfo()
-			this.completionRecords()
-			this.completionInfo()
-		},
-		computed: {
-			// 计算属性的 getter
-			bg: function() {
-				return 'rgba(255,142,60, ' + this.top / 30 + ')';
-			},
-		},
-		methods: {
-			// 查询用户积分领取记录
-			completionRecords() {
-				if (!this.liveId) return;
-				const data = {
-					liveId: this.liveId
-				}
-				completionRecords(data).then((res) => {
-					if (res.code == 200) {
-						this.list = res.data
-						console.log("查询用户积分领取记录", res)
-					}
-				}).catch((error) => {
-
-				});
-			},
-
-			//查询用户积分余额和看直播信息统计
-			completionInfo() {
-				if (!this.liveId) return;
-				const data = {
-					liveId: this.liveId
-				}
-				completionInfo(data).then((res) => {
-					if (res.code == 200) {
-						this.integral = res.data.integral
-						this.records = res.data.records
-						this.totalDays = res.data.totalDays
-						console.log("查询用户积分余额和看直播信息统计", res)
-					}
-				}).catch((error) => {
-
-				});
-			},
-
-
-			doSign() {
-				var data = {};
-				// uni.showLoading({
-				// 	title:"正在加载中..."
-				// })
-				doSign(data).then(
-					res => {
-						// uni.hideLoading()
-						if (res.code == 200) {
-							uni.showToast({
-								icon: 'success',
-								title: res.msg,
-							});
-							this.list = [];
-							this.page.page = 1;
-							this.list = [];
-							this.loaded = false;
-							this.loading = false;
-							this.getUserIntegralLogsList();
-							this.getUserSign();
-						} else {
-							uni.showToast({
-								icon: 'none',
-								title: res.msg,
-							});
-						}
-					},
-					rej => {}
-				);
-			},
-			getUserSign() {
-				getUserSign().then(
-					res => {
-						if (res.code == 200) {
-							this.data = res.member;
-							this.signNum = res.signNum;
-							this.isDaySign = res.isDaySign;
-							this.integral = res.integral;
-							this.sign = JSON.parse(res.sign);
-
-						} else {
-							uni.showToast({
-								icon: 'none',
-								title: "请求失败",
-							});
-						}
-					},
-					rej => {}
-				);
-			},
-
-
-			// 积分
-			getUserIntegralInfo() {
-				uni.showLoading({
-					title: "正在加载中..."
-				})
-				getUserIntegralInfo().then(res => {
-					uni.hideLoading()
-					if (res.code == 200) {
-						console.log("积分>>", res)
-						// 处理列表数据,将"积分"替换为"积分"
-						this.list = res.data.logs.map(item => {
-							return {
-								...item,
-								logTypeName: item.logTypeName ? item.logTypeName.replace(/积分/g, '积分') :
-									item.logTypeName
-							}
-						})
-						this.integral = res.data.integral
-					}
-				}).catch(error => {
-					console.error("获取积分数据失败:", error);
-
-				});
-			},
-
-
-
-			getDictByKey(key) {
-				var data = {
-					key: key
-				}
-				getDictByKey(data).then(
-					res => {
-						if (res.code == 200) {
-							this.typeOptions = res.data;
-						}
-					},
-					err => {}
-				);
-
-			},
-
-
-			getUserIntegralLogsList() {
-				let that = this;
-				if (that.loaded == true || that.loading == true) return;
-				that.loading = true;
-				uni.showLoading({
-					title: "加载中..."
-				})
-				getUserIntegralLogsList(that.page).then(
-					res => {
-						that.loading = false;
-						that.loaded = res.data.list.length < that.page.pageSize;
-						that.page.page = that.page.page + 1;
-						that.list.push.apply(that.list, res.data.list);
-						uni.hideLoading()
-					},
-					err => {
-						uni.hideLoading()
-						uni.showToast({
-							title: err.msg,
-							icon: 'none',
-							duration: 2000
-						});
-					}
-				);
-			},
-			// 返回上一页
-			back() {
-				uni.navigateBack()
-			},
-			// tab选择
-			// tabChange(item) {
-			// 	console.log(item)
-			// 	this.tabIndex = item.value
-			// 	this.page.type=this.tabIndex;
-			// 	this.page.page=1;
-			// 	this.list=[];
-			// 	this.loaded=false;
-			// 	this.loading=false;
-			// 	this.getUserIntegralLogsList();
-			// }
-		}
-	}
-</script>
-
-<style lang="scss">
-	.fixed-top-box {
-		width: 100%;
-		position: fixed;
-		top: 0;
-		left: 0;
-		z-index: 1000;
-		transition: all 0.5s;
-
-	}
-
-	.top-cont {
-		width: 100%;
-		height: 654upx;
-		position: relative;
-
-		.bg {
-			width: 100%;
-			height: 100%;
-			position: absolute;
-			top: 0;
-			left: 0;
-			z-index: 1;
-		}
-
-		.top-inner {
-			width: 100%;
-			height: 100%;
-			position: absolute;
-			top: 0;
-			left: 0;
-			z-index: 2;
-
-			.back-box {
-				height: 88upx;
-				padding-left: 22upx;
-				display: flex;
-				align-items: center;
-				justify-content: space-between;
-				padding: 0 20upx;
-
-				image {
-					width: 40upx;
-					height: 40upx;
-				}
-
-				.title {
-					font-size: 36upx;
-					font-family: PingFang SC;
-					font-weight: 500;
-					color: #FFFFFF;
-				}
-			}
-
-			.available-points {
-				margin-top: 140upx;
-				display: flex;
-				flex-direction: column;
-				align-items: center;
-				justify-content: center;
-
-				.label {
-					font-size: 30upx;
-					font-family: PingFang SC;
-					font-weight: bold;
-					color: #FFFFFF;
-					line-height: 1;
-				}
-
-				.num {
-					font-size: 80upx;
-					font-family: Gilroy;
-					font-weight: 500;
-					color: #FFFFFF;
-					line-height: 1;
-					margin-top: 28upx;
-				}
-			}
-
-			.singn-content {
-				padding: 0 20upx;
-				margin-top: 50upx;
-			}
-
-			.sign-in-box {
-				height: 380upx;
-				background: #FFFFFF;
-				border-radius: 16upx;
-
-				.inner {
-					padding: 40upx 30upx;
-
-					.title-box {
-						font-size: 26upx;
-						font-family: PingFang SC;
-						font-weight: 500;
-						color: #666666;
-						line-height: 1;
-
-						.num {
-							font-size: 32upx;
-							font-family: PingFang SC;
-							font-weight: Bold;
-							color: #FF7511;
-							margin: 0 10upx;
-							line-height: 1;
-						}
-					}
-
-					.sign-list {
-						display: flex;
-						align-items: center;
-						justify-content: space-between;
-						margin-top: 40upx;
-
-						.item {
-							display: flex;
-							justify-content: center;
-
-							.right {
-								display: flex;
-								flex-direction: column;
-								align-items: center;
-								justify-content: center;
-
-								image {
-									width: 44upx;
-									height: 44upx;
-									margin-bottom: 20upx;
-								}
-
-								.text {
-									font-size: 24upx;
-									font-family: PingFang SC;
-									font-weight: 500;
-									color: #FF7511;
-									line-height: 1;
-									white-space: nowrap;
-								}
-							}
-
-							.line {
-								width: 34upx;
-								height: 4upx;
-								background: #F6CDA7;
-								border-radius: 2upx;
-								margin-top: 22upx;
-							}
-
-							&:first-child {
-								.line {
-									display: none;
-								}
-							}
-
-							&.active {
-								.line {
-									background: #FF8E3C;
-								}
-							}
-						}
-					}
-				}
-
-				.sign-btn-box {
-					padding: 0 14upx;
-
-					.btn {
-						width: 100%;
-						height: 88upx;
-						box-shadow: 0px 0px 5px 2px rgba(0, 0, 0, 0.05);
-						background-color: #FF7511;
-						border-radius: 44rpx;
-						display: flex;
-						justify-content: center;
-						align-items: center;
-
-						image {
-							width: 32upx;
-							height: 32upx;
-						}
-
-						.text {
-							font-size: 30upx;
-							font-family: PingFang SC;
-							font-weight: bold;
-							color: #FFFFFF;
-							line-height: 1;
-						}
-					}
-				}
-			}
-
-		}
-	}
-
-	.content {
-		margin-top: 20upx;
-		padding: 0 20upx 40upx;
-
-		.points-cont {
-
-			background-color: #FFFFFF;
-			border-radius: 16upx;
-
-			.pub-tab-box {
-				padding: 0 80upx;
-
-				.tab-inner {
-					height: 88upx;
-					line-height: 88upx;
-					display: flex;
-					align-items: center;
-					justify-content: space-between;
-				}
-
-				.item {
-					font-size: 28upx;
-					white-space: nowrap;
-					line-height: 1;
-					font-family: PingFang SC;
-					font-weight: 500;
-					color: #666666;
-					display: flex;
-					align-items: center;
-					justify-content: center;
-
-					&.active {
-						font-weight: bold;
-						color: #333333;
-					}
-
-					.text {
-						position: relative;
-						z-index: 1;
-					}
-
-					.tab-bg {
-						width: 72upx;
-						height: 28upx;
-						position: absolute;
-						top: 17upx;
-						left: 50%;
-						transform: translateX(-36upx);
-						z-index: -1;
-					}
-				}
-			}
-
-			.point-list {
-				padding: 0 30upx;
-
-				.item {
-					padding: 30upx 0;
-					display: flex;
-					align-items: center;
-					justify-content: space-between;
-					border-bottom: 1px solid #F0F0F0;
-
-					&:last-child {
-						border-bottom: none;
-					}
-
-					.left {
-						.title {
-							font-size: 28upx;
-							font-family: PingFang SC;
-							font-weight: 500;
-							color: #111111;
-							line-height: 1;
-						}
-
-						.time {
-							font-size: 24upx;
-							font-family: PingFang SC;
-							font-weight: 500;
-							color: #999999;
-							line-height: 1;
-							margin-top: 22upx;
-						}
-					}
-
-					.right {
-						.add {
-							font-size: 28upx;
-							font-family: PingFang SC;
-							font-weight: 500;
-							color: #111111;
-						}
-
-						.less {
-							font-size: 28upx;
-							font-family: PingFang SC;
-							font-weight: 500;
-							color: #F56C6C;
-						}
-					}
-				}
-			}
-		}
-	}
+<template>
+	<view>
+		<view class="top-cont">
+			<!-- 背景图片 -->
+			<image class="bg"
+				src="https://fs-1319721001.cos.ap-chongqing.myqcloud.com/fs/20240229/ed4a8ff0406747a68e40988b210d1c78.png"
+				mode=""></image>
+			<view class="top-inner">
+				<!-- 这里是状态栏 -->
+				<view class="fixed-top-box" :style="{ background: bg }">
+					<view class="status_bar" :style="{height: statusBarHeight}"></view>
+					<view class="back-box" @click="back">
+						<text class="title">我的积分</text>
+						<text></text>
+					</view>
+				</view>
+				<!-- 顶部固定后站位元素 -->
+				<view style="padding-bottom: 88upx;">
+					<view :style="{height: statusBarHeight}"></view>
+				</view>
+				<!-- 可用积分 -->
+				<view class="available-points">
+					<text class="label">可用积分</text>
+					<text class="num">{{integral}}</text>
+				</view>
+
+			
+				<view class="content">
+					<!-- 积分列表 -->
+					<view class="points-cont">
+						<!-- 列表 -->
+						<view class="point-list">
+							<view v-for="(item,index) in list" :key="index" class="item">
+								<view class="left">
+									<text class="title">
+										<!-- {{item.logTypeName}} -->
+										<!-- 直播间完课积分 -->
+										 {{utils.getDictLabel2Name(typeOptions,item.logType)}}
+									</text>
+									<view class="time">{{item.createTime}}</view>
+								</view>
+								<view class="right">
+									<text v-if="item.integral<0" class="less">{{item.integral}}</text>
+									<text v-else class="add">+{{item.integral}}</text>
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+
+			</view>
+		</view>
+
+	</view>
+</template>
+
+<script>
+	// import {
+	// 	getUserIntegralInfo
+	// } from '@/api/living.js' // 积分
+	// import {
+	// 	completionRecords,
+	// 	completionInfo,doSign
+	// } from '@/api/integral.js'
+	import {getUserIntegralLogsList,getUserSign} from '@/api/integral';
+
+	import {getDictByKey} from '@/api/common.js'
+	// import {getUserSign,getUserIntegralLogsList,doSign} from '@/api/integral';
+	// import {
+	// 	doSign
+	// } from '@/api/integral';
+	export default {
+		comments() {
+			Loading
+		},
+		data() {
+			return {
+				totalDays: null,
+				records: null,
+				liveId: 712,
+				signNum: 0,
+				typeOptions: [],
+				top: 0,
+				integral: 0,
+				sign: [],
+				// 状态栏的高度
+				statusBarHeight: uni.getStorageSync('menuInfo').statusBarHeight,
+				// tab切换
+				// {lable:'获得',value:1},{lable:'消耗',value:2}
+				// tags: [{lable:'最近十条',value:0},],
+				// 选中的tab
+				tabIndex: 0,
+				current: 0,
+				page: {
+					type: 0,
+					page: 1,
+					pageSize: 10
+				},
+				list: [],
+				loaded: false,
+				loading: false
+			};
+		},
+		onLoad(option) {
+			this.getDictByKey("sys_integral_log_type");
+			if (option.liveId) {
+				this.liveId = option.liveId
+			}
+			console.log("进入积分页面了")
+			// this.integrallogs()
+			// this.getUserIntegralInfo()
+			// this.completionRecords()
+			// this.completionInfo()
+			this.getUserSign()
+			this.getUserIntegralLogsList();
+		},
+		computed: {
+			// 计算属性的 getter
+			bg: function() {
+				return 'rgba(255,142,60, ' + this.top / 30 + ')';
+			},
+		},
+		methods: {
+			// integrallogs() {
+			// 	integrallogs(data).then((res) => {
+			// 		if (res.code == 200) {
+			// 			console.log("用户领取看课积分", res)
+			// 			// receiveList
+			// 		}
+			// 	}).catch((error) => {});
+			// },
+			// 查询用户积分领取记录
+			// completionRecords() {
+			// 	if (!this.liveId) return;
+			// 	const data = {
+			// 		liveId: this.liveId
+			// 	}
+			// 	completionRecords(data).then((res) => {
+			// 		if (res.code == 200) {
+			// 			this.list = res.data
+			// 			console.log("查询用户积分领取记录", res)
+			// 		}
+			// 	}).catch((error) => {
+
+			// 	});
+			// },
+
+			//查询用户积分余额和看直播信息统计
+			// completionInfo() {
+			// 	if (!this.liveId) return;
+			// 	const data = {
+			// 		liveId: this.liveId
+			// 	}
+			// 	completionInfo(data).then((res) => {
+			// 		if (res.code == 200) {
+			// 			this.integral = res.data.integral
+			// 			this.records = res.data.records
+			// 			this.totalDays = res.data.totalDays
+			// 			console.log("查询用户积分余额和看直播信息统计", res)
+			// 		}
+			// 	}).catch((error) => {
+
+			// 	});
+			// },
+
+
+			// doSign() {
+			// 	var data = {};
+			// 	// uni.showLoading({
+			// 	// 	title:"正在加载中..."
+			// 	// })
+			// 	doSign(data).then(
+			// 		res => {
+			// 			// uni.hideLoading()
+			// 			if (res.code == 200) {
+			// 				uni.showToast({
+			// 					icon: 'success',
+			// 					title: res.msg,
+			// 				});
+			// 				this.list = [];
+			// 				this.page.page = 1;
+			// 				this.list = [];
+			// 				this.loaded = false;
+			// 				this.loading = false;
+			// 				this.getUserIntegralLogsList();
+			// 				this.getUserSign();
+			// 			} else {
+			// 				uni.showToast({
+			// 					icon: 'none',
+			// 					title: res.msg,
+			// 				});
+			// 			}
+			// 		},
+			// 		rej => {}
+			// 	);
+			// },
+			getUserSign() {
+				getUserSign().then(
+					res => {
+						if (res.code == 200) {
+							this.data = res.member;
+							this.signNum = res.signNum;
+							this.isDaySign = res.isDaySign;
+							this.integral = res.integral;
+							this.sign = JSON.parse(res.sign);
+
+						} else {
+							uni.showToast({
+								icon: 'none',
+								title: "请求失败",
+							});
+						}
+					},
+					rej => {}
+				);
+			},
+
+
+			// // 积分
+			// getUserIntegralInfo() {
+			// 	uni.showLoading({
+			// 		title: "正在加载中..."
+			// 	})
+			// 	getUserIntegralInfo().then(res => {
+			// 		uni.hideLoading()
+			// 		if (res.code == 200) {
+			// 			console.log("积分>>", res)
+			// 			// 处理列表数据,将"积分"替换为"积分"
+			// 			this.list = res.data.logs.map(item => {
+			// 				return {
+			// 					...item,
+			// 					logTypeName: item.logTypeName ? item.logTypeName.replace(/积分/g, '积分') :
+			// 						item.logTypeName
+			// 				}
+			// 			})
+			// 			this.integral = res.data.integral
+			// 		}
+			// 	}).catch(error => {
+			// 		console.error("获取积分数据失败:", error);
+
+			// 	});
+			// },
+
+
+
+			getDictByKey(key) {
+				var data = {
+					key: key
+				}
+				getDictByKey(data).then(
+					res => {
+						if (res.code == 200) {
+							this.typeOptions = res.data;
+						}
+					},
+					err => {}
+				);
+
+			},
+
+
+			getUserIntegralLogsList() {
+				let that = this;
+				if (that.loaded == true || that.loading == true) return;
+				that.loading = true;
+				uni.showLoading({
+					title: "加载中..."
+				})
+				getUserIntegralLogsList(that.page).then(
+					res => {
+						that.loading = false;
+						that.loaded = res.data.list.length < that.page.pageSize;
+						that.page.page = that.page.page + 1;
+						that.list.push.apply(that.list, res.data.list);
+						uni.hideLoading()
+					},
+					err => {
+						uni.hideLoading()
+						uni.showToast({
+							title: err.msg,
+							icon: 'none',
+							duration: 2000
+						});
+					}
+				);
+			},
+			// 返回上一页
+			back() {
+				uni.navigateBack()
+			},
+			// tab选择
+			// tabChange(item) {
+			// 	console.log(item)
+			// 	this.tabIndex = item.value
+			// 	this.page.type=this.tabIndex;
+			// 	this.page.page=1;
+			// 	this.list=[];
+			// 	this.loaded=false;
+			// 	this.loading=false;
+			// 	this.getUserIntegralLogsList();
+			// }
+		}
+	}
+</script>
+
+<style lang="scss">
+	.fixed-top-box {
+		width: 100%;
+		position: fixed;
+		top: 0;
+		left: 0;
+		z-index: 1000;
+		transition: all 0.5s;
+
+	}
+
+	.top-cont {
+		width: 100%;
+		height: 654upx;
+		position: relative;
+
+		.bg {
+			width: 100%;
+			height: 100%;
+			position: absolute;
+			top: 0;
+			left: 0;
+			z-index: 1;
+		}
+
+		.top-inner {
+			width: 100%;
+			height: 100%;
+			position: absolute;
+			top: 0;
+			left: 0;
+			z-index: 2;
+
+			.back-box {
+				height: 88upx;
+				padding-left: 22upx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				padding: 0 20upx;
+
+				image {
+					width: 40upx;
+					height: 40upx;
+				}
+
+				.title {
+					font-size: 36upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+			}
+
+			.available-points {
+				margin-top: 140upx;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				justify-content: center;
+
+				.label {
+					font-size: 30upx;
+					font-family: PingFang SC;
+					font-weight: bold;
+					color: #FFFFFF;
+					line-height: 1;
+				}
+
+				.num {
+					font-size: 80upx;
+					font-family: Gilroy;
+					font-weight: 500;
+					color: #FFFFFF;
+					line-height: 1;
+					margin-top: 28upx;
+				}
+			}
+
+			.singn-content {
+				padding: 0 20upx;
+				margin-top: 50upx;
+			}
+
+			.sign-in-box {
+				height: 380upx;
+				background: #FFFFFF;
+				border-radius: 16upx;
+
+				.inner {
+					padding: 40upx 30upx;
+
+					.title-box {
+						font-size: 26upx;
+						font-family: PingFang SC;
+						font-weight: 500;
+						color: #666666;
+						line-height: 1;
+
+						.num {
+							font-size: 32upx;
+							font-family: PingFang SC;
+							font-weight: Bold;
+							color: #FF7511;
+							margin: 0 10upx;
+							line-height: 1;
+						}
+					}
+
+					.sign-list {
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+						margin-top: 40upx;
+
+						.item {
+							display: flex;
+							justify-content: center;
+
+							.right {
+								display: flex;
+								flex-direction: column;
+								align-items: center;
+								justify-content: center;
+
+								image {
+									width: 44upx;
+									height: 44upx;
+									margin-bottom: 20upx;
+								}
+
+								.text {
+									font-size: 24upx;
+									font-family: PingFang SC;
+									font-weight: 500;
+									color: #FF7511;
+									line-height: 1;
+									white-space: nowrap;
+								}
+							}
+
+							.line {
+								width: 34upx;
+								height: 4upx;
+								background: #F6CDA7;
+								border-radius: 2upx;
+								margin-top: 22upx;
+							}
+
+							&:first-child {
+								.line {
+									display: none;
+								}
+							}
+
+							&.active {
+								.line {
+									background: #FF8E3C;
+								}
+							}
+						}
+					}
+				}
+
+				.sign-btn-box {
+					padding: 0 14upx;
+
+					.btn {
+						width: 100%;
+						height: 88upx;
+						box-shadow: 0px 0px 5px 2px rgba(0, 0, 0, 0.05);
+						background-color: #FF7511;
+						border-radius: 44rpx;
+						display: flex;
+						justify-content: center;
+						align-items: center;
+
+						image {
+							width: 32upx;
+							height: 32upx;
+						}
+
+						.text {
+							font-size: 30upx;
+							font-family: PingFang SC;
+							font-weight: bold;
+							color: #FFFFFF;
+							line-height: 1;
+						}
+					}
+				}
+			}
+
+		}
+	}
+
+	.content {
+		margin-top: 20upx;
+		padding: 0 20upx 40upx;
+
+		.points-cont {
+
+			background-color: #FFFFFF;
+			border-radius: 16upx;
+
+			.pub-tab-box {
+				padding: 0 80upx;
+
+				.tab-inner {
+					height: 88upx;
+					line-height: 88upx;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+				}
+
+				.item {
+					font-size: 28upx;
+					white-space: nowrap;
+					line-height: 1;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #666666;
+					display: flex;
+					align-items: center;
+					justify-content: center;
+
+					&.active {
+						font-weight: bold;
+						color: #333333;
+					}
+
+					.text {
+						position: relative;
+						z-index: 1;
+					}
+
+					.tab-bg {
+						width: 72upx;
+						height: 28upx;
+						position: absolute;
+						top: 17upx;
+						left: 50%;
+						transform: translateX(-36upx);
+						z-index: -1;
+					}
+				}
+			}
+
+			.point-list {
+				padding: 0 30upx;
+
+				.item {
+					padding: 30upx 0;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					border-bottom: 1px solid #F0F0F0;
+
+					&:last-child {
+						border-bottom: none;
+					}
+
+					.left {
+						.title {
+							font-size: 28upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #111111;
+							line-height: 1;
+						}
+
+						.time {
+							font-size: 24upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #999999;
+							line-height: 1;
+							margin-top: 22upx;
+						}
+					}
+
+					.right {
+						.add {
+							font-size: 28upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #111111;
+						}
+
+						.less {
+							font-size: 28upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #F56C6C;
+						}
+					}
+				}
+			}
+		}
+	}
 </style>

+ 177 - 174
pages_user/user/integralLogsList.vue

@@ -1,174 +1,177 @@
-<template>
-	<view class="page">
-		<view class="content">
-			<mescroll-body      ref="mescrollRef" @init="mescrollInit" :up="upOption" :down="downOption" @down="downCallback" @up="upCallback">
-			<view class="item" v-for="(item) in dataList">
-				<view class="left">
-					<text class="title"  >
-						{{utils.getDictLabel2Name(typeOptions,item.logType)}}
-					</text>
-					<view class="time">{{item.createTime}}</view>
-				</view>
-				<view class="right">
-					<text  :class="item.integral>0?'money green':'money red'">{{item.integral}}</text>
-					<text class="remark">剩余积分:{{item.balance}}</text>
-				</view>
-			</view>
-			</mescroll-body>
-		</view>
-	</view>
-</template>
-
-<script>
-	import {getDictByKey} from '@/api/common.js'
-	import {getUserIntegralLogsList} from '@/api/integral.js'
-	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
-	export default {
-		mixins: [MescrollMixin], // 使用mixin
-		data() {
-			return {
-				typeOptions:[],
-				mescroll:null,
-				downOption: {
-					auto:false//不要自动加载
-				},
-				upOption: {
-					onScroll:false,
-					use: true, // 是否启用上拉加载; 默认true
-					page: {
-						num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
-						size: 10 // 每页数据的数量,默认10
-					},
-					noMoreSize: 10, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
-					textNoMore:"已经到底了",
-					empty: {
-						icon:'https://hdtobs.obs.cn-north-4.myhuaweicloud.com/hdt/empty_icon.png',
-						tip: '暂无数据'
-					}
-				},
-				dataList: []
-				 
-			}
-		},
-		onLoad() {
-			this.getDictByKey("sys_integral_log_type");
-		},
-		methods: {
-			getDictByKey(key){
-				var data={key:key}
-				getDictByKey(data).then(
-					res => {
-						if(res.code==200){
-							this.typeOptions=res.data;
-						}
-					},
-					err => {
-					}
-				);
-			},
-			mescrollInit(mescroll) {
-				this.mescroll = mescroll;
-			},
-			/*下拉刷新的回调 */
-			downCallback(mescroll) {
-				mescroll.resetUpScroll()
-			},
-			upCallback(page) {
-				//联网加载数据
-				var that = this;
-				var data = {
-					pageNum: page.num,
-					pageSize: page.size
-				};
-				// uni.showLoading({
-				// 	title:"加载中..."
-				// })
-				getUserIntegralLogsList(data).then(res => {
-					uni.hideLoading()
-					if(res.code==200){
-						//设置列表数据
-						if (page.num == 1) {
-							that.dataList = res.data.list; 
-							
-						} else {
-							that.dataList = that.dataList.concat(res.data.list);
-							 
-						}
-						that.mescroll.endBySize(res.data.list.length, res.data.total);
-						
-					}else{
-						uni.showToast({
-							icon:'none',
-							title: "请求失败",
-						});
-						that.dataList = null;
-						that.mescroll.endErr();
-					}
-				});
-			},
-			 
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	.page{
-	}
-	.content{
-		display: flex;
-		flex-direction: column;
-		.item{
-			background-color: #fff;
-			padding: 20rpx 10rpx;
-			display: flex;
-			align-items: flex-start;
-			justify-content: space-between;
-			border-top: 1rpx solid #efefef;
-			.left{
-				display: flex;
-				flex-direction: column;
-				align-items: flex-start;
-				justify-content: flex-start;
-				.title{
-					font-size: 26rpx;
-					color: #111;
-				}
-				.time{
-					margin-top: 20rpx;
-					font-size: 24rpx;
-					color: #a5a5a5;
-				}
-			}
-			.right{
-				display: flex;
-				flex-direction: column;
-				align-items: flex-end;
-				justify-content: flex-end;
-				.money{
-					font-size: 28rpx;
-					font-weight: bold;
-					color: #111;
-				}
-				.green{
-					color: green;
-				}
-				.red{
-					color:#ff0000;
-				}
-				.remark{
-					margin-top: 20rpx;
-					font-size: 24rpx;
-					color: #a5a5a5;
-					.green{
-						color: green;
-					}
-					.red{
-						color: red;
-					}
-				}
-			}
-		}
-		
-	}
-	 
-</style>
+<template>
+	<view class="page">
+		<view class="content">
+			<mescroll-body      ref="mescrollRef" @init="mescrollInit" :up="upOption" :down="downOption" @down="downCallback" @up="upCallback">
+			<view class="item" v-for="(item) in dataList">
+				<view class="left">
+					<!-- <text class="title"  >
+						完课积分领取记录
+					</text> -->
+					<text class="title"  >
+						{{utils.getDictLabel2Name(typeOptions,item.logType)}}
+					</text>
+					<view class="time">{{item.createTime}}</view>
+				</view>
+				<view class="right">
+					<text  :class="item.integral>0?'money green':'money red'">{{item.integral}}</text>
+					<text class="remark">剩余积分:{{item.balance}}</text>
+				</view>
+			</view>
+			</mescroll-body>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {getDictByKey} from '@/api/common.js'
+	import {getUserIntegralLogsList} from '@/api/integral.js'
+	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
+	export default {
+		mixins: [MescrollMixin], // 使用mixin
+		data() {
+			return {
+				typeOptions:[],
+				mescroll:null,
+				downOption: {
+					auto:false//不要自动加载
+				},
+				upOption: {
+					onScroll:false,
+					use: true, // 是否启用上拉加载; 默认true
+					page: {
+						num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
+						size: 10 // 每页数据的数量,默认10
+					},
+					noMoreSize: 10, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
+					textNoMore:"已经到底了",
+					empty: {
+						icon:'https://hdtobs.obs.cn-north-4.myhuaweicloud.com/hdt/empty_icon.png',
+						tip: '暂无数据'
+					}
+				},
+				dataList: []
+				 
+			}
+		},
+		onLoad() {
+			this.getDictByKey("sys_integral_log_type");
+		},
+		methods: {
+			getDictByKey(key){
+				var data={key:key}
+				getDictByKey(data).then(
+					res => {
+						if(res.code==200){
+							this.typeOptions=res.data;
+						}
+					},
+					err => {
+					}
+				);
+			},
+			mescrollInit(mescroll) {
+				this.mescroll = mescroll;
+			},
+			/*下拉刷新的回调 */
+			downCallback(mescroll) {
+				mescroll.resetUpScroll()
+			},
+			upCallback(page) {
+				//联网加载数据
+				var that = this;
+				var data = {
+					pageNum: page.num,
+					pageSize: page.size
+				};
+				// uni.showLoading({
+				// 	title:"加载中..."
+				// })
+				getUserIntegralLogsList(data).then(res => {
+					uni.hideLoading()
+					if(res.code==200){
+						//设置列表数据
+						if (page.num == 1) {
+							that.dataList = res.data.list; 
+							
+						} else {
+							that.dataList = that.dataList.concat(res.data.list);
+							 
+						}
+						that.mescroll.endBySize(res.data.list.length, res.data.total);
+						
+					}else{
+						uni.showToast({
+							icon:'none',
+							title: "请求失败",
+						});
+						that.dataList = null;
+						that.mescroll.endErr();
+					}
+				});
+			},
+			 
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.page{
+	}
+	.content{
+		display: flex;
+		flex-direction: column;
+		.item{
+			background-color: #fff;
+			padding: 20rpx 10rpx;
+			display: flex;
+			align-items: flex-start;
+			justify-content: space-between;
+			border-top: 1rpx solid #efefef;
+			.left{
+				display: flex;
+				flex-direction: column;
+				align-items: flex-start;
+				justify-content: flex-start;
+				.title{
+					font-size: 26rpx;
+					color: #111;
+				}
+				.time{
+					margin-top: 20rpx;
+					font-size: 24rpx;
+					color: #a5a5a5;
+				}
+			}
+			.right{
+				display: flex;
+				flex-direction: column;
+				align-items: flex-end;
+				justify-content: flex-end;
+				.money{
+					font-size: 28rpx;
+					font-weight: bold;
+					color: #111;
+				}
+				.green{
+					color: green;
+				}
+				.red{
+					color:#ff0000;
+				}
+				.remark{
+					margin-top: 20rpx;
+					font-size: 24rpx;
+					color: #a5a5a5;
+					.green{
+						color: green;
+					}
+					.red{
+						color: red;
+					}
+				}
+			}
+		}
+		
+	}
+	 
+</style>

+ 10 - 6
pages_user/user/personInfo.vue

@@ -31,6 +31,10 @@
 				<view class="label">手机号</view>
 				<view class="right" v-if="user!=null">{{utils.parsePhone(user.phone)}}</view>
 			</view>
+			<view class="info-item">
+				<view class="label">版本号</view>
+				<view class="right">v{{ version }}</view>
+			</view>
 		</view>
 		<view class="btn-box">
 			<view class="sub-btn" @click="submit()">保存</view>
@@ -40,18 +44,18 @@
 </template>
 
 <script>
-	import {
-		getUserInfo,
-		editUser
-	} from '@/api/user'
+	import { getUserInfo,editUser} from '@/api/user'
 	export default {
 		data() {
 			return {
-				user: null
+				user: null,
+				version:"1.0",
 			}
 		},
 		onLoad() {
-			this.getUserInfo()
+			this.getUserInfo();
+			const accountInfo = wx.getAccountInfoSync();
+			this.version = accountInfo.miniProgram.version 
 		},
 		methods: {
 			bindblur(e) {

BIN
static/images/like.png


Некоторые файлы не были показаны из-за большого количества измененных файлов