Pārlūkot izejas kodu

feat : 手动消息推送, 新增补发功能

bilingfeng 10 mēneši atpakaļ
vecāks
revīzija
d0eaa66f69

+ 20 - 0
game-module/game-module-base/src/main/java/com/zanxiang/game/module/base/rpc/ICPSendMsgRpc.java

@@ -15,8 +15,26 @@ import com.zanxiang.module.util.pojo.ResultVO;
  */
 public interface ICPSendMsgRpc {
 
+    /**
+     * 根据任务id重发消息
+     *
+     * @param gameId
+     * @param taskId
+     * @return
+     */
+    ResultVO<Boolean> reSendMsgByTaskId(Long gameId, Long taskId);
+
+    /**
+     * 根据发送结果id重发消息
+     *
+     * @param resultId
+     * @return
+     */
+    ResultVO<Boolean> reSendMsgByResultId(Long resultId);
+
     /**
      * 发送消息
+     *
      * @param sendMsgDto
      * @return
      */
@@ -24,6 +42,7 @@ public interface ICPSendMsgRpc {
 
     /**
      * 获取发送消息任务列表
+     *
      * @param sendMsgTaskParam
      * @return
      */
@@ -31,6 +50,7 @@ public interface ICPSendMsgRpc {
 
     /**
      * 获取发送消息任务结果
+     *
      * @param sendMsgTaskResultParam
      * @return
      */

+ 1 - 1
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/ManageApplication.java

@@ -23,7 +23,7 @@ public class ManageApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(ManageApplication.class, args);
-        System.out.println("赞象Manage服务启动成功 < (生产测试pro・・)ノ(._.`) \n" +
+        System.out.println("赞象Manage服务启动成功 < (手动消息推送, 新增补发功能・・)ノ(._.`) \n" +
                 "___  ___  ___   _   _   ___  _____  _____ \n" +
                 "|  \\/  | / _ \\ | \\ | | / _ \\|  __ \\|  ___|\n" +
                 "| .  . |/ /_\\ \\|  \\| |/ /_\\ \\ |  \\/| |__  \n" +

+ 21 - 8
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/rpc/impl/CpSendMsgRpcImpl.java

@@ -7,31 +7,36 @@ import com.zanxiang.game.module.base.pojo.vo.SendMsgResultVO;
 import com.zanxiang.game.module.base.pojo.vo.SendMsgVO;
 import com.zanxiang.game.module.base.rpc.ICPSendMsgRpc;
 import com.zanxiang.game.module.base.util.PageUtil;
-import com.zanxiang.game.module.manage.service.ICPSendMsgTaskService;
 import com.zanxiang.game.module.manage.service.ICpSendMsgResultService;
+import com.zanxiang.game.module.manage.service.ICpSendMsgTaskService;
 import com.zanxiang.module.util.pojo.ResultVO;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboService;
+import org.springframework.beans.factory.annotation.Autowired;
 
-import javax.annotation.Resource;
-
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : CP消息发送接口
+ */
 @DubboService
 @Slf4j
 public class CpSendMsgRpcImpl implements ICPSendMsgRpc {
 
-    @Resource
-    private ICPSendMsgTaskService cpSendMsgTaskService;
-    @Resource
+    @Autowired
+    private ICpSendMsgTaskService cpSendMsgTaskService;
+
+    @Autowired
     private ICpSendMsgResultService cpSendMsgResultService;
 
     @Override
     public ResultVO<Boolean> sendMsg(SendMsgDTO sendMsgDto) {
-       return cpSendMsgTaskService.sendMsg(sendMsgDto);
+        return cpSendMsgTaskService.sendMsg(sendMsgDto);
     }
 
     @Override
     public PageUtil<SendMsgVO> getSendMsgTaskList(SendMsgTaskParam param) {
-       return cpSendMsgTaskService.getSendMsgTaskList(param);
+        return cpSendMsgTaskService.getSendMsgTaskList(param);
     }
 
     @Override
@@ -39,5 +44,13 @@ public class CpSendMsgRpcImpl implements ICPSendMsgRpc {
         return cpSendMsgResultService.getSendMsgTaskResultList(sendMsgTaskResultParam);
     }
 
+    @Override
+    public ResultVO<Boolean> reSendMsgByTaskId(Long gameId, Long taskId) {
+        return ResultVO.ok(cpSendMsgTaskService.reSendMsgByTaskId(gameId, taskId));
+    }
 
+    @Override
+    public ResultVO<Boolean> reSendMsgByResultId(Long resultId) {
+        return ResultVO.ok(cpSendMsgTaskService.reSendMsgByResultId(resultId));
+    }
 }

+ 10 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/ICpSendMsgLogService.java

@@ -3,6 +3,7 @@ package com.zanxiang.game.module.manage.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.zanxiang.game.module.manage.pojo.dto.CpSendMsgResultDTO;
 import com.zanxiang.game.module.mybatis.entity.CpSendMsgLog;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgResult;
 import com.zanxiang.game.module.mybatis.entity.GameSupper;
 
 import java.util.List;
@@ -14,6 +15,15 @@ import java.util.List;
  */
 public interface ICpSendMsgLogService extends IService<CpSendMsgLog> {
 
+    /**
+     * 消息重发
+     *
+     * @param text              : 文本
+     * @param cpSendMsgLog      : 执行日志
+     * @param sendMsgResultList : 发送结果列表
+     */
+    void reCpSendMsg(String text, CpSendMsgLog cpSendMsgLog, List<CpSendMsgResult> sendMsgResultList);
+
     /**
      * CP发送消息
      *

+ 24 - 7
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/ICPSendMsgTaskService.java → game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/ICpSendMsgTaskService.java

@@ -8,22 +8,39 @@ import com.zanxiang.game.module.base.util.PageUtil;
 import com.zanxiang.game.module.mybatis.entity.CpSendMsgTask;
 import com.zanxiang.module.util.pojo.ResultVO;
 
-public interface ICPSendMsgTaskService extends IService<CpSendMsgTask> {
+public interface ICpSendMsgTaskService extends IService<CpSendMsgTask> {
+
+    /**
+     * 根据任务id重发消息
+     *
+     * @param gameId : 游戏id
+     * @param taskId : 任务id
+     * @return : 返回执行结果
+     */
+    boolean reSendMsgByTaskId(Long gameId, Long taskId);
+
+    /**
+     * 单个执行结果重发
+     *
+     * @param resultId : 结果id
+     * @return : 发送结果
+     */
+    boolean reSendMsgByResultId(Long resultId);
 
     /**
      * 创建消息任务并发送消息
-     * @param sendMsgDto
-     * @return
+     *
+     * @param sendMsgDto : 发送消息参数
+     * @return : 返回发送结果
      */
     ResultVO<Boolean> sendMsg(SendMsgDTO sendMsgDto);
 
     /**
      * 获取消息任务列表
-     * @param param
-     * @return
+     *
+     * @param param : 参数
+     * @return : 返回结果
      */
     PageUtil<SendMsgVO> getSendMsgTaskList(SendMsgTaskParam param);
 
-
-
 }

+ 7 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IGameSupperService.java

@@ -13,6 +13,13 @@ import java.util.List;
  */
 public interface IGameSupperService extends IService<GameSupper> {
 
+    /**
+     * 根据子游戏获取超父游戏信息
+     *
+     * @param gameId : 游戏id
+     * @return : 返回超父游戏
+     */
+    GameSupper getGameSupperByGameId(Long gameId);
 
     /**
      * 获取超父游戏

+ 0 - 97
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/CPSendMsgTaskServiceImpl.java

@@ -1,97 +0,0 @@
-package com.zanxiang.game.module.manage.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.zanxiang.game.module.base.pojo.dto.SendMsgDTO;
-import com.zanxiang.game.module.base.pojo.params.SendMsgTaskParam;
-import com.zanxiang.game.module.base.pojo.vo.SendMsgVO;
-import com.zanxiang.game.module.base.util.PageUtil;
-import com.zanxiang.game.module.manage.enums.CpSendMsgTaskStatusEnum;
-import com.zanxiang.game.module.manage.enums.CpSendMsgTaskTypeEnum;
-import com.zanxiang.game.module.manage.service.ICPSendMsgTaskService;
-import com.zanxiang.game.module.manage.service.ICpSendMsgLogService;
-import com.zanxiang.game.module.mybatis.entity.CpSendMsgTask;
-import com.zanxiang.game.module.mybatis.mapper.CpSendMsgTaskMapper;
-import com.zanxiang.module.util.bean.BeanUtil;
-import com.zanxiang.module.util.pojo.ResultVO;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-@Service
-@Slf4j
-public class CPSendMsgTaskServiceImpl extends ServiceImpl<CpSendMsgTaskMapper, CpSendMsgTask> implements ICPSendMsgTaskService {
-
-    @Lazy
-    @Resource
-    private ICPSendMsgTaskService sendMsgTaskService;
-
-    @Resource
-    private ICpSendMsgLogService cpSendMsgLogService;
-
-    @Override
-    public ResultVO<Boolean> sendMsg(SendMsgDTO sendMsgDto) {
-        try {
-            //创建任务
-            CpSendMsgTask cpSendMsgTask = createSendMsgTask(sendMsgDto);
-            //保存任务
-            sendMsgTaskService.save(cpSendMsgTask);
-            //发消息
-            cpSendMsgLogService.cpSendMsg(cpSendMsgTask.getId(), sendMsgDto.getGameId(), sendMsgDto.getMsg(), sendMsgDto.getRoles());
-            //成功后修改状态
-            cpSendMsgTask.setStatus(CpSendMsgTaskStatusEnum.SUCCESS_SEND.getValue());
-            sendMsgTaskService.updateById(cpSendMsgTask);
-            log.info("发送消息成功");
-            return ResultVO.ok();
-        } catch (Exception e) {
-            log.error("发送消息异常, sendMsgDto : {}, e : {}", sendMsgDto, e.getMessage());
-            return ResultVO.fail("发送消息异常");
-        }
-    }
-
-    @Override
-    public PageUtil<SendMsgVO> getSendMsgTaskList(SendMsgTaskParam param) {
-        Page<CpSendMsgTask> page = sendMsgTaskService.page(new Page<>(param.getPageNum(), param.getPageSize()),
-                new LambdaQueryWrapper<CpSendMsgTask>()
-                        .eq(param.getGameId() != null, CpSendMsgTask::getGameId, param.getGameId())
-                        .eq(StringUtils.isNotEmpty(param.getTaskStatus()), CpSendMsgTask::getStatus, param.getTaskStatus())
-                        .orderByDesc(CpSendMsgTask::getCreateTime));
-        List<CpSendMsgTask> cpSendMsgTasks = page.getRecords();
-        List<SendMsgVO> sendMsgVos = toVo(cpSendMsgTasks);
-        return new PageUtil<>(sendMsgVos, page.getTotal(), param.getPageSize(), param.getPageNum(), 0);
-    }
-
-    private List<SendMsgVO> toVo(List<CpSendMsgTask> cpSendMsgTasks) {
-        if (Objects.isNull(cpSendMsgTasks) || cpSendMsgTasks.isEmpty()) {
-            return null;
-        }
-        return cpSendMsgTasks.stream()
-                .map(task -> BeanUtil.copy(task, SendMsgVO.class))
-                .collect(Collectors.toList());
-    }
-
-    private CpSendMsgTask createSendMsgTask(SendMsgDTO dto) {
-        CpSendMsgTask cpSendMsgTask = new CpSendMsgTask();
-        cpSendMsgTask.setMsg(dto.getMsg());
-        cpSendMsgTask.setRoleIdCount((long) dto.getRoles().size());
-        cpSendMsgTask.setTaskName(dto.getTaskName());
-        cpSendMsgTask.setTaskCondition(dto.getSendConditionJson());
-        cpSendMsgTask.setGameId(dto.getGameId());
-        //任务类型
-        cpSendMsgTask.setType(CpSendMsgTaskTypeEnum.IMMEDIATE_TASK.getValue());
-        //任务状态
-        cpSendMsgTask.setStatus(CpSendMsgTaskStatusEnum.WAIT_SEND.getValue());
-        cpSendMsgTask.setCreateBy(dto.getCreateBy());
-        cpSendMsgTask.setCreateTime(LocalDateTime.now());
-        cpSendMsgTask.setUpdateTime(LocalDateTime.now());
-        return cpSendMsgTask;
-    }
-}

+ 51 - 12
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/CpSendMsgLogServiceImpl.java

@@ -6,8 +6,10 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zanxiang.game.module.manage.enums.CpSendRoleResultEnum;
 import com.zanxiang.game.module.manage.pojo.dto.CpSendMsgResultDTO;
-import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
-import com.zanxiang.game.module.manage.service.*;
+import com.zanxiang.game.module.manage.service.ICpSendMsgLogService;
+import com.zanxiang.game.module.manage.service.ICpSendMsgResultService;
+import com.zanxiang.game.module.manage.service.IGameSupperService;
+import com.zanxiang.game.module.manage.service.IGameUserRoleService;
 import com.zanxiang.game.module.manage.utils.SignUtil;
 import com.zanxiang.game.module.mybatis.entity.CpSendMsgLog;
 import com.zanxiang.game.module.mybatis.entity.CpSendMsgResult;
@@ -45,9 +47,6 @@ public class CpSendMsgLogServiceImpl extends ServiceImpl<CpSendMsgLogMapper, CpS
     @Autowired
     private RestTemplate restTemplate;
 
-    @Autowired
-    private IGameService gameService;
-
     @Autowired
     private IGameSupperService gameSupperService;
 
@@ -57,6 +56,51 @@ public class CpSendMsgLogServiceImpl extends ServiceImpl<CpSendMsgLogMapper, CpS
     @Autowired
     private ICpSendMsgResultService cpSendMsgResultService;
 
+    @Override
+    public void reCpSendMsg(String text, CpSendMsgLog cpSendMsgLog, List<CpSendMsgResult> sendResultList) {
+        //查询超父游戏信息
+        GameSupper gameSupper = gameSupperService.getGameSupperByGameId(cpSendMsgLog.getGameId());
+        if (gameSupper == null || Strings.isBlank(gameSupper.getCpSendMsgUrl()) || Strings.isBlank(gameSupper.getCpSendMsgKey())) {
+            log.error("CP发送消息补发, 超父游戏信息不全! cpSendMsgLog : {}, resultList : {}",
+                    JsonUtil.toString(cpSendMsgLog), JsonUtil.toString(sendResultList));
+            return;
+        }
+        //角色信息按区服分组
+        Map<String, List<CpSendMsgResult>> resultMap = sendResultList.stream()
+                .collect(Collectors.groupingBy(CpSendMsgResult::getServerId));
+        resultMap.forEach((serverId, cpSendMsgResultList) -> {
+            List<String> serverRoleIdList = cpSendMsgResultList.stream().map(CpSendMsgResult::getRoleId).collect(Collectors.toList());
+            try {
+                CpSendMsgResultDTO result = this.cpSendMsgApi(gameSupper, cpSendMsgLog.getMsgId(), serverId, text, serverRoleIdList);
+                this.reResultHandle(cpSendMsgLog, result, sendResultList);
+            } catch (Exception e) {
+                log.error("CP消息发送API调用异常, cpSendMsgLog : {}, sendMsgResultList : {}",
+                        JsonUtil.toString(cpSendMsgLog), JsonUtil.toString(sendResultList));
+            }
+        });
+    }
+
+    private void reResultHandle(CpSendMsgLog cpSendMsgLog, CpSendMsgResultDTO result, List<CpSendMsgResult> sendMsgResultList) {
+        //循环处理结果
+        sendMsgResultList.forEach(sendMsgResult -> {
+            //状态判断
+            CpSendRoleResultEnum resultEnum = result.getFailList().contains(sendMsgResult.getRoleId()) ?
+                    CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_FAIL : CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_SUCCESS;
+            sendMsgResult.setSendStatus(resultEnum.getValue());
+            sendMsgResult.setUpdateTime(LocalDateTime.now());
+        });
+        //在同一个事物中进行表更新
+        transactionTemplate.execute(status -> {
+            cpSendMsgResultService.updateBatchById(sendMsgResultList);
+            super.update(new LambdaUpdateWrapper<CpSendMsgLog>()
+                    .setSql("success_count=success_count+" + result.getSucessCount())
+                    .setSql("fail_count=fail_count-" + result.getSucessCount())
+                    .eq(CpSendMsgLog::getMsgId, cpSendMsgLog.getMsgId())
+            );
+            return Boolean.TRUE;
+        });
+    }
+
     @Override
     public void cpSendMsg(Long taskId, Long gameId, String text, List<String> roleIdList) {
         //查询角色区服信息
@@ -73,13 +117,8 @@ public class CpSendMsgLogServiceImpl extends ServiceImpl<CpSendMsgLogMapper, CpS
                     taskId, gameId, JsonUtil.toString(roleIdList));
             return;
         }
-        GameDTO gameDTO = gameService.getById(gameId);
-        if (gameDTO == null) {
-            log.error("CP发送消息参数错误, 游戏信息不存在! taskId : {}, gameId : {}, roleIdList : {}",
-                    taskId, gameId, JsonUtil.toString(roleIdList));
-            return;
-        }
-        GameSupper gameSupper = gameSupperService.getById(gameDTO.getSuperGameId());
+        //查询超父游戏信息
+        GameSupper gameSupper = gameSupperService.getGameSupperByGameId(gameId);
         if (gameSupper == null || Strings.isBlank(gameSupper.getCpSendMsgUrl()) || Strings.isBlank(gameSupper.getCpSendMsgKey())) {
             log.error("CP发送消息参数错误, 超父游戏信息不全! taskId : {}, gameId : {}, roleIdList : {}, gameSupper : {}",
                     taskId, gameId, JsonUtil.toString(roleIdList), JsonUtil.toString(gameSupper));

+ 167 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/CpSendMsgTaskServiceImpl.java

@@ -0,0 +1,167 @@
+package com.zanxiang.game.module.manage.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.module.base.pojo.dto.SendMsgDTO;
+import com.zanxiang.game.module.base.pojo.params.SendMsgTaskParam;
+import com.zanxiang.game.module.base.pojo.vo.SendMsgVO;
+import com.zanxiang.game.module.base.util.PageUtil;
+import com.zanxiang.game.module.manage.enums.CpSendMsgTaskStatusEnum;
+import com.zanxiang.game.module.manage.enums.CpSendMsgTaskTypeEnum;
+import com.zanxiang.game.module.manage.enums.CpSendRoleResultEnum;
+import com.zanxiang.game.module.manage.service.ICpSendMsgLogService;
+import com.zanxiang.game.module.manage.service.ICpSendMsgResultService;
+import com.zanxiang.game.module.manage.service.ICpSendMsgTaskService;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgLog;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgResult;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgTask;
+import com.zanxiang.game.module.mybatis.mapper.CpSendMsgTaskMapper;
+import com.zanxiang.module.util.bean.BeanUtil;
+import com.zanxiang.module.util.exception.BaseException;
+import com.zanxiang.module.util.pojo.ResultVO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : CP消息发送任务
+ */
+@Service
+@Slf4j
+public class CpSendMsgTaskServiceImpl extends ServiceImpl<CpSendMsgTaskMapper, CpSendMsgTask> implements ICpSendMsgTaskService {
+
+    @Autowired
+    private ICpSendMsgLogService cpSendMsgLogService;
+
+    @Autowired
+    private ICpSendMsgResultService cpSendMsgResultService;
+
+    @Override
+    public boolean reSendMsgByTaskId(Long gameId, Long taskId) {
+        //查询任务
+        CpSendMsgTask cpSendMsgTask = super.getById(taskId);
+        if (cpSendMsgTask == null) {
+            log.error("参数错误, 任务id不存在! gameId : {}, taskId : {}", gameId, taskId);
+            throw new BaseException("参数错误, 任务id不存在");
+        }
+        //查询执行日志
+        List<CpSendMsgLog> sendMsgLogList = cpSendMsgLogService.list(new LambdaQueryWrapper<CpSendMsgLog>()
+                .eq(CpSendMsgLog::getGameId, gameId)
+                .eq(CpSendMsgLog::getTaskId, taskId));
+        if (CollectionUtils.isEmpty(sendMsgLogList)) {
+            log.error("执行日志log为空! gameId : {}, taskId : {}", gameId, taskId);
+            return Boolean.FALSE;
+        }
+        //查询日志执行结果
+        sendMsgLogList.forEach(cpSendMsgLog -> {
+            List<CpSendMsgResult> sendMsgResultList = cpSendMsgResultService.list(new LambdaQueryWrapper<CpSendMsgResult>()
+                    .eq(CpSendMsgResult::getGameId, cpSendMsgLog.getGameId())
+                    .eq(CpSendMsgResult::getTaskId, cpSendMsgLog.getTaskId())
+                    .eq(CpSendMsgResult::getMsgId, cpSendMsgLog.getMsgId())
+                    .eq(CpSendMsgResult::getSendStatus, CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_FAIL.getValue())
+            );
+            if (CollectionUtils.isEmpty(sendMsgResultList)) {
+                return;
+            }
+            cpSendMsgLogService.reCpSendMsg(cpSendMsgTask.getMsg(), cpSendMsgLog, sendMsgResultList);
+        });
+        return Boolean.TRUE;
+    }
+
+    @Override
+    public boolean reSendMsgByResultId(Long resultId) {
+        //查询执行结果
+        CpSendMsgResult sendMsgResult = cpSendMsgResultService.getById(resultId);
+        if (sendMsgResult == null) {
+            log.error("参数错误, 执行结果id不存在! id : {}", resultId);
+            throw new BaseException("参数错误, 执行结果id不存在!");
+        }
+        if (Objects.equals(sendMsgResult.getSendStatus(), CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_SUCCESS.getValue())) {
+            log.error("该发送结果已成功, 禁止重发! id : {}", resultId);
+            throw new BaseException("该发送结果已成功, 禁止重发!");
+        }
+        //查询任务
+        CpSendMsgTask cpSendMsgTask = super.getById(sendMsgResult.getTaskId());
+        if (cpSendMsgTask == null) {
+            log.error("参数错误, 任务id不存在! taskId : {}", sendMsgResult.getTaskId());
+            throw new BaseException("参数错误, 任务id不存在");
+        }
+        //查询执行记录
+        CpSendMsgLog cpSendMsgLog = cpSendMsgLogService.getById(sendMsgResult.getMsgId());
+        if (cpSendMsgLog == null) {
+            log.error("执行日志log为空! gameId : {}, taskId : {}", sendMsgResult.getGameId(), sendMsgResult.getTaskId());
+            throw new BaseException("执行日志log为空!");
+        }
+        cpSendMsgLogService.reCpSendMsg(cpSendMsgTask.getMsg(), cpSendMsgLog, Collections.singletonList(sendMsgResult));
+        return Boolean.TRUE;
+    }
+
+    @Override
+    public ResultVO<Boolean> sendMsg(SendMsgDTO sendMsgDto) {
+        try {
+            //创建任务
+            CpSendMsgTask cpSendMsgTask = createSendMsgTask(sendMsgDto);
+            //保存任务
+            super.save(cpSendMsgTask);
+            //发消息
+            cpSendMsgLogService.cpSendMsg(cpSendMsgTask.getId(), sendMsgDto.getGameId(), sendMsgDto.getMsg(), sendMsgDto.getRoles());
+            //成功后修改状态
+            cpSendMsgTask.setStatus(CpSendMsgTaskStatusEnum.SUCCESS_SEND.getValue());
+            super.updateById(cpSendMsgTask);
+            log.info("发送消息成功");
+            return ResultVO.ok();
+        } catch (Exception e) {
+            log.error("发送消息异常, sendMsgDto : {}, e : {}", sendMsgDto, e.getMessage());
+            return ResultVO.fail("发送消息异常");
+        }
+    }
+
+    @Override
+    public PageUtil<SendMsgVO> getSendMsgTaskList(SendMsgTaskParam param) {
+        Page<CpSendMsgTask> page = super.page(new Page<>(param.getPageNum(), param.getPageSize()),
+                new LambdaQueryWrapper<CpSendMsgTask>()
+                        .eq(param.getGameId() != null, CpSendMsgTask::getGameId, param.getGameId())
+                        .eq(StringUtils.isNotEmpty(param.getTaskStatus()), CpSendMsgTask::getStatus, param.getTaskStatus())
+                        .orderByDesc(CpSendMsgTask::getCreateTime));
+        List<CpSendMsgTask> cpSendMsgTasks = page.getRecords();
+        List<SendMsgVO> sendMsgVos = toVo(cpSendMsgTasks);
+        return new PageUtil<>(sendMsgVos, page.getTotal(), param.getPageSize(), param.getPageNum(), 0);
+    }
+
+    private List<SendMsgVO> toVo(List<CpSendMsgTask> cpSendMsgTasks) {
+        if (Objects.isNull(cpSendMsgTasks) || cpSendMsgTasks.isEmpty()) {
+            return null;
+        }
+        return cpSendMsgTasks.stream()
+                .map(task -> BeanUtil.copy(task, SendMsgVO.class))
+                .collect(Collectors.toList());
+    }
+
+    private CpSendMsgTask createSendMsgTask(SendMsgDTO dto) {
+        CpSendMsgTask cpSendMsgTask = new CpSendMsgTask();
+        cpSendMsgTask.setMsg(dto.getMsg());
+        cpSendMsgTask.setRoleIdCount((long) dto.getRoles().size());
+        cpSendMsgTask.setTaskName(dto.getTaskName());
+        cpSendMsgTask.setTaskCondition(dto.getSendConditionJson());
+        cpSendMsgTask.setGameId(dto.getGameId());
+        //任务类型
+        cpSendMsgTask.setType(CpSendMsgTaskTypeEnum.IMMEDIATE_TASK.getValue());
+        //任务状态
+        cpSendMsgTask.setStatus(CpSendMsgTaskStatusEnum.WAIT_SEND.getValue());
+        cpSendMsgTask.setCreateBy(dto.getCreateBy());
+        cpSendMsgTask.setCreateTime(LocalDateTime.now());
+        cpSendMsgTask.setUpdateTime(LocalDateTime.now());
+        return cpSendMsgTask;
+    }
+}

+ 16 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/GameSupperServiceImpl.java

@@ -1,12 +1,15 @@
 package com.zanxiang.game.module.manage.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
 import com.zanxiang.game.module.manage.pojo.vo.GameSupperVO;
+import com.zanxiang.game.module.manage.service.IGameService;
 import com.zanxiang.game.module.manage.service.IGameSupperService;
 import com.zanxiang.game.module.mybatis.entity.GameSupper;
 import com.zanxiang.game.module.mybatis.mapper.GameSupperMapper;
 import com.zanxiang.module.util.bean.BeanUtil;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -21,6 +24,19 @@ import java.util.stream.Collectors;
 @Service
 public class GameSupperServiceImpl extends ServiceImpl<GameSupperMapper, GameSupper> implements IGameSupperService {
 
+    @Autowired
+    private IGameService gameService;
+
+    @Override
+    public GameSupper getGameSupperByGameId(Long gameId) {
+        GameDTO gameDTO = gameService.getById(gameId);
+        if (gameDTO == null) {
+            log.error("查询超父游戏, 获取子游戏信息为空! gameId : {}", gameId);
+            return null;
+        }
+        return super.getById(gameDTO.getSuperGameId());
+    }
+
     @Override
     public List<GameSupperVO> getGameSupperList() {
         return super.list().stream()

+ 5 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/CpSendMsgResult.java

@@ -63,4 +63,9 @@ public class CpSendMsgResult implements Serializable {
      * 创建时间
      */
     private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
 }