Browse Source

fix切换腾讯IM服务

Eric 1 year ago
parent
commit
0624520e0b
89 changed files with 5664 additions and 828 deletions
  1. 1 0
      .gitignore
  2. 11 0
      mec-auth/mec-auth-api/src/main/java/com/ym/mec/auth/api/entity/SysUser.java
  3. 1 0
      mec-auth/mec-auth-api/src/main/java/com/ym/mec/auth/api/enums/SysUserType.java
  4. 19 8
      mec-auth/mec-auth-server/src/main/java/com/ym/mec/auth/core/handler/BaseAuthenticationSuccessEventHandler.java
  5. 65 3
      mec-auth/mec-auth-server/src/main/java/com/ym/mec/auth/web/controller/TokenController.java
  6. 1 2
      mec-auth/mec-auth-server/src/main/resources/bootstrap-dev.properties
  7. 1 0
      mec-auth/mec-auth-server/src/main/resources/bootstrap-test.properties
  8. 36 0
      mec-auth/mec-auth-server/src/main/resources/logback-dev.xml
  9. 36 0
      mec-auth/mec-auth-server/src/main/resources/logback-test-env.xml
  10. 31 18
      mec-biz/pom.xml
  11. 27 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ImGroupDao.java
  12. 3 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/TeacherDao.java
  13. 23 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/AuditUserInfo.java
  14. 20 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ImGroupMemberDto.java
  15. 24 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ImGroupNoticeDto.java
  16. 36 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ImUserFriendDto.java
  17. 30 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/im/BasicUserInfo.java
  18. 14 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/im/BasicUserInfoDto.java
  19. 57 29
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImGroup.java
  20. 30 114
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImGroupMember.java
  21. 94 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImHistoryMessage.java
  22. 22 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/EFriendRoleType.java
  23. 26 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/AuditStatusEnum.java
  24. 63 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ClientEnum.java
  25. 26 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImGroupMemberRoleType.java
  26. 22 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImNetworkActionEnum.java
  27. 29 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImNetworkDeviceTypeEnum.java
  28. 31 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImNetworkDisplayEnum.java
  29. 71 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImNetworkRoomErrorEnum.java
  30. 39 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImNetworkRoomMemberChangedEnum.java
  31. 34 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/RoleEnum.java
  32. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/mapper/ImGroupMemberPlusMapper.java
  33. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/mapper/ImGroupPlusMapper.java
  34. 22 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/ImGroupMemberAuditQueryInfo.java
  35. 30 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/vo/ImGroupVo.java
  36. 79 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/vo/SchoolStaffVo.java
  37. 4 3
      mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/ImGroupMemberWrapper.java
  38. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/ImGroupWrapper.java
  39. 209 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/ImHistoryMessageWrapper.java
  40. 3 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/SchoolStaffWrapper.java
  41. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/service/ImGroupMemberPlusService.java
  42. 111 72
      mec-biz/src/main/java/com/ym/mec/biz/service/ImGroupService.java
  43. 152 0
      mec-biz/src/main/java/com/ym/mec/biz/service/im/ImGroupCoreService.java
  44. 596 0
      mec-biz/src/main/java/com/ym/mec/biz/service/im/impl/ImGroupCoreServiceImpl.java
  45. 1 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ClassGroupServiceImpl.java
  46. 123 2
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/EmployeeServiceImpl.java
  47. 3 3
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImGroupMemberPlusServiceImpl.java
  48. 121 6
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImGroupMemberServiceImpl.java
  49. 3 3
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImGroupPlusServiceImpl.java
  50. 1157 114
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImGroupServiceImpl.java
  51. 37 20
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java
  52. 27 6
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImUserFriendServiceImpl.java
  53. 23 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentManageServiceImpl.java
  54. 41 0
      mec-biz/src/main/resources/config/mybatis/ImGroupMapper.xml
  55. 2 1
      mec-biz/src/main/resources/config/mybatis/ImGroupMemberMapper.xml
  56. 4 0
      mec-biz/src/main/resources/config/mybatis/TeacherMapper.xml
  57. 22 1
      mec-client-api/src/main/java/com/ym/mec/im/ImFeignService.java
  58. 11 0
      mec-client-api/src/main/java/com/ym/mec/im/fallback/ImFeignServiceFallback.java
  59. 4 1
      mec-client-api/src/main/java/com/ym/mec/task/TaskRemoteService.java
  60. 4 1
      mec-client-api/src/main/java/com/ym/mec/web/WebFeignService.java
  61. 8 0
      mec-common/audit-log/src/main/java/com/yonge/log/dal/model/HistoryMessage.java
  62. 6 0
      mec-common/audit-log/src/main/java/com/yonge/log/service/HistoryMessageService.java
  63. 51 4
      mec-common/audit-log/src/main/java/com/yonge/log/service/impl/HistoryMessageServiceImpl.java
  64. 16 20
      mec-common/common-core/pom.xml
  65. 49 0
      mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImUserModel.java
  66. 10 0
      mec-common/common-core/src/main/java/com/ym/mec/common/page/QueryInfo.java
  67. 1 0
      mec-gateway/mec-gateway-web/src/main/resources/bootstrap-test.properties
  68. 37 0
      mec-gateway/mec-gateway-web/src/main/resources/logback-dev.xml
  69. 37 0
      mec-gateway/mec-gateway-web/src/main/resources/logback-test-env.xml
  70. 1 1
      mec-im/src/main/java/com/ym/SealClassApplication.java
  71. 1 1
      mec-im/src/main/java/com/ym/config/ResourceServerConfig.java
  72. 105 28
      mec-im/src/main/java/com/ym/controller/GroupController.java
  73. 79 24
      mec-im/src/main/java/com/ym/controller/PrivateController.java
  74. 192 41
      mec-im/src/main/java/com/ym/controller/UserController.java
  75. 191 0
      mec-im/src/main/java/com/ym/service/GroupCoreService.java
  76. 902 0
      mec-im/src/main/java/com/ym/service/Impl/GroupCoreServiceImpl.java
  77. 0 112
      mec-im/src/main/resources/application-template.yml
  78. 1 0
      mec-im/src/main/resources/bootstrap-dev.properties
  79. 0 16
      mec-im/src/main/resources/bootstrap-dev_server.properties
  80. 1 0
      mec-im/src/main/resources/bootstrap-test.properties
  81. 37 0
      mec-im/src/main/resources/logback-dev.xml
  82. 37 0
      mec-im/src/main/resources/logback-test-env.xml
  83. 37 0
      mec-mall/mall-admin/src/main/resources/logback-dev.xml
  84. 37 0
      mec-mall/mall-portal/src/main/resources/logback-dev.xml
  85. 37 0
      mec-task/src/main/resources/logback-dev.xml
  86. 0 143
      mec-websocket/src/main/resources/application-template.yml
  87. 0 16
      mec-websocket/src/main/resources/bootstrap-dev_server.properties
  88. 58 0
      mec-websocket/src/main/resources/logback-dev.xml
  89. 15 12
      pom.xml

+ 1 - 0
.gitignore

@@ -39,6 +39,7 @@ mvnw.cmd
 **/bootstrap-local.yml
 **/bootstrap-local.properties
 **/logback-test.xml
+**/logback-local.xml
 
 /bin/
 **/logback-spring.xml

+ 11 - 0
mec-auth/mec-auth-api/src/main/java/com/ym/mec/auth/api/entity/SysUser.java

