Browse Source

网络教室兼容腾讯

zouxuan 1 year ago
parent
commit
198421ba37

+ 5 - 0
cooleshow-user/user-biz/pom.xml

@@ -114,6 +114,11 @@
             <groupId>com.microsvc.toolkit.middleware</groupId>
             <artifactId>microsvc-middleware-im</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.microsvc.toolkit.middleware</groupId>
+            <artifactId>microsvc-middleware-rtc</artifactId>
+            <version>1.0.0</version>
+        </dependency>
 
     </dependencies>
 

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

@@ -3,7 +3,9 @@ package com.yonge.cooleshow.biz.dal.dto;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.enums.ImNetworkDeviceTypeEnum;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
 
+@Data
 public class ImNetworkDeviceControlDto {
 	@ApiModelProperty(value = "需要操作的类型",required = true)
 	private ImNetworkDeviceTypeEnum deviceType;
@@ -35,83 +37,8 @@ public class ImNetworkDeviceControlDto {
 	@ApiModelProperty("客户端类型 ")
 	private ClientEnum clientType;
 
-	public ImNetworkDeviceTypeEnum getDeviceType() {
-		return deviceType;
-	}
-
-	public void setDeviceType(ImNetworkDeviceTypeEnum deviceType) {
-		this.deviceType = deviceType;
-	}
-
-	public Boolean getEnable() {
-		return enable;
-	}
-
-	public void setEnable(Boolean enable) {
-		this.enable = enable;
-	}
-
-	public String getRoomId() {
-		return roomId;
-	}
-
-	public void setRoomId(String roomId) {
-		this.roomId = roomId;
-	}
-
-	public String getUserId() {
-		return userId;
-	}
-
-	public void setUserId(String userId) {
-		this.userId = userId;
-	}
-
-	public String getTicket() {
-		return ticket;
-	}
-
-	public void setTicket(String ticket) {
-		this.ticket = ticket;
-	}
-
-	public Integer getStatus() {
-		return status;
-	}
-
-	public void setStatus(Integer status) {
-		this.status = status;
-	}
-
-	public Integer getMusicSheetId() {
-		return musicSheetId;
-	}
-
-	public void setMusicSheetId(Integer musicSheetId) {
-		this.musicSheetId = musicSheetId;
-	}
-
-	public Integer getMusicSheetAccompanimentId() {
-		return musicSheetAccompanimentId;
-	}
-
-	public void setMusicSheetAccompanimentId(Integer musicSheetAccompanimentId) {
-		this.musicSheetAccompanimentId = musicSheetAccompanimentId;
-	}
-
-	public Integer getSoundVolume() {
-		return soundVolume;
-	}
-
-	public void setSoundVolume(Integer soundVolume) {
-		this.soundVolume = soundVolume;
-	}
-
-	public ClientEnum getClientType() {
-		return clientType;
-	}
-
-	public void setClientType(ClientEnum clientType) {
-		this.clientType = clientType;
-	}
+	// 发送用户信息
+	private String sendUserId;
+	private String sendUserName;
+	private String avatar;
 }

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

@@ -1,11 +1,16 @@
 package com.yonge.cooleshow.biz.dal.dto;
 
+import com.microsvc.toolkit.middleware.rtc.message.RTCRoomConfig;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoom;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMember;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
 
 import java.util.List;
 
+@Data
 public class ImNetworkRoomResult extends ImNetworkRoom {
 
     @ApiModelProperty(value = "陪练课结束后,XX分钟关闭房间")
@@ -23,43 +28,12 @@ public class ImNetworkRoomResult extends ImNetworkRoom {
     @ApiModelProperty(value = "节拍器参数")
     private ImNetworkCustomMessage midiJson = new ImNetworkCustomMessage();
 
-    public ImNetworkCustomMessage getMidiJson() {
-        return midiJson;
-    }
+    @ApiModelProperty("RTC接入参数")
+    private RTCRoomConfig rtcRoomConfig;
 
-    public void setMidiJson(ImNetworkCustomMessage midiJson) {
-        this.midiJson = midiJson;
-    }
+    @ApiModelProperty("直播间用户签名")
+    private String userSig;
 
-    public Integer getSurplusTime() {
-        return surplusTime;
-    }
-
-    public void setSurplusTime(Integer surplusTime) {
-        this.surplusTime = surplusTime;
-    }
-
-    public String getAutoCloseNetworkRoomTime() {
-        return autoCloseNetworkRoomTime;
-    }
-
-    public void setAutoCloseNetworkRoomTime(String autoCloseNetworkRoomTime) {
-        this.autoCloseNetworkRoomTime = autoCloseNetworkRoomTime;
-    }
-
-    public List<ImNetworkRoomMember> getRoomMemberList() {
-        return roomMemberList;
-    }
-
-    public void setRoomMemberList(List<ImNetworkRoomMember> roomMemberList) {
-        this.roomMemberList = roomMemberList;
-    }
-
-    public ImNetworkRoomMember getRoomMember() {
-        return roomMember;
-    }
-
-    public void setRoomMember(ImNetworkRoomMember roomMember) {
-        this.roomMember = roomMember;
-    }
+    @ApiModelProperty("群组id")
+    private String groupId;
 }

+ 12 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseSchedule.java

@@ -27,13 +27,10 @@ public class CourseSchedule implements Serializable {
     @ApiModelProperty(value = "课程组id_")
     private Long courseGroupId;
 
-
-
     @TableField("room_uid_")
     @ApiModelProperty(value = "房间编号 直播课直播房间号")
     private String roomUid;
 
-
     @TableField("type_")
     @ApiModelProperty(value = "类型 practice陪练课 live直播课  CourseScheduleEnum")
     private String type;
@@ -94,5 +91,17 @@ public class CourseSchedule implements Serializable {
     @ApiModelProperty(value = "更新时间")
     private Date updatedTime;
 
+    @TableField("service_provider_")
+    @ApiModelProperty("服务提供方")
+    private String serviceProvider;
+
+    @TableField("room_id_")
+    @ApiModelProperty("房间号")
+    private String roomId;
+
+    @ApiModelProperty("全员静音")
+    @TableField("mute_all_")
+    private Boolean muteAll;
+
 }
 

+ 36 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/RoleEnum.java

@@ -0,0 +1,36 @@
+package com.yonge.cooleshow.biz.dal.enums;
+
+import com.baomidou.mybatisplus.extension.exceptions.ApiException;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Created by weiqinxiao on 2019/2/28.
+ */
+public enum RoleEnum {
+    RoleAssistant("RoleAssistant", 1),
+    RoleTeacher("RoleTeacher", 2),
+    RoleStudent("RoleStudent", 3),
+    RoleAudience("RoleAudience", 4);
+
+    private @Getter
+    @Setter(AccessLevel.PRIVATE) String msg;
+    private @Getter
+    @Setter(AccessLevel.PRIVATE) int value;
+
+    RoleEnum(String msg, int value) {
+        this.msg = msg;
+        this.value = value;
+    }
+
+    public static RoleEnum getEnumByValue(int v) {
+        for(RoleEnum item : RoleEnum.values()) {
+            if(item.getValue() == v) {
+                return item;
+            }
+        }
+
+        throw new ApiException(v + " not valid role");
+    }
+}

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

@@ -5,6 +5,7 @@ import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dao.ImNetworkRoomMemberDao;
 import com.yonge.cooleshow.biz.dal.dto.BasicUserInfo;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMember;
+import com.yonge.cooleshow.biz.dal.enums.RoleEnum;
 import com.yonge.cooleshow.biz.dal.enums.UserRoleEnum;
 
 import java.util.Date;
@@ -20,7 +21,7 @@ public interface ImNetworkRoomMemberService extends IService<ImNetworkRoomMember
 
     ImNetworkRoomMemberDao getDao();
 
-    ImNetworkRoomMember initRoomMember(String roomId, BasicUserInfo sysUser, UserRoleEnum userRole);
+    ImNetworkRoomMember initRoomMember(String roomId, BasicUserInfo sysUser, RoleEnum userRole);
 
 }
 

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

@@ -6,6 +6,7 @@ import com.yonge.cooleshow.biz.dal.dao.ImNetworkRoomMemberDao;
 import com.yonge.cooleshow.biz.dal.dto.BasicUserInfo;
 import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMember;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.RoleEnum;
 import com.yonge.cooleshow.biz.dal.enums.UserRoleEnum;
 import com.yonge.cooleshow.biz.dal.service.ImNetworkRoomMemberService;
 import org.springframework.stereotype.Service;
@@ -36,7 +37,7 @@ public class ImNetworkRoomMemberServiceImpl extends ServiceImpl<ImNetworkRoomMem
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public ImNetworkRoomMember initRoomMember(String roomId, BasicUserInfo sysUser, UserRoleEnum userRole) {
+    public ImNetworkRoomMember initRoomMember(String roomId, BasicUserInfo sysUser, RoleEnum userRole) {
         ImNetworkRoomMember roomMember = baseMapper.findByRidAndUid(roomId, sysUser.getUserId(), userRole.ordinal());
         if(Objects.isNull(roomMember)){
             roomMember = new ImNetworkRoomMember();
@@ -56,7 +57,7 @@ public class ImNetworkRoomMemberServiceImpl extends ServiceImpl<ImNetworkRoomMem
         }
 
         String imUserId = String.valueOf(sysUser.getUserId());
-        if (UserRoleEnum.STUDENT == userRole) {
+        if (RoleEnum.RoleStudent == userRole) {
             imUserId = MessageFormat.format("{0}:{1}", imUserId, ClientEnum.STUDENT.name());
         }
         roomMember.setImUserId(imUserId);

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

@@ -1,9 +1,19 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
+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.ImGroupMemberWrapper;
+import com.microsvc.toolkit.middleware.rtc.message.RTCRoomMessage;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dao.ImNetworkRoomDao;
+import com.yonge.cooleshow.biz.dal.dao.ImNetworkRoomMemberDao;
 import com.yonge.cooleshow.biz.dal.dao.SysConfigDao;
 import com.yonge.cooleshow.biz.dal.dao.TeacherDao;
 import com.yonge.cooleshow.biz.dal.dto.*;
@@ -11,6 +21,7 @@ import com.yonge.cooleshow.biz.dal.entity.*;
 import com.yonge.cooleshow.biz.dal.enums.*;
 import com.yonge.cooleshow.biz.dal.service.*;
 import com.yonge.cooleshow.biz.dal.support.IMHelper;
+import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
 import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.common.enums.EStatus;
@@ -20,6 +31,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -29,6 +41,7 @@ import javax.annotation.Resource;
 import java.text.MessageFormat;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -64,6 +77,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;
 
@@ -83,10 +98,10 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         CourseSchedule courseSchedule = Optional.ofNullable(courseScheduleService.getById(courseScheduleId)).
                 orElseThrow(()->new BizException("房间信息不存在"));
 
-        UserRoleEnum userRole = UserRoleEnum.STUDENT;
+        RoleEnum userRole = RoleEnum.RoleStudent;
         if(courseSchedule.getTeacherId().equals(userId) && ClientEnum.TEACHER == clientType){
             // 与老师帐号匹配,且来自老师客户端
-            userRole = UserRoleEnum.TEACHER;
+            userRole = RoleEnum.RoleTeacher;
         }
         log.info("joinRoom params:courseScheduleId:{},userRole:{},userId:{}",courseScheduleId,userRole,userId);
         BasicUserInfo sysUser = Optional.ofNullable(teacherDao.getBasicUserInfo(userId)).
@@ -118,11 +133,10 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                 // 学生
                 item.setImUserId(MessageFormat.format("{0}:{1}", String.valueOf(item.getUserId()), ClientEnum.STUDENT.name()));
             }
-
         }
         joinRoomResult.setRoomMemberList(roomMemberList);
         //如果是老师,重置节拍器数据
-        if(userRole == UserRoleEnum.TEACHER){
+        if(userRole == RoleEnum.RoleTeacher){
             courseScheduleStudentPaymentService.getDao().cleanPlayMidi(courseScheduleId);
             //获取所有学员的伴奏下载详情
             setMusicSheetList(roomMemberList,courseScheduleId);
@@ -134,16 +148,25 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         joinRoomResult.setAutoCloseNetworkRoomTime(sysConfigDao.findConfigValue(SysConfigConstant.DESTROY_EXPIRED_PRACTICE_ROOM_MINUTE));
 
         // IM用户ID
-        String imUserId = sysUser.getUserId().toString();
-        if (UserRoleEnum.STUDENT == userRole) {
-            imUserId = MessageFormat.format("{0}:{1}", imUserId, ClientEnum.STUDENT.name());
-        }
+        String imUserId = this.getImUserId(userId,userRole);
         roomMember.setImUserId(imUserId);
+        // 创建IM群聊
+        this.joinImGroup(roomId, courseSchedule.getTeacherId().intValue(), courseSchedule);
+        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(courseSchedule.getServiceProvider());
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+            // 腾讯云RTC
+            // 用户IM帐号创建
+            String userSig = "";
+            try {
+                userSig = pluginService.register(String.valueOf(sysUser.getUserId()), sysUser.getRealName(), sysUser.getAvatar());
+            } catch (Exception e) {
+                log.error("直播房间用户注册失败: userId={}", sysUser.getUserId(), e);
+            }
 
-        //创建、加入群聊
-        IMApiResultInfo resultInfo = imHelper.joinGroup(new String[]{imUserId}, roomId, roomId);
-        if(resultInfo.getCode() != 200){
-            log.error("加入群聊失败 resultInfo:{}",resultInfo);
+            // 返回配置参数
+            joinRoomResult.setUserSig(userSig);
+            joinRoomResult.setRtcRoomConfig(rtcRoomPluginContext.getPluginService().getRTCRoomConfig(String.valueOf(sysUser.getUserId())));
+            joinRoomResult.setGroupId(roomId);
         }
         return HttpResponseResult.succeed(joinRoomResult);
     }
@@ -169,7 +192,7 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
 
         String[] values = imUserId.split(":");
         // 用户ID
-        long userId = Long.parseLong(values[0]);
+        Long userId = Long.parseLong(values[0]);
 
         // 客户端类型
         ClientEnum clientType = ClientEnum.TEACHER;
@@ -184,11 +207,11 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         BasicUserInfo sysUser = Optional.ofNullable(teacherDao.getBasicUserInfo(userId)).
                 orElseThrow(()-> new BizException("用户信息不存在"));
 
-        UserRoleEnum userRole = UserRoleEnum.STUDENT;
+        RoleEnum userRole = RoleEnum.RoleStudent;
         if(Objects.equals(courseSchedule.getTeacherId(),userId)
                 && ClientEnum.TEACHER == clientType){
 
-            userRole = UserRoleEnum.TEACHER;
+            userRole = RoleEnum.RoleTeacher;
             teacherAttendanceService.signIn(userId,courseSchedule);
         }else {
             studentAttendanceService.signIn(userId,courseSchedule);
@@ -201,11 +224,61 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         // IM用户ID
         roomMember.setImUserId(imUserId);
         //发送人员变动消息
-        publishMemberChangedMessage(roomMember);
+        // 获取RTC服务提供方
+        String rtcServiceProvider = Optional.ofNullable(courseSchedule.getServiceProvider()).orElse("rongCloud");
+
+        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(rtcServiceProvider);
+        if (rtcServiceProvider.equals(TencentCloudRTCPlugin.PLUGIN_NAME)) {
+            // 腾讯云RTC服务
+            RTCRoomMessage.MessageContent.MessageContentBuilder action = RTCRoomMessage.MessageContent.builder()
+                    .action(EMemberAction.JOIN.getValue());
+
+            if (userRole == RoleEnum.RoleTeacher) {
+                action.role(userRole.getValue());
+            } else {
+                action.role(userRole.getValue());
+            }
+            action.handUpOn(roomMember.isHandFlag())
+                    .microphone(roomMember.isMicFlag())
+                    .timestamp(now.getTime())
+                    .camera(true)
+                    .sendUserInfo(getSendUser(sysUserService.findUserById(userId),userRole));
+
+            // 开启全员静音,重置学员状态
+            if (courseSchedule.getMuteAll()) {
+                action.microphone(false);
+            }
+
+            RTCRoomMessage roomMessage = RTCRoomMessage.builder()
+                    .objectName(RTCRoomMessage.MEMBER_CHANGE_MESSAGE)
+                    .fromUserId(userId.toString())
+                    .content(action.build())
+                    .toChatRoomId(roomId)
+                    .isPersisted(1)
+                    .isIncludeSender(1)
+                    .build();
+
+            pluginService.sendChatRoomMessage(roomMessage);
+        } else {
+            publishMemberChangedMessage(roomMember);
+        }
         //sendDisplay
         this.sendDisplay(imUserId, room);
     }
 
+    private RTCRoomMessage.MessageUser getSendUser(SysUser sysUser,RoleEnum role) {
+
+        RTCRoomMessage.MessageUser build = RTCRoomMessage.MessageUser.builder()
+                .sendUserId(sysUser.getId().toString())
+                .sendUserName(sysUser.getUsername())
+                .avatarUrl(sysUser.getAvatar())
+                .build();
+        if (role == RoleEnum.RoleTeacher) {
+            build.setSendUserName(sysUser.getRealName());
+        }
+        return build;
+    }
+
     //发送人员变动消息
     private void publishMemberChangedMessage(ImNetworkRoomMember roomMember) throws Exception {
         ImNetworkRoomMemberChangedMessage msg = new ImNetworkRoomMemberChangedMessage(roomMember,ImNetworkRoomMemberChangedEnum.JOIN);
@@ -311,20 +384,65 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         imNetworkRoomMemberService.getDao().deleteById(roomMember.getId());
     }
 
+    private String getImUserId(Long userId,ClientEnum clientEnum){
+        String imUserId = String.valueOf(userId);
+        if (ClientEnum.STUDENT == clientEnum) {
+            imUserId = MessageFormat.format("{0}:{1}", imUserId, ClientEnum.STUDENT.name());
+        }
+        return imUserId;
+    }
+
+    private String getImUserId(Long userId,RoleEnum clientEnum){
+        String imUserId = String.valueOf(userId);
+        if (RoleEnum.RoleStudent == clientEnum) {
+            imUserId = MessageFormat.format("{0}:{1}", imUserId, ClientEnum.STUDENT.name());
+        }
+        return imUserId;
+    }
+
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void sendImPlayMidiMessage(ImNetworkCustomMessage customMessage) throws Exception {
-        Long userId = sysUserService.getUserId();
+        SysUser user = sysUserService.getUser();
+        Long userId = user.getId();
         Long roomId = customMessage.getRoomId();
         log.info("sendImPlayMidiMessage: roomId={}, userId={}", roomId, userId);
         ImNetworkMetronomeMessage displayMessage = new ImNetworkMetronomeMessage(customMessage);
 
-        String imUserId = String.valueOf(userId);
-        if (ClientEnum.STUDENT == customMessage.getClientType()) {
-            imUserId = MessageFormat.format("{0}:{1}", imUserId, ClientEnum.STUDENT.name());
+        String imUserId = this.getImUserId(userId,customMessage.getClientType());
+
+        ImNetworkRoomMember roomMember = imNetworkRoomMemberService.lambdaQuery().eq(ImNetworkRoomMember::getUserId, userId)
+                .eq(ImNetworkRoomMember::getRoomId, roomId).last("LIMIT 1").one();
+        // 获取RTC服务提供方
+        CourseSchedule courseSchedule = courseScheduleService.getById(roomId);
+        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(courseSchedule.getServiceProvider());
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+
+            // 腾讯云RTC服务
+            RTCRoomMessage.MessageContent messageContent = RTCRoomMessage.MessageContent
+                    .builder()
+                    .enable(customMessage.getEnable())
+                    .rate(customMessage.getRate())
+                    .customType(customMessage.getCustomType())
+                    .userId(customMessage.getUserId())
+                    .playVolume(customMessage.getPlayVolume())
+                    .sendUserInfo(getSendUser(user, RoleEnum.getEnumByValue(roomMember.getRole())))
+                    .build();
+
+            RTCRoomMessage roomMessage = RTCRoomMessage.builder()
+                    .objectName(RTCRoomMessage.PLAY_MIDI_MESSAGE)
+                    .content(messageContent)
+                    .toChatRoomId(roomMember.getRoomId())
+                    .fromUserId(roomMember.getImUserId())
+                    .isIncludeSender(1)
+                    .isPersisted(1)
+                    .build();
+
+            pluginService.sendChatRoomMessage(roomMessage);
+        } else {
+            imHelper.publishMessage(imUserId, roomId.toString(), displayMessage, 1);
         }
-        // 用户ID
-        imHelper.publishMessage(imUserId, roomId.toString(), displayMessage, 1);
 
         //记录节拍器信息
         String collect = Arrays.stream(customMessage.getUserId().split(","))
@@ -339,7 +457,7 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         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);
-        Long userId = sysUserService.getUserId();
+        SysUser user = sysUserService.getUser();
         List<CourseScheduleStudentMusicSheetResult> scheduleStudentMusicSheetResults = courseScheduleStudentMusicSheetService.getDao().
                 queryBySheetIdAndCourseId(accompanimentId, courseScheduleId, null, null, 0);
 
@@ -360,23 +478,54 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
             musicSheet.setMusicSheetAccompanimentId(accompanimentId);
             musicSheet.setSpeed(accompaniment.getSpeed());
             musicSheet.setCourseScheduleId(courseScheduleId);
-            musicSheet.setUserId(userId);
+            musicSheet.setUserId(user.getId());
             musicSheet.setUserType(1);
             scheduleStudentMusicSheetResults.add(musicSheet);
             courseScheduleStudentMusicSheetService.getDao().batchInsert(scheduleStudentMusicSheetResults);
         }
-        ImNetworkMusicSheetDownloadMessage msg = new ImNetworkMusicSheetDownloadMessage(
-                JSON.parseObject(JSON.toJSONString(accompaniment), ImNetworkMusicSheetDownloadMessageContent.class));
-
         // IM用户ID
-        String imUserId = String.valueOf(userId);
-        if (ClientEnum.STUDENT == musicSheetDto.getClientType()) {
-            imUserId = MessageFormat.format("{0}:{1}", imUserId, ClientEnum.STUDENT.name());
-        }
+        String imUserId = this.getImUserId(user.getId(),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);
 
-        imHelper.publishMessage(imUserId, courseScheduleId.toString(), msg, 0);
+        } else {
+            ImNetworkMusicSheetDownloadMessage msg = new ImNetworkMusicSheetDownloadMessage(content);
+            // 融云消息推送
+            imHelper.publishMessage(imUserId, courseScheduleId.toString(), msg, 0);
+        }
     }
 
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void display(ImNetworkDisplayDataDto displayData) throws Exception {
@@ -408,10 +557,7 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         ImNetworkRoom room = baseMapper.findByRoomId(displayData.getRoomId());
         room.setDisplay(display.toString());
 
-        String imUserId = String.valueOf(userId);
-        if (ClientEnum.STUDENT == displayData.getClientType()) {
-            imUserId = MessageFormat.format("{0}:{1}", imUserId, ClientEnum.STUDENT.name());
-        }
+        String imUserId = this.getImUserId(userId,displayData.getClientType());
 
         this.updateDisplay(imUserId,room);
     }
@@ -465,6 +611,40 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         }
         // IM用户ID
         String imUserId = deviceControl.getUserId();
