Explorar el Código

2022/3/8 App视频通话问题解决,新增心跳机制重连机制

zkl hace 3 años
padre
commit
300e48a75c

+ 233 - 0
MingGaoApp/App - 副本.vue

@@ -0,0 +1,233 @@
+<script>
+	export default {
+		globalData: {
+			token: "",
+
+			// 文本消息
+			socketTask: null,
+			urlData: "ws://192.168.1.17:12345/api/api_gateway?method=control_center.real_time.im_message",
+			is_open_socket: false, // 确保websocket是打开状态
+			list: [],
+			userId: null, // 用户ID
+
+			// 即构
+			video: null, //房间密码和token
+			app: []
+		},
+		onLoad() {},
+		onLaunch: function() {
+			// App启动
+			
+			var that = this
+			// uni.hideTabBar({})
+			uni.getStorage({
+				key: 'session_key',
+				success: function(res) {
+					// console.log(res)
+					that.globalData.token = res.data
+					// console.log('登录成功了')
+					that.msgInit(); // 文本初始化
+				},
+				fail: function(err) {
+					// console.log(err)
+					// console.log('没有登录成功')
+				}
+			})
+			uni.getStorage({
+				key: 'session_key',
+				success: (res) => {
+					console.log(res)
+					if (res.data != "") {
+						this.getlistinfo()
+					} else {
+						uni.navigateTo({
+							url: "../login/login"
+						})
+					}
+				},
+				fail:()=> {
+					uni.navigateTo({
+						url: "../login/login"
+					})
+				}
+			})
+		},
+		onShow: function() {
+			// App展示在前台
+			// console.log('App Show')、
+			
+
+		},
+		onHide: function() {
+			// App不再再展示在前台
+			// console.log('App Hide')
+		},
+		methods: {
+			// 实时通信 - 初始化
+			async getlistinfo() {
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=sysmenage.usermanager.user_info',
+				})
+				// console.log(res)
+				this.app = res.children.filter((item) => {
+					return item.purview_name == "APP"
+				})
+
+				console.log(this.app)
+				if (this.app.length != 0) {
+					if (this.app[0].children[0].purview_name == "我的任务") {
+						uni.switchTab({
+							url: "../index/index"
+						})
+					} else if (this.app[0].children[0].purview_name == "监督") {
+						uni.switchTab({
+							url: "../supervise/index"
+						})
+						uni.setTabBarItem({
+							index: 0,
+							visible: false
+						});
+					} else {
+						uni.switchTab({
+							url: "../response/index"
+						})
+						uni.setTabBarItem({
+							index: 0,
+							visible: false
+						});
+						uni.setTabBarItem({
+							index: 1,
+							visible: false
+						});
+					}
+				} else {
+					uni.setTabBarItem({
+						index: 0,
+						visible: false
+					});
+					uni.setTabBarItem({
+						index: 1,
+						visible: false
+					});
+					uni.switchTab({
+						url: "../response/index"
+					})
+				}
+				// console.log(this.app)
+			},
+			msgInit() {
+				var that = this
+				// 连接webscoket
+				that.globalData.socketTask = uni.connectSocket({
+					url: this.globalData.urlData + "&token=" + that.globalData.token,
+					success(data) {
+						// console.log("websocket连接成功");
+					}
+				});
+
+				// 发送消息 - 获取对话列表
+				var obj = {
+					'action': 'list', // 动作标识,必填
+					'recv_user_id': '', // 接收人用户id, 非必填
+					'data': {}
+				}
+				that.globalData.socketTask.onOpen((res) => {
+					that.globalData.socketTask.send({
+						data: JSON.stringify(obj),
+						async success(res) {
+							that.globalData.is_open_socket = true
+							console.log("消息发送成功");
+						},
+					});
+				})
+
+				// // 接收服务器返回的消息
+				// // 注:只有连接正常打开中 ,才能正常收到消息
+				that.globalData.socketTask.onMessage((res) => {
+					console.log("收到服务器内容:");
+					var val = JSON.parse(res.data)
+					if (val.action == 'list') {
+						var obj1 = {
+							'action': 'list', // 动作标识,必填
+							'recv_user_id': that.globalData.userId, // 接收人用户id, 非必填
+							'data': {
+								'msg_status': false, // 消息未读
+								'msg_info': '', // 发送消息
+							}
+						}
+						that.globalData.socketTask.send({
+							data: JSON.stringify(obj1),
+							async success(res) {
+								// console.log("消息发送成功");
+							},
+						});
+					} else if (val.action == 'none') {
+						// console.log('进入了')
+						that.globalData.list = val.data
+						console.log(that.globalData.list)
+						this.$store.state.list = val.data
+						// console.log(this.$store.state.list)
+					} else if (val.action == 'recv_video') {
+						// console.log(val.data)
+						that.globalData.video = val.data
+						this.$store.state.video = val.data
+						console.log(this.$store.state.video)
+					}
+				});
+				// console.log(that.socketTask)
+
+			},
+			
+			// 关闭scoket连接
+			scoketClose() {
+			    this.socketIo.connectNum = 1
+			    var data = {
+			    	'action': 'list', // 动作标识,必填
+			    	'recv_user_id': '', // 接收人用户id, 非必填
+			    	'data': {}
+			    }
+			    this.socketIo.sen(data) // 这是给后端发送特定数据  
+			    this.socketIo.Close() // 主动关闭连接,不会重连
+			},
+			
+			// 获取websocket的数据
+			getWebsocketData() {
+			    // 要发送的数据包
+			    var data = {
+			    	'action': 'list', // 动作标识,必填
+			    	'recv_user_id': '', // 接收人用户id, 非必填
+			    	'data': {}
+			    }
+			    // 打开连接
+			    this.socketIo.connectSocketInit(data)
+			    // 接收数据
+			    uni.$on("getPositonsOrder", (res) => {
+			        this.connect = true
+			        const {
+			            Code,
+			            data
+			        } = res
+			        // if (Code == xxxx) {
+			        //     // 根据后端传过来的数据进行 业务编写。。。
+			        // } else {
+			           
+			        // }
+					console.log(Code)
+					console.log(data)
+			    })
+			    // 错误时做些什么
+			    uni.$on("connectError", () => {
+					console.log('错误了')
+			        // this.connect = false
+			        // this.scoketError = true
+			    })
+			}
+		},
+	}
+</script>
+
+<!-- // App.vue文件  中首行的位置引入,注意给style标签加入lang="scss"属性 -->
+<style lang="scss">
+	/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
+	@import "uview-ui/index.scss";
+</style>

