Quellcode durchsuchen

Merge remote-tracking branch 'origin/master_saas' into master_saas

zouxuan vor 2 Jahren
Ursprung
Commit
1c1b34de85
35 geänderte Dateien mit 1346 neuen und 115 gelöschten Zeilen
  1. 4 0
      mec-auth/mec-auth-api/src/main/java/com/ym/mec/auth/api/enums/SysUserType.java
  2. 20 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ImLiveBroadcastRoomMemberDao.java
  3. 12 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ImLiveBroadcastRoomDto.java
  4. 35 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/LiveRoomStatus.java
  5. 187 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TencentData.java
  6. 40 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TencentImCallbackResult.java
  7. 62 2
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImLiveBroadcastRoom.java
  8. 47 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImLiveBroadcastRoomMember.java
  9. 30 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/ETencentGroupType.java
  10. 31 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/ETencentImCallbackCommand.java
  11. 3 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/vo/ImLiveBroadcastRoomMemberVo.java
  12. 60 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/vo/ImLiveBroadcastRoomVo.java
  13. 1 0
      mec-biz/src/main/java/com/ym/mec/biz/service/ImLiveBroadcastRoomMemberService.java
  14. 25 0
      mec-biz/src/main/java/com/ym/mec/biz/service/ImLiveBroadcastRoomService.java
  15. 3 2
      mec-biz/src/main/java/com/ym/mec/biz/service/ImLiveRoomBlackService.java
  16. 522 55
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java
  17. 32 11
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveRoomBlackServiceImpl.java
  18. 0 5
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveRoomReservationServiceImpl.java
  19. 0 3
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImSendGroupMessageServiceImpl.java
  20. 11 6
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/LiveGoodsMapperServiceImpl.java
  21. 11 0
      mec-biz/src/main/resources/config/mybatis/ImLiveBroadcastRoomMapper.xml
  22. 21 2
      mec-biz/src/main/resources/config/mybatis/ImLiveBroadcastRoomMemberMapper.xml
  23. 1 0
      mec-biz/src/main/resources/config/mybatis/ImLiveRoomReservationMapper.xml
  24. 1 1
      mec-common/common-core/src/main/java/com/ym/mec/common/controller/BaseController.java
  25. 3 0
      mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImRoomMessage.java
  26. 2 2
      mec-im/src/main/java/com/ym/config/ResourceServerConfig.java
  27. 6 0
      mec-im/src/main/java/com/ym/controller/LiveRoomController.java
  28. 51 1
      mec-im/src/main/java/com/ym/controller/UserController.java
  29. 4 12
      mec-student/src/main/resources/logback-spring.xml
  30. 31 3
      mec-teacher/src/main/java/com/ym/mec/teacher/controller/TeacherImLiveBroadcastRoomController.java
  31. 59 0
      mec-teacher/src/main/java/com/ym/mec/teacher/controller/TeacherImLiveBroadcastRoomMemberController.java
  32. 3 3
      mec-teacher/src/main/resources/logback-spring.xml
  33. 4 1
      mec-web/pom.xml
  34. 21 2
      mec-web/src/main/java/com/ym/mec/web/controller/ImLiveBroadcastRoomController.java
  35. 3 3
      mec-web/src/main/resources/logback-spring.xml

+ 4 - 0
mec-auth/mec-auth-api/src/main/java/com/ym/mec/auth/api/enums/SysUserType.java

@@ -1,5 +1,6 @@
 package com.ym.mec.auth.api.enums;
 
+import com.baomidou.mybatisplus.annotation.EnumValue;
 import org.apache.commons.lang3.StringUtils;
 
 import com.ym.mec.common.enums.BaseEnum;
@@ -10,6 +11,9 @@ public enum SysUserType implements BaseEnum<String, SysUserType> {
 
 	private String desc;
 
+	@EnumValue
+	private String code;
+
 	private SysUserType(String desc) {
 	}
 

+ 20 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ImLiveBroadcastRoomMemberDao.java

@@ -22,5 +22,25 @@ public interface ImLiveBroadcastRoomMemberDao extends BaseMapper<ImLiveBroadcast
 
     IPage<ImLiveBroadcastRoomMemberVo> queryMemberPage(Page<ImLiveBroadcastRoomMemberVo> page, @Param("param") Map<String, Object> param);
 
+    /**
+     * 设置在线状态
+     *
+     * @param userIds      用户id
+     * @param groupId      房间编号
+     * @param onlineStatus 状态
+     */
+    void updateOnlineStatus(@Param("userIds") List<Long> userIds, @Param("groupId") String groupId, @Param(
+        "onlineStatus") Integer onlineStatus);
+    /**
+     * 设置直播状态
+     *
+     * @param userIds      用户id
+     * @param groupId      房间编号
+     * @param liveRoomStatus 状态
+     */
+    void updateLiveRoomStatus(@Param("userIds") List<Long> userIds, @Param("groupId") String groupId, @Param(
+        "liveRoomStatus") Integer liveRoomStatus);
+
+    List<ImLiveBroadcastRoomMember> queryMember(@Param("userIds") List<Long> userIds, @Param("groupId") String groupId);
 }
 

+ 12 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ImLiveBroadcastRoomDto.java

@@ -1,5 +1,6 @@
 package com.ym.mec.biz.dal.dto;
 
+import com.ym.mec.auth.api.enums.SysUserType;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -27,6 +28,9 @@ public class ImLiveBroadcastRoomDto implements Serializable {
     @ApiModelProperty(value = "主讲人id/老师id")
     private Integer speakerId;
 
+    @ApiModelProperty("用户类型 TEACHER 老师 EDUCATION 教务端")
+    private SysUserType clientType;
+
     @Size(max = 12, message = "房间标题最多12个字!")
     @NotBlank(message = "房间标题不能为空")
     @ApiModelProperty(value = "房间标题/最多12个字")
@@ -117,6 +121,14 @@ public class ImLiveBroadcastRoomDto implements Serializable {
         }
     }
 
+    public SysUserType getClientType() {
+        return clientType;
+    }
+
+    public void setClientType(SysUserType clientType) {
+        this.clientType = clientType;
+    }
+
     public Integer getId() {
         return id;
     }

+ 35 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/LiveRoomStatus.java

@@ -0,0 +1,35 @@
+package com.ym.mec.biz.dal.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2023-03-09
+ */
+@Data
+@ApiModel(value = "更新直播间状态")
+public class LiveRoomStatus {
+
+    @ApiModelProperty(value = "房间uid",required = true)
+    @NotBlank(message = "房间号不能为空")
+    private String roomUid;
+
+    @ApiModelProperty(value = "主播状态: 0离开;1在播")
+    private Integer speakerStatus;
+
+    @ApiModelProperty(value = "推流状态: 0 暂停; 1在播")
+    private Integer pushStatus;
+
+    @ApiModelProperty(value = "禁言状态: 0 取消;1禁言")
+    private Integer banStatus;
+
+    @ApiModelProperty(value = "直播时长")
+    private Integer liveTotalTime;
+
+}

+ 187 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TencentData.java

@@ -0,0 +1,187 @@
+package com.ym.mec.biz.dal.dto;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.ym.mec.biz.dal.enums.ETencentGroupType;
+import com.ym.mec.biz.dal.enums.ETencentImCallbackCommand;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2023-03-06
+ */
+@NoArgsConstructor
+@Data
+public class TencentData {
+
+    // 群成员离开之后回调对象
+    @NoArgsConstructor
+    @Data
+    public static class CallbackAfterMemberExit {
+
+
+        private String clientIP;
+
+        private String optPlatform;
+
+        // 回调命令
+        private ETencentImCallbackCommand callbackCommand;
+        // 群组 ID
+        private String groupId;
+        // 群组类型
+        private ETencentGroupType type;
+        // 成员离开方式:Kicked-被踢;Quit-主动退群
+        private String exitType;
+        // 操作者
+        private String operatorAccount;
+        // 离开群的成员列表
+        private List<MemberListDTO> exitMemberList;
+        //毫秒级别,事件触发时间戳
+        private LocalDateTime eventTime;
+
+        public static CallbackAfterMemberExit toObject(String jsonString) {
+
+            CallbackAfterMemberExit res = new CallbackAfterMemberExit();
+
+            JSONObject jsonObject = JSON.parseObject(jsonString);
+            res.setCallbackCommand(ETencentImCallbackCommand.valueOf(jsonObject.getString("CallbackCommand")));
+            res.setGroupId(jsonObject.getString("GroupId"));
+            res.setType(jsonObject.getObject("Type",ETencentGroupType.class));
+            res.setExitType(jsonObject.getString("ExitType"));
+            res.setOperatorAccount(jsonObject.getString("Operator_Account"));
+
+            JSONArray exitMemberList = jsonObject.getJSONArray("ExitMemberList");
+            if (!exitMemberList.isEmpty()) {
+                List<MemberListDTO> memberListDTOS = new ArrayList<>();
+                for (int i = 0; i < exitMemberList.size(); i++) {
+                    MemberListDTO memberListDTO = new MemberListDTO();
+                    JSONObject exitMemberListJSONObject = exitMemberList.getJSONObject(i);
+                    String member_account = exitMemberListJSONObject.getString("Member_Account");
+                    memberListDTO.setMemberAccount(member_account);
+                    memberListDTOS.add(memberListDTO);
+                }
+                res.setExitMemberList(memberListDTOS);
+            }
+
+
+            res.setEventTime(jsonObject.getTimestamp("EventTime").toLocalDateTime());
+
+            return res;
+        }
+    }
+
+    @NoArgsConstructor
+    @Data
+    public static class MemberListDTO {
+        private String memberAccount;
+    }
+
+    // 直播群成员在线状态回调
+    @NoArgsConstructor
+    @Data
+    public static class CallbackOnMemberStateChange {
+
+        // 客户端平台,对应不同的平台类型,可能的取值有:
+        // RESTAPI(使用 REST API 发送请求)、Web(使用 Web SDK 发送请求)、
+        // Android、iOS、Windows、Mac、iPad、Unknown(使用未知类型的设备发送请求)
+        private String clientIP;
+
+        private String optPlatform;
+        // 回调命令
+        private ETencentImCallbackCommand callbackCommand;
+        // 群组 ID
+        private String groupId;
+        // 事件类型:Offline - 掉线、Online - 重新上线
+        private String eventType;
+        // 离开群的成员列表
+        private List<MemberListDTO> memberList;
+
+        public static CallbackOnMemberStateChange toObject(String jsonString) {
+
+            CallbackOnMemberStateChange res = new CallbackOnMemberStateChange();
+
+            JSONObject jsonObject = JSON.parseObject(jsonString);
+            res.setCallbackCommand(ETencentImCallbackCommand.valueOf(jsonObject.getString("CallbackCommand")));
+            res.setGroupId(jsonObject.getString("GroupId"));
+
+            JSONArray exitMemberList = jsonObject.getJSONArray("MemberList");
+            if (!exitMemberList.isEmpty()) {
+                List<MemberListDTO> memberListDTOS = new ArrayList<>();
+                for (int i = 0; i < exitMemberList.size(); i++) {
+                    MemberListDTO memberListDTO = new MemberListDTO();
+                    JSONObject exitMemberListJSONObject = exitMemberList.getJSONObject(i);
+                    String member_account = exitMemberListJSONObject.getString("Member_Account");
+                    memberListDTO.setMemberAccount(member_account);
+                    memberListDTOS.add(memberListDTO);
+                }
+                res.setMemberList(memberListDTOS);
+            }
+
+            res.setEventType(jsonObject.getString("EventType"));
+
+            return res;
+        }
+    }
+
+    @NoArgsConstructor
+    @Data
+    public static class CallbackAfterNewMemberJoin {
+
+        private String clientIP;
+
+        private String optPlatform;
+        // 回调命令
+        private ETencentImCallbackCommand callbackCommand;
+        // 群组 ID
+        private String groupId;
+        // 群组类型
+        private ETencentGroupType type;
+        // 入群方式:Apply(申请入群);Invited(邀请入群)
+        private String joinType;
+        // 操作者成员
+        private String operatorAccount;
+        // 新入群成员列表
+        private List<MemberListDTO> newMemberList;
+        //毫秒级别,事件触发时间戳
+        private LocalDateTime eventTime;
+
+        public static CallbackAfterNewMemberJoin toObject(String jsonString) {
+
+            CallbackAfterNewMemberJoin res = new CallbackAfterNewMemberJoin();
+
+            JSONObject jsonObject = JSON.parseObject(jsonString);
+            res.setCallbackCommand(ETencentImCallbackCommand.valueOf(jsonObject.getString("CallbackCommand")));
+            res.setGroupId(jsonObject.getString("GroupId"));
+            res.setType(jsonObject.getObject("Type",ETencentGroupType.class));
+            res.setJoinType(jsonObject.getString("JoinType"));
+            res.setOperatorAccount(jsonObject.getString("Operator_Account"));
+
+            JSONArray exitMemberList = jsonObject.getJSONArray("NewMemberList");
+            if (!exitMemberList.isEmpty()) {
+                List<MemberListDTO> memberListDTOS = new ArrayList<>();
+                for (int i = 0; i < exitMemberList.size(); i++) {
+                    MemberListDTO memberListDTO = new MemberListDTO();
+                    JSONObject exitMemberListJSONObject = exitMemberList.getJSONObject(i);
+                    String member_account = exitMemberListJSONObject.getString("Member_Account");
+                    memberListDTO.setMemberAccount(member_account);
+                    memberListDTOS.add(memberListDTO);
+                }
+                res.setNewMemberList(memberListDTOS);
+            }
+
+
+            res.setEventTime(jsonObject.getTimestamp("EventTime").toLocalDateTime());
+
+            return res;
+        }
+    }
+
+}

