|  | @@ -1,30 +1,29 @@
 | 
	
		
			
				|  |  |  package com.yonge.cooleshow.biz.dal.service.impl;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import com.baomidou.mybatisplus.core.metadata.IPage;
 | 
	
		
			
				|  |  | +import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 | 
	
		
			
				|  |  |  import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 | 
	
		
			
				|  |  |  import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.auth.api.entity.SysUser;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.constant.CourseConstant;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant;
 | 
	
		
			
				|  |  | -import com.yonge.cooleshow.common.constant.SysConfigConstant;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.dao.CourseGroupDao;
 | 
	
		
			
				|  |  | -import com.yonge.cooleshow.biz.dal.dto.CheckLiveCourseTimeDto;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.dto.CheckCourseTimeDto;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.dto.LiveCourseGroupDto;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.dto.LiveCourseGroupDto.CoursePlanDto;
 | 
	
		
			
				|  |  | -import com.yonge.cooleshow.biz.dal.entity.CourseGroup;
 | 
	
		
			
				|  |  | -import com.yonge.cooleshow.biz.dal.entity.CoursePlan;
 | 
	
		
			
				|  |  | -import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
 | 
	
		
			
				|  |  | -import com.yonge.cooleshow.biz.dal.entity.CourseTimeEntity;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.entity.*;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.enums.CourseGroupEnum;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.service.*;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.support.PageUtil;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.vo.CourseGroupVo;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.biz.dal.vo.LiveCourseInfoVo;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.constant.SysConfigConstant;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.common.exception.BizException;
 | 
	
		
			
				|  |  |  import com.yonge.cooleshow.common.page.PageInfo;
 | 
	
		
			
				|  |  |  import com.yonge.toolset.utils.date.DateUtil;
 | 
	
		
			
				|  |  | +import org.apache.commons.collections.CollectionUtils;
 | 
	
		
			
				|  |  |  import org.apache.commons.lang3.StringUtils;
 | 
	
		
			
				|  |  |  import org.redisson.api.RMap;
 | 
	
		
			
				|  |  |  import org.redisson.api.RedissonClient;
 | 
	
	
		
			
				|  | @@ -34,6 +33,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  |  import org.springframework.stereotype.Service;
 | 
	
		
			
				|  |  |  import org.springframework.transaction.annotation.Transactional;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import java.time.LocalDate;
 | 
	
		
			
				|  |  |  import java.util.*;
 | 
	
		
			
				|  |  |  import java.util.concurrent.TimeUnit;
 | 
	
		
			
				|  |  |  import java.util.concurrent.atomic.AtomicBoolean;
 | 
	
	
		
			
				|  | @@ -67,7 +67,8 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
 | 
	
		
			
				|  |  |      private SubjectService subjectService;
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private CourseScheduleStudentPaymentService courseScheduleStudentPaymentService;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private TeacherFreeTimeService teacherFreeTimeService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      public CourseGroupDao getDao() {
 | 
	
	
		
			
				|  | @@ -201,9 +202,11 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | -     * 创建直播课程组时将课时写到缓存当作锁定的时间
 | 
	
		
			
				|  |  | +     * 创建课时写到缓存锁定时间
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    public List<CourseTimeEntity> lockCourseToCache(CheckLiveCourseTimeDto dto) {
 | 
	
		
			
				|  |  | +    public List<CourseTimeEntity> lockCourseToCache(CheckCourseTimeDto dto) {
 | 
	
		
			
				|  |  | +        //获取课程类型
 | 
	
		
			
				|  |  | +        CourseScheduleEnum courseType = CourseScheduleEnum.existCourseType(dto.getCourseType(), "课程类型不正确!");
 | 
	
		
			
				|  |  |          //先自校验传入时间是否交集
 | 
	
		
			
				|  |  |          List<CourseTimeEntity> timeList = dto.getTimeList();
 | 
	
		
			
				|  |  |          if (timeList.size() > 1) {
 | 
	
	
		
			
				|  | @@ -228,7 +231,7 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
 | 
	
		
			
				|  |  |          //需要自动补全课时
 | 
	
		
			
				|  |  |          if (dto.getLoop() == 1) {
 | 
	
		
			
				|  |  |              //自动排课,获取排课后所有的课程时间
 | 
	
		
			
				|  |  | -            List<CourseTimeEntity> allCourseTime = teacherAutoPlanningLiveCourseTime(dto.getTeacherId(), dto.getCourseNum(), timeList);
 | 
	
		
			
				|  |  | +            List<CourseTimeEntity> allCourseTime = autoPlanningLiveCourseTime(dto.getTeacherId(), dto.getCourseNum(), timeList, courseType);
 | 
	
		
			
				|  |  |              allCourseTime.sort(Comparator.comparing(CourseTimeEntity::getStartTime));
 | 
	
		
			
				|  |  |              //替换掉原有的课时
 | 
	
		
			
				|  |  |              dto.setTimeList(allCourseTime);
 | 
	
	
		
			
				|  | @@ -255,7 +258,7 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | -     * 老师创建直播课自动排课
 | 
	
		
			
				|  |  | +     * 自动排课
 | 
	
		
			
				|  |  |       * <p>自动排课规则及场景:总5节课,填入2节,需要自动补3节
 | 
	
		
			
				|  |  |       * <p>1.把前面2节课的时间循环+1周直到填满5节课为止
 | 
	
		
			
				|  |  |       * <p>2.如果自动排课时的时间和未来课程时间有冲突则继续往后面延续一周
 | 
	
	
		
			
				|  | @@ -263,9 +266,24 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
 | 
	
		
			
				|  |  |       * @param teacherId      老师id
 | 
	
		
			
				|  |  |       * @param totalCourseNum 总课程数量
 | 
	
		
			
				|  |  |       * @param paramTimeList  当前课程的时间段
 | 
	
		
			
				|  |  | +     * @param courseType     PRACTICE陪练课  LIVE直播课
 | 
	
		
			
				|  |  |       * @return 自动排课后的全部课时
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    private List<CourseTimeEntity> teacherAutoPlanningLiveCourseTime(Long teacherId, int totalCourseNum, List<CourseTimeEntity> paramTimeList) {
 | 
	
		
			
				|  |  | +    private List<CourseTimeEntity> autoPlanningLiveCourseTime(Long teacherId, int totalCourseNum, List<CourseTimeEntity> paramTimeList, CourseScheduleEnum courseType) {
 | 
	
		
			
				|  |  | +        //是否跳过节假日  0:不跳过 1跳过
 | 
	
		
			
				|  |  | +        boolean skipHoliday = false;
 | 
	
		
			
				|  |  | +        //true 陪练课
 | 
	
		
			
				|  |  | +        boolean courseTypeFlag = courseType.equals(CourseScheduleEnum.PRACTICE);
 | 
	
		
			
				|  |  | +        if (courseTypeFlag) {
 | 
	
		
			
				|  |  | +            //查询老师陪练课设置
 | 
	
		
			
				|  |  | +            TeacherFreeTime teacherTime = teacherFreeTimeService.getOne(Wrappers.<TeacherFreeTime>lambdaQuery()
 | 
	
		
			
				|  |  | +                    .eq(TeacherFreeTime::getDefaultFlag, true)
 | 
	
		
			
				|  |  | +                    .eq(TeacherFreeTime::getTeacherId, teacherId)
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +            Optional.ofNullable(teacherTime).orElseThrow(() -> new BizException("未查询到老师陪练课设置!"));
 | 
	
		
			
				|  |  | +            skipHoliday = teacherTime.getSkipHolidayFlag();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          //获取当前课程
 | 
	
		
			
				|  |  |          int nowCourseNum = paramTimeList.size();
 | 
	
		
			
				|  |  |          //获取总课程数量 - 获取当前选择的课程数量 = 要自动排课的课程数量
 | 
	
	
		
			
				|  | @@ -276,16 +294,19 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
 | 
	
		
			
				|  |  |                  .collect(Collectors.toList());
 | 
	
		
			
				|  |  |          //获取最大排课周
 | 
	
		
			
				|  |  |          String maxWeekStr = sysConfigService.findConfigValue(SysConfigConstant.AUTO_PLANNING_COURSE_MAX_WEEK);
 | 
	
		
			
				|  |  | -        int maxWeek = 26;//默认 26周
 | 
	
		
			
				|  |  | +        int maxWeek = 26;//自动生成课时最大的生成周数  默认 26周
 | 
	
		
			
				|  |  |          if (StringUtils.isBlank(maxWeekStr)) {
 | 
	
		
			
				|  |  |              maxWeek = Integer.parseInt(maxWeekStr);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        //从第index课程开始生成时间
 | 
	
		
			
				|  |  |          int index = 0;
 | 
	
		
			
				|  |  | -        //自动补全课时
 | 
	
		
			
				|  |  | +        //节假日缓存数据,避免多次查询
 | 
	
		
			
				|  |  | +        Map<Integer, List<String>> holidayMap = new HashMap<>();
 | 
	
		
			
				|  |  | +        //开始自动补全课时
 | 
	
		
			
				|  |  |          for (int i = 0; i < diffCourse; i++) {
 | 
	
		
			
				|  |  |              //需要增加的周数
 | 
	
		
			
				|  |  |              AtomicInteger week = new AtomicInteger(1);
 | 
	
		
			
				|  |  | -            //是否要一直生成课程 true 一直增加周数并生成到不冲突的时间为止
 | 
	
		
			
				|  |  | +            //是否要一直生成课程 true:一直增加周数并生成到不冲突的时间为止
 | 
	
		
			
				|  |  |              AtomicBoolean flag = new AtomicBoolean(true);
 | 
	
		
			
				|  |  |              //生成课程
 | 
	
		
			
				|  |  |              while (flag.get()) {
 | 
	
	
		
			
				|  | @@ -301,7 +322,7 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
 | 
	
		
			
				|  |  |                  Date autoStartDate = DateUtil.addWeeks(timeDto.getStartTime(), week.get());
 | 
	
		
			
				|  |  |                  Date autoEndDate = DateUtil.addWeeks(timeDto.getEndTime(), week.get());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                //true  flag = true 并且 周数+1
 | 
	
		
			
				|  |  | +                //传入 ->true :周数+1   ->false:停止生成时间
 | 
	
		
			
				|  |  |                  Consumer<Boolean> con = (check) -> {
 | 
	
		
			
				|  |  |                      //check = true ,有交集延续1周后继续生成时间
 | 
	
		
			
				|  |  |                      if (check) {
 | 
	
	
		
			
				|  | @@ -312,8 +333,30 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                boolean checkTime;
 | 
	
		
			
				|  |  | +                //是否跳过节假日
 | 
	
		
			
				|  |  | +                if (skipHoliday) {
 | 
	
		
			
				|  |  | +                    //将自动生成的开始日期转换为字符串
 | 
	
		
			
				|  |  | +                    String dateStr = DateUtil.dateToString(autoStartDate);
 | 
	
		
			
				|  |  | +                    //取年份
 | 
	
		
			
				|  |  | +                    int calendarYear = LocalDate.parse(dateStr).getYear();
 | 
	
		
			
				|  |  | +                    //获取节假日信息
 | 
	
		
			
				|  |  | +                    List<String> holiday = Optional.of(calendarYear)
 | 
	
		
			
				|  |  | +                            .map(holidayMap::get)
 | 
	
		
			
				|  |  | +                            .filter(CollectionUtils::isNotEmpty)
 | 
	
		
			
				|  |  | +                            .orElseGet(() -> {
 | 
	
		
			
				|  |  | +                                List<String> list = courseScheduleService.getHoliday(calendarYear);
 | 
	
		
			
				|  |  | +                                holidayMap.put(calendarYear, list);
 | 
	
		
			
				|  |  | +                                return list;
 | 
	
		
			
				|  |  | +                            });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +                    //如果生成的日期是节假日 则跳过当前日期
 | 
	
		
			
				|  |  | +                    con.accept(holiday.contains(dateStr));
 | 
	
		
			
				|  |  | +                    if (flag.get()) {
 | 
	
		
			
				|  |  | +                        continue;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                boolean checkTime;
 | 
	
		
			
				|  |  |                  //若:传入时间是1号10点和8号10点,然后1号10点自动生成的课时是8号10点那么就和传入的8号10点冲突了,这种情况需要继续往后延续1周
 | 
	
		
			
				|  |  |                  checkTime = courseScheduleService.checkCourseTime(resultCourseTime, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime, autoStartDate, autoEndDate);
 | 
	
		
			
				|  |  |                  con.accept(checkTime);
 |