+ 94 - 17
MingGaoApp/App.vue

@@ -12,11 +12,23 @@
 
 			// 即构
 			video: null, //房间密码和token
-			app: []
+
+			// 测试 - 心跳检测
+			status: null, // websocket是否关闭
+			lockReconnect: false, // 避免重复连接
+			timeout: 5000, // 多少秒执行监测
+			timeoutObj: null, // 检测服务器端是否还活着
+			reconnectTimeOutObj: null, // 重连之后多久再次重连
+			// 测试
+			
+			
+			app: [],
+			hdskdh: null
 		},
 		onLoad() {},
 		onLaunch: function() {
 			// App启动
+
 			var that = this
 			// uni.hideTabBar({})
 			uni.getStorage({
@@ -32,10 +44,6 @@
 					// console.log('没有登录成功')
 				}
 			})
-		},
-		onShow: function() {
-			// App展示在前台
-			// console.log('App Show')、
 			uni.getStorage({
 				key: 'session_key',
 				success: (res) => {
@@ -48,32 +56,30 @@
 						})
 					}
 				},
-				fail:()=> {
+				fail: () => {
 					uni.navigateTo({
 						url: "../login/login"
 					})
 				}
 			})
+		},
+		onShow: function() {
+			// App展示在前台
+			// console.log('App Show')、
 
 		},
 		onHide: function() {
 			// App不再再展示在前台
 			// console.log('App Hide')
+			this.close()
 		},
 		methods: {
-			// 实时通信 - 初始化
 			async getlistinfo() {
 				const res = await this.$myRequest({
 					url: '/api/api_gateway?method=sysmenage.usermanager.user_info',
 				})
-				// console.log(res)
-				this.app = res.children.filter((item) => {
-					return item.purview_name == "APP"
-				})
-
-				console.log(this.app)
-				if (this.app.length != 0) {
-					if (this.app[0].children[0].purview_name == "我的任务") {
+				if (this.globalData.app.length != 0) {
+					if (this.globalData.app[0].children[0].purview_name == "我的任务") {
 						uni.switchTab({
 							url: "../index/index"
 						})
@@ -113,14 +119,15 @@
 				}
 				// console.log(this.app)
 			},
+			
+			// 实时通信 - 初始化
 			msgInit() {
 				var that = this
 				// 连接webscoket
-				// console.log(this.globalData.urlData)
 				that.globalData.socketTask = uni.connectSocket({
 					url: this.globalData.urlData + "&token=" + that.globalData.token,
 					success(data) {
-						// console.log("websocket连接成功");
+						console.log("websocket连接成功");
 					}
 				});
 
@@ -131,11 +138,16 @@
 					'data': {}
 				}
 				that.globalData.socketTask.onOpen((res) => {
+					// 清除重连定时器
+					clearInterval(that.globalData.reconnectTimeOutObj)
+					// 开启检测
+					that.start()
 					that.globalData.socketTask.send({
 						data: JSON.stringify(obj),
 						async success(res) {
 							that.globalData.is_open_socket = true
 							console.log("消息发送成功");
+							
 						},
 					});
 				})
@@ -172,9 +184,74 @@
 						this.$store.state.video = val.data
 						console.log(this.$store.state.video)
 					}
+					
+					
+					this.reset();
+					console.log('消息可正常接收');
 				});
 				// console.log(that.socketTask)
+				
+				// 连接断开
+				// 如果希望websocket连接一直保持,在close或者error上绑定重新连接方法。
+				this.globalData.socketTask.onClose((res) => {
+					console.log(res, '连接关闭');
+					that.reconnect();
+				})
+				
+				// 连接失败
+				that.globalData.socketTask.onError((res) => {
+					console.log(res, '连接错误');
+					that.reconnect();
+				})
+			},
+
+			// 心跳机制
+			start() {
+				// console.log(this.globalData.timeoutObj)
+				// console.log('进入心跳机制了', this.globalData.timeout)
+				this.globalData.timeoutObj = setInterval(() => {
+					//这里发送一个心跳,后端收到后,返回一个心跳消息,
+					//onmessage拿到返回的心跳就说明连接正常
+					var obj = {
+						'action': 'list', // 动作标识,必填
+						'recv_user_id': '', // 接收人用户id, 非必填
+						'data': {}
+					}
+					this.globalData.socketTask.send(JSON.stringify(obj));
+					console.log('进入心跳机制了', this.globalData.timeout)
+				}, this.globalData.timeout)
+			},
+			// 清除心跳机制
+			reset() {
+				// 清除定时器重新发送一个心跳信息
+				// clearTimeout(this.globalData.timeoutObj);
+				clearInterval(this.globalData.timeoutObj);
+				this.start();
+			},
+
+			// 重连
+			reconnect() {
+				// 防止多个方法调用,多处重连
+				if (this.lockReconnect) {
+					return;
+				};
+				this.lockReconnect = true;
+
+				console.log('准备重连');
+
+				//没连接上会一直重连,设置延迟避免请求过多
+				this.globalData.reconnectTimeOutObj = setInterval(() => {
+					// 重新连接
+					this.msgInit()
+					console.log('正在重新连接')
+					this.lockReconnect = false;
+				}, 4000);
+			},
 