+ 40 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TencentImCallbackResult.java

@@ -0,0 +1,40 @@
+package com.ym.mec.biz.dal.dto;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2023-03-02
+ */
+public class TencentImCallbackResult {
+
+    private String ActionStatus = "OK";
+
+    private String ErrorInfo;
+
+    private int ErrorCode = 0;
+
+    public String getActionStatus() {
+        return ActionStatus;
+    }
+
+    public void setActionStatus(String actionStatus) {
+        ActionStatus = actionStatus;
+    }
+
+    public String getErrorInfo() {
+        return ErrorInfo;
+    }
+
+    public void setErrorInfo(String errorInfo) {
+        ErrorInfo = errorInfo;
+    }
+
+    public int getErrorCode() {
+        return ErrorCode;
+    }
+
+    public void setErrorCode(int errorCode) {
+        ErrorCode = errorCode;
+    }
+}

+ 62 - 2
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImLiveBroadcastRoom.java

@@ -4,7 +4,7 @@ import java.util.Date;
 
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
-import com.ym.mec.biz.dal.enums.LiveServiceProviderEnum;
+import com.ym.mec.auth.api.enums.SysUserType;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -35,6 +35,11 @@ public class ImLiveBroadcastRoom implements Serializable {
     @ApiModelProperty(value = "主讲人id/老师id")
     private Integer speakerId;
 
+
+    @TableField("client_type_")
+    @ApiModelProperty("用户类型 TEACHER 老师 EDUCATION 教务端")
+    private SysUserType clientType;
+
     @TableField("room_uid_")
     @ApiModelProperty(value = "房间编号")
     private String roomUid;
@@ -67,6 +72,10 @@ public class ImLiveBroadcastRoom implements Serializable {
     @ApiModelProperty(value = "直播状态 0未开始 1开始 2已结束")
     private Integer liveState;
 
+    @TableField("live_total_time_")
+    @ApiModelProperty(value = "直播时长")
+    private Integer liveTotalTime;
+
     @TableField("room_state_")
     @ApiModelProperty(value = "房间状态 0正常 1已删除 2销毁")
     private Integer roomState;
@@ -81,12 +90,24 @@ public class ImLiveBroadcastRoom implements Serializable {
 
     @TableField("os_")
     @ApiModelProperty(value = "播出端-  pc网页端 移动端mobile")
-    private String os = "pc";
+    private String os;
 
     @TableField("service_provider_")
     @ApiModelProperty(value = "服务提供方 rongCloud tencentCloud")
     private String serviceProvider;
 
+    @TableField("speaker_status_")
+    @ApiModelProperty(value = "主播状态: 0离开;1在播")
+    private Integer speakerStatus;
+
+    @TableField("push_status_")
+    @ApiModelProperty(value = "推流状态: 0 暂停; 1在播")
+    private Integer pushStatus;
+
+    @TableField("ban_status_")
+    @ApiModelProperty(value = "禁言状态: 0 取消;1禁言")
+    private Integer banStatus;
+
     @TableField("created_by_")
     @ApiModelProperty(value = "创建人")
     private Integer createdBy;
@@ -105,6 +126,14 @@ public class ImLiveBroadcastRoom implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
+    public SysUserType getClientType() {
+        return clientType;
+    }
+
+    public void setClientType(SysUserType clientType) {
+        this.clientType = clientType;
+    }
+
     public String getServiceProvider() {
         return serviceProvider;
     }
@@ -283,5 +312,36 @@ public class ImLiveBroadcastRoom implements Serializable {
         this.popularizeType = popularizeType;
     }
 
+    public Integer getSpeakerStatus() {
+        return speakerStatus;
+    }
+
+    public void setSpeakerStatus(Integer speakerStatus) {
+        this.speakerStatus = speakerStatus;
+    }
+
+    public Integer getPushStatus() {
+        return pushStatus;
+    }
+
+    public void setPushStatus(Integer pushStatus) {
+        this.pushStatus = pushStatus;
+    }
+
+    public Integer getBanStatus() {
+        return banStatus;
+    }
+
+    public void setBanStatus(Integer banStatus) {
+        this.banStatus = banStatus;
+    }
+
+    public Integer getLiveTotalTime() {
+        return liveTotalTime;
+    }
+
+    public void setLiveTotalTime(Integer liveTotalTime) {
+        this.liveTotalTime = liveTotalTime;
+    }
 }
 

+ 47 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImLiveBroadcastRoomMember.java

@@ -43,6 +43,22 @@ public class ImLiveBroadcastRoomMember implements Serializable {
     @ApiModelProperty(value = "累计观看时间/以分钟为单位")
     private Integer totalTime;
 
+    @TableField("online_status_")
+    @ApiModelProperty(value = "在线状态;0离线;1在线")
+    private Integer onlineStatus;
+
+    @TableField("ban_status_")
+    @ApiModelProperty(value = "禁言状态:0取消;1禁言")
+    private Integer banStatus;
+
+    @TableField("live_room_status_")
+    @ApiModelProperty(value = "直播状态: 0离开;1观看")
+    private Integer liveRoomStatus;
+
+    @TableField("create_time_")
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
     private static final long serialVersionUID = 1L;
 
     public Integer getId() {
@@ -93,5 +109,36 @@ public class ImLiveBroadcastRoomMember implements Serializable {
         this.totalTime = totalTime;
     }
 
+    public Integer getOnlineStatus() {
+        return onlineStatus;
+    }
+
+    public void setOnlineStatus(Integer onlineStatus) {
+        this.onlineStatus = onlineStatus;
+    }
+
+    public Integer getBanStatus() {
+        return banStatus;
+    }
+
+    public void setBanStatus(Integer banStatus) {
+        this.banStatus = banStatus;
+    }
+
+    public Integer getLiveRoomStatus() {
+        return liveRoomStatus;
+    }
+
+    public void setLiveRoomStatus(Integer liveRoomStatus) {
+        this.liveRoomStatus = liveRoomStatus;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
 }
 

+ 30 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/ETencentGroupType.java

@@ -0,0 +1,30 @@
+package com.ym.mec.biz.dal.enums;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2023-03-06
+ */
+public enum ETencentGroupType {
+
+    Public("陌生人社交群"),
+    Work("好友工作群"),
+    AVChatRoom("直播群"),
+    Meeting("临时会议群"),
+    Community("社群"),
+
+    ;
+
+    private String code;
+
+    private String msg;
+
+
+    ETencentGroupType(String msg) {
+        this.code = this.name();
+        this.msg = msg;
+    }
+
+
+}

+ 31 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/ETencentImCallbackCommand.java

@@ -0,0 +1,31 @@
+package com.ym.mec.biz.dal.enums;
+
+import lombok.Getter;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2023-03-02
+ */
+@Getter
+public enum ETencentImCallbackCommand {
+
+    // STATE_STATECHANGE("State.StateChange", "用户状态变更"),
+    GROUP_CALLBACKAFTERMEMBEREXIT("Group.CallbackAfterMemberExit", "群成员离开之后回调"),
+    GROUP_CALLBACKAFTERNEWMEMBERJOIN("Group.CallbackAfterNewMemberJoin", "新成员入群之后回调"),
+    GROUP_CALLBACKONMEMBERSTATECHANGE("Group.CallbackOnMemberStateChange", "直播群成员在线状态回调"),
+    ;
+
+    private final String command;
+    private final String desc;
+
+    private final String code;
+
+    ETencentImCallbackCommand(String command, String desc) {
+        this.command = command;
+        this.desc = desc;
+
+        this.code = this.name();
+    }
+}

+ 3 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/vo/ImLiveBroadcastRoomMemberVo.java

@@ -26,6 +26,9 @@ public class ImLiveBroadcastRoomMemberVo implements java.io.Serializable {
     @ApiModelProperty(value = "学生姓名")
     private String studentName;
 
+    @ApiModelProperty(value = "学生头像")
+    private String avatar;
+
     @ApiModelProperty(value = "手机号")
     private String phone;
 

+ 60 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/vo/ImLiveBroadcastRoomVo.java

@@ -3,6 +3,7 @@ package com.ym.mec.biz.dal.vo;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.microsvc.toolkit.middleware.live.message.LiveRoomConfig;
+import com.ym.mec.auth.api.enums.SysUserType;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -41,6 +42,9 @@ public class ImLiveBroadcastRoomVo implements Serializable {
     @ApiModelProperty(value = "主讲人id/老师id")
     private Integer speakerId;
 
+    @ApiModelProperty("用户类型 TEACHER 老师 EDUCATION 教务端")
+    private SysUserType clientType;
+
     @ApiModelProperty(value = "主讲人名称")
     private String speakerName;
 
@@ -54,6 +58,9 @@ public class ImLiveBroadcastRoomVo implements Serializable {
     @ApiModelProperty(value = "直播状态 0未开始 1开始 2结束")
     private Integer liveState;
 
+    @ApiModelProperty(value = "直播时长")
+    private Integer liveTotalTime;
+
     @ApiModelProperty(value = "房间状态 0正常 1已删除")
     private Integer roomState;
 
@@ -70,7 +77,7 @@ public class ImLiveBroadcastRoomVo implements Serializable {
     private String imToken;
 
     @ApiModelProperty(value = "播出端-  pc网页端 移动端mobile")
-    private String os = "pc";
+    private String os;
 
     @ApiModelProperty(value = "是否在首页推广 0否 1是 - 每个机构只能有一个直播间在首页推广")
     private Integer popularize;
@@ -104,6 +111,26 @@ public class ImLiveBroadcastRoomVo implements Serializable {
     @ApiModelProperty("直播配置")
     private LiveRoomConfig liveRoomConfig;
 
+    @TableField("speaker_status_")
+    @ApiModelProperty(value = "主播状态: 0离开;1在播")
+    private Integer speakerStatus;
+
+    @TableField("push_status_")
+    @ApiModelProperty(value = "推流状态: 0 暂停; 1在播")
+    private Integer pushStatus;
+
+    @TableField("ban_status_")
+    @ApiModelProperty(value = "禁言状态: 0 取消;1禁言")
+    private Integer banStatus;
+
+    public SysUserType getClientType() {
+        return clientType;
+    }
+
+    public void setClientType(SysUserType clientType) {
+        this.clientType = clientType;
+    }
+
     public String getServiceProvider() {
         return serviceProvider;
     }
@@ -351,5 +378,37 @@ public class ImLiveBroadcastRoomVo implements Serializable {
         this.liveRoomConfig = liveRoomConfig;
         return this;
     }
+
+    public Integer getSpeakerStatus() {
+        return speakerStatus;
+    }
+
+    public void setSpeakerStatus(Integer speakerStatus) {
+        this.speakerStatus = speakerStatus;
+    }
+
+    public Integer getPushStatus() {
+        return pushStatus;
+    }
+
+    public void setPushStatus(Integer pushStatus) {
+        this.pushStatus = pushStatus;
+    }
+
+    public Integer getBanStatus() {
+        return banStatus;
+    }
+
+    public void setBanStatus(Integer banStatus) {
+        this.banStatus = banStatus;
+    }
+
+    public Integer getLiveTotalTime() {
+        return liveTotalTime;
+    }
+
+    public void setLiveTotalTime(Integer liveTotalTime) {
+        this.liveTotalTime = liveTotalTime;
+    }
 }
 

+ 1 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/ImLiveBroadcastRoomMemberService.java

@@ -2,6 +2,7 @@ package com.ym.mec.biz.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ym.mec.biz.dal.dao.ImLiveBroadcastRoomMemberDao;
+import com.ym.mec.biz.dal.dto.LiveRoomStatus;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoomMember;
 import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomDetailVo;
 import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomMemberVo;

+ 25 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/ImLiveBroadcastRoomService.java

@@ -2,7 +2,9 @@ package com.ym.mec.biz.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ym.mec.biz.dal.dto.ImLiveBroadcastRoomDto;
+import com.ym.mec.biz.dal.dto.LiveRoomStatus;
 import com.ym.mec.biz.dal.dto.RoomReservationUserSearch;
+import com.ym.mec.biz.dal.dto.TencentData;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoom;
 import com.ym.mec.biz.dal.page.LiveRoomGoodsOrderQueryInfo;
 import com.ym.mec.biz.dal.vo.BaseRoomUserVo;
@@ -126,5 +128,28 @@ public interface ImLiveBroadcastRoomService extends IService<ImLiveBroadcastRoom
      * @param whetherMic 是否连麦 0: 是 1:否
      */
     void whetherMic(String roomUid, Integer whetherMic);
+
+    /**
+     * 更新主播直播间状态
+     *
+     * @param status 直播间状态
+     * @return
+     */
+    Boolean updateRoomStatus(LiveRoomStatus status);
+
+    /**
+     * 直播群成员在线状态回调处理
+     *
+     */
+    void callbackOnMemberStateChange(TencentData.CallbackOnMemberStateChange callbackOnMemberStateChange);
+    /**
+     * 群成员离开之后回调
+     */
+    void callbackAfterMemberExit(TencentData.CallbackAfterMemberExit callbackAfterMemberExit);
+
+    /**
+     * 新成员入群之后回调
+     */
+    void callbackAfterNewMemberJoin(TencentData.CallbackAfterNewMemberJoin callbackAfterNewMemberJoin);
 }
 

+ 3 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/ImLiveRoomBlackService.java

@@ -3,6 +3,7 @@ package com.ym.mec.biz.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.ImLiveRoomBlack;
+import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomVo;
 import com.ym.mec.biz.dal.vo.ImLiveRoomBlackVo;
 import com.ym.mec.common.page.PageInfo;
 
@@ -53,10 +54,10 @@ public interface ImLiveRoomBlackService extends IService<ImLiveRoomBlack> {
     /**
      * 发送黑名单消息到直播房间
      *
-     * @param roomUid    房间uid
+     * @param roomVo    房间
      * @param fromUserId 发送人id
      * @param userId     用户id
      */
-    void sendBlackMsg(String roomUid, Integer fromUserId, Integer userId, String type);
+    void sendBlackMsg(ImLiveBroadcastRoomVo roomVo, Integer fromUserId, Integer userId, String type);
 }
 

+ 522 - 55
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java

@@ -12,14 +12,19 @@ import com.microsvc.toolkit.middleware.live.LivePluginContext;
 import com.microsvc.toolkit.middleware.live.LivePluginService;
 import com.microsvc.toolkit.middleware.live.message.LiveRoomMessage;
 import com.microsvc.toolkit.middleware.live.message.LiveRoomUser;
+import com.microsvc.toolkit.middleware.live.message.RTCRequest;
 import com.microsvc.toolkit.middleware.live.message.RTCRoom;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.auth.api.enums.SysUserType;
 import com.ym.mec.biz.dal.dao.ImLiveBroadcastRoomDao;
+import com.ym.mec.biz.dal.dao.ImLiveBroadcastRoomMemberDao;
 import com.ym.mec.biz.dal.dao.LiveGoodsMapperDao;
 import com.ym.mec.biz.dal.dao.SysConfigDao;
 import com.ym.mec.biz.dal.dto.ImLiveBroadcastRoomDto;
+import com.ym.mec.biz.dal.dto.LiveRoomStatus;
 import com.ym.mec.biz.dal.dto.RoomReservationUserSearch;
+import com.ym.mec.biz.dal.dto.TencentData;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoom;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoomData;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoomMember;
@@ -43,6 +48,8 @@ import com.ym.mec.util.http.HttpUtil;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.jetbrains.annotations.NotNull;
+import org.joda.time.DateTime;
 import org.redisson.api.RBucket;
 import org.redisson.api.RLock;
 import org.redisson.api.RMap;
@@ -58,6 +65,9 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Serializable;
+import java.text.MessageFormat;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
@@ -87,6 +97,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
     @Autowired
     private ImLiveBroadcastRoomMemberService liveBroadcastRoomMemberService;
     @Autowired
+    private ImLiveBroadcastRoomMemberDao liveBroadcastRoomMemberDao;
+    @Autowired
     private ImLiveBroadcastRoomDataService liveBroadcastRoomDataService;
     @Autowired
     private LiveGoodsMapperDao liveGoodsMapperDao;
@@ -228,6 +240,9 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             log.error("直播房间用户注册失败: userId={}", sysUser.getId(), e);
         }
 
+        // 直播房间统计信息
+        getRoomData(room);
+
         // 直播间配置信息
         return room.userSig(userSig).liveRoomConfig(pluginService.getLiveRoomConfig());
     }
@@ -266,6 +281,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         String os = WrapperUtil.toStr(param, "os");
         if (StringUtils.isNotBlank(os) && os.equals("teacher")) {
             param.put("speakerId", getSysUser().getId());
+            param.put("clientType", SysUserType.TEACHER.getCode());
         }
         Page<ImLiveBroadcastRoomVo> pageInfo = PageUtil.concatTimePage(param, "startTime", "endTime");
         pageInfo.setDesc("a.created_time_");
@@ -289,9 +305,6 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                 continue;
             }
             record.setRoomReservationNum(imLiveBroadcastRoomVos.get(0).getRoomReservationNum());
-
-            // 设置直播间参数信息
-
         }
 
         return PageUtil.pageInfo(page);
@@ -328,7 +341,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
     /**
      * 修改直播间信息
      *
-     * @param dto
+     * @param dto ImLiveBroadcastRoomDto
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -587,19 +600,26 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         log.info("roomDestroy>>>> insertAndCleanLiveData {}", JSONObject.toJSONString(room));
 
         //将房间状态改为已销毁
+        ImLiveBroadcastRoom liveRoomUpdate = new ImLiveBroadcastRoom();
+        liveRoomUpdate.setId(room.getId());
+
         Date date = new Date();
-        room.setRoomState(2);
-        room.setLiveState(2);
+        liveRoomUpdate.setRoomState(2);
+        liveRoomUpdate.setLiveState(2);
         Integer userId = -1;
         try {
             userId = getSysUser().getId();
         } catch (Exception ignored) {
         }
-        room.setUpdatedBy(userId);
-        room.setUpdatedTime(date);
-        room.setLiveEndTime(date);
-        room.setPopularize(0);//销毁直播间后要关闭推广
-        this.updateById(room);
+        liveRoomUpdate.setSpeakerStatus(0);
+        liveRoomUpdate.setPushStatus(0);
+        liveRoomUpdate.setUpdatedBy(userId);
+        liveRoomUpdate.setUpdatedTime(date);
+        liveRoomUpdate.setLiveEndTime(date);
+        //销毁直播间后要关闭推广
+        liveRoomUpdate.setPopularize(0);
+
+        this.updateById(liveRoomUpdate);
 
         //下架商品
         liveGoodsMapperDao.updateStatus(room.getRoomUid(), null, false);
@@ -611,10 +631,25 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             message.setFromUserId(speakerId.toString());
             message.setToChatRoomId(roomUid);
             message.setObjectName(ImRoomMessage.FORCED_OFFLINE);
+
+            SysUser sysUser = sysUserFeignService.queryUserInfo();
+            if (Objects.nonNull(sysUser)) {
+
+                // 发送用户信息
+                LiveRoomMessage.MessageUser messageUser = LiveRoomMessage.MessageUser.builder()
+                        .sendUserId(String.valueOf(speakerId))
+                        .sendUserName(sysUser.getUsername())
+                        .avatarUrl(sysUser.getAvatar())
+                        .build();
+
+                message.setContent(LiveRoomMessage.MessageContent.builder().sendUserInfo(messageUser).build());
+            }
+
             LivePluginService pluginService = livePluginContext.getPluginService(room.getServiceProvider());
             pluginService.sendChatRoomMessage(message);
             log.info("roomDestroy>>>> FORCED_OFFLINE {}", JSONObject.toJSONString(message));
             //销毁直播间
+            pluginService.chatRoomDestroy(roomUid);
 //            imFeignService.destroyLiveRoom(roomUid);
             log.info("roomDestroy>>>> destroyLiveRoom {}", JSONObject.toJSONString(message));
         } catch (Exception e) {
@@ -747,11 +782,31 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             if (isSpeaker(user, now, userid, roomUid)) {
                 return;
             }
+
+            //向直播间发送当前在线人数消息
+            ImLiveBroadcastRoomVo roomVo = this.getImLiveBroadcastRoomVo(roomUid);
+            if (Objects.isNull(roomVo)) {
+                log.info("opsRoom>>>> roomVo is null, userState: {}", JSON.toJSONString(userState));
+                return;
+            }
+
+            Integer userId = Integer.valueOf(userid);
             //这里开始只处理观看者的数据,观看者只接受退出消息 status=0 是进入房间
             if (user.getStatus().equals("0")) {
+
+                // 用户进入直播间,发送统计数据
+                sendLiveRoomStatMessage(userid, roomVo);
+
+                // 更新用户在线状态
+                liveBroadcastRoomMemberService.lambdaUpdate()
+                        .eq(ImLiveBroadcastRoomMember::getTenantId, roomVo.getTenantId())
+                        .eq(ImLiveBroadcastRoomMember::getRoomUid, roomVo.getRoomUid())
+                        .eq(ImLiveBroadcastRoomMember::getUserId, userId)
+                        .set(ImLiveBroadcastRoomMember::getOnlineStatus, 1)
+                        .update();
+
                 return;
             }
-            Integer userId = Integer.valueOf(userid);
 
             //从房间累计用户信息中查询该用户的信息
             RMap<Integer, String> roomTotalUser = this.getTotalUserCache(roomUid);
@@ -779,29 +834,130 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             }
             //从在线人员列表删除该人员
             onlineUserInfo.fastRemove(userId);
-            //向直播间发送当前在线人数消息
-            ImLiveBroadcastRoomVo roomVo = this.getImLiveBroadcastRoomVo(roomUid);
-            this.sendOnlineUserCount(roomVo, userId, onlineUserInfo.size());
-            log.info("opsRoom>>>> looker userInfo: {}", JSONObject.toJSONString(userInfo));
-            //用户离开直播间发送退出房间消息给主讲人
-            LiveRoomMessage message = new LiveRoomMessage();
-            message.setIsIncludeSender(1);
-            message.setFromUserId(userId.toString());
-            message.setToChatRoomId(roomUid);
-            message.setObjectName(ImRoomMessage.LOOKER_LOGIN_OUT);
-            message.setContent(userId);
-            try {
-                LivePluginService pluginService = livePluginContext.getPluginService(roomVo.getServiceProvider());
-                pluginService.sendChatRoomMessage(message);
-                log.info("opsRoom>>>> looker LOOKER_LOGIN_OUT : {}", JSONObject.toJSONString(userInfo));
-            } catch (Exception e) {
-                log.error("opsRoom>>>>  looker error LOOKER_LOGIN_OUT {}", e.getMessage());
-                log.error("opsRoom>>>>  looker error sendMessage {} : LOOKER_LOGIN_OUT : {}", message, JSONObject.toJSONString(userInfo));
+
+            // 更新用户离线状态
+            ImLiveBroadcastRoomMember roomMember = new ImLiveBroadcastRoomMember();
+            roomMember.setOnlineStatus(0);
+
+            // 用户离开直播间
+            if (user.getStatus().equals("3")) {
+                roomMember.setLiveRoomStatus(0);
             }
+            // 更新用户在线状态为离线
+            liveBroadcastRoomMemberService.lambdaUpdate()
+                    .eq(ImLiveBroadcastRoomMember::getTenantId, roomVo.getTenantId())
+                    .eq(ImLiveBroadcastRoomMember::getRoomUid, roomVo.getRoomUid())
+                    .eq(ImLiveBroadcastRoomMember::getUserId, userId)
+                    .update(roomMember);
+
+            log.info("opsRoom>>>> looker userInfo: {}", JSONObject.toJSONString(userInfo));
+            // 在线用户消息同步
+            sendOnlineUserCount(roomVo, userId, onlineUserInfo.size());
+
+            // 直播间统计数据
+            sendLiveRoomStatMessage(userid, roomVo);
+
+            // 直播间用户离开消息
+            sendLiveRoomLoginOutMessage(userid, roomVo);
+
         });
     }
 
     /**
+     * 直播间统计数据同步
+     * @param userid 用户Id
+     * @param roomVo ImLiveBroadcastRoomVo
+     */
+    private void sendLiveRoomStatMessage(String userid, ImLiveBroadcastRoomVo roomVo) {
+
+        // 直播间统计数据
+        getRoomData(roomVo);
+
+        // 消息发送用户
+        LiveRoomMessage.MessageUser messageUser = null;
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (Objects.nonNull(sysUser)) {
+            // 发送用户信息
+            messageUser = LiveRoomMessage.MessageUser
+                    .builder()
+                    .sendUserId(sysUser.getId().toString())
+                    .sendUserName(sysUser.getUsername())
+                    .avatarUrl(sysUser.getAvatar())
+                    .build();
+        }
+
+        LiveRoomMessage.MessageContent messageContent = LiveRoomMessage.MessageContent
+                .builder()
+                .onlineUsers(roomVo.getLookNum().longValue())
+                .viewers(roomVo.getTotalLookNum().longValue())
+                .likes(roomVo.getLikeNum().longValue())
+                .sendUserInfo(messageUser)
+                .build();
+
+        LiveRoomMessage message = LiveRoomMessage.builder()
+                .isIncludeSender(1)
+                .objectName(LiveRoomMessage.STAT_SYNC)
+                .fromUserId(userid)
+                .toChatRoomId(roomVo.getRoomUid())
+                .content(messageContent)
+                .build();
+
+        //发送消息
+        try {
+            livePluginContext.getPluginService(roomVo.getServiceProvider()).sendChatRoomMessage(message);
+            log.info("sendLiveRoomStatMessage>>>> message: {}", JSONObject.toJSONString(message));
+        } catch (Exception e) {
+            log.error("sendLiveRoomStatMessage>>>> error {}", e.getMessage());
+            log.error("sendLiveRoomStatMessage>>>> sendMessage {} :", JSONObject.toJSONString(message));
+        }
+
+    }
+
+    /**
+     * 直播间用户离开消息
+     * @param userid 用户id
+     * @param roomVo ImLiveBroadcastRoomVo
+     */
+    private void sendLiveRoomLoginOutMessage(String userid, ImLiveBroadcastRoomVo roomVo) {
+
+        // 消息发送用户
+        LiveRoomMessage.MessageUser messageUser = null;
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (Objects.nonNull(sysUser)) {
+            // 发送用户信息
+            messageUser = LiveRoomMessage.MessageUser
+                    .builder()
+                    .sendUserId(sysUser.getId().toString())
+                    .sendUserName(sysUser.getUsername())
+                    .avatarUrl(sysUser.getAvatar())
+                    .build();
+        }
+
+        LiveRoomMessage.MessageContent messageContent = LiveRoomMessage.MessageContent
+                .builder()
+                .targetId(userid)
+                .sendUserInfo(messageUser)
+                .build();
+
+        LiveRoomMessage message = LiveRoomMessage.builder()
+                .isIncludeSender(1)
+                .objectName(LiveRoomMessage.LOOKER_LOGIN_OUT)
+                .fromUserId(userid)
+                .toChatRoomId(roomVo.getRoomUid())
+                .content(messageContent)
+                .build();
+        try {
+            //用户离开直播间发送退出房间消息给主讲人
+            LivePluginService pluginService = livePluginContext.getPluginService(roomVo.getServiceProvider());
+            pluginService.sendChatRoomMessage(message);
+            log.info("sendLiveRoomLoginOutMessage>>>> looker LOOKER_LOGIN_OUT : roomId={}, userId={}", roomVo.getRoomUid(), userid);
+        } catch (Exception e) {
+            log.error("sendLiveRoomLoginOutMessage>>>>  looker error LOOKER_LOGIN_OUT {}", e.getMessage());
+            log.error("sendLiveRoomLoginOutMessage>>>>  looker error sendMessage {} : LOOKER_LOGIN_OUT : : roomId={}, userId={}", message, roomVo.getRoomUid(), userid);
+        }
+    }
+
+    /**
      * 向直播间发送当前在线人数消息
      *
      * @param roomVo    直播间
@@ -809,20 +965,47 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
      * @param count      人数
      */
     private void sendOnlineUserCount(ImLiveBroadcastRoomVo roomVo, Integer fromUserId, Integer count) {
+
         String roomUid = roomVo.getRoomUid();
         //校验传入参数,房间uid和发送人id不能为空
         if (!WrapperUtil.checkObj(roomUid, fromUserId, count)) {
             log.info(" sendOnlineUserCount>>>> param is null   roomUid: {}  fromUserId:{}  count:{}", roomUid, fromUserId, count);
             return;
         }
-        LiveRoomMessage message = new LiveRoomMessage();
-        message.setIsIncludeSender(1);
-        message.setObjectName(ImRoomMessage.MEMBER_COUNT);
-        message.setToChatRoomId(roomUid);
-        HashMap<String, Integer> sendMap = new HashMap<>();
-        sendMap.put("count", count);
-        message.setFromUserId(fromUserId.toString());
-        message.setContent(sendMap);
+
+        // 直播间统计数据
+        getRoomData(roomVo);
+
+        // 消息发送用户
+        LiveRoomMessage.MessageUser messageUser = null;
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (Objects.nonNull(sysUser)) {
+            // 发送用户信息
+            messageUser = LiveRoomMessage.MessageUser
+                    .builder()
+                    .sendUserId(sysUser.getId().toString())
+                    .sendUserName(sysUser.getUsername())
+                    .avatarUrl(sysUser.getAvatar())
+                    .build();
+        }
+
+        LiveRoomMessage.MessageContent messageContent = LiveRoomMessage.MessageContent
+                .builder()
+                .count(count.longValue())
+                .onlineUsers(roomVo.getLookNum().longValue())
+                .viewers(roomVo.getTotalLookNum().longValue())
+                .likes(roomVo.getLikeNum().longValue())
+                .sendUserInfo(messageUser)
+                .build();
+
+        LiveRoomMessage message = LiveRoomMessage.builder()
+                .isIncludeSender(1)
+                .objectName(LiveRoomMessage.MEMBER_COUNT)
+                .fromUserId(fromUserId.toString())
+                .toChatRoomId(roomUid)
+                .content(messageContent)
+                .build();
+
         //发送消息
         try {
             livePluginContext.getPluginService(roomVo.getServiceProvider()).sendChatRoomMessage(message);
@@ -839,15 +1022,19 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
      * @return true 是主讲人 false 不是主讲人
      */
     private boolean isSpeaker(ImUserState user, Date now, String userid, String roomUid) {
+
         RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userid);
         if (!speakerCache.isExists()) {
             return false;
         }
+
+        // 当前用户为主播
         RoomSpeakerInfo speakerInfo = speakerCache.get();
         //最后一次进入房间的clientIp
         RBucket<String> lastClientIp = redissonClient.getBucket(LIVE_SPEAKER_LAST_CLIENT_IP.replace(ROOM_UID, roomUid).replace(USER_ID, userid));
         //主讲人进入房间
         if (user.getStatus().equals("0")) {
+
             speakerInfo.setJoinRoomTime(now);
             log.info("opsRoom>>>> join speakerCache {}", JSONObject.toJSONString(speakerInfo));
             speakerCache.set(speakerInfo);
@@ -855,6 +1042,14 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             if (StringUtils.isNotBlank(user.getClientIp())) {
                 lastClientIp.set(user.getClientIp());
             }
+
+            // 更新主播在线状态
+            lambdaUpdate()
+                    .eq(ImLiveBroadcastRoom::getRoomUid, roomUid)
+                    .eq(ImLiveBroadcastRoom::getSpeakerId, Integer.parseInt(userid))
+                    .set(ImLiveBroadcastRoom::getSpeakerStatus, 1)
+                    .update();
+
             return true;
         }
         //校验本次退出直播间的clientIp 是不是上次进入房间的clientIp
@@ -870,18 +1065,48 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         if (compareDate.apply(speakerInfo.getExitRoomTime(), speakerInfo.getJoinRoomTime())) {
             return true;
         }
+
         //主讲人退出房间关闭录像
         closeLive(speakerInfo);
+
+        //主讲人退出房间
         speakerInfo.setExitRoomTime(now);
         log.info("opsRoom>>>> exit speakerCache {}", JSONObject.toJSONString(speakerInfo));
         speakerCache.set(speakerInfo);
+
+        //向直播间发送当前在线人数消息
+        ImLiveBroadcastRoomVo roomVo = this.getImLiveBroadcastRoomVo(roomUid);
+        if (Objects.isNull(roomVo)) {
+            log.info("opsRoom>>>> roomVo is null, roomId: {}, userId={}", roomUid, userid);
+            return true;
+        }
+
+        ImLiveBroadcastRoom room = new ImLiveBroadcastRoom();
+        room.setSpeakerStatus(0);
+
+        // 更新推流状态
+        if (user.getStatus().equals("3")) {
+            room.setPushStatus(0);
+        }
+        // 更新主播状态
+        lambdaUpdate()
+                .eq(ImLiveBroadcastRoom::getRoomUid, roomUid)
+                .eq(ImLiveBroadcastRoom::getSpeakerId, Integer.parseInt(userid))
+                .update(room);
+
+        // 腾讯云直播方案,推送主播离开消息
+        if (roomVo.getServiceProvider().equals("tencentCloud")) {
+            // 主播离开消息通知
+            sendLiveRoomLoginOutMessage(userid, roomVo);
+        }
+
         return true;
     }
 
     /**
      * 主讲人登录专用
      *
-     * @param roomUid
+     * @param roomUid 直播间Id
      */
     public ImLiveBroadcastRoomVo speakerJoinRoom(String roomUid, String os) {
         SysUser sysUser = getSysUser();
@@ -899,8 +1124,11 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         //获取直播间信息
         RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString());
         if (!speakerCache.isExists()) {
+
             //没有主讲人信息则生成一个
             createSpeakerInfo(this.getById(roomVo.getId()), sysUser);
+
+            // 查询主播缓存信息
             speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString());
         }
         RoomSpeakerInfo speakerInfo = speakerCache.get();
@@ -908,6 +1136,14 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         speakerCache.set(speakerInfo);
         //记录用户当前房间uid
         redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid, 12L, TimeUnit.HOURS);
+
+        // 更新直播间主播状态
+        lambdaUpdate()
+                .eq(ImLiveBroadcastRoom::getRoomUid, roomUid)
+                .eq(ImLiveBroadcastRoom::getSpeakerId, userId)
+                .set(ImLiveBroadcastRoom::getSpeakerStatus, 1)
+                .update();
+
         return roomVo;
     }
 
@@ -934,11 +1170,30 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         if (roomTotalUser.containsKey(userId)) {
             //多次进入更新动态进入时间
             userInfo = JSONObject.toJavaObject(JSONObject.parseObject(roomTotalUser.get(userId)), RoomUserInfoVo.class);
+
+            ImLiveBroadcastRoomMember liveRoomMember = liveBroadcastRoomMemberService.lambdaQuery()
+                    .eq(ImLiveBroadcastRoomMember::getTenantId, userInfo.getTenantId())
+                    .eq(ImLiveBroadcastRoomMember::getRoomUid, imLiveBroadcastRoomVo.getRoomUid())
+                    .eq(ImLiveBroadcastRoomMember::getUserId, userInfo.getUserId())
+                    .list().stream().findFirst().orElse(null);
+
+            if (Objects.isNull(liveRoomMember)) {
+
+                // 初次进入房间
+                getLiveRoomUserInfo(userId, imLiveBroadcastRoomVo, now);
+            } else {
+                // 更新直播间用户信息
+                ImLiveBroadcastRoomMember roomMember = new ImLiveBroadcastRoomMember();
+                roomMember.setId(liveRoomMember.getId());
+                roomMember.setOnlineStatus(1);
+                roomMember.setLiveRoomStatus(1);
+
+                liveBroadcastRoomMemberService.updateById(roomMember);
+            }
+
         } else {
             //第一次进该房间 写入用户首次进入时间
-            userInfo = getUserInfo(userId);
-            userInfo.setFirstJoinTime(now);
-            userInfo.setTotalViewTime(0);
+            userInfo = getLiveRoomUserInfo(userId, imLiveBroadcastRoomVo, now);
         }
         //查询主讲人信息
         RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, imLiveBroadcastRoomVo.getSpeakerId().toString());
