liujc 2 年之前
父节点
当前提交
eca1384f01
共有 17 个文件被更改,包括 856 次插入287 次删除
  1. 5 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/AdminFeignService.java
  2. 16 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/dto/ImUserInfo.java
  3. 6 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/AdminFeignServiceFallback.java
  4. 5 0
      cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/web/controller/TokenController.java
  5. 6 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/ImGroupController.java
  6. 22 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/ImController.java
  7. 5 0
      cooleshow-user/user-biz/pom.xml
  8. 6 79
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkDeviceControlDto.java
  9. 11 37
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/ImNetworkRoomResult.java
  10. 12 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseSchedule.java
  11. 36 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/RoleEnum.java
  12. 12 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImGroupService.java
  13. 2 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImNetworkRoomMemberService.java
  14. 206 56
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImGroupServiceImpl.java
  15. 3 8
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImNetworkRoomMemberServiceImpl.java
  16. 497 101
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImNetworkRoomServiceImpl.java
  17. 6 1
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml

+ 5 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/AdminFeignService.java

@@ -7,6 +7,7 @@ import com.yonge.cooleshow.api.feign.dto.StudentWrapper;
 import com.yonge.cooleshow.api.feign.dto.TeacherApi;
 import com.yonge.cooleshow.api.feign.dto.TenantWrapper;
 import com.yonge.cooleshow.api.feign.dto.UserFriendInfoVO;
+import com.yonge.cooleshow.api.feign.dto.*;
 import com.yonge.cooleshow.api.feign.fallback.AdminFeignServiceFallback;
 import com.yonge.cooleshow.common.constant.AppConstant;
 import com.yonge.cooleshow.common.entity.ContractDto;
@@ -171,4 +172,8 @@ public interface AdminFeignService {
 
     @PostMapping("/open/adminClient/unionStudent")
     HttpResponseResult<StudentWrapper.UnionStudentResp> unionStudent(@RequestBody StudentWrapper.UnionStudent info);
+
+
+    @PostMapping(value = "/open/im/register")
+    ImUserInfo register(@RequestParam("userId") String userId, @RequestParam("clientType") String clientType, @RequestParam("username") String username, @RequestParam("avatar") String avatar);
 }

+ 16 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/dto/ImUserInfo.java

@@ -0,0 +1,16 @@
+package com.yonge.cooleshow.api.feign.dto;
+
+import lombok.Data;
+
+@Data
+public class ImUserInfo {
+
+    private String imUserId;
+
+    private String imToken;
+
+    public ImUserInfo imUserId(String imUserId) {
+        this.imUserId = imUserId;
+        return this;
+    }
+}

+ 6 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/AdminFeignServiceFallback.java

@@ -8,6 +8,7 @@ import com.yonge.cooleshow.api.feign.dto.StudentWrapper;
 import com.yonge.cooleshow.api.feign.dto.TeacherApi;
 import com.yonge.cooleshow.api.feign.dto.TenantWrapper;
 import com.yonge.cooleshow.api.feign.dto.UserFriendInfoVO;
+import com.yonge.cooleshow.api.feign.dto.*;
 import com.yonge.cooleshow.common.entity.ContractDto;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.common.entity.MallOrderItemDto;
@@ -161,4 +162,9 @@ public class AdminFeignServiceFallback implements AdminFeignService {
     public HttpResponseResult<StudentWrapper.UnionStudentResp> unionStudent(StudentWrapper.UnionStudent info) {
         return null;
     }
+
+    @Override
+    public ImUserInfo register(String userId, String clientType, String username, String avatar) {
+        return null;
+    }
 }

+ 5 - 0
cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/web/controller/TokenController.java

@@ -3,6 +3,8 @@ package com.yonge.cooleshow.auth.web.controller;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.yonge.cooleshow.api.feign.AdminFeignService;
+import com.yonge.cooleshow.api.feign.dto.ImUserInfo;
 import com.yonge.cooleshow.auth.api.dto.QRLoginDto;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.auth.api.vo.SysUserVo;