+			// 手动关闭
+			close() {
+				console.log('已经手动关闭了')
+				this.globalData.socketTask.close()
 			},
 		},
 	}

+ 3 - 3
MingGaoApp/manifest.json

@@ -56,9 +56,9 @@
                 "androidStyle" : "default",
                 "useOriginalMsgbox" : false,
                 "android" : {
-                    "hdpi" : "C:/Users/FC/Desktop/智网/智云图片/statr.png",
-                    "xhdpi" : "C:/Users/FC/Desktop/智网/智云图片/statr.png",
-                    "xxhdpi" : "C:/Users/FC/Desktop/智网/智云图片/statr.png"
+                    "hdpi" : "F:/000-项目/软件/名高项目App/相关/7cd5130f449996835a12c93537623d1.png",
+                    "xhdpi" : "F:/000-项目/软件/名高项目App/相关/7cd5130f449996835a12c93537623d1.png",
+                    "xxhdpi" : "F:/000-项目/软件/名高项目App/相关/7cd5130f449996835a12c93537623d1.png"
                 }
             },
             "icons" : {

+ 3 - 144
MingGaoApp/pages/response/index.vue

@@ -55,44 +55,9 @@
 			</view>
 		</u-popup>
 
-		<!-- 视频通话框 -->
-		<!-- <u-popup :show="videoShow" :closeOnClickOverlay="false" :customStyle="styleObj1" mode="center"
-			@close="videClose" @open="videOpen">
-
-			本地预览视图
-			<view class="video_me">
-				<zego-local-view :viewMode="publisherViewModeIndex"
-					style="height: 403.84rpx;flex: 1; border: 1px solid #0000;">
-				</zego-local-view>
-			</view>
-
-			服务器传来的预览图
-			<view class="video_you">
-				<zego-remote-view :viewMode="publisherViewModeIndex"
-					style="height: 403.84rpx;flex: 1; border: 1px solid #0000;">
-				</zego-remote-view>
-			</view>
-
-			<view class="video_btn">
-				<view class="video_imgList">
-					<view class="video_imgList1">
-						<view class="video_view">
-							<image src="../../static/image/9.png" mode=""></image>
-						</view>
-						<view class="">翻转镜头</view>
-					</view>
-					<view class="video_imgList2">
-						<view class="video_view">
-							<image src="../../static/image/8.png" mode=""></image>
-						</view>
-						<view class="">切换语音通话</view>
-					</view>
-				</view>
-				
-				<u-button type="error" style="border-radius: 50px; width: 50px; height: 50px;" size="mini" text="关闭">
-				</u-button>
-			</view>
-		</u-popup> -->
+		<!-- 测试 -->
+		<image id="remoteVideo"></image>
+		<!-- 测试 -->
 	</view>
 </template>
 
@@ -161,13 +126,6 @@
 					height: '500px'
 				},
 
-				// videoShow: false, // 视频通话框
-				// styleObj1: {
-				// 	backgroundColor: "#fff",
-				// 	height: '100%',
-				// 	width: '100%'
-				// },
-				// publisherViewModeIndex: 0, // 本地预览图
 				isPublishingStream: false,
 			}
 		},
@@ -191,72 +149,6 @@
 				console.log(this.list)
 			},
 
-			// 即构 - 视频通话 初始化
-			async setup() {
-				var that = this
-				// 创建引擎
-				let profile = {
-					appID: AppID,
-					appSign: AppSign,
-					scenario: ZegoScenario.General
-				}
-				this.engine = await ZegoExpressEngine.createEngineWithProfile(profile);
-				// console.log(this.engine)
-				this.addListeners();
-				// console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + that.videoObj.room_id)
-				this.engine.loginRoom(that.videoObj.room_id, {
-					userID: that.videoObj.room_id,
-					userName: that.videoObj.room_id
-				}, {
-					isUserStatusNotify: true
-				});
-			},
-
-			// 即构 - 视频通话 监听房间
-			addListeners() {
-				// 房间状态变化通知
-				this.engine.on("roomStateUpdate", (roomID, state, errorCode, extendedData) => {
-					console.log('房间状态变化')
-				});
-
-				// 房间用户变化通知
-				this.engine.on("roomUserUpdate", (roomID, updateType, userList) => {
-					console.log('房间用户变化通知')
-				});
-
-				// 房间内其他用户推的流变化通知
-				this.engine.on("roomStreamUpdate", (roomID, updateType, streamList) => {
-					console.log('房间内其他用户推的流变化通知')
-				});
-
-				// 房间内在线用户数量回调
-				this.engine.on("roomOnlineUserCountUpdate", (roomID, count) => {
-					console.log(roomID)
-					console.log(count)
-					console.log('>?>>>>>>>>>>>>>>>>>>>>>>>在线用户有变化')
-				});
-
-				// 拉流质量回调
-				this.engine.on("playerQualityUpdate", (streamID, quality) => {
-					console.log('拉流质量回调')
-				});
-
-				// 推流质量回调
-				this.engine.on("publisherQualityUpdate", (streamID, quality) => {
-					console.log('推流质量回调')
-				});
-
-				// 采集视频大小变更回调
-				this.engine.on("publisherVideoSizeChanged", (width, height, channel) => {
-					console.log('采集视频大小变更回调')
-				});
-
-				// 拉流分辨率变更通知
-				this.engine.on("playerVideoSizeChanged", (streamID, width, height) => {
-					console.log('拉流分辨率变更通知')
-				});
-			},
-
 			// 进入详情
 			defail(data) {
 				var that = this
@@ -294,43 +186,10 @@
 				this.show = false
 				console.log('close');
 			},
