Przeglądaj źródła

网络教室改造

zouxuan 2 lat temu
rodzic
commit
f960953f0b
21 zmienionych plików z 829 dodań i 772 usunięć
  1. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleStudentPaymentDao.java
  2. 30 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ETencentGroupType.java
  3. 31 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ETencentImCallbackCommand.java
  4. 57 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ETencentTRTCCallbackCommand.java
  5. 4 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkBaseDto.java
  6. 4 30
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkCustomMessage.java
  7. 7 6
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkDeviceControlDto.java
  8. 15 23
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkMetronomeMessage.java
  9. 17 6
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkMusicSheetDownloadMessage.java
  10. 7 95
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkMusicSheetDownloadMessageContent.java
  11. 2 40
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkRoomMusicSheetDownloadData.java
  12. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkRoomResult.java
  13. 34 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/RoomStatusNotify.java
  14. 2 33
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImNetworkRoomMemberStatusService.java
  15. 4 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImNetworkRoomService.java
  16. 17 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImService.java
  17. 7 56
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImNetworkRoomMemberStatusServiceImpl.java
  18. 118 411
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImNetworkRoomServiceImpl.java
  19. 380 17
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImServiceImpl.java
  20. 6 4
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/RoomServiceImpl.java
  21. 85 44
      cooleshow-user/user-classroom/src/main/java/com/yonge/cooleshow/classroom/controller/RoomController.java

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

@@ -86,6 +86,6 @@ public interface CourseScheduleStudentPaymentDao extends BaseMapper<CourseSchedu
     //查询报课学员
     List<CourseScheduleStudentVo> selectUser();
 
-    List<BasicUserInfo> queryNoJoinStu(@Param("scheduleId") Long scheduleId);
+    List<BasicUserInfo> queryNoJoinStu(@Param("scheduleId") String scheduleId);
 }
 

+ 30 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ETencentGroupType.java

@@ -0,0 +1,30 @@
+package com.yonge.cooleshow.biz.dal.dto;
+
+/**
+ * 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
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ETencentImCallbackCommand.java

@@ -0,0 +1,31 @@
+package com.yonge.cooleshow.biz.dal.dto;
+
+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();
+    }
+}

+ 57 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ETencentTRTCCallbackCommand.java

@@ -0,0 +1,57 @@
+package com.yonge.cooleshow.biz.dal.dto;
+
+import lombok.Getter;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2023-03-02
+ */
+@Getter
+public enum ETencentTRTCCallbackCommand {
+
+    // 房间事件
+    EVENT_TYPE_CREATE_ROOM("101", "创建房间"),
+    EVENT_TYPE_DISMISS_ROOM("102", "解散房间"),
+    EVENT_TYPE_ENTER_ROOM("103", "进入房间"),
+    EVENT_TYPE_EXIT_ROOM("104", "退出房间"),
+
+    // 媒体事件
+    EVENT_TYPE_START_VIDEO("201", "开始推送视频数据"),
+    EVENT_TYPE_STOP_VIDEO("202", "停止推送视频数据"),
+    EVENT_TYPE_START_AUDIO("203", "开始推送音频数据"),
+    EVENT_TYPE_STOP_AUDIO("204", "停止推送音频数据"),
+    EVENT_TYPE_START_ASSIT("205", "开始推送辅路数据"),
+    EVENT_TYPE_STOP_ASSIT("206", "停止推送辅路数据"),
+
+    EVENT_DEFAULT("-1", "默认无效事件"),
+    ;
+
+    private final String command;
+    private final String desc;
+
+    private final Integer code;
+
+    ETencentTRTCCallbackCommand(String command, String desc) {
+        this.command = command;
+        this.desc = desc;
+
+        // 枚举转换对象
+        this.code = Integer.parseInt(command);
+    }
+
+    /**
+     * 回调事件对象枚举
+     * @param eventType 事件类型
+     * @return ETencentTRTCCallbackCommand
+     */
+    public static ETencentTRTCCallbackCommand get(Integer eventType) {
+        for (ETencentTRTCCallbackCommand e : ETencentTRTCCallbackCommand.values()) {
+            if (e.getCode().equals(eventType)) {
+                return e;
+            }
+        }
+        return EVENT_DEFAULT;
+    }
+}

+ 4 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkBaseDto.java

