feat(REQ-3300) - 添加 IM 相关事件的监听处理逻辑

This commit is contained in:
wangli 2025-02-07 17:05:56 +08:00
parent a1f33a364d
commit 41e69ea0c7
11 changed files with 411 additions and 2 deletions

View File

@ -264,4 +264,26 @@ public class RocketMQEventConfiguration {
super.onEvent(message, eventConsumer);
}
}
/**
* IM 事件处理
*/
@Slf4j
@Component
@RocketMQMessageListener(topic = "topic_im_center_${spring.profiles.active}",
consumerGroup = "GID_im_${spring.application.name}_${spring.profiles.active}",
consumeMode = ConsumeMode.ORDERLY,
nameServer = "${rocketmq.name-server}"
)
public static class ImCenterListener extends BaseListener implements RocketMQListener<MessageExt> {
@Autowired
private EventConsumer eventConsumer;
@Override
public void onMessage(MessageExt message) {
log.info("ImCenterListener onMessage nanopart, message:{}", JSON.toJSONString(message));
super.onEvent(message, eventConsumer);
}
}
}

View File

@ -17,10 +17,19 @@ public interface VisaConstant {
* 用于发送待办的变量名
*/
String WORKFLOW_PENDING_TOPIC = "theme";
String MSG_CENTER_APP_CODE = "nanopart-visa";
/**
* IM 群的扩展信息
* IM 群的扩展信息变洽签 ID
*/
String IM_GROUP_BIZ_INFO_RECORD_ID = "visaId";
String IM_GROUP_BIZ_INFO_VISA_ID = "visaId";
/**
* IM 群扩展信息变洽签单据类型
*/
String IM_GROUP_BIZ_INFO_VISA_TYPE = "visaType";
/**
* IM 群扩展信息群主 workspaceId
*/
String IM_GROUP_BIZ_INFO_OWNER_WORKSPACE_ID = "ownerWorkspaceId";
// **************** 业务传入审批的表单项组件的唯一的 KEY *****************
// 单号
String FORM_FIELD_NO = "no";

View File

@ -4,6 +4,8 @@ import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 签证业务类型
*
@ -21,4 +23,8 @@ public enum VisaTypeEnum {
private final String processDefinitionKey;
private final String code;
private final String desc;
public static VisaTypeEnum valueOfCode(String code) {
return Arrays.stream(VisaTypeEnum.values()).filter(item -> item.getCode().equals(code)).findFirst().orElse(null);
}
}

View File

@ -0,0 +1,24 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* IM 群成员投票操作的清除
*
* @author wangli
* @since 2025-02-07 15:39
*/
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ImGroupOperationClearReq extends ImGroupOperationReq{
private Boolean clearAll;
}

View File

@ -22,6 +22,8 @@ public class ImGroupTipsResp {
private VisaStatusEnum status;
private String statusText;
private String tipsText;
private List<ImGroupButton> buttonList;

View File

@ -28,4 +28,19 @@ public class VisaRelationDto {
*/
private String varName;
/**
* 内容
*/
private String content;
/**
* 内容扩展
*/
private String contentExt;
/**
* 创建人
*/
private Long createBy;
}

View File

@ -0,0 +1,100 @@
package cn.axzo.nanopart.visa.server.mq.listener.im;
import cn.axzo.basics.common.util.AssertUtil;
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.group.GroupInfo;
import cn.axzo.im.center.api.vo.group.GroupMemberInfo;
import cn.axzo.im.center.api.vo.mq.GroupMembersChangeMessage;
import cn.axzo.msg.center.api.MessageAPIV3;
import cn.axzo.msg.center.api.request.v3.MessageSendReqV3;
import cn.axzo.msg.center.service.dto.PersonV3DTO;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.nanopart.visa.server.config.RefreshableConfiguration;
import cn.axzo.nanopart.visa.server.rpc.VisaProfileGateway;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.groovy.util.Maps;
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.Map;
import java.util.Objects;
import static cn.axzo.im.center.api.enums.MqEventType.GROUP_ADD_MEMBERS;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_OWNER_WORKSPACE_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_TYPE;
/**
* 监听 IM 添加群成员的广播事件
*
* @author wangli
* @since 2025-02-07 13:53
*/
@Slf4j
@Component
public class ImGroupAddMembersEventHandler implements EventHandler, InitializingBean {
@Autowired
private EventConsumer eventConsumer;
@Resource
private RefreshableConfiguration refreshableConfiguration;
@Resource
private MessageAPIV3 noticeApi;
@Resource
private VisaProfileGateway visaProfileGateway;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
if (Objects.isNull(event) || Objects.isNull(event.getEventCode())) {
log.warn("illegal event code: {}", JSON.toJSONString(event));
return;
}
log.info("receive add member event, push notice : {}", JSON.toJSONString(event));
GroupMembersChangeMessage groupMembersChangeMessage = event.normalizedData(GroupMembersChangeMessage.class);
GroupInfo group = groupMembersChangeMessage.getGroup();
AssertUtil.notNull(group, "im group is null");
GroupMemberInfo member = groupMembersChangeMessage.getMember();
AssertUtil.notNull(member, "im member is null");
Map<Long, PersonProfileDto> profileMap = visaProfileGateway.getProfileMap(Lists.newArrayList(group.getOwnerPersonId(), member.getPersonId()));
String visaId = (String) group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, "");
String visaType = (String) group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_TYPE, "");
Long workspaceId = (Long) group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_OWNER_WORKSPACE_ID, 0L);
PersonProfileDto memberProfile = profileMap.getOrDefault(member.getPersonId(), null);
PersonProfileDto ownerProfile = profileMap.getOrDefault(group.getOwnerPersonId(), null);
if (Objects.nonNull(memberProfile) && Objects.nonNull(ownerProfile)) {
MessageSendReqV3 notice = new MessageSendReqV3();
notice.setSender(PersonV3DTO.builder().build());
notice.setReceivers(Lists.newArrayList(PersonV3DTO.builder()
.id(member.getPersonId())
.name(memberProfile.getRealName())
.imReceiveModel(new PersonV3DTO.ReceiveModel(member.getPersonOuId(), workspaceId))
.build()));
notice.setBizEventMappingCode(refreshableConfiguration.getImGroupAddMemberNoticeEventCode());
notice.setBizCode(visaId);
notice.setBizExtParams(new JSONObject(Maps.of(
"initiatorName", ownerProfile.getRealName(),
"visaType", VisaTypeEnum.valueOfCode(visaType).getDesc(),
"topic", group.getName())));
noticeApi.send(notice);
}
log.info("receive add member event, push notice success!");
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(GROUP_ADD_MEMBERS.getEventCode(), this);
}
}

