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

Feature/req 1309

See merge request universal/infrastructure/backend/msg-center-plat!64
This commit is contained in:
金海洋 2023-10-16 08:08:38 +00:00
commit 725966e261
93 changed files with 4475 additions and 11 deletions

View File

@ -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();
}

View File

@ -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<IMChannelHandler> 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;
}
}
}

View File

@ -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<MessageRouterDTO> 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);
}
}

View File

@ -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<MessageRouterDTO> routers;
/**
* 消息参数 key value
*/
private JSONObject routeParam;
/**
* 消息扩展信息
*/
private JSONObject extInfo;
/**
* 业务编码
*/
private String bizCode;
/**
* 消息如果有音频信息则需要给音频文件名称
*/
private String audioFileName;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,
;
}

View File

@ -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);
}
}

View File

@ -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<IMSendSingleMessageEvent> callback;
/**
* 指定推送渠道
*/
private IMChannelEnum channel;
/**
* APP的版本号
*/
private Integer appVersionCode;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -8,7 +8,7 @@ import java.util.concurrent.atomic.AtomicInteger;
/** /**
* @ClassName SendMessgeEvent * @ClassName SendMessgeEvent
* @Description TODO * @Description
* @Author zhangran * @Author zhangran
* @Date 2022/4/8 11:36 * @Date 2022/4/8 11:36
**/ **/

View File

@ -24,7 +24,7 @@ import javax.annotation.Resource;
/** /**
* @ClassName SendMessageListener * @ClassName SendMessageListener
* @Description TODO * @Description
* @Author zhangran * @Author zhangran
* @Date 2022/4/8 11:44 * @Date 2022/4/8 11:44
**/ **/

View File

@ -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<String> addTemplate(MessageTemplateCreateRequest request) {
MessageTemplateCreateParam param = MessageTemplateCreateParam.from(request);
messageTemplateNewService.createTemplate(param);
return CommonResponse.success(param.getTemplateCode());
}
@Override
public CommonResponse<String> batchMove(MessageTemplateMoveToRequest request) {
// TODO: [cold_blade] [P2] 模板关联的批量移动
return null;
}
}

View File

@ -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<List<MessageGroupNodeResponse>> groupStatistic(MessageGroupNodeStatisticRequest request) {
List<MessageGroupNodeDTO> groupNodes = pendingMessageNewService
.groupStatistic(MessageGroupNodeStatisticParam.from(request));
return CommonResponse.success(groupNodes.stream()
.map(MessageGroupNodeDTO::toResponse)
.collect(Collectors.toList())
);
}
@Override
public CommonResponse<Page<PendingMessageResponse>> pageQuery(PendingMessagePageRequest request) {
return CommonResponse.success(pendingMessageNewService.pageQuery(request));
}
@Override
public CommonResponse<PendingMessageResponse> 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<String> push(PendingMessagePushRequest request) {
return CommonResponse.success(pendingMessageNewService.push(PendingMessagePushParam.from(request)));
}
@Override
public CommonResponse<Boolean> complete(String msgIdentityCode) {
return CommonResponse.success(pendingMessageNewService.complete(msgIdentityCode));
}
@Override
public CommonResponse<Boolean> revoke(String msgIdentityCode) {
return CommonResponse.success(pendingMessageNewService.revoke(msgIdentityCode));
}
}

View File

@ -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<MessageGroupNodeDTO> 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<MessageGroupNodeResponse> children = this.children.stream()
.map(MessageGroupNodeDTO::toResponse).collect(Collectors.toList());
response.setNodeChildren(children);
return response;
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -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<RawMessageRouterDTO> routers;
public static MessageTemplateDTO from(MessageBaseTemplate baseTemplate, List<RawMessageRouterDTO> 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);
}
}

View File

@ -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<MessageRouterDTO> 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);
}
}

View File

@ -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);
}
}

View File

@ -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<String> 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);
}
}

View File

@ -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<MessageRouterDTO> 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);
}
}

View File

@ -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);
}
}

View File

@ -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<MessageGroupNodeDTO> queryByNodeCode(String nodeCode);
/**
* 查询指定结点的字节的信息
*
* @param nodeCode 指定结点编码
* @return 子节点列表信息
*/
List<MessageGroupNodeDTO> listChildren(String nodeCode);
/**
* 模板关联分类
*
* @param templateNode 模板编码
* @param pathList 分类path列表
*/
void templateGroup(String templateNode, Collection<String> pathList);
}