@@ -40,6 +42,7 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.client.RestTemplate;
 
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.text.MessageFormat;
@@ -70,6 +73,8 @@ public class TokenController extends BaseController {
 
     @Autowired
     private RedissonClient redissonClient;
+    @Resource
+    private AdminFeignService adminFeignService;
 
     @PostMapping(value = "/smsLogin", consumes = MediaType.APPLICATION_JSON_VALUE)
     @ApiOperation(value = "短信验证码的方式登录")

+ 6 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/ImGroupController.java

@@ -150,6 +150,12 @@ public class ImGroupController extends BaseController {
 
     }
 
+    @GetMapping(value = "/groupTransfer")
+    @ApiOperation("群导入")
+    public void groupTransfer() {
+        imGroupService.groupTransfer();
+    }
+
 
 
 

+ 22 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/ImController.java

@@ -8,17 +8,21 @@ import com.microsvc.toolkit.middleware.live.impl.TencentCloudLivePlugin;
 import com.yonge.cooleshow.admin.io.request.course.CourseRelationVo;
 import com.yonge.cooleshow.admin.io.request.im.IMNotifyMessageVO;
 import com.yonge.cooleshow.admin.io.request.im.UserFriendInfoVO;
+import com.yonge.cooleshow.api.feign.dto.ImUserInfo;
 import com.yonge.cooleshow.biz.dal.dto.TencentData;
 import com.yonge.cooleshow.biz.dal.dto.TencentImCallbackResult;
 import com.yonge.cooleshow.biz.dal.entity.ImUserStateSync;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.enums.im.ETencentImCallbackCommand;
 import com.yonge.cooleshow.biz.dal.service.CourseRelationMusicAlbumService;
+import com.yonge.cooleshow.biz.dal.service.ImGroupService;
 import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
 import com.yonge.cooleshow.biz.dal.service.LiveRoomService;
 import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupWrapper;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.toolset.base.exception.BizException;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -62,6 +66,9 @@ public class ImController extends BaseController {
     @Autowired
     private LiveRoomService liveRoomService;
 
+    @Autowired
+    private ImGroupService imGroupService;
+
     @ApiOperation("新用户添加客服")
     @PostMapping(value = "/im/customerService")
     public HttpResponseResult<Boolean> customerService(@RequestBody UserFriendInfoVO info) {
@@ -241,5 +248,20 @@ public class ImController extends BaseController {
         return TencentData.StreamEventCallbackResult.builder().code(0).build();
     }
 
+    @ApiOperation("注册im用户")
+    @PostMapping(value = "/im/register")
+    public ImUserInfo register(String userId, ClientEnum clientType, String username, String avatar) {
+
+        log.info("注册im用户");
+
+        try {
+            ImGroupWrapper.ImUserInfo register = imGroupService.register(userId, clientType, username, avatar);
+            return JSON.parseObject(JSON.toJSONString(register), ImUserInfo.class);
+        } catch (Exception e) {
+            log.error("注册im用户失败", e);
+            throw new BizException(e.getMessage());
+        }
+    }
+
 }
 

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

@@ -118,6 +118,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");
+    }
+}

+ 12 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImGroupService.java

@@ -9,11 +9,11 @@ import com.yonge.cooleshow.biz.dal.entity.ImGroup;
 import com.yonge.cooleshow.biz.dal.entity.ImGroupMember;
 import com.yonge.cooleshow.biz.dal.entity.ImHistoryMessage;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.RoleEnum;
 import com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupWrapper;
 import io.rong.models.Result;
 
 import java.io.File;
-import java.net.MalformedURLException;
 import java.util.List;
 import java.util.Set;
 
@@ -45,6 +45,12 @@ public interface ImGroupService extends IService<ImGroup> {
      */
     String getImUserId(String userId,String clientType);
 
+
+    String getImUserId(Long userId, RoleEnum userRole);
+
+
+    String getImUserId(Long userId, ClientEnum clientEnum);
+
     /**
      * 解析IM用户规则
      * @param imUserId IM用户Id
@@ -154,5 +160,10 @@ public interface ImGroupService extends IService<ImGroup> {
      * @throws Exception
      */
     void importInfo(List<ImHistoryMessage> info) throws Exception;
+
+    /**
+     * 群迁移,融云->腾讯
+     */
+    void groupTransfer();
 }
 

+ 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);
 
 }
 

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

@@ -30,23 +30,31 @@ import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
 import com.yonge.cooleshow.biz.dal.service.StudentStarService;
 import com.yonge.cooleshow.biz.dal.service.SysUserService;
 import com.yonge.cooleshow.biz.dal.service.TeacherService;