+        // RTC服务对象
+        CourseSchedule courseSchedule = courseScheduleService.getById(roomId);
+        SysUser teacher = sysUserService.findUserById(courseSchedule.getTeacherId());
+        if (Objects.nonNull(sysUser)) {
+            deviceControl.setSendUserId(teacher.getId().toString());
+            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(userId.toString())
+                .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(userId.toString())
+                .toChatRoomId(roomId)
+                .content(notifyContent)
+                .isPersisted(1)
+                .isIncludeSender(0)
+                .build();
 
         if(enable){
             long scheduleId = Long.parseLong(roomId);
@@ -475,7 +655,15 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                     ImNetworkRoomMusicSheetDownloadData msg = courseScheduleStudentPaymentService.getMemberExamSong(scheduleId, userId);
                     msg.setEnable(enable);
                     courseScheduleStudentPaymentService.getDao().adjustExamSong(scheduleId,userId, JSON.toJSONString(msg));
-                    imHelper.publishMessage(imUserId, roomId, deviceResourceMessage, 1);
+
+                    // 消息发送
+                    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()).
@@ -487,7 +675,13 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                     deviceResourceMessage.setMusicSheetAccompanimentId(musicSheetId);
                     deviceResourceMessage.setUserId(imUserId);
                     deviceResourceMessage.setSoundVolume(deviceControl.getSoundVolume());
-                    imHelper.publishMessage(sysUser.getId().toString(), roomId, deviceResourceMessage, 1);
+                    if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+                        // 腾讯云推送
+                        pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
+                    } else {
+                        // 融云推送
+                        imHelper.publishMessage(sysUser.getId().toString(), roomId, deviceResourceMessage, 1);
+                    }
                     break;
                 case ACCOMPANIMENT:
                   Integer musicSheetAccompanimentId = Optional.ofNullable(deviceControl.getMusicSheetAccompanimentId()).
