Merge branch 'feature/REQ-1465' of axzsource.com:universal/infrastructure/backend/msg-center-plat into dev
This commit is contained in:
commit
c7d351d784
@ -110,6 +110,11 @@
|
|||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.axzo.pokonyan</groupId>
|
||||||
|
<artifactId>pokonyan</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@ -29,9 +29,8 @@ public class MessageTemplateController implements MessageTemplateClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResponse<String> save(MessageTemplateCreateRequest request) {
|
public CommonResponse<String> save(MessageTemplateCreateRequest request) {
|
||||||
MessageTemplateCreateParam param = MessageTemplateCreateParam.from(request);
|
return CommonResponse.success(
|
||||||
messageTemplateNewService.createTemplate(param);
|
messageTemplateNewService.createTemplate(MessageTemplateCreateParam.from(request)));
|
||||||
return CommonResponse.success(param.getTemplateCode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package cn.axzo.msg.center.message.controller;
|
package cn.axzo.msg.center.message.controller;
|
||||||
|
|
||||||
import cn.axzo.msg.center.message.domain.dto.MessageGroupNodeDTO;
|
import cn.axzo.msg.center.message.domain.dto.MessageGroupNodeStatisticDTO;
|
||||||
import cn.axzo.msg.center.message.domain.dto.PendingMessageDTO;
|
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.MessageGroupNodeStatisticParam;
|
||||||
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
|
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
|
||||||
@ -36,10 +36,10 @@ public class PendingMessageNewController implements PendingMessageClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResponse<List<MessageGroupNodeResponse>> groupStatistic(MessageGroupNodeStatisticRequest request) {
|
public CommonResponse<List<MessageGroupNodeResponse>> groupStatistic(MessageGroupNodeStatisticRequest request) {
|
||||||
List<MessageGroupNodeDTO> groupNodes = pendingMessageNewService
|
List<MessageGroupNodeStatisticDTO> groupNodes = pendingMessageNewService
|
||||||
.groupStatistic(MessageGroupNodeStatisticParam.from(request));
|
.groupStatistic(MessageGroupNodeStatisticParam.from(request));
|
||||||
return CommonResponse.success(groupNodes.stream()
|
return CommonResponse.success(groupNodes.stream()
|
||||||
.map(MessageGroupNodeDTO::toResponse)
|
.map(MessageGroupNodeStatisticDTO::toResponse)
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,58 @@
|
|||||||
|
package cn.axzo.msg.center.message.domain.dto;
|
||||||
|
|
||||||
|
import cn.axzo.msg.center.service.dto.GroupTreeNodeDTO;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cold_blade
|
||||||
|
* @date 2023/10/14
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class GroupTreeNodePathDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -6325338437781927201L;
|
||||||
|
|
||||||
|
private static final String NODE_NAME_PATH_SPLITER = "/";
|
||||||
|
private static final String NODE_CODE_PATH_SPLITER = ":";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结点编码
|
||||||
|
*/
|
||||||
|
private String nodeCode;
|
||||||
|
/**
|
||||||
|
* 结点名称格式的路径
|
||||||
|
*/
|
||||||
|
private String nodeNamePath;
|
||||||
|
/**
|
||||||
|
* 结点编码格式的路径
|
||||||
|
*/
|
||||||
|
private String nodeCodePath;
|
||||||
|
|
||||||
|
public static GroupTreeNodePathDTO of(String nodeCode, Collection<GroupTreeNodeDTO> nodes) {
|
||||||
|
String nodeNamePath = formatPath(GroupTreeNodeDTO::getNodeName, nodes, NODE_NAME_PATH_SPLITER);
|
||||||
|
String nodeCodePath = formatPath(GroupTreeNodeDTO::getNodeCode, nodes, NODE_CODE_PATH_SPLITER);
|
||||||
|
return new GroupTreeNodePathDTO(nodeCode, nodeNamePath, nodeCodePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatPath(Function<GroupTreeNodeDTO, String> pathFunc, Collection<GroupTreeNodeDTO> nodes,
|
||||||
|
String spliter) {
|
||||||
|
return nodes.stream().map(pathFunc).collect(Collectors.joining(spliter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JSON.toJSONString(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,87 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
package cn.axzo.msg.center.message.domain.dto;
|
||||||
|
|
||||||
|
import cn.axzo.basics.common.model.IBaseTree;
|
||||||
|
import cn.axzo.core.utils.converter.BeanConverter;
|
||||||
|
import cn.axzo.msg.center.service.dto.GroupTreeNodeDTO;
|
||||||
|
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 MessageGroupNodeStatisticDTO implements IBaseTree<MessageGroupNodeStatisticDTO, String>, Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 5171436359992401120L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 树结点
|
||||||
|
*/
|
||||||
|
private GroupTreeNodeDTO treeNode;
|
||||||
|
/**
|
||||||
|
* 子节点列表
|
||||||
|
*/
|
||||||
|
private List<MessageGroupNodeStatisticDTO> nodeChildren;
|
||||||
|
/**
|
||||||
|
* 结点对应的代办数量
|
||||||
|
*/
|
||||||
|
private Integer pendingCount;
|
||||||
|
|
||||||
|
public static MessageGroupNodeStatisticDTO of(GroupTreeNodeDTO groupNode) {
|
||||||
|
return MessageGroupNodeStatisticDTO.builder()
|
||||||
|
.treeNode(groupNode)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageGroupNodeResponse toResponse() {
|
||||||
|
MessageGroupNodeResponse response = BeanConverter.convert(this, MessageGroupNodeResponse.class);
|
||||||
|
List<MessageGroupNodeResponse> children = this.nodeChildren.stream()
|
||||||
|
.map(MessageGroupNodeStatisticDTO::toResponse).collect(Collectors.toList());
|
||||||
|
response.setNodeChildren(children);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JSON.toJSONString(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNodeCode() {
|
||||||
|
return treeNode.getNodeCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getParentNodeCode() {
|
||||||
|
return treeNode.getParentNodeCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
package cn.axzo.msg.center.message.domain.param;
|
package cn.axzo.msg.center.message.domain.param;
|
||||||
|
|
||||||
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
|
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
|
||||||
import cn.axzo.msg.center.service.dto.MessageRouterDTO;
|
|
||||||
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
|
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
|
||||||
|
import cn.axzo.msg.center.service.enums.PushTerminalEnum;
|
||||||
import cn.axzo.msg.center.service.template.request.MessageTemplateCreateRequest;
|
import cn.axzo.msg.center.service.template.request.MessageTemplateCreateRequest;
|
||||||
import cn.axzo.msg.center.utils.UUIDUtil;
|
import cn.axzo.msg.center.utils.JSONObjectUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@ -36,9 +36,9 @@ public class MessageTemplateCreateParam implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String templateName;
|
private String templateName;
|
||||||
/**
|
/**
|
||||||
* 系统自动生成的模板code
|
* 消息分类树的叶结点的结点编码列表
|
||||||
*/
|
*/
|
||||||
private String templateCode;
|
private List<String> leafGroupNodes;
|
||||||
/**
|
/**
|
||||||
* 所属消息类型
|
* 所属消息类型
|
||||||
* GENERAL_MESSAGE: 普通消息
|
* GENERAL_MESSAGE: 普通消息
|
||||||
@ -69,18 +69,25 @@ public class MessageTemplateCreateParam implements Serializable {
|
|||||||
* 路由列表
|
* 路由列表
|
||||||
*/
|
*/
|
||||||
private List<MessageRouterButtonDTO> routers;
|
private List<MessageRouterButtonDTO> routers;
|
||||||
|
/**
|
||||||
|
* 推送终端配置
|
||||||
|
* B_ENTERPRISE_APP: B-安心筑企业版
|
||||||
|
* C_WORKER_APP: C-安心筑工人版
|
||||||
|
*/
|
||||||
|
private List<PushTerminalEnum> pushTerminals;
|
||||||
|
|
||||||
public static MessageTemplateCreateParam from(MessageTemplateCreateRequest request) {
|
public static MessageTemplateCreateParam from(MessageTemplateCreateRequest request) {
|
||||||
return MessageTemplateCreateParam.builder()
|
return MessageTemplateCreateParam.builder()
|
||||||
.templateName(request.getTemplateName())
|
.templateName(request.getTemplateName())
|
||||||
.templateCode(UUIDUtil.uuidString())
|
|
||||||
.msgCategory(request.getCategory())
|
.msgCategory(request.getCategory())
|
||||||
|
.leafGroupNodes(request.getLeafGroupNodes())
|
||||||
.title(request.getMsgTitle())
|
.title(request.getMsgTitle())
|
||||||
.content(request.getMsgContent())
|
.content(request.getMsgContent())
|
||||||
.cardContent(request.getMsgCardInfo())
|
.cardContent(JSONObjectUtil.checkAndReturn(request.getMsgCardInfo()))
|
||||||
.icon(request.getMsgIcon())
|
.icon(request.getMsgIcon())
|
||||||
.operatorId(request.getOperatorId())
|
.operatorId(request.getOperatorId())
|
||||||
.routers(request.getRouters())
|
.routers(request.getRouters())
|
||||||
|
.pushTerminals(request.getPushTerminals())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,41 @@
|
|||||||
|
package cn.axzo.msg.center.message.service;
|
||||||
|
|
||||||
|
import cn.axzo.msg.center.service.dto.GroupTreeNodeDTO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息分类结点管理
|
||||||
|
*
|
||||||
|
* @author cold_blade
|
||||||
|
* @date 2023/10/14
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public interface MessageGroupNodeService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分类结点(叶结点)名称的路径
|
||||||
|
*
|
||||||
|
* @param leafGroupNodeCodes 分类结点(叶结点)的编码列表
|
||||||
|
* @return 分类结点(叶结点)名称的路径
|
||||||
|
*/
|
||||||
|
Map<String, String> leafGroupNodeNamePaths(Collection<String> leafGroupNodeCodes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分类结点(叶结点)编码的路径
|
||||||
|
*
|
||||||
|
* @param leafGroupNodeCodes 分类结点(叶结点)的编码列表
|
||||||
|
* @return 分类结点(叶结点)编码的路径
|
||||||
|
*/
|
||||||
|
Map<String, String> leafGroupNodeCodePaths(Collection<String> leafGroupNodeCodes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据结点编码查询结点信息
|
||||||
|
*
|
||||||
|
* @param rootNodeCode 结点编码
|
||||||
|
* @return 结点信息
|
||||||
|
*/
|
||||||
|
Optional<GroupTreeNodeDTO> queryRootNode(String rootNodeCode);
|
||||||
|
}
|
||||||
@ -1,41 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
package cn.axzo.msg.center.message.service;
|
||||||
|
|
||||||
|
import cn.axzo.msg.center.message.domain.dto.GroupTreeNodePathDTO;
|
||||||
|
import cn.axzo.msg.center.service.dto.GroupTreeNodeDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息分类树节点缓存管理
|
||||||
|
*
|
||||||
|
* @author cold_blade
|
||||||
|
* @date 2023/10/14
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public interface MessageGroupTreeNodeCacheService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有有效的分类结点树的根节点
|
||||||
|
*
|
||||||
|
* @return 树根节点列表
|
||||||
|
*/
|
||||||
|
List<GroupTreeNodeDTO> listAllRootNodes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定结点所在的树的根节点
|
||||||
|
*
|
||||||
|
* @param rootNodeCode 结点编码
|
||||||
|
* @return 根节点
|
||||||
|
*/
|
||||||
|
Optional<GroupTreeNodeDTO> queryRootNode(String rootNodeCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据结点编码查询结点信息
|
||||||
|
*
|
||||||
|
* @param groupNodeCode 结点编码
|
||||||
|
* @return 结点信息
|
||||||
|
*/
|
||||||
|
Optional<GroupTreeNodeDTO> queryNode(String groupNodeCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取叶结点对应的树的路径
|
||||||
|
*
|
||||||
|
* @param leafNodeCode 叶结点编码
|
||||||
|
* @return 路径
|
||||||
|
*/
|
||||||
|
Optional<GroupTreeNodePathDTO> queryLeafNodePath(String leafNodeCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新缓存
|
||||||
|
*/
|
||||||
|
void refreshCache();
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.msg.center.message.service;
|
package cn.axzo.msg.center.message.service;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,4 +19,12 @@ public interface MessageTemplateGroupService {
|
|||||||
* @return 模板编码列表
|
* @return 模板编码列表
|
||||||
*/
|
*/
|
||||||
List<String> listMessageTemplateCodes(String groupNodeCode);
|
List<String> listMessageTemplateCodes(String groupNodeCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板关联分类
|
||||||
|
*
|
||||||
|
* @param templateNode 模板编码
|
||||||
|
* @param groupNodeCodes 分类结点编码列表
|
||||||
|
*/
|
||||||
|
void templateGroup(String templateNode, Collection<String> groupNodeCodes);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ public interface MessageTemplateNewService {
|
|||||||
*
|
*
|
||||||
* @param param 模板内容参数
|
* @param param 模板内容参数
|
||||||
*/
|
*/
|
||||||
void createTemplate(MessageTemplateCreateParam param);
|
String createTemplate(MessageTemplateCreateParam param);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过模板编码查询模板信息
|
* 通过模板编码查询模板信息
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
package cn.axzo.msg.center.message.service;
|
package cn.axzo.msg.center.message.service;
|
||||||
|
|
||||||
import cn.axzo.msg.center.message.domain.dto.MessageGroupNodeDTO;
|
import cn.axzo.msg.center.message.domain.dto.MessageGroupNodeStatisticDTO;
|
||||||
import cn.axzo.msg.center.message.domain.dto.PendingMessageDTO;
|
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.MessageGroupNodeStatisticParam;
|
||||||
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
|
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
|
||||||
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
|
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.PendingMessagePageRequest;
|
||||||
import cn.axzo.msg.center.service.pending.request.PendingMessagePushRequest;
|
|
||||||
import cn.axzo.msg.center.service.pending.response.PendingMessageResponse;
|
import cn.axzo.msg.center.service.pending.response.PendingMessageResponse;
|
||||||
import cn.azxo.framework.common.model.Page;
|
import cn.azxo.framework.common.model.Page;
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ import java.util.Optional;
|
|||||||
*/
|
*/
|
||||||
public interface PendingMessageNewService {
|
public interface PendingMessageNewService {
|
||||||
|
|
||||||
List<MessageGroupNodeDTO> groupStatistic(MessageGroupNodeStatisticParam param);
|
List<MessageGroupNodeStatisticDTO> groupStatistic(MessageGroupNodeStatisticParam param);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代办列表分页查询
|
* 代办列表分页查询
|
||||||
|
|||||||
@ -0,0 +1,62 @@
|
|||||||
|
package cn.axzo.msg.center.message.service.impl;
|
||||||
|
|
||||||
|
import cn.axzo.msg.center.message.domain.dto.GroupTreeNodePathDTO;
|
||||||
|
import cn.axzo.msg.center.message.service.MessageGroupNodeService;
|
||||||
|
import cn.axzo.msg.center.message.service.MessageGroupTreeNodeCacheService;
|
||||||
|
import cn.axzo.msg.center.service.dto.GroupTreeNodeDTO;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cold_blade
|
||||||
|
* @date 2023/10/14
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MessageGroupNodeServiceImpl implements MessageGroupNodeService {
|
||||||
|
|
||||||
|
private final MessageGroupTreeNodeCacheService messageGroupTreeNodeCacheService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> leafGroupNodeNamePaths(Collection<String> leafGroupNodeCodes) {
|
||||||
|
if (CollectionUtils.isEmpty(leafGroupNodeCodes)) {
|
||||||
|
log.info("leafGroupNodeCodes is empty.");
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
return leafGroupNodeCodes.stream()
|
||||||
|
.map(messageGroupTreeNodeCacheService::queryLeafNodePath)
|
||||||
|
.filter(Optional::isPresent)
|
||||||
|
.map(Optional::get)
|
||||||
|
.collect(Collectors.toMap(GroupTreeNodePathDTO::getNodeCode,
|
||||||
|
GroupTreeNodePathDTO::getNodeNamePath, (cur, pre) -> cur));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> leafGroupNodeCodePaths(Collection<String> leafGroupNodeCodes) {
|
||||||
|
if (CollectionUtils.isEmpty(leafGroupNodeCodes)) {
|
||||||
|
log.info("leafGroupNodeCodes is empty.");
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
return leafGroupNodeCodes.stream()
|
||||||
|
.map(messageGroupTreeNodeCacheService::queryLeafNodePath)
|
||||||
|
.filter(Optional::isPresent)
|
||||||
|
.map(Optional::get)
|
||||||
|
.collect(Collectors.toMap(GroupTreeNodePathDTO::getNodeCode,
|
||||||
|
GroupTreeNodePathDTO::getNodeCodePath, (cur, pre) -> cur));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<GroupTreeNodeDTO> queryRootNode(String rootNodeCode) {
|
||||||
|
return messageGroupTreeNodeCacheService.queryRootNode(rootNodeCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,70 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,185 @@
|
|||||||
|
package cn.axzo.msg.center.message.service.impl;
|
||||||
|
|
||||||
|
import cn.axzo.basics.common.util.TreeUtil;
|
||||||
|
import cn.axzo.msg.center.common.enums.TableIsDeleteEnum;
|
||||||
|
import cn.axzo.msg.center.dal.MessageGroupNodeDao;
|
||||||
|
import cn.axzo.msg.center.domain.entity.MessageGroupNode;
|
||||||
|
import cn.axzo.msg.center.message.domain.dto.GroupTreeNodePathDTO;
|
||||||
|
import cn.axzo.msg.center.message.service.MessageGroupTreeNodeCacheService;
|
||||||
|
import cn.axzo.msg.center.service.dto.GroupTreeNodeDTO;
|
||||||
|
import cn.axzo.pokonyan.config.redis.RedisUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.compress.utils.Lists;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cold_blade
|
||||||
|
* @date 2023/10/14
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MessageGroupTreeNodeCacheServiceImpl implements MessageGroupTreeNodeCacheService {
|
||||||
|
|
||||||
|
private static final String CACHE_KEY = "msg-center:message:group:cache-key";
|
||||||
|
private static final String CACHE_VALUE = "msg-center:message:group:cache-val";
|
||||||
|
private static final long CACHE_KEY_TIMEOUT_DAYS = 1;
|
||||||
|
|
||||||
|
private final MessageGroupNodeDao messageGroupNodeDao;
|
||||||
|
|
||||||
|
private List<GroupTreeNodeDTO> allGroupTreeRootNodesCache = Collections.emptyList();
|
||||||
|
private List<GroupTreeNodePathDTO> leafTreeNodePathsCache = Collections.emptyList();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GroupTreeNodeDTO> listAllRootNodes() {
|
||||||
|
return getAllGroupTreeRootNodesCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<GroupTreeNodeDTO> queryRootNode(String rootNodeCode) {
|
||||||
|
if (StringUtils.isBlank(rootNodeCode)) {
|
||||||
|
log.info("rootNodeCode is blank.");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return getAllGroupTreeRootNodesCache().stream()
|
||||||
|
.filter(e -> Objects.equals(e.getNodeCode(), rootNodeCode))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<GroupTreeNodeDTO> queryNode(String groupNodeCode) {
|
||||||
|
if (StringUtils.isBlank(groupNodeCode)) {
|
||||||
|
log.info("groupNodeCode is blank.");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return getAllGroupTreeRootNodesCache().stream()
|
||||||
|
.map(e -> findTreeNode(e, groupNodeCode))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<GroupTreeNodePathDTO> queryLeafNodePath(String leafNodeCode) {
|
||||||
|
if (StringUtils.isBlank(leafNodeCode)) {
|
||||||
|
log.info("leafNodeCode is blank.");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return getLeafTreeNodePathsCache().stream()
|
||||||
|
.filter(e -> Objects.equals(e.getNodeCode(), leafNodeCode))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshCache() {
|
||||||
|
// 清除redis中的缓存标识
|
||||||
|
RedisUtil.KeyOps.delete(CACHE_KEY);
|
||||||
|
// 清除本地缓存
|
||||||
|
allGroupTreeRootNodesCache = Collections.emptyList();
|
||||||
|
leafTreeNodePathsCache = Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupTreeNodeDTO findTreeNode(GroupTreeNodeDTO root, String treeNodeCode) {
|
||||||
|
if (Objects.equals(root.getNodeCode(), treeNodeCode)) {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
LinkedList<GroupTreeNodeDTO> queue = new LinkedList<>(root.getNodeChildren());
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
GroupTreeNodeDTO node = queue.pop();
|
||||||
|
Optional<GroupTreeNodeDTO> childOp = node.getChild(treeNodeCode);
|
||||||
|
if (childOp.isPresent()) {
|
||||||
|
return childOp.get();
|
||||||
|
}
|
||||||
|
queue.addAll(node.getNodeChildren());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<GroupTreeNodeDTO> getAllGroupTreeRootNodesCache() {
|
||||||
|
if (RedisUtil.KeyOps.hasKey(CACHE_KEY)) {
|
||||||
|
// 其它结点进行了本地缓存,但是当前服务进程还未进行缓存
|
||||||
|
if (CollectionUtils.isEmpty(allGroupTreeRootNodesCache)) {
|
||||||
|
// 本地缓存初始化,不更新redis中的缓存标识
|
||||||
|
initialize(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 本地缓存初始化并更新redis中的缓存标识
|
||||||
|
initialize(true);
|
||||||
|
}
|
||||||
|
return this.allGroupTreeRootNodesCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<GroupTreeNodePathDTO> getLeafTreeNodePathsCache() {
|
||||||
|
if (RedisUtil.KeyOps.hasKey(CACHE_KEY)) {
|
||||||
|
// 其它结点进行了本地缓存,但是当前服务进程还未进行缓存
|
||||||
|
if (leafTreeNodePathsCache.isEmpty()) {
|
||||||
|
// 本地缓存初始化,不更新redis中的缓存标识
|
||||||
|
initialize(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 本地缓存初始化并更新redis中的缓存标识
|
||||||
|
initialize(true);
|
||||||
|
}
|
||||||
|
return leafTreeNodePathsCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void initialize(boolean refreshCache) {
|
||||||
|
List<GroupTreeNodeDTO> groupNodes = listAllValidNodesFromDB();
|
||||||
|
allGroupTreeRootNodesCache = TreeUtil.buildTree(groupNodes);
|
||||||
|
leafTreeNodePathsCache = allGroupTreeRootNodesCache.stream()
|
||||||
|
.flatMap(e -> parseRootNode(e).stream())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (refreshCache) {
|
||||||
|
RedisUtil.StringOps.setIfAbsent(CACHE_KEY, CACHE_VALUE, CACHE_KEY_TIMEOUT_DAYS, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<GroupTreeNodeDTO> listAllValidNodesFromDB() {
|
||||||
|
return messageGroupNodeDao.lambdaQuery()
|
||||||
|
.eq(MessageGroupNode::getIsDelete, TableIsDeleteEnum.NORMAL.value)
|
||||||
|
.list().stream()
|
||||||
|
.map(this::convert)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupTreeNodeDTO convert(MessageGroupNode groupNode) {
|
||||||
|
return GroupTreeNodeDTO.builder()
|
||||||
|
.nodeName(groupNode.getName())
|
||||||
|
.nodeCode(groupNode.getCode())
|
||||||
|
.category(groupNode.getCategory())
|
||||||
|
.parentNodeCode(groupNode.getParentCode())
|
||||||
|
.isLeaf(groupNode.getIsLeaf())
|
||||||
|
.status(groupNode.getStatus())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<GroupTreeNodePathDTO> parseRootNode(GroupTreeNodeDTO root) {
|
||||||
|
List<GroupTreeNodePathDTO> paths = Lists.newArrayList();
|
||||||
|
LinkedList<GroupTreeNodeDTO> pathNodeStack = new LinkedList<>();
|
||||||
|
LinkedList<GroupTreeNodeDTO> stack = new LinkedList<>();
|
||||||
|
stack.push(root);
|
||||||
|
while (!stack.isEmpty()) {
|
||||||
|
GroupTreeNodeDTO node = stack.pop();
|
||||||
|
pathNodeStack.push(node);
|
||||||
|
if (CollectionUtils.isEmpty(node.getNodeChildren())) {
|
||||||
|
// 当前结点为树的叶结点(逻辑上的,有可能不是业务维度的叶结点)
|
||||||
|
paths.add(GroupTreeNodePathDTO.of(node.getNodeCode(), pathNodeStack));
|
||||||
|
pathNodeStack.pop();
|
||||||
|
} else {
|
||||||
|
stack.addAll(node.getNodeChildren());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,14 +2,18 @@ package cn.axzo.msg.center.message.service.impl;
|
|||||||
|
|
||||||
import cn.axzo.msg.center.dal.MessageTemplateGroupDao;
|
import cn.axzo.msg.center.dal.MessageTemplateGroupDao;
|
||||||
import cn.axzo.msg.center.domain.entity.MessageTemplateGroup;
|
import cn.axzo.msg.center.domain.entity.MessageTemplateGroup;
|
||||||
|
import cn.axzo.msg.center.message.service.MessageGroupNodeService;
|
||||||
import cn.axzo.msg.center.message.service.MessageTemplateGroupService;
|
import cn.axzo.msg.center.message.service.MessageTemplateGroupService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,6 +26,7 @@ import java.util.stream.Collectors;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class MessageTemplateGroupServiceImpl implements MessageTemplateGroupService {
|
public class MessageTemplateGroupServiceImpl implements MessageTemplateGroupService {
|
||||||
|
|
||||||
|
private final MessageGroupNodeService messageGroupNodeService;
|
||||||
private final MessageTemplateGroupDao messageTemplateGroupDao;
|
private final MessageTemplateGroupDao messageTemplateGroupDao;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -37,4 +42,22 @@ public class MessageTemplateGroupServiceImpl implements MessageTemplateGroupServ
|
|||||||
.map(MessageTemplateGroup::getTemplateCode)
|
.map(MessageTemplateGroup::getTemplateCode)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void templateGroup(String templateNode, Collection<String> groupNodeCodes) {
|
||||||
|
if (StringUtils.isBlank(templateNode)
|
||||||
|
|| CollectionUtils.isEmpty(groupNodeCodes)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, String> pathMap = messageGroupNodeService.leafGroupNodeCodePaths(groupNodeCodes);
|
||||||
|
List<MessageTemplateGroup> rows = groupNodeCodes.stream()
|
||||||
|
.filter(pathMap::containsKey)
|
||||||
|
.map(e -> {
|
||||||
|
MessageTemplateGroup group = new MessageTemplateGroup();
|
||||||
|
group.setTemplateCode(templateNode);
|
||||||
|
group.setPath(pathMap.get(e));
|
||||||
|
return group;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
messageTemplateGroupDao.saveBatch(rows);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,24 @@
|
|||||||
package cn.axzo.msg.center.message.service.impl;
|
package cn.axzo.msg.center.message.service.impl;
|
||||||
|
|
||||||
import cn.axzo.core.utils.converter.BeanConverter;
|
import cn.axzo.basics.common.util.AssertUtil;
|
||||||
|
import cn.axzo.msg.center.common.enums.ServiceErrorCodeEnum;
|
||||||
import cn.axzo.msg.center.dal.MessageBaseTemplateDao;
|
import cn.axzo.msg.center.dal.MessageBaseTemplateDao;
|
||||||
import cn.axzo.msg.center.domain.entity.MessageBaseTemplate;
|
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.MessageTemplateDTO;
|
||||||
import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO;
|
import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO;
|
||||||
import cn.axzo.msg.center.message.domain.param.MessageTemplateCreateParam;
|
import cn.axzo.msg.center.message.domain.param.MessageTemplateCreateParam;
|
||||||
|
import cn.axzo.msg.center.message.service.MessageTemplateGroupService;
|
||||||
import cn.axzo.msg.center.message.service.MessageTemplateNewService;
|
import cn.axzo.msg.center.message.service.MessageTemplateNewService;
|
||||||
import cn.axzo.msg.center.message.service.MessageTemplateRouterService;
|
import cn.axzo.msg.center.message.service.MessageTemplateRouterService;
|
||||||
|
import cn.axzo.msg.center.utils.JSONObjectUtil;
|
||||||
|
import cn.axzo.msg.center.utils.UUIDUtil;
|
||||||
|
import cn.axzo.pokonyan.config.redis.RedisUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -33,19 +39,24 @@ import java.util.stream.Collectors;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class MessageTemplateNewServiceImpl implements MessageTemplateNewService {
|
public class MessageTemplateNewServiceImpl implements MessageTemplateNewService {
|
||||||
|
|
||||||
|
private static final String SAVE_TEMPLATE_MUTEX_KEY = "msg-center:template:save:%s";
|
||||||
|
private static final long TRY_LOCK_TIMEOUT_MILLS = 1000;
|
||||||
|
private static final int RETRY_CNT_MAX = 3;
|
||||||
|
|
||||||
private final MessageBaseTemplateDao messageBaseTemplateDao;
|
private final MessageBaseTemplateDao messageBaseTemplateDao;
|
||||||
|
private final MessageTemplateGroupService messageTemplateGroupService;
|
||||||
private final MessageTemplateRouterService messageTemplateRouterService;
|
private final MessageTemplateRouterService messageTemplateRouterService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createTemplate(MessageTemplateCreateParam param) {
|
@Transactional(rollbackFor = Exception.class)
|
||||||
// TODO: [cold_blade] [P2] 模板与分类的关系
|
public String createTemplate(MessageTemplateCreateParam param) {
|
||||||
messageBaseTemplateDao.save(convert(param));
|
// 创建模板基础数据
|
||||||
if (CollectionUtils.isNotEmpty(param.getRouters())) {
|
String templateCode = saveTemplate(param);
|
||||||
List<RawMessageRouterDTO> routers = param.getRouters().stream()
|
// 创建模板的路由数据
|
||||||
.map(e -> RawMessageRouterDTO.from(e, param.getTemplateCode()))
|
saveTemplateRouters(param, templateCode);
|
||||||
.collect(Collectors.toList());
|
// 创建模板与分类的关联关系数据
|
||||||
messageTemplateRouterService.batchInsert(routers);
|
messageTemplateGroupService.templateGroup(templateCode, param.getLeafGroupNodes());
|
||||||
}
|
return templateCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -87,12 +98,65 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String saveTemplate(MessageTemplateCreateParam param) {
|
||||||
|
String templateCode = UUIDUtil.uuidString();
|
||||||
|
MessageBaseTemplate template = convert(param);
|
||||||
|
boolean result = doSaveTemplate(template, templateCode);
|
||||||
|
int retryCnt = 0;
|
||||||
|
while (!result && retryCnt++ < RETRY_CNT_MAX) {
|
||||||
|
// 默认重试{@cod RETRY_CNT_MAX}次,若{@code RETRY_CNT_MAX}次后依然失败就报错
|
||||||
|
templateCode = UUIDUtil.uuidString();
|
||||||
|
result = doSaveTemplate(template, templateCode);
|
||||||
|
}
|
||||||
|
AssertUtil.isTrue(result, ServiceErrorCodeEnum.SYSTEM_BUSY.getDesc());
|
||||||
|
return templateCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doSaveTemplate(MessageBaseTemplate template, String templateCode) {
|
||||||
|
String requestId = UUIDUtil.uuidRawString();
|
||||||
|
try {
|
||||||
|
String opKey = String.format(SAVE_TEMPLATE_MUTEX_KEY, templateCode);
|
||||||
|
boolean lockResult = RedisUtil.LockOps.getLockUntilTimeout(opKey, requestId, TRY_LOCK_TIMEOUT_MILLS);
|
||||||
|
AssertUtil.isTrue(lockResult, ServiceErrorCodeEnum.SYSTEM_BUSY.getDesc());
|
||||||
|
if (isTemplateExist(templateCode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
template.setCode(templateCode);
|
||||||
|
messageBaseTemplateDao.save(template);
|
||||||
|
return true;
|
||||||
|
} finally {
|
||||||
|
RedisUtil.LockOps.releaseLock(SAVE_TEMPLATE_MUTEX_KEY, requestId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTemplateExist(String templateCode) {
|
||||||
|
return messageBaseTemplateDao.lambdaQuery()
|
||||||
|
.eq(MessageBaseTemplate::getCode, templateCode)
|
||||||
|
.eq(MessageBaseTemplate::getIsDelete, 0)
|
||||||
|
.count() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
private MessageBaseTemplate convert(MessageTemplateCreateParam param) {
|
private MessageBaseTemplate convert(MessageTemplateCreateParam param) {
|
||||||
MessageBaseTemplate template = BeanConverter.convert(param, MessageBaseTemplate.class);
|
MessageBaseTemplate template = new MessageBaseTemplate();
|
||||||
template.setName(param.getTemplateName());
|
template.setName(param.getTemplateName());
|
||||||
template.setCode(param.getTemplateCode());
|
template.setMsgCategory(param.getMsgCategory());
|
||||||
|
template.setTitle(param.getTitle());
|
||||||
|
template.setContent(param.getContent());
|
||||||
|
template.setCardContent(JSONObjectUtil.checkAndReturn(param.getCardContent()));
|
||||||
|
template.setIcon(param.getIcon());
|
||||||
|
template.setPushTerminal(JSONObjectUtil.toJSONString(param.getPushTerminals()));
|
||||||
template.setCreatorId(param.getOperatorId());
|
template.setCreatorId(param.getOperatorId());
|
||||||
template.setUpdaterId(param.getOperatorId());
|
template.setUpdaterId(param.getOperatorId());
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveTemplateRouters(MessageTemplateCreateParam param, String templateCode) {
|
||||||
|
if (CollectionUtils.isEmpty(param.getRouters())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<RawMessageRouterDTO> routers = param.getRouters().stream()
|
||||||
|
.map(e -> RawMessageRouterDTO.from(e, templateCode))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
messageTemplateRouterService.batchInsert(routers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,16 +5,17 @@ import cn.axzo.msg.center.common.exception.ServiceException;
|
|||||||
import cn.axzo.msg.center.common.utils.PlaceholderResolver;
|
import cn.axzo.msg.center.common.utils.PlaceholderResolver;
|
||||||
import cn.axzo.msg.center.dal.PendingMessageRecordDao;
|
import cn.axzo.msg.center.dal.PendingMessageRecordDao;
|
||||||
import cn.axzo.msg.center.domain.entity.PendingMessageRecord;
|
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.MessageGroupNodeStatisticDTO;
|
||||||
import cn.axzo.msg.center.message.domain.dto.MessageTemplateDTO;
|
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.PendingMessageDTO;
|
||||||
import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO;
|
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.MessageGroupNodeStatisticParam;
|
||||||
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
|
import cn.axzo.msg.center.message.domain.param.PendingMessagePushParam;
|
||||||
import cn.axzo.msg.center.message.service.MessageGroupService;
|
import cn.axzo.msg.center.message.service.MessageGroupNodeService;
|
||||||
import cn.axzo.msg.center.message.service.MessageTemplateGroupService;
|
import cn.axzo.msg.center.message.service.MessageTemplateGroupService;
|
||||||
import cn.axzo.msg.center.message.service.MessageTemplateNewService;
|
import cn.axzo.msg.center.message.service.MessageTemplateNewService;
|
||||||
import cn.axzo.msg.center.message.service.PendingMessageNewService;
|
import cn.axzo.msg.center.message.service.PendingMessageNewService;
|
||||||
|
import cn.axzo.msg.center.service.dto.GroupTreeNodeDTO;
|
||||||
import cn.axzo.msg.center.service.dto.IdentityDTO;
|
import cn.axzo.msg.center.service.dto.IdentityDTO;
|
||||||
import cn.axzo.msg.center.service.dto.MessageRouterDTO;
|
import cn.axzo.msg.center.service.dto.MessageRouterDTO;
|
||||||
import cn.axzo.msg.center.service.dto.PersonDTO;
|
import cn.axzo.msg.center.service.dto.PersonDTO;
|
||||||
@ -29,6 +30,7 @@ import cn.axzo.msg.center.service.pending.response.PendingMessageResponse;
|
|||||||
import cn.axzo.msg.center.utils.JSONObjectUtil;
|
import cn.axzo.msg.center.utils.JSONObjectUtil;
|
||||||
import cn.axzo.msg.center.utils.MessageRouterUtil;
|
import cn.axzo.msg.center.utils.MessageRouterUtil;
|
||||||
import cn.axzo.msg.center.utils.OrderFieldParseUtil;
|
import cn.axzo.msg.center.utils.OrderFieldParseUtil;
|
||||||
|
import cn.axzo.msg.center.utils.TreeHelperUtil;
|
||||||
import cn.axzo.msg.center.utils.UUIDUtil;
|
import cn.axzo.msg.center.utils.UUIDUtil;
|
||||||
import cn.azxo.framework.common.model.Page;
|
import cn.azxo.framework.common.model.Page;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -45,10 +47,10 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Stack;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,13 +65,13 @@ import java.util.stream.Collectors;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PendingMessageNewServiceImpl implements PendingMessageNewService {
|
public class PendingMessageNewServiceImpl implements PendingMessageNewService {
|
||||||
|
|
||||||
private final MessageGroupService messageGroupService;
|
|
||||||
private final PendingMessageRecordDao pendingMessageRecordDao;
|
private final PendingMessageRecordDao pendingMessageRecordDao;
|
||||||
|
private final MessageGroupNodeService messageGroupNodeService;
|
||||||
private final MessageTemplateNewService messageTemplateNewService;
|
private final MessageTemplateNewService messageTemplateNewService;
|
||||||
private final MessageTemplateGroupService messageTemplateGroupService;
|
private final MessageTemplateGroupService messageTemplateGroupService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<MessageGroupNodeDTO> groupStatistic(MessageGroupNodeStatisticParam param) {
|
public List<MessageGroupNodeStatisticDTO> groupStatistic(MessageGroupNodeStatisticParam param) {
|
||||||
return param.getGroupNodeCodes().stream()
|
return param.getGroupNodeCodes().stream()
|
||||||
.flatMap(e -> statistic(e, param).stream())
|
.flatMap(e -> statistic(e, param).stream())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
@ -193,26 +195,23 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
|
|||||||
return pendingMessage;
|
return pendingMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MessageGroupNodeDTO> statistic(String rootNodeCode, MessageGroupNodeStatisticParam param) {
|
private List<MessageGroupNodeStatisticDTO> statistic(String rootNodeCode, MessageGroupNodeStatisticParam param) {
|
||||||
MessageGroupNodeDTO groupNode = messageGroupService.queryByNodeCode(rootNodeCode)
|
GroupTreeNodeDTO rootNode = messageGroupNodeService.queryRootNode(rootNodeCode)
|
||||||
.orElseThrow(() -> new ServiceException("groupNodeCode is invalid."));
|
.orElseThrow(() -> new ServiceException("groupNodeCode is invalid."));
|
||||||
MessageGroupNodeDTO root = groupNode;
|
MessageGroupNodeStatisticDTO rootWrapper = TreeHelperUtil.wrapper(rootNode, MessageGroupNodeStatisticDTO::of);
|
||||||
Stack<MessageGroupNodeDTO> stack = new Stack<>();
|
LinkedList<MessageGroupNodeStatisticDTO> stack = new LinkedList<>();
|
||||||
stack.push(groupNode);
|
stack.push(rootWrapper);
|
||||||
List<MessageGroupNodeDTO> children;
|
MessageGroupNodeStatisticDTO wrapper;
|
||||||
while (!stack.isEmpty()) {
|
while (!stack.isEmpty()) {
|
||||||
// TODO: [cold_blade] [P3] 优化树形分类结点的统计效率
|
wrapper = stack.pop();
|
||||||
groupNode = stack.pop();
|
statistic(wrapper, param);
|
||||||
statistic(groupNode, param);
|
stack.addAll(wrapper.getNodeChildren());
|
||||||
children = messageGroupService.listChildren(groupNode.getNodeCode());
|
|
||||||
groupNode.setChildren(children);
|
|
||||||
children.forEach(stack::push);
|
|
||||||
}
|
}
|
||||||
// 外部传的是根节点,但是前端希望只返回根节点的字节的
|
// 外部传的是根节点,但是前端希望只返回根节点的字节的
|
||||||
return root.getChildren();
|
return rootWrapper.getNodeChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void statistic(MessageGroupNodeDTO groupNode, MessageGroupNodeStatisticParam param) {
|
private void statistic(MessageGroupNodeStatisticDTO groupNode, MessageGroupNodeStatisticParam param) {
|
||||||
List<String> templateCodes = messageTemplateGroupService.listMessageTemplateCodes(groupNode.getNodeCode());
|
List<String> templateCodes = messageTemplateGroupService.listMessageTemplateCodes(groupNode.getNodeCode());
|
||||||
if (CollectionUtils.isEmpty(templateCodes)) {
|
if (CollectionUtils.isEmpty(templateCodes)) {
|
||||||
groupNode.setPendingCount(0);
|
groupNode.setPendingCount(0);
|
||||||
@ -298,6 +297,7 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void buildTemplateInfo(PendingMessageRecord record, MessageTemplateDTO msgTemplate, String routeParam) {
|
private void buildTemplateInfo(PendingMessageRecord record, MessageTemplateDTO msgTemplate, String routeParam) {
|
||||||
|
// TODO:[cold_blade] [P3] 后续其它业务对接的时候,需要明确业务扩展字段和路由参数的分界
|
||||||
JSONObject routerParamObj = JSONObjectUtil.parseObject(routeParam);
|
JSONObject routerParamObj = JSONObjectUtil.parseObject(routeParam);
|
||||||
String title = PlaceholderResolver
|
String title = PlaceholderResolver
|
||||||
.getDefaultResolver().resolveByMap(msgTemplate.getTitle(), routerParamObj);
|
.getDefaultResolver().resolveByMap(msgTemplate.getTitle(), routerParamObj);
|
||||||
@ -316,4 +316,9 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
|
|||||||
record.setBizCategory(param.getBizCategory());
|
record.setBizCategory(param.getBizCategory());
|
||||||
record.setBizExtParam(JSONObjectUtil.checkAndReturn(param.getBizExtParams()));
|
record.setBizExtParam(JSONObjectUtil.checkAndReturn(param.getBizExtParams()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class GroupTreeNodeWrapper {
|
||||||
|
private GroupTreeNodeDTO treeNode;
|
||||||
|
private int pendingCnt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,12 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author cold_blade
|
* @author cold_blade
|
||||||
* @date 2023/10/13
|
* @date 2023/10/13
|
||||||
@ -14,6 +18,8 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public final class JSONObjectUtil {
|
public final class JSONObjectUtil {
|
||||||
private static final JSONObject EMPTY_JSON_OBJ = new JSONObject();
|
private static final JSONObject EMPTY_JSON_OBJ = new JSONObject();
|
||||||
|
private static final String EMPTY_JSON_OBJ_STR = "{}";
|
||||||
|
private static final String EMPTY_JSON_ARR_STR = "[]";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析JSON字符串,若字符串格式不正确,抛异常
|
* 解析JSON字符串,若字符串格式不正确,抛异常
|
||||||
@ -28,6 +34,20 @@ public final class JSONObjectUtil {
|
|||||||
return JSON.parseObject(str);
|
return JSON.parseObject(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String toJSONString(Object obj) {
|
||||||
|
if (Objects.isNull(obj)) {
|
||||||
|
return EMPTY_JSON_OBJ_STR;
|
||||||
|
}
|
||||||
|
return JSON.toJSONString(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toJSONString(Collection<?> objCollection) {
|
||||||
|
if (CollectionUtils.isEmpty(objCollection)) {
|
||||||
|
return EMPTY_JSON_ARR_STR;
|
||||||
|
}
|
||||||
|
return JSON.toJSONString(objCollection);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验字符串是否为有效的JSON字符串,若字符串格式不正确,抛异常
|
* 校验字符串是否为有效的JSON字符串,若字符串格式不正确,抛异常
|
||||||
*
|
*
|
||||||
|
|||||||
@ -0,0 +1,44 @@
|
|||||||
|
package cn.axzo.msg.center.utils;
|
||||||
|
|
||||||
|
import cn.axzo.basics.common.model.IBaseTree;
|
||||||
|
import cn.axzo.basics.common.util.AssertUtil;
|
||||||
|
import cn.axzo.msg.center.service.dto.GroupTreeNodeDTO;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cold_blade
|
||||||
|
* @date 2023/10/16
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public final class TreeHelperUtil {
|
||||||
|
|
||||||
|
public static <T extends IBaseTree<T, O>, O> T wrapper(GroupTreeNodeDTO treeNode,
|
||||||
|
Function<GroupTreeNodeDTO, T> wrapperFunc) {
|
||||||
|
AssertUtil.notNull(treeNode, "treeNode is null");
|
||||||
|
AssertUtil.notNull(wrapperFunc, "wrapperFunc is null");
|
||||||
|
|
||||||
|
final Map<GroupTreeNodeDTO, T> convertMap = Maps.newHashMap();
|
||||||
|
T wrapper = wrapperFunc.apply(treeNode);
|
||||||
|
convertMap.put(treeNode, wrapper);
|
||||||
|
LinkedList<GroupTreeNodeDTO> treeNodeStack = new LinkedList<>();
|
||||||
|
treeNodeStack.push(treeNode);
|
||||||
|
while (!treeNodeStack.isEmpty()) {
|
||||||
|
treeNode = treeNodeStack.pop();
|
||||||
|
List<GroupTreeNodeDTO> children = treeNode.getNodeChildren();
|
||||||
|
convertMap.get(treeNode).setNodeChildren(children.stream()
|
||||||
|
.map(e -> convertMap.put(e, wrapperFunc.apply(e)))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
treeNodeStack.addAll(children);
|
||||||
|
}
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,53 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
package cn.axzo.msg.center.service.dto;
|
||||||
|
|
||||||
|
import cn.axzo.basics.common.model.IBaseTree;
|
||||||
|
import cn.axzo.msg.center.service.enums.MessageGroupNodeCategoryEnum;
|
||||||
|
import cn.axzo.msg.center.service.enums.StatusEnum;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cold_blade
|
||||||
|
* @date 2023/10/14
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class GroupTreeNodeDTO implements IBaseTree<GroupTreeNodeDTO, String>, Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -3244632155934087302L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板分组结点名称
|
||||||
|
*/
|
||||||
|
private String nodeName;
|
||||||
|
/**
|
||||||
|
* 模板分组结点名称code
|
||||||
|
*/
|
||||||
|
private String nodeCode;
|
||||||
|
/**
|
||||||
|
* 结点类型
|
||||||
|
*/
|
||||||
|
private MessageGroupNodeCategoryEnum category;
|
||||||
|
/**
|
||||||
|
* 父节点
|
||||||
|
*/
|
||||||
|
private String parentNodeCode;
|
||||||
|
/**
|
||||||
|
* 是否为叶节点
|
||||||
|
*/
|
||||||
|
private Integer isLeaf;
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*/
|
||||||
|
private StatusEnum status;
|
||||||
|
/**
|
||||||
|
* 子节点列表
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private List<GroupTreeNodeDTO> nodeChildren = Collections.emptyList();
|
||||||
|
|
||||||
|
public Optional<GroupTreeNodeDTO> getChild(String treeNodeCode) {
|
||||||
|
if (StringUtils.isBlank(treeNodeCode)) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return getNodeChildren().stream()
|
||||||
|
.filter(e -> Objects.equals(e.getNodeCode(), treeNodeCode))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
package cn.axzo.msg.center.common.enums;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cold_blade
|
||||||
|
* @date 2023/10/14
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public enum ServiceErrorCodeEnum {
|
||||||
|
|
||||||
|
SYSTEM_BUSY("E0002", "系统繁忙,请稍后重试"),
|
||||||
|
|
||||||
|
PARAM_IS_INVALID("E0020", "参数异常"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String desc;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user