+import com.yonge.cooleshow.biz.dal.entity.CourseGroup;
+import com.yonge.cooleshow.biz.dal.entity.ImGroup;
+import com.yonge.cooleshow.biz.dal.entity.ImGroupMember;
+import com.yonge.cooleshow.biz.dal.entity.ImHistoryMessage;
+import com.yonge.cooleshow.biz.dal.entity.StudentStar;
 import com.yonge.cooleshow.biz.dal.entity.Teacher;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.enums.ImGroupMemberRoleType;
 import com.yonge.cooleshow.biz.dal.enums.ImGroupType;
-import com.yonge.cooleshow.biz.dal.entity.StudentStar;
-import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.enums.RoleEnum;
+import com.yonge.cooleshow.biz.dal.service.CourseGroupService;
+import com.yonge.cooleshow.biz.dal.service.ImGroupMemberService;
+import com.yonge.cooleshow.biz.dal.service.ImGroupService;
+import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
+import com.yonge.cooleshow.biz.dal.service.StudentStarService;
+import com.yonge.cooleshow.biz.dal.service.SysConfigService;
+import com.yonge.cooleshow.biz.dal.service.SysUserService;
+import com.yonge.cooleshow.biz.dal.service.TeacherService;
 import com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupWrapper;
 import com.yonge.toolset.base.exception.BizException;
 import com.yonge.toolset.base.util.ThreadPool;
-import com.yonge.toolset.utils.http.HttpUtil;
 import io.rong.RongCloud;
 import io.rong.methods.message.history.History;
 import io.rong.models.Result;
-import io.rong.models.group.GroupMember;
-import io.rong.models.group.GroupModel;
 import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang.math.RandomUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.redisson.api.RBucket;
 import org.redisson.api.RedissonClient;
@@ -58,23 +66,21 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.io.*;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.text.MessageFormat;
 import java.util.*;
-import java.util.stream.Collectors;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 import java.util.zip.ZipInputStream;
 
-import static com.microsvc.toolkit.middleware.im.message.ETencentMessage.TIMImageElem;
-import static com.microsvc.toolkit.middleware.im.message.ETencentMessage.TIMLocationElem;
-import static com.microsvc.toolkit.middleware.im.message.ETencentMessage.TIMTextElem;
-
 /**
  * 即时通讯群组(ImGroup)表服务实现类
  *
@@ -145,7 +151,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
      * @return IM聊天Token
      */
     @Override
-    public ImGroupWrapper.ImUserInfo register(String userId,ClientEnum clientType, String username, String avatar) throws Exception {
+    public ImGroupWrapper.ImUserInfo register(String userId, ClientEnum clientType, String username, String avatar) throws Exception {
 
         ImGroupWrapper.ImUserInfo userInfo = ImGroupWrapper.ImUserInfo.builder()
                 .imUserId("").imToken("").build();
@@ -153,7 +159,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
         try {
 
             // 聊天Token
-            String imUserId = getImUserId(userId,clientType.getCode());
+            String imUserId = getImUserId(userId, clientType.getCode());
 
             // 生成签名
             userInfo.imUserId(imUserId)
@@ -173,10 +179,36 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
      * @return String
      */
     @Override
-    public String getImUserId(String userId,String clientType) {
+    public String getImUserId(String userId, String clientType) {
         String imUserId = userId;
         if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !userId.startsWith(imConfig.getAppPrefix())) {
-            imUserId = MessageFormat.format("{0}:{1}:{2}", imConfig.getAppPrefix(), userId,clientType);
+            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId, clientType);
+        }
+        return imUserId;
+    }
+
+    @Override
+    public String getImUserId(Long userId, RoleEnum userRole) {
+        String imUserId = String.valueOf(userId);
+        String clientType = "STUDENT";
+        if(userRole.RoleTeacher == userRole){
+            clientType = "TEACHER";
+        }
+        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !imUserId.startsWith(imConfig.getAppPrefix())) {
+            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId, clientType);
+        }
+        return imUserId;
+    }
+
+    @Override
+    public String getImUserId(Long userId, ClientEnum clientEnum) {
+        String imUserId = String.valueOf(userId);
+        String clientType = "STUDENT";
+        if(clientEnum.TEACHER == clientEnum){
+            clientType = "TEACHER";
+        }
+        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !imUserId.startsWith(imConfig.getAppPrefix())) {
+            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId, clientType);
         }
         return imUserId;
     }