View File

@ -0,0 +1,41 @@
package cn.axzo.nanopart.visa.server.mq.listener.im;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Objects;
import static cn.axzo.im.center.api.enums.MqEventType.GROUP_DISMISSED;
/**
* 监听 IM 群解散的广播事件
*
* @author wangli
* @since 2025-02-07 13:53
*/
@Slf4j
@Component
public class ImGroupDismissedEventHandler implements EventHandler, InitializingBean {
@Autowired
private EventConsumer eventConsumer;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
if (Objects.isNull(event) || Objects.isNull(event.getEventCode())) {
log.warn("illegal event code: {}", JSON.toJSONString(event));
return;
}
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(GROUP_DISMISSED.getEventCode(), this);
}
}

View File

@ -0,0 +1,73 @@
package cn.axzo.nanopart.visa.server.mq.listener.im;
import cn.axzo.basics.common.util.AssertUtil;
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.group.GroupInfo;
import cn.axzo.im.center.api.vo.group.GroupMemberInfo;
import cn.axzo.im.center.api.vo.mq.GroupMembersChangeMessage;
import cn.axzo.nanopart.visa.api.request.ImGroupOperationClearReq;
import cn.axzo.nanopart.visa.server.service.ChangeRecordRelationService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
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.Objects;
import static cn.axzo.im.center.api.enums.MqEventType.GROUP_REMOVE_MEMBERS;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_ID;
/**
* 监听 IM 群成员被移除的广播事件
*
* @author wangli
* @since 2025-02-07 13:53
*/
@Slf4j
@Component
public class ImGroupRemoveMembersEventHandler implements EventHandler, InitializingBean {
@Autowired
private EventConsumer eventConsumer;
@Resource
private ChangeRecordRelationService changeRecordRelationService;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
if (Objects.isNull(event) || Objects.isNull(event.getEventCode())) {
log.warn("illegal event code: {}", JSON.toJSONString(event));
return;
}
log.info("receive remove member event: {}", JSON.toJSONString(event));
GroupMembersChangeMessage groupMembersChangeMessage = event.normalizedData(GroupMembersChangeMessage.class);
GroupInfo group = groupMembersChangeMessage.getGroup();
AssertUtil.notNull(group, "im group is null");
GroupMemberInfo member = groupMembersChangeMessage.getMember();
AssertUtil.notNull(member, "im member is null");
// 移除该群成员的投票信息
removeMemberVote(group, member);
log.info("receive remove member event handle success!");
}
private void removeMemberVote(GroupInfo group, GroupMemberInfo member) {
Long visaId = (Long) group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, "");
ImGroupOperationClearReq build = new ImGroupOperationClearReq();
build.setClearAll(false);
build.setImGroupId(group.getTid());
build.setVisaId(visaId);
build.setOperatorPersonId(member.getPersonId());
build.setOperatorOuId(member.getPersonOuId());
changeRecordRelationService.clearImOperationParticipate(build);
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(GROUP_REMOVE_MEMBERS.getEventCode(), this);
}
}

View File

