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

This commit is contained in:
luofu 2023-09-18 19:23:33 +08:00
commit 92beead12c
25 changed files with 1415 additions and 60 deletions

View File

@ -3,9 +3,19 @@ package cn.axzo.msg.center.inside.notices.service;
import cn.axzo.core.domain.PageResult;
import cn.axzo.msg.center.api.request.CmsMsgQueryReq;
import cn.axzo.msg.center.api.request.MessageModuleStatisticReq;
import cn.axzo.msg.center.api.request.MessagePageQueryReq;
import cn.axzo.msg.center.api.request.MessageReadAllReq;
import cn.axzo.msg.center.api.request.MessageStatisticReq;
import cn.axzo.msg.center.api.response.MessageDetailRes;
import cn.axzo.msg.center.api.response.MessageModuleStatisticRes;
import cn.axzo.msg.center.api.response.MessageNewRes;
import cn.axzo.msg.center.api.response.MessageStatisticRes;
import cn.axzo.msg.center.api.response.MessageTotalRes;
import cn.axzo.msg.center.domain.enums.UserTypeEnum;
import cn.azxo.framework.common.model.Page;
import java.util.List;
/**
* @author : liuchuntao
@ -14,18 +24,47 @@ import cn.axzo.msg.center.domain.enums.UserTypeEnum;
*/
public interface MessageCoreService {
/**
* 获取所有业务(按业务规则)合计未读消息数量
*
* @return
*/
MessageTotalRes statisticsMsg(Long personId, Long identityId, UserTypeEnum userTypeEnum);
/**
* 获取所有业务(按业务规则)合计未读消息数量
*
* @return
*/
MessageTotalRes statisticsMsg(Long personId, Long identityId, UserTypeEnum userTypeEnum);
PageResult<MessageNewRes> listMsgInfo(CmsMsgQueryReq req);
PageResult<MessageNewRes> listMsgInfo(CmsMsgQueryReq req);
PageResult<MessageNewRes> listMsgInfo4Trade(CmsMsgQueryReq req);
PageResult<MessageNewRes> listMsgInfo4Trade(CmsMsgQueryReq req);
/**
* 个人消息按类型统计待办/未读数量
*
* @param request 个人信息及消息类型
* @return 待办/未读数量
*/
MessageStatisticRes countPersonMessage(MessageStatisticReq request);
/**
* 个人消息按模块分组统计
*
* @param request 个人信息及消息类型
* @return 待展示的统计信息
*/
List<MessageModuleStatisticRes> statisticPersonModuleMessage(MessageModuleStatisticReq request);
/**
* 将未读消息全部置为已读
*
* @param request 个人信息
*/
void readAllMessages(MessageReadAllReq request);
/**
* 消息的分页查询
*
* @param request 分页查询相关入参
* @return 消息的分页数据
*/
Page<MessageDetailRes> pageQueryMessageRecords(MessagePageQueryReq request);
}

View File

@ -1,6 +1,10 @@
package cn.axzo.msg.center.inside.notices.service;
import cn.axzo.msg.center.domain.dto.*;
import cn.axzo.msg.center.domain.dto.CreateModuleDTO;
import cn.axzo.msg.center.domain.dto.MsgModuleDTO;
import cn.axzo.msg.center.domain.dto.SearchModuleDTO;
import cn.axzo.msg.center.domain.dto.SyncModuleDataDTO;
import cn.axzo.msg.center.domain.dto.UpdateModuleDTO;
import cn.axzo.msg.center.domain.entity.MessageModule;
import cn.axzo.msg.center.domain.enums.UserTypeEnum;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -39,4 +43,12 @@ public interface MessageModuleService {
Map<Integer, List<Long>> listModuleByBizType();
void syncData(List<SyncModuleDataDTO> dtoList);
/**
* 根据模块名称查询对应的模块列表
*
* @param moduleName 模块名称
* @return 对应的模块列表
*/
List<MessageModule> listByModuleName(String moduleName);
}

View File

@ -0,0 +1,43 @@
package cn.axzo.msg.center.inside.notices.service;
import cn.axzo.msg.center.api.enums.MsgStateEnum;
import cn.axzo.msg.center.api.response.MessageDetailRes;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Optional;
/**
* @description
* 待办消息记录Service
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
public interface PendingMessageRecordService {
/**
* 统计个人指定状态的待办消息记录数量
*
* @param personId 自然人id
* @param identifyId 身份id可为null
* @param moduleId 模块id可为null
* @param states 指定状态列表可为null
* @return 个人指定状态的待办消息记录数量
*/
int countPersonMessage(Long personId, @Nullable Long identifyId,
@Nullable Long moduleId, @Nullable Collection<MsgStateEnum> states);
/**
* 查询个人最新一条待办消息优先选择未处理的
*
* @param personId 自然人id
* @param identifyId 身份id
* @param moduleId 模块id
* @param routerType 路由类型
* @return 个人最新一条待办消息
*/
Optional<MessageDetailRes> selectLatestOnePersonMessage(Long personId, String routerType,
@Nullable Long identifyId, @Nullable Long moduleId);
}

View File

@ -0,0 +1,71 @@
package cn.axzo.msg.center.inside.notices.service;
import cn.axzo.msg.center.api.enums.MsgStateEnum;
import cn.axzo.msg.center.api.enums.MsgTypeEnum;
import cn.axzo.msg.center.api.request.MessagePageQueryReq;
import cn.axzo.msg.center.api.response.MessageDetailRes;
import cn.axzo.msg.center.domain.dto.MessagePageQueryDTO;
import cn.azxo.framework.common.model.Page;
import javax.annotation.Nullable;
import javax.validation.constraints.NotEmpty;
import java.util.Collection;
import java.util.Optional;
/**
* @description
* 原始的消息记录数据源Service
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
public interface RawMessageRecordService {
/**
* 更新个人消息记录的状态
*
* @param personId 自然人id
* @param srcStates 原状态集合
* @param tgtState 目标状态
* @param msgType 消息类型
* @param identifyId 身份id可为null
* @param moduleIds 模块id集合可为null
*/
void updatePersonMessageState(Long personId, Collection<MsgStateEnum> srcStates, MsgStateEnum tgtState,
MsgTypeEnum msgType, @Nullable Long identifyId, @Nullable Collection<Long> moduleIds);
/**
* 统计个人指定状态的消息记录数量
*
* @param personId 自然人id
* @param msgType 消息类型
* @param identifyId 身份id可为null
* @param moduleIds 模块id集合可为null
* @param states 指定状态列表可为null
* @return 个人指定状态的消息记录数量
*/
int countPersonMessage(Long personId, MsgTypeEnum msgType, @Nullable Long identifyId,
@Nullable Collection<Long> moduleIds, @Nullable Collection<MsgStateEnum> states);
/**
* 查询个人最新一条消息记录优先选择未读或未处理的
*
* @param personId 自然人id
* @param identifyId 身份id
* @param moduleIds 模块id集合可为null
* @param routerType 路由类型
* @return 个人最新一条消息记录
*/
Optional<MessageDetailRes> selectLatestOnePersonMessage(Long personId, MsgTypeEnum msgType, String routerType,
@Nullable Long identifyId,
@Nullable Collection<Long> moduleIds);
/**
* 分页查询个人的消息记录
*
* @param request 分页查询的条件
* @return 消息记录列表
*/
Page<MessageDetailRes> pagePersonMessages(MessagePageQueryDTO request);
}