View File

@ -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<String> listMessageTemplateCodes(String groupNodeCode);
}

View File

@ -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<MessageTemplateDTO> queryByTemplateCode(String msgTemplateCode);
/**
* 通过模板编码查询模板信息
*
* @param msgTemplateCodes 模板编码列表
* @return 模板信息
*/
List<MessageTemplateDTO> listByTemplateCodes(List<String> msgTemplateCodes);
}

View File

@ -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<RawMessageRouterDTO> queryByTemplateCode(String templateCode);
/**
* 批量插入模板路由
*
* @param routers 路由列表
*/
void batchInsert(List<RawMessageRouterDTO> routers);
/**
* 根据消息模板编码查询配置的路由列表
*
* @param templateCodes 消息模板编码列表
* @return 路由列表
*/
Map<String, List<RawMessageRouterDTO>> groupByTemplateCode(List<String> templateCodes);
}

View File

@ -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<MessageGroupNodeDTO> groupStatistic(MessageGroupNodeStatisticParam param);
/**
* 代办列表分页查询
*
* @param request 分页查询相关参数
* @return 代办列表
*/
Page<PendingMessageResponse> pageQuery(PendingMessagePageRequest request);
/**
* 查询代办详情
*
* @param msgIdentityCode 消息的唯一标识
* @param terminalType APP终端类型
* @return 代办详情
*/
Optional<PendingMessageDTO> 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);
}

View File

@ -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<MessageGroupNodeDTO> 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<MessageGroupNodeDTO> 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<String> pathList) {
if (StringUtils.isBlank(templateNode)
|| CollectionUtils.isEmpty(pathList)) {
return;
}
List<MessageTemplateGroup> rows = pathList.stream()
.map(e -> {
MessageTemplateGroup group = new MessageTemplateGroup();
group.setTemplateCode(templateNode);
group.setPath(e);
return group;
}).collect(Collectors.toList());
messageTemplateGroupDao.saveBatch(rows);
}
}

View File

@ -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<String> 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());
}
}

View File

@ -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<RawMessageRouterDTO> routers = param.getRouters().stream()
.map(e -> RawMessageRouterDTO.from(e, param.getTemplateCode()))
.collect(Collectors.toList());
messageTemplateRouterService.batchInsert(routers);
}
}
@Override
public Optional<MessageTemplateDTO> 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<RawMessageRouterDTO> routers = messageTemplateRouterService.queryByTemplateCode(msgTemplateCode);
return Optional.of(MessageTemplateDTO.from(msgBaseTemplate, routers));
}
@Override
public List<MessageTemplateDTO> listByTemplateCodes(List<String> msgTemplateCodes) {
if (CollectionUtils.isEmpty(msgTemplateCodes)) {
log.info("msgTemplateCodes is empty.");
return Collections.emptyList();
}
List<MessageBaseTemplate> 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<String, List<RawMessageRouterDTO>> 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;
}
}

View File

@ -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<RawMessageRouterDTO> 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<RawMessageRouterDTO> routers) {
if (CollectionUtils.isEmpty(routers)) {
return;
}
List<MessageTemplateRouter> messageTemplateRouters = routers.stream()
.map(RawMessageRouterDTO::toMessageTemplateRouter)
.collect(Collectors.toList());
messageTemplateRouterDao.saveBatch(messageTemplateRouters);
}
@Override
public Map<String, List<RawMessageRouterDTO>> groupByTemplateCode(List<String> templateCodes) {
if (CollectionUtils.isEmpty(templateCodes)) {
return Collections.emptyMap();
}
return messageTemplateRouterDao.listByTemplateCode(templateCodes).stream()
.map(RawMessageRouterDTO::from)
.collect(Collectors.groupingBy(RawMessageRouterDTO::getTemplateCode));
}
}

View File

