Ver código fonte

Merge branch 'feature/0626-live' into test

刘俊驰 9 meses atrás
pai
commit
a5f1df00c3
22 arquivos alterados com 482 adições e 55 exclusões
  1. 23 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/GYMFeignService.java
  2. 25 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/dto/RoomConfig.java
  3. 66 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/dto/RoomMember.java
  4. 19 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/dto/RoomMemberNumDto.java
  5. 25 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/GYMFeignServiceFallback.java
  6. 88 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/open/OpenLiveController.java
  7. 28 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/config/MyOAuth2AuthenticationManager.java
  8. 6 4
      cooleshow-app/src/main/java/com/yonge/cooleshow/config/ResourceServerConfig.java
  9. 9 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/student/controller/ImGroupController.java
  10. 9 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/student/controller/ImUserFriendController.java
  11. 9 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/ImGroupController.java
  12. 9 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/ImUserFriendController.java
  13. 5 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/constant/SysConfigConstant.java
  14. 4 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/LiveRoom.java
  15. 3 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/redisson/RedissonMessageService.java
  16. 7 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImUserFriendService.java
  17. 4 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/LiveRoomService.java
  18. 18 8
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImGroupServiceImpl.java
  19. 27 6
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImUserFriendServiceImpl.java
  20. 86 33
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/LiveRoomServiceImpl.java
  21. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/redisson/RedissonTopicListener.java
  22. 1 1
      pom.xml

+ 23 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/GYMFeignService.java

@@ -0,0 +1,23 @@
+package com.yonge.cooleshow.api.feign;
+
+import com.yonge.cooleshow.api.feign.dto.RoomMemberNumDto;
+import com.yonge.cooleshow.api.feign.fallback.CmsFeignServiceFallback;
+import com.yonge.cooleshow.api.feign.fallback.GYMFeignServiceFallback;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.toolset.feign.config.FeignConfiguration;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+
+@FeignClient(value = "${app-config.open-feign.gym-server.name:gym-server}", url = "${app-config.open-feign.gym-server.url:}",
+        configuration = FeignConfiguration.class, fallback = GYMFeignServiceFallback.class)
+public interface GYMFeignService {
+
+    /**
+     * 直播间人数
+     */
+    @GetMapping("/open/live/queryRoomInfo")
+    HttpResponseResult<RoomMemberNumDto> queryRoomInfo(@RequestParam("roomUid") String roomUid);
+
+}

+ 25 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/dto/RoomConfig.java

@@ -0,0 +1,25 @@
+package com.yonge.cooleshow.api.feign.dto;
+
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class RoomConfig implements Serializable {
+
+    //    @ApiModelProperty(value = "是否允许点赞 0允许 1不允许")
+//    private Integer whether_like = 1;
+
+    //    @ApiModelProperty(value = "是否允许聊天互动  0允许 1不允许")
+//    private Integer whether_chat = 0;
+
+    //    @ApiModelProperty(value = "是否允许保存直播回放 0允许 1不允许")
+//    private Integer whether_video = 0;
+
+    //    @ApiModelProperty(value = "是否允许连麦 0允许 1不允许")
+//    private Integer whether_mic = 0;
+
+    //    @ApiModelProperty(value = "是否展示购物车 0展示 1不展示")
+    private Integer whether_view_shop_cart = 0;
+}

+ 66 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/dto/RoomMember.java