View File

@ -0,0 +1,54 @@
package cn.axzo.msg.center.inside.notices.service.impl;
import cn.axzo.msg.center.api.MessageApi;
import cn.axzo.msg.center.api.request.MessageModuleStatisticReq;
import cn.axzo.msg.center.api.request.MessagePageQueryReq;
import cn.axzo.msg.center.api.request.MessageReadAllReq;
import cn.axzo.msg.center.api.request.MessageStatisticReq;
import cn.axzo.msg.center.api.response.MessageDetailRes;
import cn.axzo.msg.center.api.response.MessageModuleStatisticRes;
import cn.axzo.msg.center.api.response.MessageStatisticRes;
import cn.axzo.msg.center.inside.notices.service.MessageCoreService;
import cn.azxo.framework.common.model.CommonResponse;
import cn.azxo.framework.common.model.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
/**
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@RestController
@RequiredArgsConstructor
public class MessageApiImpl implements MessageApi {
private final MessageCoreService messageCoreService;
@Override
public CommonResponse<MessageStatisticRes> countPersonMessage(@RequestBody @Valid MessageStatisticReq request) {
return CommonResponse.success(messageCoreService.countPersonMessage(request));
}
@Override
public CommonResponse<List<MessageModuleStatisticRes>> statisticPersonModuleMessage(@RequestBody @Valid
MessageModuleStatisticReq request) {
return CommonResponse.success(messageCoreService.statisticPersonModuleMessage(request));
}
@Override
public CommonResponse<Void> readAllMessages(@RequestBody @Valid MessageReadAllReq request) {
messageCoreService.readAllMessages(request);
return CommonResponse.success();
}
@Override
public CommonResponse<Page<MessageDetailRes>> pageQueryMessageRecords(@RequestBody @Valid
MessagePageQueryReq request) {
return CommonResponse.success(messageCoreService.pageQueryMessageRecords(request));
}
}

View File

@ -1,11 +1,23 @@
package cn.axzo.msg.center.inside.notices.service.impl;
import cn.axzo.core.domain.PageResult;
import cn.axzo.msg.center.api.enums.MsgStateEnum;
import cn.axzo.msg.center.api.enums.MsgTypeEnum;
import cn.axzo.msg.center.api.request.CmsMsgQueryReq;
import cn.axzo.msg.center.api.request.MessageModuleStatisticReq;
import cn.axzo.msg.center.api.request.MessagePageQueryReq;
import cn.axzo.msg.center.api.request.MessageReadAllReq;
import cn.axzo.msg.center.api.request.MessageStatisticReq;
import cn.axzo.msg.center.api.response.MessageDetailRes;
import cn.axzo.msg.center.api.response.MessageModuleBriefRes;
import cn.axzo.msg.center.api.response.MessageModuleStatisticRes;
import cn.axzo.msg.center.api.response.MessageNewRes;
import cn.axzo.msg.center.api.response.MessageStatisticRes;
import cn.axzo.msg.center.api.response.MessageTotalRes;
import cn.axzo.msg.center.common.enums.SystemTypeEnum;
import cn.axzo.msg.center.common.utils.BeanConvertUtils;
import cn.axzo.msg.center.common.utils.PlaceholderResolver;
import cn.axzo.msg.center.domain.dto.MessagePageQueryDTO;
import cn.axzo.msg.center.domain.dto.MsgModuleDTO;
import cn.axzo.msg.center.domain.entity.MessageModule;
import cn.axzo.msg.center.domain.entity.MessageRelation;
@ -13,16 +25,38 @@ import cn.axzo.msg.center.domain.entity.MessageRouter;
import cn.axzo.msg.center.domain.enums.MsgRouteTypeEnum;
import cn.axzo.msg.center.domain.enums.NativeTypeEnum;
import cn.axzo.msg.center.domain.enums.UserTypeEnum;
import cn.axzo.msg.center.inside.notices.service.*;
import cn.axzo.msg.center.inside.notices.service.IMessageService;
import cn.axzo.msg.center.inside.notices.service.MessageCoreService;
import cn.axzo.msg.center.inside.notices.service.MessageModuleService;
import cn.axzo.msg.center.inside.notices.service.MessageRecordService;
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.RawMessageRecordService;
import cn.azxo.framework.common.model.Page;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Lists;
import jodd.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -37,6 +71,13 @@ import static cn.axzo.msg.center.domain.enums.MsgRouteTypeEnum.WECHAT_MINI_PROGR
@Slf4j
public class MessageCoreServiceImpl implements MessageCoreService {
private final ThreadFactory moduleStatisticTaskThreadFactory = ThreadFactoryBuilder.create()
.setDaemon(true)
.setNameFormat("MODULE_STATISTIC_TASK_%d")
.get();
private final ExecutorService moduleStatisticTaskThreadPool = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1024), moduleStatisticTaskThreadFactory);
@Resource
private MessageRecordService messageRecordService;
@ -51,11 +92,12 @@ public class MessageCoreServiceImpl implements MessageCoreService {
@Resource
private IMessageService messageService;
@Resource
private RawMessageRecordService rawMessageRecordService;
public MsgRouteTypeEnum getSystemType(String systemType) {
/*String systemType = ContextInfoHolder.get().getSystemAndDeviceInfo().getSystemType();*/
if(org.apache.commons.lang3.StringUtils.isEmpty(systemType)){
if (org.apache.commons.lang3.StringUtils.isEmpty(systemType)) {
return MsgRouteTypeEnum.WEB;
}
//判断是否为手机端调用
@ -78,7 +120,7 @@ public class MessageCoreServiceImpl implements MessageCoreService {
* @return
*/
@Override
public MessageTotalRes statisticsMsg(Long personId,Long identityId,UserTypeEnum userTypeEnum) {
public MessageTotalRes statisticsMsg(Long personId, Long identityId, UserTypeEnum userTypeEnum) {
//根据用户和当前身份获取未读和待办消息
return messageRecordService.statisticsMsg4Total(personId, identityId, userTypeEnum);
}
@ -100,7 +142,7 @@ public class MessageCoreServiceImpl implements MessageCoreService {
if (Objects.equals(NT_CM_APP_GENERAL, ContextInfoHolder.get().getSystemAndDeviceInfo().getLoginDevice())) {
personId = ContextInfoHolder.get().getUserInfo().getPersonId();
}*/
UserTypeEnum userTypeEnum=UserTypeEnum.valueOf(req.getUserType());
UserTypeEnum userTypeEnum = UserTypeEnum.valueOf(req.getUserType());
resPageResult = messageRecordService.pageMsgInfo(req, req.getPersonId(), req.getIdentityId(), userTypeEnum);
List<MessageNewRes> resList = refineMessageRes(resPageResult, req);
@ -119,50 +161,50 @@ public class MessageCoreServiceImpl implements MessageCoreService {
//获取relationId集合
Set<Long> relationIds = resList.stream().map(MessageNewRes::getRelationId).collect(
Collectors.toSet());
if(CollectionUtils.isNotEmpty(relationIds)){
if (CollectionUtils.isNotEmpty(relationIds)) {
relationIds.remove(null);
relationIds.remove(0L);
}
//获取oldTypeId集合
Set<Integer> oldTypeIds= resList.stream().map(MessageNewRes::getOldTypeId).collect(
Set<Integer> oldTypeIds = resList.stream().map(MessageNewRes::getOldTypeId).collect(
Collectors.toSet());
if(CollectionUtils.isNotEmpty(oldTypeIds)){
if (CollectionUtils.isNotEmpty(oldTypeIds)) {
oldTypeIds.remove(null);
oldTypeIds.remove(0);
}
if(CollectionUtils.isEmpty(relationIds) && CollectionUtils.isEmpty(oldTypeIds)){
if (CollectionUtils.isEmpty(relationIds) && CollectionUtils.isEmpty(oldTypeIds)) {
return resList;
}
//获取模板所对应的所有模块及icon
List<MsgModuleDTO> moduleDtos = messageModuleService.listModuleByRelationIdsOrTypeIds(oldTypeIds,relationIds);
List<MsgModuleDTO> moduleDtos = messageModuleService.listModuleByRelationIdsOrTypeIds(oldTypeIds, relationIds);
//新关联键分组
Map<Long, List<MsgModuleDTO>> relationModule = moduleDtos.stream().filter(k->k.getRelationId()!=null&&k.getRelationId()!=0)
Map<Long, List<MsgModuleDTO>> relationModule = moduleDtos.stream().filter(k -> k.getRelationId() != null && k.getRelationId() != 0)
.collect(Collectors.groupingBy(MsgModuleDTO::getRelationId));
//老关联键分组
Map<Integer, List<MsgModuleDTO>> typeIdModules = moduleDtos.stream().filter(k->k.getTypeId()!=null&&k.getTypeId()!=0)
Map<Integer, List<MsgModuleDTO>> typeIdModules = moduleDtos.stream().filter(k -> k.getTypeId() != null && k.getTypeId() != 0)
.collect(Collectors.groupingBy(MsgModuleDTO::getTypeId));
//批量获取路由信息
MsgRouteTypeEnum msgRouteTypeEnum = getSystemType(req.getSystemType());
List<MessageRouter> routers = new ArrayList<>();
Map<Long,List<MessageRouter>> mapRout =new HashMap<>();
if(CollectionUtils.isNotEmpty(relationIds)){
Map<Long, List<MessageRouter>> mapRout = new HashMap<>();
if (CollectionUtils.isNotEmpty(relationIds)) {
routers = messageRouterService.listRoutersByRelationIds(relationIds);
mapRout = routers.stream().collect(Collectors.groupingBy(MessageRouter::getRelationId));
}
Map<Long, List<MessageRouter>> finalMapRout = mapRout;
resList.forEach(item->{
resList.forEach(item -> {
//赋值状态
if(req.getMsgType()==1){
item.setState(item.getState()==4?2:1);
}else{
item.setState(item.getState()==5?2:1);
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){
if (item.getRelationId() != null && item.getRelationId() != 0) {
List<MsgModuleDTO> modules = relationModule.get(item.getRelationId());
if(CollectionUtils.isNotEmpty(modules)){
if (CollectionUtils.isNotEmpty(modules)) {
MsgModuleDTO first = modules.stream()
.filter(i -> i.getOwnedType().equals(item.getReceiveType()))
.findFirst().orElse(modules.get(0));
@ -170,9 +212,9 @@ public class MessageCoreServiceImpl implements MessageCoreService {
item.setMsgName(first.getMsgModuleName());
}
}
if(StrUtil.isEmpty(item.getMsgIcon())){
if (StrUtil.isEmpty(item.getMsgIcon())) {
List<MsgModuleDTO> modules = typeIdModules.get(item.getOldTypeId());
if(CollectionUtils.isNotEmpty(modules)){
if (CollectionUtils.isNotEmpty(modules)) {
MsgModuleDTO first = modules.stream()
.filter(i -> i.getOwnedType().equals(item.getReceiveType()))
.findFirst().orElse(modules.get(0));
@ -182,41 +224,41 @@ public class MessageCoreServiceImpl implements MessageCoreService {
}
//如果relationId为空 进行老方法获取路由
if(item.getRelationId() == null || item.getRelationId() ==0){
messageService.setNewRouter(item,msgRouteTypeEnum.getCode());
}else{
if (item.getRelationId() == null || item.getRelationId() == 0) {
messageService.setNewRouter(item, msgRouteTypeEnum.getCode());
} else {
List<MessageRouter> messageRouters = finalMapRout.get(item.getRelationId());
if(CollectionUtils.isNotEmpty(messageRouters)){
if(messageRouters.size() == 1){
if (CollectionUtils.isNotEmpty(messageRouters)) {
if (messageRouters.size() == 1) {
NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode(messageRouters.get(0).getRouterType().getCode());
if(nativeTypeEnum != null){
if (nativeTypeEnum != null) {
item.setRouter(messageRouters.get(0).getRouterUrl());
item.setRouterType(nativeTypeEnum.getMessage());
}
}else {
} else {
//不止一条 获取当前系统对应路由
List<MessageRouter> router = messageRouters.stream().filter(k->k.getRouterType().equals(msgRouteTypeEnum)).collect(
List<MessageRouter> router = messageRouters.stream().filter(k -> k.getRouterType().equals(msgRouteTypeEnum)).collect(
Collectors.toList());
if(CollectionUtils.isNotEmpty(router)){
if (CollectionUtils.isNotEmpty(router)) {
NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode(router.get(0).getRouterType().getCode());
if(nativeTypeEnum != null){
if (nativeTypeEnum != null) {
item.setRouter(router.get(0).getRouterUrl());
item.setRouterType(nativeTypeEnum.getMessage());
}
}else{
} else {
//优先取H5
List<MessageRouter> routerH5 = messageRouters.stream().filter(k->k.getRouterType().equals(MsgRouteTypeEnum.WEBVIEW)).collect(
List<MessageRouter> routerH5 = messageRouters.stream().filter(k -> k.getRouterType().equals(MsgRouteTypeEnum.WEBVIEW)).collect(
Collectors.toList());
if(CollectionUtils.isNotEmpty(routerH5)){
if (CollectionUtils.isNotEmpty(routerH5)) {
NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode(routerH5.get(0).getRouterType().getCode());
if(nativeTypeEnum != null){
if (nativeTypeEnum != null) {
item.setRouter(routerH5.get(0).getRouterUrl());
item.setRouterType(nativeTypeEnum.getMessage());
}
}
//再取小程序
List<MessageRouter> routerUni = messageRouters.stream().filter(k->k.getRouterType().equals(MsgRouteTypeEnum.MINI_PROGRAM)).collect(
List<MessageRouter> routerUni = messageRouters.stream().filter(k -> k.getRouterType().equals(MsgRouteTypeEnum.MINI_PROGRAM)).collect(
Collectors.toList());
if (CollectionUtils.isNotEmpty(routerUni)) {
NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode(
@ -232,7 +274,7 @@ public class MessageCoreServiceImpl implements MessageCoreService {
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)));
JSON.parseObject(Objects.equals(item.getRouterParam(), "null") ? "{}" : item.getRouterParam(), Map.class)));
}
}
});
@ -276,4 +318,75 @@ public class MessageCoreServiceImpl implements MessageCoreService {
return new PageResult<>(resList, pageResult.getTotalCount());
}
@Override
public MessageStatisticRes countPersonMessage(MessageStatisticReq request) {
List<MsgStateEnum> states = Lists.newArrayList(MsgStateEnum.HAS_BEEN_SENT, MsgStateEnum.RECEIVED);
int generalCnt = rawMessageRecordService.countPersonMessage(request.getPersonId(), MsgTypeEnum.GENERAL_MESSAGE,
null, null, states);
int pendingCnt = rawMessageRecordService.countPersonMessage(request.getPersonId(), MsgTypeEnum.PENDING_MESSAGE,
null, null, states);
return new MessageStatisticRes(generalCnt, pendingCnt);
}
@Override
public List<MessageModuleStatisticRes> statisticPersonModuleMessage(MessageModuleStatisticReq request) {
Map<String, List<MessageModule>> moduleNameMap = messageModuleService.getAllModules().stream()
.collect(Collectors.groupingBy(MessageModule::getModuleName));
final Map<String, MessageModuleStatisticRes> resultMap = new ConcurrentHashMap<>();
CompletableFuture[] asyncStatisticArray = moduleNameMap.entrySet().stream()
.map(e -> CompletableFuture.runAsync(() -> doStatistic(request, e.getKey(), e.getValue(), resultMap),
moduleStatisticTaskThreadPool))
.toArray(CompletableFuture[]::new);
CompletableFuture<Void> completableFuture = CompletableFuture.allOf(asyncStatisticArray);
completableFuture.join();
return Lists.newArrayList(resultMap.values());
}
@Override
public void readAllMessages(MessageReadAllReq request) {
List<MsgStateEnum> srcStates = Lists.newArrayList(MsgStateEnum.HAS_BEEN_SENT, MsgStateEnum.RECEIVED);
List<Long> moduleIds = messageModuleService.listByModuleName(request.getModuleName()).stream()
.map(MessageModule::getId)
.collect(Collectors.toList());
rawMessageRecordService.updatePersonMessageState(request.getPersonId(), srcStates, MsgStateEnum.HAVE_READ,
MsgTypeEnum.GENERAL_MESSAGE, null, moduleIds);
}
@Override
public Page<MessageDetailRes> pageQueryMessageRecords(MessagePageQueryReq request) {
MessagePageQueryDTO pageQuery = BeanConvertUtils.copyBean(request, MessagePageQueryDTO.class);
List<Long> moduleIds = messageModuleService.listByModuleName(request.getModuleName()).stream()
.map(MessageModule::getId)
.collect(Collectors.toList());
pageQuery.setModuleIds(moduleIds);
return rawMessageRecordService.pagePersonMessages(pageQuery);
}
private void doStatistic(MessageModuleStatisticReq request, String moduleName, List<MessageModule> modules,
Map<String, MessageModuleStatisticRes> resultMap) {
List<Long> moduleIds = modules.stream().map(MessageModule::getId).collect(Collectors.toList());
List<MsgStateEnum> states = Lists.newArrayList(MsgStateEnum.HAS_BEEN_SENT, MsgStateEnum.RECEIVED);
int cnt = rawMessageRecordService.countPersonMessage(request.getPersonId(), request.getMsgType(), null,
moduleIds, states);
Optional<MessageDetailRes> optional = rawMessageRecordService.selectLatestOnePersonMessage(request.getPersonId(),
request.getMsgType(), request.getRouterType(), null, moduleIds);
optional.ifPresent(v -> {
MessageModuleBriefRes moduleBriefRes = new MessageModuleBriefRes();
moduleBriefRes.setName(moduleName);
moduleBriefRes.setIcon(modules.stream()
.filter(e -> org.apache.commons.lang3.StringUtils.isNotBlank(e.getIcon()))
.findFirst()
.map(MessageModule::getIcon)
.orElse(null));
MessageModuleStatisticRes res = new MessageModuleStatisticRes();
res.setContent(v.getContent());
res.setCount(cnt);
res.setTitle(v.getMsgTitle());
res.setModule(moduleBriefRes);
res.setTerminalName(v.getTerminalName());
res.setCreateTimestamp(v.getMsgTimestamp());
resultMap.put(moduleName, res);
});
}
}

View File

@ -14,6 +14,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
@ -168,4 +169,14 @@ public class MessageModuleServiceImpl implements MessageModuleService {
}
messageModuleDao.insertBatchSql(adds);
}
@Override
public List<MessageModule> listByModuleName(String moduleName) {
if (StringUtils.isBlank(moduleName)) {
return Collections.emptyList();
}
return getAllModules().stream()
.filter(e -> Objects.equals(e.getModuleName(), moduleName))
.collect(Collectors.toList());
}
}

View File

@ -592,11 +592,13 @@ public class MessageRecordServiceImpl implements MessageRecordService {
if (Objects.isNull(request)) {
log.warn("==={}=== request param is null.", "deleteMessageRecords");
return false;
} else if (CollectionUtils.isEmpty(request.getMsgIds())
}
if (CollectionUtils.isEmpty(request.getMsgIds())
&& (Objects.isNull(request.getRelationId()) || request.getRelationId() < 0)) {
log.warn("==={}=== request param is invalid. {}", "deleteMessageRecords", request);
return false;
} else if (!CollectionUtils.isEmpty(request.getMsgIds())
}
if (!CollectionUtils.isEmpty(request.getMsgIds())
&& request.getMsgIds().size() > MAX_SIZE_OF_BATCH_UPDATE_ONCE) {
log.warn("==={}=== the size of request.msgIds is exceed {}.", "deleteMessageRecords", MAX_SIZE_OF_BATCH_UPDATE_ONCE);
return false;

View File

@ -0,0 +1,328 @@
package cn.axzo.msg.center.inside.notices.service.impl;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.msg.center.api.enums.MsgStateEnum;
import cn.axzo.msg.center.api.enums.MsgTypeEnum;
import cn.axzo.msg.center.api.response.MessageDetailRes;
import cn.axzo.msg.center.common.utils.BeanConvertUtils;
import cn.axzo.msg.center.common.utils.PlaceholderResolver;
import cn.axzo.msg.center.dal.MessageRecordDao;
import cn.axzo.msg.center.domain.dto.MessagePageQueryDTO;
import cn.axzo.msg.center.domain.dto.MessageRouterDTO;
import cn.axzo.msg.center.domain.dto.MsgModuleDTO;
import cn.axzo.msg.center.domain.entity.MessageRecord;
import cn.axzo.msg.center.domain.entity.MessageRouter;
import cn.axzo.msg.center.domain.enums.MsgRouteTypeEnum;
import cn.axzo.msg.center.domain.enums.NativeTypeEnum;
import cn.axzo.msg.center.domain.enums.YesNoEnum;
import cn.axzo.msg.center.inside.notices.service.MessageModuleService;
import cn.axzo.msg.center.inside.notices.service.MessageRouterService;
import cn.axzo.msg.center.inside.notices.service.RawMessageRecordService;
import cn.axzo.msg.center.inside.notices.utils.MessageRecordHelper;
import cn.azxo.framework.common.model.Page;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Nullable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @description xxx
* @author cold_blade
* @date 2023/9/13
* @version 1.0
* TODO: [cold_blade]待优化
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class RawMessageRecordServiceImpl implements RawMessageRecordService {
private static final int HOT_DATA_SAVE_DAYS = 90;
private final MessageRecordDao messageRecordDao;
private final MessageModuleService messageModuleService;
private final MessageRouterService messageRouterService;
@Override
public void updatePersonMessageState(Long personId, Collection<MsgStateEnum> srcStates, MsgStateEnum tgtState,
MsgTypeEnum msgType, @Nullable Long identifyId,
@Nullable Collection<Long> moduleIds) {
AssertUtil.notNull(personId, "personId is required");
AssertUtil.notEmpty(srcStates, "srcStates is required");
AssertUtil.notNull(tgtState, "tgtState is required");
messageRecordDao.lambdaUpdate()
.set(MessageRecord::getState, tgtState)
.eq(MessageRecord::getPersonId, personId)
.in(MessageRecord::getState, srcStates)
.eq(Objects.nonNull(identifyId), MessageRecord::getToId, identifyId)
.in(CollectionUtils.isNotEmpty(moduleIds), MessageRecord::getModuleId, moduleIds)
.eq(Objects.nonNull(msgType), MessageRecord::getType, msgType)
.eq(MessageRecord::getIsDelete, YesNoEnum.NO.getCode())
.ge(MessageRecord::getCreateAt, getQueryFromTime())
.update();
}
@Override
public int countPersonMessage(Long personId, MsgTypeEnum msgType, @Nullable Long identifyId,
@Nullable Collection<Long> moduleIds, @Nullable Collection<MsgStateEnum> states) {
AssertUtil.notNull(personId, "personId is required");
AssertUtil.notNull(msgType, "msgType is required");
return messageRecordDao.lambdaQuery()
.eq(MessageRecord::getPersonId, personId)
.eq(MessageRecord::getType, msgType)
.eq(Objects.nonNull(identifyId), MessageRecord::getToId, identifyId)
.in(CollectionUtils.isNotEmpty(moduleIds), MessageRecord::getModuleId, moduleIds)
.in(CollectionUtils.isNotEmpty(states), MessageRecord::getState, states)
.eq(MessageRecord::getIsDelete, YesNoEnum.NO.getCode())
.ge(MessageRecord::getCreateAt, getQueryFromTime())
.count();
}
@Override
public Optional<MessageDetailRes> selectLatestOnePersonMessage(Long personId, MsgTypeEnum msgType, String routerType,
@Nullable Long identifyId,
@Nullable Collection<Long> moduleIds) {
MessageRecord record = messageRecordDao.lambdaQuery()
.eq(MessageRecord::getPersonId, personId)
.eq(MessageRecord::getType, msgType)
.eq(Objects.nonNull(identifyId), MessageRecord::getToId, identifyId)
.in(CollectionUtils.isNotEmpty(moduleIds), MessageRecord::getModuleId, moduleIds)
.in(MessageRecord::getState, MsgStateEnum.successfullyStats())
.eq(MessageRecord::getIsDelete, YesNoEnum.NO.getCode())
.ge(MessageRecord::getCreateAt, getQueryFromTime())
.orderByAsc(MessageRecord::getState)
.orderByDesc(MessageRecord::getCreateAt)
.last("LIMIT 1")
.one();
return Optional.ofNullable(record)
.map(v -> {
Map<Long, MsgModuleDTO> moduleMap = listMessageModules(Lists.newArrayList(v));
if (!moduleMap.containsKey(v.getId())) {
return null;
}
MessageRouterDTO router = listRouters(Lists.newArrayList(v), routerType).get(v.getId());
return convert(v, router, moduleMap.get(v.getId()));
});
}
@Override
public Page<MessageDetailRes> pagePersonMessages(MessagePageQueryDTO request) {
AssertUtil.notNull(request.getPersonId(), "personId is required");
AssertUtil.notNull(request.getMsgType(), "msgType is required");
List<MsgStateEnum> msgStates = CollectionUtils.isEmpty(request.getStates()) ? MsgStateEnum.successfullyStats()
: request.getStates();
IPage<MessageRecord> page = request.toPage();
page = messageRecordDao.lambdaQuery()
.eq(Objects.nonNull(request.getPersonId()), MessageRecord::getPersonId, request.getPersonId())
.eq(MessageRecord::getType, request.getMsgType())
.in(CollectionUtils.isNotEmpty(request.getModuleIds()), MessageRecord::getModuleId,
request.getModuleIds())
.in(MessageRecord::getState, msgStates)
.eq(MessageRecord::getIsDelete, YesNoEnum.NO.getCode())
.ge(MessageRecord::getCreateAt, getQueryFromTime())
.orderByAsc(MessageRecord::getState)
.orderByDesc(MessageRecord::getCreateAt)
.page(page);
if (CollectionUtils.isEmpty(page.getRecords())) {
// 列表为空的场景
return Page.toPage(page.getCurrent(), page.getSize(), page.getTotal(), Collections.emptyList());
}
List<MessageRecord> records = page.getRecords();
// 查询消息对应的路由集
Map<Long, MessageRouterDTO> routerMap = listRouters(records, request.getRouteType());
Map<Long, MsgModuleDTO> moduleMap = listMessageModules(records);
// 原始的数据库模型数据转化为页面展示的数据模型
List<MessageDetailRes> msgRecordBriefs = page.getRecords().stream()
.filter(e -> moduleMap.containsKey(e.getId()))
.map(e -> convert(e, routerMap.get(e.getId()), moduleMap.get(e.getId())))
.collect(Collectors.toList());
return Page.toPage(page.getCurrent(), page.getSize(), page.getTotal(), msgRecordBriefs);
}
private Map<Long, MsgModuleDTO> listMessageModules(List<MessageRecord> msgRecords) {
//获取relationId集合
Set<Long> relationIds = msgRecords.stream().map(MessageRecord::getRelationId).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(relationIds)) {
relationIds.remove(null);
relationIds.remove(0L);
}
//获取oldTypeId集合
Set<Integer> oldTypeIds = msgRecords.stream().map(MessageRecord::getOldTypeId).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(oldTypeIds)) {
oldTypeIds.remove(null);
oldTypeIds.remove(0);
}
if (CollectionUtils.isEmpty(relationIds) && CollectionUtils.isEmpty(oldTypeIds)) {
return Collections.emptyMap();
}
//获取模板列表
List<MsgModuleDTO> modules = messageModuleService.listModuleByRelationIdsOrTypeIds(oldTypeIds, relationIds);
//新关联键分组
Map<Long, List<MsgModuleDTO>> relationModuleMap = modules.stream()
.filter(e -> Objects.nonNull(e.getRelationId()) && e.getRelationId() != 0)
.collect(Collectors.groupingBy(MsgModuleDTO::getRelationId));
//老关联键分组
Map<Integer, List<MsgModuleDTO>> typeIdModuleMap = modules.stream()
.filter(e -> Objects.nonNull(e.getTypeId()) && e.getTypeId() != 0)
.collect(Collectors.groupingBy(MsgModuleDTO::getTypeId));
return msgRecords.stream()
.map(e -> selectModule(e, relationModuleMap, typeIdModuleMap))
.filter(Objects::nonNull)
.collect(Collectors.toMap(MsgModuleDTO::getMsgId, Function.identity(), (pre, cur) -> cur));
}
private MsgModuleDTO selectModule(MessageRecord record, Map<Long, List<MsgModuleDTO>> relationModuleMap,
Map<Integer, List<MsgModuleDTO>> typeIdModuleMap) {
MsgModuleDTO module = null;
// 优先使用relation关联的模板
if (MessageRecordHelper.isRelationIdValid(record.getRelationId())) {
module = relationModuleMap.get(record.getRelationId()).stream()
.findFirst().orElse(null);
}
if (Objects.isNull(module) && MessageRecordHelper.isOldTypeIdValid(record.getOldTypeId())) {
module = typeIdModuleMap.get(record.getOldTypeId()).stream()
.findFirst().orElse(null);
}
Optional.ofNullable(module)
.ifPresent(v -> v.setMsgId(record.getId()));
return module;
}
private LocalDateTime getQueryFromTime() {
return LocalDate.now().minusDays(HOT_DATA_SAVE_DAYS).atStartOfDay();
}
private MessageDetailRes convert(MessageRecord msgRecord, MessageRouterDTO router, MsgModuleDTO module) {
MessageDetailRes res = BeanConvertUtils.copyBean(msgRecord, MessageDetailRes.class);
res.setMsgId(msgRecord.getId());
res.setMsgTitle(msgRecord.getTitle());
res.setMsgTimestamp(msgRecord.getCreateAt().getTime());
if (Objects.nonNull(router)) {
res.setRouteUrl(router.getUrl());
res.setRouteType(router.getType());
}
res.setModuleName(module.getMsgModuleName());
res.setModuleIcon(module.getMsgModuleIcon());
return res;
}
private Map<Long, MessageRouterDTO> listRouters(Collection<MessageRecord> msgRecords, String routerType) {
final Set<Long> relationIds = msgRecords.stream().map(MessageRecord::getRelationId).collect(Collectors.toSet());
Map<Long, List<MessageRouter>> rawRouterMap = messageRouterService.listRoutersByRelationIds(relationIds).stream()
.collect(Collectors.groupingBy(MessageRouter::getRelationId));
final Map<Long, MessageRouterDTO> resRouterMap = new HashMap<>();
msgRecords.forEach(e -> {
List<MessageRouter> routers = rawRouterMap.get(e.getRelationId());
MessageRouterDTO router = pickAndParseMessageRouter(routers, routerType, e.getRouterParams());
resRouterMap.put(e.getId(), router);
});
return resRouterMap;
}
private MessageRouterDTO pickAndParseMessageRouter(List<MessageRouter> rawRouters, String systemType, String routerParam) {
if (CollectionUtils.isEmpty(rawRouters)) {
return null;
}
MsgRouteTypeEnum routeType = getSystemType(systemType);
return pickAndParseMessageRouter(rawRouters, routeType, routerParam);
}
private MessageRouterDTO pickAndParseMessageRouter(List<MessageRouter> messageRouters,
MsgRouteTypeEnum msgRouteTypeEnum, String routerParam) {
String rawRouterUrl = null;
Integer routerType = null;
if (messageRouters.size() == 1) {
NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode(messageRouters.get(0).getRouterType().getCode());
if (Objects.nonNull(nativeTypeEnum)) {
rawRouterUrl = messageRouters.get(0).getRouterUrl();
routerType = nativeTypeEnum.getMessage();
}
} else {
//不止一条 获取当前系统对应路由
List<MessageRouter> routers = messageRouters.stream()
.filter(k -> k.getRouterType().equals(msgRouteTypeEnum))
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(routers)) {
NativeTypeEnum nativeTypeEnum = NativeTypeEnum.getByCode(routers.get(0).getRouterType().getCode());
if (nativeTypeEnum != null) {
rawRouterUrl = routers.get(0).getRouterUrl();
routerType = nativeTypeEnum.getMessage();
}
} else {
//优先取H5
List<MessageRouter> 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) {
rawRouterUrl = routerH5.get(0).getRouterUrl();
routerType = nativeTypeEnum.getMessage();
}
}
//再取小程序
List<MessageRouter> 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) {
rawRouterUrl = routerUni.get(0).getRouterUrl();
routerType = nativeTypeEnum.getMessage();
}
}
}
}
PlaceholderResolver resolver = PlaceholderResolver.getDefaultResolver();
if (Objects.nonNull(routerType)) {
rawRouterUrl = resolver.resolveByMap(rawRouterUrl,
isRouterParamValid(routerParam) ? JSON.parseObject(routerParam) : Collections.emptyMap());
}
return new MessageRouterDTO(rawRouterUrl, routerType);
}
private boolean isRouterParamValid(String routerParam) {
return StringUtils.isNotEmpty(routerParam)
&& !"null".equals(routerParam);
}
private MsgRouteTypeEnum getSystemType(String systemType) {
/*String systemType = ContextInfoHolder.get().getSystemAndDeviceInfo().getSystemType();*/
//判断是否为手机端调用
if (MsgRouteTypeEnum.IOS.getMessage().equals(systemType)) {
return MsgRouteTypeEnum.IOS;
}
if (MsgRouteTypeEnum.ANDROID.getMessage().equals(systemType)) {
return MsgRouteTypeEnum.ANDROID;
}
if (MsgRouteTypeEnum.WECHAT_MINI_PROGRAM.getMessage().equals(systemType)) {
return MsgRouteTypeEnum.WECHAT_MINI_PROGRAM;
}
//都不是表明确定web端调用
return MsgRouteTypeEnum.WEB;
}
}

View File

@ -0,0 +1,21 @@
package cn.axzo.msg.center.inside.notices.utils;
import java.util.Objects;
/**
* @description
* 消息记录的helper
* @author cold_blade
* @date 2023/9/15
* @version 1.0
*/
public final class MessageRecordHelper {
public static boolean isRelationIdValid(Long relationId) {
return Objects.nonNull(relationId) && relationId != 0;
}
public static boolean isOldTypeIdValid(Integer oldTypeId) {
return Objects.nonNull(oldTypeId) && oldTypeId != 0;
}
}

View File

@ -0,0 +1,70 @@
package cn.axzo.msg.center.api;
import cn.axzo.msg.center.api.fallback.MessageApiFallback;
import cn.axzo.msg.center.api.request.MessageModuleStatisticReq;
import cn.axzo.msg.center.api.request.MessagePageQueryReq;
import cn.axzo.msg.center.api.request.MessageReadAllReq;
import cn.axzo.msg.center.api.request.MessageStatisticReq;
import cn.axzo.msg.center.api.response.MessageDetailRes;
import cn.axzo.msg.center.api.response.MessageModuleStatisticRes;
import cn.axzo.msg.center.api.response.MessageStatisticRes;
import cn.azxo.framework.common.model.CommonResponse;
import cn.azxo.framework.common.model.Page;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
import java.util.List;
/**
* @description
* 消息相关API接口定义
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Component
@FeignClient(value = "msg-center", url = "${server.serviceUrl:http://msg-center:8080}",
fallback = MessageApiFallback.class)
public interface MessageApi {
/**
* 个人消息按类型统计待办/未读数量
*
* @param request 个人信息及消息类型
* @return 待办/未读数量
*/
@PostMapping(value = "/person/message/count", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<MessageStatisticRes> countPersonMessage(@RequestBody @Valid MessageStatisticReq request);
/**
* 个人消息按模块分组统计
*
* @param request 个人信息及消息类型
* @return 待展示的统计信息
*/
@PostMapping(value = "/person/message/module/statistic", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<List<MessageModuleStatisticRes>> statisticPersonModuleMessage(@RequestBody @Valid
MessageModuleStatisticReq request);
/**
* 将未读消息全部置为已读
*
* @param request 个人信息
*/
@PostMapping(value = "/message/read-all", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<Void> readAllMessages(@RequestBody @Valid MessageReadAllReq request);
/**
* 消息的分页查询
*
* @param request 分页查询相关入参
* @return 消息的分页数据
*/
@PostMapping(value = "/message/record/page-query", produces = {MediaType.APPLICATION_JSON_VALUE})
CommonResponse<Page<MessageDetailRes>> pageQueryMessageRecords(@RequestBody @Valid MessagePageQueryReq request);
}

View File

@ -1,9 +1,11 @@
package cn.axzo.msg.center.api.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.google.common.collect.Lists;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
/**
* @author: wangli
@ -38,4 +40,13 @@ public enum MsgStateEnum {
public static MsgStateEnum getByCode(Integer code) {
return Arrays.stream(values()).filter(it -> it.code.equals(code)).findFirst().orElse(null);
}
}
public static List<MsgStateEnum> successfullyStats() {
return Lists.newArrayList(
HAS_BEEN_SENT,
RECEIVED,
HAVE_READ,
COMPLETE
);
}
}

View File

@ -0,0 +1,47 @@
package cn.axzo.msg.center.api.fallback;
import cn.axzo.msg.center.api.MessageApi;
import cn.axzo.msg.center.api.request.MessageModuleStatisticReq;
import cn.axzo.msg.center.api.request.MessagePageQueryReq;
import cn.axzo.msg.center.api.request.MessageReadAllReq;
import cn.axzo.msg.center.api.request.MessageStatisticReq;
import cn.axzo.msg.center.api.response.MessageDetailRes;
import cn.axzo.msg.center.api.response.MessageModuleStatisticRes;
import cn.axzo.msg.center.api.response.MessageStatisticRes;
import cn.azxo.framework.common.model.CommonResponse;
import cn.azxo.framework.common.model.Page;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Slf4j
public class MessageApiFallback implements MessageApi {
@Override
public CommonResponse<MessageStatisticRes> countPersonMessage(MessageStatisticReq request) {
log.warn("个人消息按类型统计待办/未读数量, req:{}", request);
return CommonResponse.fail("个人消息按类型统计待办/未读数量");
}
@Override
public CommonResponse<List<MessageModuleStatisticRes>> statisticPersonModuleMessage(MessageModuleStatisticReq request) {
log.warn("按模块分组统计个人信息超时, req:{}", request);
return CommonResponse.fail("按模块分组统计个人信息超时");
}
@Override
public CommonResponse<Void> readAllMessages(MessageReadAllReq request) {
log.warn("将全部未读消息置为已读超时, req:{}", request);
return CommonResponse.fail("将全部未读消息置为已读超时");
}
@Override
public CommonResponse<Page<MessageDetailRes>> pageQueryMessageRecords(MessagePageQueryReq request) {
log.warn("分页查询消息记录超时, req:{}", request);
return CommonResponse.fail("分页查询消息记录超时");
}
}

View File

@ -0,0 +1,46 @@
package cn.axzo.msg.center.api.request;
import cn.axzo.msg.center.api.enums.MsgTypeEnum;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @description
* 个人消息按模块分组统计的请求入参数据模型
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Setter
@Getter
public class MessageModuleStatisticReq implements Serializable {
private static final long serialVersionUID = 1507456905431377437L;
/**
* 自然人id[用户信息,前端开发不用关注]
*/
@NotNull(message = "personId is required")
private Long personId;
/**
* 消息类型
* @see MsgTypeEnum#GENERAL_MESSAGE : 普通消息
* @see MsgTypeEnum#PENDING_MESSAGE : 待办消息
*/
@NotNull(message = "msgType is required")
private MsgTypeEnum msgType;
/**
* 路由类型前端不用关心
*/
private String routerType;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,66 @@
package cn.axzo.msg.center.api.request;
import cn.axzo.basics.common.page.PageRequest;
import cn.axzo.msg.center.api.enums.MsgStateEnum;
import cn.axzo.msg.center.api.enums.MsgTypeEnum;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
/**
* @description
* 个人消息分页查询请求入参数
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Setter
@Getter
public class MessagePageQueryReq extends PageRequest implements Serializable {
private static final long serialVersionUID = 2056388626718751512L;
/**
* 自然人id[用户信息,前端开发不用关注]
*/
private Long personId;
/**
* 消息类型
* @see MsgTypeEnum#GENERAL_MESSAGE : 普通消息
* @see MsgTypeEnum#PENDING_MESSAGE : 待办消息
*/
private MsgTypeEnum msgType;
/**
* 路由类型,code与枚举之间的映射如下:
* WEB: "web"
* MINI_PROGRAM: "mini_program"
* IOS: "ios"
* ANDROID: "android"
* WEBVIEW: "webview"
* WECHAT_MINI_PROGRAM: "wechat mini-program"
*/
private String routeType;
/**
* 模块名称
*/
private String moduleName;
/**
* 消息状态列表
* 1. 普通消息
* * 未读: [HAS_BEEN_SENT, RECEIVED]
* * 已读: [HAVE_READ]
* 2. 待办消息
* * 未读: [HAS_BEEN_SENT, RECEIVED]
* * 已处理: [COMPLETE]
*/
private List<MsgStateEnum> states;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,38 @@
package cn.axzo.msg.center.api.request;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @description
* 将个人按模块分组的所有未读消息改为已读
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Setter
@Getter
public class MessageReadAllReq implements Serializable {
private static final long serialVersionUID = 1507456905431377437L;
/**
* 自然人id[用户信息,前端开发不用关注]
*/
@NotNull(message = "personId is required")
private Long personId;
/**
* 模块id
*/
private String moduleName;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,34 @@
package cn.axzo.msg.center.api.request;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @description
* 个人消息按消息类型统计的请求入参数据模型
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Setter
@Getter
public class MessageStatisticReq implements Serializable {
private static final long serialVersionUID = -542167707059736842L;
/**
* 自然人id[用户信息,前端开发不用关注]
*/
@NotNull(message = "personId is required")
private Long personId;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,88 @@
package cn.axzo.msg.center.api.response;
import cn.axzo.msg.center.api.enums.MsgRecordTerminalTypeEnum;
import cn.axzo.msg.center.api.enums.MsgStateEnum;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* @description
* 消息相关API接口定义
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Setter
@Getter
public class MessageDetailRes implements Serializable {
private static final long serialVersionUID = 5633067221907248558L;
/**
* 消息Id
*/
private Long msgId;
/**
* 消息标题
*/
private String msgTitle;
/**
* 消息内容
*/
private String content;
/**
* 模块名称
*/
private String moduleName;
/**
* 模块图标
*/
private String moduleIcon;
/**
* 消息所属标识类型 PROJECT:项目 ENT:企业
*/
private MsgRecordTerminalTypeEnum terminalType;
/**
* 项目Id/企业Id 用于跳转
*/
private Long terminalId;
/**
* 项目名称/企业名称 有则展示
*/
private String terminalName;
/**
* 普通消息状态 1. HAS_BEEN_SENT: 未读 2. HAVE_READ: 已读
* <p>
* 待办消息状态 1. HAS_BEEN_SENT: 待处理 2. COMPLETE: 已完成
*/
private MsgStateEnum state;
/**
* 消息时间戳
*/
private Long msgTimestamp;
/**
* 路由地址
*/
private String routeUrl;
/**
* 路由类型: (0:null, 1:uniapp, 2:native, 3:H5 4:webCms)
*/
private Integer routeType;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,45 @@
package cn.axzo.msg.center.api.response;
import cn.axzo.msg.center.api.enums.BizTypeEnum;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* @description
* 消息模板数据模型
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Setter
@Getter
public class MessageModuleBriefRes implements Serializable {
private static final long serialVersionUID = 1669846774115763711L;
/**
* 模块id
*/
private Long id;
/**
* 模块名称
*/
private String name;
/**
* 模块图标
*/
private String icon;
/**
* 模块所属业务类型
*/
private BizTypeEnum bizType;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,52 @@
package cn.axzo.msg.center.api.response;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* @description
* 个人消息按模块分组统计的响应数据模型
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Setter
@Getter
public class MessageModuleStatisticRes implements Serializable {
private static final long serialVersionUID = -1192617834046504672L;
/**
* 消息模块信息
*/
private MessageModuleBriefRes module;
/**
* 消息所属标识名称 有则展示
*/
private String terminalName;
/**
* 消息标题
*/
private String title;
/**
* 消息内容
*/
private String content;
/**
* 消息未读OR待办未处理的个数
*/
private Integer count;
/**
* 消息时间戳
*/
private Long createTimestamp;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,40 @@
package cn.axzo.msg.center.api.response;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
/**
* @description
* 个人消息按消息类型统计的请求出参数据模型
*
* @author cold_blade
* @date 2023/9/13
* @version 1.0
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class MessageStatisticRes implements Serializable {
private static final long serialVersionUID = 5053786716345221587L;
/**
* 普通消息未读数量
*/
private Integer generalMsgUnReadCnt;
/**
* 待办消息未处理数量
*/
private Integer pendingMsgUnCompleteCnt;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,60 @@
package cn.axzo.msg.center.domain.dto;
import cn.axzo.basics.common.page.PageRequest;
import cn.axzo.msg.center.api.enums.MsgStateEnum;
import cn.axzo.msg.center.api.enums.MsgTypeEnum;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import java.util.Collection;
import java.util.List;
/**
* @description
* 消息分页查询入参数据模型
*
* @author cold_blade
* @date 2023/9/14
* @version 1.0
*/
@Setter
@Getter
public class MessagePageQueryDTO extends PageRequest {
/**
* 自然人id[用户信息,前端开发不用关注]
*/
private Long personId;
/**
* 消息类型
* @see MsgTypeEnum#GENERAL_MESSAGE : 普通消息
* @see MsgTypeEnum#PENDING_MESSAGE : 待办消息
*/
private MsgTypeEnum msgType;
/**
* 路由类型,code与枚举之间的映射如下:
* WEB: "web"
* MINI_PROGRAM: "mini_program"
* IOS: "ios"
* ANDROID: "android"
* WEBVIEW: "webview"
* WECHAT_MINI_PROGRAM: "wechat mini-program"
*/
private String routeType;
/**
* 模块id集合
*/
private Collection<Long> moduleIds;
/**
* 消息状态列表
*/
private List<MsgStateEnum> states;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,38 @@
package cn.axzo.msg.center.domain.dto;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
/**
* @description xxx
* @author cold_blade
* @date 2023/9/15
* @version 1.0
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class MessageRouterDTO implements Serializable {
private static final long serialVersionUID = -4259721279188990067L;
/**
* 路由地址
*/
private String url;
/**
* 路由类型
*/
private Integer type;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -10,6 +10,11 @@ import lombok.Data;
@Data
public class MsgModuleDTO {
/**
* 消息id
*/
private Long msgId;
/**
* 角色类型
*/

View File

@ -2,12 +2,17 @@ package cn.axzo.msg.center.notices.service.impl;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.msg.center.api.MNSNoticesApi;
import cn.axzo.msg.center.api.request.*;
import cn.axzo.msg.center.api.request.MnsCodeStatusReq;
import cn.axzo.msg.center.api.request.MnsCreateTemplateRequestReq;
import cn.axzo.msg.center.api.request.MnsQueryTemplateReq;
import cn.axzo.msg.center.api.request.MnsSendCodeV2Req;
import cn.axzo.msg.center.api.request.SendMessageRequestDto;
import cn.axzo.msg.center.api.response.MnsCodeStatusRes;
import cn.axzo.msg.center.api.response.MnsQueryTemplateRes;
import cn.axzo.msg.center.api.response.MnsSendCodeRes;
import cn.axzo.msg.center.api.response.Page;
import cn.axzo.msg.center.common.utils.BeanConvertUtils;
import cn.axzo.msg.center.notices.common.enums.ReturnCodeEnum;
import cn.axzo.msg.center.notices.manager.api.dto.request.MnsRequestDto;
import cn.axzo.msg.center.notices.manager.api.dto.request.plat.CreateTemplateRequestDto;
import cn.axzo.msg.center.notices.manager.api.dto.request.plat.QueryTemplateRequestDto;
@ -38,6 +43,8 @@ import java.util.regex.Pattern;
@RestController
public class MNSNoticesApiImpl implements MNSNoticesApi {
private static final String LOG_PREFIX = "[MNSNoticesApi]";
@Resource
private SmsService smsService;
@Resource
@ -56,8 +63,15 @@ public class MNSNoticesApiImpl implements MNSNoticesApi {
MnsRequestDto mnsRequestDto=new MnsRequestDto();
BeanUtils.copyProperties(request, mnsRequestDto);
log.info("request value={},mnsRequestDto value={}", JSONUtil.toJsonStr(request),JSONUtil.toJsonStr(mnsRequestDto));
messageService.sendMessage(mnsRequestDto);
return CommonResponse.success();
try {
messageService.sendMessage(mnsRequestDto);
return CommonResponse.success();
} catch (Exception e) {
log.warn("{}#sendMessage broke out some exception", LOG_PREFIX, e);
Integer errCode = e instanceof ServiceException ? ((ServiceException)e).getErrorCode() :
ReturnCodeEnum.SYSTEM_ERROR.getCode();
return CommonResponse.error(errCode, e.getMessage());
}
}
@Override
@ -80,10 +94,17 @@ public class MNSNoticesApiImpl implements MNSNoticesApi {
public CommonResponse<MnsCodeStatusRes> getPhoneCodeStatus(@RequestBody @Valid MnsCodeStatusReq req) {
CodeStatusReq request=new CodeStatusReq();
BeanUtils.copyProperties(req,request);
CodeStatusRes phoneCodeStatus = smsService.getPhoneCodeStatus(request);
MnsCodeStatusRes result=new MnsCodeStatusRes();
BeanUtils.copyProperties(phoneCodeStatus,result);
return CommonResponse.success(result);
try {
CodeStatusRes phoneCodeStatus = smsService.getPhoneCodeStatus(request);
MnsCodeStatusRes result=new MnsCodeStatusRes();
BeanUtils.copyProperties(phoneCodeStatus,result);
return CommonResponse.success(result);
} catch (Exception e) {
log.warn("{}#getPhoneCodeStatus broke out some exception", LOG_PREFIX, e);
Integer errCode = e instanceof ServiceException ? ((ServiceException)e).getErrorCode() :
ReturnCodeEnum.SYSTEM_ERROR.getCode();
return CommonResponse.error(errCode, e.getMessage());
}
}
@Override