@@ -164,6 +164,9 @@ public class SysUser extends BaseEntity implements Serializable{
 	@ApiModelProperty(value = "密码重置标识")
 	private Boolean resetFlag;
 
+	@ApiModelProperty("IM用户ID")
+	private String imUserId;
+
 	public String getSubjectId() {
 		return subjectId;
 	}
@@ -530,4 +533,12 @@ public class SysUser extends BaseEntity implements Serializable{
 	public void setResetFlag(Boolean resetFlag) {
 		this.resetFlag = resetFlag;
 	}
+
+	public String getImUserId() {
+		return imUserId;
+	}
+
+	public void setImUserId(String imUserId) {
+		this.imUserId = imUserId;
+	}
 }

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

@@ -13,6 +13,7 @@ public enum SysUserType implements BaseEnum<String, SysUserType> {
 	SYSTEM("系统內置"),
 	ADMIN("管理员"),
 	SCHOOL("学校员工"),
+	VISITOR("访客"),
 	;
 
 	private String desc;

+ 19 - 8
mec-auth/mec-auth-server/src/main/java/com/ym/mec/auth/core/handler/BaseAuthenticationSuccessEventHandler.java

@@ -1,5 +1,6 @@
 package com.ym.mec.auth.core.handler;
 
+import com.alibaba.fastjson.JSON;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.auth.api.entity.SysUserLogin;
@@ -9,7 +10,6 @@ import com.ym.mec.auth.service.SysUserLoginLogService;
 import com.ym.mec.auth.service.SysUserLoginService;
 import com.ym.mec.auth.service.SysUserService;
 import com.ym.mec.common.entity.HttpResponseResult;
-import com.ym.mec.common.entity.ImResult;
 import com.ym.mec.common.entity.ImUserModel;
 import com.ym.mec.common.security.SecurityConstants;
 import com.ym.mec.im.ImFeignService;
@@ -43,6 +43,7 @@ import java.util.Base64;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 @Component
@@ -83,16 +84,26 @@ public class BaseAuthenticationSuccessEventHandler extends SavedRequestAwareAuth
 		}else {
 			sysUser = sysUserService.queryLockByPhone(username.split(":")[1]);
 		}
-		if(StringUtils.isEmpty(sysUser.getImToken())){
-			String name = sysUser.getRealName();
-			if(StringUtils.isEmpty(name)){
-				name = sysUser.getUsername();
-			}
-			ImResult register = imFeignService.register(new ImUserModel(sysUser.getId().toString(), name, sysUser.getAvatar()));
-			sysUser.setImToken(register.getToken());
+
+		// 如果用户没有imToken则注册im
+		String name = sysUser.getUsername();
+		if(StringUtils.isBlank(name) && StringUtils.isNotBlank(sysUser.getRealName())){
+			name = sysUser.getRealName();
+		}
+		// IM用户信息
+		ImUserModel userModel = new ImUserModel(sysUser.getId().toString(), name, null);
+		// 用户身份
+		userModel.setClientType("");
+		// 用户头象
+		userModel.setAvatar(sysUser.getAvatar());
+		ImUserModel.ImUserResult register = imFeignService.userImTokenInfo(userModel);
+		logger.info("用户:{} 注册IM成功", JSON.toJSONString(register));
+		if (Objects.nonNull(register)) {
+			sysUser.setImToken(register.getImToken());
 			sysUser.setUpdateTime(new Date());
 			sysUserService.update(sysUser);
 		}
+
 		Date date = new Date();
 		//修改添加登录信息
 		SysUserLogin userLogin = sysUserLoginService.findLoginByUserId(sysUser.getId());

+ 65 - 3
mec-auth/mec-auth-server/src/main/java/com/ym/mec/auth/web/controller/TokenController.java

@@ -1,5 +1,6 @@
 package com.ym.mec.auth.web.controller;
 
+import com.google.common.collect.Lists;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -10,6 +11,8 @@ import java.util.Base64;
 import java.util.Collection;
 import java.util.Date;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -29,6 +32,7 @@ import org.springframework.util.MultiValueMap;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.client.RestTemplate;
 
@@ -101,12 +105,70 @@ public class TokenController extends BaseController {
     public Object apiQueryUserInfo() {
 		AuthUser authUser = SecurityUtils.getUser();
 		if(authUser != null){
-			return succeed(userService.queryUserInfo(authUser.getUserId()));
+			SysUser sysUser = userService.queryUserInfo(authUser.getUserId());
+			if (Objects.nonNull(sysUser)) {
+				ImUserModel.ImUserResult imUserResult = getImUserResult("", sysUser);
+				if (Objects.nonNull(imUserResult)) {
+					// IM用户签名
+					sysUser.setImToken(imUserResult.getImToken());
+					// IM用户ID
+					sysUser.setImUserId(imUserResult.getImUserId());
+				}
+			}
+			return succeed(sysUser);
 		}
 		return failed("获取用户信息失败");
     }
-    
-    @PostMapping(value = "/usernameLogin",consumes = MediaType.APPLICATION_JSON_VALUE)
+
+	@ApiOperation(value = "IM用户Token信息")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "clientType", value = "客户端类型: TEACHER,STUDENT,SYSTEM,SCHOOL", required = true, dataType = "String")
+	})
+	@GetMapping("/userImTokenInfo")
+	public HttpResponseResult<ImUserModel.ImUserResult> userImTokenInfo(@RequestParam(required = false) String clientType) {
+
+		AuthUser authUser = SecurityUtils.getUser();
+		if(Objects.isNull(authUser)){
+			return failed("获取用户信息失败");
+		}
+
+		if (StringUtils.isBlank(clientType)) {
+			return failed("用户身份不能为空");
+		}
+
+		SysUser sysUser = userService.queryUserInfo(authUser.getUserId());
+		if (Objects.isNull(sysUser)) {
+			return failed("无效用户信息");
+		}
+
+		ImUserModel.ImUserResult imUserResult = getImUserResult(clientType, sysUser);
+		return succeed(imUserResult);
+
+	}
+
+	/**
+	 * IM用户Token信息
+	 * @param clientType 用户身份
+	 * @param sysUser SysUser
+	 * @return ImUserModel.ImUserResult
+	 */
+	private ImUserModel.ImUserResult getImUserResult(String clientType, SysUser sysUser) {
+		String username = sysUser.getUsername();
+		if (Lists.newArrayList(sysUser.getUserType().split(",")).contains("TEACHER")) {
+			username = Optional.ofNullable(sysUser.getRealName()).orElse(username);
+		}
+
+		// IM用户信息
+		ImUserModel userModel = new ImUserModel(sysUser.getId().toString(), username, null);
+		// 用户身份
+		userModel.setClientType(clientType);
+		// 用户头象
+		userModel.setAvatar(sysUser.getAvatar());
+
+        return imFeignService.userImTokenInfo(userModel);
+	}
+
+	@PostMapping(value = "/usernameLogin",consumes = MediaType.APPLICATION_JSON_VALUE)
 	@ApiOperation(value = "手机号密码方式登录")
 	@ApiImplicitParams({ @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String"),
 			@ApiImplicitParam(name = "clientSecret", value = "固定传 app", required = true, dataType = "String"),

+ 1 - 2
mec-auth/mec-auth-server/src/main/resources/bootstrap-dev.properties

@@ -8,6 +8,5 @@ spring.cloud.nacos.config.prefix=auth
 #\u6307\u5b9a\u6587\u4ef6\u540e\u7f00
 spring.cloud.nacos.config.file-extension=yaml
 #\u662f\u5426\u52a8\u6001\u5237\u65b0
-spring.cloud.nacos.config.refresh.enabled=true
-#\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
 spring.cloud.nacos.config.enabled=true
+logging.config=classpath:logback-dev.xml

+ 1 - 0
mec-auth/mec-auth-server/src/main/resources/bootstrap-test.properties

@@ -14,3 +14,4 @@ spring.cloud.nacos.config.file-extension=yaml
 spring.cloud.nacos.config.refresh.enabled=true
 #\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
 spring.cloud.nacos.config.enabled=true
+logging.config=classpath:logback-test-env.xml

+ 36 - 0
mec-auth/mec-auth-server/src/main/resources/logback-dev.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<property name="LOG_HOME" value="/mdata/mec-dev/logs/auth-%d{yyyy-MM-dd_HH}-%i.log" />
+	<property name="CONSOLE_LOG_PATTERN"
+		value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder charset="UTF-8">
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="file"
+		class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>${LOG_HOME}</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+				class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<logger name="com.ym.mec" level="WARN" />
+	<root level="INFO">
+		<appender-ref ref="stdout" />
+		<appender-ref ref="file" />
+	</root>
+
+</configuration>

+ 36 - 0
mec-auth/mec-auth-server/src/main/resources/logback-test-env.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<property name="LOG_HOME" value="/mdata/mec-test/logs/auth-%d{yyyy-MM-dd_HH}-%i.log" />
+	<property name="CONSOLE_LOG_PATTERN"
+		value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder charset="UTF-8">
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="file"
+		class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>${LOG_HOME}</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+				class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<logger name="com.ym.mec" level="WARN" />
+	<root level="INFO">
+		<appender-ref ref="stdout" />
+		<appender-ref ref="file" />
+	</root>
+
+</configuration>

+ 31 - 18
mec-biz/pom.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <project
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
-	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+		xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+		xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
 		<groupId>com.ym</groupId>
@@ -13,7 +13,6 @@
 	<url>http://maven.apache.org</url>
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-		<redisson.version>3.16.4</redisson.version>
 	</properties>
 
 	<dependencies>
@@ -42,11 +41,6 @@
 		</dependency>
 
 		<dependency>
-			<groupId>org.redisson</groupId>
-			<artifactId>redisson-spring-boot-starter</artifactId>
-			<version>${redisson.version}</version>
-		</dependency>
-		<dependency>
 			<groupId>net.coobird</groupId>
 			<artifactId>thumbnailator</artifactId>
 			<version>0.4.11</version>
@@ -73,16 +67,16 @@
 			<groupId>org.jetbrains.kotlin</groupId>
 			<artifactId>kotlin-stdlib</artifactId>
 		</dependency>
-        <dependency>
-            <groupId>com.microsvc.toolkit.config</groupId>
-            <artifactId>microsvc-config-validator</artifactId>
-            <version>1.0.0</version>
-        </dependency>
-        <dependency>
-            <groupId>com.microsvc.toolkit.middleware</groupId>
-            <artifactId>microsvc-middleware-im</artifactId>
-            <version>1.0.0</version>
-        </dependency>
+		<dependency>
+			<groupId>com.microsvc.toolkit.config</groupId>
+			<artifactId>microsvc-config-validator</artifactId>
+			<version>1.0.0</version>
+		</dependency>
+		<dependency>
+			<groupId>com.microsvc.toolkit.middleware</groupId>
+			<artifactId>microsvc-middleware-im</artifactId>
+			<version>1.0.0</version>
+		</dependency>
 		<dependency>
 			<groupId>com.microsvc.toolkit.middleware</groupId>
 			<artifactId>microsvc-middleware-oss</artifactId>
@@ -94,6 +88,25 @@
 			<artifactId>fastjson</artifactId>
 			<version>1.2.70</version>
 		</dependency>
+		<dependency>
+			<artifactId>microsvc-common-tools</artifactId>
+			<exclusions>
+				<exclusion>
+					<artifactId>commons-io</artifactId>
+					<groupId>commons-io</groupId>
+				</exclusion>
+				<exclusion>
+					<artifactId>fastjson</artifactId>
+					<groupId>com.alibaba</groupId>
+				</exclusion>
+			</exclusions>
+			<groupId>com.microsvc.toolkit.common</groupId>
+			<version>1.0.0</version>
+		</dependency>
+		<dependency>
+			<groupId>com.yonge.log</groupId>
+			<artifactId>audit-log</artifactId>
+		</dependency>
 
 	</dependencies>
 </project>

+ 27 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ImGroupDao.java

@@ -3,8 +3,8 @@ package com.ym.mec.biz.dal.dao;
 import com.ym.mec.biz.dal.dto.ImGroupMemberDto;
 import com.ym.mec.biz.dal.dto.NameDto;
 import com.ym.mec.biz.dal.entity.ImGroup;
+import com.ym.mec.biz.dal.entity.ImHistoryMessage;
 import com.ym.mec.biz.dal.enums.EFriendRoleType;
-import com.ym.mec.biz.dal.enums.school.ESchoolStaffType;
 import com.ym.mec.biz.dal.wrapper.ImGroupWrapper;
 import com.ym.mec.common.dal.BaseDAO;
 import org.apache.ibatis.annotations.Param;
@@ -72,4 +72,30 @@ public interface ImGroupDao extends BaseDAO<String, ImGroup> {
      * @param userType
      */
     void updateSchoolRoleType(@Param("userId") Long userId, @Param("userType") EFriendRoleType userType);
+
+    /**
+     * 更新群组导入成功标志
+     * @param id
+     */
+    void updateImportStatusSuccess(@Param("id") String id);
+
+    /**
+     * 查询数据总数
+     * @return
+     */
+    int queryInfoCount();
+
+    /**
+     * 查总数据
+     * @param result
+     * @param size
+     * @return
+     */
+    List<ImHistoryMessage> selectAll(@Param("result") int result, @Param("size") int size);
+
+    /**
+     * 更新状态
+     * @param info
+     */
+    void updateStatus(@Param("info") List<ImHistoryMessage> info);
 }

+ 3 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/TeacherDao.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dto.*;
+import com.ym.mec.biz.dal.dto.im.BasicUserInfo;
 import com.ym.mec.biz.dal.entity.CourseHomework;
 import com.ym.mec.biz.dal.entity.Teacher;
 import com.ym.mec.common.dal.BaseDAO;
@@ -95,6 +96,8 @@ public interface TeacherDao extends BaseDAO<Integer, Teacher> {
 
     SimpleUserDto getSimpleUser(@Param("userId") Integer userId);
 
+    BasicUserInfo getBasicUserInfo(@Param("userId") Integer userId);
+
     /**
      * @param organId:   分部编号
      * @param subjectId: 声部编号列表

+ 23 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/AuditUserInfo.java

@@ -0,0 +1,23 @@
+package com.ym.mec.biz.dal.dto;
+
+import lombok.Data;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-05-16
+ */
+@Data
+public class AuditUserInfo {
+
+    private Long auditUserId;
+
+    private String auditUserPhone;
+
+    private String groupName;
+
+    private Long groupUserId;
+
+    private String groupUsername;
+}

+ 20 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ImGroupMemberDto.java

@@ -2,6 +2,7 @@ package com.ym.mec.biz.dal.dto;
 
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.ImGroupMember;
+import io.swagger.annotations.ApiModelProperty;
 
 public class ImGroupMemberDto extends ImGroupMember {
 
@@ -9,6 +10,11 @@ public class ImGroupMemberDto extends ImGroupMember {
 
     private String type;
 
+    private String imUserId;
+
+    @ApiModelProperty(value = "群编号;")
+    private String groupId;
+
     public String getType() {
         return type;
     }
@@ -24,4 +30,18 @@ public class ImGroupMemberDto extends ImGroupMember {
 	public void setUser(SysUser user) {
 		this.user = user;
 	}
+
+    public String getImUserId() {
+        return String.valueOf(getUserId());
+    }
+
+    public void setImUserId(String imUserId) {
+        this.imUserId = imUserId;
+    }
+
+    public String getGroupId() {
+        return getImGroupId();
+    }
+
+
 }

+ 24 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ImGroupNoticeDto.java

@@ -2,11 +2,22 @@ package com.ym.mec.biz.dal.dto;
 
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.ImGroupNotice;
+import io.swagger.annotations.ApiModelProperty;
 
 public class ImGroupNoticeDto extends ImGroupNotice {
 
 	private SysUser user = new SysUser();
 
+	// 拓展字段
+	@ApiModelProperty(value = "群编号;")
+	private String groupId;
+
+	@ApiModelProperty(value = "是否置顶")
+	private Boolean topFlag;
+
+	@ApiModelProperty(value = "是否发送给新人")
+	private Boolean sentToNewMemberFlag;
+
 	public SysUser getUser() {
 		return user;
 	}
@@ -14,4 +25,17 @@ public class ImGroupNoticeDto extends ImGroupNotice {
 	public void setUser(SysUser user) {
 		this.user = user;
 	}
+
+	public String getGroupId() {
+		return getImGroupId();
+	}
+
+	public Boolean getTopFlag() {
+		return isIsTop();
+	}
+
+	public Boolean getSentToNewMemberFlag() {
+		return isIsSentToNewMember();
+	}
+
 }

+ 36 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ImUserFriendDto.java

@@ -2,10 +2,24 @@ package com.ym.mec.biz.dal.dto;
 
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.ImUserFriend;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Objects;
+import java.util.Optional;
 
 public class ImUserFriendDto extends ImUserFriend {
 
 	private SysUser friend = new SysUser();
+	private String imUserId;
+
+	@ApiModelProperty(value = "好友身份")
+	private String friendType;
+
+	@ApiModelProperty(value = "IM用户ID")
+	private String imFriendId;
+
+	@ApiModelProperty(value = "好友头像")
+	private String friendAvatar;
 
 	public SysUser getFriend() {
 		return friend;
@@ -15,4 +29,26 @@ public class ImUserFriendDto extends ImUserFriend {
 		this.friend = friend;
 	}
 
+	public String getImUserId() {
+		return String.valueOf(getUserId());
+	}
+
+	public void setImUserId(String imUserId) {
+		this.imUserId = imUserId;
+	}
+
+	public String getFriendType() {
+		return getRoleType();
+	}
+
+	public String getImFriendId() {
+		return String.valueOf(getFriendId());
+	}
+
+	public String getFriendAvatar() {
+		if (Objects.nonNull(getFriend())) {
+			return getFriend().getAvatar();
+		}
+		return Optional.ofNullable(friendAvatar).orElse("");
+	}
 }

+ 30 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/im/BasicUserInfo.java

@@ -0,0 +1,30 @@
+package com.ym.mec.biz.dal.dto.im;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+* @description: 用户基本信息
+* @author zx
+* @date 2022/3/22 13:51
+*/
+@Data
+public class BasicUserInfo {
+    @ApiModelProperty(value = "用户编号", required = true)
+    private Long userId;
+
+    @ApiModelProperty(value = "sys_user表username_", required = true)
+    private String username;
+
+    @ApiModelProperty(value = "sys_user表real_name_", required = true)
+    private String realName;
+
+    @ApiModelProperty(value = "用户头像", required = true)
+    private String avatar;
+
+    @ApiModelProperty("IM用户ID")
+    private String imUserId;
+
+    @ApiModelProperty("用户类型")
+    private String userType;
+}

+ 14 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/im/BasicUserInfoDto.java

@@ -0,0 +1,14 @@
+package com.ym.mec.biz.dal.dto.im;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class BasicUserInfoDto {
+    @ApiModelProperty(value = "用户编号", required = true)
+    private String userId;
+
+    private String userName;
+
+    private String headUrl;
+}

+ 57 - 29
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImGroup.java

@@ -1,39 +1,56 @@
 package com.ym.mec.biz.dal.entity;
 
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.ym.mec.common.entity.BaseEntity;
 import com.ym.mec.common.enums.BaseEnum;
+import io.swagger.annotations.ApiModelProperty;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
+
 /**
  * 对应数据库表(im_group):
  */
 public class ImGroup extends BaseEntity {
 
 	/**  */
+    @TableId(value = "id_")
 	private String id;
 
+    @ApiModelProperty("学校ID")
+    @TableField(value = "school_id_")
     private Long schoolId;
 
 	/** 群名称 */
+    @TableField(value = "name_")
 	private String name;
-	
+
 	/** 群介绍 */
+    @TableField(value = "introduce_")
 	private String introduce;
-	
+
 	/** 群成员数 */
+    @TableField(value = "member_num_")
 	private Integer memberNum;
-	
+
 	/** 群备注 */
+    @TableField(value = "memo_")
 	private String memo;
-	
+
 	/** 群标签 */
+    @TableField(value = "tags_")
 	private String tags;
-	
+
+    @TableField(value = "img_")
 	private String img;
 
 	/** 乐团群 MUSIC,班级群 CLASS,训练营 TRAINING 学校SCHOOL*/
+    @TableField(value = "type_")
 	private String type;
 
+	private String importFlag;
+
 	public enum GroupTypeEnum implements BaseEnum<String,GroupTypeEnum> {
 		NORMAL("NORMAL", "普通班级"), MIX("MIX", "合奏班级"), HIGH("HIGH", "基础技能班"),
 		VIP("VIP", "vip课"), DEMO("DEMO", "试听课"), PRACTICE("PRACTICE", "网管课"),
@@ -69,6 +86,7 @@ public class ImGroup extends BaseEntity {
 	}
 
 	//群类型
+    @TableField(value = "group_type_")
 	private GroupTypeEnum groupType;
 
 	public GroupTypeEnum getGroupType() {
@@ -80,67 +98,69 @@ public class ImGroup extends BaseEntity {
 	}
 
 	/**  */
+    @TableField(value = "create_time_")
 	private java.util.Date createTime;
-	
+
 	/**  */
+    @TableField(value = "update_time_")
 	private java.util.Date updateTime;
 
-    public Long getSchoolId() {
-        return schoolId;
-    }
+	public Long getSchoolId() {
+		return schoolId;
+	}
 
-    public void setSchoolId(Long schoolId) {
-        this.schoolId = schoolId;
-    }
+	public void setSchoolId(Long schoolId) {
+		this.schoolId = schoolId;
+	}
 
-    public void setId(String id){
+	public void setId(String id){
 		this.id = id;
 	}
-	
+
 	public String getId(){
 		return this.id;
 	}
-			
+
 	public void setName(String name){
 		this.name = name;
 	}
-	
+
 	public String getName(){
 		return this.name;
 	}
-			
+
 	public void setIntroduce(String introduce){
 		this.introduce = introduce;
 	}
-	
+
 	public String getIntroduce(){
 		return this.introduce;
 	}
-			
+
 	public void setMemberNum(Integer memberNum){
 		this.memberNum = memberNum;
 	}
-	
+
 	public Integer getMemberNum(){
 		return this.memberNum;
 	}
-			
+
 	public void setMemo(String memo){
 		this.memo = memo;
 	}
-	
+
 	public String getMemo(){
 		return this.memo;
 	}
-			
+
 	public void setTags(String tags){
 		this.tags = tags;
 	}
-	
+
 	public String getTags(){
 		return this.tags;
 	}
-			
+
 	public String getImg() {
 		return img;
 	}
@@ -160,19 +180,27 @@ public class ImGroup extends BaseEntity {
 	public void setCreateTime(java.util.Date createTime){
 		this.createTime = createTime;
 	}
-	
+
 	public java.util.Date getCreateTime(){
 		return this.createTime;
 	}
-			
+
 	public void setUpdateTime(java.util.Date updateTime){
 		this.updateTime = updateTime;
 	}
-	
+
 	public java.util.Date getUpdateTime(){
 		return this.updateTime;
 	}
-			
+
+	public String getImportFlag() {
+		return importFlag;
+	}
+
+	public void setImportFlag(String importFlag) {
+		this.importFlag = importFlag;
+	}
+
 	@Override
 	public String toString() {
 		return ToStringBuilder.reflectionToString(this);

+ 30 - 114
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImGroupMember.java

@@ -1,5 +1,10 @@
 package com.ym.mec.biz.dal.entity;
 
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
 import com.ym.mec.common.entity.BaseEntity;
@@ -7,153 +12,64 @@ import com.ym.mec.common.entity.BaseEntity;
 /**
  * 对应数据库表(im_group_member):
  */
+@Data
 public class ImGroupMember extends BaseEntity {
 
 	/**  */
+    @TableId(value = "id_", type = IdType.AUTO)
 	private Long id;
 	
 	/**  */
+    @TableField(value = "im_group_id_")
 	private String imGroupId;
 	
 	/**  */
+    @TableField(value = "user_id_")
 	private Integer userId;
-	
+
+    @TableField(value = "nickname_")
 	private String nickname;
 
 	/** 群昵称 */
+    @TableField(exist = false)
 	private String groupNickname;
 	
 	/** 是否是管理员 */
-	private boolean isAdmin;
+    @ApiModelProperty("是否是管理员")
+    @TableField(value = "is_admin_")
+	private Boolean isAdmin;
 	
 	/** 群角色 */
+    @TableField(value = "role_type_")
 	private String roleType;
 
 
     /** 群角色 */
+    @TableField(value = "type_")
     private String type;
 
+    @TableField(exist = false)
 	private Integer memberRankSettingId;
 
+    @TableField(exist = false)
 	private String subjectName;
 
+    @TableField(exist = false)
 	private String subjectId;
-	
-	/**  */
+
+    /**
+     * 头像
+     */
+    @TableField(exist = false)
+    private String avatar;
+
+    /**  */
+    @TableField(value = "create_time_")
 	private java.util.Date createTime;
 	
 	/**  */
+    @TableField(value = "update_time_")
 	private java.util.Date updateTime;
 
 
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-	public String getSubjectId() {
-		return subjectId;
-	}
-
-	public void setSubjectId(String subjectId) {
-		this.subjectId = subjectId;
-	}
-
-	public Integer getMemberRankSettingId() {
-		return memberRankSettingId;
-	}
-
-	public void setMemberRankSettingId(Integer memberRankSettingId) {
-		this.memberRankSettingId = memberRankSettingId;
-	}
-
-	public String getSubjectName() {
-		return subjectName;
-	}
-
-	public void setSubjectName(String subjectName) {
-		this.subjectName = subjectName;
-	}
-
-	public void setId(Long id){
-		this.id = id;
-	}
-	
-	public Long getId(){
-		return this.id;
-	}
-			
-	public void setImGroupId(String imGroupId){
-		this.imGroupId = imGroupId;
-	}
-	
-	public String getImGroupId(){
-		return this.imGroupId;
-	}
-			
-	public void setUserId(Integer userId){
-		this.userId = userId;
-	}
-	
-	public Integer getUserId(){
-		return this.userId;
-	}
-			
-	public String getNickname() {
-		return nickname;
-	}
-
-	public void setNickname(String nickname) {
-		this.nickname = nickname;
-	}
-
-	public void setIsAdmin(boolean isAdmin){
-		this.isAdmin = isAdmin;
-	}
-	
-	public boolean getIsAdmin(){
-		return this.isAdmin;
-	}
-
-	public String getRoleType() {
-		return roleType;
-	}
-
-	public void setRoleType(String roleType) {
-		this.roleType = roleType;
-	}
-
-	public void setCreateTime(java.util.Date createTime){
-		this.createTime = createTime;
-	}
-	
-	public java.util.Date getCreateTime(){
-		return this.createTime;
-	}
-			
-	public void setUpdateTime(java.util.Date updateTime){
-		this.updateTime = updateTime;
-	}
-	
-	public java.util.Date getUpdateTime(){
-		return this.updateTime;
-	}
-
-	public String getGroupNickname() {
-		return groupNickname;
-	}
-
-	public void setGroupNickname(String groupNickname) {
-		this.groupNickname = groupNickname;
-	}
-
-	@Override
-	public String toString() {
-		return ToStringBuilder.reflectionToString(this);
-	}
-
 }

+ 94 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ImHistoryMessage.java

@@ -0,0 +1,94 @@
+package com.ym.mec.biz.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @Author:haonan
+ * @Date:2023/8/7 15:17
+ * @Filename:ImHistoryMessage
+ */
+@Data
+@ApiModel(" ImHistoryMessage-历史消息记录")
+@TableName("im_history_message")
+public class ImHistoryMessage implements Serializable {
+
+    @ApiModelProperty("可通过 msgUID 确定消息唯一")
+    @TableId(value = "msgUID_")
+    private String msgUID;
+
+    @ApiModelProperty("发送者 ID")
+    @TableField(value = "fromUserId_")
+    private String fromUserId;
+
+    @ApiModelProperty("接收者 ID,在消息路由中为 toUserId,当发送聊天室广播消息、全量用户落地通知时此字段为空")
+    @TableField(value = "targetId_")
+    private String targetId;
+
+    @ApiModelProperty("会话类型。1(单聊会话)、2(讨论组会话)、3(群组会话)、4(聊天室会话)、5(客服会话)、6(系统通知)、7(应用公众服务)、8(公众服务)、10(超级群会话)。targetType 在 SDK 中为 ConversationType。")
+    @TableField(value = "targetType_")
+    private Integer targetType;
+
+    @ApiModelProperty("根据不同的 targetType,可能是讨论组 Id、群组 ID、超级群 ID 或聊天室 ID ,如 targetType 为 1 时可忽略 GroupId")
+    @TableField(value = "GroupId_")
+    private String groupId;
+
+    @ApiModelProperty("	超级群频道 ID。")
+    @TableField(value = "busChannel_")
+    private String busChannel;
+
+    @ApiModelProperty("消息类型,例如文本消息 RC:TxtMsg、图片消息 RC:ImgMsg")
+    @TableField(value = "classname_")
+    private String classname;
+
+    @ApiModelProperty("消息内容")
+    @TableField(value = "content_")
+    private String content;
+
+    @ApiModelProperty("消息扩展")
+    @TableField(value = "extraContent_")
+    private String extraContent;
+
+    @ApiModelProperty("消息时间")
+    @TableField(value = "dateTime_")
+    private String dateTime;
+
+    @ApiModelProperty("消息来源,包括:iOS、Android、Websocket、MiniProgram(小程序)、PC、Server。")
+    @TableField(value = "source_")
+    private String source;
+
+    @ApiModelProperty("是否被丢弃,true 为是,false 为否,只针对聊天室会话类型存在。")
+    @TableField(value = "isDiscard_")
+    private String isDiscard;
+
+    @ApiModelProperty("是否含有屏蔽敏感词,true 为含有、false 为不含有。只针对聊天室会话类型存在。")
+    @TableField(value = "isSensitiveWord_")
+    private String isSensitiveWord;
+
+    @ApiModelProperty("是否为被禁言后发送的消息,只针对聊天室会话类型存在。")
+    @TableField(value = "isForbidden_")
+    private String isForbidden;
+
+    @ApiModelProperty("	消息是否不分发,true 为不分发、false 为分发。只针对聊天室会话类型存在。")
+    @TableField(value = "isNotForward_")
+    private String isNotForward;
+
+    @ApiModelProperty("targetType 为 3 时此参数有效,显示为群组中指定接收消息的用户 ID 数组,该条消息为群组定向消息。非定向消息时内容为空,如指定的用户不在群组中内容也为空。")
+    @TableField(value = "groupUserIds_")
+    private String groupUserIds;
+
+    @ApiModelProperty("App Key")
+    @TableField(value = "appId_")
+    private String appId;
+
+    @ApiModelProperty("导入状态,1 (已导入)  0(未导入)")
+    @TableField(value = "status_")
+    private Integer status;
+
+}

+ 22 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/EFriendRoleType.java

@@ -1,5 +1,6 @@
 package com.ym.mec.biz.dal.enums;
 
+import com.ym.mec.auth.api.enums.SysUserType;
 import com.ym.mec.common.enums.BaseEnum;
 
 
@@ -55,6 +56,27 @@ public enum EFriendRoleType implements BaseEnum<Integer, EFriendRoleType> {
         }
     }
 
+    //转为sysUserType
+    public SysUserType toSysUserType() {
+        switch (this) {
+            case STUDENT:
+                return SysUserType.STUDENT;
+            case SCHOOLMASTER:
+            case ORCHESTRA_LEADER:
+            case SCHOOL_LEADER:
+            case SCHOOL_TEACHER:
+                return SysUserType.SCHOOL;
+            case ORCHESTRA_MANAGER:
+            case MAINTENANCE_TECHNICIAN:
+                return SysUserType.EDUCATION;
+
+            case ORCHESTRA_TEACHER:
+                return SysUserType.STUDENT;
+        }
+
+        return SysUserType.STUDENT;
+    }
+
     public String getMsg() {
         return msg;
     }

+ 26 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/AuditStatusEnum.java

@@ -0,0 +1,26 @@
+package com.ym.mec.biz.dal.enums.im;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.ym.mec.common.enums.BaseEnum;
+
+public enum AuditStatusEnum implements BaseEnum<String,AuditStatusEnum> {
+    AUDITING("审核中"), REJECT("审核拒绝"), OPEN("审核通过");
+    @EnumValue
+    private String code;
+
+    private String msg;
+
+    AuditStatusEnum(String msg) {
+        this.code = this.name();
+        this.msg = msg;
+    }
+
+    @Override
+    public String getCode() {
+        return this.code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

+ 63 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ClientEnum.java

@@ -0,0 +1,63 @@
+package com.ym.mec.biz.dal.enums.im;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-04-28
+ */
+public enum ClientEnum{
+    TEACHER("老师端"),
+    STUDENT("学生端"),
+    SYSTEM("平台端"),
+    SCHOOL("教务端"),
+    WEBSITE("官网"),
+
+    ;
+    @EnumValue
+    private String code;
+    private String msg;
+
+    ClientEnum(String msg) {
+        this.code = this.name();
+        this.msg = msg;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    /**
+     * 校验客户端类型合法性
+     * @param clientType 客户端类型
+     * @return boolean
+     */
+    public static boolean invalid(String clientType) {
+
+        ClientEnum[] values = ClientEnum.values();
+
+        for (ClientEnum item : values) {
+
+            if (item.getCode().equals(clientType)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * 客户端类型匹配
+     * @param dataType 数据类型
+     * @return boolean
+     */
+    public boolean match(String dataType) {
+        return getCode().equals(dataType);
+    }
+}

+ 26 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImGroupMemberRoleType.java

@@ -0,0 +1,26 @@
+package com.ym.mec.biz.dal.enums.im;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.ym.mec.common.enums.BaseEnum;
+
+public enum ImGroupMemberRoleType implements BaseEnum<String, ImGroupMemberRoleType> {
+    TEACHER("老师"),
+    STUDENT("学生");
+    @EnumValue
+    private String code;
+    private String msg;
+
+    ImGroupMemberRoleType(String msg) {
+        this.code = this.name();
+        this.msg = msg;
+    }
+
+    public String getMsg() {
+        return this.msg;
+    }
+
+    @Override
+    public String getCode() {
+        return this.code;
+    }
+}

+ 22 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImNetworkActionEnum.java

@@ -0,0 +1,22 @@
+package com.ym.mec.biz.dal.enums.im;
+
+
+public enum ImNetworkActionEnum{
+    INVITE("邀请"),
+    REJECT("拒绝"),
+    APPROVE("同意");
+
+    private String msg;
+
+    ImNetworkActionEnum(String msg) {
+        this.msg = msg;
+    }
+
+    public String getCode() {
+        return this.name();
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

+ 29 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImNetworkDeviceTypeEnum.java

@@ -0,0 +1,29 @@
+package com.ym.mec.biz.dal.enums.im;
+
+
+import com.ym.mec.common.enums.BaseEnum;
+
+public enum ImNetworkDeviceTypeEnum implements BaseEnum<String,ImNetworkDeviceTypeEnum> {
+    MICROPHONE("麦克风"),
+    CAMERA("摄像头"),
+    MUSIC_MODE("音乐模式"),
+    HAND_UP("举手"),
+    EXAM_SONG("伴奏陪练"),
+    MUSIC_SHEET("原音"),
+    ACCOMPANIMENT("伴奏");
+
+    private String msg;
+
+    ImNetworkDeviceTypeEnum(String msg) {
+        this.msg = msg;
+    }
+
+    @Override
+    public String getCode() {
+        return this.name();
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

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

@@ -0,0 +1,31 @@
+package com.ym.mec.biz.dal.enums.im;
+
+// Display 定义格式如下:
+// display://type=1?userId=xxx?uri=xxxxx
+// 0,1,3 时,userId 有效,对应此人的 id,uri 无效
+// 2 时,展示白板,必须携带白板 uri
+// 4 时,清空当前 room 的 display
+
+import lombok.Getter;
+
+@Getter
+public enum ImNetworkDisplayEnum{
+    ASSISTANT("助教"),
+    TEACHER("老师"),
+    WHITE_BOARD("白板"),
+    SCREEN("屏幕"),
+    //清空当前 room 的 display
+    NONE("清空"),
+    STUDENT("学员");
+
+    private final String msg;
+
+    ImNetworkDisplayEnum(String msg) {
+        this.msg = msg;
+    }
+
+    public String getCode() {
+        return this.name();
+    }
+
+}

+ 71 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImNetworkRoomErrorEnum.java

@@ -0,0 +1,71 @@
+package com.ym.mec.biz.dal.enums.im;
+
+
+public enum ImNetworkRoomErrorEnum{
+    ERR_SUCCESS(200, "OK"),
+    ERR_REQUEST_PARA_ERR(1, "Missing or invalid parameter"),
+    ERR_INVALID_AUTH(2, "Invalid or expired authorization"),
+    ERR_ACCESS_DENIED(3, "Access denied"),
+    ERR_BAD_REQUEST(4, "Bad request"),
+
+    //IM error
+    ERR_IM_TOKEN_ERROR(10, "IM token error"),
+    ERR_CREATE_ROOM_ERROR(11, "Create room error"),
+    ERR_JOIN_ROOM_ERROR(12, "Join room error"),
+    JOIN_ROOM_ERROR(35, "加入房间失败,请前往线下教室"),
+    ROOM_NOT_START(36, "网络教室暂未开启,请稍后重试"),
+    CLOUD_BALANCE_NOT_FEE(37, "云教室受限不可进入,请联系教务老师。"),
+    ERR_MESSAGE_ERROR(13, "IM Message send error"),
+
+
+    //room error
+    ERR_ROOM_NOT_EXIST(20, "Room not exist"),
+    ERR_USER_NOT_EXIST_IN_ROOM(21, "User not exist in room"),
+    ERR_EXIT_ROOM_ERROR(22, "Exit room error"),
+    ERR_TEACHER_NOT_EXIST_IN_ROOM(23, "Teacher not exist in room"),
+    ERR_ASSISTANT_NOT_EXIST_IN_ROOM(24, "Assistant not exist in room"),
+    ERR_CREATE_WHITE_BOARD(25, "Create whiteboard error"),
+    ERR_WHITE_BOARD_NOT_EXIST(26, "Whiteboard not exist"),
+    ERR_DELETE_WHITE_BOARD(27, "Delete whiteboard error"),
+    ERR_USER_EXIST_IN_ROOM(28, "User exist in room"),
+    ERR_CHANGE_SELF_ROLE(29, "Can not change self role"),
+    ERR_APPLY_TICKET_INVALID(30, "Apply ticket invalid"),
+    ERR_OVER_MAX_COUNT(31, "云教室人数已超上线"),
+    ERR_TEACHER_EXIST_IN_ROOM(32, "Teacher exist in room"),
+    ERR_DOWNGRADE_ROLE(33, "Can't downgrade role"),
+    ERR_CHANGE_ROLE(34, "Only change student to teacher");
+
+    private int code;
+
+    private ImNetworkRoomErrorEnum(int code, String remark) {
+        this.code = code;
+        this.remark = remark;
+    }
+
+    private String remark;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public static ImNetworkRoomErrorEnum codeOf(int code) {
+        for (ImNetworkRoomErrorEnum errorEnum : ImNetworkRoomErrorEnum.values()) {
+            if (code == errorEnum.getCode()) {
+                return errorEnum;
+            }
+        }
+        return null;
+    }
+}

+ 39 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/ImNetworkRoomMemberChangedEnum.java

@@ -0,0 +1,39 @@
+package com.ym.mec.biz.dal.enums.im;
+
+
+
+/**
+* @description: 用户动作枚举
+* @author zx
+* @date 2022/4/6 13:59
+*/
+public enum ImNetworkRoomMemberChangedEnum{
+
+    JOIN(0,"加入"),
+    LEAVE(1,"离开"),
+    KICK(2,"踢出");
+
+    private Integer code;
+    private String msg;
+
+    ImNetworkRoomMemberChangedEnum(Integer code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public Integer getCode() {
+        return this.code;
+    }
+}

+ 34 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/im/RoleEnum.java

@@ -0,0 +1,34 @@
+package com.ym.mec.biz.dal.enums.im;
+
+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;
+            }
+        }
+        return RoleEnum.RoleStudent;
+    }
+}

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/mapper/ImGroupMemberPlusMapper.java

@@ -1,8 +1,8 @@
 package com.ym.mec.biz.dal.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ym.mec.biz.dal.entity.ImGroupMember;
 import org.springframework.stereotype.Repository;
+import com.ym.mec.biz.dal.entity.ImGroupMember;
 
 import java.util.List;
 

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/mapper/ImGroupPlusMapper.java

@@ -1,8 +1,8 @@
 package com.ym.mec.biz.dal.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ym.mec.biz.dal.entity.ImGroup;
 import org.springframework.stereotype.Repository;
+import com.ym.mec.biz.dal.entity.ImGroup;
 
 /**
  * 即时通讯群组

+ 22 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/ImGroupMemberAuditQueryInfo.java

@@ -0,0 +1,22 @@
+package com.ym.mec.biz.dal.page;
+
+import com.ym.mec.biz.dal.enums.im.AuditStatusEnum;
+import com.ym.mec.common.page.QueryInfo;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class ImGroupMemberAuditQueryInfo extends QueryInfo {
+
+    @ApiModelProperty(value = "审核状态")
+    private String auditStatus = AuditStatusEnum.AUDITING.getCode();
+
+    @ApiModelProperty(value = "用户编号")
+    private Long userId;
+
+    @NotBlank(message = "群编号不可为空")
+    @ApiModelProperty(value = "群编号")
+    private String groupId;
+}

+ 30 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/vo/ImGroupVo.java

@@ -0,0 +1,30 @@
+package com.ym.mec.biz.dal.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * IM群组请求
+ * Created by Eric.Shang on 2023/5/24.
+ */
+@ApiModel(value = "ImGroupVo对象", description = "IM群组对象")
+public class ImGroupVo implements Serializable {
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("GroupChangeOwner-群主转移")
+    public static class GroupChangeOwner implements Serializable {
+
+        @ApiModelProperty("群组编号")
+        private String imGroupId;
+
+        @ApiModelProperty("用户编号")
+        private Integer userId;
+    }
+}

+ 79 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/vo/SchoolStaffVo.java

@@ -0,0 +1,79 @@
+package com.ym.mec.biz.dal.vo;
+
+import com.alibaba.fastjson.JSON;
+import com.microsvc.toolkit.common.response.paging.QueryInfo;
+import com.ym.mec.biz.dal.enums.school.ESchoolStaffType;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+/**
+ * 学校员工
+ * 2023-05-06 11:08:00
+ */
+@ApiModel(value = "SchoolStaffVo对象", description = "学校员工查询视图对象")
+public class SchoolStaffVo {
+
+    @Data
+    @ApiModel(" SchoolStaffQuery-学校员工")
+    public static class SchoolStaffQuery implements QueryInfo {
+    
+        @ApiModelProperty("当前页")
+        private Integer page;
+        
+        @ApiModelProperty("分页行数")
+        private Integer rows;
+        
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static SchoolStaffQuery from(String json) {
+            return JSON.parseObject(json, SchoolStaffQuery.class);
+        }
+    }
+    
+    @Data
+    @ApiModel(" SchoolStaff-学校员工")
+    public static class SchoolStaff {
+    	
+		@ApiModelProperty("主键")
+        private Long id;
+                
+        @NotNull(message = "合作单位编号不能为空")
+		@ApiModelProperty("合作单位编号")
+        private Long schoolId;
+                
+		@ApiModelProperty("用户身份(校长,乐团领队,分管领导,负责老师)")
+        private ESchoolStaffType userType;
+                
+        @NotBlank(message = "用户名称不能为空")
+        @Length(min = 1, max = 8, message = "用户名称长度必须在1-8个字符之间")
+        @ApiModelProperty("用户名称")
+        private String username;
+
+        @NotBlank(message = "手机号码不能为空")
+        @Pattern(regexp = "1[3456789][0-9]{9}", message = "手机号码格式不正确")
+        @ApiModelProperty("手机号码")
+        private String mobile;
+
+        @NotBlank(message = "验证码不能为空")
+        @ApiModelProperty("验证码")
+        private String smsCode;
+                
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static SchoolStaff from(String json) {
+            return JSON.parseObject(json, SchoolStaff.class);
+        }
+
+    }
+    
+}

+ 4 - 3
mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/ImGroupMemberWrapper.java

@@ -4,15 +4,16 @@ import com.alibaba.fastjson.JSON;
 import com.microsvc.toolkit.common.response.paging.QueryInfo;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Date;
+import java.util.Optional;
+
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
 
-import java.util.Date;
-import java.util.Optional;
-
 /**
  * 群成员表
  * 2023-08-29 17:18:04

+ 2 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/ImGroupWrapper.java

@@ -1,12 +1,14 @@
 package com.ym.mec.biz.dal.wrapper;
 
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.annotation.TableField;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.slf4j.helpers.MessageFormatter;
 
 import java.io.Serializable;
 import java.util.Date;

+ 209 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/ImHistoryMessageWrapper.java

@@ -0,0 +1,209 @@
+package com.ym.mec.biz.dal.wrapper;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+public class ImHistoryMessageWrapper {
+
+
+    @Data
+    @ApiModel("ImHistoryMessage-iM语音消息")
+    public static class TimSoundElem {
+
+        @JSONField(name = "Url")
+        @ApiModelProperty("语音下载地址,可通过该 URL 地址直接下载相应语音。")
+        private String Url;
+
+        @JSONField(name = "UUID")
+        @ApiModelProperty("语音的唯一标识,客户端用于索引语音的键值")
+        private String UUID;
+
+        @JSONField(name = "Size")
+        @ApiModelProperty("语音数据大小,单位:字节。")
+        private Integer Size;
+
+        @JSONField(name = "Second")
+        @ApiModelProperty("语音时长,单位:秒。")
+        private Integer Second;
+
+        @JSONField(name = "Download_Flag")
+        @ApiModelProperty("语音下载方式标记。目前 Download_Flag 取值只能为2,表示可通过Url字段值的 URL 地址直接下载语音。")
+        private Integer Download_Flag;
+
+    }
+
+    @Data
+    @ApiModel("ImHistoryMessage-iM文件")
+    public static class TimFileElem {
+
+        @JSONField(name = "Url")
+        @ApiModelProperty("文件下载地址,可通过该 URL 地址直接下载相应文件。")
+        private String Url;
+
+        @JSONField(name = "UUID")
+        @ApiModelProperty("文件的唯一标识,客户端用于索引文件的键值。")
+        private String UUID;
+
+        @JSONField(name = "FileSize")
+        @ApiModelProperty("文件数据大小,单位:字节。")
+        private Integer FileSize;
+
+        @JSONField(name = "FileName")
+        @ApiModelProperty("文件名称。")
+        private String FileName;
+
+        @JSONField(name = "Download_Flag")
+        @ApiModelProperty("文件下载方式标记。目前 Download_Flag 取值只能为2,表示可通过Url字段值的 URL 地址直接下载文件。")
+        private Integer  Download_Flag;
+
+    }
+
+    @Data
+    @ApiModel("ImHistoryMessage-iM视频")
+    public static class TimVideoFileElem {
+        @JSONField(name = "VideoUrl")
+        @ApiModelProperty("视频下载地址。可通过该 URL 地址直接下载相应视频。")
+        private String VideoUrl;
+
+        @JSONField(name = "VideoUUID")
+        @ApiModelProperty("文视频的唯一标识,客户端用于索引视频的键值。")
+        private String VideoUUID;
+
+        @JSONField(name = "VideoSize")
+        @ApiModelProperty("视频数据大小,单位:字节。")
+        private Integer VideoSize;
+
+        @JSONField(name = "VideoSecond")
+        @ApiModelProperty("视频时长,单位:秒。Web 端不支持获取视频时长,值为0")
+        private Integer VideoSecond;
+
+        @JSONField(name = "VideoFormat")
+        @ApiModelProperty("视频格式,例如 mp4")
+        private String VideoFormat;
+
+        @JSONField(name = "VideoDownloadFlag")
+        @ApiModelProperty("视频下载方式标记。目前 VideoDownloadFlag 取值只能为2,表示可通过 VideoUrl 字段值的 URL 地址直接下载视频。")
+        private Integer  VideoDownloadFlag;
+
+        @JSONField(name = "ThumbUrl")
+        @ApiModelProperty("视频缩略图下载地址。可通过该 URL 地址直接下载相应视频缩略图。")
+        private String ThumbUrl;
+
+        @JSONField(name = "ThumbUUID")
+        @ApiModelProperty("视频缩略图的唯一标识,客户端用于索引视频缩略图的键值")
+        private String ThumbUUID;
+
+        @JSONField(name = "ThumbSize")
+        @ApiModelProperty("缩略图大小,单位:字节。")
+        private Integer ThumbSize;
+
+        @JSONField(name = "ThumbWidth")
+        @ApiModelProperty("缩略图宽度,单位为像素。")
+        private Integer ThumbWidth;
+
+        @JSONField(name = "ThumbHeight")
+        @ApiModelProperty("缩略图高度,单位为像素。")
+        private Integer ThumbHeight;
+
+        @JSONField(name = "ThumbFormat")
+        @ApiModelProperty("缩略图格式,例如 JPG、BMP 等。")
+        private String ThumbFormat;
+
+        @JSONField(name = "ThumbDownloadFlag")
+        @ApiModelProperty("视频缩略图下载方式标记。目前 ThumbDownloadFlag 取值只能为2,表示可通过 ThumbUrl 字段值的 URL 地址直接下载视频缩略图。")
+        private Integer ThumbDownloadFlag;
+    }
+
+
+    @Data
+    @ApiModel("ImHistoryMessage-iM位置")
+    public static class TimLocationElem {
+
+        @JSONField(name = "Desc")
+        @ApiModelProperty("地理位置描述信息。")
+        private String Desc;
+
+        @JSONField(name = "Latitude")
+        @ApiModelProperty("纬度。")
+        private double Latitude;
+
+        @JSONField(name = "Longitude")
+        @ApiModelProperty("经度。")
+        private double Longitude;
+    }
+
+    @Data
+    @ApiModel("ImHistoryMessage-iM合并转发")
+    public static class TimRelayElem {
+
+        @ApiModelProperty("合并转发消息的标题。")
+        private String Title;
+
+        @ApiModelProperty("被转发的消息条数。")
+        private Integer MsgNum;
+
+        @ApiModelProperty("兼容文本。当不支持合并转发消息的老版本 SDK 收到此类消息时,IM 后台会将该消息转化成兼容文本再下发。")
+        private String CompatibleText;
+
+        @ApiModelProperty("合并消息的摘要列表,是一个 String 数组")
+        private String[] AbstractList;
+
+        @ApiModelProperty("消息列表。当被转发的消息长度之和小于等于12K时才会有此字段,此时不会有 JsonMsgKey 字段。")
+        private List<TimRelayElemList> MsgList;
+
+        @ApiModelProperty("合并转发的消息列表 Key。当被转发的消息长度之和大于12K时才会有此字段,此时不会有 MsgList 字段。")
+        private String JsonMsgKey;
+
+
+    }
+
+
+    @Data
+    @ApiModel("ImHistoryMessage-iM合并转发消息列表")
+    public static class TimRelayElemList {
+
+        @ApiModelProperty("消息发送方 UserID。被转发的消息为单聊或群聊时都有此字段。")
+        private String From_Account;
+
+        @ApiModelProperty("消息接收方 UserID。被转发的消息为单聊才有此字段。")
+        private String To_Account;
+
+        @ApiModelProperty("群 ID。被转发的消息为群聊才有此字段。")
+        private String GroupId;
+
+        @ApiModelProperty("消息序列号(32位无符号整数)。")
+        private Integer MsgSeq;
+
+        @ApiModelProperty("消息随机数(32位无符号整数)。")
+        private Integer MsgRandom;
+
+        @ApiModelProperty("消息的秒级时间戳。")
+        private Integer MsgTimeStamp;
+
+        @ApiModelProperty("消息内容")
+        private List<TimRelayElemMessage> MsgBody;
+
+        @ApiModelProperty("消息自定义数据(云端保存,会发送到对端,程序卸载重装后还能拉取到)。")
+        private String CloudCustomData;
+
+    }
+
+    @Data
+    @ApiModel("ImHistoryMessage-iM合并转发消息内容体")
+    public static class TimRelayElemMessage {
+
+        @ApiModelProperty("消息类型")
+        private String msgType;
+
+        @ApiModelProperty("消息内容")
+        private Object msgContent;
+
+    }
+
+
+
+}

+ 3 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/wrapper/SchoolStaffWrapper.java

@@ -267,6 +267,9 @@ public class SchoolStaffWrapper {
         @ApiModelProperty("合作单位Logo")
         private String logo;
 
+        @ApiModelProperty("IM用户ID")
+        private String imUserId;
+
         public static StaffSysUser from(String json) {
             return JSON.parseObject(json, StaffSysUser.class);
         }

+ 2 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/ImGroupMemberPlusService.java

@@ -1,6 +1,8 @@
 package com.ym.mec.biz.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper;
 import com.ym.mec.biz.dal.entity.ImGroupMember;
 
 import java.util.List;

+ 111 - 72
mec-biz/src/main/java/com/ym/mec/biz/service/ImGroupService.java

@@ -1,102 +1,105 @@
 package com.ym.mec.biz.service;
 
 import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
-import com.ym.mec.auth.api.entity.SysUser;
+import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginService;
+import com.ym.mec.biz.dal.dto.im.BasicUserInfo;
 import com.ym.mec.biz.dal.dto.ImGroupDto;
 import com.ym.mec.biz.dal.dto.ImGroupMemberDto;
 import com.ym.mec.biz.dal.dto.NameDto;
 import com.ym.mec.biz.dal.entity.ImGroup;
+import com.ym.mec.biz.dal.entity.ImHistoryMessage;
 import com.ym.mec.biz.dal.enums.school.ESchoolStaffType;
 import com.ym.mec.biz.dal.wrapper.ImGroupWrapper;
 import com.ym.mec.common.service.BaseService;
+import com.yonge.log.dal.model.HistoryMessage;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 
 public interface ImGroupService extends BaseService<String, ImGroup> {
 
-	/**
-	 * 创建群组
-	 * @param id 群编号
-	 * @param userId 创建人编号
-	 * @param name 群名称
-	 * @param introduce 群介绍
-	 * @param memo 群备注
-	 * @param tags 群标签
-	 * @param img 群图像
-	 * @param type 群类型
-	 * @return
-	 */
-	ImGroup create(String id, Integer userId, String name, String introduce, String memo, String tags, String img, String type, ImGroup.GroupTypeEnum groupType);
+    /**
+     * 创建群组
+     * @param id 群编号
+     * @param userId 创建人编号
+     * @param name 群名称
+     * @param introduce 群介绍
+     * @param memo 群备注
+     * @param tags 群标签
+     * @param img 群图像
+     * @param type 群类型
+     * @return
+     */
+    ImGroup create(String id, Integer userId, String name, String introduce, String memo, String tags, String img, String type, ImGroup.GroupTypeEnum groupType);
 
-	/**
-	* @description: 创建非课程类型的业务群组
-	* @return java.lang.String
-	* @author zx
-	* @date 2022/6/7 15:20
-	*/
-	String createGroup(ImGroupDto imGroupDto);
+    /**
+     * @description: 创建非课程类型的业务群组
+     * @return java.lang.String
+     * @author zx
+     * @date 2022/6/7 15:20
+     */
+    String createGroup(ImGroupDto imGroupDto);
 
-	/**
-	 * 解散群组
-	 * @param imGroupId
-	 * @return
-	 */
-	boolean cancel(String imGroupId);
+    /**
+     * 解散群组
+     * @param imGroupId
+     * @return
+     */
+    boolean cancel(String imGroupId);
 
-	/**
-	 * 查询用户所在的群列表
-	 * @param userId
-	 * @param search
-	 * @return
-	 */
-	List<ImGroup> queryByUserId(Integer userId, String search,String groupType);
+    /**
+     * 查询用户所在的群列表
+     * @param userId
+     * @param search
+     * @return
+     */
+    List<ImGroup> queryByUserId(Integer userId, String search,String groupType);
 
-	/**
-	 * 查询群成员列表
-	 * @param imGroupId
-	 * @return
-	 */
-	List<ImGroupMemberDto> queryMemberById(String imGroupId);
-	List<ImGroupMemberDto> queryMemberById(String imGroupId,String search);
+    /**
+     * 查询群成员列表
+     * @param imGroupId
+     * @return
+     */
+    List<ImGroupMemberDto> queryMemberById(String imGroupId);
+    List<ImGroupMemberDto> queryMemberById(String imGroupId,String search);
 
-	/**
-	 * 查询指定用户在群众的信息
-	 * @param imGroupId 群编号
-	 * @param userId 指定的用户编号
-	 * @return
-	 */
-	ImGroupMemberDto queryMember(String imGroupId, Integer userId);
+    /**
+     * 查询指定用户在群众的信息
+     * @param imGroupId 群编号
+     * @param userId 指定的用户编号
+     * @return
+     */
+    ImGroupMemberDto queryMember(String imGroupId, Integer userId);
 
-	/**
-	 * 修改用户在群、通讯录的备注
-	 * @param userId
-	 * @param nickName
-	 * @return
-	 */
+    /**
+     * 修改用户在群、通讯录的备注
+     * @param userId
+     * @param nickName
+     * @return
+     */
     int updateNickName(Integer userId, String nickName);
 
-	/**
-	 * 修改用户在群、通讯录的备注
-	 * @param userId
-	 * @param nickName
-	 * @return
-	 */
-	void updateNickName1(Integer userId, String nickName);
+    /**
+     * 修改用户在群、通讯录的备注
+     * @param userId
+     * @param nickName
+     * @return
+     */
+    void updateNickName1(Integer userId, String nickName);
 
-	void updateImGroup(ImGroup imGroup);
+    void updateImGroup(ImGroup imGroup);
 
-	//解散群组
-	void dismissGroup(String imGroupId);
+    //解散群组
+    void dismissGroup(String imGroupId);
 
-	/**
-	* @description: 获取群聊、用户详情
-	 * @param nameDto
-	* @return java.lang.Object
-	* @author zx
-	* @date 2022/8/8 10:10
-	*/
-	List<NameDto> queryDetail(List<NameDto> nameDto);
+    /**
+     * @description: 获取群聊、用户详情
+     * @param nameDto
+     * @return java.lang.Object
+     * @author zx
+     * @date 2022/8/8 10:10
+     */
+    List<NameDto> queryDetail(List<NameDto> nameDto);
 
     List<ImGroup> queryByUserIdV2(Integer userId, String search, String groupType, String musicGroupId, String classType);
 
@@ -157,6 +160,14 @@ public interface ImGroupService extends BaseService<String, ImGroup> {
      */
     void quitGroup(List<String> imGroupIds, Integer userId);
 
+
+    /**
+     * IM 用户注册
+     * @param userId 用户Id
+     * @return String
+     */
+    String getImUserId(String userId,String clientType);
+
     /**
      * 学校人员加入群组
      *
@@ -164,4 +175,32 @@ public interface ImGroupService extends BaseService<String, ImGroup> {
      * @param imGroupId 群组id
      */
     void schoolJoinGroup(Integer cooperationOrganId, String imGroupId);
+
+	/**
+	 * 群迁移
+	 */
+	void groupTransfer(String startTime,String endTime);
+
+	/**
+	 * 导入用户
+	 */
+	void importUser();
+
+	/**
+	 * 查询总数
+	 * @return
+	 */
+	int queryInfoCount();
+
+	/**
+	 * 读取融云数据库信息
+	 */
+	com.yonge.mongodb.PageInfo getRongYunInfo(int page, int size);
+
+	/**
+	 * 导入IM腾讯云
+	 * @param info
+	 * @throws Exception
+	 */
+	void importInfo(List<HistoryMessage> info) throws Exception;
 }

+ 152 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/im/ImGroupCoreService.java

@@ -0,0 +1,152 @@
+package com.ym.mec.biz.service.im;
+
+import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
+import com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper;
+import com.ym.mec.biz.dal.wrapper.ImGroupWrapper;
+
+import java.util.List;
+
+/**
+ * IM群组服务
+ * Created by Eric.Shang on 2022/11/26.
+ */
+public interface ImGroupCoreService {
+
+    /**
+     * IM 用户注册
+     * @param userId 用户ID
+     * @param username 用户名
+     * @param avatar 用户头象
+     * @return IM聊天Token
+     */
+    ImGroupWrapper.ImUserInfo register(String userId, String clientType, String username, String avatar) throws Exception;
+
+    /**
+     * IM 用户签名
+     * @param userId 用户ID
+     * @param clientType 用户身份
+     * @return ImGroupWrapper.ImUserInfo
+     */
+    ImGroupWrapper.ImUserInfo getUserSig(String userId, String clientType);
+
+    /**
+     * IM 用户注册
+     * @param userId 用户Id
+     * @return String
+     */
+    String getImUserId(String userId, String clientType);
+
+    /**
+     * 解析IM用户规则
+     * @param imUserId IM用户Id
+     * @return String
+     */
+    String analysisImUserId(String imUserId);
+
+    /**
+     * 添加群组信息
+     *
+     * @param groupMember 用户信息
+     * @param imGroup     ImGroupWrapper.ImGroup
+     * @return Boolean
+     * @throws Exception Exception
+     */
+    String groupCreate(ImGroupMemberWrapper.ImGroupMember groupMember, ImGroupWrapper.ImGroup imGroup) throws Exception;
+
+    /**
+     * 群组解散
+     * @param groupId 群组ID
+     * @throws Exception Exception
+     */
+    void groupDismiss( String groupId) throws Exception;
+
+    /**
+     * 用户主动退出群聊
+     * @param groupMember 用户信息
+     * @param groupId 群组ID
+     * @throws Exception Exception
+     */
+    void groupQuit(GroupMemberWrapper.ImGroupMember groupMember, String groupId) throws Exception;
+
+
+    /**
+     * 批量退群
+     *
+     */
+    void groupQuit(List<GroupMemberWrapper.ImGroupMember> imGroupMembers, String groupId) throws Exception;
+
+    /**
+     * 用户主动退出群聊
+     * @param userId 用户信息
+     * @param clientType EClientType
+     * @param imGroupId 群组ID
+     * @throws Exception Exception
+     */
+    void groupQuit(Long userId, String clientType, String imGroupId) throws Exception;
+
+    /**
+     * 添加群组成员
+     * @param groupId 群组ID
+     * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
+     * @throws Exception Exception
+     */
+    void saveImGroupMemberList(String groupId, List<ImGroupMemberWrapper.ImGroupMember> groupMembers) throws Exception;
+
+    /**
+     * 添加群组成员
+     * @param imGroupId 群组主键ID
+     * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
+     * @throws Exception Exception
+     */
+    void saveImGroupMemberList(Long imGroupId, List<ImGroupMemberWrapper.ImGroupMember> groupMembers) throws Exception;
+
+    /**
+     * 群成员加入
+     * @param imGroupId 群主ID
+     * @param groupMembers 群成员
+     * @throws Exception Exception
+     */
+    void groupMemberJoin(String imGroupId, List<ImGroupMemberWrapper.ImGroupMember> groupMembers) throws Exception;
+
+    /**
+     * 添加进入群组
+     *
+     * @param userId 用户ID
+     * @param clientType 客户端类型
+     * @param imGroupId 群组ID
+     */
+    void groupJoin(Long userId, String clientType, String imGroupId) throws Exception;
+
+    /**
+     * 转让群主
+     *
+     * @param groupId 群组ID
+     * @param newOwner 新群主
+     * @param oldOwner 旧群主
+     */
+    void changeGroupOwner(String groupId, String newOwner, String oldOwner) throws Exception;
+
+    /**
+     * 更新群信息
+     * @param groupId 群ID
+     * @param groupName 群名称
+     * @param faceUrl 群头像
+     * @throws Exception Exception
+     */
+    void modifyGroupInfo(String groupId, String groupName, String faceUrl) throws Exception;
+
+    /**
+     * 群成员加入三方IM状态
+     * @param groupMemberIds 群成员ID
+     * @param groupJoin 加群状态
+     */
+    void updateGroupMemberJoinStatus(List<Long> groupMemberIds, Boolean groupJoin);
+
+    /**
+     * 检查IM用户ID是否符合规则
+     *
+     * @param imUserId IM用户ID
+     * @return
+     */
+    boolean checkImUserId(String imUserId);
+}

+ 596 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/im/impl/ImGroupCoreServiceImpl.java

@@ -0,0 +1,596 @@
+package com.ym.mec.biz.service.im.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.google.common.collect.Lists;
+import com.microsvc.toolkit.common.tools.ThreadPool;
+import com.microsvc.toolkit.middleware.im.ImPluginContext;
+import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
+import com.microsvc.toolkit.middleware.im.properties.ImConfigProperties;
+import com.ym.mec.biz.dal.entity.ImGroup;
+import com.ym.mec.biz.dal.entity.ImGroupMember;
+import com.ym.mec.biz.dal.enums.EFriendRoleType;
+import com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper;
+import com.ym.mec.biz.dal.wrapper.ImGroupWrapper;
+import com.ym.mec.biz.service.ImGroupMemberPlusService;
+import com.ym.mec.biz.service.ImGroupPlusService;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
+import com.ym.mec.common.exception.BizException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * IM群组务
+ * Created by Eric.Shang on 2022/11/26.
+ */
+@Slf4j
+@Service
+public class ImGroupCoreServiceImpl implements ImGroupCoreService {
+
+    @Autowired
+    private ImPluginContext imPluginContext;
+    @Autowired
+    private ImGroupPlusService imGroupService;
+    @Autowired
+    private ImConfigProperties imConfig;
+    @Autowired
+    private ImGroupMemberPlusService imGroupMemberService;
+
+    /**
+     * IM 用户注册
+     *
+     * @param userId   用户ID
+     * @param username 用户名
+     * @param avatar   用户头象
+     * @return IM聊天Token
+     */
+    @Override
+    public ImGroupWrapper.ImUserInfo register(String userId, String clientType, String username, String avatar) throws Exception {
+
+        ImGroupWrapper.ImUserInfo userInfo = ImGroupWrapper.ImUserInfo.builder()
+            .imUserId(getImUserId(userId, clientType))
+            .imToken("")
+            .build();
+
+        // 聊天Token
+        String imUserId = userInfo.getImUserId();
+        // 生成IM聊天Token
+        try {
+            // 生成签名
+            userInfo.imUserId(imUserId)
+                    .setImToken(imPluginContext.getPluginService().register(imUserId, username, avatar));
+
+        } catch (Exception e) {
+            log.error("register ImToken EX, userId={}, username={}", userId, username, e);
+            // 重新计算用户签名
+            userInfo.setImToken(imPluginContext.getPluginService().getUserSig(imUserId));
+        }
+        return userInfo;
+    }
+
+    /**
+     * IM 用户签名
+     *
+     * @param userId     用户ID
+     * @param clientType 用户身份
+     * @return ImGroupWrapper.ImUserInfo
+     */
+    @Override
+    public ImGroupWrapper.ImUserInfo getUserSig(String userId, String clientType) {
+
+        ImGroupWrapper.ImUserInfo userInfo = ImGroupWrapper.ImUserInfo.builder()
+            .imUserId(getImUserId(userId, clientType))
+            .imToken("")
+            .build();
+
+        // 计算用户IM签名
+        userInfo.setImToken(imPluginContext.getPluginService().getUserSig(userInfo.getImUserId()));
+
+        return userInfo;
+    }
+
+    /**
+     * IM 用户注册
+     *
+     * @param userId 用户Id
+     * @return String
+     */
+    @Override
+    public String getImUserId(String userId, String clientType) {
+        /*if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !userId.startsWith(imConfig.getAppPrefix())) {
+            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId, clientType);
+        }*/
+        return userId;
+    }
+
+    /**
+     * 解析IM用户规则
+     *
+     * @param imUserId IM用户Id
+     * @return String
+     */
+    @Override
+    public String analysisImUserId(String imUserId) {
+        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && imUserId.startsWith(imConfig.getAppPrefix())) {
+            return imUserId.replace(imConfig.getAppPrefix() + "_", "").split("_")[0];
+        }
+        return imUserId;
+    }
+
+    /**
+     * 添加群组信息
+     *
+     * @param userInfo 用户信息
+     * @param imGroup  ImGroupWrapper.ImGroup
+     * @return Boolean
+     */
+    @Override
+    @Transactional
+    public String groupCreate(ImGroupMemberWrapper.ImGroupMember userInfo, ImGroupWrapper.ImGroup imGroup) throws Exception {
+
+        long id = Optional.ofNullable(imGroup.getId()).orElse(IdWorker.getId());
+        // 生成群组ID
+        imGroup.id(id)
+                .type(Optional.ofNullable(imGroup.getType()).orElse("CLASS"))
+                .groupId(String.valueOf(id));
+
+        ImGroup group = JSON.parseObject(imGroup.jsonString(), ImGroup.class);
+        group.setId(imGroup.getGroupId());
+        // 保存群组信息
+        imGroupService.saveOrUpdate(group);
+
+        List<ImGroupMemberWrapper.ImGroupMember> groupMembers = null;
+        String imUserId = null;
+        if (userInfo != null) {
+            imUserId = getImUserId(userInfo.getUserId().toString(), userInfo.getClientType());
+            groupMembers = Lists.newArrayList(userInfo);
+
+            groupMembers.add(userInfo.imUserId(imUserId));
+            imGroupMemberService.insertBatch(getImGroupMemberEntity(groupMembers));
+
+            // 自动激活学生IM帐号
+            registerUser(groupMembers);
+        }
+
+        // 创建IM群组
+        imPluginContext.getPluginService().groupCreate(imGroup.getGroupId(), imGroup.getName(),imUserId);
+
+        if (userInfo != null) {
+            // 添加群成员到当前群组
+            imPluginContext.getPluginService().groupJoin(imGroup.getGroupId(), imGroup.getName(),
+                    getImGroupMembers(groupMembers));
+        }
+        return group.getId();
+    }
+
+    private List<ImGroupMember> getImGroupMemberEntity(List<ImGroupMemberWrapper.ImGroupMember> groupMembers) {
+        if (CollectionUtils.isEmpty(groupMembers)) {
+            return new ArrayList<>();
+        }
+        return groupMembers.stream().map(o -> {
+            ImGroupMember imGroupMember = new ImGroupMember();
+            imGroupMember.setImGroupId(o.getGroupId());
+            imGroupMember.setUserId(o.getUserId().intValue());
+            imGroupMember.setNickname(o.getNickname());
+            imGroupMember.setIsAdmin(o.getIsAdmin());
+            imGroupMember.setRoleType(o.getRoleType());
+            imGroupMember.setType(EFriendRoleType.getByName(o.getRoleType()).name());
+            imGroupMember.setTenantId(o.getTenantId());
+
+            return imGroupMember;
+        }).collect(Collectors.toList());
+
+    }
+
+    /**
+     * 获取群组成员信息
+     *
+     * @param groupMembers 群组成员信息
+     * @return List<GroupMemberWrapper.ImGroupMember>
+     */
+    private List<GroupMemberWrapper.ImGroupMember> getImGroupMembers(List<ImGroupMemberWrapper.ImGroupMember> groupMembers) {
+        // 统一转换为群组成员信息
+        for (ImGroupMemberWrapper.ImGroupMember member : groupMembers) {
+            member.setImUserId(getImUserId(member.getUserId().toString(), member.getClientType()));
+        }
+        return JSON.parseArray(JSON.toJSONString(groupMembers), GroupMemberWrapper.ImGroupMember.class);
+    }
+
+    /**
+     * 自动注册用户
+     * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
+     */
+    private void asyncRegisterUser(List<ImGroupMemberWrapper.ImGroupMember> groupMembers) {
+        ThreadPool.getExecutor().submit(() -> registerUser(groupMembers));
+    }
+
+    /**
+     * 批量导入用户
+     * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
+     */
+    private void registerUser(List<ImGroupMemberWrapper.ImGroupMember> groupMembers) {
+        for (ImGroupMemberWrapper.ImGroupMember member : groupMembers) {
+            // 激活用户帐号为空
+            if (StringUtils.isBlank(member.getNickname())) {
+                continue;
+            }
+
+            try {
+                String imUserId = member.getUserId().toString();
+                if (StringUtils.isBlank(imUserId)) {
+                    imUserId = getImUserId(String.valueOf(member.getUserId()),
+                            member.getClientType());
+                }
+
+                imPluginContext.getPluginService().register(imUserId, member.getNickname(), member.getAvatar());
+            } catch (Exception e) {
+                log.error("registerUser member imToken");
+            }
+        }
+    }
+
+
+
+    /**
+     * 群组解散
+     *
+     * @param groupId  群组ID
+     */
+    @Override
+    public void groupDismiss(String groupId) throws Exception {
+
+        // 判定登录用户是否为群主
+        ImGroup imGroup = imGroupService.lambdaQuery().eq(ImGroup::getId, groupId).last("LIMIT 1").one();
+        if (Objects.isNull(imGroup)) {
+            throw new BizException("群组不存在");
+        }
+
+
+        // 获取群成员
+        List<ImGroupMemberWrapper.ImGroupMember> groupMembers = imGroupMemberService.lambdaQuery()
+                .select(ImGroupMember::getUserId, ImGroupMember::getImGroupId, ImGroupMember::getRoleType)
+                .eq(ImGroupMember::getImGroupId, groupId)
+                .list().stream()
+                .map(x -> ImGroupMemberWrapper.ImGroupMember.builder().userId(x.getUserId().longValue()).groupId(x.getImGroupId()).clientType(x.getRoleType()).build())
+                .collect(Collectors.toList());
+
+        // 删除群组
+        imGroupService.remove(Wrappers.<ImGroup>lambdaQuery().eq(ImGroup::getId, groupId));
+
+        // 删除群组成员
+        imGroupMemberService.remove(Wrappers.<ImGroupMember>lambdaQuery().eq(ImGroupMember::getImGroupId, groupId));
+
+        // 解散群
+        imPluginContext.getPluginService().groupDismiss(imGroup.getId(), getImGroupMembers(groupMembers));
+
+    }
+
+    /**
+     * 用户主动退出群聊
+     *
+     * @param imGroupMember 用户信息
+     * @param groupId  群组ID
+     * @throws Exception Exception
+     */
+    @Override
+    public void groupQuit(GroupMemberWrapper.ImGroupMember imGroupMember, String groupId) throws Exception {
+
+        // 判定登录用户是否为群主
+        ImGroup imGroup = imGroupService.lambdaQuery().eq(ImGroup::getId, groupId).last("LIMIT 1").one();
+        if (Objects.isNull(imGroup)) {
+            throw new BizException("群组不存在");
+        }
+
+        // 统计当前群成员用户数
+        long count = imGroupMemberService.count(Wrappers.<ImGroupMember>lambdaQuery().eq(ImGroupMember::getImGroupId, groupId));
+
+        // 删除当前用户群成员身份
+        boolean remove = imGroupMemberService.remove(Wrappers.<ImGroupMember>lambdaQuery()
+                .eq(ImGroupMember::getImGroupId, groupId)
+                .eq(ImGroupMember::getUserId, imGroupMember.getUserId())
+//                .eq(ImGroupMember::getRoleType, imGroupMember.getRoleType())
+        );
+        if (!remove) {
+            // 用户主动退出群聊失败
+            throw new BizException("用户主动退出群聊失败");
+        }
+
+        // 修改群组成员数
+        imGroupService.lambdaUpdate()
+                .eq(ImGroup::getId, imGroup.getId())
+                .set(ImGroup::getMemberNum, count - 1)
+                .update();
+
+        // 群主退出
+        List<ImGroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList();
+        groupMembers.add(ImGroupMemberWrapper.ImGroupMember.builder()
+                .userId(imGroupMember.getUserId())
+                .groupId(groupId)
+                .clientType(imGroupMember.getClientType())
+                .imUserId(getImUserId(imGroupMember.getUserId().toString(), imGroupMember.getClientType()))
+                .build());
+
+        imPluginContext.getPluginService().groupQuit(imGroup.getId(), getImGroupMembers(groupMembers));
+    }
+
+    /**
+     * 批量退群
+     *
+     */
+    @Override
+    public void groupQuit(List<GroupMemberWrapper.ImGroupMember> imGroupMembers, String groupId) throws Exception {
+
+
+        // 判定登录用户是否为群主
+        ImGroup imGroup = imGroupService.lambdaQuery().eq(ImGroup::getId, groupId).last("LIMIT 1").one();
+        if (Objects.isNull(imGroup)) {
+            throw new BizException("群组不存在");
+        }
+        if (CollectionUtils.isEmpty(imGroupMembers)){
+            return;
+        }
+
+        // id集合
+        List<Long> userIds = imGroupMembers.stream()
+            .map(GroupMemberWrapper.ImGroupMember::getUserId).collect(Collectors.toList());
+
+
+        // 删除当前用户群成员身份
+        boolean remove = imGroupMemberService.remove(Wrappers.<ImGroupMember>lambdaQuery()
+                .eq(ImGroupMember::getImGroupId, groupId)
+                .in(ImGroupMember::getUserId, userIds)
+        );
+        if (!remove) {
+            // 用户主动退出群聊失败
+            throw new BizException("用户主动退出群聊失败");
+        }
+
+        // 统计当前群成员用户数
+        long count = imGroupMemberService.count(Wrappers.<ImGroupMember>lambdaQuery().eq(ImGroupMember::getImGroupId, groupId));
+
+        // 修改群组成员数
+        imGroupService.lambdaUpdate()
+                .eq(ImGroup::getId, imGroup.getId())
+                .set(ImGroup::getMemberNum, count)
+                .update();
+        imPluginContext.getPluginService().groupQuit(imGroup.getId(), imGroupMembers);
+
+    }
+
+        /**
+         * 用户主动退出群聊
+         *
+         * @param userId     用户信息
+         * @param clientType EClientType
+         * @param imGroupId  群组ID
+         * @throws Exception Exception
+         */
+    @Override
+    public void groupQuit(Long userId, String clientType, String imGroupId) throws Exception {
+
+        ImGroup imGroup = imGroupService.getById(imGroupId);
+        if (Objects.isNull(imGroup)) {
+            throw new BizException("群组不存在");
+        }
+
+        GroupMemberWrapper.ImGroupMember groupMember = GroupMemberWrapper.ImGroupMember.builder()
+            .userId(userId)
+            .roleType(clientType)
+            .clientType(clientType)
+            .imUserId(getImUserId(userId.toString(), clientType))
+            .build();
+        // 退出群聊
+        groupQuit(groupMember, imGroup.getId());
+    }
+
+
+    /**
+     * 添加群组成员
+     * @param imGroupId 群组ID
+     * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
+     * @throws Exception Exception
+     */
+    @Override
+    public void saveImGroupMemberList(String imGroupId, List<ImGroupMemberWrapper.ImGroupMember> groupMembers) throws Exception {
+
+        if (CollectionUtils.isEmpty(groupMembers)) {
+            // 群成员为空,直接忽略
+            return;
+        }
+        // 查询群组主键Id
+        for (ImGroupMemberWrapper.ImGroupMember item : groupMembers) {
+            item.id(IdWorker.getId()).imUserId(getImUserId(item.getUserId().toString(), item.getClientType())).setGroupId(imGroupId);
+        }
+
+        imGroupMemberService.insertBatch(getImGroupMemberEntity(groupMembers));
+        // 判断群ID是否有效
+        ImGroup imGroup = imGroupService.lambdaQuery().eq(ImGroup::getId, imGroupId).last("LIMIT 1").one();
+        if (Objects.isNull(imGroup)) {
+            throw new BizException("群组不存在");
+        }
+        // 更新群组成员数
+        updateGroupMemberNumber(imGroup.getId(), imGroup);
+
+        if (groupMembers.stream().anyMatch(ImGroupMemberWrapper.ImGroupMember::getGroupJoin)) {
+
+            // 过滤出需要添加到群组的成员
+            groupMembers = groupMembers.stream().filter(ImGroupMemberWrapper.ImGroupMember::getGroupJoin).collect(Collectors.toList());
+
+            // 添加群成员到当前群组
+            imPluginContext.getPluginService().groupJoin(imGroup.getId(), imGroup.getName(), getImGroupMembers(groupMembers));
+
+            // 自动激活用户
+            asyncRegisterUser(groupMembers);
+        }
+    }
+
+    /**
+     * 添加群组成员
+     *
+     * @param imGroupId    群组主键ID
+     * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
+     * @throws Exception Exception
+     */
+    @Override
+    public void saveImGroupMemberList(Long imGroupId, List<ImGroupMemberWrapper.ImGroupMember> groupMembers) throws Exception {
+
+        // 群组信息
+        ImGroup imGroup = imGroupService.getById(imGroupId);
+        if (Objects.isNull(imGroup)) {
+            throw new BizException("群组不存在");
+        }
+
+        // 添加群组成员信息
+        saveImGroupMemberList(imGroup.getId(), groupMembers);
+    }
+
+    /**
+     * 群成员加入
+     *
+     * @param imGroupId    群主ID
+     * @param groupMembers 群成员
+     * @throws Exception Exception
+     */
+    @Override
+    public void groupMemberJoin(String imGroupId, List<ImGroupMemberWrapper.ImGroupMember> groupMembers) throws Exception {
+
+        // 群组信息
+        ImGroup imGroup = imGroupService.lambdaQuery().eq(ImGroup::getId, imGroupId).last("LIMIT 1").one();
+        if (Objects.isNull(imGroup)) {
+            throw new BizException("群组不存在");
+        }
+
+        // 添加群组成员信息
+        if (CollectionUtils.isEmpty(groupMembers)) {
+            // 群成员为空,直接忽略
+            return;
+        }
+
+        // 添加群成员到当前群组
+        imPluginContext.getPluginService().groupJoin(imGroup.getId(), imGroup.getName(), getImGroupMembers(groupMembers));
+
+        // 自动激活用户
+        asyncRegisterUser(groupMembers);
+
+    }
+
+    /**
+     * 更新群组成员数
+     * @param groupId 群组ID
+     * @param imGroup ImGroup
+     */
+    private void updateGroupMemberNumber(String groupId, ImGroup imGroup) {
+
+        // 统计当前群成员用户数
+        long count = imGroupMemberService.count(Wrappers.<ImGroupMember>lambdaQuery().eq(ImGroupMember::getImGroupId, groupId));
+
+        // 修改群组成员数
+        imGroupService.lambdaUpdate()
+            .eq(ImGroup::getId, imGroup.getId())
+            .set(ImGroup::getMemberNum, count)
+            .update();
+    }
+
+
+    /**
+     * 添加进入群组
+     *
+     * @param userId     用户ID
+     * @param clientType 客户端类型
+     * @param imGroupId  群组ID
+     */
+    @Override
+    public void groupJoin(Long userId, String clientType, String imGroupId) throws Exception {
+
+        // 群组信息
+        ImGroup imGroup = imGroupService.getById(imGroupId);
+        if (Objects.isNull(imGroup)) {
+            throw new BizException("群组不存在");
+        }
+
+        List<ImGroupMemberWrapper.ImGroupMember> imGroupMembers = new ArrayList<>();
+        ImGroupMemberWrapper.ImGroupMember groupMember = ImGroupMemberWrapper.ImGroupMember
+                .builder()
+                .groupId(imGroup.getId())
+                .userId(userId)
+                .clientType(clientType)
+                .imUserId(getImUserId(userId.toString(),clientType))
+                .isAdmin(false)
+                .roleType(clientType)
+                .build();
+        imGroupMembers.add(groupMember);
+
+        saveImGroupMemberList(imGroupId, imGroupMembers);
+    }
+
+    /**
+     * 转让群主
+     *
+     * @param groupId  群组ID
+     * @param newOwner 新群主
+     * @param oldOwner 旧群主
+     */
+    @Override
+    public void changeGroupOwner(String groupId, String newOwner, String oldOwner) throws Exception {
+
+        // 转主群主
+        imPluginContext.getPluginService().changeGroupOwner(groupId, newOwner, oldOwner);
+    }
+
+    /**
+     * 更新群信息
+     *
+     * @param groupId   群ID
+     * @param groupName 群名称
+     * @param faceUrl   群头像
+     * @throws Exception Exception
+     */
+    @Override
+    public void modifyGroupInfo(String groupId, String groupName, String faceUrl) throws Exception {
+
+        // 更新群信息
+        imPluginContext.getPluginService().modifyGroupInfo(groupId, groupName, faceUrl);
+    }
+
+    /**
+     * 群成员加入三方IM状态
+     *
+     * @param groupMemberIds 群成员ID
+     * @param groupJoin      加群状态
+     */
+    @Override
+    public void updateGroupMemberJoinStatus(List<Long> groupMemberIds, Boolean groupJoin) {
+
+//        if (CollectionUtils.isEmpty(groupMemberIds)) {
+//            return;
+//        }
+//
+//        // 群成员加入三方IM状态
+//        imGroupMemberService.lambdaUpdate()
+//                .set(ImGroupMember::getGroupJoin, groupJoin)
+//                .in(ImGroupMember::getId, groupMemberIds)
+//                .update();
+    }
+
+    @Override
+    public boolean checkImUserId(String imUserId) {
+        try {
+            Integer.parseInt(analysisImUserId(imUserId));
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+}

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

@@ -15,6 +15,7 @@ import com.ym.mec.biz.dal.enums.*;
 import com.ym.mec.biz.dal.page.*;
 import com.ym.mec.biz.dal.wrapper.LiveGroupWrapper;
 import com.ym.mec.biz.service.*;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
 import com.ym.mec.common.constant.CommonConstants;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.dal.BaseDAO;

+ 123 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/impl/EmployeeServiceImpl.java

@@ -16,7 +16,18 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+import com.alibaba.fastjson.JSON;
+import com.google.common.collect.Lists;
+import com.microsvc.toolkit.middleware.im.ImPluginContext;
+import com.microsvc.toolkit.middleware.im.impl.RongCloudImPlugin;
+import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
+import com.ym.mec.biz.dal.dto.SimpleUserDto;
+import com.ym.mec.biz.dal.enums.im.ClientEnum;
+import com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
 import org.redisson.api.RBucket;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -73,6 +84,7 @@ import com.ym.mec.im.entity.GroupMember;
 import com.ym.mec.im.entity.GroupModel;
 import com.ym.mec.util.collection.MapUtil;
 
+@Slf4j
 @Service
 public class EmployeeServiceImpl extends BaseServiceImpl<Integer, Employee> implements EmployeeService {
 
@@ -110,6 +122,10 @@ public class EmployeeServiceImpl extends BaseServiceImpl<Integer, Employee> impl
     private SysUserTenantService sysUserTenantService;
     @Autowired
     private RedissonClient redissonClient;
+    @Autowired
+    private ImGroupCoreService imGroupCoreService;
+    @Autowired
+    private ImPluginContext imPluginContext;
 
     @Override
     public BaseDAO<Integer, Employee> getDAO() {
@@ -486,6 +502,8 @@ public class EmployeeServiceImpl extends BaseServiceImpl<Integer, Employee> impl
             //❤️用户加群
             List<com.ym.mec.biz.dal.entity.ImGroupMember> imGroupMemberList = new ArrayList<>();
             List<GroupModel> groupModelList = new ArrayList<>();
+
+            List<ImGroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList();
             for (ImGroupModel imGroupModel : educationGroupModels) {
                 String userId = imGroupModel.getMemberList().get(0).getId();
                 com.ym.mec.biz.dal.entity.ImGroupMember imGroupMember = new com.ym.mec.biz.dal.entity.ImGroupMember();
@@ -500,9 +518,52 @@ public class EmployeeServiceImpl extends BaseServiceImpl<Integer, Employee> impl
                 GroupMember groupMember = new GroupMember(userId, imGroupModel.getId());
                 GroupModel groupModel = new GroupModel(imGroupModel.getId(), new GroupMember[]{groupMember}, imGroupModel.getName());
                 groupModelList.add(groupModel);
+
+                // 腾讯云IM用户加群
+                groupMembers.add(ImGroupMemberWrapper.ImGroupMember.builder()
+                    .groupId(imGroupModel.getId())
+                    .roleType(imGroupModel.getUserRole())
+                    .isAdmin(false)
+                    .userId(Long.valueOf(userId))
+                    .imUserId(userId)
+                    .nickname(realNameMap.get(imGroupMember.getUserId()))
+                    .updateTime(DateTime.now().toDate())
+                    .createTime(DateTime.now().toDate())
+                    .build());
             }
             imGroupMemberService.batchInsert(imGroupMemberList);
-            imFeignService.groupBatchJoin(groupModelList);
+
+            if (RongCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+                // 融云IM用户加群
+                imFeignService.groupBatchJoin(groupModelList);
+            } else {
+                // 腾讯云IM用户加群
+                if (org.apache.commons.collections.CollectionUtils.isNotEmpty(groupMembers)) {
+                    Map<String, List<ImGroupMemberWrapper.ImGroupMember>> imGroupMembers = groupMembers.stream()
+                        .collect(Collectors.groupingBy(ImGroupMemberWrapper.ImGroupMember::getGroupId));
+
+                    for (Map.Entry<String, List<ImGroupMemberWrapper.ImGroupMember>> entry : imGroupMembers.entrySet()) {
+
+                        try {
+                            // 获取用户头象
+                            List<Integer> collect1 = entry.getValue().stream()
+                                .map(x -> x.getUserId().intValue()).distinct().collect(Collectors.toList());
+
+                            Map<Integer, String> avatarMap = teacherDao.getUsersSimpleInfo(collect1).stream()
+                                .collect(Collectors.toMap(SimpleUserDto::getUserId, SimpleUserDto::getAvatar, (o, n) -> n));
+
+                            // 设置用户默认头象
+                            for (ImGroupMemberWrapper.ImGroupMember member : entry.getValue()) {
+                                member.setAvatar(avatarMap.getOrDefault(member.getUserId().intValue(), ""));
+                            }
+                            // 腾讯云用户加群
+                            imGroupCoreService.groupMemberJoin(entry.getKey(), entry.getValue());
+                        } catch (Exception e) {
+                            log.error("腾讯云IM用户加群失败,groupId:{}, members={}", entry.getKey(), JSON.toJSONString(entry.getValue()), e);
+                        }
+                    }
+                }
+            }
         }
         //原有员工退群
         List<ImGroupModel> groupModels = classGroupDao.queryTeacherQuitGroups(levelUserId);
@@ -510,7 +571,10 @@ public class EmployeeServiceImpl extends BaseServiceImpl<Integer, Employee> impl
         groupModels.addAll(classGroupDao.queryQuitApplyGroups(levelUserId));
         if (groupModels.size() > 0) {
             List<com.ym.mec.biz.dal.entity.ImGroupMember> imGroupMemberList = new ArrayList<>();
+            // 融支IM用户退群
             List<GroupModel> groupModelList = new ArrayList<>();
+            // 腾讯云IM用户退群
+            List<GroupMemberWrapper.ImGroupMember> imGroupMembers = Lists.newArrayList();
             for (ImGroupModel imGroupModel : groupModels) {
                 com.ym.mec.biz.dal.entity.ImGroupMember imGroupMember = new com.ym.mec.biz.dal.entity.ImGroupMember();
                 imGroupMember.setImGroupId(imGroupModel.getId());
@@ -520,9 +584,49 @@ public class EmployeeServiceImpl extends BaseServiceImpl<Integer, Employee> impl
                 GroupMember groupMember = new GroupMember(imGroupMember.getUserId().toString(), imGroupModel.getId());
                 GroupModel groupModel = new GroupModel(imGroupModel.getId(), new GroupMember[]{groupMember}, imGroupModel.getName());
                 groupModelList.add(groupModel);
+
+                // 腾讯云
+                imGroupMembers.add(GroupMemberWrapper.ImGroupMember.builder()
+                    .groupId(imGroupModel.getId())
+                    .userId(imGroupMember.getUserId().longValue())
+                    .imUserId(imGroupMember.getUserId().toString())
+                    .build());
             }
             imGroupMemberService.batchDeleteByGroupIdAndUserId(imGroupMemberList);
-            imFeignService.groupBatchQuit(groupModelList);
+            // 用户批量退出群组
+            if (RongCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+                // 融云退群
+                imFeignService.groupBatchQuit(groupModelList);
+            } else {
+                // 腾讯云退群
+                if (org.apache.commons.collections.CollectionUtils.isNotEmpty(imGroupMembers)) {
+
+                    Map<String, List<GroupMemberWrapper.ImGroupMember>> groupMembers = imGroupMembers.stream()
+                        .collect(Collectors.groupingBy(GroupMemberWrapper.ImGroupMember::getGroupId));
+
+                    for (Map.Entry<String, List<GroupMemberWrapper.ImGroupMember>> entry : groupMembers.entrySet()) {
+
+                        try {
+                            // 获取用户头象
+                            List<Integer> collect1 = entry.getValue().stream()
+                                .map(x -> x.getUserId().intValue()).distinct().collect(Collectors.toList());
+
+                            Map<Integer, String> avatarMap = teacherDao.getUsersSimpleInfo(collect1).stream()
+                                .collect(Collectors.toMap(SimpleUserDto::getUserId, SimpleUserDto::getAvatar, (o, n) -> n));
+
+                            // 设置用户默认头象
+                            for (GroupMemberWrapper.ImGroupMember member : entry.getValue()) {
+                                member.setAvatar(avatarMap.getOrDefault(member.getUserId().intValue(), ""));
+                            }
+                            // 用户退群
+                            imGroupCoreService.groupQuit(entry.getValue(), entry.getKey());
+                        } catch (Exception e) {
+                            log.error("腾讯云IM用户退群失败,groupId:{}, members={}", entry.getKey(), JSON.toJSONString(entry.getValue()), e);
+                        }
+                    }
+                }
+            }
+
         }
         //更换教务老师等数据
         employeeDao.employeeLevel(employeeLevelDtos);
@@ -620,6 +724,23 @@ public class EmployeeServiceImpl extends BaseServiceImpl<Integer, Employee> impl
             }
         }
         employeeDao.update(employee);
+
+        // 用户更新信息同步到三方
+        SysUser userInfo = teacherDao.getUser(employee.getId());
+        if (Objects.nonNull(userInfo)) {
+
+            try {
+                String username = userInfo.getUsername();
+                if (Lists.newArrayList(userInfo.getUserType().split(",")).contains(ClientEnum.TEACHER.getCode())) {
+                    username = Optional.ofNullable(userInfo.getRealName()).orElse(username);
+                }
+
+                imGroupCoreService.register(String.valueOf(userInfo.getId()), "", username, userInfo.getAvatar());
+            } catch (Exception e) {
+                log.error("用户更新信息同步到三方失败,userId:{}", userInfo.getId(), e);
+            }
+        }
+
     }
 
     @Override

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

@@ -1,11 +1,11 @@
 package com.ym.mec.biz.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ym.mec.biz.dal.entity.ImGroupMember;
-import com.ym.mec.biz.dal.mapper.ImGroupMemberPlusMapper;
 import com.ym.mec.biz.service.ImGroupMemberPlusService;
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import lombok.extern.slf4j.Slf4j;
+import com.ym.mec.biz.dal.entity.ImGroupMember;
+import com.ym.mec.biz.dal.mapper.ImGroupMemberPlusMapper;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;

+ 121 - 6
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImGroupMemberServiceImpl.java

@@ -1,13 +1,21 @@
 package com.ym.mec.biz.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.google.common.collect.Lists;
+import com.microsvc.toolkit.middleware.im.ImPluginContext;
+import com.microsvc.toolkit.middleware.im.impl.RongCloudImPlugin;
+import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.*;
 import com.ym.mec.biz.dal.dto.ImGroupMemberDto;
+import com.ym.mec.biz.dal.dto.im.BasicUserInfo;
 import com.ym.mec.biz.dal.entity.*;
 import com.ym.mec.biz.dal.enums.GroupType;
 import com.ym.mec.biz.dal.page.GroupMemberQueryInfo;
+import com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper;
 import com.ym.mec.biz.service.ImGroupMemberService;
 import com.ym.mec.biz.service.ImGroupService;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.common.exception.BizException;
 import com.ym.mec.common.page.PageInfo;
@@ -16,7 +24,9 @@ import com.ym.mec.im.ImFeignService;
 import com.ym.mec.im.entity.GroupMember;
 import com.ym.mec.im.entity.GroupModel;
 import com.ym.mec.util.collection.MapUtil;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -25,6 +35,7 @@ import java.util.*;
 import java.util.Map.Entry;
 import java.util.stream.Collectors;
 
+@Slf4j
 @Service
 public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMember> implements ImGroupMemberService {
 	@Autowired
@@ -49,6 +60,10 @@ public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMembe
 	private ClassGroupStudentMapperDao classGroupStudentMapperDao;
 	@Autowired
 	private ImFeignService imFeignService;
+	@Autowired
+	private ImGroupCoreService imGroupCoreService;
+	@Autowired
+	private ImPluginContext imPluginContext;
 	@Override
 	public BaseDAO<Long, ImGroupMember> getDAO() {
 		return imGroupMemberDao;
@@ -147,8 +162,31 @@ public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMembe
 
 		String groupId = imGroup.getId();
 
-		GroupMember groupMember = new GroupMember(userId.toString(), groupId);
-		imFeignService.groupJoin(new GroupModel(groupId, new GroupMember[] { groupMember }, imGroup.getName()));
+		if (RongCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+			// 融云IM用户加群
+			GroupMember groupMember = new GroupMember(userId.toString(), groupId);
+			imFeignService.groupJoin(new GroupModel(groupId, new GroupMember[] { groupMember }, imGroup.getName()));
+		} else {
+			try {
+				List<ImGroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList();
+
+				groupMembers.add(ImGroupMemberWrapper.ImGroupMember.builder()
+						.groupId(groupId)
+						.isAdmin(isAdmin)
+						.roleType(roleType)
+						.nickname(imGroupMember.getNickname())
+						.userId(userId.longValue())
+						.imUserId(userId.toString())
+						.avatar(user.getAvatar())
+						.updateTime(DateTime.now().toDate())
+						.createTime(DateTime.now().toDate())
+					.build());
+				// 腾讯云IM用户加群
+				imGroupCoreService.groupMemberJoin(groupId, groupMembers);
+			} catch (Exception e) {
+				log.error("腾讯云IM用户加群失败 groupId={}, userId={}", imGroupId, userId, e);
+			}
+		}
 		return true;
 	}
 
@@ -191,8 +229,30 @@ public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMembe
 
 		String groupId = imGroup.getId().toString();
 
-		GroupMember groupMember = new GroupMember(user.getId().toString(), groupId);
-		imFeignService.groupJoin(new GroupModel(groupId, new GroupMember[] { groupMember }, imGroup.getName()));
+		if (RongCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+			// 融云IM用户加群
+			GroupMember groupMember = new GroupMember(user.getId().toString(), groupId);
+			imFeignService.groupJoin(new GroupModel(groupId, new GroupMember[] { groupMember }, imGroup.getName()));
+		} else {
+			// 腾讯云IM
+			List<ImGroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList();
+			try {
+
+				groupMembers.add(ImGroupMemberWrapper.ImGroupMember.builder()
+						.groupId(groupId)
+						.userId(imGroupMember.getUserId().longValue())
+						.imUserId(imGroupMember.getUserId().toString())
+						.nickname(imGroupMember.getNickname())
+						.isAdmin(imGroupMember.getIsAdmin())
+						.roleType(imGroupMember.getRoleType())
+						.avatar(user.getAvatar())
+					.build());
+				// 腾讯云IM用户加群
+				imGroupCoreService.groupMemberJoin(groupId, groupMembers);
+			} catch (Exception e) {
+				log.error("腾讯云IM用户加群失败 groupId={}, groupMembers={}", imGroupId, JSON.toJSONString(groupMembers), e);
+			}
+		}
 
 		return true;
 	}
@@ -218,6 +278,8 @@ public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMembe
 		List<Integer> realNameIds = new ArrayList<>();
 
 //		Map<Integer, String> nameIdMap = MapUtil.convertIntegerMap(teacherDao.queryNickNameByRole(userRoleMap.keySet(),userRoleMap));
+
+		List<ImGroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList();
 		for (Entry<Integer, String> entry : userRoleMap.entrySet()) {
 			if(existUserIdList.contains(entry.getKey())||Objects.isNull(entry.getKey())){
 				continue;
@@ -237,6 +299,17 @@ public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMembe
 //			imGroupMember.setNickname(nameIdMap.get(imGroupMember.getUserId()));
 			imGroupMemberList.add(imGroupMember);
 			groupMemberList.add(new GroupMember(imGroupMember.getUserId().toString(), groupId));
+
+			// 腾讯云IM群用户信息
+			groupMembers.add(ImGroupMemberWrapper.ImGroupMember.builder()
+					.groupId(groupId)
+					.userId(imGroupMember.getUserId().longValue())
+					.imUserId(imGroupMember.getUserId().toString())
+					.isAdmin(imGroupMember.getIsAdmin())
+					.roleType(imGroupMember.getRoleType())
+					.updateTime(imGroupMember.getUpdateTime())
+					.createTime(imGroupMember.getCreateTime())
+				.build());
 		}
 
 
@@ -261,7 +334,29 @@ public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMembe
 			imGroup.setUpdateTime(date);
 			imGroupDao.update(imGroup);
 
-			imFeignService.groupJoin(new GroupModel(groupId, groupMemberList.stream().toArray(GroupMember[]::new), imGroup.getName()));
+			if (RongCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+				// 融云IM用户加群
+				imFeignService.groupJoin(new GroupModel(groupId, groupMemberList.stream().toArray(GroupMember[]::new), imGroup.getName()));
+			} else {
+				try {
+					for (ImGroupMemberWrapper.ImGroupMember item : groupMembers) {
+						// 用户昵称
+						if (StringUtils.isBlank(item.getRoleType())) {
+							item.setNickname(usernameMap.get(item.getUserId().intValue()));
+						} else {
+							item.setNickname(realNameMap.get(item.getUserId().intValue()));
+						}
+
+						BasicUserInfo userInfo = teacherDao.getBasicUserInfo(item.getUserId().intValue());
+						// 用户头像
+						item.setAvatar(userInfo.getAvatar());
+					}
+					// 腾讯云IM用户加群
+					imGroupCoreService.groupMemberJoin(groupId, groupMembers);
+				} catch (Exception e) {
+					log.error("腾讯云IM用户加群失败 groupId={}, members={}", imGroupId, JSON.toJSONString(groupMembers), e);
+				}
+			}
 		}
 
 		return true;
@@ -310,11 +405,31 @@ public class ImGroupMemberServiceImpl extends BaseServiceImpl<Long, ImGroupMembe
 		String groupId = imGroup.getId().toString();
 
 		List<GroupMember> groupMemberList = new ArrayList<GroupMember>();
+
+		List<GroupMemberWrapper.ImGroupMember> imGroupMembers = Lists.newArrayList();
 		for (Integer userId : userIdList) {
+			// 融云IM用户
 			groupMemberList.add(new GroupMember(userId.toString(), groupId));
+
+			// 腾讯云IM用户
+			imGroupMembers.add(GroupMemberWrapper.ImGroupMember.builder()
+					.groupId(groupId)
+					.userId(userId.longValue())
+					.imUserId(userId.toString())
+				.build());
 		}
-		imFeignService.groupQuit(new GroupModel(groupId, groupMemberList.stream().toArray(GroupMember[]::new), imGroup.getName()));
 
+		if (RongCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+			// 融云IM用户退群
+			imFeignService.groupQuit(new GroupModel(groupId, groupMemberList.stream().toArray(GroupMember[]::new), imGroup.getName()));
+		} else {
+			try {
+				// 腾讯云IM用户退群
+				imGroupCoreService.groupQuit(imGroupMembers, groupId);
+			} catch (Exception e) {
+				log.error("腾讯云IM用户退群失败", e);
+			}
+		}
 		return true;
 	}
 

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

@@ -1,11 +1,11 @@
 package com.ym.mec.biz.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ym.mec.biz.dal.entity.ImGroup;
-import com.ym.mec.biz.dal.mapper.ImGroupPlusMapper;
 import com.ym.mec.biz.service.ImGroupPlusService;
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import lombok.extern.slf4j.Slf4j;
+import com.ym.mec.biz.dal.entity.ImGroup;
+import com.ym.mec.biz.dal.mapper.ImGroupPlusMapper;
 
 /**
  * 即时通讯群组

+ 1157 - 114
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImGroupServiceImpl.java

@@ -1,38 +1,95 @@
 package com.ym.mec.biz.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.Lists;
+import com.microsvc.toolkit.middleware.common.http.ImageUtil;
 import com.microsvc.toolkit.middleware.im.ImPluginContext;
-import com.microsvc.toolkit.middleware.im.ImPluginService;
 import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
+import com.microsvc.toolkit.middleware.im.message.MessageWrapper;
+import com.microsvc.toolkit.middleware.im.message.TencentRequest;
+import com.microsvc.toolkit.middleware.im.properties.ImConfigProperties;
 import com.ym.mec.auth.api.entity.SysUser;
-import com.ym.mec.biz.dal.dao.*;
+import com.ym.mec.auth.api.enums.SysUserType;
+import com.ym.mec.biz.dal.dao.ClassGroupTeacherMapperDao;
+import com.ym.mec.biz.dal.dao.ImGroupDao;
+import com.ym.mec.biz.dal.dao.ImGroupMemberDao;
+import com.ym.mec.biz.dal.dao.ImUserFriendDao;
+import com.ym.mec.biz.dal.dao.MusicGroupDao;
+import com.ym.mec.biz.dal.dao.TeacherDao;
 import com.ym.mec.biz.dal.dto.ImGroupDto;
 import com.ym.mec.biz.dal.dto.ImGroupMemberDto;
 import com.ym.mec.biz.dal.dto.NameDto;
-import com.ym.mec.biz.dal.entity.*;
+import com.ym.mec.biz.dal.entity.ClassGroupTeacherMapper;
+import com.ym.mec.biz.dal.entity.CooperationOrgan;
+import com.ym.mec.biz.dal.entity.Employee;
+import com.ym.mec.biz.dal.entity.ImGroup;
+import com.ym.mec.biz.dal.entity.ImGroupMember;
+import com.ym.mec.biz.dal.entity.MusicGroup;
+import com.ym.mec.biz.dal.entity.SchoolStaff;
+import com.ym.mec.biz.dal.entity.Student;
+import com.ym.mec.biz.dal.entity.Teacher;
 import com.ym.mec.biz.dal.enums.EFriendRoleType;
 import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
+import com.ym.mec.biz.dal.enums.im.ClientEnum;
 import com.ym.mec.biz.dal.enums.school.ESchoolStaffType;
 import com.ym.mec.biz.dal.mapper.SchoolStaffMapper;
+import com.ym.mec.biz.dal.page.GroupMemberQueryInfo;
 import com.ym.mec.biz.dal.wrapper.ImGroupWrapper;
-import com.ym.mec.biz.service.*;
+import com.ym.mec.biz.dal.wrapper.ImHistoryMessageWrapper;
+import com.ym.mec.biz.dal.wrapper.SchoolStaffWrapper;
+import com.ym.mec.biz.service.CooperationOrganService;
+import com.ym.mec.biz.service.EmployeeService;
+import com.ym.mec.biz.service.ImGroupMemberService;
+import com.ym.mec.biz.service.ImGroupService;
+import com.ym.mec.biz.service.SchoolStaffService;
+import com.ym.mec.biz.service.StudentService;
+import com.ym.mec.biz.service.SysConfigService;
+import com.ym.mec.biz.service.SysUserService;
+import com.ym.mec.biz.service.TeacherService;
+import com.ym.mec.biz.service.UploadFileService;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
 import com.ym.mec.common.dal.BaseDAO;
-import com.ym.mec.common.entity.ImUserModel;
+import com.ym.mec.common.entity.UploadReturnBean;
 import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.page.PageInfo;
+import com.ym.mec.common.page.PageUtil;
+import com.ym.mec.common.page.QueryInfo;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
 import com.ym.mec.common.tenant.TenantContextHolder;
-import com.ym.mec.im.ImFeignService;
-import com.ym.mec.im.entity.GroupMember;
-import com.ym.mec.im.entity.GroupModel;
+import com.yonge.log.dal.dao.HistoryMessageDao;
+import com.yonge.log.dal.model.HistoryMessage;
+import com.yonge.log.service.HistoryMessageService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.*;
+import javax.annotation.Resource;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Random;
+import java.util.UUID;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -40,49 +97,72 @@ import java.util.stream.Collectors;
 @Slf4j
 public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> implements ImGroupService {
 
-    @Autowired
+    @Resource
     private ImGroupDao imGroupDao;
 
-    @Autowired
+    @Resource
     private ImGroupMemberDao imGroupMemberDao;
 
-    @Autowired
-    private ImGroupNoticeDao imGroupNoticeDao;
-
-    @Autowired
+    @Resource
     private ImGroupMemberService imGroupMemberService;
 
-    @Autowired
-    private ImFeignService imFeignService;
-
-    @Autowired
+    @Resource
     private SysUserService sysUserService;
 
-    @Autowired
+    @Resource
     private ImUserFriendDao imUserFriendDao;
 
-    @Autowired
+    @Resource
     private SysConfigService sysConfigService;
+
+    @Resource
+    private CooperationOrganService cooperationOrganService;
+
+    @Resource
+    private SchoolStaffMapper schoolStaffMapper;
+
+    @Resource
+    private MusicGroupDao musicGroupDao;
+
+    @Resource
+    private ClassGroupTeacherMapperDao classGroupTeacherMapperDao;
+
     @Autowired
-    private ImPluginContext imPluginContext;
+    private ImConfigProperties imConfig;
 
     @Autowired
-    private CooperationOrganService cooperationOrganService;
+    private TeacherService teacherService;
 
     @Autowired
-    private MusicGroupDao musicGroupDao;
+    private StudentService studentService;
 
     @Autowired
-    private ClassGroupTeacherMapperDao classGroupTeacherMapperDao;
+    private SchoolStaffService schoolStaffService;
 
     @Autowired
-    private SchoolStaffMapper schoolStaffMapper;
+    private EmployeeService employeeService;
+
+    @Autowired
+    private UploadFileService uploadFileService;
 
+    @Autowired
+    private HistoryMessageDao historyMessageDao;
+    @Autowired
+    private HistoryMessageService historyMessageService;
+
+    @Resource
+    private ImGroupCoreService imGroupCoreService;
+
+    @Autowired
+    private ImPluginContext imPluginContext;
     @Override
     public BaseDAO<String, ImGroup> getDAO() {
         return imGroupDao;
     }
 
+    @Resource
+    private TeacherDao teacherDao;
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public ImGroup create(String id, Integer userId, String name, String introduce, String memo, String tags, String img, String type, ImGroup.GroupTypeEnum groupType) {
@@ -111,21 +191,38 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
         imGroup.setType(type);
         imGroup.setGroupType(groupType);
         imGroup.setUpdateTime(date);
-        imGroupDao.insert(imGroup);
 
-        String groupId = imGroup.getId();
+        try {
+            String imGroupId = createImGroup(imGroup, userId, null);
+            imGroup.setId(imGroupId);
+        } catch (Exception e) {
+            log.error("群组创建失败",e);
+            throw new BizException("群组创建失败");
+        }
 
-        if(userId != null){
-            imGroupMemberService.join(id, userId, null, true);
+        return imGroup;
+    }
 
-            GroupMember groupMember = new GroupMember(userId.toString(), groupId);
 
-            imFeignService.groupCreate(new GroupModel(groupId, new GroupMember[] { groupMember }, name));
-        }else{
-            imFeignService.groupCreate(new GroupModel(groupId, null, name));
+    private String createImGroup(ImGroup imGroup, Integer userId, String roleType) throws Exception {
+        ImGroupWrapper.ImGroup group = ImGroupWrapper.ImGroup.from(JSON.toJSONString(imGroup));
+
+        //记录群成员
+        com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper.ImGroupMember groupMember = null;
+        if (userId != null) {
+            SysUser sysUser = teacherDao.getUser(userId);
+            SysUserType sysUserType = EFriendRoleType.getByName(roleType).toSysUserType();
+            groupMember = com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper.ImGroupMember
+                    .builder()
+                    .userId(userId.longValue())
+                    .clientType(sysUserType.name())
+                    .avatar(sysUser.getAvatar())
+                    .nickname(sysUserType == SysUserType.STUDENT?sysUser.getUsername():sysUser.getRealName())
+                    .roleType(roleType)
+                    .isAdmin(true)
+                    .build();
         }
-
-        return imGroup;
+        return imGroupCoreService.groupCreate(groupMember, group);
     }
 
     @Override
@@ -152,31 +249,66 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
         imGroup.setType(type);
         imGroup.setGroupType(imGroupDto.getGroupType());
         imGroup.setUpdateTime(date);
-        imGroupDao.insert(imGroup);
+
+
+        try {
+            String imGroupId = createImGroup(imGroup, null, null);
+            imGroup.setId(imGroupId);
+        } catch (Exception e) {
+            log.error("群组创建失败",e);
+            throw new BizException("群组创建失败");
+        }
+
         List<ImGroupMember> groupMemberList = imGroupMemberDao.queryMembers(groupId, userIdList, TenantContextHolder.getTenantId());
         if(currentUserId != null){
             groupMemberList.get(0).setRoleType("乐团主管");
         }
-        imGroupMemberDao.batchInsert(groupMemberList);
-        Function<String,GroupMember> newGroup = userId ->new GroupMember(userId, groupId);
-        List<GroupMember> groupMembers =  userIdList.stream().map(newGroup).collect(Collectors.toList());
-        GroupMember[] members = new GroupMember[groupMembers.size()];
-        groupMembers.toArray(members);
-        imFeignService.groupCreate(new GroupModel(groupId,members,groupName));
+
+        addImGroupMember(groupId, groupMemberList);
         return groupId;
     }
 
+    private void addImGroupMember(String groupId, List<ImGroupMember> groupMemberList) {
+        List<com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper.ImGroupMember> imGroupMembers = Lists.newArrayList();
+        for (ImGroupMember groupMember : groupMemberList) {
+            SysUserType sysUserType = EFriendRoleType.getByName(groupMember.getRoleType()).toSysUserType();
+            imGroupMembers.add(com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper.ImGroupMember.builder()
+                    .groupId(groupMember.getImGroupId())
+                    .userId(groupMember.getUserId().longValue())
+                    .clientType(sysUserType.name())
+                    .avatar(groupMember.getAvatar())
+                    .nickname(groupMember.getNickname())
+                    .isAdmin(groupMember.getIsAdmin())
+                    .imUserId(getImUserId(groupMember.getUserId().toString(), sysUserType.name()))
+                    .roleType(groupMember.getRoleType())
+                    .build());
+        }
+        try {
+            imGroupCoreService.saveImGroupMemberList(groupId, imGroupMembers);
+        } catch (Exception e) {
+            log.error("添加群成员用户失败",e);
+            throw new BizException("添加群成员用户失败");
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean cancel(String imGroupId) {
         // 删除群成员
-        imGroupMemberDao.deleteByImGroupId(imGroupId);
-        // 删除群公告
-        imGroupNoticeDao.deleteByImGroupId(imGroupId);
-        // 删除群信息
-        imGroupDao.delete(imGroupId);
+//        imGroupMemberDao.deleteByImGroupId(imGroupId);
+//        // 删除群公告
+//        imGroupNoticeDao.deleteByImGroupId(imGroupId);
+//        // 删除群信息
+//        imGroupDao.delete(imGroupId);
+//
+//        imFeignService.groupDismiss(new GroupModel(imGroupId, null));
 
-        imFeignService.groupDismiss(new GroupModel(imGroupId, null));
+        try {
+            imGroupCoreService.groupDismiss(imGroupId);
+        } catch (Exception e) {
+            log.error("解散群组失败",e);
+            throw new BizException("解散群组失败");
+        }
 
         return true;
     }
@@ -200,6 +332,28 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
             imGroupMemberDto.setType(EFriendRoleType.getByName(imGroupMemberDto.getRoleType()).name());
             imGroupMemberDto.getUser().setUsername(imGroupMemberDto.getGroupNickname());
             imGroupMemberDto.setNickname(imGroupMemberDto.getGroupNickname());
+            String roleType = imGroupMemberDto.getRoleType();
+            if (StringUtils.isEmpty(roleType)){
+                throw new BizException("roleType为空");
+            }
+            //根据角色不同 配置imUserId
+            if (EFriendRoleType.SCHOOLMASTER.getMsg().equals(roleType) ||
+                    EFriendRoleType.ORCHESTRA_LEADER.getMsg().equals(roleType) ||
+                    EFriendRoleType.SCHOOL_LEADER.getMsg().equals(roleType) ||
+                    EFriendRoleType.SCHOOL_TEACHER.getMsg().equals(roleType)) {
+                imGroupMemberDto.setImUserId(
+                        imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()), SysUserType.SCHOOL.getCode()
+                        )
+                );
+            } else if (EFriendRoleType.ORCHESTRA_TEACHER.getMsg().equals(roleType)){
+                imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.TEACHER.getCode()));
+            } else if (EFriendRoleType.ORCHESTRA_MANAGER.getMsg().equals(roleType) || EFriendRoleType.MAINTENANCE_TECHNICIAN.getMsg().equals(roleType)){
+                imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.EDUCATION.getCode()));
+            } else if (EFriendRoleType.STUDENT.getMsg().equals(roleType)){
+                imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.STUDENT.getCode()));
+            } else {
+                imGroupMemberDto.setImUserId("");
+            }
         }
         return imGroupMemberDtos;
     }
@@ -213,6 +367,29 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
                 imGroupMemberDto.setRoleType(null);
             }
         }
+        String roleType = imGroupMemberDto.getRoleType();
+        if (StringUtils.isEmpty(roleType)){
+            throw new BizException("roleType为空");
+        }
+
+        //根据角色不同 配置imUserId
+        if (EFriendRoleType.SCHOOLMASTER.getMsg().equals(roleType) ||
+                EFriendRoleType.ORCHESTRA_LEADER.getMsg().equals(roleType) ||
+                EFriendRoleType.SCHOOL_LEADER.getMsg().equals(roleType) ||
+                EFriendRoleType.SCHOOL_TEACHER.getMsg().equals(roleType)) {
+            imGroupMemberDto.setImUserId(
+                    imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()), SysUserType.SCHOOL.getCode()
+                    )
+            );
+        } else if (EFriendRoleType.ORCHESTRA_TEACHER.getMsg().equals(roleType)){
+            imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.TEACHER.getCode()));
+        } else if (EFriendRoleType.ORCHESTRA_MANAGER.getMsg().equals(roleType) || EFriendRoleType.MAINTENANCE_TECHNICIAN.getMsg().equals(roleType)){
+            imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.EDUCATION.getCode()));
+        } else if (EFriendRoleType.STUDENT.getMsg().equals(roleType)){
+            imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.STUDENT.getCode()));
+        } else{
+            imGroupMemberDto.setImUserId("");
+        }
         return imGroupMemberDto;
     }
 
@@ -239,8 +416,15 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
             sysUser.setRealName(nickName);
         }
         sysUserService.updateSysUser(sysUser);
-        //同步融云基本信息
-        imFeignService.update(new ImUserModel(sysUser.getId().toString(),nickName,sysUser.getAvatar()));
+
+        // IM用户信息更新
+        try {
+            imGroupCoreService.register(userId.toString(),"",nickName,sysUser.getAvatar());
+        } catch (Exception e) {
+            log.error("更新用户信息失败",e);
+            throw new BizException("更新用户信息失败");
+        }
+
     }
 
     @Override
@@ -248,16 +432,23 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
     public void updateImGroup(ImGroup imGroup) {
         imGroup.setMemberNum(null);
         imGroupDao.update(imGroup);
-        imFeignService.groupUpdate(new GroupModel(imGroup.getId(),null,imGroup.getName()));
+        try {
+            imGroupCoreService.modifyGroupInfo(imGroup.getId(),imGroup.getName(),imGroup.getImg());
+        } catch (Exception e) {
+            log.error("群信息修改失败",e);
+            throw new BizException("群信息修改失败");
+        }
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void dismissGroup(String imGroupId) {
-        imFeignService.groupDismiss(new GroupModel(imGroupId, null));
-        imGroupDao.delete(imGroupId);
-        imGroupMemberDao.deleteByImGroupId(imGroupId);
-        imGroupNoticeDao.deleteByImGroupId(imGroupId);
+        try {
+            imGroupCoreService.groupDismiss(imGroupId);
+        } catch (Exception e) {
+            log.error("解散群组失败",e);
+            throw new BizException("解散群组失败");
+        }
     }
 
     @Override
@@ -303,11 +494,6 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
     @Transactional(rollbackFor = Exception.class)
     public void quitAllGroup(Long userId) {
 
-        // 退出群组
-        String serviceProvider = sysConfigService.findByParamName(SysConfigService.IM_SERVICE_PROVIDER).getParanValue();
-
-        ImPluginService imPluginService =imPluginContext.getPluginService(serviceProvider);
-
         List<ImGroupMember> imGroupMembers = imGroupMemberDao.queryMembersByUserId(userId);
 
         if (CollectionUtils.isEmpty(imGroupMembers)) {
@@ -327,7 +513,7 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
                 }
             }
             try {
-                imPluginService.groupQuit(imGroupMember.getImGroupId(), GroupMemberWrapper.ImGroupMember.builder().userId(userId).imUserIdFormat(false).build());
+                imGroupCoreService.groupQuit(userId,"",imGroupMember.getImGroupId());
             } catch (Exception e) {
                 log.error("用户退出群失败{},{}", userId, imGroupMember.getImGroupId(), e);
             }
@@ -349,8 +535,7 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
         List<ImGroup> groups = imGroups.stream().filter(imGroup -> imGroup.getMemberNum().equals(1)).collect(Collectors.toList());
         for (ImGroup group : groups) {
             try {
-                GroupMemberWrapper.ImGroupMember build = GroupMemberWrapper.ImGroupMember.builder().userId(userId).imUserIdFormat(false).build();
-                imPluginService.groupDismiss(group.getId(), Lists.newArrayList(build));
+                dismissGroup(group.getId());
             } catch (Exception e) {
                 log.error("解散群组失败{},{}", userId, group.getId(), e);
             }
@@ -372,13 +557,9 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
         // 查询群是否存在
         ImGroup imGroup = imGroupDao.queryBySchoolId(schoolId);
 
-        String serviceProvider = sysConfigService.findByParamName(SysConfigService.IM_SERVICE_PROVIDER).getParanValue();
-
-        ImPluginService imPluginService =imPluginContext.getPluginService(serviceProvider);
-
 
         // 注册主播用户信息到三方平台
-        imPluginService.register(userId.toString(), name, avatar);
+        imGroupCoreService.register(userId.toString(),"", name, avatar);
 
         // 群组不存在,先创建群组
         if (Objects.isNull(imGroup)) {
@@ -396,13 +577,12 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
             imGroup.setCreateTime(new Date());
             imGroup.setUpdateTime(new Date());
             imGroup.setTenantId(cooperationOrgan.getTenantId());
-            imGroupDao.insert(imGroup);
-            imPluginService.groupCreate(imGroup.getId(), imGroup.getName(), userId.toString());
+
+            createImGroup(imGroup,userId,"");
 
             initSchoolGroup(imGroup.getSchoolId());
         }
-        imPluginService.groupJoin(imGroup.getId(), imGroup.getName(), GroupMemberWrapper.ImGroupMember.builder()
-                .userId(userId.longValue()).imUserIdFormat(false).build());
+
 
         if (schoolStaffType.equals(ESchoolStaffType.ORCHESTRA_LEADER)) {
             groupChangeOwner(userId, imGroup.getId());
@@ -496,16 +676,8 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
             groupMember.setImUserIdFormat(false);
         }
 
-        String serviceProvider = sysConfigService.findByParamName(SysConfigService.IM_SERVICE_PROVIDER).getParanValue();
 
-        ImPluginService imPluginService =imPluginContext.getPluginService(serviceProvider);
-
-        try {
-            imPluginService.groupJoin(imGroup.getId(), imGroup.getName(), imGroupMembers);
-        } catch (Exception e) {
-            log.error("添加群成员失败{}", imGroup.getId(), e);
-        }
-        imGroupMemberDao.batchInsert(imGroupMemberList);
+        addImGroupMember(imGroup.getId(), imGroupMemberList);
         updateImGroupUserNumber(imGroup.getId());
     }
 
@@ -527,22 +699,17 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
         }
 
 
-        String serviceProvider = sysConfigService.findByParamName(SysConfigService.IM_SERVICE_PROVIDER).getParanValue();
 
         List<Integer> userIds = new ArrayList<>();
-        ImPluginService imPluginService =imPluginContext.getPluginService(serviceProvider);
         for (GroupMemberWrapper.ImGroupMember imGroupMember : imGroupMembers) {
             imGroupMember.setImUserIdFormat(false);
             userIds.add(imGroupMember.getUserId().intValue());
         }
         try {
-            imPluginService.groupQuit(imGroup.getId(),imGroupMembers);
+            imGroupCoreService.groupQuit(imGroupMembers,imGroup.getId());
         } catch (Exception e) {
             log.error("退出群成员失败{}", imGroup.getId(), e);
         }
-
-
-        imGroupMemberDao.delByImGroupAndUserId(imGroup.getId(),userIds);
         updateImGroupUserNumber(imGroup.getId());
     }
 
@@ -562,9 +729,6 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
     @Transactional(rollbackFor = Exception.class)
     public Boolean groupChangeOwner(Integer userId, String imGroupId) throws Exception {
 
-        String serviceProvider = sysConfigService.findByParamName(SysConfigService.IM_SERVICE_PROVIDER).getParanValue();
-
-        ImPluginService imPluginService =imPluginContext.getPluginService(serviceProvider);
 
         ImGroupMember imGroupMember = imGroupMemberDao.getAdmin(imGroupId);
         Integer adminId = userId;
@@ -573,7 +737,7 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
             imGroupMember.setIsAdmin(false);
             imGroupMemberDao.update(imGroupMember);
         }
-        imPluginService.changeGroupOwner(imGroupId, userId.toString(), adminId.toString());
+        imGroupCoreService.changeGroupOwner(imGroupId, userId.toString(), adminId.toString());
 
         imGroupMemberDao.updateAdmin(imGroupId, userId);
         return true;
@@ -593,10 +757,6 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
             return;
         }
 
-        String serviceProvider = sysConfigService.findByParamName(SysConfigService.IM_SERVICE_PROVIDER).getParanValue();
-
-        ImPluginService imPluginService =imPluginContext.getPluginService(serviceProvider);
-
         List<ImGroup> groupList = imGroupDao.getByIds(imGroupIds);
 
         // id 分组
@@ -609,18 +769,7 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
                 continue;
             }
             try {
-                imPluginService.groupJoin(imGroup.getId(), imGroup.getName(), GroupMemberWrapper.ImGroupMember.builder()
-                        .userId(userId)
-                        .imUserIdFormat(false).build());
-
-                ImGroupMember imGroupMember = new ImGroupMember();
-                imGroupMember.setImGroupId(imGroup.getId());
-                imGroupMember.setUserId(userId.intValue());
-                imGroupMember.setIsAdmin(false);
-                imGroupMember.setRoleType(roleType);
-                imGroupMember.setType(EFriendRoleType.getByName(roleType).name());
-                imGroupMember.setTenantId(imGroup.getTenantId());
-                imGroupMemberDao.insert(imGroupMember);
+                imGroupCoreService.groupJoin(userId,"",imGroup.getId());
 
                 updateImGroupUserNumber(imGroup.getId());
             } catch (Exception e) {
@@ -654,16 +803,12 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
             return;
         }
 
-        String serviceProvider = sysConfigService.findByParamName(SysConfigService.IM_SERVICE_PROVIDER).getParanValue();
-
-        ImPluginService imPluginService =imPluginContext.getPluginService(serviceProvider);
-
         List<ImGroup> groupList = imGroupDao.getByIds(imGroupIds);
 
         List<com.ym.mec.biz.dal.entity.ImGroupMember> imGroupMemberList = new ArrayList<>();
         for (ImGroup imGroup : groupList) {
             try {
-                imPluginService.groupQuit(imGroup.getId(),  GroupMemberWrapper.ImGroupMember.builder().userId(userId.longValue()).imUserIdFormat(false).build());
+                imGroupCoreService.groupQuit(userId.longValue(), "",imGroup.getId());
             } catch (Exception e) {
                 log.error("退出群聊失败",e);
             }
@@ -679,7 +824,6 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
         }
     }
 
-
     /**
      * 学校人员加入群组
      *
@@ -714,4 +858,903 @@ public class ImGroupServiceImpl extends BaseServiceImpl<String, ImGroup> impleme
         addImGroup(Lists.newArrayList(imGroup.getId()),schoolStaff.getUserId(),ESchoolStaffType.ORCHESTRA_LEADER.getDescribe());
 
     }
+
+
+    /**
+     * IM 用户注册
+     *
+     * @param userId 用户Id
+     * @return String
+     */
+    @Override
+    public String getImUserId(String userId, String clientType) {
+        /*if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !userId.startsWith(imConfig.getAppPrefix())) {
+            imUserId = MessageFormat.format("{0}_{1}", imConfig.getAppPrefix(), userId);
+        }*/
+        return userId;
+    }
+
+
+    /**
+     * 群迁移
+     */
+    @Override
+    public void groupTransfer(String startTime, String endTime) {
+        int page = 1;
+        int size = 100;
+        QueryInfo queryInfo = new QueryInfo();
+        queryInfo.setPage(page);
+        queryInfo.setRows(size);
+        queryInfo.setImportFlag(false);
+        PageInfo<ImGroup> imGroupPageInfo = this.queryPage(queryInfo);
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        int importImGroupCount = 0;
+        while (!imGroupPageInfo.getRows().isEmpty()) {
+            List<ImGroup> rows = imGroupPageInfo.getRows();
+            try {
+                if (StringUtils.isNotEmpty(startTime)) {
+                    Date startDate = sdf.parse(startTime);
+                    rows.removeIf(next -> next.getCreateTime().before(startDate));
+                }
+
+                if (StringUtils.isNotEmpty(endTime)) {
+                    Date endDate = sdf.parse(endTime);
+                    Calendar calendar = Calendar.getInstance();
+                    calendar.setTime(endDate);
+                    calendar.set(Calendar.HOUR_OF_DAY, 23);
+                    calendar.set(Calendar.MINUTE, 59);
+                    calendar.set(Calendar.SECOND, 59);
+                    rows.removeIf(next -> next.getCreateTime().after(calendar.getTime()));
+                }
+            } catch (ParseException e) {
+                throw new BizException("时间区间参数错误,格式为:yyyy-MM-dd");
+            }
+            groupTransfer(rows);
+            importImGroupCount += rows.size();
+            log.info("------------------------------- import im group --------------------------------------------");
+            log.info("import im group success count:{}/{}", importImGroupCount, imGroupPageInfo.getTotal());
+
+            page++;
+            queryInfo.setPage(page);
+            imGroupPageInfo = this.queryPage(queryInfo);
+        }
+        log.info("-------------------- import im group finished and success! -------------------------------");
+    }
+
+    private void groupTransfer(List<ImGroup> records) {
+
+        for (ImGroup imGroup : records) {
+
+            log.info("群销毁开始:{}", imGroup.getId());
+            // 先删除群组
+            try {
+                // 解散群
+                imPluginContext.getPluginService().groupDismiss(imGroup.getId(), new ArrayList<>());
+            } catch (Exception e) {
+                log.error(String.format("群迁移删除群聊失败:%s", e.getMessage()), e);
+            }
+        }
+
+        for (ImGroup imGroup : records) {
+
+            log.info("群迁移开始:{}", imGroup.getId());
+
+            GroupMemberQueryInfo groupMemberQueryInfo = new GroupMemberQueryInfo();
+            groupMemberQueryInfo.setPage(1);
+            groupMemberQueryInfo.setRows(9999);
+            groupMemberQueryInfo.setImGroupId(imGroup.getId());
+            PageInfo<ImGroupMemberDto> pageInfo = imGroupMemberService.queryGroupMemberPage(groupMemberQueryInfo);
+            ImGroupMember admin = pageInfo.getRows().stream().filter(ImGroupMember::getIsAdmin).findFirst().orElse(null);
+            if (admin == null) {
+                log.info("群主不存在,groupId:{}",imGroup.getId());
+//                continue;
+            }
+            try {
+                MessageWrapper.ImportGroup importGroup = new MessageWrapper.ImportGroup();
+                if (admin != null) {
+                    importGroup.setOwnerAccount(getImUserId(admin.getUserId().toString(), getClientType(admin.getRoleType())));
+                }
+                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/icon_group_avatar1.png");
+                }
+                importGroup.setApplyJoinOption("FreeAccess");
+                importGroup.setCreateTime(imGroup.getCreateTime().getTime() / 1000);
+                if (admin != null) {
+                    register(admin.getUserId().toString(), getClientType(admin.getRoleType()));
+                }
+                imPluginContext.getPluginService().importGroup(importGroup);
+
+                List<ImGroupMember> groupMembers = pageInfo.getRows().stream()
+                        .filter(next -> !next.getIsAdmin()).collect(Collectors.toList());
+                if (groupMembers.isEmpty()) {
+                    imGroupDao.updateImportStatusSuccess(imGroup.getId());
+                    continue;
+                }
+                for (ImGroupMember member : groupMembers) {
+                    register(member.getUserId().toString(), getClientType(member.getRoleType()));
+                }
+                MessageWrapper.ImportGroupMember importGroupMember = new MessageWrapper.ImportGroupMember();
+                importGroupMember.setGroupId(imGroup.getId());
+                Date date = new DateTime(imGroup.getCreateTime()).plusSeconds(3).toDate();
+                List<MessageWrapper.ImportGroupMemberData> members =
+                        groupMembers.stream().map(next -> {
+                            MessageWrapper.ImportGroupMemberData data = new MessageWrapper.ImportGroupMemberData();
+                            data.setMemberAccount(getImUserId(next.getUserId().toString(),
+                                    getClientType(next.getRoleType())));
+                            if (next.getCreateTime().getTime() / 1000 <= importGroup.getCreateTime()) {
+                                data.setJoinTime(date.getTime() / 1000);
+                            } else {
+                                data.setJoinTime(next.getCreateTime().getTime() / 1000);
+                            }
+                            data.setUnreadMsgNum(0);
+                            return data;
+                        }).collect(Collectors.toList());
+                importGroupMember.setMemberList(members);
+                imPluginContext.getPluginService().importGroupMember(importGroupMember);
+                imGroupDao.updateImportStatusSuccess(imGroup.getId());
+            } catch (Exception e) {
+                log.error(String.format("群迁移失败,失败群组:%s", JSON.toJSONString(imGroup)));
+                log.error(String.format("群迁移失败:%s", e.getMessage()));
+            }
+            log.info("群迁移成功:{}", imGroup.getId());
+        }
+    }
+
+    private void register(String userId, String clientType) {
+        SysUser user = sysUserService.queryUserById(Integer.valueOf(userId));
+        String avatar = user.getAvatar();
+        if (StringUtils.isEmpty(avatar)) {
+            avatar = "https://daya.ks3-cn-beijing.ksyun.com/202203/T1WgJaE.png";
+        }
+        try {
+            String username = user.getUsername();
+
+            // 老师默认使用真实姓名
+            if (Lists.newArrayList(user.getUserType().split(",")).contains(ClientEnum.TEACHER.getCode())) {
+                username = Optional.ofNullable(user.getRealName()).orElse(username);
+            }
+            // 自动激活学生IM帐号
+            imGroupCoreService.register(userId,clientType, username, avatar);
+        } catch (Exception e) {
+            log.error("register user error", e);
+        }
+    }
+
+
+    public String getClientType(String roleType) {
+        EFriendRoleType byName = EFriendRoleType.getByName(roleType);
+        if (EFriendRoleType.STUDENT.equals(byName)) {
+            return "STUDENT";
+        } else if (EFriendRoleType.ORCHESTRA_TEACHER.equals(byName)) {
+            return "TEACHER";
+        } else if (EFriendRoleType.ORCHESTRA_MANAGER.equals(byName) ||
+                EFriendRoleType.MAINTENANCE_TECHNICIAN.equals(byName)) {
+            return "EMPLOYEE";
+        } else {
+            return "SCHOOL";
+        }
+    }
+
+    /**
+     * 导入用户
+     */
+    @Override
+    public void importUser() {
+        int page = 1;
+        int rows = 200;
+
+        int count = 0;
+
+        log.info("------------------------------- import user student ---------------------------");
+        List<String[]> student = getStudent(page, rows);
+        while (!student.isEmpty()) {
+            for (String[] next : student) {
+                register(next[0], next[1]);
+            }
+            count += student.size();
+            log.info("import im student success count:{}", count);
+            page++;
+            student = getStudent(page, rows);
+        }
+
+        log.info("------------------------------- import user staff ---------------------------");
+        count = 0;
+        page = 1;
+        List<String[]> staff = getStaff(page, rows);
+        while (!staff.isEmpty()) {
+            for (String[] next : staff) {
+                register(next[0], next[1]);
+            }
+            count += staff.size();
+            log.info("import im staff success count:{}", count);
+            page++;
+            staff = getStaff(page, rows);
+        }
+
+        log.info("------------------------------- import user emps ---------------------------");
+        count = 0;
+        page = 1;
+        List<String[]> emps = getEmp(page, rows);
+        while (!emps.isEmpty()) {
+            for (String[] next : emps) {
+                register(next[0], next[1]);
+            }
+            count += emps.size();
+            log.info("import im emps success count:{}", count);
+            page++;
+            emps = getEmp(page, rows);
+        }
+
+        log.info("------------------------------- import user teacher ---------------------------");
+        count = 0;
+        page = 1;
+        List<String[]> teachers = getTeachers(page, rows);
+        while (!teachers.isEmpty()) {
+            for (String[] next : teachers) {
+                register(next[0], next[1]);
+            }
+            count += teachers.size();
+            log.info("import im teacher success count:{}", count);
+            page++;
+            teachers = getTeachers(page, rows);
+        }
+
+        log.info("------------------------------- import user success ---------------------------");
+    }
+
+    @Override
+    public int queryInfoCount() {
+        long count = historyMessageService.selectCount(0,new DateTime().plusMonths(-2).toDate());
+        return (int) count;
+    }
+
+    private List<String[]> getEmp(int page, int rows) {
+        QueryInfo queryInfo = new QueryInfo();
+        queryInfo.setPage(page);
+        queryInfo.setRows(rows);
+        PageInfo<Employee> employeePageInfo = employeeService.queryPage(queryInfo);
+        return employeePageInfo.getRows().stream().map(next -> {
+            String[] strList = new String[2];
+            strList[0] = next.getId().toString();
+            strList[1] = "EMPLOYEE";
+            return strList;
+        }).collect(Collectors.toList());
+    }
+
+    private List<String[]> getStaff(int page, int rows) {
+        Page<SchoolStaffWrapper.SchoolStaff> staffPage = PageUtil.getPage(page, rows);
+        IPage<SchoolStaffWrapper.SchoolStaff> iPage = schoolStaffService.selectPage(staffPage,
+                new SchoolStaffWrapper.SchoolStaffQuery());
+        return iPage.getRecords().stream().map(next -> {
+            String[] strList = new String[2];
+            strList[0] = next.getId().toString();
+            strList[1] = "SCHOOL";
+            return strList;
+        }).collect(Collectors.toList());
+    }
+
+    private List<String[]> getStudent(int page, int rows) {
+        QueryInfo queryInfo = new QueryInfo();
+        queryInfo.setPage(page);
+        queryInfo.setRows(rows);
+        PageInfo<Student> studentPageInfo = studentService.queryPage(queryInfo);
+        return studentPageInfo.getRows().stream().map(next -> {
+            String[] strList = new String[2];
+            strList[0] = next.getId().toString();
+            strList[1] = "STUDENT";
+            return strList;
+        }).collect(Collectors.toList());
+    }
+
+    private List<String[]> getTeachers(int page, int rows) {
+        QueryInfo queryInfo = new QueryInfo();
+        queryInfo.setPage(page);
+        queryInfo.setRows(rows);
+        PageInfo<Teacher> teacherPageInfo = teacherService.queryPage(queryInfo);
+        return teacherPageInfo.getRows().stream().map(next -> {
+            String[] strList = new String[2];
+            strList[0] = next.getId().toString();
+            strList[1] = "TEACHER";
+            return strList;
+        }).collect(Collectors.toList());
+    }
+
+
+
+    @Override
+    public com.yonge.mongodb.PageInfo<HistoryMessage> getRongYunInfo( int page, int size) {
+        com.yonge.mongodb.PageInfo<HistoryMessage> pageInfo = historyMessageService.selectPage(page, size, 0,new DateTime().plusMonths(-2).toDate());
+        //List<HistoryMessage> imHistoryMessageslist = imGroupDao.selectAll(result,size);
+        return pageInfo;
+    }
+
+
+
+    /**
+     * IM导入消息
+     */
+    @Override
+    public void importInfo(List<HistoryMessage> info) throws Exception {
+
+        for (HistoryMessage i : info) {//判断消息类型
+            log.info("消息导入:{}", i);
+            try {
+                Integer type = i.getTargetType();
+                if (type == 1) {
+                    //单聊会话
+                    MessageWrapper.PrivateImportMessage privateImportMessage = new MessageWrapper.PrivateImportMessage();
+                    //2:表示历史消息导入,消息不计入未读计数,且消息不会推送到终端
+                    privateImportMessage.setSyncFromOldSystem(2);
+                    //设置发送人
+                    //根据发送者分场景讨论
+                    String id = i.getFromUserId();
+                    String imUserId;
+                    if (id.contains(":STUDENT")) {
+                        String[] split = id.split(":");
+                        String userId = split[0];
+                        String clientType = split[1];
+                        imUserId = getImUserId(userId, clientType);
+                    } else {
+                        imUserId = getImUserId(id, "TEACHER");
+                    }
+
+                    String targetId = i.getTargetId();
+                    String targetIdUserId;
+                    if (targetId.contains(":STUDENT")) {
+                        String[] split = targetId.split(":");
+                        String userId = split[0];
+                        String clientType = split[1];
+                        targetIdUserId = getImUserId(userId, clientType);
+                    } else {
+                        targetIdUserId = getImUserId(targetId, "TEACHER");
+                    }
+
+                    privateImportMessage.setFromAccount(imUserId);
+                    //设置接收人
+                    privateImportMessage.setToAccount(targetIdUserId);
+                    //设置随机数
+                    privateImportMessage.setMsgRandom(new Random().nextInt());
+
+                    //设置发送时间
+                    String time = i.getDateTime();
+                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                    try {
+                        Date date = df.parse(time);
+                        long dateTime = date.getTime();
+                        dateTime = dateTime / (1000);
+                        privateImportMessage.setMsgTimeStamp(dateTime);
+                    } catch (ParseException e) {
+                        e.printStackTrace();
+                    }
+
+                    //设置body
+                    TencentRequest.MessageBody body = new TencentRequest.MessageBody();
+                    List<TencentRequest.MessageBody> list = new ArrayList<>();
+
+                    JSONObject jsonObject = JSONObject.parseObject(i.getContent());
+
+                    if (i.getClassname().equals("RC:TxtMsg")) {
+                        //文本
+                        TencentRequest.MessageBody body1 = getTimTextElem(jsonObject.getString("content"));
+                        list.add(body1);
+                    } else if (i.getClassname().equals("RC:ImgMsg")) {
+                        //图片
+                        TencentRequest.MessageBody body1 = getTimImageElem(jsonObject.getString("imageUri"));
+                        list.add(body1);
+                    } else if (i.getClassname().equals("RC:GIFMsg")) {
+                        //GIf
+                        String remoteUrl = jsonObject.getString("remoteUrl");
+                        int gifDataSize = jsonObject.getInteger("gifDataSize");
+                        int width = jsonObject.getInteger("width");
+                        int height = jsonObject.getInteger("height");
+                        TencentRequest.MessageBody body1 = getTimGifElem(remoteUrl, gifDataSize, width, height);
+                        list.add(body1);
+                    } else if (i.getClassname().equals("RC:HQVCMsg")) {
+                        //语音
+                        String remoteUrl = jsonObject.getString("remoteUrl");
+                        int duration = jsonObject.getInteger("duration");
+                        TencentRequest.MessageBody body1 = getTimSoundElem(remoteUrl, duration);
+                        list.add(body1);
+                    } else if (i.getClassname().equals("RC:FileMsg")) {
+                        //文件
+                        String fileUrl = jsonObject.getString("fileUrl");
+                        String size = jsonObject.getString("size");
+                        String name = jsonObject.getString("name");
+
+                        TencentRequest.MessageBody body1 = getTimFileElem(fileUrl, size, name);
+                        list.add(body1);
+                    } else if (i.getClassname().equals("RC:SightMsg")) {
+                        //视频
+                        String sightUrl = jsonObject.getString("sightUrl");
+                        String size = jsonObject.getString("size");
+                        int duration = jsonObject.getInteger("duration");
+                        String content = jsonObject.getString("content");
+                        TencentRequest.MessageBody body1 = null;
+                        try {
+                            body1 = getTimVideoFileElem(sightUrl, size, duration, content);
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                        list.add(body1);
+                    } else if (i.getClassname().equals("RC:LBSMsg")) {
+                        //位置
+                        double latitude = jsonObject.getDouble("latitude");
+                        double longitude = jsonObject.getDouble("longitude");
+                        String poi = jsonObject.getString("poi");
+                        TencentRequest.MessageBody body1 = getTimLocationElem(latitude, longitude, poi);
+                        list.add(body1);
+                    } else if (i.getClassname().equals("RC:ImgTextMsg")) {
+                        //图文
+                        TencentRequest.MessageBody body1 = getTimTextElem(jsonObject.getString("content"));
+                        TencentRequest.MessageBody body2 = getTimImageElem(jsonObject.getString("imageUri"));
+                        list.add(body1);
+                        list.add(body2);
+                    }
+
+               /* body.setMsgType(i.getClassname());
+                body.setMsgContent(i.getContent());*/
+
+                    /*list.add(body);*/
+               /* 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")) {
+                    //文本对象
+                    list.forEach(item -> item.setMsgType("TIMTextElem"));
+                } else if (list.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:ImgMsg")) {
+                    //图文对象
+                    list.forEach(item -> item.setMsgType("TIMImageElem"));
+                } else if (list.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:HQVCMsg")){
+                    //高清语音消息对象
+                    list.forEach(item -> item.setMsgType("TIMSoundElem"));
+                } else if (list.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:HQVCMsg")){
+                    list.forEach(item -> item.setMsgType("TIMSoundElem"));
+                }*/
+                    privateImportMessage.setTencentMessageBody(list);
+                    privateImportMessage.setCloudCustomData(jsonObject.getString("extra"));
+                    try {
+                        imPluginContext.getPluginService().importPrivateMessage(privateImportMessage);
+                        //为已导入数据更改标识
+                        updateStatus(i,1);
+                    } catch (Exception e) {
+                        updateStatus(i,2);
+                        log.error("导入私聊IM消息失败 msg:{},entity:{}", list, i, e);
+                    }
+                } else if (type == 3) {
+                    //群组会话
+                    MessageWrapper.GroupImportMessage groupImportMessage = new MessageWrapper.GroupImportMessage();
+                    List<MessageWrapper.GroupImportMessageData> list = new ArrayList<>();
+                    MessageWrapper.GroupImportMessageData data1 = new MessageWrapper.GroupImportMessageData();
+                    List<TencentRequest.MessageBody> bodyList = new ArrayList<>();
+                    TencentRequest.MessageBody body = new TencentRequest.MessageBody();
+                    //设置群组Id
+                    groupImportMessage.setGroupId(i.getGroupId());
+                    //设置发送人
+                    String imUserId;
+                    String id = i.getFromUserId();
+                    //根据发送者分场景讨论
+                    if (id.contains(":STUDENT")) {
+                        String[] split = id.split(":");
+                        String userId = split[0];
+                        String clientType = split[1];
+                        imUserId = getImUserId(userId, clientType);
+                    } else {
+                        imUserId = getImUserId(id, "TEACHER");
+                    }
+
+
+                    data1.setFromAccount(imUserId);
+                    //设置随机数
+                    data1.setRandom(new Random().nextInt());
+                    //设置发送时间
+
+                    String time = i.getDateTime();
+                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                    try {
+                        Date date = df.parse(time);
+                        long dateTime = date.getTime();
+                        dateTime = dateTime / (1000);
+                        data1.setSendTime(dateTime);
+                    } catch (ParseException e) {
+                        e.printStackTrace();
+                    }
+                /*bodyList.stream().forEach(item->{
+                            item.setMsgContent(i.getContent());
+                            item.setMsgType(i.getClassname());
+                        });*/
+                    JSONObject jsonObject = JSONObject.parseObject(i.getContent());
+
+
+                    if (i.getClassname().equals("RC:TxtMsg")) {
+                        //文本
+                        TencentRequest.MessageBody body1 = getTimTextElem(jsonObject.getString("content"));
+                        bodyList.add(body1);
+                    } else if (i.getClassname().equals("RC:ImgMsg")) {
+                        //图片
+                        TencentRequest.MessageBody body1 = getTimImageElem(jsonObject.getString("imageUri"));
+                        bodyList.add(body1);
+                    } else if (i.getClassname().equals("RC:GIFMsg")) {
+                        //GIf
+                        String remoteUrl = jsonObject.getString("remoteUrl");
+                        int gifDataSize = jsonObject.getInteger("gifDataSize");
+                        int width = jsonObject.getInteger("width");
+                        int height = jsonObject.getInteger("height");
+                        TencentRequest.MessageBody body1 = getTimGifElem(remoteUrl, gifDataSize, width, height);
+                        bodyList.add(body1);
+                    } else if (i.getClassname().equals("RC:HQVCMsg")) {
+                        //语音
+                        String remoteUrl = jsonObject.getString("remoteUrl");
+                        int duration = jsonObject.getInteger("duration");
+                        TencentRequest.MessageBody body1 = getTimSoundElem(remoteUrl, duration);
+                        bodyList.add(body1);
+                    } else if (i.getClassname().equals("RC:FileMsg")) {
+                        //文件
+                        String fileUrl = jsonObject.getString("fileUrl");
+                        String size = jsonObject.getString("size");
+                        String name = jsonObject.getString("name");
+
+                        TencentRequest.MessageBody body1 = getTimFileElem(fileUrl, size, name);
+                        bodyList.add(body1);
+                    } else if (i.getClassname().equals("RC:SightMsg")) {
+                        //视频
+                        String sightUrl = jsonObject.getString("sightUrl");
+                        String size = jsonObject.getString("size");
+                        int duration = jsonObject.getInteger("duration");
+                        String content = jsonObject.getString("content");
+                        TencentRequest.MessageBody body1 = null;
+                        try {
+                            body1 = getTimVideoFileElem(sightUrl, size, duration, content);
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                        bodyList.add(body1);
+                    } else if (i.getClassname().equals("RC:LBSMsg")) {
+                        //位置
+                        double latitude = jsonObject.getDouble("latitude");
+                        double longitude = jsonObject.getDouble("longitude");
+                        String poi = jsonObject.getString("poi");
+                        TencentRequest.MessageBody body1 = getTimLocationElem(latitude, longitude, poi);
+                        bodyList.add(body1);
+                    } else if (i.getClassname().equals("RC:ImgTextMsg")) {
+                        //图文
+                        TencentRequest.MessageBody body1 = getTimTextElem(jsonObject.getString("content"));
+                        TencentRequest.MessageBody body2 = getTimImageElem(jsonObject.getString("imageUri"));
+                        bodyList.add(body1);
+                        bodyList.add(body2);
+                    } else if (i.getClassname().equals("RC:CombineMsg")) {
+                        //合并转发
+                        String remoteUrl = jsonObject.getString("remoteUrl");
+                        int conversationType = jsonObject.getInteger("conversationType");
+                        getTimRelayElem();
+                    } else {
+                        continue;
+                    }
+                /*body.setMsgContent(i.getContent());
+                body.setMsgType(i.getClassname());*/
+
+                    //文本对象
+                /*if (bodyList.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:TxtMsg")) {
+                    bodyList.forEach(item -> item.setMsgType("TIMTextElem"));
+                } else if (bodyList.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:ImgMsg")) {
+                    //暂未支持图文对象
+                    bodyList.forEach(item -> item.setMsgType("TIMCustomElem"));
+                }*/
+
+                    data1.setTencentMessageBody(bodyList);
+                    data1.setCloudCustomData(jsonObject.getString("extra"));
+
+                    list.add(data1);
+                    //导入消息列表
+                    groupImportMessage.setMsgList(list);
+                    try {
+                        imPluginContext.getPluginService().importGroupMessage(groupImportMessage);
+                        //为已导入数据更改标识
+                        updateStatus(i,1);
+                    } catch (Exception e) {
+                        updateStatus(i,2);
+                        log.error("导入群组IM消息失败 msg:{},entity:{}", list, i, e);
+                    }
+                    log.info("导入消息成功:{}", i);
+                }
+            }catch (Exception e) {
+                log.error("导入消息失败:", e);
+                updateStatus(i,2);
+            }
+        }
+    }
+
+    private TencentRequest.MessageBody getTimGifElem(String remoteUr,int size,int width,int height) {
+        if (StringUtils.isEmpty(remoteUr) && size == 0 && width == 0 && height == 0) {
+            return null;
+        }
+
+        // 腾讯云消息
+        // 腾讯云消息
+        //转换url格式
+        String newRemoteUr = urlTypeChange(remoteUr);
+        ImageUtil.ImageInfo imageReq = ImageUtil.ImageInfo.builder()
+                .imgUrl(newRemoteUr)
+                .suffix("GIF")
+                .build();
+
+        // 获取图片基本信息
+        ImageUtil.imageToBase64(imageReq);
+
+        // 图片格式。 JPG = 1 GIF = 2 PNG = 3 BMP = 4 其他 = 255
+        // 图片类型。原图 = 1,大图 = 2,缩略图 = 3
+        int imageFormat = 1;
+        if ("PNG".equalsIgnoreCase(imageReq.getSuffix())) {
+            imageFormat = 3;
+        }
+        if ("GIF".equalsIgnoreCase(imageReq.getSuffix())) {
+            imageFormat = 2;
+        }
+        return TencentRequest.MessageBody.builder()
+                .msgType("TIMImageElem")
+                .msgContent(TencentRequest.ImageMessageBody.builder()
+                        .uuid(imageReq.getMd5())
+                        .imageFormat(imageFormat)
+                        .type(1)
+                        .height(height)
+                        .width(width)
+                        .url(newRemoteUr)
+                        .size(imageReq.getSize()).build())
+                .build();
+
+    }
+
+    /**
+     * 更新已修改数据的状态
+     * @param info
+     */
+    public void updateStatus(HistoryMessage info,int status) {
+        HistoryMessage historyMessage = new HistoryMessage();
+        historyMessage.setStatus(status);
+        historyMessageDao.update(info.getMsgUID(), historyMessage);
+    }
+
+
+    //构造文本请求体
+    public static TencentRequest.MessageBody getTimTextElem(String textMessage) {
+
+        if (StringUtils.isEmpty(textMessage)) {
+            return null;
+        }
+
+        return TencentRequest.MessageBody.builder()
+                .msgType("TIMTextElem")
+                .msgContent(TencentRequest.TextMessageBody.builder().text(textMessage).build())
+                .build();
+    }
+
+
+    //构造图片请求体
+    public static TencentRequest.MessageBody getTimImageElem(String imgMessage) {
+
+
+
+        if (StringUtils.isEmpty(imgMessage)) {
+            return null;
+        }
+
+        // 腾讯云消息
+        // 腾讯云消息
+
+        String newImgMessage = urlTypeChange(imgMessage);
+        ImageUtil.ImageInfo imageReq = ImageUtil.ImageInfo.builder()
+                .imgUrl(newImgMessage)
+                .suffix(newImgMessage.substring(newImgMessage.lastIndexOf(".") + 1))
+                .build();
+
+        // 获取图片基本信息
+        ImageUtil.imageToBase64(imageReq);
+
+        // 图片格式。 JPG = 1 GIF = 2 PNG = 3 BMP = 4 其他 = 255
+        // 图片类型。原图 = 1,大图 = 2,缩略图 = 3
+        int imageFormat = 1;
+        if ("PNG".equalsIgnoreCase(imageReq.getSuffix())) {
+            imageFormat = 3;
+        }
+        if ("GIF".equalsIgnoreCase(imageReq.getSuffix())) {
+            imageFormat = 2;
+        }
+        return TencentRequest.MessageBody.builder()
+                .msgType("TIMImageElem")
+                .msgContent(TencentRequest.ImageMessageBody.builder()
+                        .uuid(imageReq.getMd5())
+                        .imageFormat(imageFormat)
+                        .type(1)
+                        .height(imageReq.getHeight())
+                        .width(imageReq.getWidth())
+                        .url(newImgMessage)
+                        .size(imageReq.getSize()).build())
+                .build();
+    }
+
+
+    //构造语音请求体
+    public static TencentRequest.MessageBody getTimSoundElem(String remoteUrl,int duration) {
+        if (StringUtils.isEmpty(remoteUrl) && duration == 0) {
+            return null;
+        }
+
+        ImHistoryMessageWrapper.TimSoundElem timSoundElem = new ImHistoryMessageWrapper.TimSoundElem();
+
+        String newRemoteUrl = urlTypeChange(remoteUrl);
+        timSoundElem.setUrl(newRemoteUrl);
+        timSoundElem.setUUID(UUID.randomUUID().toString());
+        timSoundElem.setSecond(duration);
+        timSoundElem.setDownload_Flag(2);
+
+        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
+        messageBody.setMsgType("TIMSoundElem");
+        messageBody.setMsgContent(timSoundElem);
+        return  messageBody;
+}
+
+    //构建文件请求体
+    public static TencentRequest.MessageBody getTimFileElem(String fileUrl, String size, String name) {
+        if (StringUtils.isEmpty(fileUrl) && StringUtils.isEmpty(size) &&  StringUtils.isEmpty(name)) {
+            return null;
+        }
+        ImHistoryMessageWrapper.TimFileElem timFileElem = new ImHistoryMessageWrapper.TimFileElem();
+        String newFileUrl = urlTypeChange(fileUrl);
+        timFileElem.setUrl(newFileUrl);
+        timFileElem.setUUID(UUID.randomUUID().toString());
+        timFileElem.setFileName(name);
+        timFileElem.setFileSize(Integer.valueOf(size));
+        timFileElem.setDownload_Flag(2);
+
+        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
+        messageBody.setMsgType("TIMFileElem");
+        messageBody.setMsgContent(timFileElem);
+        return  messageBody;
+    }
+
+    //构建视频请求体
+    public  TencentRequest.MessageBody getTimVideoFileElem(String sightUrl, String size, int duration, String content) throws IOException {
+        if (StringUtils.isEmpty(sightUrl) && StringUtils.isEmpty(sightUrl) && duration == 0) {
+            return null;
+        }
+        ByteArrayInputStream bais = null;
+        String  format = "";
+        //判断是否有前缀
+        if (content.contains(",")){
+            String[] split = content.split(",");
+            String s = split[0];
+            format = s.substring(s.indexOf("/")+ 1,s.indexOf(";"));
+            content = split[1];
+        } else {
+            format = "JPG";
+        }
+
+        byte[] bytes = Base64.getDecoder().decode(content);
+        //构建字节数组输入流
+        bais = new ByteArrayInputStream(bytes);
+
+
+
+        UploadReturnBean uploadReturnBean = uploadFileService.uploadFile(bais, format);
+        String url = uploadReturnBean.getUrl();
+
+        String newUrl = urlTypeChange(url);
+        URL url2 =  new URL(newUrl);
+        BufferedImage read = ImageIO.read(url2);
+        int width = read.getWidth();
+        int height = read.getHeight();
+
+        ImageUtil.ImageInfo imageReq = ImageUtil.ImageInfo.builder()
+                .imgUrl(newUrl)
+                .suffix(format)
+                .build();
+
+        // 获取图片基本信息
+        ImageUtil.imageToBase64(imageReq);
+
+        ImHistoryMessageWrapper.TimVideoFileElem timVideoFileElem = new ImHistoryMessageWrapper.TimVideoFileElem();
+        String newSightUrl = urlTypeChange(sightUrl);
+        timVideoFileElem.setVideoUrl(newSightUrl);
+        timVideoFileElem.setVideoUUID(UUID.randomUUID().toString());
+        timVideoFileElem.setVideoSize(Integer.valueOf(size));
+        timVideoFileElem.setVideoSecond(duration);
+        timVideoFileElem.setVideoFormat("mp4");
+        timVideoFileElem.setVideoDownloadFlag(2);
+        timVideoFileElem.setThumbUrl(newUrl);
+        timVideoFileElem.setThumbUUID(imageReq.getMd5());
+        timVideoFileElem.setThumbWidth( width);
+        timVideoFileElem.setThumbHeight( height);
+        //timVideoFileElem.setThumbSize((imageReq.getSize().intValue()));
+        timVideoFileElem.setThumbDownloadFlag(2);
+        timVideoFileElem.setThumbFormat(format);
+
+        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
+        messageBody.setMsgType("TIMVideoFileElem");
+        messageBody.setMsgContent(timVideoFileElem);
+        return  messageBody;
+    }
+
+    //构建位置请求体
+    private TencentRequest.MessageBody getTimLocationElem(double latitude, double longitude, String poi) {
+        if (latitude == 0 && longitude == 0 &&  StringUtils.isEmpty(poi)) {
+            return null;
+        }
+        ImHistoryMessageWrapper.TimLocationElem timLocationElem = new ImHistoryMessageWrapper.TimLocationElem();
+        timLocationElem.setDesc(poi);
+        timLocationElem.setLatitude(latitude);
+        timLocationElem.setLongitude(longitude);
+
+        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
+        messageBody.setMsgType("TIMLocationElem");
+        messageBody.setMsgContent(timLocationElem);
+        return  messageBody;
+    }
+
+
+    //构建合并转发请求体
+    private TencentRequest.MessageBody getTimRelayElem() {
+        ImHistoryMessageWrapper.TimRelayElem timRelayElem = new ImHistoryMessageWrapper.TimRelayElem();
+        //todo
+        //timRelayElem.setMsgNum();
+
+        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
+        messageBody.setMsgType("TIMRelayElem");
+        messageBody.setMsgContent(timRelayElem);
+        return  messageBody;
+    }
+
+
+
+    //url路径改造
+    private static String urlTypeChange(String url){
+        if (url.isEmpty()){
+            throw new BizException("链接地址为空!!!");
+        }
+        String replace;
+        if (url.startsWith("https://ks3-cn-beijing.ksyuncs.com")){
+             replace = url.replace("https://ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com");
+        } else if (url.startsWith("https://daya.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://daya.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/daya");
+        } else if (url.startsWith("https://appstore.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://appstore.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/appstore");
+        } else if (url.startsWith("https://cloud-coach.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://cloud-coach.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/cloud-coach");
+        } else if (url.startsWith("https://contracts.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://contracts.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/contracts");
+        } else if (url.startsWith("https://cooperation.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://cooperation.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/cooperation");
+        } else if (url.startsWith("https://daya-docs.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://daya-docs.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/daya-docs");
+        } else if (url.startsWith("https://gyt.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://gyt.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/gyt");
+        } else if (url.startsWith("https://homework.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://homework.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/homework");
+        } else if (url.startsWith("https://i-m.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://i-m.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/i-m");
+        } else if (url.startsWith("https://live-rewind.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://live-rewind.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/live-rewind");
+        } else if (url.startsWith("https://mall.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://mall.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/mall");
+        } else if (url.startsWith("https://musescoreconverresult.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://musescoreconverresult.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/musescoreconverresult");
+        } else if (url.startsWith("https://news-info.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://news-info.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/news-info");
+        } else if (url.startsWith("https://question-bank.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://question-bank.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/question-bank");
+        } else if (url.startsWith("https://video-course.ks3-cn-beijing.ksyuncs.com")){
+            replace = url.replace("https://video-course.ks3-cn-beijing.ksyuncs.com", "https://oss.dayaedu.com/video-course");
+        } else {
+            return url;
+        }
+        return replace;
+    }
+
+
 }

+ 37 - 20
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java

@@ -35,6 +35,7 @@ import com.ym.mec.biz.dal.page.LiveRoomGoodsOrderQueryInfo;
 import com.ym.mec.biz.dal.vo.*;
 import com.ym.mec.biz.redisson.RedissonMessageService;
 import com.ym.mec.biz.service.*;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
 import com.ym.mec.common.entity.ImRoomMessage;
 import com.ym.mec.common.entity.ImUserState;
 import com.ym.mec.common.exception.BizException;
@@ -130,6 +131,13 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
     @Autowired
     private CourseScheduleDao courseScheduleDao;
 
+    @Autowired
+    private  ImGroupService imGroupService;
+
+    @Autowired
+    private ImGroupCoreService imGroupCoreService;
+
+
     //待替换的变量
     public static final String USER_ID = "${userId}";
     public static final String ROOM_UID = "${roomUid}";
@@ -238,7 +246,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         String userSig = "";
         try {
             // 生成聊天签名
-            userSig = pluginService.register(userInfo.getUserId().toString(), userInfo.getUserName(), userInfo.getAvatar());
+            userSig = pluginService.register(imGroupCoreService.getImUserId(userInfo.getUserId().toString(),SysUserType.VISITOR.getCode()), userInfo.getUserName(), userInfo.getAvatar());
 
         } catch (Exception e) {
             log.error("直播房间游客注册失败: userId={}", userInfo.getUserId(), e);
@@ -263,7 +271,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         if (vo.getLiveState() == 0) {
             throw new BizException("直播尚未开始");
         }
-        return queryRoomAndCheck(vo, sysUser);
+        return queryRoomAndCheck(vo, sysUser,SysUserType.STUDENT);
     }
 
     public ImLiveBroadcastRoomVo teacherQueryRoomAndCheck(String roomUid, SysUser sysUser) {
@@ -272,16 +280,16 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         if (vo.getOs().equals("pc")) {
             throw new BizException("该直播间仅可在移动端直播");
         }
-        return queryRoomAndCheck(vo, sysUser);
+        return queryRoomAndCheck(vo, sysUser, SysUserType.TEACHER);
     }
 
     public ImLiveBroadcastRoomVo queryRoomAndCheck(String roomUid, SysUser sysUser) {
         ImLiveBroadcastRoomVo vo = Optional.ofNullable(roomUid).map(this::queryRoomInfo)
                 .orElseThrow(() -> new BizException("直播间不存在"));
-        return queryRoomAndCheck(vo, sysUser);
+        return queryRoomAndCheck(vo, sysUser,vo.getClientType());
     }
 
-    public ImLiveBroadcastRoomVo queryRoomAndCheck(ImLiveBroadcastRoomVo room, SysUser sysUser) {
+    public ImLiveBroadcastRoomVo queryRoomAndCheck(ImLiveBroadcastRoomVo room, SysUser sysUser,SysUserType sysUserType) {
 
         //直播间信息校验
         if (!room.getTenantId().equals(sysUser.getTenantId())) {
@@ -317,7 +325,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         // 直播房间配置信息
         String userSig = "";
         try {
-            userSig = pluginService.register(String.valueOf(sysUser.getId()), sysUser.getUsername(),
+
+            userSig = pluginService.register(imGroupCoreService.getImUserId(String.valueOf(sysUser.getId()),sysUserType.getCode()), sysUser.getUsername(),
                     sysUser.getAvatar());
         } catch (Exception e) {
             log.error("直播房间用户注册失败: userId={}", sysUser.getId(), e);
@@ -728,7 +737,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 
             // 发送用户信息
             LiveRoomMessage.MessageUser messageUser = LiveRoomMessage.MessageUser.builder()
-                    .sendUserId(String.valueOf(room.getSpeakerId()))
+                    .sendUserId(imGroupCoreService.getImUserId(String.valueOf(room.getSpeakerId()),room.getClientType().getCode()))
                     .sendUserName(sysUser.getUsername())
                     .avatarUrl(sysUser.getAvatar())
                     .build();
@@ -795,11 +804,11 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 
 
             TencentWrapper.LiveStreamState liveStreamState = pluginService.liveStreamState(
-                getStreamId(room.getRoomUid(), room.getSpeakerId()));
+                getStreamId(room.getRoomUid(),Integer.parseInt(imGroupCoreService.getImUserId(String.valueOf(room.getSpeakerId()),room.getClientType().getCode()))));
             if (liveStreamState == null) {
                 log.error("查询直播间流失败,返回结果为空");
             } else if ("active".equals(liveStreamState.getStreamState())) {
-                pluginService.liveStreamStop(getStreamId(room.getRoomUid(), room.getSpeakerId()));
+                pluginService.liveStreamStop(getStreamId(room.getRoomUid(), Integer.parseInt(imGroupCoreService.getImUserId(String.valueOf(room.getSpeakerId()),room.getClientType().getCode()))));
             }
 
             // 录制任务Id
@@ -1161,7 +1170,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         LiveRoomMessage message = LiveRoomMessage.builder()
                 .isIncludeSender(1)
                 .objectName(LiveRoomMessage.LOOKER_LOGIN_OUT)
-                .fromUserId(fromUserId)
+                .fromUserId(imGroupCoreService.getImUserId(fromUserId,roomVo.getClientType().getCode()))
                 .toChatRoomId(roomVo.getRoomUid())
                 .content(messageContent)
                 .build();
@@ -1961,7 +1970,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                     RTCRoom.RecordResp recordResp = pluginService.rtcRoomRecordStart(RTCRequest.RecordStart.builder()
                            .startTime(dateTime.getMillis() )
                            .endTime(dateTime.plusDays(1).getMillis() )
-                           .streamName(MessageFormat.format("{0}_{1}", imLiveBroadcastRoomVo.getRoomUid(), String.valueOf(imLiveBroadcastRoomVo.getSpeakerId())))
+                           .streamName(MessageFormat.format("{0}_{1}", imLiveBroadcastRoomVo.getRoomUid(), imGroupCoreService.getImUserId(String.valueOf(imLiveBroadcastRoomVo.getSpeakerId()),imLiveBroadcastRoomVo.getClientType().getCode())))
                            .build());
                     roomSpeakerInfo.setVideoTemplate(1);
 
@@ -2036,7 +2045,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         LivePluginService pluginService = livePluginContext.getPluginService(imLiveBroadcastRoomVo.getServiceProvider());
         if (StringUtils.isBlank(sequence)) {
             try {
-                TencentWrapper.LiveStreamState liveStreamState = pluginService.liveStreamState(getStreamId(imLiveBroadcastRoomVo.getRoomUid(), imLiveBroadcastRoomVo.getSpeakerId()));
+                TencentWrapper.LiveStreamState liveStreamState = pluginService.liveStreamState(getStreamId(imLiveBroadcastRoomVo.getRoomUid(), Integer.parseInt(imGroupCoreService.getImUserId(String.valueOf(imLiveBroadcastRoomVo.getSpeakerId()),imLiveBroadcastRoomVo.getClientType().getCode()))));
                 if (liveStreamState == null) {
                     log.error("查询直播间流失败,返回结果为空");
                 } else {
@@ -2258,9 +2267,10 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                 LivePluginService pluginService = livePluginContext.getPluginService(room.getServiceProvider());
 
                 // 注册主播用户信息到三方平台
-                pluginService.register(sysUser.getId().toString(), sysUser.getUsername(), sysUser.getAvatar());
+
+                pluginService.register(imGroupCoreService.getImUserId(sysUser.getId().toString(),room.getClientType().getCode()), sysUser.getUsername(), sysUser.getAvatar());
                 // 创建直播间IM群
-                pluginService.chatRoomCreate(room.getRoomUid(), room.getRoomTitle(),sysUser.getId().toString());
+                pluginService.chatRoomCreate(room.getRoomUid(), room.getRoomTitle(),imGroupCoreService.getImUserId(sysUser.getId().toString(),room.getClientType().getCode()));
 
                 createSpeakerInfo(room, sysUser);
                 Boolean whetherVideoFlag = getRoomConfig(room.getRoomConfig()).map(o -> o.getWhether_video() == 0).orElse(true);
@@ -2271,7 +2281,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                     DateTime now = DateTime.now();
 
                     RTCRequest.RecordStart recordStart = RTCRequest.RecordStart.builder()
-                                                   .streamName(MessageFormat.format("{0}_{1}", room.getRoomUid(), room.getSpeakerId().toString()))
+                                                   .streamName(MessageFormat.format("{0}_{1}", room.getRoomUid(), imGroupCoreService.getImUserId(room.getSpeakerId().toString(),room.getClientType().getCode())))
                                                    .extra("")
                                                    .startTime(now.toDateTime().getMillis())
                                                    .endTime(now.plusDays(1).toDateTime().getMillis())
@@ -2845,8 +2855,11 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             imUserState.setRoomUid(callbackOnMemberStateChange.getGroupId());
             imUserStates.add(imUserState);
         }
-        opsRoom(imUserStates);
         liveBroadcastRoomMemberDao.updateOnlineStatus(userIds, callbackOnMemberStateChange.getGroupId(),onlineStatus);
+        CompletableFuture.runAsync(() -> {
+            opsRoom(imUserStates);
+        });
+
     }
 
     @Override
@@ -2878,8 +2891,10 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             imUserState.setRoomUid(callbackAfterMemberExit.getGroupId());
             imUserStates.add(imUserState);
         }
-        opsRoom(imUserStates);
         liveBroadcastRoomMemberDao.updateLiveRoomStatus(userIds, callbackAfterMemberExit.getGroupId(),liveRoomStatus);
+        CompletableFuture.runAsync(() -> {
+            opsRoom(imUserStates);
+        });
     }
 
     @Override
@@ -2922,8 +2937,10 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             imUserState.setRoomUid(callbackAfterNewMemberJoin.getGroupId());
             imUserStates.add(imUserState);
         }
-        opsRoom(imUserStates);
         liveBroadcastRoomMemberDao.updateLiveRoomStatus(userIds, callbackAfterNewMemberJoin.getGroupId(),liveRoomStatus);
+        CompletableFuture.runAsync(() -> {
+            opsRoom(imUserStates);
+        });
     }
 
     @Override
@@ -2953,7 +2970,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
             }
             if (pluginService.pluginName().equals(TencentCloudLivePlugin.PLUGIN_NAME)) {
                 TencentWrapper.LiveStreamState liveStreamState = pluginService.liveStreamState(
-                    getStreamId(imLiveBroadcastRoom.getRoomUid(), imLiveBroadcastRoom.getSpeakerId()));
+                    getStreamId(imLiveBroadcastRoom.getRoomUid(), Integer.parseInt(imGroupCoreService.getImUserId(String.valueOf(imLiveBroadcastRoom.getSpeakerId()),imLiveBroadcastRoom.getClientType().getCode()))));
                 if (liveStreamState == null) {
                     log.error("查询直播间流失败,返回结果为空");
                     return false;
@@ -3098,7 +3115,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
         try {
             LivePluginService pluginService = livePluginContext.getPluginService(roomVo.getServiceProvider());
 
-            liveStreamState = pluginService.liveStreamState(getStreamId(roomUid, roomVo.getSpeakerId()));
+            liveStreamState = pluginService.liveStreamState(getStreamId(roomUid, Integer.parseInt(imGroupCoreService.getImUserId(String.valueOf(roomVo.getSpeakerId()),roomVo.getClientType().getCode()))));
         } catch (Exception e) {
             log.error("roomLiveStreamStatus roomUid={}", roomUid, e);
         }

+ 27 - 6
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImUserFriendServiceImpl.java

@@ -13,6 +13,7 @@ import com.ym.mec.biz.dal.enums.school.ESchoolStaffType;
 import com.ym.mec.biz.dal.mapper.SchoolStaffMapper;
 import com.ym.mec.biz.dal.wrapper.ImGroupWrapper;
 import com.ym.mec.biz.service.TeacherService;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
 import com.ym.mec.util.collection.MapUtil;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -63,6 +64,9 @@ public class ImUserFriendServiceImpl extends BaseServiceImpl<Long, ImUserFriend>
     @Autowired
     private ImGroupMemberDao imGroupMemberDao;
 
+    @Autowired
+    private ImGroupCoreService imGroupCoreService;
+
     @Override
     public BaseDAO<Long, ImUserFriend> getDAO() {
         return imUserFriendDao;
@@ -119,15 +123,25 @@ public class ImUserFriendServiceImpl extends BaseServiceImpl<Long, ImUserFriend>
     public List<ImUserFriendDto> queryFriendListByUserId(Integer userId, String search) {
         String syncImUserFriendKey = "syncImUserFriend:" + userId;
         if(redisTemplate.hasKey(syncImUserFriendKey)){
-            return imUserFriendDao.queryFriendListByUserId(userId, search);
+            List<ImUserFriendDto> imUserFriendDtoList = imUserFriendDao.queryFriendListByUserId(userId, search);
+            imUserFriendDtoList.stream().forEach(i->{
+                i.setImUserId(imGroupCoreService.getImUserId(String.valueOf(i.getUserId()),""));
+            });
+            return imUserFriendDtoList;
         }else {
-            return teacherService.queryGroupStudents1(userId,null);
+            List<ImUserFriendDto> imUserFriendDtoList = teacherService.queryGroupStudents1(userId, null);
+            imUserFriendDtoList.stream().forEach(i->{
+                i.setImUserId(imGroupCoreService.getImUserId(String.valueOf(i.getUserId()),""));
+            });
+            return imUserFriendDtoList;
         }
     }
 
     @Override
     public ImUserFriendDto queryFriendDetail(Integer userId, Integer friendUserId) {
-        return imUserFriendDao.queryFriendDetail(userId, friendUserId);
+        ImUserFriendDto imUserFriendDto = imUserFriendDao.queryFriendDetail(userId, friendUserId);
+        imUserFriendDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imUserFriendDto.getUserId()),""));
+        return imUserFriendDto;
     }
 
     @Override
@@ -280,7 +294,11 @@ public class ImUserFriendServiceImpl extends BaseServiceImpl<Long, ImUserFriend>
     @Override
     public List<ImUserFriendDto> queryFriendListByUserIdV2(Integer userId, String search, String musicGroupId, Integer subjectId, Boolean vipFlag) {
         // 逻辑过于复杂 拿出数据后筛选
-        return imUserFriendDao.queryFriendListByUserIdV2(userId, search,musicGroupId,subjectId,vipFlag);
+        List<ImUserFriendDto> imUserFriendDtoList = imUserFriendDao.queryFriendListByUserIdV2(userId, search, musicGroupId, subjectId, vipFlag);
+        imUserFriendDtoList.stream().forEach(i->{
+            i.setImUserId(imGroupCoreService.getImUserId(String.valueOf(i.getUserId()),""));
+        });
+        return imUserFriendDtoList;
 
     }
 
@@ -319,8 +337,11 @@ public class ImUserFriendServiceImpl extends BaseServiceImpl<Long, ImUserFriend>
             query.setUserIds(userIds);
             query.setMusicGroupId(null);
         }
-
-        return imUserFriendDao.getFriendListByUserId(query);
+        List<ImUserFriendDto> friendListByUserId = imUserFriendDao.getFriendListByUserId(query);
+        friendListByUserId.stream().forEach(f->{
+            f.setImUserId(imGroupCoreService.getImUserId(String.valueOf(f.getUserId()),""));
+        });
+        return friendListByUserId;
 
     }
 

+ 23 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentManageServiceImpl.java

@@ -1,6 +1,7 @@
 package com.ym.mec.biz.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.google.common.collect.Lists;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.*;
@@ -10,8 +11,10 @@ import com.ym.mec.biz.dal.enums.CourseStatusEnum;
 import com.ym.mec.biz.dal.enums.StudentMusicGroupStatusEnum;
 import com.ym.mec.biz.dal.enums.SysUserRoleEnum;
 import com.ym.mec.biz.dal.enums.YesOrNoEnum;
+import com.ym.mec.biz.dal.enums.im.ClientEnum;
 import com.ym.mec.biz.dal.page.*;
 import com.ym.mec.biz.service.*;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
 import com.ym.mec.common.entity.ImResult;
 import com.ym.mec.common.entity.ImUserModel;
 import com.ym.mec.common.exception.BizException;
@@ -21,6 +24,7 @@ import com.ym.mec.im.ImFeignService;
 import com.ym.mec.util.collection.MapUtil;
 import com.ym.mec.util.date.DateUtil;
 import com.ym.mec.web.WebFeignService;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@@ -39,6 +43,7 @@ import java.util.stream.Collectors;
  * @Author Joburgess
  * @Date 2019/9/19
  */
+@Slf4j
 @Service
 public class StudentManageServiceImpl implements StudentManageService {
 
@@ -111,6 +116,8 @@ public class StudentManageServiceImpl implements StudentManageService {
 
     @Autowired
     private ImGroupDao imGroupDao;
+    @Autowired
+    private ImGroupCoreService imGroupCoreService;
 
     @Override
     public PageInfo<StudentManageListDto> findStudentsByOrganId(StudentManageQueryInfo queryInfo) {
@@ -744,6 +751,22 @@ public class StudentManageServiceImpl implements StudentManageService {
             Optional.ofNullable(sysUser.getSubjectId()).ifPresent(student::setSubjectIdList);
             studentDao.update(student);
         }
+
+        // 用户更新信息同步到三方
+        SysUser userInfo = teacherDao.getUser(sysUser.getId());
+        if (Objects.nonNull(userInfo)) {
+
+            try {
+                String username = userInfo.getUsername();
+                if (Lists.newArrayList(userInfo.getUserType().split(",")).contains(ClientEnum.TEACHER.getCode())) {
+                    username = Optional.ofNullable(userInfo.getRealName()).orElse(username);
+                }
+
+                imGroupCoreService.register(String.valueOf(userInfo.getId()), "", username, userInfo.getAvatar());
+            } catch (Exception e) {
+                log.error("用户更新信息同步到三方失败,userId:{}", userInfo.getId(), e);
+            }
+        }
     }
 
 

+ 41 - 0
mec-biz/src/main/resources/config/mybatis/ImGroupMapper.xml

@@ -19,6 +19,7 @@
 		<result column="create_time_" property="createTime" />
 		<result column="update_time_" property="updateTime" />
         <result column="tenant_id_" property="tenantId"/>
+        <result column="import_flag_" property="importFlag"/>
 	</resultMap>
 	
 	<resultMap type="com.ym.mec.biz.dal.dto.ImGroupMemberDto" id="ImGroupMemberDto">
@@ -125,6 +126,9 @@
 			<if test="groupType != null">
 				AND ig.group_type_ = #{groupType}
 			</if>
+			<if test="importFlag != null">
+				AND ig.import_flag_ = #{importFlag}
+			</if>
 		</where>
 	</sql>
 	
@@ -288,8 +292,45 @@
             and ig.group_type_ = #{param.groupType.code}
         </if>
     </select>
+    <select id="queryInfoCount" resultType="java.lang.Integer">
+		SELECT COUNT(*) FROM im_history_message
+	</select>
+	<select id="selectAll" resultType="com.ym.mec.biz.dal.entity.ImHistoryMessage">
+		select msgUID_          AS msgUID,
+			   fromUserId_      AS fromUserId,
+			   targetId_        AS targetId,
+			   targetType_      AS targetType,
+			   GroupId_         AS groupId,
+			   busChannel_      AS busChannel,
+			   classname_       AS classname,
+			   content_         AS content,
+			   extraContent_    AS extraContent,
+			   dateTime_        AS dateTime,
+			   source_          AS source,
+			   isDiscard_       AS isDiscard,
+			   isSensitiveWord_ AS isSensitiveWord,
+			   isForbidden_     AS isForbidden,
+			   isNotForward_    AS isNotForward,
+			   groupUserIds_    AS groupUserIds,
+			   appId_           AS appId
+
+		from im_history_message
+		limit #{result},#{size}
+
+	</select>
 
 	<update id="updateSchoolRoleType">
         update im_group_member set role_type_ = #{userType.msg} ,type_ = #{userType.name}  where user_id_ = #{userId}
     </update>
+
+	<update id="updateImportStatusSuccess">
+		update im_group set import_flag_ = 1
+		where id_ = #{id}
+	</update>
+	<update id="updateStatus">
+		update im_history_message set status_ = 1
+		where msgUID in <foreach collection="info" open="(" close=")" separator="," item="info">
+		#{info.msgUID}
+	</foreach>
+	</update>
 </mapper>

+ 2 - 1
mec-biz/src/main/resources/config/mybatis/ImGroupMemberMapper.xml

@@ -17,6 +17,7 @@
 		<result column="create_time_" property="createTime" />
 		<result column="update_time_" property="updateTime" />
         <result column="tenant_id_" property="tenantId"/>
+        <result column="avatar_" property="avatar"/>
 	</resultMap>
 	
 	<!-- 根据主键查询一条记录 -->
@@ -140,7 +141,7 @@
 	</select>
     <select id="queryMembers" resultMap="ImGroupMember">
 		SELECT #{groupId} im_group_id_,CASE WHEN su.username_ IS NULL OR su.username_ = '' THEN su.real_name_ ELSE su.username_ END nickname_,
-		       #{tenantId} tenant_id_,su.id_ user_id_
+		       #{tenantId} tenant_id_,su.id_ user_id_,su.avatar_
 		FROM sys_user su
 		WHERE su.id_ IN
 		<foreach collection="userIdList" item="item" open="(" separator="," close=")">

+ 4 - 0
mec-biz/src/main/resources/config/mybatis/TeacherMapper.xml

@@ -1570,5 +1570,9 @@
             #{phone}
         </foreach>
     </select>
+    <select id="getBasicUserInfo" resultType="com.ym.mec.biz.dal.dto.im.BasicUserInfo">
+        SELECT id_ user_id_,username_,real_name_,avatar_,user_type_ FROM sys_user
+        WHERE id_ = #{userId} LIMIT 1
+    </select>
 
 </mapper>

+ 22 - 1
mec-client-api/src/main/java/com/ym/mec/im/ImFeignService.java

@@ -25,6 +25,14 @@ public interface ImFeignService {
     ImResult register(@RequestBody ImUserModel userModel);
 
     /**
+     * IM用户Token信息
+     * @param userModel ImUserModel
+     * @return ImUserModel.ImUserResult
+     */
+    @PostMapping(value = "user/userImTokenInfo", consumes = MediaType.APPLICATION_JSON_VALUE)
+    ImUserModel.ImUserResult userImTokenInfo(@RequestBody ImUserModel userModel);
+
+    /**
      * 用户信息修改
      *
      * @param userModel
@@ -39,6 +47,7 @@ public interface ImFeignService {
      * @param groupModel
      * @return
      */
+    @Deprecated
     @PostMapping(value = "group/create")
     Object groupCreate(@RequestBody GroupModel groupModel);
 
@@ -48,6 +57,7 @@ public interface ImFeignService {
      * @param groupModel
      * @return
      */
+    @Deprecated
     @PostMapping(value = "group/update")
     Object groupUpdate(@RequestBody GroupModel groupModel);
 
@@ -57,6 +67,7 @@ public interface ImFeignService {
      * @param groupModels
      * @return
      */
+    @Deprecated
     @PostMapping(value = "group/batchCreate")
     void groupBatchCreate(@RequestBody List<GroupModel> groupModels);
 
@@ -93,6 +104,7 @@ public interface ImFeignService {
      * @param groupModel
      * @return
      */
+    @Deprecated
     @PostMapping(value = "group/dismiss")
     Object groupDismiss(@RequestBody GroupModel groupModel);
 
@@ -102,6 +114,7 @@ public interface ImFeignService {
      * @param groupModels
      * @return
      */
+    @Deprecated
     @PostMapping(value = "group/batchDismiss")
     Object groupBatchDismiss(@RequestBody List<ImGroupModel> groupModels);
 
@@ -117,7 +130,7 @@ public interface ImFeignService {
     /**
      * 发送私聊消息
      *
-     * @param privateMessage
+     * @param imMessageDto ImMessageDto
      * @return
      */
     @PostMapping(value = "private/send")
@@ -141,6 +154,7 @@ public interface ImFeignService {
      * @param roomId   直播间uid
      * @param roomName 直播间名称
      */
+    @Deprecated
     @PostMapping(value = "/liveRoom/create")
     Object createLiveRoom(@RequestParam("roomId") String roomId, @RequestParam("roomName") String roomName);
 
@@ -149,6 +163,7 @@ public interface ImFeignService {
      *
      * @param roomId 直播间uid
      */
+    @Deprecated
     @PostMapping(value = "/liveRoom/destroy")
     Object destroyLiveRoom(@RequestParam("roomId") String roomId);
 
@@ -169,12 +184,14 @@ public interface ImFeignService {
      * @author zx
      * @date 2022/2/25 13:52
      */
+    @Deprecated
     @PostMapping(value = "/liveRoom/stopRecord")
     void stopRecord(@RequestParam("roomId") String roomId);
 
     /**
      * 向直播间发送文本消息
      */
+    @Deprecated
     @PostMapping(value = "/liveRoom/publishRoomMsg", consumes = MediaType.APPLICATION_JSON_VALUE)
     Object publishRoomMsg(@RequestBody ImRoomMessage message);
 
@@ -185,6 +202,7 @@ public interface ImFeignService {
      * @param userId     要查询的用户 ID(必传)
      * @return true 在聊天室,false 不在聊天室
      */
+    @Deprecated
     @PostMapping(value = "/liveRoom/userExistInRoom")
     boolean userExistInRoom(@RequestParam("chatroomId") String chatroomId, @RequestParam("userId") String userId);
 
@@ -195,6 +213,7 @@ public interface ImFeignService {
      * @param userId 要查询的用户 ID(必传)
      * @return 在线状态,true 在线,false 不在线
      */
+    @Deprecated
     @PostMapping(value = "/liveRoom/checkOnline")
     boolean checkOnline(@RequestParam("userId") String userId);
 
@@ -204,6 +223,7 @@ public interface ImFeignService {
      * @param roomUid 房间uid
      * @param userId  用户id
      */
+    @Deprecated
     @PostMapping(value ="/liveRoom/addUserUnableSpeak")
     boolean addUserUnableSpeak(@RequestParam("roomUid") String roomUid, @RequestParam("userId") String userId);
 
@@ -213,6 +233,7 @@ public interface ImFeignService {
      * @param roomUid 房间uid
      * @param userId  用户id
      */
+    @Deprecated
     @PostMapping(value ="/liveRoom/removeUserUnableSpeak")
     boolean removeUserUnableSpeak(@RequestParam("roomUid") String roomUid, @RequestParam("userId") String userId);
 

+ 11 - 0
mec-client-api/src/main/java/com/ym/mec/im/fallback/ImFeignServiceFallback.java

@@ -15,6 +15,17 @@ public class ImFeignServiceFallback implements ImFeignService {
         return null;
     }
 
+    /**
+     * IM用户Token信息
+     *
+     * @param userModel ImUserModel
+     * @return ImUserModel.ImUserResult
+     */
+    @Override
+    public ImUserModel.ImUserResult userImTokenInfo(ImUserModel userModel) {
+        return null;
+    }
+
     @Override
     public void update(ImUserModel userModel) {
 

+ 4 - 1
mec-client-api/src/main/java/com/ym/mec/task/TaskRemoteService.java

@@ -5,7 +5,10 @@ import com.ym.mec.task.fallback.TaskRemoteServiceFallback;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 
-@FeignClient(name = "web-server", contextId = "TaskRemoteService", configuration = {FeignConfiguration.class}, fallback = TaskRemoteServiceFallback.class)
+@FeignClient(name = "${app-config.open-feign.web-server.name:web-server}",
+        contextId = "TaskRemoteService",
+        url = "${app-config.open-feign.web-server.url:}",
+        configuration = {FeignConfiguration.class}, fallback = TaskRemoteServiceFallback.class)
 public interface TaskRemoteService {
 
     @GetMapping(value = "task/pushWaitSendMessageTask")

+ 4 - 1
mec-client-api/src/main/java/com/ym/mec/web/WebFeignService.java

@@ -16,7 +16,10 @@ import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
-@FeignClient(name = "web-server", contextId = "WebFeignService", configuration = FeignConfiguration.class, fallback = WebFeignServiceFallback.class)
+@FeignClient(name = "${app-config.open-feign.web-server.name:web-server}",
+		contextId = "WebFeignService",
+		url = "${app-config.open-feign.web-server.url:}",
+		configuration = FeignConfiguration.class, fallback = WebFeignServiceFallback.class)
 public interface WebFeignService {
 
 	@RequestMapping(value = "api/createCashAccount")

+ 8 - 0
mec-common/audit-log/src/main/java/com/yonge/log/dal/model/HistoryMessage.java

@@ -1,11 +1,13 @@
 package com.yonge.log.dal.model;
 
+import lombok.Data;
 import org.springframework.data.annotation.Id;
 import org.springframework.data.mongodb.core.mapping.Document;
 
 import java.io.Serializable;
 import java.util.Objects;
 
+@Data
 @Document(collection = "im_history_message")
 public class HistoryMessage implements Serializable {
     @Id
@@ -37,6 +39,12 @@ public class HistoryMessage implements Serializable {
 
     private String content;
 
+    private Integer status;
+
+    private String appId;
+
+    private String busChannel;
+
     public String getFromUserId() {
         return fromUserId;
     }

+ 6 - 0
mec-common/audit-log/src/main/java/com/yonge/log/service/HistoryMessageService.java

@@ -1,9 +1,11 @@
 package com.yonge.log.service;
 
 import com.yonge.log.dal.model.HistoryMessage;
+import com.yonge.mongodb.PageInfo;
 import com.yonge.mongodb.service.BaseServiceWithMongo;
 
 import java.io.File;
+import java.util.Date;
 
 public interface HistoryMessageService extends BaseServiceWithMongo<String, HistoryMessage> {
 
@@ -13,4 +15,8 @@ public interface HistoryMessageService extends BaseServiceWithMongo<String, Hist
      * @throws Exception
      */
     void saveImHistoryMessage(File file) throws Exception;
+
+    long selectCount(int status, Date date);
+
+    PageInfo<HistoryMessage> selectPage(int page, int size, int status, Date date);
 }

+ 51 - 4
mec-common/audit-log/src/main/java/com/yonge/log/service/impl/HistoryMessageServiceImpl.java

@@ -4,16 +4,27 @@ import com.alibaba.fastjson.JSONObject;
 import com.yonge.log.dal.dao.HistoryMessageDao;
 import com.yonge.log.dal.model.HistoryMessage;
 import com.yonge.log.service.HistoryMessageService;
+import com.yonge.mongodb.PageInfo;
 import com.yonge.mongodb.dao.BaseDaoWithMongo;
 import com.yonge.mongodb.service.impl.BaseServiceImplWithMongo;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.stereotype.Service;
 
-import java.io.*;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
@@ -25,6 +36,9 @@ public class HistoryMessageServiceImpl extends BaseServiceImplWithMongo<String,
 	@Autowired
 	private HistoryMessageDao historyMessageDao;
 
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
 	@Override
 	public BaseDaoWithMongo<String, HistoryMessage> getDAO() {
 		return historyMessageDao;
@@ -40,6 +54,39 @@ public class HistoryMessageServiceImpl extends BaseServiceImplWithMongo<String,
 //		}
 	}
 
+    @Override
+    public long selectCount(int status, Date date) {
+        Query query = new Query();
+
+        // 查询status 为null or 0
+        // 查询时间大于date
+        Criteria criteria = Criteria.where("dateTime").gt(date).orOperator(Criteria.where("status").is(0),Criteria.where("status").is(null));
+        query.addCriteria(criteria);
+        return mongoTemplate.count(query,HistoryMessage.class);
+    }
+
+    @Override
+    public PageInfo<HistoryMessage> selectPage(int page, int size, int status, Date date) {
+        PageInfo<HistoryMessage> pageInfo = new PageInfo<HistoryMessage>(page, size);
+
+        List<HistoryMessage> dataList = null;
+        long total = this.selectCount(status,date);
+        if (total > 0) {
+            pageInfo.setTotal(total);
+
+            Query query = new Query();
+            Criteria criteria = Criteria.where("dateTime").gt(date).orOperator(Criteria.where("status").is(0),Criteria.where("status").is(null));
+            query.addCriteria(criteria);
+            query.skip(pageInfo.getOffset()).limit(pageInfo.getLimit());
+            dataList = mongoTemplate.find(query, HistoryMessage.class);
+        }
+        if (total == 0) {
+            dataList = new ArrayList<>();
+        }
+        pageInfo.setRows(dataList);
+        return pageInfo;
+    }
+
 //	public static void main(String[] args) throws Exception {
 //		doNioReadFile1(new File("/Users/chenxiaoyu/Documents/77fe9ce6-7d91-4568-afe3-9e8ac351e87f.zip"));
 //	}

+ 16 - 20
mec-common/common-core/pom.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <project
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
-	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+		xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+		xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
 		<groupId>com.ym</groupId>
@@ -13,7 +13,8 @@
 	<url>http://maven.apache.org</url>
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <mybatis-plus.version>3.0.7.1</mybatis-plus.version>
+		<mybatis-plus.version>3.0.7.1</mybatis-plus.version>
+		<redisson.version>3.16.4</redisson.version>
 	</properties>
 
 	<dependencies>
@@ -25,14 +26,9 @@
 
 		<!-- Redis缓存整合开始 -->
 		<dependency>
-			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-data-redis</artifactId>
-			<exclusions>
-				<exclusion>
-					<groupId>io.lettuce</groupId>
-					<artifactId>lettuce-core</artifactId>
-				</exclusion>
-			</exclusions>
+			<groupId>org.redisson</groupId>
+			<artifactId>redisson-spring-boot-starter</artifactId>
+			<version>${redisson.version}</version>
 		</dependency>
 		<!-- Redis缓存整合结束 -->
 
@@ -50,17 +46,17 @@
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-websocket</artifactId>
 		</dependency>
-		
+
 		<dependency>
 			<groupId>com.ym</groupId>
 			<artifactId>mec-thirdparty</artifactId>
 		</dependency>
-		
+
 		<dependency>
 			<groupId>redis.clients</groupId>
 			<artifactId>jedis</artifactId>
 		</dependency>
-		
+
 		<dependency>
 			<groupId>org.springframework.security.oauth</groupId>
 			<artifactId>spring-security-oauth2</artifactId>
@@ -79,11 +75,11 @@
 			<version>2.4.1</version>
 		</dependency>
 
-        <!--mybatis plus-->
-        <dependency>
-            <groupId>com.baomidou</groupId>
-            <artifactId>mybatis-plus-boot-starter</artifactId>
-            <version>${mybatis-plus.version}</version>
-        </dependency>
+		<!--mybatis plus-->
+		<dependency>
+			<groupId>com.baomidou</groupId>
+			<artifactId>mybatis-plus-boot-starter</artifactId>
+			<version>${mybatis-plus.version}</version>
+		</dependency>
 	</dependencies>
 </project>

+ 49 - 0
mec-common/common-core/src/main/java/com/ym/mec/common/entity/ImUserModel.java

@@ -2,6 +2,8 @@ package com.ym.mec.common.entity;
 
 import org.apache.commons.lang3.StringUtils;
 
+import java.io.Serializable;
+
 public class ImUserModel {
     public String id;
 
@@ -15,6 +17,11 @@ public class ImUserModel {
 
     private ImUserModel[] blacklist;
 
+    // 用户身份
+    private String clientType;
+    // 用户头象
+    private String avatar;
+
     public ImUserModel(String id, String name, String portrait) {
         this.id = id;
         this.name = name;
@@ -76,5 +83,47 @@ public class ImUserModel {
         this.blacklist = blacklist;
     }
 
+    public String getClientType() {
+        return clientType;
+    }
+
+    public void setClientType(String clientType) {
+        this.clientType = clientType;
+    }
+
+    public String getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    /**
+     * IM用户Token返回信息
+     */
+    public static class ImUserResult implements Serializable {
 
+        // 用户ID
+        private String imUserId;
+
+        // 授权Token
+        private String imToken;
+
+        public String getImUserId() {
+            return imUserId;
+        }
+
+        public void setImUserId(String imUserId) {
+            this.imUserId = imUserId;
+        }
+
+        public String getImToken() {
+            return imToken;
+        }
+
+        public void setImToken(String imToken) {
+            this.imToken = imToken;
+        }
+    }
 }

+ 10 - 0
mec-common/common-core/src/main/java/com/ym/mec/common/page/QueryInfo.java

@@ -32,6 +32,8 @@ public class QueryInfo {
 	
 	private String search;
 
+	private Boolean importFlag;
+
 	private Integer tenantId = TenantContextHolder.getTenantId();
 	
 	public String getSearch() {
@@ -97,4 +99,12 @@ public class QueryInfo {
 	public void setTenantId(Integer tenantId) {
 		this.tenantId = tenantId;
 	}
+
+	public Boolean getImportFlag() {
+		return importFlag;
+	}
+
+	public void setImportFlag(Boolean importFlag) {
+		this.importFlag = importFlag;
+	}
 }

+ 1 - 0
mec-gateway/mec-gateway-web/src/main/resources/bootstrap-test.properties

@@ -14,3 +14,4 @@ spring.cloud.nacos.config.file-extension=yaml
 spring.cloud.nacos.config.refresh.enabled=true
 #\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
 spring.cloud.nacos.config.enabled=true
+logging.config=classpath:logback-test-env.xml

+ 37 - 0
mec-gateway/mec-gateway-web/src/main/resources/logback-dev.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<property name="LOG_HOME" value="/mdata/mec-dev/logs/gateway-%d{yyyy-MM-dd_HH}-%i.log" />
+	<property name="CONSOLE_LOG_PATTERN"
+		value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder charset="UTF-8">
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="file"
+		class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>${LOG_HOME}</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+				class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<logger name="com.ym.mec" level="INFO" />
+
+	<root level="INFO">
+		<appender-ref ref="stdout" />
+		<appender-ref ref="file" />
+	</root>
+
+</configuration>

+ 37 - 0
mec-gateway/mec-gateway-web/src/main/resources/logback-test-env.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<property name="LOG_HOME" value="/mdata/mec-test/logs/gateway-%d{yyyy-MM-dd_HH}-%i.log" />
+	<property name="CONSOLE_LOG_PATTERN"
+		value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder charset="UTF-8">
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="file"
+		class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>${LOG_HOME}</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+				class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<logger name="com.ym.mec" level="INFO" />
+
+	<root level="INFO">
+		<appender-ref ref="stdout" />
+		<appender-ref ref="file" />
+	</root>
+
+</configuration>

+ 1 - 1
mec-im/src/main/java/com/ym/SealClassApplication.java

@@ -20,7 +20,7 @@ import org.springframework.web.client.RestTemplate;
 @SpringBootApplication
 @EnableFeignClients("com.ym.mec")
 @MapperScan(basePackages = {"com.ym.mec.biz.dal.dao", "com.ym.mec.biz.dal.mapper"})
-@ComponentScan(basePackages = {"com.ym", "com.mec.redisson"})
+@ComponentScan(basePackages = {"com.ym", "com.mec.redisson", "com.yonge.log"})
 @EnableScheduling
 @EnableDiscoveryClient
 @Configuration

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

@@ -21,7 +21,7 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
 
     @Override
     public void configure(HttpSecurity http) throws Exception {
-        http.authorizeRequests().antMatchers("/v2/api-docs", "/user/register",
+        http.authorizeRequests().antMatchers("/v2/api-docs", "/user/register", "/user/userImTokenInfo",
                         "/group/join", "/group/create", "/group/quit", "/room/leave", "/room/statusSync",
                         "/room/statusImMsg", "/group/batchDismiss", "/private/send", "/group/send", "/user/tencentImCallback",
                         "/group/dismiss", "/room/statusImMsg", "/history/get", "/user/statusImUser", "/liveRoom/recordSync",

+ 105 - 28
mec-im/src/main/java/com/ym/controller/GroupController.java

@@ -1,6 +1,15 @@
 package com.ym.controller;
 
+import com.alibaba.fastjson.JSON;
 import com.google.common.collect.Lists;
+import com.microsvc.toolkit.middleware.common.http.ImageUtil;
+import com.microsvc.toolkit.middleware.im.ImPluginContext;
+import com.microsvc.toolkit.middleware.im.impl.RongCloudImPlugin;
+import com.microsvc.toolkit.middleware.im.impl.TencentCloudImPlugin;
+import com.microsvc.toolkit.middleware.im.message.ETencentMessage;
+import com.microsvc.toolkit.middleware.im.message.MessageWrapper;
+import com.microsvc.toolkit.middleware.im.message.TencentRequest;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
 import com.ym.mec.common.entity.ImMessageDto;
 import com.ym.pojo.NoticeMessage;
 import com.ym.service.GroupService;
@@ -9,13 +18,13 @@ import io.rong.messages.FileMessage;
 import io.rong.messages.ImgMessage;
 import io.rong.messages.TxtMessage;
 import io.rong.messages.UserInfo;
-import io.rong.models.Result;
 import io.rong.models.group.GroupMember;
 import io.rong.models.group.GroupModel;
 import io.rong.models.group.UserGroup;
 import io.rong.models.message.GroupMessage;
 import io.rong.models.message.MentionMessage;
 import io.rong.models.message.RecallMessage;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -30,6 +39,7 @@ import java.util.stream.Collectors;
 /**
  * Created by weiqinxiao on 2019/2/25.
  */
+@Slf4j
 @RestController
 @RequestMapping("/group")
 public class GroupController{
@@ -38,45 +48,112 @@ public class GroupController{
     MessageService messageService;
     @Autowired
     GroupService groupService;
+    @Autowired
+    private ImPluginContext imPluginContext;
+    @Autowired
+    private ImGroupCoreService imGroupCoreService;
 
     @RequestMapping(value = "/send", method = RequestMethod.POST)
     public Object send(@RequestBody ImMessageDto imMessageDto) throws Exception {
-        GroupMessage groupMessage = new GroupMessage();
+
+        // 群组消息
+        MessageWrapper.GroupMessage build = MessageWrapper.GroupMessage.builder()
+            .senderId(imMessageDto.getSenderId())
+            .objectName(imMessageDto.getObjectName())
+            //.targetIds()
+            //.groupId()
+            .pushExt("")
+            .includeSender(imMessageDto.getIsIncludeSender())
+            .cloudCustomData(imMessageDto.getExtra())
+            .build();
+
         String objectName = imMessageDto.getObjectName();
-        UserInfo userInfo = new UserInfo();
-        if(imMessageDto.getUserInfo() != null){
-            BeanUtils.copyProperties(imMessageDto.getUserInfo(),userInfo);
+        if (RongCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+
+            // 融云消息
+            GroupMessage groupMessage = new GroupMessage();
+            UserInfo userInfo = new UserInfo();
+            if(imMessageDto.getUserInfo() != null){
+                BeanUtils.copyProperties(imMessageDto.getUserInfo(),userInfo);
+            }
+            if("DY:NoticeMsg".equals(objectName)){
+                NoticeMessage noticeMessage = new NoticeMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra());
+                noticeMessage.setUser(userInfo);
+                groupMessage.setContent(noticeMessage);
+            }else if("RC:ImgMsg".equals(objectName)){
+                ImgMessage imgMessage = new ImgMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra(),imMessageDto.getFileUrl());
+                imgMessage.setUser(userInfo);
+                groupMessage.setContent(imgMessage);
+            }else if("RC:FileMsg".equals(objectName)){
+                FileMessage imgMessage = new FileMessage(imMessageDto.getFileName(),imMessageDto.getFileSize(),imMessageDto.getFileUrl(),imMessageDto.getExtra());
+                groupMessage.setContent(imgMessage);
+            }else {
+                TxtMessage txtMessage = new TxtMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra());
+                txtMessage.setUser(userInfo);
+                groupMessage.setContent(txtMessage);
+            }
+            groupMessage.setSenderId(imMessageDto.getSenderId());
+            groupMessage.setObjectName(imMessageDto.getObjectName());
+            groupMessage.setIsIncludeSender(imMessageDto.getIsIncludeSender());
+
+            build.rongCloueMessage(groupMessage.getContent());
+        } else {
+            // 腾讯云消息
+            if ("RC:ImgMsg".equals(objectName)) {
+                // 图片消息
+                ImageUtil.ImageInfo imageReq = ImageUtil.ImageInfo.builder()
+                    .imgUrl(imMessageDto.getFileUrl())
+                    .suffix(imMessageDto.getFileUrl().substring(imMessageDto.getFileUrl().lastIndexOf(".") + 1))
+                    .build();
+
+                // 获取图片基本信息
+                ImageUtil.imageToBase64(imageReq);
+
+                // 图片消息
+                build.tencentMessage(TencentRequest.getTIMImageElem(imageReq));
+            } else if ("RC:FileMsg".equals(objectName)) {
+                // 文件消息
+                build.tencentMessage(TencentRequest.getTIMFileElem(imMessageDto.getFileUrl(), imMessageDto.getFileSize().intValue(), imMessageDto.getFileName()));
+            } else {
+                // DY:NoticeMsg 当作普通文本消息发送
+                // 文本消息
+                build.tencentMessage(TencentRequest.MessageBody.builder()
+                    .msgType(ETencentMessage.TIMTextElem.name())
+                    .msgContent(TencentRequest.TextMessageBody.builder().text(imMessageDto.getMessageContent()).build())
+                    .build());
+            }
         }
-        if("DY:NoticeMsg".equals(objectName)){
-            NoticeMessage noticeMessage = new NoticeMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra());
-            noticeMessage.setUser(userInfo);
-            groupMessage.setContent(noticeMessage);
-        }else if("RC:ImgMsg".equals(objectName)){
-            ImgMessage imgMessage = new ImgMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra(),imMessageDto.getFileUrl());
-            imgMessage.setUser(userInfo);
-            groupMessage.setContent(imgMessage);
-        }else if("RC:FileMsg".equals(objectName)){
-            FileMessage imgMessage = new FileMessage(imMessageDto.getFileName(),imMessageDto.getFileSize(),imMessageDto.getFileUrl(),imMessageDto.getExtra());
-            groupMessage.setContent(imgMessage);
-        }else {
-            TxtMessage txtMessage = new TxtMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra());
-            txtMessage.setUser(userInfo);
-            groupMessage.setContent(txtMessage);
-        }
-        groupMessage.setSenderId(imMessageDto.getSenderId());
-        groupMessage.setObjectName(imMessageDto.getObjectName());
-        groupMessage.setIsIncludeSender(imMessageDto.getIsIncludeSender());
+
         //融云只支持3个群以内的群发
         String[] targetIds = imMessageDto.getTargetIds();
         List<String> imGroupIds = Arrays.stream(targetIds).collect(Collectors.toList());
         List<List<String>> partition = Lists.partition(imGroupIds, 3);
-        Result result = null;
+        //Result result = null;
         for (List<String> integers : partition) {
-            String[] strings = integers.toArray(new String[integers.size()]);
+            /*String[] strings = integers.toArray(new String[integers.size()]);
             groupMessage.setTargetId(strings);
-            result = messageService.groupSend(groupMessage);
+            result = messageService.groupSend(groupMessage);*/
+
+            if (TencentCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+                // 腾讯云消息
+                for (String groupId : integers) {
+                    MessageWrapper.GroupMessage groupMessage = JSON.parseObject(build.groupId(groupId).toString(),
+                        MessageWrapper.GroupMessage.class);
+                    Boolean ret = imPluginContext.getPluginService().sendGroupMessage(groupMessage);
+                    log.info("batchSendPrivateMessage GROUP tencentCloud senderId={}, ret={}, message={}", build.getSenderId(), ret, JSON.toJSONString(groupMessage));
+
+                }
+            } else {
+
+                MessageWrapper.GroupMessage groupMessage = JSON.parseObject(build.targetIds(integers).toString(),
+                    MessageWrapper.GroupMessage.class);
+                // 融云消息
+                Boolean ret = imPluginContext.getPluginService().sendGroupMessage(groupMessage);
+                log.info("batchSendPrivateMessage GROUP rongCloud senderId={}, ret={}", build.getSenderId(), ret);
+            }
+
         }
-        return result;
+        return true;
     }
 
     @RequestMapping(value = "/sendDirection", method = RequestMethod.POST)

+ 79 - 24
mec-im/src/main/java/com/ym/controller/PrivateController.java

@@ -1,9 +1,13 @@
 package com.ym.controller;
 
+import com.google.common.collect.Lists;
+import com.microsvc.toolkit.middleware.common.http.ImageUtil;
+import com.microsvc.toolkit.middleware.im.ImPluginContext;
+import com.microsvc.toolkit.middleware.im.impl.RongCloudImPlugin;
+import com.microsvc.toolkit.middleware.im.message.ETencentMessage;
+import com.microsvc.toolkit.middleware.im.message.MessageWrapper;
+import com.microsvc.toolkit.middleware.im.message.TencentRequest;
 import com.ym.mec.common.entity.ImMessageDto;
-import com.ym.mec.common.entity.ImPrivateMessage;
-import com.ym.mec.common.entity.ImTxtMessage;
-import com.ym.pojo.NoticeMessage;
 import com.ym.service.MessageService;
 import io.rong.messages.FileMessage;
 import io.rong.messages.ImgMessage;
@@ -12,6 +16,7 @@ import io.rong.messages.UserInfo;
 import io.rong.models.message.PrivateMessage;
 import io.rong.models.message.RecallMessage;
 import io.rong.models.message.TemplateMessage;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -22,38 +27,88 @@ import org.springframework.web.bind.annotation.RestController;
 /**
  * Created by weiqinxiao on 2019/2/25.
  */
+@Slf4j
 @RestController
 @RequestMapping("/private")
 public class PrivateController {
 
     @Autowired
     MessageService messageService;
+    @Autowired
+    private ImPluginContext imPluginContext;
 
     @RequestMapping(value = "/send", method = RequestMethod.POST)
     public Object send(@RequestBody ImMessageDto imMessageDto) throws Exception {
-        PrivateMessage privateMessage = new PrivateMessage();
+
+        // 消息对象
+        MessageWrapper.PrivateMessage build = MessageWrapper.PrivateMessage.builder()
+            .senderId(imMessageDto.getSenderId())
+            .targetIds(Lists.newArrayList(imMessageDto.getTargetIds()))
+            .objectName(imMessageDto.getObjectName())
+            //.rongCloueMessage(txtMessage)
+            .pushExt("")
+            .includeSender(1)
+            .cloudCustomData(imMessageDto.getExtra())
+            .build();
+
         String objectName = imMessageDto.getObjectName();
-        UserInfo userInfo = new UserInfo();
-        if(imMessageDto.getUserInfo() != null){
-            BeanUtils.copyProperties(imMessageDto.getUserInfo(),userInfo);
-        }
-        if("RC:ImgMsg".equals(objectName)){
-            ImgMessage imgMessage = new ImgMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra(),imMessageDto.getFileUrl());
-            imgMessage.setUser(userInfo);
-            privateMessage.setContent(imgMessage);
-        }else if("RC:FileMsg".equals(objectName)){
-            FileMessage imgMessage = new FileMessage(imMessageDto.getFileName(),imMessageDto.getFileSize(),imMessageDto.getFileUrl(),imMessageDto.getExtra());
-            privateMessage.setContent(imgMessage);
-        }else {
-            TxtMessage txtMessage = new TxtMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra());
-            txtMessage.setUser(userInfo);
-            privateMessage.setContent(txtMessage);
+        if (RongCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+            // 融云消息体
+            PrivateMessage privateMessage = new PrivateMessage();
+            UserInfo userInfo = new UserInfo();
+            if(imMessageDto.getUserInfo() != null){
+                BeanUtils.copyProperties(imMessageDto.getUserInfo(),userInfo);
+            }
+
+            if("RC:ImgMsg".equals(objectName)){
+                ImgMessage imgMessage = new ImgMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra(),imMessageDto.getFileUrl());
+                imgMessage.setUser(userInfo);
+                privateMessage.setContent(imgMessage);
+            }else if("RC:FileMsg".equals(objectName)){
+                FileMessage imgMessage = new FileMessage(imMessageDto.getFileName(),imMessageDto.getFileSize(),imMessageDto.getFileUrl(),imMessageDto.getExtra());
+                privateMessage.setContent(imgMessage);
+            }else {
+                TxtMessage txtMessage = new TxtMessage(imMessageDto.getMessageContent(),imMessageDto.getExtra());
+                txtMessage.setUser(userInfo);
+                privateMessage.setContent(txtMessage);
+            }
+            privateMessage.setTargetId(imMessageDto.getTargetIds());
+            privateMessage.setSenderId(imMessageDto.getSenderId());
+            privateMessage.setObjectName(imMessageDto.getObjectName());
+            privateMessage.setIsIncludeSender(1);
+            //messageService.privateSend(privateMessage);
+
+            build.rongCloueMessage(privateMessage.getContent());
+        } else {
+            // 腾讯云消息体
+            if("RC:ImgMsg".equals(objectName)){
+                // 图片消息
+                ImageUtil.ImageInfo imageReq = ImageUtil.ImageInfo.builder()
+                    .imgUrl(imMessageDto.getFileUrl())
+                    .suffix(imMessageDto.getFileUrl().substring(imMessageDto.getFileUrl().lastIndexOf(".") + 1))
+                    .build();
+
+                // 获取图片基本信息
+                ImageUtil.imageToBase64(imageReq);
+
+                // 图片消息
+                build.tencentMessage(TencentRequest.getTIMImageElem(imageReq));
+
+            } else if ("RC:FileMsg".equals(objectName)) {
+                // 文件消息
+                build.tencentMessage(TencentRequest.getTIMFileElem(imMessageDto.getFileUrl(), imMessageDto.getFileSize().intValue(), imMessageDto.getFileName()));
+            } else {
+                // 文本消息
+                build.tencentMessage(TencentRequest.MessageBody.builder()
+                    .msgType(ETencentMessage.TIMTextElem.name())
+                    .msgContent(TencentRequest.TextMessageBody.builder().text(imMessageDto.getMessageContent()).build())
+                    .build());
+            }
         }
-        privateMessage.setTargetId(imMessageDto.getTargetIds());
-        privateMessage.setSenderId(imMessageDto.getSenderId());
-        privateMessage.setObjectName(imMessageDto.getObjectName());
-        privateMessage.setIsIncludeSender(1);
-        return messageService.privateSend(privateMessage);
+        Boolean ret = imPluginContext.getPluginService().sendPrivateMessage(build);
+        log.info("privateMessage send ret:{}", ret);
+
+        return true;
     }
 
     /*@RequestMapping(value = "/sendCustom", method = RequestMethod.POST)

+ 192 - 41
mec-im/src/main/java/com/ym/controller/UserController.java

@@ -2,18 +2,32 @@ package com.ym.controller;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Lists;
+import com.microsvc.toolkit.middleware.im.ImPluginContext;
+import com.microsvc.toolkit.middleware.im.impl.TencentCloudImPlugin;
 import com.microsvc.toolkit.middleware.live.LivePluginContext;
 import com.microsvc.toolkit.middleware.live.LivePluginService;
 import com.microsvc.toolkit.middleware.live.impl.TencentCloudLivePlugin;
 import com.ym.common.BaseResponse;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.dao.TeacherDao;
 import com.ym.mec.biz.dal.dto.TencentData;
 import com.ym.mec.biz.dal.dto.TencentImCallbackResult;
+import com.ym.mec.biz.dal.dto.im.BasicUserInfo;
 import com.ym.mec.biz.dal.enums.ETencentImCallbackCommand;
+import com.ym.mec.biz.dal.enums.im.ClientEnum;
+import com.ym.mec.biz.dal.wrapper.ImGroupWrapper;
 import com.ym.mec.biz.service.ImLiveBroadcastRoomService;
+import com.ym.mec.biz.service.SysUserService;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
+import com.ym.mec.common.entity.ImUserModel;
 import com.ym.mec.common.entity.ImUserState;
 import com.ym.service.LiveRoomService;
 import com.ym.service.RoomService;
 import com.ym.service.UserService;
+import io.rong.models.Result;
+import io.rong.models.response.ResponseResult;
+import io.rong.models.response.TokenResult;
 import io.rong.models.user.UserModel;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.collections.CollectionUtils;
@@ -25,11 +39,15 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
 
 import static com.ym.mec.common.controller.BaseController.succeed;
 
@@ -47,15 +65,123 @@ public class UserController {
     private LivePluginContext livePluginContext;
     @Autowired
     private RoomService roomService;
+    @Autowired
+    private ImGroupCoreService imGroupCoreService;
+    @Autowired
+    private ImPluginContext imPluginContext;
+    @Autowired
+    private TeacherDao teacherDao;
+    @Autowired
+    private SysUserService sysUserService;
+
+
 
     @RequestMapping(value = "/register", method = RequestMethod.POST)
-    public Object register(@RequestBody UserModel userModel) throws Exception {
-        return userService.register(userModel);
+    public Object register(@RequestParam(required = false, defaultValue = "") String clientType,
+                           @RequestBody UserModel userModel) throws Exception {
+
+
+        TokenResult tokenResult = new TokenResult(0, "", "", "");
+        // 默认使用腾讯云IM
+        if (TencentCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())
+            && StringUtils.isNotBlank(clientType)) {
+
+            // 用户对象
+            BasicUserInfo userInfo = teacherDao.getBasicUserInfo(Integer.parseInt(userModel.getId()));
+            if (Objects.nonNull(userInfo)) {
+
+                String username = userInfo.getUsername();
+                if (Lists.newArrayList(userInfo.getUserType().split(",")).contains(ClientEnum.TEACHER.getCode())) {
+                    username = Optional.ofNullable(userInfo.getRealName()).orElse(username);
+                }
+
+                ImGroupWrapper.ImUserInfo register = imGroupCoreService.register(userModel.getId(), clientType, username, userInfo.getAvatar());
+
+                // 用户注册接入Token
+                tokenResult.setToken(register.getImToken());
+                // 用户注册接入Id
+                tokenResult.setUserId(register.getImUserId());
+
+                SysUser sysUser = new SysUser();
+                sysUser.setId(Integer.parseInt(userModel.getId()));
+                // 更新用户imToken值
+                sysUser.setImToken(register.getImToken());
+                sysUser.setUpdateTime(new Date());
+                sysUserService.updateSysUser(sysUser);
+            }
+
+        } else {
+            // 融云
+            tokenResult = userService.register(userModel);
+        }
+        return tokenResult;
+    }
+
+    @ApiOperation("IM用户Token信息")
+    @RequestMapping(value = "/userImTokenInfo", method = RequestMethod.POST)
+    public ImUserModel.ImUserResult userImTokenInfo(@RequestBody ImUserModel userModel) {
+
+        ImUserModel.ImUserResult tokenResult = new ImUserModel.ImUserResult();
+        // 用户对象
+        BasicUserInfo userInfo = teacherDao.getBasicUserInfo(Integer.parseInt(userModel.getId()));
+        if (Objects.nonNull(userInfo)) {
+
+            String username = userInfo.getUsername();
+            if (Lists.newArrayList(userInfo.getUserType().split(",")).contains(ClientEnum.TEACHER.getCode())) {
+                username = Optional.ofNullable(userInfo.getRealName()).orElse(username);
+            }
+
+            try {
+
+                ImGroupWrapper.ImUserInfo register = imGroupCoreService.register(userModel.getId(), userModel.getClientType(),
+                    username, Optional.ofNullable(userInfo.getAvatar()).orElse(""));
+
+                // 用户注册接入Token
+                tokenResult.setImToken(register.getImToken());
+                // 用户注册接入Id
+                tokenResult.setImUserId(register.getImUserId());
+
+            } catch (Exception e) {
+                log.error("注册IM用户Token失败", e);
+            }
+
+        }
+        return tokenResult;
     }
 
     @RequestMapping(value = "/update", method = RequestMethod.POST)
     public Object update(@RequestBody UserModel userModel) throws Exception {
-        return userService.update(userModel);
+
+        Result result = new ResponseResult(0, "");
+        // 默认使用腾讯云IM
+        if (TencentCloudImPlugin.PLUGIN_NAME.equals(imPluginContext.defaultService())) {
+            // 腾讯云IM
+            BasicUserInfo userInfo = teacherDao.getBasicUserInfo(Integer.parseInt(userModel.getId()));
+            if (Objects.nonNull(userInfo)) {
+
+                String username = userInfo.getUsername();
+                if (Lists.newArrayList(userInfo.getUserType().split(",")).contains(ClientEnum.TEACHER.getCode())) {
+                    username = Optional.ofNullable(userInfo.getRealName()).orElse(username);
+                }
+
+                try {
+
+                    ImGroupWrapper.ImUserInfo register = imGroupCoreService.register(userModel.getId(), "",
+                        username, Optional.ofNullable(userModel.getPortrait()).orElse(userInfo.getAvatar()));
+
+                    log.info("update IM_USER register: {}", JSONObject.toJSONString(register));
+                } catch (Exception e) {
+                    log.error("更新注册IM用户信息", e);
+                }
+
+            }
+
+        } else {
+            // 融云IM
+            result = userService.update(userModel);
+            log.info("update IM_USER result: {}", JSONObject.toJSONString(result));
+        }
+        return result;
     }
 
     /**
@@ -121,6 +247,13 @@ public class UserController {
             // 直播群成员在线状态回调
             TencentData.CallbackOnMemberStateChange callbackOnMemberStateChange = TencentData.CallbackOnMemberStateChange.toObject(
                 body);
+            // 检查imUserId 是否是当前项目的
+            for (TencentData.MemberListDTO memberListDTO : callbackOnMemberStateChange.getMemberList()) {
+                if (imGroupCoreService.checkImUserId(memberListDTO.getMemberAccount())) {
+                    log.info("tencentImCallback imUserId is not match, imUserId={}", memberListDTO.getMemberAccount());
+                    return new TencentImCallbackResult();
+                }
+            }
 
             log.debug("callbackOnMemberStateChange: {}", callbackOnMemberStateChange);
             callbackOnMemberStateChange.setClientIP(clientIP);
@@ -140,28 +273,30 @@ public class UserController {
                     // 学生编号
                     String userId = callbackOnMemberStateChange.getMemberList().get(0).getMemberAccount();
 
-                    if (userId.matches("\\d+")) {
-                        String eventType = callbackOnMemberStateChange.getEventType();
-                        // 学生离线消息通知
-                        if ("Offline".equals(eventType)) {
+                    String imUserId = imGroupCoreService.analysisImUserId(userId);
+
 
-                            try {
-                                roomService.leaveRoomSuccess(roomId, userId, null);
-                            } catch (Exception e) {
-                                log.error("tencentImCallback leaveRoomSuccess error, roomId={}, userId={}", roomId, userId, e);
-                            }
+                    String eventType = callbackOnMemberStateChange.getEventType();
+                    // 学生离线消息通知
+                    if ("Offline".equals(eventType)) {
+
+                        try {
+                            roomService.leaveRoomSuccess(roomId, imUserId, null);
+                        } catch (Exception e) {
+                            log.error("tencentImCallback leaveRoomSuccess error, roomId={}, imUserId={}", roomId, imUserId, e);
                         }
+                    }
 
-                        // 学生在线消息通知
-                        if ("Online".equals(eventType)) {
+                    // 学生在线消息通知
+                    if ("Online".equals(eventType)) {
 
-                            try {
-                                roomService.joinRoomSuccess(roomId, userId, null);
-                            } catch (Exception e) {
-                                log.error("tencentImCallback joinRoomSuccess error, roomId={}, userId={}", roomId, userId, e);
-                            }
+                        try {
+                            roomService.joinRoomSuccess(roomId, imUserId, null);
+                        } catch (Exception e) {
+                            log.error("tencentImCallback joinRoomSuccess error, roomId={}, imUserId={}", roomId, imUserId, e);
                         }
                     }
+
                 }
             }
 
@@ -170,7 +305,13 @@ public class UserController {
             // 群成员离开之后回调
             TencentData.CallbackAfterMemberExit callbackAfterMemberExit = TencentData.CallbackAfterMemberExit.toObject(
                 body);
-
+            // 检查imUserId 是否是当前项目的
+            for (TencentData.MemberListDTO memberListDTO : callbackAfterMemberExit.getExitMemberList()) {
+                if (imGroupCoreService.checkImUserId(memberListDTO.getMemberAccount())) {
+                    log.info("tencentImCallback imUserId is not match, imUserId={}", memberListDTO.getMemberAccount());
+                    return new TencentImCallbackResult();
+                }
+            }
             log.debug("callbackAfterMemberExit: {}", callbackAfterMemberExit);
             callbackAfterMemberExit.setClientIP(clientIP);
             callbackAfterMemberExit.setOptPlatform(optPlatform);
@@ -189,13 +330,12 @@ public class UserController {
 
                     // 学生编号
                     String userId = callbackAfterMemberExit.getExitMemberList().get(0).getMemberAccount();
+                    String imUserId = imGroupCoreService.analysisImUserId(userId);
 
-                    if (userId.matches("\\d+")) {
-                        try {
-                            roomService.leaveRoomSuccess(roomId, userId, null);
-                        } catch (Exception e) {
-                            log.error("tencentImCallback leaveRoomSuccess error, roomId={}, userId={}", roomId, userId, e);
-                        }
+                    try {
+                        roomService.leaveRoomSuccess(roomId, imUserId, null);
+                    } catch (Exception e) {
+                        log.error("tencentImCallback leaveRoomSuccess error, roomId={}, imUserId={}", roomId, imUserId, e);
                     }
 
                 }
@@ -205,7 +345,13 @@ public class UserController {
             // 新成员入群之后回调
             TencentData.CallbackAfterNewMemberJoin callbackAfterNewMemberJoin = TencentData.CallbackAfterNewMemberJoin.toObject(
                 body);
-
+            // 检查imUserId 是否是当前项目的
+            for (TencentData.MemberListDTO memberListDTO : callbackAfterNewMemberJoin.getNewMemberList()) {
+                if (imGroupCoreService.checkImUserId(memberListDTO.getMemberAccount())) {
+                    log.info("tencentImCallback imUserId is not match, imUserId={}", memberListDTO.getMemberAccount());
+                    return new TencentImCallbackResult();
+                }
+            }
             log.debug("CallbackAfterNewMemberJoin: {}", callbackAfterNewMemberJoin);
             callbackAfterNewMemberJoin.setClientIP(clientIP);
             callbackAfterNewMemberJoin.setOptPlatform(optPlatform);
@@ -225,12 +371,11 @@ public class UserController {
                     // 学生编号
                     String userId = callbackAfterNewMemberJoin.getNewMemberList().get(0).getMemberAccount();
 
-                    if (userId.matches("\\d+")) {
-                        try {
-                            roomService.joinRoomSuccess(roomId, userId, null);
-                        } catch (Exception e) {
-                            log.error("tencentImCallback joinRoomSuccess error, roomId={}, userId={}", roomId, userId, e);
-                        }
+                    String imUserId = imGroupCoreService.analysisImUserId(userId);
+                    try {
+                        roomService.joinRoomSuccess(roomId, imUserId, null);
+                    } catch (Exception e) {
+                        log.error("tencentImCallback joinRoomSuccess error, roomId={}, imUserId={}", roomId, imUserId, e);
                     }
 
                 }
@@ -249,7 +394,10 @@ public class UserController {
         log.info("tencentStreamEventCallback body:{}", body);
 
         TencentData.CallbackStreamStateEvent event = TencentData.CallbackStreamStateEvent.from(body);
-
+        boolean b = checkStream(event.getStreamId());
+        if (!b) {
+            return TencentData.StreamEventCallbackResult.builder().code(0).build();
+        }
         // 直播间推流事件
         if (event.getStreamId().startsWith("LIVE")) {
 
@@ -281,6 +429,7 @@ public class UserController {
 
                 Integer speakerId = getSpeakerId(event.getStreamId());
                 if (speakerId > 0) {
+
                     // 自动开启录制
                     imLiveBroadcastRoomService.startLive(getRoomUid(event.getStreamId()), getSpeakerId(event.getStreamId()), null,event.getSequence());
 
@@ -293,13 +442,12 @@ public class UserController {
         return TencentData.StreamEventCallbackResult.builder().code(0).build();
     }
 
-    private Integer getSpeakerId(String streamId) {
+    private boolean checkStream(String streamId) {
+        return imGroupCoreService.checkImUserId(streamId.split("_",2)[1]);
+    }
 
-        String userId = streamId.split("_")[1];
-        if (userId.matches("\\d+")) {
-            return Integer.parseInt(userId);
-        }
-        return -1;
+    private Integer getSpeakerId(String streamId) {
+        return Integer.parseInt(imGroupCoreService.analysisImUserId(streamId.split("_",2)[1]));
     }
 
     private String getRoomUid(String streamId) {
@@ -313,7 +461,10 @@ public class UserController {
         log.info("tencentStreamRecordCallback body:{}", body);
 
         TencentData.CallbackSteamRecordEvent event = TencentData.CallbackSteamRecordEvent.from(body);
-
+        boolean b = checkStream(event.getStreamId());
+        if (!b) {
+            return TencentData.StreamEventCallbackResult.builder().code(0).build();
+        }
         // 直播录制事件通知
         if (event.getStreamId().startsWith("LIVE")) {
             log.info("taskId={}, url={}", event.getTaskId(), event.getVideoUrl());

+ 191 - 0
mec-im/src/main/java/com/ym/service/GroupCoreService.java

@@ -0,0 +1,191 @@
+package com.ym.service;
+
+import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
+import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginService;
+import com.ym.mec.biz.dal.dto.ImGroupDto;
+import com.ym.mec.biz.dal.dto.ImGroupMemberDto;
+import com.ym.mec.biz.dal.dto.NameDto;
+import com.ym.mec.biz.dal.dto.im.BasicUserInfo;
+import com.ym.mec.biz.dal.entity.ImGroup;
+import com.ym.mec.biz.dal.enums.im.RoleEnum;
+import com.ym.mec.biz.dal.enums.school.ESchoolStaffType;
+import com.ym.mec.biz.dal.wrapper.ImGroupWrapper;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+public interface GroupCoreService {
+
+	/**
+	 * 创建群组
+	 * @param id 群编号
+	 * @param userId 创建人编号
+	 * @param name 群名称
+	 * @param introduce 群介绍
+	 * @param memo 群备注
+	 * @param tags 群标签
+	 * @param img 群图像
+	 * @param type 群类型
+	 * @return
+	 */
+	ImGroup create(String id, Integer userId, String name, String introduce, String memo, String tags, String img, String type, ImGroup.GroupTypeEnum groupType);
+
+	/**
+	* @description: 创建非课程类型的业务群组
+	* @return java.lang.String
+	* @author zx
+	* @date 2022/6/7 15:20
+	*/
+	String createGroup(ImGroupDto imGroupDto);
+
+	/**
+	 * 解散群组
+	 * @param imGroupId
+	 * @return
+	 */
+	boolean cancel(String imGroupId);
+
+	/**
+	 * 查询用户所在的群列表
+	 * @param userId
+	 * @param search
+	 * @return
+	 */
+	List<ImGroup> queryByUserId(Integer userId, String search,String groupType);
+
+	/**
+	 * 查询群成员列表
+	 * @param imGroupId
+	 * @return
+	 */
+	List<ImGroupMemberDto> queryMemberById(String imGroupId);
+	List<ImGroupMemberDto> queryMemberById(String imGroupId,String search);
+
+	/**
+	 * 查询指定用户在群众的信息
+	 * @param imGroupId 群编号
+	 * @param userId 指定的用户编号
+	 * @return
+	 */
+	ImGroupMemberDto queryMember(String imGroupId, Integer userId);
+
+	/**
+	 * 修改用户在群、通讯录的备注
+	 * @param userId
+	 * @param nickName
+	 * @return
+	 */
+    int updateNickName(Integer userId, String nickName);
+
+	/**
+	 * 修改用户在群、通讯录的备注
+	 * @param userId
+	 * @param nickName
+	 * @return
+	 */
+	void updateNickName1(Integer userId, String nickName);
+
+	void updateImGroup(ImGroup imGroup);
+
+	//解散群组
+	void dismissGroup(String imGroupId);
+
+	/**
+	* @description: 获取群聊、用户详情
+	 * @param nameDto
+	* @return java.lang.Object
+	* @author zx
+	* @date 2022/8/8 10:10
+	*/
+	List<NameDto> queryDetail(List<NameDto> nameDto);
+
+    List<ImGroup> queryByUserIdV2(Integer userId, String search, String groupType, String musicGroupId, String classType);
+
+    List<ImGroupMemberDto> queryMemberByIdV2(String imGroupId,String search,Integer subjectId,Boolean vipFlag);
+
+    /**
+     * 用户退出所有群
+     *
+     * @param userId 用户id
+     */
+    void quitAllGroup(Long userId);
+
+    /**
+     * 用户加入群
+     *
+     * @param schoolId 学校id
+     * @param userId 用户id
+     * @param leader 是否是群主
+     */
+    void addSchoolStaffGroup(Long schoolId, Integer userId,String name,String avatar, ESchoolStaffType leader) throws Exception;
+
+    @Transactional(rollbackFor = Exception.class)
+    void addSchoolGroup(Long schoolId, List<GroupMemberWrapper.ImGroupMember> imGroupMembers);
+
+    @Transactional(rollbackFor = Exception.class)
+    void quitSchoolGroup(Long schoolId, List<GroupMemberWrapper.ImGroupMember> imGroupMembers);
+
+    /**
+     * 群主移交
+     * @param userId 用户id
+     * @param imGroupId     群组id
+     */
+    @Transactional(rollbackFor = Exception.class)
+    Boolean  groupChangeOwner(Integer userId, String imGroupId) throws Exception;
+
+    /**
+     * 加群
+     *
+     * @param musicGroupIds 群组ID
+     * @param userId          用户信息
+     * @param roleType
+     */
+    void addImGroup(List<String> musicGroupIds, Long  userId,  String roleType);
+
+    /**
+     * 查询群组
+     *
+     * @param query 查询条件
+     * @return 群组列表
+     */
+    List<ImGroup> queryByUserId(ImGroupWrapper.ImQuery query);
+
+    /**
+     * 退出群组
+     *
+     * @param imGroupIds 群组ID
+     * @param userId    用户ID
+     */
+    void quitGroup(List<String> imGroupIds, Integer userId);
+
+    /**
+     * 学校人员加入群组
+     *
+     * @param cooperationOrganId 合作机构id
+     * @param imGroupId 群组id
+     */
+    void schoolJoinGroup(Integer cooperationOrganId, String imGroupId);
+
+
+	/**
+	 * 解析IM用户规则
+	 * @param imUserId IM用户Id
+	 * @return String
+	 */
+	String analysisImUserId(String imUserId);
+
+	/**
+	 * IM 用户注册
+	 * @param userId 用户Id
+	 * @return String
+	 */
+	String getImUserId(String userId,String clientType);
+
+	String getImUserId(Long userId, RoleEnum userRole);
+
+	String analysisImUserClient(String imUserId);
+
+	void joinImGroup(String roomId, BasicUserInfo userInfo, String serverProvider, List<Long> studentIds) throws Exception;
+
+	RTCRoomPluginService getRTCRoomPluginService(String serviceProvider);
+}

+ 902 - 0
mec-im/src/main/java/com/ym/service/Impl/GroupCoreServiceImpl.java

@@ -0,0 +1,902 @@
+package com.ym.service.Impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.google.common.collect.Lists;
+import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
+import com.microsvc.toolkit.middleware.im.properties.ImConfigProperties;
+import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginContext;
+import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginService;
+import com.microsvc.toolkit.middleware.rtc.impl.TencentCloudRTCPlugin;
+import com.microsvc.toolkit.middleware.rtc.message.ImGroupMemberWrapper;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.auth.api.enums.SysUserType;
+import com.ym.mec.biz.dal.dao.*;
+import com.ym.mec.biz.dal.dto.ImGroupDto;
+import com.ym.mec.biz.dal.dto.ImGroupMemberDto;
+import com.ym.mec.biz.dal.dto.NameDto;
+import com.ym.mec.biz.dal.dto.im.BasicUserInfo;
+import com.ym.mec.biz.dal.entity.*;
+import com.ym.mec.biz.dal.enums.EFriendRoleType;
+import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
+import com.ym.mec.biz.dal.enums.im.RoleEnum;
+import com.ym.mec.biz.dal.enums.school.ESchoolStaffType;
+import com.ym.mec.biz.dal.mapper.SchoolStaffMapper;
+import com.ym.mec.biz.dal.wrapper.ImGroupWrapper;
+import com.ym.mec.biz.service.CooperationOrganService;
+import com.ym.mec.biz.service.ImGroupMemberService;
+import com.ym.mec.biz.service.SysConfigService;
+import com.ym.mec.biz.service.SysUserService;
+import com.ym.mec.biz.service.im.ImGroupCoreService;
+import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.tenant.TenantContextHolder;
+import com.ym.mec.im.IMHelper;
+import com.ym.service.GroupCoreService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+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;
+
+@Service
+@Slf4j
+public class GroupCoreServiceImpl implements GroupCoreService {
+
+    @Resource
+    private ImGroupDao imGroupDao;
+
+    @Resource
+    private ImGroupMemberDao imGroupMemberDao;
+
+    @Resource
+    private ImGroupMemberService imGroupMemberService;
+
+    @Resource
+    private SysUserService sysUserService;
+
+    @Resource
+    private ImUserFriendDao imUserFriendDao;
+
+    @Resource
+    private SysConfigService sysConfigService;
+
+    @Resource
+    private CooperationOrganService cooperationOrganService;
+
+    @Resource
+    private MusicGroupDao musicGroupDao;
+
+    @Resource
+    private ClassGroupTeacherMapperDao classGroupTeacherMapperDao;
+
+    @Resource
+    private SchoolStaffMapper schoolStaffMapper;
+    @Resource
+    private RedisTemplate<String,Object> redisTemplate;
+    @Resource
+    private RTCRoomPluginContext rtcRoomPluginContext;
+
+    @Resource
+    private IMHelper imHelper;
+
+    @Resource
+    private ImGroupCoreService imGroupCoreService;
+
+    @Resource
+    private ImConfigProperties imConfig;
+
+    @Resource
+    private TeacherDao teacherDao;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public ImGroup create(String id, Integer userId, String name, String introduce, String memo, String tags, String img, String type, ImGroup.GroupTypeEnum groupType) {
+        ImGroup imGroup = imGroupDao.get(id);
+        if (imGroup != null) {
+            return imGroup;
+        }
+
+        imGroup = new ImGroup();
+
+        Date date = new Date();
+
+        imGroup.setId(id);
+        imGroup.setCreateTime(date);
+        imGroup.setIntroduce(introduce);
+
+        if(userId != null){
+            imGroup.setMemberNum(1);
+        }else{
+            imGroup.setMemberNum(0);
+        }
+        imGroup.setMemo(memo);
+        imGroup.setName(name);
+        imGroup.setTags(tags);
+        imGroup.setImg(img);
+        imGroup.setType(type);
+        imGroup.setGroupType(groupType);
+        imGroup.setUpdateTime(date);
+
+        try {
+            String imGroupId = createImGroup(imGroup, userId, null);
+            imGroup.setId(imGroupId);
+        } catch (Exception e) {
+            log.error("群组创建失败",e);
+            throw new BizException("群组创建失败");
+        }
+
+        return imGroup;
+    }
+
+
+    private String createImGroup(ImGroup imGroup, Integer userId, String roleType) throws Exception {
+        ImGroupWrapper.ImGroup group = ImGroupWrapper.ImGroup.from(JSON.toJSONString(imGroup));
+
+        //记录群成员
+        com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper.ImGroupMember groupMember = null;
+        if (userId != null) {
+            SysUser sysUser = teacherDao.getUser(userId);
+            SysUserType sysUserType = EFriendRoleType.getByName(roleType).toSysUserType();
+            groupMember = com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper.ImGroupMember
+                    .builder()
+                    .userId(userId.longValue())
+                    .clientType(sysUserType.name())
+                    .avatar(sysUser.getAvatar())
+                    .nickname(sysUserType == SysUserType.STUDENT?sysUser.getUsername():sysUser.getRealName())
+                    .roleType(roleType)
+                    .isAdmin(true)
+                    .build();
+        }
+        return imGroupCoreService.groupCreate(groupMember, group);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String createGroup(ImGroupDto imGroupDto){
+        List<String> userIdList = imGroupDto.getUserIdList();
+        Integer currentUserId = null;
+        if (CollectionUtils.isEmpty(userIdList)){
+            userIdList.add(sysUserService.getUserId().toString());
+        }
+        String groupName = imGroupDto.getGroupName();
+        String type = imGroupDto.getType();
+        Optional.ofNullable(groupName).filter(StringUtils::isNotBlank).orElseThrow(() -> new BizException("群名称不能为空"));
+        Optional.ofNullable(type).filter(StringUtils::isNotBlank).orElseThrow(() -> new BizException("群类型不能为空"));
+        Date date = new Date();
+        ImGroup imGroup = new ImGroup();
+        String groupId = UUID.randomUUID().toString();
+        imGroup.setId(groupId);
+        imGroup.setCreateTime(date);
+        imGroup.setIntroduce(groupName);
+        imGroup.setMemo(groupName);
+        imGroup.setMemberNum(userIdList.size());
+        imGroup.setName(groupName);
+        imGroup.setType(type);
+        imGroup.setGroupType(imGroupDto.getGroupType());
+        imGroup.setUpdateTime(date);
+
+
+        try {
+            String imGroupId = createImGroup(imGroup, null, null);
+            imGroup.setId(imGroupId);
+        } catch (Exception e) {
+            log.error("群组创建失败",e);
+            throw new BizException("群组创建失败");
+        }
+
+        List<ImGroupMember> groupMemberList = imGroupMemberDao.queryMembers(groupId, userIdList, TenantContextHolder.getTenantId());
+        if(currentUserId != null){
+            groupMemberList.get(0).setRoleType("乐团主管");
+        }
+
+        addImGroupMember(groupId, groupMemberList);
+        return groupId;
+    }
+
+    private void addImGroupMember(String groupId, List<ImGroupMember> groupMemberList) {
+        List<com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper.ImGroupMember> imGroupMembers = Lists.newArrayList();
+        for (ImGroupMember groupMember : groupMemberList) {
+            SysUserType sysUserType = EFriendRoleType.getByName(groupMember.getRoleType()).toSysUserType();
+            imGroupMembers.add(com.ym.mec.biz.dal.wrapper.ImGroupMemberWrapper.ImGroupMember.builder()
+                    .groupId(groupMember.getImGroupId())
+                    .userId(groupMember.getUserId().longValue())
+                    .clientType(sysUserType.name())
+                    .avatar(groupMember.getAvatar())
+                    .nickname(groupMember.getNickname())
+                    .isAdmin(groupMember.getIsAdmin())
+                    .imUserId(getImUserId(groupMember.getUserId().toString(), sysUserType.name()))
+                    .roleType(groupMember.getRoleType())
+                    .build());
+        }
+        try {
+            imGroupCoreService.saveImGroupMemberList(groupId, imGroupMembers);
+        } catch (Exception e) {
+            log.error("添加群成员用户失败",e);
+            throw new BizException("添加群成员用户失败");
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean cancel(String imGroupId) {
+        try {
+            imGroupCoreService.groupDismiss(imGroupId);
+        } catch (Exception e) {
+            log.error("解散群组失败",e);
+            throw new BizException("解散群组失败");
+        }
+
+        return true;
+    }
+
+    @Override
+    public List<ImGroup> queryByUserId(Integer userId, String search,String groupType) {
+        return imGroupDao.queryByUserId(userId, search,groupType);
+    }
+
+    @Override
+    public List<ImGroupMemberDto> queryMemberById(String imGroupId) {
+        return  queryMemberById(imGroupId,null);
+    }
+
+
+    @Override
+    public List<ImGroupMemberDto> queryMemberById(String imGroupId,String search) {
+        List<ImGroupMemberDto> imGroupMemberDtos = imGroupDao.queryMemberById(imGroupId,search);
+
+        for (ImGroupMemberDto imGroupMemberDto : imGroupMemberDtos) {
+            imGroupMemberDto.setType(EFriendRoleType.getByName(imGroupMemberDto.getRoleType()).name());
+            imGroupMemberDto.getUser().setUsername(imGroupMemberDto.getGroupNickname());
+            imGroupMemberDto.setNickname(imGroupMemberDto.getGroupNickname());
+            String roleType = imGroupMemberDto.getRoleType();
+            if (StringUtils.isEmpty(roleType)){
+                throw new BizException("roleType为空");
+            }
+            //根据角色不同 配置imUserId
+            if (EFriendRoleType.SCHOOLMASTER.getMsg().equals(roleType) ||
+                    EFriendRoleType.ORCHESTRA_LEADER.getMsg().equals(roleType) ||
+                    EFriendRoleType.SCHOOL_LEADER.getMsg().equals(roleType) ||
+                    EFriendRoleType.SCHOOL_TEACHER.getMsg().equals(roleType)) {
+                imGroupMemberDto.setImUserId(
+                        imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()), SysUserType.SCHOOL.getCode()
+                        )
+                );
+            } else if (EFriendRoleType.ORCHESTRA_TEACHER.getMsg().equals(roleType)){
+                imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.TEACHER.getCode()));
+            } else if (EFriendRoleType.ORCHESTRA_MANAGER.getMsg().equals(roleType) || EFriendRoleType.MAINTENANCE_TECHNICIAN.getMsg().equals(roleType)){
+                imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.EDUCATION.getCode()));
+            } else if (EFriendRoleType.STUDENT.getMsg().equals(roleType)){
+                imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.STUDENT.getCode()));
+            } else {
+                imGroupMemberDto.setImUserId("");
+            }
+        }
+        return imGroupMemberDtos;
+    }
+
+    @Override
+    public ImGroupMemberDto queryMember(String imGroupId, Integer userId) {
+        ImGroupMemberDto imGroupMemberDto = imGroupDao.queryMember(imGroupId, userId);
+        if(Objects.isNull(imGroupMemberDto)){
+            imGroupMemberDto = imGroupDao.queryMember(null, userId);
+            if (Objects.nonNull(imGroupMemberDto)){
+                imGroupMemberDto.setRoleType(null);
+            }
+        }
+        String roleType = imGroupMemberDto.getRoleType();
+        if (StringUtils.isEmpty(roleType)){
+            throw new BizException("roleType为空");
+        }
+
+        //根据角色不同 配置imUserId
+        if (EFriendRoleType.SCHOOLMASTER.getMsg().equals(roleType) ||
+                EFriendRoleType.ORCHESTRA_LEADER.getMsg().equals(roleType) ||
+                EFriendRoleType.SCHOOL_LEADER.getMsg().equals(roleType) ||
+                EFriendRoleType.SCHOOL_TEACHER.getMsg().equals(roleType)) {
+            imGroupMemberDto.setImUserId(
+                    imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()), SysUserType.SCHOOL.getCode()
+                    )
+            );
+        } else if (EFriendRoleType.ORCHESTRA_TEACHER.getMsg().equals(roleType)){
+            imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.TEACHER.getCode()));
+        } else if (EFriendRoleType.ORCHESTRA_MANAGER.getMsg().equals(roleType) || EFriendRoleType.MAINTENANCE_TECHNICIAN.getMsg().equals(roleType)){
+            imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.EDUCATION.getCode()));
+        } else if (EFriendRoleType.STUDENT.getMsg().equals(roleType)){
+            imGroupMemberDto.setImUserId(imGroupCoreService.getImUserId(String.valueOf(imGroupMemberDto.getUserId()),SysUserType.STUDENT.getCode()));
+        } else{
+            imGroupMemberDto.setImUserId("");
+        }
+        return imGroupMemberDto;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateNickName(Integer userId, String nickName) {
+        //修改群成员备注
+        int i = imGroupDao.updateNickname(userId, nickName);
+        imGroupDao.updateUserFriendNickname(userId, nickName);
+        return i;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateNickName1(Integer userId, String nickName) {
+        //修改群成员备注
+        imGroupDao.updateNickname(userId, nickName);
+        imGroupDao.updateUserFriendNickname(userId, nickName);
+        //修改sysUser名称,如果包含学员的角色,那么修改userName。否则修改realName
+        SysUser sysUser = sysUserService.queryUserById(userId);
+        if(sysUser.getUserType().contains("STUDENT")){
+            sysUser.setUsername(nickName);
+        }else {
+            sysUser.setRealName(nickName);
+        }
+        sysUserService.updateSysUser(sysUser);
+
+        // IM用户信息更新
+        try {
+            imGroupCoreService.register(userId.toString(),"",nickName,sysUser.getAvatar());
+        } catch (Exception e) {
+            log.error("更新用户信息失败",e);
+            throw new BizException("更新用户信息失败");
+        }
+
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateImGroup(ImGroup imGroup) {
+        imGroup.setMemberNum(null);
+        imGroupDao.update(imGroup);
+        try {
+            imGroupCoreService.modifyGroupInfo(imGroup.getId(),imGroup.getName(),imGroup.getImg());
+        } catch (Exception e) {
+            log.error("群信息修改失败",e);
+            throw new BizException("群信息修改失败");
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void dismissGroup(String imGroupId) {
+        try {
+            imGroupCoreService.groupDismiss(imGroupId);
+        } catch (Exception e) {
+            log.error("解散群组失败",e);
+            throw new BizException("解散群组失败");
+        }
+    }
+
+    @Override
+    public List<NameDto> queryDetail(List<NameDto> nameDto) {
+        List<NameDto> dtos = new ArrayList<>();
+        if(CollectionUtils.isNotEmpty(nameDto)){
+            Map<Integer, List<NameDto>> collect = nameDto.stream().collect(Collectors.groupingBy(NameDto::getType));
+            for (Integer integer : collect.keySet()) {
+                List<NameDto> nameDtos = collect.get(integer);
+                if(CollectionUtils.isNotEmpty(nameDtos)){
+                    String idList = nameDtos.stream().map(e -> e.getId()).collect(Collectors.joining(","));
+                    if(integer.equals(3)){
+                        dtos.addAll(imGroupDao.queryNameByIds(idList));
+                    }else if (integer.equals(1)){
+                        Integer userId = sysUserService.getUserId();
+                        dtos.addAll(imUserFriendDao.queryNameByIds(idList,userId));
+                    }
+                }
+            }
+        }
+        return dtos;
+    }
+
+    @Override
+    public List<ImGroup> queryByUserIdV2(Integer userId, String search, String groupType, String musicGroupId, String classType) {
+        return imGroupDao.queryByUserIdV2(userId, search, groupType, musicGroupId, classType);
+    }
+
+    @Override
+    public List<ImGroupMemberDto> queryMemberByIdV2(String imGroupId, String search, Integer subjectId, Boolean vipFlag) {
+        return imGroupDao.queryMemberByIdV2(imGroupId,search,subjectId,vipFlag);
+    }
+
+    /**
+     * 用户退出所有群
+     * <p>
+     * 删除时判断是否群主,
+     * 如果是,则随机分配一个群主,
+     * 如果删除的是最后一个群成员,那么解散群
+     * @param userId 用户id
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void quitAllGroup(Long userId) {
+
+        List<ImGroupMember> imGroupMembers = imGroupMemberDao.queryMembersByUserId(userId);
+
+        if (CollectionUtils.isEmpty(imGroupMembers)) {
+            return;
+        }
+        for (ImGroupMember imGroupMember : imGroupMembers) {
+            // 如果是群主,随机分配一个群主
+            if (imGroupMember.getIsAdmin()) {
+                try {
+                    // 获取一个群成员
+                    ImGroupMember imGroupMember1 = imGroupMemberDao.queryOneByGroupIdAndNotUser(imGroupMember.getImGroupId(), userId);
+                    if (Objects.nonNull(imGroupMember1)) {
+                        groupChangeOwner(imGroupMember1.getUserId(),imGroupMember.getImGroupId());
+                    }
+                } catch (Exception e) {
+                    log.error("更换群主失败{},{}", userId, imGroupMember.getImGroupId(), e);
+                }
+            }
+            try {
+                imGroupCoreService.groupQuit(userId,"",imGroupMember.getImGroupId());
+            } catch (Exception e) {
+                log.error("用户退出群失败{},{}", userId, imGroupMember.getImGroupId(), e);
+            }
+        }
+        List<String> imGroupIds = imGroupMembers.stream().map(ImGroupMember::getImGroupId).collect(Collectors.toList());
+        // 群组没人,删除群组
+        List<ImGroup> imGroups = imGroupDao.queryByUserId(userId.intValue(),null, ImGroup.GroupTypeEnum.SCHOOL.getCode());
+
+
+        imGroupMemberDao.deleteByUserId(userId);
+        // 更新群组人员数
+        imGroupDao.addMemberNum(imGroupIds,-1);
+
+        if (CollectionUtils.isEmpty(imGroups)) {
+            return;
+        }
+
+
+        List<ImGroup> groups = imGroups.stream().filter(imGroup -> imGroup.getMemberNum().equals(1)).collect(Collectors.toList());
+        for (ImGroup group : groups) {
+            try {
+                dismissGroup(group.getId());
+            } catch (Exception e) {
+                log.error("解散群组失败{},{}", userId, group.getId(), e);
+            }
+            imGroupDao.delete(group.getId());
+        }
+    }
+
+    /**
+     * 用户加入群
+     *
+     * @param schoolId 学校id
+     * @param userId   用户id
+     * @param schoolStaffType   是否是群主
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void addSchoolStaffGroup(Long schoolId, Integer userId,String name,String avatar, ESchoolStaffType schoolStaffType) throws Exception {
+
+        // 查询群是否存在
+        ImGroup imGroup = imGroupDao.queryBySchoolId(schoolId);
+
+
+        // 注册主播用户信息到三方平台
+        imGroupCoreService.register(userId.toString(),"", name, avatar);
+
+        // 群组不存在,先创建群组
+        if (Objects.isNull(imGroup)) {
+            CooperationOrgan cooperationOrgan = cooperationOrganService.get(schoolId.intValue());
+            imGroup = new ImGroup();
+            imGroup.setSchoolId(schoolId);
+            imGroup.setId(IdWorker.getIdStr());
+            imGroup.setName("教学团队衔接群");
+            imGroup.setIntroduce(imGroup.getName());
+            imGroup.setMemo(imGroup.getName());
+            imGroup.setMemberNum(0);
+            imGroup.setImg(sysConfigService.findByParamName(SysConfigService.SCHOOL_IM_GROUP_IMG).getParanValue());
+            imGroup.setType(ImGroup.GroupTypeEnum.SCHOOL.getCode());
+            imGroup.setGroupType(ImGroup.GroupTypeEnum.SCHOOL);
+            imGroup.setCreateTime(new Date());
+            imGroup.setUpdateTime(new Date());
+            imGroup.setTenantId(cooperationOrgan.getTenantId());
+
+            createImGroup(imGroup,userId,"");
+
+            initSchoolGroup(imGroup.getSchoolId());
+        }
+
+
+        if (schoolStaffType.equals(ESchoolStaffType.ORCHESTRA_LEADER)) {
+            groupChangeOwner(userId, imGroup.getId());
+        }
+        ImGroupMember imGroupMember = new ImGroupMember();
+        imGroupMember.setImGroupId(imGroup.getId());
+        imGroupMember.setUserId(userId);
+        imGroupMember.setIsAdmin(schoolStaffType.equals(ESchoolStaffType.ORCHESTRA_LEADER));
+        imGroupMember.setRoleType(schoolStaffType.getDescribe());
+        imGroupMember.setType(EFriendRoleType.getByName(schoolStaffType.getDescribe()).name());
+        imGroupMember.setTenantId(imGroup.getTenantId());
+        imGroupMemberDao.insert(imGroupMember);
+
+        updateImGroupUserNumber(imGroup.getId());
+    }
+
+    private void initSchoolGroup(Long schoolId) {
+
+
+        // 查询乐团主管
+        List<MusicGroup> musicGroupList = musicGroupDao.findByCooperationId(schoolId.intValue());
+        if (CollectionUtils.isEmpty(musicGroupList)) {
+            return;
+        }
+        musicGroupList = musicGroupList.stream()
+                .filter(o -> o.getStatus().equals(MusicGroupStatusEnum.PROGRESS))
+                .collect(Collectors.toList());
+        if (CollectionUtils.isEmpty(musicGroupList)) {
+            return;
+        }
+
+        // 乐团主管
+        List<Integer> groupLeaderIds = musicGroupList.stream().map(MusicGroup::getEducationalTeacherId).collect(Collectors.toList());
+
+        // 乐团ID集合
+        List<String> musicGroupIds = musicGroupList.stream().map(MusicGroup::getId).collect(Collectors.toList());
+
+        // 班级列表主教/助教老师
+        List<ClassGroupTeacherMapper> teacherMapperList = classGroupTeacherMapperDao.findAllByMusicGroupIds(musicGroupIds);
+
+        List<Integer> teacherIds = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(teacherMapperList)) {
+            teacherIds.addAll(teacherMapperList.stream().map( o -> o.getUserId()).collect(Collectors.toSet()));
+        }
+
+        List<GroupMemberWrapper.ImGroupMember> imGroupMembers = new ArrayList<>();
+        for (Integer groupLeaderId : groupLeaderIds) {
+            imGroupMembers.add(GroupMemberWrapper.ImGroupMember.builder()
+                    .userId(groupLeaderId.longValue()).roleType(EFriendRoleType.ORCHESTRA_MANAGER.getMsg()).imUserIdFormat(false).build());
+        }
+
+        for (Integer teacherId : teacherIds) {
+            imGroupMembers.add(GroupMemberWrapper.ImGroupMember.builder()
+                    .userId(teacherId.longValue()).roleType(EFriendRoleType.ORCHESTRA_TEACHER.getMsg()).imUserIdFormat(false).build());
+        }
+
+        addSchoolGroup(schoolId, imGroupMembers);
+    }
+
+    /**
+     * 加入学校群聊
+     *
+     * @param schoolId
+     * @param imGroupMembers
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void addSchoolGroup(Long schoolId, List<GroupMemberWrapper.ImGroupMember> imGroupMembers) {
+        // 添加乐团领队,班级老师
+        List<ImGroupMember> imGroupMemberList =new ArrayList<>();
+
+
+        // 查询群是否存在
+        ImGroup imGroup = imGroupDao.queryBySchoolId(schoolId);
+        if (imGroup == null) {
+            return;
+        }
+        if (CollectionUtils.isEmpty(imGroupMembers)) {
+            return;
+        }
+
+        for (GroupMemberWrapper.ImGroupMember groupMember : imGroupMembers) {
+            ImGroupMember imGroupMember = new ImGroupMember();
+            imGroupMember.setImGroupId(imGroup.getId());
+            imGroupMember.setUserId(groupMember.getUserId().intValue());
+            imGroupMember.setIsAdmin(false);
+            imGroupMember.setRoleType(groupMember.getRoleType());
+            imGroupMember.setType(EFriendRoleType.getByName(groupMember.getRoleType()).name());
+            imGroupMember.setTenantId(imGroup.getTenantId());
+            imGroupMemberList.add(imGroupMember);
+            groupMember.setImUserIdFormat(false);
+        }
+
+
+        addImGroupMember(imGroup.getId(), imGroupMemberList);
+        updateImGroupUserNumber(imGroup.getId());
+    }
+
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void quitSchoolGroup(Long schoolId, List<GroupMemberWrapper.ImGroupMember> imGroupMembers) {
+        // 添加乐团领队,班级老师
+
+
+        // 查询群是否存在
+        ImGroup imGroup = imGroupDao.queryBySchoolId(schoolId);
+        if (imGroup == null) {
+            return;
+        }
+
+        if (CollectionUtils.isEmpty(imGroupMembers)) {
+            return;
+        }
+
+
+
+        List<Integer> userIds = new ArrayList<>();
+        for (GroupMemberWrapper.ImGroupMember imGroupMember : imGroupMembers) {
+            imGroupMember.setImUserIdFormat(false);
+            userIds.add(imGroupMember.getUserId().intValue());
+        }
+        try {
+            imGroupCoreService.groupQuit(imGroupMembers,imGroup.getId());
+        } catch (Exception e) {
+            log.error("退出群成员失败{}", imGroup.getId(), e);
+        }
+        updateImGroupUserNumber(imGroup.getId());
+    }
+
+    private void updateImGroupUserNumber(String imGroupId) {
+        ImGroup imGroup = new ImGroup();
+        imGroup.setId(imGroupId);
+        imGroup.setMemberNum(imGroupMemberDao.getByGroupId(Lists.newArrayList(imGroupId)).size());
+        imGroupDao.updateMember(imGroup.getId(),imGroup.getMemberNum());
+    }
+
+    /**
+     * 群主移交
+     * @param userId 用户id
+     * @param imGroupId     群组id
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean groupChangeOwner(Integer userId, String imGroupId) throws Exception {
+
+
+        ImGroupMember imGroupMember = imGroupMemberDao.getAdmin(imGroupId);
+        Integer adminId = userId;
+        if (Objects.nonNull(imGroupMember)) {
+            adminId = imGroupMember.getUserId();
+            imGroupMember.setIsAdmin(false);
+            imGroupMemberDao.update(imGroupMember);
+        }
+        imGroupCoreService.changeGroupOwner(imGroupId, userId.toString(), adminId.toString());
+
+        imGroupMemberDao.updateAdmin(imGroupId, userId);
+        return true;
+    }
+
+    /**
+     * 加群
+     *
+     * @param imGroupIds    群组ID
+     * @param userId          用户信息
+     * @param roleType      用户类型
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void addImGroup(List<String> imGroupIds, Long  userId, String roleType) {
+        if (CollectionUtils.isEmpty(imGroupIds)) {
+            return;
+        }
+
+        List<ImGroup> groupList = imGroupDao.getByIds(imGroupIds);
+
+        // id 分组
+        Map<String, ImGroup> map = groupList.stream().collect(Collectors.toMap(ImGroup::getId, Function.identity()));
+
+
+        for (String musicGroupId : imGroupIds) {
+            ImGroup imGroup = map.get(musicGroupId);
+            if (imGroup == null) {
+                continue;
+            }
+            try {
+                imGroupCoreService.groupJoin(userId,"",imGroup.getId());
+
+                updateImGroupUserNumber(imGroup.getId());
+            } catch (Exception e) {
+                log.error("加入群聊失败",e);
+            }
+
+        }
+    }
+
+    /**
+     * 查询群组
+     *
+     * @param query 查询条件
+     * @return 群组列表
+     */
+    @Override
+    public List<ImGroup> queryByUserId(ImGroupWrapper.ImQuery query) {
+        return imGroupDao.getByUserId(query);
+    }
+
+    /**
+     * 退出群组
+     *
+     * @param imGroupIds 群组ID
+     * @param userId     用户ID
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void quitGroup(List<String> imGroupIds, Integer userId) {
+        if (CollectionUtils.isEmpty(imGroupIds)) {
+            return;
+        }
+
+        List<ImGroup> groupList = imGroupDao.getByIds(imGroupIds);
+
+        List<ImGroupMember> imGroupMemberList = new ArrayList<>();
+        for (ImGroup imGroup : groupList) {
+            try {
+                imGroupCoreService.groupQuit(userId.longValue(), "",imGroup.getId());
+            } catch (Exception e) {
+                log.error("退出群聊失败",e);
+            }
+            ImGroupMember imGroupMember = new ImGroupMember();
+            imGroupMember.setImGroupId(imGroup.getId());
+            imGroupMember.setUserId(userId);
+            imGroupMemberList.add(imGroupMember);
+        }
+
+        imGroupMemberService.batchDeleteByGroupIdAndUserId(imGroupMemberList);
+        for (String imGroupId : imGroupIds) {
+            updateImGroupUserNumber(imGroupId);
+        }
+    }
+
+
+    /**
+     * 学校人员加入群组
+     *
+     * @param cooperationOrganId 合作机构id
+     * @param imGroupId 群组id
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void schoolJoinGroup(Integer cooperationOrganId, String imGroupId) {
+
+        CooperationOrgan cooperationOrgan = cooperationOrganService.get(cooperationOrganId);
+        if (cooperationOrgan == null) {
+            return;
+        }
+        List<SchoolStaff> schoolStaffs = schoolStaffMapper.getByCoopIdAndType(cooperationOrganId, ESchoolStaffType.ORCHESTRA_LEADER);
+        if (CollectionUtils.isEmpty(schoolStaffs)) {
+            return;
+        }
+
+
+        // 查询群是否存在
+        ImGroup imGroup = imGroupDao.get(imGroupId);
+        if (imGroup == null) {
+            return;
+        }
+
+
+        SchoolStaff schoolStaff = schoolStaffs.get(0);
+
+
+
+        addImGroup(Lists.newArrayList(imGroup.getId()),schoolStaff.getUserId(),ESchoolStaffType.ORCHESTRA_LEADER.getDescribe());
+
+    }
+
+    /**
+     * 解析IM用户规则
+     *
+     * @param imUserId IM用户Id
+     * @return String
+     */
+    @Override
+    public String analysisImUserId(String imUserId) {
+        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && imUserId.startsWith(imConfig.getAppPrefix())) {
+            return imUserId.replace(imConfig.getAppPrefix() + "_", "").split("_")[0];
+        }
+        return imUserId;
+    }
+
+    /**
+     * IM 用户注册
+     *
+     * @param userId 用户Id
+     * @return String
+     */
+    @Override
+    public String getImUserId(String userId, String clientType) {
+        /*if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !userId.startsWith(imConfig.getAppPrefix())) {
+            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId, clientType);
+        }*/
+        return userId;
+    }
+
+    @Override
+    public String getImUserId(Long userId, RoleEnum userRole) {
+        /*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 String.valueOf(userId);
+    }
+
+    @Override
+    public String analysisImUserClient(String imUserId) {
+        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && imUserId.startsWith(imConfig.getAppPrefix())) {
+            imUserId =  imUserId.replace(imConfig.getAppPrefix() + "_", "");
+            String[] s = imUserId.split("_");
+            if (s.length > 1) {
+                return imUserId.replace(s[0] + "_", "");
+            }
+        }
+        return imUserId;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void joinImGroup(String roomId, BasicUserInfo userInfo, String serverProvider, List<Long> studentIds) throws Exception {
+
+        String joinImGroupKey = "joinImGroup:" + roomId;
+        // VIP课或网络课,IM群聊已创建标识
+        Boolean exists = redisTemplate.opsForValue().setIfAbsent(joinImGroupKey, roomId, 1L, TimeUnit.DAYS);
+        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(serverProvider);
+        if (Optional.ofNullable(exists).orElse(false)) {
+            // 群组老师信息
+            List<ImGroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList(ImGroupMemberWrapper.ImGroupMember
+                    .builder()
+                    .userId(userInfo.getUserId())
+                    .imUserId(this.getImUserId(userInfo.getUserId().toString(), "TEACHER"))
+                    .imUserIdFormat(false)
+                    .build());
+
+            for (Long studentId : studentIds) {
+                groupMembers.add(ImGroupMemberWrapper.ImGroupMember
+                        .builder()
+                        .userId(studentId)
+                        .imUserId(this.getImUserId(studentId.toString(),"STUDENT"))
+                        .imUserIdFormat(false)
+                        .build());
+            }
+            try {
+                // 创建群组
+                log.info("createImGroup: roomId = {}, userId = {}", roomId, userInfo.getUserId());
+                if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {
+
+                    // 群组帐号注册
+                    try {
+                        pluginService.register(userInfo.getImUserId(), userInfo.getRealName(), userInfo.getAvatar());
+                    } catch (Exception e) {
+                        log.error("直播房间群主注册失败: userId={}",userInfo.getUserId(), e);
+                    }
+
+                    // 生成群组
+                    pluginService.chatRoomCreate(roomId, roomId, userInfo.getImUserId());
+
+                    // 加入群组成员
+//                    log.info("joinImGroup: roomId = {}, serviceProvider={}, userIds = {}", roomId,serverProvider, groupMembers);
+//                    pluginService.chatRoomGroupJoin(roomId, roomId, groupMembers);
+                } else {
+                    String[] integers = groupMembers.stream().map(e->e.getImUserId()).collect(Collectors.toList()).toArray(new String[]{});
+                    imHelper.joinGroup(integers, roomId, roomId);
+                }
+
+            } catch (Exception e) {
+
+                redisTemplate.delete(joinImGroupKey);
+                // 异常抛出,删除缓存标识
+                throw e;
+            }
+
+        }
+    }
+
+    @Override
+    public RTCRoomPluginService getRTCRoomPluginService(String serviceProvider) {
+        return rtcRoomPluginContext.getPluginService(serviceProvider);
+    }
+
+}

+ 0 - 112
mec-im/src/main/resources/application-template.yml

@@ -1,112 +0,0 @@
-server:
-  port: 9999
-  tomcat:
-    accesslog:
-      enabled: true
-      buffered: true
-      directory: /var/logs
-      file-date-format: -yyyy-MM-dd
-      pattern: common
-      prefix: tomcat-im
-      rename-on-rotate: false
-      request-attributes-enabled: false
-      rotate: true
-      suffix: .log
-      uri-encoding: UTF-8
-  ssl:
-    enabled: false
-    key-alias: sealclass
-    key-store: classpath:sealclass.key
-    key-store-password: 123456
-
-eureka:
-  client:
-    serviceUrl:
-      defaultZone: http://admin:admin123@localhost:8761/eureka/eureka/
-
-spring:
-  application:
-    name: im-server
-
-  datasource:
-    name: test
-    url: jdbc:mysql://47.114.1.200:3306/mec_dev?useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai
-    username: mec_dev
-    password: mec_dev
-    # 使用druid数据源
-    type: com.alibaba.druid.pool.DruidDataSource
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    filters: stat
-    maxActive: 20
-    initialSize: 1
-    maxWait: 60000
-    minIdle: 1
-    timeBetweenEvictionRunsMillis: 60000
-    minEvictableIdleTimeMillis: 300000
-    validationQuery: select 'x'
-    testWhileIdle: true
-    testOnBorrow: false
-    testOnReturn: false
-    poolPreparedStatements: true
-    maxOpenPreparedStatements: 20
-
-  redis:
-    host: 47.114.1.200
-    port: 6379
-    password:
-    database: 0
-    #连接超时时间(毫秒)
-    timeout: 10000
-    pool:
-      #连接池最大连接数(使用负值表示没有限制)
-      max-active: 10
-      #连接池最大阻塞等待时间(使用负值表示没有限制)
-      max-wait: -1
-      #连接池中的最大空闲连接
-      max-idle: 10
-      #连接池中的最小空闲连接
-      min-idle: 0
-
-swagger:
-  base-package: com.ym.controller
-
-##认证
-security:
-  oauth2:
-    client:
-      client-id: app
-      client-secret: app
-    resource:
-      token-info-uri: http://localhost:8001/oauth/check_token
-
-#spring boot admin 相关配置
-management:
-  endpoints:
-    web:
-      exposure:
-        include: "*"
-  endpoint:
-    health:
-      show-details: ALWAYS
-
-cn:
-  rongcloud:
-    jwt:
-      secret: ay9pL#$Ws8Lpapo
-      ttlInMilliSec: -1
-    im:
-      appkey: c9kqb3rdc451j
-      secret: gnskN9VRnbm
-      host: http://api-cn.ronghub.com
-    whiteboard:
-      host: https://sealclass.rongcloud.cn/ewb
-    hereWhite:
-      url: https://cloudcapiv4.herewhite.com
-      token: WHITEcGFydG5lcl9pZD1EUzdrQ3JOenJnRU1Hc1ZnelV5T1czOFl3ZlJuTUF5MjMyMmkmc2lnPTUwMjEwNDVjNzY3Mzc1YjEyZDEzYWY4MDM4M2Q5MTA0YTJhNGQwYjM6YWRtaW5JZD00ODkmcm9sZT1taW5pJmV4cGlyZV90aW1lPTE2MDI0MDIzMDUmYWs9RFM3a0NyTnpyZ0VNR3NWZ3pVeU9XMzhZd2ZSbk1BeTIzMjJpJmNyZWF0ZV90aW1lPTE1NzA4NDUzNTMmbm9uY2U9MTU3MDg0NTM1Mjc1MzAw
-    web:
-      enableCors: true
-    room:
-      maxCount: 16
-      taskTtl: 30000
-      roomTtl: 7200000
-      userIMOfflineKickTtl: 300000

+ 1 - 0
mec-im/src/main/resources/bootstrap-dev.properties

@@ -11,3 +11,4 @@ spring.cloud.nacos.config.file-extension=yaml
 spring.cloud.nacos.config.refresh.enabled=true
 #\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
 spring.cloud.nacos.config.enabled=true
+logging.config=classpath:logback-dev.xml

+ 0 - 16
mec-im/src/main/resources/bootstrap-dev_server.properties

@@ -1,16 +0,0 @@
-#\u6307\u5b9a\u5f00\u53d1\u73af\u5883
-#spring.profiles.active=dev
-#\u670d\u52a1\u5668\u5730\u5740
-spring.cloud.nacos.config.server-addr=47.114.1.200:8848
-#\u9ed8\u8ba4\u4e3aPublic\u547d\u540d\u7a7a\u95f4,\u53ef\u4ee5\u7701\u7565\u4e0d\u5199
-spring.cloud.nacos.config.namespace=fd352683-69df-439a-802f-c44f0c21329c
-#\u6307\u5b9a\u914d\u7f6e\u7fa4\u7ec4 --\u5982\u679c\u662fPublic\u547d\u540d\u7a7a\u95f4 \u5219\u53ef\u4ee5\u7701\u7565\u7fa4\u7ec4\u914d\u7f6e
-spring.cloud.nacos.config.group=DEFAULT_GROUP
-#\u6587\u4ef6\u540d -- \u5982\u679c\u6ca1\u6709\u914d\u7f6e\u5219\u9ed8\u8ba4\u4e3a ${spring.appliction.name}
-spring.cloud.nacos.config.prefix=im
-#\u6307\u5b9a\u6587\u4ef6\u540e\u7f00
-spring.cloud.nacos.config.file-extension=yaml
-#\u662f\u5426\u52a8\u6001\u5237\u65b0
-spring.cloud.nacos.config.refresh.enabled=true
-#\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
-spring.cloud.nacos.config.enabled=true

+ 1 - 0
mec-im/src/main/resources/bootstrap-test.properties

@@ -14,3 +14,4 @@ spring.cloud.nacos.config.file-extension=yaml
 spring.cloud.nacos.config.refresh.enabled=true
 #\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
 spring.cloud.nacos.config.enabled=true
+logging.config=classpath:logback-test-env.xml

+ 37 - 0
mec-im/src/main/resources/logback-dev.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+    <property name="LOG_HOME" value="/mdata/mec-dev/logs/im-%d{yyyy-MM-dd_HH}-%i.log" />
+    <property name="CONSOLE_LOG_PATTERN"
+              value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder charset="UTF-8">
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="file"
+              class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <FileNamePattern>${LOG_HOME}</FileNamePattern>
+            <MaxHistory>90</MaxHistory>
+            <TimeBasedFileNamingAndTriggeringPolicy
+                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <MaxFileSize>20MB</MaxFileSize>
+            </TimeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="com.ym.mec" level="INFO" />
+
+    <root level="INFO">
+        <appender-ref ref="stdout" />
+        <appender-ref ref="file" />
+    </root>
+
+</configuration>

+ 37 - 0
mec-im/src/main/resources/logback-test-env.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+    <property name="LOG_HOME" value="/mdata/mec-test/logs/im-%d{yyyy-MM-dd_HH}-%i.log" />
+    <property name="CONSOLE_LOG_PATTERN"
+              value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder charset="UTF-8">
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="file"
+              class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <FileNamePattern>${LOG_HOME}</FileNamePattern>
+            <MaxHistory>90</MaxHistory>
+            <TimeBasedFileNamingAndTriggeringPolicy
+                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <MaxFileSize>20MB</MaxFileSize>
+            </TimeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="com.ym.mec" level="INFO" />
+
+    <root level="INFO">
+        <appender-ref ref="stdout" />
+        <appender-ref ref="file" />
+    </root>
+
+</configuration>

+ 37 - 0
mec-mall/mall-admin/src/main/resources/logback-dev.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<property name="LOG_HOME" value="/mdata/mec-dev/logs/mall-admin-%d{yyyy-MM-dd_HH}-%i.log" />
+	<property name="CONSOLE_LOG_PATTERN"
+			  value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder charset="UTF-8">
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="file"
+			  class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>${LOG_HOME}</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+					class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<logger name="com.yonge" level="INFO" />
+
+	<root level="INFO">
+		<appender-ref ref="stdout" />
+		<appender-ref ref="file" />
+	</root>
+
+</configuration>

+ 37 - 0
mec-mall/mall-portal/src/main/resources/logback-dev.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<property name="LOG_HOME" value="/mdata/mec-dev/logs/mall-portal-%d{yyyy-MM-dd_HH}-%i.log" />
+	<property name="CONSOLE_LOG_PATTERN"
+			  value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder charset="UTF-8">
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="file"
+			  class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>${LOG_HOME}</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+					class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<logger name="com.yonge" level="info" />
+
+	<root level="INFO">
+		<appender-ref ref="stdout" />
+		<appender-ref ref="file" />
+	</root>
+
+</configuration>

+ 37 - 0
mec-task/src/main/resources/logback-dev.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<property name="LOG_HOME" value="/mdata/mec-dev/logs/task-%d{yyyy-MM-dd_HH}-%i.log" />
+	<property name="CONSOLE_LOG_PATTERN"
+			  value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder charset="UTF-8">
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="file"
+			  class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>${LOG_HOME}</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+					class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<logger name="com.ym.mec" level="debug" />
+
+	<root level="INFO">
+		<appender-ref ref="stdout" />
+		<appender-ref ref="file" />
+	</root>
+
+</configuration>

+ 0 - 143
mec-websocket/src/main/resources/application-template.yml

@@ -1,143 +0,0 @@
-server:
-  port: 8005
-  connection-timeout: 60000
-  tomcat:
-    min-spare-threads: 50
-    max-threads: 500
-    accesslog:
-      enabled: true
-      buffered: true
-      directory: /var/logs
-      file-date-format: -yyyy-MM-dd
-      pattern: common
-      prefix: tomcat-websocket
-      rename-on-rotate: false
-      request-attributes-enabled: false
-      rotate: true
-      suffix: .log
-
-eureka:
-  client:
-    serviceUrl:
-      defaultZone: http://admin:admin123@localhost:8761/eureka/eureka/
-    instance:
-      lease-renewal-interval-in-seconds: 5
-      prefer-ip-address: true
-
-spring:
-  servlet:
-    multipart:
-      max-file-size: 150MB
-      max-request-size: 150MB
-  application:
-    name: websocket-server
-
-  data:
-    mongodb:
-      uri: mongodb://root:dayayuemeng2019@47.114.1.200:27017/mec_dev
-
-  datasource:
-    name: test
-    url: jdbc:mysql://rm-bp13774a2o87ti8c7mo.mysql.rds.aliyuncs.com:3306/mec_pro?useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
-    username: mec_pro
-    password: mec@Pro9
-    # 使用druid数据源
-    type: com.alibaba.druid.pool.DruidDataSource
-    druid:
-      connection-init-sqls: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    filters: stat
-    maxActive: 50
-    initialSize: 10
-    maxWait: 60000
-    minIdle: 1
-    timeBetweenEvictionRunsMillis: 60000
-    minEvictableIdleTimeMillis: 300000
-    validationQuery: select 'x'
-    testWhileIdle: true
-    testOnBorrow: false
-    testOnReturn: false
-    poolPreparedStatements: true
-    maxOpenPreparedStatements: 20
-
-  redis:
-    host: 47.114.1.200
-    port: 6379
-    password: dyym
-    database: 1
-    #连接超时时间(毫秒)
-    timeout: 10000
-    jedis:
-      pool:
-        #连接池最大连接数(使用负值表示没有限制)
-        max-active: 20
-        #连接池最大阻塞等待时间(使用负值表示没有限制)
-        max-wait: 10000
-        #连接池中的最大空闲连接
-        max-idle: 10
-        #连接池中的最小空闲连接
-        min-idle: 5
-
-mybatis:
-  mapperLocations: classpath:config/mybatis/*.xml
-#  configuration:
-#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
-
-swagger:
-  base-package: com.ym.mec.web.controller
-
-##认证
-security:
-  oauth2:
-    client:
-      client-id: app
-      client-secret: app
-    resource:
-      token-info-uri: http://localhost:8001/oauth/check_token
-
-#spring boot admin 相关配置
-management:
-  endpoints:
-    web:
-      exposure:
-        include: "*"
-  endpoint:
-    health:
-      show-details: ALWAYS
-
-
-ribbon:
-  ReadTimeout: 600000
-  ConnectTimeout: 60000
-
-logging:
-  level:
-    com.ym.mec.auth.api.client.SysUserFeignService: INFO
-
-message:
-  debugMode: true
-
-##支付流水隐藏
-payment:
-  hiddenMode: false
-  #隐藏的支付方式
-  channel: YQPAY
-
-eseal:
-  tsign:
-    projectid: 4438776254
-    projectSecret: a94cf63d6361084d232f345d71321691
-    apisUrl: http://smlitsm.tsign.cn:8080/tgmonitor/rest/app!getAPIInfo2
-
-push:
-  jiguang:
-    reqURL: https://api.jpush.cn/v3/push
-    appKey:
-      student: 0e7422e1d6e73637e678716a
-      teacher: 7e0282ca92c12c8c45a93bb3
-      system: 496fc1007dea59b1b4252d2b
-    masterSecret:
-      student: c2361016604eab56ab2db2ac
-      teacher: d47430e2f4755ef5dc050ac5
-      system: a5e51e9cdb25417463afbf7a
-    apns_production: false

+ 0 - 16
mec-websocket/src/main/resources/bootstrap-dev_server.properties

@@ -1,16 +0,0 @@
-#\u6307\u5b9a\u5f00\u53d1\u73af\u5883
-#spring.profiles.active=dev
-#\u670d\u52a1\u5668\u5730\u5740
-spring.cloud.nacos.config.server-addr=47.114.1.200:8848
-#\u9ed8\u8ba4\u4e3aPublic\u547d\u540d\u7a7a\u95f4,\u53ef\u4ee5\u7701\u7565\u4e0d\u5199
-spring.cloud.nacos.config.namespace=fd352683-69df-439a-802f-c44f0c21329c
-#\u6307\u5b9a\u914d\u7f6e\u7fa4\u7ec4 --\u5982\u679c\u662fPublic\u547d\u540d\u7a7a\u95f4 \u5219\u53ef\u4ee5\u7701\u7565\u7fa4\u7ec4\u914d\u7f6e
-spring.cloud.nacos.config.group=DEFAULT_GROUP
-#\u6587\u4ef6\u540d -- \u5982\u679c\u6ca1\u6709\u914d\u7f6e\u5219\u9ed8\u8ba4\u4e3a ${spring.appliction.name}
-spring.cloud.nacos.config.prefix=websocket
-#\u6307\u5b9a\u6587\u4ef6\u540e\u7f00
-spring.cloud.nacos.config.file-extension=yaml
-#\u662f\u5426\u52a8\u6001\u5237\u65b0
-spring.cloud.nacos.config.refresh.enabled=true
-#\u662f\u5426\u542f\u7528nacos\u914d\u7f6e\u4e2d\u5fc3
-spring.cloud.nacos.config.enabled=true

+ 58 - 0
mec-websocket/src/main/resources/logback-dev.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<property name="LOG_HOME" value="/mdata/mec-dev/logs/websocket-%d{yyyy-MM-dd_HH}-%i.log" />
+	<property name="CONSOLE_LOG_PATTERN"
+			  value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
+
+	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder charset="UTF-8">
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="file"
+			  class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>${LOG_HOME}</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+					class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<appender name="messagefile"
+			  class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+			<FileNamePattern>/mdata/logs/web-message-%d{yyyy-MM-dd_HH}-%i.log</FileNamePattern>
+			<MaxHistory>90</MaxHistory>
+			<TimeBasedFileNamingAndTriggeringPolicy
+					class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+				<MaxFileSize>20MB</MaxFileSize>
+			</TimeBasedFileNamingAndTriggeringPolicy>
+		</rollingPolicy>
+
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+		</encoder>
+	</appender>
+
+	<logger name="com.ym.mec" level="INFO" />
+
+	<logger name="com.ym.mec.thirdparty" level="INFO"
+			additivity="false">
+		<appender-ref ref="messagefile" />
+	</logger>
+
+	<root level="INFO">
+		<appender-ref ref="stdout" />
+		<appender-ref ref="file" />
+	</root>
+
+</configuration>

+ 15 - 12
pom.xml

@@ -26,6 +26,16 @@
 
 	<dependencyManagement>
 		<dependencies>
+			<!--<dependency>
+				<groupId>com.alibaba.cloud</groupId>
+				<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+				<version>2.2.1.RELEASE</version>
+			</dependency>-->
+			<dependency>
+				<groupId>org.springframework.cloud</groupId>
+				<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+				<version>0.9.0.RELEASE</version>
+			</dependency>
 			<!--֧��Spring Boot 2.1.X -->
 			<dependency>
 				<groupId>org.springframework.boot</groupId>
@@ -96,19 +106,19 @@
 				<artifactId>mec-util</artifactId>
 				<version>1.0</version>
 			</dependency>
-			
+
 			<dependency>
 				<groupId>com.yonge.mongodb</groupId>
 				<artifactId>mongo-db</artifactId>
 				<version>1.0</version>
 			</dependency>
-		
+
 			<dependency>
 				<groupId>com.yonge.datasource</groupId>
 				<artifactId>dynamic-datasource</artifactId>
 				<version>1.0</version>
 			</dependency>
-		
+
 			<dependency>
 				<groupId>com.yonge.log</groupId>
 				<artifactId>audit-log</artifactId>
@@ -128,13 +138,6 @@
 			</dependency>
 
 			<dependency>
-				<groupId>org.springframework.cloud</groupId>
-				<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
-				<version>0.9.0.RELEASE</version>
-			</dependency>
-
-
-			<dependency>
 				<groupId>io.zipkin.java</groupId>
 				<artifactId>zipkin-server</artifactId>
 				<version>${zipkin.version}</version>
@@ -440,7 +443,7 @@
 		<module>mec-client-api</module>
 		<module>mec-application</module>
 		<module>mec-biz</module>
-		<module>dynamic-datasource</module>
-		<module>audio-analysis</module>
+	  	<module>dynamic-datasource</module>
+	  	<module>audio-analysis</module>
 		<module>mec-mall</module>
 	</modules></project>