@@ -499,15 +693,28 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                     deviceResourceMessage.setMusicSheetAccompanimentId(musicSheetAccompanimentId);
                     deviceResourceMessage.setUserId(imUserId);
                     deviceResourceMessage.setSoundVolume(deviceControl.getSoundVolume());
-                    imHelper.publishMessage(sysUser.getId().toString(), roomId, deviceResourceMessage, 1);
+                    if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+                        // 腾讯云推送
+                        pluginService.sendChatRoomMessage(message.objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE).content(notifyContent));
+                    } else {
+                        // 融云推送
+                        imHelper.publishMessage(sysUser.getId().toString(), roomId, deviceResourceMessage, 1);
+                    }
                     break;
                 default:
-                    //邀请打开指定设备权限
-                    ImNetworkControlDeviceNotifyMessage message = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.INVITE.ordinal());
-                    message.setType(deviceControl.getDeviceType().ordinal());
-                    message.setOpUserId(sysUser.getId().toString());
-                    message.setOpUserName(sysUser.getUsername());
-                    imHelper.publishMessage(sysUser.getId().toString(), imUserId, roomId, message);
+                    // 发送消息
+                    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(sysUser.getId().toString());
+                        message1.setOpUserName(sysUser.getUsername());
+                        imHelper.publishMessage(sysUser.getId().toString(), imUserId, roomId, message1);
+                    }
                     break;
             }
         }else {
@@ -543,13 +750,19 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                     deviceControl.getDeviceType() != ImNetworkDeviceTypeEnum.ACCOMPANIMENT){
                 imNetworkRoomMemberService.getDao().updateById(roomMember);
             }