@@ -8,7 +8,10 @@ import lombok.Data;
 public class ImNetworkBaseDto {
 
     @ApiModelProperty(value = "房间号(课程编号)",required = true)
-    private Long roomId;
+    private String roomId;
+
+    @ApiModelProperty(value = "设备号",required = true)
+    private String deviceNum;
 
     @ApiModelProperty("客户端类型 ")
     private ClientEnum clientType;

+ 4 - 30
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkCustomMessage.java

@@ -1,26 +1,12 @@
 package com.yonge.cooleshow.biz.dal.dto;
 
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
-import io.rong.messages.BaseMessage;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-import org.apache.commons.lang3.StringUtils;
 
 @Data
-public class ImNetworkCustomMessage extends BaseMessage {
-    @ApiModelProperty(value = "节拍器开关",required = true)
-    private boolean enable;
-
-    @ApiModelProperty(value = "消息类型(移动端定义,具体的类型不太清楚)",required = true)
-    private int customType;
-
-    @ApiModelProperty(value = "速度",required = true)
-    private int rate;
-
-    @ApiModelProperty(value = "音量",required = true)
-    private int playVolume;
-
-    @ApiModelProperty(value = "学员编号列表,都还分割",required = true)
+public class ImNetworkCustomMessage{
+    @ApiModelProperty(value = "学员编号列表,逗号分割",required = true)
     private String userId;
 
     @ApiModelProperty(value = "当前用户")
@@ -35,18 +21,6 @@ public class ImNetworkCustomMessage extends BaseMessage {
     @ApiModelProperty("服务提供方")
     private String serviceProvider;
 
-    @Override
-    public String getType() {
-        return "DY:PlayMidiMessage";
-    }
-
-    @Override
-    public String toString() {
-        return "{\"enable\":" + enable +
-                ", \"customType\":" + customType +
-                ", \"rate\":" + rate +
-                ", \"playVolume\":" + playVolume +
-                ", \"userId\":" + (StringUtils.isEmpty(userId)?"\"\"":"\"" + userId + "\"") +
-                '}';
-    }
+    @ApiModelProperty("消息内容JSON")
+    private String content;
 }

+ 7 - 6
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkDeviceControlDto.java

@@ -16,9 +16,12 @@ public class ImNetworkDeviceControlDto {
 	@ApiModelProperty(value = "房间号",required = true)
 	private String roomId;
 
-	@ApiModelProperty(value = "IM用户ID",required = true)
+	@ApiModelProperty(value = "用户ID",required = true)
 	private String userId;
 
+	@ApiModelProperty(value = "IM用户ID",required = true)
+	private String imUserId;
+
 	@ApiModelProperty(value = "ticket",required = true)
 	private String ticket;
 
@@ -29,7 +32,7 @@ public class ImNetworkDeviceControlDto {
 	private Integer musicSheetId;
 
 	@ApiModelProperty(value = "伴奏",required = true)
-	private Integer musicSheetAccompanimentId;
+	private Integer accompanimentId;
 
 	@ApiModelProperty(value = "伴奏音量",required = true)
 	private Integer soundVolume = 100;
@@ -37,8 +40,6 @@ public class ImNetworkDeviceControlDto {
 	@ApiModelProperty("客户端类型 ")
 	private ClientEnum clientType;
 
-	// 发送用户信息
-	private String sendUserId;
-	private String sendUserName;
-	private String avatar;
+	@ApiModelProperty("服务提供方")
+	private String serviceProvider;
 }

+ 15 - 23
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkMetronomeMessage.java

@@ -1,38 +1,30 @@
 package com.yonge.cooleshow.biz.dal.dto;
 
 import com.yonge.cooleshow.biz.dal.entity.BaseMessage;
+import lombok.Data;
 import org.apache.commons.lang3.StringUtils;
 
 //节拍器消息
+@Data
 public class ImNetworkMetronomeMessage extends BaseMessage {
-    private ImNetworkCustomMessage content;
+    private Boolean enable;
+    private int customType;
+    private int rate;
+    private int playVolume;
+    private String userId;
 
-    private static final transient String TYPE = "DY:PlayMidiMessage";
-
-    public ImNetworkMetronomeMessage(ImNetworkCustomMessage content) {
-        this.content = content;
-    }
-
-    public ImNetworkCustomMessage getContent() {
-        return content;
-    }
-
-    public void setContent(ImNetworkCustomMessage content) {
-        this.content = content;
+    @Override
+    public String getObjectName() {
+        return "DY:PlayMidiMessage";
     }
 
     @Override
     public String toString() {
-        return "{\"enable\":" + content.isEnable() +
-                ", \"customType\":" + content.getCustomType() +
-                ", \"rate\":" + content.getRate() +
-                ", \"playVolume\":" + content.getPlayVolume() +
-                ", \"userId\":" + (StringUtils.isEmpty(content.getUserId())?"\"\"":"\"" + content.getUserId() + "\"") +
+        return "{\"enable\":" + enable +
+                ", \"customType\":" + customType +
+                ", \"rate\":" + rate +
+                ", \"playVolume\":" + playVolume +
+                ", \"userId\":" + (StringUtils.isEmpty(userId)?"\"\"":"\"" + userId + "\"") +
                 '}';
     }
-
-    @Override
-    public String getObjectName() {
-        return TYPE;
-    }
 }

+ 17 - 6
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkMusicSheetDownloadMessage.java

@@ -2,7 +2,9 @@ package com.yonge.cooleshow.biz.dal.dto;
 
 
 import com.yonge.cooleshow.biz.dal.entity.BaseMessage;
+import lombok.Data;
 
+@Data
 public class ImNetworkMusicSheetDownloadMessage extends BaseMessage {
     
     private ImNetworkMusicSheetDownloadMessageContent content;
@@ -13,12 +15,21 @@ public class ImNetworkMusicSheetDownloadMessage extends BaseMessage {
         this.content = content;
     }
 
-    public ImNetworkMusicSheetDownloadMessageContent getContent() {
-        return content;
-    }
-
-    public void setContent(ImNetworkMusicSheetDownloadMessageContent content) {
-        this.content = content;
+    @Override
+    public String toString() {
+        return "{\"id\":\"" + content.getId() +
+                "\", \"examSongId\":\"" + content.getExamSongId() +
+                "\", \"subjectId\":\"" + content.getSubjectId() +
+                "\", \"subjectName\":\"" + content.getSubjectName() +
+                "\", \"mp3Url\":\"" + content.getMp3Url() +
+                "\", \"speed\":\"" + content.getSpeed() +
+                "\", \"xmlUrl\":\"" + content.getXmlUrl() +
+                "\", \"examSongName\":\"" + content.getExamSongName() +
+                "\", \"categoriesName\":\"" + content.getCategoriesName() +
+                "\", \"categoriesId\":\"" + content.getCategoriesId() +
+                "\", \"type\":\"" + content.getType() +
+                "\", \"url\":\"" + content.getUrl() +
+                "\"}";
     }
 
     @Override

+ 7 - 95
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkMusicSheetDownloadMessageContent.java

@@ -2,8 +2,10 @@ package com.yonge.cooleshow.biz.dal.dto;
 
 
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
+@Data
 public class ImNetworkMusicSheetDownloadMessageContent{
     //伴奏编号
     @ApiModelProperty(value = "伴奏编号")
@@ -11,7 +13,7 @@ public class ImNetworkMusicSheetDownloadMessageContent{
 
     //曲目编号
     @ApiModelProperty(value = "曲目编号")
-    private Integer musicSheetId;
+    private Integer examSongId;
 
     //声部
     @ApiModelProperty(value = "声部")
@@ -52,101 +54,11 @@ public class ImNetworkMusicSheetDownloadMessageContent{
     @ApiModelProperty(value = "url")
     private String url = "";
 
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-
-    public Integer getMusicSheetId() {
-        return musicSheetId;
-    }
-
-    public void setMusicSheetId(Integer musicSheetId) {
-        this.musicSheetId = musicSheetId;
-    }
-
-    public Integer getSubjectId() {
-        return subjectId;
-    }
-
-    public void setSubjectId(Integer subjectId) {
-        this.subjectId = subjectId;
-    }
-
-    public String getSubjectName() {
-        return subjectName;
-    }
-
-    public void setSubjectName(String subjectName) {
-        this.subjectName = subjectName;
-    }
-
-    public String getMp3Url() {
-        return mp3Url;
-    }
-
-    public void setMp3Url(String mp3Url) {
-        this.mp3Url = mp3Url;
-    }
-
-    public Integer getSpeed() {
-        return speed;
-    }
-
-    public void setSpeed(Integer speed) {
-        this.speed = speed;
-    }
+    //服务提供商
+    private String serviceProvider;
 
-    public String getXmlUrl() {
-        return xmlUrl;
-    }
-
-    public void setXmlUrl(String xmlUrl) {
-        this.xmlUrl = xmlUrl;
-    }
-
-    public String getExamSongName() {
-        return examSongName;
-    }
-
-    public void setExamSongName(String examSongName) {
-        this.examSongName = examSongName;
-    }
-
-    public String getCategoriesName() {
-        return categoriesName;
-    }
-
-    public void setCategoriesName(String categoriesName) {
-        this.categoriesName = categoriesName;
-    }
-
-    public Integer getCategoriesId() {
-        return categoriesId;
-    }
-
-    public void setCategoriesId(Integer categoriesId) {
-        this.categoriesId = categoriesId;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
+    //房间号
+    private String roomId;
 
     @Override
     public String toString() {

+ 2 - 40
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkRoomMusicSheetDownloadData.java

@@ -1,8 +1,10 @@
 package com.yonge.cooleshow.biz.dal.dto;
 
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
 
 //网络教室伴奏下载信息
+@Data
 public class ImNetworkRoomMusicSheetDownloadData {
     @ApiModelProperty(value = "伴奏下载状态(1下载成功0下载中2下载失败)")
     private Integer status;
@@ -18,44 +20,4 @@ public class ImNetworkRoomMusicSheetDownloadData {
 
     @ApiModelProperty(value = "是否开启伴奏")
     private Boolean enable = false;
-
-    public Boolean getEnable() {
-        return enable;
-    }
-
-    public void setEnable(Boolean enable) {
-        this.enable = enable;
-    }
-
-    public Integer getStatus() {
-        return status;
-    }
-
-    public void setStatus(Integer status) {
-        this.status = status;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-    public String getMusicSheetName() {
-        return musicSheetName;
-    }
-
-    public void setMusicSheetName(String musicSheetName) {
-        this.musicSheetName = musicSheetName;
-    }
-
-    public Long getMusicSheetId() {
-        return musicSheetId;
-    }
-
-    public void setMusicSheetId(Long musicSheetId) {
-        this.musicSheetId = musicSheetId;
-    }
 }

+ 1 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkRoomResult.java

@@ -26,7 +26,7 @@ public class ImNetworkRoomResult extends ImNetworkRoom {
     private ImNetworkRoomMember roomMember;
 
     @ApiModelProperty(value = "节拍器参数")
-    private ImNetworkCustomMessage midiJson = new ImNetworkCustomMessage();
+    private ImNetworkMetronomeMessage midiJson = new ImNetworkMetronomeMessage();
 
     @ApiModelProperty("RTC接入参数")
     private RTCRoomConfig rtcRoomConfig;

+ 34 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/RoomStatusNotify.java

@@ -0,0 +1,34 @@
+package com.yonge.cooleshow.biz.dal.dto;
+
+
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class RoomStatusNotify {
+	@ApiModelProperty("房间号")
+	private String roomId;
+
+	@ApiModelProperty("用户编号")
+	private String userId;
+
+	@ApiModelProperty("设备号")
+	private String deviceNum;
+
+	@ApiModelProperty("状态")
+	private boolean requestStatus;
+
+	@ApiModelProperty("客户端类型 ")
+	private ClientEnum clientType;
+
+
+	@Override
+	public String toString() {
+		return "RoomStatusNotify{" +
+				"roomId='" + roomId + '\'' +
+				", userId='" + userId + '\'' +
+				", requestStatus=" + requestStatus +
+				'}';
+	}
+}

+ 2 - 33
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImNetworkRoomMemberStatusService.java

@@ -1,11 +1,9 @@
 package com.yonge.cooleshow.biz.dal.service;
 
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.yonge.cooleshow.biz.dal.dto.ImNetworkCustomMessage;
+import com.yonge.cooleshow.biz.dal.dto.ImNetworkMetronomeMessage;
 import com.yonge.cooleshow.biz.dal.dto.ImNetworkRoomMusicSheetDownloadData;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMember;
-import com.yonge.cooleshow.biz.dal.wrapper.ImNetworkRoomMemberStatusWrapper;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMemberStatus;
 
 /**
@@ -14,39 +12,10 @@ import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMemberStatus;
  */
 public interface ImNetworkRoomMemberStatusService extends IService<ImNetworkRoomMemberStatus>  {
 
-	/**
-     * 查询详情
-     * @param id 详情ID
-     * @return ImNetworkRoomMemberStatus
-     */
-	ImNetworkRoomMemberStatus detail(Long id);
-
-    /**
-     * 分页查询
-     * @param page IPage<ImNetworkRoomMemberStatus>
-     * @param query ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatusQuery
-     * @return IPage<ImNetworkRoomMemberStatus>
-     */
-    IPage<ImNetworkRoomMemberStatus> selectPage(IPage<ImNetworkRoomMemberStatus> page, ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatusQuery query);
-	
-    /**
-     * 添加
-     * @param imNetworkRoomMemberStatus ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatus
-     * @return Boolean
-     */
-     Boolean add(ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatus imNetworkRoomMemberStatus);   
-
-    /**
-     * 更新
-     * @param imNetworkRoomMemberStatus ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatus
-     * @return Boolean
-     */
-     Boolean update(ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatus imNetworkRoomMemberStatus);
-
     void add(ImNetworkRoomMember roomMember);
 
     //获取网络教室成员midi
-    ImNetworkCustomMessage getMemberMidi(String roomId, Long userId);
+    ImNetworkMetronomeMessage getMemberMidi(String roomId, Long userId);
 
     //获取伴奏信息
     ImNetworkRoomMusicSheetDownloadData getMemberExamSong(String roomId, Long userId);

+ 4 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImNetworkRoomService.java

@@ -22,7 +22,9 @@ public interface ImNetworkRoomService extends IService<ImNetworkRoom> {
     ImNetworkRoomDao getDao();
 
     //加入网络教室
-    BaseResponse<ImNetworkRoomResult> joinRoom(Long courseScheduleId, ClientEnum clientType) throws Exception;
+    BaseResponse<ImNetworkRoomResult> joinRoom(String roomId, ClientEnum clientType) throws Exception;
+
+    BaseResponse<ImNetworkRoomResult> roomInfo(ImNetworkBaseDto imNetworkBaseDto);
 
     //加入网络教室成功
     void joinRoomSuccess(String roomId, String imUserId) throws Exception;
@@ -61,6 +63,6 @@ public interface ImNetworkRoomService extends IService<ImNetworkRoom> {
     void deviceStatusSync(ImNetworkDeviceControlDto deviceStatusSync) throws Exception;
 
     //查询不在教室的学员
-    List<BasicUserInfo> queryNoJoinStu(Long roomId);
+    List<BasicUserInfo> queryNoJoinStu(String roomId);
 }
 

+ 17 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImService.java

@@ -1,9 +1,11 @@
 package com.yonge.cooleshow.biz.dal.service;
 
+import com.yonge.cooleshow.biz.dal.dto.BasicUserInfo;
 import com.yonge.cooleshow.biz.dal.dto.ImNetworkCustomMessage;
+import com.yonge.cooleshow.biz.dal.dto.ImNetworkDeviceControlDto;
+import com.yonge.cooleshow.biz.dal.dto.ImNetworkMusicSheetDownloadMessageContent;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoom;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMember;
-import org.springframework.transaction.annotation.Transactional;
 
 /**
  * 网络教室成员(ImNetworkRoomMember)表服务接口
@@ -13,13 +15,26 @@ import org.springframework.transaction.annotation.Transactional;
  */
 public interface ImService{
 
-
     //发送人员变动消息
     void publishMemberChangedMessage(ImNetworkRoomMember roomMember,String serviceProvider) throws Exception;
 
     //发送display改动通知
     void sendDisplay(String imUserId, ImNetworkRoom room,String serviceProvider) throws Exception;
 
+    //发送节拍器消息
     void sendImPlayMidiMessage(ImNetworkCustomMessage customMessage) throws Exception;
+
+    //通知学员下载伴奏
+    void pushDownloadMusicSheetMsg(ImNetworkMusicSheetDownloadMessageContent content, BasicUserInfo userInfo) throws Exception;
+
+    void pushDeviceResourceMessage(ImNetworkDeviceControlDto deviceControl,BasicUserInfo teacher) throws Exception;
+
+    //用户同意设备控制
+    void pushApproveControlDevice(ImNetworkDeviceControlDto deviceControl, ImNetworkRoomMember roomMember
+            ,BasicUserInfo student,BasicUserInfo teacher) throws Exception;
+
+    void sendDeviceStatusSync(ImNetworkDeviceControlDto deviceStatusSync, ImNetworkRoomMember roomMember) throws Exception;
+
+    void sendRejectControlDevice(ImNetworkDeviceControlDto deviceControl, ImNetworkRoomMember roomMember, BasicUserInfo teacher) throws Exception;
 }
 

+ 7 - 56
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImNetworkRoomMemberStatusServiceImpl.java

@@ -1,20 +1,16 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.yonge.cooleshow.biz.dal.dto.ImNetworkCustomMessage;
+import com.yonge.cooleshow.biz.dal.dto.ImNetworkMetronomeMessage;
 import com.yonge.cooleshow.biz.dal.dto.ImNetworkRoomMusicSheetDownloadData;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMember;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.beans.BeanUtils;
-import lombok.extern.slf4j.Slf4j;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMemberStatus;
-import com.yonge.cooleshow.biz.dal.wrapper.ImNetworkRoomMemberStatusWrapper;
 import com.yonge.cooleshow.biz.dal.mapper.ImNetworkRoomMemberStatusMapper;
 import com.yonge.cooleshow.biz.dal.service.ImNetworkRoomMemberStatusService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -25,51 +21,6 @@ import org.springframework.transaction.annotation.Transactional;
 @Service
 public class ImNetworkRoomMemberStatusServiceImpl extends ServiceImpl<ImNetworkRoomMemberStatusMapper, ImNetworkRoomMemberStatus> implements ImNetworkRoomMemberStatusService {
 
-	/**
-     * 查询详情
-     * @param id 详情ID
-     * @return ImNetworkRoomMemberStatus
-     */
-	@Override
-    public ImNetworkRoomMemberStatus detail(Long id) {
-        
-        return baseMapper.selectById(id);
-    }
-    
-    /**
-     * 分页查询
-     * @param page IPage<ImNetworkRoomMemberStatus>
-     * @param query ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatusQuery
-     * @return IPage<ImNetworkRoomMemberStatus>
-     */
-    @Override
-    public IPage<ImNetworkRoomMemberStatus> selectPage(IPage<ImNetworkRoomMemberStatus> page, ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatusQuery query) {
-        
-        return page.setRecords(baseMapper.selectPage(page, query));
-    }
-	
-    /**
-     * 添加
-     * @param imNetworkRoomMemberStatus ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatus
-     * @return Boolean
-     */
-    @Override
-    public Boolean add(ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatus imNetworkRoomMemberStatus) {    	
-        
-        return this.save(JSON.parseObject(imNetworkRoomMemberStatus.jsonString(), ImNetworkRoomMemberStatus.class));
-    }
-
-    /**
-     * 更新
-     * @param imNetworkRoomMemberStatus ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatus
-     * @return Boolean
-     */
-    @Override
-    public Boolean update(ImNetworkRoomMemberStatusWrapper.ImNetworkRoomMemberStatus imNetworkRoomMemberStatus){
-
-        return this.updateById(JSON.parseObject(imNetworkRoomMemberStatus.jsonString(), ImNetworkRoomMemberStatus.class));       
-    }
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void add(ImNetworkRoomMember roomMember) {
@@ -81,13 +32,13 @@ public class ImNetworkRoomMemberStatusServiceImpl extends ServiceImpl<ImNetworkR
     }
 
     @Override
-    public ImNetworkCustomMessage getMemberMidi(String roomId, Long userId) {
+    public ImNetworkMetronomeMessage getMemberMidi(String roomId, Long userId) {
         String midi = this.lambdaQuery().eq(ImNetworkRoomMemberStatus::getRoomId,roomId)
                 .eq(ImNetworkRoomMemberStatus::getUserId,userId).last("LIMIT 1").one().getPlayMidi();
         if(StringUtils.isNotEmpty(midi)){
-            return JSONObject.parseObject(midi, ImNetworkCustomMessage.class);
+            return JSONObject.parseObject(midi, ImNetworkMetronomeMessage.class);
         }
-        return new ImNetworkCustomMessage();
+        return new ImNetworkMetronomeMessage();
     }
 
     @Override

+ 118 - 411
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImNetworkRoomServiceImpl.java

@@ -80,11 +80,8 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
     private StudentAttendanceService studentAttendanceService;
     @Resource
     private TeacherAttendanceService teacherAttendanceService;
-    @Autowired
-    private RTCRoomPluginContext rtcRoomPluginContext;
     @Resource
     private RedisTemplate<String,Object> redisTemplate;
-
     @Autowired
     private ImGroupService imGroupService;
     @Autowired
@@ -94,8 +91,6 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
     @Autowired
     private ImService imService;
 
-    private String QUIT_ROOM_SUCCESS = "quitRoomSuccess:";
-
     @Override
     public ImNetworkRoomDao getDao() {
         return this.baseMapper;
@@ -103,18 +98,18 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public BaseResponse<ImNetworkRoomResult> joinRoom(Long courseScheduleId, ClientEnum clientType) throws Exception {
+    public BaseResponse<ImNetworkRoomResult> joinRoom(String roomId, ClientEnum clientType) throws Exception {
         // 当前登录用户ID
         Long userId = sysUserService.getUserId();
-        CourseSchedule courseSchedule = Optional.ofNullable(courseScheduleService.getById(courseScheduleId)).
+        CourseSchedule courseSchedule = Optional.ofNullable(courseScheduleService.getById(roomId)).
                 orElseThrow(()->new BizException("房间信息不存在"));
 
         RoleEnum userRole = RoleEnum.RoleStudent;
-        if(courseSchedule.getTeacherId().equals(userId) && ClientEnum.TEACHER == clientType){
-            // 与老师帐号匹配,且来自老师客户端
+        if(clientType == ClientEnum.TEACHER
+                || courseSchedule.getTeacherId().equals(userId)){
             userRole = RoleEnum.RoleTeacher;
         }
-        log.info("joinRoom params:courseScheduleId:{},userRole:{},userId:{}",courseScheduleId,userRole,userId);
+        log.info("joinRoom params:roomId:{},userRole:{},userId:{}",roomId,userRole,userId);
         BasicUserInfo sysUser = Optional.ofNullable(teacherDao.getBasicUserInfo(userId)).
                 orElseThrow(()-> new BizException("用户信息不存在"));
         Date now = new Date();
@@ -123,7 +118,6 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         if (roomNotStart(courseSchedule)) {
             return BaseResponse.failed(ErrorEnum.ROOM_NOT_START);
         }
-        String roomId = courseScheduleId.toString();
         ImNetworkRoomResult joinRoomResult = new ImNetworkRoomResult();
         //初始化房间信息
         ImNetworkRoom room = roomService.initRoom(roomId,userRole,sysUser.getUserId());
@@ -144,7 +138,7 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
             imNetworkRoomMemberStatusService.lambdaUpdate().set(ImNetworkRoomMemberStatus::getPlayMidi,null)
                             .eq(ImNetworkRoomMemberStatus::getRoomId,roomId).update();
             //获取所有学员的伴奏下载详情
-            setMusicSheetList(roomMemberList,courseScheduleId);
+            setMusicSheetList(roomMemberList,Long.parseLong(roomId));
         }else {
             //获取节拍器信息
             joinRoomResult.setMidiJson(imNetworkRoomMemberStatusService.getMemberMidi(roomId, sysUser.getUserId()));
@@ -156,8 +150,9 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         //获取老师基本信息
         BasicUserInfo basicUserInfo = teacherDao.getBasicUserInfo(courseSchedule.getTeacherId());
         //获取学员列表
-        List<CourseScheduleStudentPayment> studentPayments = courseScheduleStudentPaymentService.getDao().queryByCourseId(courseScheduleId);
-        List<Long> studentIds = studentPayments.stream().map(e -> e.getUserId()).collect(Collectors.toList());
+        List<CourseScheduleStudentPayment> studentPayments =
+                courseScheduleStudentPaymentService.lambdaQuery().eq(CourseScheduleStudentPayment::getCourseId,roomId).list();
+        List<Long> studentIds = studentPayments.stream().map(CourseScheduleStudentPayment::getUserId).collect(Collectors.toList());
         //创建并加入群组
         imGroupService.joinImGroup(roomId, basicUserInfo,
                 courseSchedule.getServiceProvider(), studentIds);
@@ -167,13 +162,64 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         return BaseResponse.success(joinRoomResult);
     }
 
+    @Override
+    public BaseResponse<ImNetworkRoomResult> roomInfo(ImNetworkBaseDto imNetworkBaseDto) {
+        // 当前登录用户ID
+        String roomId = imNetworkBaseDto.getRoomId();
+        Long userId = sysUserService.getUserId();
+        CourseSchedule courseSchedule = Optional.ofNullable(courseScheduleService.getById(imNetworkBaseDto.getRoomId())).
+                orElseThrow(()->new BizException("房间信息不存在"));
+
+        RoleEnum userRole = RoleEnum.RoleStudent;
+        if((imNetworkBaseDto.getClientType() != null && imNetworkBaseDto.getClientType() == ClientEnum.TEACHER)
+                || courseSchedule.getTeacherId().equals(userId)){
+            userRole = RoleEnum.RoleTeacher;
+        }
+        log.info("joinRoom params:roomId:{},userRole:{},userId:{}",roomId,userRole,userId);
+        BasicUserInfo sysUser = Optional.ofNullable(teacherDao.getBasicUserInfo(userId)).
+                orElseThrow(()-> new BizException("用户信息不存在"));
+
+        ImNetworkRoomResult joinRoomResult = new ImNetworkRoomResult();
+        //初始化房间信息
+        ImNetworkRoom room = roomService.getById(roomId);
+        if(Objects.isNull(room)){
+            return BaseResponse.failed(ErrorEnum.ROOM_NOT_START);
+        }
+        BeanUtils.copyProperties(room,joinRoomResult);
+        //定时销毁房间
+        //初始化房间用户信息
+        ImNetworkRoomMember roomMember = imNetworkRoomMemberService.lambdaQuery().eq(ImNetworkRoomMember::getRoomId,roomId)
+                .eq(ImNetworkRoomMember::getUserId,userId).last("LIMIT 1").one();
+        joinRoomResult.setRoomMember(roomMember);
+        //获取教室剩余时长
+        joinRoomResult.setSurplusTime(DateUtil.secondsBetween(new Date(), courseSchedule.getEndTime()));
+        //获取房间所有成员
+        List<ImNetworkRoomMember> roomMemberList = imNetworkRoomMemberService.queryByRoomId(roomId);
+
+        joinRoomResult.setRoomMemberList(roomMemberList);
+        //如果是老师,
+        if(userRole == RoleEnum.RoleTeacher){
+            //获取所有学员的伴奏下载详情
+            setMusicSheetList(roomMemberList,Long.parseLong(roomId));
+        }else {
+            //获取节拍器信息
+            joinRoomResult.setMidiJson(imNetworkRoomMemberStatusService.getMemberMidi(roomId, sysUser.getUserId()));
+        }
+        //课程结束后关闭教室的时间
+        joinRoomResult.setAutoCloseNetworkRoomTime(sysConfigDao.findConfigValue(SysConfigConstant.DESTROY_EXPIRED_PRACTICE_ROOM_MINUTE));
+        //获取腾讯所需基本信息配置
+        joinRoomResult.setRtcRoomConfig(roomService.getRtcRoomConfig(courseSchedule.getServiceProvider(),sysUser));
+        joinRoomResult.setGroupId(roomId);
+        return BaseResponse.success(joinRoomResult);
+    }
+
     private void setMusicSheetList(List<ImNetworkRoomMember> roomMemberList,Long courseScheduleId){
         List<CourseScheduleStudentMusicSheetResult> musicSheetResults = courseScheduleStudentMusicSheetService.getDao().
                 queryBySheetIdAndCourseId(null,courseScheduleId,null,null,null);
         if (!CollectionUtils.isEmpty(musicSheetResults)) {
             //分组塞到学员列表中
             Map<Long, List<CourseScheduleStudentMusicSheetResult>> musicSheetResultMap = musicSheetResults.stream().
-                    collect(Collectors.groupingBy(e -> e.getUserId()));
+                    collect(Collectors.groupingBy(CourseScheduleStudentMusicSheet::getUserId));
             roomMemberList.forEach(e -> {
                 if (musicSheetResultMap.containsKey(e.getUserId())) {
                     e.setMusicSheetResults(musicSheetResultMap.get(e.getUserId()));
@@ -216,20 +262,6 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         imService.sendDisplay(imUserId, room,courseSchedule.getServiceProvider());
     }
 
-    private RTCRoomMessage.MessageUser getSendUser(SysUser sysUser,RoleEnum role) {
-        String imUserId = imGroupService.getImUserId(sysUser.getId(), role);
-        RTCRoomMessage.MessageUser build = RTCRoomMessage.MessageUser.builder()
-                .sendUserId(imUserId)
-                .sendUserName(sysUser.getUsername())
-                .avatarUrl(sysUser.getAvatar())
-                .build();
-        if (role == RoleEnum.RoleTeacher) {
-            build.setSendUserName(sysUser.getRealName());
-        }
-        return build;
-    }
-
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void joinRoomFailure(String roomId, ClientEnum clientType) {
@@ -259,8 +291,9 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         UserRoleEnum userRole = UserRoleEnum.convert(clientType);
         log.info("quitRoomSuccess: roomId={}, userId={}", roomId, userId);
         //防止幂等
-        StringBuffer sb  = new StringBuffer(QUIT_ROOM_SUCCESS).append(roomId).append(userId);
-        if (!redisTemplate.opsForValue().setIfAbsent(sb.toString(),userId,1l, TimeUnit.SECONDS)){
+        String QUIT_ROOM_SUCCESS = "quitRoomSuccess:";
+        StringBuilder sb  = new StringBuilder(QUIT_ROOM_SUCCESS).append(roomId).append(userId);
+        if (Boolean.FALSE.equals(redisTemplate.opsForValue().setIfAbsent(sb.toString(), userId, 1L, TimeUnit.SECONDS))){
             log.info("quitRoomSuccess break: roomId={}, userId={}", roomId, userId);
             return;
         }
@@ -306,80 +339,52 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         imNetworkRoomMemberStatusService.lambdaUpdate()
                         .eq(ImNetworkRoomMemberStatus::getRoomId,customMessage.getRoomId())
                                 .in(ImNetworkRoomMemberStatus::getUserId,collect)
-                                        .set(ImNetworkRoomMemberStatus::getPlayMidi,customMessage.toString());
+                                        .set(ImNetworkRoomMemberStatus::getPlayMidi,customMessage.getContent());
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void pushDownloadMusicSheetMsg(ImNetworkMusicSheetDto musicSheetDto) throws Exception {
-        Long courseScheduleId = Optional.ofNullable(musicSheetDto).map(ImNetworkBaseDto::getRoomId).orElseThrow(() -> new BizException("房间编号不能为空"));
-        Long accompanimentId = Optional.ofNullable(musicSheetDto).map(ImNetworkMusicSheetDto::getAccompanimentId).orElseThrow(() -> new BizException("伴奏编号不能为空"));
-        log.info("pushDownloadMusicSheetMsg: courseScheduleId:{} ,accompanimentId:{} ,deviceType:{}", courseScheduleId,accompanimentId);
-        SysUser user = sysUserService.getUser();
+        String roomId = Optional.ofNullable(musicSheetDto).map(ImNetworkBaseDto::getRoomId).orElseThrow(() -> new BizException("房间编号不能为空"));
+        Long accompanimentId = Optional.of(musicSheetDto).map(ImNetworkMusicSheetDto::getAccompanimentId).orElseThrow(() -> new BizException("伴奏编号不能为空"));
+        log.info("pushDownloadMusicSheetMsg: roomId:{} ,accompanimentId:{}", roomId,accompanimentId);
+        Long userId = sysUserService.getUserId();
         List<CourseScheduleStudentMusicSheetResult> scheduleStudentMusicSheetResults = courseScheduleStudentMusicSheetService.getDao().
-                queryBySheetIdAndCourseId(accompanimentId, courseScheduleId, null, null, 0);
+                queryBySheetIdAndCourseId(accompanimentId, Long.parseLong(roomId), null, null, 0);
 
         MusicSheetAccompaniment accompaniment = musicSheetAccompanimentService.getById(accompanimentId);
-        if (scheduleStudentMusicSheetResults.size() == 0) {
+        if (scheduleStudentMusicSheetResults.isEmpty()) {
             //第一次下载,生成数据
-            List<CourseScheduleStudentPayment> courseScheduleStudentPayments = courseScheduleStudentPaymentService.getDao().queryByCourseId(courseScheduleId);
-            Set<Long> studentIds = courseScheduleStudentPayments.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
+            List<CourseScheduleStudentPayment> studentPayments =
+                    courseScheduleStudentPaymentService.lambdaQuery().eq(CourseScheduleStudentPayment::getCourseId,roomId).list();
+            Set<Long> studentIds = studentPayments.stream().map(CourseScheduleStudentPayment::getUserId).collect(Collectors.toSet());
             studentIds.forEach(e -> {
                 CourseScheduleStudentMusicSheetResult musicSheet = new CourseScheduleStudentMusicSheetResult();
                 musicSheet.setMusicSheetAccompanimentId(accompanimentId);
                 musicSheet.setSpeed(accompaniment.getSpeed());
-                musicSheet.setCourseScheduleId(courseScheduleId);
+                musicSheet.setCourseScheduleId(Long.parseLong(roomId));
                 musicSheet.setUserId(e);
                 scheduleStudentMusicSheetResults.add(musicSheet);
             });
             CourseScheduleStudentMusicSheetResult musicSheet = new CourseScheduleStudentMusicSheetResult();
             musicSheet.setMusicSheetAccompanimentId(accompanimentId);
             musicSheet.setSpeed(accompaniment.getSpeed());
-            musicSheet.setCourseScheduleId(courseScheduleId);
-            musicSheet.setUserId(user.getId());
+            musicSheet.setCourseScheduleId(Long.parseLong(roomId));
+            musicSheet.setUserId(userId);
             musicSheet.setUserType(1);
             scheduleStudentMusicSheetResults.add(musicSheet);
             courseScheduleStudentMusicSheetService.getDao().batchInsert(scheduleStudentMusicSheetResults);
         }
+        //通知学员下载伴奏
         // IM用户ID
-        String imUserId = imGroupService.getImUserId(user.getId(),musicSheetDto.getClientType());
+        String imUserId = imGroupService.getImUserId(userId,musicSheetDto.getClientType());
         ImNetworkMusicSheetDownloadMessageContent content = JSON.parseObject(JSON.toJSONString(accompaniment), ImNetworkMusicSheetDownloadMessageContent.class);
-        // 发送消息
-        CourseSchedule courseSchedule = courseScheduleService.getById(courseScheduleId);
-        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(courseSchedule.getServiceProvider())) {
-
-            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(courseSchedule.getServiceProvider());
-            // 腾讯消息推送
-            RTCRoomMessage.MessageContent messageContent = RTCRoomMessage.MessageContent
-                    .builder()
-                    .url(content.getUrl())
-                    .mp3Url(content.getMp3Url())
-                    .songId(String.valueOf(content.getId()))
-                    .speed(content.getSpeed())
-                    .sendUserInfo(RTCRoomMessage.MessageUser.builder()
-                            .sendUserId(imUserId)
-                            .sendUserName(user.getUsername())
-                            .avatarUrl(user.getAvatar())
-                            .build())
-                    .build();
-
-            RTCRoomMessage roomMessage = RTCRoomMessage.builder()
-                    .objectName(RTCRoomMessage.MUSIC_SCORE_MESSAGE)
-                    .content(messageContent)
-                    .toChatRoomId(courseScheduleId.toString())
-                    .fromUserId(imUserId)
-                    .isIncludeSender(1)
-                    .isPersisted(1)
-                    .build();
-
-            // 发送消息
-            pluginService.sendChatRoomMessage(roomMessage);
-
-        } else {
-            ImNetworkMusicSheetDownloadMessage msg = new ImNetworkMusicSheetDownloadMessage(content);
-            // 融云消息推送
-            imHelper.publishMessage(imUserId, courseScheduleId.toString(), msg, 0);
-        }
+        BasicUserInfo basicUserInfo = teacherDao.getBasicUserInfo(userId);
+        basicUserInfo.setImUserId(imUserId);
+        CourseSchedule courseSchedule = courseScheduleService.getById(roomId);
+        content.setServiceProvider(courseSchedule.getServiceProvider());
+        content.setRoomId(roomId);
+        imService.pushDownloadMusicSheetMsg(content,basicUserInfo);
     }
 
 
@@ -407,7 +412,7 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                 List<CourseScheduleStudentPayment> studentPayments = courseScheduleStudentPaymentService.getDao().queryByCourseId(Long.parseLong(deviceControl.getRoomId()));
 
                 for (CourseScheduleStudentPayment studentPayment : studentPayments) {
-                    deviceControl.setUserId(imGroupService.getImUserId(String.valueOf(studentPayment.getUserId()), ClientEnum.STUDENT.name()));
+                    deviceControl.setImUserId(imGroupService.getImUserId(String.valueOf(studentPayment.getUserId()), ClientEnum.STUDENT.name()));
                     controlDevice(deviceControl);
                 }
 
@@ -415,7 +420,7 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                 List<ImNetworkRoomMember> roomMembers = imNetworkRoomMemberService.getDao().findByRoomAndRole(deviceControl.getRoomId(), 0);
                 if (!CollectionUtils.isEmpty(roomMembers)) {
                     for (ImNetworkRoomMember roomMember : roomMembers) {
-                        deviceControl.setUserId(imGroupService.getImUserId(String.valueOf(roomMember.getUserId()), ClientEnum.STUDENT.name()));
+                        deviceControl.setImUserId(imGroupService.getImUserId(String.valueOf(roomMember.getUserId()), ClientEnum.STUDENT.name()));
                         controlDevice(deviceControl);
                     }
                 }
@@ -430,261 +435,69 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         SysUser sysUser = sysUserService.getUser();
         String roomId = deviceControl.getRoomId();
 
-        String[] values = deviceControl.getUserId().split(":");
+        String[] values = deviceControl.getImUserId().split(":");
         // 学生信息
         Long userId = Long.parseLong(values[0]);
         Boolean enable = deviceControl.getEnable();
         log.info("controlDevice: roomId:{} ,deviceType:{} ,enable:{} ,userId:{}", roomId,deviceControl.getDeviceType(),enable,userId);
 
-        UserRoleEnum userRole = UserRoleEnum.TEACHER;
-        if (values.length > 1 && ClientEnum.STUDENT.match(values[1])) {
-
-            userRole = UserRoleEnum.STUDENT;
-        }
-        // IM用户ID
-        String imUserId = deviceControl.getUserId();
         // RTC服务对象
         CourseSchedule courseSchedule = courseScheduleService.getById(roomId);
-        SysUser teacher = sysUserService.findUserById(courseSchedule.getTeacherId());
-        if (Objects.nonNull(sysUser)) {
-            deviceControl.setSendUserId(imGroupService.getImUserId(teacher.getId(),RoleEnum.RoleTeacher));
-            deviceControl.setSendUserName(teacher.getRealName());
-            deviceControl.setAvatar(teacher.getAvatar());
-        }
-        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(courseSchedule.getServiceProvider());
-        // 通知消息
-        RTCRoomMessage.MessageContent notifyContent = RTCRoomMessage.MessageContent
-                .builder()
-                .type(deviceControl.getDeviceType().ordinal())
-                .enable(enable)
-                .targetId(imUserId)
-                .targetName(sysUser.getUsername())
-                .songId(Optional.ofNullable(deviceControl.getMusicSheetAccompanimentId()).map(String::valueOf).orElse(null))
-                .songVolume(deviceControl.getSoundVolume())
-                .sendUserInfo(RTCRoomMessage.MessageUser.builder()
-                        .sendUserId(deviceControl.getSendUserId())
-                        .sendUserName(deviceControl.getSendUserName())
-                        .avatarUrl(deviceControl.getAvatar())
-                        .build())
-                .build();
-
-        // 腾讯云消息推送
-        RTCRoomMessage message = RTCRoomMessage.builder()
-                .objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE)
-                .fromUserId(imUserId)
-                .toChatRoomId(roomId)
-                .content(notifyContent)
-                .isPersisted(1)
-                .isIncludeSender(0)
-                .build();
+        BasicUserInfo teacher = teacherDao.getBasicUserInfo(sysUser.getId());
+        teacher.setImUserId(imGroupService.getImUserId(teacher.getUserId(),RoleEnum.RoleTeacher));
+
+        deviceControl.setServiceProvider(courseSchedule.getServiceProvider());
 
         if(enable){
             long scheduleId = Long.parseLong(roomId);
-            ImNetworkDeviceStateChangedMessage deviceResourceMessage = new ImNetworkDeviceStateChangedMessage(deviceControl.getDeviceType().ordinal(),enable);
-            deviceResourceMessage.setUserId(imUserId);
             switch (deviceControl.getDeviceType()) {
-                case EXAM_SONG:
-                    ImNetworkRoomMusicSheetDownloadData msg = imNetworkRoomMemberStatusService.getMemberExamSong(roomId, userId);
-                    msg.setEnable(enable);
-                    courseScheduleStudentPaymentService.getDao().adjustExamSong(scheduleId,userId, JSON.toJSONString(msg));
-
-                    // 消息发送
-                    if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
-                        // 腾讯云推送
-                        pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
-                    } else {
-                        // 融云推送
-                        imHelper.publishMessage(imUserId, roomId, deviceResourceMessage, 1);
-                    }
-                    break;
                 case MUSIC_SHEET:
-                    Integer musicSheetId = Optional.ofNullable(deviceControl.getMusicSheetAccompanimentId()).
+                    Integer musicSheetId = Optional.ofNullable(deviceControl.getAccompanimentId()).
                             orElseThrow(()-> new BizException("请选择曲目"));
                     //关闭所有曲目播放
                     courseScheduleStudentMusicSheetService.getDao().closePlayStatus(scheduleId,userId);
                     //打开原音
                     courseScheduleStudentMusicSheetService.getDao().openPlayStatus(scheduleId,musicSheetId,userId);
-                    deviceResourceMessage.setMusicSheetAccompanimentId(musicSheetId);
-                    deviceResourceMessage.setUserId(imUserId);
-                    deviceResourceMessage.setSoundVolume(deviceControl.getSoundVolume());
-                    if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
-                        // 腾讯云推送
-                        pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
-                    } else {
-                        // 融云推送
-                        imHelper.publishMessage(deviceControl.getSendUserId(), roomId, deviceResourceMessage, 1);
-                    }
                     break;
                 case ACCOMPANIMENT:
-                  Integer musicSheetAccompanimentId = Optional.ofNullable(deviceControl.getMusicSheetAccompanimentId()).
+                  Integer musicSheetAccompanimentId = Optional.ofNullable(deviceControl.getAccompanimentId()).
                             orElseThrow(()-> new BizException("请选择曲目"));
                     //关闭所有曲目播放
                     courseScheduleStudentMusicSheetService.getDao().closePlayStatus(scheduleId,userId);
                     //打开伴奏
                     courseScheduleStudentMusicSheetService.getDao().openAccompanimentPlayStatus(scheduleId,musicSheetAccompanimentId,userId);
-                    deviceResourceMessage.setMusicSheetAccompanimentId(musicSheetAccompanimentId);
-                    deviceResourceMessage.setUserId(imUserId);
-                    deviceResourceMessage.setSoundVolume(deviceControl.getSoundVolume());
-                    if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
-                        // 腾讯云推送
-                        pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
-                    } else {
-                        // 融云推送
-                        imHelper.publishMessage(deviceControl.getSendUserId(), roomId, deviceResourceMessage, 1);
-                    }
-                    break;
-                default:
-                    // 发送消息
-                    if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
-                        // 腾讯消息
-                        pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
-                    } else {
-                        // 融云消息
-                        //邀请打开指定设备权限
-                        ImNetworkControlDeviceNotifyMessage message1 = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.INVITE.ordinal());
-                        message1.setType(deviceControl.getDeviceType().ordinal());
-                        message1.setOpUserId(deviceControl.getSendUserId());
-                        message1.setOpUserName(sysUser.getUsername());
-                        imHelper.publishMessage(deviceControl.getSendUserId(), imUserId, roomId, message1);
-                    }
                     break;
             }
         }else {
-            ImNetworkRoomMember roomMember = Optional.ofNullable(imNetworkRoomMemberService.getDao().findByRidAndUid(roomId, userId, userRole.ordinal()))
-                    .orElseThrow(()-> new BizException("用户不在房间内"));
             long scheduleId = Long.parseLong(roomId);
             switch (deviceControl.getDeviceType()) {
-                case CAMERA:
-                    roomMember.setCameraFlag(deviceControl.getEnable());
-                    break;
-                case MICROPHONE:
-                    roomMember.setMicFlag(deviceControl.getEnable());
-                    break;
-                case HAND_UP:
-                    roomMember.setHandFlag(deviceControl.getEnable());
-                    break;
-                case MUSIC_MODE:
-                    roomMember.setMusicModeFlag(deviceControl.getEnable());
-                    break;
-                case EXAM_SONG:
-                    ImNetworkRoomMusicSheetDownloadData msg = imNetworkRoomMemberStatusService.getMemberExamSong(roomId, userId);
-                    msg.setEnable(deviceControl.getEnable());
-                    courseScheduleStudentPaymentService.getDao().adjustExamSong(scheduleId,userId, JSON.toJSONString(msg));
-                    break;
                 case MUSIC_SHEET:
                 case ACCOMPANIMENT:
                     //关闭所有曲目播放
                     courseScheduleStudentMusicSheetService.getDao().closePlayStatus(scheduleId,userId);
                     break;
             }
-            if(deviceControl.getDeviceType() != ImNetworkDeviceTypeEnum.MUSIC_SHEET &&
-                    deviceControl.getDeviceType() != ImNetworkDeviceTypeEnum.EXAM_SONG &&
-                    deviceControl.getDeviceType() != ImNetworkDeviceTypeEnum.ACCOMPANIMENT){
-                imNetworkRoomMemberService.getDao().updateById(roomMember);
-            }
-            if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
-                // 腾讯消息
-                pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
-            } else {
-                // 融云消息
-                ImNetworkDeviceStateChangedMessage deviceResourceMessage = new ImNetworkDeviceStateChangedMessage(deviceControl.getDeviceType().ordinal(),deviceControl.getEnable());
-                deviceResourceMessage.setUserId(imUserId);
-                BasicUserInfo basicUserInfo = teacherDao.getBasicUserInfo(userId);
-                if (Objects.nonNull(basicUserInfo)) {
-                    deviceResourceMessage.setUserName(basicUserInfo.getUsername());
-                }
-                imHelper.publishMessage(deviceControl.getSendUserId(), roomId, deviceResourceMessage, 1);
-            }
         }
+        imService.pushDeviceResourceMessage(deviceControl,teacher);
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void approveControlDevice(ImNetworkDeviceControlDto deviceControl) throws Exception {
         log.info("approveControlDevice: roomId:{} ,deviceType:{} ,enable:{}", deviceControl.getRoomId(),deviceControl.getDeviceType(),deviceControl.getEnable());
-        SysUser sysUser = sysUserService.getUser();
-
         UserRoleEnum userRole = UserRoleEnum.TEACHER;
         if (ClientEnum.STUDENT == deviceControl.getClientType()) {
             userRole = UserRoleEnum.STUDENT;
         }
-        String imUserId = imGroupService.getImUserId(sysUser.getId(),deviceControl.getClientType());
-
-        ImNetworkRoomMember roomMember = Optional.ofNullable(imNetworkRoomMemberService.getDao().findByRidAndUid(deviceControl.getRoomId(), sysUser.getId(),
+        ImNetworkRoomMember roomMember = Optional.ofNullable(imNetworkRoomMemberService.getDao().findByRidAndUid(deviceControl.getRoomId(),sysUserService.getUserId(),
                         userRole.ordinal())).
                 orElseThrow(()-> new BizException("用户不在房间内"));
-        switch (deviceControl.getDeviceType()) {
-            case CAMERA:
-                roomMember.setCameraFlag(deviceControl.getEnable());
-                break;
-            case EXAM_SONG:
-                long scheduleId = Long.parseLong(deviceControl.getRoomId());
-                ImNetworkRoomMusicSheetDownloadData msg = imNetworkRoomMemberStatusService.getMemberExamSong(roomMember.getRoomId(), sysUser.getId());
-                msg.setEnable(deviceControl.getEnable());
-                courseScheduleStudentPaymentService.getDao().adjustExamSong(scheduleId, sysUser.getId(), JSON.toJSONString(msg));
-                break;
-            case MICROPHONE:
-                roomMember.setMicFlag(deviceControl.getEnable());
-                break;
-        }
-        if(deviceControl.getDeviceType() == ImNetworkDeviceTypeEnum.CAMERA ||
-                deviceControl.getDeviceType() == ImNetworkDeviceTypeEnum.MICROPHONE){
-            imNetworkRoomMemberService.getDao().updateById(roomMember);
-        }
-
         CourseSchedule courseSchedule = courseScheduleService.getById(deviceControl.getRoomId());
-        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(courseSchedule.getServiceProvider())) {
-
-            // 获取RTC服务提供方
-            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(TencentCloudRTCPlugin.PLUGIN_NAME);
-            // 腾讯云RTC服务
-            RTCRoomMessage.MessageContent.MessageContentBuilder action = RTCRoomMessage.MessageContent.builder()
-                    .type(ImNetworkActionEnum.APPROVE.ordinal())
-                    .enable(deviceControl.getEnable())
-                    .targetId(imUserId)
-                    .targetName(sysUser.getUsername())
-                    .sendUserInfo(getSendUser(sysUserService.findUserById(courseSchedule.getTeacherId()), RoleEnum.RoleTeacher));
-
-
-            RTCRoomMessage roomMessage = RTCRoomMessage.builder()
-                    .objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE)
-                    .content(action.build())
-                    .toChatRoomId(roomMember.getRoomId())
-                    .fromUserId(imUserId)
-                    .isIncludeSender(1)
-                    .isPersisted(1)
-                    .build();
-
-            pluginService.sendChatRoomMessage(roomMessage);
-
-            // 腾讯云RTC服务
-            action = RTCRoomMessage.MessageContent.builder()
-                    .type(ImNetworkActionEnum.APPROVE.ordinal())
-                    .enable(deviceControl.getEnable())
-                    .sendUserInfo(getSendUser(sysUser,RoleEnum.getEnumByValue(roomMember.getRole())));
-
-            // 腾讯云消息推送
-            RTCRoomMessage message = RTCRoomMessage.builder()
-                    .objectName(RTCRoomMessage.DEVICE_MESSAGE)
-                    .fromUserId(imUserId)
-                    .toChatRoomId(roomMember.getRoomId())
-                    .content(action.build())
-                    .isPersisted(1)
-                    .isIncludeSender(0)
-                    .build();
-
-            pluginService.sendChatRoomMessage(message);
-        }else {
-            ImNetworkControlDeviceNotifyMessage msg = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.APPROVE.ordinal());
-            msg.setType(deviceControl.getDeviceType().ordinal());
-            msg.setOpUserId(sysUser.getId().toString());
-            msg.setOpUserName(sysUser.getUsername());
-            //获取老师编号
-            String imUserId1 = imGroupService.getImUserId(courseSchedule.getTeacherId(), RoleEnum.RoleTeacher);
-            imHelper.publishMessage(imUserId, imUserId1, deviceControl.getRoomId(), msg);
-            //发送设备状态变更消息
-            this.sendDeviceStateChangedMessage(deviceControl, imUserId);
-        }
+        deviceControl.setServiceProvider(courseSchedule.getServiceProvider());
+
+        imService.pushApproveControlDevice(deviceControl,roomMember,
+                teacherDao.getBasicUserInfo(roomMember.getUserId()),
+                teacherDao.getBasicUserInfo(courseSchedule.getTeacherId()));
     }
 
     @Override
@@ -698,88 +511,25 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         if (ClientEnum.STUDENT == deviceStatusSync.getClientType()) {
             userRole = UserRoleEnum.STUDENT;
         }
-        String imUserId = imGroupService.getImUserId(userId,deviceStatusSync.getClientType());
 
-        ImNetworkDeviceTypeEnum deviceType = deviceStatusSync.getDeviceType();
+        CourseSchedule courseSchedule = courseScheduleService.getById(deviceStatusSync.getRoomId());
+        deviceStatusSync.setServiceProvider(courseSchedule.getServiceProvider());
         ImNetworkRoomMember roomMember = Optional.ofNullable(imNetworkRoomMemberService.getDao().
                         findByRidAndUid(deviceStatusSync.getRoomId(), userId, userRole.ordinal()))
                 .orElseThrow(()-> new BizException("用户不在房间内"));
-        switch (deviceType) {
-            case CAMERA:
-                roomMember.setCameraFlag(deviceStatusSync.getEnable());
-                break;
-            case MICROPHONE:
-                roomMember.setMicFlag(deviceStatusSync.getEnable());
-                break;
-            case HAND_UP:
-                roomMember.setHandFlag(deviceStatusSync.getEnable());
-                break;
-            case MUSIC_MODE:
-                roomMember.setMusicModeFlag(deviceStatusSync.getEnable());
-                break;
-            case EXAM_SONG:
-                long scheduleId = Long.parseLong(deviceStatusSync.getRoomId());
-                ImNetworkRoomMusicSheetDownloadData msg = imNetworkRoomMemberStatusService.getMemberExamSong(deviceStatusSync.getRoomId(), userId);
-                msg.setEnable(deviceStatusSync.getEnable());
-                courseScheduleStudentPaymentService.getDao().adjustExamSong(scheduleId, userId, JSON.toJSONString(msg));
-                break;
-        }
-        if(deviceType == ImNetworkDeviceTypeEnum.CAMERA ||
-                deviceType == ImNetworkDeviceTypeEnum.MICROPHONE ||
-                deviceType == ImNetworkDeviceTypeEnum.HAND_UP ||
-                deviceType == ImNetworkDeviceTypeEnum.MUSIC_MODE){
-            imNetworkRoomMemberService.getDao().updateById(roomMember);
-        }
-        CourseSchedule courseSchedule = courseScheduleService.getById(deviceStatusSync.getRoomId());
-        //发送设备状态同步消息
-        if (TencentCloudRTCPlugin.PLUGIN_NAME.matches(courseSchedule.getServiceProvider())) {
-            // RTC服务对象
-            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(courseSchedule.getServiceProvider());
-            // 消息内容
-            RTCRoomMessage.MessageContent messageContent = RTCRoomMessage.MessageContent
-                    .builder()
-                    .type(deviceType.ordinal())
-                    .enable(deviceStatusSync.getEnable())
-                    .sendUserInfo(getSendUser(user, RoleEnum.RoleTeacher))
-                    .build();
-            // 腾讯云消息推送
-            RTCRoomMessage message = RTCRoomMessage.builder()
-                    .objectName(RTCRoomMessage.DEVICE_MESSAGE)
-                    .fromUserId(imUserId)
-                    .toChatRoomId(deviceStatusSync.getRoomId())
-                    .content(messageContent)
-                    .isPersisted(1)
-                    .isIncludeSender(0)
-                    .build();
-            // 发送消息
-            pluginService.sendChatRoomMessage(message);
-        } else {
-            // 融云消息推送
-            this.sendDeviceStateChangedMessage(deviceStatusSync, imUserId);
-        }
+        imService.sendDeviceStatusSync(deviceStatusSync,roomMember);
     }
 
     @Override
-    public List<BasicUserInfo> queryNoJoinStu(Long roomId) {
-
+    public List<BasicUserInfo> queryNoJoinStu(String roomId) {
         List<BasicUserInfo> userInfos = courseScheduleStudentPaymentService.getDao().queryNoJoinStu(roomId);
 
         for (BasicUserInfo item : userInfos) {
             item.setImUserId(imGroupService.getImUserId(String.valueOf(item.getUserId()),ClientEnum.STUDENT.name()));
         }
-
         return userInfos;
     }
 
-    //发送设备状态同步消息
-    private void sendDeviceStateChangedMessage(ImNetworkDeviceControlDto deviceStatusSync,String imUserId) throws Exception {
-        ImNetworkRoom room = baseMapper.findByRoomId(deviceStatusSync.getRoomId());
-        ImNetworkDeviceStateChangedMessage deviceResourceMessage = new ImNetworkDeviceStateChangedMessage(deviceStatusSync.getDeviceType().ordinal(),deviceStatusSync.getEnable());
-        deviceResourceMessage.setUserId(imUserId);
-        deviceResourceMessage.setSoundVolume(room.getSoundVolume());
-        imHelper.publishMessage(imUserId, deviceStatusSync.getRoomId(), deviceResourceMessage, 1);
-    }
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void rejectControlDevice(ImNetworkDeviceControlDto deviceControl) throws Exception {
@@ -787,50 +537,25 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         SysUser sysUser = sysUserService.getUser();
 
         CourseSchedule courseSchedule = courseScheduleService.getById(deviceControl.getRoomId());
-        String imUserId = imGroupService.getImUserId(sysUser.getId(), RoleEnum.RoleStudent);
-        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(courseSchedule.getServiceProvider())) {
-
-            // 获取RTC服务提供方
-            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(TencentCloudRTCPlugin.PLUGIN_NAME);
-
-            RTCRoomMessage.MessageContent.MessageContentBuilder action = RTCRoomMessage.MessageContent.builder()
-                    .type(ImNetworkActionEnum.REJECT.ordinal())
-                    .enable(deviceControl.getEnable())
-                    .targetId(imUserId)
-                    .targetName(sysUser.getUsername())
-                    .sendUserInfo(getSendUser(sysUserService.findUserById(courseSchedule.getTeacherId()), RoleEnum.RoleTeacher));
-
-
-            RTCRoomMessage roomMessage = RTCRoomMessage.builder()
-                    .objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE)
-                    .content(action.build())
-                    .toChatRoomId(deviceControl.getRoomId())
-                    .fromUserId(imUserId)
-                    .isIncludeSender(1)
-                    .isPersisted(1)
-                    .build();
-
-            pluginService.sendChatRoomMessage(roomMessage);
-        } else {
-            ImNetworkControlDeviceNotifyMessage msg = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.REJECT.ordinal());
-            msg.setType(deviceControl.getDeviceType().ordinal());
-            msg.setOpUserId(imUserId);
-            msg.setOpUserName(sysUser.getUsername());
-            //获取老师编号
-            String imUserId1 = imGroupService.getImUserId(courseSchedule.getTeacherId(), RoleEnum.RoleTeacher);
-            imHelper.publishMessage(imUserId,imUserId1, deviceControl.getRoomId(), msg);
-        }
+        deviceControl.setServiceProvider(courseSchedule.getServiceProvider());
+        ImNetworkRoomMember roomMember = imNetworkRoomMemberService.lambdaQuery()
+                .eq(ImNetworkRoomMember::getUserId, sysUser.getId())
+                .eq(ImNetworkRoomMember::getRoomId, deviceControl.getRoomId())
+                .last("LIMIT 1").one();
+        imService.sendRejectControlDevice(deviceControl,roomMember,
+                teacherDao.getBasicUserInfo(courseSchedule.getTeacherId()));
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void musicSheetDownNotify(ImNetworkMusicSheetDto musicSheetDto) throws Exception {
-        Long roomId = Optional.ofNullable(musicSheetDto).map(ImNetworkBaseDto::getRoomId).orElseThrow(() -> new BizException("房间编号不能为空"));
-        Long accompanimentId = Optional.ofNullable(musicSheetDto).map(ImNetworkMusicSheetDto::getAccompanimentId).orElseThrow(() -> new BizException("伴奏编号不能为空"));
-        Integer status = Optional.ofNullable(musicSheetDto).map(ImNetworkMusicSheetDto::getStatus).orElseThrow(() -> new BizException("伴奏下载状态不能为空"));
+        String roomId = Optional.ofNullable(musicSheetDto).map(ImNetworkBaseDto::getRoomId).orElseThrow(() -> new BizException("房间编号不能为空"));
+        Long accompanimentId = Optional.of(musicSheetDto).map(ImNetworkMusicSheetDto::getAccompanimentId).orElseThrow(() -> new BizException("伴奏编号不能为空"));
+        Integer status = Optional.of(musicSheetDto).map(ImNetworkMusicSheetDto::getStatus).orElseThrow(() -> new BizException("伴奏下载状态不能为空"));
         log.info("musicSheetDownNotify: roomId:{} ,accompanimentId:{} ,status:{}", roomId,accompanimentId,status);
         Long userId = sysUserService.getUserId();
-        List<CourseScheduleStudentMusicSheetResult> studentMusicSheetResults = courseScheduleStudentMusicSheetService.getDao().queryBySheetIdAndCourseId(accompanimentId, roomId,userId, null, null);
+        List<CourseScheduleStudentMusicSheetResult> studentMusicSheetResults = courseScheduleStudentMusicSheetService.getDao().
+                queryBySheetIdAndCourseId(accompanimentId, Long.parseLong(roomId),userId, null, null);
         if(CollectionUtils.isEmpty(studentMusicSheetResults)){
             return;
         }
@@ -847,7 +572,7 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         // IM用户ID
         String imUserId = imGroupService.getImUserId(userId,musicSheetDto.getClientType());
 
-        imHelper.publishMessage(imUserId, courseSchedule.getTeacherId().toString(), roomId.toString(), statusMessage);
+        imHelper.publishMessage(imUserId, courseSchedule.getTeacherId().toString(), roomId, statusMessage);
     }
 
     //校验用户是否提前进入教室
@@ -860,22 +585,4 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         Date addMinutes = DateUtil.addMinutes(courseSchedule.getStartTime(), Integer.parseInt(courseBeforeBufferTime));
         return courseSchedule.getStartTime().compareTo(addMinutes) > 0;
     }
-
-
-    //修改节拍器
-    public void updateDisplay(String imUserId,ImNetworkRoom room,String serviceProvider) throws Exception {
-        roomService.updateById(room);
-        //节拍器修改消息发送
-        imService.sendDisplay(imUserId,room,serviceProvider);
-    }
-
-    public boolean isUserDisplay(String display, Long userId) {
-        boolean result = false;
-        if (!display.isEmpty() && display.contains("userId=" + userId)) {
-            if (display.contains("type=0") || display.contains("type=2")) {
-                result = true;
-            }
-        }
-        return result;
-    }
 }

+ 380 - 17
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImServiceImpl.java

@@ -1,18 +1,23 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginContext;
 import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginService;
 import com.microsvc.toolkit.middleware.rtc.enums.EMemberAction;
 import com.microsvc.toolkit.middleware.rtc.impl.TencentCloudRTCPlugin;
 import com.microsvc.toolkit.middleware.rtc.message.RTCRoomMessage;
 import com.yonge.cooleshow.biz.dal.dto.*;
+import com.yonge.cooleshow.biz.dal.entity.CourseSchedule;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoom;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMember;
-import com.yonge.cooleshow.biz.dal.enums.ImNetworkRoomMemberChangedEnum;
-import com.yonge.cooleshow.biz.dal.service.ImNetworkRoomMemberService;
-import com.yonge.cooleshow.biz.dal.service.ImNetworkRoomMemberStatusService;
-import com.yonge.cooleshow.biz.dal.service.ImService;
+import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMemberStatus;
+import com.yonge.cooleshow.biz.dal.enums.*;
+import com.yonge.cooleshow.biz.dal.service.*;
 import com.yonge.cooleshow.biz.dal.support.IMHelper;
+import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.base.util.StringUtil;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -20,6 +25,8 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Date;
+import java.util.Objects;
+import java.util.Optional;
 
 /**
  * 网络教室成员(ImNetworkRoomMember)表服务实现类
@@ -44,13 +51,19 @@ public class ImServiceImpl implements ImService {
     @Autowired
     private ImNetworkRoomMemberService imNetworkRoomMemberService;
 
+    @Autowired
+    private ImGroupService imGroupService;
+
+    @Autowired
+    private ImNetworkRoomService imNetworkRoomService;
+
 
     @Override
     public void publishMemberChangedMessage(ImNetworkRoomMember roomMember,String serviceProvider) throws Exception {
         //发送人员变动消息
         // 获取RTC服务提供方
-        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(serviceProvider);
-        if (serviceProvider.equals(TencentCloudRTCPlugin.PLUGIN_NAME)) {
+        if (serviceProvider.equals(TencentCloudRTCPlugin.PLUGIN_NAME) || StringUtils.isEmpty(serviceProvider)) {
+            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(serviceProvider);
             // 腾讯云RTC服务
             RTCRoomMessage.MessageContent.MessageContentBuilder action = RTCRoomMessage.MessageContent.builder()
                     .action(EMemberAction.JOIN.getValue());
@@ -76,8 +89,8 @@ public class ImServiceImpl implements ImService {
         } else {
             ImNetworkRoomMemberChangedMessage msg = new ImNetworkRoomMemberChangedMessage(roomMember, ImNetworkRoomMemberChangedEnum.JOIN);
             //获取节拍器信息
-            ImNetworkCustomMessage imNetworkCustomMessage = imNetworkRoomMemberStatusService.getMemberMidi(roomMember.getRoomId(), roomMember.getUserId());
-            msg.setMetronomeSwitch(imNetworkCustomMessage.isEnable());
+            ImNetworkMetronomeMessage imNetworkCustomMessage = imNetworkRoomMemberStatusService.getMemberMidi(roomMember.getRoomId(), roomMember.getUserId());
+            msg.setMetronomeSwitch(imNetworkCustomMessage.getEnable());
             //获取伴奏信息
             ImNetworkRoomMusicSheetDownloadData musicSheetDownloadData = imNetworkRoomMemberStatusService.getMemberExamSong(roomMember.getRoomId(), roomMember.getUserId());
             msg.setExamSongSwitch(musicSheetDownloadData.getEnable());
@@ -90,7 +103,7 @@ public class ImServiceImpl implements ImService {
         // IM发送用户消息
         ImNetworkRoomMember roomMember = imNetworkRoomMemberService.lambdaQuery().eq(ImNetworkRoomMember::getUserId, imUserId)
                 .eq(ImNetworkRoomMember::getRoomId, room.getRoomId()).last("LIMIT 1").one();
-        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(serviceProvider)) {
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(serviceProvider) || StringUtils.isEmpty(serviceProvider)) {
             // 获取RTC服务提供方
             RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(TencentCloudRTCPlugin.PLUGIN_NAME);
             // 腾讯云RTC服务
@@ -121,21 +134,21 @@ public class ImServiceImpl implements ImService {
     @Transactional(rollbackFor = Exception.class)
     public void sendImPlayMidiMessage(ImNetworkCustomMessage customMessage) throws Exception {
         log.info("sendImPlayMidiMessage: customMessage={}", customMessage);
-        ImNetworkMetronomeMessage displayMessage = new ImNetworkMetronomeMessage(customMessage);
+        ImNetworkMetronomeMessage playMidiMessage = JSONObject.parseObject(customMessage.getContent(), ImNetworkMetronomeMessage.class);
 
         ImNetworkRoomMember roomMember = imNetworkRoomMemberService.lambdaQuery().eq(ImNetworkRoomMember::getUserId, customMessage.getCurrentUserId())
                 .eq(ImNetworkRoomMember::getRoomId, customMessage.getRoomId()).last("LIMIT 1").one();
         // 获取RTC服务提供方
-        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(customMessage.getServiceProvider());
-        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(customMessage.getServiceProvider()) || StringUtils.isEmpty(customMessage.getServiceProvider())) {
+            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(customMessage.getServiceProvider());
             // 腾讯云RTC服务
             RTCRoomMessage.MessageContent messageContent = RTCRoomMessage.MessageContent
                     .builder()
-                    .enable(customMessage.isEnable())
-                    .rate(customMessage.getRate())
-                    .customType(customMessage.getCustomType())
+                    .enable(playMidiMessage.getEnable())
+                    .rate(playMidiMessage.getRate())
+                    .customType(playMidiMessage.getCustomType())
                     .userId(customMessage.getUserId())
-                    .playVolume(customMessage.getPlayVolume())
+                    .playVolume(playMidiMessage.getPlayVolume())
                     .sendUserInfo(getSendUser(roomMember))
                     .build();
 
@@ -150,7 +163,348 @@ public class ImServiceImpl implements ImService {
 
             pluginService.sendChatRoomMessage(roomMessage);
         } else {
-            imHelper.publishMessage(roomMember.getImUserId(), roomMember.getRoomId(), displayMessage, 1);
+            imHelper.publishMessage(roomMember.getImUserId(), roomMember.getRoomId(), playMidiMessage, 1);
+        }
+    }
+
+    @Override
+    public void pushDownloadMusicSheetMsg(ImNetworkMusicSheetDownloadMessageContent content,BasicUserInfo userInfo) throws Exception {
+        // 发送消息
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(content.getServiceProvider()) || StringUtils.isEmpty(content.getServiceProvider())) {
+
+            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(content.getServiceProvider());
+            // 腾讯消息推送
+            RTCRoomMessage.MessageContent messageContent = RTCRoomMessage.MessageContent
+                    .builder()
+                    .url(content.getUrl())
+                    .mp3Url(content.getMp3Url())
+                    .songId(String.valueOf(content.getId()))
+                    .speed(content.getSpeed())
+                    .sendUserInfo(RTCRoomMessage.MessageUser.builder()
+                            .sendUserId(userInfo.getImUserId())
+                            .sendUserName(userInfo.getRealName())
+                            .avatarUrl(userInfo.getAvatar())
+                            .build())
+                    .build();
+
+            RTCRoomMessage roomMessage = RTCRoomMessage.builder()
+                    .objectName(RTCRoomMessage.MUSIC_SCORE_MESSAGE)
+                    .content(messageContent)
+                    .toChatRoomId(content.getRoomId())
+                    .fromUserId(userInfo.getImUserId())
+                    .isIncludeSender(1)
+                    .isPersisted(1)
+                    .build();
+
+            // 发送消息
+            pluginService.sendChatRoomMessage(roomMessage);
+        } else {
+            ImNetworkMusicSheetDownloadMessage msg = new ImNetworkMusicSheetDownloadMessage(content);
+            // 融云消息推送
+            imHelper.publishMessage(userInfo.getImUserId(), content.getRoomId(), msg, 0);
+        }
+    }
+
+    @Override
+    public void pushDeviceResourceMessage(ImNetworkDeviceControlDto deviceControl,BasicUserInfo teacher) throws Exception {
+        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(deviceControl.getServiceProvider());
+        String roomId = deviceControl.getRoomId();
+        // 通知消息
+        RTCRoomMessage.MessageContent notifyContent = RTCRoomMessage.MessageContent
+                .builder()
+                .type(deviceControl.getDeviceType().ordinal())
+                .enable(deviceControl.getEnable())
+                .targetId(deviceControl.getImUserId())
+                .targetName(teacher.getRealName())
+                .songId(Optional.ofNullable(deviceControl.getAccompanimentId()).map(String::valueOf).orElse(null))
+                .songVolume(deviceControl.getSoundVolume())
+                .sendUserInfo(RTCRoomMessage.MessageUser.builder()
+                        .sendUserId(teacher.getImUserId())
+                        .sendUserName(teacher.getRealName())
+                        .avatarUrl(teacher.getAvatar())
+                        .build())
+                .build();
+
+        // 腾讯云消息推送
+        RTCRoomMessage message = RTCRoomMessage.builder()
+                .objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE)
+                .fromUserId(deviceControl.getImUserId())
+                .toChatRoomId(roomId)
+                .content(notifyContent)
+                .isPersisted(1)
+                .isIncludeSender(0)
+                .build();
+        String userId = imGroupService.analysisImUserId(deviceControl.getImUserId());
+
+        if(deviceControl.getEnable()){
+            ImNetworkDeviceStateChangedMessage deviceResourceMessage = new ImNetworkDeviceStateChangedMessage(deviceControl.getDeviceType().ordinal(),true);
+            deviceResourceMessage.setUserId(deviceControl.getImUserId());
+            switch (deviceControl.getDeviceType()) {
+                case EXAM_SONG:
+                    ImNetworkRoomMusicSheetDownloadData msg = imNetworkRoomMemberStatusService.getMemberExamSong(roomId, Long.parseLong(userId));
+                    msg.setEnable(true);
+                    imNetworkRoomMemberStatusService.lambdaUpdate()
+                                    .eq(ImNetworkRoomMemberStatus::getRoomId,roomId)
+                                            .eq(ImNetworkRoomMemberStatus::getUserId,userId)
+                                                    .set(ImNetworkRoomMemberStatus::getMusicSheetDownloadJson,JSON.toJSONString(msg)).update();
+
+                    // 消息发送
+                    if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(deviceControl.getServiceProvider()) || StringUtils.isEmpty(deviceControl.getServiceProvider())) {
+                        // 腾讯云推送
+                        pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
+                    } else {
+                        // 融云推送
+                        imHelper.publishMessage(deviceControl.getImUserId(), roomId, deviceResourceMessage, 1);
+                    }
+                    break;
+                case MUSIC_SHEET:
+                case ACCOMPANIMENT:
+                    deviceResourceMessage.setMusicSheetAccompanimentId(deviceControl.getAccompanimentId());
+                    deviceResourceMessage.setUserId(deviceControl.getImUserId());
+                    deviceResourceMessage.setSoundVolume(deviceControl.getSoundVolume());
+                    if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+                        // 腾讯云推送
+                        pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
+                    } else {
+                        // 融云推送
+                        imHelper.publishMessage(teacher.getImUserId(), roomId, deviceResourceMessage, 1);
+                    }
+                    break;
+                default:
+                    // 发送消息
+                    if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+                        // 腾讯消息
+                        pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
+                    } else {
+                        // 融云消息
+                        //邀请打开指定设备权限
+                        ImNetworkControlDeviceNotifyMessage message1 = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.INVITE.ordinal());
+                        message1.setType(deviceControl.getDeviceType().ordinal());
+                        message1.setOpUserId(teacher.getImUserId());
+                        message1.setOpUserName(teacher.getRealName());
+                        imHelper.publishMessage(teacher.getImUserId(), deviceControl.getImUserId(), roomId, message1);
+                    }
+                    break;
+            }
+        }else {
+            ImNetworkRoomMember roomMember = Optional.ofNullable(imNetworkRoomMemberService.getDao().findByRidAndUid(roomId, Long.parseLong(userId), UserRoleEnum.STUDENT.ordinal()))
+                    .orElseThrow(()-> new BizException("用户不在房间内"));
+            switch (deviceControl.getDeviceType()) {
+                case CAMERA:
+                    roomMember.setCameraFlag(deviceControl.getEnable());
+                    break;
+                case MICROPHONE:
+                    roomMember.setMicFlag(deviceControl.getEnable());
+                    break;
+                case HAND_UP:
+                    roomMember.setHandFlag(deviceControl.getEnable());
+                    break;
+                case MUSIC_MODE:
+                    roomMember.setMusicModeFlag(deviceControl.getEnable());
+                    break;
+                case EXAM_SONG:
+                    ImNetworkRoomMusicSheetDownloadData msg = imNetworkRoomMemberStatusService.getMemberExamSong(roomId, roomMember.getUserId());
+                    msg.setEnable(false);
+                    imNetworkRoomMemberStatusService.lambdaUpdate()
+                            .eq(ImNetworkRoomMemberStatus::getRoomId,roomId)
+                            .eq(ImNetworkRoomMemberStatus::getUserId,userId)
+                            .set(ImNetworkRoomMemberStatus::getMusicSheetDownloadJson,JSON.toJSONString(msg)).update();
+                    break;
+            }
+            if(deviceControl.getDeviceType() != ImNetworkDeviceTypeEnum.MUSIC_SHEET &&
+                    deviceControl.getDeviceType() != ImNetworkDeviceTypeEnum.EXAM_SONG &&
+                    deviceControl.getDeviceType() != ImNetworkDeviceTypeEnum.ACCOMPANIMENT){
+                imNetworkRoomMemberService.getDao().updateById(roomMember);
+            }
+            if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+                // 腾讯消息
+                pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
+            } else {
+                // 融云消息
+                ImNetworkDeviceStateChangedMessage deviceResourceMessage = new ImNetworkDeviceStateChangedMessage(deviceControl.getDeviceType().ordinal(),deviceControl.getEnable());
+                deviceResourceMessage.setUserId(deviceControl.getImUserId());
+                deviceResourceMessage.setUserName(teacher.getRealName());
+                imHelper.publishMessage(teacher.getImUserId(), roomId, deviceResourceMessage, 1);
+            }
+        }
+    }
+
+    @Override
+    public void pushApproveControlDevice(ImNetworkDeviceControlDto deviceControl, ImNetworkRoomMember roomMember,BasicUserInfo student,BasicUserInfo teacher) throws Exception {
+        switch (deviceControl.getDeviceType()) {
+            case CAMERA:
+                roomMember.setCameraFlag(deviceControl.getEnable());
+                break;
+            case EXAM_SONG:
+                ImNetworkRoomMusicSheetDownloadData msg = imNetworkRoomMemberStatusService.getMemberExamSong(roomMember.getRoomId(), roomMember.getUserId());
+                msg.setEnable(deviceControl.getEnable());
+                imNetworkRoomMemberStatusService.lambdaUpdate()
+                        .eq(ImNetworkRoomMemberStatus::getRoomId,roomMember.getRoomId())
+                        .eq(ImNetworkRoomMemberStatus::getUserId,roomMember.getUserId())
+                        .set(ImNetworkRoomMemberStatus::getMusicSheetDownloadJson,JSON.toJSONString(msg)).update();
+                break;
+            case MICROPHONE:
+                roomMember.setMicFlag(deviceControl.getEnable());
+                break;
+        }
+        if(deviceControl.getDeviceType() == ImNetworkDeviceTypeEnum.CAMERA ||
+                deviceControl.getDeviceType() == ImNetworkDeviceTypeEnum.MICROPHONE){
+            imNetworkRoomMemberService.updateById(roomMember);
+        }
+
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(deviceControl.getServiceProvider())) {
+
+            // 获取RTC服务提供方
+            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(TencentCloudRTCPlugin.PLUGIN_NAME);
+            RTCRoomMessage.MessageUser build = RTCRoomMessage.MessageUser.builder()
+                    .sendUserId(teacher.getImUserId())
+                    .sendUserName(teacher.getRealName())
+                    .avatarUrl(teacher.getAvatar())
+                    .build();
+            // 腾讯云RTC服务
+            RTCRoomMessage.MessageContent.MessageContentBuilder action = RTCRoomMessage.MessageContent.builder()
+                    .type(ImNetworkActionEnum.APPROVE.ordinal())
+                    .enable(deviceControl.getEnable())
+                    .targetId(roomMember.getImUserId())
+                    .targetName(student.getUsername())
+                    .sendUserInfo(build);
+
+
+            RTCRoomMessage roomMessage = RTCRoomMessage.builder()
+                    .objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE)
+                    .content(action.build())
+                    .toChatRoomId(roomMember.getRoomId())
+                    .fromUserId(roomMember.getImUserId())
+                    .isIncludeSender(1)
+                    .isPersisted(1)
+                    .build();
+
+            pluginService.sendChatRoomMessage(roomMessage);
+
+            // 腾讯云RTC服务
+            action = RTCRoomMessage.MessageContent.builder()
+                    .type(ImNetworkActionEnum.APPROVE.ordinal())
+                    .enable(deviceControl.getEnable())
+                    .sendUserInfo(getSendUser(roomMember));
+
+            // 腾讯云消息推送
+            RTCRoomMessage message = RTCRoomMessage.builder()
+                    .objectName(RTCRoomMessage.DEVICE_MESSAGE)
+                    .fromUserId(roomMember.getImUserId())
+                    .toChatRoomId(roomMember.getRoomId())
+                    .content(action.build())
+                    .isPersisted(1)
+                    .isIncludeSender(0)
+                    .build();
+
+            pluginService.sendChatRoomMessage(message);
+        }else {
+            ImNetworkControlDeviceNotifyMessage msg = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.APPROVE.ordinal());
+            msg.setType(deviceControl.getDeviceType().ordinal());
+            msg.setOpUserId(roomMember.getImUserId());
+            msg.setOpUserName(student.getUsername());
+            //获取老师编号
+            String imUserId1 = imGroupService.getImUserId(teacher.getUserId(), RoleEnum.RoleTeacher);
+            imHelper.publishMessage(roomMember.getImUserId(), imUserId1, deviceControl.getRoomId(), msg);
+            //发送设备状态变更消息
+            this.sendDeviceStateChangedMessage(deviceControl, roomMember.getImUserId());
+        }
+    }
+
+    @Override
+    public void sendDeviceStatusSync(ImNetworkDeviceControlDto deviceStatusSync, ImNetworkRoomMember roomMember) throws Exception {
+        ImNetworkDeviceTypeEnum deviceType = deviceStatusSync.getDeviceType();
+        switch (deviceType) {
+            case CAMERA:
+                roomMember.setCameraFlag(deviceStatusSync.getEnable());
+                break;
+            case MICROPHONE:
+                roomMember.setMicFlag(deviceStatusSync.getEnable());
+                break;
+            case HAND_UP:
+                roomMember.setHandFlag(deviceStatusSync.getEnable());
+                break;
+            case MUSIC_MODE:
+                roomMember.setMusicModeFlag(deviceStatusSync.getEnable());
+                break;
+            case EXAM_SONG:
+                ImNetworkRoomMusicSheetDownloadData msg = imNetworkRoomMemberStatusService.getMemberExamSong(roomMember.getRoomId(), roomMember.getUserId());
+                msg.setEnable(deviceStatusSync.getEnable());
+                imNetworkRoomMemberStatusService.lambdaUpdate()
+                        .eq(ImNetworkRoomMemberStatus::getRoomId,roomMember.getRoomId())
+                        .eq(ImNetworkRoomMemberStatus::getUserId,roomMember.getUserId())
+                        .set(ImNetworkRoomMemberStatus::getMusicSheetDownloadJson,JSON.toJSONString(msg)).update();
+                break;
+        }
+        if(deviceType == ImNetworkDeviceTypeEnum.CAMERA ||
+                deviceType == ImNetworkDeviceTypeEnum.MICROPHONE ||
+                deviceType == ImNetworkDeviceTypeEnum.HAND_UP ||
+                deviceType == ImNetworkDeviceTypeEnum.MUSIC_MODE){
+            imNetworkRoomMemberService.getDao().updateById(roomMember);
+        }
+        //发送设备状态同步消息
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.matches(deviceStatusSync.getServiceProvider())) {
+            // RTC服务对象
+            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(deviceStatusSync.getServiceProvider());
+            // 消息内容
+            RTCRoomMessage.MessageContent messageContent = RTCRoomMessage.MessageContent
+                    .builder()
+                    .type(deviceType.ordinal())
+                    .enable(deviceStatusSync.getEnable())
+                    .sendUserInfo(getSendUser(roomMember))
+                    .build();
+            // 腾讯云消息推送
+            RTCRoomMessage message = RTCRoomMessage.builder()
+                    .objectName(RTCRoomMessage.DEVICE_MESSAGE)
+                    .fromUserId(roomMember.getImUserId())
+                    .toChatRoomId(deviceStatusSync.getRoomId())
+                    .content(messageContent)
+                    .isPersisted(1)
+                    .isIncludeSender(0)
+                    .build();
+            // 发送消息
+            pluginService.sendChatRoomMessage(message);
+        } else {
+            // 融云消息推送
+            this.sendDeviceStateChangedMessage(deviceStatusSync, roomMember.getImUserId());
+        }
+    }
+
+    @Override
+    public void sendRejectControlDevice(ImNetworkDeviceControlDto deviceControl, ImNetworkRoomMember roomMember, BasicUserInfo teacher) throws Exception {
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(deviceControl.getServiceProvider())) {
+            // 获取RTC服务提供方
+            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(TencentCloudRTCPlugin.PLUGIN_NAME);
+
+            RTCRoomMessage.MessageUser build = RTCRoomMessage.MessageUser.builder()
+                    .sendUserId(imGroupService.getImUserId(teacher.getUserId(),ClientEnum.TEACHER))
+                    .sendUserName(teacher.getRealName())
+                    .avatarUrl(teacher.getAvatar())
+                    .build();
+            RTCRoomMessage.MessageContent.MessageContentBuilder action = RTCRoomMessage.MessageContent.builder()
+                    .type(ImNetworkActionEnum.REJECT.ordinal())
+                    .enable(deviceControl.getEnable())
+                    .targetId(roomMember.getImUserId())
+                    .targetName(roomMember.getUsername())
+                    .sendUserInfo(build);
+
+            RTCRoomMessage roomMessage = RTCRoomMessage.builder()
+                    .objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE)
+                    .content(action.build())
+                    .toChatRoomId(roomMember.getRoomId())
+                    .fromUserId(roomMember.getImUserId())
+                    .isIncludeSender(1)
+                    .isPersisted(1)
+                    .build();
+
+            pluginService.sendChatRoomMessage(roomMessage);
+        } else {
+            ImNetworkControlDeviceNotifyMessage msg = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.REJECT.ordinal());
+            msg.setType(deviceControl.getDeviceType().ordinal());
+            msg.setOpUserId(roomMember.getImUserId());
+            msg.setOpUserName(roomMember.getUsername());
+            imHelper.publishMessage(roomMember.getImUserId(),
+                    imGroupService.getImUserId(teacher.getUserId(),ClientEnum.TEACHER), roomMember.getRoomId(), msg);
         }
     }
 
@@ -162,5 +516,14 @@ public class ImServiceImpl implements ImService {
                 .build();
         return build;
     }
+
+    //发送设备状态同步消息
+    private void sendDeviceStateChangedMessage(ImNetworkDeviceControlDto deviceStatusSync,String imUserId) throws Exception {
+        ImNetworkRoom room = imNetworkRoomService.getById(deviceStatusSync.getRoomId());
+        ImNetworkDeviceStateChangedMessage deviceResourceMessage = new ImNetworkDeviceStateChangedMessage(deviceStatusSync.getDeviceType().ordinal(),deviceStatusSync.getEnable());
+        deviceResourceMessage.setUserId(imUserId);
+        deviceResourceMessage.setSoundVolume(room.getSoundVolume());
+        imHelper.publishMessage(imUserId, deviceStatusSync.getRoomId(), deviceResourceMessage, 1);
+    }
 }
 

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

@@ -10,7 +10,10 @@ import com.yonge.cooleshow.biz.dal.dao.ImNetworkRoomMemberDao;
 import com.yonge.cooleshow.biz.dal.dto.BasicUserInfo;
 import com.yonge.cooleshow.biz.dal.dto.ImNetworkDisplayDataDto;
 import com.yonge.cooleshow.biz.dal.dto.ImNetworkRoomMemberChangedMessage;
-import com.yonge.cooleshow.biz.dal.entity.*;
+import com.yonge.cooleshow.biz.dal.entity.IMApiResultInfo;
+import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoom;
+import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMember;
+import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMemberStatus;
 import com.yonge.cooleshow.biz.dal.enums.ImNetworkRoomMemberChangedEnum;
 import com.yonge.cooleshow.biz.dal.enums.RoleEnum;
 import com.yonge.cooleshow.biz.dal.service.ImGroupService;
@@ -18,7 +21,7 @@ import com.yonge.cooleshow.biz.dal.service.ImNetworkRoomMemberStatusService;
 import com.yonge.cooleshow.biz.dal.service.ImService;
 import com.yonge.cooleshow.biz.dal.service.RoomService;
 import com.yonge.cooleshow.biz.dal.support.IMHelper;
-import com.yonge.toolset.base.exception.BizException;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -27,7 +30,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.util.Objects;
-import java.util.Optional;
 
 /**
  * 网络教室房间(ImNetworkRoom)表服务实现类
@@ -89,7 +91,7 @@ public class RoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNetworkRoom
     @Transactional(rollbackFor = Exception.class)
     public RTCRoomConfig getRtcRoomConfig(String serviceProvider, BasicUserInfo basicUserInfo) {
         RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(serviceProvider);
-        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(serviceProvider) || StringUtils.isEmpty(serviceProvider)) {
             // 腾讯云RTC
             // 用户IM帐号创建
             try {

+ 85 - 44
cooleshow-user/user-classroom/src/main/java/com/yonge/cooleshow/classroom/controller/RoomController.java

@@ -11,14 +11,14 @@ import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.BaseResponse;
 import com.yonge.toolset.base.exception.BizException;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
+import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import java.util.List;
@@ -50,31 +50,22 @@ public class RoomController extends BaseController {
     @ApiOperation("加入网络教室")
     @PostMapping(value = "/join")
     public BaseResponse<ImNetworkRoomResult> joinRoom(@RequestBody ImNetworkBaseDto imNetworkBaseDto) throws Exception {
-
-        // 设置请求客户端来源
-        if (Objects.isNull(imNetworkBaseDto.getClientType())) {
-            imNetworkBaseDto.setClientType(ClientEnum.STUDENT);
-        }
-
-        return imNetworkRoomService.joinRoom(Optional.ofNullable(imNetworkBaseDto)
-                .map(ImNetworkBaseDto::getRoomId)
-                .orElseThrow(()->new BizException("房间号不可为空")), imNetworkBaseDto.getClientType());
+        return imNetworkRoomService.joinRoom(imNetworkBaseDto.getRoomId(), imNetworkBaseDto.getClientType());
     }
 
+    @ApiOperation("查询网络教室信息")
+    @PostMapping(value = "/info")
+    public BaseResponse<ImNetworkRoomResult> getRoomInfo(@RequestBody ImNetworkBaseDto imNetworkBaseDto){
+        return imNetworkRoomService.roomInfo(imNetworkBaseDto);
+    }
 
-    @ApiOperation("加入网络教室状态回调")
-    @PostMapping(value = "joinRoomFailure")
-    public BaseResponse joinRoomFailure(@RequestBody ImNetworkBaseDto imNetworkBaseDto){
-
-        // 设置请求客户端来源
-        if (Objects.isNull(imNetworkBaseDto.getClientType())) {
-            imNetworkBaseDto.setClientType(ClientEnum.STUDENT);
+    @RequestMapping(value = "joinRoomStatusNotify", method = RequestMethod.POST)
+    public Object joinRoomStatusNotify(@RequestBody RoomStatusNotify roomStatusNotify) throws Exception {
+        log.info("joinRoomStatusNotify: {}",JSONObject.toJSON(roomStatusNotify));
+        if(!roomStatusNotify.isRequestStatus()){
+            imNetworkRoomService.joinRoomFailure(roomStatusNotify.getRoomId(), roomStatusNotify.getClientType());
         }
-
-        imNetworkRoomService.joinRoomFailure(Optional.ofNullable(imNetworkBaseDto)
-                .map(ImNetworkBaseDto::getRoomId)
-                .orElseThrow(()->new BizException("房间号不可为空")).toString(), imNetworkBaseDto.getClientType());
-        return BaseResponse.success();
+        return new BaseResponse<>();
     }
 
     @PostMapping(value = "/statusSync")
@@ -95,18 +86,78 @@ public class RoomController extends BaseController {
         }
     }
 
+
+    @PostMapping(value = "/statusSyncTencent")
+    public void statusSyncTencent(@RequestBody TencentData.TRTCEventInfo eventInfo) {
+        try {
+            if (Objects.isNull(eventInfo.getEventInfo())) {
+                log.warn("statusSyncTencent eventInfo is null, time={}", DateTime.now().toString("yyy-MM-dd HH:mm:ss"));
+                return;
+            }
+            log.info("statusSyncTencent: {}", eventInfo.jsonString());
+            String roomId = eventInfo.getEventInfo().getRoomId();
+
+            // 网络教室回调整消息
+            if (roomId.startsWith("S") || roomId.startsWith("I")) {
+                // 进出用户信息
+                String userId = eventInfo.getEventInfo().getUserId();
+                switch (ETencentTRTCCallbackCommand.get(eventInfo.getEventType())){
+                    case EVENT_TYPE_ENTER_ROOM:
+                        //成员加入
+                        imNetworkRoomService.joinRoomSuccess(roomId, userId);
+                        break;
+                    case EVENT_TYPE_EXIT_ROOM:
+                        //成员退出
+                        imNetworkRoomService.quitRoomSuccess(roomId, userId);
+                        break;
+                    default:
+                        // 默认事件,直接忽略
+                        break;
+                }
+            }
+
+            // 直播课回调消息, roomId.startsWith("LIVE")
+            if (roomId.startsWith("LIVE")) {
+                String[] values = roomId.split("-");
+                if (values.length < 2 || !values[1].startsWith("S")) {
+                    return;
+                }
+
+                roomId = values[1];
+                // 直播课回调事件处理, 课程编号
+                switch (ETencentTRTCCallbackCommand.get(eventInfo.getEventType())){
+                    case EVENT_TYPE_START_VIDEO:
+                    case EVENT_TYPE_START_AUDIO:
+                    case EVENT_TYPE_START_ASSIT:
+                        //成员加入
+                        imNetworkRoomService.joinRoomSuccess(roomId, eventInfo.getEventInfo().getUserId());
+                        break;
+                    case EVENT_TYPE_STOP_VIDEO:
+                    case EVENT_TYPE_STOP_AUDIO:
+                    case EVENT_TYPE_STOP_ASSIT:
+                        //成员退出
+                        imNetworkRoomService.quitRoomSuccess(roomId, eventInfo.getEventInfo().getUserId());
+                        break;
+                    default:
+                        // 默认事件,直接忽略
+                        break;
+                }
+            }
+
+        }catch (Exception e){
+            log.error("statusSyncTencent event={}", eventInfo.jsonString(), e);
+        }
+    }
+
     @ApiOperation("退出网络教室")
     @PostMapping(value = "/leave")
     public BaseResponse leaveRoom(@RequestBody ImNetworkBaseDto imNetworkBaseDto) throws Exception {
-
         // 设置请求客户端来源
         if (Objects.isNull(imNetworkBaseDto.getClientType())) {
             imNetworkBaseDto.setClientType(ClientEnum.STUDENT);
         }
-
         // 用户ID
         Long userId = sysUserService.getUserId();
-
         // IM用户ID
         String imUserId = String.valueOf(userId);
         if (ClientEnum.STUDENT == imNetworkBaseDto.getClientType()) {
@@ -115,21 +166,17 @@ public class RoomController extends BaseController {
             imUserId = imGroupService.getImUserId(imUserId, ClientEnum.TEACHER.name());
         }
 
-        imNetworkRoomService.quitRoomSuccess(Optional.ofNullable(imNetworkBaseDto)
-                .map(ImNetworkBaseDto::getRoomId)
-                .orElseThrow(()->new BizException("房间号不可为空")).toString(), imUserId);
+        imNetworkRoomService.quitRoomSuccess(imNetworkBaseDto.getRoomId(), imUserId);
         return BaseResponse.success();
     }
 
     @ApiOperation("控制学员节拍器")
     @PostMapping(value = "/sendImPlayMidiMessage")
     public BaseResponse sendImPlayMidiMessage(@RequestBody ImNetworkCustomMessage customMessage) throws Exception {
-
         // 设置客户端类型
         if (Objects.isNull(customMessage.getClientType())) {
             customMessage.setClientType(ClientEnum.TEACHER);
         }
-
         imNetworkRoomService.sendImPlayMidiMessage(customMessage);
         return BaseResponse.success();
     }
@@ -137,12 +184,10 @@ public class RoomController extends BaseController {
     @ApiOperation("移动端用来渲染页面")
     @PostMapping(value = "/display")
     public BaseResponse display(@RequestBody ImNetworkDisplayDataDto displayData) throws Exception {
-
         // 设置客户端类型
         if (Objects.isNull(displayData.getClientType())) {
             displayData.setClientType(ClientEnum.TEACHER);
         }
-
         imNetworkRoomService.display(displayData);
         return BaseResponse.success();
     }
@@ -218,20 +263,18 @@ public class RoomController extends BaseController {
     }
 
     @ApiOperation(value = "老师在网络教室选择完伴奏后、通知学员下载伴奏")
-    @PostMapping(value = "pushDownloadMusicSheetMsg")
+    @PostMapping(value = "pushDownloadMusicScoreMsg")
     public BaseResponse pushDownloadMusicSheetMsg(@RequestBody ImNetworkMusicSheetDto musicSheetDto) throws Exception {
-
         // 设置客户端类型
         if (Objects.isNull(musicSheetDto.getClientType())) {
             musicSheetDto.setClientType(ClientEnum.TEACHER);
         }
-
         imNetworkRoomService.pushDownloadMusicSheetMsg(musicSheetDto);
         return BaseResponse.success();
     }
 
     @ApiOperation(value = "学员伴奏下载状态回调")
-    @PostMapping(value = "musicSheetDownNotify")
+    @PostMapping(value = "adjustExamSong")
     public BaseResponse adjustMusicScore(@RequestBody ImNetworkMusicSheetDto musicSheetDto) throws Exception {
 
         // 设置客户端类型
@@ -244,11 +287,9 @@ public class RoomController extends BaseController {
     }
 
     @ApiOperation(value = "查询不在教室的学员")
-    @PostMapping(value = "/queryNoJoinStu")
-    public BaseResponse<List<BasicUserInfo>> queryNoJoinStu(@RequestBody ImNetworkBaseDto imNetworkBaseDto){
-        return BaseResponse.success(imNetworkRoomService.queryNoJoinStu(Optional.ofNullable(imNetworkBaseDto)
-                .map(ImNetworkBaseDto::getRoomId)
-                .orElseThrow(()->new BizException("房间号不可为空"))));
+    @GetMapping(value = "/queryNoJoinStu")
+    public BaseResponse<List<BasicUserInfo>> queryNoJoinStu(String roomId){
+        return BaseResponse.success(imNetworkRoomService.queryNoJoinStu(roomId));
     }
 }