@@ -0,0 +1,66 @@
+package com.yonge.cooleshow.api.feign.dto;
+
+
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class RoomMember {
+
+
+    @ApiModelProperty(value = "房间编号")
+    private String roomUid;
+
+    @ApiModelProperty(value = "房间标题")
+    private String roomTitle;
+
+    @ApiModelProperty(value = "主讲人")
+    private String speakerName;
+
+    @ApiModelProperty(value = "学生编号")
+    private Long studentId;
+
+
+    @ApiModelProperty(value = "学生编号")
+    private String imUserId;
+
+    @ApiModelProperty(value = "学生姓名")
+    private String studentName;
+
+    @ApiModelProperty(value = "学生头像")
+    private String avatar;
+
+    @ApiModelProperty(value = "手机号")
+    private String phone;
+
+    @ApiModelProperty(value = "声部名称")
+    private String subName;
+
+    @ApiModelProperty(value = "进入房间时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date joinTime;
+
+    @ApiModelProperty(value = "累计观看时长")
+    private Integer totalViewTime;
+
+    @ApiModelProperty(value = "连麦状态 0:未申请1:申请连麦中2:连麦中")
+    private Integer whetherMicStatus;
+
+    @ApiModelProperty(value = "是否黑名单")
+    private boolean blackFlag;
+
+    @ApiModelProperty("游客凭据")
+    private String fingerprint;
+
+    @ApiModelProperty(value = "是否能上麦:false否;true是")
+    private boolean microphoneFlag;
+    public String jsonString() {
+        return JSON.toJSONString(this);
+    }
+
+}

+ 19 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/dto/RoomMemberNumDto.java

@@ -0,0 +1,19 @@
+package com.yonge.cooleshow.api.feign.dto;
+
+import lombok.Data;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2023-03-29
+ */
+@Data
+public class RoomMemberNumDto {
+
+    private String roomUid;
+
+    private Integer onlineNum;
+
+    private Integer totalNum;
+}

+ 25 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/GYMFeignServiceFallback.java

@@ -0,0 +1,25 @@
+package com.yonge.cooleshow.api.feign.fallback;
+
+import com.yonge.cooleshow.api.feign.CmsFeignService;
+import com.yonge.cooleshow.api.feign.GYMFeignService;
+import com.yonge.cooleshow.api.feign.dto.RoomMemberNumDto;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-04-29
+ */
+public class GYMFeignServiceFallback implements GYMFeignService {
+
+    /**
+     * 直播间人数
+     *
+     * @param roomUid
+     */
+    @Override
+    public HttpResponseResult<RoomMemberNumDto> queryRoomInfo(String roomUid) {
+        return null;
+    }
+}

+ 88 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/open/OpenLiveController.java

@@ -0,0 +1,88 @@
+package com.yonge.cooleshow.admin.controller.open;
+
+import com.alibaba.fastjson.JSON;
+import com.yonge.cooleshow.api.feign.dto.RoomMember;
+import com.yonge.cooleshow.biz.dal.dto.LiveRoomStatus;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.service.ImGroupService;
+import com.yonge.cooleshow.biz.dal.service.ImLiveBroadcastRoomMemberService;
+import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
+import com.yonge.cooleshow.biz.dal.wrapper.liveroom.ImLiveBroadcastRoomMemberWrapper;
+import com.yonge.cooleshow.biz.dal.wrapper.liveroom.LiveRoomWrapper;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.toolset.base.page.PageInfo;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("${app-config.url.admin:}/open/live")
+@Slf4j
+public class OpenLiveController extends BaseController {
+
+    @Autowired
+    private LiveRoomService liveRoomService;
+
+    @Autowired
+    private ImLiveBroadcastRoomMemberService imLiveBroadcastRoomMemberService;
+
+    @Autowired
+    private ImGroupService imGroupService;
+
+    @ApiOperation("查询房间人数")
+    @GetMapping("/queryRoomInfo")
+    public HttpResponseResult<ImLiveBroadcastRoomMemberWrapper.RoomMemberNumDto> queryRoomInfo(@ApiParam(value = "房间uid", required = true) String roomUid) {
+        return succeed(liveRoomService.getRoomMemberNumDto(roomUid));
+    }
+
+
+    @ApiOperation("分页查询直播间人员列表")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "search", dataType = "String", value = "模糊搜索 学员编号姓名"),
+        @ApiImplicitParam(name = "roomUid", dataType = "String", value = "房间uid"),
+        @ApiImplicitParam(name = "onlineStatus", dataType = "String ", value = "0:离线 1:在线  不传是全部"),
+        @ApiImplicitParam(name = "whetherMicStatus", dataType = "String", value = "连麦状态 0:未申请1:申请连麦中2:连麦中"),
+        @ApiImplicitParam(name = "page", dataType = "Integer", value = "页数"),
+        @ApiImplicitParam(name = "rows", dataType = "Integer", value = "每页数量"),
+    })
+    @PostMapping("/queryRoomMember")
+    public HttpResponseResult<List<RoomMember>> queryRoomMember(@RequestBody Map<String, Object> param) {
+        param.put("page",1);
+        param.put("rows",-1);
+        List<ImLiveBroadcastRoomMemberWrapper.ImLiveBroadcastRoomMember> rows = imLiveBroadcastRoomMemberService.queryRoomMember(param).getRows();
+        if (CollectionUtils.isNotEmpty(rows)) {
+            List<RoomMember> roomMembers = JSON.parseArray(JSON.toJSONString(rows), RoomMember.class);
+            for (RoomMember roomMember : roomMembers) {
+                roomMember.setImUserId(imGroupService.getImUserId(roomMember.getStudentId(), ClientEnum.STUDENT));
+            }
+            return succeed(roomMembers);
+        }
+        return succeed();
+    }
+
+
+    @ApiOperation("更新直播间状态")
+    @PostMapping("/updateRoomStatus")
+    public HttpResponseResult<Boolean> updateRoomStatus(@RequestBody @Valid LiveRoomStatus status ) {
+        return succeed(liveRoomService.updateRoomStatus(status));
+    }
+
+
+    @ApiOperation("设置是否允许连麦")
+    @GetMapping("/whetherMic")
+    public HttpResponseResult<Object> whetherMic(@ApiParam(value = "房间uid", required = true) String roomUid,
+                                                 @ApiParam(value = "是否连麦 0:是 1否", required = true) Integer whetherMic) {
+        liveRoomService.whetherMic(roomUid,whetherMic);
+        return succeed();
+    }
+}

