Bläddra i källkod

Merge remote-tracking branch 'origin/package' into package

zhangxianyu 1 år sedan
förälder
incheckning
b5f2917a4e
12 ändrade filer med 487 tillägg och 10 borttagningar
  1. 1 1
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/ManageApplication.java
  2. 29 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/enums/CpSendRoleResultEnum.java
  3. 24 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/CpSendMsgResultDTO.java
  4. 24 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/ICpSendMsgLogService.java
  5. 12 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/ICpSendMsgResultService.java
  6. 50 9
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/CpCallServiceImpl.java
  7. 173 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/CpSendMsgLogServiceImpl.java
  8. 18 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/CpSendMsgResultServiceImpl.java
  9. 66 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/CpSendMsgLog.java
  10. 66 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/CpSendMsgResult.java
  11. 12 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/CpSendMsgLogMapper.java
  12. 12 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/CpSendMsgResultMapper.java

+ 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服务启动成功 <解决客服系统小程序消息推送的问题 ( ´・・)ノ(._.`) \n" +
+        System.out.println("赞象Manage服务启动成功 <CP推送消息代码提交 ( ´・・)ノ(._.`) \n" +
                 "___  ___  ___   _   _   ___  _____  _____ \n" +
                 "|  \\/  | / _ \\ | \\ | | / _ \\|  __ \\|  ___|\n" +
                 "| .  . |/ /_\\ \\|  \\| |/ /_\\ \\ |  \\/| |__  \n" +

+ 29 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/enums/CpSendRoleResultEnum.java

@@ -0,0 +1,29 @@
+package com.zanxiang.game.module.manage.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : 角色发送结果
+ */
+@Getter
+@AllArgsConstructor
+public enum CpSendRoleResultEnum {
+
+    /**
+     * 成功
+     */
+    CP_SEND_ROLE_RESULT_SUCCESS("CP_SEND_ROLE_RESULT_SUCCESS"),
+
+    /**
+     * 失败
+     */
+    CP_SEND_ROLE_RESULT_FAIL("CP_SEND_ROLE_RESULT_FAIL");
+
+    /**
+     * 状态
+     */
+    private String value;
+}

+ 24 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/CpSendMsgResultDTO.java

@@ -0,0 +1,24 @@
+package com.zanxiang.game.module.manage.pojo.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : CP发送消息结果
+ */
+@Data
+public class CpSendMsgResultDTO {
+
+    /**
+     * 成功人数
+     */
+    private Long sucessCount;
+
+    /**
+     * 失败列表
+     */
+    private List<String> failList;
+}

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

@@ -0,0 +1,24 @@
+package com.zanxiang.game.module.manage.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgLog;
+
+import java.util.List;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : CP消息发送记录
+ */
+public interface ICpSendMsgLogService extends IService<CpSendMsgLog> {
+
+    /**
+     * CP发送消息
+     *
+     * @param taskId     : 任务id
+     * @param gameId     : 游戏od
+     * @param text       : 文本内容
+     * @param roleIdList : 角色列表
+     */
+    void cpSendMsg(Long taskId, Long gameId, String text, List<String> roleIdList);
+}

+ 12 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/ICpSendMsgResultService.java

@@ -0,0 +1,12 @@
+package com.zanxiang.game.module.manage.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgResult;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description :
+ */
+public interface ICpSendMsgResultService extends IService<CpSendMsgResult> {
+}

+ 50 - 9
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/CpCallServiceImpl.java

@@ -1,6 +1,8 @@
 package com.zanxiang.game.module.manage.service.impl;
 
+import com.zanxiang.game.module.manage.pojo.dto.CpSendMsgResultDTO;
 import com.zanxiang.module.util.JsonUtil;
+import com.zanxiang.module.util.exception.BaseException;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
@@ -8,15 +10,12 @@ import org.springframework.web.client.RestTemplate;
 
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * @author : lingfeng
  * @time : 2024-02-22