@@ -191,7 +223,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
     @Override
     public String analysisImUserId(String imUserId) {
         if (StringUtils.isNotBlank(imConfig.getAppPrefix())) {
-            return imUserId.replace(imConfig.getAppPrefix() + ":", "");
+            return imUserId.replace(imConfig.getAppPrefix() + "_", "");
         }
         return imUserId;
     }
@@ -218,9 +250,9 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
         }
 
         //创建融云群
-        this.rtcCreate(imGroup.getCreateBy(),imGroupId,imGroup.getName());
+        this.rtcCreate(imGroup.getCreateBy(), imGroupId, imGroup.getName());
         //加入融云群
-        imGroupMemberService.join(groupMembers,imGroupId);
+        imGroupMemberService.join(groupMembers, imGroupId);
     }
 
 
@@ -273,9 +305,13 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
         imUserFriendService.saveUserFriend(teacherId, studentIds);
         //处理本地群成员列表
         // 添加老师
-        List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMember(imGroupId, imGroup.getCreateBy(), true, ImGroupMemberRoleType.TEACHER);
-        // 添加学生
-        groupMembers.addAll(imGroupMemberService.initGroupMembers(imGroupId, studentIds, ImGroupMemberRoleType.STUDENT));
+        List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMember(imGroupId, imGroup.getCreateBy(),
+                true, ImGroupMemberRoleType.TEACHER);
+        if (CollectionUtils.isNotEmpty(studentIds)) {
+            // 添加学生
+            groupMembers.addAll(imGroupMemberService.initGroupMembers(imGroupId, studentIds,
+                    ImGroupMemberRoleType.STUDENT));
+        }
         //创建融云群
         this.rtcCreate(courseGroup.getTeacherId(), imGroupId, imGroup.getName());
         //加入融云群
@@ -285,12 +321,12 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 
 
     //创建融云群