-            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());
+            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(sysUser.getId().toString(), roomId, deviceResourceMessage, 1);
             }
-            imHelper.publishMessage(sysUser.getId().toString(), roomId, deviceResourceMessage, 1);
         }
     }
 
@@ -588,25 +801,67 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                 deviceControl.getDeviceType() == ImNetworkDeviceTypeEnum.MICROPHONE){
             imNetworkRoomMemberService.getDao().updateById(roomMember);
         }
-        ImNetworkControlDeviceNotifyMessage msg = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.APPROVE.ordinal());
-        msg.setType(deviceControl.getDeviceType().ordinal());
-        msg.setOpUserId(sysUser.getId().toString());
-        msg.setOpUserName(sysUser.getUsername());
-        //获取老师编号
-        Long teacherId = Optional.ofNullable(courseScheduleService.getById(deviceControl.getRoomId())).
-                map(CourseSchedule::getTeacherId).
-                orElseThrow(()->new BizException("房间信息不存在"));
-        imHelper.publishMessage(imUserId, teacherId.toString(), deviceControl.getRoomId(), msg);
 
-        //发送设备状态变更消息
-        this.sendDeviceStateChangedMessage(deviceControl, imUserId);
+        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());
+            //获取老师编号
+            imHelper.publishMessage(imUserId, courseSchedule.getTeacherId().toString(), deviceControl.getRoomId(), msg);
+            //发送设备状态变更消息
+            this.sendDeviceStateChangedMessage(deviceControl, imUserId);
+        }
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deviceStatusSync(ImNetworkDeviceControlDto deviceStatusSync) throws Exception {
         log.info("deviceStatusSync: enable:{} ,roomId:{} ,deviceType:{}", deviceStatusSync.getEnable(),deviceStatusSync.getRoomId(),deviceStatusSync.getDeviceType());
-        Long userId = sysUserService.getUserId();
+        SysUser user = sysUserService.getUser();
+        Long userId = user.getId();
 
         UserRoleEnum userRole = UserRoleEnum.TEACHER;
         String imUserId = String.valueOf(userId);
@@ -646,8 +901,33 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                 deviceType == ImNetworkDeviceTypeEnum.MUSIC_MODE){
             imNetworkRoomMemberService.getDao().updateById(roomMember);
         }