- * @description : CP接口交互
+ * @description : CP接口交互 demo类, 测试完成要删除
  */
 public class CpCallServiceImpl {
 
@@ -26,9 +25,51 @@ public class CpCallServiceImpl {
     private static final String SIGN_MD5 = "MD5";
 
 //    public static void main(String[] args) throws Exception {
-//        test();
+//
+//        String text = "尊敬的尊享玩家“角色名”:\n" +
+//                "叮,尊享管家小诗正在微信上等待与您的见面,根据您的游戏角色成长,小诗特意为您定制一份战力快速升级的攻略和几个尊享限定礼包,助您快速提升~\n" +
+//                "您要尽快通过游戏内“联系客服”按钮与我联系,时间有限,请您尽快与我联系哦。\n" +
+//                "联系时请您带上此页面截图,同时请您保密勿将此内容分享给其他玩家,可能会导致尊享限定礼包被冒领哦!";
+////        test();
+//        CpSendMsgResultDTO result = cpSendMsgApi("testMsgId2", "668", Collections.singletonList("821112073166082222"), text);
+//        System.out.println("11111111" + JsonUtil.toString(result));
 //    }
 
+    public static CpSendMsgResultDTO cpSendMsgApi(String msgId, String serverId, List<String> roleIdList, String text) throws Exception {
+        long time = System.currentTimeMillis() / 1000;
+        Map<String, Object> param = new HashMap<>(8);
+        param.put("msgId", msgId);
+        param.put("strRan", msgId);
+        param.put("time", time);
+        param.put("sign", MD5("key=" + "355b7f07125c1ef71cfd10166e0b90aa" + "&msgId=" + msgId + "&strRan=" + msgId + "&time=" + time));
+        param.put("pushType", 1);
+        param.put("serverid", serverId);
+        param.put("roleIds", roleIdList);
+        //图片地址弄一张最小的, CP方不会用, 有默认底图
+        List<String> imgList = Collections.singletonList("https://manage.84game.cn/image/WechatIMG56.jpeg");
+        Map<String, Object> msgContent = new HashMap<>(2);
+        msgContent.put("text", text);
+        msgContent.put("imgs", JsonUtil.toString(imgList));
+        param.put("msgContent", msgContent);
+        //请求头
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        headers.set(HttpHeaders.ACCEPT_CHARSET, "UTF-8");
+        HttpEntity<String> request = new HttpEntity<>(JsonUtil.toString(param), headers);
+        String result;
+        try {
+            RestTemplate restTemplate = new RestTemplate();
+            result = restTemplate.postForObject("https://ht.lttx.t5yx.cn/extapi?action=BgzszhSendTip",
+                    request, String.class);
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
+            throw new BaseException("消息发送失败");
+        }
+        System.out.println("返回结果" + result);
+        CpSendMsgResultDTO cpSendMsgResultDTO = JsonUtil.toObj(result, CpSendMsgResultDTO.class);
+        return cpSendMsgResultDTO;
+    }
+
     public static void test() throws Exception {
         String key = "355b7f07125c1ef71cfd10166e0b90aa";
         RestTemplate restTemplate = new RestTemplate();
@@ -54,10 +95,10 @@ public class CpCallServiceImpl {
         param.put("sign", CpCallServiceImpl.MD5(signStr));
 
 //        param.put("serverid", 226);
-        param.put("serverid", 592);
+        param.put("serverid", 668);
         List<String> roleIds = new ArrayList<>();
 //        roleIds.add("798136461189027272");
-        roleIds.add("815728771283100062");
+        roleIds.add("821112073166082222");
         param.put("roleIds", roleIds);
 
         param.put("pushType", 1);
@@ -71,7 +112,7 @@ public class CpCallServiceImpl {
 
         List<String> imgs = new ArrayList<>();
         //图片地址弄一张最小的, CP方不会用, 有默认底图
-        imgs.add("https://test.84game.cn/1709024863.jpeg");
+        imgs.add("https://manage.84game.cn/image/WechatIMG56.jpeg");
         msgContent.put("imgs", JsonUtil.toString(imgs));
 
         param.put("msgContent", msgContent);

+ 173 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/CpSendMsgLogServiceImpl.java

@@ -0,0 +1,173 @@
+package com.zanxiang.game.module.manage.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+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.service.ICpSendMsgLogService;
+import com.zanxiang.game.module.manage.service.ICpSendMsgResultService;
+import com.zanxiang.game.module.manage.service.IGameUserRoleService;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgLog;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgResult;
+import com.zanxiang.game.module.mybatis.entity.GameUserRole;
+import com.zanxiang.game.module.mybatis.mapper.CpSendMsgLogMapper;
+import com.zanxiang.module.util.JsonUtil;
+import com.zanxiang.module.util.exception.BaseException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.support.TransactionTemplate;
+import org.springframework.web.client.RestTemplate;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : CP消息发送记录
+ */
+@Slf4j
+@Service
+public class CpSendMsgLogServiceImpl extends ServiceImpl<CpSendMsgLogMapper, CpSendMsgLog> implements ICpSendMsgLogService {
+
+    private static final String SIGN_MD5 = "MD5";
+
+    private static final String CP_API_KEY = "355b7f07125c1ef71cfd10166e0b90aa";
+
+    @Autowired
+    private TransactionTemplate transactionTemplate;
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private IGameUserRoleService gameUserRoleService;
+
+    @Autowired
+    private ICpSendMsgResultService cpSendMsgResultService;
+
+    @Override
+    public void cpSendMsg(Long taskId, Long gameId, String text, List<String> roleIdList) {
+        //查询角色区服信息
+        List<GameUserRole> gameUserRoleList = gameUserRoleService.list(new LambdaQueryWrapper<GameUserRole>()
+                .select(GameUserRole::getGameId, GameUserRole::getServerId, GameUserRole::getRoleId)
+                .eq(GameUserRole::getGameId, gameId)
+                .in(GameUserRole::getRoleId, roleIdList));
+        String msgId = UUID.randomUUID().toString().replace("-", "");
+        //保存发送记录
+        CpSendMsgLog cpSendMsgLog = this.transform(taskId, gameId, msgId, gameUserRoleList.size());
+        super.save(cpSendMsgLog);
+        if (CollectionUtils.isEmpty(gameUserRoleList)) {
+            return;
+        }
+        //角色信息按区服分组
+        Map<String, List<GameUserRole>> serverIdRoleMap = gameUserRoleList.stream()
+                .collect(Collectors.groupingBy(GameUserRole::getServerId));
+        serverIdRoleMap.forEach((serverId, roleList) -> {
+            List<String> serverRoleIdList = roleList.stream().map(GameUserRole::getRoleId).collect(Collectors.toList());
+            try {
+                CpSendMsgResultDTO result = this.cpSendMsgApi(msgId, serverId, serverRoleIdList, text);
+                this.resultHandle(cpSendMsgLog, result, serverId, serverRoleIdList);
+            } catch (Exception e) {
+                log.error("CP消息发送API调用异常, serverId : {}, roleList : {}", serverId, roleList);
+            }
+        });
+    }
+
+    private CpSendMsgLog transform(Long taskId, Long gameId, String msgId, Integer roleCount) {
+        return CpSendMsgLog.builder()
+                .msgId(msgId)
+                .taskId(taskId)
+                .gameId(gameId)
+                .roleCount(roleCount)
+                .successCount(0L)
+                .failCount(0L)
+                .createTime(LocalDateTime.now())
+                .build();
+    }
+
+    private void resultHandle(CpSendMsgLog cpSendMsgLog, CpSendMsgResultDTO result, String serverId, List<String> roleList) {
+        //结果列表
+        List<CpSendMsgResult> resultList = new ArrayList<>();
+        roleList.forEach(roleId -> {
+            //状态判断
+            CpSendRoleResultEnum resultEnum = result.getFailList().contains(roleId) ?
+                    CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_FAIL : CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_SUCCESS;
+            resultList.add(this.transform(cpSendMsgLog.getTaskId(), cpSendMsgLog.getMsgId(), resultEnum.getValue(),
+                    cpSendMsgLog.getGameId(), serverId, roleId));
+        });
+        //在同一个事物中进行表更新
+        transactionTemplate.execute(status -> {
+            cpSendMsgResultService.saveBatch(resultList);
+            super.update(new LambdaUpdateWrapper<CpSendMsgLog>()
+                    .setSql("success_count=success_count+" + result.getSucessCount())
+                    .setSql("fail_count=fail_count+" + result.getFailList().size())
+                    .eq(CpSendMsgLog::getMsgId, cpSendMsgLog.getMsgId())
+            );
+            return Boolean.TRUE;
+        });
+    }
+
+    private CpSendMsgResult transform(Long taskId, String msgId, String sendStatus, Long gameId, String serverId, String roleId) {
+        return CpSendMsgResult.builder()
+                .taskId(taskId)
+                .msgId(msgId)
+                .gameId(gameId)
+                .serverId(serverId)
+                .roleId(roleId)
+                .sendStatus(sendStatus)
+                .createTime(LocalDateTime.now())
+                .build();
+    }
+
+    private CpSendMsgResultDTO cpSendMsgApi(String msgId, String serverId, List<String> roleIdList, String text) throws Exception {
+        long time = System.currentTimeMillis() / 1000;
+        Map<String, Object> param = new HashMap<>(8);
+        param.put("msgId", msgId);
+        param.put("strRan", msgId);
+        param.put("time", time);
+        param.put("sign", this.MD5("key=" + CP_API_KEY + "&msgId=" + msgId + "&strRan=" + msgId + "&time=" + time));
+        param.put("pushType", 1);
+        param.put("serverid", serverId);
+        param.put("roleIds", roleIdList);
+        //图片地址弄一张最小的, CP方不会用, 有默认底图
+        List<String> imgList = Collections.singletonList("https://manage.84game.cn/image/WechatIMG56.jpeg");
+        Map<String, Object> msgContent = new HashMap<>(2);
+        msgContent.put("text", text);
+        msgContent.put("imgs", JsonUtil.toString(imgList));
+        param.put("msgContent", msgContent);
+        //请求头
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        headers.set(HttpHeaders.ACCEPT_CHARSET, "UTF-8");
+        HttpEntity<String> request = new HttpEntity<>(JsonUtil.toString(param), headers);
+        String result;
+        try {
+            result = restTemplate.postForObject("https://ht.lttx.t5yx.cn/extapi?action=BgzszhSendTip",
+                    request, String.class);
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
+            throw new BaseException("消息发送失败");
+        }
+        return JsonUtil.toObj(result, CpSendMsgResultDTO.class);
+    }
+
+    private String MD5(String data) throws Exception {
+        java.security.MessageDigest md = MessageDigest.getInstance(SIGN_MD5);
+        byte[] array = md.digest(data.getBytes(StandardCharsets.UTF_8));
+        StringBuilder sb = new StringBuilder();
+        for (byte item : array) {
+            sb.append(Integer.toHexString((item & 0xFF) | 0x100), 1, 3);
+        }
+        return sb.toString();
+    }
+}

+ 18 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/CpSendMsgResultServiceImpl.java

@@ -0,0 +1,18 @@
+package com.zanxiang.game.module.manage.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.module.manage.service.ICpSendMsgResultService;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgResult;
+import com.zanxiang.game.module.mybatis.mapper.CpSendMsgResultMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : CP消息发送结果
+ */
+@Slf4j
+@Service
+public class CpSendMsgResultServiceImpl extends ServiceImpl<CpSendMsgResultMapper, CpSendMsgResult> implements ICpSendMsgResultService {
+}

+ 66 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/CpSendMsgLog.java

@@ -0,0 +1,66 @@
+package com.zanxiang.game.module.mybatis.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : cp发送消息记录
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+@Builder
+@TableName("t_cp_send_msg_log")
+public class CpSendMsgLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 消息id
+     */
+    @TableId(value = "msg_id", type = IdType.INPUT)
+    private String msgId;
+
+    /**
+     * 任务id
+     */
+    private Long taskId;
+
+    /**
+     * 游戏id
+     */
+    private Long gameId;
+
+    /**
+     * 角色执行人数
+     */
+    private Integer roleCount;
+
+    /**
+     * 成功人数
+     */
+    private Long successCount;
+
+    /**
+     * 失败人数
+     */
+    private Long failCount;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+}

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

@@ -0,0 +1,66 @@
+package com.zanxiang.game.module.mybatis.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : cp发送消息结果
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+@Builder
+@TableName("t_cp_send_msg_result")
+public class CpSendMsgResult implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 任务id
+     */
+    private Long taskId;
+
+    /**
+     * 消息id
+     */
+    private String msgId;
+
+    /**
+     * 游戏id
+     */
+    private Long gameId;
+
+    /**
+     * 区服id
+     */
+    private String serverId;
+
+    /**
+     * 角色id
+     */
+    private String roleId;
+
+    /**
+     * 发送状态
+     */
+    private String sendStatus;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+}

+ 12 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/CpSendMsgLogMapper.java

@@ -0,0 +1,12 @@
+package com.zanxiang.game.module.mybatis.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgLog;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : ${description}
+ */
+public interface CpSendMsgLogMapper extends BaseMapper<CpSendMsgLog> {
+}

+ 12 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/CpSendMsgResultMapper.java

@@ -0,0 +1,12 @@
+package com.zanxiang.game.module.mybatis.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgResult;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-03-14
+ * @description : ${description}
+ */
+public interface CpSendMsgResultMapper extends BaseMapper<CpSendMsgResult> {
+}