-    private void rtcCreate(Long userId,String imGroupId,String imGroupName) throws Exception {
-        rtcCreate(userId,imGroupId,imGroupName,ClientEnum.TEACHER);
+    private void rtcCreate(Long userId, String imGroupId, String imGroupName) throws Exception {
+        rtcCreate(userId, imGroupId, imGroupName, ClientEnum.TEACHER);
     }
 
     //创建融云群
-    private void rtcCreate(Long userId,String imGroupId,String imGroupName,ClientEnum clientType) throws Exception {
+    private void rtcCreate(Long userId, String imGroupId, String imGroupName, ClientEnum clientType) throws Exception {
         //创建群
         SysUser user = sysUserService.findUserById(userId);
 
@@ -307,7 +343,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
                 .avatar(null)
                 .nickname(user.getUsername())
                 .isAdmin(true)
-                .imUserId(getImUserId(userId.toString(),clientType.getCode()))
+                .imUserId(getImUserId(userId.toString(), clientType.getCode()))
                 .roleType(clientType.getCode())
                 .build();
         groupMembers.add(groupMember);
@@ -317,7 +353,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 
         // 创建IM群组
         imPluginContext.getPluginService().groupCreate(imGroupId, imGroupName,
-                getImUserId(userId.toString(),clientType.getCode()));
+                getImUserId(userId.toString(), clientType.getCode()));
 
         // 添加群成员到当前群组
         imPluginContext.getPluginService().groupJoin(imGroupId, imGroupName,
@@ -327,6 +363,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 
     /**
      * 批量导入用户
+     *
      * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
      */
     private void registerUser(List<GroupMemberWrapper.ImGroupMember> groupMembers) {
@@ -343,7 +380,8 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
                             member.getClientType());
                 }
 
-                imPluginContext.getPluginService().register(getImUserId(imUserId,member.getClientType()), member.getNickname(), member.getAvatar());
+                imPluginContext.getPluginService().register(getImUserId(imUserId, member.getClientType()),
+                        member.getNickname(), member.getAvatar());
             } catch (Exception e) {
                 log.error("registerUser member imToken");
             }
@@ -370,6 +408,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 
     /**
      * 自动注册用户
+     *
      * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
      */
     @Override
@@ -383,7 +422,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
         Long createBy = Optional.ofNullable(this.baseMapper.selectById(groupId)).
                 map(ImGroup::getCreateBy).
                 orElseThrow(() -> new BizException("操作失败:群组不存在"));
-        if(!sysUserService.getUserId().equals(createBy)){
+        if (!sysUserService.getUserId().equals(createBy)) {
             throw new BizException("操作失败:您没有操作权限");
         }
         //删除入群申请
@@ -420,7 +459,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
     @Override
     public ImGroup getByCourseGroupId(Long courseGroupId) {
         return this.lambdaQuery()
-                .eq(ImGroup::getCourseGroupId,courseGroupId)
+                .eq(ImGroup::getCourseGroupId, courseGroupId)
                 .last("limit 1")
                 .one();
     }
@@ -444,7 +483,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
             imUserId = MessageFormat.format("{0}:{1}", imUserId, ClientEnum.STUDENT.name());
         }
 
-        if(imGroupMemberService.getDao().delByGroupIdAndUserId(groupId, userId, roleType) < 1){
+        if (imGroupMemberService.getDao().delByGroupIdAndUserId(groupId, userId, roleType) < 1) {
             throw new BizException("操作失败:用户不在此群组");
         }
         //修改群成员数
@@ -470,10 +509,10 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 
             // 已经有群的不操作
             Integer count = this.lambdaQuery()
-                                .eq(ImGroup::getCreateBy, teacher.getUserId())
-                                .eq(ImGroup::getAutoPassFlag, true)
-                                .eq(ImGroup::getType, ImGroupType.FAN)
-                                .count();
+                    .eq(ImGroup::getCreateBy, teacher.getUserId())
+                    .eq(ImGroup::getAutoPassFlag, true)
+                    .eq(ImGroup::getType, ImGroupType.FAN)
+                    .count();
             if (count > 0) {
                 continue;
             }
@@ -487,8 +526,8 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 
             // 查询老师的粉丝,添加到群
             List<StudentStar> list = studentStarService.lambdaQuery()
-                                                       .eq(StudentStar::getTeacherId, teacher.getUserId())
-                                                       .list();
+                    .eq(StudentStar::getTeacherId, teacher.getUserId())
+                    .list();
             Set<Long> studentIdList = list.stream().map(StudentStar::getStudentId).collect(Collectors.toSet());
 
 
@@ -505,9 +544,11 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
             String imGroupId = UUID.randomUUID() + imGroup.getType().getCode();
             imGroup.setId(imGroupId);
             this.baseMapper.insert(imGroup);
-            List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMember(imGroupId, imGroup.getCreateBy(), true, ImGroupMemberRoleType.TEACHER);
+            List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMember(imGroupId, imGroup.getCreateBy(),
+                    true, ImGroupMemberRoleType.TEACHER);
             if (!CollectionUtils.isEmpty(studentIdList)) {
-                groupMembers.addAll(imGroupMemberService.initGroupMembers(imGroupId, studentIdList, ImGroupMemberRoleType.STUDENT));
+                groupMembers.addAll(imGroupMemberService.initGroupMembers(imGroupId, studentIdList,
+                        ImGroupMemberRoleType.STUDENT));
             }
             //创建融云群
             this.rtcCreate(sysUser.getId(), imGroupId, imGroup.getName());
@@ -548,7 +589,8 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 
                     if (Objects.nonNull(groupMember)) {
 
-                        String imIdentity = MessageFormat.format("{0}:{1}", String.valueOf(userId), ClientEnum.STUDENT.name());
+                        String imIdentity = MessageFormat.format("{0}:{1}", String.valueOf(userId),
+                                ClientEnum.STUDENT.name());
                         // 缓存用户重新入群标识
                         String userKey = MessageFormat.format("{0}:{1}", groupId, imIdentity);
                         RBucket<Object> bucket = redissonClient.getBucket(userKey);
@@ -584,6 +626,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
 
     /**
      * 同步即时通讯聊天记录
+     *
      * @param date
      * @return
      */
@@ -594,7 +637,7 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
     }
 
     @Override
-    public void saveImHistoryMessage(File file)  {
+    public void saveImHistoryMessage(File file) {
         ZipInputStream zin = null;
         try {
             zin = new ZipInputStream(new FileInputStream(file), StandardCharsets.UTF_8);
@@ -606,19 +649,20 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
                 String line;
                 while ((line = br.readLine()) != null) {
                     try {
-                        historyMessages.add(JSONObject.parseObject(line.substring(line.indexOf("{")), ImHistoryMessage.class));
+                        historyMessages.add(JSONObject.parseObject(line.substring(line.indexOf("{")),
+                                ImHistoryMessage.class));
 //						if(historyMessages.size() >= 2000){
 //							historyMessageDao.batchInsert(new ArrayList<>(historyMessages),HistoryMessage.class);
 //							historyMessages.clear();
 //						}
-                    }catch (Exception e){
+                    } catch (Exception e) {
                         e.printStackTrace();
                     }
                 }
                 br.close();
                 break;
             }
-            if(historyMessages.size() > 0){
+            if (historyMessages.size() > 0) {
                 ImGroupDao dao = getDao();
                 dao.batchInsert(historyMessages.stream().sorted(Comparator.comparing(ImHistoryMessage::getDateTime)).collect(Collectors.toList()));
             }
@@ -665,14 +709,14 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
                 //设置body
 
                 List<TencentRequest.MessageBody> list = new ArrayList<>();
-                list.stream().forEach(item->{
+                list.stream().forEach(item -> {
                     item.setMsgContent(i.getContent());
                     item.setMsgType(i.getClassname());
                 });
-                if (list.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:TxtMsg")){
+                if (list.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:TxtMsg")) {
                     //文本对象
                     list.stream().forEach(item -> item.setMsgType("TIMTextElem"));
-                } else if (list.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:ImgMsg")){
+                } else if (list.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:ImgMsg")) {
                     //图文对象
                     list.stream().forEach(item -> item.setMsgType("TIMImageElem"));
                 }
@@ -698,13 +742,13 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
                 data1.setRandom(new Random().nextInt());
                 //设置发送时间
                 data1.setSendTime(Long.parseLong(i.getDateTime()));
-                bodyList.stream().forEach(item->{
-                            item.setMsgContent(i.getContent());
-                            item.setMsgType(i.getClassname());
-                        });
-                if (bodyList.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:TxtMsg")){
+                bodyList.stream().forEach(item -> {
+                    item.setMsgContent(i.getContent());
+                    item.setMsgType(i.getClassname());
+                });
+                if (bodyList.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:TxtMsg")) {
                     bodyList.stream().forEach(item -> item.setMsgType("TIMTextElem"));
-                } else if (bodyList.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:ImgMsg")){
+                } else if (bodyList.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:ImgMsg")) {
                     //暂未支持图文对象
                     bodyList.stream().forEach(item -> item.setMsgType("TIMCustomElem"));
                 }
@@ -728,11 +772,117 @@ public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> impleme
     }
 
 
-    private History getHistory(){
+    private History getHistory() {
         RongCloud rongCloud = RongCloud.getInstance(appKey, appSecret);
         History history = new History(appKey, appSecret);
         history.setRongCloud(rongCloud);
         return history;
     }
+
+
+    /**
+     * 群迁移
+     */
+    @Override
+    public void groupTransfer() {
+        int page = 1;
+        int size = 100;
+        List<ImGroup> imGroups = this.lambdaQuery().orderByDesc(ImGroup::getCreateTime)
+                .last("limit " + ((page - 1) * size) + "," + size).list();
+        while (!imGroups.isEmpty()) {
+            groupTransfer(imGroups);
+
+            page++;
+            imGroups = this.lambdaQuery().orderByDesc(ImGroup::getCreateTime)
+                    .last("limit " + ((page - 1) * size) + "," + size).list();
+        }
+    }
+
+    private void groupTransfer(List<ImGroup> records) {
+        for (ImGroup imGroup : records) {
+            List<ImGroupMember> memberList = imGroupMemberService.lambdaQuery()
+                    .eq(ImGroupMember::getGroupId, imGroup.getId())
+                    .list();
+            ImGroupMember admin = memberList.stream().filter(ImGroupMember::getIsAdmin).findFirst().orElse(null);
+            if (admin == null) {
+                continue;
+            }
+            try {
+                MessageWrapper.ImportGroup importGroup = new MessageWrapper.ImportGroup();
+                importGroup.setOwnerAccount(getImUserId(admin.getUserId().toString(), "TEACHER"));
+                importGroup.setType("Public");
+                importGroup.setGroupId(imGroup.getId());
+                importGroup.setName(imGroup.getName());
+                importGroup.setIntroduction(imGroup.getIntroduce());
+                importGroup.setNotification(imGroup.getMemo());
+                importGroup.setFaceUrl(imGroup.getImg());
+                if (StringUtils.isEmpty(imGroup.getImg())) {
+                    importGroup.setFaceUrl("https://gyt.ks3-cn-beijing.ksyuncs.com/example/group_default_avatar.png");
+                }
+                importGroup.setApplyJoinOption(Boolean.TRUE.equals(imGroup.getAutoPassFlag()) ? "FreeAccess" :
+                        "NeedPermission");
+                importGroup.setCreateTime(imGroup.getCreateTime().getTime() / 1000);
+
+                register(admin.getUserId(), imGroup.getId(), admin.getAvatar(), true, ClientEnum.TEACHER);
+                imPluginContext.getPluginService().importGroup(importGroup);
+
+                List<ImGroupMember> groupMembers = memberList.stream()
+                        .filter(next -> !next.getIsAdmin()).collect(Collectors.toList());
+                if (groupMembers.isEmpty()) {
+                    continue;
+                }
+                for (ImGroupMember member : groupMembers) {
+                    String avatar = member.getAvatar();
+                    if (StringUtils.isEmpty(avatar)) {
+                        avatar = "https://daya.ks3-cn-beijing.ksyun.com/202203/T1WgJaE.png";
+                    }
+                    register(member.getUserId(), imGroup.getId(), avatar, false,
+                            ImGroupMemberRoleType.STUDENT.equals(member.getRoleType()) ? ClientEnum.STUDENT :
+                                    ClientEnum.TEACHER);
+                }
+                MessageWrapper.ImportGroupMember importGroupMember = new MessageWrapper.ImportGroupMember();
+                importGroupMember.setGroupId(imGroup.getId());
+                List<MessageWrapper.ImportGroupMemberData> members =
+                        groupMembers.stream().map(next -> {
+                            MessageWrapper.ImportGroupMemberData data = new MessageWrapper.ImportGroupMemberData();
+                            data.setMemberAccount(getImUserId(next.getUserId().toString(),
+                                    ImGroupMemberRoleType.STUDENT.equals(next.getRoleType()) ?
+                                            ClientEnum.STUDENT.name() :
+                                            ClientEnum.TEACHER.name()));
+                            data.setJoinTime(next.getCreateTime().getTime() / 1000);
+                            data.setUnreadMsgNum(0);
+                            return data;
+                        }).collect(Collectors.toList());
+                importGroupMember.setMemberList(members);
+                imPluginContext.getPluginService().importGroupMember(importGroupMember);
+            } catch (Exception e) {
+                log.error(String.format("群迁移加入群聊失败:%s", e.getMessage()));
+            }
+        }
+    }
+
+    private void register(Long userId, String imGroupId, String avatar, Boolean admin, ClientEnum clientType) {
+        SysUser user = sysUserService.findUserById(userId);
+
+        // 群组默认头象
+        List<GroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList();
+        //记录群成员
+        GroupMemberWrapper.ImGroupMember groupMember = GroupMemberWrapper.ImGroupMember
+                .builder()
+                .id(IdWorker.getId())
+                .groupId(imGroupId)
+                .userId(userId)
+                .clientType(clientType.getCode())
+                .avatar(avatar)
+                .nickname(user.getUsername())
+                .isAdmin(admin)
+                .imUserId(getImUserId(userId.toString(), clientType.getCode()))
+                .roleType(clientType.getCode())
+                .build();
+        groupMembers.add(groupMember);
+
+        // 自动激活学生IM帐号
+        registerUser(groupMembers);
+    }
 }
 

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

@@ -5,6 +5,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.ImGroupService;
 import com.yonge.cooleshow.biz.dal.service.ImNetworkRoomMemberService;
@@ -37,7 +38,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,13 +57,7 @@ public class ImNetworkRoomMemberServiceImpl extends ServiceImpl<ImNetworkRoomMem
 
         }
 
-        String imUserId = String.valueOf(sysUser.getUserId());
-        if (UserRoleEnum.STUDENT == userRole) {
-            imUserId = imGroupService.getImUserId(imUserId, ClientEnum.STUDENT.name());
-        }else if(UserRoleEnum.TEACHER == userRole){
-            imUserId = imGroupService.getImUserId(imUserId, ClientEnum.TEACHER.name());
-        }
-        roomMember.setImUserId(imUserId);
+        roomMember.setImUserId(imGroupService.getImUserId(sysUser.getUserId(),userRole));
 
         return roomMember;
     }

+ 497 - 101
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;
@@ -30,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;
 
 /**
@@ -65,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;
 
@@ -87,10 +101,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)).
@@ -122,11 +136,10 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
                 // 学生
                 item.setImUserId(imGroupService.getImUserId(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);
@@ -138,18 +151,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 = imGroupService.getImUserId(imUserId, ClientEnum.STUDENT.name());
-        } else {
-            imUserId = imGroupService.getImUserId(imUserId, ClientEnum.TEACHER.name());
-        }
+        String imUserId = imGroupService.getImUserId(sysUser.getUserId(),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);
     }
@@ -175,7 +195,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;
@@ -190,11 +210,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);
@@ -207,11 +227,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);
@@ -317,22 +387,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 = imGroupService.getImUserId(imUserId, ClientEnum.STUDENT.name());
-        }else if(ClientEnum.TEACHER == customMessage.getClientType()){
-            imUserId = imGroupService.getImUserId(imUserId, ClientEnum.TEACHER.name());
+        String imUserId = imGroupService.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(","))
@@ -347,7 +460,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);
 
@@ -368,25 +481,53 @@ 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= imGroupService.getImUserId(imUserId,ClientEnum.STUDENT.name());
-        }else if (ClientEnum.TEACHER == musicSheetDto.getClientType()) {
-            imUserId= imGroupService.getImUserId(imUserId,ClientEnum.TEACHER.name());
-        }
+        String imUserId = imGroupService.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 {
@@ -418,12 +559,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 = imGroupService.getImUserId(imUserId, ClientEnum.STUDENT.name());
-        } else if (ClientEnum.TEACHER == displayData.getClientType()) {
-            imUserId = imGroupService.getImUserId(imUserId, ClientEnum.TEACHER.name());
-        }
+        String imUserId = imGroupService.getImUserId(userId,displayData.getClientType());
 
         this.updateDisplay(imUserId,room);
     }
@@ -477,6 +613,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);
@@ -487,7 +657,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()).
@@ -499,7 +677,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()).
@@ -511,15 +695,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 {
@@ -555,13 +752,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);
         }
     }
 
@@ -571,14 +774,11 @@ public class ImNetworkRoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNe
         log.info("approveControlDevice: roomId:{} ,deviceType:{} ,enable:{}", deviceControl.getRoomId(),deviceControl.getDeviceType(),deviceControl.getEnable());
         SysUser sysUser = sysUserService.getUser();
 
-        String imUserId = String.valueOf(sysUser.getId());
         UserRoleEnum userRole = UserRoleEnum.TEACHER;
         if (ClientEnum.STUDENT == deviceControl.getClientType()) {
-            imUserId = imGroupService.getImUserId(imUserId, ClientEnum.STUDENT.name());
             userRole = UserRoleEnum.STUDENT;
-        }else {
-            imUserId = imGroupService.getImUserId(imUserId, ClientEnum.TEACHER.name());
         }
+        String imUserId = imGroupService.getImUserId(sysUser.getId(),deviceControl.getClientType());
 
         ImNetworkRoomMember roomMember = Optional.ofNullable(imNetworkRoomMemberService.getDao().findByRidAndUid(deviceControl.getRoomId(), sysUser.getId(),
                         userRole.ordinal())).
@@ -601,35 +801,73 @@ 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);
         if (ClientEnum.STUDENT == deviceStatusSync.getClientType()) {
-            imUserId = imGroupService.getImUserId(imUserId,ClientEnum.STUDENT.name());
-
             userRole = UserRoleEnum.STUDENT;
-        }else {
-            imUserId = imGroupService.getImUserId(imUserId, ClientEnum.TEACHER.name());
         }
+        String imUserId = imGroupService.getImUserId(userId,deviceStatusSync.getClientType());
 
         ImNetworkDeviceTypeEnum deviceType = deviceStatusSync.getDeviceType();
         ImNetworkRoomMember roomMember = Optional.ofNullable(imNetworkRoomMemberService.getDao().
@@ -661,8 +899,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
@@ -691,15 +954,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
@@ -725,12 +1015,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 = imGroupService.getImUserId(imUserId, ClientEnum.STUDENT.name());
-        }else {
-            imUserId = imGroupService.getImUserId(imUserId, ClientEnum.TEACHER.name());
-        }
+        String imUserId = imGroupService.getImUserId(userId,musicSheetDto.getClientType());
 
         imHelper.publishMessage(imUserId, courseSchedule.getTeacherId().toString(), roomId.toString(), statusMessage);
     }
@@ -746,10 +1031,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)){
@@ -766,7 +1051,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);
             }
@@ -777,9 +1062,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 {
@@ -798,4 +1110,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"