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

This commit is contained in:
luofu 2023-11-11 15:51:31 +08:00
commit 4c8ff7dc95
15 changed files with 279 additions and 291 deletions

View File

@ -56,7 +56,7 @@ public class PendingMessageNewController implements PendingMessageClient {
if (Objects.isNull(pendingMessage)) {
return CommonResponse.success();
}
return CommonResponse.success(pendingMessage.toResponse());
return CommonResponse.success(pendingMessage.toResponse(terminalType));
}
@Override

View File

@ -11,13 +11,9 @@ import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @description
@ -92,15 +88,6 @@ public class MessageTemplateDTO implements Serializable {
.build();
}
public Map<String, String> toCardContentMap() {
if (CollectionUtils.isEmpty(msgCardContentItems)) {
return Collections.emptyMap();
}
Map<String, String> map = new HashMap<>();
msgCardContentItems.forEach(e -> map.put(e.getLabel(), e.getValue()));
return map;
}
@Override
public String toString() {
return JSON.toJSONString(this);

View File

@ -2,10 +2,13 @@ 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.MessageCardContentItemDTO;
import cn.axzo.msg.center.service.dto.PersonDTO;
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import cn.axzo.msg.center.service.pending.response.PendingMessageResponse;
import cn.axzo.msg.center.utils.DateFormatUtil;
import cn.axzo.msg.center.utils.MessageRouterUtil;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Builder;
@ -15,6 +18,7 @@ import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
/**
@ -46,9 +50,9 @@ public class PendingMessageDTO implements Serializable {
*/
private String content;
/**
* 卡片信息的JSON字符串
* 卡片信息
*/
private String cardContent;
private List<MessageCardContentItemDTO> cardItems;
/**
* 代办发起者信息
*/
@ -69,10 +73,26 @@ public class PendingMessageDTO implements Serializable {
* 业务状态描述
*/
private String bizDesc;
/**
* 业务标签
*/
private String bizFlag;
/**
* 工作台id
*/
private Long workspaceId;
/**
* 工作台名称
*/
private String workspaceName;
/**
* 业务类型
*/
private BizCategoryEnum bizCategory;
/**
* 待办截至时间
*/
private LocalDateTime deadline;
/**
* 申请时间戳
*/
@ -86,9 +106,9 @@ public class PendingMessageDTO implements Serializable {
*/
private MessageTemplateRouterDTO msgTemplateRouter;
/**
* 参数及其对应的值的JSON串
* 业务终态的印章图片地址
*/
private String routerParams;
private String bizFinalStateIcon;
public static PendingMessageDTO from(PendingMessageRecord pendingMessageRecord) {
// 代办发起者信息
@ -98,6 +118,7 @@ public class PendingMessageDTO implements Serializable {
.id(pendingMessageRecord.getPromoterId())
.type(pendingMessageRecord.getPromoterType())
.build())
.name(pendingMessageRecord.getPromoterName())
.build();
// 代办执行者信息
PersonDTO executor = PersonDTO.builder()
@ -106,6 +127,7 @@ public class PendingMessageDTO implements Serializable {
.id(pendingMessageRecord.getExecutorId())
.type(pendingMessageRecord.getExecutorType())
.build())
.name(pendingMessageRecord.getExecutorName())
.build();
return PendingMessageDTO.builder()
.identityCode(pendingMessageRecord.getIdentityCode())
@ -116,33 +138,41 @@ public class PendingMessageDTO implements Serializable {
.bizCode(pendingMessageRecord.getBizCode())
.subBizCode(pendingMessageRecord.getSubBizCode())
.bizDesc(pendingMessageRecord.getBizDesc())
.bizFlag(pendingMessageRecord.getBizFlag())
.workspaceId(pendingMessageRecord.getOrgId())
.workspaceName(pendingMessageRecord.getOrgName())
.bizCategory(pendingMessageRecord.getBizCategory())
.deadline(DateFormatUtil.toLocalDateTime(pendingMessageRecord.getDeadline()))
.createTime(DateFormatUtil.toLocalDateTime(pendingMessageRecord.getCreateAt()))
.updateTime(DateFormatUtil.toLocalDateTime(pendingMessageRecord.getUpdateAt()))
.routerParams(pendingMessageRecord.getRouterParams())
.build();
}
public PendingMessageResponse toResponse() {
public PendingMessageResponse toResponse(TerminalTypeEnum terminalType) {
return PendingMessageResponse.builder()
.identityCode(this.identityCode)
.title(this.title)
.content(this.content)
// TODO: [cold_blade] [P0] 待实现
// .cardContent(this.cardContent)
.cardItems(this.cardItems)
.promoterPersonId(Optional.ofNullable(this.promoter).map(PersonDTO::getId).orElse(null))
.promoterName(Optional.ofNullable(this.promoter).map(PersonDTO::getName).orElse(null))
.promoterIdentity(Optional.ofNullable(this.promoter).map(PersonDTO::getIdentity).orElse(null))
.executorPersonId(Optional.ofNullable(this.executor).map(PersonDTO::getId).orElse(null))
.executorName(Optional.ofNullable(this.executor).map(PersonDTO::getName).orElse(null))
.executorIdentity(Optional.ofNullable(this.executor).map(PersonDTO::getIdentity).orElse(null))
.bizCode(this.bizCode)
.subBizCode(this.subBizCode)
.bizDesc(this.bizDesc)
.bizFlag(this.bizFlag)
.bizCategory(this.bizCategory)
.workspaceId(this.workspaceId)
.workspaceName(this.workspaceName)
.createTimestamp(DateFormatUtil.toTimestamp(this.createTime))
.updateTimestamp(DateFormatUtil.toTimestamp(this.updateTime))
// TODO:[cold_blade] [P0]
// .routers(this.routers)
// .routerParams(this.routerParams)
.deadlineTimestamp(DateFormatUtil.toTimestamp(this.deadline))
.detailRouter(MessageRouterUtil.fetchBizDetailRouter(this.msgTemplateRouter, terminalType).orElse(null))
.buttonRouters(MessageRouterUtil.fetchMessageRouterButtons(this.msgTemplateRouter, terminalType))
.bizFinalStateIcon(this.bizFinalStateIcon)
.build();
}

View File

@ -1,131 +0,0 @@
package cn.axzo.msg.center.message.domain.dto;
import cn.axzo.msg.center.domain.entity.MessageTemplateRouter;
import cn.axzo.msg.center.service.dto.MessageButtonRouteStrategyDTO;
import cn.axzo.msg.center.service.dto.ButtonRouterDTO;
import cn.axzo.msg.center.service.dto.MessageRouterTerminalDTO;
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 cn.axzo.msg.center.utils.MessageRouterUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
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
*
* @author cold_blade
* @date 2023/9/28
* @version 1.0
*/
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RawMessageRouterDTO implements Serializable {
private static final long serialVersionUID = -3751613307785030747L;
/**
* 路由描述
*/
private String desc;
/**
* 路由分类
* JUMP: 直接跳转
* ACTION: 接口调用
*/
private RouterCategoryEnum category;
/**
* 路由终端
*/
private List<MessageRouterTerminalDTO> terminals;
/**
* 模板编码
*/
private String templateCode;
/**
* 按钮样式配置
*/
private List<ButtonStyleEnum> style;
public static RawMessageRouterDTO from(MessageButtonRouteStrategyDTO router, String templateCode) {
return RawMessageRouterDTO.builder()
.desc(router.getDesc())
.category(router.getCategory())
.terminals(router.getTerminals())
.style(router.getStyle())
.templateCode(templateCode)
.build();
}
public MessageButtonRouteStrategyDTO toMessageRouterButton() {
return MessageButtonRouteStrategyDTO.builder()
.desc(this.desc)
.category(this.category)
.terminals(this.terminals)
.style(this.style)
.build();
}
public List<MessageTemplateRouter> toMessageTemplateRouters() {
return this.terminals.stream()
.map(this::convert)
.collect(Collectors.toList());
}
public ButtonRouterDTO toMessageRouter(TerminalTypeEnum terminalType) {
MessageRouterTerminalDTO terminal = MessageRouterUtil.select(this, terminalType);
return ButtonRouterDTO.builder()
.desc(this.desc)
.category(this.category)
.style(this.style)
.terminalType(terminal.getTerminalType())
.url(terminal.getUrl())
.build();
}
private MessageTemplateRouter convert(MessageRouterTerminalDTO terminal) {
MessageTemplateRouter router = new MessageTemplateRouter();
router.setName(desc);
router.setCategory(category);
router.setTemplateCode(templateCode);
router.setStyle(JSON.toJSONString(style));
router.setUrl(terminal.getUrl());
router.setTerminalType(terminal.getTerminalType());
return router;
}
private static MessageRouterTerminalDTO convert2Terminal(MessageTemplateRouter router) {
return MessageRouterTerminalDTO.builder()
.url(router.getUrl())
.terminalType(router.getTerminalType())
.build();
}
public RawMessageRouterDTO deepClone() {
return RawMessageRouterDTO.builder()
.desc(this.desc)
.category(this.category)
.terminals(this.terminals.stream().map(MessageRouterTerminalDTO::deepClone).collect(Collectors.toList()))
.templateCode(this.templateCode)
.style(Lists.newArrayList(this.getStyle()))
.build();
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -44,11 +44,10 @@ public class PendingMessagePushParam implements Serializable {
* 模板编码
*/
private String templateCode;
// /**
// * 删除工作台类型,通过id查
// * 消息所属项目部类型
// */
// private OrganizationTypeEnum orgType;
/**
* 消息所属组织类型
*/
private OrganizationTypeEnum orgType;
/**
* 消息所属项目部Id
*/

View File

@ -403,7 +403,7 @@ public class MessageTemplateNewServiceImpl implements MessageTemplateNewService
.cardContentItems(JSONObjectUtil.parseArray(record.getCardContent(), MessageCardContentItemDTO.class))
.msgIcon(record.getIcon())
.detailStrategy(MessageRouterUtil.fetchBizDetailShowStrategy(msgTemplateRouter).orElse(null))
.routers(MessageRouterUtil.fetchMessageRouterButtons(msgTemplateRouter))
.routers(MessageRouterUtil.fetchMessageRouterButtonStrategies(msgTemplateRouter))
.minAppVersion(record.getMinAppVersion())
.createTimestamp(record.getCreateAt().getTime())
.updateTimestamp(record.getUpdateAt().getTime())

View File

@ -20,16 +20,24 @@ 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.MessageCardContentItemDTO;
import cn.axzo.msg.center.service.dto.PersonDTO;
import cn.axzo.msg.center.service.dto.QueryOrderByDTO;
import cn.axzo.msg.center.service.enums.*;
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
import cn.axzo.msg.center.service.enums.IdentityTypeEnum;
import cn.axzo.msg.center.service.enums.MessageGroupCategoryEnum;
import cn.axzo.msg.center.service.enums.OrganizationTypeEnum;
import cn.axzo.msg.center.service.enums.PendingMessageRoleCategoryEnum;
import cn.axzo.msg.center.service.enums.PendingMessageStateEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import cn.axzo.msg.center.service.pending.request.PendingMessagePageRequest;
import cn.axzo.msg.center.service.pending.response.PendingMessageResponse;
import cn.axzo.msg.center.utils.JSONObjectUtil;
import cn.axzo.msg.center.utils.MessageCardUtil;
import cn.axzo.msg.center.utils.MessageRouterUtil;
import cn.axzo.msg.center.utils.OrderFieldParseUtil;
import cn.axzo.msg.center.utils.UUIDUtil;
import cn.azxo.framework.common.model.Page;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
@ -78,10 +86,15 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
@Override
public Page<PendingMessageResponse> pageQuery(PendingMessagePageRequest request) {
PersonDTO operator = PersonDTO.from(request.getPersonId(), request.getIdentityId(), request.getIdentityType());
PendingMessageStateEnum pendingMessageState = fetchPendingMessageState(request.getRoleCategory(), request.getMsgState());
BizFinalStateEnum bizFinalState = fetchBizFinalState(request.getRoleCategory(), request.getBizFinalState());
// 开始构建分页查询条件
LambdaQueryChainWrapper<PendingMessageRecord> query = pendingMessageRecordDao.lambdaQuery()
.eq(Objects.nonNull(request.getMsgState()), PendingMessageRecord::getState, request.getMsgState())
.like(StringUtils.isNotBlank(request.getTitle()), PendingMessageRecord::getTitle, request.getTitle())
.eq(PendingMessageRecord::getIsDelete, 0);
.eq(Objects.nonNull(pendingMessageState), PendingMessageRecord::getState, pendingMessageState)
.eq(Objects.nonNull(bizFinalState), PendingMessageRecord::getBizFinalState, bizFinalState)
.and(v -> v.like(StringUtils.isNotBlank(request.getTitle()), PendingMessageRecord::getTitle, request.getTitle())
.or().like(StringUtils.isNotBlank(request.getTitle()), PendingMessageRecord::getPromoterName, request.getTitle()))
.eq(Objects.nonNull(request.getWorkspaceId()), PendingMessageRecord::getOrgId, request.getWorkspaceId());
// 构建人维度的查询条件
buildPersonCondition(query, request.getWithIdentify(), request.getRoleCategory(), operator);
// 模板的分类对代办进行分组过滤
@ -99,7 +112,7 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
.collect(Collectors.toList());
List<MessageTemplateDTO> messageTemplates = messageTemplateNewService.listByTemplateCodes(templateCodes);
List<PendingMessageResponse> responseRecords = result.getRecords().stream()
.map(e -> convert(e, request.getTerminalType(), messageTemplates).toResponse())
.map(e -> convert(e, messageTemplates).toResponse(request.getTerminalType()))
.collect(Collectors.toList());
return Page.toPage(request.getPage(), request.getPageSize(), result.getTotal(), responseRecords);
}
@ -118,7 +131,7 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
List<MessageTemplateDTO> messageTemplates = messageTemplateNewService
.listByTemplateCodes(Lists.newArrayList(record.getTemplateCode()));
return pendingMessageRecordDao.queryByIdentityCode(msgIdentityCode)
.map(v -> convert(v, terminalType, messageTemplates));
.map(v -> convert(v, messageTemplates));
}
@Override
@ -133,11 +146,11 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
Long workspaceId = param.getWorkspaceId();
Result<SimpleWorkspaceRes> workspaceRes = workspaceApi.getOne(workspaceId);
if (!"200".equals(workspaceRes.getCode())) {
log.info("未查询到工作台信息 workspaceId:{}",workspaceId);
}else{
log.info("未查询到工作台信息 workspaceId:{}", workspaceId);
} else {
workspace = workspaceRes.getData();
}
List<PendingMessageRecord> record = convert(param, msgTemplate,requestNo,workspace);
List<PendingMessageRecord> record = convert(param, msgTemplate, requestNo, workspace);
pendingMessageRecordDao.saveBatch(record);
// TODO 消息推送 @luofu
return requestNo;
@ -173,27 +186,28 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
.update();
}
private PendingMessageDTO convert(PendingMessageRecord pendingMessageRecord, TerminalTypeEnum terminalType,
List<MessageTemplateDTO> messageTemplates) {
private PendingMessageDTO convert(PendingMessageRecord pendingMessageRecord, List<MessageTemplateDTO> messageTemplates) {
PendingMessageDTO pendingMessage = PendingMessageDTO.from(pendingMessageRecord);
// 对应模板的路由列表
// 对应模板的路由策略
MessageTemplateRouterDTO msgTemplateRouter = messageTemplates.stream()
.filter(e -> Objects.equals(e.getCode(), pendingMessageRecord.getTemplateCode()))
.findFirst()
.map(MessageTemplateDTO::getMsgTemplateRouter)
.orElse(null);
// 解析并替换掉路由地址中的动态参数变量
msgTemplateRouter = MessageRouterUtil
.parseAndConcatRouteUrl(msgTemplateRouter, JSONObjectUtil.parseObject(pendingMessageRecord.getRouterParams()));
pendingMessage.setMsgTemplateRouter(msgTemplateRouter);
// 获取模板卡片信息
String cardContent = messageTemplates.stream()
List<MessageCardContentItemDTO> msgCardContentItems = messageTemplates.stream()
.filter(e -> Objects.equals(e.getCode(), pendingMessageRecord.getTemplateCode()))
.findFirst()
.map(e -> JSON.toJSONString(e.toCardContentMap()))
.map(MessageTemplateDTO::getMsgCardContentItems)
.orElse(null);
if (StringUtils.isNotBlank(cardContent) && StringUtils.isNotBlank(pendingMessageRecord.getRouterParams())) {
cardContent = PlaceholderResolver.getDefaultResolver()
.resolveByMap(cardContent, JSON.parseObject(pendingMessageRecord.getRouterParams()));
}
pendingMessage.setCardContent(cardContent);
// 解析并替换卡片信息里面的动态参数变量
msgCardContentItems = MessageCardUtil.parseMessageCard(msgCardContentItems, pendingMessageRecord.getBizExtParam());
pendingMessage.setCardItems(msgCardContentItems);
// TODO: [cold_blade] [P0] 业务终态图标url
return pendingMessage;
}
@ -220,6 +234,20 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
return query.count();
}
private PendingMessageStateEnum fetchPendingMessageState(PendingMessageRoleCategoryEnum roleCategory,
PendingMessageStateEnum pendingMessageState) {
// 当且仅当查询的角色不为发起者时待办状态参数才有意义
return PendingMessageRoleCategoryEnum.PROMOTER.equals(roleCategory) ? null : pendingMessageState;
}
private BizFinalStateEnum fetchBizFinalState(PendingMessageRoleCategoryEnum roleCategory, BizFinalStateEnum bizFinalState) {
// 当且仅当查询的角色为发起者时业务终态参数才有意义
return Optional.ofNullable(roleCategory)
.filter(PendingMessageRoleCategoryEnum.PROMOTER::equals)
.map(v -> bizFinalState)
.orElse(null);
}
private void buildPersonCondition(LambdaQueryChainWrapper<PendingMessageRecord> query, Boolean withIdentify,
PendingMessageRoleCategoryEnum roleCategory, PersonDTO operator) {
IdentityDTO identity = null;
@ -251,6 +279,8 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
private void buildSortCondition(LambdaQueryChainWrapper<PendingMessageRecord> query,
Collection<QueryOrderByDTO> orderFields) {
if (CollectionUtils.isEmpty(orderFields)) {
// 默认时间降序
query.orderByDesc(PendingMessageRecord::getId);
return;
}
orderFields.stream()
@ -264,9 +294,10 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
});
}
private List<PendingMessageRecord> convert(PendingMessagePushParam param, MessageTemplateDTO msgTemplate,String requestNo,SimpleWorkspaceRes workspace) {
private List<PendingMessageRecord> convert(PendingMessagePushParam param, MessageTemplateDTO msgTemplate,
String requestNo, SimpleWorkspaceRes workspace) {
// 多个执行者生成多条record
return param.getExecutor().stream().map(executor ->{
return param.getExecutor().stream().map(executor -> {
PendingMessageRecord record = new PendingMessageRecord();
record.setIdentityCode(UUIDUtil.uuidString());
record.setRequestNo(requestNo);
@ -276,9 +307,9 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
// 构建模板信息
buildTemplateInfo(record, msgTemplate, param.getRouterParams());
// 构建代办所属企业/项目等相关信息
record.setOrgType(Objects.isNull(param.getOrgType()) ? OrganizationTypeEnum.UNKNOWN : param.getOrgType());
record.setOrgId(param.getWorkspaceId());
if (workspace != null) {
record.setOrgType(OrganizationTypeEnum.codeOf(workspace.getType()));
record.setOrgName(workspace.getName());
}
// 构建业务类信息

View File

@ -7,6 +7,7 @@ import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;
/**
@ -21,13 +22,16 @@ import java.util.Optional;
public final class DateFormatUtil {
public static LocalDateTime toLocalDateTime(Date date) {
if (Objects.isNull(date)) {
return null;
}
ZoneId zoneId = ZoneId.systemDefault();
return date.toInstant().atZone(zoneId).toLocalDateTime();
}
public static long toTimestamp(LocalDateTime dateTime) {
public static Long toTimestamp(LocalDateTime dateTime) {
return Optional.ofNullable(dateTime)
.map(v -> v.atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli())
.orElse(0L);
.orElse(null);
}
}

View File

@ -0,0 +1,46 @@
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.service.dto.MessageCardContentItemDTO;
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.List;
/**
* @description
* 消息卡片信息工具方法
*
* @author cold_blade
* @date 2023/11/10
* @version 1.0
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class MessageCardUtil {
/**
* 解析模板上配置的卡片信息并替换其中的动态参数
*
* @param msgCardContentItems 路由信息
* @param bizExtParamStr 业务扩展参数
* @return List<MessageCardContentItemDTO>
*/
public static List<MessageCardContentItemDTO> parseMessageCard(List<MessageCardContentItemDTO> msgCardContentItems,
String bizExtParamStr) {
if (CollectionUtils.isNotEmpty(msgCardContentItems) && StringUtils.isNotBlank(bizExtParamStr)) {
JSONObject bizExtParam = JSON.parseObject(bizExtParamStr);
// 复制一个副本避免直接修改
msgCardContentItems = BeanConvertUtils.copyList(msgCardContentItems, MessageCardContentItemDTO.class);
msgCardContentItems.forEach(e -> {
String modifiedValue = PlaceholderResolver.getDefaultResolver().resolveByMap(e.getValue(), bizExtParam);
e.setValue(modifiedValue);
});
}
return msgCardContentItems;
}
}

View File

@ -5,11 +5,11 @@ 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.MessageDetailRouteStrategyDTO;
import cn.axzo.msg.center.service.dto.MessageButtonRouteStrategyDTO;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouterConfigDTO;
import cn.axzo.msg.center.service.dto.ButtonRouterDTO;
import cn.axzo.msg.center.service.dto.MessageRouterTerminalDTO;
import cn.axzo.msg.center.service.dto.DetailRouterDTO;
import cn.axzo.msg.center.service.dto.MessageButtonRouteStrategyDTO;
import cn.axzo.msg.center.service.dto.MessageDetailRouteStrategyDTO;
import cn.axzo.msg.center.service.enums.ButtonStyleEnum;
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
@ -21,6 +21,7 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -42,9 +43,6 @@ public final class MessageRouterUtil {
public static final String DETAIL_ROUTER_DESC = "查看详情";
// 非法路由参数的定义
private static final String INVALID_ROUTER_PARAM = "null";
/**
* 获取业务详情路由策略
*
@ -59,13 +57,28 @@ public final class MessageRouterUtil {
.map(MessageRouteDetailDTO::toBizDetailShowStrategyDTO);
}
/**
* 获取业务详情路由
*
* @param msgTemplateRouter 模板路由配置
* @return 业务展示详情策略
*/
public static Optional<DetailRouterDTO> fetchBizDetailRouter(MessageTemplateRouterDTO msgTemplateRouter,
TerminalTypeEnum terminalType) {
if (Objects.isNull(msgTemplateRouter)) {
return Optional.empty();
}
return Optional.ofNullable(msgTemplateRouter.getRouteDetail())
.map(v -> convert(v, terminalType));
}
/**
* 获取业务按钮路由策略
*
* @param msgTemplateRouter 模板路由配置
* @return 业务按钮路由策略
*/
public static List<MessageButtonRouteStrategyDTO> fetchMessageRouterButtons(MessageTemplateRouterDTO msgTemplateRouter) {
public static List<MessageButtonRouteStrategyDTO> fetchMessageRouterButtonStrategies(MessageTemplateRouterDTO msgTemplateRouter) {
if (Objects.isNull(msgTemplateRouter)) {
return Collections.emptyList();
}
@ -77,6 +90,26 @@ public final class MessageRouterUtil {
.collect(Collectors.toList());
}
/**
* 获取业务按钮路由
*
* @param msgTemplateRouter 模板路由配置
* @return 业务按钮路由
*/
public static List<ButtonRouterDTO> fetchMessageRouterButtons(MessageTemplateRouterDTO msgTemplateRouter,
TerminalTypeEnum terminalType) {
if (Objects.isNull(msgTemplateRouter)) {
return Collections.emptyList();
}
if (CollectionUtils.isEmpty(msgTemplateRouter.getRouteButtons())) {
return Collections.emptyList();
}
return msgTemplateRouter.getRouteButtons().stream()
.sorted(Comparator.comparing(MessageRouteButtonDTO::getPriority))
.map(e -> convert(e, terminalType))
.collect(Collectors.toList());
}
/**
* 解析按钮风格的存储模型
*
@ -90,51 +123,6 @@ public final class MessageRouterUtil {
return JSON.parseArray(styleObj.toJSONString(), ButtonStyleEnum.class);
}
/**
* 根据指定的终端类型选取合适的路由
*
* @param rawMessageRouter 原始的模板路由策略
* @param terminalType 当前请求的终端类型
* @return 合适的路由数据
*/
public static MessageRouterTerminalDTO select(RawMessageRouterDTO rawMessageRouter, TerminalTypeEnum terminalType) {
if (RouterCategoryEnum.ACTION.equals(rawMessageRouter.getCategory())) {
return rawMessageRouter.getTerminals().get(0);
}
return rawMessageRouter.getTerminals().stream()
.filter(e -> Objects.equals(terminalType, e.getTerminalType()))
.findFirst()
// 优先选择H5没有则选择第一个元素
.orElseGet(() -> selectH5(rawMessageRouter).orElseGet(() -> rawMessageRouter.getTerminals().get(0)));
}
/**
* 判断路由参数的合法性
*
* @param routerParam 路由参数
* @return 合法返回 {@code true} 否则返回 {@code false}
*/
public static boolean isRouterParamValid(String routerParam) {
return StringUtils.isNotEmpty(routerParam)
&& !INVALID_ROUTER_PARAM.equals(routerParam);
}
/**
* 解析模板上配置的路由地址,并将发送消息时的参数替换上去
*
* @param router 路由信息
* @param routerParam 路由参数
*/
public static void parseRouteUrl(ButtonRouterDTO router, String routerParam) {
// 路由参数有效
if (isRouterParamValid(routerParam)) {
// 替换原始URL中的参数变量
String routerUrl = PlaceholderResolver
.getDefaultResolver().resolveByMap(router.getUrl(), JSON.parseObject(routerParam));
router.setUrl(routerUrl);
}
}
/**
* 解析模板上配置的路由地址,将发送消息时的参数替换上去并将路由参数追加到模板的路由地址后面兼容APP端新老版本
*
@ -142,34 +130,45 @@ public final class MessageRouterUtil {
* @param routerParam 路由参数
* @return MessageTemplateRouterDTO
*/
public static MessageTemplateRouterDTO parseAndConcatRouteUrl(MessageTemplateRouterDTO msgTemplateRouter, JSONObject routerParam) {
public static MessageTemplateRouterDTO parseAndConcatRouteUrl(MessageTemplateRouterDTO msgTemplateRouter,
JSONObject routerParam) {
// 路由参数有效
if (Objects.nonNull(routerParam) && Objects.nonNull(msgTemplateRouter)) {
// 拷贝一份避免修改入参
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));
}
});
}
// 编排业务详情路由
parseAndConcatDetailRouterUrl(msgTemplateRouter.getRouteDetail(), routerParam);
// 编排路由按钮
parseAndConcatButtonRouterUrl(msgTemplateRouter.getRouteButtons(), routerParam);
}
return msgTemplateRouter;
}
private static void parseAndConcatDetailRouterUrl(MessageRouteDetailDTO routeDetail, JSONObject routerParam) {
if (Objects.isNull(routeDetail)) {
return;
}
routeDetail.getRouterConfigs()
.forEach(e -> concatRouterParam(e::getUrl, e::setUrl, routerParam));
}
private static void parseAndConcatButtonRouterUrl(List<MessageRouteButtonDTO> routeButtons, JSONObject routerParam) {
if (CollectionUtils.isNotEmpty(routeButtons)) {
return;
}
routeButtons.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));
}
});
}
private static void concatRouterParam(Supplier<String> getUrlSupplier, Consumer<String> setUrlConsumer,
JSONObject routerParam) {
// 替换原始URL中的参数变量
@ -194,21 +193,45 @@ public final class MessageRouterUtil {
return originalUrl + paramBuilder;
}
/**
* 解析按钮style
*
* @param style 按钮style的JSON字串
* @return 按钮style的枚举列表
*/
public static List<ButtonStyleEnum> parseButtonStyle(String style) {
if (StringUtils.isBlank(style)) {
return Collections.emptyList();
}
return JSON.parseArray(style, ButtonStyleEnum.class);
private static DetailRouterDTO convert(MessageRouteDetailDTO detailRouteStrategy, TerminalTypeEnum terminalType) {
MessageRouterConfigDTO routerTerminal = select(detailRouteStrategy.getRouterConfigs(), terminalType);
return DetailRouterDTO.builder()
.showStrategy(detailRouteStrategy.getShowStrategy())
.url(routerTerminal.getUrl())
.terminalType(routerTerminal.getTerminalType())
.build();
}
private static Optional<MessageRouterTerminalDTO> selectH5(RawMessageRouterDTO rawMessageRouter) {
return rawMessageRouter.getTerminals().stream()
private static ButtonRouterDTO convert(MessageRouteButtonDTO routeButton, TerminalTypeEnum terminalType) {
if (RouterCategoryEnum.ACTION.equals(routeButton.getCategory())) {
return ButtonRouterDTO.builder()
.desc(routeButton.getName())
.style(parseButtonStyle(routeButton.getStyle()))
.category(routeButton.getCategory())
.url(routeButton.getApiUrl())
.build();
}
MessageRouterConfigDTO routerConfig = select(routeButton.getRouterConfigs(), terminalType);
return ButtonRouterDTO.builder()
.desc(routeButton.getName())
.style(parseButtonStyle(routeButton.getStyle()))
.category(routeButton.getCategory())
.url(routerConfig.getUrl())
.terminalType(routerConfig.getTerminalType())
.build();
}
private static MessageRouterConfigDTO select(List<MessageRouterConfigDTO> routerTerminals,
TerminalTypeEnum terminalType) {
return routerTerminals.stream()
.filter(e -> Objects.equals(terminalType, e.getTerminalType()))
.findFirst()
// 优先选择H5没有则选择第一个元素
.orElseGet(() -> selectH5(routerTerminals).orElseGet(() -> routerTerminals.get(0)));
}
private static Optional<MessageRouterConfigDTO> selectH5(List<MessageRouterConfigDTO> routerTerminals) {
return routerTerminals.stream()
.filter(e -> Objects.equals(TerminalTypeEnum.WEB_VIEW, e.getTerminalType()))
.findFirst();
}

View File

@ -17,17 +17,11 @@ import java.util.Arrays;
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum OrganizationTypeEnum {
ENT(1, "企业工作台"),
PROJECT(2, "项目部工作台"),
ENT(2, "企业"),
PROJECT(1, "项目"),
UNKNOWN(0, "未知");
private final Integer code;
private final String message;
public static OrganizationTypeEnum codeOf(Integer code) {
return Arrays.stream(values())
.filter(e -> e.code.equals(code))
.findFirst().orElse(UNKNOWN);
}
}

View File

@ -87,6 +87,10 @@ public class PendingMessagePageRequest extends PageRequest implements Serializab
* 消息标题
*/
private String title;
/**
* 工作台id
*/
private Long workspaceId;
/**
* 排序字段集合
*/

View File

@ -40,11 +40,10 @@ public class PendingMessagePushRequest implements Serializable {
*/
@NotBlank(message = "templateCode is required")
private String templateCode;
// /**
// * 删除工作台类型,通过id查
// * 消息所属项目部类型
// */
// private OrganizationTypeEnum orgType;
/**
* 消息所属组织类型
*/
private OrganizationTypeEnum orgType;
/**
* 消息所属工作台ID
*/

View File

@ -88,13 +88,13 @@ public class PendingMessageResponse implements Serializable {
*/
private String bizFlag;
/**
* 项目部图标
* 工作台id
*/
private String projectIcon;
private Long workspaceId;
/**
* 项目部名称
* 工作台名称
*/
private String projectName;
private String workspaceName;
/**
* 业务类型
*/

View File

@ -4,6 +4,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
import static cn.axzo.msg.center.MsgCenterConfig.IM_CENTER;
import static cn.axzo.msg.center.MsgCenterConfig.WORKSPACE;
/**
* @author cn
@ -12,8 +13,9 @@ import static cn.axzo.msg.center.MsgCenterConfig.IM_CENTER;
* @date 2023/5/30 11:33
*/
@Configuration
@EnableFeignClients(basePackages = {IM_CENTER})
@EnableFeignClients(basePackages = {IM_CENTER, WORKSPACE})
public class MsgCenterConfig {
public static final String IM_CENTER = "cn.axzo.im.center.api.feign";
public static final String WORKSPACE = "cn.axzo.apollo.workspace";
}