Переглянути джерело

Merge remote-tracking branch 'origin/master'

weifanli 3 роки тому
батько
коміт
245f10f739
13 змінених файлів з 396 додано та 112 видалено
  1. 56 14
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/RoomInfoCache.java
  2. 83 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/RoomUserInfoCache.java
  3. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImGroupService.java
  4. 7 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/LiveRoomService.java
  5. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImGroupServiceImpl.java
  6. 203 68
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/LiveRoomServiceImpl.java
  7. 9 8
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/support/IMHelper.java
  8. 4 4
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/ImGroupController.java
  9. 3 3
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/ImGroupMemberController.java
  10. 3 3
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/ImUserFriendController.java
  11. 4 4
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/ImGroupController.java
  12. 19 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/ImGroupMemberController.java
  13. 3 3
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/ImUserFriendController.java

+ 56 - 14
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/RoomSpeakerInfo.java → cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/RoomInfoCache.java

@@ -1,32 +1,50 @@
 package com.yonge.cooleshow.biz.dal.entity;
 
 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-22
+ * Created by 2022年3月24日
  */
-public class RoomSpeakerInfo implements Serializable {
-    //主讲人id
+public class RoomInfoCache implements Serializable {
+    @ApiModelProperty(value = "主讲人id")
     private Long speakerId;
-    //主讲人名称
+
+    @ApiModelProperty(value = "主讲人名称")
     private String speakerName;
-    //直播状态 0在房间 1不在房间
-    private Integer state;
-    //房间uid
+
+    @ApiModelProperty(value = "主讲人 0在房间 1不在房间")
+    private Integer speakerState;
+
+    @ApiModelProperty(value = "房间uid")
     private String roomUid;
-    //房间创建时间
+
+    @ApiModelProperty(value = "直播开始时间")
+    private Date liveStartTime;
+
+    @ApiModelProperty(value = "直播结束时间")
+    private Date liveEndTime;
+
+    @ApiModelProperty(value = "房间创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date createRoomTime;
-    //进入房间时间
+
+    @ApiModelProperty(value = "结束时间后最多延迟分钟数")
+    private Integer expiredMinute;
+
+    @ApiModelProperty(value = "主讲人进入房间时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date joinRoomTime;
-    //退出房间时间
+
+    @ApiModelProperty(value = "主讲人退出房间时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date exitRoomTime;
 
+    @ApiModelProperty(value = "房间类型 RoomTypeEnum")
     private String roomType;
 
     public Long getSpeakerId() {
@@ -45,12 +63,12 @@ public class RoomSpeakerInfo implements Serializable {
         this.speakerName = speakerName;
     }
 
-    public Integer getState() {
-        return state;
+    public Integer getSpeakerState() {
+        return speakerState;
     }
 
-    public void setState(Integer state) {
-        this.state = state;
+    public void setSpeakerState(Integer speakerState) {
+        this.speakerState = speakerState;
     }
 
     public String getRoomUid() {
@@ -61,6 +79,22 @@ public class RoomSpeakerInfo implements Serializable {
         this.roomUid = roomUid;
     }
 
+    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 Date getCreateRoomTime() {
         return createRoomTime;
     }
@@ -69,6 +103,14 @@ public class RoomSpeakerInfo implements Serializable {
         this.createRoomTime = createRoomTime;
     }
 
+    public Integer getExpiredMinute() {
+        return expiredMinute;
+    }
+
+    public void setExpiredMinute(Integer expiredMinute) {
+        this.expiredMinute = expiredMinute;
+    }
+
     public Date getJoinRoomTime() {
         return joinRoomTime;
     }

+ 83 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/RoomUserInfoCache.java

@@ -0,0 +1,83 @@
+package com.yonge.cooleshow.biz.dal.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author hgw
+ * Created by 2022年3月24日
+ */
+public class RoomUserInfoCache implements Serializable {
+
+    @ApiModelProperty(value = "用户id")
+    private Long userId;
+
+    @ApiModelProperty(value = "用户名称")
+    private String userName;
+
+    @ApiModelProperty(value = "首次进入时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date firstJoinTime;
+
+    @ApiModelProperty(value = "动态进入房间时间  多次进入房间每次进入更新")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date dynamicJoinTime;
+
+    @ApiModelProperty(value = "最后一次退出时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date lastOutTime;
+
+    @ApiModelProperty(value = "0:在房间 1:不在房间")
+    private Integer state;
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public Date getFirstJoinTime() {
+        return firstJoinTime;
+    }
+
+    public void setFirstJoinTime(Date firstJoinTime) {
+        this.firstJoinTime = firstJoinTime;
+    }
+
+    public Date getDynamicJoinTime() {
+        return dynamicJoinTime;
+    }
+
+    public void setDynamicJoinTime(Date dynamicJoinTime) {
+        this.dynamicJoinTime = dynamicJoinTime;
+    }
+
+    public Date getLastOutTime() {
+        return lastOutTime;
+    }
+
+    public void setLastOutTime(Date lastOutTime) {
+        this.lastOutTime = lastOutTime;
+    }
+
+    public Integer getState() {
+        return state;
+    }
+
+    public void setState(Integer state) {
+        this.state = state;
+    }
+}

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImGroupService.java

@@ -51,6 +51,6 @@ public interface ImGroupService extends IService<ImGroup> {
     */
     void syncGroupMemberNum(Long groupId) throws Exception;
 
-    List<ImGroup> queryPage(Map<String, Object> params);
+    List<ImGroup> queryAll(Map<String, Object> params);
 }
 

+ 7 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/LiveRoomService.java

@@ -2,10 +2,10 @@ 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.IMApiResultInfo;
-import com.yonge.cooleshow.biz.dal.entity.ImRoomMessage;
 import com.yonge.cooleshow.biz.dal.entity.LiveRoom;
-import com.yonge.cooleshow.biz.dal.entity.RecordNotify;
+import com.yonge.cooleshow.biz.dal.entity.RoomUserInfoCache;
+
+import java.util.List;
 
 /**
  * 直播房间与课程的关系表表(LiveRoom)表服务接口
@@ -17,9 +17,13 @@ public interface LiveRoomService extends IService<LiveRoom> {
 
     LiveRoomDao getDao();
 
+    void createCourseLiveRoom();
+
     void createTempLiveRoom(LiveRoom room);
 
+    void joinRoom(String roomUid, Long userId);
 
+    List<RoomUserInfoCache> queryRoomUserInfo(String roomUid);
 
 }
 

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImGroupServiceImpl.java

@@ -172,7 +172,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
     }
 
     @Override
-    public List<ImGroup> queryPage(Map<String, Object> params) {
+    public List<ImGroup> queryAll(Map<String, Object> params) {
         return baseMapper.findAll(params);
     }
 }

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

@@ -12,18 +12,28 @@ import com.yonge.cooleshow.biz.dal.enums.RoomTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.CourseGroupService;
 import com.yonge.cooleshow.biz.dal.service.CourseScheduleService;
 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.common.exception.BizException;
 import com.yonge.toolset.utils.date.DateUtil;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.api.RBucket;
+import org.redisson.api.RMap;
 import org.redisson.api.RedissonClient;
 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 java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
+import java.util.stream.Collectors;
+
+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;
 
 /**
  * 直播房间与课程的关系表表(LiveRoom)表服务实现类
@@ -45,22 +55,25 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     private CourseGroupService courseGroupService;
     @Autowired
     private CourseScheduleService courseScheduleService;
+    @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 = COOLESHOW + ":LIVE_ROOM_TOTAL_USER_LIST:" + ROOM_UID;
-    //主讲人信息
-    public static final String LIVE_SPEAKER_INFO = COOLESHOW + ":LIVE_SPEAKER_INFO:" + USER_ID;
-    //用户对应的直播间Uid
+    //用户当前对应的直播间Uid
     public static final String LIVE_USER_ROOM = COOLESHOW + ":LIVE_ROOM_USER:" + USER_ID;
     //房间点赞数
     public static final String LIVE_ROOM_LIKE = COOLESHOW + ":LIVE_ROOM_LIKE:" + ROOM_UID;
     //生成房间UID
     public static Function<Long, String> GenRoomUid = (userId) -> COOLESHOW + "-" + userId + "-" + new Date().getTime();
+    //房间的信息
+    public static final String LIVE_ROOM_INFO = COOLESHOW + ":LIVE_ROOM_INFO:" + ROOM_UID;
 
     @Override
     public LiveRoomDao getDao() {
@@ -68,12 +81,29 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     }
 
     /**
+     * 根据课程id查询直播间信息
+     */
+    public void getLiveRoomByCourseId(Long courseId) {
+        CourseSchedule course = courseScheduleService.getById(courseId);
+        if (Objects.isNull(course)) {
+            throw new BizException("该课程没有直播间");
+        }
+    }
+
+    /**
      * 定时任务创建直播间
      */
-    public void createLiveRoom() {
+    @Override
+    public void createCourseLiveRoom() {
         Date now = new Date();
-        Date endTime = DateUtil.addMinutes(now, 30);
-        //查询课时表生成直播间 这里错了
+        //查询房间提前创建的时间
+        String preCreateRoomMinute = sysConfigService.findConfigValue(PRE_CREATE_LIVE_ROOM_MINUTE);
+        if (StringUtils.isEmpty(preCreateRoomMinute)) {
+            log.info("roomDestroy>>>> 未查询到配置:{}", PRE_CREATE_LIVE_ROOM_MINUTE);
+            return;
+        }
+        Date endTime = DateUtil.addMinutes(now, Integer.parseInt(preCreateRoomMinute));
+        //查询课时表生成直播间
         List<CourseSchedule> courseScheduleList = courseScheduleService.list(new QueryWrapper<CourseSchedule>().lambda()
                 .eq(CourseSchedule::getType, CourseScheduleTypeEnum.LIVE.getCode())
                 .eq(CourseSchedule::getLock, 0)
@@ -82,11 +112,20 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         if (CollectionUtils.isEmpty(courseScheduleList)) {
             return;
         }
+        //获取课程组名称
+        Map<Long, String> titleMap = courseScheduleList.stream()
+                .map(CourseSchedule::getCourseGroupId)
+                .distinct()
+                .map(courseGroupService::getById)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toMap(CourseGroup::getId, CourseGroup::getName));
+        //生成课程对应的房间
         courseScheduleList.forEach(c -> {
             LiveRoom room = new LiveRoom();
             room.setCourseGroupId(c.getCourseGroupId());
             room.setCourseId(c.getId());
             room.setRoomUid(GenRoomUid.apply(c.getTeacherId()));
+            room.setRoomTitle(titleMap.get(c.getCourseGroupId()));
             room.setSpeakerId(c.getTeacherId());
             room.setLiveStartTime(c.getStartTime());
             room.setLiveEndTime(c.getEndTime());
@@ -96,11 +135,16 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
             room.setCreatedBy(-2L);
             room.setCreatedTime(now);
             this.save(room);
-            //生成主讲人信息
-            createSpeakerInfo(room);
-            //
-            //去融云创建房间
-            createLiveRoom(room.getRoomUid(), room.getRoomTitle());
+            try {
+                //生成主讲人信息
+                createRoomInfoCache(room);
+                //去融云创建房间
+                createLiveRoom(room.getRoomUid(), room.getRoomTitle());
+            } catch (Exception e) {
+                //为什么要删除,因为如果融云创建失败,那么就不会有房间了,需要删除
+                this.removeById(room.getId());
+                log.error("创建直播间失败", e.getCause());
+            }
         });
 
     }
@@ -108,52 +152,51 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     /**
      * 创建临时房间-直播间
      */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
     public void createTempLiveRoom(LiveRoom room) {
-        log.info("createLiveRoom>>>>>>roomUid:{}", room.getRoomUid());
-        try {
+        //查询主讲人信息
+        SysUser sysUser = getSysUser();
 
-            //临时课程没有课程组和课表
-            if (room.getType().equals(RoomTypeEnum.TEMP.getCode())) {
-                room.setCourseGroupId(0L);
-                room.setCourseId(0L);
-            }
-            //查询主讲人信息
-            SysUser sysUser = getSysUser();
-            if (Objects.isNull(sysUser)) {
-                return;
-            }
-            room.setRoomUid(GenRoomUid.apply(sysUser.getId()));
-            this.save(room);
-            //生成主讲人信息到缓存
-            createSpeakerInfo(room, sysUser);
-            //去融云创建房间
-            createLiveRoom(room.getRoomUid(), room.getRoomTitle());
-        } catch (Exception e) {
-            log.error(">>>>>>>>>> createLiveRoom error roomUid:{} msg:{}", room.getRoomUid(), e.getMessage());
-        }
+        room.setCourseGroupId(0L);
+        room.setCourseId(0L);
+        room.setType(RoomTypeEnum.TEMP.getCode());
+        room.setRoomUid(GenRoomUid.apply(sysUser.getId()));
+        this.save(room);
+        log.info("createTempLiveRoom>>>>>>room:{}", room.getRoomUid());
+        //生成主讲人信息到缓存
+        createRoomInfoCache(room, sysUser);
+        //去融云创建房间
+        createLiveRoom(room.getRoomUid(), room.getRoomTitle());
     }
 
     //生成主讲人信息
-    private void createSpeakerInfo(LiveRoom room) {
+    private void createRoomInfoCache(LiveRoom room) {
         //查询主讲人信息
         SysUser sysUser = getSysUser(room.getSpeakerId());
-        if (Objects.isNull(sysUser)) {
-            return;
-        }
-        createSpeakerInfo(room, sysUser);
+        createRoomInfoCache(room, sysUser);
     }
 
-    private void createSpeakerInfo(LiveRoom room, SysUser sysUser) {
-        RoomSpeakerInfo speakerInfo = new RoomSpeakerInfo();
-        speakerInfo.setSpeakerId(sysUser.getId());
-        speakerInfo.setSpeakerName(sysUser.getRealName());
-        speakerInfo.setCreateRoomTime(new Date());
-        speakerInfo.setRoomUid(room.getRoomUid());
-        speakerInfo.setRoomType(room.getType());
-        //写入主讲人信息
-        redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, room.getSpeakerId().toString())).set(speakerInfo);
+    //生成主讲人信息
+    private void createRoomInfoCache(LiveRoom room, SysUser sysUser) {
+        RoomInfoCache roomCache = new RoomInfoCache();
+        roomCache.setSpeakerId(sysUser.getId());
+        roomCache.setSpeakerName(sysUser.getRealName());
+        roomCache.setSpeakerState(1);
+        roomCache.setRoomUid(room.getRoomUid());
+        roomCache.setLiveStartTime(room.getLiveStartTime());
+        roomCache.setLiveEndTime(room.getLiveEndTime());
+        roomCache.setCreateRoomTime(new Date());
+        String configValue = sysConfigService.findConfigValue(PRE_CREATE_LIVE_ROOM_MINUTE);
+        roomCache.setExpiredMinute(Integer.parseInt(configValue));
+        roomCache.setRoomType(room.getType());
+
+        //写入房间信息
+        redissonClient.getBucket(LIVE_ROOM_INFO.replace(ROOM_UID, room.getRoomUid()))
+                .set(roomCache, 2L, TimeUnit.DAYS);
         //生成0点赞
-        redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, room.getRoomUid())).set(0);
+        redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, room.getRoomUid()))
+                .set(0, 2L, TimeUnit.DAYS);
     }
 
     /**
@@ -162,20 +205,45 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
      * @param roomId   房间Uid
      * @param roomName 房间名称
      */
-    private IMApiResultInfo createLiveRoom(String roomId, String roomName) {
+    private void createLiveRoom(String roomId, String roomName) {
         IMApiResultInfo resultInfo;
         try {
             resultInfo = imHelper.createChatRoom(roomId, roomName);
         } catch (Exception e) {
-            log.error("create chatRoom error >>>", e.getCause());
-            throw new RuntimeException("创建聊天室失败!");
+            throw new BizException("创建聊天室失败!" + e.getMessage());
         }
         if (!resultInfo.isSuccess()) {
-            log.error("create chatRoom error: {}", resultInfo.getErrorMessage());
-            throw new RuntimeException("创建聊天室失败!");
+            throw new BizException("创建聊天室失败!" + resultInfo.getErrorMessage());
         }
         log.info("create chatRoom success: {}", roomId);
-        return resultInfo;
+    }
+
+    /**
+     * 定时任务-清理过期的房间
+     */
+    public void destroyExpiredLiveRoom() {
+        //查询房间过期时间
+        String expiredMinuteStr = sysConfigService.findConfigValue(DESTROY_EXPIRED_LIVE_ROOM_MINUTE);
+        if (StringUtils.isEmpty(expiredMinuteStr)) {
+            log.info("roomDestroy>>>> 未查询到配置:{}", DESTROY_EXPIRED_LIVE_ROOM_MINUTE);
+            return;
+        }
+        Date now = new Date();
+        //查询已经开始并且没有删除及销毁的直播间
+        List<LiveRoom> list = this.list(new QueryWrapper<LiveRoom>().lambda()
+                .eq(LiveRoom::getType, RoomTypeEnum.LIVE.getCode())
+                .ge(LiveRoom::getLiveEndTime, now));
+        if (CollectionUtils.isEmpty(list)) {
+            return;
+        }
+        list.forEach(room -> {
+            Date expiredDate = DateUtil.addMinutes(room.getLiveEndTime(), Integer.parseInt(expiredMinuteStr));
+            //当前时间 大于(结束播时间 + 设置的过期分钟数)
+            if (now.getTime() >= expiredDate.getTime()) {
+                //删除房间
+                destroyLiveRoom(room.getRoomUid());
+            }
+        });
     }
 
     /**
@@ -183,7 +251,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
      *
      * @param roomId 房间Uid
      */
-    private IMApiResultInfo destroyLiveRoom(String roomId) {
+    private void destroyLiveRoom(String roomId) {
         //删除服务器房间
         List<String> deleteRoomIds = new ArrayList<String>() {{
             add(roomId);
@@ -192,13 +260,58 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         try {
             resultInfo = imHelper.deleteChrm(deleteRoomIds);
         } catch (Exception e) {
-            throw new RuntimeException("关闭聊天室失败!");
+            throw new BizException("关闭聊天室失败!" + e.getMessage());
         }
         if (!resultInfo.isSuccess()) {
-            log.error("destroy chatRoom error: {}", resultInfo.getErrorMessage());
-            throw new RuntimeException("关闭聊天室失败!");
+            throw new BizException("关闭聊天室失败!" + resultInfo.getErrorMessage());
         }
-        return resultInfo;
+        log.info("destroyLiveRoom success: {}", roomId);
+    }
+
+    /**
+     * 进入房间
+     *
+     * @param roomUid 房间uid
+     * @param userId  用户id 主讲人或者用户的id
+     */
+    public void 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 (roomInfo.getSpeakerId().equals(userId)) {
+            roomInfo.setSpeakerState(0);
+            roomInfo.setJoinRoomTime(new Date());
+            roomInfoCache.set(roomInfo, 2L, TimeUnit.DAYS);
+            return;
+        }
+        //进入房间的是学生 记录用户对应的当前房间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));
+        //判断是否第一次进房间
+        RoomUserInfoCache userInfo;
+        Date now = new Date();
+        if (roomTotalUser.containsKey(userId)) {
+            //多次进入更新动态进入时间
+            userInfo = roomTotalUser.get(userId);
+        } else {
+            //第一次进该房间 写入用户首次进入时间
+            SysUser sysUser = getSysUser(userId);
+            userInfo = new RoomUserInfoCache();
+            userInfo.setUserId(sysUser.getId());
+            userInfo.setUserName(sysUser.getRealName());
+            userInfo.setFirstJoinTime(now);
+        }
+        userInfo.setState(0);//0 进入/在房间
+        userInfo.setDynamicJoinTime(now);
+        roomTotalUser.fastPut(userId, userInfo);
+        log.info("joinRoom>>>> userInfo: {}", JSONObject.toJSONString(userInfo));
     }
 
     /**
@@ -206,19 +319,19 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
      *
      * @param message
      */
-    private IMApiResultInfo publishRoomMessage(ImRoomMessage message) {
-        log.info("publishRoomMessage message : {}", JSONObject.toJSONString(message));
+    private void publishRoomMessage(ImRoomMessage message) {
+        String msgStr = JSONObject.toJSONString(message);
+        log.info("publishRoomMessage message : {}", msgStr);
         IMApiResultInfo resultInfo;
         try {
             resultInfo = imHelper.publishRoomMessage(message.getFromUserId(), message.getToChatroomId(), message);
         } catch (Exception e) {
-            throw new RuntimeException("消息发送失败" + e.getMessage());
+            throw new BizException("消息发送失败" + e.getMessage());
         }
         if (!resultInfo.isSuccess()) {
-            log.error("publishRoomMessage chatRoom error: {}", resultInfo.getErrorMessage());
-            throw new RuntimeException("消息发送失败!");
+            throw new BizException("消息发送失败!" + resultInfo.getErrorMessage());
         }
-        return resultInfo;
+        log.info("publishRoomMessage success: {}", msgStr);
     }
 
     /**
@@ -238,16 +351,15 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         try {
             resultInfo = imHelper.isInChartRoom(chatroomId, userId);
         } catch (Exception e) {
-            throw new RuntimeException("查询失败" + e.getMessage());
+            throw new BizException("查询失败" + e.getMessage());
         }
         if (!resultInfo.isSuccess()) {
             log.error("userExistInRoom  chatroomId : {}  userId : {}", chatroomId, userId);
-            throw new RuntimeException("查询失败!");
+            throw new BizException("查询失败!");
         }
         return resultInfo.isSuccess() && resultInfo.getInChrm();
     }
 
-
     private SysUser getSysUser(Long userId) {
         return Optional.ofNullable(userId)
                 .map(sysUserFeignService::queryUserById)
@@ -255,10 +367,33 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     }
 
     private SysUser getSysUser() {
-        //修改机构基础信息
         return Optional.ofNullable(sysUserFeignService.queryUserInfo())
                 .orElseThrow(() -> new BizException("用户不存在"));
     }
 
+    /**
+     * 查询在观看直播的用户信息
+     *
+     * @param roomUid 直播间uid
+     */
+    @Override
+    public List<RoomUserInfoCache> queryRoomUserInfo(String roomUid) {
+        List<RoomUserInfoCache> roomUserInfoVos = queryTotalRoomUserInfo(roomUid);
+        return queryRoomUserInfo(roomUserInfoVos);
+    }
+
+    private List<RoomUserInfoCache> queryRoomUserInfo(List<RoomUserInfoCache> totalUserInfo) {
+        return totalUserInfo.stream()
+                .filter(o -> Objects.nonNull(o.getState()) && o.getState() == 0)
+                .collect(Collectors.toList());
+    }
+
+    private List<RoomUserInfoCache> queryTotalRoomUserInfo(String roomUid) {
+        RMap<Integer, RoomUserInfoCache> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
+        return roomTotalUser.values().stream()
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+    }
+
 }
 

+ 9 - 8
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/support/IMHelper.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.yonge.cooleshow.biz.dal.entity.BaseMessage;
 import com.yonge.cooleshow.biz.dal.entity.IMApiResultInfo;
 import com.yonge.cooleshow.biz.dal.entity.IMTokenInfo;
+import com.yonge.cooleshow.common.exception.BizException;
 import io.rong.util.GsonUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
@@ -342,11 +343,11 @@ public class IMHelper {
      */
     public IMApiResultInfo createChatRoom(String chatRoomId, String chatRoomName) throws Exception {
         if (chatRoomId == null) {
-            throw new RuntimeException("房间Uid不能为空");
+            throw new BizException("房间Uid不能为空");
         }
 
         if (chatRoomName == null) {
-            throw new RuntimeException("房间名称不能为空");
+            throw new BizException("房间名称不能为空");
         }
 
         StringBuilder sb = new StringBuilder();
@@ -376,7 +377,7 @@ public class IMHelper {
     public IMApiResultInfo deleteChrm(List<String> chatroomIds)
             throws Exception {
         if (chatroomIds == null) {
-            throw new RuntimeException("房间Uid不能为空");
+            throw new BizException("房间Uid不能为空");
         }
         StringBuilder sb = new StringBuilder();
         for (String child : chatroomIds) {
@@ -408,13 +409,13 @@ public class IMHelper {
 
     public IMApiResultInfo publishRoomMessage(String fromUserId, String[] toChatroomIds, BaseMessage message) throws Exception {
         if (StringUtils.isBlank(fromUserId)) {
-            throw new RuntimeException("发送人不能为空");
+            throw new BizException("发送人不能为空");
         }
         if (Objects.isNull(toChatroomIds)) {
-            throw new RuntimeException("房间Uid不能为空");
+            throw new BizException("房间Uid不能为空");
         }
         if (Objects.isNull(message)) {
-            throw new RuntimeException("消息不能为空");
+            throw new BizException("消息不能为空");
         }
 
         StringBuilder sb = new StringBuilder();
@@ -449,10 +450,10 @@ public class IMHelper {
      */
     public IMApiResultInfo isInChartRoom(String chatroomId, String userId) throws Exception {
         if (chatroomId == null) {
-            throw new RuntimeException("房间Uid不能为空");
+            throw new BizException("房间Uid不能为空");
         }
         if (userId == null) {
-            throw new RuntimeException("用户不能为空");
+            throw new BizException("用户不能为空");
         }
         String body = "&chatroomId=" + URLEncoder.encode(chatroomId, UTF8) +
                 "&userId=" + URLEncoder.encode(userId, UTF8);

+ 4 - 4
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/ImGroupController.java

@@ -42,12 +42,12 @@ public class ImGroupController extends BaseController {
     @ApiImplicitParams({
             @ApiImplicitParam(name = "search", dataType = "String", value = "根据群名称、编号、简介模糊查询"),
     })
-    @ApiOperation("分页查询")
-    @PostMapping(value = "/queryPage")
-    public HttpResponseResult<List<ImGroup>> queryPage(@RequestBody Map<String,Object> params) throws Exception {
+    @ApiOperation("群列表")
+    @PostMapping(value = "/queryAll")
+    public HttpResponseResult<List<ImGroup>> queryAll(@RequestBody Map<String,Object> params) throws Exception {
         SysUser sysUser = sysUserFeignService.queryUserInfo();
         params.put("userId",sysUser.getId());
-        return succeed(imGroupService.queryPage(params));
+        return succeed(imGroupService.queryAll(params));
     }
 }
 

+ 3 - 3
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/ImGroupMemberController.java

@@ -55,9 +55,9 @@ public class ImGroupMemberController extends BaseController {
             @ApiImplicitParam(name = "search", dataType = "String", value = "根据用户编号、昵称模糊查询"),
             @ApiImplicitParam(name = "groupId", dataType = "Long", value = "群编号")
     })
-    @ApiOperation("分页查询")
-    @PostMapping(value = "/queryPage")
-    public HttpResponseResult<List<ImGroupMember>> queryPage(@RequestBody Map<String,Object> params) throws Exception {
+    @ApiOperation("获取群成员列表")
+    @PostMapping(value = "/queryAll")
+    public HttpResponseResult<List<ImGroupMember>> queryAll(@RequestBody Map<String,Object> params) throws Exception {
         if(Objects.isNull(params.get("search")) || Objects.isNull(params.get("groupId"))){
             throw new BizException("参数校验失败");
         }

+ 3 - 3
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/ImUserFriendController.java

@@ -36,9 +36,9 @@ public class ImUserFriendController extends BaseController {
     @ApiImplicitParams({
             @ApiImplicitParam(name = "search", dataType = "String", value = "根据用户编号、昵称模糊查询")
     })
-    @ApiOperation("分页查询")
-    @PostMapping(value = "/queryPage")
-    public HttpResponseResult<List<ImUserFriend>> queryPage(@RequestBody Map<String,Object> params) throws Exception {
+    @ApiOperation("获取通讯录成员列表")
+    @PostMapping(value = "/queryAll")
+    public HttpResponseResult<List<ImUserFriend>> queryAll(@RequestBody Map<String,Object> params) throws Exception {
         SysUser sysUser = sysUserFeignService.queryUserInfo();
         List<ImUserFriend> iPage = imUserFriendService.getBaseMapper().selectList(Wrappers.<ImUserFriend>query().lambda()
                 .or(e->e.eq(ImUserFriend::getFriendId, params.get("search"))

+ 4 - 4
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/ImGroupController.java

@@ -61,12 +61,12 @@ public class ImGroupController extends BaseController {
     @ApiImplicitParams({
             @ApiImplicitParam(name = "search", dataType = "String", value = "根据群名称、编号、简介模糊查询"),
     })
-    @ApiOperation("分页查询")
-    @PostMapping(value = "/queryPage")
-    public HttpResponseResult<List<ImGroup>> queryPage(@RequestBody Map<String,Object> params) throws Exception {
+    @ApiOperation("群列表")
+    @PostMapping(value = "/queryAll")
+    public HttpResponseResult<List<ImGroup>> queryAll(@RequestBody Map<String,Object> params) throws Exception {
         SysUser sysUser = sysUserFeignService.queryUserInfo();
         params.put("userId",sysUser.getId());
-        return succeed(imGroupService.queryPage(params));
+        return succeed(imGroupService.queryAll(params));
     }
 
     @ApiOperation("修改群信息")

+ 19 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/ImGroupMemberController.java

@@ -1,6 +1,7 @@
 package com.yonge.cooleshow.teacher.controller;
 
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.yonge.cooleshow.biz.dal.entity.ImGroupMember;
 import com.yonge.cooleshow.biz.dal.entity.ImUserFriend;
 import com.yonge.cooleshow.biz.dal.service.ImGroupMemberService;
@@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -48,5 +50,22 @@ public class ImGroupMemberController extends BaseController {
         }
         return succeed(imGroupMemberService.getUserDetail(params.get("userId"),params.get("groupId")));
     }
+
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "search", dataType = "String", value = "根据用户编号、昵称模糊查询"),
+            @ApiImplicitParam(name = "groupId", dataType = "Long", value = "群编号")
+    })
+    @ApiOperation("获取群成员列表")
+    @PostMapping(value = "/queryAll")
+    public HttpResponseResult<List<ImGroupMember>> queryAll(@RequestBody Map<String,Object> params) throws Exception {
+        if(Objects.isNull(params.get("search")) || Objects.isNull(params.get("groupId"))){
+            throw new BizException("参数校验失败");
+        }
+        List<ImGroupMember> iPage = imGroupMemberService.getBaseMapper().selectList(Wrappers.<ImGroupMember>query().lambda()
+                .or(e->e.eq(ImGroupMember::getUserId, params.get("search"))
+                        .like(ImGroupMember::getNickname, params.get("search")))
+                .eq(ImGroupMember::getGroupId,params.get("groupId")).orderByDesc(ImGroupMember::getId));
+        return succeed(iPage);
+    }
 }
 

+ 3 - 3
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/ImUserFriendController.java

@@ -43,9 +43,9 @@ public class ImUserFriendController extends BaseController {
     @ApiImplicitParams({
             @ApiImplicitParam(name = "search", dataType = "String", value = "根据用户编号、昵称模糊查询")
     })
-    @ApiOperation("分页查询")
-    @PostMapping(value = "/queryPage")
-    public HttpResponseResult<List<ImUserFriend>> queryPage(@RequestBody Map<String,Object> params) throws Exception {
+    @ApiOperation("获取通讯录成员列表")
+    @PostMapping(value = "/queryAll")
+    public HttpResponseResult<List<ImUserFriend>> queryAll(@RequestBody Map<String,Object> params) throws Exception {
         SysUser sysUser = sysUserFeignService.queryUserInfo();
         List<ImUserFriend> iPage = imUserFriendService.getBaseMapper().selectList(Wrappers.<ImUserFriend>query().lambda()
                 .or(e->e.eq(ImUserFriend::getFriendId, params.get("search"))