@ -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<MessageGroupNodeDTO> groupStatistic(MessageGroupNodeStatisticParam param) {
return param.getGroupNodeCodes().stream()
.flatMap(e -> statistic(e, param).stream())
.collect(Collectors.toList());
}
@Override
public Page<PendingMessageResponse> pageQuery(PendingMessagePageRequest request) {
PersonDTO operator = PersonDTO.from(request.getPersonId(), request.getIdentityId(), request.getIdentityType());
LambdaQueryChainWrapper<PendingMessageRecord> 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<String> templateCodes = messageTemplateGroupService
.listMessageTemplateCodes(request.getGroupNodeCode());
query.in(CollectionUtils.isNotEmpty(templateCodes), PendingMessageRecord::getTemplateCode, templateCodes);
}
// 构建排序条件
buildSortCondition(query, request.getOrderFields());
IPage<PendingMessageRecord> page = request.toPage();
IPage<PendingMessageRecord> result = query.page(page);
List<String> templateCodes = result.getRecords().stream().map(PendingMessageRecord::getTemplateCode)
.collect(Collectors.toList());
List<MessageTemplateDTO> messageTemplates = messageTemplateNewService.listByTemplateCodes(templateCodes);
List<PendingMessageResponse> 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<PendingMessageDTO> 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<MessageTemplateDTO> 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<MessageTemplateDTO> messageTemplates) {
PendingMessageDTO pendingMessage = PendingMessageDTO.from(pendingMessageRecord);
// 对应模板的路由列表
List<RawMessageRouterDTO> rawRouters = messageTemplates.stream()
.filter(e -> Objects.equals(e.getCode(), pendingMessageRecord.getTemplateCode()))
.findFirst()
.map(MessageTemplateDTO::getRouters)
.orElseGet(Collections::emptyList);
rawRouters = MessageRouterUtil.selectRouter(rawRouters, terminalType);
List<MessageRouterDTO> 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<MessageGroupNodeDTO> statistic(String rootNodeCode, MessageGroupNodeStatisticParam param) {
MessageGroupNodeDTO groupNode = messageGroupService.queryByNodeCode(rootNodeCode)
.orElseThrow(() -> new ServiceException("groupNodeCode is invalid."));
MessageGroupNodeDTO root = groupNode;
Stack<MessageGroupNodeDTO> stack = new Stack<>();
stack.push(groupNode);
List<MessageGroupNodeDTO> 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<String> templateCodes = messageTemplateGroupService.listMessageTemplateCodes(groupNode.getNodeCode());
if (CollectionUtils.isEmpty(templateCodes)) {
groupNode.setPendingCount(0);
return;
}
LambdaQueryChainWrapper<PendingMessageRecord> 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<PendingMessageRecord> query, Boolean withIdentify,
PendingMessageRoleCategoryEnum roleCategory, PersonDTO operator) {
IdentityDTO identity = null;
if (Objects.equals(withIdentify, true)) {
// 代办需要对身份进行隔离
identity = operator.getIdentity();
}
SFunction<PendingMessageRecord, Long> personIdFunc;
SFunction<PendingMessageRecord, Long> identityIdFunc;
SFunction<PendingMessageRecord, IdentityTypeEnum> 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<PendingMessageRecord> query,
Collection<QueryOrderByDTO> 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);
}
}

View File

@ -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);
}
}

View File

@ -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<TerminalTypeEnum, Integer> ROUTER_SELECT_ORDER =
ImmutableMap.<TerminalTypeEnum, Integer>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<RawMessageRouterDTO> selectRouter(List<RawMessageRouterDTO> 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);
}
}

View File

@ -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<String, SFunction<PendingMessageRecord, ?>>
PENDING_MESSAGE_RECORD_ORDER_FIELD = ImmutableMap.<String, SFunction<PendingMessageRecord, ?>>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<PendingMessageRecord, ?> parsePendingMessageRecordOrderField(String orderField) {
return PENDING_MESSAGE_RECORD_ORDER_FIELD.get(orderField);
}
}

View File

@ -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();
}
}

View File