@ -0,0 +1,103 @@
package cn.axzo.nanopart.visa.server.mq.listener.im;
import cn.axzo.basics.common.util.AssertUtil;
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.PersonAccountAttribute;
import cn.axzo.im.center.api.vo.group.GroupInfo;
import cn.axzo.im.center.api.vo.group.GroupMemberInfo;
import cn.axzo.im.center.api.vo.mq.GroupChangedMessage;
import cn.axzo.im.center.api.vo.req.GroupGetOwnerRequest;
import cn.axzo.im.center.api.vo.req.SendChatMessageRequest;
import cn.axzo.im.center.api.vo.resp.GroupGetOwnerResponse;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.msg.center.service.dto.PeerPerson;
import cn.axzo.msg.center.service.pending.request.CardSendRequest;
import cn.axzo.nanopart.visa.server.rpc.MsgCenterGateway;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.groovy.util.Maps;
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.HashSet;
import java.util.Map;
import java.util.Objects;
import static cn.axzo.im.center.api.enums.MqEventType.GROUP_CREATED;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_OWNER_WORKSPACE_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.MSG_CENTER_APP_CODE;
/**
* 监听 IM 群创建的广播事件
*
* @author wangli
* @since 2025-02-07 13:53
*/
@Slf4j
@Component
public class ImGroupsCreatedEventHandler implements EventHandler, InitializingBean {
@Autowired
private EventConsumer eventConsumer;
@Resource
private MsgCenterGateway msgCenterGateway;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
if (Objects.isNull(event) || Objects.isNull(event.getEventCode())) {
log.warn("illegal event code: {}", JSON.toJSONString(event));
return;
}
log.info("receive create im group event: {}", JSON.toJSONString(event));
GroupChangedMessage groupChangedMessage = event.normalizedData(GroupChangedMessage.class);
GroupInfo group = groupChangedMessage.getGroup();
AssertUtil.notNull(group, "group info is null");
sendCardAndMsgToImGroup(group);
log.info("receive create im group event, handle success: {}", JSON.toJSONString(event));
}
private void sendCardAndMsgToImGroup(GroupInfo group) {
Map<String, Object> bizGroupInfo = group.getBizGroupInfo();
HashSet<String> imReceiveAccounts = Sets.newHashSet(String.valueOf(group.getTid()));
GroupGetOwnerRequest ownerRequest = new GroupGetOwnerRequest();
GroupGetOwnerResponse groupOwner = msgCenterGateway.getGroupOwner(ownerRequest);
AssertUtil.isTrue(Objects.nonNull(groupOwner) && Objects.nonNull(groupOwner.getOwner()), "im group owner is null");
GroupMemberInfo owner = groupOwner.getOwner();
// 发送卡片
CardSendRequest cardRequest = new CardSendRequest();
cardRequest.setAppCode(MSG_CENTER_APP_CODE);
cardRequest.setTemplateCode("");
Long visaId = (Long) bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, "");
cardRequest.setBizCode(IM_GROUP_BIZ_INFO_VISA_ID + ":" + visaId);
Long ownerWorkspaceId = (Long) bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_OWNER_WORKSPACE_ID, 0L);
cardRequest.setSender(PeerPerson.create(owner.getPersonId(), owner.getPersonOuId(), ownerWorkspaceId));
cardRequest.setImSenderAccountAppType(AppTypeEnum.CMP);
cardRequest.setImReceiveAccounts(imReceiveAccounts);
cardRequest.setBizParam(new JSONObject(Maps.of("topic", "")));
msgCenterGateway.sendCardToCroup(cardRequest);
// 普通群消息
SendChatMessageRequest msgRequest = new SendChatMessageRequest();
msgRequest.setAsTextMessage(group.getName() + ",请各位审阅");
msgRequest.setImReceiveAccounts(imReceiveAccounts);
msgRequest.setSender(PersonAccountAttribute.builder()
.personId(String.valueOf(owner.getPersonId()))
.ouId(owner.getPersonOuId())
.workspaceId(ownerWorkspaceId)
.appType(AppTypeEnum.CMP)
.build());
msgRequest.setBizId(IM_GROUP_BIZ_INFO_VISA_ID + ":" + visaId);
msgCenterGateway.sendMsgToGroup(msgRequest);
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(GROUP_CREATED.getEventCode(), this);
}
}

View File

@ -5,13 +5,18 @@ import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
import cn.azxo.framework.common.logger.MethodAroundLog;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author chenwenjian
@ -60,4 +65,13 @@ public class VisaProfileGateway {
}
return Collections.emptyList();
}
@MethodAroundLog(target = "pudge", source = "nanopart", value = "获取用户档案并转换Map")
public Map<Long, PersonProfileDto> getProfileMap(List<Long> personIds) {
List<PersonProfileDto> profiles = getProfiles(personIds);
if (CollectionUtils.isEmpty(profiles)) {
return Maps.newHashMap();
}
return profiles.stream().collect(Collectors.toMap(PersonProfileDto::getId, Function.identity(), (x, y) -> x));
}
}