Merge branch 'feature/REQ-2012' into 'master'

Feature/req 2012

See merge request universal/infrastructure/backend/im-center!39
This commit is contained in:
宋远伦 2024-01-17 09:43:45 +00:00
commit 46ff499b6f
12 changed files with 548 additions and 44 deletions

View File

@ -0,0 +1,28 @@
package cn.axzo.im.center.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 渠道消息类型
*/
@Getter
@AllArgsConstructor
public enum ChannelMsgTypeEnum {
/**
* 文本
*/
TEXT(0, "文本消息"),
/**
* 自定义
*/
CUSTOM(100, "自定义消息"),
;
private final Integer code;
private final String message;
}

View File

@ -52,6 +52,11 @@
<artifactId>axzo-data-mybatis-plus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.trade</groupId>
<artifactId>trade-data-security-spring-boot-starter</artifactId>

View File

@ -1,7 +1,6 @@
package cn.axzo.im;
import cn.axzo.framework.data.mybatisplus.config.MybatisPlusAutoConfiguration;
import cn.axzo.trade.theadpool.annotation.EnableTradeTaskExecutor;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
@ -9,15 +8,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableAsync;
@Slf4j
@SpringBootApplication(scanBasePackages = "cn.axzo", exclude = MybatisPlusAutoConfiguration.class)
@EnableFeignClients(basePackages = {
"cn.axzo.im.center.api",
})
@EnableFeignClients(basePackages = {"cn.axzo"})
@MapperScan(value = {"cn.axzo.im.dao.mapper"})
@EnableDiscoveryClient
public class Application {

View File

@ -3,7 +3,17 @@ 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.*;
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchRequest;
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchResponse;
import cn.axzo.im.channel.netease.dto.MessageCustomDispatchRequest;
import cn.axzo.im.channel.netease.dto.MessageCustomDispatchResponse;
import cn.axzo.im.channel.netease.dto.MessageDispatchRequest;
import cn.axzo.im.channel.netease.dto.MessageDispatchResponse;
import cn.axzo.im.channel.netease.dto.NimAccountInfo;
import cn.axzo.im.channel.netease.dto.QueryAccountResp;
import cn.axzo.im.channel.netease.dto.RegisterRequest;
import cn.axzo.im.channel.netease.dto.RegisterResponse;
import cn.axzo.im.channel.netease.dto.RegisterUpdateRequest;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
@ -11,17 +21,16 @@ import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Resource;
import javax.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* 网易云信IM服务
*
@ -149,7 +158,6 @@ public class NimChannelService implements IMChannelProvider {
}
//目前支持的默认值 0单聊消息 100自定义消息
messageInfo.setOpe(MSG_OPE);
messageInfo.setType(MSG_TYPE);
HashMap<String, Object> paramMap = Maps.newHashMap();
paramMap.put("from", messageInfo.getFrom());
paramMap.put("body", messageInfo.getBody());

View File

@ -1,20 +1,26 @@
package cn.axzo.im.config;
import cn.axzo.basics.common.exception.ServiceException;
import cn.azxo.framework.common.constatns.Constants;
import cn.hutool.core.util.ReflectUtil;
import com.google.common.collect.Lists;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.Target.HardCodedTarget;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Objects;
/**
* FeignConfig配置
@ -23,15 +29,26 @@ import java.util.Objects;
* @version V1.0
* @date 2023/10/18 10:52
*/
@Component
@Slf4j
@Profile({"dev", "test", "local"})
public class FeignConfig implements RequestInterceptor, EnvironmentAware {
@Configuration(value = "imFeignConfig")
public class FeignConfig implements RequestInterceptor {
@Autowired
private Environment environment;
@Value("${imCenterEnvUrl:http://dev-app.axzo.cn/im-center}")
private String imCenterEnvUrl;
private static String POD_NAMESPACE;
private static final String FEIGN_URL_REGEX = "http://([A-Za-z-|_]+)(:[1-9]\\d{1,4}[/]?$)?";
private static final String LOCAL_HOST = "localhost";
private static final String DEV_HOST = "http://dev-app.axzo.cn/";
private static final String TEST_HOST = "http://test-api.axzo.cn/";
private static final String TEST1_HOST = "http://test1-api.axzo.cn/";
private static final String PRE_HOST = "http://pre-api.axzo.cn/";
private static final String PRE_NEW_HOST = "http://pre-new-api.axzo.cn/";
private static final String UAT_HOST = "http://uat-api.axzo.cn/";
private static final List<String> HOSTS = Lists
.newArrayList(LOCAL_HOST, DEV_HOST, TEST_HOST, TEST1_HOST, PRE_HOST, PRE_NEW_HOST, UAT_HOST);
static {
Map<String, String> env = System.getenv();
if (env != null) {
@ -44,28 +61,113 @@ public class FeignConfig implements RequestInterceptor, EnvironmentAware {
@Override
public void apply(RequestTemplate requestTemplate) {
if (POD_NAMESPACE == null) {
HardCodedTarget target = (HardCodedTarget) requestTemplate.feignTarget();
String url = requestTemplate.feignTarget().url();
// 如需修改微服务地址,建议通过外部化参数来调整
url = url.replace("http://im-center:8080", imCenterEnvUrl);
String profile = environment.getProperty("spring.profiles.active");
if(Objects.equals(profile, "test") && url.contains("dev-app.axzo.cn")) {
url = url.replace("dev-app", "test-api");
}
requestTemplate.target(url);
HardCodedTarget<?> target = (HardCodedTarget<?>) requestTemplate.feignTarget();
Field field = ReflectUtil.getField(target.getClass(), "url");
field.setAccessible(true);
field.set(target, url);
String url = (String) field.get(target);
// 如需要调用开发者本地启动的xxx服务传入到toLocalServiceNames
List<String> toLocalServiceNames = Lists.newArrayList("");
String convertUrl = convertUrl(url, toLocalServiceNames);
field.set(target, convertService(convertUrl));
target.apply(requestTemplate);
}
requestTemplate.header(Constants.CTX_LOG_ID_MDC, MDC.get(Constants.CTX_LOG_ID_MDC));
}
/**
* 某些服务URL需要特殊处理
*/
private String convertService(String url) {
if (url.contains("data-collection")) {
return url.replaceAll("data-collection", "dataCollection");
}
return url;
}
/**
* 将feign api中的url替换为其他环境
*/
private String convertUrl(String url, List<String> toLocalServiceNames) {
// 已经替换过的 不再进行替换了
if (HOSTS.stream().anyMatch(url::contains)) {
return url;
}
String convertUrl = toLocalHost(url, toLocalServiceNames);
if (!convertUrl.equals(url)) {
return convertUrl;
}
// 环境为空或为生产环境不替换
String profile = environment.getProperty("spring.profiles.active");
if (profile == null) {
return url;
}
// 调用profile对应环境的服务
switch (profile.toLowerCase()) {
case "local":
return toLocalHost(url);
case "dev":
return toRemoteHost(url, DEV_HOST);
case "test":
return toRemoteHost(url, TEST_HOST);
case "test1":
return toRemoteHost(url, TEST1_HOST);
case "pre":
return toRemoteHost(url, PRE_HOST);
case "pre-new":
return toRemoteHost(url, PRE_NEW_HOST);
case "uat":
return toRemoteHost(url, UAT_HOST);
default:
throw new ServiceException("不支持该环境的feign api调用");
}
}
/**
* Set the {@code Environment} that this component runs in.
* 调用本地启动的服务
*
* @param environment
* @param url 原url
* @param toLocalServiceNames 需要切换到本地的服务名
*/
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
private static String toLocalHost(String url, List<String> toLocalServiceNames) {
if (CollectionUtils.isEmpty(toLocalServiceNames)) {
return url;
}
if (toLocalServiceNames.stream().anyMatch(o -> StringUtils.isNotBlank(o) && url.contains(o))) {
return toLocalHost(url);
}
return url;
}
/**
* 调用本地启动的服务http://apollo:11000 -> http://localhost:11000
*/
private static String toLocalHost(String url) {
String serviceName = getServiceNameFromUrl(url);
// 替换服务名为localhost
return serviceName == null ? url : url.replaceAll(serviceName, LOCAL_HOST);
}
/**
* 调用远程指定环境的服务http://apollo:11000 -> http://dev-app.axzo.cn/apollo
*/
private static String toRemoteHost(String url, String host) {
String serviceName = getServiceNameFromUrl(url);
// 拼接远端host到url
return serviceName == null ? url : host + serviceName;
}
/**
* 提取url中的服务名
*/
private static String getServiceNameFromUrl(String url) {
Pattern pattern = Pattern.compile(FEIGN_URL_REGEX);
Matcher matcher = pattern.matcher(url);
String serviceName = null;
if (matcher.matches()) {
serviceName = matcher.group(1);
}
return serviceName;
}
}

View File

@ -0,0 +1,199 @@
package cn.axzo.im.controller;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.im.center.api.vo.resp.MessageDispatchResp;
import cn.axzo.im.center.common.enums.AccountTypeEnum;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.center.common.enums.ChannelMsgTypeEnum;
import cn.axzo.im.channel.IMChannelProvider;
import cn.axzo.im.channel.netease.dto.MessageDispatchRequest;
import cn.axzo.im.channel.netease.dto.MessageDispatchResponse;
import cn.axzo.im.channel.netease.dto.RegisterUpdateRequest;
import cn.axzo.im.entity.AccountRegister;
import cn.axzo.im.entity.bo.AccountQueryParam;
import cn.axzo.im.entity.dto.PlatPersonDto;
import cn.axzo.im.gateway.ProfilesApiGateway;
import cn.axzo.im.service.AccountService;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Objects;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author syl
* @date 2024/1/8
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/text/message")
public class PrivateMessageController {
@Autowired
private IMChannelProvider imChannel;
@Autowired
private AccountService accountService;
@Autowired
private ProfilesApiGateway profilesApiGateway;
@PostMapping(value = "/send")
public CommonResponse<List<MessageDispatchResp>> sendMessage(@RequestBody @Valid SendMessageRequest param) {
log.info("send message param: [{}]", JSONUtil.toJsonStr(param));
String appKey = imChannel.getProviderAppKey();
List<MessageDispatchResp> result = Lists.newArrayList();
List<AccountRegister> accounts = accountService.listAccount(
AccountQueryParam.builder().accountType(param.getSenderType())
.accountId(param.getSenderId())
.appKey(appKey).build());
if (CollUtil.isEmpty(accounts)) {
log.info("appKey= [{}], senderId= [{}] 用户没有注册im账号, 请检查",
appKey, param.getSenderId());
AssertUtil.notEmpty(accounts, "发送者未注册im账号, 请检查");
}
AccountRegister account = accounts.get(0);
if (param.getSenderType() == AccountTypeEnum.USER) {
// 更新用户头像和昵称到网易云信
updateUserProfile(param, account, false);
}
param.getAppTypeList().forEach(type -> {
List<AccountRegister> receivers = accountService.listAccount(
AccountQueryParam.builder().accountId(param.getToPersonId())
.appKey(appKey)
.appType(type).build());
if (CollUtil.isEmpty(receivers)) {
log.info("appKey= [{}], appType= [{}], receiverId= [{}] 用户没有注册im账号, 请检查",
appKey, type, param.getToPersonId());
return;
}
AccountRegister receiver = receivers.get(0);
if (AccountTypeEnum.USER.getCode().equals(receiver.getAccountType())) {
// 更新接收方头像和昵称到网易云信
log.info("updateUserProfile receiver avatarUrl and nickName, receiverPersonId= [{}]"
, receiver.getAccountId());
updateUserProfile(param, receiver,true);
}
MessageDispatchRequest messageRequest = new MessageDispatchRequest();
messageRequest.setFrom(account.getImAccount());
messageRequest.setTo(receiver.getImAccount());
messageRequest.setType(param.getChannelMsgType().getCode());
// 暂时支持客户端的文本消息其他后续扩展
messageRequest.setBody(new JSONObject().fluentPut("msg", param.getMsgContent()).toJSONString());
MessageDispatchResponse response = imChannel.dispatchMessage(messageRequest);
log.info("send text message= [{}]", JSONUtil.toJsonStr(response));
MessageDispatchResp messageDispatchResp = BeanUtil.copyProperties(response.getData(),
MessageDispatchResp.class);
if (StringUtils.isNotBlank(response.getDesc())) {
messageDispatchResp.setDesc(response.getDesc());
}
messageDispatchResp.setAppType(type.getCode());
messageDispatchResp.setFromImAccount(messageRequest.getFrom());
messageDispatchResp.setToImAccount(messageRequest.getTo());
messageDispatchResp.setPersonId(param.getToPersonId());
result.add(messageDispatchResp);
});
return CommonResponse.success(result);
}
private void updateUserProfile(SendMessageRequest param, AccountRegister account, boolean fromUserFlag) {
String extJson = new JSONObject().fluentPut("accountType", AccountTypeEnum.USER.getCode()).toJSONString();
RegisterUpdateRequest updateProfile = new RegisterUpdateRequest();
updateProfile.setAccid(account.getImAccount());
if (Objects.nonNull(param.getExt()) && BooleanUtils.isNotTrue(fromUserFlag)) {
log.info("普通用户从请求参数获取头像昵称, personId= [{}]", account.getAccountId());
updateProfile.setName(param.getExt().getString("nickName"));
updateProfile.setIcon(param.getExt().getString("avatarUrl"));
} else {
log.info("从用户中心获取头像昵称, personId= [{}]", account.getAccountId());
PlatPersonDto platPerson = profilesApiGateway.getPersonProfileV2(
Long.valueOf(account.getAccountId()));
AssertUtil.notNull(platPerson, "用户信息不存在");
updateProfile.setName(platPerson.getRealName());
updateProfile.setIcon(platPerson.getAvatarUrl());
}
updateProfile.setExtJson(extJson);
log.info("updateUserProfile:{}", JSONUtil.toJsonStr(updateProfile));
imChannel.updateAccountProfile(updateProfile);
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class SendMessageRequest {
/**
* 发送消息到App端 工人端企业端服务器 CMCMPSYSTEM
*
* @See cn.axzo.im.center.common.enums.AppTypeEnum
*/
@NotNull(message = "消息接收端类型appTypeList不能为空")
private List<AppTypeEnum> appTypeList;
/**
* 发送者类型
*/
@NotNull(message = "发送者类型不能为空")
private AccountTypeEnum senderType;
/**
* 发送用户Id
*/
@NotBlank(message = "发送用户Id")
private String senderId;
/**
* 接收用户自然人Id
*/
@NotBlank(message = "接收用户自然人Id不能为空")
private String toPersonId;
/**
* 渠道消息类型
*/
@NotNull(message = "渠道消息类型不能为空")
private ChannelMsgTypeEnum channelMsgType;
/**
* 消息内容
*/
@NotBlank(message = "消息内容不能为空")
@Size(max = 4900, message = "内容过长")
private String msgContent;
/**
* 扩展信息
*/
private JSONObject ext;
}
}

View File

@ -0,0 +1,25 @@
package cn.axzo.im.entity.bo;
import cn.axzo.im.center.common.enums.AccountTypeEnum;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author syl
* @date 2024/1/6
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AccountQueryParam {
private AccountTypeEnum accountType;
private AppTypeEnum appType;
private String appKey;
private String accountId;
}

View File

@ -0,0 +1,76 @@
package cn.axzo.im.entity.dto;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PlatPersonDto {
/**
* 自然人id
*/
private Long personId;
private String uuid;
/**
* 人脸照片
*/
private String avatarUrl;
private String realNamePinyin;
private String idFaceUrl;
private Date idStartDate;
private Date idEndDate;
/**
*身份证签发机构
*/
private String idAuthority;
/**
*身份证籍贯
*/
private String idNativePlace;
/**
* 手机号
*/
private String phone;
private String realName;
/**
* 实名认证 true-认证通过 false 认证失败
*/
private boolean verify;
/**
* 1- 2-
*/
private Integer sex;
private Date birthday;
/**
* 民族
*/
private String nationality;
/**
*
*身份证
**/
private String idNumber;
/**
*
*身份证地址
**/
private String idAddress ;
/**
* 学历
*/
private String education;
}

View File

@ -0,0 +1,38 @@
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.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.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
@Service("profilesApiGateway")
@Slf4j
public class ProfilesApiGateway {
@Autowired
private UserProfileServiceApi userProfileServiceApi;
/**
* 获取自然人信息V2
* @param personId 自然人id
*/
@MethodAroundLog(source = "im-center", target = "basics", value = "获取自然人信息")
public PlatPersonDto getPersonProfileV2(Long personId) {
log.info("im-center->pudge : 获取自然人信息 :入参 --> {}", personId);
CommonResponse<PersonProfileDto> response = userProfileServiceApi
.getPersonProfile(personId);
if (Objects.isNull(response) || response.getCode() != HttpStatus.OK.value()) {
log.warn("im-center<---basics : 获取自然人信息 :返回值 {}", JSONUtil.toJsonStr(response));
return null;
}
return BeanUtil.copyProperties(response.getData(), PlatPersonDto.class);
}
}

View File

@ -19,6 +19,8 @@ import cn.axzo.im.dao.repository.AccountRegisterDao;
import cn.axzo.im.dao.repository.RobotInfoDao;
import cn.axzo.im.entity.AccountRegister;
import cn.axzo.im.entity.RobotInfo;
import cn.axzo.im.entity.bo.AccountQueryParam;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.google.common.collect.Lists;
import java.util.Date;
import java.util.List;
@ -292,4 +294,24 @@ public class AccountService {
}
return userAccountAll;
}
public List<AccountRegister> listAccount(AccountQueryParam param) {
return build(param).list();
}
public LambdaQueryChainWrapper<AccountRegister> build(AccountQueryParam param) {
LambdaQueryChainWrapper<AccountRegister> lambdaQuery = accountRegisterDao.lambdaQuery()
.eq(AccountRegister::getIsDelete, 0)
.eq(StringUtils.isNotBlank(param.getAppKey()), AccountRegister::getAppKey, param.getAppKey())
.eq(StringUtils.isNotBlank(param.getAccountId()), AccountRegister::getAccountId, param.getAccountId())
.isNotNull(AccountRegister::getToken);
if (Objects.nonNull(param.getAccountType())) {
lambdaQuery.eq(AccountRegister::getAccountType, param.getAccountType().getCode());
}
if (Objects.nonNull(param.getAppType())) {
lambdaQuery.eq(AccountRegister::getAppType, param.getAppType().getCode());
}
return lambdaQuery;
}
}

View File

@ -11,6 +11,7 @@ import cn.axzo.im.center.api.vo.resp.MessageDispatchResp;
import cn.axzo.im.center.api.vo.resp.UserAccountResp;
import cn.axzo.im.center.common.enums.AccountTypeEnum;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.center.common.enums.ChannelMsgTypeEnum;
import cn.axzo.im.channel.IMChannelProvider;
import cn.axzo.im.channel.netease.NimMsgTypeEnum;
import cn.axzo.im.channel.netease.dto.MessageBatchDispatchRequest;
@ -305,6 +306,7 @@ public class MessageService {
if (StringUtils.isNotEmpty(accountRegister.getImAccount()) &&
StringUtils.isNotEmpty(accountRegister.getToken())) {
messageRequest.setTo(accountRegister.getImAccount());
messageRequest.setType(ChannelMsgTypeEnum.CUSTOM.getCode());
MessageDispatchResponse response = imChannel.dispatchMessage(messageRequest);
MessageDispatchResp messageDispatchResp = BeanMapper.map(response.getData(), MessageDispatchResp.class);
if (messageDispatchResp == null) {

View File

@ -8,14 +8,15 @@ import cn.axzo.im.channel.netease.INotifyService;
import cn.axzo.im.channel.netease.dto.RegisterUpdateRequest;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
/**
* 通知到IM系统
*
@ -44,8 +45,11 @@ public class NotifyChannelServiceImpl implements INotifyService {
userProfileMap.put("accountType", AccountTypeEnum.ROBOT.getCode());
List<RobotTagResp> robotTags = robotInfoResp.getRobotTagList();
if (CollectionUtils.isNotEmpty(robotTags)) {
robotTags = robotTags.stream().sorted(
Comparator.comparing(RobotTagResp::getWeight, Comparator.reverseOrder())
.thenComparing(RobotTagResp::getId, Comparator.reverseOrder()))
.collect(Collectors.toList());
robotTags.forEach(robotTagResp -> {
robotTagResp.setId(null);
robotTagResp.setUseCount(null);
robotTagResp.setWeight(null);
});