+        CourseSchedule courseSchedule = courseScheduleService.getById(deviceStatusSync.getRoomId());
         //发送设备状态同步消息
-        this.sendDeviceStateChangedMessage(deviceStatusSync, imUserId);
+        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);
+        }
     }
 
     @Override
@@ -678,15 +958,42 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
     public void rejectControlDevice(ImNetworkDeviceControlDto deviceControl) throws Exception {
         log.info("rejectControlDevice: roomId:{} ,deviceType:{}", deviceControl.getRoomId(),deviceControl.getDeviceType());
         SysUser sysUser = sysUserService.getUser();
-        ImNetworkControlDeviceNotifyMessage msg = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.REJECT.ordinal());
-        msg.setType(deviceControl.getDeviceType().ordinal());
-        msg.setOpUserId(sysUser.getId().toString());
-        msg.setOpUserName(sysUser.getUsername());
-        //获取老师编号
-        Long teacherId = Optional.ofNullable(courseScheduleService.getById(deviceControl.getRoomId())).
-                map(CourseSchedule::getTeacherId).
-                orElseThrow(()->new BizException("房间信息不存在"));
-        imHelper.publishMessage(sysUser.getId().toString(),teacherId.toString(), deviceControl.getRoomId(), msg);
+
+        CourseSchedule courseSchedule = courseScheduleService.getById(deviceControl.getRoomId());
+        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(sysUser.getId().toString())
+                    .targetName(sysUser.getUsername())
+                    .sendUserInfo(getSendUser(sysUser, RoleEnum.RoleTeacher));
+
+
+            RTCRoomMessage roomMessage = RTCRoomMessage.builder()
+                    .objectName(RTCRoomMessage.CONTROL_DEVICE_NOTIFY_MESSAGE)
+                    .content(action.build())
+                    .toChatRoomId(deviceControl.getRoomId())
+                    .fromUserId(sysUser.getId().toString())
+                    .isIncludeSender(1)
+                    .isPersisted(1)
+                    .build();
+
+            pluginService.sendChatRoomMessage(roomMessage);
+        } else {
+            ImNetworkControlDeviceNotifyMessage msg = new ImNetworkControlDeviceNotifyMessage(ImNetworkActionEnum.REJECT.ordinal());
+            msg.setType(deviceControl.getDeviceType().ordinal());
+            msg.setOpUserId(sysUser.getId().toString());
+            msg.setOpUserName(sysUser.getUsername());
+            //获取老师编号
+            Long teacherId = Optional.ofNullable(courseScheduleService.getById(deviceControl.getRoomId())).
+                    map(CourseSchedule::getTeacherId).
+                    orElseThrow(()->new BizException("房间信息不存在"));
+            imHelper.publishMessage(sysUser.getId().toString(),teacherId.toString(), deviceControl.getRoomId(), msg);
+        }
     }
 
     @Override