@ -5,7 +5,7 @@ import lombok.Getter;
import java.util.Arrays; import java.util.Arrays;
/** /**
* TODO *
* *
* @author wangli * @author wangli
* @date 2023/5/6 19:11 * @date 2023/5/6 19:11

View File

@ -6,7 +6,7 @@ import java.io.Serializable;
/** /**
* @ClassName MsgReturnParamRes * @ClassName MsgReturnParamRes
* @Description TODO * @Description
* @Author zhangran * @Author zhangran
* @Date 2022/3/28 19:12 * @Date 2022/3/28 19:12
**/ **/

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<IdentityTypeEnum> codeOf(Integer code) {
return Arrays.stream(values())
.filter(e -> Objects.equals(e.code, code))
.findFirst();
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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<Void> addNode(@RequestBody @Valid MessageGroupNodeAddRequest request);
/**
* 更新结点数据
*
* @param request 待更新的结点相关数据项
*/
@PostMapping(value = "/message/group/node/update", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<Void> updateStatus(@RequestBody MessageGroupNodeUpdateRequest request);
/**
* 删除结点
*
* @param nodeCode 结点编码
*/
@PostMapping(value = "/message/group/node/delete", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<Void> deleteNode(@RequestParam("nodeCode") String nodeCode,
@RequestParam("operatorId") Long operatorId);
}

View File

@ -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<Void> 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<Void> 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<Void> 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");
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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<List<MessageGroupNodeResponse>> groupStatistic(@RequestBody @Valid
MessageGroupNodeStatisticRequest request);
/**
* 代办列表分页查询
*
* @param request 分页查询相关参数
* @return 代办列表
*/
@PostMapping(value = "/pending-message/record/page", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<Page<PendingMessageResponse>> pageQuery(@RequestBody @Valid PendingMessagePageRequest request);
/**
* 查询代办详情
*
* @param msgIdentityCode 消息的唯一标识
* @param terminalType APP终端类型
* @return 代办详情
*/
@PostMapping(value = "/pending-message/record/detail", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<PendingMessageResponse> detail(@RequestParam("msgIdentityCode") String msgIdentityCode,
@RequestParam("terminalType") TerminalTypeEnum terminalType);
/**
* 发送代办
*
* @param request 代办核心参数
* @return 代办唯一标识
*/
@PostMapping(value = "/pending-message/push", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<String> push(@RequestBody @Valid PendingMessagePushRequest request);
/**
* 完成代办
*
* @param msgIdentityCode 代办唯一标识
* @return 成功返回 {@code true} 失败返回 {@code false}
*/
@PostMapping(value = "/pending-message/complete", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<Boolean> complete(@RequestParam("msgIdentityCode") String msgIdentityCode);
/**
* 撤销代办
*
* @param msgIdentityCode 代办唯一标识
* @return 成功返回 {@code true} 失败返回 {@code false}
*/
@PostMapping(value = "/pending-message/revoke", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<Boolean> revoke(@RequestParam("msgIdentityCode") String msgIdentityCode);
}

View File

@ -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<List<MessageGroupNodeResponse>> 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<Page<PendingMessageResponse>> 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<PendingMessageResponse> 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<String> 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<Boolean> 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<Boolean> revoke(String msgIdentityCode) {
log.error("fall back while revoking pending message. msgIdentityCode:[{}]", msgIdentityCode);
return CommonResponse.error("fall back while revoking pending message");
}
}

View File

@ -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<String> 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);
}
}

View File

@ -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<QueryOrderByDTO> orderFields;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -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);
}
}

View File

@ -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<MessageGroupNodeResponse, String>, 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<MessageGroupNodeResponse> nodeChildren;
/**
* 结点对应的代办数量
*/
private Integer pendingCount;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -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<MessageRouterDTO> routers;
/**
* 参数及其对应的值的JSON串
*/
private String routerParams;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -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<String> addTemplate(@RequestBody @Valid MessageTemplateCreateRequest request);
/**
* 批量消息模板分类迁移
*
* @param request 待迁移的关联关系id以及目标分类
*/
@PostMapping(value = "/message/template/group/batch-move", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<String> batchMove(@RequestBody @Valid MessageTemplateMoveToRequest request);
}

View File

@ -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<String> addTemplate(MessageTemplateCreateRequest request) {
log.error("fall back while adding template. request:{}", request);
return CommonResponse.error("fall back while adding template");
}
@Override
public CommonResponse<String> 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");
}
}

View File

@ -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<String> 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<MessageRouterDTO> routers;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -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<Long> templateGroupRelationIds;
/**
* 迁移的目标分类结点编码
*/
private String targetGroupNodeCode;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -3,7 +3,7 @@ package cn.axzo.msg.center.common.enums;
/** /**
* 项目名称pudge * 项目名称pudge
* AbstractEnum * AbstractEnum
* TODO *
* 创建时间2022/7/14 12:26 * 创建时间2022/7/14 12:26
* xuyaozuo * xuyaozuo
*/ */

View File

@ -8,7 +8,7 @@ import lombok.RequiredArgsConstructor;
/** /**
* 项目名称profiles * 项目名称profiles
* OuType * OuType
* TODO *
* 创建时间2022/5/13 14:41 * 创建时间2022/5/13 14:41
* xuyaozuo * xuyaozuo
*/ */