-
-			// 视频通话弹框
-			// videOpen() {
-			// 	console.log('open');
-			// },
-			// videClose() {
-			// 	console.log('close');
-			// },
-			
-			// 推流 - 展示视图
-			onPublish() {
-				// 设置视频配置
-				ZegoExpressEngine.instance().setVideoConfig(this.videoObj.room_id);
-				
-				if (this.isPublishingStream) {
-					this.engine.stopPreview();
-					this.engine.stopPublishingStream();
-					this.publishBtnName = "Start Publishing";
-				} else {
-					this.engine.startPreview();
-					this.engine.startPublishingStream(this.videoObj.room_id);
-					this.publishBtnName = "Stop Publishing";
-				}
-				this.isPublishingStream = !this.isPublishingStream;
-			},
 		},
 
 		async onLoad() {
 			// uni.startPullDownRefresh(); // 开始刷新
-
-			// 即构 - 视频通话
-			// 获取系统信息同步接口
-			// if (uni.getSystemInfoSync().platform === 'android') {
-			// 	await permision.requestAndroidPermission('android.permission.RECORD_AUDIO');
-			// 	await permision.requestAndroidPermission('android.permission.CAMERA');
-			// }
-			// await this.setup()
 		},
 
 		onShow() {

+ 359 - 0
MingGaoApp/pages/response/video - 副本 (2).nvue

@@ -0,0 +1,359 @@
+<template>
+	<view class="video_box" :style="'height:' +  phoneHeight + 'px'">
+		<!-- 本地预览视图 -->
+		<view class="video_me" :style="'height:' +  phoneHeight + 'px'">
+			<zego-local-view v-if="videoShow" :viewMode="publisherViewModeIndex"
+				style="width: 100%; flex: 1; border: 1px solid #0000; z-index: 20">
+			</zego-local-view>
+		</view>
+
+		<!-- 服务器传来的预览图 -->
+		<!-- <view class="video_you" @click="changeShow"> -->
+		<view class="video_you">
+			<zego-remote-view :streamID="serveViewModeIndex" :viewMode="viewModeA"
+				style="height: 403.84rpx; flex: 1;">
+			</zego-remote-view>
+		</view>
+
+		<view class="video_btn">
+			<view class="video_imgList">
+				<view class="video_imgList1">
+					<view class="video_view" @click="turn">
+						<image class="video_view_img" src="../../static/image/9.png" mode=""></image>
+					</view>
+					<text class="video_view_txt">翻转镜头</text>
+				</view>
+				<view class="video_imgList2">
+					<view class="video_view">
+						<image class="video_view_img" src="../../static/image/8.png" mode=""></image>
+					</view>
+					<text class="video_view_txt">切换语音通话</text>
+				</view>
+			</view>
+
+			<!-- 	<u-button type="error" class="offBtn" @click="offVideo()"  size="mini" text="关闭">
+			</u-button> -->
+			<image @click="offVideo()" style="width: 50px; height: 50px; margin: 0 0 0 330rpx;"
+				src="../../static/image/10.png" mode=""></image>
+		</view>
+
+		<!-- 消息提醒 -->
+		<u-toast ref="uToast"></u-toast>
+	</view>
+</template>
+
+<script>
+	import permision from "@/zego-express-video-uniapp/permission.js";
+	import ZegoExpressEngine from '@/zego-express-video-uniapp/lib/ZegoExpressEngine';
+	import {
+		ZegoScenario,
+		ZegoRoomState,
+		ZegoUpdateType,
+		// ZegoViewMode
+	} from '@/zego-express-video-uniapp/lib/ZegoExpressDefines'
+	import {
+		AppID,
+		AppSign
+	} from '@/zego-express-video-uniapp/KeyCenter.js'
+	import ZegoLocalView from '@/zego-express-video-uniapp/zego-view/ZegoLocalView';
+	import ZegoRemoteView from '@/zego-express-video-uniapp/zego-view/ZegoRemoteView';
+	export default {
+		data() {
+			return {
+				phoneHeight: '', // 获取当前的屏幕高度
+
+				// 即构
+				publisherViewModeIndex: 0, // 本地预览图
+				viewModeA: 0, // 服务器预览图
+				serveViewModeIndex: "", // 服务器拉流预览图
+				engine: undefined,
+				videoObj: null,
+				userid: "Uni" + Math.floor(Math.random() * 1000000).toString(),
+				isPublishingStream: false,
+				shotShow: false, // 翻转镜头
+				videoShow: true, // 切换视频显示
+			}
+		},
+		components: {
+			ZegoLocalView: ZegoLocalView,
+			ZegoRemoteView: ZegoRemoteView
+		},
+
+		methods: {
+			// 即构 - 视频通话 初始化
+			async setup() {
+				var that = this
+				// 创建引擎
+				let profile = {
+					appID: AppID,
+					appSign: AppSign,
+					scenario: ZegoScenario.General
+				}
+				this.engine = await ZegoExpressEngine.createEngineWithProfile(profile);
+				this.engine.useFrontCamera(this.shotShow); // 设置前后摄像头
+				// console.log(this.engine)
+				this.addListeners();
+				// console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + that.videoObj.room_id)
+				this.engine.loginRoom(that.videoObj.room_id, {
+					userID: that.videoObj.room_id,
+					userName: that.videoObj.room_id
+				}, {
+					isUserStatusNotify: true
+				});
+			},
+
+			// 即构 - 翻转镜头
+			turn() {
+				this.shotShow = !this.shotShow
+				this.engine.useFrontCamera(this.shotShow)
+			},
+
+			// 切换视频显示
+			changeShow() {
+				this.videoShow = !this.videoShow
+				// this.onPublish()
+				this.engine.startPreview();
+				this.engine.startPublishingStream(this.videoObj.room_id);
+				this.publishBtnName = "Stop Publishing";
+				console.log(this.videoShow)
+			},
+
+			// 即构 - 视频通话 监听房间
+			addListeners() {
+				// 房间状态变化通知
+				this.engine.on("roomStateUpdate", (roomID, state, errorCode, extendedData) => {
+					// console.log('房间状态变化')
+					if (state == "CONNECTED") {
+						// 与房间连接成功,只有当房间状态是连接成功时,才能进行推流、拉流等操作。
+						// 接下来的“预览并推流”的代码写在这里
+						console.log("房间连接成功");
+					}
+					if (state == "DISCONNECTED") {
+						// 与房间断开了连接
+						console.log("与房间断开连接");
+					}
+
+					if (state == "CONNECTING") {
+						// 与房间尝试连接中
+						console.log("与房间尝试连接中");
+					}
+				});
+
+				// 房间用户变化通知
+				this.engine.on("roomUserUpdate", (roomID, updateType, userList) => {
+					// console.log('房间用户变化通知')
+					// console.log(updateType)
+					// console.log(userList)
+					// if (updateType == "ADD") {
+					// 	console.log('hsdjshadjh')
+					// } else if (updateType == 1 ) {
+					// 	console.log('几十块的教科书')
+					// 	this.offVideo()
+					// }
+					// console.log(updateType + '------------------------')
+					// console.log(userList)
+					// console.log("有其他用户进出房间");
+
+					if (updateType == "1") {
+						// 有其他用户退出房间
+						this.offVideo()
+					}
+				});
+
+				// 房间内其他用户推的流变化通知
+				this.engine.on("roomStreamUpdate", (roomID, updateType, streamList) => {
+					if (updateType == "0") {
+						// 流新增,开始拉流
+						this.tensile(streamList[0].streamID)
+					} else if (updateType == "1") {
+						// 流删除,停止拉流
+						this.notTensile(streamList[0].streamID);
+					}
+				});
+
+				// 房间内在线用户数量回调
+				// this.engine.on("roomOnlineUserCountUpdate", (roomID, count) => {
+				// 	// console.log(roomID)	
+				// 	console.log(count)
+				// 	console.log('>?>>>>>>>>>>>>>>>>>>>>>>>在线用户有变化')
+				// });
+
+				// 拉流质量回调
+				this.engine.on("playerQualityUpdate", (streamID, quality) => {
+					console.log('拉流质量回调')
+				});
+
+				// 拉流后的事件回调
+				this.engine.on("playerStateUpdate", (streamID, state, errorCode, extendedData) => {
+					console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + '拉流后的事件触发了')
+				})
+			},
+
+			// 拉流 
+			tensile(roomId) {
+				console.log('拉流进入了啊')
+				console.log(roomId)
+				this.serveViewModeIndex = roomId
+				console.log(this.serveViewModeIndex)
+				this.engine.startPlayingStream(roomId);
+			},
+
+			// 停止拉流
+			notTensile(roomId) {
+				console.log(roomId)
+				this.serveViewModeIndex = roomId
+				console.log(this.serveViewModeIndex)
+				this.engine.stopPlayingStream(roomId)
+			},
+
+			// 推流 - 展示视图 - 本地视频流
+			onPublish() {
+				// 设置视频配置
+				// ZegoExpressEngine.instance().setVideoConfig(this.videoObj.room_id);
+
+				if (this.isPublishingStream) {
+					// 停止推流
+					this.engine.stopPreview();
+					this.engine.stopPublishingStream();
+					this.publishBtnName = "Start Publishing";
+				} else {
+					// 开始推流
+					this.engine.startPreview();
+					this.engine.startPublishingStream(this.videoObj.room_id);
+					this.publishBtnName = "Stop Publishing";
+				}
+				this.isPublishingStream = !this.isPublishingStream;
+			},
+
+			// 挂断退出
+			offVideo() {
+				console.log('进入了啊')
+				this.engine.logoutRoom(this.videoObj.room_id)
+				this.$refs.uToast.show({
+					type: 'default',
+					message: '结束视频通话!',
+				})
+				setTimeout(() => {
+					uni.navigateBack({
+						delta: 1
+					})
+				}, 1500)
+				// uni.redirectTo({
+				// 	url: "/pages/response/index"
+				// })
+
+			},
+		},
+
+		async onLoad(optinos) {
+			var that = this
+			that.videoObj = JSON.parse(optinos.videoObj)
+			// console.log(that.videoObj)
+			// 即构 - 视频通话
+			// 获取系统信息同步接口
+			if (uni.getSystemInfoSync().platform === 'android') {
+				await permision.requestAndroidPermission('android.permission.RECORD_AUDIO');
+				await permision.requestAndroidPermission('android.permission.CAMERA');
+			}
+			await this.setup()
+			this.onPublish(); // 推流
+			uni.getSystemInfo({ //异步获取。
+				success(res) {
+					// that.phoneHeight = res.windowHeight - 13; //窗口高度
+					that.phoneHeight = res.windowHeight; //窗口高度
+				}
+			});
+		},
+
+		// 监听页面返回
+		onBackPress() {
+			console.log('返回了!')
+		},
+	}
+</script>
+
+<style lang="scss">
+	.video_box {
+		background: #000;
+
+		.video_you {
+			border: 1px solid;
+			background: #fff;
+			width: 150px;
+			height: 200px;
+			position: absolute;
+			right: 10px;
+			top: 10px;
+			overflow: hidden;
+		}
+
+		.video_me {
+			z-index: 100;
+			background: #000;
+			position: relative;
+			right: 0;
+			top: 0;
+		}
+
+		.video_btn {
+			position: absolute;
+			bottom: 35rpx;
+			left: 0;
+			width: 750rpx;
+
+			.video_imgList {
+				display: flex;
+				flex-direction: row;
+				justify-content: space-around;
+
+				// 翻转
+				.video_imgList1 {
+					.video_view {
+						background: rgba(0, 0, 0, .5);
+						border-radius: 50px;
+						width: 50px;
+						height: 50px;
+						margin: 0 auto;
+
+						.video_view_img {
+							height: 25px;
+							width: 25px;
+							margin: 24rpx 0 0 25rpx;
+						}
+					}
+
+					.video_view_txt {
+						color: #fff;
+						font-size: 14px;
+						line-height: 30px;
+						text-align: center;
+					}
+				}
+
+				// 语音通话
+				.video_imgList2 {
+					.video_view {
+						background: rgba(0, 0, 0, .5);
+						border-radius: 50px;
+						width: 50px;
+						height: 50px;
+						margin: 0 0 0 30rpx;
+
+						.video_view_img {
+							height: 25px;
+							width: 25px;
+							margin: 24rpx 0 0 25rpx;
+						}
+					}
+
+					.video_view_txt {
+						color: #fff;
+						font-size: 14px;
+						line-height: 30px;
+						text-align: center;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 119 - 73
MingGaoApp/pages/response/video.nvue

@@ -5,22 +5,13 @@
 			<zego-local-view v-if="videoShow" :viewMode="publisherViewModeIndex"
 				style="width: 100%; flex: 1; border: 1px solid #0000; z-index: 20">
 			</zego-local-view>
-			
-			<zego-remote-view v-else :viewMode="publisherViewModeIndex"
-				style="height: 403.84rpx;flex: 1; z-index: 20">
-			</zego-remote-view>
 		</view>
 
 		<!-- 服务器传来的预览图 -->
-		<!-- <view class="video_you" @click="changeShow"> -->
-		<view class="video_you">
-			<zego-remote-view v-if="videoShow" :viewMode="publisherViewModeIndex"
-				style="height: 403.84rpx;flex: 1; z-index: 20">
+		<view class="video_you" v-if="allUserViewObjectList.length > 0" v-for="(item, index) in allUserViewObjectList" :key="item.userID">
+			<zego-remote-view v-if="item.streamID" :streamID="item.streamID" :viewMode="item.viewMode"
+				style="height: 403.84rpx; flex: 1;">
 			</zego-remote-view>
-			
-			<zego-local-view v-else :viewMode="publisherViewModeIndex"
-				style="width: 100%; flex: 1; border: 1px solid #0000; z-index: 20">
-			</zego-local-view>
 		</view>
 
 		<view class="video_btn">
@@ -39,8 +30,6 @@
 				</view>
 			</view>
 
-			<!-- 	<u-button type="error" class="offBtn" @click="offVideo()"  size="mini" text="关闭">
-			</u-button> -->
 			<image @click="offVideo()" style="width: 50px; height: 50px; margin: 0 0 0 330rpx;"
 				src="../../static/image/10.png" mode=""></image>
 		</view>
@@ -72,24 +61,37 @@
 
 				// 即构
 				publisherViewModeIndex: 0, // 本地预览图
-				serveViewModeIndex: 0, // 服务器拉流预览图
+				viewModeA: 0, // 服务器预览图
+				serveViewModeIndex: "", // 服务器拉流预览图
 				engine: undefined,
 				videoObj: null,
 				userid: "Uni" + Math.floor(Math.random() * 1000000).toString(),
 				isPublishingStream: false,
 				shotShow: false, // 翻转镜头
 				videoShow: true, // 切换视频显示
-
-				// 消息提醒
-				// typeVide: '',
-				// videoMsg: "",
+				
+				allStreamList: [],
+				allUserViewObjectList: [],
 			}
 		},
 		components: {
 			ZegoLocalView: ZegoLocalView,
 			ZegoRemoteView: ZegoRemoteView
 		},
-
+		
+		watch: {
+			allUserViewObjectList(val) {
+				if (val.length > 0) {
+					val.forEach((item) => {
+						if (item.streamID) {
+							this.tensile(item)
+							return true
+						}
+					})
+				}
+			}
+		},
+		
 		methods: {
 			// 即构 - 视频通话 初始化
 			async setup() {
@@ -118,7 +120,7 @@
 				this.shotShow = !this.shotShow
 				this.engine.useFrontCamera(this.shotShow)
 			},
-			
+
 			// 切换视频显示
 			changeShow() {
 				this.videoShow = !this.videoShow
@@ -128,7 +130,7 @@
 				this.publishBtnName = "Stop Publishing";
 				console.log(this.videoShow)
 			},
-			
+
 			// 即构 - 视频通话 监听房间
 			addListeners() {
 				// 房间状态变化通知
@@ -152,75 +154,122 @@
 
 				// 房间用户变化通知
 				this.engine.on("roomUserUpdate", (roomID, updateType, userList) => {
-					// console.log('房间用户变化通知')
-					// console.log(updateType)
-					// console.log(userList)
-					// if (updateType == "ADD") {
-					// 	console.log('hsdjshadjh')
-					// } else if (updateType == 1 ) {
-					// 	console.log('几十块的教科书')
-					// 	this.offVideo()
-					// }
 					console.log(updateType)
 					console.log(userList)
 					console.log("有其他用户进出房间");
+					if (updateType == ZegoUpdateType.Add) {
+						for (let user of userList) {
+							for (let stream of this.allStreamList) {
+								if (user.userID == stream.user.userID) {
+									user.streamID = stream.streamID;
+								}
+							}
+							this.allUserViewObjectList.push(user);
+						}
+					} else if (updateType == ZegoUpdateType.Delete) {
+						this.allUserViewObjectList = this.allUserViewObjectList.filter((object) => {
+							for (let user of userList) {
+								if (user.userID == object.userID) {
+									return false;
+								}
+							}
+							return true;
+						});
+					}
+
+					if (updateType == "1") {
+						// 有其他用户退出房间
+						this.offVideo()
+					}
 				});
 
 				// 房间内其他用户推的流变化通知
 				this.engine.on("roomStreamUpdate", (roomID, updateType, streamList) => {
-					console.log('房间内其他用户推的流变化通知')
-					console.log(updateType)
-					console.log(streamList)
-
-					// 房间内其他用户音视频流变化的通知
-					console.log("有其他用户开启或关闭音频");
-					if (updateType == "ADD") {
-						// 流新增,开始拉流
-						this.tensile(streamList[0].streamID);
-					} else if (updateType == "DELETE") {
-						// 流删除,停止拉流
-						this.notTensile(streamList[0].streamID);
+					// if (updateType == "0") {
+					// 	// 流新增,开始拉流
+					// 	this.tensile(streamList[0].streamID)
+					// } else if (updateType == "1") {
+					// 	// 流删除,停止拉流
+					// 	this.notTensile(streamList[0].streamID);
+					// }
+					
+					console.log('---------updateType-----------', updateType)
+					console.log('---------streamList-----------', streamList)
+					console.log('---------ZegoUpdateType-----------', ZegoUpdateType)
+					console.log('---------ZegoUpdateType.Add-----------', ZegoUpdateType.Add)
+					console.log('---------ZegoUpdateType.Delete-----------', ZegoUpdateType.Delete)
+					console.log('---------allUserViewObjectList-----------', this.allUserViewObjectList)
+					
+					if (updateType == ZegoUpdateType.Add) {
+						for (let object of this.allUserViewObjectList) {
+							for (let stream of streamList) {
+								if (object.userID == stream.user.userID) {
+									object.streamID = stream.streamID;
+								}
+							}
+						}
+						this.allStreamList = this.allStreamList.concat(streamList);
+					} else if (updateType == ZegoUpdateType.Delete) {
+						for (let object of this.allUserViewObjectList) {
+							for (let stream of streamList) {
+								if (object.streamID == stream.streamID) {
+									object.streamID = undefined;
+								}
+							}
+						}
+						this.allStreamList = this.allStreamList.filter((object) => {
+							for (let stream of streamList) {
+								if (object.streamID == stream.streamID) {
+									return false;
+								}
+							}
+							return true;
+						});
 					}
 				});
 
 				// 房间内在线用户数量回调
 				// this.engine.on("roomOnlineUserCountUpdate", (roomID, count) => {
 				// 	// console.log(roomID)	
-				// 	// console.log(count)
-				// 	// console.log('>?>>>>>>>>>>>>>>>>>>>>>>>在线用户有变化')
+				// 	console.log(count)
+				// 	console.log('>?>>>>>>>>>>>>>>>>>>>>>>>在线用户有变化')
 				// });
 
 				// 拉流质量回调
-				// this.engine.on("playerQualityUpdate", (streamID, quality) => {
-				// 	console.log('拉流质量回调')
-				// });
-
-				// // 推流质量回调
-				// this.engine.on("publisherQualityUpdate", (streamID, quality) => {
-				// 	// console.log('推流质量回调')
-				// });
-
-				// // 采集视频大小变更回调
-				// this.engine.on("publisherVideoSizeChanged", (width, height, channel) => {
-				// 	// console.log('采集视频大小变更回调')
-				// });
+				this.engine.on("playerQualityUpdate", (streamID, quality) => {
+					console.log('拉流质量回调')
+				});
 
-				// // 拉流分辨率变更通知
-				// this.engine.on("playerVideoSizeChanged", (streamID, width, height) => {
-				// 	// console.log('拉流分辨率变更通知')
-				// });
+				// 拉流后的事件回调
+				this.engine.on("playerStateUpdate", (streamID, state, errorCode, extendedData) => {
+					console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + '拉流后的事件触发了')
+				})
 			},
-			
+
 			// 拉流 
-			tensile(roomId) {
-				this.engine.instance().startPlayingStream(roomId)
-			},
+			// tensile(roomId) {
+			// 	console.log('拉流进入了啊')
+			// 	console.log(roomId)
+			// 	this.serveViewModeIndex = roomId
+			// 	console.log(this.serveViewModeIndex)
+			// 	this.engine.startPlayingStream(roomId);
+			// },
 			
+			tensile(item) {
+				console.log(this.allStreamList)
+				console.log(item)
+				console.log(this.allUserViewObjectList)
+				this.engine.startPlayingStream(item.streamID)
+			},
+
 			// 停止拉流
 			notTensile(roomId) {
-				this.engine.instance().stopPlayingStream(roomId)
+				console.log(roomId)
+				this.serveViewModeIndex = roomId
+				console.log(this.serveViewModeIndex)
+				this.engine.stopPlayingStream(roomId)
 			},
-			
+
 			// 推流 - 展示视图 - 本地视频流
 			onPublish() {
 				// 设置视频配置
@@ -239,9 +288,6 @@
 				}
 				this.isPublishingStream = !this.isPublishingStream;
 			},
-			
-			// 停止推流
-			// notTensile() {},
 
 			// 挂断退出
 			offVideo() {
@@ -253,13 +299,13 @@
 				})
 				setTimeout(() => {
 					uni.navigateBack({
-					    delta: 1
+						delta: 1
 					})
 				}, 1500)
 				// uni.redirectTo({
 				// 	url: "/pages/response/index"
 				// })
-				
+
 			},
 		},
 

