|  | @@ -3093,7 +3093,7 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  			// 直播课发送推送消息
 | 
	
		
			
				|  |  | -			if (LIVE.equals(oldCourseSchedule.getGroupType()) && StringUtils.isNotBlank(oldCourseSchedule.getLiveRoomId())) {
 | 
	
		
			
				|  |  | +			if (LIVE.equals(oldCourseSchedule.getGroupType())) {
 | 
	
		
			
				|  |  |  				// 日期,时间,时长,主教老师不一致时,发送消息
 | 
	
		
			
				|  |  |  				if (newCourseSchedule.getClassDate() != oldCourseSchedule.getClassDate()
 | 
	
		
			
				|  |  |  						|| newCourseSchedule.getStartClassTime() != oldCourseSchedule.getStartClassTime()
 | 
	
	
		
			
				|  | @@ -3549,38 +3549,50 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 | 
	
		
			
				|  |  |  		// 直播课消息推送
 | 
	
		
			
				|  |  |  		if (CollectionUtils.isNotEmpty(liveCourseSchedules)) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -			liveCourseSchedules.parallelStream().forEach(item -> {
 | 
	
		
			
				|  |  | +			CompletableFuture.runAsync(() ->
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -				ImLiveBroadcastRoom liveRoom = imLiveBroadcastRoomService.getByRoomUid(item.getLiveRoomId());
 | 
	
		
			
				|  |  | -				if (Objects.isNull(liveRoom)) {
 | 
	
		
			
				|  |  | -					log.warn("liveRoom is null, liveRoomId:{}", item.getLiveRoomId());
 | 
	
		
			
				|  |  | -					return;
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | +				liveCourseSchedules.parallelStream().forEach(item -> {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -				try {
 | 
	
		
			
				|  |  | -					LivePluginService pluginService = livePluginContext.getPluginService(liveRoom.getServiceProvider());
 | 
	
		
			
				|  |  | +					// 是否是连堂课
 | 
	
		
			
				|  |  | +					String continueCourseTime = sysTenantConfigService.getTenantConfigValue(SysConfigService.ONLINE_CONTINUE_COURSE_TIME, item.getTenantId());
 | 
	
		
			
				|  |  | +					if (StringUtils.isEmpty(continueCourseTime)) {
 | 
	
		
			
				|  |  | +						continueCourseTime = "5";
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -					LiveRoomMessage message = new LiveRoomMessage();
 | 
	
		
			
				|  |  | -					message.setIsIncludeSender(1);
 | 
	
		
			
				|  |  | -					message.setFromUserId(item.getActualTeacherId().toString());
 | 
	
		
			
				|  |  | -					message.setToChatRoomId(item.getLiveRoomId());
 | 
	
		
			
				|  |  | -					message.setObjectName(LiveRoomMessage.LIVE_STATUS_CHANGE);
 | 
	
		
			
				|  |  | +					// 直播课关联直播间编号
 | 
	
		
			
				|  |  | +					String liveRoomId = getCourseScheduleLiveRoomId(item, continueCourseTime, Lists.newArrayList(), Lists.newArrayList());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -					// 发送用户信息
 | 
	
		
			
				|  |  | -					LiveRoomMessage.MessageUser messageUser = LiveRoomMessage.MessageUser.builder()
 | 
	
		
			
				|  |  | -							.sendUserId("")
 | 
	
		
			
				|  |  | -							.sendUserName("")
 | 
	
		
			
				|  |  | -							.avatarUrl("")
 | 
	
		
			
				|  |  | -							.build();
 | 
	
		
			
				|  |  | +					ImLiveBroadcastRoom liveRoom = imLiveBroadcastRoomService.getByRoomUid(liveRoomId);
 | 
	
		
			
				|  |  | +					if (Objects.isNull(liveRoom)) {
 | 
	
		
			
				|  |  | +						log.warn("liveRoom is null, liveRoomId:{}", item.getLiveRoomId());
 | 
	
		
			
				|  |  | +						return;
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -					message.setContent(LiveRoomMessage.MessageContent.builder()
 | 
	
		
			
				|  |  | -							.sendUserInfo(messageUser).build());
 | 
	
		
			
				|  |  | +					try {
 | 
	
		
			
				|  |  | +						LivePluginService pluginService = livePluginContext.getPluginService(liveRoom.getServiceProvider());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -					pluginService.sendChatRoomMessage(message);
 | 
	
		
			
				|  |  | -				} catch (Exception e) {
 | 
	
		
			
				|  |  | -					log.error("liveRoom error", e);
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			});
 | 
	
		
			
				|  |  | +						LiveRoomMessage message = new LiveRoomMessage();
 | 
	
		
			
				|  |  | +						message.setIsIncludeSender(1);
 | 
	
		
			
				|  |  | +						message.setFromUserId(item.getActualTeacherId().toString());
 | 
	
		
			
				|  |  | +						message.setToChatRoomId(item.getLiveRoomId());
 | 
	
		
			
				|  |  | +						message.setObjectName(LiveRoomMessage.LIVE_STATUS_CHANGE);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +						// 发送用户信息
 | 
	
		
			
				|  |  | +						LiveRoomMessage.MessageUser messageUser = LiveRoomMessage.MessageUser.builder()
 | 
	
		
			
				|  |  | +								.sendUserId("")
 | 
	
		
			
				|  |  | +								.sendUserName("")
 | 
	
		
			
				|  |  | +								.avatarUrl("")
 | 
	
		
			
				|  |  | +								.build();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +						message.setContent(LiveRoomMessage.MessageContent.builder()
 | 
	
		
			
				|  |  | +								.sendUserInfo(messageUser).build());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +						pluginService.sendChatRoomMessage(message);
 | 
	
		
			
				|  |  | +					} catch (Exception e) {
 | 
	
		
			
				|  |  | +						log.error("liveRoom error", e);
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +				})
 | 
	
		
			
				|  |  | +			);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		return BaseController.succeed();
 | 
	
	
		
			
				|  | @@ -6195,16 +6207,76 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 | 
	
		
			
				|  |  |  		if (courseSchedule.getTeachMode() == TeachModeEnum.OFFLINE) {
 | 
	
		
			
				|  |  |  			throw new BizException("请前往线下教室");
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 是否是连堂课
 | 
	
		
			
				|  |  | +		String continueCourseTime = sysTenantConfigService.getTenantConfigValue(SysConfigService.ONLINE_CONTINUE_COURSE_TIME, courseSchedule.getTenantId());
 | 
	
		
			
				|  |  | +		if (StringUtils.isEmpty(continueCourseTime)) {
 | 
	
		
			
				|  |  | +			continueCourseTime = "5";
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 直播课关联直播间
 | 
	
		
			
				|  |  | +		List<CourseSchedule> newCourseSchedules = Lists.newArrayList();
 | 
	
		
			
				|  |  | +		// 课程时间长计算
 | 
	
		
			
				|  |  | +		List<CourseScheduleWrapper.CourseScheduleTime> courseScheduleTimes = Lists.newArrayList();
 | 
	
		
			
				|  |  | +		// 直播课关联直播间编号
 | 
	
		
			
				|  |  | +		String liveRoomId = getCourseScheduleLiveRoomId(courseSchedule, continueCourseTime, newCourseSchedules, courseScheduleTimes);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 定时任务更新课程状态为进行中,判断当前课程状态是否匹配
 | 
	
		
			
				|  |  | +		int studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		Date date = DateUtil.startDateAndEndTime(courseSchedule.getClassDate(), courseSchedule.getStartClassTime());
 | 
	
		
			
				|  |  | +		date = DateUtil.addMinutes(date, -studentRemindTime);
 | 
	
		
			
				|  |  | +		// 课程是否开始
 | 
	
		
			
				|  |  | +		if(CourseStatusEnum.NOT_START.equals(courseSchedule.getStatus()) && date.after(new Date())) {
 | 
	
		
			
				|  |  | +			throw new BizException("直播课暂未开启,请稍后重试");
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if (CourseStatusEnum.OVER == courseSchedule.getStatus()) {
 | 
	
		
			
				|  |  | +			throw new BizException("直播课已结束");
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 直播间配置
 | 
	
		
			
				|  |  | +		ImLiveBroadcastRoom liveBroadcastRoom = imLiveBroadcastRoomService.lambdaQuery()
 | 
	
		
			
				|  |  | +				.eq(ImLiveBroadcastRoom::getRoomUid, liveRoomId)
 | 
	
		
			
				|  |  | +				.last("LIMIT 1")
 | 
	
		
			
				|  |  | +				.one();
 | 
	
		
			
				|  |  | +		if (Objects.isNull(liveBroadcastRoom)) {
 | 
	
		
			
				|  |  | +			throw new BizException("请先进入直播课教室");
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		return CourseScheduleWrapper.LiveCourseSchedule.builder()
 | 
	
		
			
				|  |  | +				.liveRoomId(liveRoomId)
 | 
	
		
			
				|  |  | +				.subjectId(liveBroadcastRoom.getSubjectId())
 | 
	
		
			
				|  |  | +				.autoCloseFlag(true)
 | 
	
		
			
				|  |  | +				.autoCloseNetworkRoomTime(getCloseNetworkRoomTime(courseSchedule, continueCourseTime))
 | 
	
		
			
				|  |  | +				.surplusTime(DateUtil.secondsBetween(new Date(), courseSchedule.getEndClassTime()))
 | 
	
		
			
				|  |  | +				.timestamp(DateTime.now().getMillis())
 | 
	
		
			
				|  |  | +				.courseScheduleTimes(courseScheduleTimes)
 | 
	
		
			
				|  |  | +				.build();
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * 同步连堂课状态,获取直播间编号
 | 
	
		
			
				|  |  | +	 * @param courseSchedule CourseSchedule
 | 
	
		
			
				|  |  | +	 * @param continueCourseTime 连堂课时长
 | 
	
		
			
				|  |  | +	 * @param newCourseSchedules List<CourseSchedule>
 | 
	
		
			
				|  |  | +	 * @param courseScheduleTimes List<CourseScheduleWrapper.CourseScheduleTime>
 | 
	
		
			
				|  |  | +	 * @return String
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	private String getCourseScheduleLiveRoomId(CourseSchedule courseSchedule,
 | 
	
		
			
				|  |  | +											   String continueCourseTime,
 | 
	
		
			
				|  |  | +											   List<CourseSchedule> newCourseSchedules,
 | 
	
		
			
				|  |  | +											   List<CourseScheduleWrapper.CourseScheduleTime> courseScheduleTimes) {
 | 
	
		
			
				|  |  | +		String liveRoomId;
 | 
	
		
			
				|  |  |  		// 课程开始时间
 | 
	
		
			
				|  |  |  		courseSchedule.setStartClassTime(getDateTime(courseSchedule.getClassDate(), courseSchedule.getStartClassTime()).toDate());
 | 
	
		
			
				|  |  |  		// 课程结束时间
 | 
	
		
			
				|  |  |  		courseSchedule.setEndClassTime(getDateTime(courseSchedule.getClassDate(), courseSchedule.getEndClassTime()).toDate());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		// 是否是连堂课
 | 
	
		
			
				|  |  | -		String continueCourseTime = sysTenantConfigService.getTenantConfigValue(SysConfigService.ONLINE_CONTINUE_COURSE_TIME, courseSchedule.getTenantId());
 | 
	
		
			
				|  |  | +		/*String continueCourseTime = sysTenantConfigService.getTenantConfigValue(SysConfigService.ONLINE_CONTINUE_COURSE_TIME, courseSchedule.getTenantId());
 | 
	
		
			
				|  |  |  		if (StringUtils.isEmpty(continueCourseTime)) {
 | 
	
		
			
				|  |  |  			continueCourseTime = "5";
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		}*/
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		// 连堂课标准:同一个老师,同一天,同一课程组,连续上课
 | 
	
		
			
				|  |  |  		List<CourseSchedule> continuousCourse = courseScheduleDao.getTeacherContinuousCourse(courseSchedule.getClassGroupId(),
 | 
	
	
		
			
				|  | @@ -6249,7 +6321,6 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 | 
	
		
			
				|  |  |  		// 课程前连堂状态
 | 
	
		
			
				|  |  |  		updateContinuousCourseStatus(continueCourseTime, beforeCourse);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		List<CourseSchedule> newCourseSchedules = Lists.newArrayList();
 | 
	
		
			
				|  |  |  		// 课程连堂状态
 | 
	
		
			
				|  |  |  		if (beforeCourse.get(beforeCourse.size() - 1).getContinuousCourse()) {
 | 
	
		
			
				|  |  |  			List<CourseSchedule> collect = beforeCourse.stream()
 | 
	
	
		
			
				|  | @@ -6276,10 +6347,6 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		// 直播课关联直播间编号
 | 
	
		
			
				|  |  | -		String liveRoomId = courseSchedule.getLiveRoomId();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		List<CourseScheduleWrapper.CourseScheduleTime> courseScheduleTimes = Lists.newArrayList();
 | 
	
		
			
				|  |  |  		if (CollectionUtils.isNotEmpty(newCourseSchedules)) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  			// 连党课程信息
 | 
	
	
		
			
				|  | @@ -6322,39 +6389,10 @@ public class CourseScheduleServiceImpl extends BaseServiceImpl<Long, CourseSched
 | 
	
		
			
				|  |  |  					.startTime(courseSchedule.getStartClassTime().getTime())
 | 
	
		
			
				|  |  |  					.endTime(courseSchedule.getEndClassTime().getTime())
 | 
	
		
			
				|  |  |  					.build());
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		// 定时任务更新课程状态为进行中,判断当前课程状态是否匹配
 | 
	
		
			
				|  |  | -		int studentRemindTime = Integer.parseInt(sysConfigService.findByParamName(SysConfigService.LIVE_CLASS_START_REMIND_TIME).getParanValue());
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		Date date = DateUtil.startDateAndEndTime(courseSchedule.getClassDate(), courseSchedule.getStartClassTime());
 | 
	
		
			
				|  |  | -		date = DateUtil.addMinutes(date, -studentRemindTime);
 | 
	
		
			
				|  |  | -		// 课程是否开始
 | 
	
		
			
				|  |  | -		if(CourseStatusEnum.NOT_START.equals(courseSchedule.getStatus()) && date.after(new Date())) {
 | 
	
		
			
				|  |  | -			throw new BizException("直播课暂未开启,请稍后重试");
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		if (CourseStatusEnum.OVER == courseSchedule.getStatus()) {
 | 
	
		
			
				|  |  | -			throw new BizException("直播课已结束");
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		// 直播间配置
 | 
	
		
			
				|  |  | -		ImLiveBroadcastRoom liveBroadcastRoom = imLiveBroadcastRoomService.lambdaQuery()
 | 
	
		
			
				|  |  | -				.eq(ImLiveBroadcastRoom::getRoomUid, liveRoomId)
 | 
	
		
			
				|  |  | -				.last("LIMIT 1")
 | 
	
		
			
				|  |  | -				.one();
 | 
	
		
			
				|  |  | -		if (Objects.isNull(liveBroadcastRoom)) {
 | 
	
		
			
				|  |  | -			throw new BizException("请先进入直播课教室");
 | 
	
		
			
				|  |  | +			liveRoomId = courseSchedule.getLiveRoomId();
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		return CourseScheduleWrapper.LiveCourseSchedule.builder()
 | 
	
		
			
				|  |  | -				.liveRoomId(liveRoomId)
 | 
	
		
			
				|  |  | -				.subjectId(liveBroadcastRoom.getSubjectId())
 | 
	
		
			
				|  |  | -				.autoCloseFlag(true)
 | 
	
		
			
				|  |  | -				.autoCloseNetworkRoomTime(getCloseNetworkRoomTime(courseSchedule, continueCourseTime))
 | 
	
		
			
				|  |  | -				.surplusTime(DateUtil.secondsBetween(new Date(), courseSchedule.getEndClassTime()))
 | 
	
		
			
				|  |  | -				.timestamp(DateTime.now().getMillis())
 | 
	
		
			
				|  |  | -				.courseScheduleTimes(courseScheduleTimes)
 | 
	
		
			
				|  |  | -				.build();
 | 
	
		
			
				|  |  | +		return liveRoomId;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/**
 |