+ 28 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/config/MyOAuth2AuthenticationManager.java

@@ -0,0 +1,28 @@
+package com.yonge.cooleshow.config;
+
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager;
+
+import java.util.UUID;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-06-30
+ */
+public class MyOAuth2AuthenticationManager extends OAuth2AuthenticationManager {
+
+    @Override
+    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+        try {
+            return super.authenticate(authentication);
+        } catch (AuthenticationException | InvalidTokenException e) {
+            return new AnonymousAuthenticationToken(UUID.randomUUID().toString(), "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
+        }
+    }
+}

+ 6 - 4
cooleshow-app/src/main/java/com/yonge/cooleshow/config/ResourceServerConfig.java

@@ -53,9 +53,11 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
 				.and().httpBasic();
 	}
 
-	@Override
-	public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
-		resources.authenticationEntryPoint(baseAuthenticationEntryPoint).accessDeniedHandler(baseAccessDeniedHandler);
-	}
+
+    @Override
+    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
+        resources.authenticationEntryPoint(baseAuthenticationEntryPoint).accessDeniedHandler(baseAccessDeniedHandler);
+        resources.authenticationManager(new MyOAuth2AuthenticationManager());
+    }
 
 }

+ 9 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/student/controller/ImGroupController.java

@@ -131,6 +131,15 @@ public class ImGroupController extends BaseController {
     @GetMapping(value = "/queryFriendDetail")
     public HttpResponseResult<ImUserFriendVO.ImUserFriend> queryFriendDetail(String userId) {
 
+        // 管乐迷、酷乐秀直播播允许多端学生观看,这里增加了对用户ID的解析
+        if (userId.matches(MK.EXP_INT)) {
+            ImUserFriend userProfile = imUserFriendService.getImUserProfile(userId);
+            if (Objects.isNull(userProfile)) {
+                return failed("当前好友不存在");
+            }
+            return succeed(ImUserFriendVO.ImUserFriend.from(JSON.toJSONString(userProfile)));
+        }
+
         String ret = imGroupService.analysisImUserId(userId);
         if (!ret.matches(MK.EXP_INT)) {
             return failed("无效的用户ID");

+ 9 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/student/controller/ImUserFriendController.java

@@ -86,6 +86,15 @@ public class ImUserFriendController extends BaseController {
     @PostMapping(value = "/getDetail/{userId}")
     public HttpResponseResult<ImUserFriendVO.ImUserFriend> getDetail(@ApiParam(value = "用户编号", required = true) @PathVariable("userId") String userId) {
 
+        // 管乐迷、酷乐秀直播播允许多端学生观看,这里增加了对用户ID的解析
+        if (userId.matches(MK.EXP_INT)) {
+            ImUserFriend userProfile = imUserFriendService.getImUserProfile(userId);
+            if (Objects.isNull(userProfile)) {
+                return failed("当前好友不存在");
+            }
+            return succeed(ImUserFriendVO.ImUserFriend.from(JSON.toJSONString(userProfile)));
+        }
+
         String ret = imGroupService.analysisImUserId(userId);
         if (!ret.matches(MK.EXP_INT)) {
             return failed("无效的用户ID");

+ 9 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/ImGroupController.java

@@ -190,6 +190,15 @@ public class ImGroupController extends BaseController {
     @GetMapping(value = "/queryFriendDetail")
     public HttpResponseResult<ImUserFriendVO.ImUserFriend> queryFriendDetail(String userId) {
 
+        // 管乐迷、酷乐秀直播播允许多端学生观看,这里增加了对用户ID的解析
+        if (userId.matches(MK.EXP_INT)) {
+            ImUserFriend userProfile = imUserFriendService.getImUserProfile(userId);
+            if (Objects.isNull(userProfile)) {
+                return failed("当前好友不存在");
+            }
+            return succeed(ImUserFriendVO.ImUserFriend.from(JSON.toJSONString(userProfile)));
+        }
+
         String ret = imGroupService.analysisImUserId(userId);
         if (!ret.matches(MK.EXP_INT)) {
             return failed("无效的用户ID");

+ 9 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/ImUserFriendController.java

@@ -85,6 +85,15 @@ public class ImUserFriendController extends BaseController {
     @PostMapping(value = "/getDetail/{userId}")
     public HttpResponseResult<ImUserFriendVO.ImUserFriend> getDetail(@ApiParam(value = "用户编号", required = true) @PathVariable("userId") String userId) {
 
+        // 管乐迷、酷乐秀直播播允许多端学生观看,这里增加了对用户ID的解析
+        if (userId.matches(MK.EXP_INT)) {
+            ImUserFriend userProfile = imUserFriendService.getImUserProfile(userId);
+            if (Objects.isNull(userProfile)) {
+                return failed("当前好友不存在");
+            }
+            return succeed(ImUserFriendVO.ImUserFriend.from(JSON.toJSONString(userProfile)));
+        }
+
         String ret = imGroupService.analysisImUserId(userId);
         if (!ret.matches(MK.EXP_INT)) {
             return failed("无效的用户ID");

+ 5 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/constant/SysConfigConstant.java

@@ -429,4 +429,9 @@ public interface SysConfigConstant {
      * 草稿保存时长
      */
     String USER_MUSIC_DRAFT_TIME = "user_music_draft_time";
+
+    /**
+     * 管乐迷和酷乐秀同时直播老师ID
+     */
+    String LIVE_TEACHER_IDS = "live_teacher_ids";
 }

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

@@ -137,5 +137,9 @@ public class LiveRoom implements Serializable {
     @ApiModelProperty(value = "更新时间")
     private Date updatedTime;
 
+
+    @TableField("room_config_")
+    @ApiModelProperty(value = "房间配置json格式-是否允许点赞-是否允许聊天互动-是否允许保存直播回放")
+    private String roomConfig;
 }
 

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

@@ -14,10 +14,10 @@ import org.springframework.stereotype.Service;
 public class RedissonMessageService {
 
     // 订阅消息通知
-    public static final String TOPIC_MESSAGE = "topic:message";
+    public static final String TOPIC_MESSAGE = "klx:topic:message";
     // 直播在线人数
-    public static final String LIVE_ROOM_MEMBER = "delayQueue:liveRoomMember:";
-    public static final String LIVE_ROOM_MEMBER_LOCK = "LOCK:liveRoomMember:";
+    public static final String LIVE_ROOM_MEMBER = "klx:delayQueue:liveRoomMember:";
+    public static final String LIVE_ROOM_MEMBER_LOCK = "klx:LOCK:liveRoomMember:";
 
     private final RedissonClient redissonClient;
 

+ 7 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImUserFriendService.java

@@ -44,6 +44,13 @@ public interface ImUserFriendService extends IService<ImUserFriend> {
     ImUserFriend getDetail(String userId, ClientEnum clientType);
 
     /**
+     * 获取用户详情
+     * @param userId 用户ID
+     * @return ImUserFriend
+     */
+    ImUserFriend getImUserProfile(String userId);
+
+    /**
      * 新用户自动添加客服
      * @param userId 新用户ID
      * @param friendIds 好友ID

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

@@ -12,6 +12,7 @@ import com.yonge.cooleshow.biz.dal.dto.TencentData;
 import com.yonge.cooleshow.biz.dal.entity.*;
 import com.yonge.cooleshow.biz.dal.enums.RoomTypeEnum;
 import com.yonge.cooleshow.biz.dal.vo.TeacherLivingInfoVo;
+import com.yonge.cooleshow.biz.dal.wrapper.liveroom.ImLiveBroadcastRoomMemberWrapper;
 import com.yonge.cooleshow.biz.dal.wrapper.liveroom.LiveRoomWrapper;
 import com.yonge.toolset.base.page.PageInfo;
 
@@ -200,6 +201,9 @@ public interface LiveRoomService extends IService<LiveRoom> {
      */
     LiveRoomWrapper.LiveRoomVo queryRoomInfo(String roomUid);
 
+
+    ImLiveBroadcastRoomMemberWrapper.RoomMemberNumDto getRoomMemberNumDto(String roomUid);
+
     /**
      * 同步直播间点赞数
      *

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

@@ -230,6 +230,14 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
     @Override
     public String getImUserId(String userId, String clientType) {
         String imUserId = userId;
+
+        if (StringUtils.isNotBlank(clientType) && clientType.equals(ClientEnum.TEACHER.name())) {
+            String teacherIds = sysConfigService.findConfigValue(SysConfigConstant.LIVE_TEACHER_IDS);
+            if (StringUtils.isNotBlank(teacherIds) && Arrays.asList(teacherIds.split(",")).contains(userId)) {
+                return userId;
+            }
+        }
+
         if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !userId.startsWith(imConfig.getAppPrefix())) {
             imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId, clientType);
         }
@@ -243,10 +251,8 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
         if(userRole.RoleTeacher == userRole){
             clientType = "TEACHER";
         }
-        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !imUserId.startsWith(imConfig.getAppPrefix())) {
-            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId.toString(), clientType);
-        }
-        return imUserId;
+
+        return getImUserId(imUserId,clientType);
     }
 
     @Override
@@ -256,10 +262,9 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
         if(clientEnum.TEACHER == clientEnum){
             clientType = "TEACHER";
         }
-        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !imUserId.startsWith(imConfig.getAppPrefix())) {
-            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId.toString(), clientType);
-        }
-        return imUserId;
+
+
+        return getImUserId(imUserId,clientType);
     }
 
 
@@ -286,6 +291,11 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
      */
     @Override
     public boolean checkImUserId(String imUserId) {
+
+        String teacherIds = sysConfigService.findConfigValue(SysConfigConstant.LIVE_TEACHER_IDS);
+        if (StringUtils.isNotBlank(teacherIds) && Arrays.asList(teacherIds.split(",")).contains(imUserId)) {
+            return true;
+        }
        return imUserId.startsWith(imConfig.getAppPrefix());
     }
 

+ 27 - 6
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImUserFriendServiceImpl.java

@@ -11,6 +11,7 @@ import com.microsvc.toolkit.middleware.im.impl.TencentCloudImPlugin;
 import com.microsvc.toolkit.middleware.im.message.ETencentMessage;
 import com.microsvc.toolkit.middleware.im.message.MessageWrapper;
 import com.microsvc.toolkit.middleware.im.message.TencentRequest;
+import com.microsvc.toolkit.middleware.im.message.TencentWrapper;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.auth.config.CustomerServiceConfig;
@@ -30,9 +31,7 @@ import com.yonge.toolset.base.util.ImUtil;
 import io.rong.messages.BaseMessage;
 import io.rong.messages.ImgMessage;
 import io.rong.messages.TxtMessage;
-import io.rong.models.message.PrivateMessage;
 import io.rong.models.message.PushExt;
-import io.rong.models.response.ResponseResult;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -41,13 +40,11 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -70,8 +67,6 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
     private CustomerServiceConfig customerServiceConfig;
     @Autowired
     private SysUserMapper sysUserMapper;
-    @Autowired
-    private ImUserFriendService imUserFriendService;
 
     @Autowired
     private ImGroupService imGroupService;
@@ -229,6 +224,32 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
     }
 
     /**
+     * 获取用户详情
+     *
+     * @param userId 用户ID
+     * @return ImUserFriend
+     */
+    @Override
+    public ImUserFriend getImUserProfile(String userId) {
+
+        try {
+            TencentWrapper.UserProfile userProfile = imPluginContext.getPluginService().getUserProfile(userId);
+            // 返回当前登录用户信息
+            ImUserFriend imUserFriend = new ImUserFriend();
+            imUserFriend.setFriendAvatar(userProfile.getAvatar());
+            imUserFriend.setFriendNickname(userProfile.getUsername());
+            imUserFriend.setFriendId(Long.valueOf(userId));
+            imUserFriend.setFriendType(ClientEnum.STUDENT);
+            // 设置融云IM好友ID
+            imUserFriend.setImFriendId(userId);
+            return imUserFriend;
+        } catch (Exception e) {
+            log.error("getImUserProfile userId={}", userId, e);
+        }
+        return null;
+    }
+
+    /**
      * 新用户自动添加客服
      *
      * @param userId     新用户ID

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

@@ -13,18 +13,17 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.function.BiFunction;
 import java.util.function.BiPredicate;
-import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import com.alibaba.fastjson.JSON;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import com.google.common.collect.Lists;
 import com.microsvc.toolkit.middleware.live.LivePluginContext;
 import com.microsvc.toolkit.middleware.live.LivePluginService;
 import com.microsvc.toolkit.middleware.live.impl.RongCloudLivePlugin;
 import com.microsvc.toolkit.middleware.live.impl.TencentCloudLivePlugin;
 import com.microsvc.toolkit.middleware.live.message.*;
+import com.yonge.cooleshow.api.feign.dto.RoomConfig;
 import com.yonge.cooleshow.biz.dal.dto.LiveRoomStatus;
 import com.yonge.cooleshow.biz.dal.dto.TencentData;
 import com.yonge.cooleshow.biz.dal.entity.*;
@@ -36,6 +35,7 @@ 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;
+import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import com.yonge.cooleshow.common.enums.EGroupDefinedDataType;
 import com.yonge.toolset.payment.util.DistributedLock;
 import lombok.Data;
@@ -222,33 +222,37 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
             log.error("teacherCheckRoomInfo>>>not speaker  roomUid: {} userId:{}", roomUid, userId);
             throw new BizException("您不是该直播间的主讲人!");
         }
+        speakCache(room, userId);
+        return liveRoom;
+    }
+
+    private void speakCache(LiveRoom room, Long userId) {
         //获取直播间信息
-        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString());
+        RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(room.getRoomUid(), userId.toString());
         if (!speakerCache.isExists()) {
 
             //没有主讲人信息则生成一个
-            createSpeakerInfo(this.getById(liveRoom.getId()), sysUser);
+            createSpeakerInfo(this.getById(room.getId()), userId);
 
             // 查询主播缓存信息
-            speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString());
+            speakerCache = getRoomSpeakerInfoCache(room.getRoomUid(), userId.toString());
         }
         RoomSpeakerInfo speakerInfo = speakerCache.get();
-        speakerInfo.setJoinRoomTime(now);
+        speakerInfo.setJoinRoomTime(new Date());
         speakerCache.set(speakerInfo);
 
         //记录用户当前房间uid
-        redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid, 12L, TimeUnit.HOURS);
+        redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(room.getRoomUid(), 12L, TimeUnit.HOURS);
 
         // 更新直播间主播状态
         lambdaUpdate()
-                .eq(LiveRoom::getRoomUid, roomUid)
+                .eq(LiveRoom::getRoomUid, room.getRoomUid())
                 .eq(LiveRoom::getSpeakerId, userId)
                 .set(LiveRoom::getSpeakerStatus, 1)
                 .update();
 
         // 设置直播群组自定义数据
         setGroupDefinedData(room,EGroupDefinedDataType.ANCHOR_STATUS,EAnchorStatus.ONLINE.getCode());
-        return liveRoom;
     }
 
     /**
@@ -263,7 +267,10 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
 
 
     //生成主讲人信息
-    private void createSpeakerInfo(LiveRoom room, SysUser sysUser) {
+    private void createSpeakerInfo(LiveRoom room, Long userId) {
+
+        SysUser sysUser = sysUserFeignService.queryUserById(userId);
+
         Date now = new Date();
         RoomSpeakerInfo speakerInfo = new RoomSpeakerInfo();
         speakerInfo.setSpeakerId(sysUser.getId());
@@ -332,7 +339,8 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         Date now = new Date();
         courseScheduleList.forEach(c -> {
             try {
-                liveRoomService.updateLiveCourseSchedule(preCreateRoomMinute, titleMap, remarkMap, en, now, c);
+                DistributedLock.of(redissonClient).runIfLockCanGet("LIVE_COURSE_CREATE:"+c.getId(), () ->
+                    liveRoomService.updateLiveCourseSchedule(preCreateRoomMinute, titleMap, remarkMap, en, now, c));
             } catch (Exception e) {
                 log.error("createCourseLiveRoom>>>生成直播间失败:{}", c, e);
             }
@@ -348,12 +356,38 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
             return;
         }
         //避免重复创建直播间
+
+        // 如果是同时在管乐迷和酷乐秀直播的老师
+
+        LiveRoom room = new LiveRoom();
+        String teacherIds = sysConfigService.findConfigValue(SysConfigConstant.LIVE_TEACHER_IDS);
         if (StringUtils.isNotBlank(c.getRoomUid())) {
-            log.info("createCourseLiveRoom>>>roomUid:{} 已存在", c.getRoomUid());
-            return;
+            if ((StringUtils.isBlank(teacherIds) || !Arrays.asList(teacherIds.split(",")).contains(c.getTeacherId().toString()))) {
+                log.info("createCourseLiveRoom>>>roomUid:{} 已存在", c.getRoomUid());
+                return;
+            } else {
+                LiveRoom liveRoom = getByRoomUid(c.getRoomUid());
+                if (liveRoom != null) {
+                    log.info("createCourseLiveRoom>>>roomUid:{} 已存在", c.getRoomUid());
+                   return;
+                } else {
+                    // 设置直播间不显示购物车
+                    RoomConfig roomConfig = new RoomConfig();
+                    // 1:是隐藏, 和管乐迷一样
+                    roomConfig.setWhether_view_shop_cart(1);
+                    room.setRoomConfig(JSON.toJSONString(roomConfig));
+
+                }
+            }
+        }
+        if (StringUtils.isBlank(c.getRoomUid())) {
+            room.setRoomUid(GenRoomUid.apply(c.getTeacherId(), en));
+        } else {
+            room.setRoomUid(c.getRoomUid());
+        }
+        if (StringUtils.isNotBlank(teacherIds) && Arrays.asList(teacherIds.split(",")).contains(c.getTeacherId().toString())) {
+            room.setOs("pc");
         }
-        LiveRoom room = new LiveRoom();
-        room.setRoomUid(GenRoomUid.apply(c.getTeacherId(), en));
         room.setRoomTitle(titleMap.get(c.getCourseGroupId()));
         room.setLiveRemark(remarkMap.get(c.getCourseGroupId()));
         room.setSpeakerId(c.getTeacherId());
@@ -372,6 +406,10 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         this.createLiveRoomInfo(room);
         //开课提醒
         this.pushLiveCreateRoom(room);
+
+        if (StringUtils.isNotBlank(teacherIds) && Arrays.asList(teacherIds.split(",")).contains(room.getSpeakerId().toString())) {
+            speakCache(room, room.getSpeakerId());
+        }
     }
 
     /**
@@ -492,20 +530,28 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
 
                     // 生成录制任务
                     log.info("createLiveRoom>>>>>> recordStart:{}", recordStart.jsonString());
-                    RTCRoom.RecordResp resp = pluginService.rtcRoomRecordStart(recordStart);
-
-                    // 设置录制任务Id
-                    LiveRoom update = new LiveRoom();
-                    update.setId(room.getId());
-                    if (StringUtils.isBlank(room.getVideoRecord())) {
-                        update.setVideoRecord(resp.getRecordId());
-                    } else {
-                        update.setVideoRecord(room.getVideoRecord() + "," + resp.getRecordId());
+                    try {
+
+                        RTCRoom.RecordResp resp = pluginService.rtcRoomRecordStart(recordStart);
+                        // 设置录制任务Id
+                        LiveRoom update = new LiveRoom();
+                        update.setId(room.getId());
+                        if (StringUtils.isBlank(room.getVideoRecord())) {
+                            update.setVideoRecord(resp.getRecordId());
+                        } else {
+                            update.setVideoRecord(room.getVideoRecord() + "," + resp.getRecordId());
+                        }
+                        updateById(update);
+                    }catch (Exception e) {
+                        log.error("createLiveRoom>>>>>> recordStart error:{}", e.getMessage());
                     }
-                    updateById(update);
+
                 }
                 // 设置直播间房间属性默认值
-                setDefaultRoomDefinedInfo(room);
+                List<TencentWrapper.ChatRoomGroupCounter> chatRoomGroupDefinedData = pluginService.getChatRoomGroupDefinedData(room.getRoomUid());
+                if (CollectionUtils.isEmpty(chatRoomGroupDefinedData)) {
+                    setDefaultRoomDefinedInfo(room);
+                }
             }
         } catch (Exception e) {
             throw new BizException("创建直播间失败!", e);
@@ -1265,7 +1311,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         message.setContent(sendMap);
         //发送消息
         try {
-            this.publishRoomMessage(message);
+//            this.publishRoomMessage(message);
             log.info("sendOnlineUserCount>>>> message: {}", JSONObject.toJSONString(message));
         } catch (Exception e) {
             log.error("sendOnlineUserCount>>>> error {}", e.getMessage());
@@ -2134,12 +2180,7 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
         roomVo.setTotalLookNum(0);
         roomVo.setLookNum(0);
 
-        ImLiveBroadcastRoomMemberWrapper.RoomMemberNumDto roomMemberNumDto = imLiveBroadcastRoomMemberMapper.queryMemberNum(roomVo.getRoomUid());
-        if (roomMemberNumDto == null) {
-            roomMemberNumDto = new ImLiveBroadcastRoomMemberWrapper.RoomMemberNumDto();
-            roomMemberNumDto.setTotalNum(0);
-            roomMemberNumDto.setOnlineNum(0);
-        }
+        ImLiveBroadcastRoomMemberWrapper.RoomMemberNumDto roomMemberNumDto = getRoomMemberNumDto(roomVo.getRoomUid());
         roomVo.setTotalLookNum(roomMemberNumDto.getTotalNum() == null? 0 : roomMemberNumDto.getTotalNum());
         roomVo.setLookNum(roomMemberNumDto.getOnlineNum() == null? 0 : roomMemberNumDto.getOnlineNum());
 
@@ -2163,6 +2204,18 @@ public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomDao, LiveRoom> impl
     }
 
 
+    @Override
+    public ImLiveBroadcastRoomMemberWrapper.RoomMemberNumDto getRoomMemberNumDto(String roomUid) {
+        ImLiveBroadcastRoomMemberWrapper.RoomMemberNumDto roomMemberNumDto = imLiveBroadcastRoomMemberMapper.queryMemberNum(roomUid);
+        if (roomMemberNumDto == null) {
+            roomMemberNumDto = new ImLiveBroadcastRoomMemberWrapper.RoomMemberNumDto();
+            roomMemberNumDto.setTotalNum(0);
+            roomMemberNumDto.setOnlineNum(0);
+        }
+        return roomMemberNumDto;
+    }
+
+
     /**
      * 同步直播间点赞数
      *

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

@@ -1,8 +1,11 @@
 package com.yonge.redisson;
 
+import com.yonge.cooleshow.api.feign.GYMFeignService;
+import com.yonge.cooleshow.api.feign.dto.RoomMemberNumDto;
 import com.yonge.cooleshow.biz.dal.redisson.RedissonMessageService;
 import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
 import com.yonge.cooleshow.biz.dal.wrapper.liveroom.LiveRoomWrapper;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import lombok.extern.slf4j.Slf4j;
 import org.redisson.api.RBucket;
 import org.redisson.api.RLock;
@@ -30,6 +33,9 @@ public class RedissonTopicListener implements ApplicationRunner, Ordered {
 
     @Autowired
     private LiveRoomService liveRoomService;
+
+    @Autowired
+    private GYMFeignService gymFeignService;
  
     @Override
     public void run(ApplicationArguments args) {
@@ -60,6 +66,11 @@ public class RedissonTopicListener implements ApplicationRunner, Ordered {
                             return;
                         }
                         try {
+                            HttpResponseResult<RoomMemberNumDto> roomMemberNumDtoHttpResponseResult = gymFeignService.queryRoomInfo(message);
+                            if (roomMemberNumDtoHttpResponseResult.getStatus()) {
+                                liveRoomVo.setLookNum(roomMemberNumDtoHttpResponseResult.getData().getOnlineNum() + liveRoomVo.getLookNum());
+                                liveRoomVo.setTotalLookNum(roomMemberNumDtoHttpResponseResult.getData().getTotalNum() + liveRoomVo.getTotalLookNum());
+                            }
                             liveRoomService.setGroupMemberDefinedData(liveRoomVo,liveRoomVo.getLookNum(),liveRoomVo.getTotalLookNum());
                         } catch (Exception e) {
                             log.error("RedissonMessageService subscribe setGroupMemberDefinedData error", e);

+ 1 - 1
pom.xml

@@ -69,7 +69,7 @@
 			<dependency>
 				<groupId>com.microsvc.toolkit</groupId>
 				<artifactId>microsvc-dependencies-bom</artifactId>
-				<version>1.0.4</version>
+				<version>1.0.7</version>
 				<type>pom</type>
 				<scope>import</scope>
 			</dependency>