diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/MessageTemplateV3Controller.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/MessageTemplateV3Controller.java index 045cb97b..2fdbe057 100644 --- a/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/MessageTemplateV3Controller.java +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/controller/MessageTemplateV3Controller.java @@ -1,29 +1,27 @@ package cn.axzo.msg.center.message.controller; -import cn.axzo.basics.common.util.AssertUtil; import cn.axzo.msg.center.message.domain.param.MessageTemplateV3SaveOrUpdateParam; import cn.axzo.msg.center.message.domain.param.RelationTemplateMapInitParam; import cn.axzo.msg.center.message.domain.vo.RelationTemplateMapInitRequest; import cn.axzo.msg.center.message.service.MessageTemplateNewService; -import cn.axzo.msg.center.message.service.MessageTemplateNewSyncService; import cn.axzo.msg.center.message.service.MessageTemplateV3Service; import cn.axzo.msg.center.message.service.RelationTemplateMapService; +import cn.axzo.msg.center.message.service.impl.MessageTemplateV3SyncService; import cn.axzo.msg.center.service.template.client.MessageTemplateV3Client; -import cn.axzo.msg.center.service.template.request.MessageTemplateV3CreateRequest; -import cn.axzo.msg.center.service.template.request.MessageTemplateSyncDto; import cn.axzo.msg.center.service.template.request.MessageTemplateSyncQueryRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateV3CreateRequest; import cn.axzo.msg.center.service.template.request.MessageTemplateV3DeleteRequest; import cn.axzo.msg.center.service.template.request.MessageTemplateV3PageRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateV3SyncRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateV3SyncResponse; import cn.axzo.msg.center.service.template.request.MessageTemplateV3UpdateRequest; import cn.axzo.msg.center.service.template.request.MessageTemplateV3UpdateStatusRequest; import cn.axzo.msg.center.service.template.response.MessageDetailStyle; -import cn.axzo.msg.center.service.template.response.MessageTemplateDetailResponse; import cn.axzo.msg.center.service.template.response.MessageTemplatePageResponse; import cn.axzo.msg.center.service.template.response.MessageTemplateV3DetailResponse; import cn.axzo.msg.center.service.template.response.MessageTemplateV3PageResponse; import cn.azxo.framework.common.model.CommonResponse; import cn.azxo.framework.common.model.Page; -import cn.hutool.core.bean.BeanUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import lombok.RequiredArgsConstructor; @@ -51,7 +49,7 @@ public class MessageTemplateV3Controller implements MessageTemplateV3Client { private final MessageTemplateNewService messageTemplateNewService; private final RelationTemplateMapService relationTemplateMapService; - private final MessageTemplateNewSyncService messageTemplateNewSyncService; + private final MessageTemplateV3SyncService messageTemplateV3SyncService; private final MessageTemplateV3Service messageTemplateV3Service; @Override @@ -98,17 +96,6 @@ public class MessageTemplateV3Controller implements MessageTemplateV3Client { return CommonResponse.success(); } - @Override - public CommonResponse getSyncMessageTemplate( - MessageTemplateSyncQueryRequest request) { - MessageTemplateDetailResponse detail = messageTemplateNewService.querySyncMessageTemplate(request.getTemplateCode()); - AssertUtil.notNull(detail, "消息模板不存在"); - MessageTemplateSyncDto result = BeanUtil.copyProperties(detail, MessageTemplateSyncDto.class); - result.setTemplateCode(request.getTemplateCode()); - result.setEnv(request.getEnv()); - return CommonResponse.success(result); - } - @Override public CommonResponse> listTemplateDetailStyles() { List styles = messageTemplateNewService.listTemplateDetailStyles(); @@ -116,10 +103,16 @@ public class MessageTemplateV3Controller implements MessageTemplateV3Client { } @Override - public CommonResponse syncTemplate(MessageTemplateSyncDto param) { - log.info("syncTemplate param= [{}]", JSONUtil.toJsonStr(param)); - messageTemplateNewSyncService.syncTemplate(param); - return CommonResponse.success(); + public CommonResponse + getSyncMessageTemplate(MessageTemplateSyncQueryRequest request) { + log.info("getSyncMessageTemplate param= [{}]", JSONUtil.toJsonStr(request)); + return CommonResponse.success(messageTemplateV3SyncService.getSyncMessageTemplate(request)); + } + + @Override + public CommonResponse syncTemplate(MessageTemplateV3SyncRequest request) { + log.info("syncTemplate param= [{}]", JSONUtil.toJsonStr(request)); + return CommonResponse.success(messageTemplateV3SyncService.syncTemplate(request)); } @PostMapping(value = "/message/template/relation/init/v3", produces = {MediaType.APPLICATION_JSON_VALUE}) diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageTemplateV3Model.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageTemplateV3Model.java new file mode 100644 index 00000000..0a4cdc27 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageTemplateV3Model.java @@ -0,0 +1,26 @@ +package cn.axzo.msg.center.message.domain.dto; + +import cn.axzo.msg.center.domain.entity.MessageTemplateButtonV3; +import cn.axzo.msg.center.domain.entity.MessageTemplateGroupV3; +import cn.axzo.msg.center.domain.entity.MessageTemplateV3; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * @author yanglin + */ +@Setter +@Getter +public class MessageTemplateV3Model { + + private MessageTemplateV3 template; + private List groups; + private List buttons; + + public String getTemplateCode() { + return template.getCode(); + } + +} \ No newline at end of file diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateV3ModelService.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateV3ModelService.java new file mode 100644 index 00000000..e712816f --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateV3ModelService.java @@ -0,0 +1,92 @@ +package cn.axzo.msg.center.message.service.impl; + +import cn.axzo.msg.center.dal.MessageTemplateButtonV3Dao; +import cn.axzo.msg.center.dal.MessageTemplateGroupV3Dao; +import cn.axzo.msg.center.dal.MessageTemplateV3Dao; +import cn.axzo.msg.center.domain.entity.MessageTemplateButtonV3; +import cn.axzo.msg.center.domain.entity.MessageTemplateGroupV3; +import cn.axzo.msg.center.domain.entity.MessageTemplateV3; +import cn.axzo.msg.center.message.domain.dto.MessageTemplateV3Model; +import cn.axzo.msg.center.service.enums.StatusEnum; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toList; + +/** + * @author yanglin + */ +@Service +@RequiredArgsConstructor +public class MessageTemplateV3ModelService { + + private final MessageTemplateV3Dao messageTemplateV3Dao; + private final MessageTemplateGroupV3Dao messageTemplateGroupV3Dao; + private final MessageTemplateButtonV3Dao messageTemplateButtonV3Dao; + + public Optional findEnabledByCode(String templateCode) { + MessageTemplateV3 template = messageTemplateV3Dao.lambdaQuery() + .eq(MessageTemplateV3::getCode, templateCode) + .eq(MessageTemplateV3::getIsDelete, 0) + .eq(MessageTemplateV3::getStatus, StatusEnum.ENABLE) + .one(); + if (template == null) + return Optional.empty(); + ModelBuilder builder = new ModelBuilder(templateCode); + return Optional.of(builder.build(template)); + } + + public List getByCodes(List templateCodes) { + if (CollectionUtils.isEmpty(templateCodes)) + return Collections.emptyList(); + List templates = messageTemplateV3Dao.lambdaQuery() + .in(MessageTemplateV3::getCode, templateCodes) + .eq(MessageTemplateV3::getIsDelete, 0) + .list(); + ModelBuilder builder = new ModelBuilder(templateCodes.toArray(new String[0])); + return templates.stream() + .map(builder::build) + .collect(toList()); + } + + @RequiredArgsConstructor + private class ModelBuilder { + + final Map> templateCode2Groups; + final Map> templateCode2Buttons; + + ModelBuilder(String... templateCodes) { + if (templateCodes.length > 0) { + templateCode2Groups = messageTemplateGroupV3Dao.lambdaQuery() + .in(MessageTemplateGroupV3::getTemplateCode, Arrays.asList(templateCodes)) + .list().stream() + .collect(groupingBy(MessageTemplateGroupV3::getTemplateCode)); + templateCode2Buttons = messageTemplateButtonV3Dao.lambdaQuery() + .in(MessageTemplateButtonV3::getTemplateCode, Arrays.asList(templateCodes)) + .list().stream() + .collect(groupingBy(MessageTemplateButtonV3::getTemplateCode)); + } else { + templateCode2Groups = Collections.emptyMap(); + templateCode2Buttons = Collections.emptyMap(); + } + } + + MessageTemplateV3Model build(MessageTemplateV3 template) { + MessageTemplateV3Model model = new MessageTemplateV3Model(); + model.setTemplate(template); + model.setGroups(templateCode2Groups.getOrDefault(template.getCode(), Collections.emptyList())); + model.setButtons(templateCode2Buttons.getOrDefault(template.getCode(), Collections.emptyList())); + return model; + } + + } + +} \ No newline at end of file diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateV3SyncService.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateV3SyncService.java new file mode 100644 index 00000000..583a3edd --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/service/impl/MessageTemplateV3SyncService.java @@ -0,0 +1,91 @@ +package cn.axzo.msg.center.message.service.impl; + +import cn.axzo.msg.center.common.utils.BizAssertions; +import cn.axzo.msg.center.dal.MessageTemplateButtonV3Dao; +import cn.axzo.msg.center.dal.MessageTemplateGroupV3Dao; +import cn.axzo.msg.center.dal.MessageTemplateV3Dao; +import cn.axzo.msg.center.domain.entity.BaseEntityWithOperator; +import cn.axzo.msg.center.domain.entity.MessageTemplateButtonV3; +import cn.axzo.msg.center.domain.entity.MessageTemplateGroupV3; +import cn.axzo.msg.center.domain.entity.MessageTemplateV3; +import cn.axzo.msg.center.service.template.request.MessageTemplateSyncQueryRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateV3SyncRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateV3SyncResponse; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author yanglin + */ +@Service +@RequiredArgsConstructor +public class MessageTemplateV3SyncService { + + private final MessageTemplateV3Dao messageTemplateV3Dao; + private final MessageTemplateGroupV3Dao messageTemplateGroupV3Dao; + private final MessageTemplateButtonV3Dao messageTemplateButtonV3Dao; + + public MessageTemplateV3SyncResponse getSyncMessageTemplate(MessageTemplateSyncQueryRequest request) { + MessageTemplateV3 template = findTemplate(request.getTemplateCode()); + BizAssertions.assertNotNull(template, "未找到需要同步的模版: {}", request.getTemplateCode()); + List groups = messageTemplateGroupV3Dao.lambdaQuery() + .eq(MessageTemplateGroupV3::getTemplateCode, template.getCode()) + .list(); + List buttons = messageTemplateButtonV3Dao.lambdaQuery() + .eq(MessageTemplateButtonV3::getTemplateCode, template.getCode()) + .list(); + MessageTemplateV3SyncResponse resp = new MessageTemplateV3SyncResponse(); + JSONObject respJson = new JSONObject(); + respJson.put("template", template); + respJson.put("groups", groups); + respJson.put("buttons", buttons); + resp.setTemplate(respJson); + return resp; + } + + /** + * @return error + */ + public String syncTemplate(MessageTemplateV3SyncRequest request) { + MessageTemplateV3 template = request.getTemplate() + .getObject("template", MessageTemplateV3.class); + MessageTemplateV3 savedTemplate = findTemplate(template.getCode()); + if (savedTemplate != null) return "模板已存在"; + List groups = request.getTemplate() + .getObject("groups", new TypeReference>() {}); + List buttons = request.getTemplate() + .getObject("groups", new TypeReference>() {}); + + setBasicProps(template, request.getOperatorId(), request.getOperatorName()); + groups.forEach(group -> setBasicProps(group, request.getOperatorId(), request.getOperatorName())); + buttons.forEach(button -> setBasicProps(button, request.getOperatorId(), request.getOperatorName())); + + messageTemplateV3Dao.save(template); + if (CollectionUtils.isNotEmpty(groups)) + messageTemplateGroupV3Dao.saveBatch(groups); + if (CollectionUtils.isNotEmpty(buttons)) + messageTemplateButtonV3Dao.saveBatch(buttons); + + return null; + } + + private MessageTemplateV3 findTemplate(String templateCode) { + return messageTemplateV3Dao.lambdaQuery() + .eq(MessageTemplateV3::getCode, templateCode) + .one(); + } + + private void setBasicProps(BaseEntityWithOperator entity, Long operatorId, String operatorName) { + entity.setCreateAt(null); + entity.setUpdateAt(null); + entity.setCreatePersonId(operatorId); + entity.setCreatePersonName(operatorName); + entity.setUpdatePersonId(operatorId); + entity.setUpdatePersonName(operatorName); + } +} \ No newline at end of file diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/message/xxl/MigrateMessageTemplateV3Job.java b/inside-notices/src/main/java/cn/axzo/msg/center/message/xxl/MigrateMessageTemplateV3Job.java new file mode 100644 index 00000000..dc3661a7 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/message/xxl/MigrateMessageTemplateV3Job.java @@ -0,0 +1,378 @@ +package cn.axzo.msg.center.message.xxl; + +import cn.axzo.maokai.api.util.Ref; +import cn.axzo.maokai.api.vo.response.tree.ValueNode; +import cn.axzo.msg.center.dal.MessageBaseTemplateDao; +import cn.axzo.msg.center.dal.MessageTemplateButtonV3Dao; +import cn.axzo.msg.center.dal.MessageTemplateGroupDao; +import cn.axzo.msg.center.dal.MessageTemplateGroupV3Dao; +import cn.axzo.msg.center.dal.MessageTemplateV3Dao; +import cn.axzo.msg.center.domain.entity.BaseEntityWithOperator; +import cn.axzo.msg.center.domain.entity.MessageBaseTemplate; +import cn.axzo.msg.center.domain.entity.MessageTemplateButtonV3; +import cn.axzo.msg.center.domain.entity.MessageTemplateGroup; +import cn.axzo.msg.center.domain.entity.MessageTemplateGroupV3; +import cn.axzo.msg.center.domain.entity.MessageTemplateV3; +import cn.axzo.msg.center.inside.notices.config.PendingMessageBizConfig; +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.MessageTemplateRouterDTO.MessageRouteButtonDTO; +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.service.MessageTemplateNewService; +import cn.axzo.msg.center.message.service.group.GroupTemplateService; +import cn.axzo.msg.center.message.service.group.NodeWrapper; +import cn.axzo.msg.center.message.service.group.RootNodeWrapper; +import cn.axzo.msg.center.service.domain.CardUrlConfig; +import cn.axzo.msg.center.service.domain.DetailConfig; +import cn.axzo.msg.center.service.domain.GroupConfig; +import cn.axzo.msg.center.service.domain.KVConfig; +import cn.axzo.msg.center.service.domain.UrlConfig; +import cn.axzo.msg.center.service.domain.url.AppUrl; +import cn.axzo.msg.center.service.domain.url.WebUrl; +import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO; +import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum; +import cn.axzo.msg.center.service.enums.BizDetailShowStrategyEnum; +import cn.axzo.msg.center.service.enums.CardUrlOpenStrategy; +import cn.axzo.msg.center.service.enums.GroupType; +import cn.axzo.msg.center.service.enums.KVContentType; +import cn.axzo.msg.center.service.enums.MessageCategoryEnum; +import cn.axzo.msg.center.service.enums.PushTerminalEnum; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import cn.axzo.msg.center.service.enums.WebPageOpenStrategy; +import cn.axzo.msg.center.service.enums.YesOrNo; +import cn.axzo.msg.center.utils.JSONObjectUtil; +import com.alibaba.fastjson.JSON; +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.support.TransactionTemplate; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.toList; + +/** + * @author yanglin + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class MigrateMessageTemplateV3Job { + + private final TransactionTemplate transactionTemplate; + private final MessageBaseTemplateDao messageBaseTemplateDao; + private final MessageTemplateNewService messageTemplateNewService; + private final MessageTemplateV3Dao messageTemplateV3Dao; + private final GroupTemplateService groupTemplateService; + private final MessageTemplateGroupV3Dao messageTemplateGroupV3Dao; + private final MessageTemplateButtonV3Dao messageTemplateButtonV3Dao; + private final MessageTemplateGroupDao messageTemplateGroupDao; + private final PendingMessageBizConfig pendingMessageBizConfig; + + @SuppressWarnings("unused") + @XxlJob("migrateMessageTemplateV3Job") + public ReturnT execute(String jsonStr) { + try { + Param param = StringUtils.isBlank(jsonStr) + ? new Param() + : JSONObjectUtil.parseObject(jsonStr, Param.class); + return executeImpl(param); + } catch (Exception e) { + log.warn("job failed", e); + throw e; + } + } + + private ReturnT executeImpl(Param param) { + RootNodeWrapper groupRoot = groupTemplateService.getGroupRoot(); + List baseTemplates = messageBaseTemplateDao.lambdaQuery() + .eq(MessageBaseTemplate::getIsDelete, 0) + .in(CollectionUtils.isNotEmpty(param.getTemplateCodes()), + MessageBaseTemplate::getCode, param.getTemplateCodes()) + .list(); + for (int i = 0; i < baseTemplates.size(); i++) { + MessageBaseTemplate baseTemplate = baseTemplates.get(i); + log.info("migrating template: {}/{}", i + 1, baseTemplates.size()); + transactionTemplate.executeWithoutResult(unused -> migrateTemplate(groupRoot, baseTemplate)); + } + return ReturnT.SUCCESS; + } + + private void migrateTemplate(RootNodeWrapper groupRoot, MessageBaseTemplate baseTemplate) { + MessageTemplateDTO baseTemplateModel = messageTemplateNewService + .listByTemplateCodes(Collections.singletonList(baseTemplate.getCode())) + .get(0); + + MessageTemplateV3 templateV3 = new MessageTemplateV3(); + templateV3.setName(baseTemplate.getName()); + templateV3.setCode(baseTemplate.getCode()); + templateV3.setMsgCategory(baseTemplate.getMsgCategory()); + templateV3.setTitle(baseTemplate.getTitle()); + templateV3.setContent(baseTemplate.getContent()); + templateV3.setDetailStyleCode(baseTemplate.getDetailStyleCode()); + templateV3.setIcon(baseTemplate.getIcon()); + templateV3.setMinAppVersion(baseTemplate.getMinAppVersion()); + templateV3.setStatus(baseTemplate.getStatus()); + templateV3.setPushTerminal(baseTemplate.getPushTerminal()); + templateV3.setPushData(baseTemplate.getPushData()); + templateV3.setImSendPriority(baseTemplate.getImSendPriority()); + templateV3.setDisplayOnList(YesOrNo.YES); + templateV3.setIsDelete(0L); + templateV3.setCreateAt(baseTemplate.getCreateAt()); + templateV3.getOrCreateRecordExt().setIsMigrated(true); + setOperatorAsSystem(templateV3); + + Runnable defaultCardUrlSetter = () -> templateV3.setCardUrlOpenStrategy( + baseTemplate.getMsgCategory() == MessageCategoryEnum.GENERAL_MESSAGE + ? CardUrlOpenStrategy.NONE + : CardUrlOpenStrategy.OPEN_TODO_DETAIL); + List buttons = null; + MessageTemplateRouterDTO baseTemplateRouter = baseTemplateModel.getMsgTemplateRouter(); + if (baseTemplateRouter != null) { + if (baseTemplateRouter.getRouteDetail() != null) + configureCardUrl(groupRoot, baseTemplate, baseTemplateRouter.getRouteDetail(), templateV3); + else + defaultCardUrlSetter.run(); + if (baseTemplateRouter.getRouteButtons() != null) + buttons = migrateButtons(groupRoot, baseTemplate, baseTemplateRouter.getRouteButtons()); + } else { + defaultCardUrlSetter.run(); + } + + MessageTemplateGroupV3 group = migrateGroups(groupRoot, baseTemplate, baseTemplateModel); + + messageTemplateV3Dao.save(templateV3); + if (CollectionUtils.isNotEmpty(buttons)) + messageTemplateButtonV3Dao.saveBatch(buttons); + if (group != null) + messageTemplateGroupV3Dao.save(group); + } + + private void configureCardUrl(RootNodeWrapper groupRoot, + MessageBaseTemplate baseTemplate, + MessageRouteDetailDTO routeDetail, + MessageTemplateV3 templateV3) { + if (baseTemplate.getMsgCategory() == MessageCategoryEnum.GENERAL_MESSAGE) { + templateV3.setCardUrlOpenStrategy(CardUrlOpenStrategy.OPEN_CUSTOM_PAGE); + } else { + if (routeDetail.getShowStrategy() == BizDetailShowStrategyEnum.INLINE) + templateV3.setCardUrlOpenStrategy(CardUrlOpenStrategy.OPEN_TODO_DETAIL); + else + templateV3.setCardUrlOpenStrategy(CardUrlOpenStrategy.OPEN_CUSTOM_PAGE); + } + CardUrlConfig cardUrConfig = new CardUrlConfig(); + cardUrConfig.setUrlConfig(buildUrlConfig(groupRoot, baseTemplate, routeDetail.getRouterConfigs())); + templateV3.setCardUrlConfig(cardUrConfig); + } + + private List migrateButtons(RootNodeWrapper groupRoot, + MessageBaseTemplate baseTemplate, + List routeButtons) { + if (CollectionUtils.isEmpty(routeButtons)) return Collections.emptyList(); + ArrayList buttons = new ArrayList<>(); + for (MessageRouteButtonDTO routeButton : routeButtons) { + MessageTemplateButtonV3 button = new MessageTemplateButtonV3(); + button.setName(routeButton.getName()); + button.setTemplateCode(baseTemplate.getCode()); + button.setPresetBtnType(routeButton.getPresetButtonType()); + button.setSource(routeButton.getSource()); + button.setCategory(routeButton.getCategory()); + button.setApiUrl(routeButton.getApiUrl()); + button.setUrlConfig(buildUrlConfig(groupRoot, baseTemplate, routeButton.getRouterConfigs())); + button.setStyle(routeButton.getStyle()); + button.setExecutorShow(routeButton.getExecutorShow()); + button.setPendingShow(routeButton.getPendingShow()); + button.setPriority(routeButton.getPriority()); + button.getOrCreateRecordExt().setBtnCode(routeButton.getBtnCode()); + button.getOrCreateRecordExt().setIsMigrated(true); + setOperatorAsSystem(button); + buttons.add(button); + } + return buttons; + } + + private MessageTemplateGroupV3 migrateGroups(RootNodeWrapper groupRoot, + MessageBaseTemplate baseTemplate, + MessageTemplateDTO baseTemplateModel) { + + if (StringUtils.isBlank(baseTemplate.getCardContent())) return null; + + List cardItems = JSONObjectUtil + .parseArray(baseTemplate.getCardContent(), MessageCardContentItemDTO.class); + + cardItems = cardItems.stream() + // 工人卡片的去掉,产品说他去配置 + .filter(cardItem -> !cardItem.getLabel().equals("customerPersonId")) + .collect(toList()); + + if (CollectionUtils.isEmpty(cardItems)) return null; + + GroupConfig groupConfig = new GroupConfig(); + groupConfig.setKeyValues(new ArrayList<>()); + for (int i = 0; i < cardItems.size(); i++) { + MessageCardContentItemDTO cardItem = cardItems.get(i); + KVConfig kv = new KVConfig(); + kv.setContentType(KVContentType.TEXT); + kv.setKey(cardItem.getLabel()); + kv.setValue(cardItem.getValue()); + kv.setDisplayOnCard(i < 3); + groupConfig.getKeyValues().add(kv); + } + + Supplier detailFactory = () -> { + MessageTemplateRouterDTO templateRouter = baseTemplateModel.getMsgTemplateRouter(); + if (templateRouter == null) return null; + return templateRouter.getRouteDetail(); + }; + + if (detailFactory.get() != null + && detailFactory.get().getShowStrategy() == BizDetailShowStrategyEnum.JUMP_TO) { + DetailConfig detailConfig = new DetailConfig(); + detailConfig.setName("查看详情"); + detailConfig.setUrlConfig(buildUrlConfig( + groupRoot, baseTemplate, detailFactory.get().getRouterConfigs())); + groupConfig.setDetail(detailConfig); + } + + MessageTemplateGroupV3 group = new MessageTemplateGroupV3(); + group.setName("基本信息"); + group.setTemplateCode(baseTemplate.getCode()); + group.setSortOrder(1); + group.setGroupType(GroupType.KV_VALUES); + group.setGroupConfig(groupConfig); + group.getOrCreateRecordExt().setIsMigrated(true); + setOperatorAsSystem(group); + return group; + } + + private UrlConfig buildUrlConfig(RootNodeWrapper groupRoot, + MessageBaseTemplate baseTemplate, + List routers) { + UrlConfig urlConfig = new UrlConfig(); + Ref propsSet = Ref.create(false); + + searchRouter(routers, TerminalTypeEnum.WEB).ifPresent(router -> { + WebUrl pcCms = new WebUrl(); + pcCms.setOpenStrategy(WebPageOpenStrategy.NEW_PAGE); + pcCms.setUrl(router.getUrl()); + urlConfig.setPcCms(pcCms); + propsSet.set(true); + }); + List terminals = determineTerminalTypes(groupRoot, baseTemplate); + searchRouter(routers, TerminalTypeEnum.IOS).ifPresent(router -> { + AppUrl ios = new AppUrl(); + ios.setUrl(router.getUrl()); + if (terminals.contains(PushTerminalEnum.B_ENTERPRISE_APP)) { + urlConfig.getOrCreateAppManager().setIos(ios); + propsSet.set(true); + } + if (terminals.contains(PushTerminalEnum.C_WORKER_APP)) { + urlConfig.getOrCrateAppWorker().setIos(ios); + propsSet.set(true); + } + }); + searchRouter(routers, TerminalTypeEnum.ANDROID).ifPresent(router -> { + AppUrl android = new AppUrl(); + android.setUrl(router.getUrl()); + if (terminals.contains(PushTerminalEnum.B_ENTERPRISE_APP)) { + urlConfig.getOrCreateAppManager().setAndroid(android); + propsSet.set(true); + } + if (terminals.contains(PushTerminalEnum.C_WORKER_APP)) { + urlConfig.getOrCrateAppWorker().setAndroid(android); + propsSet.set(true); + } + }); + searchRouter(routers, + TerminalTypeEnum.WEB_VIEW, + TerminalTypeEnum.MINI_PROGRAM, + TerminalTypeEnum.WECHAT_MINI_PROGRAM).ifPresent(router -> { + AppUrl appUrl = new AppUrl(); + appUrl.setUrl(router.getUrl()); + if (terminals.contains(PushTerminalEnum.B_ENTERPRISE_APP)) { + urlConfig.getOrCreateAppManager().setIos(appUrl); + urlConfig.getOrCreateAppManager().setAndroid(appUrl); + propsSet.set(true); + } + if (terminals.contains(PushTerminalEnum.C_WORKER_APP)) { + urlConfig.getOrCrateAppWorker().setIos(appUrl); + urlConfig.getOrCrateAppWorker().setAndroid(appUrl); + propsSet.set(true); + } + }); + + return propsSet.get() ? urlConfig : null; + } + + private Optional searchRouter(List routers, + TerminalTypeEnum... terminalTypes) { + List terminalTypesList = Arrays.asList(terminalTypes); + return routers.stream() + .filter(r -> terminalTypesList.contains(r.getTerminalType())) + .findFirst(); + } + + private List determineTerminalTypes(RootNodeWrapper groupRoot, + MessageBaseTemplate baseTemplate) { + if (baseTemplate.getMsgCategory() == MessageCategoryEnum.GENERAL_MESSAGE) { + return JSON.parseArray(baseTemplate.getPushTerminal(), PushTerminalEnum.class); + } + Set paths = messageTemplateGroupDao.lambdaQuery() + .eq(MessageTemplateGroup::getTemplateCode, baseTemplate.getCode()) + .list().stream() + .map(MessageTemplateGroup::getPath) + .collect(Collectors.toSet()); + Map> appType2NodeIds = pendingMessageBizConfig.getMsgGroupConfig(); + Function, Boolean> appSelector = appTypes -> { + for (Map.Entry> e : appType2NodeIds.entrySet()) { + if (!appTypes.contains(e.getKey())) + continue; + for (Long parentNodeId : e.getValue()) { + ValueNode parentNode = groupRoot + .findValueNode(parentNodeId).orElse(null); + if (parentNode == null) continue; + String code = parentNode.getValue().unwrap().getCode(); + if (paths.stream().anyMatch(path -> path.contains(code))) return true; + } + } + return false; + }; + ArrayList terminals = new ArrayList<>(); + if (appSelector.apply(Collections.singletonList( + AppTerminalTypeEnum.C_WORKER_APP))) + terminals.add(PushTerminalEnum.C_WORKER_APP); + if (appSelector.apply(Arrays.asList( + AppTerminalTypeEnum.B_ENTERPRISE_APP, AppTerminalTypeEnum.CMS_WEB_PC))) + terminals.add(PushTerminalEnum.B_ENTERPRISE_APP); + return terminals; + } + + private void setOperatorAsSystem(BaseEntityWithOperator entity) { + entity.setCreatePersonId(0L); + entity.setCreatePersonName("system"); + entity.setUpdatePersonId(0L); + entity.setUpdatePersonName("system"); + } + + @Setter + @Getter + public static class Param { + private Set templateCodes; + } +} \ No newline at end of file diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/UrlConfig.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/UrlConfig.java index 40f849bf..fef5cc68 100644 --- a/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/UrlConfig.java +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/UrlConfig.java @@ -1,10 +1,18 @@ package cn.axzo.msg.center.service.domain; +import cn.axzo.msg.center.service.domain.parse.TerminalUrl; +import cn.axzo.msg.center.service.domain.parse.TerminalUrlParser; import cn.axzo.msg.center.service.domain.url.WebUrl; +import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum; +import com.alibaba.fastjson.annotation.JSONField; import lombok.Getter; import lombok.Setter; +import java.util.List; + /** + * REQ-3045 + * * @author yanglin */ @Setter @@ -36,4 +44,22 @@ public class UrlConfig { */ private MobileUrlConfig appManager; + @JSONField(serialize = false) + public MobileUrlConfig getOrCrateAppWorker() { + if (appWorker == null) + appWorker = new MobileUrlConfig(); + return appWorker; + } + + @JSONField(serialize = false) + public MobileUrlConfig getOrCreateAppManager() { + if (appManager == null) + appManager = new MobileUrlConfig(); + return appManager; + } + + public List parse(AppTerminalTypeEnum appType) { + return new TerminalUrlParser(this, appType).parse(); + } + } \ No newline at end of file diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/parse/TerminalUrl.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/parse/TerminalUrl.java new file mode 100644 index 00000000..905806e2 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/parse/TerminalUrl.java @@ -0,0 +1,36 @@ +package cn.axzo.msg.center.service.domain.parse; + +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * @author yanglin + */ +@Setter +@Getter +@NoArgsConstructor +public class TerminalUrl { + + public TerminalUrl(TerminalTypeEnum terminalType, String url) { + this.terminalType = terminalType; + this.url = url; + } + + /** + * 路由编码 + */ + private String routerCode; + + /** + * 路由的系统类型 + */ + private TerminalTypeEnum terminalType; + + /** + * 路由地址 + */ + private String url; + +} \ No newline at end of file diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/parse/TerminalUrlParser.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/parse/TerminalUrlParser.java new file mode 100644 index 00000000..032ff8ab --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/parse/TerminalUrlParser.java @@ -0,0 +1,73 @@ +package cn.axzo.msg.center.service.domain.parse; + +import cn.axzo.msg.center.service.domain.MobileUrlConfig; +import cn.axzo.msg.center.service.domain.UrlConfig; +import cn.axzo.msg.center.service.domain.url.WebUrl; +import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum; +import cn.axzo.msg.center.service.enums.TerminalTypeEnum; +import lombok.RequiredArgsConstructor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.B_ENTERPRISE_APP; +import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.CMS_WEB_PC; +import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.C_WORKER_APP; +import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.OMS_WEB_PC; +import static cn.axzo.msg.center.service.enums.AppTerminalTypeEnum.PC_GA_GENERAL; + +/** + * @author yanglin + */ +@RequiredArgsConstructor +public class TerminalUrlParser { + + private final UrlConfig config; + private final AppTerminalTypeEnum requestType; + + public List parse() { + ArrayList urls = new ArrayList<>(); + + // !! 只会命中其一 + + // PC(CMS) + selectWeb(CMS_WEB_PC, config.getPcCms()).ifPresent(urls::add); + // PC(OMS) + selectWeb(OMS_WEB_PC, config.getPcOms()).ifPresent(urls::add); + // PC(政务系统) + selectWeb(PC_GA_GENERAL, config.getPcGaGeneral()).ifPresent(urls::add); + + // !! 只会命中其一 + + // APP工人端 + urls.addAll(selectApp(C_WORKER_APP, config.getAppWorker())); + // APP管理端 + urls.addAll(selectApp(B_ENTERPRISE_APP, config.getAppManager())); + + return urls; + } + + private Optional selectWeb( + AppTerminalTypeEnum selectType, WebUrl webUrl) { + if (requestType != selectType) + return Optional.empty(); + if (webUrl == null) + return Optional.empty(); + return Optional.of(new TerminalUrl(TerminalTypeEnum.WEB, webUrl.getUrl())); + } + + private List selectApp( + AppTerminalTypeEnum selectType, MobileUrlConfig mobileUrl) { + if (requestType != selectType) + return Collections.emptyList(); + if (mobileUrl == null) + return Collections.emptyList(); + ArrayList urls = new ArrayList<>(); + urls.add(new TerminalUrl(TerminalTypeEnum.IOS, mobileUrl.getIos().getUrl())); + urls.add(new TerminalUrl(TerminalTypeEnum.ANDROID, mobileUrl.getAndroid().getUrl())); + return urls; + } + +} \ No newline at end of file diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/url/WebUrl.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/url/WebUrl.java index 9b03363f..1f74da83 100644 --- a/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/url/WebUrl.java +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/domain/url/WebUrl.java @@ -1,7 +1,9 @@ package cn.axzo.msg.center.service.domain.url; import cn.axzo.msg.center.service.enums.WebPageOpenStrategy; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; /** diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/MessageTemplateV3Client.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/MessageTemplateV3Client.java index b930a4d3..fecab719 100644 --- a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/MessageTemplateV3Client.java +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/client/MessageTemplateV3Client.java @@ -5,6 +5,8 @@ import cn.axzo.msg.center.service.template.request.MessageTemplateSyncDto; import cn.axzo.msg.center.service.template.request.MessageTemplateSyncQueryRequest; import cn.axzo.msg.center.service.template.request.MessageTemplateV3DeleteRequest; import cn.axzo.msg.center.service.template.request.MessageTemplateV3PageRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateV3SyncRequest; +import cn.axzo.msg.center.service.template.request.MessageTemplateV3SyncResponse; import cn.axzo.msg.center.service.template.request.MessageTemplateV3UpdateRequest; import cn.axzo.msg.center.service.template.request.MessageTemplateV3UpdateStatusRequest; import cn.axzo.msg.center.service.template.response.MessageDetailStyle; @@ -96,14 +98,14 @@ public interface MessageTemplateV3Client { * 查询消息模板 */ @PostMapping(value = "/message/template/v3/sync/get", produces = {MediaType.APPLICATION_JSON_VALUE}) - CommonResponse getSyncMessageTemplate(@RequestBody @Valid MessageTemplateSyncQueryRequest request); + CommonResponse getSyncMessageTemplate(@RequestBody @Valid MessageTemplateSyncQueryRequest request); /** * 同步消息模板 * req-1896 说明:仅pre环境能同步 */ @PostMapping(value = "/message/template/v3/sync", produces = {MediaType.APPLICATION_JSON_VALUE}) - CommonResponse syncTemplate(@RequestBody @Valid MessageTemplateSyncDto request); + CommonResponse syncTemplate(@RequestBody @Valid MessageTemplateV3SyncRequest request); /** * 获取所有消息样式 diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3SyncRequest.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3SyncRequest.java new file mode 100644 index 00000000..c8cf2438 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3SyncRequest.java @@ -0,0 +1,16 @@ +package cn.axzo.msg.center.service.template.request; + +import com.alibaba.fastjson.JSONObject; +import lombok.Getter; +import lombok.Setter; + +/** + * @author yanglin + */ +@Setter +@Getter +public class MessageTemplateV3SyncRequest { + private JSONObject template; + private Long operatorId; + private String operatorName; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3SyncResponse.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3SyncResponse.java new file mode 100644 index 00000000..486f1127 --- /dev/null +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3SyncResponse.java @@ -0,0 +1,14 @@ +package cn.axzo.msg.center.service.template.request; + +import com.alibaba.fastjson.JSONObject; +import lombok.Getter; +import lombok.Setter; + +/** + * @author yanglin + */ +@Setter +@Getter +public class MessageTemplateV3SyncResponse { + private JSONObject template; +} diff --git a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3UpdateStatusRequest.java b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3UpdateStatusRequest.java index 369a9426..f6f86ee6 100644 --- a/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3UpdateStatusRequest.java +++ b/msg-center-api/src/main/java/cn/axzo/msg/center/service/template/request/MessageTemplateV3UpdateStatusRequest.java @@ -23,7 +23,6 @@ public class MessageTemplateV3UpdateStatusRequest implements Serializable { /** * 操作者的自然人id */ - @NotNull(message = "operatorId is required") private Long operatorId; /** * 模板编码 diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateButtonV3.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateButtonV3.java index be150cfd..fea3f6f4 100644 --- a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateButtonV3.java +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/entity/MessageTemplateButtonV3.java @@ -77,7 +77,7 @@ public class MessageTemplateButtonV3 extends BaseEntityWithOperator /** * 卡片跳转配置. 在links的基础上再包一层, 避免以后卡片增加自己的配置 */ - @TableField(typeHandler = FastjsonTypeHandler.class) + @TableField(typeHandler = IgnorePropsJsonTypeHandler.class) private CardUrlConfig cardUrlConfig; /** @@ -98,4 +99,22 @@ public class MessageTemplateV3 extends BaseEntityWithOperator * 是否显示在列表中. YES: 是, NO: 否 */ private YesOrNo displayOnList; + + /** + * 扩展字段 + */ + @TableField(typeHandler = IgnorePropsJsonTypeHandler.class) + private RecordExt recordExt; + + public RecordExt getOrCreateRecordExt() { + if (recordExt == null) recordExt = new RecordExt(); + return recordExt; + } + + @Setter + @Getter + public static class RecordExt { + private Boolean isMigrated; + } + } \ No newline at end of file diff --git a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/utils/IgnorePropsJsonTypeHandler.java b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/utils/IgnorePropsJsonTypeHandler.java index 4f26168d..e5b5b06f 100644 --- a/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/utils/IgnorePropsJsonTypeHandler.java +++ b/msg-center-domain/src/main/java/cn/axzo/msg/center/domain/utils/IgnorePropsJsonTypeHandler.java @@ -1,6 +1,7 @@ package cn.axzo.msg.center.domain.utils; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -29,7 +30,7 @@ public class IgnorePropsJsonTypeHandler extends AbstractJsonTypeHandler @Override protected String toJson(Object obj) { - return JSON.toJSONString(obj); + return JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect); } } \ No newline at end of file diff --git a/msg-notices/msg-notices-client/src/main/java/cn/axzo/msg/center/notices/client/config/MybatisPlusConfig.java b/msg-notices/msg-notices-client/src/main/java/cn/axzo/msg/center/notices/client/config/MybatisPlusConfig.java index 1e819082..ff7a19de 100644 --- a/msg-notices/msg-notices-client/src/main/java/cn/axzo/msg/center/notices/client/config/MybatisPlusConfig.java +++ b/msg-notices/msg-notices-client/src/main/java/cn/axzo/msg/center/notices/client/config/MybatisPlusConfig.java @@ -26,7 +26,7 @@ public class MybatisPlusConfig { return new EntityMetaObjectHandler(); } - @Component + //@Component public static class JsonObjectTypeHandlerRegister implements BeanPostProcessor { @Override diff --git a/start/src/test/java/cn/axzo/msg/center/message/xxl/MigrateMessageTemplateV3JobTest.java b/start/src/test/java/cn/axzo/msg/center/message/xxl/MigrateMessageTemplateV3JobTest.java new file mode 100644 index 00000000..a0a81039 --- /dev/null +++ b/start/src/test/java/cn/axzo/msg/center/message/xxl/MigrateMessageTemplateV3JobTest.java @@ -0,0 +1,28 @@ +package cn.axzo.msg.center.message.xxl; + +import cn.axzo.msg.center.MsgCenterApplication; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.Commit; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author yanglin + */ +@SpringBootTest(classes = MsgCenterApplication.class) +@RequiredArgsConstructor(onConstructor_ = @Autowired) +class MigrateMessageTemplateV3JobTest { + + private final MigrateMessageTemplateV3Job migrateMessageTemplateV3Job; + + @Test @Rollback @Transactional + void exec() { + migrateMessageTemplateV3Job.execute("{\"templateCodes\":[\"1c7effbba987411fbb6719619d2f5f07\"]}"); + } + +} \ No newline at end of file