@@ -712,10 +1019,7 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         ImNetworkMusicSheetDownloadStatusMessage statusMessage = new ImNetworkMusicSheetDownloadStatusMessage(status,studentMusicSheetResults);
 
         // IM用户ID
-        String imUserId = String.valueOf(userId);
-        if (ClientEnum.STUDENT == musicSheetDto.getClientType()) {
-            imUserId = MessageFormat.format("{0}:{1}", imUserId, ClientEnum.STUDENT.name());
-        }
+        String imUserId = this.getImUserId(userId,musicSheetDto.getClientType());
 
         imHelper.publishMessage(imUserId, courseSchedule.getTeacherId().toString(), roomId.toString(), statusMessage);
     }
@@ -731,10 +1035,10 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         return courseSchedule.getStartTime().compareTo(addMinutes) > 0;
     }
 
-    public ImNetworkRoom initRoom(String roomId,Long courseId,UserRoleEnum userRole,Long userId,Date now) throws Exception {
+    public ImNetworkRoom initRoom(String roomId,Long courseId,RoleEnum userRole,Long userId,Date now) throws Exception {
         ImNetworkRoom room = baseMapper.findByRoomId(roomId);
         String display = "";
-        if (userRole == UserRoleEnum.TEACHER) {
+        if (userRole == RoleEnum.RoleTeacher) {
             display = "display://type=0?userId=" + userId + "?uri=";
         }
         if(Objects.isNull(room)){
@@ -751,7 +1055,7 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                 log.error("创建群聊失败 resultInfo:{}",resultInfo);
             }
         }else {
-            if(userRole == UserRoleEnum.TEACHER){
+            if(userRole == RoleEnum.RoleTeacher){
                 room.setDisplay(display);
                 baseMapper.updateById(room);
             }
@@ -762,9 +1066,36 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
     //修改节拍器
     public void updateDisplay(String imUserId,ImNetworkRoom room) throws Exception {
         baseMapper.updateById(room);
-
         // IM发送用户消息
-        this.sendDisplay(imUserId,room);
+        ImNetworkRoomMember roomMember = imNetworkRoomMemberService.lambdaQuery().eq(ImNetworkRoomMember::getUserId, imUserId)
+                .eq(ImNetworkRoomMember::getRoomId, room.getRoomId()).last("LIMIT 1").one();
+        CourseSchedule courseSchedule = courseScheduleService.getById(room.getRoomId());
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(courseSchedule.getServiceProvider())) {
+            sendDisplayMessage(room.getDisplay(), roomMember);
+        } else {
+            this.sendDisplay(imUserId,room);
+        }
+    }
+
+    private void sendDisplayMessage(String display, ImNetworkRoomMember roomMember) throws Exception {
+        // 获取RTC服务提供方
+        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(TencentCloudRTCPlugin.PLUGIN_NAME);
+        // 腾讯云RTC服务
+        RTCRoomMessage.MessageContent.MessageContentBuilder action = RTCRoomMessage.MessageContent.builder()
+                .display(display)
+                .sendUserInfo(getSendUser(sysUserService.findUserById(roomMember.getUserId()),RoleEnum.getEnumByValue(roomMember.getRole())));
+
+
+        RTCRoomMessage roomMessage = RTCRoomMessage.builder()
+                .objectName(RTCRoomMessage.DISPLAY_MESSAGE)
+                .content(action.build())
+                .toChatRoomId(roomMember.getRoomId())
+                .fromUserId(roomMember.getUserId().toString())
+                .isIncludeSender(1)
+                .isPersisted(1)
+                .build();
+
+        pluginService.sendChatRoomMessage(roomMessage);
     }
 
     public void sendDisplay(String imUserId,ImNetworkRoom room) throws Exception {
@@ -783,4 +1114,88 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         }
         return result;
     }
+
+    private void joinImGroup(String roomId, Integer actualTeacherId, CourseSchedule courseSchedule) throws Exception {
+
+        String joinImGroupKey = "joinImGroup:" + roomId;
+        // VIP课或网络课,IM群聊已创建标识
+        Boolean exists = redisTemplate.opsForValue().setIfAbsent(joinImGroupKey, roomId, 1L, TimeUnit.DAYS);
+
+        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(courseSchedule.getServiceProvider());
+        if (Optional.ofNullable(exists).orElse(false)) {
+
+            try {
+                // 创建群组
+                log.info("createImGroup: roomId = {}, userId = {}", roomId, actualTeacherId);
+                if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+
+                    // 群组帐号注册
+                    TeacherVo teacherVo = teacherDao.detail(courseSchedule.getTeacherId());
+                    if (Objects.nonNull(teacherVo)) {
+                        try {
+                            pluginService.register(courseSchedule.getTeacherId().toString(), teacherVo.getRealName(), teacherVo.getAvatar());
+                        } catch (Exception e) {
+                            log.error("直播房间群主注册失败: userId={}", courseSchedule.getTeacherId(), e);
+                        }
+                    }
+
+                    // 生成群组
+                    pluginService.chatRoomCreate(roomId, roomId, courseSchedule.getTeacherId().toString());
+
+                    // 群组老师信息
+                    List<ImGroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList(ImGroupMemberWrapper.ImGroupMember
+                            .builder()
+                            .userId(Long.valueOf(actualTeacherId))
+                            .imUserIdFormat(false)
+                            .build());
+
+                    List<CourseScheduleStudentPayment> payments = courseScheduleStudentPaymentService.getByCourseId(Long.parseLong(roomId.substring(1)));
+                    // 群组学生信息
+                    if (org.apache.commons.collections.CollectionUtils.isNotEmpty(payments)) {
+                        for (CourseScheduleStudentPayment item : payments) {
+                            groupMembers.add(ImGroupMemberWrapper.ImGroupMember
+                                    .builder()
+                                    .userId(Long.valueOf(item.getUserId()))
+                                    .imUserIdFormat(false)
+                                    .build());
+                        }
+                    }
+
+                    // 加入群组成员
+                    log.info("joinImGroup: roomId = {}, serviceProvider={}, userIds = {}", roomId, courseSchedule.getServiceProvider(), groupMembers);
+                    pluginService.chatRoomGroupJoin(roomId, roomId, groupMembers);
+                } else {
+
+                    List<CourseScheduleStudentPayment> payments = courseScheduleStudentPaymentService.getByCourseId(Long.parseLong(roomId.substring(1)));
+                    List<String> collect = payments.stream().map(e -> e.getUserId().toString()).collect(Collectors.toList());
+                    collect.add(actualTeacherId.toString());
+                    String[] integers = collect.toArray(new String[]{});
+                    imHelper.joinGroup(integers, roomId, roomId);
+                }
+
+            } catch (Exception e) {
+
+                redisTemplate.delete(joinImGroupKey);
+                // 异常抛出,删除缓存标识
+                throw e;
+            }
+
+        }
+    }
+
+    private void dismissImGroup(String userId,String roomId, String serviceProvider) throws Exception {
+        log.info("dismissImGroup: roomId = {}, userId = {}", roomId, userId);
+        String joinImGroupKey = "joinImGroup:" + roomId;
+        redisTemplate.delete(joinImGroupKey);
+
+        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(serviceProvider);
+        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+            // 腾讯云群销毁
+            pluginService.chatRoomDestroy(roomId);
+        } else {
+            // 融云群销毁
+            // 销毁群组
+            imHelper.dismiss(userId, roomId);
+        }
+    }
 }

+ 6 - 1
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml

@@ -18,11 +18,16 @@
         <result column="created_time_" jdbcType="TIMESTAMP" property="createdTime"/>
         <result column="updated_by_" jdbcType="INTEGER" property="updatedBy"/>
         <result column="updated_time_" jdbcType="TIMESTAMP" property="updatedTime"/>
+        <result column="service_provider_"  property="serviceProvider"/>
+        <result column="room_id_"  property="roomId"/>
+        <result column="mute_all_"  property="muteAll"/>
     </resultMap>
 
     <sql id="Base_Column_List">
         id_
-        , course_group_id_, type_, status_,class_num_, teacher_id_, class_date_, start_time_, end_time_, lock_, lock_time_, ex_student_num_, created_by_, created_time_, updated_by_, updated_time_
+        , course_group_id_, type_, status_,class_num_, teacher_id_, class_date_,
+            start_time_, end_time_, lock_, lock_time_, ex_student_num_,
+            created_by_, created_time_, updated_by_, updated_time_,service_provider_,room_id_,mute_all_
     </sql>
 
     <insert id="insertBatch" keyColumn="id_" keyProperty="id" useGeneratedKeys="true"