BIN
MingGaoApp/unpackage/debug/android_debug.apk


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
MingGaoApp/unpackage/dist/build/app-plus/app-config-service.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 3 - 3
MingGaoApp/unpackage/dist/build/app-plus/app-service.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
MingGaoApp/unpackage/dist/build/app-plus/app-view.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
MingGaoApp/unpackage/dist/build/app-plus/manifest.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
MingGaoApp/unpackage/dist/build/app-plus/pages/response/video.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2 - 2
MingGaoApp/unpackage/dist/build/app-plus/view.umd.min.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2083 - 2082
MingGaoApp/unpackage/dist/dev/app-plus/app-service.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2326 - 2325
MingGaoApp/unpackage/dist/dev/app-plus/app-view.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
MingGaoApp/unpackage/dist/dev/app-plus/manifest.json


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 379 - 391
MingGaoApp/unpackage/dist/dev/app-plus/pages/response/video.js


+ 112 - 0
MingGaoApp/util/socket.js

@@ -0,0 +1,112 @@
+class wsRequest {
+
+	constructor(url, time) {
+		this.status = null; // websocket是否关闭
+		this.lockReconnect = false //避免重复连接
+		this.url = url
+
+		//心跳检测
+		this.timeout= time //多少秒执行检测
+		this.timeoutObj= null //检测服务器端是否还活着
+		this.reconnectTimeOutObj= null //重连之后多久再次重连
+
+		try {
+			return this.initRequest()
+		} catch (e) {
+			console.log('catch');
+			this.reconnect();
+		}
+	}
+
+	initRequest() {
+		this.socketTask = uni.connectSocket({
+			url: this.url, //接口地址。
+			success: () => {
+				console.log('连接成功');
+				// 返回实例
+				return this.socketTask
+			}
+		})
+		
+		this.socketTask.onOpen(res => {
+			console.log(res, '连接打开');
+			// 清除重连定时器
+			clearTimeout(this.reconnectTimeOutObj)
+			// 开启检测
+			this.start()
+			
+		})
+
+		// 如果希望websocket连接一直保持,在close或者error上绑定重新连接方法。
+		this.socketTask.onClose((res) => {
+			console.log(res, '连接关闭');
+			this.reconnect();
+		})
+
+		this.socketTask.onError((res) => {
+			console.log(res, '连接错误');
+			this.reconnect();
+		})
+		
+		this.socketTask.onMessage(res => {
+			//接受任何消息都说明当前连接是正常的
+			this.reset();
+			console.log(res, 'pong');
+		})
+
+	}
+
+	send(value) {
+		return new Promise((resovle,reject)=>{
+			this.socketTask.send({
+				data: value,
+				success:()=>{
+					resovle('发送成功')
+				}
+			})
+		})
+	}
+
+	// reset和start方法主要用来控制心跳的定时。
+	reset(){
+		// 清除定时器重新发送一个心跳信息
+		clearTimeout(this.timeoutObj);
+     this.start();
+	}
+	start(){
+		this.timeoutObj = setTimeout(() => {
+			//这里发送一个心跳,后端收到后,返回一个心跳消息,
+			//onmessage拿到返回的心跳就说明连接正常
+			console.log('ping');
+			this.socketTask.send({data:"ping"});
+			
+		}, this.timeout)
+	}
+
+	// 重连
+	reconnect() {
+		// 防止多个方法调用,多处重连
+		if (this.lockReconnect) {
+			return;
+		};
+		this.lockReconnect = true;
+		
+		console.log('准备重连');
+		
+		//没连接上会一直重连,设置延迟避免请求过多
+		this.reconnectTimeOutObj = setTimeout(()=>{
+			// 重新连接
+			this.initRequest()
+
+			this.lockReconnect = false;
+		}, 4000);
+	}
+
+	// 手动关闭
+	close() {
+		this.socketTask.close()
+	}
+}
+
+module.exports = wsRequest
+

+ 2 - 2
MingGaoApp/util/url.js

@@ -1,4 +1,4 @@
 export default{
- baseUrl:"http://114.115.147.140:12345"
- // baseUrl:"http://192.168.1.17:12345"
+ // baseUrl:"http://114.115.147.140:12345"
+ baseUrl:"http://192.168.1.17:12345"
 }