@@ -961,6 +1216,37 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
     }
 
     /**
+     * 获取直播间用户信息
+     * @param userId 用户id
+     * @param imLiveBroadcastRoomVo 直播间信息
+     * @param now 当前时间
+     * @return RoomUserInfoVo
+     */
+    @NotNull
+    private RoomUserInfoVo getLiveRoomUserInfo(Integer userId, ImLiveBroadcastRoomVo imLiveBroadcastRoomVo, Date now) {
+
+        RoomUserInfoVo userInfo = getUserInfo(userId);
+        userInfo.setFirstJoinTime(now);
+        userInfo.setTotalViewTime(0);
+
+        // 记录直播间用户信息
+        ImLiveBroadcastRoomMember roomMember = new ImLiveBroadcastRoomMember();
+        roomMember.setTenantId(userInfo.getTenantId());
+        roomMember.setRoomUid(imLiveBroadcastRoomVo.getRoomUid());
+        roomMember.setUserId(userInfo.getUserId());
+        roomMember.setJoinTime(DateTime.now().toDate());
+        roomMember.setTotalTime(0);
+        roomMember.setOnlineStatus(1);
+        roomMember.setBanStatus(0);
+        roomMember.setLiveRoomStatus(1);
+
+        // 保存直播间用户信息
+        liveBroadcastRoomMemberService.save(roomMember);
+
+        return userInfo;
+    }
+
+    /**
      * 开始直播-录像
      *
      * @param roomUid 房间uid
@@ -995,8 +1281,19 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                     return;
                 }
 
-                pluginService.rtcRoomRecordStop(rtcRoom.getSessionId());
-                // pluginService.rtcRoomRecordStart(roomUid, videoResolution);
+                // 直播开始时间
+                DateTime dateTime = new DateTime(imLiveBroadcastRoomVo.getLiveStartTime());
+
+                RTCRoom.RecordResp recordResp = pluginService.rtcRoomRecordStart(RTCRequest.RecordStart.builder()
+                        .startTime(dateTime.plusMillis(5).getMillis() / 1000)
+                        .endTime(dateTime.plusDays(1).getMillis() / 1000)
+                        .steamName(MessageFormat.format("{0}_{1}", imLiveBroadcastRoomVo.getRoomUid(), String.valueOf(imLiveBroadcastRoomVo.getSpeakerId())))
+                        .sessionId(rtcRoom.getSessionId())
+                        .config(RTCRequest.RecordConfig.builder()
+                                .videoResolution(videoResolution)
+                                .build())
+                        .build());
+                log.info("startLive 直播录录开启: recordResp={}", JSON.toJSONString(recordResp));
             } catch (Exception e) {
                 log.error("startRecord error: {}", e.getMessage());
             }
@@ -1058,6 +1355,11 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                     return;
                 }
 
+                // 若返回的sessionId为空,则手动查询录制任务taskId
+                if (StringUtils.isBlank(rtcRoom.getSessionId())) {
+                    // FIXME: 获取腾讯云直播录制任务Id
+                }
+
                 pluginService.rtcRoomRecordStop(rtcRoom.getSessionId());
             } catch (Exception e) {
                 log.error("stopRecord error: {}", e.getMessage());
@@ -1140,7 +1442,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         List<ImLiveBroadcastRoom> list = this.list(new WrapperUtil<ImLiveBroadcastRoom>()
                 .hasEq("live_state_", 0)
                 .hasEq("room_state_", 0)
-                .hasGe("live_start_time_", now)
+                // .hasGe("live_start_time_", now)
                 .hasLe("live_start_time_", endTime)
                 .queryWrapper());
         if (CollectionUtils.isEmpty(list)) {
@@ -1159,15 +1461,22 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             //生成主讲人信息到缓存
             SysUser sysUser = getSysUser(room.getSpeakerId());
             createSpeakerInfo(room, sysUser);
+
             //去融云创建房间
             LivePluginService pluginService = livePluginContext.getPluginService(room.getServiceProvider());
-            pluginService.chatRoomCreate(room.getRoomUid(),room.getRoomTitle(),sysUser.getId().toString());
+
+            // 注册主播用户信息到三方平台
+            pluginService.register(sysUser.getId().toString(), sysUser.getUsername(), sysUser.getAvatar());
+            // 创建直播间IM群
+            pluginService.chatRoomCreate(room.getRoomUid(), room.getRoomTitle(),sysUser.getId().toString());
 
             // imFeignService.createLiveRoom(room.getRoomUid(), room.getRoomTitle());
             //推送预约直播间消息
             imLiveRoomReservationService.push(room);
+
             //推送直播开始消息
             this.sendRoomLiveState(sysUser, room, MessageTypeEnum.JIGUANG_LIVE_STARTED);
+
         } catch (Exception e) {
             log.error(">>>>>>>>>> createLiveRoom error roomUid:{} msg:{}", room.getRoomUid(), e.getMessage());
         }
@@ -1204,10 +1513,13 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, room.getRoomUid())).set(0);
 
         //修改房间状态为开始
-        room.setLiveState(1);
-        room.setUpdatedTime(now);
-        room.setUpdatedBy(-2);
-        baseMapper.updateById(room);
+        ImLiveBroadcastRoom liveRoomUpdate = new ImLiveBroadcastRoom();
+        liveRoomUpdate.setId(room.getId());
+        liveRoomUpdate.setLiveState(1);
+        liveRoomUpdate.setUpdatedTime(now);
+        liveRoomUpdate.setUpdatedBy(-2);
+        liveRoomUpdate.setSpeakerStatus(1);
+        baseMapper.updateById(liveRoomUpdate);
     }
 
     private Optional<ImLiveBroadcastRoomDto.RoomConfig> getRoomConfig(String roomConfig) {
@@ -1225,12 +1537,17 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
      *             <P>/#/liveRoomList 直播中
      */
     private void sendRoomLiveState(SysUser user, ImLiveBroadcastRoom room, MessageTypeEnum en) {
-        String teacherBaseUrl = sysConfigDao.findConfigValue(SysConfigService.TEACHER_BASE_URL);
-        if (StringUtils.isBlank(teacherBaseUrl)) {
+        String baseUrl;
+        if (room.getClientType().equals(SysUserType.EDUCATION)) {
+            baseUrl=sysConfigDao.findConfigValue(SysConfigService.EDU_TEACHER_BASE_URL);
+        } else {
+            baseUrl=sysConfigDao.findConfigValue(SysConfigService.TEACHER_BASE_URL);
+        }
+        if (StringUtils.isBlank(baseUrl)) {
             log.error("sendRoomState error: teacherBaseUrl is null");
             return;
         }
-        teacherBaseUrl = "13?" + teacherBaseUrl;
+        baseUrl = "13?" + baseUrl;
         Map<Integer, String> pushMap = new HashMap<>();
         pushMap.put(user.getId(), user.getId().toString());
         String memo;
@@ -1240,12 +1557,12 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             //创建直播间
             if (en.equals(MessageTypeEnum.JIGUANG_LIVE_CREATED)) {
                 //创建直播间-发送消息-跳到未开始页面
-                memo = teacherBaseUrl + "/#/liveRoomList?t=0";
+                memo = baseUrl + "/#/liveRoomList?t=0";
                 SysUser createUser = getSysUser(room.getCreatedBy());
                 objs = new Object[]{createUser.getUsername(), liveDateStr, room.getLiveRemark()};
             } else if (en.equals(MessageTypeEnum.JIGUANG_LIVE_STARTED)) {
                 //直播开始-发送消息-跳到直播中页面
-                memo = teacherBaseUrl + "/#/liveRoomList";
+                memo = baseUrl + "/#/liveRoomList";
                 objs = new Object[]{liveDateStr, room.getRoomTitle()};
             } else {
                 log.error("sendRoomState error: MessageTypeEnum error " + en);
@@ -1493,6 +1810,156 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         this.updateById(imLiveBroadcastRoom);
     }
 
+    /**
+     * 更新主播直播间状态
+     *
+     * @param liveRoom 直播间状态
+     */
+    @Override
+    public Boolean updateRoomStatus(LiveRoomStatus liveRoom) {
+        // 获取直播间信息
+        ImLiveBroadcastRoomVo room = this.getImLiveBroadcastRoomVo(liveRoom.getRoomUid());
+        if (room == null) {
+            throw new BizException("直播间不存在");
+        }
+        ImLiveBroadcastRoom imLiveBroadcastRoom = new ImLiveBroadcastRoom();
+        imLiveBroadcastRoom.setId(room.getId());
+        imLiveBroadcastRoom.setSpeakerStatus(liveRoom.getSpeakerStatus());
+        imLiveBroadcastRoom.setPushStatus(liveRoom.getPushStatus());
+        imLiveBroadcastRoom.setBanStatus(liveRoom.getBanStatus());
+        imLiveBroadcastRoom.setLiveTotalTime(liveRoom.getLiveTotalTime());
+
+        return this.updateById(imLiveBroadcastRoom);
+    }
+
+
+    /**
+     * 直播群成员在线状态回调处理
+     *
+     * @param callbackOnMemberStateChange
+     */
+    @Override
+    @Transactional
+    public void callbackOnMemberStateChange(TencentData.CallbackOnMemberStateChange callbackOnMemberStateChange) {
+
+        if (callbackOnMemberStateChange == null) {
+            return;
+        }
+
+        Integer onlineStatus = callbackOnMemberStateChange.getEventType().equals("Online")?1:0;
+
+        // 用户id
+        if (CollectionUtils.isEmpty(callbackOnMemberStateChange.getMemberList())) {
+            return;
+        }
+        List<Long> userIds = callbackOnMemberStateChange.getMemberList()
+                                                        .stream()
+                                                        .map(o -> Long.parseLong(o.getMemberAccount()))
+                                                        .collect(Collectors.toList());
+
+
+        List<ImLiveBroadcastRoomMember> imLiveBroadcastRoomMembers = liveBroadcastRoomMemberDao.queryMember(userIds,
+                                                                                                            callbackOnMemberStateChange.getGroupId());
+
+        if (CollectionUtils.isEmpty(imLiveBroadcastRoomMembers)) {
+            return;
+        }
+
+        // 根据用户id分组
+        Map<Integer, ImLiveBroadcastRoomMember> userMap = imLiveBroadcastRoomMembers.stream()
+                                                                                    .collect(Collectors.toMap(ImLiveBroadcastRoomMember::getUserId,o ->o, (k1, k2) -> k1));
+
+        List<ImUserState> imUserStates = new ArrayList<>();
+        for (Long userId : userIds) {
+            Integer liveRoomStatus = userMap.getOrDefault(userId.intValue(), new ImLiveBroadcastRoomMember())
+                                           .getLiveRoomStatus();
+            ImUserState imUserState = new ImUserState();
+            imUserState.setUserid(userId.toString());
+            imUserState.setStatus(onlineStatus == 1 && liveRoomStatus == 1?"0":"1");
+            imUserState.setOs(callbackOnMemberStateChange.getOptPlatform());
+            imUserState.setTime(new Date().getTime());
+            imUserState.setClientIp(callbackOnMemberStateChange.getClientIP());
+            imUserStates.add(imUserState);
+        }
+        opsRoom(imUserStates);
+        liveBroadcastRoomMemberDao.updateOnlineStatus(userIds, callbackOnMemberStateChange.getGroupId(),onlineStatus);
+    }
+
+    @Override
+    public void callbackAfterMemberExit(TencentData.CallbackAfterMemberExit callbackAfterMemberExit) {
+        if (callbackAfterMemberExit == null) {
+            return;
+        }
+
+        Integer liveRoomStatus = 0;
+
+        // 用户id
+        if (CollectionUtils.isEmpty(callbackAfterMemberExit.getExitMemberList())) {
+            return;
+        }
+        List<Long> userIds = callbackAfterMemberExit.getExitMemberList()
+                                                        .stream()
+                                                        .map(o -> Long.parseLong(o.getMemberAccount()))
+                                                        .collect(Collectors.toList());
+
+
+        List<ImUserState> imUserStates = new ArrayList<>();
+        for (Long userId : userIds) {
+            ImUserState imUserState = new ImUserState();
+            imUserState.setUserid(userId.toString());
+            imUserState.setStatus("3");
+            imUserState.setOs(callbackAfterMemberExit.getOptPlatform());
+            imUserState.setTime(callbackAfterMemberExit.getEventTime().atZone(ZoneId.systemDefault()).toEpochSecond());
+            imUserState.setClientIp(callbackAfterMemberExit.getClientIP());
+            imUserStates.add(imUserState);
+        }
+        opsRoom(imUserStates);
+        liveBroadcastRoomMemberDao.updateLiveRoomStatus(userIds, callbackAfterMemberExit.getGroupId(),liveRoomStatus);
+    }
+
+    @Override
+    public void callbackAfterNewMemberJoin(TencentData.CallbackAfterNewMemberJoin callbackAfterNewMemberJoin) {
+        if (callbackAfterNewMemberJoin == null) {
+            return;
+        }
+
+        Integer liveRoomStatus = 1;
+
+        // 用户id
+        if (CollectionUtils.isEmpty(callbackAfterNewMemberJoin.getNewMemberList())) {
+            return;
+        }
+        List<Long> userIds = callbackAfterNewMemberJoin.getNewMemberList()
+                                                    .stream()
+                                                    .map(o -> Long.parseLong(o.getMemberAccount()))
+                                                    .collect(Collectors.toList());
+
+
+        List<ImLiveBroadcastRoomMember> imLiveBroadcastRoomMembers = liveBroadcastRoomMemberDao.queryMember(userIds,
+                                                                                    callbackAfterNewMemberJoin.getGroupId());
+
+        if (CollectionUtils.isEmpty(imLiveBroadcastRoomMembers)) {
+            return;
+        }
+
+        // 根据用户id分组
+        Map<Integer, ImLiveBroadcastRoomMember> userMap = imLiveBroadcastRoomMembers.stream()
+                .collect(Collectors.toMap(ImLiveBroadcastRoomMember::getUserId,o ->o, (k1, k2) -> k1));
+
+        List<ImUserState> imUserStates = new ArrayList<>();
+        for (Long userId : userIds) {
+            ImUserState imUserState = new ImUserState();
+            imUserState.setUserid(userId.toString());
+            imUserState.setStatus(userMap.getOrDefault(userId.intValue(), new ImLiveBroadcastRoomMember()).getOnlineStatus() == 1 ? "0" : "1");
+            imUserState.setOs(callbackAfterNewMemberJoin.getOptPlatform());
+            imUserState.setTime(callbackAfterNewMemberJoin.getEventTime().atZone(ZoneId.systemDefault()).toEpochSecond());
+            imUserState.setClientIp(callbackAfterNewMemberJoin.getClientIP());
+            imUserStates.add(imUserState);
+        }
+        opsRoom(imUserStates);
+        liveBroadcastRoomMemberDao.updateLiveRoomStatus(userIds, callbackAfterNewMemberJoin.getGroupId(),liveRoomStatus);
+    }
+
 
     /**
      * 查询直播间所有用户信息

+ 32 - 11
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveRoomBlackServiceImpl.java

@@ -5,11 +5,16 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.microsvc.toolkit.middleware.live.LivePluginContext;
+import com.microsvc.toolkit.middleware.live.LivePluginService;
+import com.microsvc.toolkit.middleware.live.message.LiveRoomMessage;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.ImLiveRoomBlackDao;
 import com.ym.mec.biz.dal.entity.ImLiveRoomBlack;
+import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomVo;
 import com.ym.mec.biz.dal.vo.ImLiveRoomBlackVo;
+import com.ym.mec.biz.service.ImLiveBroadcastRoomService;
 import com.ym.mec.biz.service.ImLiveRoomBlackService;
 import com.ym.mec.common.entity.ImRoomMessage;
 import com.ym.mec.common.exception.BizException;
@@ -17,7 +22,6 @@ import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.page.PageUtil;
 import com.ym.mec.common.page.WrapperUtil;
 import com.ym.mec.common.tenant.TenantContextHolder;
-import com.ym.mec.im.ImFeignService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -40,7 +44,9 @@ public class ImLiveRoomBlackServiceImpl extends ServiceImpl<ImLiveRoomBlackDao,
     @Autowired
     private SysUserFeignService sysUserFeignService;
     @Autowired
-    private ImFeignService imFeignService;
+    private LivePluginContext livePluginContext;
+    @Autowired
+    private ImLiveBroadcastRoomService imLiveBroadcastRoomService;
 
     /**
      * 查询当前机构学生 -下拉框
@@ -73,6 +79,7 @@ public class ImLiveRoomBlackServiceImpl extends ServiceImpl<ImLiveRoomBlackDao,
     public void add(Map<String, Object> param) {
         String roomUid = WrapperUtil.toStr(param, "roomUid");
         List<String> userIdList = WrapperUtil.toList(WrapperUtil.toStr(param, "userIdList", "用户id不能为空"));
+
         userIdList.forEach(userIdStr -> {
             Integer userId = Integer.parseInt(userIdStr);
             int count = this.count(Wrappers.<ImLiveRoomBlack>lambdaQuery()
@@ -88,10 +95,16 @@ public class ImLiveRoomBlackServiceImpl extends ServiceImpl<ImLiveRoomBlackDao,
             imLiveRoomBlack.setCreateBy(getSysUser().getId());
             imLiveRoomBlack.setCreateTime(new Date());
             this.save(imLiveRoomBlack);
+            ImLiveBroadcastRoomVo roomVo = imLiveBroadcastRoomService.queryRoomInfo(roomUid);
             //发送消息到直播房间
-            this.sendBlackMsg(roomUid, userId, userId, ImRoomMessage.BLOCK_BLACK_USER);
+            this.sendBlackMsg(roomVo, userId, userId, ImRoomMessage.BLOCK_BLACK_USER);
             //调用融云方法加入禁言
-            imFeignService.addUserUnableSpeak(roomUid, userIdStr);
+            LivePluginService pluginService = livePluginContext.getPluginService(roomVo.getServiceProvider());
+            try {
+                pluginService.chatRoomUserGagCreate(userIdStr, roomUid, -1);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
         });
     }
 
@@ -107,15 +120,21 @@ public class ImLiveRoomBlackServiceImpl extends ServiceImpl<ImLiveRoomBlackDao,
     public void delete(Map<String, Object> param) {
         String roomUid = WrapperUtil.toStr(param, "roomUid");
         List<String> userIdList = WrapperUtil.toList(WrapperUtil.toStr(param, "userIdList", "用户id不能为空"));
+        ImLiveBroadcastRoomVo roomVo = imLiveBroadcastRoomService.queryRoomInfo(roomUid);
         userIdList.forEach(userIdStr -> {
             Integer userId = Integer.parseInt(userIdStr);
             this.remove(Wrappers.<ImLiveRoomBlack>lambdaQuery()
                     .eq(ImLiveRoomBlack::getRoomUid, roomUid)
                     .eq(ImLiveRoomBlack::getUserId, userId));
             //发送消息到直播房间
-            this.sendBlackMsg(roomUid, userId, userId, ImRoomMessage.UNBLOCK_BLACK_USER);
+            this.sendBlackMsg(roomVo, userId, userId, ImRoomMessage.UNBLOCK_BLACK_USER);
             //调用融云方法加入禁言
-            imFeignService.removeUserUnableSpeak(roomUid, userIdStr);
+            LivePluginService pluginService = livePluginContext.getPluginService(roomVo.getServiceProvider());
+            try {
+                pluginService.chatRoomuserGagRemove(userIdStr,roomUid);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
         });
     }
 
@@ -136,27 +155,29 @@ public class ImLiveRoomBlackServiceImpl extends ServiceImpl<ImLiveRoomBlackDao,
     /**
      * 发送黑名单消息到直播房间
      *
-     * @param roomUid    房间uid
+     * @param roomVo    房间uid
      * @param fromUserId 发送人id
      * @param userId     用户id
      */
-    public void sendBlackMsg(String roomUid, Integer fromUserId, Integer userId, String type) {
+    public void sendBlackMsg(ImLiveBroadcastRoomVo roomVo, Integer fromUserId, Integer userId, String type) {
+        String roomUid = roomVo.getRoomUid();
         //校验传入参数,房间uid和发送人id不能为空
         if (!WrapperUtil.checkObj(roomUid, fromUserId, userId, type)) {
             log.info(" sendBlackMsg>>>> param is null   roomUid: {}  fromUserId:{}  type:{}", roomUid, fromUserId, type);
             return;
         }
-        ImRoomMessage message = new ImRoomMessage();
+        LiveRoomMessage message = new LiveRoomMessage();
         message.setIsIncludeSender(1);
         message.setObjectName(type);
-        message.setToChatroomId(roomUid);
+        message.setToChatRoomId(roomUid);
         HashMap<String, Integer> sendMap = new HashMap<>();
         sendMap.put("userId", userId);
         message.setFromUserId(fromUserId.toString());
         message.setContent(sendMap);
         //发送消息
         try {
-            imFeignService.publishRoomMsg(message);
+            LivePluginService pluginService = livePluginContext.getPluginService(roomVo.getServiceProvider());
+            pluginService.sendChatRoomMessage(message);
             log.info("sendBlackMsg>>>> message: {}", JSONObject.toJSONString(message));
         } catch (Exception e) {
             log.error("sendBlackMsg>>>> error {}", e.getMessage());

+ 0 - 5
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveRoomReservationServiceImpl.java

@@ -1,7 +1,6 @@
 package com.ym.mec.biz.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -10,11 +9,9 @@ import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.ImLiveRoomReservationDao;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoom;
 import com.ym.mec.biz.dal.entity.ImLiveRoomReservation;
-import com.ym.mec.biz.dal.entity.Student;
 import com.ym.mec.biz.dal.enums.MessageTypeEnum;
 import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomVo;
 import com.ym.mec.biz.service.ImLiveRoomReservationService;
-import com.ym.mec.biz.service.StudentService;
 import com.ym.mec.biz.service.SysMessageService;
 import com.ym.mec.common.exception.BizException;
 import com.ym.mec.common.page.PageInfo;
@@ -46,8 +43,6 @@ public class ImLiveRoomReservationServiceImpl extends ServiceImpl<ImLiveRoomRese
     @Autowired
     private SysUserFeignService sysUserFeignService;
     @Autowired
-    private StudentService studentService;
-    @Autowired
     private SysMessageService sysMessageService;
 
     /**

+ 0 - 3
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImSendGroupMessageServiceImpl.java

@@ -3,7 +3,6 @@ package com.ym.mec.biz.service.impl;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.ImSendGroupMessageDao;
-import com.ym.mec.biz.dal.dao.SysConfigDao;
 import com.ym.mec.biz.dal.entity.ImSendGroupMessage;
 import com.ym.mec.biz.dal.enums.ImSendTypeEnum;
 import com.ym.mec.biz.service.ImSendGroupMessageService;
@@ -28,8 +27,6 @@ public class ImSendGroupMessageServiceImpl extends BaseServiceImpl<Long, ImSendG
 	private SysMessageService sysMessageService;
 	@Autowired
 	private SysUserFeignService sysUserFeignService;
-	@Autowired
-	private SysConfigDao sysConfigDao;
 
 	@Override
 	public BaseDAO<Long, ImSendGroupMessage> getDAO() {

+ 11 - 6
mec-biz/src/main/java/com/ym/mec/biz/service/impl/LiveGoodsMapperServiceImpl.java

@@ -1,6 +1,8 @@
 package com.ym.mec.biz.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.microsvc.toolkit.middleware.live.LivePluginContext;
+import com.microsvc.toolkit.middleware.live.message.LiveRoomMessage;
 import com.ym.mec.biz.dal.dao.LiveGoodsMapperDao;
 import com.ym.mec.biz.dal.dto.LiveGoodsMapperDto;
 import com.ym.mec.biz.dal.dto.RedisKeyConstant;
@@ -15,7 +17,6 @@ import com.ym.mec.common.entity.ImRoomMessage;
 import com.ym.mec.common.exception.BizException;
 import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
-import com.ym.mec.im.ImFeignService;
 import com.ym.mec.util.collection.MapUtil;
 import org.apache.commons.collections.CollectionUtils;
 import org.redisson.api.RedissonClient;
@@ -24,7 +25,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.*;
-import java.util.stream.Collectors;
 
 @Service
 public class LiveGoodsMapperServiceImpl extends BaseServiceImpl<Integer, LiveGoodsMapper>  implements LiveGoodsMapperService {
@@ -34,7 +34,7 @@ public class LiveGoodsMapperServiceImpl extends BaseServiceImpl<Integer, LiveGoo
 	@Autowired
 	private LiveGoodsMapperDao liveGoodsMapperDao;
 	@Autowired
-	private ImFeignService imFeignService;
+	private LivePluginContext livePluginContext;
 	@Autowired
 	private ImLiveBroadcastRoomService imLiveBroadcastRoomService;
 	@Autowired
@@ -104,13 +104,18 @@ public class LiveGoodsMapperServiceImpl extends BaseServiceImpl<Integer, LiveGoo
 	}
 
 	private void publishRoomMsg(ImLiveBroadcastRoom imLiveBroadcastRoom) {
-		ImRoomMessage message = new ImRoomMessage();
+		LiveRoomMessage message = new LiveRoomMessage();
 		message.setIsIncludeSender(1);
 		message.setObjectName(ImRoomMessage.LIVE_GOODS_CHANGE);
-		message.setToChatroomId(imLiveBroadcastRoom.getRoomUid());
+		message.setToChatRoomId(imLiveBroadcastRoom.getRoomUid());
 		message.setFromUserId(imLiveBroadcastRoom.getSpeakerId().toString());
 		message.setContent(liveGoodsMapperDao.getLiveGoodsList(imLiveBroadcastRoom.getRoomUid(),null,true));
-		imFeignService.publishRoomMsg(message);
+		try {
+			livePluginContext.getPluginService(imLiveBroadcastRoom.getServiceProvider())
+					.sendChatRoomMessage(message);
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
 	}
 
 	@Override

+ 11 - 0
mec-biz/src/main/resources/config/mybatis/ImLiveBroadcastRoomMapper.xml

@@ -47,17 +47,22 @@
         a.room_title_ AS roomTitle,
         a.live_remark_ AS liveRemark,
         a.speaker_id_ AS speakerId,
+        a.client_type_ as clientType,
         b.real_name_ AS speakerName,
         b.im_token_ as imToken,
         b.avatar_ AS speakerPic,
         a.live_start_time_ AS liveStartTime,
         a.live_state_ AS liveState,
+        a.live_total_time_ AS liveTotalTime,
         a.room_state_ AS roomState,
         c.real_name_ AS createdByName,
         a.pre_template_ AS preTemplate,
         a.room_config_ AS roomConfig,
         a.popularize_ AS popularize,
         a.popularize_type_ AS popularizeType,
+        a.speaker_status_ AS speakerStatus,
+        a.push_status_ AS pushStatus,
+        a.ban_status_ AS banStatus,
         a.service_provider_ as serviceProvider
         from im_live_broadcast_room as a
         left join tenant_info AS t on a.tenant_id_ = t.id_
@@ -92,6 +97,12 @@
             <if test="param.speakerId != null">
                 and  a.speaker_id_ = #{param.speakerId}
             </if>
+            <if test="param.serviceProvider != null and param.serviceProvider != ''">
+                and  a.service_provider_ = #{param.serviceProvider}
+            </if>
+            <if test="param.clientType != null and param.clientType != ''">
+                and  a.client_type_ = #{param.clientType}
+            </if>
         </where>
     </select>
 

+ 21 - 2
mec-biz/src/main/resources/config/mybatis/ImLiveBroadcastRoomMemberMapper.xml

@@ -17,11 +17,11 @@
 
     <insert id="insertBatch" keyColumn="id_" keyProperty="id" useGeneratedKeys="true"
             parameterType="com.ym.mec.biz.dal.entity.ImLiveBroadcastRoomMember">
-        insert into im_live_broadcast_room_member(tenant_id_, room_uid_, user_id_, join_time_, total_time_)
-        values
+        insert into im_live_broadcast_room_member(tenant_id_, room_uid_, user_id_, join_time_, total_time_) values
         <foreach collection="entities" item="entity" separator=",">
             (#{entity.tenantId}, #{entity.roomUid}, #{entity.userId}, #{entity.joinTime}, #{entity.totalTime})
         </foreach>
+        ON DUPLICATE KEY UPDATE join_time_ = VALUES(join_time_), total_time_ = VALUES(total_time_)
     </insert>
 
     <select id="queryMemberPage" resultType="com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomMemberVo">
@@ -30,6 +30,7 @@
         tu.real_name_ speakerName,
         a.user_id_ as studentId,
         su.username_ as studentName,
+        su.avatar_ as avatar,
         su.phone_ as phone,
         b.name_ as subName,
         o.name_ organName,
@@ -55,4 +56,22 @@
         group by a.user_id_
     </select>
 
+    <update id="updateOnlineStatus">
+        update im_live_broadcast_room_member
+        set online_status_ = #{onlineStatus}
+        where room_uid_ = #{groupId} and user_id_ in <foreach collection="userIds" item="userId" open="(" separator="," close=")">#{userId}</foreach>
+    </update>
+
+    <update id="updateLiveRoomStatus">
+        update im_live_broadcast_room_member
+        set live_room_status_ = #{onlineStatus}
+        where room_uid_ = #{groupId} and user_id_ in <foreach collection="userIds" item="userId" open="(" separator="," close=")">#{userId}</foreach>
+
+    </update>
+
+    <select id="queryMember" resultType="com.ym.mec.biz.dal.entity.ImLiveBroadcastRoomMember">
+        select * from im_live_broadcast_room_member
+        where room_uid_ = #{groupId} and user_id_ in <foreach collection="userIds" item="userId" open="(" separator="," close=")">#{userId}</foreach>
+
+    </select>
 </mapper>

+ 1 - 0
mec-biz/src/main/resources/config/mybatis/ImLiveRoomReservationMapper.xml

@@ -43,6 +43,7 @@
         a.pre_template_ AS preTemplate,
         a.room_config_ AS roomConfig,
         a.popularize_ AS popularize,
+        a.service_provider_ as serviceProvider,
         a.popularize_type_ AS popularizeType,
         IF(d.user_id_ is null, 0, 1) as reserve
         from (

+ 1 - 1
mec-common/common-core/src/main/java/com/ym/mec/common/controller/BaseController.java

@@ -88,7 +88,7 @@ public class BaseController {
 		if (e == null) {
 			e = ex;
 		}
-		logger.error("System Error", ex);
+		logger.error("System Error", e);
 		// return failed(e.getMessage());
 		if (e instanceof BizException || e instanceof ThirdpartyException) {
 			if(e.getMessage().equals("205")){

+ 3 - 0
mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImRoomMessage.java

@@ -24,6 +24,9 @@ public class ImRoomMessage extends BaseMessage {
     //objectName 类型-在黑名单中解除该用户
     public static final String UNBLOCK_BLACK_USER = "RC:UNBLOCK_BLACK_USER";
 
+    //objectName 类型-用户点赞数同步
+    public static final String LIKES_COUNT = "RC:Chatroom:LikeCount";
+
     /**
      * <p>必传
      * 消息类型

+ 2 - 2
mec-im/src/main/java/com/ym/config/ResourceServerConfig.java

@@ -12,11 +12,11 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
     public void configure(HttpSecurity http) throws Exception {
         http.authorizeRequests().antMatchers("/v2/api-docs", "/user/register",
                         "/group/join", "/group/create", "/group/quit", "/room/leave", "/room/statusSync",
-                        "/room/statusImMsg", "/group/batchDismiss", "/private/send", "/group/send",
+                        "/room/statusImMsg", "/group/batchDismiss", "/private/send", "/group/send", "/user/tencentImCallback",
                         "/group/dismiss", "/room/statusImMsg", "/history/get", "/user/statusImUser", "/liveRoom/recordSync",
                         "/liveRoom/publishRoomMsg", "/liveRoom/destroy", "/liveRoom/create", "/liveRoom/startRecord",
                         "/liveRoom/stopRecord", "/liveRoom/userExistInRoom","/liveRoom/checkOnline",
-                        "/liveRoom/addUserUnableSpeak","/liveRoom/removeUserUnableSpeak","/liveRoom/syncChatRoomStatus")
+                        "/liveRoom/addUserUnableSpeak","/liveRoom/removeUserUnableSpeak","/liveRoom/syncChatRoomStatus","/liveRoom/tencentImCallback")
                 .permitAll().anyRequest().authenticated().and().csrf().disable();
     }
 }

+ 6 - 0
mec-im/src/main/java/com/ym/controller/LiveRoomController.java

@@ -1,9 +1,13 @@
 package com.ym.controller;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.ym.mec.biz.dal.enums.ETencentImCallbackCommand;
 import com.ym.mec.common.entity.ImRoomMessage;
 import com.ym.pojo.IMApiResultInfo;
 import com.ym.pojo.RecordNotify;
+import com.ym.mec.biz.dal.dto.TencentData;
+import com.ym.mec.biz.dal.dto.TencentImCallbackResult;
 import com.ym.service.LiveRoomService;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -13,6 +17,8 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * @author hgw
  * Created by 2022-02-21

+ 51 - 1
mec-im/src/main/java/com/ym/controller/UserController.java

@@ -1,16 +1,22 @@
 package com.ym.controller;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.ym.common.BaseResponse;
+import com.ym.mec.biz.dal.dto.TencentData;
+import com.ym.mec.biz.dal.dto.TencentImCallbackResult;
+import com.ym.mec.biz.dal.enums.ETencentImCallbackCommand;
 import com.ym.mec.biz.service.ImLiveBroadcastRoomService;
 import com.ym.mec.common.entity.ImUserState;
 import com.ym.service.UserService;
 import io.rong.models.user.UserModel;
+import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 
 @RestController
@@ -35,7 +41,7 @@ public class UserController {
     /**
      * 监听融云用户状态变更
      *
-     * @param userState
+     * @param userState List<ImUserState>
      */
     @PostMapping(value = "/statusImUser")
     public BaseResponse statusImUser(@RequestBody List<ImUserState> userState) {
@@ -43,4 +49,48 @@ public class UserController {
         imLiveBroadcastRoomService.opsRoom(userState);
         return new BaseResponse<>();
     }
+
+
+    @ApiOperation("腾讯im 回调接口")
+    @PostMapping(value = "/tencentImCallback")
+    public TencentImCallbackResult tencentImCallback(@RequestBody String body, HttpServletRequest request) {
+        log.info("tencentImCallback body:{}", body);
+
+        log.info("tencentImCallback request param:{}", JSON.toJSONString(request.getParameterMap()));
+
+        String clientIP = request.getParameter("ClientIP");
+        String optPlatform = request.getParameter("OptPlatform");
+
+
+        if(request.getParameter("CallbackCommand").equals(ETencentImCallbackCommand.GROUP_CALLBACKONMEMBERSTATECHANGE.name())) {
+            TencentData.CallbackOnMemberStateChange callbackOnMemberStateChange = TencentData.CallbackOnMemberStateChange.toObject(
+                body);
+
+            log.debug("callbackOnMemberStateChange: {}", callbackOnMemberStateChange);
+            callbackOnMemberStateChange.setClientIP(clientIP);
+            callbackOnMemberStateChange.setOptPlatform(optPlatform);
+            imLiveBroadcastRoomService.callbackOnMemberStateChange(callbackOnMemberStateChange);
+
+
+        } else if(request.getParameter("CallbackCommand").equals(ETencentImCallbackCommand.GROUP_CALLBACKAFTERMEMBEREXIT.name())) {
+            TencentData.CallbackAfterMemberExit callbackAfterMemberExit = TencentData.CallbackAfterMemberExit.toObject(
+                body);
+
+            log.debug("callbackAfterMemberExit: {}", callbackAfterMemberExit);
+            callbackAfterMemberExit.setClientIP(clientIP);
+            callbackAfterMemberExit.setOptPlatform(optPlatform);
+            imLiveBroadcastRoomService.callbackAfterMemberExit(callbackAfterMemberExit);
+        }  else if(request.getParameter("CallbackCommand").equals(ETencentImCallbackCommand.GROUP_CALLBACKAFTERNEWMEMBERJOIN.name())) {
+            TencentData.CallbackAfterNewMemberJoin callbackAfterNewMemberJoin = TencentData.CallbackAfterNewMemberJoin.toObject(
+                body);
+
+            log.debug("CallbackAfterNewMemberJoin: {}", callbackAfterNewMemberJoin);
+            callbackAfterNewMemberJoin.setClientIP(clientIP);
+            callbackAfterNewMemberJoin.setOptPlatform(optPlatform);
+            imLiveBroadcastRoomService.callbackAfterNewMemberJoin(callbackAfterNewMemberJoin);
+        }
+
+
+        return new TencentImCallbackResult();
+    }
 }

+ 4 - 12
mec-student/src/main/resources/logback-spring.xml

@@ -52,15 +52,7 @@
 
 	<!--本地环境:打印控制台 -->
 	<springProfile name="local">
-		<root level="INFO">
-			<appender-ref ref="stdout" />
-			<appender-ref ref="file" />
-		</root>
-	</springProfile>
-
-	<!--本地环境:打印控制台 -->
-	<springProfile name="local">
-		<root level="INFO">
+		<root level="DEBUG">
 			<appender-ref ref="stdout" />
 			<appender-ref ref="file" />
 		</root>
@@ -68,21 +60,21 @@
 
 	<!--开发环境:打印控制台 -->
 	<springProfile name="dev">
-		<root level="INFO">
+		<root level="DEBUG">
 			<appender-ref ref="stdout" />
 			<appender-ref ref="file" />
 		</root>
 	</springProfile>
 
 	<springProfile name="test">
-		<root level="INFO">
+		<root level="DEBUG">
 			<appender-ref ref="stdout" />
 			<appender-ref ref="file" />
 		</root>
 	</springProfile>
 
 	<springProfile name="dev_server">
-		<root level="INFO">
+		<root level="DEBUG">
 			<appender-ref ref="stdout" />
 			<appender-ref ref="file" />
 		</root>

+ 31 - 3
mec-teacher/src/main/java/com/ym/mec/teacher/controller/TeacherImLiveBroadcastRoomController.java

@@ -1,18 +1,31 @@
 package com.ym.mec.teacher.controller;
 
+import com.ym.mec.biz.dal.dto.LiveRoomStatus;
 import com.ym.mec.biz.dal.dto.RoomReservationUserSearch;
 import com.ym.mec.biz.dal.page.LiveRoomGoodsOrderQueryInfo;
 import com.ym.mec.biz.dal.vo.BaseRoomUserVo;
+import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomMemberVo;
 import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomVo;
 import com.ym.mec.biz.dal.vo.LiveRoomGoodsOrderVo;
 import com.ym.mec.biz.dal.vo.RoomReservationUserVo;
+import com.ym.mec.biz.service.ImLiveBroadcastRoomMemberService;
 import com.ym.mec.biz.service.ImLiveBroadcastRoomService;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.entity.HttpResponseResult;
-import com.ym.mec.common.entity.ImUserState;
 import com.ym.mec.common.page.PageInfo;
-import io.swagger.annotations.*;
-import org.springframework.web.bind.annotation.*;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+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.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
@@ -35,6 +48,8 @@ public class TeacherImLiveBroadcastRoomController extends BaseController {
      */
     @Resource
     private ImLiveBroadcastRoomService imLiveBroadcastRoomService;
+    @Autowired
+    private ImLiveBroadcastRoomMemberService imLiveBroadcastRoomMemberService;
 
     @ApiImplicitParams({
             @ApiImplicitParam(name = "search", dataType = "String", value = "模糊查询关键字"),
@@ -150,5 +165,18 @@ public class TeacherImLiveBroadcastRoomController extends BaseController {
     public HttpResponseResult<PageInfo<LiveRoomGoodsOrderVo>> queryLiveRoomGoodsOrderList(LiveRoomGoodsOrderQueryInfo queryInfo) {
         return succeed(imLiveBroadcastRoomService.queryLiveRoomGoodsOrderList(queryInfo));
     }
+
+    @ApiOperation("分页查询直播间人员列表")
+    @PostMapping("/queryRoomMember")
+    public HttpResponseResult<PageInfo<ImLiveBroadcastRoomMemberVo>> queryRoomMember(@RequestBody Map<String, Object> param) {
+        return succeed(imLiveBroadcastRoomMemberService.queryRoomMember(param));
+    }
+
+
+    @ApiOperation("更新直播间状态")
+    @PostMapping("/updateRoomStatus")
+    public HttpResponseResult<Boolean> updateRoomStatus(@RequestBody @Valid LiveRoomStatus status ) {
+        return succeed(imLiveBroadcastRoomService.updateRoomStatus(status));
+    }
 }
 

+ 59 - 0
mec-teacher/src/main/java/com/ym/mec/teacher/controller/TeacherImLiveBroadcastRoomMemberController.java

@@ -0,0 +1,59 @@
+package com.ym.mec.teacher.controller;
+
+import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomDetailVo;
+import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomMemberVo;
+import com.ym.mec.biz.service.ImLiveBroadcastRoomMemberService;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
+import com.ym.mec.common.page.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Map;
+
+/**
+ * 直播间人员关系表(ImLiveBroadcastRoomMember)表控制层
+ *
+ * @author hgw
+ * @since 2022-02-21 14:26:58
+ */
+@Api(tags = "直播间人员关系表")
+@RestController
+@RequestMapping("/imLiveBroadcastRoomMember")
+public class TeacherImLiveBroadcastRoomMemberController extends BaseController {
+    /**
+     * 服务对象
+     */
+    @Resource
+    private ImLiveBroadcastRoomMemberService imLiveBroadcastRoomMemberService;
+
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "roomUid", dataType = "String", value = "房间uid")
+    })
+    @ApiOperation("直播间详情")
+    @PostMapping("/queryRoomDetail")
+    public HttpResponseResult<ImLiveBroadcastRoomDetailVo> queryRoomDetail(@RequestBody Map<String, Object> param) {
+        return succeed(imLiveBroadcastRoomMemberService.queryRoomDetail(param));
+    }
+
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "search", dataType = "String", value = "模糊搜索 学员编号姓名"),
+            @ApiImplicitParam(name = "roomUid", dataType = "String", value = "房间uid"),
+            @ApiImplicitParam(name = "page", dataType = "Integer", value = "页数"),
+            @ApiImplicitParam(name = "rows", dataType = "Integer", value = "每页数量"),
+    })
+    @ApiOperation("分页查询直播间人员列表")
+    @PostMapping("/queryRoomMember")
+    public HttpResponseResult<PageInfo<ImLiveBroadcastRoomMemberVo>> queryRoomMember(@RequestBody Map<String, Object> param) {
+        return succeed(imLiveBroadcastRoomMemberService.queryRoomMember(param));
+    }
+
+}
+

+ 3 - 3
mec-teacher/src/main/resources/logback-spring.xml

@@ -60,21 +60,21 @@
 
 	<!--开发环境:打印控制台 -->
 	<springProfile name="dev">
-		<root level="INFO">
+		<root level="DEBUG">
 			<appender-ref ref="stdout" />
 			<appender-ref ref="file" />
 		</root>
 	</springProfile>
 
 	<springProfile name="test">
-		<root level="INFO">
+		<root level="DEBUG">
 			<appender-ref ref="stdout" />
 			<appender-ref ref="file" />
 		</root>
 	</springProfile>
 
 	<springProfile name="dev_server">
-		<root level="INFO">
+		<root level="DEBUG">
 			<appender-ref ref="stdout" />
 			<appender-ref ref="file" />
 		</root>

+ 4 - 1
mec-web/pom.xml

@@ -70,7 +70,10 @@
 			<groupId>com.yonge.datasource</groupId>
 			<artifactId>dynamic-datasource</artifactId>
 		</dependency>
-
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-api</artifactId>
+		</dependency>
 	</dependencies>
 	<build>
 		<plugins>

+ 21 - 2
mec-web/src/main/java/com/ym/mec/web/controller/ImLiveBroadcastRoomController.java

@@ -1,6 +1,7 @@
 package com.ym.mec.web.controller;
 
 import com.ym.mec.biz.dal.dto.ImLiveBroadcastRoomDto;
+import com.ym.mec.biz.dal.dto.LiveRoomStatus;
 import com.ym.mec.biz.dal.dto.RoomReservationUserSearch;
 import com.ym.mec.biz.dal.page.LiveRoomGoodsOrderQueryInfo;
 import com.ym.mec.biz.dal.vo.BaseRoomUserVo;
@@ -13,9 +14,19 @@ import com.ym.mec.common.entity.HttpResponseResult;
 import com.ym.mec.common.entity.ImUserState;
 import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.page.WrapperUtil;
-import io.swagger.annotations.*;
+import io.swagger.annotations.Api;
+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.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+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 javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
@@ -33,6 +44,7 @@ import java.util.concurrent.CompletableFuture;
  */
 @Api(tags = "直播房间管理表")
 @RestController
+@Slf4j
 @RequestMapping("/imLiveBroadcastRoom")
 public class ImLiveBroadcastRoomController extends BaseController {
     /**
@@ -47,6 +59,7 @@ public class ImLiveBroadcastRoomController extends BaseController {
             @ApiImplicitParam(name = "startTime", dataType = "String", value = "开始时间"),
             @ApiImplicitParam(name = "endTime", dataType = "String", value = "结束时间"),
             @ApiImplicitParam(name = "popularize", dataType = "Integer", value = "是否在首页推广 0否 1是"),
+            @ApiImplicitParam(name = "clientType", dataType = "String", value = "用户类型 TEACHER 老师 EDUCATION 教务端"),
             @ApiImplicitParam(name = "page", dataType = "Integer", value = "页数"),
             @ApiImplicitParam(name = "rows", dataType = "Integer", value = "每页数量"),
     })
@@ -234,5 +247,11 @@ public class ImLiveBroadcastRoomController extends BaseController {
     public HttpResponseResult<PageInfo<LiveRoomGoodsOrderVo>> queryLiveRoomGoodsOrderList(LiveRoomGoodsOrderQueryInfo queryInfo) {
         return succeed(imLiveBroadcastRoomService.queryLiveRoomGoodsOrderList(queryInfo));
     }
+
+    @ApiOperation("更新直播间状态")
+    @PostMapping("/updateRoomStatus")
+    public HttpResponseResult<Boolean> updateRoomStatus(@RequestBody @Valid LiveRoomStatus status ) {
+        return succeed(imLiveBroadcastRoomService.updateRoomStatus(status));
+    }
 }
 

+ 3 - 3
mec-web/src/main/resources/logback-spring.xml

@@ -80,21 +80,21 @@
 
     <!--开发环境:打印控制台 -->
     <springProfile name="dev">
-        <root level="INFO">
+        <root level="DEBUG">
             <appender-ref ref="stdout"/>
             <appender-ref ref="file"/>
         </root>
     </springProfile>
 
     <springProfile name="test">
-        <root level="INFO">
+        <root level="DEBUG">
             <appender-ref ref="stdout"/>
             <appender-ref ref="file"/>
         </root>
     </springProfile>
 
     <springProfile name="dev_server">
-        <root level="INFO">
+        <root level="DEBUG">
             <appender-ref ref="stdout"/>
             <appender-ref ref="file"/>
         </root>