diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/channel/IMChannelHandler.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/channel/IMChannelHandler.java new file mode 100644 index 00000000..05ed604a --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/channel/IMChannelHandler.java @@ -0,0 +1,17 @@ +package cn.axzo.msg.center.im.channel; + +import cn.axzo.msg.center.im.domain.enums.IMChannelEnum; +import cn.axzo.msg.center.im.domain.param.IMSendSingleMessageParam; + +/** + * @description + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +public interface IMChannelHandler { + + void sendSingleMessage(IMSendSingleMessageParam param); + + IMChannelEnum channel(); +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/channel/IMChannelHandlerFactory.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/channel/IMChannelHandlerFactory.java new file mode 100644 index 00000000..743684cf --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/channel/IMChannelHandlerFactory.java @@ -0,0 +1,64 @@ +package cn.axzo.msg.center.im.channel; + +import cn.axzo.basics.common.exception.ServiceException; +import cn.axzo.msg.center.im.domain.enums.IMSendMessageStatusEnum; +import cn.axzo.msg.center.im.domain.event.IMSendSingleMessageEvent; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; + +/** + * @description + * 即时通信渠道工厂 + * + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class IMChannelHandlerFactory { + + private final List handlers; + + @EventListener(classes = IMSendSingleMessageEvent.class) + public void sendSingleMessage(IMSendSingleMessageEvent event) { + IMChannelHandler handler = handlers.stream() + .filter(e -> Objects.equals(e.channel(), event.getParam().getChannel())) + .findFirst() + .orElse(null); + if (Objects.isNull(handler)) { + log.error("[{}] not registered.", event.getParam().getChannel()); + return; + } + log.info("start to send single message. event:{}", event); + retrySendSingleMessage(event, handler); + } + + @Retryable(value = ServiceException.class, backoff = @Backoff(delay = 1000L, multiplier = 1)) + public void retrySendSingleMessage(IMSendSingleMessageEvent event, IMChannelHandler handler) { + try { + if (event.getRetryCounter().longValue() > event.getRetryCnt()) { + log.warn("failed to retry send single message. event:{}", event); + event.setStatus(IMSendMessageStatusEnum.FAILED); + } else { + handler.sendSingleMessage(event.getParam()); + event.setStatus(IMSendMessageStatusEnum.SUCCESS); + log.warn("successfully send single message. event:{}", event); + } + // 回调函数处理 + event.getParam().getCallback().accept(event); + } catch (ServiceException e) { + log.error("broke out some exception while sending single message. event:{}", event); + event.getRetryCounter().increment(); + throw e; + } + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/channel/handler/YouMengHandler.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/channel/handler/YouMengHandler.java new file mode 100644 index 00000000..26bf52e6 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/channel/handler/YouMengHandler.java @@ -0,0 +1,132 @@ +package cn.axzo.msg.center.im.channel.handler; + +import cn.axzo.msg.center.api.enums.ReceiveTypeEnum; +import cn.axzo.msg.center.api.request.MsgBody4Guest; +import cn.axzo.msg.center.common.exception.ServiceException; +import cn.axzo.msg.center.common.model.ProfileIdRepair; +import cn.axzo.msg.center.common.utils.PlaceholderResolver; +import cn.axzo.msg.center.domain.enums.NativeTypeEnum; +import cn.axzo.msg.center.im.channel.IMChannelHandler; +import cn.axzo.msg.center.im.domain.dto.IMSendMessageDTO; +import cn.axzo.msg.center.im.domain.enums.IMChannelEnum; +import cn.axzo.msg.center.im.domain.param.IMSendSingleMessageParam; +import cn.axzo.msg.center.inside.notices.service.IYouMengMessageService; +import cn.axzo.msg.center.service.dto.MessageRouterDTO; +import cn.axzo.msg.center.service.dto.PersonDTO; +import cn.axzo.msg.center.service.enums.IdentityTypeEnum; +import cn.azxo.framework.common.utils.StringUtils; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.Optional; + +/** + * @description + * 友盟即时通信渠道 + * + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class YouMengHandler implements IMChannelHandler { + + private final IYouMengMessageService youMengMessageService; + + @Override + public void sendSingleMessage(IMSendSingleMessageParam param) { + youMengMessageService.sendPushMessage(convert(param)); + } + + @Override + public IMChannelEnum channel() { + return IMChannelEnum.YOU_MENG; + } + + private MsgBody4Guest convert(IMSendSingleMessageParam param) { + MsgBody4Guest imMessage = new MsgBody4Guest(); + imMessage.setTy(0); + imMessage.setF("0"); + imMessage.setNickName(param.getMessage().getGroupName()); + imMessage.setAppClient(param.getAppClientType().getCode()); + String toId = buildToId(param.getReceiver(), param.getMessage().getBizCode()); + imMessage.setT(toId); + imMessage.setM(param.getMessage().getMsgContent()); + + JSONObject jsonObject = buildMessageExt2(param.getMessage()); + imMessage.setM2(jsonObject.toJSONString()); + imMessage.setM3(String.valueOf(param.getReceiver().getId())); + return imMessage; + } + + private String buildToId(PersonDTO person, String bizCode) { + Long identityId = person.getIdentity().getId(); + switch (toReceiveType(person.getIdentity().getType())) { + case CM_LEADER: + return ReceiveTypeEnum.CM_LEADER.getMessage() + ProfileIdRepair.workerLeaderNewId2Old(identityId); + case CM_WORKER: + return ReceiveTypeEnum.CM_WORKER.getMessage() + ProfileIdRepair.workerNewId2OldId(identityId); + case CMP_USER: + return ReceiveTypeEnum.CMP_USER.getMessage() + ProfileIdRepair.entUserNew2OldId(identityId); + case NOT_IDENTITY: + return ReceiveTypeEnum.NOT_IDENTITY.getMessage() + person.getId(); + case NORMAL: + return ReceiveTypeEnum.NORMAL.getMessage() + person.getId(); + default: + log.error("消息推送用户类型错误 bizId:[{}]", bizCode); + throw new ServiceException("消息推送失败"); + } + } + + private JSONObject buildMessageExt2(IMSendMessageDTO message) { + final JSONObject extra = new JSONObject(); + Collection messageRouters = message.getRouters(); + if (messageRouters.isEmpty()) { + extra.put("ar", ""); + extra.put("ir", ""); + } else { + // 业务上不会跳转微信小程序 + messageRouters.forEach(item -> { + PlaceholderResolver pr = PlaceholderResolver.getDefaultResolver(); + String url = pr.resolveByMap(item.getUrl(), message.getRouteParam()); + extra.put("rt", NativeTypeEnum.getByCode(item.getTerminalType().getCode()).getMessage()); + switch (item.getTerminalType()) { + case IOS: + extra.put("ir", url); + break; + case ANDROID: + extra.put("ar", url); + break; + case WEB_VIEW: + case MINI_PROGRAM: + // 小程序 + extra.put("ar", url); + extra.put("ir", url); + break; + default: + } + }); + } + extra.put("msgId", message.getMsgId()); + extra.put("p", message.getRouteParam()); + extra.put("t", message.getMsgTitle()); + extra.put("extra", message.getExtInfo().toJSONString()); + // 临时处理发送类型,如果消息type为1时,需要前端清空teamId,并且重新拉取数据 + Integer exType = message.getExtInfo().getInteger("type"); + extra.put("type", exType); + if (StringUtils.isNotBlank(message.getAudioFileName())) { + extra.put("audio", message.getAudioFileName()); + } + return extra; + } + + private ReceiveTypeEnum toReceiveType(IdentityTypeEnum identityType) { + return Optional.ofNullable(ReceiveTypeEnum.valueOf(identityType.getCode())) + .orElse(ReceiveTypeEnum.NOT_IDENTITY); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/dto/IMSendMessageDTO.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/dto/IMSendMessageDTO.java new file mode 100644 index 00000000..c9ed0216 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/dto/IMSendMessageDTO.java @@ -0,0 +1,72 @@ +package cn.axzo.msg.center.im.domain.dto; + +import cn.axzo.msg.center.service.dto.MessageRouterDTO; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Collection; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IMSendMessageDTO implements Serializable { + + private static final long serialVersionUID = -5019078100836274269L; + + /** + * 消息id + */ + private Long msgId; + /** + * 消息标题 + */ + private String msgTitle; + /** + * 消息内容 + */ + private String msgContent; + /** + * 分类名称 + */ + private String groupName; + /** + * 消息路由列表 + */ + private Collection routers; + /** + * 消息参数 key value + */ + private JSONObject routeParam; + /** + * 消息扩展信息 + */ + private JSONObject extInfo; + /** + * 业务编码 + */ + private String bizCode; + /** + * 消息如果有音频信息,则需要给音频文件名称 + */ + private String audioFileName; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/enums/AppClientTypeEnum.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/enums/AppClientTypeEnum.java new file mode 100644 index 00000000..9bd3f186 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/enums/AppClientTypeEnum.java @@ -0,0 +1,24 @@ +package cn.axzo.msg.center.im.domain.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum AppClientTypeEnum { + + CM("cm", "工人端"), + CMP("cmp", "管理端"), + ; + + private final String code; + private final String desc; +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/enums/IMChannelEnum.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/enums/IMChannelEnum.java new file mode 100644 index 00000000..fb6aa0ed --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/enums/IMChannelEnum.java @@ -0,0 +1,22 @@ +package cn.axzo.msg.center.im.domain.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum IMChannelEnum { + + YOU_MENG("友盟"), + ; + + private final String desc; +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/enums/IMSendMessageStatusEnum.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/enums/IMSendMessageStatusEnum.java new file mode 100644 index 00000000..df94d9a8 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/enums/IMSendMessageStatusEnum.java @@ -0,0 +1,24 @@ +package cn.axzo.msg.center.im.domain.enums; + +/** + * @description + * @author cold_blade + * @date 2023/9/28 + * @version 1.0 + */ +public enum IMSendMessageStatusEnum { + + /** + * 发送中 + */ + SENDING, + /** + * 发送成功 + */ + SUCCESS, + /** + * 发送失败 + */ + FAILED, + ; +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/event/IMSendSingleMessageEvent.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/event/IMSendSingleMessageEvent.java new file mode 100644 index 00000000..91b48097 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/event/IMSendSingleMessageEvent.java @@ -0,0 +1,57 @@ +package cn.axzo.msg.center.im.domain.event; + +import cn.axzo.msg.center.im.domain.enums.IMSendMessageStatusEnum; +import cn.axzo.msg.center.im.domain.param.IMSendSingleMessageParam; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.concurrent.atomic.LongAdder; + +/** + * @description + * 即时通信发送消息事件 + * + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +@Setter +@Getter +public class IMSendSingleMessageEvent implements Serializable { + + private static final long serialVersionUID = 4652087357183307179L; + + /** + * 待发送的消息 + */ + private IMSendSingleMessageParam param; + /** + * 充实次数,默认重试3次,必须为非负数 + */ + private long retryCnt = 3L; + /** + * 充实次数计数器 + */ + private final LongAdder retryCounter = new LongAdder(); + /** + * 消息发送状态 + */ + private IMSendMessageStatusEnum status = IMSendMessageStatusEnum.SENDING; + /** + * 发送失败时的错误信息 + */ + private String errInfo; + + public static IMSendSingleMessageEvent build(IMSendSingleMessageParam param) { + IMSendSingleMessageEvent event = new IMSendSingleMessageEvent(); + event.setParam(param); + return event; + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/param/IMSendSingleMessageParam.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/param/IMSendSingleMessageParam.java new file mode 100644 index 00000000..f4782d2f --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/domain/param/IMSendSingleMessageParam.java @@ -0,0 +1,61 @@ +package cn.axzo.msg.center.im.domain.param; + +import cn.axzo.msg.center.im.domain.dto.IMSendMessageDTO; +import cn.axzo.msg.center.im.domain.enums.AppClientTypeEnum; +import cn.axzo.msg.center.im.domain.enums.IMChannelEnum; +import cn.axzo.msg.center.im.domain.event.IMSendSingleMessageEvent; +import cn.axzo.msg.center.service.dto.PersonDTO; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.function.Consumer; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +@Setter +@Getter +public class IMSendSingleMessageParam implements Serializable { + + private static final long serialVersionUID = 235976408457947264L; + + /** + * 消息 + */ + private IMSendMessageDTO message; + /** + * 消息发送者信息 + */ + private PersonDTO sender; + /** + * 消息接收者信息 + */ + private PersonDTO receiver; + /** + * 应用客户端类型 + */ + private AppClientTypeEnum appClientType; + /** + * 底层渠道发送消息后的回调 + */ + private Consumer callback; + /** + * 指定推送渠道 + */ + private IMChannelEnum channel; + /** + * APP的版本号 + */ + private Integer appVersionCode; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/service/IMService.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/service/IMService.java new file mode 100644 index 00000000..89b5527a --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/service/IMService.java @@ -0,0 +1,20 @@ +package cn.axzo.msg.center.im.service; + +import cn.axzo.msg.center.im.domain.param.IMSendSingleMessageParam; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +public interface IMService { + + /** + * 异步发送消息 + * + * @param param 消息内容 + */ + void asyncSendSingleMessage(IMSendSingleMessageParam param); +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/im/service/impl/IMServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/im/service/impl/IMServiceImpl.java new file mode 100644 index 00000000..6216a999 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/im/service/impl/IMServiceImpl.java @@ -0,0 +1,45 @@ +package cn.axzo.msg.center.im.service.impl; + +import cn.axzo.core.utils.converter.BeanConverter; +import cn.axzo.msg.center.common.utils.SpringUtils; +import cn.axzo.msg.center.im.domain.enums.AppClientTypeEnum; +import cn.axzo.msg.center.im.domain.event.IMSendSingleMessageEvent; +import cn.axzo.msg.center.im.domain.param.IMSendSingleMessageParam; +import cn.axzo.msg.center.im.service.IMService; +import cn.axzo.msg.center.service.enums.IdentityTypeEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Objects; + +/** + * @description + * 即时通信功能模块 + * + * @author cold_blade + * @date 2023/9/27 + * @version 1.0 + */ +@Slf4j +@Service +public class IMServiceImpl implements IMService { + + @Override + public void asyncSendSingleMessage(IMSendSingleMessageParam param) { + // 深拷贝一个外界的参数 + IMSendSingleMessageParam copyParam = BeanConverter.convert(param, IMSendSingleMessageParam.class); + // 发送推送消息事件 + SpringUtils.publishEvent(buildEvent(copyParam)); + } + + private IMSendSingleMessageEvent buildEvent(IMSendSingleMessageParam param) { + IMSendSingleMessageEvent event = IMSendSingleMessageEvent.build(param); + Integer appVersionCode = param.getAppVersionCode(); + if (Objects.nonNull(appVersionCode) && appVersionCode >= 330 + && IdentityTypeEnum.WORKER_LEADER.equals(param.getReceiver().getIdentity().getType())) { + log.info("班组长转到cmp,发给用户:{}, versionCode:[{}]", param.getReceiver(), appVersionCode); + param.setAppClientType(AppClientTypeEnum.CMP); + } + return event; + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/SendMessageEvent.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/SendMessageEvent.java index 409db481..398c8dd1 100644 --- a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/SendMessageEvent.java +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/SendMessageEvent.java @@ -8,7 +8,7 @@ import java.util.concurrent.atomic.AtomicInteger; /** * @ClassName SendMessgeEvent - * @Description TODO + * @Description * @Author zhangran * @Date 2022/4/8 11:36 **/ diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/listener/SendMessageListener.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/listener/SendMessageListener.java index 48bb86ab..d06d219d 100644 --- a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/listener/SendMessageListener.java +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/listener/SendMessageListener.java @@ -24,7 +24,7 @@ import javax.annotation.Resource; /** * @ClassName SendMessageListener - * @Description TODO + * @Description * @Author zhangran * @Date 2022/4/8 11:44 **/ diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/MessageTemplateController.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/MessageTemplateController.java new file mode 100644 index 00000000..d8e9d4d0 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/MessageTemplateController.java @@ -0,0 +1,37 @@ +package cn.axzo.msg.center.message.controller; + +import cn.axzo.msg.center.message.domain.param.MessageTemplateCreateParam; +import cn.axzo.msg.center.message.service.MessageTemplateNewService; +import cn.axzo.msg.center.service.template.client.MessageTemplateClient; +import cn.axzo.msg.center.service.template.request.MessageTemplateCreateRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateMoveToRequest; +import cn.azxo.framework.common.model.CommonResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RestController; + +/** + * 消息模板管理 + * + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@RestController +@RequiredArgsConstructor +public class MessageTemplateController implements MessageTemplateClient { + + private final MessageTemplateNewService messageTemplateNewService; + + @Override + public CommonResponse addTemplate(MessageTemplateCreateRequest request) { + MessageTemplateCreateParam param = MessageTemplateCreateParam.from(request); + messageTemplateNewService.createTemplate(param); + return CommonResponse.success(param.getTemplateCode()); + } + + @Override + public CommonResponse batchMove(MessageTemplateMoveToRequest request) { + // TODO: [cold_blade] [P2] 模板关联的批量移动 + return null; + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/PendingMessageNewController.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/PendingMessageNewController.java new file mode 100644 index 00000000..90d07020 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/PendingMessageNewController.java @@ -0,0 +1,76 @@ +package cn.axzo.msg.center.message.controller; + +import cn.axzo.msg.center.message.domain.dto.MessageGroupNodeDTO; +import cn.axzo.msg.center.message.domain.dto.PendingMessageDTO; +import cn.axzo.msg.center.message.domain.param.MessageGroupNodeStatisticParam; +import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam; +import cn.axzo.msg.center.message.service.PendingMessageNewService; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import cn.axzo.msg.center.service.pending.client.PendingMessageClient; +import cn.axzo.msg.center.service.pending.request.MessageGroupNodeStatisticRequest; +import cn.axzo.msg.center.service.pending.request.PendingMessagePageRequest; +import cn.axzo.msg.center.service.pending.request.PendingMessagePushRequest; +import cn.axzo.msg.center.service.pending.response.MessageGroupNodeResponse; +import cn.axzo.msg.center.service.pending.response.PendingMessageResponse; +import cn.azxo.framework.common.model.CommonResponse; +import cn.azxo.framework.common.model.Page; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @description + * + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@RestController +@RequiredArgsConstructor +public class PendingMessageNewController implements PendingMessageClient { + + private final PendingMessageNewService pendingMessageNewService; + + @Override + public CommonResponse> groupStatistic(MessageGroupNodeStatisticRequest request) { + List groupNodes = pendingMessageNewService + .groupStatistic(MessageGroupNodeStatisticParam.from(request)); + return CommonResponse.success(groupNodes.stream() + .map(MessageGroupNodeDTO::toResponse) + .collect(Collectors.toList()) + ); + } + + @Override + public CommonResponse> pageQuery(PendingMessagePageRequest request) { + return CommonResponse.success(pendingMessageNewService.pageQuery(request)); + } + + @Override + public CommonResponse detail(String msgIdentityCode, TerminalTypeEnum terminalType) { + PendingMessageDTO pendingMessage = pendingMessageNewService.detail(msgIdentityCode, terminalType) + .orElse(null); + if (Objects.isNull(pendingMessage)) { + return CommonResponse.success(); + } + return CommonResponse.success(pendingMessage.toResponse()); + } + + @Override + public CommonResponse push(PendingMessagePushRequest request) { + return CommonResponse.success(pendingMessageNewService.push(PendingMessagePushParam.from(request))); + } + + @Override + public CommonResponse complete(String msgIdentityCode) { + return CommonResponse.success(pendingMessageNewService.complete(msgIdentityCode)); + } + + @Override + public CommonResponse revoke(String msgIdentityCode) { + return CommonResponse.success(pendingMessageNewService.revoke(msgIdentityCode)); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageGroupNodeDTO.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageGroupNodeDTO.java new file mode 100644 index 00000000..37bd6303 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageGroupNodeDTO.java @@ -0,0 +1,87 @@ +package cn.axzo.msg.center.message.domain.dto; + +import cn.axzo.core.utils.converter.BeanConverter; +import cn.axzo.msg.center.domain.entity.MessageGroupNode; +import cn.axzo.msg.center.service.enums.MessageGroupNodeCategoryEnum; +import cn.axzo.msg.center.service.pending.response.MessageGroupNodeResponse; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @description + * 消息分类结点DTO + * + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MessageGroupNodeDTO implements Serializable { + + private static final long serialVersionUID = 5171436359992401120L; + + /** + * 结点类型 + * GENERAL_MESSAGE_CENTER: 消息中心 + * GENERAL_MESSAGE_MODULE: 消息模块 + * GENERAL_MESSAGE_CATEGORY: 消息分类 + * PENDING_MESSAGE_CENTER: 待办中心 + * PENDING_MESSAGE_MODULE: 待办模块 + * PENDING_MESSAGE_CATEGORY: 待办分类 + */ + private MessageGroupNodeCategoryEnum category; + /** + * 结点名称 + */ + private String nodeName; + /** + * 结点编码 + */ + private String nodeCode; + /** + * 父节点编码 + */ + private String parentNodeCode; + /** + * 结点对应的代办数量 + */ + private Integer pendingCount; + /** + * 子节点列表 + */ + private List children; + + public static MessageGroupNodeDTO from(MessageGroupNode groupNode) { + return MessageGroupNodeDTO.builder() + .category(groupNode.getCategory()) + .nodeName(groupNode.getName()) + .nodeCode(groupNode.getCode()) + .parentNodeCode(groupNode.getParentCode()) + .build(); + } + + public MessageGroupNodeResponse toResponse() { + MessageGroupNodeResponse response = BeanConverter.convert(this, MessageGroupNodeResponse.class); + List children = this.children.stream() + .map(MessageGroupNodeDTO::toResponse).collect(Collectors.toList()); + response.setNodeChildren(children); + return response; + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageTemplateDTO.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageTemplateDTO.java new file mode 100644 index 00000000..88fafc90 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageTemplateDTO.java @@ -0,0 +1,81 @@ +package cn.axzo.msg.center.message.domain.dto; + +import cn.axzo.msg.center.domain.entity.MessageBaseTemplate; +import cn.axzo.msg.center.service.enums.MessageCategoryEnum; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * @description + * + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MessageTemplateDTO implements Serializable { + + private static final long serialVersionUID = -2658385672181452557L; + + /** + * 模板名称 + */ + private String name; + /** + * 系统自动生成的模板code + */ + private String code; + /** + * 模板标题 + */ + private String title; + /** + * 模板类容 + */ + private String content; + /** + * 卡片信息,json字串 + */ + private String cardContent; + /** + * 所属消息类型 + */ + private MessageCategoryEnum msgCategory; + /** + * 模板icon + */ + private String icon; + /** + * 模板路由信息 + */ + private List routers; + + public static MessageTemplateDTO from(MessageBaseTemplate baseTemplate, List routers) { + return MessageTemplateDTO.builder() + .name(baseTemplate.getName()) + .code(baseTemplate.getCode()) + .title(baseTemplate.getTitle()) + .content(baseTemplate.getContent()) + .cardContent(baseTemplate.getCardContent()) + .msgCategory(baseTemplate.getMsgCategory()) + .icon(baseTemplate.getIcon()) + .routers(routers) + .build(); + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/PendingMessageDTO.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/PendingMessageDTO.java new file mode 100644 index 00000000..d073790c --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/PendingMessageDTO.java @@ -0,0 +1,153 @@ +package cn.axzo.msg.center.message.domain.dto; + +import cn.axzo.msg.center.domain.entity.PendingMessageRecord; +import cn.axzo.msg.center.service.dto.IdentityDTO; +import cn.axzo.msg.center.service.dto.MessageRouterDTO; +import cn.axzo.msg.center.service.dto.PersonDTO; +import cn.axzo.msg.center.service.enums.BizCategoryEnum; +import cn.axzo.msg.center.service.pending.response.PendingMessageResponse; +import cn.axzo.msg.center.utils.DateFormatUtil; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +/** + * @description + * 代办消息记录DTO + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PendingMessageDTO implements Serializable { + + private static final long serialVersionUID = 2207968284043321033L; + + /** + * 消息的唯一标识 + */ + private String identityCode; + /** + * 消息标题 + */ + private String title; + /** + * 消息内容 + */ + private String content; + /** + * 卡片信息的JSON字符串 + */ + private String cardContent; + /** + * 代办发起者信息 + */ + private PersonDTO promoter; + /** + * 代办执行者信息 + */ + private PersonDTO executor; + /** + * 业务编码 + */ + private String bizCode; + /** + * 子业务编码 + */ + private String subBizCode; + /** + * 业务状态描述 + */ + private String bizDesc; + /** + * 业务类型 + */ + private BizCategoryEnum bizCategory; + /** + * 申请时间戳 + */ + private LocalDateTime createTime; + /** + * 处理时间戳 + */ + private LocalDateTime updateTime; + /** + * 路由信息,可为空 + */ + private List routers; + /** + * 参数及其对应的值的JSON串 + */ + private String routerParams; + + public static PendingMessageDTO from(PendingMessageRecord pendingMessageRecord) { + // 代办发起者信息 + PersonDTO promoter = PersonDTO.builder() + .id(pendingMessageRecord.getPromoterPersonId()) + .identity(IdentityDTO.builder() + .id(pendingMessageRecord.getPromoterId()) + .type(pendingMessageRecord.getPromoterType()) + .build()) + .build(); + // 代办执行者信息 + PersonDTO executor = PersonDTO.builder() + .id(pendingMessageRecord.getExecutorPersonId()) + .identity(IdentityDTO.builder() + .id(pendingMessageRecord.getExecutorId()) + .type(pendingMessageRecord.getExecutorType()) + .build()) + .build(); + return PendingMessageDTO.builder() + .identityCode(pendingMessageRecord.getIdentityCode()) + .title(pendingMessageRecord.getTitle()) + .content(pendingMessageRecord.getContent()) + .promoter(promoter) + .executor(executor) + .bizCode(pendingMessageRecord.getBizCode()) + .subBizCode(pendingMessageRecord.getSubBizCode()) + .bizDesc(pendingMessageRecord.getBizDesc()) + .bizCategory(pendingMessageRecord.getBizCategory()) + .createTime(DateFormatUtil.toLocalDateTime(pendingMessageRecord.getCreateAt())) + .updateTime(DateFormatUtil.toLocalDateTime(pendingMessageRecord.getUpdateAt())) + .routerParams(pendingMessageRecord.getRouterParams()) + .build(); + } + + public PendingMessageResponse toResponse() { + return PendingMessageResponse.builder() + .identityCode(this.identityCode) + .title(this.title) + .content(this.content) + .cardContent(this.cardContent) + .promoterPersonId(Optional.ofNullable(this.promoter).map(PersonDTO::getId).orElse(null)) + .promoterIdentity(Optional.ofNullable(this.promoter).map(PersonDTO::getIdentity).orElse(null)) + .executorPersonId(Optional.ofNullable(this.executor).map(PersonDTO::getId).orElse(null)) + .executorIdentity(Optional.ofNullable(this.executor).map(PersonDTO::getIdentity).orElse(null)) + .bizCode(this.bizCode) + .subBizCode(this.subBizCode) + .bizDesc(this.bizDesc) + .bizCategory(this.bizCategory) + .createTimestamp(DateFormatUtil.toTimestamp(this.createTime)) + .updateTimestamp(DateFormatUtil.toTimestamp(this.updateTime)) + .routers(this.routers) + .routerParams(this.routerParams) + .build(); + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/RawMessageRouterDTO.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/RawMessageRouterDTO.java new file mode 100644 index 00000000..1c8ea27a --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/RawMessageRouterDTO.java @@ -0,0 +1,95 @@ +package cn.axzo.msg.center.message.domain.dto; + +import cn.axzo.msg.center.domain.entity.MessageTemplateRouter; +import cn.axzo.msg.center.service.dto.MessageRouterDTO; +import cn.axzo.msg.center.service.enums.RouterCategoryEnum; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/28 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RawMessageRouterDTO implements Serializable { + + private static final long serialVersionUID = -3751613307785030747L; + + /** + * 路由描述 + */ + private String desc; + /** + * 路由分类 + * JUMP: 直接跳转 + * ACTION: 接口调用 + */ + private RouterCategoryEnum category; + /** + * 页面地址 OR API接口地址 + */ + private String url; + /** + * 页面地址所属应用端(如果是API接口地址,请忽略改字段值) + * WEB: web端页面 + * MINI_PROGRAM: 安心筑小程序端页面 + * IOS: 原生IOS端页面 + * ANDROID: 原生Android端页面 + * WEB_VIEW: H5页面 + * WECHAT_MINI_PROGRAM: 微信小程序页面 + */ + private TerminalTypeEnum terminalType; + /** + * 模板编码 + */ + private String templateCode; + + public static RawMessageRouterDTO from(MessageTemplateRouter msgTemplateRouter) { + return RawMessageRouterDTO.builder() + .desc(msgTemplateRouter.getName()) + .url(msgTemplateRouter.getUrl()) + .category(msgTemplateRouter.getCategory()) + .terminalType(msgTemplateRouter.getTerminalType()) + .templateCode(msgTemplateRouter.getTemplateCode()) + .build(); + } + + public static RawMessageRouterDTO from(MessageRouterDTO router, String templateCode) { + return RawMessageRouterDTO.builder() + .desc(router.getDesc()) + .url(router.getUrl()) + .category(router.getCategory()) + .terminalType(router.getTerminalType()) + .templateCode(templateCode) + .build(); + } + + public MessageTemplateRouter toMessageTemplateRouter() { + MessageTemplateRouter router = new MessageTemplateRouter(); + router.setName(this.desc); + router.setUrl(this.url); + router.setCategory(this.category); + router.setTerminalType(this.terminalType); + router.setTemplateCode(this.templateCode); + return router; + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/param/MessageGroupNodeStatisticParam.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/param/MessageGroupNodeStatisticParam.java new file mode 100644 index 00000000..1609d360 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/param/MessageGroupNodeStatisticParam.java @@ -0,0 +1,81 @@ +package cn.axzo.msg.center.message.domain.param; + +import cn.axzo.core.utils.converter.BeanConverter; +import cn.axzo.msg.center.service.dto.IdentityDTO; +import cn.axzo.msg.center.service.dto.PersonDTO; +import cn.axzo.msg.center.service.enums.PendingMessageRoleCategoryEnum; +import cn.axzo.msg.center.service.enums.PendingMessageStateEnum; +import cn.axzo.msg.center.service.pending.request.MessageGroupNodeStatisticRequest; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Collection; + +/** + * @description + * 消息分类统计功能的入参Param + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Setter +@Getter +public class MessageGroupNodeStatisticParam implements Serializable { + + private static final long serialVersionUID = 2301361555618643235L; + + /** + * 当前登录账户的自然id(前端不care) + */ + private PersonDTO operator; + /** + * 业务方是否只关注特定身份的消息 + * true: 是 + * false: 否 + */ + private Boolean withIdentify; + /** + * 消息的分类结点编码集合 + */ + private Collection groupNodeCodes; + /** + * 代办角色 + * PROMOTER: 发起者 + * EXECUTOR: 执行者 + */ + private PendingMessageRoleCategoryEnum roleCategory; + /** + * 代办消息状态 + * UNSENT: 未发送 + * HAS_BEEN_SENT: 已发送 + * COMPLETED: 已办 + * RETRACT: 已撤回 + * DELETED: 已删除 + */ + private PendingMessageStateEnum msgState; + /** + * 消息标题 + */ + private String title; + + public static MessageGroupNodeStatisticParam from(MessageGroupNodeStatisticRequest request) { + MessageGroupNodeStatisticParam param = BeanConverter.convert(request, MessageGroupNodeStatisticParam.class); + IdentityDTO identity = IdentityDTO.builder() + .id(request.getIdentityId()) + .type(request.getIdentityType()) + .build(); + PersonDTO person = PersonDTO.builder() + .id(request.getPersonId()) + .identity(identity) + .build(); + param.setOperator(person); + return param; + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/param/MessageTemplateCreateParam.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/param/MessageTemplateCreateParam.java new file mode 100644 index 00000000..f99c1cbe --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/param/MessageTemplateCreateParam.java @@ -0,0 +1,90 @@ +package cn.axzo.msg.center.message.domain.param; + +import cn.axzo.msg.center.service.dto.MessageRouterDTO; +import cn.axzo.msg.center.service.enums.MessageCategoryEnum; +import cn.axzo.msg.center.service.template.request.MessageTemplateCreateRequest; +import cn.axzo.msg.center.utils.UUIDUtil; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * @description + * + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MessageTemplateCreateParam implements Serializable { + + private static final long serialVersionUID = 6657624182580261353L; + + /** + * 模板名称 + */ + private String templateName; + /** + * 系统自动生成的模板code + */ + private String templateCode; + /** + * 所属消息类型 + * GENERAL_MESSAGE: 普通消息 + * PENDING_MESSAGE: 待办消息 + */ + private MessageCategoryEnum msgCategory; + /** + * 模板标题 + */ + private String title; + /** + * 模板类容 + */ + private String content; + /** + * 卡片信息,json字串 + */ + private String cardContent; + /** + * 模板icon + */ + private String icon; + /** + * 操作者自然人id + */ + private Long operatorId; + /** + * 路由列表 + */ + private List routers; + + public static MessageTemplateCreateParam from(MessageTemplateCreateRequest request) { + return MessageTemplateCreateParam.builder() + .templateName(request.getTemplateName()) + .templateCode(UUIDUtil.uuidString()) + .msgCategory(request.getCategory()) + .title(request.getMsgTitle()) + .content(request.getMsgContent()) + .cardContent(request.getMsgCardInfo()) + .icon(request.getMsgIcon()) + .operatorId(request.getOperatorId()) + .routers(request.getRouters()) + .build(); + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/param/PendingMessagePushParam.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/param/PendingMessagePushParam.java new file mode 100644 index 00000000..429b0a31 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/param/PendingMessagePushParam.java @@ -0,0 +1,85 @@ +package cn.axzo.msg.center.message.domain.param; + +import cn.axzo.core.utils.converter.BeanConverter; +import cn.axzo.msg.center.service.dto.PersonDTO; +import cn.axzo.msg.center.service.enums.BizCategoryEnum; +import cn.axzo.msg.center.service.enums.OrganizationTypeEnum; +import cn.axzo.msg.center.service.pending.request.PendingMessagePushRequest; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PendingMessagePushParam implements Serializable { + + private static final long serialVersionUID = 6308469943450138452L; + + /** + * 发起者 + */ + private PersonDTO promoter; + /** + * 执行者 + */ + private PersonDTO executor; + /** + * 模板编码 + */ + private String templateCode; + /** + * 消息所属组织类型 + */ + private OrganizationTypeEnum orgType; + /** + * 消息所属组织Id + */ + private Long orgId; + /** + * 消息所属组织名称 + */ + private String orgName; + /** + * 业务类型 + */ + private BizCategoryEnum bizCategory; + /** + * 关联业务主键 + */ + private String bizCode; + /** + * 流程类代办的流程结点编码 + */ + private String subBizCode; + /** + * 业务描述eg:流程结点描述 + */ + private String bizDesc; + /** + * 路由参数(json string) + */ + private String routerParams; + + public static PendingMessagePushParam from(PendingMessagePushRequest request) { + return BeanConverter.convert(request, PendingMessagePushParam.class); + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageGroupService.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageGroupService.java new file mode 100644 index 00000000..66dabe02 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageGroupService.java @@ -0,0 +1,41 @@ +package cn.axzo.msg.center.message.service; + +import cn.axzo.msg.center.message.domain.dto.MessageGroupNodeDTO; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +/** + * 消息分类管理 + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +public interface MessageGroupService { + + /** + * 通过结点编码查询结点信息 + * + * @param nodeCode 结点编码 + * @return 结点信息 + */ + Optional queryByNodeCode(String nodeCode); + + /** + * 查询指定结点的字节的信息 + * + * @param nodeCode 指定结点编码 + * @return 子节点列表信息 + */ + List listChildren(String nodeCode); + + /** + * 模板关联分类 + * + * @param templateNode 模板编码 + * @param pathList 分类path列表 + */ + void templateGroup(String templateNode, Collection pathList); +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageTemplateGroupService.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageTemplateGroupService.java new file mode 100644 index 00000000..f830e062 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageTemplateGroupService.java @@ -0,0 +1,21 @@ +package cn.axzo.msg.center.message.service; + +import java.util.List; + +/** + * 消息模板分类管理 + * + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +public interface MessageTemplateGroupService { + + /** + * 通过分组结点编码查询关联的模板编码列表 + * + * @param groupNodeCode 分组结点编码 + * @return 模板编码列表 + */ + List listMessageTemplateCodes(String groupNodeCode); +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageTemplateNewService.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageTemplateNewService.java new file mode 100644 index 00000000..6836bb14 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageTemplateNewService.java @@ -0,0 +1,40 @@ +package cn.axzo.msg.center.message.service; + +import cn.axzo.msg.center.message.domain.dto.MessageTemplateDTO; +import cn.axzo.msg.center.message.domain.param.MessageTemplateCreateParam; + +import java.util.List; +import java.util.Optional; + +/** + * @description + * 消息模板管理 + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +public interface MessageTemplateNewService { + + /** + * 创建模板 + * + * @param param 模板内容参数 + */ + void createTemplate(MessageTemplateCreateParam param); + + /** + * 通过模板编码查询模板信息 + * + * @param msgTemplateCode 模板编码 + * @return 模板信息 + */ + Optional queryByTemplateCode(String msgTemplateCode); + + /** + * 通过模板编码查询模板信息 + * + * @param msgTemplateCodes 模板编码列表 + * @return 模板信息 + */ + List listByTemplateCodes(List msgTemplateCodes); +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageTemplateRouterService.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageTemplateRouterService.java new file mode 100644 index 00000000..915b43c1 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/MessageTemplateRouterService.java @@ -0,0 +1,40 @@ +package cn.axzo.msg.center.message.service; + +import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO; + +import java.util.List; +import java.util.Map; + +/** + * @description + * 消息模板路由管理 + * + * @author cold_blade + * @date 2023/9/28 + * @version 1.0 + */ +public interface MessageTemplateRouterService { + + /** + * 根据消息模板编码查询配置的路由列表 + * + * @param templateCode 消息模板编码 + * @return 路由列表 + */ + List queryByTemplateCode(String templateCode); + + /** + * 批量插入模板路由 + * + * @param routers 路由列表 + */ + void batchInsert(List routers); + + /** + * 根据消息模板编码查询配置的路由列表 + * + * @param templateCodes 消息模板编码列表 + * @return 路由列表 + */ + Map> groupByTemplateCode(List templateCodes); +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/PendingMessageNewService.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/PendingMessageNewService.java new file mode 100644 index 00000000..df132a34 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/PendingMessageNewService.java @@ -0,0 +1,67 @@ +package cn.axzo.msg.center.message.service; + +import cn.axzo.msg.center.message.domain.dto.MessageGroupNodeDTO; +import cn.axzo.msg.center.message.domain.dto.PendingMessageDTO; +import cn.axzo.msg.center.message.domain.param.MessageGroupNodeStatisticParam; +import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import cn.axzo.msg.center.service.pending.request.PendingMessagePageRequest; +import cn.axzo.msg.center.service.pending.request.PendingMessagePushRequest; +import cn.axzo.msg.center.service.pending.response.PendingMessageResponse; +import cn.azxo.framework.common.model.Page; + +import java.util.List; +import java.util.Optional; + +/** + * @description + * 待办Service + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +public interface PendingMessageNewService { + + List groupStatistic(MessageGroupNodeStatisticParam param); + + /** + * 代办列表分页查询 + * + * @param request 分页查询相关参数 + * @return 代办列表 + */ + Page pageQuery(PendingMessagePageRequest request); + + /** + * 查询代办详情 + * + * @param msgIdentityCode 消息的唯一标识 + * @param terminalType APP终端类型 + * @return 代办详情 + */ + Optional detail(String msgIdentityCode, TerminalTypeEnum terminalType); + + /** + * 发送代办 + * + * @param param 代办核心参数 + * @return 代办唯一标识 + */ + String push(PendingMessagePushParam param); + + /** + * 完成代办 + * + * @param msgIdentityCode 代办唯一标识 + * @return 成功返回 {@code true} 失败返回 {@code false} + */ + Boolean complete(String msgIdentityCode); + + /** + * 撤销代办 + * + * @param msgIdentityCode 代办唯一标识 + * @return 成功返回 {@code true} 失败返回 {@code false} + */ + Boolean revoke(String msgIdentityCode); +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageGroupServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageGroupServiceImpl.java new file mode 100644 index 00000000..0ca69898 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageGroupServiceImpl.java @@ -0,0 +1,70 @@ +package cn.axzo.msg.center.message.service.impl; + +import cn.axzo.msg.center.dal.MessageGroupNodeDao; +import cn.axzo.msg.center.dal.MessageTemplateGroupDao; +import cn.axzo.msg.center.domain.entity.MessageGroupNode; +import cn.axzo.msg.center.domain.entity.MessageTemplateGroup; +import cn.axzo.msg.center.message.domain.dto.MessageGroupNodeDTO; +import cn.axzo.msg.center.message.service.MessageGroupService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @author cold_blade + * @date 2023/10/6 + * @version 1.0 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MessageGroupServiceImpl implements MessageGroupService { + + private final MessageGroupNodeDao messageGroupNodeDao; + private final MessageTemplateGroupDao messageTemplateGroupDao; + + @Override + public Optional queryByNodeCode(String nodeCode) { + if (StringUtils.isBlank(nodeCode)) { + return Optional.empty(); + } + MessageGroupNode groupNode = messageGroupNodeDao.lambdaQuery() + .eq(MessageGroupNode::getCode, nodeCode) + .eq(MessageGroupNode::getIsDelete, 0) + .one(); + return Optional.ofNullable(groupNode).map(MessageGroupNodeDTO::from); + } + + @Override + public List listChildren(String nodeCode) { + return messageGroupNodeDao.lambdaQuery() + .eq(MessageGroupNode::getParentCode, nodeCode) + .eq(MessageGroupNode::getIsDelete, 0) + .list().stream() + .map(MessageGroupNodeDTO::from) + .collect(Collectors.toList()); + } + + @Override + public void templateGroup(String templateNode, Collection pathList) { + if (StringUtils.isBlank(templateNode) + || CollectionUtils.isEmpty(pathList)) { + return; + } + List rows = pathList.stream() + .map(e -> { + MessageTemplateGroup group = new MessageTemplateGroup(); + group.setTemplateCode(templateNode); + group.setPath(e); + return group; + }).collect(Collectors.toList()); + messageTemplateGroupDao.saveBatch(rows); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateGroupServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateGroupServiceImpl.java new file mode 100644 index 00000000..cfcd1b34 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateGroupServiceImpl.java @@ -0,0 +1,40 @@ +package cn.axzo.msg.center.message.service.impl; + +import cn.axzo.msg.center.dal.MessageTemplateGroupDao; +import cn.axzo.msg.center.domain.entity.MessageTemplateGroup; +import cn.axzo.msg.center.message.service.MessageTemplateGroupService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MessageTemplateGroupServiceImpl implements MessageTemplateGroupService { + + private final MessageTemplateGroupDao messageTemplateGroupDao; + + @Override + public List listMessageTemplateCodes(String groupNodeCode) { + if (StringUtils.isBlank(groupNodeCode)) { + log.info("groupNodeCode is blank."); + return Collections.emptyList(); + } + return messageTemplateGroupDao.lambdaQuery() + .like(MessageTemplateGroup::getPath, groupNodeCode) + .eq(MessageTemplateGroup::getIsDelete, 0) + .list().stream() + .map(MessageTemplateGroup::getTemplateCode) + .collect(Collectors.toList()); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateNewServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateNewServiceImpl.java new file mode 100644 index 00000000..5a149989 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateNewServiceImpl.java @@ -0,0 +1,98 @@ +package cn.axzo.msg.center.message.service.impl; + +import cn.axzo.core.utils.converter.BeanConverter; +import cn.axzo.msg.center.dal.MessageBaseTemplateDao; +import cn.axzo.msg.center.domain.entity.MessageBaseTemplate; +import cn.axzo.msg.center.message.domain.dto.MessageTemplateDTO; +import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO; +import cn.axzo.msg.center.message.domain.param.MessageTemplateCreateParam; +import cn.axzo.msg.center.message.service.MessageTemplateNewService; +import cn.axzo.msg.center.message.service.MessageTemplateRouterService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @description + * + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MessageTemplateNewServiceImpl implements MessageTemplateNewService { + + private final MessageBaseTemplateDao messageBaseTemplateDao; + private final MessageTemplateRouterService messageTemplateRouterService; + + @Override + public void createTemplate(MessageTemplateCreateParam param) { + // TODO: [cold_blade] [P2] 模板与分类的关系 + messageBaseTemplateDao.save(convert(param)); + if (CollectionUtils.isNotEmpty(param.getRouters())) { + List routers = param.getRouters().stream() + .map(e -> RawMessageRouterDTO.from(e, param.getTemplateCode())) + .collect(Collectors.toList()); + messageTemplateRouterService.batchInsert(routers); + } + } + + @Override + public Optional queryByTemplateCode(String msgTemplateCode) { + if (StringUtils.isBlank(msgTemplateCode)) { + log.info("msgTemplateCode is blank."); + return Optional.empty(); + } + MessageBaseTemplate msgBaseTemplate = messageBaseTemplateDao.lambdaQuery() + .eq(MessageBaseTemplate::getCode, msgTemplateCode) + .eq(MessageBaseTemplate::getIsDelete, 0) + .one(); + if (Objects.isNull(msgBaseTemplate)) { + log.info("not find the [{}] template.", msgTemplateCode); + return Optional.empty(); + } + List routers = messageTemplateRouterService.queryByTemplateCode(msgTemplateCode); + return Optional.of(MessageTemplateDTO.from(msgBaseTemplate, routers)); + } + + @Override + public List listByTemplateCodes(List msgTemplateCodes) { + if (CollectionUtils.isEmpty(msgTemplateCodes)) { + log.info("msgTemplateCodes is empty."); + return Collections.emptyList(); + } + List msgBaseTemplates = messageBaseTemplateDao.lambdaQuery() + .in(MessageBaseTemplate::getCode, msgTemplateCodes) + .eq(MessageBaseTemplate::getIsDelete, 0) + .list(); + if (Objects.isNull(msgBaseTemplates)) { + log.info("not find the [{}] templates.", msgTemplateCodes); + return Collections.emptyList(); + } + Map> templateRouterMap = messageTemplateRouterService + .groupByTemplateCode(msgTemplateCodes); + return msgBaseTemplates.stream() + .map(e -> MessageTemplateDTO.from(e, templateRouterMap.getOrDefault(e.getCode(), Collections.emptyList()))) + .collect(Collectors.toList()); + } + + private MessageBaseTemplate convert(MessageTemplateCreateParam param) { + MessageBaseTemplate template = BeanConverter.convert(param, MessageBaseTemplate.class); + template.setName(param.getTemplateName()); + template.setCode(param.getTemplateCode()); + template.setCreatorId(param.getOperatorId()); + template.setUpdaterId(param.getOperatorId()); + return template; + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateRouterServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateRouterServiceImpl.java new file mode 100644 index 00000000..8a0ca09d --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateRouterServiceImpl.java @@ -0,0 +1,64 @@ +package cn.axzo.msg.center.message.service.impl; + +import cn.axzo.msg.center.dal.MessageTemplateRouterDao; +import cn.axzo.msg.center.domain.entity.MessageTemplateRouter; +import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO; +import cn.axzo.msg.center.message.service.MessageTemplateRouterService; +import com.google.common.collect.Lists; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/28 + * @version 1.0 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MessageTemplateRouterServiceImpl implements MessageTemplateRouterService { + + private final MessageTemplateRouterDao messageTemplateRouterDao; + + @Override + public List queryByTemplateCode(String templateCode) { + if (StringUtils.isBlank(templateCode)) { + log.warn("the template code is blank."); + return Collections.emptyList(); + } + return messageTemplateRouterDao.listByTemplateCode(Lists.newArrayList(templateCode)).stream() + .map(RawMessageRouterDTO::from) + .collect(Collectors.toList()); + } + + @Override + public void batchInsert(List routers) { + if (CollectionUtils.isEmpty(routers)) { + return; + } + List messageTemplateRouters = routers.stream() + .map(RawMessageRouterDTO::toMessageTemplateRouter) + .collect(Collectors.toList()); + messageTemplateRouterDao.saveBatch(messageTemplateRouters); + } + + @Override + public Map> groupByTemplateCode(List templateCodes) { + if (CollectionUtils.isEmpty(templateCodes)) { + return Collections.emptyMap(); + } + return messageTemplateRouterDao.listByTemplateCode(templateCodes).stream() + .map(RawMessageRouterDTO::from) + .collect(Collectors.groupingBy(RawMessageRouterDTO::getTemplateCode)); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/PendingMessageNewServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/PendingMessageNewServiceImpl.java new file mode 100644 index 00000000..079a52d6 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/PendingMessageNewServiceImpl.java @@ -0,0 +1,315 @@ +package cn.axzo.msg.center.message.service.impl; + +import cn.axzo.core.utils.converter.BeanConverter; +import cn.axzo.msg.center.common.enums.TableIsDeleteEnum; +import cn.axzo.msg.center.common.exception.ServiceException; +import cn.axzo.msg.center.common.utils.PlaceholderResolver; +import cn.axzo.msg.center.dal.PendingMessageRecordDao; +import cn.axzo.msg.center.domain.entity.PendingMessageRecord; +import cn.axzo.msg.center.message.domain.dto.MessageGroupNodeDTO; +import cn.axzo.msg.center.message.domain.dto.MessageTemplateDTO; +import cn.axzo.msg.center.message.domain.dto.PendingMessageDTO; +import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO; +import cn.axzo.msg.center.message.domain.param.MessageGroupNodeStatisticParam; +import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam; +import cn.axzo.msg.center.message.service.MessageGroupService; +import cn.axzo.msg.center.message.service.MessageTemplateGroupService; +import cn.axzo.msg.center.message.service.MessageTemplateNewService; +import cn.axzo.msg.center.message.service.PendingMessageNewService; +import cn.axzo.msg.center.service.dto.IdentityDTO; +import cn.axzo.msg.center.service.dto.MessageRouterDTO; +import cn.axzo.msg.center.service.dto.PersonDTO; +import cn.axzo.msg.center.service.dto.QueryOrderByDTO; +import cn.axzo.msg.center.service.enums.IdentityTypeEnum; +import cn.axzo.msg.center.service.enums.OrganizationTypeEnum; +import cn.axzo.msg.center.service.enums.PendingMessageRoleCategoryEnum; +import cn.axzo.msg.center.service.enums.PendingMessageStateEnum; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import cn.axzo.msg.center.service.pending.request.PendingMessagePageRequest; +import cn.axzo.msg.center.service.pending.response.PendingMessageResponse; +import cn.axzo.msg.center.utils.MessageRouterUtil; +import cn.axzo.msg.center.utils.OrderFieldParseUtil; +import cn.axzo.msg.center.utils.UUIDUtil; +import cn.azxo.framework.common.model.Page; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; +import com.google.common.collect.Lists; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Stack; +import java.util.stream.Collectors; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/28 + * @version 1.0 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class PendingMessageNewServiceImpl implements PendingMessageNewService { + + private final MessageGroupService messageGroupService; + private final PendingMessageRecordDao pendingMessageRecordDao; + private final MessageTemplateNewService messageTemplateNewService; + private final MessageTemplateGroupService messageTemplateGroupService; + + @Override + public List groupStatistic(MessageGroupNodeStatisticParam param) { + return param.getGroupNodeCodes().stream() + .flatMap(e -> statistic(e, param).stream()) + .collect(Collectors.toList()); + } + + @Override + public Page pageQuery(PendingMessagePageRequest request) { + PersonDTO operator = PersonDTO.from(request.getPersonId(), request.getIdentityId(), request.getIdentityType()); + LambdaQueryChainWrapper query = pendingMessageRecordDao.lambdaQuery() + .eq(Objects.nonNull(request.getMsgState()), PendingMessageRecord::getState, request.getMsgState()) + .like(StringUtils.isNotBlank(request.getTitle()), PendingMessageRecord::getTitle, request.getTitle()) + .eq(PendingMessageRecord::getIsDelete, 0); + // 构建人维度的查询条件 + buildPersonCondition(query, request.getWithIdentify(), request.getRoleCategory(), operator); + // 模板的分类,对代办进行分组过滤 + if (StringUtils.isNotBlank(request.getGroupNodeCode())) { + List templateCodes = messageTemplateGroupService + .listMessageTemplateCodes(request.getGroupNodeCode()); + query.in(CollectionUtils.isNotEmpty(templateCodes), PendingMessageRecord::getTemplateCode, templateCodes); + } + // 构建排序条件 + buildSortCondition(query, request.getOrderFields()); + + IPage page = request.toPage(); + IPage result = query.page(page); + List templateCodes = result.getRecords().stream().map(PendingMessageRecord::getTemplateCode) + .collect(Collectors.toList()); + List messageTemplates = messageTemplateNewService.listByTemplateCodes(templateCodes); + List responseRecords = result.getRecords().stream() + .map(e -> convert(e, request.getTerminalType(), messageTemplates).toResponse()) + .collect(Collectors.toList()); + return Page.toPage(request.getPage(), request.getPageSize(), result.getTotal(), responseRecords); + } + + @Override + public Optional detail(String msgIdentityCode, TerminalTypeEnum terminalType) { + if (StringUtils.isBlank(msgIdentityCode)) { + log.info("the param of identityCode is blank."); + return Optional.empty(); + } + PendingMessageRecord record = pendingMessageRecordDao.queryByIdentityCode(msgIdentityCode) + .orElse(null); + if (Objects.isNull(record)) { + return Optional.empty(); + } + List messageTemplates = messageTemplateNewService + .listByTemplateCodes(Lists.newArrayList(record.getTemplateCode())); + return pendingMessageRecordDao.queryByIdentityCode(msgIdentityCode) + .map(v -> convert(v, terminalType, messageTemplates)); + } + + @Override + public String push(PendingMessagePushParam param) { + MessageTemplateDTO msgTemplate = messageTemplateNewService + .queryByTemplateCode(param.getTemplateCode()) + .orElseThrow(() -> new ServiceException("not found message template.")); + PendingMessageRecord record = convert(param, msgTemplate); + pendingMessageRecordDao.save(record); + return record.getIdentityCode(); + } + + @Override + public Boolean complete(String msgIdentityCode) { + if (StringUtils.isBlank(msgIdentityCode)) { + log.warn("the message identity code is blank."); + return false; + } + log.info("the [{}] record is updated complete.", msgIdentityCode); + return pendingMessageRecordDao.lambdaUpdate() + .set(PendingMessageRecord::getState, PendingMessageStateEnum.COMPLETED) + .eq(PendingMessageRecord::getIdentityCode, msgIdentityCode) + .eq(PendingMessageRecord::getState, PendingMessageStateEnum.HAS_BEEN_SENT) + .eq(PendingMessageRecord::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .update(); + } + + @Override + public Boolean revoke(String msgIdentityCode) { + if (StringUtils.isBlank(msgIdentityCode)) { + log.warn("the message identity code is blank."); + return false; + } + log.info("the [{}] record is updated retract.", msgIdentityCode); + return pendingMessageRecordDao.lambdaUpdate() + .set(PendingMessageRecord::getState, PendingMessageStateEnum.RETRACT) + .eq(PendingMessageRecord::getIdentityCode, msgIdentityCode) + .eq(PendingMessageRecord::getState, PendingMessageStateEnum.HAS_BEEN_SENT) + .eq(PendingMessageRecord::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .update(); + } + + private PendingMessageDTO convert(PendingMessageRecord pendingMessageRecord, TerminalTypeEnum terminalType, + List messageTemplates) { + PendingMessageDTO pendingMessage = PendingMessageDTO.from(pendingMessageRecord); + // 对应模板的路由列表 + List rawRouters = messageTemplates.stream() + .filter(e -> Objects.equals(e.getCode(), pendingMessageRecord.getTemplateCode())) + .findFirst() + .map(MessageTemplateDTO::getRouters) + .orElseGet(Collections::emptyList); + rawRouters = MessageRouterUtil.selectRouter(rawRouters, terminalType); + List routers = rawRouters.stream().map(e -> { + MessageRouterDTO router = BeanConverter.convert(e, MessageRouterDTO.class); + // 视情况替换原始URL中的参数变量 + MessageRouterUtil.parseRouteUrl(router, pendingMessageRecord.getRouterParams()); + return router; + }).collect(Collectors.toList()); + pendingMessage.setRouters(routers); + // 获取模板卡片信息 + String cardContent = messageTemplates.stream() + .filter(e -> Objects.equals(e.getCode(), pendingMessageRecord.getTemplateCode())) + .findFirst() + .map(MessageTemplateDTO::getCardContent) + .orElse(null); + if (StringUtils.isNotBlank(cardContent) && StringUtils.isNotBlank(pendingMessageRecord.getRouterParams())) { + cardContent = PlaceholderResolver.getDefaultResolver() + .resolveByMap(cardContent, JSON.parseObject(pendingMessageRecord.getRouterParams())); + } + pendingMessage.setCardContent(cardContent); + return pendingMessage; + } + + private List statistic(String rootNodeCode, MessageGroupNodeStatisticParam param) { + MessageGroupNodeDTO groupNode = messageGroupService.queryByNodeCode(rootNodeCode) + .orElseThrow(() -> new ServiceException("groupNodeCode is invalid.")); + MessageGroupNodeDTO root = groupNode; + Stack stack = new Stack<>(); + stack.push(groupNode); + List children; + while (!stack.isEmpty()) { + // TODO: [cold_blade] [P3] 优化树形分类结点的统计效率 + groupNode = stack.pop(); + statistic(groupNode, param); + children = messageGroupService.listChildren(groupNode.getNodeCode()); + groupNode.setChildren(children); + children.forEach(stack::push); + } + // 外部传的是根节点,但是前端希望只返回根节点的字节的 + return root.getChildren(); + } + + private void statistic(MessageGroupNodeDTO groupNode, MessageGroupNodeStatisticParam param) { + List templateCodes = messageTemplateGroupService.listMessageTemplateCodes(groupNode.getNodeCode()); + if (CollectionUtils.isEmpty(templateCodes)) { + groupNode.setPendingCount(0); + return; + } + LambdaQueryChainWrapper query = pendingMessageRecordDao.lambdaQuery() + .in(PendingMessageRecord::getTemplateCode, templateCodes) + .like(StringUtils.isNotBlank(param.getTitle()), PendingMessageRecord::getTitle, param.getTitle()) + .eq(Objects.nonNull(param.getMsgState()), PendingMessageRecord::getState, param.getMsgState()) + .eq(PendingMessageRecord::getIsDelete, 0); + buildPersonCondition(query, param.getWithIdentify(), param.getRoleCategory(), param.getOperator()); + groupNode.setPendingCount(query.count()); + } + + private void buildPersonCondition(LambdaQueryChainWrapper query, Boolean withIdentify, + PendingMessageRoleCategoryEnum roleCategory, PersonDTO operator) { + IdentityDTO identity = null; + if (Objects.equals(withIdentify, true)) { + // 代办需要对身份进行隔离 + identity = operator.getIdentity(); + } + SFunction personIdFunc; + SFunction identityIdFunc; + SFunction identityTypeFunc; + if (Objects.equals(PendingMessageRoleCategoryEnum.PROMOTER, roleCategory)) { + // 代办发起者查询条件 + personIdFunc = PendingMessageRecord::getPromoterPersonId; + identityIdFunc = PendingMessageRecord::getPromoterId; + identityTypeFunc = PendingMessageRecord::getPromoterType; + } else { + // 代办执行者查询条件 + personIdFunc = PendingMessageRecord::getExecutorPersonId; + identityIdFunc = PendingMessageRecord::getExecutorId; + identityTypeFunc = PendingMessageRecord::getExecutorType; + } + query.eq(personIdFunc, operator.getId()); + if (Objects.nonNull(identity) && identity.isValid()) { + query.eq(identityIdFunc, identity.getId()); + query.eq(identityTypeFunc, identity.getType()); + } + } + + private void buildSortCondition(LambdaQueryChainWrapper query, + Collection orderFields) { + if (CollectionUtils.isEmpty(orderFields)) { + return; + } + orderFields.stream() + .filter(e -> OrderFieldParseUtil.containsPendingMessageRecordOrderField(e.getOrderField())) + .forEach(e -> { + if (e.getIsAsc()) { + query.orderByAsc(OrderFieldParseUtil.parsePendingMessageRecordOrderField(e.getOrderField())); + } else { + query.orderByDesc(OrderFieldParseUtil.parsePendingMessageRecordOrderField(e.getOrderField())); + } + }); + } + + private PendingMessageRecord convert(PendingMessagePushParam param, MessageTemplateDTO msgTemplate) { + PendingMessageRecord record = new PendingMessageRecord(); + record.setIdentityCode(UUIDUtil.uuidString()); + record.setState(PendingMessageStateEnum.HAS_BEEN_SENT); + // 构建代办记录的人维度的相关信息 + buildPersonInfo(record, param.getPromoter(), param.getExecutor()); + // 构建模板信息 + buildTemplateInfo(record, msgTemplate, param.getRouterParams()); + // 构建代办所属企业/项目等相关信息 + record.setOrgType(Objects.isNull(param.getOrgType()) ? OrganizationTypeEnum.UNKNOWN : param.getOrgType()); + record.setOrgId(param.getOrgId()); + record.setOrgName(param.getOrgName()); + // 构建业务类信息 + record.setBizCode(param.getBizCode()); + record.setSubBizCode(param.getSubBizCode()); + record.setBizDesc(param.getBizDesc()); + record.setBizCategory(param.getBizCategory()); + return record; + } + + private void buildPersonInfo(PendingMessageRecord record, PersonDTO promoter, PersonDTO executor) { + record.setPromoterId(promoter.getIdentity().getId()); + record.setPromoterType(promoter.getIdentity().getType()); + record.setPromoterPersonId(promoter.getId()); + record.setExecutorId(executor.getIdentity().getId()); + record.setExecutorType(executor.getIdentity().getType()); + record.setExecutorPersonId(executor.getId()); + } + + private void buildTemplateInfo(PendingMessageRecord record, MessageTemplateDTO msgTemplate, String routeParam) { + String title = msgTemplate.getTitle(); + String content = msgTemplate.getContent(); + if (StringUtils.isNotBlank(routeParam)) { + title = PlaceholderResolver + .getDefaultResolver().resolveByMap(title, JSON.parseObject(routeParam)); + content = PlaceholderResolver + .getDefaultResolver().resolveByMap(content, JSON.parseObject(routeParam)); + } + record.setTitle(title); + record.setContent(content); + record.setTemplateCode(msgTemplate.getCode()); + record.setRouterParams(routeParam); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/utils/DateFormatUtil.java b/inside-notices/src/main/java/cn/axzo/msg/center/utils/DateFormatUtil.java new file mode 100644 index 00000000..1bbe4886 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/utils/DateFormatUtil.java @@ -0,0 +1,33 @@ +package cn.axzo.msg.center.utils; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.Date; +import java.util.Optional; + +/** + * @description + * 日期格式转换工具类 + * + * @author cold_blade + * @date 2023/9/28 + * @version 1.0 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class DateFormatUtil { + + public static LocalDateTime toLocalDateTime(Date date) { + ZoneId zoneId = ZoneId.systemDefault(); + return date.toInstant().atZone(zoneId).toLocalDateTime(); + } + + public static long toTimestamp(LocalDateTime dateTime) { + return Optional.ofNullable(dateTime) + .map(v -> v.atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli()) + .orElse(0L); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/utils/MessageRouterUtil.java b/inside-notices/src/main/java/cn/axzo/msg/center/utils/MessageRouterUtil.java new file mode 100644 index 00000000..1ec2d748 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/utils/MessageRouterUtil.java @@ -0,0 +1,106 @@ +package cn.axzo.msg.center.utils; + +import cn.axzo.msg.center.common.utils.PlaceholderResolver; +import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO; +import cn.axzo.msg.center.service.dto.MessageRouterDTO; +import cn.axzo.msg.center.service.enums.RouterCategoryEnum; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import com.alibaba.fastjson.JSON; +import com.google.common.collect.ImmutableMap; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @description + * 消息路由工具方法 + * + * @author cold_blade + * @date 2023/9/28 + * @version 1.0 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class MessageRouterUtil { + + // 非法路由参数的定义 + private static final String INVALID_ROUTER_PARAM = "null"; + // 当前系统选取路由的优先级策略 + private static final ImmutableMap ROUTER_SELECT_ORDER = + ImmutableMap.builder() + .put(TerminalTypeEnum.WEB_VIEW, 1) + .put(TerminalTypeEnum.MINI_PROGRAM, 2) + .put(TerminalTypeEnum.ANDROID, 3) + .put(TerminalTypeEnum.IOS, 3) + .put(TerminalTypeEnum.WEB, 3) + .put(TerminalTypeEnum.WECHAT_MINI_PROGRAM, 3) + .build(); + + /** + * 根据指定的终端类型选取合适的路由 + * + * @param messageRouters 模板配置的路由列表 + * @param terminalType 指定的终端类型,可为null + * @return 合适的路由 + */ + public static List selectRouter(List messageRouters, + TerminalTypeEnum terminalType) { + if (CollectionUtils.isEmpty(messageRouters)) { + return Collections.emptyList(); + } + return messageRouters.stream() + .filter(e -> Objects.equals(e.getTerminalType(), terminalType)) + .collect(Collectors.toList()); + } + + /** + * 判断路由参数的合法性 + * + * @param routerParam 路由参数 + * @return 合法返回 {@code true} 否则返回 {@code false} + */ + public static boolean isRouterParamValid(String routerParam) { + return StringUtils.isNotEmpty(routerParam) + && !INVALID_ROUTER_PARAM.equals(routerParam); + } + + /** + * 解析模板上配置的路由地址,并将发送消息时的参数替换上去 + * + * @param router 路由信息 + * @param routerParam 路由参数 + */ + public static void parseRouteUrl(MessageRouterDTO router, String routerParam) { + // 路由参数有效且是直接调整页面地址的路由类型 + if (isRouterParamValid(routerParam) + && RouterCategoryEnum.JUMP.equals(router.getCategory())) { + // 替换原始URL中的参数变量 + String routerUrl = PlaceholderResolver + .getDefaultResolver().resolveByMap(router.getUrl(), JSON.parseObject(routerParam)); + router.setUrl(routerUrl); + } + } + + private static Integer compare(RawMessageRouterDTO src, RawMessageRouterDTO tgt) { + if (Objects.isNull(tgt)) { + // NULL 默认优先级最低 + return 1; + } + Integer srcOrder = ROUTER_SELECT_ORDER.get(src.getTerminalType()); + Integer tgtOrder = ROUTER_SELECT_ORDER.get(tgt.getTerminalType()); + if (Objects.isNull(srcOrder)) { + // 新增的类型未指定优先级的话,则默认最低 + return 1; + } + if (Objects.isNull(tgtOrder)) { + // 新增的类型未指定优先级的话,则默认最低 + return -1; + } + return srcOrder.compareTo(tgtOrder); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/utils/OrderFieldParseUtil.java b/inside-notices/src/main/java/cn/axzo/msg/center/utils/OrderFieldParseUtil.java new file mode 100644 index 00000000..972f0dcf --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/utils/OrderFieldParseUtil.java @@ -0,0 +1,32 @@ +package cn.axzo.msg.center.utils; + +import cn.axzo.msg.center.domain.entity.PendingMessageRecord; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.google.common.collect.ImmutableMap; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +/** + * 排序字段的解析管理 + * + * @author cold_blade + * @date 2023/10/7 + * @version 1.0 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class OrderFieldParseUtil { + + private static final ImmutableMap> + PENDING_MESSAGE_RECORD_ORDER_FIELD = ImmutableMap.>builder() + .put("createTimestamp", PendingMessageRecord::getCreateAt) + .put("updateTimestamp", PendingMessageRecord::getUpdateAt) + .build(); + + public static boolean containsPendingMessageRecordOrderField(String orderField) { + return PENDING_MESSAGE_RECORD_ORDER_FIELD.containsKey(orderField); + } + + public static SFunction parsePendingMessageRecordOrderField(String orderField) { + return PENDING_MESSAGE_RECORD_ORDER_FIELD.get(orderField); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/utils/UUIDUtil.java b/inside-notices/src/main/java/cn/axzo/msg/center/utils/UUIDUtil.java new file mode 100644 index 00000000..167ccc52 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/utils/UUIDUtil.java @@ -0,0 +1,26 @@ +package cn.axzo.msg.center.utils; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +/** + * UUID生成器 + * + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class UUIDUtil { + + public static String uuidString() { + String str = UUID.randomUUID().toString(); + return str.replaceAll("-", ""); + } + + public static String uuidRawString() { + return UUID.randomUUID().toString(); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/api/enums/BizTypeEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/api/enums/BizTypeEnum.java index c3d5a146..0b4d5585 100644 --- a/msg-center-api/src/main/java/cn/axzo/msg/center/api/enums/BizTypeEnum.java +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/api/enums/BizTypeEnum.java @@ -5,7 +5,7 @@ import lombok.Getter; import java.util.Arrays; /** - * TODO + * * * @author wangli * @date 2023/5/6 19:11 diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/api/request/MsgReturnParamRes.java b/msg-center-api/src/main/java/cn/axzo/msg/center/api/request/MsgReturnParamRes.java index e3d3a818..e6713d3c 100644 --- a/msg-center-api/src/main/java/cn/axzo/msg/center/api/request/MsgReturnParamRes.java +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/api/request/MsgReturnParamRes.java @@ -6,7 +6,7 @@ import java.io.Serializable; /** * @ClassName MsgReturnParamRes - * @Description TODO + * @Description * @Author zhangran * @Date 2022/3/28 19:12 **/ diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/GroupNodeDTO.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/GroupNodeDTO.java new file mode 100644 index 00000000..256ada15 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/GroupNodeDTO.java @@ -0,0 +1,53 @@ +package cn.axzo.msg.center.service.dto; + +import cn.axzo.msg.center.service.enums.MessageGroupNodeCategoryEnum; +import cn.axzo.msg.center.service.enums.StatusEnum; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Setter +@Getter +public class GroupNodeDTO implements Serializable { + + private static final long serialVersionUID = -5935469947222698608L; + + /** + * 模板分组结点名称 + */ + private String name; + /** + * 模板分组结点名称code + */ + private String code; + /** + * 结点类型 + */ + private MessageGroupNodeCategoryEnum category; + /** + * 父节点 + */ + private String parentCode; + /** + * 是否为叶节点 + */ + private Integer isLeaf; + /** + * 状态 + */ + private StatusEnum status; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/IdentityDTO.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/IdentityDTO.java new file mode 100644 index 00000000..3eb6ec55 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/IdentityDTO.java @@ -0,0 +1,47 @@ +package cn.axzo.msg.center.service.dto; + +import cn.axzo.msg.center.service.enums.IdentityTypeEnum; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Objects; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IdentityDTO implements Serializable { + + private static final long serialVersionUID = 7176145314439312573L; + + /** + * 身份id + */ + private Long id; + /** + * 身份类型 + */ + private IdentityTypeEnum type; + + public boolean isValid() { + return Objects.nonNull(id) && Objects.nonNull(type); + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/MessageRouterDTO.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/MessageRouterDTO.java new file mode 100644 index 00000000..9afba13a --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/MessageRouterDTO.java @@ -0,0 +1,59 @@ +package cn.axzo.msg.center.service.dto; + +import cn.axzo.msg.center.service.enums.RouterCategoryEnum; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MessageRouterDTO implements Serializable { + + private static final long serialVersionUID = 1326971022827041566L; + + /** + * 路由描述 + */ + private String desc; + /** + * 路由分类 + * JUMP: 直接跳转 + * ACTION: 接口调用 + */ + private RouterCategoryEnum category; + /** + * 页面地址 OR API接口地址 + */ + private String url; + /** + * 页面地址所属应用端(如果是API接口地址,请忽略改字段值) + * WEB: web端页面 + * MINI_PROGRAM: 安心筑小程序端页面 + * IOS: 原生IOS端页面 + * ANDROID: 原生Android端页面 + * WEB_VIEW: H5页面 + * WECHAT_MINI_PROGRAM: 微信小程序页面 + */ + private TerminalTypeEnum terminalType; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/PersonDTO.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/PersonDTO.java new file mode 100644 index 00000000..fad40f2d --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/PersonDTO.java @@ -0,0 +1,53 @@ +package cn.axzo.msg.center.service.dto; + +import cn.axzo.msg.center.service.enums.IdentityTypeEnum; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PersonDTO implements Serializable { + + private static final long serialVersionUID = 1231840051925115741L; + + /** + * 自然人id + */ + private Long id; + /** + * 身份信息 + */ + private IdentityDTO identity; + + public static PersonDTO from(Long personId, Long identityId, IdentityTypeEnum identityType) { + IdentityDTO identity = IdentityDTO.builder() + .id(identityId) + .type(identityType) + .build(); + return PersonDTO.builder() + .id(personId) + .identity(identity) + .build(); + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/QueryOrderByDTO.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/QueryOrderByDTO.java new file mode 100644 index 00000000..711d9845 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/dto/QueryOrderByDTO.java @@ -0,0 +1,35 @@ +package cn.axzo.msg.center.service.dto; + +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Setter +@Getter +public class QueryOrderByDTO implements Serializable { + + private static final long serialVersionUID = 4374533352245898714L; + + /** + * 排序字段 + */ + private String orderField; + /** + * 是否为升序排序 + */ + private Boolean isAsc; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/BizCategoryEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/BizCategoryEnum.java new file mode 100644 index 00000000..e3085def --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/BizCategoryEnum.java @@ -0,0 +1,22 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/22 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum BizCategoryEnum { + + FLOW("流程"), OTHER("其它"), + ; + + private final String desc; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/GeneralMessageStateEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/GeneralMessageStateEnum.java new file mode 100644 index 00000000..2bb0a13f --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/GeneralMessageStateEnum.java @@ -0,0 +1,28 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum GeneralMessageStateEnum { + + UNSENT(1, "未发送"), + HAS_BEEN_SENT(2, "已发送"), + RECEIVED(3, "已接收"), + HAVE_READ(4, "已读"), + RETRACT(6, "已撤销"), + DELETED(7, "已删除"), + ; + + private final Integer code; + private final String message; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/IdentityTypeEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/IdentityTypeEnum.java new file mode 100644 index 00000000..d11466e4 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/IdentityTypeEnum.java @@ -0,0 +1,45 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum IdentityTypeEnum { + + /*人员身份类型*/ + NOT_SUPPORT(0, "NOT_SUPPORT", "无效类型"), + WORKER(1, "WORKER", "工人"), + WORKER_LEADER(2, "WORKER_LEADER", "班组长"), + PRACTITIONER(3, "PRACTITIONER", "从业人员"), + REGULATOR(4, "REGULATOR", "监管人员"), + OPERATOR(5, "OPERATOR", "运营人员"), + ; + private final Integer code; + private final String message; + private final String desc; + + /** + * 通过code获取对应的枚举实例 + * + * @param code 身份枚举的编码 + * @return 身份枚举实例 {@code OR} 空 + */ + public static Optional codeOf(Integer code) { + return Arrays.stream(values()) + .filter(e -> Objects.equals(e.code, code)) + .findFirst(); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/MessageCategoryEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/MessageCategoryEnum.java new file mode 100644 index 00000000..b879e335 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/MessageCategoryEnum.java @@ -0,0 +1,23 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum MessageCategoryEnum { + + GENERAL_MESSAGE(1, "普通消息"), + PENDING_MESSAGE(2, "待办消息"); + + private final Integer code; + private final String message; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/MessageGroupNodeCategoryEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/MessageGroupNodeCategoryEnum.java new file mode 100644 index 00000000..0727b216 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/MessageGroupNodeCategoryEnum.java @@ -0,0 +1,27 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum MessageGroupNodeCategoryEnum { + + GENERAL_MESSAGE_CENTER("消息中心"), + GENERAL_MESSAGE_MODULE("消息模块"), + GENERAL_MESSAGE_CATEGORY("消息分类"), + PENDING_MESSAGE_CENTER("待办中心"), + PENDING_MESSAGE_MODULE("待办模块"), + PENDING_MESSAGE_CATEGORY("待办分类"), + ; + + private final String desc; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/OrganizationTypeEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/OrganizationTypeEnum.java new file mode 100644 index 00000000..fb469054 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/OrganizationTypeEnum.java @@ -0,0 +1,23 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum OrganizationTypeEnum { + ENT(2, "企业"), + PROJECT(1, "项目"), + UNKNOWN(0, "未知"); + + private final Integer code; + private final String message; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/PendingMessageRoleCategoryEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/PendingMessageRoleCategoryEnum.java new file mode 100644 index 00000000..1e56a261 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/PendingMessageRoleCategoryEnum.java @@ -0,0 +1,22 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum PendingMessageRoleCategoryEnum { + + PROMOTER("发起者"), EXECUTOR("执行者"), + ; + + private final String desc; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/PendingMessageStateEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/PendingMessageStateEnum.java new file mode 100644 index 00000000..ec90f79d --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/PendingMessageStateEnum.java @@ -0,0 +1,27 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum PendingMessageStateEnum { + + UNSENT(1, "未发送"), + HAS_BEEN_SENT(2, "代办"), + COMPLETED(5, "已办"), + RETRACT(6, "已撤回"), + DELETED(7, "已删除"), + ; + + private final Integer code; + private final String message; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/RouterCategoryEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/RouterCategoryEnum.java new file mode 100644 index 00000000..04a10dcd --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/RouterCategoryEnum.java @@ -0,0 +1,22 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum RouterCategoryEnum { + + JUMP("直接跳转"), + ACTION("接口调用"); + + private final String desc; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/StatusEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/StatusEnum.java new file mode 100644 index 00000000..6d3b6686 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/StatusEnum.java @@ -0,0 +1,22 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum StatusEnum { + + ENABLE("启用"), + DISABLE("禁用"); + + private final String desc; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/TerminalTypeEnum.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/TerminalTypeEnum.java new file mode 100644 index 00000000..1394e4fc --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/enums/TerminalTypeEnum.java @@ -0,0 +1,43 @@ +package cn.axzo.msg.center.service.enums; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum TerminalTypeEnum { + + WEB(1, "web"), + MINI_PROGRAM(2, "mini_program"), + IOS(3, "ios"), + ANDROID(4, "android"), + WEB_VIEW(5, "webview"), + WECHAT_MINI_PROGRAM(6, "wechat mini-program"); + + private final Integer code; + private final String desc; + + public static TerminalTypeEnum descOf(String systemType) { + if (IOS.desc.equals(systemType)) { + return IOS; + } + if (ANDROID.desc.equals(systemType)) { + return ANDROID; + } + if (WECHAT_MINI_PROGRAM.desc.equals(systemType)) { + return WECHAT_MINI_PROGRAM; + } + if (MINI_PROGRAM.desc.equals(systemType)) { + return MINI_PROGRAM; + } + return WEB; + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/client/MessageGroupClient.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/client/MessageGroupClient.java new file mode 100644 index 00000000..611167eb --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/client/MessageGroupClient.java @@ -0,0 +1,53 @@ +package cn.axzo.msg.center.service.group.client; + +import cn.axzo.msg.center.service.group.client.fallback.MessageGroupClientFallback; +import cn.axzo.msg.center.service.group.request.MessageGroupNodeAddRequest; +import cn.axzo.msg.center.service.group.request.MessageGroupNodeUpdateRequest; +import cn.azxo.framework.common.model.CommonResponse; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.validation.Valid; + +/** + * 消息分类管理 + * + * @description + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Component +@FeignClient(value = "msg-center", url = "${server.serviceUrl:http://msg-center:8080}", + fallback = MessageGroupClientFallback.class) +public interface MessageGroupClient { + + /** + * 添加消息分类结点 + * + * @param request 结点相关参数 + */ + @PostMapping(value = "/message/group/node/add", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse addNode(@RequestBody @Valid MessageGroupNodeAddRequest request); + + /** + * 更新结点数据 + * + * @param request 待更新的结点相关数据项 + */ + @PostMapping(value = "/message/group/node/update", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse updateStatus(@RequestBody MessageGroupNodeUpdateRequest request); + + /** + * 删除结点 + * + * @param nodeCode 结点编码 + */ + @PostMapping(value = "/message/group/node/delete", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse deleteNode(@RequestParam("nodeCode") String nodeCode, + @RequestParam("operatorId") Long operatorId); +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/client/fallback/MessageGroupClientFallback.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/client/fallback/MessageGroupClientFallback.java new file mode 100644 index 00000000..9c350661 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/client/fallback/MessageGroupClientFallback.java @@ -0,0 +1,37 @@ +package cn.axzo.msg.center.service.group.client.fallback; + +import cn.axzo.msg.center.service.group.client.MessageGroupClient; +import cn.axzo.msg.center.service.group.request.MessageGroupNodeAddRequest; +import cn.axzo.msg.center.service.group.request.MessageGroupNodeUpdateRequest; +import cn.azxo.framework.common.model.CommonResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Slf4j +@Component +public class MessageGroupClientFallback implements MessageGroupClient { + @Override + public CommonResponse addNode(MessageGroupNodeAddRequest request) { + log.error("fall back while adding message group node. request:{}", request); + return CommonResponse.error("fall back while adding message group node"); + } + + @Override + public CommonResponse updateStatus(MessageGroupNodeUpdateRequest request) { + log.error("fall back while updating message group node. request:{}", request); + return CommonResponse.error("fall back while updating message group node"); + } + + @Override + public CommonResponse deleteNode(String nodeCode, Long operatorId) { + log.error("fall back while deleting message group node. nodeCode:[{}], operatorId:[{}]", nodeCode, operatorId); + return CommonResponse.error("fall back while deleting message group node"); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/request/MessageGroupNodeAddRequest.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/request/MessageGroupNodeAddRequest.java new file mode 100644 index 00000000..852c215b --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/request/MessageGroupNodeAddRequest.java @@ -0,0 +1,58 @@ +package cn.axzo.msg.center.service.group.request; + +import cn.axzo.msg.center.service.enums.MessageGroupNodeCategoryEnum; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Setter +@Getter +public class MessageGroupNodeAddRequest implements Serializable { + + private static final long serialVersionUID = -6296122036443137951L; + + /** + * 操作者的自然人id + */ + @NotNull(message = "operatorId is required") + private Long operatorId; + /** + * 父节点编码 + */ + private String parentNodeCode; + /** + * 待添加结点名称 + */ + @NotEmpty(message = "nodeName is required") + private String nodeName; + /** + * 待添加结点编码 + */ + @NotEmpty(message = "nodeCode is required") + private String nodeCode; + /** + * 待添加结点类型 + */ + @NotNull(message = "category is required") + private MessageGroupNodeCategoryEnum category; + /** + * 待添加结点图标 + */ + private String icon; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/request/MessageGroupNodeUpdateRequest.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/request/MessageGroupNodeUpdateRequest.java new file mode 100644 index 00000000..de903960 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/group/request/MessageGroupNodeUpdateRequest.java @@ -0,0 +1,53 @@ +package cn.axzo.msg.center.service.group.request; + +import cn.axzo.msg.center.service.enums.MessageGroupNodeCategoryEnum; +import cn.axzo.msg.center.service.enums.StatusEnum; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Setter +@Getter +public class MessageGroupNodeUpdateRequest implements Serializable { + + private static final long serialVersionUID = -7719513661519986970L; + + /** + * 操作者的自然人id + */ + @NotNull(message = "operatorId is required") + private Long operatorId; + /** + * 待添加结点编码 + */ + @NotEmpty(message = "nodeCode is required") + private String nodeCode; + /** + * 待添加结点名称 + */ + private String nodeName; + /** + * 结点状态 + */ + private StatusEnum status; + /** + * 待添加结点图标 + */ + private String icon; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/client/PendingMessageClient.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/client/PendingMessageClient.java new file mode 100644 index 00000000..2203d579 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/client/PendingMessageClient.java @@ -0,0 +1,85 @@ +package cn.axzo.msg.center.service.pending.client; + +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import cn.axzo.msg.center.service.pending.client.fallback.PendingMessageClientFallback; +import cn.axzo.msg.center.service.pending.request.MessageGroupNodeStatisticRequest; +import cn.axzo.msg.center.service.pending.request.PendingMessagePageRequest; +import cn.axzo.msg.center.service.pending.request.PendingMessagePushRequest; +import cn.axzo.msg.center.service.pending.response.MessageGroupNodeResponse; +import cn.axzo.msg.center.service.pending.response.PendingMessageResponse; +import cn.azxo.framework.common.model.CommonResponse; +import cn.azxo.framework.common.model.Page; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.validation.Valid; +import java.util.List; + +/** + * 代办消息模块管理 + * + * @description + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Component +@FeignClient(value = "msg-center", url = "${server.serviceUrl:http://msg-center:8080}", + fallback = PendingMessageClientFallback.class) +public interface PendingMessageClient { + + @PostMapping(value = "/pending-message/record/group/statistic", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse> groupStatistic(@RequestBody @Valid + MessageGroupNodeStatisticRequest request); + + /** + * 代办列表分页查询 + * + * @param request 分页查询相关参数 + * @return 代办列表 + */ + @PostMapping(value = "/pending-message/record/page", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse> pageQuery(@RequestBody @Valid PendingMessagePageRequest request); + + /** + * 查询代办详情 + * + * @param msgIdentityCode 消息的唯一标识 + * @param terminalType APP终端类型 + * @return 代办详情 + */ + @PostMapping(value = "/pending-message/record/detail", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse detail(@RequestParam("msgIdentityCode") String msgIdentityCode, + @RequestParam("terminalType") TerminalTypeEnum terminalType); + + /** + * 发送代办 + * + * @param request 代办核心参数 + * @return 代办唯一标识 + */ + @PostMapping(value = "/pending-message/push", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse push(@RequestBody @Valid PendingMessagePushRequest request); + + /** + * 完成代办 + * + * @param msgIdentityCode 代办唯一标识 + * @return 成功返回 {@code true} 失败返回 {@code false} + */ + @PostMapping(value = "/pending-message/complete", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse complete(@RequestParam("msgIdentityCode") String msgIdentityCode); + + /** + * 撤销代办 + * + * @param msgIdentityCode 代办唯一标识 + * @return 成功返回 {@code true} 失败返回 {@code false} + */ + @PostMapping(value = "/pending-message/revoke", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse revoke(@RequestParam("msgIdentityCode") String msgIdentityCode); +} \ No newline at end of file diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/client/fallback/PendingMessageClientFallback.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/client/fallback/PendingMessageClientFallback.java new file mode 100644 index 00000000..07916a64 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/client/fallback/PendingMessageClientFallback.java @@ -0,0 +1,64 @@ +package cn.axzo.msg.center.service.pending.client.fallback; + +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import cn.axzo.msg.center.service.pending.client.PendingMessageClient; +import cn.axzo.msg.center.service.pending.request.MessageGroupNodeStatisticRequest; +import cn.axzo.msg.center.service.pending.request.PendingMessagePageRequest; +import cn.axzo.msg.center.service.pending.request.PendingMessagePushRequest; +import cn.axzo.msg.center.service.pending.response.MessageGroupNodeResponse; +import cn.axzo.msg.center.service.pending.response.PendingMessageResponse; +import cn.azxo.framework.common.model.CommonResponse; +import cn.azxo.framework.common.model.Page; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @description + * client降级处理类 + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Slf4j +@Component +public class PendingMessageClientFallback implements PendingMessageClient { + + @Override + public CommonResponse> groupStatistic(MessageGroupNodeStatisticRequest request) { + log.error("fall back while statistic pending message. req:{}", request); + return CommonResponse.error("fall back while statistic pending message"); + } + + @Override + public CommonResponse> pageQuery(PendingMessagePageRequest request) { + log.error("fall back while page querying pending message. req:{}", request); + return CommonResponse.error("fall back while page querying pending message"); + } + + @Override + public CommonResponse detail(String msgIdentityCode, TerminalTypeEnum terminalType) { + log.error("fall back while querying pending message. msgIdentityCode:[{}], terminalType:[{}]", + msgIdentityCode, terminalType); + return CommonResponse.error("fall back while querying pending message"); + } + + @Override + public CommonResponse push(PendingMessagePushRequest request) { + log.error("fall back while push pending message. request:{}", request); + return CommonResponse.error("fall back while push pending message"); + } + + @Override + public CommonResponse complete(String msgIdentityCode) { + log.error("fall back while completing pending message. msgIdentityCode:[{}]", msgIdentityCode); + return CommonResponse.error("fall back while completing pending message"); + } + + @Override + public CommonResponse revoke(String msgIdentityCode) { + log.error("fall back while revoking pending message. msgIdentityCode:[{}]", msgIdentityCode); + return CommonResponse.error("fall back while revoking pending message"); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/request/MessageGroupNodeStatisticRequest.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/request/MessageGroupNodeStatisticRequest.java new file mode 100644 index 00000000..8cfb6c3c --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/request/MessageGroupNodeStatisticRequest.java @@ -0,0 +1,77 @@ +package cn.axzo.msg.center.service.pending.request; + +import cn.axzo.msg.center.service.enums.IdentityTypeEnum; +import cn.axzo.msg.center.service.enums.PendingMessageRoleCategoryEnum; +import cn.axzo.msg.center.service.enums.PendingMessageStateEnum; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Collection; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Setter +@Getter +public class MessageGroupNodeStatisticRequest implements Serializable { + + private static final long serialVersionUID = 9160942889637654608L; + + /** + * 当前登录账户的自然id(前端不care) + */ + @NotNull(message = "personId is required") + private Long personId; + /** + * 当前登录账户的身份id(前端不care) + */ + private Long identityId; + /** + * 当前登录账户的身份类型(前端不care) + */ + private IdentityTypeEnum identityType; + /** + * 消息的分类结点编码集合 + */ + @NotEmpty(message = "groupNodeCodes is required") + private Collection groupNodeCodes; + /** + * 业务方是否只关注特定身份的消息 + * true: 是 + * false: 否 + */ + private Boolean withIdentify; + /** + * 代办角色 + * PROMOTER: 发起者 + * CREATOR: 创建者 + * EXECUTOR: 执行者 + */ + private PendingMessageRoleCategoryEnum roleCategory; + /** + * 代办消息状态 + * UNSENT: 未发送 + * HAS_BEEN_SENT: 已发送 + * COMPLETED: 已办 + * RETRACT: 已撤回 + * DELETED: 已删除 + */ + private PendingMessageStateEnum msgState; + /** + * 消息标题 + */ + private String title; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/request/PendingMessagePageRequest.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/request/PendingMessagePageRequest.java new file mode 100644 index 00000000..b27a7d6d --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/request/PendingMessagePageRequest.java @@ -0,0 +1,91 @@ +package cn.axzo.msg.center.service.pending.request; + +import cn.axzo.basics.common.page.PageRequest; +import cn.axzo.msg.center.service.dto.QueryOrderByDTO; +import cn.axzo.msg.center.service.enums.IdentityTypeEnum; +import cn.axzo.msg.center.service.enums.PendingMessageRoleCategoryEnum; +import cn.axzo.msg.center.service.enums.PendingMessageStateEnum; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Collection; + +/** + * @description + * 代办记录分页查询参数的数模型 + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Setter +@Getter +public class PendingMessagePageRequest extends PageRequest implements Serializable { + + private static final long serialVersionUID = 7172093131252325437L; + + /** + * APP终端类型(前端不care) + * WEB: web端页面 + * MINI_PROGRAM: 安心筑小程序端页面 + * IOS: 原生IOS端页面 + * ANDROID: 原生Android端页面 + * WEB_VIEW: H5页面 + * WECHAT_MINI_PROGRAM: 微信小程序页面 + */ + private TerminalTypeEnum terminalType; + /** + * 当前登录账户的自然id(前端不care) + */ + @NotNull(message = "personId is required") + private Long personId; + /** + * 当前登录账户的身份id(前端不care) + */ + private Long identityId; + /** + * 当前登录账户的身份类型(前端不care) + */ + private IdentityTypeEnum identityType; + /** + * 业务方是否只关注特定身份的消息 + * true: 是 + * false: 否 + */ + private Boolean withIdentify; + /** + * 代办角色 + * PROMOTER: 发起者 + * EXECUTOR: 执行者 + */ + private PendingMessageRoleCategoryEnum roleCategory; + /** + * 代办消息状态 + * UNSENT: 未发送 + * HAS_BEEN_SENT: 已发送 + * COMPLETED: 已办 + * RETRACT: 已撤回 + * DELETED: 已删除 + */ + private PendingMessageStateEnum msgState; + /** + * 代办消息的分类结点编码 + */ + private String groupNodeCode; + /** + * 消息标题 + */ + private String title; + /** + * 排序字段集合 + */ + private Collection orderFields; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/request/PendingMessagePushRequest.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/request/PendingMessagePushRequest.java new file mode 100644 index 00000000..ab8182c3 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/request/PendingMessagePushRequest.java @@ -0,0 +1,80 @@ +package cn.axzo.msg.center.service.pending.request; + +import cn.axzo.msg.center.service.dto.PersonDTO; +import cn.axzo.msg.center.service.enums.BizCategoryEnum; +import cn.axzo.msg.center.service.enums.OrganizationTypeEnum; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Setter +@Getter +public class PendingMessagePushRequest implements Serializable { + + private static final long serialVersionUID = -4523292375275477706L; + + /** + * 发起者 + */ + @NotNull(message = "promoter is required") + private PersonDTO promoter; + /** + * 执行者 + */ + @NotNull(message = "executor is required") + private PersonDTO executor; + /** + * 模板编码 + */ + @NotBlank(message = "templateCode is required") + private String templateCode; + /** + * 消息所属组织类型 + */ + private OrganizationTypeEnum orgType; + /** + * 消息所属组织Id + */ + private Long orgId; + /** + * 消息所属组织名称 + */ + private String orgName; + /** + * 业务类型 + */ + @NotNull(message = "bizCategory is required") + private BizCategoryEnum bizCategory; + /** + * 关联业务主键 + */ + private String bizCode; + /** + * 流程类代办的流程结点编码 + */ + private String subBizCode; + /** + * 业务描述eg:流程结点描述 + */ + private String bizDesc; + /** + * 路由参数(json string) + */ + private String routerParams; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/response/MessageGroupNodeResponse.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/response/MessageGroupNodeResponse.java new file mode 100644 index 00000000..fe55fd6e --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/response/MessageGroupNodeResponse.java @@ -0,0 +1,60 @@ +package cn.axzo.msg.center.service.pending.response; + +import cn.axzo.basics.common.model.IBaseTree; +import cn.axzo.msg.center.service.enums.MessageGroupNodeCategoryEnum; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Setter +@Getter +public class MessageGroupNodeResponse implements IBaseTree, Serializable { + + private static final long serialVersionUID = 972200410809186003L; + + /** + * 结点类型 + * GENERAL_MESSAGE_CENTER: 消息中心 + * GENERAL_MESSAGE_MODULE: 消息模块 + * GENERAL_MESSAGE_CATEGORY: 消息分类 + * PENDING_MESSAGE_CENTER: 待办中心 + * PENDING_MESSAGE_MODULE: 待办模块 + * PENDING_MESSAGE_CATEGORY: 待办分类 + */ + private MessageGroupNodeCategoryEnum category; + /** + * 结点名称 + */ + private String nodeName; + /** + * 结点编码 + */ + private String nodeCode; + /** + * 父节点编码 + */ + private String parentNodeCode; + /** + * 子节点列表 + */ + private List nodeChildren; + /** + * 结点对应的代办数量 + */ + private Integer pendingCount; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/response/PendingMessageResponse.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/response/PendingMessageResponse.java new file mode 100644 index 00000000..643408cf --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/pending/response/PendingMessageResponse.java @@ -0,0 +1,101 @@ +package cn.axzo.msg.center.service.pending.response; + +import cn.axzo.msg.center.service.dto.IdentityDTO; +import cn.axzo.msg.center.service.dto.MessageRouterDTO; +import cn.axzo.msg.center.service.enums.BizCategoryEnum; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * @description + * 代办消息记录页面展示数模型 + * @author cold_blade + * @date 2023/9/23 + * @version 1.0 + */ +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PendingMessageResponse implements Serializable { + + private static final long serialVersionUID = -4133864010679470398L; + + /** + * 消息的唯一标识 + */ + private String identityCode; + /** + * 消息标题 + */ + private String title; + /** + * 消息内容 + */ + private String content; + /** + * 卡片信息 + */ + private String cardContent; + /** + * 代办发起者自然人id + */ + private Long promoterPersonId; + /** + * 代办发起者身份 + */ + private IdentityDTO promoterIdentity; + /** + * 代办执行者自然人id + */ + private Long executorPersonId; + /** + * 代办执行者身份 + */ + private IdentityDTO executorIdentity; + /** + * 业务编码 + */ + private String bizCode; + /** + * 子业务编码 + */ + private String subBizCode; + /** + * 业务状态描述 + */ + private String bizDesc; + /** + * 业务类型 + */ + private BizCategoryEnum bizCategory; + /** + * 申请时间戳 + */ + private Long createTimestamp; + /** + * 处理时间戳 + */ + private Long updateTimestamp; + /** + * 路由信息,可为空 + */ + private List routers; + /** + * 参数及其对应的值的JSON串 + */ + private String routerParams; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/MessageTemplateClient.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/MessageTemplateClient.java new file mode 100644 index 00000000..325c6d2f --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/MessageTemplateClient.java @@ -0,0 +1,43 @@ +package cn.axzo.msg.center.service.template.client; + +import cn.axzo.msg.center.service.template.client.fallback.MessageTemplateClientFallback; +import cn.axzo.msg.center.service.template.request.MessageTemplateCreateRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateMoveToRequest; +import cn.azxo.framework.common.model.CommonResponse; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import javax.validation.Valid; + +/** + * 消息模板管理 + * + * @description + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Component +@FeignClient(value = "msg-center", url = "${server.serviceUrl:http://msg-center:8080}", + fallback = MessageTemplateClientFallback.class) +public interface MessageTemplateClient { + + /** + * 添加消息模板 + * + * @param request 模板数据模型 + */ + @PostMapping(value = "/message/template/add", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse addTemplate(@RequestBody @Valid MessageTemplateCreateRequest request); + + /** + * 批量消息模板分类迁移 + * + * @param request 待迁移的关联关系id以及目标分类 + */ + @PostMapping(value = "/message/template/group/batch-move", produces = {MediaType.APPLICATION_JSON_VALUE}) + CommonResponse batchMove(@RequestBody @Valid MessageTemplateMoveToRequest request); +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/fallback/MessageTemplateClientFallback.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/fallback/MessageTemplateClientFallback.java new file mode 100644 index 00000000..1b79f7d7 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/fallback/MessageTemplateClientFallback.java @@ -0,0 +1,31 @@ +package cn.axzo.msg.center.service.template.client.fallback; + +import cn.axzo.msg.center.service.template.client.MessageTemplateClient; +import cn.axzo.msg.center.service.template.request.MessageTemplateCreateRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateMoveToRequest; +import cn.azxo.framework.common.model.CommonResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Slf4j +@Component +public class MessageTemplateClientFallback implements MessageTemplateClient { + @Override + public CommonResponse addTemplate(MessageTemplateCreateRequest request) { + log.error("fall back while adding template. request:{}", request); + return CommonResponse.error("fall back while adding template"); + } + + @Override + public CommonResponse batchMove(MessageTemplateMoveToRequest request) { + log.error("fall back while batch moving to target group. request:{}", request); + return CommonResponse.error("fall back while batch moving to target group"); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateCreateRequest.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateCreateRequest.java new file mode 100644 index 00000000..f4cec735 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateCreateRequest.java @@ -0,0 +1,77 @@ +package cn.axzo.msg.center.service.template.request; + +import cn.axzo.msg.center.service.dto.MessageRouterDTO; +import cn.axzo.msg.center.service.enums.MessageCategoryEnum; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Setter +@Getter +public class MessageTemplateCreateRequest implements Serializable { + + private static final long serialVersionUID = -2894419272913799317L; + + /** + * 操作者的自然人id + */ + @NotNull(message = "operatorId is required") + private Long operatorId; + /** + * 模板名称 + */ + @NotBlank(message = "templateName is required") + private String templateName; + /** + * 消息类型 + * GENERAL_MESSAGE: 普通消息 + * PENDING_MESSAGE: 待办消息 + */ + @NotNull(message = "category is required") + private MessageCategoryEnum category; + /** + * 消息分类结点的结点编码列表 + */ + @NotEmpty(message = "msgGroupNodeCodes is required") + private List msgGroupNodeCodes; + /** + * 消息标题 + */ + @NotBlank(message = "msgTitle is required") + private String msgTitle; + /** + * 消息卡片信息 + */ + private String msgCardInfo; + /** + * 消息内容 + */ + @NotBlank(message = "msgContent is required") + private String msgContent; + /** + * 消息图标 + */ + private String msgIcon; + /** + * 路由策略列表 + */ + private List routers; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateMoveToRequest.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateMoveToRequest.java new file mode 100644 index 00000000..c7bee961 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateMoveToRequest.java @@ -0,0 +1,40 @@ +package cn.axzo.msg.center.service.template.request; + +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/26 + * @version 1.0 + */ +@Setter +@Getter +public class MessageTemplateMoveToRequest implements Serializable { + + private static final long serialVersionUID = 6484726175219602690L; + + /** + * 操作者的自然人id + */ + private Long operatorId; + /** + * 模板与分类的关联关系的id列表 + */ + private List templateGroupRelationIds; + /** + * 迁移的目标分类结点编码 + */ + private String targetGroupNodeCode; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IEnum.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IEnum.java index 5cfefbe0..e115d593 100644 --- a/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IEnum.java +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IEnum.java @@ -3,7 +3,7 @@ package cn.axzo.msg.center.common.enums; /** * 项目名称:pudge * 类 名 称:AbstractEnum - * 类 描 述:TODO + * 类 描 述: * 创建时间:2022/7/14 12:26 * 创 建 人:xuyaozuo */ diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/OuType.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/OuType.java index b5fd0c9c..3c7a58d8 100644 --- a/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/OuType.java +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/OuType.java @@ -8,7 +8,7 @@ import lombok.RequiredArgsConstructor; /** * 项目名称:profiles * 类 名 称:OuType - * 类 描 述:TODO + * 类 描 述: * 创建时间:2022/5/13 14:41 * 创 建 人:xuyaozuo */ diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageBaseTemplateDao.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageBaseTemplateDao.java new file mode 100644 index 00000000..dc21f689 --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageBaseTemplateDao.java @@ -0,0 +1,18 @@ +package cn.axzo.msg.center.dal; + +import cn.axzo.msg.center.dal.mapper.MessageBaseTemplateMapper; +import cn.axzo.msg.center.domain.entity.MessageBaseTemplate; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @description + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@Slf4j +@Component +public class MessageBaseTemplateDao extends ServiceImpl { +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageGroupNodeDao.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageGroupNodeDao.java new file mode 100644 index 00000000..cfced37a --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageGroupNodeDao.java @@ -0,0 +1,17 @@ +package cn.axzo.msg.center.dal; + +import cn.axzo.msg.center.dal.mapper.MessageGroupNodeMapper; +import cn.axzo.msg.center.domain.entity.MessageGroupNode; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author cold_blade + * @date 2023/10/6 + * @version 1.0 + */ +@Slf4j +@Component +public class MessageGroupNodeDao extends ServiceImpl { +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageTemplateGroupDao.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageTemplateGroupDao.java new file mode 100644 index 00000000..fa93940f --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageTemplateGroupDao.java @@ -0,0 +1,17 @@ +package cn.axzo.msg.center.dal; + +import cn.axzo.msg.center.dal.mapper.MessageTemplateGroupMapper; +import cn.axzo.msg.center.domain.entity.MessageTemplateGroup; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author cold_blade + * @date 2023/10/5 + * @version 1.0 + */ +@Slf4j +@Component +public class MessageTemplateGroupDao extends ServiceImpl { +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageTemplateRouterDao.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageTemplateRouterDao.java new file mode 100644 index 00000000..ac1867f8 --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/MessageTemplateRouterDao.java @@ -0,0 +1,39 @@ +package cn.axzo.msg.center.dal; + +import cn.axzo.msg.center.dal.mapper.MessageTemplateRouterMapper; +import cn.axzo.msg.center.domain.entity.MessageTemplateRouter; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; + +/** + * @description + * + * @author cold_blade + * @date 2023/9/28 + * @version 1.0 + */ +@Slf4j +@Component +public class MessageTemplateRouterDao extends ServiceImpl { + + /** + * 通过模板编码获取对应的路由列表 + * + * @param templateCodes 模板编码列表 + * @return 路由列表 + */ + public List listByTemplateCode(List templateCodes) { + if (CollectionUtils.isEmpty(templateCodes)) { + return Collections.emptyList(); + } + return lambdaQuery() + .in(MessageTemplateRouter::getTemplateCode, templateCodes) + .eq(MessageTemplateRouter::getIsDelete, 0) + .list(); + } +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/PendingMessageRecordDao.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/PendingMessageRecordDao.java new file mode 100644 index 00000000..de4a3053 --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/PendingMessageRecordDao.java @@ -0,0 +1,38 @@ +package cn.axzo.msg.center.dal; + +import cn.axzo.msg.center.dal.mapper.PendingMessageRecordMapper; +import cn.axzo.msg.center.domain.entity.PendingMessageRecord; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +/** + * @description + * @author cold_blade + * @date 2023/9/28 + * @version 1.0 + */ +@Slf4j +@Component +public class PendingMessageRecordDao extends ServiceImpl { + + /** + * 通过消息唯一标识查询对应的消息记录 + * + * @param msgIdentityCode 消息唯一标识 + * @return 消息记录 + */ + public Optional queryByIdentityCode(String msgIdentityCode) { + if (StringUtils.isBlank(msgIdentityCode)) { + return Optional.empty(); + } + PendingMessageRecord record = lambdaQuery() + .eq(PendingMessageRecord::getIdentityCode, msgIdentityCode) + .eq(PendingMessageRecord::getIsDelete, 0) + .one(); + return Optional.ofNullable(record); + } +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/GeneralMessageRecordMapper.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/GeneralMessageRecordMapper.java new file mode 100644 index 00000000..0fa04068 --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/GeneralMessageRecordMapper.java @@ -0,0 +1,14 @@ +package cn.axzo.msg.center.dal.mapper; + +import cn.axzo.msg.center.domain.entity.GeneralMessageRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @description + * 普通消息记录表Mapper + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +public interface GeneralMessageRecordMapper extends BaseMapper { +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageBaseTemplateMapper.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageBaseTemplateMapper.java new file mode 100644 index 00000000..5937e5bb --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageBaseTemplateMapper.java @@ -0,0 +1,16 @@ +package cn.axzo.msg.center.dal.mapper; + +import cn.axzo.msg.center.domain.entity.MessageBaseTemplate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * @description + * 消息基础模板Mapper + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Mapper +public interface MessageBaseTemplateMapper extends BaseMapper { +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageGroupNodeMapper.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageGroupNodeMapper.java new file mode 100644 index 00000000..c02a23d7 --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageGroupNodeMapper.java @@ -0,0 +1,14 @@ +package cn.axzo.msg.center.dal.mapper; + +import cn.axzo.msg.center.domain.entity.MessageGroupNode; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @description + * 消息分组结点Mapper + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +public interface MessageGroupNodeMapper extends BaseMapper { +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageTemplateGroupMapper.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageTemplateGroupMapper.java new file mode 100644 index 00000000..b01ef351 --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageTemplateGroupMapper.java @@ -0,0 +1,14 @@ +package cn.axzo.msg.center.dal.mapper; + +import cn.axzo.msg.center.domain.entity.MessageTemplateGroup; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @description + * 消息模板关联分类Mapper + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +public interface MessageTemplateGroupMapper extends BaseMapper { +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageTemplateRouterMapper.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageTemplateRouterMapper.java new file mode 100644 index 00000000..da05d77d --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/MessageTemplateRouterMapper.java @@ -0,0 +1,14 @@ +package cn.axzo.msg.center.dal.mapper; + +import cn.axzo.msg.center.domain.entity.MessageTemplateRouter; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @description + * 消息模板路由Mapper + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +public interface MessageTemplateRouterMapper extends BaseMapper { +} diff --git a/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/PendingMessageRecordMapper.java b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/PendingMessageRecordMapper.java new file mode 100644 index 00000000..54d10b5c --- /dev/null +++ b/msg-center-dal/src/main/java/cn/axzo/msg/center/dal/mapper/PendingMessageRecordMapper.java @@ -0,0 +1,14 @@ +package cn.axzo.msg.center.dal.mapper; + +import cn.axzo.msg.center.domain.entity.PendingMessageRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @description + * 待办消息记录Mapper + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +public interface PendingMessageRecordMapper extends BaseMapper { +} diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/GeneralMessageRecord.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/GeneralMessageRecord.java new file mode 100644 index 00000000..dd744f9e --- /dev/null +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/GeneralMessageRecord.java @@ -0,0 +1,93 @@ +package cn.axzo.msg.center.domain.entity; + +import cn.axzo.msg.center.domain.persistence.BaseEntity; +import cn.axzo.msg.center.service.enums.GeneralMessageStateEnum; +import cn.axzo.msg.center.service.enums.IdentityTypeEnum; +import cn.axzo.msg.center.service.enums.OrganizationTypeEnum; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * 普通消息记录表数据模型 + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Setter +@Getter +@TableName("general_message_record") +public class GeneralMessageRecord extends BaseEntity implements Serializable { + + private static final long serialVersionUID = -1271402884501451185L; + + /** + * 发送者ID + */ + private Long senderId; + /** + * 接收者ID + */ + private Long receiverId; + /** + * 接收者类型 + */ + private IdentityTypeEnum receiverType; + /** + * 自然人 ID + */ + private Long personId; + /** + * 模板编码 + */ + private String templateCode; + /** + * 消息标题 + */ + private String title; + /** + * 消息内容 + */ + private String content; + /** + * 消息所属组织类型 + */ + private OrganizationTypeEnum orgType; + /** + * 消息所属组织Id + */ + private Long orgId; + /** + * 消息所属组织名称 + */ + private String orgName; + /** + * 消息状态 + */ + private GeneralMessageStateEnum state; + /** + * 关联业务主键 + */ + private String bizCode; + /** + * 路由参数(留存) + */ + private String routerParams; + /** + * 重试次数 + */ + private Integer retryCount; + /** + * 最终失败原因 + */ + private String failCause; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageBaseTemplate.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageBaseTemplate.java new file mode 100644 index 00000000..b652f869 --- /dev/null +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageBaseTemplate.java @@ -0,0 +1,67 @@ +package cn.axzo.msg.center.domain.entity; + +import cn.axzo.msg.center.domain.persistence.BaseEntity; +import cn.axzo.msg.center.service.enums.MessageCategoryEnum; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * 消息基础模板数据模型 + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Setter +@Getter +@TableName("message_base_template") +public class MessageBaseTemplate extends BaseEntity implements Serializable { + + private static final long serialVersionUID = -880409106378455813L; + + /** + * 模板名称 + */ + private String name; + /** + * 系统自动生成的模板code + */ + private String code; + /** + * 所属消息类型 + */ + private MessageCategoryEnum msgCategory; + /** + * 模板标题 + */ + private String title; + /** + * 模板类容 + */ + private String content; + /** + * 卡片信息,json字串 + */ + private String cardContent; + /** + * 模板icon + */ + private String icon; + /** + * 创建者自然人id + */ + private Long creatorId; + /** + * 更新者自然人id + */ + private Long updaterId; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageGroupNode.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageGroupNode.java new file mode 100644 index 00000000..75509df6 --- /dev/null +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageGroupNode.java @@ -0,0 +1,66 @@ +package cn.axzo.msg.center.domain.entity; + +import cn.axzo.msg.center.domain.persistence.BaseEntity; +import cn.axzo.msg.center.service.enums.MessageGroupNodeCategoryEnum; +import cn.axzo.msg.center.service.enums.StatusEnum; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * 消息分组结点表数据模型 + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Setter +@Getter +public class MessageGroupNode extends BaseEntity implements Serializable { + + private static final long serialVersionUID = -4536503805143925884L; + + /** + * 模板分组结点名称 + */ + private String name; + /** + * 模板分组结点code + */ + private String code; + /** + * 分组结点图标 + */ + private String icon; + /** + * 结点类型 + */ + private MessageGroupNodeCategoryEnum category; + /** + * 父节点 + */ + private String parentCode; + /** + * 是否为叶节点 + */ + private Integer isLeaf; + /** + * 状态 + */ + private StatusEnum status; + /** + * 创建者自然人id + */ + private Long creatorId; + /** + * 更新者自然人id + */ + private Long updaterId; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateGroup.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateGroup.java new file mode 100644 index 00000000..766c4f6a --- /dev/null +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateGroup.java @@ -0,0 +1,39 @@ +package cn.axzo.msg.center.domain.entity; + +import cn.axzo.msg.center.domain.persistence.BaseEntity; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * 消息模板关联分类表数据模型 + * + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Setter +@Getter +@TableName("message_template_group") +public class MessageTemplateGroup extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 3902204750978588588L; + + /** + * 模板编码 + */ + private String templateCode; + /** + * 分类路径 + */ + private String path; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateRouter.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateRouter.java new file mode 100644 index 00000000..68215289 --- /dev/null +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateRouter.java @@ -0,0 +1,52 @@ +package cn.axzo.msg.center.domain.entity; + +import cn.axzo.msg.center.domain.persistence.BaseEntity; +import cn.axzo.msg.center.service.enums.RouterCategoryEnum; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * 消息模板路由表数据模型 + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Setter +@Getter +@TableName("message_template_router") +public class MessageTemplateRouter extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 6549664208396593182L; + + /** + * 路由显示名称 + */ + private String name; + /** + * 模板code + */ + private String templateCode; + /** + * 路由类型 + */ + private RouterCategoryEnum category; + /** + * 路由的终端类型 + */ + private TerminalTypeEnum terminalType; + /** + * 路由地址 + */ + private String url; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/PendingMessageRecord.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/PendingMessageRecord.java new file mode 100644 index 00000000..e519ed29 --- /dev/null +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/PendingMessageRecord.java @@ -0,0 +1,118 @@ +package cn.axzo.msg.center.domain.entity; + +import cn.axzo.msg.center.domain.persistence.BaseEntity; +import cn.axzo.msg.center.service.enums.BizCategoryEnum; +import cn.axzo.msg.center.service.enums.IdentityTypeEnum; +import cn.axzo.msg.center.service.enums.OrganizationTypeEnum; +import cn.axzo.msg.center.service.enums.PendingMessageStateEnum; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @description + * 待办消息记录表数据模型 + * @author cold_blade + * @date 2023/9/20 + * @version 1.0 + */ +@Setter +@Getter +@TableName("pending_message_record") +public class PendingMessageRecord extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 2184329278851311992L; + + /** + * 消息的唯一标识 + */ + private String identityCode; + /** + * 发起者ID + */ + private Long promoterId; + /** + * 发起者的自然人ID + */ + private Long promoterPersonId; + /** + * 发起者身份 + */ + private IdentityTypeEnum promoterType; + /** + * 执行者ID + */ + private Long executorId; + /** + * 执行者的自然人ID + */ + private Long executorPersonId; + /** + * 执行者身份 + */ + private IdentityTypeEnum executorType; + /** + * 模板编码 + */ + private String templateCode; + /** + * 消息标题 + */ + private String title; + /** + * 消息内容 + */ + private String content; + /** + * 消息所属组织类型 + */ + private OrganizationTypeEnum orgType; + /** + * 消息所属组织Id + */ + private Long orgId; + /** + * 消息所属组织名称 + */ + private String orgName; + /** + * 待办状态 + */ + private PendingMessageStateEnum state; + /** + * 业务类型 + */ + private BizCategoryEnum bizCategory; + /** + * 关联业务主键 + */ + private String bizCode; + /** + * 流程类代办的流程结点编码 + */ + private String subBizCode; + /** + * 业务描述eg:流程结点描述 + */ + private String bizDesc; + /** + * 路由参数(留存) + */ + private String routerParams; + /** + * 重试次数 + */ + private Integer retryCount; + /** + * 最终失败原因 + */ + private String failCause; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/msg-notices/msg-notices-manager-api/src/main/java/cn/axzo/msg/center/notices/manager/api/SmsSendManager.java b/msg-notices/msg-notices-manager-api/src/main/java/cn/axzo/msg/center/notices/manager/api/SmsSendManager.java index 81d8fa63..56848363 100644 --- a/msg-notices/msg-notices-manager-api/src/main/java/cn/axzo/msg/center/notices/manager/api/SmsSendManager.java +++ b/msg-notices/msg-notices-manager-api/src/main/java/cn/axzo/msg/center/notices/manager/api/SmsSendManager.java @@ -24,7 +24,7 @@ public interface SmsSendManager { /** * 发送批量短信 * - * TODO 多个渠道请求对象响应对象需求统一 + * 多个渠道请求对象响应对象需求统一 * @param requestDto * @return */ diff --git a/msg-notices/msg-notices-manager/src/main/java/cn/axzo/msg/center/notices/manager/LianLuSmsSendManagerImpl.java b/msg-notices/msg-notices-manager/src/main/java/cn/axzo/msg/center/notices/manager/LianLuSmsSendManagerImpl.java index 4dd8a404..4b99e991 100644 --- a/msg-notices/msg-notices-manager/src/main/java/cn/axzo/msg/center/notices/manager/LianLuSmsSendManagerImpl.java +++ b/msg-notices/msg-notices-manager/src/main/java/cn/axzo/msg/center/notices/manager/LianLuSmsSendManagerImpl.java @@ -65,7 +65,6 @@ public class LianLuSmsSendManagerImpl implements SmsSendManager { @Override public BatchMessageSendResponseDto sendBatchMessage(BatchMessageSendRequestDto requestDto) { - // FIXME:[cold_blade] 暂时还未支持有待后续的开发 throw new UnsupportedOperationException(); } diff --git a/msg-notices/msg-notices-manager/src/main/java/cn/axzo/msg/center/notices/manager/SubMailSmsSendManagerImpl.java b/msg-notices/msg-notices-manager/src/main/java/cn/axzo/msg/center/notices/manager/SubMailSmsSendManagerImpl.java index 7a1888ac..3d572bdf 100644 --- a/msg-notices/msg-notices-manager/src/main/java/cn/axzo/msg/center/notices/manager/SubMailSmsSendManagerImpl.java +++ b/msg-notices/msg-notices-manager/src/main/java/cn/axzo/msg/center/notices/manager/SubMailSmsSendManagerImpl.java @@ -51,7 +51,6 @@ public class SubMailSmsSendManagerImpl implements SmsSendManager { @Override public BatchMessageSendResponseDto sendBatchMessage(BatchMessageSendRequestDto requestDto) { - // FIXME:[cold_blade] 暂时还未支持有待后续的开发 throw new UnsupportedOperationException(); } } diff --git a/msg-notices/msg-notices-service/src/main/java/cn/axzo/msg/center/notices/service/impl/TaskServiceImpl.java b/msg-notices/msg-notices-service/src/main/java/cn/axzo/msg/center/notices/service/impl/TaskServiceImpl.java index 75e47658..83b1eab7 100644 --- a/msg-notices/msg-notices-service/src/main/java/cn/axzo/msg/center/notices/service/impl/TaskServiceImpl.java +++ b/msg-notices/msg-notices-service/src/main/java/cn/axzo/msg/center/notices/service/impl/TaskServiceImpl.java @@ -354,7 +354,6 @@ public class TaskServiceImpl implements TaskService { try { batchMessageManger.sendBatchMessageAndHandleReceipt(message); } catch (Exception e) { - // TODO 发送消息到钉钉 LogUtil.error("TaskServiceImpl.realBatchMessageSplitCompensation send channel fail", e); } }); diff --git a/start/src/main/java/cn/axzo/msg/center/MsgCenterApplication.java b/start/src/main/java/cn/axzo/msg/center/MsgCenterApplication.java index bfdabdee..c738a49d 100644 --- a/start/src/main/java/cn/axzo/msg/center/MsgCenterApplication.java +++ b/start/src/main/java/cn/axzo/msg/center/MsgCenterApplication.java @@ -17,7 +17,7 @@ import org.springframework.scheduling.annotation.EnableAsync; * @date 2023/5/30 11:01 */ @Slf4j -@MapperScan(value = "cn.axzo.msg.center.dal") +@MapperScan(value = {"cn.axzo.msg.center.dal"}) @SpringBootApplication(scanBasePackages = {"cn.axzo.msg"}) @EnableFeignClients(basePackages = "cn.axzo.log") /*@EnableAsync*/