View File

@ -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<MessageBaseTemplateMapper, MessageBaseTemplate> {
}

View File

@ -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<MessageGroupNodeMapper, MessageGroupNode> {
}

View File

@ -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<MessageTemplateGroupMapper, MessageTemplateGroup> {
}

View File

@ -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<MessageTemplateRouterMapper, MessageTemplateRouter> {
/**
* 通过模板编码获取对应的路由列表
*
* @param templateCodes 模板编码列表
* @return 路由列表
*/
public List<MessageTemplateRouter> listByTemplateCode(List<String> templateCodes) {
if (CollectionUtils.isEmpty(templateCodes)) {
return Collections.emptyList();
}
return lambdaQuery()
.in(MessageTemplateRouter::getTemplateCode, templateCodes)
.eq(MessageTemplateRouter::getIsDelete, 0)
.list();
}
}

View File

@ -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<PendingMessageRecordMapper, PendingMessageRecord> {
/**
* 通过消息唯一标识查询对应的消息记录
*
* @param msgIdentityCode 消息唯一标识
* @return 消息记录
*/
public Optional<PendingMessageRecord> 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);
}
}

View File

@ -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<GeneralMessageRecord> {
}

View File

@ -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<MessageBaseTemplate> {
}

View File

@ -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<MessageGroupNode> {
}

View File

@ -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<MessageTemplateGroup> {
}

View File

@ -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<MessageTemplateRouter> {
}

View File

@ -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<PendingMessageRecord> {
}

View File

@ -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<GeneralMessageRecord> 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);
}
}

View File

@ -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<MessageBaseTemplate> 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);
}
}

View File

@ -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<MessageGroupNode> 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);
}
}

View File

@ -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<MessageTemplateGroup> implements Serializable {
private static final long serialVersionUID = 3902204750978588588L;
/**
* 模板编码
*/
private String templateCode;
/**
* 分类路径
*/
private String path;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -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<MessageTemplateRouter> 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);
}
}

View File

@ -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<PendingMessageRecord> 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);
}
}

View File

@ -24,7 +24,7 @@ public interface SmsSendManager {
/** /**
* 发送批量短信 * 发送批量短信
* *
* TODO 多个渠道请求对象响应对象需求统一 * 多个渠道请求对象响应对象需求统一
* @param requestDto * @param requestDto
* @return * @return
*/ */

View File

@ -65,7 +65,6 @@ public class LianLuSmsSendManagerImpl implements SmsSendManager {
@Override @Override
public BatchMessageSendResponseDto sendBatchMessage(BatchMessageSendRequestDto requestDto) { public BatchMessageSendResponseDto sendBatchMessage(BatchMessageSendRequestDto requestDto) {
// FIXME:[cold_blade] 暂时还未支持有待后续的开发
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -51,7 +51,6 @@ public class SubMailSmsSendManagerImpl implements SmsSendManager {
@Override @Override
public BatchMessageSendResponseDto sendBatchMessage(BatchMessageSendRequestDto requestDto) { public BatchMessageSendResponseDto sendBatchMessage(BatchMessageSendRequestDto requestDto) {
// FIXME:[cold_blade] 暂时还未支持有待后续的开发
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }

View File

@ -354,7 +354,6 @@ public class TaskServiceImpl implements TaskService {
try { try {
batchMessageManger.sendBatchMessageAndHandleReceipt(message); batchMessageManger.sendBatchMessageAndHandleReceipt(message);
} catch (Exception e) { } catch (Exception e) {
// TODO 发送消息到钉钉
LogUtil.error("TaskServiceImpl.realBatchMessageSplitCompensation send channel fail", e); LogUtil.error("TaskServiceImpl.realBatchMessageSplitCompensation send channel fail", e);
} }
}); });

View File

@ -17,7 +17,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
* @date 2023/5/30 11:01 * @date 2023/5/30 11:01
*/ */
@Slf4j @Slf4j
@MapperScan(value = "cn.axzo.msg.center.dal") @MapperScan(value = {"cn.axzo.msg.center.dal"})
@SpringBootApplication(scanBasePackages = {"cn.axzo.msg"}) @SpringBootApplication(scanBasePackages = {"cn.axzo.msg"})
@EnableFeignClients(basePackages = "cn.axzo.log") @EnableFeignClients(basePackages = "cn.axzo.log")
/*@EnableAsync*/ /*@EnableAsync*/