feat: (REQ-3057) 创建群聊校验优化-超过人数/重复建群
feat: (REQ-3057) 创建群聊返回参数优化 feat: (REQ-3057) 创建群聊告警钉钉群/投诉/rpc封装优化 feat: (REQ-3057) 创建群聊告警钉钉群/投诉/rpc封装优化 feat: (REQ-3057) 创建群聊告警钉钉群/投诉/rpc封装优化 feat: (REQ-3057) 监控群主变更逻辑优化 feat: (REQ-3057) 监控群主变更逻辑优化 feat: (REQ-3057) 监控群主变更逻辑优化 feat: (REQ-3057) 监控群主变更逻辑优化 feat: (REQ-3057) 监控群主变更逻辑优化
This commit is contained in:
parent
be26aa75e9
commit
1b7337b987
@ -48,6 +48,10 @@
|
||||
<groupId>cn.axzo.apollo</groupId>
|
||||
<artifactId>apollo-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>event-hub-api</artifactId>
|
||||
<groupId>cn.axzo.event-hub</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
@ -2,7 +2,9 @@ package cn.axzo.im.center.api.feign;
|
||||
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupQueryReq;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupCreateResp;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupQueryResp;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -23,5 +25,11 @@ public interface ChatGroupApi {
|
||||
@PostMapping("api/im/chat/group/create")
|
||||
ApiResult<ChatGroupCreateResp> chatGroupCreate(@RequestBody @Validated ChatGroupCreateReq chatGroupCreateReq);
|
||||
|
||||
/**
|
||||
* 获取群聊
|
||||
*/
|
||||
@PostMapping("api/im/chat/group/query")
|
||||
ApiResult<ChatGroupQueryResp> chatGroupQuery(@RequestBody @Validated ChatGroupQueryReq chatGroupQueryReq);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package cn.axzo.im.center.api.feign;
|
||||
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ComplaintCreateReq;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -20,7 +21,7 @@ public interface ComplaintApi {
|
||||
* 投诉
|
||||
*/
|
||||
@PostMapping("api/im/complaint/create")
|
||||
ApiResult<Void> complaintCreate(@RequestBody @Validated ChatGroupCreateReq chatGroupCreateReq);
|
||||
ApiResult<Void> complaintCreate(@RequestBody @Validated ComplaintCreateReq req);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
package cn.axzo.im.center.api.vo.req;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
@ -21,7 +23,7 @@ import java.io.Serializable;
|
||||
public class ChatGroupCreateReq implements Serializable {
|
||||
|
||||
/**
|
||||
* 群类型,项目专属群:workspace
|
||||
* 群类型,项目专属群:WORKSPACE
|
||||
*/
|
||||
@NotEmpty(message = "群类型不能为空")
|
||||
private String groupType;
|
||||
@ -46,13 +48,33 @@ public class ChatGroupCreateReq implements Serializable {
|
||||
private Long workspaceId;
|
||||
|
||||
/**
|
||||
* 人群类型,项目:workspace,单位:ou,班组:team
|
||||
* 人群类型,项目:WORKSPACE,单位:OU,班组:TEAM
|
||||
*/
|
||||
@NotEmpty(message = "人群类型不能为空")
|
||||
private String crowType;
|
||||
@NotNull(message = "人群类型不能为空")
|
||||
private CrowTypeEnum crowType;
|
||||
|
||||
/**
|
||||
* 群主账号,accid,最大长度 32 位字符
|
||||
*/
|
||||
private Long owner;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private Long creator;
|
||||
|
||||
private Long ouId;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public enum CrowTypeEnum {
|
||||
WORKSPACE("workspace", "项目"),
|
||||
OU("ou", "单位"),
|
||||
TEAM("team", "班组"),
|
||||
;
|
||||
|
||||
private String code;
|
||||
|
||||
private String desc;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
package cn.axzo.im.center.api.vo.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatGroupGenericSearchReq {
|
||||
|
||||
private Long workspaceId;
|
||||
|
||||
private Long ouId;
|
||||
|
||||
private Long teamId;
|
||||
|
||||
private ChatGroupCreateReq.CrowTypeEnum crowType;
|
||||
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
package cn.axzo.im.center.api.vo.req;
|
||||
|
||||
public class ChatGroupListReq {
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package cn.axzo.im.center.api.vo.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 群聊创建请求
|
||||
* @author xudawei
|
||||
* @date 2024/11/04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatGroupQueryReq implements Serializable {
|
||||
|
||||
/**
|
||||
* 群 ID 列表,如["3083","3084"],一次最多查询 10 个群,最大长度 1024 位字符
|
||||
*/
|
||||
@NotEmpty(message = "tids不能为空")
|
||||
private List<String> tids;
|
||||
|
||||
|
||||
/**
|
||||
* 1,表示带上群成员列表;0,表示不带群成员列表,只返回群信息
|
||||
*/
|
||||
@NotNull(message = "ope不能为空")
|
||||
private Integer ope;
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package cn.axzo.im.center.api.vo.req;
|
||||
|
||||
import cn.axzo.im.center.common.enums.ChatGroupStatusEnum;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupUserTypeEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatGroupUserGenericSearchReq {
|
||||
|
||||
/**
|
||||
* 项目Id
|
||||
*/
|
||||
private Long workspaceId;
|
||||
/**
|
||||
* 单位Id
|
||||
*/
|
||||
private Long ouId;
|
||||
|
||||
/**
|
||||
* 班组Id
|
||||
*/
|
||||
private Long teamId;
|
||||
|
||||
/**
|
||||
* 人群
|
||||
*/
|
||||
private ChatGroupCreateReq.CrowTypeEnum crowType;
|
||||
|
||||
/**
|
||||
* 群聊Id
|
||||
*/
|
||||
private Long chatGroupId;
|
||||
|
||||
/**
|
||||
* 网易云信唯一标识,网易返回
|
||||
*/
|
||||
private String tid;
|
||||
/**
|
||||
* IM账号Id
|
||||
*/
|
||||
private String accId;
|
||||
|
||||
/**
|
||||
* 类型,OWNER:群主;USER:普通用户
|
||||
*/
|
||||
private ChatGroupUserTypeEnum type;
|
||||
|
||||
/**
|
||||
* 状态,SUCCESS:成功;FAIL:失败
|
||||
*/
|
||||
private ChatGroupStatusEnum status;
|
||||
|
||||
}
|
||||
@ -1,8 +1,10 @@
|
||||
package cn.axzo.im.center.api.vo.req;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
@ -25,14 +27,39 @@ public class ComplaintCreateReq {
|
||||
private String complaintContent;
|
||||
|
||||
/**
|
||||
* 类型,私聊:private,群聊:group
|
||||
* 类型,私聊:PRIVATE,群聊:GROUP
|
||||
*/
|
||||
@NotNull(message = "类型不能为空")
|
||||
private String type;
|
||||
private ChatTypeEnum type;
|
||||
|
||||
/**
|
||||
* 发送人
|
||||
*/
|
||||
@NotNull(message = "发送人不能为空")
|
||||
private String fromId;
|
||||
|
||||
/**
|
||||
* 群聊Id或者IM账号Id,根据type而订
|
||||
*/
|
||||
@NotNull(message = "群聊Id或者IM账号Id,不能为空")
|
||||
private String t_acc_id;
|
||||
private String taccId;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private Long creator;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public enum ChatTypeEnum {
|
||||
PRIVATE("private", "私聊"),
|
||||
GROUP("group", "群聊"),
|
||||
;
|
||||
|
||||
private String code;
|
||||
|
||||
private String desc;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -17,8 +17,33 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor
|
||||
public class ChatGroupCreateResp {
|
||||
|
||||
/**
|
||||
* code
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 网易云信服务器产生,群唯一标识
|
||||
*/
|
||||
private String tid;
|
||||
|
||||
private JSONArray faccid;
|
||||
|
||||
/**
|
||||
* 群名称
|
||||
*/
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 群头像
|
||||
*/
|
||||
private String avatarUrl;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,161 @@
|
||||
package cn.axzo.im.center.api.vo.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 创建群聊
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatGroupQueryResp {
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 网易云信服务器产生,群唯一标识
|
||||
*/
|
||||
private List<TInfo> tinfos;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class TInfo {
|
||||
/**
|
||||
* 群名称
|
||||
*/
|
||||
private String tname;
|
||||
/**
|
||||
* 群头像
|
||||
*/
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 群主用户帐号
|
||||
*/
|
||||
private String owner;
|
||||
/**
|
||||
* 群成员最大数量
|
||||
*/
|
||||
private Integer maxusers;
|
||||
|
||||
/**
|
||||
* 群 ID
|
||||
*/
|
||||
private Long tid;
|
||||
|
||||
/**
|
||||
* 当前群成员数量
|
||||
*/
|
||||
private Integer size;
|
||||
|
||||
/**
|
||||
* 群公告
|
||||
*/
|
||||
private String announcement;
|
||||
|
||||
/**
|
||||
* 群介绍
|
||||
*/
|
||||
private String intro;
|
||||
|
||||
/**
|
||||
* 申请入群的验证方式
|
||||
* 0,不用验证;1,需要验证;2,不允许任何人加入
|
||||
*/
|
||||
private Integer joinmode;
|
||||
|
||||
/**
|
||||
* 群创建完成后,邀请入群时是否需要被邀请人的同意
|
||||
* 0,需要同意(默认);1,不需要同意
|
||||
*/
|
||||
private Integer beinvitemode;
|
||||
|
||||
/**
|
||||
* 邀请权限,即谁可以邀请他人入群
|
||||
* 0,群主和管理员(默认);1,所有人
|
||||
*/
|
||||
private Integer invitemode;
|
||||
|
||||
/**
|
||||
* 客户端修改群信息权限,即谁可以修改群信息
|
||||
* 0,群主和管理员(默认);1,所有人
|
||||
*/
|
||||
private Integer uptinfomode;
|
||||
|
||||
/**
|
||||
* 客户端修改群自定义属性权限,即谁可以修改群自定义属性
|
||||
* 0,群主和管理员(默认);1,所有人
|
||||
*/
|
||||
private Integer upcustommode;
|
||||
|
||||
/**
|
||||
* 群禁言类型
|
||||
* 0,解除禁言;1,禁言普通成员;3,禁言整个群(包括群主)
|
||||
*/
|
||||
private Integer muteType;
|
||||
|
||||
/**
|
||||
* 群通知消息是否关闭在线发送(开启该功能才会有该字段)
|
||||
*/
|
||||
private Boolean isNotifyCloseOnline;
|
||||
|
||||
/**
|
||||
* 群通知消息是否关闭持久化存储(开启该功能才会有该字段)
|
||||
*/
|
||||
private Boolean isNotifyClosePersistent;
|
||||
|
||||
/**
|
||||
* 自定义高级群扩展属性
|
||||
*/
|
||||
private String custom;
|
||||
|
||||
/**
|
||||
* 客户端自定义字段
|
||||
*/
|
||||
private String clientCustom;
|
||||
|
||||
/**
|
||||
* 是否全员禁言
|
||||
*/
|
||||
private Boolean mute;
|
||||
|
||||
/**
|
||||
* 管理员账号
|
||||
*/
|
||||
private String admins;
|
||||
|
||||
/**
|
||||
* 群成员列表
|
||||
*/
|
||||
private String members;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Long createtime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Long updatetime;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package cn.axzo.im.center.common.enums;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
|
||||
/**
|
||||
* 群聊状态
|
||||
*
|
||||
* @author xudawei
|
||||
* @date 2024/11/12
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public enum ChatGroupStatusEnum {
|
||||
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
SUCCESS("success", "成功"),
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
FAIL("fail", "失败"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
|
||||
private final String message;
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package cn.axzo.im.center.common.enums;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
|
||||
/**
|
||||
* 群聊用户类型
|
||||
*
|
||||
* @author xudawei
|
||||
* @date 2024/11/13
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public enum ChatGroupUserTypeEnum {
|
||||
|
||||
/**
|
||||
* 群主
|
||||
*/
|
||||
OWNER("owner", "群主"),
|
||||
/**
|
||||
* 普通用户
|
||||
*/
|
||||
USER("user", "普通用户"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
|
||||
private final String message;
|
||||
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package cn.axzo.im.center.common.enums;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
|
||||
/**
|
||||
* 群聊状态
|
||||
*
|
||||
* @author xudawei
|
||||
* @date 2024/11/12
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public enum OperateLogTypeEnum {
|
||||
|
||||
/**
|
||||
* 群聊新增
|
||||
*/
|
||||
GROUP_ADD("groupAdd", "群聊新增"),
|
||||
/**
|
||||
* 群聊解散
|
||||
*/
|
||||
GROUP_DELETE("groupDelete", "群聊解散"),
|
||||
/**
|
||||
* 人员新增群聊
|
||||
*/
|
||||
USER_ENTER_CHAT_GROUP("userEnterChatGroup", "人员进入群聊"),
|
||||
/**
|
||||
* 人员退出群聊
|
||||
*/
|
||||
USER_EXIT_CHAT_GROUP("userExitChatGroup", "人员退出群聊"),
|
||||
|
||||
/**
|
||||
* 更改群主
|
||||
*/
|
||||
CHANGE_OWNER("changeOwner", "更改群主"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
|
||||
private final String message;
|
||||
|
||||
}
|
||||
@ -109,6 +109,12 @@
|
||||
<dependency>
|
||||
<groupId>cn.axzo.maokai</groupId>
|
||||
<artifactId>maokai-api</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>event-hub-api</artifactId>
|
||||
<groupId>cn.axzo.event-hub</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@ -125,6 +131,12 @@
|
||||
<groupId>cn.axzo.tyr</groupId>
|
||||
<artifactId>tyr-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
package cn.axzo.im;
|
||||
|
||||
import cn.axzo.framework.data.mybatisplus.config.MybatisPlusAutoConfiguration;
|
||||
import cn.axzo.im.config.RocketMQEventConfiguration;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
@Slf4j
|
||||
//@SpringBootApplication(scanBasePackages = "cn.axzo", exclude = MybatisPlusAutoConfiguration.class)
|
||||
//@EnableFeignClients(basePackages = {"cn.axzo"})
|
||||
//@MapperScan(value = {"cn.axzo.im.dao.mapper"})
|
||||
//@EnableDiscoveryClient
|
||||
//@Import(RocketMQEventConfiguration.class)
|
||||
public class ImCenterDevApplication {
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("spring.profiles.active","dev");
|
||||
System.setProperty("NACOS_HOST","https://dev-nacos.axzo.cn");
|
||||
System.setProperty("NACOS_PORT","443");
|
||||
System.setProperty("NACOS_NAMESPACE_ID","35eada10-9574-4db8-9fea-bc6a4960b6c7");
|
||||
System.setProperty("CUSTOM_ENV","dev");
|
||||
|
||||
System.setProperty("spring.redis.port","6379");
|
||||
System.setProperty("spring.redis.host","172.16.2.219");
|
||||
System.setProperty("spring.redis.password","!rHV2!fctYtV4vF");
|
||||
System.setProperty("xxl.job.admin.addresses","http://dev-xxl-job.axzo.cn/xxl-job-admin");
|
||||
System.setProperty("rocketmq.name-server", "172.16.2.82:9876");
|
||||
SpringApplication application = new SpringApplication(ImCenterDevApplication.class);
|
||||
ApplicationContext applicationContext = application.run(args);
|
||||
Environment env = applicationContext.getEnvironment();
|
||||
log.info(
|
||||
"--------------------------------------------------------------------------------------------------------------------\n" +
|
||||
"Application 【{}】 is running on 【{}】 environment!\n" +
|
||||
"Api Local: \thttp://127.0.0.1:{}\n" +
|
||||
"Mysql: \t{}\t username:{}\n" +
|
||||
"Redis: \t{}:{}\t database:{}\n" +
|
||||
"RabbitMQ: \t{}\t username:{}",
|
||||
env.getProperty("spring.application.name"),
|
||||
env.getProperty("spring.profiles.active"),
|
||||
env.getProperty("server.port"),
|
||||
env.getProperty("spring.datasource.url"),
|
||||
env.getProperty("spring.datasource.username"),
|
||||
env.getProperty("spring.redis.host"),
|
||||
env.getProperty("spring.redis.port"),
|
||||
env.getProperty("spring.redis.database"),
|
||||
env.getProperty("spring.rabbitmq.addresses"),
|
||||
env.getProperty("spring.rabbitmq.username") +
|
||||
"\n----------------------------------------------------------");
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,11 @@
|
||||
package cn.axzo.im.channel;
|
||||
|
||||
import cn.axzo.im.channel.netease.dto.ChangeOwnerRequest;
|
||||
import cn.axzo.im.channel.netease.dto.ChangeOwnerResponse;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateRequest;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateResponse;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupQueryResponse;
|
||||
import cn.axzo.im.channel.netease.dto.KickChatGroupRequest;
|
||||
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchRequest;
|
||||
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchResponse;
|
||||
import cn.axzo.im.channel.netease.dto.MessageCustomDispatchRequest;
|
||||
@ -15,6 +19,7 @@ import cn.axzo.im.channel.netease.dto.UserAddChatGroupRequest;
|
||||
import cn.axzo.im.channel.netease.dto.UserAddChatGroupResponse;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* im-center
|
||||
@ -80,6 +85,11 @@ public interface IMChannelProvider {
|
||||
*/
|
||||
RegisterResponse updateAccountProfile(RegisterUpdateRequest updateProfile);
|
||||
|
||||
/**
|
||||
* 踢人出群
|
||||
*/
|
||||
UserAddChatGroupResponse kickChatGroup(KickChatGroupRequest request);
|
||||
|
||||
/**
|
||||
* 创建群聊
|
||||
*/
|
||||
@ -89,4 +99,16 @@ public interface IMChannelProvider {
|
||||
* 用户加入群聊
|
||||
*/
|
||||
UserAddChatGroupResponse userAddChatGroup(UserAddChatGroupRequest request);
|
||||
|
||||
/**
|
||||
* 获取群聊
|
||||
* @param tids 群 ID 列表
|
||||
* @param ope 1,表示带上群成员列表;0,表示不带群成员列表,只返回群信息
|
||||
*/
|
||||
ChatGroupQueryResponse chatGroupQueryByTids(List<String> tids, Integer ope);
|
||||
|
||||
/**
|
||||
* 转让群主
|
||||
*/
|
||||
ChangeOwnerResponse changeOwner(ChangeOwnerRequest request);
|
||||
}
|
||||
|
||||
@ -3,8 +3,12 @@ package cn.axzo.im.channel.netease;
|
||||
import cn.axzo.basics.common.exception.ServiceException;
|
||||
import cn.axzo.basics.common.util.AssertUtil;
|
||||
import cn.axzo.im.channel.IMChannelProvider;
|
||||
import cn.axzo.im.channel.netease.dto.ChangeOwnerRequest;
|
||||
import cn.axzo.im.channel.netease.dto.ChangeOwnerResponse;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateRequest;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateResponse;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupQueryResponse;
|
||||
import cn.axzo.im.channel.netease.dto.KickChatGroupRequest;
|
||||
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchRequest;
|
||||
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchResponse;
|
||||
import cn.axzo.im.channel.netease.dto.MessageCustomDispatchRequest;
|
||||
@ -24,6 +28,7 @@ import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -34,7 +39,9 @@ import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@ -68,6 +75,21 @@ public class NimChannelService implements IMChannelProvider {
|
||||
*/
|
||||
private static final String USER_ADD_CHAT_GROUP = "https://api.netease.im/nimserver/team/add.action";
|
||||
|
||||
/**
|
||||
* 踢人出群
|
||||
*/
|
||||
private static final String KICK_CHAT_GROUP = "https://api.netease.im/nimserver/team/kick.action";
|
||||
|
||||
/**
|
||||
* 获取群聊
|
||||
*/
|
||||
private static final String CHAT_GROUP_QUERY = "https://api.netease.im/nimserver/team/query.action";
|
||||
|
||||
/**
|
||||
* 转让群主
|
||||
*/
|
||||
private static final String CHANGE_OWNER = "https://api.netease.im/nimserver/team/changeOwner.action";
|
||||
|
||||
public static final int SUCCESS_CODE = 200;
|
||||
|
||||
public static final int RATE_LIMITED_CODE = 416;
|
||||
@ -75,10 +97,6 @@ public class NimChannelService implements IMChannelProvider {
|
||||
private static final int NIM_ACCOUNT_ALREADY_REGISTER = 414;
|
||||
|
||||
private static final String PROVIDER_NAME = "NIM";
|
||||
/**
|
||||
* 消息接收者的网易云信IM账号(accid)列表上限是500人,但是返回msgid最多100人,故目前设置100人
|
||||
*/
|
||||
private static final int NIM_MSG_BATCH_MAX_NUM = 100;
|
||||
/**
|
||||
* 目前支持 100、自定义消息
|
||||
*/
|
||||
@ -359,19 +377,22 @@ public class NimChannelService implements IMChannelProvider {
|
||||
HttpResponse response = HttpRequest.post(CHAT_GROUP_CREATE).addHeaders(authHeaderMap)
|
||||
.form(paramMap).timeout(5000).execute();
|
||||
String result = response.body();
|
||||
if (response.getStatus() == SUCCESS_CODE) {
|
||||
log.info("chatGroupCreate-请求网易云信,result:{}", result);
|
||||
if (response.getStatus() != SUCCESS_CODE) {
|
||||
log.error("chatGroupCreate-请求网易云信Server:{},异常:{}", CHAT_GROUP_CREATE, result);
|
||||
ChatGroupCreateResponse chatGroupCreateResponse = JSONUtil.toBean(result, ChatGroupCreateResponse.class);
|
||||
throw new ServiceException("创建群聊异常," + chatGroupCreateResponse.getDesc());
|
||||
}
|
||||
ChatGroupCreateResponse chatGroupCreateResponse = JSONUtil.toBean(result, ChatGroupCreateResponse.class);
|
||||
if (chatGroupCreateResponse == null) {
|
||||
return ChatGroupCreateResponse.builder().desc("chatGroupCreate-请求网易云信Server异常[" + result + "],请联系管理员!").build();
|
||||
log.warn("chatGroupCreate-请求网易云信Server:{},返回异常:{}", CHAT_GROUP_CREATE, result);
|
||||
throw new ServiceException("创建群聊异常," + chatGroupCreateResponse.getDesc());
|
||||
}
|
||||
if (chatGroupCreateResponse.getCode() != SUCCESS_CODE) {
|
||||
log.warn("chatGroupCreate-请求网易云信Server:{},返回异常:{}", CHAT_GROUP_CREATE, result);
|
||||
throw new ServiceException("创建群聊异常," + chatGroupCreateResponse.getDesc());
|
||||
}
|
||||
return chatGroupCreateResponse;
|
||||
} else {
|
||||
log.error("chatGroupCreate-请求网易云信Server:{},异常:{}", CHAT_GROUP_CREATE, result);
|
||||
}
|
||||
return ChatGroupCreateResponse.builder().desc("chatGroupCreate-请求网易云信Server异常,请联系管理员!").build();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -399,6 +420,10 @@ public class NimChannelService implements IMChannelProvider {
|
||||
*/
|
||||
@Override
|
||||
public UserAddChatGroupResponse userAddChatGroup(UserAddChatGroupRequest request) {
|
||||
if (Objects.isNull(request) || CollectionUtils.isEmpty(request.getMembers())) {
|
||||
log.info("userAddChatGroup-请求网易云信,members is empty");
|
||||
return UserAddChatGroupResponse.builder().build();
|
||||
}
|
||||
//构建用户加入群聊
|
||||
HashMap<String, Object> paramMap = this.buildUserAddChatGroup(request);
|
||||
|
||||
@ -408,21 +433,67 @@ public class NimChannelService implements IMChannelProvider {
|
||||
HttpResponse response = HttpRequest.post(USER_ADD_CHAT_GROUP).addHeaders(authHeaderMap)
|
||||
.form(paramMap).timeout(5000).execute();
|
||||
String result = response.body();
|
||||
if (response.getStatus() == SUCCESS_CODE) {
|
||||
log.info("userAddChatGroup-请求网易云信,result:{}", result);
|
||||
if (response.getStatus() != SUCCESS_CODE) {
|
||||
log.error("userAddChatGroup-请求网易云信Server:{},异常:{}", CHAT_GROUP_CREATE, result);
|
||||
throw new ServiceException("userAddChatGroup-请求网易云信Server异常,result:" + result);
|
||||
}
|
||||
UserAddChatGroupResponse userAddChatGroupResponse = JSONUtil.toBean(result, UserAddChatGroupResponse.class);
|
||||
if (userAddChatGroupResponse == null) {
|
||||
return UserAddChatGroupResponse.builder().desc("userAddChatGroup-请求网易云信Server异常[" + result + "],请联系管理员!").build();
|
||||
throw new ServiceException("userAddChatGroup-请求网易云信Server异常[" + result + "],请联系管理员!");
|
||||
}
|
||||
if (userAddChatGroupResponse.getCode() != SUCCESS_CODE) {
|
||||
log.warn("userAddChatGroup-请求网易云信Server:{},返回异常:{}", CHAT_GROUP_CREATE, result);
|
||||
throw new ServiceException(userAddChatGroupResponse.getCode(), "userAddChatGroup-请求网易云信Server异常,result:" + userAddChatGroupResponse.getDesc());
|
||||
}
|
||||
|
||||
return userAddChatGroupResponse;
|
||||
} else {
|
||||
log.error("userAddChatGroup-请求网易云信Server:{},异常:{}", CHAT_GROUP_CREATE, result);
|
||||
}
|
||||
return UserAddChatGroupResponse.builder().desc("userAddChatGroup-请求网易云信Server异常,请联系管理员!").build();
|
||||
|
||||
/**
|
||||
* 踢人出群
|
||||
*/
|
||||
@Override
|
||||
public UserAddChatGroupResponse kickChatGroup(KickChatGroupRequest request) {
|
||||
//构建用户加入群聊
|
||||
HashMap<String, Object> paramMap = this.buildKickChatGroup(request);
|
||||
|
||||
Map<String, String> authHeaderMap = buildAuthHeader(getProviderAppKey(), getProviderAppSecret());
|
||||
log.info("kickChatGroup-请求网易云信,URL:{},Header:{},请求参数:{}", KICK_CHAT_GROUP,
|
||||
JSONUtil.toJsonStr(authHeaderMap), JSONUtil.toJsonStr(paramMap));
|
||||
HttpResponse response = HttpRequest.post(KICK_CHAT_GROUP).addHeaders(authHeaderMap)
|
||||
.form(paramMap).timeout(5000).execute();
|
||||
String result = response.body();
|
||||
log.info("kickChatGroup-请求网易云信,result:{}", result);
|
||||
if (response.getStatus() != SUCCESS_CODE) {
|
||||
log.error("kickChatGroup-请求网易云信Server:{},异常:{}", KICK_CHAT_GROUP, result);
|
||||
throw new ServiceException("kickChatGroup-请求网易云信Server:" + KICK_CHAT_GROUP +",异常:" + result);
|
||||
}
|
||||
|
||||
UserAddChatGroupResponse kickChatGroupResponse = JSONUtil.toBean(result, UserAddChatGroupResponse.class);
|
||||
if (kickChatGroupResponse == null) {
|
||||
throw new ServiceException("kickChatGroup-请求网易云信Server异常[" + result + "],请联系管理员!");
|
||||
}
|
||||
if (kickChatGroupResponse.getCode() != SUCCESS_CODE) {
|
||||
log.warn("kickChatGroup-请求网易云信Server:{},返回异常:{}", KICK_CHAT_GROUP, result);
|
||||
throw new ServiceException(kickChatGroupResponse.getCode(), "kickChatGroup-请求网易云信Server:"+KICK_CHAT_GROUP+",返回异常:" + result);
|
||||
}
|
||||
return kickChatGroupResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建创建群聊对象
|
||||
*/
|
||||
private HashMap<String, Object> buildKickChatGroup(KickChatGroupRequest request) {
|
||||
HashMap<String, Object> paramMap = Maps.newHashMap();
|
||||
paramMap.put("tid", request.getTid());
|
||||
paramMap.put("owner", request.getOwner());
|
||||
paramMap.put("members", request.getMembers());
|
||||
paramMap.put("attach",request.getAttach());
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构建创建群聊对象
|
||||
*/
|
||||
@ -430,10 +501,91 @@ public class NimChannelService implements IMChannelProvider {
|
||||
HashMap<String, Object> paramMap = Maps.newHashMap();
|
||||
paramMap.put("tid", request.getTid());
|
||||
paramMap.put("owner", request.getOwner());
|
||||
paramMap.put("members", request.getMembers());
|
||||
paramMap.put("members", JSON.toJSONString(request.getMembers()));
|
||||
paramMap.put("magree", 0);
|
||||
paramMap.put("msg",request.getMsg());
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChatGroupQueryResponse chatGroupQueryByTids(List<String> tids, Integer ope) {
|
||||
//构建创建群聊对象
|
||||
HashMap<String, Object> paramMap = this.buildChatGroupQuery(tids, ope);
|
||||
|
||||
Map<String, String> authHeaderMap = buildAuthHeader(getProviderAppKey(), getProviderAppSecret());
|
||||
log.info("chatGroupQuery-请求网易云信,URL:{},Header:{},请求参数:{}", CHAT_GROUP_QUERY,
|
||||
JSONUtil.toJsonStr(authHeaderMap), JSONUtil.toJsonStr(paramMap));
|
||||
HttpResponse response = HttpRequest.post(CHAT_GROUP_QUERY).addHeaders(authHeaderMap)
|
||||
.form(paramMap).timeout(5000).execute();
|
||||
String result = response.body();
|
||||
log.info("chatGroupQuery-请求网易云信,result:{}", result);
|
||||
if (response.getStatus() != SUCCESS_CODE) {
|
||||
log.error("chatGroupQuery-请求网易云信Server:{},异常:{}", CHAT_GROUP_QUERY, result);
|
||||
return ChatGroupQueryResponse.builder().desc("chatGroupQuery-请求网易云信Server异常,请联系管理员!").build();
|
||||
}
|
||||
|
||||
ChatGroupQueryResponse chatGroupQueryResponse = JSONUtil.toBean(result, ChatGroupQueryResponse.class);
|
||||
if (chatGroupQueryResponse == null) {
|
||||
return ChatGroupQueryResponse.builder().desc("chatGroupQuery-请求网易云信Server异常[" + result + "],请联系管理员!").build();
|
||||
}
|
||||
if (chatGroupQueryResponse.getCode() != SUCCESS_CODE) {
|
||||
log.warn("chatGroupQuery-请求网易云信Server:{},返回异常:{}", CHAT_GROUP_QUERY, result);
|
||||
}
|
||||
return chatGroupQueryResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建获取群聊对象
|
||||
*/
|
||||
private HashMap<String, Object> buildChatGroupQuery(List<String> tids, Integer ope) {
|
||||
HashMap<String, Object> paramMap = Maps.newHashMap();
|
||||
paramMap.put("tids", JSON.toJSONString(tids));
|
||||
paramMap.put("ope", ope);
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转让群主
|
||||
*/
|
||||
public ChangeOwnerResponse changeOwner(ChangeOwnerRequest request) {
|
||||
//构建创建群聊对象
|
||||
HashMap<String, Object> paramMap = this.buildChangeOwner(request);
|
||||
|
||||
Map<String, String> authHeaderMap = buildAuthHeader(getProviderAppKey(), getProviderAppSecret());
|
||||
log.info("changeOwner-请求网易云信,URL:{},Header:{},请求参数:{}", CHANGE_OWNER,
|
||||
JSONUtil.toJsonStr(authHeaderMap), JSONUtil.toJsonStr(paramMap));
|
||||
HttpResponse response = HttpRequest.post(CHANGE_OWNER).addHeaders(authHeaderMap)
|
||||
.form(paramMap).timeout(5000).execute();
|
||||
String result = response.body();
|
||||
log.info("changeOwner-请求网易云信,result:{}", result);
|
||||
if (response.getStatus() != SUCCESS_CODE) {
|
||||
log.error("changeOwner-请求网易云信Server:{},异常:{}", CHANGE_OWNER, result);
|
||||
throw new ServiceException("changeOwner-请求网易云信Server:" + KICK_CHAT_GROUP +",异常:" + result);
|
||||
}
|
||||
ChangeOwnerResponse changeOwnerResponse = JSONUtil.toBean(result, ChangeOwnerResponse.class);
|
||||
if (changeOwnerResponse == null) {
|
||||
log.error("changeOwner-请求网易云信Server:{},异常:{}", CHANGE_OWNER, result);
|
||||
throw new ServiceException("changeOwner-请求网易云信Server:" + KICK_CHAT_GROUP +",异常:" + result);
|
||||
}
|
||||
if (changeOwnerResponse.getCode() != SUCCESS_CODE) {
|
||||
log.error("changeOwner-请求网易云信Server:{},异常:{}", CHANGE_OWNER, result);
|
||||
throw new ServiceException("changeOwner-请求网易云信Server:" + KICK_CHAT_GROUP +",异常:" + result);
|
||||
}
|
||||
return changeOwnerResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建转让群主
|
||||
*/
|
||||
private HashMap<String, Object> buildChangeOwner(ChangeOwnerRequest request) {
|
||||
HashMap<String, Object> paramMap = Maps.newHashMap();
|
||||
paramMap.put("tid", request.getTid());
|
||||
paramMap.put("owner", request.getOwner());
|
||||
paramMap.put("newowner", request.getNewowner());
|
||||
paramMap.put("leave", request.getLeave());
|
||||
paramMap.put("attach", request.getAttach());
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
package cn.axzo.im.channel.netease.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 转让群主
|
||||
* 文档地址:https://doc.yunxin.163.com/messaging/server-apis/jM0MjQzODA?platform=server
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/08
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class ChangeOwnerRequest {
|
||||
/**
|
||||
* 云信服务器产生,群组唯一标识,创建群时会返回,最大长度 64 位长整型
|
||||
*/
|
||||
private String tid;
|
||||
/**
|
||||
* 邀请人的用户帐号,accid,最大长度 32 位字符,按照群属性 invitemode(0:只有群主和管理员可以邀请他人入群,1:所有人都可以邀请)配置传入
|
||||
*/
|
||||
private String owner;
|
||||
/**
|
||||
* 新群主帐号,accid,最大长度 32 位字符
|
||||
*/
|
||||
private String newowner;
|
||||
/**
|
||||
* 1,群主身份转让后离开群;2,群主身份转让后成为普通成员
|
||||
*/
|
||||
private Integer leave;
|
||||
|
||||
/**
|
||||
* 自定义扩展字段,最大长度 512 位字符
|
||||
*/
|
||||
private String attach;
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package cn.axzo.im.channel.netease.dto;
|
||||
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupCreateResp;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 转让群主
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/08
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChangeOwnerResponse {
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
package cn.axzo.im.channel.netease.dto;
|
||||
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@ -47,17 +49,23 @@ public class ChatGroupCreateRequest {
|
||||
*/
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 自定义扩展字段,最大长度 512 位字符
|
||||
*/
|
||||
private String attach;
|
||||
|
||||
/**
|
||||
* 对象转换
|
||||
*/
|
||||
public static ChatGroupCreateRequest convertRequest(ChatGroupCreateReq req, String owner) {
|
||||
public static ChatGroupCreateRequest convertRequest(ChatGroupCreateReq req, String owner, String attach) {
|
||||
|
||||
return ChatGroupCreateRequest.builder()
|
||||
.tname(req.getGroupName())
|
||||
.owner(owner)
|
||||
.members(owner)
|
||||
.members(JSON.toJSONString(Lists.newArrayList(owner)))
|
||||
.msg("进入群聊," + req.getGroupName())
|
||||
.icon(req.getAvatarUrl())
|
||||
.attach(attach)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@ -42,9 +42,11 @@ public class ChatGroupCreateResponse {
|
||||
private String desc;
|
||||
|
||||
|
||||
public static ChatGroupCreateResp convertResp(ChatGroupCreateResponse response) {
|
||||
public static ChatGroupCreateResp convertResp(ChatGroupCreateResponse response, String groupName, String avatarUrl) {
|
||||
return ChatGroupCreateResp.builder()
|
||||
.tid(response.getTid())
|
||||
.groupName(groupName)
|
||||
.avatarUrl(avatarUrl)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,163 @@
|
||||
package cn.axzo.im.channel.netease.dto;
|
||||
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupCreateResp;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import io.swagger.models.auth.In;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 获取群聊
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/08
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatGroupQueryResponse {
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 网易云信服务器产生,群唯一标识
|
||||
*/
|
||||
private List<TInfo> tinfos;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class TInfo {
|
||||
/**
|
||||
* 群名称
|
||||
*/
|
||||
private String tname;
|
||||
/**
|
||||
* 群头像
|
||||
*/
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 群主用户帐号
|
||||
*/
|
||||
private String owner;
|
||||
/**
|
||||
* 群成员最大数量
|
||||
*/
|
||||
private Integer maxusers;
|
||||
|
||||
/**
|
||||
* 群 ID
|
||||
*/
|
||||
private Long tid;
|
||||
|
||||
/**
|
||||
* 当前群成员数量
|
||||
*/
|
||||
private Integer size;
|
||||
|
||||
/**
|
||||
* 群公告
|
||||
*/
|
||||
private String announcement;
|
||||
|
||||
/**
|
||||
* 群介绍
|
||||
*/
|
||||
private String intro;
|
||||
|
||||
/**
|
||||
* 申请入群的验证方式
|
||||
* 0,不用验证;1,需要验证;2,不允许任何人加入
|
||||
*/
|
||||
private Integer joinmode;
|
||||
|
||||
/**
|
||||
* 群创建完成后,邀请入群时是否需要被邀请人的同意
|
||||
* 0,需要同意(默认);1,不需要同意
|
||||
*/
|
||||
private Integer beinvitemode;
|
||||
|
||||
/**
|
||||
* 邀请权限,即谁可以邀请他人入群
|
||||
* 0,群主和管理员(默认);1,所有人
|
||||
*/
|
||||
private Integer invitemode;
|
||||
|
||||
/**
|
||||
* 客户端修改群信息权限,即谁可以修改群信息
|
||||
* 0,群主和管理员(默认);1,所有人
|
||||
*/
|
||||
private Integer uptinfomode;
|
||||
|
||||
/**
|
||||
* 客户端修改群自定义属性权限,即谁可以修改群自定义属性
|
||||
* 0,群主和管理员(默认);1,所有人
|
||||
*/
|
||||
private Integer upcustommode;
|
||||
|
||||
/**
|
||||
* 群禁言类型
|
||||
* 0,解除禁言;1,禁言普通成员;3,禁言整个群(包括群主)
|
||||
*/
|
||||
private Integer muteType;
|
||||
|
||||
/**
|
||||
* 群通知消息是否关闭在线发送(开启该功能才会有该字段)
|
||||
*/
|
||||
private Boolean isNotifyCloseOnline;
|
||||
|
||||
/**
|
||||
* 群通知消息是否关闭持久化存储(开启该功能才会有该字段)
|
||||
*/
|
||||
private Boolean isNotifyClosePersistent;
|
||||
|
||||
/**
|
||||
* 自定义高级群扩展属性
|
||||
*/
|
||||
private String custom;
|
||||
|
||||
/**
|
||||
* 客户端自定义字段
|
||||
*/
|
||||
private String clientCustom;
|
||||
|
||||
/**
|
||||
* 是否全员禁言
|
||||
*/
|
||||
private Boolean mute;
|
||||
|
||||
/**
|
||||
* 管理员账号
|
||||
*/
|
||||
private String admins;
|
||||
|
||||
/**
|
||||
* 群成员列表
|
||||
*/
|
||||
private String members;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Long createtime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Long updatetime;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package cn.axzo.im.channel.netease.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 踢人出群
|
||||
* 文档地址:https://doc.yunxin.163.com/messaging/server-apis/TY4MDA5ODE?platform=server
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/08
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class KickChatGroupRequest {
|
||||
/**
|
||||
* 云信服务器产生,群组唯一标识,创建群时会返回,最大长度 64 位长整型
|
||||
*/
|
||||
private String tid;
|
||||
/**
|
||||
* 邀请人的用户帐号,accid,最大长度 32 位字符,按照群属性 invitemode(0:只有群主和管理员可以邀请他人入群,1:所有人都可以邀请)配置传入
|
||||
*/
|
||||
private String owner;
|
||||
|
||||
/**
|
||||
* 当移除单个成员时必填
|
||||
* 被移除的用户账号 accid,最大长度 32 位字符
|
||||
* 相对于 members,优先使用 member 参数
|
||||
*/
|
||||
private String member;
|
||||
/**
|
||||
* 被邀请入群的用户列表,\["aaa","bbb"\](JSONArray 对应的 accid,如果解析出错会报 414),一次最多邀请 200 个成员
|
||||
*/
|
||||
private String members;
|
||||
/**
|
||||
* 自定义扩展字段,最大长度 512 位字符
|
||||
*/
|
||||
private String attach;
|
||||
|
||||
}
|
||||
@ -5,6 +5,8 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户加入群聊
|
||||
* 文档地址:https://doc.yunxin.163.com/messaging/server-apis/DA2MzQ0MzA?platform=server
|
||||
@ -27,13 +29,13 @@ public class UserAddChatGroupRequest {
|
||||
/**
|
||||
* 被邀请入群的用户列表,\["aaa","bbb"\](JSONArray 对应的 accid,如果解析出错会报 414),一次最多邀请 200 个成员
|
||||
*/
|
||||
private String members;
|
||||
private List<String> members;
|
||||
/**
|
||||
* 邀请发送的文字,最大长度 150 位字符
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
public static UserAddChatGroupRequest buildRequest(String tid, String owner, String members, String msg) {
|
||||
public static UserAddChatGroupRequest buildRequest(String tid, String owner, List<String> members, String msg) {
|
||||
return UserAddChatGroupRequest.builder()
|
||||
.tid(tid)
|
||||
.owner(owner)
|
||||
|
||||
@ -14,7 +14,16 @@ public enum BizResultCode implements ResultCode {
|
||||
ALL_PERSSON_TYPE_NOT_EMPTY("103", "全员发送时,接收端不能为空"),
|
||||
ACQUIRE_RATE_LIMITER_FAIL("104", "获取滑动窗口令牌失败"),
|
||||
MESSAGE_TASK_STATUS_ERROR("105", "更新消息任务失败,状态异常"),
|
||||
MESSAGE_TASK_NOT_FOUND("106", "消息任务不存在"),;
|
||||
MESSAGE_TASK_NOT_FOUND("106", "消息任务不存在"),
|
||||
|
||||
/**
|
||||
* 群聊
|
||||
*/
|
||||
CHAT_GROUP_ALREADY_EXISTS("501", "群聊已经存在"),
|
||||
CHAT_GROUP_OVER_MEMBERS_COUNT_LIMIT("502", "超过人数限制"),
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
private String errorCode;
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.axzo.im.config;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 群聊配置
|
||||
*
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/12
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@RefreshScope
|
||||
@Data
|
||||
public class ChatGroupConfig {
|
||||
//TODO
|
||||
@Value("${chatgroup.dingTalkBotAccessToken:1}")
|
||||
private String dingTalkBotAccessToken;
|
||||
//TODO
|
||||
@Value("${chatgroup.dingTalkBotSecret:1}")
|
||||
private String dingTalkBotSecret;
|
||||
//TODO
|
||||
@Value("${chatgroup.dingTalkBotEnabled:false}")
|
||||
private Boolean dingTalkBotEnabled;
|
||||
}
|
||||
@ -92,7 +92,7 @@ public class RocketMQEventConfiguration {
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(topic = "topic_profile_${spring.profiles.active}",
|
||||
@RocketMQMessageListener(topic = "topic_im_center_${spring.profiles.active}",
|
||||
consumerGroup = "GID_chat_group_create_${spring.application.name}_${spring.profiles.active}",
|
||||
consumeMode = ConsumeMode.ORDERLY,
|
||||
nameServer = "${rocketmq.name-server}"
|
||||
@ -108,4 +108,61 @@ public class RocketMQEventConfiguration {
|
||||
super.onEvent(message, eventConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(topic = "topic_profile_${spring.profiles.active}",
|
||||
consumerGroup = "GID_chat_group_create_${spring.application.name}_${spring.profiles.active}",
|
||||
consumeMode = ConsumeMode.ORDERLY,
|
||||
nameServer = "${rocketmq.name-server}"
|
||||
)
|
||||
public static class PersonProfileAvatarUpdateListener extends BaseListener implements RocketMQListener<MessageExt> {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
|
||||
@Override
|
||||
public void onMessage(MessageExt message) {
|
||||
log.info("PersonProfileAvatarUpdateListener onMessage,message:{}", JSON.toJSONString(message));
|
||||
super.onEvent(message, eventConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(topic = "topic_organizational_${spring.profiles.active}",
|
||||
consumerGroup = "GID_chat_group_create_${spring.application.name}_${spring.profiles.active}",
|
||||
consumeMode = ConsumeMode.ORDERLY,
|
||||
nameServer = "${rocketmq.name-server}"
|
||||
)
|
||||
public static class OrganizationalNodeUserChangeListener extends BaseListener implements RocketMQListener<MessageExt> {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
|
||||
@Override
|
||||
public void onMessage(MessageExt message) {
|
||||
log.info("OrganizationalNodeUserChangeListener onMessage,message:{}", JSON.toJSONString(message));
|
||||
super.onEvent(message, eventConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(topic = "topic_tyr_${spring.profiles.active}",
|
||||
consumerGroup = "GID_chat_group_change_owner_${spring.application.name}_${spring.profiles.active}",
|
||||
consumeMode = ConsumeMode.ORDERLY,
|
||||
nameServer = "${rocketmq.name-server}"
|
||||
)
|
||||
public static class ChatGroupChangeOwnerListener extends BaseListener implements RocketMQListener<MessageExt> {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
|
||||
@Override
|
||||
public void onMessage(MessageExt message) {
|
||||
log.info("ChatGroupChangeOwnerListener onMessage,message:{}", JSON.toJSONString(message));
|
||||
super.onEvent(message, eventConsumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,13 +3,14 @@ package cn.axzo.im.controller;
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.im.center.api.feign.ChatGroupApi;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupQueryReq;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupCreateResp;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateRequest;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateResponse;
|
||||
import cn.axzo.im.service.AccountService;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupQueryResp;
|
||||
import cn.axzo.im.service.ChatGroupService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@ -29,6 +30,15 @@ public class ChatGroupController implements ChatGroupApi {
|
||||
|
||||
@Override
|
||||
public ApiResult<ChatGroupCreateResp> chatGroupCreate(ChatGroupCreateReq req) {
|
||||
return ApiResult.ok(chatGroupService.chatGroupCreate(req));
|
||||
return chatGroupService.chatGroupCreate(req);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取群聊
|
||||
*/
|
||||
@Override
|
||||
public ApiResult<ChatGroupQueryResp> chatGroupQuery(@RequestBody @Validated ChatGroupQueryReq req) {
|
||||
return ApiResult.ok(chatGroupService.chatGroupQuery(req));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,9 +4,12 @@ import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.im.center.api.feign.ChatGroupApi;
|
||||
import cn.axzo.im.center.api.feign.ComplaintApi;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ComplaintCreateReq;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupCreateResp;
|
||||
import cn.axzo.im.service.ComplaintService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
@ -19,9 +22,12 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RequiredArgsConstructor
|
||||
public class ComplaintController implements ComplaintApi {
|
||||
|
||||
@Autowired
|
||||
private ComplaintService complaintService;
|
||||
|
||||
@Override
|
||||
public ApiResult<Void> complaintCreate(ChatGroupCreateReq chatGroupCreateReq) {
|
||||
return null;
|
||||
public ApiResult<Void> complaintCreate(ComplaintCreateReq req) {
|
||||
complaintService.complaintCreate(req);
|
||||
return ApiResult.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
package cn.axzo.im.dao.mapper;
|
||||
|
||||
import cn.axzo.im.entity.BizData;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
public interface BizDataMapper extends BaseMapper<BizData> {
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
package cn.axzo.im.dao.mapper;
|
||||
|
||||
import cn.axzo.im.entity.BizLog;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
public interface BizLogMapper extends BaseMapper<BizLog> {
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package cn.axzo.im.dao.mapper;
|
||||
|
||||
import cn.axzo.im.entity.ChatGroupUser;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/05
|
||||
* @desc 群聊
|
||||
*/
|
||||
public interface ChatGroupUserMapper extends BaseMapper<ChatGroupUser> {
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package cn.axzo.im.dao.mapper;
|
||||
|
||||
import cn.axzo.im.entity.ChatGroup;
|
||||
import cn.axzo.im.entity.Complaint;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/05
|
||||
* @desc 群聊
|
||||
*/
|
||||
public interface ComplaintMapper extends BaseMapper<Complaint> {
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package cn.axzo.im.dao.mapper;
|
||||
|
||||
import cn.axzo.im.entity.OperateLog;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/12
|
||||
* @desc 操作日志
|
||||
*/
|
||||
public interface OperateLogMapper extends BaseMapper<OperateLog> {
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package cn.axzo.im.dao.repository;
|
||||
|
||||
import cn.axzo.im.dao.mapper.BizDataMapper;
|
||||
import cn.axzo.im.entity.BizData;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Repository("bizDataDao")
|
||||
public class BizDataDao extends ServiceImpl<BizDataMapper, BizData> {
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package cn.axzo.im.dao.repository;
|
||||
|
||||
import cn.axzo.im.dao.mapper.BizLogMapper;
|
||||
import cn.axzo.im.entity.BizLog;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Repository("bizLogDao")
|
||||
public class BizLogDao extends ServiceImpl<BizLogMapper, BizLog> {
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
package cn.axzo.im.entity;
|
||||
|
||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
||||
import cn.axzo.im.utils.YesNo;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@TableName(value = "im_biz_data", autoResultMap = true)
|
||||
public class BizData {
|
||||
|
||||
private Long id;
|
||||
private String bizId;
|
||||
private Long taskId;
|
||||
private Long receiverPersonId;
|
||||
private Long receiverOuId;
|
||||
private AppTypeEnum appType;
|
||||
private YesNo valid;
|
||||
private String bizMessageId;
|
||||
private Long initHistoryId;
|
||||
private Long updateHistoryId;
|
||||
private Long retryHistoryId;
|
||||
private JSONObject messageBody;
|
||||
private JSONObject bizBody;
|
||||
private Long dataVersion;
|
||||
private Long ackDataVersion;
|
||||
private Date ackTime;
|
||||
private Integer retryCount;
|
||||
private RecordExt recordExt;
|
||||
private Long isDelete;
|
||||
private Date createAt;
|
||||
private Date updateAt;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class RecordExt {
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package cn.axzo.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@TableName(value = "im_biz_log", autoResultMap = true)
|
||||
public class BizLog {
|
||||
private Long id;
|
||||
private String bizId;
|
||||
private String bizMessageId;
|
||||
private Long initHistoryId;
|
||||
private Long updateHistoryId;
|
||||
private JSONObject messageBody;
|
||||
private JSONObject bizBody;
|
||||
private Long dataVersion;
|
||||
private Long isDelete;
|
||||
private Date createAt;
|
||||
private Date updateAt;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.im.entity;
|
||||
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@ -47,45 +48,57 @@ public class ChatGroup implements Serializable {
|
||||
* 群头像
|
||||
*/
|
||||
@TableField("avatar_url")
|
||||
private String avatar_url;
|
||||
private String avatarUrl;
|
||||
|
||||
|
||||
/**
|
||||
* 项目Id
|
||||
*/
|
||||
@TableField("workspace_id")
|
||||
private Long workspace_id;
|
||||
private Long workspaceId;
|
||||
|
||||
/**
|
||||
* 单位Id
|
||||
*/
|
||||
@TableField("ou_id")
|
||||
private Long ouId;
|
||||
|
||||
/**
|
||||
* 班组Id
|
||||
*/
|
||||
@TableField("team_id")
|
||||
private Long teamId;
|
||||
|
||||
/**
|
||||
* 群类型,项目专属群:workspace
|
||||
*/
|
||||
@TableField("group_type")
|
||||
private String group_type;
|
||||
private String groupType;
|
||||
|
||||
|
||||
/**
|
||||
* 人群类型,项目:workspace,单位:ou,班组:team
|
||||
*/
|
||||
@TableField("crow_type")
|
||||
private String crow_type;
|
||||
|
||||
/**
|
||||
* 关联id,单位Id或者班组Id或者项目Id
|
||||
*/
|
||||
@TableField("relate_id")
|
||||
private Long relate_id;
|
||||
|
||||
/**
|
||||
* 群主名称
|
||||
*/
|
||||
@TableField("group_owner_name")
|
||||
private String group_owner_name;
|
||||
private ChatGroupCreateReq.CrowTypeEnum crowType;
|
||||
|
||||
/**
|
||||
* 群主
|
||||
*/
|
||||
@TableField("group_owner")
|
||||
private Long group_owner;
|
||||
private String groupOwner;
|
||||
|
||||
/**
|
||||
* 状态,成功:success;失败:fail
|
||||
*/
|
||||
@TableField("status")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注,目前记录创建群失败原因
|
||||
*/
|
||||
@TableField("remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
@ -97,7 +110,7 @@ public class ChatGroup implements Serializable {
|
||||
* 是否删除
|
||||
*/
|
||||
@TableField("is_delete")
|
||||
private Integer isDelete;
|
||||
private Long isDelete;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
package cn.axzo.im.entity;
|
||||
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupStatusEnum;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupUserTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 群聊成员
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/12
|
||||
*/
|
||||
@TableName("im_chat_group_user")
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ChatGroupUser implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 群聊Id
|
||||
*/
|
||||
@TableField("chat_group_id")
|
||||
private Long chatGroupId;
|
||||
|
||||
/**
|
||||
* 网易云信唯一标识,网易返回
|
||||
*/
|
||||
@TableField("tid")
|
||||
private String tid;
|
||||
|
||||
/**
|
||||
* IM账号Id
|
||||
*/
|
||||
@TableField("acc_id")
|
||||
private String accId;
|
||||
|
||||
|
||||
/**
|
||||
* 类型,OWNER:群主;USER:普通用户
|
||||
*/
|
||||
@TableField("type")
|
||||
private ChatGroupUserTypeEnum type;
|
||||
|
||||
/**
|
||||
* 状态,success:成功;fail:失败
|
||||
*/
|
||||
@TableField("status")
|
||||
private ChatGroupStatusEnum status;
|
||||
|
||||
/**
|
||||
* 状态,success:成功;fail:失败
|
||||
*/
|
||||
@TableField("crow_type")
|
||||
private ChatGroupCreateReq.CrowTypeEnum crowType;
|
||||
|
||||
/**
|
||||
* 备注,目前记录群成员失败加入群原因
|
||||
*/
|
||||
@TableField("remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@TableField("creator")
|
||||
private Long creator;
|
||||
|
||||
/**
|
||||
* 是否删除,0:未删除;非0:已删除
|
||||
*/
|
||||
@TableField("is_delete")
|
||||
private Long isDelete;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_at")
|
||||
private Date createAt;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_at")
|
||||
private Date updateAt;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.im.entity;
|
||||
|
||||
import cn.axzo.im.center.api.vo.req.ComplaintCreateReq;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@ -41,31 +42,26 @@ public class Complaint implements Serializable {
|
||||
* 类型,私聊:private,群聊:group
|
||||
*/
|
||||
@TableField("type")
|
||||
private String type;
|
||||
private ComplaintCreateReq.ChatTypeEnum type;
|
||||
|
||||
/**
|
||||
* 发送人Id
|
||||
*/
|
||||
@TableField("from_id")
|
||||
private Long fromId;
|
||||
|
||||
/**
|
||||
* 发送人名称
|
||||
*/
|
||||
@TableField("from_name")
|
||||
private String fromName;
|
||||
private String fromId;
|
||||
|
||||
/**
|
||||
* 接收人Id
|
||||
*/
|
||||
@TableField("to_id")
|
||||
private Long toId;
|
||||
private String toId;
|
||||
|
||||
/**
|
||||
* 接收人名称
|
||||
* 群Id
|
||||
*/
|
||||
@TableField("to_name")
|
||||
private String toName;
|
||||
@TableField("tid")
|
||||
private String tid;
|
||||
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
@ -77,7 +73,7 @@ public class Complaint implements Serializable {
|
||||
* 是否删除
|
||||
*/
|
||||
@TableField("is_delete")
|
||||
private Integer isDelete;
|
||||
private Long isDelete;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.im.entity;
|
||||
|
||||
import cn.axzo.im.center.common.enums.OperateLogTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@ -14,47 +15,28 @@ import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 群聊日志
|
||||
* 操作日志
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/05
|
||||
*/
|
||||
@TableName("im_chat_group_change_log")
|
||||
@TableName("im_operate_log")
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ChatGroupChangeLog implements Serializable {
|
||||
public class OperateLog implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 群聊名称
|
||||
*/
|
||||
@TableField("name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 群聊Id
|
||||
*/
|
||||
@TableField("group_chat_id")
|
||||
private String group_chat_id;
|
||||
|
||||
/**
|
||||
* 项目Id
|
||||
*/
|
||||
@TableField("workspace_id")
|
||||
private Long workspace_id;
|
||||
|
||||
|
||||
/**
|
||||
* 变更类型,群变更:groupAdd;群变更:groupUpdate;人员变更:userAdd;人员变更:userUpdate
|
||||
*/
|
||||
@TableField("change_type")
|
||||
private String change_type;
|
||||
@TableField("type")
|
||||
private OperateLogTypeEnum type;
|
||||
|
||||
/**
|
||||
* 变更内容
|
||||
@ -72,7 +54,7 @@ public class ChatGroupChangeLog implements Serializable {
|
||||
* 是否删除
|
||||
*/
|
||||
@TableField("is_delete")
|
||||
private Integer isDelete;
|
||||
private Long isDelete;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
@ -14,6 +14,13 @@ public enum EventTypeEnum {
|
||||
MESSAGE_HISTORY_CREATED("message-history", "message-history-created", "发送记录创建"),
|
||||
MESSAGE_HISTORY_UPDATED("message-history", "message-history-updated", "发送记录修改"),
|
||||
MESSAGE_CHAT_GROUP_CREATE("chat-group", "chat-group-create", "群聊创建"),
|
||||
UPDATE_AVATAR("profile", "update-avatar", "头像更新"),
|
||||
NODE_USER_CREATE("node-user", "node-user-create", "节点用户创建"),
|
||||
NODE_USER_UPDATE("node-user", "node-user-update", "节点用户修改"),
|
||||
NODE_USER_DELETE("node-user", "node-user-delete", "节点用户删除"),
|
||||
NODE_USER_UPSERTED("node-user", "node-user-upserted", "节点用户更新"),
|
||||
SAAS_ROLE_USER_RELATION_REMOVED("saas-role-user-relation", "saas-role-user-relation-removed", "删除用户角色信息"),
|
||||
SAAS_ROLE_USER_RELATION_UPSERT("saas-role-user-relation", "saas-role-user-relation-upsert", "更新用户角色信息"),
|
||||
;
|
||||
|
||||
EventTypeEnum(String model, String name, String desc) {
|
||||
|
||||
@ -20,4 +20,7 @@ public class ChatGroupCreatePayload implements Serializable {
|
||||
|
||||
private String owner;
|
||||
|
||||
private String imAccountOwner;
|
||||
|
||||
private Long chatGroupId;
|
||||
}
|
||||
|
||||
@ -0,0 +1,131 @@
|
||||
package cn.axzo.im.event.payload;
|
||||
|
||||
import cn.axzo.maokai.api.vo.response.NodeUserPersonGroupLike;
|
||||
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
|
||||
import cn.axzo.trade.datasecurity.core.annotation.CryptField;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 组织人员表表实体类
|
||||
*
|
||||
* @author makejava
|
||||
* @since 2022-06-05 10:59:31
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class OrganizationalNodeUserPayload{
|
||||
|
||||
private static final long serialVersionUID = 297636361732939329L;
|
||||
|
||||
/**
|
||||
* identity_id
|
||||
*/
|
||||
private Long identityId;
|
||||
|
||||
/**
|
||||
* 身份类型 0-无效类型, 1-工人, 2-班组长, 3-从业人员, 4-政务人员,5-运营人员
|
||||
*/
|
||||
private Integer identityType;
|
||||
|
||||
/**
|
||||
* 自然人id
|
||||
*/
|
||||
private Long personId;
|
||||
|
||||
/**
|
||||
* 主电话
|
||||
*/
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String realName;
|
||||
|
||||
/**
|
||||
* 身份证号
|
||||
*/
|
||||
private String idNumber;
|
||||
|
||||
/**
|
||||
* 单位id
|
||||
*/
|
||||
private Long organizationalUnitId;
|
||||
|
||||
/**
|
||||
* 组织节点id
|
||||
*/
|
||||
private Long organizationalNodeId;
|
||||
|
||||
/**
|
||||
* 岗位id
|
||||
*/
|
||||
private Long organizationalJobId;
|
||||
|
||||
/**
|
||||
* 是否是主岗位
|
||||
* 0:普通岗位、1:主岗位
|
||||
*/
|
||||
private Integer primaryJob;
|
||||
/**
|
||||
* 是否允许进入工地 1.允许 2.不允许
|
||||
*/
|
||||
private Integer isAllowed;
|
||||
|
||||
/**
|
||||
* 加入时间
|
||||
*/
|
||||
private Date joinAt;
|
||||
|
||||
/**
|
||||
* 是否是部门管理员
|
||||
*/
|
||||
private Boolean manager;
|
||||
|
||||
/**
|
||||
* 离开时间
|
||||
*/
|
||||
private Date leaveAt;
|
||||
|
||||
/**
|
||||
* 迁移数据临时源id
|
||||
*/
|
||||
private Long tempSourceId;
|
||||
|
||||
/**
|
||||
* 顶级节点的nodeId
|
||||
*/
|
||||
private Long topNodeId;
|
||||
|
||||
/** 数据同步ID **/
|
||||
private Long syncDataId;
|
||||
|
||||
/** 工号 - 需要作为查询条件和排序 不使用扩展字段**/
|
||||
private String jobNumber;
|
||||
|
||||
/**
|
||||
* workspace id
|
||||
*/
|
||||
private Long workspaceId;
|
||||
|
||||
private String groupNodeIds = "";
|
||||
|
||||
private String groupJobIds = "";
|
||||
|
||||
private String groupIdentityIds = "";
|
||||
}
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
package cn.axzo.im.event.payload;
|
||||
|
||||
import cn.axzo.basics.auth.dto.SaasRoleUserRelation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SaasRoleUserRelationRemovePayload {
|
||||
|
||||
private List<SaasRoleUserRelation> values;
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package cn.axzo.im.event.payload;
|
||||
|
||||
import cn.axzo.basics.auth.dto.SaasRoleUserRelation;
|
||||
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserV2DTO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SaasRoleUserRelationUpsertPayload {
|
||||
|
||||
private List<SaasRoleUserRelation> oldValues;
|
||||
|
||||
private List<SaasRoleUserRelation> newValues;
|
||||
|
||||
public static SaasRoleUserRelation from(SaasRoleUserV2DTO saasRoleUserV2DTO) {
|
||||
SaasRoleUserRelation result = new SaasRoleUserRelation();
|
||||
BeanUtils.copyProperties(saasRoleUserV2DTO, result);
|
||||
result.setNaturalPersonId(saasRoleUserV2DTO.getSaasRoleUser().getPersonId());
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.axzo.im.gateway;
|
||||
|
||||
import cn.axzo.im.utils.BizAssertions;
|
||||
import cn.axzo.maokai.api.client.OrgJobApi;
|
||||
import cn.axzo.maokai.api.vo.request.OrgJobListReq;
|
||||
import cn.axzo.maokai.api.vo.response.OrgJobRes;
|
||||
import cn.axzo.pokonyan.util.RpcUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service("orgJobApiGateway")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class OrgJobApiGateway {
|
||||
|
||||
private final OrgJobApi orgJobApi;
|
||||
|
||||
public OrgJobRes fetchJobCodeByJobId(Long jobId) {
|
||||
OrgJobListReq req = new OrgJobListReq();
|
||||
req.setJobIdList(Lists.newArrayList(jobId));
|
||||
List<OrgJobRes> orgJobRes = RpcUtil.rpcApiResultProcessor(() -> orgJobApi.list(req), "fetchJobCodeByJobId", jobId);
|
||||
BizAssertions.assertNotEmpty(orgJobRes, "根据jobId:{}获取Job为空", jobId);
|
||||
return orgJobRes.get(0);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.axzo.im.gateway;
|
||||
|
||||
import cn.axzo.maokai.api.client.OrganizationalNodeApi;
|
||||
import cn.axzo.maokai.api.vo.request.OrganizationalNodeBatchQueryVO;
|
||||
import cn.axzo.maokai.api.vo.response.OrganizationalNodeVO;
|
||||
import cn.axzo.pokonyan.util.RpcUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service("organizationalNodeApiGateway")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class OrganizationalNodeApiGateway {
|
||||
|
||||
private final OrganizationalNodeApi organizationalNodeApi;
|
||||
|
||||
public List<OrganizationalNodeVO> fetchNodesByNodeIds(List<Long> nodeIdList) {
|
||||
OrganizationalNodeBatchQueryVO organizationalNodeBatchQueryVO = new OrganizationalNodeBatchQueryVO();
|
||||
organizationalNodeBatchQueryVO.setNodeIds(nodeIdList);
|
||||
organizationalNodeBatchQueryVO.setContainsDeleted(false);
|
||||
List<OrganizationalNodeVO> nodeVOList = organizationalNodeApi.listNode(organizationalNodeBatchQueryVO).getData();
|
||||
return RpcUtil.rpcApiResultProcessor(() -> organizationalNodeApi.listNode(organizationalNodeBatchQueryVO), "fetchNodesByNodeIds", JSON.toJSONString(nodeVOList));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package cn.axzo.im.gateway;
|
||||
|
||||
import cn.axzo.maokai.api.client.OrganizationalNodeUserApi;
|
||||
import cn.axzo.maokai.api.vo.request.OrganizationalNodeUserSearchReq;
|
||||
import cn.axzo.maokai.api.vo.response.OrganizationalNodeUserVO;
|
||||
import cn.axzo.pokonyan.util.RpcUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Service("organizationalNodeUserApiGateway")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class OrganizationalNodeUserApiGateway {
|
||||
|
||||
private final OrganizationalNodeUserApi organizationalNodeUserApi;
|
||||
|
||||
public List<OrganizationalNodeUserVO> searchNodeUser(Long nodeId, Long workspaceId, Set<String> jobCodes, Long personId) {
|
||||
OrganizationalNodeUserSearchReq searchReq = new OrganizationalNodeUserSearchReq();
|
||||
searchReq.setOrganizationNodeId(nodeId);
|
||||
searchReq.setWorkspaceId(workspaceId);
|
||||
searchReq.setJobCodes(jobCodes);
|
||||
searchReq.setPersonId(personId);
|
||||
return RpcUtil.rpcApiResultProcessor(() -> organizationalNodeUserApi.list(searchReq), "searchNodeUser", JSON.toJSONString(searchReq));
|
||||
}
|
||||
|
||||
public List<OrganizationalNodeUserVO> fetchNodeUsersByWorkspaceNodeIdJobCodes(Long workspaceId, Long nodeId,Set<String> jobCodes) {
|
||||
OrganizationalNodeUserSearchReq searchReq = new OrganizationalNodeUserSearchReq();
|
||||
searchReq.setWorkspaceId(workspaceId);
|
||||
searchReq.setOrganizationNodeId(nodeId);
|
||||
searchReq.setJobCodes(jobCodes);//班组长/带班长
|
||||
return RpcUtil.rpcApiResultProcessor(() -> organizationalNodeUserApi.list(searchReq), "fetchNodeUsersByWorkspaceOuIdJobCodes", JSON.toJSONString(searchReq));
|
||||
}
|
||||
|
||||
public List<OrganizationalNodeUserVO> fetchNodeUsersByWorkspaceIdJobCodes(Long workspaceId, Set<String> jobCodes) {
|
||||
OrganizationalNodeUserSearchReq searchReq = new OrganizationalNodeUserSearchReq();
|
||||
searchReq.setWorkspaceId(workspaceId);
|
||||
searchReq.setJobCodes(jobCodes);
|
||||
return RpcUtil.rpcApiResultProcessor(() -> organizationalNodeUserApi.list(searchReq), "fetchNodeUsersByWorkspaceIdJobCodes", JSON.toJSONString(searchReq));
|
||||
}
|
||||
|
||||
public List<OrganizationalNodeUserVO> fetchNodeUsersByWorkspaceOuIdJobCodes(Long workspaceId, Long ouId, Set<String> jobCodes) {
|
||||
OrganizationalNodeUserSearchReq searchReq = new OrganizationalNodeUserSearchReq();
|
||||
searchReq.setWorkspaceId(workspaceId);
|
||||
searchReq.setOrganizationalUnitId(ouId);
|
||||
searchReq.setJobCodes(jobCodes);
|
||||
return RpcUtil.rpcApiResultProcessor(() -> organizationalNodeUserApi.list(searchReq), "fetchNodeUsersByWorkspaceOuIdJobCodes", JSON.toJSONString(searchReq));
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,11 +3,16 @@ package cn.axzo.im.gateway;
|
||||
import cn.axzo.basics.profiles.api.UserProfileServiceApi;
|
||||
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
|
||||
import cn.axzo.im.entity.dto.PlatPersonDto;
|
||||
import cn.axzo.pokonyan.util.RpcUtil;
|
||||
import cn.azxo.framework.common.logger.MethodAroundLog;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@ -35,4 +40,12 @@ public class ProfilesApiGateway {
|
||||
}
|
||||
return BeanUtil.copyProperties(response.getData(), PlatPersonDto.class);
|
||||
}
|
||||
|
||||
public PersonProfileDto getPersonProfileById(Long personId) {
|
||||
return RpcUtil.rpcCommonProcessor(() -> userProfileServiceApi.getPersonProfile(personId), "getPersonProfileById", personId);
|
||||
}
|
||||
|
||||
public List<PersonProfileDto> getPersonProfilesByIds(List<Long> personIds) {
|
||||
return RpcUtil.rpcCommonProcessor(() -> userProfileServiceApi.getPersonProfiles(personIds), "getPersonProfilesByIds", JSON.toJSONString(personIds));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package cn.axzo.im.gateway;
|
||||
|
||||
import cn.axzo.pokonyan.util.RpcUtil;
|
||||
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
|
||||
import cn.axzo.tyr.client.feign.TyrSaasRoleUserApi;
|
||||
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserV2DTO;
|
||||
import cn.axzo.tyr.client.model.roleuser.req.ListRoleUserRelationParam;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Service("tyrApiGateway")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class TyrApiGateway {
|
||||
|
||||
private final TyrSaasRoleUserApi tyrSaasRoleUserApi;
|
||||
|
||||
public List<SaasRoleUserV2DTO> fetchSaasRoleUserByWorkspaceOuIdRoleTypes(Long workspaceId, Long ouId, Set<RoleTypeEnum> roleTypeEnumSet) {
|
||||
ArrayList<ListRoleUserRelationParam.WorkspaceOuPair> workspaceOuPairs = Lists.newArrayList(ListRoleUserRelationParam.WorkspaceOuPair.builder().workspaceId(workspaceId).ouId(ouId).build());
|
||||
ListRoleUserRelationParam listRoleUserRelationParam = ListRoleUserRelationParam.builder().roleTypes(roleTypeEnumSet).workspaceOuPairs(workspaceOuPairs).build();
|
||||
return RpcUtil.rpcApiResultProcessor(() -> tyrSaasRoleUserApi.roleUserListV2(listRoleUserRelationParam), "fetchSaasRoleUserByWorkspaceOuIdRoleTypes", JSON.toJSONString(listRoleUserRelationParam));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package cn.axzo.im.gateway;
|
||||
|
||||
import cn.axzo.apollo.core.web.Result;
|
||||
import cn.axzo.apollo.workspace.api.workspace.WorkspaceApi;
|
||||
import cn.axzo.apollo.workspace.api.workspace.res.GetDetailRes;
|
||||
import cn.axzo.pokonyan.util.RpcUtil;
|
||||
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
|
||||
import cn.axzo.tyr.client.feign.TyrSaasRoleUserApi;
|
||||
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserV2DTO;
|
||||
import cn.axzo.tyr.client.model.roleuser.req.ListRoleUserRelationParam;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Service("workspaceApiGateway")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class WorkspaceApiGateway {
|
||||
|
||||
private final WorkspaceApi workspaceApi;
|
||||
|
||||
public GetDetailRes getWorkspaceById(Long workspaceId) {
|
||||
try {
|
||||
log.info("getWorkspaceById-param:{}", workspaceId);
|
||||
Result<GetDetailRes> result = workspaceApi.getById(workspaceId);
|
||||
log.info("getWorkspaceById-result:{}", JSON.toJSONString(result));
|
||||
return result.getData();
|
||||
} catch (Exception e) {
|
||||
log.error("getWorkspaceById-error", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,161 @@
|
||||
package cn.axzo.im.handler.chatgroup;
|
||||
|
||||
import cn.axzo.basics.auth.dto.SaasRoleUserRelation;
|
||||
import cn.axzo.basics.common.exception.ServiceException;
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.framework.rocketmq.EventConsumer;
|
||||
import cn.axzo.framework.rocketmq.EventHandler;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupUserGenericSearchReq;
|
||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupUserTypeEnum;
|
||||
import cn.axzo.im.entity.ChatGroupUser;
|
||||
import cn.axzo.im.event.inner.EventTypeEnum;
|
||||
import cn.axzo.im.event.payload.SaasRoleUserRelationRemovePayload;
|
||||
import cn.axzo.im.event.payload.SaasRoleUserRelationUpsertPayload;
|
||||
import cn.axzo.im.gateway.TyrApiGateway;
|
||||
import cn.axzo.im.service.AccountService;
|
||||
import cn.axzo.im.service.ChatGroupService;
|
||||
import cn.axzo.im.service.ChatGroupUserService;
|
||||
import cn.axzo.im.utils.BizAssertions;
|
||||
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
|
||||
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserV2DTO;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/07
|
||||
* @desc 群聊创建MQ消费
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ChatGroupChangeOwnerEventHandler implements EventHandler, InitializingBean {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
|
||||
@Autowired
|
||||
private TyrApiGateway tyrApiGateway;
|
||||
|
||||
@Autowired
|
||||
private ChatGroupUserService chatGroupUserService;
|
||||
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
|
||||
@Autowired
|
||||
private ChatGroupService chatGroupService;
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event, EventConsumer.Context context) {
|
||||
if (!EventTypeEnum.SAAS_ROLE_USER_RELATION_REMOVED.getName().equalsIgnoreCase(event.getEventCode().getName())
|
||||
&& !EventTypeEnum.SAAS_ROLE_USER_RELATION_UPSERT.getName().equalsIgnoreCase(event.getEventCode().getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("ChatGroupChangeOwnerEventHandler-start - handle mq event, event={}", JSON.toJSONString(event));
|
||||
long start = System.currentTimeMillis();
|
||||
try {
|
||||
//角色删除
|
||||
if (EventTypeEnum.SAAS_ROLE_USER_RELATION_REMOVED.getName().equalsIgnoreCase(event.getEventCode().getName())) {
|
||||
this.handleMqMessageRoleRemove(event);
|
||||
log.info("ChatGroupChangeOwnerEventHandler-handle-roleRemove mq event, event={},used={}ms", JSON.toJSONString(event), System.currentTimeMillis() - start);
|
||||
return;
|
||||
}
|
||||
//角色变更
|
||||
if (EventTypeEnum.SAAS_ROLE_USER_RELATION_UPSERT.getName().equalsIgnoreCase(event.getEventCode().getName())) {
|
||||
this.handleMqMessageRoleUpsert(event);
|
||||
log.info("ChatGroupChangeOwnerEventHandler-handle-upsert mq event, event={},used={}ms", JSON.toJSONString(event), System.currentTimeMillis() - start);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("ChatGroupChangeOwnerEventHandler-handle error mq event, event={},used={}ms", JSON.toJSONString(event), System.currentTimeMillis() - start, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务逻辑-角色删除
|
||||
*/
|
||||
private void handleMqMessageRoleRemove(Event event) {
|
||||
//解析数据
|
||||
// SaasRoleUserRelationRemovePayload payload = event.normalizedData(SaasRoleUserRelationRemovePayload.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务逻辑-角色变更
|
||||
* 1 用户是群主的群聊集合
|
||||
* 2 更换群主
|
||||
*/
|
||||
private void handleMqMessageRoleUpsert(Event event) {
|
||||
//解析数据
|
||||
SaasRoleUserRelationUpsertPayload payload = event.normalizedData(SaasRoleUserRelationUpsertPayload.class);
|
||||
if (Objects.isNull(payload) || CollectionUtils.isEmpty(payload.getOldValues())) {
|
||||
log.info("ChatGroupChangeOwnerEventHandler-角色变更mq对象为空");
|
||||
return;
|
||||
}
|
||||
for(SaasRoleUserRelation item : payload.getOldValues()) {
|
||||
ChatGroupUserGenericSearchReq req = new ChatGroupUserGenericSearchReq();
|
||||
|
||||
String oldImAccountOwner = accountService.buildUserIdWrapper(item.getNaturalPersonId().toString(), AppTypeEnum.CMP.getCode(), item.getOuId());
|
||||
|
||||
//1 用户是群主的群聊集合
|
||||
req.setAccId(oldImAccountOwner);
|
||||
req.setType(ChatGroupUserTypeEnum.OWNER);
|
||||
List<ChatGroupUser> chatGroupUsers = chatGroupUserService.genericQuery(req);
|
||||
if (CollectionUtils.isEmpty(chatGroupUsers)) {
|
||||
log.info("ChatGroupChangeOwnerEventHandler-角色变更,personId:{},没有群是群主", item.getNaturalPersonId());
|
||||
continue;
|
||||
}
|
||||
for(ChatGroupUser chatGroupUser : chatGroupUsers) {
|
||||
switch (chatGroupUser.getCrowType()) {
|
||||
case WORKSPACE:
|
||||
// 2 更换群主
|
||||
this.changeOwner(item.getWorkspaceId(), null, Sets.newHashSet(RoleTypeEnum.SUPER_ADMIN), item, oldImAccountOwner, chatGroupUser);
|
||||
break;
|
||||
case OU:
|
||||
//2 更换群主
|
||||
this.changeOwner(item.getWorkspaceId(), item.getOuId(), Sets.newHashSet(RoleTypeEnum.ADMIN), item, oldImAccountOwner, chatGroupUser);
|
||||
break;
|
||||
case TEAM:
|
||||
break;
|
||||
default:
|
||||
throw new ServiceException("人群不存在");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更换群主
|
||||
*/
|
||||
private void changeOwner(Long workspaceId, Long ouId, Set<RoleTypeEnum> roleTypeEnumSet,SaasRoleUserRelation item, String oldImAccountOwner, ChatGroupUser chatGroupUser) {
|
||||
//获取最新群主
|
||||
List<SaasRoleUserV2DTO> saasRoleUserV2DTOS = tyrApiGateway.fetchSaasRoleUserByWorkspaceOuIdRoleTypes(workspaceId, ouId, roleTypeEnumSet);
|
||||
if (CollectionUtils.isEmpty(saasRoleUserV2DTOS)) {
|
||||
this.chatGroupService.sendDingRobot(String.format("创建群聊,personId:%d在workspaceId:%d,ouId:%d,人群:%s,找不到群主信息", item.getNaturalPersonId(), item.getWorkspaceId(), ouId, chatGroupUser.getCrowType()));
|
||||
}
|
||||
BizAssertions.assertNotEmpty(saasRoleUserV2DTOS, "personId:{}在workspaceId:{},ouId:%d,找不到群主信息", item.getNaturalPersonId(), item.getWorkspaceId(), ouId);
|
||||
SaasRoleUserV2DTO saasRoleUserV2DTOWhenOu = saasRoleUserV2DTOS.get(0);
|
||||
String newImAccountOwnerWhenOu = accountService.buildUserIdWrapper(saasRoleUserV2DTOWhenOu.getSaasRoleUser().getPersonId().toString(), AppTypeEnum.CMP.getCode(), item.getOuId());
|
||||
this.chatGroupService.changeOwner(chatGroupUser.getChatGroupId(), oldImAccountOwner, newImAccountOwnerWhenOu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Event.EventCode removedEventCode = new Event.EventCode(EventTypeEnum.SAAS_ROLE_USER_RELATION_REMOVED.getModel(), EventTypeEnum.SAAS_ROLE_USER_RELATION_REMOVED.getName());
|
||||
Event.EventCode upsertEventCode = new Event.EventCode(EventTypeEnum.SAAS_ROLE_USER_RELATION_UPSERT.getModel(), EventTypeEnum.SAAS_ROLE_USER_RELATION_UPSERT.getName());
|
||||
eventConsumer.registerHandler(removedEventCode, this);
|
||||
eventConsumer.registerHandler(upsertEventCode, this);
|
||||
}
|
||||
}
|
||||
@ -1,28 +1,42 @@
|
||||
package cn.axzo.im.handler.chatgroup;
|
||||
|
||||
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.framework.rocketmq.EventConsumer;
|
||||
import cn.axzo.framework.rocketmq.EventHandler;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.UserAccountReq;
|
||||
import cn.axzo.im.center.api.vo.resp.UserAccountResp;
|
||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
||||
import cn.axzo.im.channel.IMChannelProvider;
|
||||
import cn.axzo.im.channel.netease.INotifyService;
|
||||
import cn.axzo.im.channel.netease.dto.UserAddChatGroupRequest;
|
||||
import cn.axzo.im.event.inner.EventTypeEnum;
|
||||
import cn.axzo.im.event.payload.ChatGroupCreatePayload;
|
||||
import cn.axzo.im.gateway.ProfilesApiGateway;
|
||||
import cn.axzo.im.service.AccountService;
|
||||
import cn.axzo.im.service.ChatGroupService;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/07
|
||||
* @desc 群聊创建MQ消费
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@ -32,8 +46,6 @@ public class ChatGroupEventHandler implements EventHandler, InitializingBean {
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
|
||||
@Autowired
|
||||
private IMChannelProvider imChannelProvider;
|
||||
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
@ -41,8 +53,17 @@ public class ChatGroupEventHandler implements EventHandler, InitializingBean {
|
||||
@Resource
|
||||
private INotifyService iNotifyService;
|
||||
|
||||
@Autowired
|
||||
private ChatGroupService chatGroupService;
|
||||
|
||||
@Autowired
|
||||
private ProfilesApiGateway profilesApiGateway;
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event, EventConsumer.Context context) {
|
||||
if (!EventTypeEnum.MESSAGE_CHAT_GROUP_CREATE.getName().equalsIgnoreCase(event.getEventCode().getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("ChatGroupEventHandler-start - handle mq event, event={}", JSON.toJSONString(event));
|
||||
try {
|
||||
@ -51,27 +72,90 @@ public class ChatGroupEventHandler implements EventHandler, InitializingBean {
|
||||
long end = System.currentTimeMillis();
|
||||
log.info("ChatGroupEventHandlerend-handle mq event, used={}ms, event={}", end - start, JSON.toJSONString(event));
|
||||
} catch (Exception e) {
|
||||
log.warn("ChatGroupEventHandler-error - handle mq event, event={}", JSON.toJSONString(event));
|
||||
log.warn("ChatGroupEventHandler-error - handle mq event, event={}", JSON.toJSONString(event), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务逻辑
|
||||
*/
|
||||
private void handleMqMessage(Event event) {
|
||||
//解析数据
|
||||
ChatGroupCreatePayload payload = event.normalizedData(ChatGroupCreatePayload.class);
|
||||
ChatGroupCreateReq req = payload.getReq();
|
||||
|
||||
String tid = payload.getTid();
|
||||
String owner = payload.getOwner();
|
||||
String imAccountOwner = payload.getImAccountOwner();
|
||||
|
||||
String members = "";//TODO
|
||||
UserAccountReq userAccountReq = UserAccountReq.builder().appType(AppTypeEnum.SYSTEM.getCode()).userId("").nickName("").headImageUrl("").organizationalUnitId(1L).build();
|
||||
accountService.generateAccount(userAccountReq, iNotifyService);
|
||||
List<String> members = this.chatGroupOfMembers(req);
|
||||
this.chatGroupService.userAddChatGroup(payload.getChatGroupId(), tid,imAccountOwner,members, req.getGroupName());
|
||||
}
|
||||
|
||||
imChannelProvider.userAddChatGroup(UserAddChatGroupRequest.buildRequest(tid, owner, members,"进入群:" + req.getGroupName()));
|
||||
/**
|
||||
* 构建群成员信息
|
||||
*/
|
||||
public List<String> chatGroupOfMembers(ChatGroupCreateReq req) {
|
||||
//Pair,key:管理人员集合;value:工人集合
|
||||
Pair<Set<Long>, Set<Long>> adminWorkerSet = chatGroupService.fetchUsersByWorkspaceOuId(req.getCrowType(), req.getWorkspaceId(), req.getOuId(), this.chatGroupService.buildJobCodesByCrowType(req.getCrowType()), req.getCreator());
|
||||
Set<Long> adminSet = adminWorkerSet.getKey();
|
||||
Set<Long> workerSet = adminWorkerSet.getValue();
|
||||
|
||||
Map<Long, PersonProfileDto> personProfileMap = this.buildPersonProfileMap(adminWorkerSet);
|
||||
|
||||
List<UserAccountResp> userAccountRespList = Lists.newArrayList();
|
||||
|
||||
for (Long item : adminSet) {
|
||||
PersonProfileDto personProfileDto = personProfileMap.get(item);
|
||||
if (Objects.isNull(personProfileDto) || Objects.isNull(personProfileDto.getId())) {
|
||||
log.info("admin-personProfileDto is null");
|
||||
continue;
|
||||
}
|
||||
UserAccountReq userAccountReq = UserAccountReq.builder()
|
||||
.appType(AppTypeEnum.CMP.getCode())//管理端:AppTypeEnum.CMP.getCode();工人端:AppTypeEnum.CM.getCode()
|
||||
.userId(item.toString()).nickName(personProfileDto.getRealName())
|
||||
.headImageUrl(personProfileDto.getAvatarUrl())
|
||||
.organizationalUnitId(req.getOuId())
|
||||
.build();
|
||||
userAccountRespList.add(accountService.generateAccount(userAccountReq, iNotifyService));
|
||||
}
|
||||
|
||||
for (Long worker : workerSet) {
|
||||
PersonProfileDto personProfileDto = personProfileMap.get(worker);
|
||||
if (Objects.isNull(personProfileDto) || Objects.isNull(personProfileDto.getId())) {
|
||||
log.info("worker-personProfileDto is null");
|
||||
continue;
|
||||
}
|
||||
UserAccountReq userAccountReq = UserAccountReq.builder()
|
||||
.appType(AppTypeEnum.CM.getCode())//管理端:AppTypeEnum.CMP.getCode();工人端:AppTypeEnum.CM.getCode()
|
||||
.userId(worker.toString()).nickName(personProfileDto.getRealName())
|
||||
.headImageUrl(personProfileDto.getAvatarUrl())
|
||||
.organizationalUnitId(req.getOuId())
|
||||
.build();
|
||||
userAccountRespList.add(accountService.generateAccount(userAccountReq, iNotifyService));
|
||||
}
|
||||
|
||||
return userAccountRespList.stream().map(UserAccountResp::getImAccount).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建personProfile的Map
|
||||
* key:id,value:personProfile
|
||||
*/
|
||||
private Map<Long, PersonProfileDto> buildPersonProfileMap(Pair<Set<Long>, Set<Long>> adminWorkerSet) {
|
||||
|
||||
Set<Long> adminSet = CollectionUtils.isNotEmpty(adminWorkerSet.getKey()) ? adminWorkerSet.getKey() : Sets.newHashSet();
|
||||
Set<Long> workerSet = CollectionUtils.isNotEmpty(adminWorkerSet.getValue()) ? adminWorkerSet.getValue() : Sets.newHashSet();
|
||||
|
||||
List<Long> adminWorkerList = Lists.newArrayList();
|
||||
adminWorkerList.addAll(Lists.newArrayList(adminSet));
|
||||
adminWorkerList.addAll(Lists.newArrayList(workerSet));
|
||||
|
||||
List<PersonProfileDto> personProfileDtoList = profilesApiGateway.getPersonProfilesByIds(adminWorkerList);
|
||||
return personProfileDtoList.stream().collect(Collectors.toMap(PersonProfileDto::getId, Function.identity(), (x, y) -> x));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
public void afterPropertiesSet() {
|
||||
Event.EventCode eventCode = new Event.EventCode(EventTypeEnum.MESSAGE_CHAT_GROUP_CREATE.getModel(), EventTypeEnum.MESSAGE_CHAT_GROUP_CREATE.getName());
|
||||
eventConsumer.registerHandler(eventCode, this);
|
||||
}
|
||||
|
||||
@ -0,0 +1,261 @@
|
||||
package cn.axzo.im.handler.chatgroup;
|
||||
|
||||
import cn.axzo.apollo.core.service.ServiceException;
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.framework.rocketmq.EventConsumer;
|
||||
import cn.axzo.framework.rocketmq.EventHandler;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupGenericSearchReq;
|
||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
||||
import cn.axzo.im.channel.netease.NimChannelService;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupQueryResponse;
|
||||
import cn.axzo.im.entity.ChatGroup;
|
||||
import cn.axzo.im.event.inner.EventTypeEnum;
|
||||
import cn.axzo.im.event.payload.OrganizationalNodeUserPayload;
|
||||
import cn.axzo.im.gateway.OrgJobApiGateway;
|
||||
import cn.axzo.im.service.AccountService;
|
||||
import cn.axzo.im.service.ChatGroupService;
|
||||
import cn.axzo.im.utils.BizAssertions;
|
||||
import cn.axzo.im.utils.JobCodeUtils;
|
||||
import cn.axzo.maokai.api.vo.response.OrgJobRes;
|
||||
import com.alibaba.excel.util.StringUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/07
|
||||
* @desc 群聊创建MQ消费-同步网易云信
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class OrganizationalNodeUserChangeEventHandler implements EventHandler, InitializingBean {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
|
||||
@Autowired
|
||||
private ChatGroupService chatGroupService;
|
||||
|
||||
@Autowired
|
||||
private NimChannelService nimChannelService;
|
||||
|
||||
@Autowired
|
||||
private OrgJobApiGateway orgJobApiGateway;
|
||||
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event, EventConsumer.Context context) {
|
||||
|
||||
if (!EventTypeEnum.NODE_USER_CREATE.getName().equalsIgnoreCase(event.getEventCode().getName())
|
||||
&& !EventTypeEnum.NODE_USER_UPDATE.getName().equalsIgnoreCase(event.getEventCode().getName())
|
||||
&& !EventTypeEnum.NODE_USER_DELETE.getName().equalsIgnoreCase(event.getEventCode().getName())
|
||||
&& !EventTypeEnum.NODE_USER_UPSERTED.getName().equalsIgnoreCase(event.getEventCode().getName())) {
|
||||
return;
|
||||
}
|
||||
log.info("im-organizationalNodeUserChange-start mq,eventModule:{},eventName:{}, event:{}", event.getEventCode().getModule(), event.getEventCode().getName(), JSON.toJSONString(event));
|
||||
long start = System.currentTimeMillis();
|
||||
try {
|
||||
handleMqMessage(event);
|
||||
log.info("OrganizationalNodeUserChangeEventHandler-handle mq event, event={},used={}ms", JSON.toJSONString(event), System.currentTimeMillis() - start);
|
||||
} catch (Exception e) {
|
||||
log.warn("OrganizationalNodeUserChangeEventHandler-handle error mq event, event={},used={}ms", JSON.toJSONString(event), System.currentTimeMillis() - start, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务逻辑
|
||||
*/
|
||||
private void handleMqMessage(Event event) {
|
||||
//解析数据
|
||||
OrganizationalNodeUserPayload payload = event.normalizedData(OrganizationalNodeUserPayload.class);
|
||||
|
||||
Long workspaceId = payload.getWorkspaceId();
|
||||
Long ouId = payload.getOrganizationalUnitId();
|
||||
Long nodeId = payload.getOrganizationalNodeId();
|
||||
|
||||
|
||||
this.enterOrExitChatGroupByCrowType(ChatGroupCreateReq.CrowTypeEnum.WORKSPACE, workspaceId, null, null, payload, event.getEventCode().getName());
|
||||
this.enterOrExitChatGroupByCrowType(ChatGroupCreateReq.CrowTypeEnum.OU, workspaceId, ouId, null, payload, event.getEventCode().getName());
|
||||
this.enterOrExitChatGroupByCrowType(ChatGroupCreateReq.CrowTypeEnum.TEAM, workspaceId, null, nodeId, payload, event.getEventCode().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入群聊或者退出群聊-通过人群
|
||||
* @param crowTypeEnum 人群
|
||||
* @param workspaceId 项目ID
|
||||
* @param ouId 单位Id
|
||||
* @param teamId 班组Id
|
||||
* @param payload mq消息
|
||||
* @param tag mq的tag
|
||||
*/
|
||||
private void enterOrExitChatGroupByCrowType(ChatGroupCreateReq.CrowTypeEnum crowTypeEnum, Long workspaceId,Long ouId, Long teamId, OrganizationalNodeUserPayload payload, String tag) {
|
||||
List<ChatGroup> workspaceChatGroups = chatGroupService.genericQuery(ChatGroupGenericSearchReq.builder()
|
||||
.crowType(crowTypeEnum)
|
||||
.workspaceId(workspaceId)
|
||||
.ouId(ouId)
|
||||
.teamId(teamId)
|
||||
.build());
|
||||
if (CollectionUtils.isEmpty(workspaceChatGroups)) {
|
||||
log.info("群聊监控orgNodeUser,人员变更查询不到群聊,workspaceId:{},crowType:{}", workspaceId, crowTypeEnum);
|
||||
return;
|
||||
}
|
||||
//人群类型:项目,同一个项目只存在一个群聊
|
||||
ChatGroup chatGroup = workspaceChatGroups.get(0);
|
||||
String jobCode = fetchJobCodeByJobId(payload.getOrganizationalJobId());
|
||||
if (StringUtils.isBlank(jobCode)) {
|
||||
log.info("群聊监控orgNodeUser,人员变更根据jobId获取jobCode为空,jobId:{}", payload.getOrganizationalJobId());
|
||||
chatGroupService.sendDingRobot(String.format("群聊监控orgNodeUser,人员变更根据jobId获取jobCode为空,jobId:%s,nodeId:%d", payload.getOrganizationalJobId(), payload.getOrganizationalNodeId()));
|
||||
return;
|
||||
}
|
||||
|
||||
String imAccount = this.buildImAccount(payload.getPersonId(), payload.getOrganizationalUnitId(), jobCode, chatGroup.getCrowType());
|
||||
this.enterOrExitChatGroup(tag, chatGroup, jobCode, imAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取岗位code
|
||||
*/
|
||||
private String fetchJobCodeByJobId(Long jobId) {
|
||||
OrgJobRes orgJobRes = orgJobApiGateway.fetchJobCodeByJobId(jobId);
|
||||
if (Objects.nonNull(orgJobRes)) {
|
||||
return orgJobRes.getCode();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入群聊或者退出群聊
|
||||
* @param tag MQ的tag
|
||||
* @param chatGroup 群聊对象
|
||||
* @param currentJobCode 岗位code
|
||||
* @param currentImAccount im账号
|
||||
*/
|
||||
private void enterOrExitChatGroup(String tag, ChatGroup chatGroup, String currentJobCode, String currentImAccount) {
|
||||
String tid = chatGroup.getTid();
|
||||
ChatGroupQueryResponse chatGroupQueryResponse = nimChannelService.chatGroupQueryByTids(Lists.newArrayList(tid), 1);
|
||||
if (Objects.isNull(chatGroupQueryResponse) || CollectionUtils.isEmpty(chatGroupQueryResponse.getTinfos())) {
|
||||
log.info("enterOrExitChatGroup-chatGroupQueryByTids response is empty or tinfos is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
ChatGroupQueryResponse.TInfo tInfo = chatGroupQueryResponse.getTinfos().get(0);
|
||||
String members = tInfo.getMembers();
|
||||
|
||||
switch (chatGroup.getCrowType()) {
|
||||
case WORKSPACE:
|
||||
case OU:
|
||||
//加入群聊或者退出群聊-执行动作
|
||||
this.doEnterOrExitChatGroup(tag, chatGroup, currentImAccount, members, tInfo.getOwner(), JobCodeUtils.isAdmin(currentJobCode));
|
||||
break;
|
||||
case TEAM:
|
||||
//当处理项目内班组时,更改群组
|
||||
this.changeOwnerWithTeam(chatGroup, currentImAccount, JobCodeUtils.isProjectTeamLeader(currentJobCode));
|
||||
//加入群聊或者退出群聊-执行动作
|
||||
this.doEnterOrExitChatGroup(tag, chatGroup, currentImAccount, members, tInfo.getOwner(), JobCodeUtils.isTeam(currentJobCode));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当处理项目内班组时,更改群组
|
||||
* @param chatGroup 群聊对象
|
||||
* @param currentImAccount 当前Im账号
|
||||
* @param isProjectTeamLeader 岗位是否时班组长
|
||||
*/
|
||||
private void changeOwnerWithTeam(ChatGroup chatGroup, String currentImAccount, boolean isProjectTeamLeader) {
|
||||
if(!isProjectTeamLeader) {
|
||||
log.info("岗位不是班组长,不执行更改群主逻辑,currentImAccount:{},chatGroupId:{}", currentImAccount, chatGroup.getId());
|
||||
return;
|
||||
}
|
||||
if (chatGroup.getGroupOwner().equals(currentImAccount)) {
|
||||
log.info("班组长并未变更,不执行更改群主逻辑,currentImAccount:{},chatGroupId:{}", currentImAccount, chatGroup.getId());
|
||||
return;
|
||||
}
|
||||
this.chatGroupService.changeOwner(chatGroup.getId(), chatGroup.getGroupOwner(), currentImAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入群聊或者退出群聊-执行动作
|
||||
* @param tag MQ的tag
|
||||
* @param chatGroup 群聊对象
|
||||
* @param currentImAccount im账号
|
||||
* @param members 群聊已有会员
|
||||
* @param owner 群主
|
||||
* @param containJobCode 包含job
|
||||
*/
|
||||
private void doEnterOrExitChatGroup(String tag, ChatGroup chatGroup, String currentImAccount,String members, String owner, boolean containJobCode) {
|
||||
|
||||
//orgNodeUser新增人,并且当前群不包含人
|
||||
if (tag.equals(EventTypeEnum.NODE_USER_CREATE.getName()) && containJobCode &&!members.contains(currentImAccount)) {
|
||||
//拉人进群
|
||||
this.chatGroupService.userAddChatGroup(chatGroup.getId(), chatGroup.getTid(), owner, Lists.newArrayList(currentImAccount), chatGroup.getName());
|
||||
return;
|
||||
}
|
||||
//orgNodeUser删除人 并且当前成员不包含人
|
||||
if (tag.equals(EventTypeEnum.NODE_USER_DELETE.getName()) && members.contains(currentImAccount)) {
|
||||
//踢出群
|
||||
this.chatGroupService.kickChatGroup(chatGroup.getId(), chatGroup.getTid(), owner,currentImAccount);
|
||||
return;
|
||||
}
|
||||
//以下orgNodeUser更新
|
||||
if (!tag.equals(EventTypeEnum.NODE_USER_UPDATE.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (containJobCode && !members.contains(currentImAccount)) {
|
||||
//拉人进群
|
||||
this.chatGroupService.userAddChatGroup(chatGroup.getId(), chatGroup.getTid(), owner, Lists.newArrayList(currentImAccount), chatGroup.getName());
|
||||
return;
|
||||
}
|
||||
if (!containJobCode && members.contains(currentImAccount)) {
|
||||
//踢出群
|
||||
this.chatGroupService.kickChatGroup(chatGroup.getId(), chatGroup.getTid(), owner, currentImAccount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建IM账号
|
||||
*/
|
||||
private String buildImAccount(Long personId, Long ouId, String jobCode, ChatGroupCreateReq.CrowTypeEnum crowTypeEnum) {
|
||||
switch (crowTypeEnum) {
|
||||
case WORKSPACE:
|
||||
case OU:
|
||||
return accountService.buildUserIdWrapper(personId.toString(), AppTypeEnum.CMP.getCode(), ouId);
|
||||
case TEAM:
|
||||
if (jobCode.equals("projTeamLeader") || jobCode.equals("projectTeamManager")) {
|
||||
return accountService.buildUserIdWrapper(personId.toString(), AppTypeEnum.CMP.getCode(), ouId);
|
||||
}
|
||||
return accountService.buildUserIdWrapper(personId.toString(), AppTypeEnum.CM.getCode(), ouId);
|
||||
default:
|
||||
BizAssertions.assertTrue(false, "人群类型不匹配");
|
||||
}
|
||||
throw new ServiceException("人群类型不匹配");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Event.EventCode nodeUserCreateEventCode = new Event.EventCode(EventTypeEnum.NODE_USER_CREATE.getModel(), EventTypeEnum.NODE_USER_CREATE.getName());
|
||||
Event.EventCode nodeUserUpdateEventCode = new Event.EventCode(EventTypeEnum.NODE_USER_UPDATE.getModel(), EventTypeEnum.NODE_USER_UPDATE.getName());
|
||||
Event.EventCode nodeUserDeleteEventCode = new Event.EventCode(EventTypeEnum.NODE_USER_DELETE.getModel(), EventTypeEnum.NODE_USER_DELETE.getName());
|
||||
Event.EventCode nodeUserUpsertedEventCode = new Event.EventCode(EventTypeEnum.NODE_USER_UPSERTED.getModel(), EventTypeEnum.NODE_USER_UPSERTED.getName());
|
||||
|
||||
eventConsumer.registerHandler(nodeUserCreateEventCode, this);
|
||||
eventConsumer.registerHandler(nodeUserUpdateEventCode, this);
|
||||
eventConsumer.registerHandler(nodeUserDeleteEventCode, this);
|
||||
eventConsumer.registerHandler(nodeUserUpsertedEventCode, this);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
package cn.axzo.im.handler.chatgroup;
|
||||
|
||||
import cn.axzo.basics.profiles.api.UserProfileServiceApi;
|
||||
import cn.axzo.basics.profiles.common.enums.ProfileMQEventEnum;
|
||||
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
|
||||
import cn.axzo.basics.profiles.dto.mq.ProfileMQBaseEntity;
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.framework.rocketmq.EventConsumer;
|
||||
import cn.axzo.framework.rocketmq.EventHandler;
|
||||
import cn.axzo.im.channel.netease.dto.GetAccountInfoResponse;
|
||||
import cn.axzo.im.entity.AccountRegister;
|
||||
import cn.axzo.im.entity.bo.AccountQueryParam;
|
||||
import cn.axzo.im.event.inner.EventTypeEnum;
|
||||
import cn.axzo.im.service.AccountService;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/07
|
||||
* @desc 群聊创建MQ消费-同步网易云信
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PersonProfileAvatarUpdateEventHandler implements EventHandler, InitializingBean {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
|
||||
@Autowired
|
||||
private UserProfileServiceApi userProfileServiceApi;
|
||||
@Override
|
||||
public void onEvent(Event event, EventConsumer.Context context) {
|
||||
|
||||
if (!ProfileMQEventEnum.UPDATE_AVATAR.getTag().equalsIgnoreCase(event.getEventCode().getName())) {
|
||||
return;
|
||||
}
|
||||
log.info("im-updateAvatar-start mq,eventModule:{},eventName:{}, event:{}", event.getEventCode().getModule(), event.getEventCode().getName(), JSON.toJSONString(event));
|
||||
long start = System.currentTimeMillis();
|
||||
try {
|
||||
handleMqMessage(event);
|
||||
log.info("PersonProfileAvatarUpdateEventHandler-handle mq event, event={},used={}ms", JSON.toJSONString(event), System.currentTimeMillis() - start);
|
||||
} catch (Exception e) {
|
||||
log.warn("PersonProfileAvatarUpdateEventHandler-handle error mq event, event={},used={}ms", JSON.toJSONString(event), System.currentTimeMillis() - start, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务逻辑
|
||||
*/
|
||||
private void handleMqMessage(Event event) {
|
||||
//解析数据
|
||||
ProfileMQBaseEntity eventData = event.normalizedData(ProfileMQBaseEntity.class);
|
||||
|
||||
AccountQueryParam param = new AccountQueryParam();
|
||||
param.setAccountId(eventData.getId().toString());
|
||||
//1 获取账号信息
|
||||
List<AccountRegister> accountRegisters = accountService.listAccount(param);
|
||||
if (CollectionUtils.isEmpty(accountRegisters)) {
|
||||
log.info("未找到im账号信息,personId:{}", eventData.getId().toString());
|
||||
return;
|
||||
}
|
||||
//2 获取PersonProfile
|
||||
CommonResponse<PersonProfileDto> personProfileDtoCommonResponse = userProfileServiceApi.getPersonProfile(eventData.getId());
|
||||
if (Objects.isNull(personProfileDtoCommonResponse) || Objects.isNull(personProfileDtoCommonResponse.getData())) {
|
||||
log.info("未找到personProfile信息,personId:{}", eventData.getId().toString());
|
||||
return;
|
||||
}
|
||||
//3 同步网易云信账号
|
||||
PersonProfileDto personProfileDto = personProfileDtoCommonResponse.getData();
|
||||
for (AccountRegister accountRegister : accountRegisters) {
|
||||
GetAccountInfoResponse.AccountInfo accountInfo = accountService.fetchImAccountInfoByImAccount(accountRegister.getImAccount());
|
||||
accountService.syncImAccount(accountRegister.getAccountId(), accountRegister.getImAccount(), accountInfo.getOrCreateExtObject(),personProfileDto.getAvatarUrl(), personProfileDto.getRealName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Event.EventCode eventCode = new Event.EventCode(EventTypeEnum.UPDATE_AVATAR.getModel(), EventTypeEnum.UPDATE_AVATAR.getName());
|
||||
eventConsumer.registerHandler(eventCode, this);
|
||||
}
|
||||
}
|
||||
@ -6,12 +6,12 @@ import cn.axzo.basics.profiles.dto.basic.BasicDto;
|
||||
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
|
||||
import cn.axzo.im.center.common.enums.AccountTypeEnum;
|
||||
import cn.axzo.im.channel.netease.client.NimClient;
|
||||
import cn.axzo.im.channel.netease.dto.GetAccountInfoRequest;
|
||||
import cn.axzo.im.channel.netease.dto.GetAccountInfoResponse;
|
||||
import cn.axzo.im.channel.netease.dto.UpdateAccountInfoRequest;
|
||||
import cn.axzo.im.channel.netease.dto.UpdateAccountInfoResponse;
|
||||
import cn.axzo.im.dao.repository.AccountRegisterDao;
|
||||
import cn.axzo.im.entity.AccountRegister;
|
||||
import cn.axzo.im.service.AccountService;
|
||||
import cn.axzo.im.utils.BizAssertions;
|
||||
import cn.axzo.maokai.api.util.Ref;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
@ -44,6 +44,8 @@ public class UpdateImAccountPersonInfoJob {
|
||||
private final NimClient nimClient;
|
||||
private final UserProfileServiceApi userProfileServiceApi;
|
||||
|
||||
private final AccountService accountService;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@XxlJob("updateImAccountPersonInfoJob")
|
||||
public ReturnT<String> execute(String jsonStr) throws Exception {
|
||||
@ -59,21 +61,62 @@ public class UpdateImAccountPersonInfoJob {
|
||||
}
|
||||
|
||||
private void executeImpl() {
|
||||
RateLimiter rateLimiter = RateLimiter.create(60);
|
||||
|
||||
Supplier<List<AccountRegister>> cursor = accountsCursor();
|
||||
int count = 0;
|
||||
for (List<AccountRegister> accounts = cursor.get(); !accounts.isEmpty(); accounts = cursor.get()) {
|
||||
log.info("update account info, count: {}", count += accounts.size());
|
||||
GetAccountInfoRequest getAccountInfoRequest = new GetAccountInfoRequest();
|
||||
getAccountInfoRequest.setImAccountIds(accounts.stream()
|
||||
.map(AccountRegister::getImAccount)
|
||||
.distinct()
|
||||
.collect(toList()));
|
||||
GetAccountInfoResponse getAccountInfoResponse = nimClient.getAccountInfo(getAccountInfoRequest);
|
||||
if (!getAccountInfoResponse.isSuccess()) {
|
||||
log.warn("get account info failed, {}", getAccountInfoResponse);
|
||||
//1 获取IM账号
|
||||
GetAccountInfoResponse imAccountList = accountService.getImAccount(accounts);
|
||||
|
||||
if (!imAccountList.isSuccess()) {
|
||||
log.warn("get account info failed, {}", imAccountList);
|
||||
continue;
|
||||
}
|
||||
//2 构建PersonProfile
|
||||
Map<Long, PersonProfileDto> id2PersonProfile = this.buildPersonProfileMap(accounts);
|
||||
for (AccountRegister account : accounts) {
|
||||
GetAccountInfoResponse.AccountInfo imAccount = imAccountList.findImAccountInfo(account.getImAccount()).orElse(null);
|
||||
if (imAccount == null) continue;
|
||||
//3 获取personProfile
|
||||
PersonProfileDto person = this.fetchPersonById(account.getAccountId(), id2PersonProfile);
|
||||
if (Objects.isNull(person) || Objects.isNull(person.getId())) {
|
||||
log.info("personProfile为空,personId:{}", account.getAccountId());
|
||||
continue;
|
||||
}
|
||||
//4 更新IM账号
|
||||
UpdateAccountInfoResponse updateAccountInfoResponse
|
||||
= accountService.syncImAccount(account.getAccountId(), imAccount.getAccid()
|
||||
,imAccount.getOrCreateExtObject(), person.getAvatarUrl(), person.getRealName());
|
||||
//日志打印
|
||||
this.successLog(updateAccountInfoResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PersonProfileDto fetchPersonById(String accountId, Map<Long, PersonProfileDto> id2PersonProfile) {
|
||||
long personId = Long.parseLong(accountId);
|
||||
PersonProfileDto person = id2PersonProfile.get(personId);
|
||||
if (Objects.isNull(person) || Objects.isNull(person.getId())) {
|
||||
log.info("personProfile为空,personId:{}", person);
|
||||
return null;
|
||||
}
|
||||
return person;
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志打印
|
||||
* @param updateAccountInfoResponse
|
||||
*/
|
||||
private void successLog(UpdateAccountInfoResponse updateAccountInfoResponse) {
|
||||
if (updateAccountInfoResponse.isSuccess()) {
|
||||
log.info("update account info success, {}", updateAccountInfoResponse);
|
||||
} else {
|
||||
log.warn("update account info failed, {}", updateAccountInfoResponse);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Long, PersonProfileDto> buildPersonProfileMap(List<AccountRegister> accounts) {
|
||||
List<Long> personIds = accounts.stream()
|
||||
.map(AccountRegister::getAccountId)
|
||||
.filter(Objects::nonNull)
|
||||
@ -81,14 +124,13 @@ public class UpdateImAccountPersonInfoJob {
|
||||
.map(Long::parseLong)
|
||||
.distinct()
|
||||
.collect(toList());
|
||||
Map<Long, PersonProfileDto> id2PersonProfile = BizAssertions.assertResponse(
|
||||
return BizAssertions.assertResponse(
|
||||
userProfileServiceApi.getPersonProfiles(personIds)).stream()
|
||||
.collect(Collectors.toMap(BasicDto::getId, i -> i));
|
||||
for (AccountRegister account : accounts) {
|
||||
GetAccountInfoResponse.AccountInfo accountInfo = getAccountInfoResponse
|
||||
.findImAccountInfo(account.getImAccount()).orElse(null);
|
||||
if (accountInfo == null) continue;
|
||||
}
|
||||
|
||||
private UpdateAccountInfoResponse updateImAccount(AccountRegister account, GetAccountInfoResponse.AccountInfo accountInfo,Map<Long, PersonProfileDto> id2PersonProfile) {
|
||||
RateLimiter rateLimiter = RateLimiter.create(60);
|
||||
JSONObject ext = accountInfo.getOrCreateExtObject();
|
||||
ext.put("personId", account.getAccountId());
|
||||
|
||||
@ -110,15 +152,8 @@ public class UpdateImAccountPersonInfoJob {
|
||||
}
|
||||
|
||||
rateLimiter.acquire();
|
||||
UpdateAccountInfoResponse updateAccountInfoResponse = nimClient
|
||||
return nimClient
|
||||
.updateAccountInfo(updateAccountInfoRequest);
|
||||
if (updateAccountInfoResponse.isSuccess()) {
|
||||
log.info("update account info success, {}", updateAccountInfoResponse);
|
||||
} else {
|
||||
log.warn("update account info failed, {}", updateAccountInfoResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Supplier<List<AccountRegister>> accountsCursor() {
|
||||
|
||||
@ -14,11 +14,15 @@ import cn.axzo.im.center.common.enums.RobotStatusEnum;
|
||||
import cn.axzo.im.channel.IMChannelProvider;
|
||||
import cn.axzo.im.channel.netease.INotifyService;
|
||||
import cn.axzo.im.channel.netease.client.NimClient;
|
||||
import cn.axzo.im.channel.netease.dto.GetAccountInfoRequest;
|
||||
import cn.axzo.im.channel.netease.dto.GetAccountInfoResponse;
|
||||
import cn.axzo.im.channel.netease.dto.NimAccountInfo;
|
||||
import cn.axzo.im.channel.netease.dto.RefreshTokenRequest;
|
||||
import cn.axzo.im.channel.netease.dto.RefreshTokenResponse;
|
||||
import cn.axzo.im.channel.netease.dto.RegisterRequest;
|
||||
import cn.axzo.im.channel.netease.dto.RegisterResponse;
|
||||
import cn.axzo.im.channel.netease.dto.UpdateAccountInfoRequest;
|
||||
import cn.axzo.im.channel.netease.dto.UpdateAccountInfoResponse;
|
||||
import cn.axzo.im.dao.mapper.AccountRegisterMapper;
|
||||
import cn.axzo.im.dao.repository.AccountRegisterDao;
|
||||
import cn.axzo.im.dao.repository.RobotInfoDao;
|
||||
@ -27,13 +31,16 @@ import cn.axzo.im.entity.RobotInfo;
|
||||
import cn.axzo.im.entity.bo.AccountQueryParam;
|
||||
import cn.axzo.im.utils.MiscUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.util.concurrent.RateLimiter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.env.Environment;
|
||||
@ -55,6 +62,7 @@ import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.im.utils.Queries.query;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* IM账户服务
|
||||
@ -459,4 +467,61 @@ public class AccountService {
|
||||
}
|
||||
return lambdaQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步网易云信账号
|
||||
*/
|
||||
public UpdateAccountInfoResponse syncImAccount(String accountId, String accid, JSONObject ext, String avatarUrl, String realName) {
|
||||
RateLimiter rateLimiter = RateLimiter.create(60);
|
||||
ext.put("personId", accountId);
|
||||
|
||||
UpdateAccountInfoRequest updateAccountInfoRequest = new UpdateAccountInfoRequest();
|
||||
updateAccountInfoRequest.setImAccountId(accid);
|
||||
updateAccountInfoRequest.addExt(ext);
|
||||
|
||||
if (accountId != null && NumberUtils.isCreatable(accountId)) {
|
||||
if (StringUtils.isNotBlank(avatarUrl)) {
|
||||
updateAccountInfoRequest.setIcon(avatarUrl);
|
||||
}
|
||||
if (StringUtils.isNotBlank(realName)) {
|
||||
updateAccountInfoRequest.setName(realName);
|
||||
}
|
||||
}
|
||||
|
||||
rateLimiter.acquire();
|
||||
return nimClient.updateAccountInfo(updateAccountInfoRequest);
|
||||
}
|
||||
|
||||
public GetAccountInfoResponse getImAccount(List<AccountRegister> accounts) {
|
||||
if (CollectionUtils.isEmpty(accounts)) {
|
||||
return null;
|
||||
}
|
||||
GetAccountInfoRequest getAccountInfoRequest = new GetAccountInfoRequest();
|
||||
getAccountInfoRequest.setImAccountIds(accounts.stream().map(item -> item.getImAccount()).distinct().collect(toList()));
|
||||
return nimClient.getAccountInfo(getAccountInfoRequest);
|
||||
}
|
||||
|
||||
public List<GetAccountInfoResponse.AccountInfo> fetchImAccountsByImAccounts(List<String> accounts) {
|
||||
if (CollectionUtils.isEmpty(accounts)) {
|
||||
return null;
|
||||
}
|
||||
GetAccountInfoRequest getAccountInfoRequest = new GetAccountInfoRequest();
|
||||
getAccountInfoRequest.setImAccountIds(accounts);
|
||||
GetAccountInfoResponse response = nimClient.getAccountInfo(getAccountInfoRequest);
|
||||
if (Objects.isNull(response) || CollectionUtils.isEmpty(response.getUinfos())) {
|
||||
return null;
|
||||
}
|
||||
return response.getUinfos();
|
||||
}
|
||||
|
||||
public GetAccountInfoResponse.AccountInfo fetchImAccountInfoByImAccount(String imAccount) {
|
||||
if (StringUtils.isBlank(imAccount)) {
|
||||
return null;
|
||||
}
|
||||
List<GetAccountInfoResponse.AccountInfo> accountInfos = this.fetchImAccountsByImAccounts(Lists.newArrayList(imAccount));
|
||||
if (CollectionUtils.isEmpty(accountInfos)) {
|
||||
return null;
|
||||
}
|
||||
return accountInfos.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,18 @@
|
||||
package cn.axzo.im.service;
|
||||
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupGenericSearchReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupQueryReq;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupCreateResp;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateRequest;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateResponse;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupQueryResp;
|
||||
import cn.axzo.im.entity.ChatGroup;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/05
|
||||
@ -17,6 +23,63 @@ public interface ChatGroupService extends IService<ChatGroup> {
|
||||
/**
|
||||
* 创建群聊
|
||||
*/
|
||||
ChatGroupCreateResp chatGroupCreate(ChatGroupCreateReq req);
|
||||
ApiResult<ChatGroupCreateResp> chatGroupCreate(ChatGroupCreateReq req);
|
||||
|
||||
/**
|
||||
* 获取IM账号
|
||||
*/
|
||||
Pair<Set<Long>, Set<Long>> fetchUsersByWorkspaceOuId(ChatGroupCreateReq.CrowTypeEnum crowType, Long workspaceId, Long ouId, Set<String> jobCodes, Long personId);
|
||||
|
||||
/**
|
||||
* 通用查询-少条件后期在补
|
||||
*/
|
||||
List<ChatGroup> genericQuery(ChatGroupGenericSearchReq req);
|
||||
|
||||
/**
|
||||
* 通过Id查询群聊
|
||||
*/
|
||||
ChatGroup getById(Long id);
|
||||
|
||||
/**
|
||||
* 获取群聊
|
||||
*/
|
||||
ChatGroupQueryResp chatGroupQuery(ChatGroupQueryReq req);
|
||||
|
||||
|
||||
/**
|
||||
* 根据人群,返回jobCode
|
||||
*/
|
||||
Set<String> buildJobCodesByCrowType(ChatGroupCreateReq.CrowTypeEnum crowType);
|
||||
|
||||
/**
|
||||
* 发送钉钉群
|
||||
*/
|
||||
void sendDingRobot(String content);
|
||||
|
||||
/**
|
||||
* 拉人进群
|
||||
* @param tid 群Id
|
||||
* @param owner 群主
|
||||
* @param members im账号集合
|
||||
* @param groupName 群名称
|
||||
*/
|
||||
void userAddChatGroup(Long chatGroupId, String tid, String owner, List<String> members, String groupName);
|
||||
|
||||
/**
|
||||
* 踢出群
|
||||
* @param tid 群Id
|
||||
* @param owner 群主
|
||||
* @param imAccount im账号
|
||||
*/
|
||||
void kickChatGroup(Long chatGroupId, String tid, String owner, String imAccount);
|
||||
|
||||
/**
|
||||
* 更改群主
|
||||
* @param chatGroupId 群聊Id
|
||||
* @param oldAccIdOwner 原群主账号
|
||||
* @param newAccIdOwner 新群主账号
|
||||
*/
|
||||
void changeOwner(Long chatGroupId, String oldAccIdOwner, String newAccIdOwner);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
package cn.axzo.im.service;
|
||||
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupUserGenericSearchReq;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupStatusEnum;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupUserTypeEnum;
|
||||
import cn.axzo.im.entity.ChatGroup;
|
||||
import cn.axzo.im.entity.ChatGroupUser;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/12
|
||||
* @desc 群聊成员
|
||||
*/
|
||||
public interface ChatGroupUserService extends IService<ChatGroupUser> {
|
||||
|
||||
/**
|
||||
* 创建群聊成员
|
||||
*/
|
||||
Boolean chatGroupUserCreate(Long chatGroupId, String tid,String accId, ChatGroupStatusEnum status, String remark, ChatGroupCreateReq.CrowTypeEnum crowType, ChatGroupUserTypeEnum type);
|
||||
|
||||
/**
|
||||
* 批量创建群聊成员
|
||||
*/
|
||||
Boolean chatGroupUserBatchCreate(Long chatGroupId, String tid, List<String> members, ChatGroupStatusEnum status, String remark, ChatGroupCreateReq.CrowTypeEnum crowType);
|
||||
|
||||
/**
|
||||
* 删除群聊成员
|
||||
*/
|
||||
Boolean chatGroupUserDelete(Long chatGroupId, String accId);
|
||||
|
||||
|
||||
/**
|
||||
* 通用查询-少条件后期在补
|
||||
*/
|
||||
List<ChatGroupUser> genericQuery(ChatGroupUserGenericSearchReq req);
|
||||
|
||||
/**
|
||||
* 通用查询数量
|
||||
*/
|
||||
Integer genericQueryCount(ChatGroupUserGenericSearchReq req);
|
||||
|
||||
/**
|
||||
* 更改群主
|
||||
* @param chatGroupId 群聊Id
|
||||
* @param oldAccId 原有账号
|
||||
* @param newAccId 新账号
|
||||
*/
|
||||
void changeOwner(Long chatGroupId, String oldAccId, String newAccId);
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package cn.axzo.im.service;
|
||||
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ComplaintCreateReq;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupCreateResp;
|
||||
import cn.axzo.im.entity.ChatGroup;
|
||||
import cn.axzo.im.entity.Complaint;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/05
|
||||
* @desc 群聊
|
||||
*/
|
||||
public interface ComplaintService extends IService<Complaint> {
|
||||
|
||||
/**
|
||||
* 创建群聊
|
||||
*/
|
||||
void complaintCreate(ComplaintCreateReq req);
|
||||
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package cn.axzo.im.service;
|
||||
|
||||
public interface DingDingRobotService {
|
||||
/**
|
||||
* 发钉钉消息。先默认是泰州的,后续如果不同三方对应的行为不一致,再调整
|
||||
*
|
||||
* @param content
|
||||
*/
|
||||
void send(String content);
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package cn.axzo.im.service;
|
||||
|
||||
import cn.axzo.im.center.common.enums.OperateLogTypeEnum;
|
||||
import cn.axzo.im.entity.OperateLog;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/12
|
||||
* @desc 操作日志
|
||||
*/
|
||||
public interface OperateLogService extends IService<OperateLog> {
|
||||
/**
|
||||
* 创建操作日志
|
||||
*/
|
||||
Boolean create(OperateLogTypeEnum typeEnum, String content);
|
||||
|
||||
}
|
||||
@ -1,20 +1,77 @@
|
||||
package cn.axzo.im.service.impl;
|
||||
|
||||
import cn.axzo.apollo.workspace.api.workspace.res.GetDetailRes;
|
||||
import cn.axzo.basics.common.exception.ServiceException;
|
||||
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupGenericSearchReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupQueryReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupUserGenericSearchReq;
|
||||
import cn.axzo.im.center.api.vo.req.UserAccountReq;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupCreateResp;
|
||||
import cn.axzo.im.center.api.vo.resp.ChatGroupQueryResp;
|
||||
import cn.axzo.im.center.api.vo.resp.UserAccountResp;
|
||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupStatusEnum;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupUserTypeEnum;
|
||||
import cn.axzo.im.center.common.enums.OperateLogTypeEnum;
|
||||
import cn.axzo.im.channel.IMChannelProvider;
|
||||
import cn.axzo.im.channel.netease.INotifyService;
|
||||
import cn.axzo.im.channel.netease.NimChannelService;
|
||||
import cn.axzo.im.channel.netease.dto.ChangeOwnerRequest;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateRequest;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupCreateResponse;
|
||||
import cn.axzo.im.channel.netease.dto.ChatGroupQueryResponse;
|
||||
import cn.axzo.im.channel.netease.dto.KickChatGroupRequest;
|
||||
import cn.axzo.im.channel.netease.dto.UserAddChatGroupRequest;
|
||||
import cn.axzo.im.config.BizResultCode;
|
||||
import cn.axzo.im.config.ChatGroupConfig;
|
||||
import cn.axzo.im.config.MqProducer;
|
||||
import cn.axzo.im.dao.mapper.ChatGroupMapper;
|
||||
import cn.axzo.im.entity.ChatGroup;
|
||||
import cn.axzo.im.event.payload.ChatGroupCreatePayload;
|
||||
import cn.axzo.im.gateway.OrganizationalNodeApiGateway;
|
||||
import cn.axzo.im.gateway.OrganizationalNodeUserApiGateway;
|
||||
import cn.axzo.im.gateway.ProfilesApiGateway;
|
||||
import cn.axzo.im.gateway.TyrApiGateway;
|
||||
import cn.axzo.im.gateway.WorkspaceApiGateway;
|
||||
import cn.axzo.im.service.AccountService;
|
||||
import cn.axzo.im.service.ChatGroupService;
|
||||
import cn.axzo.im.service.ChatGroupUserService;
|
||||
import cn.axzo.im.service.OperateLogService;
|
||||
import cn.axzo.im.utils.BizAssertions;
|
||||
import cn.axzo.im.utils.DingTalkUtil;
|
||||
import cn.axzo.im.utils.JobCodeUtils;
|
||||
import cn.axzo.maokai.api.vo.request.OrganizationalNodeUserSearchReq;
|
||||
import cn.axzo.maokai.api.vo.response.OrganizationalNodeUserVO;
|
||||
import cn.axzo.maokai.api.vo.response.OrganizationalNodeVO;
|
||||
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
|
||||
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserV2DTO;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.im.event.inner.EventTypeEnum.MESSAGE_CHAT_GROUP_CREATE;
|
||||
|
||||
@ -25,6 +82,7 @@ import static cn.axzo.im.event.inner.EventTypeEnum.MESSAGE_CHAT_GROUP_CREATE;
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RefreshScope
|
||||
public class ChatGroupServiceImpl extends ServiceImpl<ChatGroupMapper, ChatGroup>
|
||||
implements ChatGroupService {
|
||||
|
||||
@ -34,27 +92,434 @@ public class ChatGroupServiceImpl extends ServiceImpl<ChatGroupMapper, ChatGrou
|
||||
@Autowired
|
||||
private MqProducer mqProducer;
|
||||
|
||||
@Resource
|
||||
private AccountService accountService;
|
||||
|
||||
@Resource
|
||||
private INotifyService iNotifyService;
|
||||
|
||||
@Autowired
|
||||
private ChatGroupConfig chatGroupConfig;
|
||||
|
||||
@Autowired
|
||||
private NimChannelService nimChannelService;
|
||||
|
||||
@Autowired
|
||||
private ChatGroupUserService chatGroupUserService;
|
||||
|
||||
@Autowired
|
||||
private OperateLogService operateLogService;
|
||||
|
||||
@Autowired
|
||||
private TyrApiGateway tyrApiGateway;
|
||||
|
||||
@Autowired
|
||||
private ProfilesApiGateway profilesApiGateway;
|
||||
|
||||
@Autowired
|
||||
private WorkspaceApiGateway workspaceApiGateway;
|
||||
|
||||
@Autowired
|
||||
private OrganizationalNodeApiGateway organizationalNodeApiGateway;
|
||||
|
||||
@Autowired
|
||||
private OrganizationalNodeUserApiGateway organizationalNodeUserApiGateway;
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String env;
|
||||
|
||||
@Value("${chatgroup.maxmember.count:199}")
|
||||
private Integer chatGroupMaxMemberCount;
|
||||
|
||||
|
||||
@Override
|
||||
public ChatGroupCreateResp chatGroupCreate(ChatGroupCreateReq req) {
|
||||
String owner = "";//TODO
|
||||
//1 群聊创建
|
||||
ChatGroupCreateResponse response = imChannelProvider.chatGroupCreate(ChatGroupCreateRequest.convertRequest(req, owner));
|
||||
//2 群聊创建成功发送MQ
|
||||
this.chatGroupCreateSendMQ(req, response);
|
||||
//3 返回
|
||||
return ChatGroupCreateResponse.convertResp(response);
|
||||
@Transactional(rollbackFor = Throwable.class)
|
||||
public ApiResult<ChatGroupCreateResp> chatGroupCreate(ChatGroupCreateReq req) {
|
||||
// 超管账号
|
||||
ChatGroupFetchOwnerResp resp = this.fetchAdminByWorkspaceOuId(req.getCrowType(), req.getWorkspaceId(), req.getOuId(), req.getCreator());
|
||||
req.setOwner(resp.getOwnerId());
|
||||
//创建群聊-校验
|
||||
ApiResult<ChatGroupCreateResp> apiResult = this.checkChatGroupCreate(req, resp.getTeamNodeId());
|
||||
if (Objects.nonNull(apiResult)) {
|
||||
return apiResult;
|
||||
}
|
||||
|
||||
// 群聊创建
|
||||
ChatGroupCreateResponse response = imChannelProvider.chatGroupCreate(ChatGroupCreateRequest.convertRequest(req, resp.getOwnerImAccount(), this.buildAttach(req)));
|
||||
ChatGroup chatGroup = this.buildChatGroupCreate(req, response, resp.getOwnerImAccount(), req.getOuId(), resp.getTeamNodeId());
|
||||
// 保存db
|
||||
this.saveOrUpdate(chatGroup);
|
||||
this.chatGroupUserService.chatGroupUserCreate(chatGroup.getId(), response.getTid(), resp.getOwnerImAccount(), ChatGroupStatusEnum.SUCCESS, null, req.getCrowType(), ChatGroupUserTypeEnum.OWNER);
|
||||
// 群聊创建成功发送MQ
|
||||
this.chatGroupCreateSendMQ(req, response, resp.getOwnerId().toString(), resp.getOwnerImAccount(), chatGroup.getId());
|
||||
// 返回
|
||||
return ApiResult.ok(ChatGroupCreateResponse.convertResp(response, req.getGroupName(), req.getAvatarUrl()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建群聊-校验
|
||||
*/
|
||||
public ApiResult<ChatGroupCreateResp> checkChatGroupCreate(ChatGroupCreateReq req , Long teamId) {
|
||||
|
||||
ChatGroup chatGroup = null;
|
||||
StringBuilder desc = new StringBuilder();
|
||||
//1 是否已经创建群聊校验
|
||||
switch (req.getCrowType()) {
|
||||
case WORKSPACE:
|
||||
List<ChatGroup> chatGroups = this.genericQuery(ChatGroupGenericSearchReq.builder().workspaceId(req.getWorkspaceId()).crowType(req.getCrowType()).build());
|
||||
chatGroup = CollectionUtils.isNotEmpty(chatGroups) ? chatGroups.get(0) : null;
|
||||
desc.append("人群类型:项目,群聊已存在,workspaceId:").append(req.getWorkspaceId());
|
||||
break;
|
||||
case OU:
|
||||
List<ChatGroup> chatGroupsWhenOu = this.genericQuery(ChatGroupGenericSearchReq.builder().workspaceId(req.getWorkspaceId()).ouId(req.getOuId()).crowType(req.getCrowType()).build());
|
||||
chatGroup = CollectionUtils.isNotEmpty(chatGroupsWhenOu) ? chatGroupsWhenOu.get(0) : null;
|
||||
desc.append("人群类型:单位,群聊已存在,workspaceId:").append(req.getWorkspaceId());
|
||||
break;
|
||||
case TEAM:
|
||||
List<ChatGroup> chatGroupsWhenTeam = this.genericQuery(ChatGroupGenericSearchReq.builder().workspaceId(req.getWorkspaceId()).teamId(teamId).crowType(req.getCrowType()).build());
|
||||
chatGroup = CollectionUtils.isNotEmpty(chatGroupsWhenTeam) ? chatGroupsWhenTeam.get(0) : null;
|
||||
desc.append("人群类型:班组,群聊已存在,workspaceId:").append(req.getWorkspaceId());
|
||||
break;
|
||||
default:
|
||||
BizAssertions.assertTrue(false, "人群不存在");
|
||||
}
|
||||
|
||||
if (Objects.nonNull(chatGroup)) {
|
||||
return ApiResult.ok(ChatGroupCreateResp.builder().tid(chatGroup.getTid())
|
||||
.groupName(chatGroup.getName()).avatarUrl(chatGroup.getAvatarUrl())
|
||||
.code(Integer.parseInt(BizResultCode.CHAT_GROUP_ALREADY_EXISTS.getErrorCode()))
|
||||
.desc(desc.toString())
|
||||
.build());
|
||||
}
|
||||
|
||||
//2 人数超限校验
|
||||
//Pair,key:管理人员集合;value:工人集合
|
||||
Pair<Set<Long>, Set<Long>> adminWorkerSet = this.fetchUsersByWorkspaceOuId(req.getCrowType(), req.getWorkspaceId(), req.getOuId(), this.buildJobCodesByCrowType(req.getCrowType()), req.getCreator());
|
||||
Set<Long> adminSet = adminWorkerSet.getKey();
|
||||
Set<Long> workerSet = adminWorkerSet.getValue();
|
||||
if ((adminSet.size() + workerSet.size()) > chatGroupMaxMemberCount) {
|
||||
String error = String.format("创建群组:%s,超过人数:%d,项目Id:%d,人群类型:%s", req.getGroupName(), chatGroupMaxMemberCount, req.getWorkspaceId(), req.getCrowType());
|
||||
this.sendDingRobot(error);
|
||||
return ApiResult.ok(ChatGroupCreateResp.builder()
|
||||
.code(Integer.parseInt(BizResultCode.CHAT_GROUP_OVER_MEMBERS_COUNT_LIMIT.getErrorCode()))
|
||||
.desc(BizResultCode.CHAT_GROUP_OVER_MEMBERS_COUNT_LIMIT.getErrorMessage()).build());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<ChatGroup> genericQuery(ChatGroupGenericSearchReq req) {
|
||||
return this.lambdaQuery().eq(Objects.nonNull(req.getWorkspaceId()), ChatGroup::getWorkspaceId, req.getWorkspaceId())
|
||||
.eq(Objects.nonNull(req.getOuId()), ChatGroup::getOuId, req.getOuId())
|
||||
.eq(Objects.nonNull(req.getTeamId()), ChatGroup::getTeamId, req.getTeamId())
|
||||
.eq(Objects.nonNull(req.getCrowType()), ChatGroup::getCrowType, req.getCrowType())
|
||||
.eq(ChatGroup::getIsDelete,0)
|
||||
.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过Id查询群聊
|
||||
*/
|
||||
public ChatGroup getById(Long id) {
|
||||
return this.lambdaQuery().eq(ChatGroup::getId, id)
|
||||
.one();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建群聊创建对象
|
||||
*/
|
||||
private ChatGroup buildChatGroupCreate(ChatGroupCreateReq req, ChatGroupCreateResponse response, String groupOwner, Long ouId, Long teamNodeId) {
|
||||
return ChatGroup.builder()
|
||||
.name(req.getGroupName())
|
||||
.tid(response.getTid())
|
||||
.avatarUrl(req.getAvatarUrl())
|
||||
.workspaceId(req.getWorkspaceId())
|
||||
.groupType(req.getGroupType())
|
||||
.crowType(req.getCrowType())
|
||||
.ouId(req.getCrowType() == ChatGroupCreateReq.CrowTypeEnum.OU ? ouId : null)
|
||||
.teamId(req.getCrowType() == ChatGroupCreateReq.CrowTypeEnum.TEAM ? teamNodeId : null)
|
||||
.groupOwner(groupOwner)
|
||||
.creator(req.getCreator())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建自定义扩展字段
|
||||
*/
|
||||
private String buildAttach(ChatGroupCreateReq req) {
|
||||
GetDetailRes getDetailRes = workspaceApiGateway.getWorkspaceById(req.getWorkspaceId());
|
||||
String workspaceName = getDetailRes.getName();
|
||||
Map<String, String> attachMap = new HashMap<>();
|
||||
attachMap.put("workspaceId", req.getWorkspaceId().toString());
|
||||
attachMap.put("workspaceName", workspaceName);
|
||||
return JSONUtil.toJsonStr(attachMap);//TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* 群聊创建成功发送MQ
|
||||
*/
|
||||
private void chatGroupCreateSendMQ(ChatGroupCreateReq req, ChatGroupCreateResponse response) {
|
||||
private void chatGroupCreateSendMQ(ChatGroupCreateReq req, ChatGroupCreateResponse response, String owner, String imAccountOwner, Long chatGroupId) {
|
||||
Event event = Event.builder()
|
||||
.targetId(String.valueOf(response.getTid()))
|
||||
.targetType(MESSAGE_CHAT_GROUP_CREATE.getModel())
|
||||
.eventCode(MESSAGE_CHAT_GROUP_CREATE.getEventCode())
|
||||
.data(ChatGroupCreatePayload.builder().req(req).tid(response.getTid()).build())
|
||||
.data(ChatGroupCreatePayload.builder().req(req).tid(response.getTid()).owner(owner).imAccountOwner(imAccountOwner).chatGroupId(chatGroupId).build())
|
||||
.build();
|
||||
mqProducer.send(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取超管账号
|
||||
*/
|
||||
private ChatGroupFetchOwnerResp fetchAdminByWorkspaceOuId(ChatGroupCreateReq.CrowTypeEnum crowType, Long workspaceId, Long ouId, Long personId) {
|
||||
ChatGroupFetchOwnerResp resp = new ChatGroupFetchOwnerResp();
|
||||
|
||||
Long ownerId = null;
|
||||
switch (crowType) {
|
||||
case WORKSPACE:
|
||||
List<SaasRoleUserV2DTO> saasRoleUserV2DTOS = tyrApiGateway.fetchSaasRoleUserByWorkspaceOuIdRoleTypes(workspaceId, null, Sets.newHashSet(RoleTypeEnum.SUPER_ADMIN));
|
||||
if (CollectionUtils.isEmpty(saasRoleUserV2DTOS)) {
|
||||
this.sendDingRobot(String.format("创建群聊,personId:%d在workspaceId:%d,人群:%s,找不到群主信息", personId, workspaceId,crowType));
|
||||
}
|
||||
BizAssertions.assertNotEmpty(saasRoleUserV2DTOS, "personId:{}在workspaceId:{},找不到群主信息", personId, workspaceId);
|
||||
ownerId = saasRoleUserV2DTOS.get(0).getSaasRoleUser().getPersonId();
|
||||
break;
|
||||
case OU:
|
||||
List<SaasRoleUserV2DTO> saasRoleUserV2DTOSWhenOu = tyrApiGateway.fetchSaasRoleUserByWorkspaceOuIdRoleTypes(workspaceId, ouId, Sets.newHashSet(RoleTypeEnum.ADMIN));
|
||||
if (CollectionUtils.isEmpty(saasRoleUserV2DTOSWhenOu)) {
|
||||
this.sendDingRobot(String.format("创建群聊,personId:%d在workspaceId:%d,ouId:%d,人群:%s,找不到群主信息", personId, workspaceId,ouId, crowType));
|
||||
}
|
||||
BizAssertions.assertNotEmpty(saasRoleUserV2DTOSWhenOu, "personId:{}在workspaceId:{},ouId:{},找不到群主信息", personId, workspaceId, ouId);
|
||||
ownerId = saasRoleUserV2DTOSWhenOu.get(0).getSaasRoleUser().getPersonId();
|
||||
break;
|
||||
case TEAM:
|
||||
//获取personId,在workspaceId下项目班组对象,(角色列表:班组长/带班长/小组长/工人)
|
||||
OrganizationalNodeVO projectTeamUser = this.fetchProjectTeamByWorkspacePersonIdJobCodes(workspaceId, personId, JobCodeUtils.CHAT_GROUP_TEAM_MEMBER_JOB_CODES);
|
||||
resp.setTeamNodeId(projectTeamUser.getId());
|
||||
|
||||
//查询项目Id下的班组的班组长
|
||||
List<OrganizationalNodeUserVO> projectTeamLeaderList = this.organizationalNodeUserApiGateway.searchNodeUser( projectTeamUser.getId(), workspaceId, Sets.newHashSet(JobCodeUtils.WORKSPACE_TEAM_ADMIN_JOB_CODE), null);
|
||||
BizAssertions.assertNotEmpty(projectTeamLeaderList, "personId:{}在workspaceId:{},找不到班组长信息");
|
||||
ownerId = projectTeamLeaderList.get(0).getPersonId();
|
||||
break;
|
||||
default:
|
||||
BizAssertions.assertTrue(false, "人群不存在");
|
||||
}
|
||||
if (Objects.isNull(ownerId)) {
|
||||
this.sendDingRobot(String.format("群主用户不存在,workspaceId:%d,ouId:%d,personId:%d,crowType:%s", workspaceId, ouId, personId, crowType));
|
||||
}
|
||||
BizAssertions.assertNotNull(ownerId, "群主用户不存在");
|
||||
|
||||
PersonProfileDto owner = profilesApiGateway.getPersonProfileById(ownerId);
|
||||
BizAssertions.assertFalse(Objects.isNull(owner) || Objects.isNull(owner.getId()), "超管用户不存在");
|
||||
|
||||
UserAccountReq userAccountReq = UserAccountReq.builder()
|
||||
.appType(AppTypeEnum.CMP.getCode())//管理端:AppTypeEnum.CMP.getCode();工人端:AppTypeEnum.CM.getCode()
|
||||
.userId(owner.getId().toString()).nickName(owner.getRealName())
|
||||
.headImageUrl(owner.getAvatarUrl())
|
||||
.organizationalUnitId(ouId)
|
||||
.build();
|
||||
UserAccountResp userAccountResp = accountService.generateAccount(userAccountReq, iNotifyService);
|
||||
resp.setOwnerId(owner.getId());
|
||||
resp.setOwnerImAccount(userAccountResp.getImAccount());
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取IM账号
|
||||
*/
|
||||
public Pair<Set<Long>, Set<Long>> fetchUsersByWorkspaceOuId(ChatGroupCreateReq.CrowTypeEnum crowType, Long workspaceId, Long ouId, Set<String> jobCodes,Long personId) {
|
||||
switch (crowType) {
|
||||
case WORKSPACE:
|
||||
List<OrganizationalNodeUserVO> userListWhenWorkspace = organizationalNodeUserApiGateway.fetchNodeUsersByWorkspaceIdJobCodes(workspaceId, jobCodes);
|
||||
BizAssertions.assertNotEmpty(userListWhenWorkspace, "人群是项目时,管理员为空,workspaceId:{},ouId:{}", workspaceId, ouId);
|
||||
Set<Long> personListWhenWorkspace = userListWhenWorkspace.stream().map(OrganizationalNodeUserVO::getPersonId).collect(Collectors.toSet());
|
||||
return Pair.of(personListWhenWorkspace, Sets.newHashSet());
|
||||
case OU:
|
||||
List<OrganizationalNodeUserVO> userListWhenOuId = organizationalNodeUserApiGateway.fetchNodeUsersByWorkspaceOuIdJobCodes(workspaceId,ouId,jobCodes);
|
||||
BizAssertions.assertNotEmpty(userListWhenOuId, "人群是单位时,管理员为空,workspaceId:{},ouId:{}", workspaceId, ouId);
|
||||
Set<Long> personIdListWhenOuId = userListWhenOuId.stream().map(OrganizationalNodeUserVO::getPersonId).collect(Collectors.toSet());
|
||||
return Pair.of(personIdListWhenOuId, Sets.newHashSet());
|
||||
case TEAM:
|
||||
//获取personId,在workspaceId下项目班组对象,(角色列表:班组长/带班长/小组长/工人)
|
||||
OrganizationalNodeVO projectTeamUser = this.fetchProjectTeamByWorkspacePersonIdJobCodes(workspaceId, personId, JobCodeUtils.CHAT_GROUP_TEAM_MEMBER_JOB_CODES);
|
||||
|
||||
//班组长/带班长
|
||||
Set<Long> teamerList = this.fetchUsersByWorkspaceIdJobCodes(workspaceId, ouId,projectTeamUser.getId(), Sets.newHashSet("projTeamLeader", "projectTeamManager"), true);
|
||||
Set<Long> workerList = this.fetchUsersByWorkspaceIdJobCodes(workspaceId, ouId,projectTeamUser.getId(), Sets.newHashSet("projWorker","projectTeamGPLeader"), false);
|
||||
return Pair.of(teamerList,workerList);
|
||||
default:
|
||||
throw new ServiceException("人群不存在");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过项目Id/人员Id/岗位code集合,获取项目内班组的OrganizationalNode组织对象
|
||||
* @param workspaceId 项目Id
|
||||
* @param personId 人员Id
|
||||
* @param jobCodes 岗位code集合
|
||||
* @return 项目内班组的OrganizationalNode组织对象
|
||||
*/
|
||||
private OrganizationalNodeVO fetchProjectTeamByWorkspacePersonIdJobCodes(Long workspaceId,Long personId, Set<String> jobCodes) {
|
||||
List<OrganizationalNodeUserVO> projectTeamUserList = this.organizationalNodeUserApiGateway.searchNodeUser( null, workspaceId, jobCodes, personId);
|
||||
BizAssertions.assertNotEmpty(projectTeamUserList, "personId:{}在workspaceId:{},找不到项目内组织用户信息");
|
||||
|
||||
List<Long> nodeIdList = projectTeamUserList.stream().map(OrganizationalNodeUserVO::getOrganizationalNodeId).collect(Collectors.toList());
|
||||
BizAssertions.assertNotEmpty(nodeIdList, "personId:{}在workspaceId:{},找不到项目内组织信息");
|
||||
|
||||
List<OrganizationalNodeVO> nodeVOList = organizationalNodeApiGateway.fetchNodesByNodeIds(nodeIdList);
|
||||
BizAssertions.assertNotEmpty(nodeVOList, "personId:{}在workspaceId:{},找不到项目内组织信息");
|
||||
|
||||
//只获取项目内班组,节点类型 1.部门 2.平台班组 3.小组 4.项目内班组 5.项目内小组
|
||||
List<OrganizationalNodeVO> nodeVOTeamList = nodeVOList.stream().filter(item -> item.getNodeType().equals(4)).collect(Collectors.toList());
|
||||
BizAssertions.assertNotEmpty(nodeVOTeamList, "personId:{}在workspaceId:{},找不到项目内班组信息");
|
||||
|
||||
return nodeVOTeamList.get(0);
|
||||
}
|
||||
|
||||
private Set<Long> fetchUsersByWorkspaceIdJobCodes(Long workspaceId, Long ouId, Long nodeId,Set<String> jobCodes, boolean isAdmin) {
|
||||
List<OrganizationalNodeUserVO> userListWhenTeamer = organizationalNodeUserApiGateway.fetchNodeUsersByWorkspaceNodeIdJobCodes(workspaceId, nodeId, jobCodes);
|
||||
BizAssertions.assertTrue(CollectionUtils.isNotEmpty(userListWhenTeamer) && isAdmin, "人群是班组时,{}为空,workspaceId:{},ouId:{}", isAdmin ? "班组长/带班长" : "工人", workspaceId, ouId);
|
||||
return userListWhenTeamer.stream().map(OrganizationalNodeUserVO::getPersonId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取群聊
|
||||
*/
|
||||
@Override
|
||||
public ChatGroupQueryResp chatGroupQuery(ChatGroupQueryReq req) {
|
||||
ChatGroupQueryResponse chatGroupQueryResponse = this.imChannelProvider.chatGroupQueryByTids(req.getTids(), req.getOpe());
|
||||
return BeanUtil.copyProperties(chatGroupQueryResponse, ChatGroupQueryResp.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据人群,返回jobCode
|
||||
*/
|
||||
@Override
|
||||
public Set<String> buildJobCodesByCrowType(ChatGroupCreateReq.CrowTypeEnum crowType) {
|
||||
switch (crowType) {
|
||||
case WORKSPACE:
|
||||
return Sets.newHashSet(JobCodeUtils.CHAT_GROUP_ADMIN_JOB_CODES);
|
||||
case OU:
|
||||
return Sets.newHashSet(JobCodeUtils.CHAT_GROUP_ADMIN_JOB_CODES);
|
||||
case TEAM:
|
||||
return Sets.newHashSet(JobCodeUtils.CHAT_GROUP_TEAM_MEMBER_JOB_CODES);// TODO
|
||||
default:
|
||||
throw new ServiceException("人群不存在");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改群主
|
||||
* @param chatGroupId 群聊Id
|
||||
* @param oldAccIdOwner 原群主账号
|
||||
* @param newAccIdOwner 新群主账号
|
||||
*/
|
||||
@Override
|
||||
public void changeOwner(Long chatGroupId, String oldAccIdOwner, String newAccIdOwner) {
|
||||
|
||||
//根据群聊Id,获取群聊
|
||||
ChatGroup chatGroup = this.getById(chatGroupId);
|
||||
try {
|
||||
ChangeOwnerRequest changeOwnerRequest = new ChangeOwnerRequest();
|
||||
changeOwnerRequest.setTid(chatGroup.getTid());
|
||||
changeOwnerRequest.setOwner(oldAccIdOwner);
|
||||
changeOwnerRequest.setNewowner(newAccIdOwner);
|
||||
changeOwnerRequest.setLeave(1);
|
||||
|
||||
nimChannelService.changeOwner(changeOwnerRequest);
|
||||
chatGroupUserService.changeOwner(chatGroupId, oldAccIdOwner, newAccIdOwner);
|
||||
operateLogService.create(OperateLogTypeEnum.USER_ENTER_CHAT_GROUP, String.format("changeOwner-success,chatGroupId:%d,oldAccIdOwner:%s,newAccIdOwner:%s", chatGroupId, oldAccIdOwner, newAccIdOwner));
|
||||
} catch (ServiceException serviceException) {
|
||||
operateLogService.create(OperateLogTypeEnum.CHANGE_OWNER, String.format("changeOwner-fail,chatGroupId:%d,oldAccIdOwner:%s,newAccIdOwner:%s", chatGroupId, oldAccIdOwner, newAccIdOwner));
|
||||
String error = String.format("更改群主失败,群聊名称:%s,原群主账号:%s,新群主账号:%s", chatGroup.getName(), oldAccIdOwner, newAccIdOwner);
|
||||
this.sendDingRobot(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拉人进群
|
||||
* @param chatGroupId 群Id
|
||||
* @param tid 网易云信群Id
|
||||
* @param owner 群主
|
||||
* @param members im账号集合
|
||||
* @param groupName 群名称
|
||||
*/
|
||||
@Override
|
||||
public void userAddChatGroup(Long chatGroupId, String tid, String owner, List<String> members, String groupName) {
|
||||
ChatGroupUserGenericSearchReq req = new ChatGroupUserGenericSearchReq();
|
||||
req.setChatGroupId(chatGroupId);
|
||||
|
||||
Integer chatGroupCount = this.chatGroupUserService.genericQueryCount(req);
|
||||
ChatGroup chatGroup = this.getById(chatGroupId);
|
||||
|
||||
//超过限制人数校验
|
||||
if (chatGroupCount > chatGroupMaxMemberCount) {
|
||||
String error = String.format("群组:%s,超过人数:%d,项目Id:%d,人群类型:%s", groupName, chatGroupMaxMemberCount, chatGroup.getWorkspaceId(), chatGroup.getCrowType());
|
||||
this.sendDingRobot(error);
|
||||
return ;
|
||||
}
|
||||
|
||||
UserAddChatGroupRequest request = new UserAddChatGroupRequest();
|
||||
request.setTid(tid);
|
||||
request.setOwner(owner);
|
||||
|
||||
request.setMembers(members);
|
||||
request.setMsg("进入群:" + groupName);
|
||||
try {
|
||||
nimChannelService.userAddChatGroup(request);
|
||||
chatGroupUserService.chatGroupUserBatchCreate(chatGroupId,tid, members, ChatGroupStatusEnum.SUCCESS,null, chatGroup.getCrowType());
|
||||
operateLogService.create(OperateLogTypeEnum.USER_ENTER_CHAT_GROUP, String.format("user:%s,enter chatGroup:%s,owner:%s", JSON.toJSONString(members), tid, owner));
|
||||
} catch (ServiceException serviceException) {
|
||||
String error = String.format("errorCode: %s;msg:%s" ,serviceException.getErrorCode(), serviceException.getMessage());
|
||||
chatGroupUserService.chatGroupUserBatchCreate(chatGroupId,tid, members, ChatGroupStatusEnum.FAIL,error, chatGroup.getCrowType());
|
||||
operateLogService.create(OperateLogTypeEnum.USER_ENTER_CHAT_GROUP, String.format("user:%s,enter-error chatGroup:%s,owner:%s", JSON.toJSONString(members), tid, owner));
|
||||
this.sendDingRobot(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢出群
|
||||
* @param tid 群Id
|
||||
* @param owner 群主
|
||||
* @param imAccount im账号
|
||||
*/
|
||||
@Override
|
||||
public void kickChatGroup(Long chatGroupId, String tid, String owner, String imAccount) {
|
||||
KickChatGroupRequest kickChatGroupRequest = new KickChatGroupRequest();
|
||||
kickChatGroupRequest.setTid(tid);
|
||||
kickChatGroupRequest.setOwner(owner);
|
||||
kickChatGroupRequest.setMember(imAccount);
|
||||
try {
|
||||
nimChannelService.kickChatGroup(kickChatGroupRequest);
|
||||
chatGroupUserService.chatGroupUserDelete(chatGroupId, imAccount);
|
||||
operateLogService.create(OperateLogTypeEnum.USER_EXIT_CHAT_GROUP, String.format("user:%s,exit chatGroup:%s,owner:%s", imAccount, tid, owner));
|
||||
} catch (ServiceException serviceException) {
|
||||
String error = String.format("errorCode: %s;msg:%s" ,serviceException.getErrorCode(), serviceException.getMessage());
|
||||
operateLogService.create(OperateLogTypeEnum.USER_EXIT_CHAT_GROUP, String.format("user:%s,exit-error chatGroup:%s,owner:%s,error", imAccount, tid, owner, error));
|
||||
this.sendDingRobot(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDingRobot(String content) {
|
||||
if (BooleanUtils.isNotTrue(chatGroupConfig.getDingTalkBotEnabled())) {
|
||||
log.info("DingTalkBotEnabled = false,屏蔽钉钉消息发送。content = {}", content);
|
||||
return;
|
||||
}
|
||||
DingTalkUtil.sendMessage("【环境:" + env + "】\n" + content, chatGroupConfig.getDingTalkBotAccessToken(), chatGroupConfig.getDingTalkBotSecret());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
class ChatGroupFetchOwnerResp {
|
||||
private Long ownerId;
|
||||
|
||||
private String ownerImAccount;
|
||||
|
||||
private Long teamNodeId;
|
||||
|
||||
private String desc;
|
||||
}
|
||||
|
||||
@ -0,0 +1,106 @@
|
||||
package cn.axzo.im.service.impl;
|
||||
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupCreateReq;
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupUserGenericSearchReq;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupStatusEnum;
|
||||
import cn.axzo.im.center.common.enums.ChatGroupUserTypeEnum;
|
||||
import cn.axzo.im.dao.mapper.ChatGroupUserMapper;
|
||||
import cn.axzo.im.entity.ChatGroup;
|
||||
import cn.axzo.im.entity.ChatGroupUser;
|
||||
import cn.axzo.im.service.ChatGroupService;
|
||||
import cn.axzo.im.service.ChatGroupUserService;
|
||||
import com.alibaba.excel.util.StringUtils;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/05
|
||||
* @desc 群聊用户
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RefreshScope
|
||||
public class ChatGroupUserServiceImpl extends ServiceImpl<ChatGroupUserMapper, ChatGroupUser>
|
||||
implements ChatGroupUserService {
|
||||
|
||||
@Autowired
|
||||
private ChatGroupService chatGroupService;
|
||||
|
||||
@Override
|
||||
public Boolean chatGroupUserCreate(Long chatGroupId, String tid, String accId, ChatGroupStatusEnum status, String remark, ChatGroupCreateReq.CrowTypeEnum crowType, ChatGroupUserTypeEnum type) {
|
||||
return this.saveOrUpdate(ChatGroupUser.builder()
|
||||
.chatGroupId(chatGroupId)
|
||||
.tid(tid)
|
||||
.accId(accId)
|
||||
.status(status)
|
||||
.crowType(crowType)
|
||||
.type(type)
|
||||
.remark(remark).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改群主
|
||||
* @param chatGroupId 群聊Id
|
||||
* @param oldAccId 原有账号
|
||||
* @param newAccId 新账号
|
||||
*/
|
||||
@Override
|
||||
public void changeOwner(Long chatGroupId, String oldAccId, String newAccId) {
|
||||
|
||||
this.chatGroupUserDelete(chatGroupId, oldAccId);
|
||||
ChatGroup chatGroup = chatGroupService.getById(chatGroupId);
|
||||
this.chatGroupUserCreate(chatGroupId, chatGroup.getTid(), newAccId, ChatGroupStatusEnum.SUCCESS, null, chatGroup.getCrowType(), ChatGroupUserTypeEnum.OWNER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean chatGroupUserBatchCreate(Long chatGroupId, String tid, List<String> members, ChatGroupStatusEnum status, String remark, ChatGroupCreateReq.CrowTypeEnum crowType) {
|
||||
if (CollectionUtils.isEmpty(members)) {
|
||||
return true;
|
||||
}
|
||||
List<ChatGroupUser> chatGroupUsers = members.stream().map(item -> ChatGroupUser.builder().
|
||||
chatGroupId(chatGroupId)
|
||||
.tid(tid)
|
||||
.accId(item)
|
||||
.status(status)
|
||||
.crowType(crowType)
|
||||
.remark(remark).build()).collect(Collectors.toList());
|
||||
return this.saveBatch(chatGroupUsers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean chatGroupUserDelete(Long chatGroupId, String accId) {
|
||||
return this.lambdaUpdate().eq(ChatGroupUser::getChatGroupId, chatGroupId)
|
||||
.eq(ChatGroupUser::getAccId, accId)
|
||||
.eq(ChatGroupUser::getIsDelete, 0)
|
||||
.setSql("is_delete = id").update();
|
||||
}
|
||||
|
||||
private LambdaQueryChainWrapper<ChatGroupUser> genericQueryWrapper(ChatGroupUserGenericSearchReq req) {
|
||||
return this.lambdaQuery()
|
||||
.eq(Objects.nonNull(req.getChatGroupId()), ChatGroupUser::getChatGroupId, req.getChatGroupId())
|
||||
.eq(StringUtils.isNotBlank(req.getTid()), ChatGroupUser::getTid, req.getTid())
|
||||
.eq(StringUtils.isNotBlank(req.getAccId()), ChatGroupUser::getAccId, req.getAccId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChatGroupUser> genericQuery(ChatGroupUserGenericSearchReq req) {
|
||||
return this.genericQueryWrapper(req).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer genericQueryCount(ChatGroupUserGenericSearchReq req) {
|
||||
return this.genericQueryWrapper(req).count();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package cn.axzo.im.service.impl;
|
||||
|
||||
import cn.axzo.im.center.api.vo.req.ComplaintCreateReq;
|
||||
import cn.axzo.im.dao.mapper.ComplaintMapper;
|
||||
import cn.axzo.im.entity.Complaint;
|
||||
import cn.axzo.im.service.ChatGroupService;
|
||||
import cn.axzo.im.service.ComplaintService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/05
|
||||
* @desc 群聊
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ComplaintServiceImpl extends ServiceImpl<ComplaintMapper, Complaint>
|
||||
implements ComplaintService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private ChatGroupService chatGroupService;
|
||||
|
||||
@Override
|
||||
public void complaintCreate(ComplaintCreateReq req) {
|
||||
chatGroupService.sendDingRobot(String.format("IM投诉,fromId:%s,toId:%s,类型:%s,投诉内容:%s", req.getFromId(), req.getTaccId(), req.getType(), req.getComplaintContent()));
|
||||
// 保存投诉
|
||||
this.saveOrUpdate(this.buildComplaint(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建投诉
|
||||
*/
|
||||
private Complaint buildComplaint(ComplaintCreateReq req) {
|
||||
String toId = "";
|
||||
String tid = "";
|
||||
switch (req.getType()) {
|
||||
case GROUP:
|
||||
tid = req.getTaccId();
|
||||
break;
|
||||
case PRIVATE:
|
||||
toId = req.getTaccId();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return Complaint.builder()
|
||||
.complaintContent(req.getComplaintContent())
|
||||
.type(req.getType())
|
||||
.fromId(req.getFromId())
|
||||
.toId(toId)
|
||||
.tid(tid)
|
||||
.creator(req.getCreator())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package cn.axzo.im.service.impl;
|
||||
|
||||
import cn.axzo.im.config.ChatGroupConfig;
|
||||
import cn.axzo.im.service.DingDingRobotService;
|
||||
import cn.axzo.im.utils.DingTalkUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DingDingRobotServiceImpl implements DingDingRobotService {
|
||||
@Value("${spring.profiles.active}")
|
||||
private String env;
|
||||
private final ChatGroupConfig chatGroupConfig;
|
||||
|
||||
@Override
|
||||
public void send(String content) {
|
||||
if (BooleanUtils.isNotTrue(chatGroupConfig.getDingTalkBotEnabled())) {
|
||||
log.info("DingTalkBotEnabled = false,屏蔽钉钉消息发送。content = {}", content);
|
||||
return;
|
||||
}
|
||||
DingTalkUtil.sendMessage("【环境:" + env + "】\n" + content, chatGroupConfig.getDingTalkBotAccessToken(), chatGroupConfig.getDingTalkBotSecret());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package cn.axzo.im.service.impl;
|
||||
|
||||
import cn.axzo.im.center.api.vo.req.ChatGroupUserGenericSearchReq;
|
||||
import cn.axzo.im.center.common.enums.OperateLogTypeEnum;
|
||||
import cn.axzo.im.dao.mapper.ChatGroupUserMapper;
|
||||
import cn.axzo.im.dao.mapper.OperateLogMapper;
|
||||
import cn.axzo.im.entity.ChatGroup;
|
||||
import cn.axzo.im.entity.ChatGroupUser;
|
||||
import cn.axzo.im.entity.OperateLog;
|
||||
import cn.axzo.im.service.ChatGroupUserService;
|
||||
import cn.axzo.im.service.OperateLogService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2024/11/12
|
||||
* @desc 操作日志
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RefreshScope
|
||||
public class OperateLogServiceImpl extends ServiceImpl<OperateLogMapper, OperateLog>
|
||||
implements OperateLogService {
|
||||
|
||||
|
||||
/**
|
||||
* 创建操作日志
|
||||
*/
|
||||
@Override
|
||||
public Boolean create(OperateLogTypeEnum typeEnum, String content) {
|
||||
return this.saveOrUpdate(OperateLog.builder().type(typeEnum).content(content).build());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package cn.axzo.im.utils;
|
||||
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.dingtalk.api.DefaultDingTalkClient;
|
||||
import com.dingtalk.api.DingTalkClient;
|
||||
import com.dingtalk.api.request.OapiRobotSendRequest;
|
||||
import com.dingtalk.api.response.OapiRobotSendResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Slf4j
|
||||
public class DingTalkUtil {
|
||||
|
||||
public static void sendMessage(String content, String accessToken, String secret) {
|
||||
Long timestamp = System.currentTimeMillis();
|
||||
String sign = getSign(timestamp, secret);
|
||||
if (StrUtil.isBlank(sign)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String url = StrUtil.format("https://oapi.dingtalk.com/robot/send?access_token={}&sign={}×tamp={}",
|
||||
accessToken, sign, String.valueOf(timestamp));
|
||||
DingTalkClient client = new DefaultDingTalkClient(url);
|
||||
|
||||
OapiRobotSendRequest req = new OapiRobotSendRequest();
|
||||
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
|
||||
text.setContent(content);
|
||||
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
|
||||
at.setIsAtAll(false);
|
||||
req.setMsgtype("text");
|
||||
req.setText(text);
|
||||
req.setAt(at);
|
||||
try {
|
||||
OapiRobotSendResponse response = client.execute(req);
|
||||
log.info("发送钉钉消息结果:{}", response);
|
||||
} catch (Exception error) {
|
||||
log.error("发送钉钉消息失败:{}", error.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSign(Long timestamp, String secret) {
|
||||
try {
|
||||
String stringToSign = timestamp + "\n" + secret;
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
|
||||
byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
|
||||
return URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
|
||||
} catch (Exception ignored) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package cn.axzo.im.utils;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author xudawei@axzo.cn
|
||||
* @date 2014/11/07
|
||||
*/
|
||||
public class JobCodeUtils {
|
||||
|
||||
public static Set<String> CHAT_GROUP_ADMIN_JOB_CODES = Sets.newHashSet("HumanResources","YoElse","YoUserexperiencedesi","YoProdcutmanager","YoHardwareengineer","YoTestengineer","YoOperationmanager","YoOperationandmainte","YoProjectimplementer","YoIndustryresearcher","YoDeveloper","YoTheprojectmanager"
|
||||
,"YoChieftechnologyoff","YoChieffinancialoffi","YoChiefoperatingoffi","YoChiefexecutiveoffi","cms:ou_staff","cms:ou_archivist","cms:ou_seal_administrator","cms:ou_office_staff","cms:ou_office_chief","cms:ou_legal_staff","EwLegaldepartmentman","cms:ou_hr_staff","EwHumanresourcesmana","cms:ou_accountant_staff"
|
||||
,"cms:ou_cashier_staff","EwFinancialcontrolle","cms:ou_contract_staff","EwContractdepartment","cms:ou_budget_staff","cms:ou_calculate_engnieer","cms:ou_cost_engnieer","cms:ou_business_manager","cms:ou_buyer","cms:ou_operation_staff","EwBusinessdepartment","cms:ou_business_vice_officer","cms:ou_chief_economic_manager"
|
||||
,"cms:ou_technology_staff","EwTechnicaldepartmen","EwChiefengineer","cms:ou_machine_staff","cms:ou_securityt_staff","EwSecuritydepartment","cms:ou_quantity_staff","EwQualitydepartmentm","cms:ou_material_staff","cms:ou_professional_engineer","cms:ou_engineering_manager","EwProductiongeneralm","EwThesecretary","EwThegeneralmanager"
|
||||
,"cms:ou_executive_director","cms:ou_chairman","other","OtProjectManager","scother","scresposible","scinspector","scSafetydesignedprison","cms:jl_project_professional_supervision_engineer","scCostofthedesignedprison","scTherepresentative","scProjectmanager","cuother","cms:js_project_security_chief","cuTheprojectintheindustry","curesposible"
|
||||
,"cuThecostengineer","cuProfessionalengineers","cuProjectmanager","lsother","istreasurer1","isTreasurer","lsTestsamplingmember","lsQualitativecheckmember","lsThequalitysupervis","cms:lafb_project_machine_staff","lssafe","lsSecuritychief","lsMaterialkeeper","lsGoodsreceiving","lsSuppliestobuyer","lsCompetentmaterials","cms:lafb_project_contract_staff"
|
||||
,"lsBudgetmember","lsLabormember","cms:lafb_project_business_vice_officer","lssurveyor","ziliaoyuan","lsThetechnician","lsTechnicalmanager","cms:lafb_project_trainee_construction_staff","lsThebuilder","isEngineeringmanager","lsProductionvicemanager","lsTheprojectmanager","psother","pstreasurer1","cms:mafb_project_accountant_staff","PSTreasurer"
|
||||
,"psresposible","psTestsamplingmember","psQualitativecheckmember","psThequalitysupervisor","pssafe","psSecuritychief","cms:mafb_project_machine_staff","psMaterialwarehousekeeper","psGoodsreceiving","psSuppliestobuyer","psCompetentmaterials","psLabormember","psThecontractadministrator","psBudgetmember","cms:mafb_project_business_vice_officer"
|
||||
,"cms:mafb_project_standard_staff","pssurveyor","psThetechnician","psTechnicalmanage","cms:mafb_project_technology_president","cms:mafb_project_electricity_manager","cms:mafb_project_trainee_construction_staff","psThebuilder","cms:mafb_project_schedule_manager","psEngineeringmanager","psProductionvicemanager","cms:mafb_project_secretary"
|
||||
,"cms:mafb_project_manger","psTheprojectmanager","coother","coLogisticsAdministr","coOfficeclerk","cms:zb_project_comperhensive_chief","cotreasurer","coaccounting","cms:zb_project_financial_chief","coresposible","cms:zb_project_referenc_chief","coTheoperator","coQualitativecheckmember","cms:zb_project_quantity_chief","cosafe","cms:zb_project_security_chief"
|
||||
,"coMechanicaladministrator","coMaterialwarehousekeeper","coGoodsreceiving","coSuppliestobuyer","cms:zb_project_material_chief","coLabormember","cms:zb_project_contract_manager","coBudgetmember","coTheprojectbusinessassistantmanager","coStandardOfficer","cosurveyor","coMeasuringhead","coThetechnician","cms:zb_project_technology_commissioner","coTechnicalprojectgeneral"
|
||||
,"coNearwatertheelectricityintheadministrator","coTraineebuilder","coThebuilder","coPlanadministrator","comechanicalandelectricalmanager","cms:zb_project_engineering_commissioner","coProductionvicemanageroftheproject","coSecretaryoftheproject","coProjectimplementationmanager","coTheprojectmanager");
|
||||
|
||||
|
||||
/**
|
||||
* 班组长/带班长/小组长工人
|
||||
*/
|
||||
public static Set<String> CHAT_GROUP_TEAM_MEMBER_JOB_CODES = Sets.newHashSet("projTeamLeader","projectTeamManager","projectTeamGPLeader","projWorker");
|
||||
|
||||
/**
|
||||
* 班组长岗位code
|
||||
*/
|
||||
private static String PROJECT_TEAM_LEADER_JOB_CODE = "projTeamLeader";
|
||||
|
||||
|
||||
/**
|
||||
* 项目管理员岗位code
|
||||
*/
|
||||
public static final String WORKSPACE_ADMIN_JOB_CODE = "super admin";
|
||||
/**
|
||||
* 项目单位下的管理员岗位code
|
||||
*/
|
||||
public static final String WORKSPACE_OU_ADMIN_JOB_CODE = "sub admin";
|
||||
/**
|
||||
* 项目内班组长
|
||||
*/
|
||||
public static final String WORKSPACE_TEAM_ADMIN_JOB_CODE = "projTeamLeader";
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 是否管理岗位
|
||||
*/
|
||||
public static boolean isAdmin(String jobCode) {
|
||||
return CHAT_GROUP_ADMIN_JOB_CODES.contains(jobCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否项目班组内的岗位(班组长/带班长/小组长工人)
|
||||
*
|
||||
*/
|
||||
public static boolean isTeam(String jobCode) {
|
||||
return CHAT_GROUP_TEAM_MEMBER_JOB_CODES.contains(jobCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是班组长
|
||||
*/
|
||||
public static boolean isProjectTeamLeader(String jobCode) {
|
||||
return PROJECT_TEAM_LEADER_JOB_CODE.equals(jobCode);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user