Merge branch 'feature/REQ-1507' of axzsource.com:universal/infrastructure/backend/msg-center-plat into dev

This commit is contained in:
luofu 2023-11-09 10:14:28 +08:00
commit 560493a122
17 changed files with 704 additions and 268 deletions

View File

@ -5,7 +5,6 @@ import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO;
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
import cn.axzo.msg.center.service.enums.PushTerminalEnum;
import cn.axzo.msg.center.utils.JSONObjectUtil;
import cn.axzo.msg.center.utils.MessageRouterUtil;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Builder;
@ -67,7 +66,7 @@ public class MessageTemplateDTO implements Serializable {
/**
* 模板路由信息
*/
private List<RawMessageRouterDTO> routers;
private MessageTemplateRouterDTO msgTemplateRouter;
/**
* 推送终端
*/
@ -77,7 +76,7 @@ public class MessageTemplateDTO implements Serializable {
*/
private String minAppVersion;
public static MessageTemplateDTO from(MessageBaseTemplate baseTemplate, List<RawMessageRouterDTO> routers) {
public static MessageTemplateDTO from(MessageBaseTemplate baseTemplate, MessageTemplateRouterDTO msgTemplateRouter) {
// 业务详情展示策略
return MessageTemplateDTO.builder()
.name(baseTemplate.getName())
@ -87,7 +86,7 @@ public class MessageTemplateDTO implements Serializable {
.msgCardContentItems(JSONObjectUtil.parseArray(baseTemplate.getCardContent(), MessageCardContentItemDTO.class))
.msgCategory(baseTemplate.getMsgCategory())
.icon(baseTemplate.getIcon())
.routers(MessageRouterUtil.selectRouterButtons(routers))
.msgTemplateRouter(msgTemplateRouter)
.pushTerminals(JSON.parseArray(baseTemplate.getPushTerminal(), PushTerminalEnum.class))
.minAppVersion(baseTemplate.getMinAppVersion())
.build();

View File

@ -1,18 +1,33 @@
package cn.axzo.msg.center.message.domain.dto;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.msg.center.domain.entity.MessageRouteButton;
import cn.axzo.msg.center.domain.entity.MessageRouteDetail;
import cn.axzo.msg.center.domain.entity.MessageRouterConfig;
import cn.axzo.msg.center.service.dto.BizDetailShowStrategyDTO;
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
import cn.axzo.msg.center.service.dto.MessageRouterTerminalDTO;
import cn.axzo.msg.center.service.enums.BizDetailShowStrategyEnum;
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
import cn.axzo.msg.center.service.enums.ButtonStyleEnum;
import cn.axzo.msg.center.service.enums.RouterButtonSourceEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import cn.axzo.msg.center.utils.MessageRouterUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
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;
import java.util.stream.Collectors;
/**
* @author cold_blade
@ -30,11 +45,30 @@ public class MessageTemplateRouterDTO implements Serializable {
/**
* 业务详情路由
*/
private BizDetailRouterDTO bizDetailRouter;
private MessageRouteDetailDTO routeDetail;
/**
* 按钮路由列表
*/
private List<MessageTemplateRouteButtonDTO> routeButtons;
private List<MessageRouteButtonDTO> routeButtons;
public boolean isValid() {
return Objects.nonNull(routeDetail)
|| CollectionUtils.isNotEmpty(routeButtons);
}
public boolean isInValid() {
return !isValid();
}
public Optional<String> fetchTemplateCode() {
if (Objects.nonNull(routeDetail)) {
return Optional.ofNullable(routeDetail.getTemplateCode());
}
if (CollectionUtils.isNotEmpty(routeButtons)) {
return Optional.ofNullable(routeButtons.get(0).getTemplateCode());
}
return Optional.empty();
}
@Override
public String toString() {
@ -45,23 +79,77 @@ public class MessageTemplateRouterDTO implements Serializable {
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class BizDetailRouterDTO implements Serializable {
public static class MessageRouteDetailDTO implements Serializable {
private static final long serialVersionUID = -6332526731908737802L;
/**
* 模板编码
* 显示名称
*/
private String name;
/**
* 模板code
*/
private String templateCode;
/**
* 业务详情展示策略
*/
private BizDetailShowStrategyEnum bizDetailShowStrategy;
private BizDetailShowStrategyEnum showStrategy;
/**
* 跳转路由的配置列表
*/
private List<MessageRouterConfigDTO> routerConfigs;
public static MessageRouteDetailDTO from(MessageRouteDetail msgRouteDetail,
List<MessageRouterConfig> routerConfigs) {
AssertUtil.notNull(msgRouteDetail, "msgRouteDetail can not be null");
AssertUtil.notEmpty(routerConfigs, "routerConfigs can not be empty");
return MessageRouteDetailDTO.builder()
.name(msgRouteDetail.getName())
.templateCode(msgRouteDetail.getTemplateCode())
.showStrategy(msgRouteDetail.getShowStrategy())
.routerConfigs(routerConfigs.stream().map(MessageRouterConfigDTO::from).collect(Collectors.toList()))
.build();
}
public static MessageRouteDetailDTO from(BizDetailShowStrategyDTO bizDetailShowStrategy, String templateCode) {
AssertUtil.notNull(bizDetailShowStrategy, "btnRouter can not be null");
AssertUtil.notEmpty(templateCode, "templateCode can not be empty");
List<MessageRouterConfigDTO> configs = bizDetailShowStrategy.getTerminals().stream()
.map(e -> MessageRouterConfigDTO.builder().url(e.getUrl()).terminalType(e.getTerminalType()).build())
.collect(Collectors.toList());
return MessageRouteDetailDTO.builder()
.name("详情")
.templateCode(templateCode)
.showStrategy(bizDetailShowStrategy.getShowStrategy())
.routerConfigs(configs)
.build();
}
public MessageRouteDetail fetchMessageRouteDetail() {
return MessageRouteDetail.builder()
.name(this.name)
.showStrategy(this.showStrategy)
.templateCode(this.templateCode)
.build();
}
public List<MessageRouterConfig> fetchMessageRouterConfigs() {
return CollectionUtils.isEmpty(this.routerConfigs) ? Collections.emptyList() :
this.routerConfigs.stream()
.map(MessageRouterConfigDTO::fetchMessageRouterConfig)
.collect(Collectors.toList());
}
public BizDetailShowStrategyDTO toBizDetailShowStrategyDTO() {
List<MessageRouterTerminalDTO> terminals = this.routerConfigs.stream()
.map(e -> MessageRouterTerminalDTO.builder().terminalType(e.terminalType).url(e.url).build())
.collect(Collectors.toList());
return BizDetailShowStrategyDTO.builder().showStrategy(this.showStrategy).terminals(terminals).build();
}
@Override
public String toString() {
return JSON.toJSONString(this);
@ -72,7 +160,7 @@ public class MessageTemplateRouterDTO implements Serializable {
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class MessageTemplateRouteButtonDTO implements Serializable {
public static class MessageRouteButtonDTO implements Serializable {
private static final long serialVersionUID = -7544674409859277745L;
@ -95,7 +183,7 @@ public class MessageTemplateRouterDTO implements Serializable {
/**
* 路由类型
*/
private MessageCategoryEnum category;
private RouterCategoryEnum category;
/**
* API地址,仅当按钮是接口调用类型时有值
*/
@ -108,6 +196,94 @@ public class MessageTemplateRouterDTO implements Serializable {
* 按钮style配置
*/
private JSONObject style;
/**
* 按钮优先级数值越大优先级越低
*/
private Integer priority;
public static MessageRouteButtonDTO from(MessageRouteButton routeButton,
List<MessageRouterConfig> routerConfigs) {
AssertUtil.notNull(routeButton, "msgRouteDetail can not be null");
AssertUtil.notEmpty(routerConfigs, "routerConfigs can not be empty");
List<MessageRouterConfigDTO> configs = CollectionUtils.isEmpty(routerConfigs) ? Collections.emptyList() :
routerConfigs.stream().map(MessageRouterConfigDTO::from).collect(Collectors.toList());
return MessageRouteButtonDTO.builder()
.name(routeButton.getName())
.btnCode(routeButton.getBtnCode())
.templateCode(routeButton.getTemplateCode())
.source(routeButton.getSource())
.category(routeButton.getCategory())
.apiUrl(routeButton.getApiUrl())
.style(routeButton.getStyle())
.priority(routeButton.getPriority())
.routerConfigs(configs)
.build();
}
public static MessageRouteButtonDTO from(MessageRouterButtonDTO btnRouter, String templateCode) {
AssertUtil.notNull(btnRouter, "btnRouter can not be null");
AssertUtil.notEmpty(templateCode, "templateCode can not be empty");
JSONObject style = CollectionUtils.isEmpty(btnRouter.getStyle()) ? null
: JSON.parseObject(JSON.toJSONString(btnRouter.getStyle()));
List<MessageRouterConfigDTO> routerConfigs = CollectionUtils.isEmpty(btnRouter.getTerminals()) ? null :
btnRouter.getTerminals().stream()
.map(e -> MessageRouterConfigDTO.builder().url(e.getUrl()).terminalType(e.getTerminalType()).build())
.collect(Collectors.toList());
return MessageRouteButtonDTO.builder()
.name(btnRouter.getDesc())
.btnCode(btnRouter.getIdentityCode())
.templateCode(templateCode)
.source(btnRouter.getSource())
.category(btnRouter.getCategory())
.apiUrl(btnRouter.getApiUrl())
.routerConfigs(routerConfigs)
.style(style)
.build();
}
public MessageRouteButton fetchMessageRouteButton() {
return MessageRouteButton.builder()
.name(this.name)
.btnCode(this.btnCode)
.templateCode(this.templateCode)
.source(this.source)
.category(this.category)
.apiUrl(this.apiUrl)
.style(this.style)
.build();
}
public List<MessageRouterConfig> fetchMessageRouterConfigs() {
return CollectionUtils.isEmpty(this.routerConfigs) ? Collections.emptyList() :
this.routerConfigs.stream()
.map(MessageRouterConfigDTO::fetchMessageRouterConfig)
.collect(Collectors.toList());
}
public boolean isValid() {
if (RouterCategoryEnum.ACTION.equals(this.category)) {
return StringUtils.isNotBlank(apiUrl);
}
return CollectionUtils.isNotEmpty(routerConfigs);
}
public MessageRouterButtonDTO toMessageRouterButton() {
List<MessageRouterTerminalDTO> terminals = CollectionUtils.isEmpty(this.routerConfigs) ?
Collections.emptyList() : this.routerConfigs.stream()
.map(e -> MessageRouterTerminalDTO.builder().terminalType(e.terminalType).url(e.url).build())
.collect(Collectors.toList());
return MessageRouterButtonDTO.builder()
.desc(this.name)
.category(this.category)
.identityCode(this.btnCode)
.source(this.source)
.style(MessageRouterUtil.parseButtonStyle(this.style))
.apiUrl(this.apiUrl)
.terminals(terminals)
.build();
}
@Override
public String toString() {
@ -136,6 +312,22 @@ public class MessageTemplateRouterDTO implements Serializable {
*/
private String url;
static MessageRouterConfigDTO from(MessageRouterConfig config) {
return MessageRouterConfigDTO.builder()
.routerCode(config.getRouterCode())
.terminalType(config.getTerminalType())
.url(config.getUrl())
.build();
}
MessageRouterConfig fetchMessageRouterConfig() {
return MessageRouterConfig.builder()
.routerCode(this.routerCode)
.terminalType(this.terminalType)
.url(this.url)
.build();
}
@Override
public String toString() {
return JSON.toJSONString(this);

View File

@ -2,7 +2,6 @@ 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;
@ -16,7 +15,6 @@ import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
/**
@ -86,7 +84,7 @@ public class PendingMessageDTO implements Serializable {
/**
* 路由信息,可为空
*/
private List<MessageRouterDTO> routers;
private MessageTemplateRouterDTO msgTemplateRouter;
/**
* 参数及其对应的值的JSON串
*/
@ -141,7 +139,8 @@ public class PendingMessageDTO implements Serializable {
.bizCategory(this.bizCategory)
.createTimestamp(DateFormatUtil.toTimestamp(this.createTime))
.updateTimestamp(DateFormatUtil.toTimestamp(this.updateTime))
.routers(this.routers)
// TODO:[cold_blade] [P0]
// .routers(this.routers)
.routerParams(this.routerParams)
.bizExtParams("{}")
.build();

View File

@ -60,28 +60,6 @@ public class RawMessageRouterDTO implements Serializable {
*/
private List<ButtonStyleEnum> style;
public static RawMessageRouterDTO from(List<MessageTemplateRouter> msgTemplateRouters) {
MessageTemplateRouter router = msgTemplateRouters.get(0);
List<MessageRouterTerminalDTO> terminals = msgTemplateRouters.stream()
.map(RawMessageRouterDTO::convert2Terminal)
.collect(Collectors.toList());
return RawMessageRouterDTO.builder()
.desc(router.getName())
.category(router.getCategory())
.templateCode(router.getTemplateCode())
.style(MessageRouterUtil.parseButtonStyle(router.getStyle()))
.terminals(terminals)
.build();
}
public static RawMessageRouterDTO from(BizDetailShowStrategyDTO showStrategy, String templateCode) {
return RawMessageRouterDTO.builder()
.desc("业务详情展示策略")
.category(RouterCategoryEnum.DETAIL)
.terminals(showStrategy.getTerminals())
.templateCode(templateCode)
.build();
}
public static RawMessageRouterDTO from(MessageRouterButtonDTO router, String templateCode) {
return RawMessageRouterDTO.builder()

View File

@ -1,9 +1,11 @@
package cn.axzo.msg.center.message.domain.vo;
import cn.axzo.msg.center.domain.entity.GeneralMessageRecord;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO;
import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO;
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
import cn.axzo.msg.center.service.enums.ButtonStyleEnum;
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.Lists;
import lombok.AllArgsConstructor;
@ -17,6 +19,7 @@ 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;
import java.util.stream.Collectors;
@ -80,19 +83,10 @@ public class GeneralMessagePushVO implements Serializable {
private Long sendTimestamp;
public static GeneralMessagePushVO from(GeneralMessageRecord record, String templateIcon, String orgIcon,
List<MessageRouterButtonDTO> routerButtons,
MessageTemplateRouterDTO msgTemplateRouter,
List<MessageCardContentItemDTO> cardContentItems) {
CardButton cardDetailButton = CollectionUtils.isEmpty(routerButtons) ? null : routerButtons.stream()
.filter(e -> RouterCategoryEnum.DETAIL.equals(e.getCategory()))
.findFirst()
.map(CardButton::from)
.orElse(null);
List<CardButton> cardButtons = CollectionUtils.isEmpty(routerButtons) ? Collections.emptyList() :
routerButtons.stream()
.filter(e -> !RouterCategoryEnum.DETAIL.equals(e.getCategory()))
.filter(MessageRouterButtonDTO::isShowOnCard)
.map(CardButton::from)
.collect(Collectors.toList());
CardButton cardDetailButton = parseDetailButton(msgTemplateRouter);
List<CardButton> cardButtons = parseCardButtons(msgTemplateRouter);
List<CardExtensionItem> cardExtension = CollectionUtils.isEmpty(cardContentItems) ? Collections.emptyList() :
cardContentItems.stream()
.map(CardExtensionItem::from)
@ -117,6 +111,23 @@ public class GeneralMessagePushVO implements Serializable {
.build();
}
private static CardButton parseDetailButton(MessageTemplateRouterDTO msgTemplateRouter) {
if (Objects.isNull(msgTemplateRouter) || Objects.isNull(msgTemplateRouter.getRouteDetail())) {
return null;
}
return CardButton.from(msgTemplateRouter.getRouteDetail());
}
private static List<CardButton> parseCardButtons(MessageTemplateRouterDTO msgTemplateRouter) {
if (Objects.isNull(msgTemplateRouter)
|| CollectionUtils.isEmpty(msgTemplateRouter.getRouteButtons())) {
return Collections.emptyList();
}
return msgTemplateRouter.getRouteButtons().stream()
.map(CardButton::from)
.collect(Collectors.toList());
}
@Override
public String toString() {
return JSON.toJSONString(this);
@ -178,12 +189,34 @@ public class GeneralMessagePushVO implements Serializable {
*/
private List<ButtonAction> actionPaths;
static CardButton from(MessageRouterButtonDTO routerButton) {
static CardButton from(MessageTemplateRouterDTO.MessageRouteDetailDTO routeDetail) {
return CardButton.builder()
.title(routerButton.getDesc())
.title(routeDetail.getName())
.action(RouterCategoryEnum.JUMP.name())
.isHighlight(false)
.actionPaths(routeDetail.getRouterConfigs().stream()
.map(e -> new ButtonAction(e.getTerminalType().name(), e.getUrl()))
.collect(Collectors.toList())
).build();
}
static CardButton from(MessageTemplateRouterDTO.MessageRouteButtonDTO routerButton) {
List<ButtonStyleEnum> buttonStyles = Objects.isNull(routerButton.getStyle()) ? Collections.emptyList() :
JSON.parseArray(routerButton.getStyle().toJSONString(), ButtonStyleEnum.class);
if (RouterCategoryEnum.ACTION.equals(routerButton.getCategory())) {
return CardButton.builder()
.title(routerButton.getName())
.action(routerButton.getCategory().name())
.isHighlight(buttonStyles.stream().allMatch(ButtonStyleEnum.HIGH_LIGHT::equals))
.actionPaths(Lists.newArrayList(
new ButtonAction(TerminalTypeEnum.WEB_VIEW.name(), routerButton.getApiUrl())))
.build();
}
return CardButton.builder()
.title(routerButton.getName())
.action(routerButton.getCategory().name())
.isHighlight(routerButton.isHighlight())
.actionPaths(routerButton.getTerminals().stream()
.isHighlight(buttonStyles.stream().allMatch(ButtonStyleEnum.HIGH_LIGHT::equals))
.actionPaths(routerButton.getRouterConfigs().stream()
.map(e -> new ButtonAction(e.getTerminalType().name(), e.getUrl()))
.collect(Collectors.toList())
).build();

View File

@ -1,10 +1,11 @@
package cn.axzo.msg.center.message.service;
import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO;
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* @description
@ -14,30 +15,23 @@ import java.util.Map;
* @date 2023/9/28
* @version 1.0
*/
public interface MessageTemplateRouterService {//TODO:[cold_blade] P0路由模型改版
public interface MessageTemplateRouterService {
/**
* 根据消息模板编码查询配置的路由列表
* 根据消息模板编码查询配置的路由
*
* @param templateCode 消息模板编码
* @return 路由列表
* @return 路由
*/
List<RawMessageRouterDTO> queryByTemplateCode(String templateCode);
Optional<MessageTemplateRouterDTO> queryByTemplateCode(String templateCode);
/**
* 批量插入模板路由
* 保存OR更新消息模板的路由
*
* @param routers 路由列表
* @param router 路由配置
* @param isUpdate 是否更新
*/
void batchInsert(List<RawMessageRouterDTO> routers);
/**
* 更新模板的路由信息
*
* @param templateCode 模板编码
* @param routers 路由列表
*/
void updateTemplateRoutes(String templateCode, List<MessageRouterButtonDTO> routers);
void saveOrUpdate(MessageTemplateRouterDTO router, boolean isUpdate);
/**
* 根据消息模板编码查询配置的路由列表
@ -45,5 +39,5 @@ public interface MessageTemplateRouterService {//TODO:[cold_blade] P0路由模
* @param templateCodes 消息模板编码列表
* @return 路由列表
*/
Map<String, List<RawMessageRouterDTO>> groupByTemplateCode(List<String> templateCodes);
Map<String, MessageTemplateRouterDTO> groupByTemplateCode(Collection<String> templateCodes);
}

View File

@ -14,7 +14,7 @@ import cn.axzo.msg.center.domain.entity.GeneralMessageRecord;
import cn.axzo.msg.center.domain.enums.UserTypeEnum;
import cn.axzo.msg.center.inside.notices.config.MessageSystemConfig;
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.MessageTemplateRouterDTO;
import cn.axzo.msg.center.message.domain.dto.SendImMessageDTO;
import cn.axzo.msg.center.message.domain.vo.GeneralMessagePushVO;
import cn.axzo.msg.center.message.service.GeneralMessageOldService;
@ -23,7 +23,6 @@ import cn.axzo.msg.center.message.service.MessageSendTwiceRecordService;
import cn.axzo.msg.center.message.service.MessageTemplateNewService;
import cn.axzo.msg.center.service.dto.IdentityDTO;
import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO;
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
import cn.axzo.msg.center.service.dto.PersonDTO;
import cn.axzo.msg.center.service.enums.GeneralMessageStateEnum;
import cn.axzo.msg.center.service.enums.IdentityTypeEnum;
@ -181,15 +180,9 @@ public class GeneralMessageServiceImpl implements GeneralMessageService {
private GeneralMessagePushVO convert(GeneralMessageRecord record, MessageTemplateDTO template) {
// 对应模板的路由列表
List<RawMessageRouterDTO> rawRouters = template.getRouters();
MessageTemplateRouterDTO msgTemplateRouter = template.getMsgTemplateRouter();
// 解析路由地址
List<RawMessageRouterDTO> routers = rawRouters.stream()
.map(e -> MessageRouterUtil.parseAndConcatRouteUrl(e, record.getRouterParams()))
.collect(Collectors.toList());
// 转化成客户端展示的数据模型
List<MessageRouterButtonDTO> routerButtons = routers.stream()
.map(RawMessageRouterDTO::toMessageRouterButton)
.collect(Collectors.toList());
msgTemplateRouter = MessageRouterUtil.parseAndConcatRouteUrl(msgTemplateRouter, record.getRouterParams());
// 获取模板卡片信息
List<MessageCardContentItemDTO> rawCardContentItems = template.getMsgCardContentItems();
List<MessageCardContentItemDTO> cardContentItems = rawCardContentItems;
@ -205,7 +198,8 @@ public class GeneralMessageServiceImpl implements GeneralMessageService {
e.setValue(value);
});
}
return GeneralMessagePushVO.from(record, template.getIcon(), messageSystemConfig.getOrgIcon(), routerButtons, cardContentItems);
return GeneralMessagePushVO
.from(record, template.getIcon(), messageSystemConfig.getOrgIcon(), msgTemplateRouter, cardContentItems);
}
private String parseString(String string, JSONObject params) {

View File

@ -9,18 +9,17 @@ import cn.axzo.msg.center.dal.MessageBaseTemplateDao;
import cn.axzo.msg.center.domain.entity.MessageBaseTemplate;
import cn.axzo.msg.center.message.domain.dto.GroupTreeNodePathDTO;
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.MessageTemplateRouterDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouteButtonDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouteDetailDTO;
import cn.axzo.msg.center.message.domain.param.MessageTemplateSaveOrUpdateParam;
import cn.axzo.msg.center.message.service.MessageGroupNodeService;
import cn.axzo.msg.center.message.service.MessageTemplateGroupService;
import cn.axzo.msg.center.message.service.MessageTemplateNewService;
import cn.axzo.msg.center.message.service.MessageTemplateRouterService;
import cn.axzo.msg.center.service.dto.BizDetailShowStrategyDTO;
import cn.axzo.msg.center.service.dto.MessageBaseTemplateDTO;
import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO;
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
import cn.axzo.msg.center.service.enums.PushTerminalEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import cn.axzo.msg.center.service.enums.StatusEnum;
import cn.axzo.msg.center.service.template.request.MessageTemplatePageRequest;
import cn.axzo.msg.center.service.template.response.MessageTemplateDetailResponse;
@ -75,6 +74,7 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
@Override
@Transactional(rollbackFor = Exception.class)
public String createTemplate(MessageTemplateSaveOrUpdateParam param) {
// 参数检测 TODO:[cold_blade] [P0]
// 创建模板基础数据
String templateCode = saveTemplate(param);
// 创建模板的路由数据
@ -111,8 +111,10 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
// 获取模板关联分类的path列表
List<String> groupNodePaths = messageTemplateGroupService.listMessageTemplateGroupPaths(
Lists.newArrayList(templateCode)).getOrDefault(templateCode, Collections.emptyList());
List<RawMessageRouterDTO> routers = messageTemplateRouterService.queryByTemplateCode(templateCode);
return convert(baseTemplate, groupNodePaths, routers);
// 获取模板配置的路由信息
MessageTemplateRouterDTO msgTemplateRouter = messageTemplateRouterService.queryByTemplateCode(templateCode)
.orElse(null);
return convert(baseTemplate, groupNodePaths, msgTemplateRouter);
}
@Override
@ -143,8 +145,10 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
log.info("not find the [{}] template.", msgTemplateCode);
return Optional.empty();
}
List<RawMessageRouterDTO> routers = messageTemplateRouterService.queryByTemplateCode(msgTemplateCode);
return Optional.of(MessageTemplateDTO.from(msgBaseTemplate, routers));
// 获取模板的路由配置信息
MessageTemplateRouterDTO msgTemplateRouter = messageTemplateRouterService.queryByTemplateCode(msgTemplateCode)
.orElse(null);
return Optional.of(MessageTemplateDTO.from(msgBaseTemplate, msgTemplateRouter));
}
@Override
@ -161,10 +165,10 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
log.info("not find the [{}] templates.", msgTemplateCodes);
return Collections.emptyList();
}
Map<String, List<RawMessageRouterDTO>> templateRouterMap = messageTemplateRouterService
Map<String, MessageTemplateRouterDTO> templateRouterMap = messageTemplateRouterService
.groupByTemplateCode(msgTemplateCodes);
return msgBaseTemplates.stream()
.map(e -> MessageTemplateDTO.from(e, templateRouterMap.getOrDefault(e.getCode(), Collections.emptyList())))
.map(e -> MessageTemplateDTO.from(e, templateRouterMap.get(e.getCode())))
.collect(Collectors.toList());
}
@ -280,19 +284,11 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
}
private void saveTemplateRouters(MessageTemplateSaveOrUpdateParam param, String templateCode) {
List<RawMessageRouterDTO> routers = Lists.newArrayList();
if (Objects.nonNull(param.getBizDetailShowStrategy())
&& CollectionUtils.isNotEmpty(param.getBizDetailShowStrategy().getTerminals())) {
routers.add(RawMessageRouterDTO.from(param.getBizDetailShowStrategy(), templateCode));
MessageTemplateRouterDTO templateRouter = buildTemplateRouter(param, templateCode);
if (templateRouter.isValid()) {
// 模板配置了路由的场景
messageTemplateRouterService.saveOrUpdate(templateRouter, false);
}
// TODO: [cold_blade] P0 路由按钮需要解析并新增按钮标识
if (CollectionUtils.isNotEmpty(param.getRouters())) {
List<RawMessageRouterDTO> btnRouters = param.getRouters().stream()
.map(e -> RawMessageRouterDTO.from(e, templateCode))
.collect(Collectors.toList());
routers.addAll(btnRouters);
}
messageTemplateRouterService.batchInsert(routers);
}
private void updateBaseTemplate(MessageTemplateSaveOrUpdateParam param) {
@ -322,21 +318,11 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
}
private void updateTemplateRouters(MessageTemplateSaveOrUpdateParam param) {
// TODO: [cold_blade] P0 路由按钮需要解析并新增按钮标识
List<MessageRouterButtonDTO> routers = Lists.newArrayList();
if (Objects.nonNull(param.getBizDetailShowStrategy())
&& CollectionUtils.isNotEmpty(param.getBizDetailShowStrategy().getTerminals())) {
MessageRouterButtonDTO btn = MessageRouterButtonDTO.builder()
.desc(RouterCategoryEnum.DETAIL.getDesc())
.category(RouterCategoryEnum.DETAIL)
.terminals(param.getBizDetailShowStrategy().getTerminals())
.build();
routers.add(btn);
MessageTemplateRouterDTO templateRouter = buildTemplateRouter(param, param.getTemplateCode());
if (templateRouter.isValid()) {
// 模板修改了路由的场景
messageTemplateRouterService.saveOrUpdate(templateRouter, true);
}
if (CollectionUtils.isNotEmpty(param.getRouters())) {
routers.addAll(param.getRouters());
}
messageTemplateRouterService.updateTemplateRoutes(param.getTemplateCode(), routers);
}
private IPage<MessageBaseTemplate> pageQueryBaseTemplate(MessageTemplatePageRequest request) {
@ -401,13 +387,11 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
}
private MessageTemplateDetailResponse convert(MessageBaseTemplate record, List<String> groupNodePaths,
List<RawMessageRouterDTO> routers) {
MessageTemplateRouterDTO msgTemplateRouter) {
// 将path解析中解析出分类结点路径叶结点的编码
List<String> groupNodeCodes = groupNodePaths.stream()
.map(GroupTreeNodePathDTO::parseLeafNodeCode)
.collect(Collectors.toList());
// 按钮路由策略
List<MessageRouterButtonDTO> msgRouterButtons = MessageRouterUtil.selectAndConvertRouterButtons(routers);
return MessageTemplateDetailResponse.builder()
.templateName(record.getName())
.category(MessageTemplateCategoryUtil.parentCategory(record.getMsgCategory()))
@ -418,12 +402,27 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
.msgContent(record.getContent())
.cardContentItems(JSONObjectUtil.parseArray(record.getCardContent(), MessageCardContentItemDTO.class))
.msgIcon(record.getIcon())
.routers(msgRouterButtons)
// TODO: [cold_blade] P0
.detailStrategy(null)
.detailStrategy(MessageRouterUtil.fetchBizDetailShowStrategy(msgTemplateRouter).orElse(null))
.routers(MessageRouterUtil.fetchMessageRouterButtons(msgTemplateRouter))
.minAppVersion(record.getMinAppVersion())
.createTimestamp(record.getCreateAt().getTime())
.updateTimestamp(record.getUpdateAt().getTime())
.build();
}
private MessageTemplateRouterDTO buildTemplateRouter(MessageTemplateSaveOrUpdateParam param, String templateCode) {
MessageTemplateRouterDTO templateRouter = MessageTemplateRouterDTO.builder().build();
if (Objects.nonNull(param.getBizDetailShowStrategy())
&& CollectionUtils.isNotEmpty(param.getBizDetailShowStrategy().getTerminals())) {
MessageRouteDetailDTO detailRouter = MessageRouteDetailDTO.from(param.getBizDetailShowStrategy(), templateCode);
templateRouter.setRouteDetail(detailRouter);
}
if (CollectionUtils.isNotEmpty(param.getRouters())) {
List<MessageRouteButtonDTO> btnRouters = param.getRouters().stream()
.map(e -> MessageRouteButtonDTO.from(e, templateCode))
.collect(Collectors.toList());
templateRouter.setRouteButtons(btnRouters);
}
return templateRouter;
}
}

View File

@ -1,21 +1,40 @@
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.framework.core.util.MapUtil;
import cn.axzo.msg.center.dal.MessageRouteButtonDao;
import cn.axzo.msg.center.dal.MessageRouteDetailDao;
import cn.axzo.msg.center.dal.MessageRouterConfigDao;
import cn.axzo.msg.center.domain.entity.MessageRouteButton;
import cn.axzo.msg.center.domain.entity.MessageRouteDetail;
import cn.axzo.msg.center.domain.entity.MessageRouterConfig;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouteButtonDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouteDetailDTO;
import cn.axzo.msg.center.message.service.MessageTemplateRouterService;
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
import com.google.common.collect.Lists;
import cn.axzo.msg.center.service.enums.RouterButtonSourceEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import cn.axzo.msg.center.utils.UUIDUtil;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Getter;
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 org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @description
@ -29,66 +48,258 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class MessageTemplateRouterServiceImpl implements MessageTemplateRouterService {
private final MessageTemplateRouterDao messageTemplateRouterDao;
private final MessageRouteDetailDao messageRouteDetailDao;
private final MessageRouteButtonDao messageRouteButtonDao;
private final MessageRouterConfigDao messageRouterConfigDao;
@Override
public List<RawMessageRouterDTO> queryByTemplateCode(String templateCode) {
public Optional<MessageTemplateRouterDTO> queryByTemplateCode(String templateCode) {
if (StringUtils.isBlank(templateCode)) {
log.warn("the template code is blank.");
return Collections.emptyList();
log.info("templateCode is blank.");
}
return listByTemplateCodes(Lists.newArrayList(templateCode));
MessageTemplateRouterDTO router = MessageTemplateRouterDTO.builder()
.routeDetail(queryDetailRouter(templateCode))
.routeButtons(listButtonRouters(templateCode))
.build();
return router.isValid() ? Optional.of(router) : Optional.empty();
}
@Override
public void batchInsert(List<RawMessageRouterDTO> routers) {
if (CollectionUtils.isEmpty(routers)) {
@Transactional(rollbackFor = Exception.class)
public void saveOrUpdate(MessageTemplateRouterDTO router, boolean isUpdate) {
if (Objects.isNull(router) || router.isInValid()) {
log.info("invalid message template router. router:{}", router);
return;
}
List<MessageTemplateRouter> messageTemplateRouters = routers.stream()
.flatMap(e -> e.toMessageTemplateRouters().stream())
.collect(Collectors.toList());
messageTemplateRouterDao.saveBatch(messageTemplateRouters);
}
@Override
public void updateTemplateRoutes(String templateCode, List<MessageRouterButtonDTO> routers) {
if (StringUtils.isBlank(templateCode)
|| CollectionUtils.isEmpty(routers)) {
log.info("the param is invalid. templateCode:[{}], routers:{}", templateCode, routers);
return;
if (isUpdate) {
// 更新的逻辑为删除旧的重新创建
remove(router.fetchTemplateCode().orElse(null));
}
// 移除之前的路由信息
messageTemplateRouterDao.lambdaUpdate()
.eq(MessageTemplateRouter::getTemplateCode, templateCode)
.remove();
// 创建信息的路由信息
List<RawMessageRouterDTO> newRouters = routers.stream()
.map(e -> RawMessageRouterDTO.from(e, templateCode))
.collect(Collectors.toList());
batchInsert(newRouters);
saveDetailRouter(router.getRouteDetail());
batchSaveButtonRouter(router.getRouteButtons());
}
@Override
public Map<String, List<RawMessageRouterDTO>> groupByTemplateCode(List<String> templateCodes) {
public Map<String, MessageTemplateRouterDTO> groupByTemplateCode(Collection<String> templateCodes) {
if (CollectionUtils.isEmpty(templateCodes)) {
log.info("templateCodes is empty.");
return Collections.emptyMap();
}
return listByTemplateCodes(templateCodes).stream()
.collect(Collectors.groupingBy(RawMessageRouterDTO::getTemplateCode));
Set<String> distinctTemplateCodes = Sets.newHashSet(templateCodes);
Map<String, MessageRouteDetailDTO> detailRouters = listDetailRoutersGroupingByTemplateCode(distinctTemplateCodes);
Map<String, List<MessageRouteButtonDTO>> buttonRouters = listButtonRoutersGroupingByTemplateCode(distinctTemplateCodes);
return distinctTemplateCodes.stream()
.filter(e -> detailRouters.containsKey(e) || buttonRouters.containsKey(e))
.collect(Collectors.toMap(Function.identity(), e -> MessageTemplateRouterDTO.builder()
.routeDetail(detailRouters.get(e))
.routeButtons(buttonRouters.get(e))
.build())
);
}
private List<RawMessageRouterDTO> listByTemplateCodes(List<String> templateCodes) {
// 根据模板编码进行分组
Map<String, List<MessageTemplateRouter>> routers = messageTemplateRouterDao
.listByTemplateCode(templateCodes).stream()
.collect(Collectors.groupingBy(MessageTemplateRouter::getTemplateCode));
return routers.values().stream()
.flatMap(e -> {
// 模板路由的按钮维度
Map<String, List<MessageTemplateRouter>> btnMap = e.stream()
.collect(Collectors.groupingBy(MessageTemplateRouter::getName));
return btnMap.values().stream().map(RawMessageRouterDTO::from);
}).collect(Collectors.toList());
private MessageRouteDetailDTO queryDetailRouter(String templateCode) {
MessageRouteDetail msgRouteDetail = selectRouteDetail(templateCode);
if (Objects.isNull(msgRouteDetail)) {
return null;
}
List<MessageRouterConfig> routerConfigs = listByRouterCode(msgRouteDetail.getTemplateCode());
return MessageRouteDetailDTO.from(msgRouteDetail, routerConfigs);
}
private Map<String, MessageRouteDetailDTO> listDetailRoutersGroupingByTemplateCode(Collection<String> templateCodes) {
Map<String, MessageRouteDetail> routeDetails = listRouteDetailsGroupingByTemplateCode(templateCodes);
if (MapUtil.isEmpty(routeDetails)) {
log.info("there is not any route detail. templateCodes:{}", templateCodes);
return Collections.emptyMap();
}
Map<String, List<MessageRouterConfig>> routerConfigs = groupingByRouterCode(templateCodes);
Map<String, MessageRouteDetailDTO> result = Maps.newHashMap();
routeDetails.entrySet().stream()
.filter(e -> routerConfigs.containsKey(e.getKey()))
.forEach(e -> result.put(e.getKey(), MessageRouteDetailDTO.from(e.getValue(), routerConfigs.get(e.getKey()))));
return result;
}
private List<MessageRouteButtonDTO> listButtonRouters(String templateCode) {
List<MessageRouteButton> routeButtons = messageRouteButtonDao.lambdaQuery()
.eq(MessageRouteButton::getTemplateCode, templateCode)
.list();
if (CollectionUtils.isEmpty(routeButtons)) {
log.info("the is not any router button. templateCode:[{}]", templateCode);
return Collections.emptyList();
}
List<String> btnCodes = routeButtons.stream().map(MessageRouteButton::getBtnCode).collect(Collectors.toList());
Map<String, List<MessageRouterConfig>> btnRouterConfigs = groupingByRouterCode(btnCodes);
return routeButtons.stream()
.map(e -> MessageRouteButtonDTO.from(e, btnRouterConfigs.get(e.getBtnCode())))
.collect(Collectors.toList());
}
private Map<String, List<MessageRouteButtonDTO>> listButtonRoutersGroupingByTemplateCode(
Collection<String> templateCodes) {
List<MessageRouteButton> routeButtons = messageRouteButtonDao.lambdaQuery()
.in(MessageRouteButton::getTemplateCode, templateCodes)
.list();
if (CollectionUtils.isEmpty(routeButtons)) {
log.info("the is not any router button. templateCodes:{}", templateCodes);
return Collections.emptyMap();
}
Set<String> btnCodes = routeButtons.stream().map(MessageRouteButton::getBtnCode).collect(Collectors.toSet());
Map<String, List<MessageRouterConfig>> btnRouterConfigs = groupingByRouterCode(btnCodes);
return routeButtons.stream()
.map(e -> MessageRouteButtonDTO.from(e, btnRouterConfigs.get(e.getBtnCode())))
.collect(Collectors.groupingBy(MessageRouteButtonDTO::getTemplateCode));
}
private MessageRouteDetail selectRouteDetail(String templateCode) {
List<MessageRouteDetail> msgRouteDetails = messageRouteDetailDao.lambdaQuery()
.eq(MessageRouteDetail::getTemplateCode, templateCode)
.orderByDesc(MessageRouteDetail::getId)
.list();
if (CollectionUtils.isEmpty(msgRouteDetails)) {
return null;
}
if (msgRouteDetails.size() > 1) {
log.warn("there is some dirty data in table:[message_route_detail]");
}
return msgRouteDetails.get(0);
}
private Map<String, MessageRouteDetail> listRouteDetailsGroupingByTemplateCode(Collection<String> templateCodes) {
List<MessageRouteDetail> msgRouteDetails = messageRouteDetailDao.lambdaQuery()
.in(MessageRouteDetail::getTemplateCode, templateCodes)
.orderByDesc(MessageRouteDetail::getId)
.list();
if (CollectionUtils.isEmpty(msgRouteDetails)) {
return Collections.emptyMap();
}
Map<String, List<MessageRouteDetail>> groupingBy = msgRouteDetails.stream()
.collect(Collectors.groupingBy(MessageRouteDetail::getTemplateCode));
Map<String, MessageRouteDetail> result = Maps.newHashMap();
for (List<MessageRouteDetail> elem : groupingBy.values()) {
MessageRouteDetail detail = elem.get(0);
result.put(detail.getTemplateCode(), detail);
if (msgRouteDetails.size() > 1) {
log.warn("there is some dirty data in table:[message_route_detail]. templateCode:[{}]",
elem.get(0).getTemplateCode());
}
}
return result;
}
private List<MessageRouterConfig> listByRouterCode(String routerCode) {
if (StringUtils.isBlank(routerCode)) {
log.info("routerCode is blank.");
return Collections.emptyList();
}
return messageRouterConfigDao.lambdaQuery()
.eq(MessageRouterConfig::getRouterCode, routerCode)
.list();
}
private Map<String, List<MessageRouterConfig>> groupingByRouterCode(Collection<String> routerCodes) {
if (CollectionUtils.isEmpty(routerCodes)) {
log.info("routerCodes is empty.");
return Collections.emptyMap();
}
return messageRouterConfigDao.lambdaQuery()
.in(MessageRouterConfig::getRouterCode, routerCodes)
.list().stream()
.collect(Collectors.groupingBy(MessageRouterConfig::getRouterCode));
}
private void saveDetailRouter(MessageRouteDetailDTO detailRouter) {
if (Objects.isNull(detailRouter)) {
log.info("detailRouter is null.");
return;
}
messageRouteDetailDao.save(detailRouter.fetchMessageRouteDetail());
messageRouterConfigDao.saveBatch(detailRouter.fetchMessageRouterConfigs());
}
private void batchSaveButtonRouter(List<MessageRouteButtonDTO> buttonRouters) {
if (CollectionUtils.isEmpty(buttonRouters)) {
log.info("buttonRouters is empty.");
return;
}
List<MessageRouteButtonWrapper> routeButtonWrappers = buttonRouters.stream()
.filter(MessageRouteButtonDTO::isValid)
.map(e -> MessageRouteButtonWrapper.of(e.fetchMessageRouteButton(), e))
.collect(Collectors.toList());
// 生成自定义按钮的唯一标识和顺序
buildButtonCodeAndPriority(routeButtonWrappers);
// 保存模板对应的按钮路由
List<MessageRouteButton> routeButtons = routeButtonWrappers.stream()
.map(MessageRouteButtonWrapper::getRouteButton)
.collect(Collectors.toList());
messageRouteButtonDao.saveBatch(routeButtons);
List<MessageRouterConfig> routerConfigs = routeButtonWrappers.stream()
.filter(e -> RouterCategoryEnum.JUMP.equals(e.getButtonRouter().getCategory()))
.flatMap(this::routerConfigStream)
.collect(Collectors.toList());
messageRouterConfigDao.saveBatch(routerConfigs);
}
private void buildButtonCodeAndPriority(List<MessageRouteButtonWrapper> routeButtonWrappers) {
for (int i = 0; i < routeButtonWrappers.size(); i++) {
MessageRouteButton button = routeButtonWrappers.get(i).getRouteButton();
if (RouterButtonSourceEnum.CUSTOM.equals(button.getSource())) {
// 这里仅对自定义的按钮设置按钮标识
button.setBtnCode(UUIDUtil.uuidString());
}
// 优先级默认从1开始
button.setPriority(i + 1);
}
}
private Stream<MessageRouterConfig> routerConfigStream(MessageRouteButtonWrapper routeButtonWrapper) {
// 获取对应按钮的唯一标识
String btnCode = routeButtonWrapper.getRouteButton().getBtnCode();
// 转化为存储的数据模型
List<MessageRouterConfig> routerConfigs = routeButtonWrapper.buttonRouter.fetchMessageRouterConfigs();
// 将按钮唯一标识与路由跳转配置进行映射
routerConfigs.forEach(e -> e.setRouterCode(btnCode));
return routerConfigs.stream();
}
private void remove(String templateCode) {
if (StringUtils.isBlank(templateCode)) {
log.info("===remove=== templateCode is blank.");
return;
}
Set<String> routerCodes = Sets.newHashSet();
// 查询对应模板的路由按钮
Set<String> btnCodes = messageRouteButtonDao.lambdaQuery()
.eq(MessageRouteButton::getTemplateCode, templateCode)
.select(MessageRouteButton::getBtnCode)
.list().stream().map(MessageRouteButton::getBtnCode).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(btnCodes)) {
// 逻辑删除该模板对应的路由按钮
messageRouteButtonDao.lambdaUpdate().eq(MessageRouteButton::getTemplateCode, templateCode).remove();
routerCodes.addAll(btnCodes);
}
// 逻辑删除业务详情路由
boolean result = messageRouteDetailDao.lambdaUpdate()
.eq(MessageRouteDetail::getTemplateCode, templateCode)
.remove();
if (result) {
routerCodes.add(templateCode);
}
if (CollectionUtils.isEmpty(routerCodes)) {
return;
}
// 逻辑删除该模板对应的路由按钮的URL相关配置
messageRouterConfigDao.lambdaUpdate().in(MessageRouterConfig::getRouterCode, routerCodes).remove();
}
@Getter
@AllArgsConstructor
private static class MessageRouteButtonWrapper {
private MessageRouteButton routeButton;
private MessageRouteButtonDTO buttonRouter;
static MessageRouteButtonWrapper of(MessageRouteButton routeButton, MessageRouteButtonDTO buttonRouter) {
return new MessageRouteButtonWrapper(routeButton, buttonRouter);
}
}
}

View File

@ -7,8 +7,8 @@ import cn.axzo.msg.center.dal.PendingMessageRecordDao;
import cn.axzo.msg.center.domain.entity.PendingMessageRecord;
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.MessageTemplateRouterDTO;
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.MessageGroupNodeService;
@ -17,7 +17,6 @@ import cn.axzo.msg.center.message.service.MessageTemplateNewService;
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.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;
@ -28,7 +27,6 @@ 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.JSONObjectUtil;
import cn.axzo.msg.center.utils.MessageRouterUtil;
import cn.axzo.msg.center.utils.OrderFieldParseUtil;
import cn.axzo.msg.center.utils.TreeHelperUtil;
import cn.axzo.msg.center.utils.UUIDUtil;
@ -46,7 +44,6 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
@ -167,20 +164,12 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
List<MessageTemplateDTO> messageTemplates) {
PendingMessageDTO pendingMessage = PendingMessageDTO.from(pendingMessageRecord);
// 对应模板的路由列表
List<RawMessageRouterDTO> rawRouters = messageTemplates.stream()
MessageTemplateRouterDTO msgTemplateRouter = messageTemplates.stream()
.filter(e -> Objects.equals(e.getCode(), pendingMessageRecord.getTemplateCode()))
.findFirst()
.map(MessageTemplateDTO::getRouters)
.orElseGet(Collections::emptyList);
List<MessageRouterDTO> routers = rawRouters.stream()
.map(e -> {
MessageRouterDTO router = e.toMessageRouter(terminalType);
// 视情况替换原始URL中的参数变量
MessageRouterUtil.parseRouteUrl(router, pendingMessageRecord.getRouterParams());
return router;
})
.collect(Collectors.toList());
pendingMessage.setRouters(routers);
.map(MessageTemplateDTO::getMsgTemplateRouter)
.orElse(null);
pendingMessage.setMsgTemplateRouter(msgTemplateRouter);
// 获取模板卡片信息
String cardContent = messageTemplates.stream()
.filter(e -> Objects.equals(e.getCode(), pendingMessageRecord.getTemplateCode()))
@ -316,9 +305,4 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
record.setBizCategory(param.getBizCategory());
record.setBizExtParam(JSONObjectUtil.checkAndReturn(param.getBizExtParams()));
}
private static class GroupTreeNodeWrapper {
private GroupTreeNodeDTO treeNode;
private int pendingCnt;
}
}

View File

@ -12,19 +12,19 @@ import cn.axzo.msg.center.domain.entity.RelationTemplateMap;
import cn.axzo.msg.center.inside.notices.service.MessageRelationService;
import cn.axzo.msg.center.inside.notices.service.MessageRouterService;
import cn.axzo.msg.center.inside.notices.service.MessageTemplateService;
import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouteDetailDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouterConfigDTO;
import cn.axzo.msg.center.message.domain.param.RelationTemplateMapInitParam;
import cn.axzo.msg.center.message.service.MessageTemplateGroupService;
import cn.axzo.msg.center.message.service.MessageTemplateRouterService;
import cn.axzo.msg.center.message.service.RelationTemplateMapService;
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
import cn.axzo.msg.center.service.dto.MessageRouterTerminalDTO;
import cn.axzo.msg.center.service.enums.ButtonStyleEnum;
import cn.axzo.msg.center.service.enums.BizDetailShowStrategyEnum;
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
import cn.axzo.msg.center.service.enums.PushTerminalEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import cn.axzo.msg.center.utils.JSONObjectUtil;
import cn.axzo.msg.center.utils.MessageRouterUtil;
import cn.axzo.msg.center.utils.UUIDUtil;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
@ -145,9 +145,10 @@ public class RelationTemplateMapServiceImpl implements RelationTemplateMapServic
// 批量插入
messageBaseTemplateDao.saveBatch(wrappers.stream()
.map(CreateNewTemplateAndMapWrapper::getBaseTemplate).collect(Collectors.toList()));
messageTemplateRouterService.batchInsert(wrappers.stream()
.filter(e -> CollectionUtils.isNotEmpty(e.getRouters()))
.flatMap(e -> e.getRouters().stream()).collect(Collectors.toList()));
// TODO: [cold_blade] P0
// messageTemplateRouterService.batchInsert(wrappers.stream()
// .filter(e -> CollectionUtils.isNotEmpty(e.getRouters()))
// .flatMap(e -> e.getRouters().stream()).collect(Collectors.toList()));
List<String> groupNodes = Lists.newArrayList(param.getGroupNodeCode());
Map<String, List<String>> templateGroupNodeMap = wrappers.stream()
.map(CreateNewTemplateAndMapWrapper::getBaseTemplate)
@ -170,12 +171,28 @@ public class RelationTemplateMapServiceImpl implements RelationTemplateMapServic
.relationId(relationId)
.build();
if (CollectionUtils.isNotEmpty(routers)) {
wrapper.setRouters(Lists.newArrayList(
RawMessageRouterDTO.from(convert(routers), baseTemplate.getCode())));
wrapper.setMsgTemplateRouter(convert2MessageTemplateRouter(routers, baseTemplate.getCode()));
}
return wrapper;
}
private MessageTemplateRouterDTO convert2MessageTemplateRouter(List<MessageRouter> routers, String templateCode) {
List<MessageRouterConfigDTO> routerConfigs = routers.stream()
.map(e -> MessageRouterConfigDTO.builder()
.routerCode(templateCode)
.terminalType(TerminalTypeEnum.codeOf(e.getRouterType().getCode()))
.url(e.getRouterUrl())
.build())
.collect(Collectors.toList());
MessageRouteDetailDTO detailRouter = MessageRouteDetailDTO.builder()
.name(MessageRouterUtil.DETAIL_ROUTER_DESC)
.templateCode(templateCode)
.showStrategy(BizDetailShowStrategyEnum.JUMP_TO)
.routerConfigs(routerConfigs)
.build();
return MessageTemplateRouterDTO.builder().routeDetail(detailRouter).build();
}
private MessageBaseTemplate convert(MessageTemplate srcTemplate) {
MessageBaseTemplate template = new MessageBaseTemplate();
template.setCode(UUIDUtil.uuidString());
@ -190,22 +207,6 @@ public class RelationTemplateMapServiceImpl implements RelationTemplateMapServic
return template;
}
private MessageRouterButtonDTO convert(List<MessageRouter> routers) {
return MessageRouterButtonDTO.builder()
.style(Lists.newArrayList(ButtonStyleEnum.values()))
.desc("查看详情")
.category(RouterCategoryEnum.DETAIL)
.terminals(routers.stream().map(this::convert).collect(Collectors.toList()))
.build();
}
private MessageRouterTerminalDTO convert(MessageRouter router) {
return MessageRouterTerminalDTO.builder()
.url(router.getRouterUrl())
.terminalType(TerminalTypeEnum.codeOf(router.getRouterType().getCode()))
.build();
}
private Set<Long> getAllOriginalRelationIds() {
return relationTemplateMapDao.lambdaQuery()
.select(RelationTemplateMap::getOriginalRelationId)
@ -220,6 +221,6 @@ public class RelationTemplateMapServiceImpl implements RelationTemplateMapServic
private static class CreateNewTemplateAndMapWrapper {
private Long relationId;
private MessageBaseTemplate baseTemplate;
private List<RawMessageRouterDTO> routers;
private MessageTemplateRouterDTO msgTemplateRouter;
}
}

View File

@ -1,12 +1,15 @@
package cn.axzo.msg.center.utils;
import cn.axzo.msg.center.common.utils.BeanConvertUtils;
import cn.axzo.msg.center.common.utils.PlaceholderResolver;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouteButtonDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouteDetailDTO;
import cn.axzo.msg.center.message.domain.dto.RawMessageRouterDTO;
import cn.axzo.msg.center.service.dto.BizDetailShowStrategyDTO;
import cn.axzo.msg.center.service.dto.MessageRouterButtonDTO;
import cn.axzo.msg.center.service.dto.MessageRouterDTO;
import cn.axzo.msg.center.service.dto.MessageRouterTerminalDTO;
import cn.axzo.msg.center.service.enums.BizDetailShowStrategyEnum;
import cn.axzo.msg.center.service.enums.ButtonStyleEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
@ -14,6 +17,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Collections;
@ -21,6 +25,8 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
@ -34,52 +40,54 @@ import java.util.stream.Collectors;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class MessageRouterUtil {
public static final String DETAIL_ROUTER_DESC = "查看详情";
// 非法路由参数的定义
private static final String INVALID_ROUTER_PARAM = "null";
/**
* 获取业务展示详情策略
* 获取业务详情路由策略
*
* @param showStrategy 展示策略
* @param routers 路由列表
* @param msgTemplateRouter 模板路由配置
* @return 业务展示详情策略
*/
public static Optional<BizDetailShowStrategyDTO> selectAndConvertBizDetailShowStrategy(
BizDetailShowStrategyEnum showStrategy, List<RawMessageRouterDTO> routers) {
return routers.stream()
// 过滤掉非页面详情相关的路由
.filter(e -> RouterCategoryEnum.DETAIL.equals(e.getCategory()))
.map(e -> BizDetailShowStrategyDTO.builder()
.terminals(e.getTerminals())
// 兼容老数据默认为跳转业务详情
.showStrategy(Objects.nonNull(showStrategy) ? showStrategy : BizDetailShowStrategyEnum.JUMP_TO)
.build())
.findFirst();
public static Optional<BizDetailShowStrategyDTO> fetchBizDetailShowStrategy(MessageTemplateRouterDTO msgTemplateRouter) {
if (Objects.isNull(msgTemplateRouter)) {
return Optional.empty();
}
return Optional.ofNullable(msgTemplateRouter.getRouteDetail())
.map(MessageRouteDetailDTO::toBizDetailShowStrategyDTO);
}
/**
* 获取业务按钮路由策略
*
* @param routers 路由列表
* @return 业务展示详情策略
* @param msgTemplateRouter 模板路由配置
* @return 业务按钮路由策略
*/
public static List<MessageRouterButtonDTO> selectAndConvertRouterButtons(List<RawMessageRouterDTO> routers) {
return selectRouterButtons(routers).stream()
.map(RawMessageRouterDTO::toMessageRouterButton)
public static List<MessageRouterButtonDTO> fetchMessageRouterButtons(MessageTemplateRouterDTO msgTemplateRouter) {
if (Objects.isNull(msgTemplateRouter)) {
return Collections.emptyList();
}
if (CollectionUtils.isEmpty(msgTemplateRouter.getRouteButtons())) {
return Collections.emptyList();
}
return msgTemplateRouter.getRouteButtons().stream()
.map(MessageRouteButtonDTO::toMessageRouterButton)
.collect(Collectors.toList());
}
/**
* 获取业务按钮路由策略
* 解析按钮风格的存储模型
*
* @param routers 路由列表
* @return 业务展示详情策略
* @param styleObj 按钮style对象
* @return 按钮style列表
*/
public static List<RawMessageRouterDTO> selectRouterButtons(List<RawMessageRouterDTO> routers) {
return routers.stream()
// 过滤掉页面详情相关的路由
.filter(e -> !RouterCategoryEnum.DETAIL.equals(e.getCategory()))
.collect(Collectors.toList());
public static List<ButtonStyleEnum> parseButtonStyle(JSONObject styleObj) {
if (Objects.isNull(styleObj)) {
return Collections.emptyList();
}
return JSON.parseArray(styleObj.toJSONString(), ButtonStyleEnum.class);
}
/**
@ -130,24 +138,45 @@ public final class MessageRouterUtil {
/**
* 解析模板上配置的路由地址,将发送消息时的参数替换上去并将路由参数追加到模板的路由地址后面兼容APP端新老版本
*
* @param router 路由信息
* @param msgTemplateRouter 路由信息
* @param routerParam 路由参数
* @return RawMessageRouterDTO
* @return MessageTemplateRouterDTO
*/
public static RawMessageRouterDTO parseAndConcatRouteUrl(RawMessageRouterDTO router, JSONObject routerParam) {
public static MessageTemplateRouterDTO parseAndConcatRouteUrl(MessageTemplateRouterDTO msgTemplateRouter, JSONObject routerParam) {
// 路由参数有效
if (Objects.nonNull(routerParam) && !routerParam.isEmpty()) {
if (Objects.nonNull(routerParam) && Objects.nonNull(msgTemplateRouter)) {
// 拷贝一份避免修改入参
router = router.deepClone();
router.getTerminals().forEach(e -> {
// 替换原始URL中的参数变量
String routerUrl = PlaceholderResolver.getDefaultResolver().resolveByMap(e.getUrl(), routerParam);
// 将routerParam追加到原始的URL后面
routerUrl = concatRouterParam(routerUrl, routerParam);
e.setUrl(routerUrl);
});
msgTemplateRouter = BeanConvertUtils.copyBean(msgTemplateRouter, MessageTemplateRouterDTO.class);
if (Objects.nonNull(msgTemplateRouter.getRouteDetail())) {
// 编排业务详情路由
msgTemplateRouter.getRouteDetail().getRouterConfigs()
.forEach(e -> concatRouterParam(e::getUrl, e::setUrl, routerParam));
}
if (CollectionUtils.isNotEmpty(msgTemplateRouter.getRouteButtons())) {
// 编排路由按钮
msgTemplateRouter.getRouteButtons().forEach(e -> {
if (StringUtils.isNotBlank(e.getApiUrl())) {
// API调用类型的按钮
concatRouterParam(e::getApiUrl, e::setApiUrl, routerParam);
}
if (CollectionUtils.isNotEmpty(e.getRouterConfigs())) {
// 页面跳转类型的按钮
e.getRouterConfigs()
.forEach(config -> concatRouterParam(config::getUrl, config::setUrl, routerParam));
}
});
}
}
return router;
return msgTemplateRouter;
}
private static void concatRouterParam(Supplier<String> getUrlSupplier, Consumer<String> setUrlConsumer,
JSONObject routerParam) {
// 替换原始URL中的参数变量
String routerUrl = PlaceholderResolver.getDefaultResolver().resolveByMap(getUrlSupplier.get(), routerParam);
// 将routerParam追加到原始的URL后面
routerUrl = concatRouterParam(routerUrl, routerParam);
setUrlConsumer.accept(routerUrl);
}
private static String concatRouterParam(String originalUrl, JSONObject routerParam) {

View File

@ -13,6 +13,7 @@ import org.apache.commons.collections.CollectionUtils;
import java.io.Serializable;
import java.util.List;
import java.util.Optional;
/**
* @description
@ -42,7 +43,6 @@ public class MessageRouterButtonDTO implements Serializable {
* 路由分类
* JUMP: 直接跳转
* ACTION: 接口调用
* DETAIL: 页面详情
*/
private RouterCategoryEnum category;
/**
@ -58,9 +58,23 @@ public class MessageRouterButtonDTO implements Serializable {
*/
private List<ButtonStyleEnum> style;
/**
* 路由终端列表若当前按钮为ACTION则只能配一个接口地址
* 路由按钮的跳转url配置
*/
private List<MessageRouterTerminalDTO> terminals;
/**
* 当按钮类型为API调用时该字段有值
*/
private String apiUrl;
public boolean isValid() {
if (CollectionUtils.isEmpty(terminals)) {
return false;
}
if (RouterCategoryEnum.ACTION.equals(category) && terminals.size() > 1) {
return false;
}
return terminals.stream().allMatch(MessageRouterTerminalDTO::isValid);
}
public boolean isHighlight() {
return CollectionUtils.isNotEmpty(style)

View File

@ -7,6 +7,7 @@ import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
@ -46,6 +47,10 @@ public class MessageRouterTerminalDTO implements Serializable {
.build();
}
public boolean isValid() {
return StringUtils.isNotBlank(url);
}
@Override
public String toString() {
return JSON.toJSONString(this);

View File

@ -17,7 +17,6 @@ public enum RouterCategoryEnum {
JUMP("直接跳转"),
ACTION("接口调用"),
DETAIL("页面详情"),
;
private final String desc;

View File

@ -86,7 +86,7 @@ public class PendingMessageResponse implements Serializable {
*/
private Long updateTimestamp;
/**
* 路由信息,可为空
* 路由信息,可为空 TODO:[cold_blade] [P0]
*/
private List<MessageRouterDTO> routers;
/**

View File

@ -3,6 +3,7 @@ package cn.axzo.msg.center.domain.entity;
import cn.axzo.msg.center.domain.persistence.BaseEntityExt;
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
import cn.axzo.msg.center.service.enums.RouterButtonSourceEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
@ -52,7 +53,7 @@ public class MessageRouteButton extends BaseEntityExt<MessageRouteButton> implem
/**
* 路由类型
*/
private MessageCategoryEnum category;
private RouterCategoryEnum category;
/**
* API地址,仅当按钮是接口调用类型时有值
*/
@ -62,6 +63,10 @@ public class MessageRouteButton extends BaseEntityExt<MessageRouteButton> implem
*/
@TableField(typeHandler = FastjsonTypeHandler.class)
private JSONObject style;
/**
* 按钮优先级数值越大优先级越低
*/
private Integer priority;
@Override
public String toString() {