Browse Source

Merge remote-tracking branch 'origin/master'

weifanli 3 năm trước cách đây
mục cha
commit
24cc731dce
18 tập tin đã thay đổi với 833 bổ sung153 xóa
  1. 17 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/constant/SysConfigConstant.java
  2. 15 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleDao.java
  3. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/LiveRoomDao.java
  4. 12 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseSchedule.java
  5. 22 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/RoomInfoCache.java
  6. 74 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/CourseScheduleEnum.java
  7. 0 50
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/CourseScheduleTypeEnum.java
  8. 2 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/RoomTypeEnum.java
  9. 28 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseScheduleService.java
  10. 11 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/LiveRoomService.java
  11. 124 30
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java
  12. 127 53
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/LiveRoomServiceImpl.java
  13. 2 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/support/DistributedLock.java
  14. 194 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/RoomVo.java
  15. 104 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/TeacherCourseVo.java
  16. 61 3
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml
  17. 23 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/CourseScheduleController.java
  18. 16 7
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/LiveRoomController.java

+ 17 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/constant/SysConfigConstant.java

@@ -32,16 +32,26 @@ public interface SysConfigConstant {
     String WITHDRAWAL_SERVICE_FEE = "withdrawal_service_fee";
 
     /**
-     * 提前创建直播房间的时间
+     * 提前XX分钟创建/进入直播房间的时间
      */
     String PRE_CREATE_LIVE_ROOM_MINUTE = "pre_create_live_room_minute";
 
     /**
-     * 直播结束后,直播房间的有效时间
+     * 提前XX分钟创建/进入陪练课房间时间
+     */
+    String PRE_CREATE_PRACTICE_ROOM_MINUTE = "pre_create_practice_room_minute";
+
+    /**
+     * 直播结束后,XX分钟关闭房间
      */
     String DESTROY_EXPIRED_LIVE_ROOM_MINUTE = "destroy_expired_live_room_minute";
 
     /**
+     * 陪练课结束后,XX分钟关闭房间
+     */
+    String DESTROY_EXPIRED_PRACTICE_ROOM_MINUTE = "destroy_expired_practice_room_minute";
+
+    /**
      * 陪练课提现手续费
      */
     String PRACTICE_SERVICE_FEE = "practice_service_fee";
@@ -51,4 +61,9 @@ public interface SysConfigConstant {
      */
     String PRACTICE_TIMES_SETTING = "practice_times_setting";
 
+    /**
+     * 课程结束后,XX天后结算课酬
+     */
+    String COURSE_SETTLEMENT_TIME_DAY = "course_settlement_time_day";
+
 }

+ 15 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleDao.java

@@ -1,12 +1,15 @@
 package com.yonge.cooleshow.biz.dal.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
 import com.yonge.cooleshow.biz.dal.vo.StudentTotalVo;
 import com.yonge.cooleshow.biz.dal.vo.TeacherTotalVo;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 老师课程表(CourseSchedule)表数据库访问层
@@ -17,6 +20,7 @@ import java.util.List;
 public interface CourseScheduleDao extends BaseMapper<CourseSchedule> {
 
     int insertBatch(@Param("entities") List<CourseSchedule> entities);
+
     /***
      * 查询所有老师课时统计
      * @author liweifan
@@ -24,6 +28,7 @@ public interface CourseScheduleDao extends BaseMapper<CourseSchedule> {
      * @return: com.yonge.cooleshow.biz.dal.vo.TeacherTotalVo
      */
     List<TeacherTotalVo> queryTeacherHomeTotal();
+
     /***
      * 查询所有学生课时统计
      * @author liweifan
@@ -32,5 +37,15 @@ public interface CourseScheduleDao extends BaseMapper<CourseSchedule> {
      */
     List<StudentTotalVo> queryStudentHomeTotal();
 
+    /**
+     * 根据学生id查询大于当前时间并未开始的课程
+     *
+     * @param studentId 学生id
+     * @param classDate 年月日
+     */
+    List<CourseSchedule> queryStudentCourse(@Param("studentId") Long studentId, @Param("classDate") String classDate);
+
+    <T> IPage<T> queryTeacherCourse(Page<T> page, @Param("param") Map<String, Object> param);
+
 }
 

+ 1 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/LiveRoomDao.java

@@ -2,6 +2,7 @@ package com.yonge.cooleshow.biz.dal.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.yonge.cooleshow.biz.dal.entity.LiveRoom;
+import com.yonge.cooleshow.biz.dal.vo.RoomVo;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;

+ 12 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseSchedule.java

@@ -1,6 +1,5 @@
 package com.yonge.cooleshow.biz.dal.entity;
 
-
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -27,9 +26,13 @@ public class CourseSchedule implements Serializable {
     private Long courseGroupId;
 
     @TableField("type_")
-    @ApiModelProperty(value = "类型 practice陪练课 live直播课")
+    @ApiModelProperty(value = "类型 practice陪练课 live直播课  CourseScheduleEnum")
     private String type;
 
+    @TableField("status_")
+    @ApiModelProperty(value = "课程状态 NOT未开始 ING进行中 COMPLETE已完成 CANCEL已取消  CourseScheduleEnum")
+    private String status;
+
     @TableField("class_num_")
     @ApiModelProperty(value = "课堂编号-第几堂课")
     private Integer classNum;
@@ -211,5 +214,12 @@ public class CourseSchedule implements Serializable {
         this.updatedTime = updatedTime;
     }
 
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
 }
 

+ 22 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/RoomInfoCache.java

@@ -47,6 +47,12 @@ public class RoomInfoCache implements Serializable {
     @ApiModelProperty(value = "房间类型 RoomTypeEnum")
     private String roomType;
 
+    @ApiModelProperty(value = "点赞数")
+    private Integer likeNum;
+
+    @ApiModelProperty(value = "当前观看人数")
+    private Integer lookNum;
+
     public Long getSpeakerId() {
         return speakerId;
     }
@@ -134,4 +140,20 @@ public class RoomInfoCache implements Serializable {
     public void setRoomType(String roomType) {
         this.roomType = roomType;
     }
+
+    public Integer getLikeNum() {
+        return likeNum;
+    }
+
+    public void setLikeNum(Integer likeNum) {
+        this.likeNum = likeNum;
+    }
+
+    public Integer getLookNum() {
+        return lookNum;
+    }
+
+    public void setLookNum(Integer lookNum) {
+        this.lookNum = lookNum;
+    }
 }

+ 74 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/CourseScheduleEnum.java

@@ -0,0 +1,74 @@
+package com.yonge.cooleshow.biz.dal.enums;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 课程类型
+ */
+public enum CourseScheduleEnum {
+    //课程类型
+    PRACTICE("PRACTICE", "陪练课"),
+    LIVE("LIVE", "直播课"),
+    //课程状态
+    NOT_START("NOT_START", "未开始"),
+    ING("ING", "进行中"),
+    COMPLETE("COMPLETE", "已完成"),
+    CANCEL("CANCEL", "已取消");
+
+    private String code;
+
+    private String msg;
+
+    CourseScheduleEnum(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    /**
+     * 校验课程类型code是否正确
+     *
+     * @param code   code
+     * @param errMsg 错误异常
+     */
+    public static void existCourseType(String code, String errMsg) {
+        CourseScheduleEnum[] values = {PRACTICE, LIVE};
+        existCourse(values, code, errMsg);
+    }
+
+    /**
+     * 校验课程状态code是否正确
+     *
+     * @param code   code
+     * @param errMsg 错误异常
+     */
+    public static void existCourseState(String code, String errMsg) {
+        CourseScheduleEnum[] values = {NOT_START, ING, COMPLETE, CANCEL};
+        existCourse(values, code, errMsg);
+    }
+
+    private static void existCourse(CourseScheduleEnum[] values,String code,String errMsg){
+        List<String> collect = Arrays.stream(values).map(CourseScheduleEnum::getCode).collect(Collectors.toList());
+        boolean typeFlag = collect.contains(code);
+        if (!typeFlag) {
+            throw new RuntimeException(errMsg);
+        }
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+}

+ 0 - 50
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/CourseScheduleTypeEnum.java

@@ -1,50 +0,0 @@
-package com.yonge.cooleshow.biz.dal.enums;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * 课程类型
- */
-public enum CourseScheduleTypeEnum {
-
-    PRACTICE("PRACTICE", "陪练课"),
-    LIVE("LIVE", "直播课");
-
-    private String code;
-
-    private String msg;
-
-    CourseScheduleTypeEnum(String code, String msg) {
-        this.code = code;
-        this.msg = msg;
-    }
-
-    /**
-     * 校验code是否存在
-     * @param code code
-     * @return true存在
-     */
-    public static boolean isExistCode(String code) {
-        CourseScheduleTypeEnum[] values = CourseScheduleTypeEnum.values();
-        List<String> collect = Arrays.stream(values).map(CourseScheduleTypeEnum::getCode).collect(Collectors.toList());
-        return collect.contains(code);
-    }
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    public String getMsg() {
-        return msg;
-    }
-
-    public void setMsg(String msg) {
-        this.msg = msg;
-    }
-}

+ 2 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/RoomTypeEnum.java

@@ -24,8 +24,8 @@ public enum RoomTypeEnum {
      * @return true存在
      */
     public static boolean isExistCode(String code) {
-        CourseScheduleTypeEnum[] values = CourseScheduleTypeEnum.values();
-        List<String> collect = Arrays.stream(values).map(CourseScheduleTypeEnum::getCode).collect(Collectors.toList());
+        CourseScheduleEnum[] values = CourseScheduleEnum.values();
+        List<String> collect = Arrays.stream(values).map(CourseScheduleEnum::getCode).collect(Collectors.toList());
         return collect.contains(code);
     }
 

+ 28 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseScheduleService.java

@@ -3,10 +3,13 @@ package com.yonge.cooleshow.biz.dal.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.dao.CourseScheduleDao;
 import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
+import com.yonge.cooleshow.biz.dal.vo.TeacherCourseVo;
+import com.yonge.cooleshow.common.page.PageInfo;
 
 import javax.validation.Valid;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 老师课程表(CourseSchedule)表服务接口
@@ -18,10 +21,35 @@ public interface CourseScheduleService extends IService<CourseSchedule> {
 
     CourseScheduleDao getDao();
 
+    /**
+     * 老师端-首页-我的课程-直播课
+     *
+     * @param param 传入参数
+     *              <p> - year 年
+     *              <p> - month 月
+     *              <p> - row 条数
+     *              <p> - page 页数
+     *              <p> - status 课程状态 NOT_START未开始 ING进行中 COMPLETE已完成
+     */
+    PageInfo<TeacherCourseVo> queryTeacherLiveCourse(Map<String, Object> param);
+
+    /**
+     * 锁定课时
+     *
+     * @param id 课程id
+     */
     void lockCourseTime(Long id);
 
+    /**
+     * 解锁
+     *
+     * @param id 课程id
+     */
     void unlockCourseTime(Long id);
 
+    /**
+     * 添加课时
+     */
     void add(@Valid CourseSchedule course);
 
 }

+ 11 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/LiveRoomService.java

@@ -3,7 +3,9 @@ package com.yonge.cooleshow.biz.dal.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.dao.LiveRoomDao;
 import com.yonge.cooleshow.biz.dal.entity.LiveRoom;
+import com.yonge.cooleshow.biz.dal.entity.RoomInfoCache;
 import com.yonge.cooleshow.biz.dal.entity.RoomUserInfoCache;
+import com.yonge.cooleshow.biz.dal.vo.RoomVo;
 
 import java.util.List;
 import java.util.Map;
@@ -19,6 +21,13 @@ public interface LiveRoomService extends IService<LiveRoom> {
     LiveRoomDao getDao();
 
     /**
+     * 根据房间uid查询房间信息
+     *
+     * @param roomUid 房间uid
+     */
+    RoomVo queryRoomInfo(String roomUid);
+
+    /**
      * 定时任务创建直播间
      */
     void createCourseLiveRoom();
@@ -31,7 +40,7 @@ public interface LiveRoomService extends IService<LiveRoom> {
     /**
      * 创建临时房间-直播间
      */
-    void createTempLiveRoom(Map<String, Object> param);
+    String createTempLiveRoom(Map<String, Object> param);
 
     /**
      * 进入房间
@@ -39,7 +48,7 @@ public interface LiveRoomService extends IService<LiveRoom> {
      * @param roomUid 房间uid
      * @param userId  用户id 主讲人或者用户的id
      */
-    void joinRoom(String roomUid, Long userId);
+    RoomInfoCache joinRoom(String roomUid, Long userId);
 
     /**
      * 查询在观看直播的用户信息

+ 124 - 30
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java

@@ -1,23 +1,38 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+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.dao.CourseScheduleDao;
 import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
-import com.yonge.cooleshow.biz.dal.enums.CourseScheduleTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
 import com.yonge.cooleshow.biz.dal.service.CourseScheduleService;
+import com.yonge.cooleshow.biz.dal.support.PageUtil;
+import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
+import com.yonge.cooleshow.biz.dal.vo.TeacherCourseVo;
 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.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.validation.Valid;
+import java.time.LocalDate;
+import java.time.temporal.TemporalAdjusters;
 import java.util.Date;
 import java.util.List;
-import java.util.Objects;
+import java.util.Map;
+import java.util.Optional;
 
 /**
  * 老师课程表(CourseSchedule)表服务实现类
@@ -31,52 +46,127 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
 
     private final static Logger log = LoggerFactory.getLogger(CourseScheduleServiceImpl.class);
 
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+
     @Override
     public CourseScheduleDao getDao() {
         return this.baseMapper;
     }
 
     /**
-     * 根据老师id查询直播课程
+     * 老师端-首页-我的课程-直播课
+     *
+     * @param param 传入参数
+     *              <p> - year 年
+     *              <p> - month 月
+     *              <p> - row 条数
+     *              <p> - page 页数
+     *              <p> - status 课程状态 NOT_START未开始 ING进行中 COMPLETE已完成
+     *              <p> - subjectId 声部id
      */
-    public void queryCourseList(Long teacherId) {
-        List<CourseSchedule> list = this.list(new QueryWrapper<>(new CourseSchedule()).lambda()
-                .eq(CourseSchedule::getTeacherId, teacherId)
-        );
-        if (CollectionUtils.isEmpty(list)) {
-            throw new BizException("没有课程");
-        }
+    public PageInfo<TeacherCourseVo> queryTeacherLiveCourse(Map<String, Object> param) {
+        String status = WrapperUtil.toStr(param, "status", "课程状态不能为空!");
+        CourseScheduleEnum.existCourseState(status, "查询条件错误,课程状态不正确");
+        Integer year = WrapperUtil.toInt(param, "year", "查询时间年份不能为空!");
+        Integer month = WrapperUtil.toInt(param, "month", "查询时间月份不能为空!");
+        //本月的第一天
+        LocalDate firstDay = LocalDate.of(year, month, 1);
+        //本月的最后一天
+        LocalDate lastDay = firstDay.with(TemporalAdjusters.lastDayOfMonth());
+        //查询该月的所有课程
+        param.put("startDate", firstDay.toString());
+        param.put("endDate", lastDay.toString());
+        param.put("teacherId", getSysUser().getId());
+        param.put("type", CourseScheduleEnum.LIVE.getCode());
+        Page<TeacherCourseVo> pageInfo = PageUtil.getPageInfo(param);
+        pageInfo.setAsc("a.start_time_");
+        IPage<TeacherCourseVo> page = baseMapper.queryTeacherCourse(pageInfo, param);
+        return PageUtil.pageInfo(page);
     }
 
     /**
-     * 根据课程id查询直播间信息
+     * 校验该学生大于当前时间并未开始的课程时间和传入时间段有没有交集
+     *
+     * @param studentId 学生id
+     * @param startTime 新增课程 开始时间
+     * @param endTime   新增课程 结束时间
+     * @return true 被占用 false 没有被占用
      */
-    public void getCourseInfo(Long courseId) {
-        CourseSchedule course = this.getById(courseId);
-        if (Objects.isNull(course)) {
-            throw new BizException("该课程没有直播间");
-        }
+    public boolean checkStudentCourseTime(Long studentId, Date startTime, Date endTime) {
+        WrapperUtil.checkObj(studentId, "学生id不能为空!");
+        WrapperUtil.checkObj(startTime, "开始时间不能为空!");
+        //获取日期-目前上课没有跨天情况
+        String ymd = DateUtil.format(startTime, DateUtil.DEFAULT_PATTERN);
+        //查询大于当前时间并未开始的课程
+        List<CourseSchedule> list = baseMapper.queryStudentCourse(studentId, ymd);
+        return checkCourseTime(list, startTime, endTime);
     }
 
     /**
-     * 查询这个时间段有没有被占用-校验课时
+     * 校验老师这个时间段有没有被占用-校验课时
      *
      * @param teacherId 老师id
-     * @param startTime 开始时间
-     * @param endTime   结束时间
-     * @return true 没有被占用  false 被占用
+     * @param startTime 新增课程 开始时间
+     * @param endTime   新增课程 结束时间
+     * @return true 被占用 false 没有被占用
      */
-    public boolean checkCourseTime(Long teacherId, Date startTime, Date endTime) {
-        List<CourseSchedule> list = this.list(new QueryWrapper<>(new CourseSchedule()).lambda()
+    public boolean checkTeacherCourseTime(Long teacherId, Date startTime, Date endTime) {
+        WrapperUtil.checkObj(teacherId, "老师id不能为空!");
+        WrapperUtil.checkObj(startTime, "开始时间不能为空!");
+        //获取日期-目前上课没有跨天情况
+        String ymd = DateUtil.format(startTime, DateUtil.DEFAULT_PATTERN);
+        //查询老师当天所有的课程时间数据
+        List<CourseSchedule> list = this.list(Wrappers.<CourseSchedule>lambdaQuery()
                 .eq(CourseSchedule::getTeacherId, teacherId)
-                .gt(CourseSchedule::getEndTime, startTime)
-                .lt(CourseSchedule::getStartTime, endTime)
-        );
-        return CollectionUtils.isEmpty(list);
+                .eq(CourseSchedule::getClassDate, ymd));
+        return checkCourseTime(list, startTime, endTime);
+    }
+
+    /**
+     * 查询这个课程列表中时间是否有重叠
+     * <p>案例:1
+     * <p>已有9:00~ 10:00 课程
+     * <p>新增课程 09:10~ 09:40
+     * <p>返回 true
+     *
+     * <p>案例:2
+     * <p>已有9:00~ 10:00 课程
+     * <p>新增课程 08:45~ 09:40
+     * <p>返回 true
+     *
+     * <p>案例:3
+     * <p>已有9:00~ 10:00 课程
+     * <p>新增课程 10:00~ 10:40
+     * <p>返回 false
+     *
+     * @param list      课程列表
+     * @param startTime 新增课程 开始时间
+     * @param endTime   新增课程 结束时间
+     * @return true 被占用 false 没有被占用
+     */
+    public boolean checkCourseTime(List<CourseSchedule> list, Date startTime, Date endTime) {
+        WrapperUtil.checkObj(startTime, "开始时间不能为空!");
+        WrapperUtil.checkObj(endTime, "结束时间不能为空!");
+        // 如果没有课程,直接返回false
+        if (CollectionUtils.isEmpty(list)) {
+            return false;
+        }
+        boolean result;
+        //匹配时间是否有交集
+        for (CourseSchedule course : list) {
+            result = WrapperUtil.inInterSection(course.getStartTime(), course.getEndTime(), startTime, endTime);
+            if (result) {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
      * 锁定课时
+     *
+     * @param id 课程id
      */
     @Transactional(rollbackFor = Exception.class)
     @Override
@@ -90,6 +180,8 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
 
     /**
      * 解锁
+     *
+     * @param id 课程id
      */
     @Transactional(rollbackFor = Exception.class)
     @Override
@@ -107,10 +199,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
     @Transactional(rollbackFor = Exception.class)
     @Override
     public void add(@Valid CourseSchedule course) {
-        boolean typeFlag = CourseScheduleTypeEnum.isExistCode(course.getType());
-        if (!typeFlag) {
-            throw new RuntimeException("课程类型不正确");
-        }
+        CourseScheduleEnum.existCourseType(course.getType(), "课程类型不正确");
         this.save(course);
     }
 
@@ -124,5 +213,10 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
 
     }
 
+    private SysUser getSysUser() {
+        return Optional.ofNullable(sysUserFeignService.queryUserInfo())
+                .orElseThrow(() -> new BizException("用户不存在"));
+    }
+
 }
 

+ 127 - 53
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/LiveRoomServiceImpl.java

@@ -1,13 +1,13 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 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.dao.LiveRoomDao;
 import com.yonge.cooleshow.biz.dal.entity.*;
-import com.yonge.cooleshow.biz.dal.enums.CourseScheduleTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
 import com.yonge.cooleshow.biz.dal.enums.RoomTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.CourseGroupService;
 import com.yonge.cooleshow.biz.dal.service.CourseScheduleService;
@@ -15,6 +15,7 @@ import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
 import com.yonge.cooleshow.biz.dal.service.SysConfigService;
 import com.yonge.cooleshow.biz.dal.support.IMHelper;
 import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
+import com.yonge.cooleshow.biz.dal.vo.RoomVo;
 import com.yonge.cooleshow.common.exception.BizException;
 import com.yonge.toolset.utils.date.DateUtil;
 import org.apache.commons.collections.CollectionUtils;
@@ -24,6 +25,7 @@ import org.redisson.api.RMap;
 import org.redisson.api.RedissonClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -33,6 +35,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.function.BiFunction;
 import java.util.stream.Collectors;
 
+import static com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant.*;
 import static com.yonge.cooleshow.biz.dal.constant.SysConfigConstant.DESTROY_EXPIRED_LIVE_ROOM_MINUTE;
 import static com.yonge.cooleshow.biz.dal.constant.SysConfigConstant.PRE_CREATE_LIVE_ROOM_MINUTE;
 
@@ -59,22 +62,8 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     @Autowired
     private SysConfigService sysConfigService;
 
-    //替换的字符串
-    public static final String USER_ID = "${userId}";
-    public static final String ROOM_UID = "${roomUid}";
-    //缓存排头
-    public static final String COOLESHOW = "COOLESHOW";
-
-    //直播间累计用户信息-指只要进入到该房间的用户都要记录
-    public static final String LIVE_ROOM_TOTAL_USER_LIST = String.join(":", COOLESHOW, "LIVE_ROOM_TOTAL_USER_LIST" + ROOM_UID);
-    //用户当前对应的直播间Uid
-    public static final String LIVE_USER_ROOM = String.join(":", COOLESHOW, "LIVE_ROOM_USER", USER_ID);
-    //房间点赞数
-    public static final String LIVE_ROOM_LIKE = String.join(":", COOLESHOW, "LIVE_ROOM_LIKE", ROOM_UID);
     //生成房间UID
     public static BiFunction<Long, RoomTypeEnum, String> GenRoomUid = (userId, en) -> String.join("-", COOLESHOW, en.getCode(), userId.toString(), new Date().getTime() + "");
-    //房间的信息
-    public static final String LIVE_ROOM_INFO = String.join(":", COOLESHOW, "LIVE_ROOM_INFO", ROOM_UID);
 
     @Override
     public LiveRoomDao getDao() {
@@ -82,6 +71,26 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     }
 
     /**
+     * 根据房间uid查询房间信息
+     *
+     * @param roomUid 房间uid
+     */
+    @Override
+    public RoomVo queryRoomInfo(String roomUid) {
+        LiveRoom liveRoom = this.getOne(Wrappers.<LiveRoom>lambdaQuery()
+                .eq(LiveRoom::getRoomUid, roomUid));
+        if (liveRoom == null) {
+            throw new BizException("房间不存在");
+        }
+        RoomVo roomVo = new RoomVo();
+        BeanUtils.copyProperties(liveRoom, roomVo);
+        roomVo.setSpeakerName(getSysUser(liveRoom.getSpeakerId()).getRealName());
+        roomVo.setLikeNum(getLike(roomUid));
+        roomVo.setLookNum(getLooker(roomUid));
+        return roomVo;
+    }
+
+    /**
      * 定时任务创建直播间
      */
     @Override
@@ -96,8 +105,8 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         }
         Date endTime = DateUtil.addMinutes(now, Integer.parseInt(preCreateRoomMinute));
         //查询课时表生成直播间
-        List<CourseSchedule> courseScheduleList = courseScheduleService.list(new QueryWrapper<CourseSchedule>().lambda()
-                .eq(CourseSchedule::getType, CourseScheduleTypeEnum.LIVE.getCode())
+        List<CourseSchedule> courseScheduleList = courseScheduleService.list(Wrappers.<CourseSchedule>lambdaQuery()
+                .eq(CourseSchedule::getType, CourseScheduleEnum.LIVE.getCode())
                 .eq(CourseSchedule::getLock, 0)
                 .ge(CourseSchedule::getStartTime, now)
                 .le(CourseSchedule::getStartTime, endTime));
@@ -105,12 +114,18 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
             return;
         }
         //获取课程组名称
-        Map<Long, String> titleMap = courseScheduleList.stream()
+        Map<Long, String> titleMap = new HashMap<>();
+        //获取课程组介绍
+        Map<Long, String> remarkMap = new HashMap<>();
+        courseScheduleList.stream()
                 .map(CourseSchedule::getCourseGroupId)
                 .distinct()
                 .map(courseGroupService::getById)
                 .filter(Objects::nonNull)
-                .collect(Collectors.toMap(CourseGroup::getId, CourseGroup::getName));
+                .forEach(courseGroup -> {
+                    titleMap.put(courseGroup.getId(), courseGroup.getName());
+                    remarkMap.put(courseGroup.getId(), courseGroup.getCourseIntroduce());
+                });
         //生成课程对应的房间
         RoomTypeEnum en = RoomTypeEnum.LIVE;
         courseScheduleList.forEach(c -> {
@@ -119,6 +134,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
             room.setCourseId(c.getId());
             room.setRoomUid(GenRoomUid.apply(c.getTeacherId(), en));
             room.setRoomTitle(titleMap.get(c.getCourseGroupId()));
+            room.setLiveRemark(remarkMap.get(c.getCourseGroupId()));
             room.setSpeakerId(c.getTeacherId());
             room.setLiveStartTime(c.getStartTime());
             room.setLiveEndTime(c.getEndTime());
@@ -131,7 +147,6 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
             //去融云创建房间及创建房间缓存信息
             createLiveRoomInfo(room);
         });
-
     }
 
     /**
@@ -139,22 +154,24 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void createTempLiveRoom(Map<String, Object> param) {
-        String roomTitle = WrapperUtil.toStr(param, "roomTitle", "房间标题不能为空!");
-        String liveRemark = WrapperUtil.toStr(param, "liveRemark", "直播间描述不能为空!");
-        String coverPic = WrapperUtil.toStr(param, "coverPic", "直播间封面不能为空!");
+    public String createTempLiveRoom(Map<String, Object> param) {
         //查询主讲人信息
         SysUser sysUser = getSysUser();
-        Long id = sysUser.getId();
         Date now = new Date();
+        //当前时间有课程则不能开启直播
+        checkTempLive(sysUser.getId());
+        String roomTitle = WrapperUtil.toStr(param, "roomTitle", "房间标题不能为空!");
+        String liveRemark = WrapperUtil.toStr(param, "liveRemark", "直播间描述不能为空!");
+
+        Long id = sysUser.getId();
         RoomTypeEnum en = RoomTypeEnum.TEMP;
+        String roomUid = GenRoomUid.apply(id, en);
         LiveRoom room = new LiveRoom();
         room.setCourseGroupId(-1L);
         room.setCourseId(-1L);
-        room.setRoomUid(GenRoomUid.apply(id, en));
+        room.setRoomUid(roomUid);
         room.setRoomTitle(roomTitle);
         room.setLiveRemark(liveRemark);
-        room.setCoverPic(coverPic);
         room.setSpeakerId(id);
         room.setLiveStartTime(now);
         room.setLiveState(0);
@@ -165,16 +182,44 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         this.save(room);
         log.info("createTempLiveRoom>>>>>>room:{}", room.getRoomUid());
         //去融云创建房间及创建房间缓存信息
-        createLiveRoomInfo(room);
+        createLiveRoomInfo(room, sysUser);
+        return roomUid;
+    }
+
+    /**
+     * 校验开启临时直播间是否会有课程冲突
+     */
+    @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) {
+        //查询主讲人信息
+        SysUser sysUser = getSysUser(room.getSpeakerId());
+        createLiveRoomInfo(room, sysUser);
+    }
+
+    private void createLiveRoomInfo(LiveRoom room, SysUser sysUser) {
         try {
             //生成主讲人信息
-            createRoomInfoCache(room);
+            createRoomInfoCache(room, sysUser);
             //去融云创建房间
             createLiveRoom(room.getRoomUid(), room.getRoomTitle());
         } catch (Exception e) {
@@ -183,13 +228,6 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     }
 
     //生成主讲人信息
-    private void createRoomInfoCache(LiveRoom room) {
-        //查询主讲人信息
-        SysUser sysUser = getSysUser(room.getSpeakerId());
-        createRoomInfoCache(room, sysUser);
-    }
-
-    //生成主讲人信息
     private void createRoomInfoCache(LiveRoom room, SysUser sysUser) {
         RoomInfoCache roomCache = new RoomInfoCache();
         roomCache.setSpeakerId(sysUser.getId());
@@ -209,6 +247,9 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         //生成0点赞
         redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, room.getRoomUid()))
                 .set(0, 2L, TimeUnit.DAYS);
+        //生成房间人员列表数据
+        redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, room.getRoomUid()))
+                .expire(2L, TimeUnit.DAYS);
     }
 
     /**
@@ -242,7 +283,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         }
         Date now = new Date();
         //查询已经开始并且没有删除及销毁的直播间
-        List<LiveRoom> list = this.list(new QueryWrapper<LiveRoom>().lambda()
+        List<LiveRoom> list = this.list(Wrappers.<LiveRoom>lambdaQuery()
                 .eq(LiveRoom::getRoomState, 0)
                 .eq(LiveRoom::getLiveState, 1)
                 .eq(LiveRoom::getType, RoomTypeEnum.LIVE.getCode())
@@ -288,25 +329,28 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
      * @param roomUid 房间uid
      * @param userId  用户id 主讲人或者用户的id
      */
-    public void joinRoom(String roomUid, Long userId) {
+    public RoomInfoCache joinRoom(String roomUid, Long userId) {
         //校验房间是否存在
         RBucket<RoomInfoCache> roomInfoCache = redissonClient.getBucket(LIVE_ROOM_INFO.replace(ROOM_UID, roomUid));
-        RoomInfoCache roomInfo;
-        if (roomInfoCache.isExists()) {
-            roomInfo = roomInfoCache.get();
-        } else {
-            throw new BizException("房间不存在!");
+        if (!roomInfoCache.isExists()) {
+            throw new BizException("直播还未开始!");
         }
+        RoomInfoCache roomInfo = roomInfoCache.get();
+        roomInfo.setLikeNum(getLike(roomUid));
+        roomInfo.setLookNum(getLooker(roomUid));
+
+        //记录当前对应的房间uid
+        redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid, 2L, TimeUnit.DAYS);
+
         Date now = new Date();
         //进入房间的是主讲人
         if (roomInfo.getSpeakerId().equals(userId)) {
             roomInfo.setSpeakerState(0);
             roomInfo.setJoinRoomTime(now);
-            roomInfoCache.set(roomInfo, 2L, TimeUnit.DAYS);
-            return;
+            roomInfoCache.set(roomInfo);
+            return roomInfo;
         }
-        //进入房间的是学生 记录用户对应的当前房间uid
-        redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid);
+
         //房间累计用户信息-指只要进入到该房间的用户都要记录
         RMap<Long, RoomUserInfoCache> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
         //判断是否第一次进房间
@@ -322,10 +366,11 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
             userInfo.setUserName(sysUser.getRealName());
             userInfo.setFirstJoinTime(now);
         }
-        userInfo.setState(0);//0 进入/在房间
+        userInfo.setState(0);//0:在房间 1:不在房间
         userInfo.setDynamicJoinTime(now);
         roomTotalUser.fastPut(userId, userInfo);
         log.info("joinRoom>>>> userInfo: {}", JSONObject.toJSONString(userInfo));
+        return roomInfo;
     }
 
     /**
@@ -354,10 +399,10 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
      * @param chatroomId 要查询的聊天室 ID(必传)
      * @param userId     要查询的用户 ID(必传)
      * @return true 在聊天室,false 不在聊天室
-     * <p>有可能出现已退出聊天室后使用该功能查询,得到的结果是未退出聊天室
+     * <p>注意:有可能出现已退出聊天室后使用该功能查询,得到的结果是未退出聊天室
      * <p>触发融云退出聊天室机制:
-     * <p>1.聊天室中用户在离线 30 秒后有新消息产生时或离线后聊天室中产生 30 条消息时会被自动退出聊天室
-     * <p>2.此状态需要聊天室中有新消息时才会进行同步
+     * <p>1.聊天室中用户在离线 30 秒后有新消息产生时状态改变为退出聊天室
+     * <p>2.离线后聊天室中产生 30 条消息时状态时状态改变为退出聊天室
      */
     private boolean userExistInRoom(String chatroomId, String userId) {
         log.info("userExistInRoom chatroomId : {}  userId : {}", chatroomId, userId);
@@ -403,11 +448,40 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     }
 
     private List<RoomUserInfoCache> queryTotalRoomUserInfo(String roomUid) {
-        RMap<Integer, RoomUserInfoCache> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
+        RMap<Long, RoomUserInfoCache> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
         return roomTotalUser.values().stream()
                 .filter(Objects::nonNull)
                 .collect(Collectors.toList());
     }
 
+    /**
+     * 获取房间点赞数
+     *
+     * @param roomUid 房间UId
+     * @return 点赞数
+     */
+    private int getLike(String roomUid) {
+        //点赞数
+        Object like = redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomUid)).get();
+        if (Objects.isNull(like)) {
+            return 0;
+        }
+        return (int) like;
+    }
+
+    /**
+     * 获取房间当前观看人数
+     *
+     * @param roomUid 房间uid
+     * @return 当前观看人数
+     */
+    private int getLooker(String roomUid) {
+        List<RoomUserInfoCache> roomUserInfoCaches = queryRoomUserInfo(roomUid);
+        if (CollectionUtils.isEmpty(roomUserInfoCaches)) {
+            return 0;
+        }
+        return roomUserInfoCaches.size();
+    }
+
 }
 

+ 2 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/support/DistributedLock.java

@@ -80,7 +80,7 @@ public class DistributedLock {
      * @param callable 任务
      * @param timeout  超时时间
      * @param unit     超时时间单位
-     * @return true 锁成功  false 锁失败
+     * @return Future 异步任务
      */
     public <T> Future<T> callIfLockCanGet(final String lockName, Callable<T> callable, final long timeout, TimeUnit unit) {
         RLock lock = redissonClient.getLock(lockName);
@@ -107,7 +107,7 @@ public class DistributedLock {
     /**
      * 解锁
      */
-    private void unlock(RLock lock) {
+    public void unlock(RLock lock) {
         if (lock.getHoldCount() != 0) {
             lock.unlock();
         }

+ 194 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/RoomVo.java

@@ -0,0 +1,194 @@
+package com.yonge.cooleshow.biz.dal.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author hgw
+ * Created by 2022-03-28
+ */
+@ApiModel(value = "房间信息返回", description = "房间信息返回")
+public class RoomVo implements Serializable {
+
+    @ApiModelProperty(value = "课程组id")
+    private Long courseGroupId;
+
+    @ApiModelProperty(value = "课程id")
+    private Long courseId;
+
+    @ApiModelProperty(value = "声部")
+    private Long subjectId;
+
+    @ApiModelProperty(value = "房间编号")
+    private String roomUid;
+
+    @ApiModelProperty(value = "房间标题/最多12个字")
+    private String roomTitle;
+
+    @ApiModelProperty(value = "直播内容/最多200个字")
+    private String liveRemark;
+
+    @ApiModelProperty(value = "主讲人id/老师id")
+    private Integer speakerId;
+
+    @ApiModelProperty(value = "主讲人名称")
+    private String speakerName;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "直播开始时间")
+    private Date liveStartTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "直播开始时间")
+    private Date liveEndTime;
+
+    @ApiModelProperty(value = "直播状态 0未开始 1已开始 2已结束")
+    private Integer liveState;
+
+    @ApiModelProperty(value = "房间状态 0正常 1已删除 2已销毁")
+    private Integer roomState;
+
+    @ApiModelProperty(value = "房间类型 live直播课  temp临时直播间")
+    private String type;
+
+    @ApiModelProperty(value = "封面图片")
+    private String coverPic;
+
+    @ApiModelProperty(value = "点赞数")
+    private Integer likeNum;
+
+    @ApiModelProperty(value = "当前观看人数")
+    private Integer lookNum;
+
+    public Long getCourseGroupId() {
+        return courseGroupId;
+    }
+
+    public void setCourseGroupId(Long courseGroupId) {
+        this.courseGroupId = courseGroupId;
+    }
+
+    public Long getCourseId() {
+        return courseId;
+    }
+
+    public void setCourseId(Long courseId) {
+        this.courseId = courseId;
+    }
+
+    public Long getSubjectId() {
+        return subjectId;
+    }
+
+    public void setSubjectId(Long subjectId) {
+        this.subjectId = subjectId;
+    }
+
+    public String getRoomUid() {
+        return roomUid;
+    }
+
+    public void setRoomUid(String roomUid) {
+        this.roomUid = roomUid;
+    }
+
+    public String getRoomTitle() {
+        return roomTitle;
+    }
+
+    public void setRoomTitle(String roomTitle) {
+        this.roomTitle = roomTitle;
+    }
+
+    public String getLiveRemark() {
+        return liveRemark;
+    }
+
+    public void setLiveRemark(String liveRemark) {
+        this.liveRemark = liveRemark;
+    }
+
+    public Integer getSpeakerId() {
+        return speakerId;
+    }
+
+    public void setSpeakerId(Integer speakerId) {
+        this.speakerId = speakerId;
+    }
+
+    public String getSpeakerName() {
+        return speakerName;
+    }
+
+    public void setSpeakerName(String speakerName) {
+        this.speakerName = speakerName;
+    }
+
+    public Date getLiveStartTime() {
+        return liveStartTime;
+    }
+
+    public void setLiveStartTime(Date liveStartTime) {
+        this.liveStartTime = liveStartTime;
+    }
+
+    public Date getLiveEndTime() {
+        return liveEndTime;
+    }
+
+    public void setLiveEndTime(Date liveEndTime) {
+        this.liveEndTime = liveEndTime;
+    }
+
+    public Integer getLiveState() {
+        return liveState;
+    }
+
+    public void setLiveState(Integer liveState) {
+        this.liveState = liveState;
+    }
+
+    public Integer getRoomState() {
+        return roomState;
+    }
+
+    public void setRoomState(Integer roomState) {
+        this.roomState = roomState;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getCoverPic() {
+        return coverPic;
+    }
+
+    public void setCoverPic(String coverPic) {
+        this.coverPic = coverPic;
+    }
+
+    public Integer getLikeNum() {
+        return likeNum;
+    }
+
+    public void setLikeNum(Integer likeNum) {
+        this.likeNum = likeNum;
+    }
+
+    public Integer getLookNum() {
+        return lookNum;
+    }
+
+    public void setLookNum(Integer lookNum) {
+        this.lookNum = lookNum;
+    }
+}

+ 104 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/TeacherCourseVo.java

@@ -0,0 +1,104 @@
+package com.yonge.cooleshow.biz.dal.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author hgw
+ * Created by 2022-03-29
+ */
+public class TeacherCourseVo implements Serializable {
+
+    @ApiModelProperty(value = "课程组id")
+    private Long courseGroupId;
+
+    @ApiModelProperty(value = "名称")
+    private String courseGroupName;
+
+    @ApiModelProperty(value = "声部名称")
+    private String subjectName;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "开始时间")
+    private Date startTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "结束时间")
+    private Date endTime;
+
+    @ApiModelProperty(value = "课程状态 NOT_START未开始 ING进行中 COMPLETE已完成 CANCEL已取消")
+    private String status;
+
+    @ApiModelProperty(value = "课程人数")
+    private Integer studentCount;
+
+    @ApiModelProperty(value = "课程图片")
+    private String backgroundPic;
+
+    public Long getCourseGroupId() {
+        return courseGroupId;
+    }
+
+    public void setCourseGroupId(Long courseGroupId) {
+        this.courseGroupId = courseGroupId;
+    }
+
+    public String getCourseGroupName() {
+        return courseGroupName;
+    }
+
+    public void setCourseGroupName(String courseGroupName) {
+        this.courseGroupName = courseGroupName;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public Integer getStudentCount() {
+        return studentCount;
+    }
+
+    public void setStudentCount(Integer studentCount) {
+        this.studentCount = studentCount;
+    }
+
+    public String getBackgroundPic() {
+        return backgroundPic;
+    }
+
+    public void setBackgroundPic(String backgroundPic) {
+        this.backgroundPic = backgroundPic;
+    }
+}

+ 61 - 3
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml

@@ -5,6 +5,7 @@
         <id column="id_" jdbcType="INTEGER" property="id"/>
         <result column="course_group_id_" jdbcType="INTEGER" property="courseGroupId"/>
         <result column="type_" jdbcType="VARCHAR" property="type"/>
+        <result column="status_" jdbcType="VARCHAR" property="status"/>
         <result column="class_num_" jdbcType="INTEGER" property="classNum"/>
         <result column="teacher_id_" jdbcType="INTEGER" property="teacherId"/>
         <result column="class_date_" jdbcType="TIMESTAMP" property="classDate"/>
@@ -22,17 +23,17 @@
 
     <sql id="Base_Column_List">
         id_
-        , course_group_id_, type_, class_num_, teacher_id_, class_date_, start_time_, end_time_, lock_, lock_time_, pre_student_num_, ex_student_num_, created_by_, created_time_, updated_by_, updated_time_
+        , course_group_id_, type_, status_,class_num_, teacher_id_, class_date_, start_time_, end_time_, lock_, lock_time_, pre_student_num_, ex_student_num_, created_by_, created_time_, updated_by_, updated_time_
     </sql>
 
     <insert id="insertBatch" keyColumn="id_" keyProperty="id" useGeneratedKeys="true"
             parameterType="com.yonge.cooleshow.biz.dal.entity.CourseSchedule">
-        insert into course_schedule(course_group_id_, type_, class_num_, teacher_id_, class_date_, start_time_,
+        insert into course_schedule(course_group_id_, type_, status_,class_num_, teacher_id_, class_date_, start_time_,
         end_time_, lock_, lock_time_, pre_student_num_, ex_student_num_, created_by_, created_time_, updated_by_,
         updated_time_)
         values
         <foreach collection="entities" item="entity" separator=",">
-            (#{entity.courseGroupId}, #{entity.type}, #{entity.classNum}, #{entity.teacherId}, #{entity.classDate},
+            (#{entity.courseGroupId}, #{entity.type}, #{entity.status},#{entity.classNum}, #{entity.teacherId}, #{entity.classDate},
             #{entity.startTime}, #{entity.endTime}, #{entity.lock}, #{entity.lockTime}, #{entity.preStudentNum},
             #{entity.exStudentNum}, #{entity.createdBy}, #{entity.createdTime}, #{entity.updatedBy},
             #{entity.updatedTime})
@@ -71,4 +72,61 @@
         where a.lock_ = 0 and a.type_ = 'PRACTICE'
         group by b.user_id_
     </select>
+
+    <select id="queryStudentCourse" resultMap="BaseResultMap">
+        select b.id_,
+               b.course_group_id_,
+               b.type_,
+               b.class_num_,
+               b.teacher_id_,
+               b.class_date_,
+               b.start_time_,
+               b.end_time_,
+               b.lock_,
+               b.lock_time_,
+               b.pre_student_num_,
+               b.ex_student_num_,
+               b.status_,
+               b.created_by_,
+               b.created_time_,
+               b.updated_by_,
+               b.updated_time_
+        from course_schedule_student_payment as a
+                 left join course_schedule as b on a.course_id_ = b.id_
+        where b.start_time_ > now()
+          and b.class_date_ = #{classDate}
+          and b.status_ = 'NOT_START'
+          and a.user_id_ = #{studentId}
+        order by b.start_time_ desc
+    </select>
+
+
+    <select id="queryTeacherCourse" resultType="com.yonge.cooleshow.biz.dal.vo.TeacherCourseVo">
+        select
+               b.id_  as courseGroupId,
+               b.name_             as courseGroupName,
+               s.name_             as subjectName,
+               a.start_time_ as startTime,
+               a.end_time_ as endTime,
+               a.status_           as `status`,
+               a.pre_student_num_  as studentCount,
+               b.background_pic_   as backgroundPic
+        from course_schedule as a
+                 left join course_group as b on a.course_group_id_ = b.id_
+                 left join subject as s on b.subject_id_ = s.id_
+        where b.teacher_id_ = #{param.teacherId}
+          and a.lock_ = 0
+          and a.status_ = #{param.status}
+          and a.type_ = #{param.type}
+        <![CDATA[
+          AND a.class_date_  >= #{param.startDate}
+          AND a.class_date_  <= #{param.endDate}
+            # ]]>
+        <if test="param.subjectId != null">
+            AND b.subject_id_ = #{param.subjectId}
+        </if>
+
+    </select>
+
+
 </mapper>

+ 23 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/CourseScheduleController.java

@@ -2,12 +2,21 @@ package com.yonge.cooleshow.teacher.controller;
 
 
 import com.yonge.cooleshow.biz.dal.service.CourseScheduleService;
+import com.yonge.cooleshow.biz.dal.vo.TeacherCourseVo;
 import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.common.page.PageInfo;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
+import java.util.Map;
 
 /**
  * 老师课程表(CourseSchedule)表控制层
@@ -25,5 +34,19 @@ public class CourseScheduleController extends BaseController {
     @Resource
     private CourseScheduleService courseScheduleService;
 
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "year", dataType = "Integer", value = "年"),
+            @ApiImplicitParam(name = "month", dataType = "Integer", value = "月"),
+            @ApiImplicitParam(name = "status", dataType = "String", value = "课程状态 NOT_START未开始 ING进行中 COMPLETE已完成"),
+            @ApiImplicitParam(name = "subjectId", dataType = "Long", value = "声部id"),
+            @ApiImplicitParam(name = "page", dataType = "Integer", value = "页数"),
+            @ApiImplicitParam(name = "rows", dataType = "Integer", value = "每页数量"),
+    })
+    @ApiOperation("老师端-首页-我的课程-直播课")
+    @PostMapping("/queryTeacherLiveCourse")
+    public HttpResponseResult<PageInfo<TeacherCourseVo>> queryTeacherLiveCourse(@RequestBody Map<String, Object> param) {
+        return succeed(courseScheduleService.queryTeacherLiveCourse(param));
+    }
+
 }
 

+ 16 - 7
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/LiveRoomController.java

@@ -1,7 +1,9 @@
 package com.yonge.cooleshow.teacher.controller;
 
 
+import com.yonge.cooleshow.biz.dal.entity.RoomInfoCache;
 import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
+import com.yonge.cooleshow.biz.dal.vo.RoomVo;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import io.swagger.annotations.Api;
@@ -29,23 +31,30 @@ public class LiveRoomController extends BaseController {
     @Resource
     private LiveRoomService liveRoomService;
 
+    /**
+     * 根据房间uid查询房间信息
+     *
+     * @param roomUid 房间uid
+     */
+    @GetMapping("queryRoomInfo")
+    public HttpResponseResult<RoomVo> queryRoomInfo(@RequestParam("roomUid") String roomUid) {
+        return succeed(liveRoomService.queryRoomInfo(roomUid));
+    }
+
     @ApiImplicitParams({
             @ApiImplicitParam(name = "roomTitle", dataType = "String", value = "房间标题"),
             @ApiImplicitParam(name = "liveRemark", dataType = "String", value = "直播内容/最多200个字"),
-            @ApiImplicitParam(name = "coverPic", dataType = "String", value = "封面图片"),
     })
     @ApiOperation("创建临时房间-直播间")
     @PostMapping("/createTempLiveRoom")
-    public HttpResponseResult<Object> createTempLiveRoom(@RequestBody Map<String, Object> param) {
-        liveRoomService.createTempLiveRoom(param);
-        return succeed();
+    public HttpResponseResult<String> createTempLiveRoom(@RequestBody Map<String, Object> param) {
+        return succeed(liveRoomService.createTempLiveRoom(param));
     }
 
     @ApiOperation("进入房间")
     @GetMapping(value = "/joinRoom")
-    public HttpResponseResult<Object> joinRoom(String roomUid, Long userId) {
-        liveRoomService.joinRoom(roomUid, userId);
-        return succeed();
+    public HttpResponseResult<RoomInfoCache> joinRoom(String roomUid, Long userId) {
+        return succeed(liveRoomService.joinRoom(roomUid, userId));
     }
 
     @ApiOperation("定时任务-创建房间-直播间")