| 
					
				 | 
			
			
				@@ -3,6 +3,7 @@ package com.yonge.cooleshow.biz.dal.service.impl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.alibaba.fastjson.JSONObject; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.baomidou.mybatisplus.core.toolkit.Wrappers; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.beust.jcommander.internal.Lists; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.yonge.cooleshow.auth.api.client.SysUserFeignService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.yonge.cooleshow.auth.api.entity.SysUser; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.yonge.cooleshow.biz.dal.dao.LiveRoomDao; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -30,6 +31,7 @@ import org.springframework.transaction.annotation.Transactional; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.concurrent.TimeUnit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.function.BiFunction; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.function.Function; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.stream.Collectors; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import static com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant.*; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -68,8 +70,14 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private TeacherAttendanceService teacherAttendanceService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    //生成房间UID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static BiFunction<Long, RoomTypeEnum, String> GenRoomUid = (userId, en) -> String.join("-", COOLESHOW, en.getCode(), userId.toString(), new Date().getTime() + ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 生成房间UID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <p> userId:主讲人id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <p> en :房间类型 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final BiFunction<Long, RoomTypeEnum, String> GenRoomUid = (userId, en) -> String 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .join("-", COOLESHOW, en.getCode(), userId.toString(), new Date().getTime() + ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public LiveRoomDao getDao() { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -92,11 +100,23 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         BeanUtils.copyProperties(liveRoom, roomVo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         roomVo.setSpeakerName(getSysUser(liveRoom.getSpeakerId()).getRealName()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         roomVo.setLikeNum(getLike(roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        roomVo.setLookNum(getLooker(roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomVo.setLookNum(getNum.apply(this::getOnlineUserCache, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return roomVo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 校验房间信息,及个人信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param roomUid 房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public RoomVo studentCheckRoomInfo(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //校验学生与房间的关系 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        checkStudentRoom(roomUid, getSysUser()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return queryRoomInfo(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 定时任务创建直播间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -163,27 +183,33 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public String createTempLiveRoom(Map<String, Object> param) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //查询主讲人信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         SysUser sysUser = getSysUser(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Date now = new Date(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //当前时间有课程则不能开启直播 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        checkTempLive(sysUser.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String roomTitle = WrapperUtil.toStr(param, "roomTitle", "房间标题不能为空!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String liveRemark = WrapperUtil.toStr(param, "liveRemark", "直播间描述不能为空!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Long id = sysUser.getId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Integer liveTime = WrapperUtil.toInt(param, "liveTime","请选择直播时长!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date liveStartTime = new Date(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date liveEndTime = DateUtil.addMinutes(liveStartTime, liveTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Long teacherId = sysUser.getId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //当前时间有课程则不能开启直播 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        boolean check =  courseScheduleService.checkTeacherCourseTime(teacherId,liveStartTime,liveEndTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (check) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //如果当前时间和课程时间有交集则不能开启临时直播 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new BizException("当前选择的时间段有课无法开启直播"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         RoomTypeEnum en = RoomTypeEnum.TEMP; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String roomUid = GenRoomUid.apply(id, en); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String roomUid = GenRoomUid.apply(teacherId, en); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         LiveRoom room = new LiveRoom(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         room.setCourseGroupId(-1L); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         room.setCourseId(-1L); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         room.setRoomUid(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         room.setRoomTitle(roomTitle); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         room.setLiveRemark(liveRemark); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        room.setSpeakerId(id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        room.setLiveStartTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        room.setSpeakerId(teacherId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        room.setLiveStartTime(liveStartTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        room.setLiveEndTime(liveEndTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         room.setLiveState(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         room.setRoomState(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        room.setCreatedBy(id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        room.setCreatedTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        room.setCreatedBy(teacherId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        room.setCreatedTime(liveStartTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         room.setType(en.getCode()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         this.save(room); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log.info("createTempLiveRoom>>>>>>room:{}", room.getRoomUid()); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -193,27 +219,6 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * 校验开启临时直播间是否会有课程冲突 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @SuppressWarnings("unchecked") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private void checkTempLive(Long teacherId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //查询当前未锁的最近的一节课 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        CourseSchedule course = courseScheduleService.getOne(Wrappers.<CourseSchedule>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .eq(CourseSchedule::getTeacherId, teacherId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .eq(CourseSchedule::getLock, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .orderByDesc(CourseSchedule::getStartTime)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (Objects.isNull(course)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Date now = new Date(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Boolean check = WrapperUtil.inInterSection(now, now, course.getStartTime(), course.getEndTime(), false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (check) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //如果当前时间和课程时间有交集则不能开启临时直播 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            throw new BizException("当前有课无法开启直播"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 去融云创建房间及创建房间缓存信息-直播间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private void createLiveRoomInfo(LiveRoom room) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -307,30 +312,35 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 //删除房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 destroyLiveRoom(room.getRoomUid()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 //查询老师分润表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                CourseScheduleTeacherSalary salary = courseScheduleTeacherSalaryService.getOne(Wrappers.<CourseScheduleTeacherSalary>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                List<CourseScheduleTeacherSalary> salaryList = courseScheduleTeacherSalaryService.list(Wrappers.<CourseScheduleTeacherSalary>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         .eq(CourseScheduleTeacherSalary::getCourseScheduleId, room.getCourseId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (Objects.isNull(salary)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //查询该学生及课程id 对应的支付订单号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                CourseScheduleStudentPayment payment = courseScheduleStudentPaymentService.getOne(Wrappers.<CourseScheduleStudentPayment>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        .eq(CourseScheduleStudentPayment::getCourseId, room.getCourseId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        .eq(CourseScheduleStudentPayment::getUserId, salary.getStudentId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (Objects.isNull(payment)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (CollectionUtils.isEmpty(salaryList)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //获取教师课酬写入到金额变更表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                UserAccountRecordDto userAccountRecord = new UserAccountRecordDto(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userAccountRecord.setUserId(room.getSpeakerId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userAccountRecord.setInOrOut(InOrOutEnum.IN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userAccountRecord.setBizType(AccountBizTypeEnum.LIVE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userAccountRecord.setBizId(room.getCourseId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userAccountRecord.setBizName(room.getRoomTitle()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userAccountRecord.setTransAmount(salary.getActualSalary());//扣除手续费后所得金额 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userAccountRecord.setOrderNo(payment.getOrderNo()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                userAccountService.accountChange(userAccountRecord); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                salaryList.forEach(salary -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    //查询该学生及课程id 对应的支付订单号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    CourseScheduleStudentPayment payment = courseScheduleStudentPaymentService.getOne(Wrappers.<CourseScheduleStudentPayment>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .eq(CourseScheduleStudentPayment::getCourseId, room.getCourseId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .eq(CourseScheduleStudentPayment::getUserId, salary.getStudentId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (Objects.isNull(payment)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    //获取教师课酬写入到金额变更表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    UserAccountRecordDto userAccountRecord = new UserAccountRecordDto(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userAccountRecord.setUserId(room.getSpeakerId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userAccountRecord.setInOrOut(InOrOutEnum.IN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userAccountRecord.setBizType(AccountBizTypeEnum.LIVE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userAccountRecord.setBizId(room.getCourseId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userAccountRecord.setBizName(room.getRoomTitle()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userAccountRecord.setTransAmount(salary.getActualSalary());//扣除手续费后所得金额 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userAccountRecord.setOrderNo(payment.getOrderNo()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    userAccountService.accountChange(userAccountRecord); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    //修改教师课酬状态-已结算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    salary.setStatus(TeacherSalaryEnum.COMPLETE.getCode()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    courseScheduleTeacherSalaryService.updateById(salary); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -396,20 +406,17 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @param roomId 房间Uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private void destroyLiveRoom(String roomId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //删除服务器房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        List<String> deleteRoomIds = new ArrayList<String>() {{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            add(roomId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        IMApiResultInfo resultInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            resultInfo = imHelper.deleteChrm(deleteRoomIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //删除服务器房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            List<String> deleteRoomIds = Lists.newArrayList(roomId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            IMApiResultInfo resultInfo = imHelper.deleteChrm(deleteRoomIds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!resultInfo.isSuccess()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.error("destroyLiveRoom error" + resultInfo.getErrorMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.info("destroyLiveRoom success: {}", roomId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            throw new BizException("关闭聊天室失败!" + e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.error("destroyLiveRoom error" + e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!resultInfo.isSuccess()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            throw new BizException("关闭聊天室失败!" + resultInfo.getErrorMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        log.info("destroyLiveRoom success: {}", roomId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -431,7 +438,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //获取当前用户状态变更的时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             long userStateTime = Optional.ofNullable(user.getTime()).orElse(now.getTime()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             String userIdStr = user.getUserid(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            RBucket<Long> userStateTimeCache = redissonClient.getBucket(LIVE_TEACHER_LAST_TIME.replace(USER_ID, userIdStr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            RBucket<Long> userStateTimeCache = redissonClient.getBucket(LIVE_USER_LAST_TIME.replace(USER_ID, userIdStr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (userStateTimeCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 //缓存的时间比当前传入时间大则放弃这条数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 long cacheTime = userStateTimeCache.get(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -441,101 +448,156 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //将最新的时间写入缓存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             userStateTimeCache.set(userStateTime, 5L, TimeUnit.MINUTES); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //直播间号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            String roomUid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //根据用户id获取用户当前房间号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            RBucket<String> roomUidCache = redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userIdStr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (!roomUidCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //获取当前用户所在房间的uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            RBucket<String> userRoom = redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userIdStr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!userRoom.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            roomUid = roomUidCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String roomUid = userRoom.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //根据房间号获取房间信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             RBucket<RoomInfoCache> roomInfoCache = redissonClient.getBucket(LIVE_ROOM_INFO.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (!roomInfoCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             RoomInfoCache roomInfo = roomInfoCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //用户id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            Long userId = Long.valueOf(userIdStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //主讲人 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 查询userId是不是主讲人 ,如果是主讲人则返回 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (roomInfo.getSpeakerId().toString().equals(userIdStr)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //进退房间写老师考勤表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                TeacherAttendance teacherAttendance = teacherAttendanceService.getOne(Wrappers.<TeacherAttendance>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        .eq(TeacherAttendance::getTeacherId, userId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        .eq(TeacherAttendance::getCourseScheduleId, roomInfo.getCourseId())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //主讲人进入房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (user.getStatus().equals("0")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    roomInfo.setSpeakerState(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    roomInfo.setJoinRoomTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    log.info("opsRoom>>>> join roomInfo {}", JSONObject.toJSONString(roomInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    roomInfoCache.set(roomInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //查询老师是否有进入过,没有则写老师考勤表的进入时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (Objects.isNull(teacherAttendance)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        setTeacherAttendance(userId, roomInfo.getCourseGroupId(), roomInfo.getCourseId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                roomInfo.setSpeakerState(1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                roomInfo.setExitRoomTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                log.info("opsRoom>>>> exit roomInfo {}", JSONObject.toJSONString(roomInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                roomInfoCache.set(roomInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (Objects.isNull(teacherAttendance)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance = new TeacherAttendance(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance.setTeacherId(userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance.setCourseGroupType(CourseScheduleEnum.LIVE.getCode()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance.setCourseGroupId(roomInfo.getCourseGroupId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance.setCourseScheduleId(roomInfo.getCourseId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance.setSignInTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance.setSignOutTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance.setCreateTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendanceService.save(teacherAttendance); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //修改老师考勤表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance.setSignOutTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendance.setUpdateTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    teacherAttendanceService.updateById(teacherAttendance); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                opsSpeaker(roomInfoCache, user, now, userIdStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //观看者只需要接收退出房间的消息 status=0进入房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //这里开始只处理观看者的数据,观看者只接受退出消息 status=0 是进入房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (user.getStatus().equals("0")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //用户id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Long userId = Long.valueOf(userIdStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //从房间累计用户信息中查询该用户的信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            RMap<Long, RoomUserInfoCache> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            RMap<Long, String> roomTotalUser = getTotalUserCache(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //该房间未查询到用户数据则不处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (!roomTotalUser.isExists() && !roomTotalUser.containsKey(userId)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //查询到用户数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            RoomUserInfoCache userInfo = roomTotalUser.get(userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //用户突然离线 - 那么融云会发送用户离线消息-此刻就发送退出房间消息给主讲人 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (user.getStatus().equals("1")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                ImRoomMessage message = new ImRoomMessage(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                message.setFromUserId(userId.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                message.setContent(userId.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                message.setToChatroomId(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                message.setObjectName(ImRoomMessage.RC_CHATROOM_LEAVE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    publishRoomMessage(message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    log.error("opsRoom>>>>  looker leave error {}", e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    log.error("opsRoom>>>>  looker leave error sendMessage {} : userInfo : {}", message, JSONObject.toJSONString(userInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                log.info("opsRoom>>>> looker leave userInfo : {}", JSONObject.toJSONString(userInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //记录退出时间 并写入缓存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //查询用户数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            RoomUserInfoCache userInfo = JSONObject.toJavaObject(JSONObject.parseObject(roomTotalUser.get(userId)), RoomUserInfoCache.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             userInfo.setLastOutTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userInfo.setState(1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            roomTotalUser.fastPut(userId, userInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //todo 写学生考勤表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            log.info("opsRoom>>>> looker userInfo: {}", JSONObject.toJSONString(userInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String userJsonStr = JSONObject.toJSONString(userInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            roomTotalUser.fastPut(userId, userJsonStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //查询在线人员列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            RMap<Long, String> onlineUserInfo = getOnlineUserCache(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!onlineUserInfo.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //从在线人员列表删除该人员 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            onlineUserInfo.fastRemove(userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //学员退出 写学生考勤表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            StudentAttendance studentAttendance = studentAttendanceService.getOne(Wrappers.<StudentAttendance>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .eq(StudentAttendance::getStudentId, userId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .eq(StudentAttendance::getCourseScheduleId, roomInfo.getCourseId())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (Objects.nonNull(studentAttendance)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                studentAttendance.setSignOutTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                studentAttendanceService.updateById(studentAttendance); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //向直播间发送当前在线人数消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.sendOnlineUserCount(roomUid, userId, onlineUserInfo.size()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.info("opsRoom>>>> looker userInfo: {}", userJsonStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //用户离开直播间发送退出房间消息给主讲人 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ImRoomMessage message = new ImRoomMessage(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            message.setFromUserId(userId.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            message.setToChatroomId(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            message.setObjectName(ImRoomMessage.RC_CHATROOM_LEAVE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            message.setContent(userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                publishRoomMessage(message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.info("opsRoom>>>> looker RC_CHATROOM_LEAVE : {}", userJsonStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.error("opsRoom>>>>  looker error RC_CHATROOM_LEAVE {}", e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.error("opsRoom>>>>  looker error sendMessage {} : RC_CHATROOM_LEAVE : {}", message, userJsonStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 主讲人 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return true 是主讲人 false 不是主讲人 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private void opsSpeaker(RBucket<RoomInfoCache> roomInfoCache, ImUserStateSync user, Date now, String userIdStr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RoomInfoCache roomInfo = roomInfoCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String roomUid = roomInfo.getRoomUid(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //进退房间写老师考勤表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        TeacherAttendance teacherAttendance = teacherAttendanceService.getOne(Wrappers.<TeacherAttendance>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .eq(TeacherAttendance::getTeacherId, userIdStr) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .eq(TeacherAttendance::getCourseScheduleId, roomInfo.getCourseId())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //最后一次进入房间的clientIp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<String> lastClientIp = redissonClient.getBucket(LIVE_USER_LAST_CLIENT_IP.replace(ROOM_UID, roomUid).replace(USER_ID, userIdStr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //主讲人进入房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (user.getStatus().equals("0")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            roomInfo.setSpeakerState(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            roomInfo.setJoinRoomTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //将本次进入房间的clientIp添加到主讲人最后一次clientIp缓存中 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (StringUtils.isNotBlank(user.getClientIp())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lastClientIp.set(user.getClientIp()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //查询老师是否有进入过放假,没有则写老师考勤表的进入时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (Objects.isNull(teacherAttendance)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                setTeacherAttendance(Long.parseLong(userIdStr), roomInfo.getCourseGroupId(), roomInfo.getCourseId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            roomInfoCache.set(roomInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.info("opsRoom>>>> join speakerCache {}", JSONObject.toJSONString(roomInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //退出房间 - 校验本次退出直播间的clientIp 是不是上次进入房间的clientIp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (StringUtils.isNotBlank(user.getClientIp())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (lastClientIp.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //如果是上次进入房间的clientIp和本次退出房间的clientIp不相同,则直接忽略 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!user.getClientIp().equals(lastClientIp.get())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //如果退出时间大于进入时间就无需再次退出-直接返回 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (compareDate.apply(roomInfo.getExitRoomTime(), roomInfo.getJoinRoomTime())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfo.setSpeakerState(1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfo.setExitRoomTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (Objects.isNull(teacherAttendance)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance = new TeacherAttendance(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance.setTeacherId(Long.parseLong(userIdStr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance.setCourseGroupType(CourseScheduleEnum.LIVE.getCode()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance.setCourseGroupId(roomInfo.getCourseGroupId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance.setCourseScheduleId(roomInfo.getCourseId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance.setSignInTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance.setSignOutTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance.setCreateTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendanceService.save(teacherAttendance); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //修改老师考勤表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance.setSignOutTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendance.setUpdateTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            teacherAttendanceService.updateById(teacherAttendance); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("opsRoom>>>> exit speakerCache {}", JSONObject.toJSONString(roomInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfoCache.set(roomInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 对比时间,2个时间一个为空返回false,否则对比时间大小 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <p>- date1 时间1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <p>- date2 时间2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final BiFunction<Date, Date, Boolean> compareDate = (date1, date2) -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (Objects.nonNull(date1) && Objects.nonNull(date2)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return date1.getTime() > date2.getTime(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 同步点赞数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @param roomUid 房间uid 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -544,51 +606,62 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public void syncLike(String roomUid, Integer likeNum) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomUid)).set(likeNum); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //增加房间心跳 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        redissonClient.getBucket(LIVE_ROOM_HEART_BEAT.replace(ROOM_UID, roomUid)).set(new Date()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * 进入房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 主讲人-进入房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @param roomUid 房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param userId  用户id 主讲人或者用户的id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param userId  主讲人id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public RoomInfoCache joinRoom(String roomUid, Long userId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public RoomInfoCache speakerJoinRoom(String roomUid, Long userId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //校验房间是否存在 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         RBucket<RoomInfoCache> roomInfoCache = redissonClient.getBucket(LIVE_ROOM_INFO.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!roomInfoCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             throw new BizException("直播还未开始!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         RoomInfoCache roomInfo = roomInfoCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date now = new Date(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //校验进入房间的是否是该直播间的主讲人 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!roomInfo.getSpeakerId().equals(userId)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new BizException("您不是该直播间的主讲人!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfo.setSpeakerState(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfo.setJoinRoomTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfoCache.set(roomInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //查询老师是否有进入过,没有则写老师考勤表的进入时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        setTeacherAttendance(userId, roomInfo.getCourseGroupId(), roomInfo.getCourseId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         roomInfo.setLikeNum(getLike(roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        roomInfo.setLookNum(getLooker(roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfo.setLookNum(getNum.apply(this::getOnlineUserCache, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //记录当前用户对应的房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid, 2L, TimeUnit.DAYS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return roomInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 观看者-进入房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param roomUid 房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param userId  用户id 观看者id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public RoomInfoCache joinRoom(String roomUid, Long userId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //获取进入房间人员信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        SysUser sysUser = getSysUser(userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //校验信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomInfoCache> roomInfoCache = checkStudentRoom(roomUid, sysUser); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RoomInfoCache roomInfo = roomInfoCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Date now = new Date(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //进入房间的是主讲人 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (roomInfo.getSpeakerId().equals(userId)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            roomInfo.setSpeakerState(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            roomInfo.setJoinRoomTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            roomInfoCache.set(roomInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //查询老师是否有进入过,没有则写老师考勤表的进入时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            setTeacherAttendance(userId, roomInfo.getCourseGroupId(), roomInfo.getCourseId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return roomInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //todo 查询是否是临时直播间,临时直播间可以直接进入教师 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //todo 校验观看者是否可以进入该房间,查询该学员购买成功则有权限进入该房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //房间累计用户信息-指只要进入到该房间的用户都要记录 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RMap<Long, RoomUserInfoCache> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RMap<Long, String> roomTotalUser = getTotalUserCache(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //判断是否第一次进房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         RoomUserInfoCache userInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (roomTotalUser.containsKey(userId)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //多次进入更新动态进入时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            userInfo = roomTotalUser.get(userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            userInfo = JSONObject.toJavaObject(JSONObject.parseObject(roomTotalUser.get(userId)), RoomUserInfoCache.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //第一次进该房间 写入用户首次进入时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            SysUser sysUser = getSysUser(userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             userInfo = new RoomUserInfoCache(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             userInfo.setUserId(sysUser.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             userInfo.setUserName(sysUser.getRealName()); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -596,13 +669,51 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //查询学生是否有进入过,没有则写学生考勤表的进入时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             setStudentAttendance(userId, roomInfo.getCourseGroupId(), roomInfo.getCourseId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        userInfo.setState(0);//0:在房间 1:不在房间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         userInfo.setDynamicJoinTime(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        roomTotalUser.fastPut(userId, userInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        log.info("joinRoom>>>> userInfo: {}", JSONObject.toJSONString(userInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //用户json信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String userJsonStr = JSONObject.toJSONString(userInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //写入人员缓存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomTotalUser.fastPut(userId, userJsonStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //写入在线人员缓存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RMap<Long, String> onlineUserCache = getOnlineUserCache(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlineUserCache.fastPut(userId, userJsonStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("joinRoom>>>> userInfo: {}", userJsonStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //刷新当前房间的点赞及观看人数信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfo.setLikeNum(getLike(roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfo.setLookNum(getNum.apply(this::getOnlineUserCache, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roomInfoCache.set(roomInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //向直播间发送当前在线人数消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.sendOnlineUserCount(roomUid, userId, onlineUserCache.size()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("join sendOnlineUserCount>>>> param is null   roomUid: {}  fromUserId:{}  count:{}", roomUid, userId, onlineUserCache.size()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("joinRoom>>>> userInfo: {}", userJsonStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //记录当前用户对应的房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid, 2L, TimeUnit.DAYS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return roomInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //校验学生与房间的关系 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private RBucket<RoomInfoCache> checkStudentRoom(String roomUid, SysUser sysUser) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //校验房间是否存在 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<RoomInfoCache> roomInfoCache = redissonClient.getBucket(LIVE_ROOM_INFO.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!roomInfoCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new BizException("直播还未开始!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RoomInfoCache roomInfo = roomInfoCache.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //校验观看者是否可以进入该房间,如果是非临时直播间,则校验是否已经买过课 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!roomInfo.getRoomType().equals(RoomTypeEnum.TEMP.getCode())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 查询该学员成功购买课程 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            int count = courseScheduleStudentPaymentService.count(Wrappers.<CourseScheduleStudentPayment>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .eq(CourseScheduleStudentPayment::getUserId, sysUser.getId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .eq(CourseScheduleStudentPayment::getCourseId, roomInfo.getCourseId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .eq(CourseScheduleStudentPayment::getCourseGroupId, roomInfo.getCourseGroupId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .eq(CourseScheduleStudentPayment::getCourseType, CourseScheduleEnum.LIVE.getCode())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (count < 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new BizException("您还未购买课程!"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return roomInfoCache; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 查询学生是否有进入过,没有则写学生考勤表的进入时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -611,12 +722,12 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @param courseId      课程id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private void setStudentAttendance(Long studentId, Long courseGroupId, Long courseId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Date now = new Date(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //写学生第一次进入时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         StudentAttendance studentAttendance = studentAttendanceService.getOne(Wrappers.<StudentAttendance>lambdaQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .eq(StudentAttendance::getStudentId, studentId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .eq(StudentAttendance::getCourseScheduleId, courseId)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (Objects.isNull(studentAttendance)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Date now = new Date(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             studentAttendance = new StudentAttendance(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             studentAttendance.setCourseGroupType(CourseScheduleEnum.LIVE.getCode()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             studentAttendance.setCourseGroupId(courseGroupId); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -653,6 +764,36 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 向直播间发送当前在线人数消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param roomUid    房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param fromUserId 发送人id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param count      人数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private void sendOnlineUserCount(String roomUid, Long fromUserId, Integer count) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //校验传入参数,房间uid和发送人id不能为空 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!WrapperUtil.checkObj(roomUid, fromUserId, count)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.info(" sendOnlineUserCount>>>> param is null   roomUid: {}  fromUserId:{}  count:{}", roomUid, fromUserId, count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ImRoomMessage message = new ImRoomMessage(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        message.setObjectName(ImRoomMessage.MEMBER_COUNT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        message.setToChatroomId(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        HashMap<String, Integer> sendMap = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sendMap.put("count", count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        message.setFromUserId(fromUserId.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        message.setContent(sendMap); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //发送消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            publishRoomMessage(message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.info("sendOnlineUserCount>>>> message: {}", JSONObject.toJSONString(message)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.error("sendOnlineUserCount>>>> error {}", e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.error("sendOnlineUserCount>>>> sendMessage {} :", JSONObject.toJSONString(message)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 发送消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @param message 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -689,26 +830,46 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @param roomUid 直播间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public List<RoomUserInfoCache> queryRoomUserInfo(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        List<RoomUserInfoCache> roomUserInfoVos = queryTotalRoomUserInfo(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return queryRoomUserInfo(roomUserInfoVos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private List<RoomUserInfoCache> getTotalUserInfo(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RMap<Long, String> roomTotalUser = getTotalUserCache(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return roomTotalUser.values().parallelStream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .map(a -> JSONObject.toJavaObject(JSONObject.parseObject(a), RoomUserInfoCache.class)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private List<RoomUserInfoCache> queryRoomUserInfo(List<RoomUserInfoCache> totalUserInfo) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return totalUserInfo.stream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .filter(o -> Objects.nonNull(o.getState()) && o.getState() == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 获取直播间所有用户信息缓存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param roomUid 直播间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return RMap key:userId value:RoomUserInfoCache -> jsonToString 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private RMap<Long, String> getTotalUserCache(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private List<RoomUserInfoCache> queryTotalRoomUserInfo(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RMap<Long, RoomUserInfoCache> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return roomTotalUser.values().stream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                .filter(Objects::nonNull) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 查询在观看直播的用户信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param roomUid 直播间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private List<RoomUserInfoCache> getOnlineUserInfo(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RMap<Long, String> roomTotalUser = getOnlineUserCache(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return roomTotalUser.values().parallelStream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .map(a -> JSONObject.toJavaObject(JSONObject.parseObject(a), RoomUserInfoCache.class)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 .collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 获取直播间在线用户信息缓存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param roomUid 直播间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return RMap key:userId value:BaseRoomUserVo -> jsonToString 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private RMap<Long, String> getOnlineUserCache(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return redissonClient.getMap(LIVE_ROOM_ONLINE_USER_LIST.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 获取房间点赞数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @param roomUid 房间UId 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -724,18 +885,17 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * 获取房间当前观看人数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 获取房间缓存中的用户数量/观看人数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param roomUid 房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @return 当前观看人数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <p> func:查询用户数量/观看人数的方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <p> roomUid :房间uid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <p> return :用户数量/观看人数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private int getLooker(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        List<RoomUserInfoCache> roomUserInfoCaches = queryRoomUserInfo(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (CollectionUtils.isEmpty(roomUserInfoCaches)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return roomUserInfoCaches.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final BiFunction<Function<String, RMap<Long, ?>>, String, Integer> getNum = (func, roomUid) -> Optional.of(roomUid) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .map(func) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .filter(RMap::isExists) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .map(RMap::size) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .orElse(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 方便测试观察房间数据的方法 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -743,16 +903,6 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public Map<String, Object> test(String roomUid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Map<String, Object> result = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        Map<String, Object> param = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        param.put("day", "05"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        param.put("month", "06"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        param.put("year", "2022"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        param.put("teacherId", "174"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        param.put("studentId", 164); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        List<CourseCalendarEntity> courseTimeEntities = courseScheduleService.createPracticeCourseCalender(param); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        List<CourseCalendarEntity> courseTimeEntities = courseScheduleService.createLiveCourseCalendar(param); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//        result.put("自动生成课时", courseTimeEntities); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //获取房间信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         RBucket<RoomInfoCache> speakerCache = redissonClient.getBucket(LIVE_ROOM_INFO.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (speakerCache.isExists()) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -761,6 +911,14 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result.put("房间信息", "房间信息不存在"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //校验房间心跳是否过期没续租 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RBucket<Date> lastRoomHeartbeatCache = redissonClient.getBucket(LIVE_ROOM_HEART_BEAT.replace(ROOM_UID, roomUid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (lastRoomHeartbeatCache.isExists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("房间心跳", DateUtil.dateToString(lastRoomHeartbeatCache.get(), DateUtil.EXPANDED_DATE_TIME_FORMAT)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("房间心跳", "房间心跳不存在"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //点赞数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Object like = redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomUid)).get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (Objects.isNull(like)) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -770,33 +928,31 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int totalLook = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int look = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        List<RoomUserInfoCache> inRoomUserInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //累计总观看的用户数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        List<RoomUserInfoCache> totalUserInfo = queryTotalRoomUserInfo(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<RoomUserInfoCache> totalUserInfo = getTotalUserInfo(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (CollectionUtils.isNotEmpty(totalUserInfo)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //正在房间观看的用户数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            inRoomUserInfo = queryRoomUserInfo(totalUserInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (CollectionUtils.isNotEmpty(inRoomUserInfo)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                look = inRoomUserInfo.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                result.put("正在观看的人员信息", inRoomUserInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                result.put("正在观看的人员信息", "没有正在观看的人员数据"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             totalLook = totalUserInfo.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result.put("总人员数据", totalUserInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result.put("总人员数据", "没有人员数据"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         result.put("总观看人数", totalLook); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //正在房间观看的用户数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<RoomUserInfoCache> onlineUserInfo = getOnlineUserInfo(roomUid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (CollectionUtils.isNotEmpty(onlineUserInfo)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            look = onlineUserInfo.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("正在观看的人员信息", onlineUserInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("正在观看的人员信息", "没有正在观看的人员数据"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         result.put("实时观看数", look); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public LiveRoom getliveingRoomBySpeakerId(Long speakerId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return baseMapper.getliveingRoomBySpeakerId(speakerId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public LiveRoom getLiveInRoomBySpeakerId(Long speakerId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return baseMapper.getLiveInRoomBySpeakerId(speakerId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |