| 
					
				 | 
			
			
				@@ -92,19 +92,23 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public static final String ROOM_UID = "${roomUid}"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //直播间累计用户信息-指只要进入到该房间的用户都要记录 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static final String LIVE_ROOM_TOTAL_USER_LIST = "IM:LIVE_ROOM_TOTAL_USER_LIST:" + ROOM_UID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String LIVE_ROOM_TOTAL_USER_LIST = String.join(":", "IM:LIVE_ROOM_TOTAL_USER_LIST", ROOM_UID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //直播间在线用户信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static final String LIVE_ROOM_ONLINE_USER_LIST = "IM:LIVE_ROOM_ONLINE_USER_LIST:" + ROOM_UID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //主讲人信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static final String LIVE_SPEAKER_INFO = "IM:LIVE_SPEAKER_INFO:" + USER_ID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //用户对应的直播间Uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static final String LIVE_USER_ROOM = "IM:LIVE_ROOM_USER:" + USER_ID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //记录人员最后变更的状态消息时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static final String LIVE_USER_STATE_TIME = "IM:LIVE_USER_STATE_TIME:" + USER_ID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String LIVE_ROOM_ONLINE_USER_LIST = String.join(":", "IM:LIVE_ROOM_ONLINE_USER_LIST", ROOM_UID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //当前房间主讲人心跳 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String LIVE_ROOM_SPEAKER_HEART_BEAT = String.join(":", "IM:LIVE_ROOM_SPEAKER_HEART_BEAT", ROOM_UID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //房间点赞数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static final String LIVE_ROOM_LIKE = "IM:LIVE_ROOM_LIKE:" + ROOM_UID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String LIVE_ROOM_LIKE = String.join(":", "IM:LIVE_ROOM_LIKE", ROOM_UID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //计算人员观看时长锁 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static final String LIVE_LOOK_LOCK = "IM:LIVE_LOOK_LOCK:" + ROOM_UID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String LIVE_LOOK_LOCK = String.join(":", "IM:LIVE_LOOK_LOCK", ROOM_UID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //用户对应的直播间Uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String LIVE_USER_ROOM = String.join(":", "IM:LIVE_ROOM_USER", USER_ID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //记录人员最后变更的状态消息时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String LIVE_USER_STATE_TIME = String.join(":", "IM:LIVE_USER_STATE_TIME", USER_ID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //主讲人信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String LIVE_SPEAKER_INFO = String.join(":", "IM:LIVE_SPEAKER_INFO", ROOM_UID, USER_ID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //主讲人最近一次加入房间的clientIp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String LIVE_SPEAKER_LAST_CLIENT_IP = String.join(":", "IM:LIVE_SPEAKER_LAST_CLIENT_IP", ROOM_UID, USER_ID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //直播提前开始时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public static final int PRE_LIVE_TIME_MINUTE = 30; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -198,14 +202,17 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         param.put("tenantId", TenantContextHolder.getTenantId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //查询该人员分部  及 分部下包含的学校(合作单位) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         SysUser sysUser = getSysUser(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //分部 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String organIds = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //如果是超管就查询当前机构所有的直播间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (sysUser.getTenantId() == -1 || sysUser.getIsSuperAdmin()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             param.put("allRoom", 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Employee employee = employeeService.get(sysUser.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (Objects.nonNull(employee) && Objects.nonNull(employee.getOrganIdList())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                param.put("organIds", employee.getOrganIdList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                String schoolIds = baseMapper.querySchoolIds(employee.getOrganIdList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                organIds = employee.getOrganIdList(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                param.put("organIds", organIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                String schoolIds = baseMapper.querySchoolIds(organIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (StringUtils.isNotBlank(schoolIds)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     param.put("schoolIds", schoolIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -435,9 +442,27 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //获取直播间主讲人信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, room.getSpeakerId().toString())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(room.getRoomUid(), room.getSpeakerId().toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (speakerCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             RoomSpeakerInfo speakerInfo = speakerCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //查询用户是否在线 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (imFeignService.checkOnline(speakerInfo.getSpeakerId().toString())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.info("roomDestroy destroyExpiredLiveRoom  is online >>>> roomId:{} speakerId:{}", room.getId(), speakerInfo.getSpeakerId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //校验房间心跳是否过期没续租 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            RBucket<Date> lastRoomHeartbeatCache = redissonClient.getBucket(LIVE_ROOM_SPEAKER_HEART_BEAT.replace(ROOM_UID, room.getRoomUid())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (lastRoomHeartbeatCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //获取最后一次房间心跳时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Date lastDate = lastRoomHeartbeatCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //房间心跳过期时间 = 将房间心跳时间+过期分钟 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Date lastRoomDateExpired = DateUtil.addMinutes(lastDate, expiredMinute); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //当前时间 小于 房间心跳过期时间 则不销毁 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (now.getTime() <= lastRoomDateExpired.getTime()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    log.info("roomDestroy destroyExpiredLiveRoom  last room heartbeat  >>>> roomId:{} speakerId:{}", room.getId(), speakerInfo.getSpeakerId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //1.主播没有进入房间,则直接销毁房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (Objects.isNull(speakerInfo.getJoinRoomTime())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 log.info("roomDestroy not joinRoom >>>> cache : {}", JSONObject.toJSONString(test(room.getRoomUid()))); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -525,7 +550,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             imFeignService.publishRoomMsg(message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             log.info("roomDestroy>>>> FORCED_OFFLINE {}", JSONObject.toJSONString(message)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //销毁直播间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            imFeignService.destroyLiveRoom(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            imFeignService.destroyLiveRoom(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             log.info("roomDestroy>>>> destroyLiveRoom {}", JSONObject.toJSONString(message)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             log.error("roomDestroy>>>> errorMsg{}", e.getMessage(), e.getCause()); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -565,7 +590,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int speakerLiveTime = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //获取直播间主讲人信息 写入im_live_broadcast_room_data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, speakerId.toString())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, speakerId.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (speakerCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ImLiveBroadcastRoomData liveData = new ImLiveBroadcastRoomData(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             RoomSpeakerInfo speakerInfo = speakerCache.get(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -613,6 +638,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public void syncLike(String roomUid, Integer likeNum) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomUid)).set(likeNum); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //增加房间心跳 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        redissonClient.getBucket(LIVE_ROOM_SPEAKER_HEART_BEAT.replace(ROOM_UID, roomUid)).set(new Date()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -645,20 +672,20 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //将最新的时间写入缓存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             userStateTimeCache.set(userStateTime, 5L, TimeUnit.MINUTES); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //获取当前用户所在房间的uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            RBucket<String> userRoom = redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!userRoom.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String roomUid = userRoom.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //查询userId是不是主讲人 ,如果是主讲人则返回 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (isSpeaker(user, now, userid)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (isSpeaker(user, now, userid, roomUid)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //这里开始只处理观看者的数据,观看者只接受退出消息 status=0 是进入房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (user.getStatus().equals("0")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //获取当前用户所在房间的uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            RBucket<String> userRoom = redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (!userRoom.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            String roomUid = userRoom.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Integer userId = Integer.valueOf(userid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //从房间累计用户信息中查询该用户的信息 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -738,19 +765,34 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @return true 是主讲人 false 不是主讲人 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private boolean isSpeaker(ImUserState user, Date now, String userid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private boolean isSpeaker(ImUserState user, Date now, String userid, String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!speakerCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         RoomSpeakerInfo speakerInfo = speakerCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //最后一次进入房间的clientIp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<String> lastClientIp = redissonClient.getBucket(LIVE_SPEAKER_LAST_CLIENT_IP.replace(ROOM_UID, roomUid).replace(USER_ID, userid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //主讲人进入房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (user.getStatus().equals("0")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             speakerInfo.setJoinRoomTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             log.info("opsRoom>>>> join speakerCache {}", JSONObject.toJSONString(speakerInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             speakerCache.set(speakerInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //将本次进入房间的clientIp添加到主讲人最后一次clientIp缓存中 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (StringUtils.isNotBlank(user.getClientIp())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lastClientIp.set(user.getClientIp()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //校验本次退出直播间的clientIp 是不是上次进入房间的clientIp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (StringUtils.isNotBlank(user.getClientIp())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (lastClientIp.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //如果是上次进入房间的clientIp和本次退出房间的clientIp不相同,则直接忽略 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!user.getClientIp().equals(lastClientIp.get())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //主讲人退出房间关闭录像 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         closeLive(speakerInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         speakerInfo.setExitRoomTime(now); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -773,15 +815,17 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Date now = new Date(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //获取直播间信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId.toString())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!speakerCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //没有主讲人信息则生成一个 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             createSpeakerInfo(this.getById(roomVo.getId()), sysUser); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId.toString())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         RoomSpeakerInfo speakerInfo = speakerCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         speakerInfo.setJoinRoomTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         speakerCache.set(speakerInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //记录用户当前房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid, 12L, TimeUnit.HOURS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return roomVo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -815,7 +859,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             userInfo.setTotalViewTime(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //查询主讲人信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, imLiveBroadcastRoomVo.getSpeakerId().toString())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, imLiveBroadcastRoomVo.getSpeakerId().toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (speakerCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //如果用户进来时主讲人已经开启直播则修改学生观看时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Integer state = speakerCache.get().getState(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -841,7 +885,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public void startLive(String roomUid, Integer userId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //查询房间信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId.toString())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!speakerCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -877,7 +921,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public void closeLive(String roomUid, Integer userId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //查询房间主播信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId.toString())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!speakerCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -948,7 +992,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (onlineUserInfoExists && onlineUserInfo.containsKey(id)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (type.equals(1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         //开启直播后对当前在房间的用户写入观看时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        userInfo.setDynamicLookTime(new Date()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        userInfo.setDynamicLookTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } else if (type.equals(2)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         userInfo.setTotalViewTime(getLookMinutes(userInfo.getDynamicLookTime(), now, userInfo.getTotalViewTime())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         userInfo.setDynamicLookTime(null); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1036,7 +1080,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             speakerInfo.setWhetherVideo(1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //写入主讲人信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, room.getSpeakerId().toString())).set(speakerInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        getRoomSpeakerInfoCache(room.getRoomUid(), room.getSpeakerId().toString()).set(speakerInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //生成0点赞 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, room.getRoomUid())).set(0); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1097,6 +1141,26 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public Map<String, Object> test(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Map<String, Object> result = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //校验房间心跳是否过期没续租 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<Date> lastRoomHeartbeatCache = redissonClient.getBucket(LIVE_ROOM_SPEAKER_HEART_BEAT.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (lastRoomHeartbeatCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("房间心跳", DateUtil.dateToString(lastRoomHeartbeatCache.get(), DateUtil.EXPANDED_DATE_TIME_FORMAT)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("房间心跳", "房间心跳不存在"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String userId = ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String[] split = roomUid.split("-"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            userId = split[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (Exception ignored) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //获取主讲人信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (speakerCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("主讲人信息", speakerCache.get()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("主讲人信息", "主讲人信息不存在"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //点赞数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Object like = redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomUid)).get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (Objects.isNull(like)) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1113,29 +1177,15 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (CollectionUtils.isNotEmpty(totalUserInfo)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (CollectionUtils.isNotEmpty(inRoomUserInfo)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 look = inRoomUserInfo.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                result.put("正在观看的人员信息", inRoomUserInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                result.put("正在观看的人员信息", inRoomUserInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 result.put("正在观看的人员信息", "没有正在观看的人员数据"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             totalLook = totalUserInfo.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            result.put("总人员数据", totalUserInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            result.put("总人员数据", totalUserInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result.put("总人员数据", "没有人员数据"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String userId = ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            String[] split = roomUid.split("-"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userId = split[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } catch (Exception ignored) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //获取主讲人信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (speakerCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            result.put("主讲人信息", speakerCache.get()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            result.put("主讲人信息", "主讲人信息不存在"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         result.put("总观看人数", totalLook); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         result.put("实时观看数", look); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return result; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1254,6 +1304,16 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 获取房间主讲人消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param roomUid 房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param userId  用户id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private RBucket<RoomSpeakerInfo> getRoomSpeakerInfoCache(String roomUid, String userId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId).replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private RoomUserInfoVo getUserInfo(Integer userId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         RoomUserInfoVo userInfo = new RoomUserInfoVo(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         userInfo.setUserId(userId); 
			 |