Browse Source

Merge branch 'feature/0803-im' of http://git.dayaedu.com/yonge/cooleshow into feature/0803-im

zouxuan 2 years ago
parent
commit
a942e2e059
15 changed files with 482 additions and 28 deletions
  1. 4 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/LiveRoom.java
  2. 57 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/redisson/RedissonMessageService.java
  3. 88 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/redisson/RedissonTopicListener.java
  4. 8 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseScheduleService.java
  5. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/LiveRoomService.java
  6. 45 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java
  7. 48 5
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/LiveRoomServiceImpl.java
  8. 39 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/course/CourseScheduleWrapper.java
  9. 4 12
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/liveroom/LiveRoomWrapper.java
  10. 32 5
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/ImGroupController.java
  11. 2 0
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/ImLiveBroadcastRoomController.java
  12. 58 0
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/UserController.java
  13. 34 3
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/ImGroupController.java
  14. 15 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherCourseScheduleController.java
  15. 47 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/UserController.java

+ 4 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/LiveRoom.java

@@ -117,6 +117,10 @@ public class LiveRoom implements Serializable {
     @ApiModelProperty(value = "封面图片")
     private String coverPic;
 
+    @TableField("shop_car_url_")
+    @ApiModelProperty(value = "购物车地址")
+    private String shopCarUrl;
+
     @TableField("created_by_")
     @ApiModelProperty(value = "创建人")
     private Long createdBy;

+ 57 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/redisson/RedissonMessageService.java

@@ -0,0 +1,57 @@
+package com.yonge.cooleshow.biz.dal.redisson;
+
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RTopic;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Redisson消息发布订阅服务
+ */
+@Slf4j
+@Service
+public class RedissonMessageService {
+
+    // 订阅消息通知
+    public static final String TOPIC_MESSAGE = "topic:message";
+    // 直播在线人数
+    public static final String LIVE_ROOM_MEMBER = "delayQueue:liveRoomMember:";
+    public static final String LIVE_ROOM_MEMBER_LOCK = "LOCK:liveRoomMember:";
+
+    private final RedissonClient redissonClient;
+
+    @Autowired
+    public RedissonMessageService(RedissonClient redissonClient) {
+
+        this.redissonClient = redissonClient;
+    }
+
+    /**
+     * 订阅消息
+     * @param topic 消息主题
+     * @param listener MessageListener
+     */
+    public void subscribe(String topic, MessageListener listener) {
+        RTopic messageTopic = redissonClient.getTopic(topic);
+        messageTopic.addListener(String.class, (channel, msg) -> listener.onMessage(msg));
+    }
+
+    /**
+     * 发布消息
+     * @param topic 消息主题
+     * @param message 消息内容
+     */
+    public void publish(String topic, String message) {
+        RTopic messageTopic = redissonClient.getTopic(topic);
+        messageTopic.publish(message);
+    }
+
+    /**
+     * 消息监听
+     */
+    public interface MessageListener {
+        void onMessage(String message);
+    }
+
+}

+ 88 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/redisson/RedissonTopicListener.java

@@ -0,0 +1,88 @@
+package com.yonge.cooleshow.biz.dal.redisson;
+
+import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
+import com.yonge.cooleshow.biz.dal.wrapper.liveroom.LiveRoomWrapper;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RBucket;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.core.Ordered;
+import org.springframework.stereotype.Service;
+
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Redisson消息发布订阅服务监听
+ */
+@Slf4j
+@Service
+public class RedissonTopicListener implements ApplicationRunner, Ordered {
+ 
+    @Autowired
+    private RedissonMessageService redissonMessageService;
+    @Autowired
+    private RedissonClient redissonClient;
+
+    @Autowired
+    private LiveRoomService liveRoomService;
+ 
+    @Override
+    public void run(ApplicationArguments args) {
+
+        if (Objects.nonNull(redissonMessageService)) {
+
+            redissonMessageService.subscribe(RedissonMessageService.TOPIC_MESSAGE, (message) -> {
+                log.info("RedissonMessageService subscribe message={}", message);
+                try {
+                    TimeUnit.SECONDS.sleep(1);
+                } catch (InterruptedException e) {
+                    log.error("RedissonMessageService subscribe sleep error", e);
+                }
+
+                RLock lock = redissonClient.getLock(RedissonMessageService.LIVE_ROOM_MEMBER_LOCK + message);
+                try {
+                    if (lock.tryLock()) {
+                        // 缓存JoinRoom用户信息到redis
+                        RBucket<Object> bucket = redissonClient.getBucket(RedissonMessageService.LIVE_ROOM_MEMBER + message);
+                        if (!bucket.isExists()) {
+                            return;
+                        }
+                        Integer times = (Integer) bucket.get();
+                        bucket.delete();
+
+                        LiveRoomWrapper.LiveRoomVo liveRoomVo = liveRoomService.queryRoomInfo(message);
+                        if (Objects.isNull(liveRoomVo)) {
+                            return;
+                        }
+                        try {
+                            liveRoomService.setGroupMemberDefinedData(liveRoomVo,liveRoomVo.getLookNum(),liveRoomVo.getTotalLookNum());
+                        } catch (Exception e) {
+                            log.error("RedissonMessageService subscribe setGroupMemberDefinedData error", e);
+                            if (times>=3) {
+                                return;
+                            }
+                            bucket.set(times +1, 30, TimeUnit.MINUTES);
+                        }
+                        redissonMessageService.publish(RedissonMessageService.TOPIC_MESSAGE, message);
+                    }
+                } finally {
+                    if (lock.getHoldCount() != 0 && lock.isHeldByCurrentThread()) {
+                        lock.unlock();
+                    }
+                }
+
+
+            });
+            log.info("---> RedissonMessageService subscribe success");
+        }
+    }
+
+    @Override
+    public int getOrder() {
+        return 1;
+    }
+}

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

@@ -12,6 +12,7 @@ import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
 import com.yonge.cooleshow.biz.dal.entity.TeacherSubjectPrice;
 import com.yonge.cooleshow.biz.dal.vo.*;
 import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
+import com.yonge.cooleshow.biz.dal.wrapper.course.CourseScheduleWrapper;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.base.page.PageInfo;
@@ -257,5 +258,12 @@ public interface CourseScheduleService extends IService<CourseSchedule> {
     PageInfo<CourseScheduleRecordVo> selectCourseList(Map<String, Object> param);
 
     IPage<PianoClassVo> queryPianoClass(IPage<PianoClassVo> page, MyCourseSearch search);
+
+    /**
+     * 获取课程直播时间
+     *
+     * @param roomUid 直播间uid
+     */
+    CourseScheduleWrapper.LiveRoomTime getLiveCourseScheduleTime(String roomUid);
 }
 

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

@@ -93,6 +93,7 @@ public interface LiveRoomService extends IService<LiveRoom> {
     void syncLike(String roomUid, Integer likeNum);
 
 
+    void setGroupMemberDefinedData(LiveRoomWrapper.LiveRoomVo  roomVo, Integer onlineUser, Integer totalUser);
     /**
      * 观看者-进入房间
      *

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

@@ -22,6 +22,8 @@ import com.yonge.cooleshow.biz.dal.dto.search.PracticeTeacherSearch;
 import com.yonge.cooleshow.biz.dal.entity.*;
 import com.yonge.cooleshow.biz.dal.enums.*;
 import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.wrapper.course.CourseScheduleWrapper;
+import com.yonge.cooleshow.biz.dal.wrapper.liveroom.LiveRoomWrapper;
 import com.yonge.cooleshow.common.enums.PostStatusEnum;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
 import com.yonge.toolset.payment.util.DistributedLock;
@@ -69,6 +71,7 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import static com.yonge.cooleshow.biz.dal.support.WrapperUtil.inInterSection;
+import static com.yonge.cooleshow.common.constant.SysConfigConstant.DESTROY_EXPIRED_LIVE_ROOM_MINUTE;
 
 /**
  * 老师课程表(CourseSchedule)表服务实现类
@@ -129,6 +132,8 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
     
     @Autowired
     private StudentService studentService;
+    @Autowired
+    private LiveRoomService liveRoomService;
 
     @Override
     public CourseScheduleDao getDao() {
@@ -1362,10 +1367,10 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
             appAuditVersion = YesOrNoEnum.NO;
         }
         if (teacherId == null) {
-        	Student student = studentService.getById(studentId);
-        	Long subjectId = null;
+            Student student = studentService.getById(studentId);
+            Long subjectId = null;
             if (student != null && student.getSubjectId() != null) {
-            	subjectId = Long.parseLong(student.getSubjectId());
+                subjectId = Long.parseLong(student.getSubjectId());
             }
             
             homePage.setLiveList(baseMapper.selectLive(appAuditVersion, subjectId));
@@ -2465,4 +2470,41 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         monthToDate(search);
         return page.setRecords(baseMapper.queryPianoClass(page, search));
     }
+
+    @Override
+    public CourseScheduleWrapper.LiveRoomTime getLiveCourseScheduleTime(String roomUid) {
+        CourseSchedule one = this.lambdaQuery().eq(CourseSchedule::getRoomUid, roomUid).last("limit 1").one();
+
+        LiveRoomWrapper.LiveRoomVo liveRoomVo = liveRoomService.queryRoomInfo(roomUid);
+
+        if (liveRoomVo == null) {
+            throw new BizException("直播间不存在");
+        }
+
+        CourseScheduleWrapper.LiveRoomTime liveRoomTime = new CourseScheduleWrapper.LiveRoomTime();
+        liveRoomTime.setLiveRoomUid(liveRoomVo.getRoomUid());
+        liveRoomTime.setTimestamp(System.currentTimeMillis());
+        List<CourseScheduleWrapper.CourseTimeInfoBean> courseTimeInfoBeans = new ArrayList<>();
+
+        liveRoomTime.setCourseScheduleTimes(courseTimeInfoBeans);
+        CourseScheduleWrapper.CourseTimeInfoBean bean = new CourseScheduleWrapper.CourseTimeInfoBean();
+        bean.setStartTime(liveRoomVo.getLiveStartTime().getTime());
+        bean.setEndTime(liveRoomVo.getLiveEndTime().getTime());
+        courseTimeInfoBeans.add(bean);
+        if (liveRoomVo.getType().equals(RoomTypeEnum.LIVE.getCode())) {
+            //查询房间过期时间
+            String expiredMinuteStr = sysConfigService.findConfigValue(DESTROY_EXPIRED_LIVE_ROOM_MINUTE);
+            liveRoomTime.setAutoCloseNetworkRoomTime(expiredMinuteStr);
+
+            if (one != null) {
+                CourseGroup courseGroup = courseGroupService.getById(one.getCourseGroupId());
+                if (courseGroup != null) {
+                    liveRoomTime.setSubjectId(courseGroup.getSubjectId().toString());
+                }
+            }
+
+        }
+
+        return liveRoomTime;
+    }
 }

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

@@ -32,6 +32,7 @@ import com.yonge.cooleshow.biz.dal.enums.live.EAnchorStatus;
 import com.yonge.cooleshow.biz.dal.enums.live.EOnOffStatus;
 import com.yonge.cooleshow.biz.dal.mapper.ImLiveBroadcastRoomMemberMapper;
 import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
+import com.yonge.cooleshow.biz.dal.redisson.RedissonMessageService;
 import com.yonge.cooleshow.biz.dal.service.*;
 import com.yonge.cooleshow.biz.dal.wrapper.liveroom.ImLiveBroadcastRoomMemberWrapper;
 import com.yonge.cooleshow.biz.dal.wrapper.liveroom.LiveRoomWrapper;
@@ -134,6 +135,10 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
 
     @Autowired
     private ImGroupService imGroupService;
+
+    @Autowired
+    private RedissonMessageService redissonMessageService;
+
     /**
      * 生成房间UID
      *
@@ -1019,6 +1024,31 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     }
 
 
+    @Override
+    public void setGroupMemberDefinedData(LiveRoomWrapper.LiveRoomVo  roomVo, Integer onlineUser, Integer totalUser) {
+        List<TencentRequest.ChatRoomGroupDefinedData> appDefinedData = new ArrayList<>();
+        appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
+                .key(EGroupDefinedDataType.MEMBER_ONLINE.getCode())
+                .value(onlineUser.toString())
+                .build());
+        appDefinedData.add(TencentRequest.ChatRoomGroupDefinedData.builder()
+                .key(EGroupDefinedDataType.MEMBER_TOTAL.getCode())
+                .value(totalUser.toString())
+                .build());
+        try {
+            livePluginContext.getPluginService(roomVo.getServiceProvider())
+                    .chatRoomGroupDefinedData(TencentRequest.ChatRoomGroup.builder()
+                            .groupId(roomVo.getRoomUid())
+                            .appDefinedData(appDefinedData)
+                            .build());
+            log.info("设置直播群观看人数 roomUid:{}, data {}",roomVo.getRoomUid(), JSONObject.toJSONString(appDefinedData));
+        } catch (Exception e) {
+            log.error("设置直播群观看人数失败", e);
+            throw new BizException("设置直播群观看人数失败");
+        }
+    }
+
+
     /**
      * 观看者-进入房间
      *
@@ -1133,6 +1163,13 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
             log.info(" sendOnlineUserCount>>>> param is null   roomUid: {}  fromUserId:{}  count:{}", roomUid, fromUserId, count);
             return;
         }
+        // 缓存JoinRoom用户信息到redis
+        RBucket<Object> bucket = redissonClient.getBucket(RedissonMessageService.LIVE_ROOM_MEMBER + roomUid);
+        if (!bucket.isExists()) {
+            bucket.set(0, 30, TimeUnit.MINUTES);
+            // 发布删除缓存消息
+            redissonMessageService.publish(RedissonMessageService.TOPIC_MESSAGE, roomUid);
+        }
         ImRoomMessage message = new ImRoomMessage();
         message.setObjectName(ImRoomMessage.MEMBER_COUNT);
         message.setClientType(ClientEnum.TEACHER.getCode());
@@ -1197,9 +1234,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     private LiveRoomMessage.MessageContent getMessageContent(ImRoomMessage message) {
 
         switch (message.getObjectName()) {
-            case LiveRoomMessage.FORCED_OFFLINE:
-                return LiveRoomMessage.MessageContent.builder()
-                        .build();
+
             case LiveRoomMessage.LOOKER_LOGIN_OUT:
                 return LiveRoomMessage.MessageContent.builder()
                         .targetId( imGroupService.getImUserId(message.getFromUserId(),message.getClientType()))
@@ -1212,9 +1247,8 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
                         .viewers(liveRoomVo.getTotalLookNum().longValue())
                         .likes(liveRoomVo.getLikeNum().longValue())
                         .build();
+            case LiveRoomMessage.FORCED_OFFLINE:
             case LiveRoomMessage.WELCOME:
-                return LiveRoomMessage.MessageContent.builder()
-                        .build();
             default:
                 return LiveRoomMessage.MessageContent.builder()
                         .build();
@@ -1999,6 +2033,15 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         } else {
             roomVo.setVideoNum(0);
         }
+
+        // 直播间主讲人信息
+        SysUser sysUser = sysUserFeignService.queryUserById(roomVo.getSpeakerId());
+        if (sysUser !=null) {
+            roomVo.setSpeakerName(sysUser.getRealName());
+            roomVo.setSpeakerPic(sysUser.getAvatar());
+        }
+
+
         return roomVo;
     }
 

+ 39 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/course/CourseScheduleWrapper.java

@@ -0,0 +1,39 @@
+package com.yonge.cooleshow.biz.dal.wrapper.course;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class CourseScheduleWrapper {
+
+
+
+    @Data
+    public static class LiveRoomTime implements Serializable {
+
+        @ApiModelProperty(value = "直播间房间号")
+        private String liveRoomUid;
+
+        @ApiModelProperty(value = "声部ID")
+        private String subjectId;
+        @ApiModelProperty(value ="直播延长时间")
+        private String autoCloseNetworkRoomTime;
+        @ApiModelProperty("服务器时间 毫秒")
+        private long timestamp;
+
+        @ApiModelProperty("直播时间")
+        private List<CourseTimeInfoBean> courseScheduleTimes;
+    }
+
+    @Data
+    public static class CourseTimeInfoBean {
+
+        @ApiModelProperty(value = "开始时间")
+        private long startTime;
+
+        @ApiModelProperty("结束时间")
+        private long endTime;
+    }
+}

+ 4 - 12
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/liveroom/LiveRoomWrapper.java

@@ -15,6 +15,7 @@ import lombok.NoArgsConstructor;
 
 import java.io.Serializable;
 import java.util.Date;
+import java.util.List;
 
 /**
  * 直播间详情信息
@@ -192,22 +193,12 @@ public class LiveRoomWrapper implements Serializable {
         @ApiModelProperty("直播观看模式")
         private ELiveViewMode viewMode;
 
-        @ApiModelProperty("购物车标题")
-        private String shoppingTitle;
+        @ApiModelProperty(value = "购物车地址")
+        private String shopCarUrl;
 
         @ApiModelProperty("使用场景 正常:NORMAL 音乐:MUSIC")
         private EUseScene useScene;
 
-        @ApiModelProperty("课程结束后多少分钟关闭网络教室")
-        private String autoCloseNetworkRoomTime;
-
-        @ApiModelProperty("剩余时长")
-        private int surplusTime;
-
-        @ApiModelProperty("声部ID")
-        private Integer subjectId;
-
-
         @ApiModelProperty("直播类型 NORMAL:普通直播  LIVE:直播课直播")
         private String  groupType;
 
@@ -238,4 +229,5 @@ public class LiveRoomWrapper implements Serializable {
 
         private String userName;
     }
+
 }

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

@@ -1,15 +1,20 @@
 package com.yonge.cooleshow.student.controller;
 
 
+import com.alibaba.fastjson.JSON;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dto.ImGroupResultDto;
 import com.yonge.cooleshow.biz.dal.dto.ImGroupSearchDto;
 import com.yonge.cooleshow.biz.dal.entity.ImGroup;
+import com.yonge.cooleshow.biz.dal.entity.ImUserFriend;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.enums.ImGroupMemberRoleType;
+import com.yonge.cooleshow.biz.dal.enums.MK;
 import com.yonge.cooleshow.biz.dal.service.ImGroupService;
+import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
 import com.yonge.cooleshow.biz.dal.service.SysUserService;
+import com.yonge.cooleshow.biz.dal.vo.im.ImUserFriendVO;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.toolset.utils.validator.ValidationKit;
@@ -20,15 +25,12 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.PathVariable;
-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 org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * 即时通讯群组(ImGroup)表控制层
@@ -50,6 +52,9 @@ public class ImGroupController extends BaseController {
     @Autowired
     private SysUserFeignService sysUserFeignService;
 
+    @Autowired
+    private ImUserFriendService imUserFriendService;
+
     @ApiOperation("获取群详情")
     @PostMapping(value = "/getDetail/{groupId}")
     public HttpResponseResult<ImGroup> getDetail(@ApiParam(value = "群编号", required = true) @PathVariable("groupId") String groupId) throws Exception {
@@ -99,5 +104,27 @@ public class ImGroupController extends BaseController {
         imGroupService.quit(groupId,sysUserService.getUserId(), ClientEnum.STUDENT);
         return succeed();
     }
+
+
+    @ApiOperation("查询好友详情")
+    @GetMapping(value = "/queryFriendDetail")
+    public HttpResponseResult<ImUserFriendVO.ImUserFriend> queryFriendDetail(String userId) {
+
+        String ret = imGroupService.analysisImUserId(userId);
+        if (!ret.matches(MK.EXP_INT)) {
+            return failed("无效的用户ID");
+        }
+
+        ImUserFriend userFriend = imUserFriendService.getDetail(userId, ClientEnum.TEACHER);
+        if (Objects.isNull(userFriend)) {
+            return failed("当前好友不存在");
+        }
+
+        if (Objects.isNull(userFriend.getFriendType())) {
+            userFriend.setFriendType(ClientEnum.STUDENT);
+        }
+
+        return succeed(ImUserFriendVO.ImUserFriend.from(JSON.toJSONString(userFriend)));
+    }
 }
 

+ 2 - 0
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/ImLiveBroadcastRoomController.java

@@ -1,5 +1,6 @@
 package com.yonge.cooleshow.student.controller;
 
+import com.alibaba.fastjson.JSONObject;
 import com.yonge.cooleshow.biz.dal.entity.ImUserStateSync;
 import com.yonge.cooleshow.biz.dal.service.ImGroupService;
 import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
@@ -88,5 +89,6 @@ public class ImLiveBroadcastRoomController extends BaseController {
         liveRoomService.userWhetherMic(roomUid,userIdLong,whetherMicStatus);
         return succeed();
     }
+
 }
 

+ 58 - 0
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/UserController.java

@@ -0,0 +1,58 @@
+package com.yonge.cooleshow.student.controller;
+
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
+import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.entity.ImUserFriend;
+import com.yonge.cooleshow.biz.dal.entity.ImUserStateSync;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.MK;
+import com.yonge.cooleshow.biz.dal.service.ImGroupService;
+import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
+import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
+import com.yonge.cooleshow.biz.dal.vo.im.ImUserFriendVO;
+import com.yonge.cooleshow.biz.dal.wrapper.im.ImUserWrapper;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import io.swagger.annotations.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 用户通讯录表(ImUserFriend)表控制层
+ *
+ * @author zx
+ * @since 2022-03-22 10:45:59
+ */
+@Api(tags = "用户通讯录表")
+@RestController
+@Slf4j
+@RequestMapping("/user")
+public class UserController extends BaseController {
+
+    @Autowired
+    private LiveRoomService liveRoomService;
+
+
+
+    /**
+     * 同步融云用户状态变更
+     *
+     * @param userState
+     */
+    @PostMapping(value = "/statusImUser")
+    public void statusImUser(@RequestBody List<ImUserStateSync> userState) {
+        log.info("opsRoom >>>>> : {}", JSONObject.toJSONString(userState));
+        liveRoomService.opsRoom(userState);
+    }
+
+}
+

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

@@ -1,13 +1,18 @@
 package com.yonge.cooleshow.teacher.controller;
 
 
+import com.alibaba.fastjson.JSON;
 import com.yonge.cooleshow.biz.dal.dto.ImGroupResultDto;
 import com.yonge.cooleshow.biz.dal.dto.ImGroupSearchDto;
 import com.yonge.cooleshow.biz.dal.entity.ImGroup;
+import com.yonge.cooleshow.biz.dal.entity.ImUserFriend;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.enums.ImGroupMemberRoleType;
+import com.yonge.cooleshow.biz.dal.enums.MK;
 import com.yonge.cooleshow.biz.dal.service.ImGroupService;
+import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
 import com.yonge.cooleshow.biz.dal.service.SysUserService;
+import com.yonge.cooleshow.biz.dal.vo.im.ImUserFriendVO;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.toolset.utils.validator.ValidationKit;
@@ -15,6 +20,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.validation.BindingResult;
 import org.springframework.web.bind.annotation.*;
@@ -22,6 +28,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * 即时通讯群组(ImGroup)表控制层
@@ -41,10 +48,13 @@ public class ImGroupController extends BaseController {
     @Resource
     private SysUserService sysUserService;
 
+    @Autowired
+    private ImUserFriendService imUserFriendService;
+
     @ApiOperation("创建群聊")
     @PostMapping(value = "/create")
     public HttpResponseResult create(@Valid @RequestBody ImGroup imGroup, BindingResult bindingResult) throws Exception {
-        ValidationKit.ignoreFields(bindingResult,"id");
+        ValidationKit.ignoreFields(bindingResult, "id");
         imGroup.setCreateBy(sysUserService.getUserId());
         imGroupService.create(imGroup);
         return succeed();
@@ -60,7 +70,7 @@ public class ImGroupController extends BaseController {
     @ApiOperation("退出群聊")
     @PostMapping(value = "/quit/{groupId}")
     public HttpResponseResult quit(@ApiParam(value = "群编号", required = true) @PathVariable("groupId") String groupId) throws Exception {
-        imGroupService.quit(groupId,sysUserService.getUserId(), ClientEnum.TEACHER);
+        imGroupService.quit(groupId, sysUserService.getUserId(), ClientEnum.TEACHER);
         return succeed();
     }
 
@@ -77,7 +87,7 @@ public class ImGroupController extends BaseController {
     @ApiOperation("群列表")
     @PostMapping(value = "/queryAll")
     public HttpResponseResult<List<ImGroup>> queryAll(@Valid @RequestBody ImGroupSearchDto imGroupSearchDto, BindingResult bindingResult) throws Exception {
-        ValidationKit.ignoreFields(bindingResult,"createUserId");
+        ValidationKit.ignoreFields(bindingResult, "createUserId");
         imGroupSearchDto.setUserId(sysUserService.getUserId());
         // 设置群组成员身份
         imGroupSearchDto.setRoleType(ImGroupMemberRoleType.TEACHER);
@@ -99,5 +109,26 @@ public class ImGroupController extends BaseController {
         }
         return succeed(imGroupService.queryTeacherFun(imGroupSearchDto));
     }
+
+    @ApiOperation("查询好友详情")
+    @GetMapping(value = "/queryFriendDetail")
+    public HttpResponseResult<ImUserFriendVO.ImUserFriend> queryFriendDetail(String userId) {
+
+        String ret = imGroupService.analysisImUserId(userId);
+        if (!ret.matches(MK.EXP_INT)) {
+            return failed("无效的用户ID");
+        }
+
+        ImUserFriend userFriend = imUserFriendService.getDetail(userId, ClientEnum.TEACHER);
+        if (Objects.isNull(userFriend)) {
+            return failed("当前好友不存在");
+        }
+
+        if (Objects.isNull(userFriend.getFriendType())) {
+            userFriend.setFriendType(ClientEnum.STUDENT);
+        }
+
+        return succeed(ImUserFriendVO.ImUserFriend.from(JSON.toJSONString(userFriend)));
+    }
 }
 

+ 15 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherCourseScheduleController.java

@@ -7,6 +7,8 @@ import com.yonge.cooleshow.biz.dal.dto.search.MyCourseSearch;
 import com.yonge.cooleshow.biz.dal.entity.CourseCalendarEntity;
 import com.yonge.cooleshow.biz.dal.service.CourseScheduleService;
 import com.yonge.cooleshow.biz.dal.service.HolidaysFestivalsService;
+import com.yonge.cooleshow.biz.dal.wrapper.course.CourseScheduleWrapper;
+import com.yonge.toolset.base.exception.BizException;
 import com.yonge.toolset.mybatis.support.PageUtil;
 import com.yonge.cooleshow.biz.dal.vo.*;
 import com.yonge.cooleshow.common.controller.BaseController;
@@ -23,6 +25,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -303,5 +306,17 @@ public class TeacherCourseScheduleController extends BaseController {
         }
         return succeed(holidaysFestivalsService.queryByYear(year));
     }
+
+
+    @ApiOperation(value = "获取老师直播课程时间")
+    @GetMapping("/liveCourseScheduleTime")
+    public HttpResponseResult<CourseScheduleWrapper.LiveRoomTime> liveCourseScheduleTime(@RequestParam String roomUid){
+
+        if (Objects.isNull(roomUid)) {
+            throw new BizException("直播编号不能为空");
+        }
+
+        return succeed(courseScheduleService.getLiveCourseScheduleTime(roomUid));
+    }
 }
 

+ 47 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/UserController.java

@@ -0,0 +1,47 @@
+package com.yonge.cooleshow.teacher.controller;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.yonge.cooleshow.biz.dal.entity.ImUserStateSync;
+import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
+import com.yonge.cooleshow.common.controller.BaseController;
+import io.swagger.annotations.Api;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+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 java.util.List;
+
+/**
+ * 用户通讯录表(ImUserFriend)表控制层
+ *
+ * @author zx
+ * @since 2022-03-22 10:45:59
+ */
+@Api(tags = "用户通讯录表")
+@RestController
+@Slf4j
+@RequestMapping("/user")
+public class UserController extends BaseController {
+
+    @Autowired
+    private LiveRoomService liveRoomService;
+
+
+
+    /**
+     * 同步融云用户状态变更
+     *
+     * @param userState
+     */
+    @PostMapping(value = "/statusImUser")
+    public void statusImUser(@RequestBody List<ImUserStateSync> userState) {
+        log.info("opsRoom >>>>> : {}", JSONObject.toJSONString(userState));
+        liveRoomService.opsRoom(userState);
+    }
+
+}
+