From dea8895673cee1ac00b1a58b507ef981d162c6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=89=8D=E7=A6=8F?= Date: Wed, 7 Jun 2023 11:22:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0mapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inside-notices/pom.xml | 34 + .../notices/enums/AgencyOperationEnum.java | 26 + .../inside/notices/enums/NativeTypeEnum.java | 41 ++ .../notices/event/AgencyChangeEvent.java | 38 ++ .../notices/event/SendMessageEvent.java | 61 ++ .../notices/service/IMessageService.java | 48 -- .../notices/service/MessageCoreService.java | 29 + .../notices/service/MessageRouterService.java | 2 - .../service/impl/MessageCoreServiceImpl.java | 290 +++++++++ .../impl/MessageRecordServiceImpl.java | 597 ++++++++++++++++++ .../impl/MessageRelationServiceImpl.java | 141 +++++ .../impl/MessageRouterServiceImpl.java | 109 ++++ .../impl/MessageTemplateServiceImpl.java | 87 +++ .../resources/mapper/MessageModuleMapper.xml | 55 ++ .../resources/mapper/MessageRecordMapper.xml | 174 +++++ .../mapper/MessageRelationMapper.xml | 17 + .../resources/mapper/MessageRouterMapper.xml | 18 + .../mapper/MessageTemplateMapper.xml | 17 + .../axzo/msg/center/common/enums/IEnum.java | 27 + .../msg/center/common/enums/IdentityType.java | 53 ++ .../axzo/msg/center/common/enums/OuType.java | 39 ++ .../center/common/enums/SystemTypeEnum.java | 43 ++ .../center/common/model/ProfileIdRepair.java | 204 ++++++ .../center/common/utils/BeanConvertUtils.java | 142 +++++ .../msg/center/common/utils/ObjectUtils.java | 97 +++ .../common/utils/PlaceholderResolver.java | 193 ++++++ .../center/common/utils/ReflectionUtils.java | 247 ++++++++ .../msg/center/common/utils/SpringUtils.java | 98 +++ msg-center-webapi/pom.xml | 6 + .../msg/center/webapi/MessageController.java | 54 ++ .../controller/MessageNotifyController.java | 4 +- .../http/api/api/MessageNotifyApi.java | 2 +- .../axzo/msg/center/MsgCenterApplication.java | 4 +- 33 files changed, 2943 insertions(+), 54 deletions(-) create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/enums/AgencyOperationEnum.java create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/enums/NativeTypeEnum.java create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/AgencyChangeEvent.java create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/SendMessageEvent.java delete mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/IMessageService.java create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/MessageCoreService.java create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageCoreServiceImpl.java create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRecordServiceImpl.java create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRelationServiceImpl.java create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRouterServiceImpl.java create mode 100644 inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageTemplateServiceImpl.java create mode 100644 inside-notices/src/main/resources/mapper/MessageModuleMapper.xml create mode 100644 inside-notices/src/main/resources/mapper/MessageRecordMapper.xml create mode 100644 inside-notices/src/main/resources/mapper/MessageRelationMapper.xml create mode 100644 inside-notices/src/main/resources/mapper/MessageRouterMapper.xml create mode 100644 inside-notices/src/main/resources/mapper/MessageTemplateMapper.xml create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IEnum.java create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IdentityType.java create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/OuType.java create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/SystemTypeEnum.java create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/model/ProfileIdRepair.java create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/BeanConvertUtils.java create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/ObjectUtils.java create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/PlaceholderResolver.java create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/ReflectionUtils.java create mode 100644 msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/SpringUtils.java create mode 100644 msg-center-webapi/src/main/java/cn/axzo/msg/center/webapi/MessageController.java diff --git a/inside-notices/pom.xml b/inside-notices/pom.xml index 02a0afca..3174d467 100644 --- a/inside-notices/pom.xml +++ b/inside-notices/pom.xml @@ -56,6 +56,40 @@ org.aspectj aspectjweaver + + org.springframework.boot + spring-boot-starter-aop + + + com.baomidou + mybatis-plus-boot-starter + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + RELEASE + + + mysql + mysql-connector-java + runtime + + + org.mapstruct + mapstruct + + + com.zaxxer + HikariCP + + + org.springframework.boot + spring-boot-starter-jdbc + + + com.baomidou + mybatis-plus-generator + \ No newline at end of file diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/enums/AgencyOperationEnum.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/enums/AgencyOperationEnum.java new file mode 100644 index 00000000..bc63af24 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/enums/AgencyOperationEnum.java @@ -0,0 +1,26 @@ +package cn.axzo.msg.center.inside.notices.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import lombok.Getter; + +/** + * 分包信息操作枚举 + * + * @author: wangli + * @date: 2021/10/28 14:11 + */ +@Getter +public enum AgencyOperationEnum { + CREATE(1, "创建"), + DELETE(2, "删除"), + UPDATE(3, "更新"); + + @EnumValue + private final Integer value; + private final String desc; + + AgencyOperationEnum(Integer value, String desc) { + this.value = value; + this.desc = desc; + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/enums/NativeTypeEnum.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/enums/NativeTypeEnum.java new file mode 100644 index 00000000..19600518 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/enums/NativeTypeEnum.java @@ -0,0 +1,41 @@ +package cn.axzo.msg.center.inside.notices.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +public enum NativeTypeEnum { + + //路由类型(0=null 1=uniapp 2=native 3=H5 4=webCms)", example = "1 + WEB(1,4), + MINI_PROGRAM(2, 1), + IOS(3, 2), + ANDROID(4, 2), + H5(5, 3), + WECHAT_MP(6, 5), + ; + + @EnumValue + private final Integer code; + private final Integer message; + + NativeTypeEnum(Integer code, Integer message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return this.code; + } + + public Integer getMessage() { + return this.message; + } + + public static NativeTypeEnum getByCode(Integer code) { + return Arrays.stream(values()).filter(it -> it.code.equals(code)).findFirst().orElse(null); + } + +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/AgencyChangeEvent.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/AgencyChangeEvent.java new file mode 100644 index 00000000..a8289fbe --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/AgencyChangeEvent.java @@ -0,0 +1,38 @@ +package cn.axzo.msg.center.inside.notices.event; + +import cn.axzo.msg.center.inside.notices.enums.AgencyOperationEnum; +import org.springframework.context.ApplicationEvent; + +/** + * 分包机构创建事件对象 + * + * @author: wangli + * @date: 2021/10/28 14:06 + */ +public class AgencyChangeEvent extends ApplicationEvent { + + public final static Object OBJECT = new Object(); + /** + * 分包机构 id + */ + private final Long departmentId; + + /** + * 分包机构操作类型 + */ + private final AgencyOperationEnum operation; + + public AgencyChangeEvent(Long departmentId, AgencyOperationEnum operation) { + super(OBJECT); + this.departmentId = departmentId; + this.operation = operation; + } + + public Long getDepartmentId() { + return departmentId; + } + + public AgencyOperationEnum getOperation() { + return operation; + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/SendMessageEvent.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/SendMessageEvent.java new file mode 100644 index 00000000..409db481 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/event/SendMessageEvent.java @@ -0,0 +1,61 @@ +package cn.axzo.msg.center.inside.notices.event; + +import cn.axzo.msg.center.api.request.MsgBody4Guest; +import org.springframework.context.ApplicationEvent; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @ClassName SendMessgeEvent + * @Description TODO + * @Author zhangran + * @Date 2022/4/8 11:36 + **/ +public class SendMessageEvent extends ApplicationEvent { + + /** + * 消息实体 + */ + private MsgBody4Guest message; + /** + * 消息id + */ + private Long msgId; + + private AtomicInteger retryCounting = new AtomicInteger(0); + + private AtomicBoolean isSend = new AtomicBoolean(true); + private String errMsg; + + + public SendMessageEvent(Long msgId, MsgBody4Guest message) { + super(AgencyChangeEvent.OBJECT); + this.message = message; + this.msgId = msgId; + } + + public AtomicInteger getRetryCounting() { + return retryCounting; + } + + public MsgBody4Guest getMessage() { + return message; + } + + public Long getMsgId() { + return msgId; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } + + public AtomicBoolean getIsSend() { + return isSend; + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/IMessageService.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/IMessageService.java deleted file mode 100644 index 1a32154d..00000000 --- a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/IMessageService.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.axzo.msg.center.inside.notices.service; - -import cn.axzo.basics.common.page.PageRequest; -import cn.axzo.basics.common.page.PageResult; -import cn.axzo.msg.center.inside.notices.model.request.ConversationRes; -import cn.axzo.msg.center.inside.notices.model.request.MessageNewRes; -import cn.axzo.msg.center.inside.notices.model.request.MessageRes; -import cn.axzo.msg.center.api.response.Message; - -import java.util.List; - -/** - * @author zhangPeng - * @description - * @date 2021/2/4 15:48 - */ -public interface IMessageService { - - List getConversations(Long userId, Long acctId); - - /** - * 班组长同意工人的加入班组申请通知 - * - * @param message - */ - void sendNotify(Message message); - - - - PageResult getConversationMsg(Long conversationId, PageRequest pageRequest); - - void setNewRouter(MessageNewRes message, int system); - - int submitReadStatus(List msgIds); - - int submitConversationReadStatus(Long conversationId, List msgIds); - - int delConversation(Long userId, Long acctId, Integer imId); - - /** - * 获取userId的推送计数 - * @param userId - * @param count - * @return - */ - boolean resetNotifyCount(Long userId, Integer count); - -} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/MessageCoreService.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/MessageCoreService.java new file mode 100644 index 00000000..f4dc3e97 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/MessageCoreService.java @@ -0,0 +1,29 @@ +package cn.axzo.msg.center.inside.notices.service; + + + +import cn.axzo.msg.center.common.page.PageResult; +import cn.axzo.msg.center.inside.notices.model.request.CmsMsgQueryReq; +import cn.axzo.msg.center.inside.notices.model.request.MessageNewRes; +import cn.axzo.msg.center.inside.notices.model.response.MessageTotalRes; + +import java.util.List; + +/** + * @author : liuchuntao + * @date : 2022/3/28 11:48 + * @description : 消息中心新接口相关 + */ +public interface MessageCoreService { + + /** + * 获取所有业务(按业务规则)合计未读消息数量 + * + * @return + */ + MessageTotalRes statisticsMsg(); + + + + PageResult listMsgInfo(CmsMsgQueryReq req); +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/MessageRouterService.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/MessageRouterService.java index 1c5565d4..4d127ddc 100644 --- a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/MessageRouterService.java +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/MessageRouterService.java @@ -30,6 +30,4 @@ public interface MessageRouterService { List getRouterMapByRelationIds(List relationIds); - void syncData(SyncRelationDataDTO routers); - } diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageCoreServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageCoreServiceImpl.java new file mode 100644 index 00000000..2e6294f6 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageCoreServiceImpl.java @@ -0,0 +1,290 @@ +package cn.axzo.msg.center.inside.notices.service.impl; + +import cn.axzo.basics.common.util.AssertUtil; +import cn.axzo.framework.auth.domain.ContextInfoHolder; +import cn.axzo.msg.center.common.enums.SystemTypeEnum; +import cn.axzo.msg.center.common.exception.ServiceException; +import cn.axzo.msg.center.common.page.PageResult; +import cn.axzo.msg.center.common.utils.PlaceholderResolver; +import cn.axzo.msg.center.inside.notices.entity.MessageModule; +import cn.axzo.msg.center.inside.notices.entity.MessageRelation; +import cn.axzo.msg.center.inside.notices.entity.MessageRouter; +import cn.axzo.msg.center.inside.notices.enums.ModuleBizTypeEnum; +import cn.axzo.msg.center.inside.notices.enums.MsgRouteTypeEnum; +import cn.axzo.msg.center.inside.notices.enums.NativeTypeEnum; +import cn.axzo.msg.center.inside.notices.enums.UserTypeEnum; +import cn.axzo.msg.center.inside.notices.model.request.CmsMsgQueryReq; +import cn.axzo.msg.center.inside.notices.model.request.MessageNewRes; +import cn.axzo.msg.center.inside.notices.model.response.MessageTotalRes; +import cn.axzo.msg.center.inside.notices.service.*; +import cn.axzo.msg.center.inside.notices.service.dto.MsgModuleDTO; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static cn.axzo.framework.auth.domain.TerminalInfo.NT_CM_APP_GENERAL; +import static cn.axzo.msg.center.inside.notices.enums.MsgRouteTypeEnum.WECHAT_MINI_PROGRAM; + +/** + * @author : liuchuntao + * @date : 2022/3/28 11:52 + * @description : 消息中心实现 + */ +@Service +@Slf4j +public class MessageCoreServiceImpl implements MessageCoreService { + + @Resource + private MessageRecordService messageRecordService; + + @Resource + private MessageModuleService messageModuleService; + + @Resource + private MessageRouterService messageRouterService; + + @Resource + private MessageRelationService relationService; + + /** + * 获取用户类型 + * + * @return + */ + public UserTypeEnum getUserType() { + + UserTypeEnum userTypeEnum = UserTypeEnum.valueOf(ContextInfoHolder.get().getUserInfo().getIdentityType()); + + if (userTypeEnum == null) { + throw new ServiceException("未获取到用户类型"); + } + return userTypeEnum; + } + + public MsgRouteTypeEnum getSystemType() { + String systemType = ContextInfoHolder.get().getSystemAndDeviceInfo().getSystemType(); + + //判断是否为手机端调用 + if (SystemTypeEnum.IOS.get().equals(systemType)) { + return MsgRouteTypeEnum.IOS; + } + if (SystemTypeEnum.ANDROID.get().equals(systemType)) { + return MsgRouteTypeEnum.ANDROID; + } + if (WECHAT_MINI_PROGRAM.getMessage().equals(systemType)) { + return WECHAT_MINI_PROGRAM; + } + //都不是表明确定web端调用 + return MsgRouteTypeEnum.WEB; + } + + /** + * 消息统计 + * + * @return + */ + @Override + public MessageTotalRes statisticsMsg() { + Long personId = ContextInfoHolder.get().getUserInfo().getPersonId(); + AssertUtil.isTrue(0L != personId, "数据异常, 当前登录用户的自然人 ID 为 0, 无法执行消息统计查询!, ContextInfo : " + + JSON.toJSONString(ContextInfoHolder.get())); + + // 如果是工人 APP,则需要走特殊的查询逻辑, 需要将施工业务的对应身份数据查询出来,交易业务全量数据查询出来,合并为一个列表返回 +// if(Objects.equals(NT_CM_APP_GENERAL, ContextInfoHolder.get().getSystemAndDeviceInfo().getLoginDevice())) { +// personId = ContextInfoHolder.get().getUserInfo().getPersonId(); +// } + + Long identityId = ContextInfoHolder.get().getUserInfo().getIdentityId(); + UserTypeEnum userTypeEnum = getUserType(); + + //根据用户和当前身份获取未读和待办消息 + return messageRecordService.statisticsMsg4Total(personId, identityId, userTypeEnum); + } + + + /** + * 消息列表 (原施工逻辑中兼容交易业务的无身份类型) + * + * @param req + * @return + */ + @Override + public PageResult listMsgInfo(CmsMsgQueryReq req) { + PageResult resPageResult; + Long identityId = ContextInfoHolder.get().getUserInfo().getIdentityId(); + Long personId = null; + + // 如果是工人 APP,则需要走特殊的查询逻辑, 需要将施工业务的对应身份数据查询出来,交易业务全量数据查询出来,合并为一个列表返回 + if (Objects.equals(NT_CM_APP_GENERAL, ContextInfoHolder.get().getSystemAndDeviceInfo().getLoginDevice())) { + personId = ContextInfoHolder.get().getUserInfo().getPersonId(); + } + resPageResult = messageRecordService.pageMsgInfo(req, personId, identityId, getUserType()); + + List resList = refineMessageRes(resPageResult, req); + + complementMsg(resList); + return new PageResult<>(resList, resPageResult.getTotalCount()); + } + + public List refineMessageRes(PageResult resPageResult, + CmsMsgQueryReq req) { + //路由信息获取 + List resList = resPageResult.getData(); + if (CollectionUtils.isEmpty(resList)) { + return resList; + } + //获取relationId集合 + Set relationIds = resList.stream().map(MessageNewRes::getRelationId).collect( + Collectors.toSet()); + if (CollectionUtils.isNotEmpty(relationIds)) { + relationIds.remove(null); + relationIds.remove(0L); + } + + //获取oldTypeId集合 + Set oldTypeIds = resList.stream().map(MessageNewRes::getOldTypeId).collect( + Collectors.toSet()); + if (CollectionUtils.isNotEmpty(oldTypeIds)) { + oldTypeIds.remove(null); + oldTypeIds.remove(0); + } + if (CollectionUtils.isEmpty(relationIds) && CollectionUtils.isEmpty(oldTypeIds)) { + return resList; + } + //获取模板所对应的所有模块及icon + List moduleDtos = messageModuleService.listModuleByRelationIdsOrTypeIds(oldTypeIds, relationIds); + //新关联键分组 + Map> relationModule = moduleDtos.stream().filter(k -> k.getRelationId() != null && k.getRelationId() != 0) + .collect(Collectors.groupingBy(MsgModuleDTO::getRelationId)); + //老关联键分组 + Map> typeIdModules = moduleDtos.stream().filter(k -> k.getTypeId() != null && k.getTypeId() != 0) + .collect(Collectors.groupingBy(MsgModuleDTO::getTypeId)); + + //批量获取路由信息 + MsgRouteTypeEnum msgRouteTypeEnum = getSystemType(); + List routers = new ArrayList<>(); + Map> mapRout = new HashMap<>(); + if (CollectionUtils.isNotEmpty(relationIds)) { + routers = messageRouterService.listRoutersByRelationIds(relationIds); + mapRout = routers.stream().collect(Collectors.groupingBy(MessageRouter::getRelationId)); + } + Map> finalMapRout = mapRout; + resList.forEach(item -> { + //赋值状态 + if (req.getMsgType() == 1) { + item.setState(item.getState() == 4 ? 2 : 1); + } else { + item.setState(item.getState() == 5 ? 2 : 1); + } + //赋值模板 + if (item.getRelationId() != null && item.getRelationId() != 0) { + List modules = relationModule.get(item.getRelationId()); + if (CollectionUtils.isNotEmpty(modules)) { + MsgModuleDTO first = modules.stream() + .filter(i -> i.getOwnedType().equals(item.getReceiveType())) + .findFirst().orElse(modules.get(0)); + item.setMsgIcon(first.getMsgModuleIcon()); + item.setMsgName(first.getMsgModuleName()); + } + } + if (StrUtil.isEmpty(item.getMsgIcon())) { + List modules = typeIdModules.get(item.getOldTypeId()); + if (CollectionUtils.isNotEmpty(modules)) { + MsgModuleDTO first = modules.stream() + .filter(i -> i.getOwnedType().equals(item.getReceiveType())) + .findFirst().orElse(modules.get(0)); + item.setMsgIcon(first.getMsgModuleIcon()); + item.setMsgName(first.getMsgModuleName()); + } + } + List messageRouters = finalMapRout.get(item.getRelationId()); + if (CollectionUtils.isNotEmpty(messageRouters)) { + if (messageRouters.size() == 1) { + NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode(messageRouters.get(0).getRouterType().getCode()); + if (nativeTypeEnum != null) { + item.setRouter(messageRouters.get(0).getRouterUrl()); + item.setRouterType(nativeTypeEnum.getMessage()); + } + } else { + //不止一条 获取当前系统对应路由 + List router = messageRouters.stream().filter(k -> k.getRouterType().equals(msgRouteTypeEnum)).collect( + Collectors.toList()); + if (CollectionUtils.isNotEmpty(router)) { + NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode(router.get(0).getRouterType().getCode()); + if (nativeTypeEnum != null) { + item.setRouter(router.get(0).getRouterUrl()); + item.setRouterType(nativeTypeEnum.getMessage()); + } + } else { + //优先取H5 + List routerH5 = messageRouters.stream().filter(k -> k.getRouterType().equals(MsgRouteTypeEnum.WEBVIEW)).collect( + Collectors.toList()); + if (CollectionUtils.isNotEmpty(routerH5)) { + NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode(routerH5.get(0).getRouterType().getCode()); + if (nativeTypeEnum != null) { + item.setRouter(routerH5.get(0).getRouterUrl()); + item.setRouterType(nativeTypeEnum.getMessage()); + } + } + + //再取小程序 + List routerUni = messageRouters.stream().filter(k -> k.getRouterType().equals(MsgRouteTypeEnum.MINI_PROGRAM)).collect( + Collectors.toList()); + if (CollectionUtils.isNotEmpty(routerUni)) { + NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode( + routerUni.get(0).getRouterType().getCode()); + if (nativeTypeEnum != null) { + item.setRouter(routerUni.get(0).getRouterUrl()); + item.setRouterType(nativeTypeEnum.getMessage()); + } + } + } + } + } + PlaceholderResolver resolver = PlaceholderResolver.getDefaultResolver(); + if (StringUtils.hasLength(item.getRouter())) { + item.setRouter(resolver.resolveByMap(item.getRouter(), + JSON.parseObject(Objects.equals(item.getRouterParam(), "null") ? "{}" : item.getRouterParam(), Map.class))); + } + }); + return resList; + } + + private void complementMsg(List resList) { + Set nullModuleRelationIds = resList.stream().filter( + i -> !StringUtils.hasLength(i.getMsgIcon()) && !StringUtils.hasLength(i.getMsgName())) + .map(MessageNewRes::getRelationId).collect( + Collectors.toSet()); + if (CollectionUtils.isEmpty(nullModuleRelationIds)) { + return; + } + List msgRelation = relationService.getRelationByIds(nullModuleRelationIds); + List moduleIds = msgRelation.stream() + .map(MessageRelation::getModuleId).collect(Collectors.toList()); + + Map moduleMap = messageModuleService.getModuleByIds(moduleIds).stream() + .collect(Collectors.toMap(MessageModule::getId, Function.identity(), (s, t) -> s)); + + Map relationModuleMapping = new HashMap<>(); + msgRelation.forEach(i -> { + relationModuleMapping.put(i.getId(), moduleMap.get(i.getModuleId())); + }); + + resList.stream().filter(i -> !StringUtils.hasLength(i.getMsgIcon()) && !StringUtils.hasLength(i.getMsgName())).forEach(i -> { + MessageModule messageModule = relationModuleMapping.getOrDefault(i.getRelationId(), + new MessageModule()); + i.setMsgIcon(messageModule.getIcon()); + i.setMsgName(messageModule.getModuleName()); + }); + } + +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRecordServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRecordServiceImpl.java new file mode 100644 index 00000000..5ccfdedf --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRecordServiceImpl.java @@ -0,0 +1,597 @@ +package cn.axzo.msg.center.inside.notices.service.impl; + +import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum; +import cn.axzo.basics.common.util.AssertUtil; +import cn.axzo.framework.auth.domain.ContextInfoHolder; +import cn.axzo.msg.center.api.enums.*; +import cn.axzo.msg.center.api.request.CmsReadMsgReq; +import cn.axzo.msg.center.api.request.GeneralMessage; +import cn.axzo.msg.center.api.request.MsgBody4Guest; +import cn.axzo.msg.center.api.request.MsgReturnParamRes; +import cn.axzo.msg.center.common.enums.IdentityType; +import cn.axzo.msg.center.common.exception.ServiceException; +import cn.axzo.msg.center.common.model.ProfileIdRepair; +import cn.axzo.msg.center.common.page.PageResult; +import cn.axzo.msg.center.common.utils.BeanConvertUtils; +import cn.axzo.msg.center.common.utils.PlaceholderResolver; +import cn.axzo.msg.center.common.utils.SpringUtils; +import cn.axzo.msg.center.inside.notices.dao.*; +import cn.axzo.msg.center.inside.notices.entity.*; +import cn.axzo.msg.center.inside.notices.enums.ModuleBizTypeEnum; +import cn.axzo.msg.center.inside.notices.enums.MsgRouteTypeEnum; +import cn.axzo.msg.center.inside.notices.enums.NativeTypeEnum; +import cn.axzo.msg.center.inside.notices.enums.UserTypeEnum; +import cn.axzo.msg.center.inside.notices.event.SendMessageEvent; +import cn.axzo.msg.center.inside.notices.model.request.CmsMsgQueryReq; +import cn.axzo.msg.center.inside.notices.model.request.MessageNewRes; +import cn.axzo.msg.center.inside.notices.model.response.MessageTotalRes; +import cn.axzo.msg.center.inside.notices.service.MessageRecordService; +import cn.axzo.msg.center.inside.notices.service.dto.MsgStatisticsDTO; +import cn.azxo.framework.common.utils.LogUtil; +import cn.azxo.framework.common.utils.LogUtil.ErrorLevel; +import cn.azxo.framework.common.utils.LogUtil.ErrorType; +import cn.azxo.framework.common.utils.StringUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.text.StrSubstitutor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.util.*; +import java.util.stream.Collectors; + +import static cn.axzo.msg.center.inside.notices.enums.MsgRouteTypeEnum.WECHAT_MINI_PROGRAM; + + +/** + * 消息记录(MessageRecord)表服务实现类 + * + * @author zhangran + * @since 2022-03-28 14:59:16 + */ +@Service +@Slf4j +public class MessageRecordServiceImpl implements MessageRecordService { + + @Value("${msg.center.server.partition-size:5000}") + private Integer partitionSize; + @Value("${msg.center.server.push-athena:true}") + private Boolean pushAthena; + + @Resource + private MessageRecordDao messageRecordDao; + @Resource + private MessageRelationDao messageRelationDao; + @Resource + private MessageTemplateDao messageTemplateDao; + @Resource + private MessageModuleDao messageModuleDao; + @Resource + private MessageRouterDao messageRouterDao; + /*@Resource + private IdentityProfileService identityProfileService;*/ + + /** + * 新增推送消息接口 + * + * @param message + * @return 消息唯一主键 + */ + @Override + public List pushMsg(GeneralMessage message) { + log.info("pushMsg message:{}", JSON.toJSONString(message)); + + MessageRecord basic = BeanConvertUtils.copyBean(message, MessageRecord.class); + basic.setExtra(org.springframework.util.StringUtils.hasLength(message.getExt()) + ? message.getExt() : "{}"); + basic.setRouterParams(Objects.nonNull(message.getRouterParams()) + ? JSON.toJSONString(message.getRouterParams()) : "{}"); + + // 消息模板参数替换 + MessageRelation relation = messageRelationDao.getById(message.getRelationId()); + AssertUtil.notNull(relation, "消息模板不存在"); + + MessageTemplate messageTemplate = messageTemplateDao.getById(relation.getTemplateId()); + AssertUtil.notNull(messageTemplate, "消息模板不存在"); + + StrSubstitutor strSubstitutor = new StrSubstitutor(message.getMsgParams()); + String title = strSubstitutor.replace(messageTemplate.getTitle()); + String content = strSubstitutor.replace(messageTemplate.getContent()); + + // 消息模块 + MessageModule messageModule = messageModuleDao.getById(relation.getModuleId()); + AssertUtil.notNull(messageModule, "消息模块不存在"); + + basic.setModuleId(messageModule.getId()); + basic.setTitle(title); + basic.setContent(content); + basic.setReceiveType(message.getReceiveType()); + basic.setState(MsgStateEnum.UNSENT); + + if (message.getTerminalType() == null) { + basic.setTerminalType(MsgRecordTerminalTypeEnum.UNKNOWN); + } + + List pushMessages = new ArrayList<>(); + Lists.partition(Lists.newArrayList(message.getToId()), partitionSize).forEach(toIds -> { + pushMessages.addAll(saveBatch(basic, toIds)); + }); + + if(pushAthena) { + asyncPushAthena(message, messageTemplate.getAudioFileName(), messageModule.getModuleName(), pushMessages); + } + + return pushMessages.stream().map(item -> { + MsgReturnParamRes res = new MsgReturnParamRes(); + res.setToId(0L == item.getToId() ? item.getPersonId(): item.getToId()); + res.setRecordId(item.getId()); + return res; + }).collect(Collectors.toList()); + } + + @Async + public void asyncPushAthena(GeneralMessage message, String audioFileName, String moduleName, + List pushMessages) { + sendMessage(message.getRelationId(), audioFileName, + moduleName, pushMessages, message.getRouterParams()); + } + @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) + public List saveBatch(MessageRecord basic, List toIds) { + if(CollectionUtils.isEmpty(toIds)) { + return Collections.emptyList(); + } + + List pushMessages = new ArrayList<>(); + if(ReceiveTypeEnum.NOT_IDENTITY.equals(basic.getReceiveType())) { + toIds.forEach(i -> { + MessageRecord messageRecord = BeanConvertUtils.copyBean(basic, MessageRecord.class); + messageRecord.setToId(0L); + messageRecord.setPersonId(i); + pushMessages.add(messageRecord); + }); + }/*else{ + // 根据身份获取自然人信息 + Map profileMap = identityProfileService.findProfileByIdSetV2( + new HashSet<>(toIds), ConvertIdentity(basic.getReceiveType())); + toIds.forEach(i-> { + MessageRecord messageRecord = BeanConvertUtils.copyBean(basic, MessageRecord.class); + IdentityProfileDto dto = profileMap.getOrDefault(i, null); + messageRecord.setToId(i); + messageRecord.setPersonId(Objects.nonNull(dto) && Objects.nonNull(dto.getPersonProfile()) ? + dto.getPersonProfile().getId() : 0L); + pushMessages.add(messageRecord); + }); + }*/ + messageRecordDao.saveBatch(pushMessages); + return pushMessages; + } + + public static IdentityType ConvertIdentity(ReceiveTypeEnum receiveTypeEnum) { + IdentityType identityType; + switch (receiveTypeEnum) { + case CM_LEADER: + identityType = IdentityType.WORKER_LEADER; + break; + case CM_WORKER: + identityType = IdentityType.WORKER; + break; + case CMP_USER: + identityType = IdentityType.PRACTITIONER; + break; + default: + identityType = null; + break; + } + return identityType; + } + + /** + * 推送消息 + * + * @param pushMessages 推送消息 + * @param audioFileName 语音文件 + */ + private void sendMessage(Long relationId, String audioFileName, String moduleName, + List pushMessages, Map routerParams) { + + ArrayList msgRouteTypeEnums = Lists.newArrayList(MsgRouteTypeEnum.ANDROID, + MsgRouteTypeEnum.IOS, MsgRouteTypeEnum.MINI_PROGRAM, MsgRouteTypeEnum.WEBVIEW); + List messageRouters = messageRouterDao.getByRelationId(relationId, + msgRouteTypeEnums); + + MsgBody4Guest imMessage = new MsgBody4Guest(); + imMessage.setTy(0); + imMessage.setF("0"); + imMessage.setNickName(moduleName); + + pushMessages.forEach(item -> { + String toId = buildToId(item.getToId(), item.getPersonId(), item.getReceiveType(), item.getBizId()); + imMessage.setT(toId); + imMessage.setM(item.getContent()); + + JSONObject jsonObject = constructImMessage(item, audioFileName, routerParams, messageRouters); + imMessage.setM2(jsonObject.toJSONString()); + imMessage.setM3(String.valueOf(item.getPersonId())); + + // 发送推送消息事件 + SpringUtils.publishEvent(new SendMessageEvent(item.getId(), imMessage)); + }); + } + + private String buildToId(Long itemToId, Long personId, ReceiveTypeEnum receiveType, Long bizId) { + String toId = ""; + switch (receiveType) { + case CM_LEADER: + toId = ReceiveTypeEnum.CM_LEADER.getMessage() + ProfileIdRepair.workerLeaderNewId2Old( + itemToId); + break; + case CM_WORKER: + toId = ReceiveTypeEnum.CM_WORKER.getMessage() + ProfileIdRepair.workerNewId2OldId(itemToId); + break; + case CMP_USER: + toId = ReceiveTypeEnum.CMP_USER.getMessage() + ProfileIdRepair.entUserNew2OldId(itemToId); + break; + case NOT_IDENTITY: + toId = ReceiveTypeEnum.NOT_IDENTITY.getMessage() + personId; + break; + default: + LogUtil.error(ErrorLevel.P0, ErrorType.ERROR_BUSINESS, "消息推送用户类型错误 bizId", bizId); + throw new ServiceException("消息推送失败"); + } + return toId; + } + + private JSONObject constructImMessage(MessageRecord message, String audioFileName, + Map routerParams, List messageRouters) { + + JSONObject extra = new JSONObject(); + + if (messageRouters.isEmpty()) { + extra.put("ar", ""); + extra.put("ir", ""); + } else { + + // 业务上不会跳转微信小程序 + messageRouters.forEach(item -> { + PlaceholderResolver pr = PlaceholderResolver.getDefaultResolver(); + String url = pr.resolveByMap(item.getRouterUrl(), routerParams); + extra.put("rt", NativeTypeEnum.getByCode(item.getRouterType().getCode()).getMessage()); + switch (item.getRouterType()) { + case IOS: + extra.put("ir", url); + break; + case ANDROID: + extra.put("ar", url); + break; + case WEBVIEW: + case MINI_PROGRAM: + // 小程序 + extra.put("ar", url); + extra.put("ir", url); + break; + default: + } + }); + } + extra.put("msgId", message.getId()); + extra.put("p", message.getRouterParams()); + extra.put("t", message.getTitle()); + extra.put("extra", message.getExtra()); + // 临时处理发送类型,如果消息type为1时,需要前端清空teamId,并且重新拉取数据 + Integer type = 0; + if (StringUtils.isNotBlank(message.getExtra())) { + JSONObject jsonObject = JSON.parseObject(message.getExtra()); + Integer exType = jsonObject.getInteger("type"); + if (type != null) { + type = exType; + } + } + extra.put("type", type); + + if (StringUtils.isNotBlank(audioFileName)) { + extra.put("audio", audioFileName); + } + return extra; + } + + + /** + * 变更执行消息的状态 + * + * @param msgId + * @param state + * @return + */ + @Override + public Boolean changeMessageState(List msgId, MsgStateEnum state) { + List messageRecords = messageRecordDao.listByIds(msgId); + messageRecords = messageRecords.stream().map(item -> { + item.setState(state); + return item; + }).collect(Collectors.toList()); + return messageRecordDao.updateBatchById(messageRecords); + } + + @Override + public Boolean changeMessageState(Long toId, Long relationId, Long bizId, MsgStateEnum state) { + List records = messageRecordDao.lambdaQuery().eq(MessageRecord::getToId, toId) + .eq(MessageRecord::getRelationId, relationId) + .eq(MessageRecord::getBizId, bizId) + .in(MessageRecord::getState, Arrays.asList(2, 3)) + .list(); + if (CollectionUtils.isEmpty(records)) { + log.info("未找到 toId={}, relationId={}, bizId={} 的数据, 无法修改状态!", toId, relationId, bizId); + return false; + } + if (records.size() > 1) { + throw new IllegalStateException("存在多条相同 toId,relationId,bizId 的消息记录"); + } + MessageRecord record = records.get(0); + log.info("消息主键为: {} 的状态被更新为: {}({})", record.getId(), + record.getState().getMessage(), + record.getState().getCode()); + record.setState(state); + return messageRecordDao.updateById(record); + } + + /** + * 消息Id+当前登录类型进行消息读取 + * + * @param req + */ + @Override + public void readMsg(CmsReadMsgReq req) { + if(WECHAT_MINI_PROGRAM.getMessage().equals(ContextInfoHolder.get().getSystemAndDeviceInfo().getSystemType())) { + req.setBizTypeEnum(BizTypeEnum.TRADE); + } else { + req.setBizTypeEnum(BizTypeEnum.CONSTRUCTION); + } + Long personId = ContextInfoHolder.get().getUserInfo().getPersonId(); + Long identityId = ContextInfoHolder.get().getUserInfo().getIdentityId(); + messageRecordDao.readMsg(req, personId, identityId); + } + + /** + * 分页查询-不含路由信息 + * + * @param req + * @param personId + * @param identityId + * @param userTypeEnum + * @return + */ + @Override + public PageResult pageMsgInfo(CmsMsgQueryReq req, Long personId, Long identityId, + UserTypeEnum userTypeEnum) { + log.info("消息列表查询时,身份类型为:{}", userTypeEnum); + ReceiveTypeEnum receiveTypeEnum = ReceiveTypeEnum.getByMessage(userTypeEnum.getName()); + IPage page = req.toPage(); + ArrayList states = buildStates(req); + IPage iPage = messageRecordDao.pageMsgInfo(req, page, receiveTypeEnum.getCode(), + personId, identityId, states); + return new PageResult<>(iPage.getRecords(), iPage.getTotal()); + } + + @Override + public PageResult pageMsgInfo4WechatAndTrade(CmsMsgQueryReq req, Long personId) { + List moduleIds = messageModuleDao.lambdaQuery() + .eq(MessageModule::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .eq(MessageModule::getBizType, ModuleBizTypeEnum.TRADE.getCode()) + .select(MessageModule::getId) + .list().stream().map(MessageModule::getId).collect(Collectors.toList()); + ArrayList states = buildStates(req); + IPage iPage = messageRecordDao.pageMsgInfo4WechatAndTrade(req, moduleIds, personId, + states); + return new PageResult<>(iPage.getRecords(), iPage.getTotal()); + } + + private static ArrayList buildStates(CmsMsgQueryReq req) { + // 普通消息、待办消息未读及未处理消息默认初始状态 2,3 + ArrayList states = Lists.newArrayList(2, 3); + if (req.getMsgType().equals(MsgTypeEnum.GENERAL_MESSAGE.getCode())) { + if (req.getMsgStatus() == 0) { + // 全部 + states.add(4); + } + } else if (req.getMsgType().equals(MsgTypeEnum.PENDING_MESSAGE.getCode())) { + if (req.getMsgStatus() == 1) { + // 未处理 + states.add(4); + } else if (req.getMsgStatus() == 2) { + // 已完成 + states = Lists.newArrayList(5); + } + } + return states; + } + + + /** + * 用户Id + 用户类型进行消息统计 + * + * @param personId + * @param identityId + * @param userTypeEnum + * @return + */ + @Override + public MessageTotalRes statisticsMsg4Total(Long personId, Long identityId, UserTypeEnum userTypeEnum) { + ReceiveTypeEnum typeEnum = ReceiveTypeEnum.getByMessage(userTypeEnum.getName()); + if (typeEnum == null) { + throw new ServiceException("未获取到用户类型信息"); + } + MessageTotalRes res = new MessageTotalRes(); + + List constructionList = messageRecordDao.statisticsMsg4Construction( + identityId, + typeEnum.getCode() + ); + calcCount(constructionList, res); + + List tradeList = messageRecordDao.statisticsMsg4Trade(personId); + calcCount(tradeList, res); + return res; + } + + @Override + public MessageTotalRes statisticsMsg4Construction(Long identityId, UserTypeEnum userTypeEnum) { + List res = messageRecordDao.statisticsMsg4Construction(identityId, + userTypeEnum.getValue()); + return calcCount(res, null); + } + + private MessageTotalRes calcCount(List list, MessageTotalRes res) { + if(Objects.isNull(res)) { + res = new MessageTotalRes(); + } + for (MsgStatisticsDTO item : list) { + if (item.getType().equals(MsgTypeEnum.GENERAL_MESSAGE.getCode())) { + res.setMsgTotal(res.getMsgTotal() + item.getNum()); + } + if (item.getType().equals(MsgTypeEnum.PENDING_MESSAGE.getCode())) { + res.setUpcomingTotal(res.getUpcomingTotal() + item.getNum()); + } + } + res.setAllTotal(res.getMsgTotal() + res.getUpcomingTotal()); + return res; + } + + @Override + public MessageTotalRes statisticsMsg4Trade(Long personId) { + List res = messageRecordDao.statisticsMsg4Trade(personId); + return calcCount(res, null); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void initRelation(List> relations, List> routers) { + HashMap> hashMap = new HashMap<>(); + + HashMap moduleMap = new HashMap<>(); + moduleMap.put("施工管理", 1L); + moduleMap.put("交底管理", 4L); + moduleMap.put("违规通告", 7L); + moduleMap.put("劳务发包", 10L); + moduleMap.put("招工找活", 13L); + moduleMap.put("薪资管理", 16L); + moduleMap.put("我的收入", 19L); + moduleMap.put("项目公告", 22L); + moduleMap.put("系统消息", 25L); + + for (Map item : routers) { + Long typeid = (Long) item.get("typeid"); + String ios = (String) item.get("ios"); + String ar = (String) item.get("ar"); + String un = (String) item.get("un"); + + ArrayList rs = Lists.newArrayList(); + addList(ios, rs); + addList(ar, rs); + addList(un, rs); + hashMap.put(typeid, rs); + } + + ArrayList routerLists = Lists.newArrayList(); + + for (Map item : relations) { + String module = (String) item.get("module"); + Long id = (Long) item.get("id"); + String leader = (String) item.get("leader"); + String worker = (String) item.get("worker"); + String cmp = (String) item.get("cmp"); + + MessageRelation messageRelation = new MessageRelation(); + messageRelation.setTemplateId(id); + + if (StringUtils.isNotBlank(leader)) { + messageRelation.setModuleId(moduleMap.get(module)); + messageRelation.setTypeId(Integer.parseInt(leader)); + messageRelationDao.save(messageRelation); + + List messageRouters = + saveRouterList(messageRelation.getId(), leader, hashMap); + routerLists.addAll(messageRouters); + } + if (StringUtils.isNotBlank(worker)) { + messageRelation.setModuleId(moduleMap.get(module) + 1L); + messageRelation.setTypeId(Integer.parseInt(worker)); + messageRelation.setId(null); + messageRelationDao.save(messageRelation); + + List messageRouters = + saveRouterList(messageRelation.getId(), worker, hashMap); + routerLists.addAll(messageRouters); + } + if (StringUtils.isNotBlank(cmp)) { + messageRelation.setModuleId(moduleMap.get(module) + 2L); + messageRelation.setTypeId(Integer.parseInt(cmp)); + messageRelation.setId(null); + messageRelationDao.save(messageRelation); + + List messageRouters = + saveRouterList(messageRelation.getId(), cmp, hashMap); + routerLists.addAll(messageRouters); + } + } + messageRouterDao.saveBatch(routerLists); + } + + private List saveRouterList(Long relationId, String typeId, + HashMap> hashMap) { + + List stringList = hashMap.getOrDefault(Long.parseLong(typeId), Lists.newArrayList()); + if (stringList.isEmpty()) { + return Lists.newArrayList(); + } + + return stringList.stream().map(item -> { + MessageRouter messageRouter = new MessageRouter(); + messageRouter.setRelationId(relationId); + if (item.startsWith("AX")) { + messageRouter.setRouterType(MsgRouteTypeEnum.IOS); + messageRouter.setRouterUrl(item); + } else if (item.startsWith("cn")) { + messageRouter.setRouterType(MsgRouteTypeEnum.ANDROID); + messageRouter.setRouterUrl(item); + } else { + messageRouter.setRouterType(MsgRouteTypeEnum.MINI_PROGRAM); + messageRouter.setRouterUrl(item); + } + return messageRouter; + }).collect(Collectors.toList()); + + + } + + @Override + public IPage querySendFailMsg(IPage page) { + return messageRecordDao.lambdaQuery() + .eq(MessageRecord::getState, MsgStateEnum.UNSENT.getCode()) +// .ne(MessageRecord::getEventSource, "") + .page(page); + } + + private void addList(String param, List list) { + if (!StringUtils.isBlank(param)) { + list.add(param); + } + } + + @Override + public PageResult mixIdentityPageMsgInfo(CmsMsgQueryReq req, List identityIds, Long personId) { + ArrayList states = buildStates(req); + IPage iPage = messageRecordDao.mixIdentityPageMsgInfo(req, identityIds, personId, states); + return new PageResult<>(iPage.getRecords(), iPage.getTotal()); + } + + +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRelationServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRelationServiceImpl.java new file mode 100644 index 00000000..bf28d1d9 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRelationServiceImpl.java @@ -0,0 +1,141 @@ +package cn.axzo.msg.center.inside.notices.service.impl; + +import cn.axzo.msg.center.common.enums.TableIsDeleteEnum; +import cn.axzo.msg.center.inside.notices.dao.MessageRelationDao; +import cn.axzo.msg.center.inside.notices.entity.MessageRelation; +import cn.axzo.msg.center.inside.notices.entity.MessageRouter; +import cn.axzo.msg.center.inside.notices.entity.MessageTemplate; +import cn.axzo.msg.center.inside.notices.enums.MsgRouteTypeEnum; +import cn.axzo.msg.center.inside.notices.persistence.BaseEntity; +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.inside.notices.service.dto.CreateTemplateDTO; +import cn.axzo.msg.center.inside.notices.service.dto.SearchTemplateDTO; +import cn.axzo.msg.center.inside.notices.service.dto.SyncRelationDataDTO; +import cn.axzo.msg.center.inside.notices.service.dto.UpdateTemplateDTO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 模块与模板的关系表(MessageRelation)表服务实现类 + * + * @author zhangran + * @since 2022-03-28 14:59:16 + */ +@Service +@Slf4j +public class MessageRelationServiceImpl implements MessageRelationService { + + @Autowired + private MessageRelationDao messageRelationDao; + @Autowired + private MessageTemplateService templateService; + @Autowired + private MessageRouterService routerService; + + @Override + public List getAllRelations() { + return messageRelationDao.lambdaQuery() + .eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .list(); + } + + @Override + public Boolean hasRelationGtUpdateAt(LocalDateTime updateAt) { + return messageRelationDao.lambdaQuery() + .gt(Objects.nonNull(updateAt), MessageRelation::getUpdateAt, updateAt) + .count() > 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void createTemplate(CreateTemplateDTO dto) { + MessageTemplate template = new MessageTemplate(); + template.setTitle(dto.getTitle()); + template.setContent(dto.getContent()); + templateService.saveOrUpdateTemplate(template); + + MessageRelation relation = new MessageRelation(); + relation.setTypeId(0); + relation.setModuleId(dto.getModuleId()); + relation.setTemplateId(template.getId()); + relation.setContactUser(dto.getContactUser()); + messageRelationDao.save(relation); + + List routerList = new ArrayList<>(); + dto.getRouters().forEach(r -> { + MessageRouter router = new MessageRouter(); + router.setRelationId(relation.getId()); + router.setRouterType(MsgRouteTypeEnum.getRouteType(r.getType())); + router.setRouterUrl(r.getUrl()); + routerList.add(router); + }); + routerService.saveOrUpdateRouters(routerList); + + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateTemplate(UpdateTemplateDTO dto) { + MessageRelation relation = messageRelationDao.getById(dto.getRelationId()); + MessageTemplate template = templateService.getTemplateById(relation.getTemplateId()); + template.setTitle(dto.getTitle()); + template.setContent(dto.getContent()); + templateService.saveOrUpdateTemplate(template); + relation.setModuleId(dto.getModuleId()); + relation.setContactUser(dto.getContactUser()); + messageRelationDao.saveOrUpdate(relation); + routerService.updateRouters(dto.getRouters(), relation.getId()); + } + + @Override + public IPage page(SearchTemplateDTO dto) { + List relationIds; + if(!StringUtils.hasLength(dto.getRelationId())){ + relationIds = new ArrayList<>(); + }else { + relationIds =Arrays.stream(dto.getRelationId().split(",")).mapToLong(Long::parseLong).boxed().collect(Collectors.toList()); + } + return messageRelationDao.page(dto.toPage(), + new LambdaQueryWrapper() + .in(!CollectionUtils.isEmpty(relationIds), MessageRelation::getId, relationIds) + .in(!CollectionUtils.isEmpty(dto.getInnerTemplateIds()), MessageRelation::getTemplateId, dto.getInnerTemplateIds()) + .eq(MessageRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .orderByDesc(MessageRelation::getCreateAt) + ); + + } + + @Override + public MessageRelation getRelationById(Long id) { + return messageRelationDao.getById(id); + } + + @Override + public List getRelationByIds(Set relationIds) { + return messageRelationDao.listByIds(relationIds); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long id) { + MessageRelation mr = messageRelationDao.getById(id); + MessageTemplate mt = templateService.getTemplateById(mr.getTemplateId()); + List routers = routerService.getRoutersByRelationId(mr.getId()); + messageRelationDao.removeById(id); + templateService.removeById(mt); + routerService.batchRemoveByIds(routers); + } + +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRouterServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRouterServiceImpl.java new file mode 100644 index 00000000..c7f515f5 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageRouterServiceImpl.java @@ -0,0 +1,109 @@ +package cn.axzo.msg.center.inside.notices.service.impl; + +import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum; +import cn.axzo.msg.center.inside.notices.dao.MessageRouterDao; +import cn.axzo.msg.center.inside.notices.entity.MessageRouter; +import cn.axzo.msg.center.inside.notices.enums.MsgRouteTypeEnum; +import cn.axzo.msg.center.inside.notices.model.dto.SyncRouterDataDTO; +import cn.axzo.msg.center.inside.notices.model.dto.TemplateRouterDTO; +import cn.axzo.msg.center.inside.notices.service.MessageRouterService; +import cn.axzo.msg.center.inside.notices.service.dto.SyncRelationDataDTO; +import cn.hutool.core.collection.CollectionUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 消息路由配置信息(MessageRouter)表服务实现类 + * + * @author zhangran + * @since 2022-03-28 14:59:16 + */ +@Service +@Slf4j +public class MessageRouterServiceImpl implements MessageRouterService { + + @Resource + private MessageRouterDao routerDao; + + @Override + public void saveOrUpdateRouters(List routerList) { + routerDao.saveOrUpdateBatch(routerList); + } + + @Override + public List listRoutersByRelationIds(Set relationIds) { + if(CollectionUtils.isEmpty(relationIds)){ + return new ArrayList<>(); + } + return routerDao.listRoutersByRelationIds(relationIds); + } + + @Override + public void updateRouters(Set routers, Long relationId) { + List inDBRouters = getRoutersByRelationId(relationId); + if (CollectionUtils.isEmpty(routers)) { + if (CollectionUtils.isEmpty(inDBRouters)) { + return; + } else { + List removeIds = inDBRouters.stream().map(MessageRouter::getId) + .collect(Collectors.toList()); + routerDao.removeByIds(removeIds); + return; + } + + } + + List addRouters = new ArrayList<>(); + List updateRouters = new ArrayList<>(); + routers.forEach(i -> { + MessageRouter router = new MessageRouter(); + router.setRouterType(MsgRouteTypeEnum.getRouteType(i.getType())); + router.setRouterUrl(i.getUrl()); + if (Objects.isNull(i.getId())) { + router.setRelationId(relationId); + addRouters.add(router); + } else { + router.setId(i.getId()); + updateRouters.add(router); + } + }); + routerDao.updateBatchById(updateRouters); + routerDao.saveBatch(addRouters); + + // 移除被删除的路由 + if (!CollectionUtils.isEmpty(inDBRouters)) { + List aliveIds = routers.stream().map(TemplateRouterDTO::getId) + .collect(Collectors.toList()); + List removeIds = inDBRouters.stream().filter(i -> !aliveIds.contains(i.getId())) + .map(MessageRouter::getId).collect(Collectors.toList()); + routerDao.removeByIds(removeIds); + } + } + + @Override + public List getRoutersByRelationId(Long relationId) { + return routerDao.lambdaQuery().eq(MessageRouter::getRelationId, relationId) + .eq(MessageRouter::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .list(); + } + + @Override + public void batchRemoveByIds(List routerList) { + List ids = routerList.stream().map(MessageRouter::getId).collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(ids)) { + routerDao.removeByIds(ids); + } + } + + @Override + public List getRouterMapByRelationIds(List relationIds) { + return routerDao.lambdaQuery().in(MessageRouter::getRelationId, relationIds) + .eq(MessageRouter::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .list(); + } +} diff --git a/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageTemplateServiceImpl.java b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageTemplateServiceImpl.java new file mode 100644 index 00000000..3bd4d6e2 --- /dev/null +++ b/inside-notices/src/main/java/cn/axzo/msg/center/inside/notices/service/impl/MessageTemplateServiceImpl.java @@ -0,0 +1,87 @@ +package cn.axzo.msg.center.inside.notices.service.impl; + + +import cn.axzo.msg.center.common.enums.TableIsDeleteEnum; +import cn.axzo.msg.center.inside.notices.dao.MessageTemplateDao; +import cn.axzo.msg.center.inside.notices.entity.MessageTemplate; +import cn.axzo.msg.center.inside.notices.persistence.BaseEntity; +import cn.axzo.msg.center.inside.notices.service.MessageTemplateService; +import cn.axzo.msg.center.inside.notices.service.dto.SearchTemplateDTO; +import cn.axzo.msg.center.inside.notices.service.dto.SyncTemplateDataDTO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * 消息模板(MessageTemplate)表服务实现类 + * + * @author zhangran + * @since 2022-03-28 14:59:16 + */ +@Service +@Slf4j +public class MessageTemplateServiceImpl implements MessageTemplateService { + + @Autowired + private MessageTemplateDao messageTemplateDao; + + + @Override + public List getAllTemplates() { + return messageTemplateDao.lambdaQuery() + .eq(MessageTemplate::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .select(BaseEntity::getId, MessageTemplate::getTitle, MessageTemplate::getContent, + MessageTemplate::getUpdateAt) + .list(); + } + + @Override + public Boolean hasTemplateGtUpdateAt(LocalDateTime updateAt) { + return messageTemplateDao.lambdaQuery() + .gt(Objects.nonNull(updateAt), MessageTemplate::getUpdateAt, updateAt) + .count() > 0; + } + + @Override + public void saveOrUpdateTemplate(MessageTemplate template) { + messageTemplateDao.saveOrUpdate(template); + } + + @Override + public MessageTemplate getTemplateById(Long templateId) { + return messageTemplateDao.getById(templateId); + } + + @Override + public List getTemplateByIds(List templateIds) { + if(CollectionUtils.isEmpty(templateIds)){ + return new ArrayList<>(); + } + return messageTemplateDao.listByIds(templateIds); + } + + @Override + public void removeById(MessageTemplate mt) { + messageTemplateDao.removeById(mt.getId()); + } + + @Override + public void insertNativeSql(SyncTemplateDataDTO template) { + messageTemplateDao.insertSql(template); + } + + @Override + public List getListByTitleAndContent(SearchTemplateDTO dto) { + return messageTemplateDao.lambdaQuery() + .like(StringUtils.hasLength(dto.getTitle()), MessageTemplate::getTitle, dto.getTitle()) + .like(StringUtils.hasLength(dto.getContent()), MessageTemplate::getContent, dto.getContent()) + .list(); + } +} diff --git a/inside-notices/src/main/resources/mapper/MessageModuleMapper.xml b/inside-notices/src/main/resources/mapper/MessageModuleMapper.xml new file mode 100644 index 00000000..ac724197 --- /dev/null +++ b/inside-notices/src/main/resources/mapper/MessageModuleMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + diff --git a/inside-notices/src/main/resources/mapper/MessageRecordMapper.xml b/inside-notices/src/main/resources/mapper/MessageRecordMapper.xml new file mode 100644 index 00000000..d715bfce --- /dev/null +++ b/inside-notices/src/main/resources/mapper/MessageRecordMapper.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + update message_record set state = 4 + where id in + + #{id} + + + + + diff --git a/inside-notices/src/main/resources/mapper/MessageRelationMapper.xml b/inside-notices/src/main/resources/mapper/MessageRelationMapper.xml new file mode 100644 index 00000000..6cef2811 --- /dev/null +++ b/inside-notices/src/main/resources/mapper/MessageRelationMapper.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/inside-notices/src/main/resources/mapper/MessageRouterMapper.xml b/inside-notices/src/main/resources/mapper/MessageRouterMapper.xml new file mode 100644 index 00000000..dcb93c81 --- /dev/null +++ b/inside-notices/src/main/resources/mapper/MessageRouterMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/inside-notices/src/main/resources/mapper/MessageTemplateMapper.xml b/inside-notices/src/main/resources/mapper/MessageTemplateMapper.xml new file mode 100644 index 00000000..0d89f916 --- /dev/null +++ b/inside-notices/src/main/resources/mapper/MessageTemplateMapper.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IEnum.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IEnum.java new file mode 100644 index 00000000..5cfefbe0 --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IEnum.java @@ -0,0 +1,27 @@ +package cn.axzo.msg.center.common.enums; + +/** + * 项目名称:pudge + * 类 名 称:AbstractEnum + * 类 描 述:TODO + * 创建时间:2022/7/14 12:26 + * 创 建 人:xuyaozuo + */ +public interface IEnum { + + Integer getCode(); + String getMessage(); + + static & IEnum> T enumFromCode(Class enumType, Integer code) { + T defaultEnum = null; + for (T c : enumType.getEnumConstants()) { + if (c.getCode().equals(code)) { + return c; + } + if (c.getCode().equals(0)) { + defaultEnum = c; + } + } + return defaultEnum; + } +} diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IdentityType.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IdentityType.java new file mode 100644 index 00000000..181edb2d --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/IdentityType.java @@ -0,0 +1,53 @@ +package cn.axzo.msg.center.common.enums; + +import cn.axzo.msg.center.common.exception.ServiceException; +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 人员身份类型枚举 + * + * @author xuyaozuo + * @since 2022/5/9 21:59 + */ +@Getter +@AllArgsConstructor +public enum IdentityType implements IEnum{ + + /*人员身份类型*/ + NOT_SUPPORT(0, "NOT_SUPPORT", "无效类型"), + WORKER(1, "WORKER", "工人"), + WORKER_LEADER(2, "WORKER_LEADER", "班组长"), + PRACTITIONER(3, "PRACTITIONER", "从业人员"), + REGULATOR(4, "REGULATOR", "监管人员"), + OPERATOR(5, "OPERATOR", "运营人员"), + ; + @EnumValue + @JsonValue + private final Integer code; + private final String message; + private final String desc; + + + public static IdentityType getIdentityType(Integer code) { + IdentityType[] values = values(); + for (IdentityType item : values) { + if (item.getCode().equals(code)) { + return item; + } + } + throw new ServiceException("档案身份类型不匹配 code:" + code); + } + + public static IdentityType getIdentityType(String message) { + IdentityType[] values = values(); + for (IdentityType item : values) { + if (item.getMessage().equals(message)) { + return item; + } + } + throw new ServiceException("档案身份类型不匹配 message:" + message); + } +} diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/OuType.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/OuType.java new file mode 100644 index 00000000..b5fd0c9c --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/OuType.java @@ -0,0 +1,39 @@ +package cn.axzo.msg.center.common.enums; + +import cn.axzo.msg.center.common.exception.ServiceException; +import com.baomidou.mybatisplus.annotation.EnumValue; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * 项目名称:profiles + * 类 名 称:OuType + * 类 描 述:TODO + * 创建时间:2022/5/13 14:41 + * 创 建 人:xuyaozuo + */ +@RequiredArgsConstructor +@Getter +public enum OuType implements IEnum { + OTHERS(0, "OTHERS"), + CONTRACTOR_UNIT(1, "CONTRACTOR_UNIT"), + BUILDING_UNIT(2, "BUILDING_UNIT"), + LAB_SUBCONTRACTOR_UNIT(3, "LAB_SUBCONTRACTOR_UNIT"), + PROFESSIONAL_SUBCONTRACTOR_UNIT(4, "PROFESSIONAL_SUBCONTRACTOR_UNIT"), + SUPERVISING_UNIT(5, "SUPERVISING_UNIT"), + WORKER_GROUP(6, "WORKER_GROUP"), + ; + @EnumValue + private final Integer code; + private final String message; + + public static OuType getOuType(Integer code) { + OuType[] values = values(); + for (OuType item : values) { + if (item.getCode().equals(code)) { + return item; + } + } + throw new ServiceException("班组类型不匹配 code:" + code); + } +} diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/SystemTypeEnum.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/SystemTypeEnum.java new file mode 100644 index 00000000..9f979d62 --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/enums/SystemTypeEnum.java @@ -0,0 +1,43 @@ +package cn.axzo.msg.center.common.enums; + +import java.util.Arrays; +import java.util.Objects; + +/** + * @author zhangran + * @Date 2020/8/14 10:49 + * @Description + */ +public enum SystemTypeEnum { + + // 安卓系统 + ANDROID("android", "安卓"), + + // ios + IOS("ios", "苹果"); + + private final String type; + public final String desc; + + SystemTypeEnum(String type, String desc) { + this.type = type; + this.desc = desc; + } + + public String get() { + return type; + } + + /** + * 判断是否存在 + * + * @param type + * @return + */ + public static SystemTypeEnum getSystem(String type) { + String lowType = type.toLowerCase(); + return Arrays.stream(SystemTypeEnum.values()).filter(it -> Objects.equals(it.type, lowType)) + .findFirst().orElse(null); + } + +} diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/model/ProfileIdRepair.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/model/ProfileIdRepair.java new file mode 100644 index 00000000..768078b2 --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/model/ProfileIdRepair.java @@ -0,0 +1,204 @@ +package cn.axzo.msg.center.common.model; + + +import cn.axzo.msg.center.common.enums.IdentityType; +import cn.axzo.msg.center.common.enums.OuType; +import cn.axzo.msg.center.common.exception.ServiceException; + +import static cn.axzo.msg.center.common.enums.OuType.*; + +/** + * @author tanjie@axzo.cn + * @date 2022/6/15 10:28 + */ +public class ProfileIdRepair { +// private static int NEW_ID_START = 5000000; +// +// private static int ENT_USER_START_ID = 1200000; +// +// private static int PLAT_USER_NEW_START = 1400000; +// +// private static int WORKER_START = 1600000; +// +// private static int WORKER_LEADER_START = 1800000; +// +// private static int REGULATOR_START = 2000000; +// +// /* 迁移范围 */ +// private static int TRANSFER_ID_START = 1000000; +// +// private static int TEAM_START = 3000000; +// private static int ENT_START = 3200000; +// private static int AGENCY_START = 3400000; +// private static int REGULATORY_START = 3600000; + + private static int NEW_ID_START = 0; + + private static int ENT_USER_START_ID = 0; + + private static int PLAT_USER_NEW_START = 0; + + private static int WORKER_START = 0; + + private static int WORKER_LEADER_START = 0; + + private static int REGULATOR_START = 0; + + /* 迁移范围 */ + private static int TRANSFER_ID_START = 0; + + private static int TEAM_START = 0; + private static int ENT_START = 0; + private static int AGENCY_START = 0; + private static int REGULATORY_START = 0; + + public static Long identityOld2NewId(Long id, IdentityType identityType) { + return id; +// if (id > TRANSFER_ID_START) { +// return id; +// } +// switch (identityType) { +// case OPERATOR: +// return id + PLAT_USER_NEW_START; +// case WORKER: +// return id + WORKER_START; +// case PRACTITIONER: +// return id + ENT_USER_START_ID; +// case WORKER_LEADER: +// return id + WORKER_LEADER_START; +// case REGULATOR: +// return id + REGULATOR_START; +// default: +// throw new ServiceException("bad identity type to convert id"); +// } + } + + public static Long identityNew2OldId(Long id, IdentityType identityType) { + return id; + +// if (id < TRANSFER_ID_START) {// 进来的就是旧id +// return id; +// } +// +// if (id >= NEW_ID_START) {// 是全新的id,不用换 +// return id; +// } +// +// switch (identityType) { +// case OPERATOR: +// return id - PLAT_USER_NEW_START; +// case WORKER: +// return id - WORKER_START; +// case PRACTITIONER: +// return id - ENT_USER_START_ID; +// case WORKER_LEADER: +// return id - WORKER_LEADER_START; +// case REGULATOR: +// return id - REGULATOR_START; +// default: +// throw new ServiceException("bad identity type to convert id"); +// } + } + + + public static Long workerOld2NewId(Long id) { + return identityOld2NewId(id, IdentityType.WORKER); + } + + public static Long workerNewId2OldId(Long id) { + return identityNew2OldId(id, IdentityType.WORKER); + } + + public static Long teamLeaderOld2NewId(Long id) { + return identityOld2NewId(id, IdentityType.WORKER); + } + + public static Long teamLeaderNew2OldId(Long id) { + return identityNew2OldId(id, IdentityType.WORKER_LEADER); + } + + public static Long entUserNew2OldId(Long id) { + return identityNew2OldId(id, IdentityType.PRACTITIONER); + } + + public static Long entUserOld2NewId(Long id) { + return identityOld2NewId(id, IdentityType.PRACTITIONER); + } + + public static Long regulatorNew2OldId(Long id) { + return identityNew2OldId(id, IdentityType.REGULATOR); + } + + public static Long regulatorOld2NewId(Long id) { + return identityOld2NewId(id, IdentityType.REGULATOR); + } + + public static Long platUserOld2NewId(Long id) { + return identityOld2NewId(id, IdentityType.OPERATOR); + } + + public static Long platUserNew2OldId(Long id) { + return identityNew2OldId(id, IdentityType.OPERATOR); + } + + public static Long workerLeaderNewId2Old(Long id) { + return identityNew2OldId(id, IdentityType.WORKER_LEADER); + } + + public static Long workerLeaderOldId2New(Long id) { + return identityOld2NewId(id, IdentityType.WORKER_LEADER); + } + + public static Long ouOld2NewId(Long id, OuType ouType) { + if (id > TRANSFER_ID_START) { + return id; + } + switch (ouType) { + case WORKER_GROUP: + return id + TEAM_START; + case CONTRACTOR_UNIT: + return id + ENT_START; + case BUILDING_UNIT: + return id + ENT_START; + case LAB_SUBCONTRACTOR_UNIT: + return id + AGENCY_START; + case PROFESSIONAL_SUBCONTRACTOR_UNIT: + return id + AGENCY_START; + case SUPERVISING_UNIT: + return id + REGULATORY_START; + default: + throw new ServiceException("bad identity type to convert id"); + } + } + + public static Long ouNew2OldId(Long id, OuType ouType) { + if (id < TRANSFER_ID_START) {// 进来的就是旧id + return id; + } + + if (id >= NEW_ID_START) {// 是全新的id,不用换 + return id; + } + + switch (ouType) { + case WORKER_GROUP: + return id - TEAM_START; + case CONTRACTOR_UNIT: + return id - ENT_START; + case BUILDING_UNIT: + return id - ENT_START; + case LAB_SUBCONTRACTOR_UNIT: + return id - AGENCY_START; + case PROFESSIONAL_SUBCONTRACTOR_UNIT: + return id - AGENCY_START; + case SUPERVISING_UNIT: + return id - REGULATORY_START; + default: + throw new ServiceException("bad identity type to convert id"); + } + } + + public static Long identityNew2OldId(Long identityId, Integer identityType) { + return identityNew2OldId(identityId, IdentityType.getIdentityType(identityType)); + } +} diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/BeanConvertUtils.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/BeanConvertUtils.java new file mode 100644 index 00000000..63bc582e --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/BeanConvertUtils.java @@ -0,0 +1,142 @@ +package cn.axzo.msg.center.common.utils; + +import cn.hutool.core.collection.CollUtil; +import org.springframework.beans.BeanUtils; +import org.springframework.util.CollectionUtils; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.*; +import java.util.Map.Entry; +import java.util.function.BiConsumer; + +public class BeanConvertUtils { + + public static T copyBean(Object sourceObj, Class targetCls) { + T targetObj = null; + if (sourceObj != null) { + try { + targetObj = BeanUtils.instantiate(targetCls); + BeanUtils.copyProperties(sourceObj, targetObj); + } catch (Exception e) { + e.printStackTrace(); + } + } + return targetObj; + } + + public static List copyList(Collection list, Class targetCls) { + List result = new ArrayList(); + if (list == null || list.size() == 0) { + return result; + } + + for (Object obj : list) { + result.add(copyBean(obj, targetCls)); + } + + return result; + } + + /** + * 将集合中的map转为对应的dto + */ + public static List map2Java(List> list, Class targetCls) { + if (CollectionUtils.isEmpty(list)) { + return new ArrayList(); + } + List resultList = new ArrayList<>(); + try { + for (int i = 0; i < list.size(); i++) { + Map map = list.get(i); + Set set = map.entrySet(); + T targetObject = targetCls.newInstance(); + for (Entry entry : set) { + Field field = targetCls.getDeclaredField(entry.getKey().toString()); + field.setAccessible(true); + field.set(targetObject, entry.getValue().toString()); + } + resultList.add(targetObject); + } + } catch (Exception e) { + e.printStackTrace(); + } + return resultList; + } + + /** + * 深度拷贝list 集合 + */ + public static List deepCopy(List src) { + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream out = null; + try { + out = new ObjectOutputStream(byteOut); + out.writeObject(src); + ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); + ObjectInputStream in = new ObjectInputStream(byteIn); + @SuppressWarnings("unchecked") + List dest = (List) in.readObject(); + return dest; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + // Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map + public static Map transBean2Map(Object obj) { + + if (obj == null) { + return null; + } + Map map = new HashMap(); + try { + BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()); + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + for (PropertyDescriptor property : propertyDescriptors) { + String key = property.getName(); + + // 过滤class属性 + if (!"class".equals(key)) { + // 得到property对应的getter方法 + Method getter = property.getReadMethod(); + Object value = getter.invoke(obj); + + map.put(key, value); + } + + } + } catch (Exception e) { + System.out.println("transBean2Map Error " + e); + } + + return map; + + } + + public static List copyList(Collection list, Class targetCls, BiConsumer action) { + List result = new ArrayList(); + if (CollUtil.isEmpty(list)) { + return result; + } + + for (S obj : list) { + T res = copyBean(obj, targetCls); + if (action != null) { + action.accept(obj, res); + } + result.add(res); + } + + return result; + } +} + diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/ObjectUtils.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/ObjectUtils.java new file mode 100644 index 00000000..21b885ac --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/ObjectUtils.java @@ -0,0 +1,97 @@ +package cn.axzo.msg.center.common.utils; + +import java.time.temporal.TemporalAccessor; +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +/** + * @author: wangli + * @date: 2022/3/26 14:32 + */ +public class ObjectUtils { + + /** + * 如果obj为null,则返回默认值,不为null,则返回obj + * + * @param obj obj + * @param defaultValue 默认值 + * @param 值泛型 + * @return obj不为null 返回obj,否则返回默认值 + */ + public static T defaultIfNull(T obj, T defaultValue) { + return obj != null ? obj : defaultValue; + } + + //--------------------------------------------------------------------- + // 对象类型判断 + //--------------------------------------------------------------------- + + public static boolean isCollection(Object obj) { + return obj instanceof Collection; + } + + public static boolean isMap(Object obj) { + return obj instanceof Map; + } + + public static boolean isNumber(Object obj) { + return obj instanceof Number; + } + + public static boolean isBoolean(Object obj) { + return obj instanceof Boolean; + } + + public static boolean isEnum(Object obj) { + return obj instanceof Enum; + } + + public static boolean isDate(Object obj) { + return obj instanceof Date || obj instanceof TemporalAccessor; + } + + public static boolean isCharSequence(Object obj) { + return obj instanceof CharSequence; + } + + /** + * 判断对象是否为八大基本类型包装类除外即(boolean, byte, char, short, int, long, float, and double)
+ * + * @param obj + * @return + */ + public static boolean isPrimitive(Object obj) { + return obj != null && obj.getClass().isPrimitive(); + } + + /** + * 判断对象是否为包装类或者非包装类的基本类型 + * + * @param obj + * @return + */ + public static boolean isWrapperOrPrimitive(Object obj) { + return isPrimitive(obj) || isNumber(obj) || isCharSequence(obj) || isBoolean(obj); + } + + /** + * 判断一个对象是否为数组 + * + * @param obj + * @return + */ + public static boolean isArray(Object obj) { + return obj != null && obj.getClass().isArray(); + } + + /** + * 判断一个对象是否为基本类型数组即(int[], long[], boolean[], double[]....) + * + * @param obj + * @return + */ + public static boolean isPrimitiveArray(Object obj) { + return isArray(obj) && obj.getClass().getComponentType().isPrimitive(); + } +} diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/PlaceholderResolver.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/PlaceholderResolver.java new file mode 100644 index 00000000..5a0c1780 --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/PlaceholderResolver.java @@ -0,0 +1,193 @@ +package cn.axzo.msg.center.common.utils; + +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * @author wangli + * @date 2022/3/26 14:28 + */ +public class PlaceholderResolver { + + /** + * 默认前缀占位符 + */ + private static final String DEFAULT_PLACEHOLDER_PREFIX = "${"; + + /** + * 默认后缀占位符 + */ + private static final String DEFAULT_PLACEHOLDER_SUFFIX = "}"; + + /** + * 默认单例解析器 + */ + private static PlaceholderResolver defaultResolver = new PlaceholderResolver(); + + /** + * 占位符前缀 + */ + private String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX; + + /** + * 占位符后缀 + */ + private String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX; + + + private PlaceholderResolver() { + } + + private PlaceholderResolver(String placeholderPrefix, String placeholderSuffix) { + this.placeholderPrefix = placeholderPrefix; + this.placeholderSuffix = placeholderSuffix; + } + + /** + * 获取默认的占位符解析器,即占位符前缀为"${", 后缀为"}" + * + * @return + */ + public static PlaceholderResolver getDefaultResolver() { + return defaultResolver; + } + + public static PlaceholderResolver getResolver(String placeholderPrefix, + String placeholderSuffix) { + return new PlaceholderResolver(placeholderPrefix, placeholderSuffix); + } + + /** + * 解析带有指定占位符的模板字符串,默认占位符为前缀:${ 后缀:}

如:template = category:${}:product:${}
values = + * {"1", "2"}
返回 category:1:product:2
+ * + * @param content 要解析的带有占位符的模板字符串 + * @param values 按照模板占位符索引位置设置对应的值 + * @return + */ + public String resolve(String content, String[] values) { + int start = content.indexOf(this.placeholderPrefix); + if (start == -1) { + return content; + } + //值索引 + int valueIndex = 0; + StringBuilder result = new StringBuilder(content); + while (start != -1) { + int end = result.indexOf(this.placeholderSuffix); + String replaceContent = values[valueIndex++]; + result.replace(start, end + this.placeholderSuffix.length(), replaceContent); + start = result.indexOf(this.placeholderPrefix, start + replaceContent.length()); + } + return result.toString(); + } + + /** + * 解析带有指定占位符的模板字符串参数名称

如: template = 您所在的${projectName}有工资发薪${state}
返回 Set + * = ["projectName", "state"] + * + * @return + */ + public Set resolveParamName(String content) { + Set paramNames = new HashSet<>(); + int start = content.indexOf(this.placeholderPrefix); + if (start == -1) { + return paramNames; + } + StringBuilder result = new StringBuilder(content); + while (start != -1) { + int end = result.indexOf(this.placeholderSuffix, start); + //获取占位符属性值,如${id}, 即获取id + String placeholder = result.substring(start + this.placeholderPrefix.length(), end); + paramNames.add(placeholder); + //替换整个占位符内容,即将${id}值替换为替换规则回调中的内容 + result.replace(start, end + this.placeholderSuffix.length(), ""); + start = result.indexOf(this.placeholderPrefix, start); + } + return paramNames; + } + + /** + * 解析带有指定占位符的模板字符串,默认占位符为前缀:${ 后缀:}

如:template = category:${}:product:${}
values = + * {"1", "2"}
返回 category:1:product:2
+ * + * @param content 要解析的带有占位符的模板字符串 + * @param values 按照模板占位符索引位置设置对应的值 + * @return + */ + public String resolve(String content, Object... values) { + return resolve(content, Stream.of(values).map(String::valueOf).toArray(String[]::new)); + } + + /** + * 根据替换规则来替换指定模板中的占位符值 + * + * @param content 要解析的字符串 + * @param rule 解析规则回调 + * @return + */ + public String resolveByRule(String content, Function rule) { + int start = content.indexOf(this.placeholderPrefix); + if (start == -1) { + return content; + } + StringBuilder result = new StringBuilder(content); + while (start != -1) { + int end = result.indexOf(this.placeholderSuffix, start); + //获取占位符属性值,如${id}, 即获取id + String placeholder = result.substring(start + this.placeholderPrefix.length(), end); + //替换整个占位符内容,即将${id}值替换为替换规则回调中的内容 + String replaceContent = placeholder.trim().isEmpty() ? "" : rule.apply(placeholder); + result.replace(start, end + this.placeholderSuffix.length(), replaceContent); + start = result.indexOf(this.placeholderPrefix, start + replaceContent.length()); + } + return result.toString(); + } + + /** + * 替换模板中占位符内容,占位符的内容即为map key对应的值,key为占位符中的内容。

如:content = + * product:${id}:detail:${did}
valueMap = id -> 1; pid -> 2
经过解析返回 + * product:1:detail:2
+ * + * @param content 模板内容。 + * @param valueMap 值映射 + * @return 替换完成后的字符串。 + */ + public String resolveByMap(String content, final Map valueMap) { + return resolveByRule(content, + placeholderValue -> String.valueOf(valueMap.get(placeholderValue))); + } + + /** + * 根据properties文件替换占位符内容 + * + * @param content + * @param properties + * @return + */ + public String resolveByProperties(String content, final Properties properties) { + return resolveByRule(content, properties::getProperty); + } + + /** + * 根据对象中字段路径(即类似js访问对象属性值)替换模板中的占位符

如 content = product:${id}:detail:${detail.id}
+ * obj = Product.builder().id(1).detail(Detail.builder().id(2).build()).build();
经过解析返回 + * product:1:detail:2
+ * + * @param content 要解析的内容 + * @param obj 填充解析内容的对象(如果是基本类型,则所有占位符替换为相同的值) + * @return + */ + @SuppressWarnings("unchecked") + public String resolveByObject(String content, final Object obj) { + if (obj instanceof Map) { + return resolveByMap(content, (Map) obj); + } + return resolveByRule(content, placeholderValue -> String.valueOf( + ReflectionUtils.getValueByFieldPath(obj, placeholderValue))); + } +} diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/ReflectionUtils.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/ReflectionUtils.java new file mode 100644 index 00000000..edfbd5f5 --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/ReflectionUtils.java @@ -0,0 +1,247 @@ +package cn.axzo.msg.center.common.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Predicate; + +/** + * @author: wangli + * @date: 2022/3/26 14:29 + */ +public final class ReflectionUtils { + + + /** + * 获取所有field字段,包含父类继承的 + * + * @param clazz 字段所属类型 + * @return + */ + public static Field[] getFields(Class clazz) { + return getFields(clazz, null); + } + + /** + * 获取指定类的所有的field,包括父类 + * + * @param clazz 字段所属类型 + * @param fieldFilter 字段过滤器 + * @return 符合过滤器条件的字段数组 + */ + public static Field[] getFields(Class clazz, Predicate fieldFilter) { + List fields = new ArrayList<>(32); + while (Object.class != clazz && clazz != null) { + // 获得该类所有声明的字段,即包括public、private和protected,但是不包括父类的申明字段, + // getFields:获得某个类的所有的公共(public)的字段,包括父类中的字段 + for (Field field : clazz.getDeclaredFields()) { + if (fieldFilter != null && !fieldFilter.test(field)) { + continue; + } + fields.add(field); + } + clazz = clazz.getSuperclass(); + } + return fields.toArray(new Field[0]); + } + + /** + * 对指定类的所有字段执行consumer操作 + * + * @param clazz 目标对象 + * @param consumer 对字段进行操作 + */ + public static void doWithFields(Class clazz, Consumer consumer) { + Arrays.stream(getFields(clazz)).forEach(consumer); + } + + /** + * 获取指定类的指定field,包括父类 + * + * @param clazz 字段所属类型 + * @param name 字段名 + * @return + */ + public static Field getField(Class clazz, String name) { + return getField(clazz, name, null); + } + + /** + * 获取指定类的指定field,包括父类 + * + * @param clazz 字段所属类型 + * @param name 字段名 + * @param type field类型 + * @return Field对象 + */ + public static Field getField(Class clazz, String name, Class type) { + while (clazz != Object.class && clazz != null) { + for (Field field : clazz.getDeclaredFields()) { + if ((name == null || name.equals(field.getName())) && + (type == null || type.equals(field.getType()))) { + return field; + } + } + clazz = clazz.getSuperclass(); + } + return null; + } + + /** + * 获取字段值 + * + * @param field 字段 + * @param target 字段所属实例对象 + * @return 字段值 + */ + public static Object getFieldValue(Field field, Object target) { + makeAccessible(field); + try { + return field.get(target); + } catch (Exception e) { + throw new IllegalStateException(String.format("获取%s对象的%s字段值错误!" + , target.getClass().getName(), field.getName()), e); + } + } + + /** + * 获取对象中指定field值 + * + * @param obj 对象 + * @param fieldName 字段名 + * @return 字段值 + */ + public static Object getFieldValue(Object obj, String fieldName) { + if (ObjectUtils.isWrapperOrPrimitive(obj)) { + return obj; + } + return getFieldValue(getField(obj.getClass(), fieldName), obj); + } + + /** + * 获取指定对象中指定字段路径的值(类似js访问对象属性)
如:Product p = new Product(new User())
+ * 可使用ReflectionUtils.getValueByFieldPath(p, "user.name")获取到用户的name属性 + * + * @param obj 取值对象 + * @param fieldPath 字段路径(形如 user.name) + * @return 字段value + */ + public static Object getValueByFieldPath(Object obj, String fieldPath) { + String[] fieldNames = fieldPath.split("\\."); + Object result = null; + for (String fieldName : fieldNames) { + result = getFieldValue(obj, fieldName); + if (result == null) { + return null; + } + obj = result; + } + return result; + } + + /** + * 设置字段值 + * + * @param field 字段 + * @param target 字段所属对象实例 + * @param value 需要设置的值 + */ + public static void setFieldValue(Field field, Object target, Object value) { + makeAccessible(field); + try { + field.set(target, value); + } catch (Exception e) { + throw new IllegalStateException(String.format("设置%s对象的%s字段值错误!" + , target.getClass().getName(), field.getName()), e); + } + } + + /** + * 设置字段为可见 + * + * @param field + */ + public static void makeAccessible(Field field) { + if ((!Modifier.isPublic(field.getModifiers()) || + !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || + Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) { + field.setAccessible(true); + } + } + + /** + * 调用无参数方法 + * + * @param method 方法对象 + * @param target 调用对象 + * @return 执行结果 + */ + public static Object invokeMethod(Method method, Object target) { + return invokeMethod(method, target, new Object[0]); + } + + /** + * 调用指定对象的方法 + * + * @param method 方法对象 + * @param target 调用对象 + * @param args 方法参数 + * @return 执行结果 + */ + public static Object invokeMethod(Method method, Object target, Object... args) { + try { + makeAccessible(method); + return method.invoke(target, args); + } catch (Exception ex) { + throw new IllegalStateException(String.format("执行%s.%s()方法错误!" + , target.getClass().getName(), method.getName()), ex); + } + } + + /** + * 设置方法可见性 + * + * @param method 方法 + */ + public static void makeAccessible(Method method) { + if ((!Modifier.isPublic(method.getModifiers()) || + !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) { + method.setAccessible(true); + } + } + + /** + * 是否为equals方法 + * + * @see Object#equals(Object) + */ + public static boolean isEqualsMethod(Method method) { + if (!"equals".equals(method.getName())) { + return false; + } + Class[] paramTypes = method.getParameterTypes(); + return (paramTypes.length == 1 && paramTypes[0] == Object.class); + } + + /** + * 是否为hashCode方法 + * + * @see Object#hashCode() + */ + public static boolean isHashCodeMethod(Method method) { + return "hashCode".equals(method.getName()) && method.getParameterCount() == 0; + } + + /** + * 是否为Object的toString方法 + * + * @see Object#toString() + */ + public static boolean isToStringMethod(Method method) { + return "toString".equals(method.getName()) && method.getParameterCount() == 0; + } +} diff --git a/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/SpringUtils.java b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/SpringUtils.java new file mode 100644 index 00000000..918ce1a4 --- /dev/null +++ b/msg-center-common/src/main/java/cn/axzo/msg/center/common/utils/SpringUtils.java @@ -0,0 +1,98 @@ +package cn.axzo.msg.center.common.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.ApplicationContext; +import org.springframework.util.Assert; + +import java.util.Map; + +/** + * Spring 工具类 + */ +public final class SpringUtils { + + private static ObjectMapper objectMapper = null; + + public static ObjectMapper getObjectMapper() { + if (objectMapper == null) { + objectMapper = getBean(ObjectMapper.class); + } + return objectMapper; + } + + private SpringUtils() { + } + + public static SpringUtils getInstance() { + return SpringUtilsHolder.INSTANCE; + } + + private static ApplicationContext applicationContext; + private static ApplicationContext parentApplicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static void setApplicationContext(ApplicationContext ctx) { + Assert.notNull(ctx, "SpringUtil injection ApplicationContext is null"); + applicationContext = ctx; + parentApplicationContext = ctx.getParent(); + } + + public static Object getBean(String name) { + Assert.hasText(name, "SpringUtil name is null or empty"); + try { + return applicationContext.getBean(name); + } catch (Exception e) { + return parentApplicationContext.getBean(name); + } + } + + public static T getBean(String name, Class type) { + Assert.hasText(name, "SpringUtil name is null or empty"); + Assert.notNull(type, "SpringUtil type is null"); + try { + return applicationContext.getBean(name, type); + } catch (Exception e) { + return parentApplicationContext.getBean(name, type); + } + } + + public static T getBean(Class type) { + Assert.notNull(type, "SpringUtil type is null"); + try { + return applicationContext.getBean(type); + } catch (Exception e) { + return parentApplicationContext.getBean(type); + } + } + + public static Map getBeansOfType(Class type) { + Assert.notNull(type, "SpringUtil type is null"); + try { + return applicationContext.getBeansOfType(type); + } catch (Exception e) { + return parentApplicationContext.getBeansOfType(type); + } + } + + public static ApplicationContext publishEvent(Object event) { + applicationContext.publishEvent(event); + return applicationContext; + } + + + /** + *

+ * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 + * 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载 + */ + private static class SpringUtilsHolder { + /** + * 静态初始化器,由JVM来保证线程安全 + */ + private static final SpringUtils INSTANCE = new SpringUtils(); + } + +} diff --git a/msg-center-webapi/pom.xml b/msg-center-webapi/pom.xml index 9bdc0000..501fdaa0 100644 --- a/msg-center-webapi/pom.xml +++ b/msg-center-webapi/pom.xml @@ -32,5 +32,11 @@ org.springframework.boot spring-boot-starter-json + + cn.axzo.msgcenter + inside-notices + 1.0.0-SNAPSHOT + compile + \ No newline at end of file diff --git a/msg-center-webapi/src/main/java/cn/axzo/msg/center/webapi/MessageController.java b/msg-center-webapi/src/main/java/cn/axzo/msg/center/webapi/MessageController.java new file mode 100644 index 00000000..93beff95 --- /dev/null +++ b/msg-center-webapi/src/main/java/cn/axzo/msg/center/webapi/MessageController.java @@ -0,0 +1,54 @@ +package cn.axzo.msg.center.webapi; + +import cn.axzo.core.web.Result; +import cn.axzo.core.web.Results; +import cn.axzo.framework.auth.annotation.PreBuildContext; +import cn.axzo.msg.center.common.page.PageResult; +import cn.axzo.msg.center.inside.notices.model.request.CmsMsgQueryReq; +import cn.axzo.msg.center.inside.notices.model.request.MessageNewRes; +import cn.axzo.msg.center.inside.notices.model.response.MessageTotalRes; +import cn.axzo.msg.center.inside.notices.service.MessageCoreService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; + +/** + * @author zhangPeng + * @description + * @date 2021/2/4 15:44 + */ +@Slf4j +@RestController +@RequestMapping("webApi/message") +public class MessageController { + + @Autowired + private MessageCoreService messageCoreService; + + /** + * 消息\待办数量总数 + * + * @return + */ + @GetMapping("v1/msg/total") + @PreBuildContext + public Result msgTotal() { + log.info("msgTotal executing..."); + return Results.ok(messageCoreService.statisticsMsg()); + } + + /** + * 消息列表搜索、待办列表 + * + * @param req + * @return + */ + @PostMapping("v1/msg/list") + @PreBuildContext + public Result> msgList(@RequestBody @Valid CmsMsgQueryReq req) { + log.info("msgList executing..."); + return Results.ok(messageCoreService.listMsgInfo(req)); + } +} diff --git a/msg-notices/msg-notices-client/src/main/java/cn/axzo/msg/center/notices/client/controller/MessageNotifyController.java b/msg-notices/msg-notices-client/src/main/java/cn/axzo/msg/center/notices/client/controller/MessageNotifyController.java index 67f60c78..f8bde5e3 100644 --- a/msg-notices/msg-notices-client/src/main/java/cn/axzo/msg/center/notices/client/controller/MessageNotifyController.java +++ b/msg-notices/msg-notices-client/src/main/java/cn/axzo/msg/center/notices/client/controller/MessageNotifyController.java @@ -35,7 +35,7 @@ public class MessageNotifyController implements MessageNotifyApi { private GenericConversionService genericConversionService; @Override - @MethodAroundLog(source = "业务方", target = "mns", value = "发送单条短信") + @MethodAroundLog(source = "业务方", target = "msg-center", value = "发送单条短信") @PushOperation("发送短信") public CommonResponse sendMobileMessage(@RequestBody @Valid SendMobileMessageRequest request) { // 转换对象 @@ -49,7 +49,7 @@ public class MessageNotifyController implements MessageNotifyApi { } @Override - @MethodAroundLog(source = "业务方", target = "mns", value = "发送批量短信", requestExcludeName = {"smsContents"}) + @MethodAroundLog(source = "业务方", target = "msg-center", value = "发送批量短信", requestExcludeName = {"smsContents"}) public CommonResponse sendBatchMessage(@RequestBody @Valid SendBatchMessageRequest request) { LogUtil.error("请联系管理员,批量发送短信功能已弃用"); diff --git a/msg-notices/msg-notices-http-api/src/main/java/cn/axzo/msg/center/notices/http/api/api/MessageNotifyApi.java b/msg-notices/msg-notices-http-api/src/main/java/cn/axzo/msg/center/notices/http/api/api/MessageNotifyApi.java index 31b11cd8..e655a6ab 100644 --- a/msg-notices/msg-notices-http-api/src/main/java/cn/axzo/msg/center/notices/http/api/api/MessageNotifyApi.java +++ b/msg-notices/msg-notices-http-api/src/main/java/cn/axzo/msg/center/notices/http/api/api/MessageNotifyApi.java @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.RequestMethod; */ @FeignClient( name = "mns", - url = "http://mns:8989" + url = "http://msg-center:10086" ) public interface MessageNotifyApi { diff --git a/start/src/main/java/cn/axzo/msg/center/MsgCenterApplication.java b/start/src/main/java/cn/axzo/msg/center/MsgCenterApplication.java index 8a1b99ba..d167e358 100644 --- a/start/src/main/java/cn/axzo/msg/center/MsgCenterApplication.java +++ b/start/src/main/java/cn/axzo/msg/center/MsgCenterApplication.java @@ -1,6 +1,7 @@ package cn.axzo.msg.center; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; @@ -14,7 +15,8 @@ import org.springframework.core.env.Environment; * @date 2023/5/30 11:01 */ @Slf4j -@SpringBootApplication(scanBasePackages = "cn.axzo.msg.center",exclude = DataSourceAutoConfiguration.class) +@MapperScan(value = "cn.axzo.msg.center.inside.notices.dao.mapper") +@SpringBootApplication(scanBasePackages = "cn.axzo") public class MsgCenterApplication { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MsgCenterApplication.class, args);