Selaa lähdekoodia

Merge branch 'package' of GameCenter/game-center into dev

zhimo 1 vuosi sitten
vanhempi
commit
7e1644a93b
40 muutettua tiedostoa jossa 3526 lisäystä ja 138 poistoa
  1. 1 3
      game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/utils/BackPolicyUtil.java
  2. 2 18
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/PlayerDataController.java
  3. 49 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/RoleManageController.java
  4. 152 2
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerDataListDTO.java
  5. 0 28
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerDataListTotalDTO.java
  6. 160 4
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerRoleDataListDTO.java
  7. 0 28
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerRoleDataListTotalDTO.java
  8. 59 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/RoleCombatRankingDTO.java
  9. 150 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/RoleRechargeRankingDTO.java
  10. 238 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/entity/AdsRoleRechargeRanking.java
  11. 243 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/entity/TGameUser.java
  12. 87 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/enums/GameCategoryEnum.java
  13. 233 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/AdsRoleRechargeRanking.java
  14. 188 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PlayerDataVO.java
  15. 212 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PlayerRoleDataVO.java
  16. 0 16
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/IPlayerDataService.java
  17. 15 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/IRoleManageService.java
  18. 348 18
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PlayerDataServiceImpl.java
  19. 802 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/RoleManageServiceImpl.java
  20. 10 0
      game-module/game-module-base/src/main/java/com/zanxiang/game/module/base/pojo/enums/GameAuthEnum.java
  21. 1 1
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/ManageApplication.java
  22. 32 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/controller/GameServerController.java
  23. 2 2
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/controller/UserController.java
  24. 15 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/GameDTO.java
  25. 60 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/params/GameMergeServerParam.java
  26. 2 2
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/params/IpBanAddParam.java
  27. 64 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/GameServerListVO.java
  28. 26 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/GameServerVO.java
  29. 25 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/GameSupperVO.java
  30. 19 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IGameServerService.java
  31. 23 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IGameSupperService.java
  32. 2 1
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IUserService.java
  33. 146 7
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/GameServerServiceImpl.java
  34. 31 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/GameSupperServiceImpl.java
  35. 2 1
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/IpBanServiceImpl.java
  36. 22 7
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/UserServiceImpl.java
  37. 5 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/Game.java
  38. 30 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/GameServer.java
  39. 58 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/GameSupper.java
  40. 12 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/GameSupperMapper.java

+ 1 - 3
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/utils/BackPolicyUtil.java

@@ -98,7 +98,6 @@ public class BackPolicyUtil {
                     throw new RuntimeException("回传策略[" + gameBackPolicy.getId() + "]配置错误,未知的回传类型:" + backType);
                 }
                 if (gameBackPolicy.getMarkUpBackCountOfUser() == null) {
-                    backMsg = backMsg + ",未配置单用户最大回传笔数";
                     log.error("订单 id[{}]通过回传策略[{}]判断后,回传,原因:回传概率 {}", orderId, gameBackPolicy.getId(), backMsg);
                     return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), backMsg);
                 }
@@ -108,7 +107,7 @@ public class BackPolicyUtil {
                 return Tuples.tuple(userBackCount < gameBackPolicy.getMarkUpBackCountOfUser(), downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), backMsg);
             } else {
                 log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:超过注册充值间隔时间但是未开启补单", orderId, gameBackPolicy.getId());
-                return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), "回传策略未开启补单");
+                return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), "补单-未开启补单");
             }
         }
 
@@ -193,7 +192,6 @@ public class BackPolicyUtil {
         }
 
         if (maxBackCountOfUser == null) {
-            backMsg = backMsg + ",未配置单用户最大回传笔数";
             log.error("订单 id[{}]通过回传策略[{}]判断后,回传,原因:回传概率 {}", orderId, gameBackPolicy.getId(), backMsg);
             return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevelString), backMsg);
         }

+ 2 - 18
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/PlayerDataController.java

@@ -1,9 +1,8 @@
 package com.zanxiang.game.data.serve.controller;
 
+import com.zanxiang.erp.security.annotation.PreAuthorize;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerDataListDTO;
-import com.zanxiang.game.data.serve.pojo.dto.PlayerDataListTotalDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerRoleDataListDTO;
-import com.zanxiang.game.data.serve.pojo.dto.PlayerRoleDataListTotalDTO;
 import com.zanxiang.game.data.serve.pojo.vo.PlayerDataVO;
 import com.zanxiang.game.data.serve.pojo.vo.PlayerRoleDataVO;
 import com.zanxiang.game.data.serve.service.IPlayerDataService;
@@ -33,19 +32,12 @@ public class PlayerDataController {
     private IPlayerDataService playerDataService;
 
     @ApiOperation("玩家列表")
-    //@PreAuthorize(permissionKey = "playerData:player:list")
+    @PreAuthorize(permissionKey = "playerData:player:list")
     @PostMapping("/list")
     public ResultVO<Page<PlayerDataVO>> getPlayerDataList(@RequestBody PlayerDataListDTO dto) {
         return ResultVO.ok(playerDataService.getPlayerDataList(dto));
     }
 
-    @ApiOperation("玩家列表总计一栏")
-    //@PreAuthorize(permissionKey = "playerData:player:listTotal")
-    @PostMapping("/listTotal")
-    public ResultVO<PlayerDataVO> getPlayerDataListTotal(@RequestBody PlayerDataListTotalDTO dto) {
-        return ResultVO.ok(playerDataService.getPlayerDataListTotal(dto));
-    }
-
     @ApiOperation("玩家角色列表")
     //@PreAuthorize(permissionKey = "playerData:role:list")
     @PostMapping("/role/list")
@@ -53,12 +45,4 @@ public class PlayerDataController {
         return ResultVO.ok(playerDataService.getPlayerRoleDataList(dto));
     }
 
-    @ApiOperation("玩家角色列表总计一栏")
-    //@PreAuthorize(permissionKey = "playerData:role:listTotal")
-    @PostMapping("/role/listTotal")
-    public ResultVO<PlayerRoleDataVO> getPlayerRoleDataListTotal(@RequestBody PlayerRoleDataListTotalDTO dto) {
-        return ResultVO.ok(playerDataService.getPlayerRoleDataListTotal(dto));
-    }
-
-
 }

+ 49 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/RoleManageController.java

@@ -0,0 +1,49 @@
+package com.zanxiang.game.data.serve.controller;
+
+import com.zanxiang.game.data.serve.pojo.dto.RoleCombatRankingDTO;
+import com.zanxiang.game.data.serve.pojo.dto.RoleRechargeRankingDTO;
+import com.zanxiang.game.data.serve.service.IRoleManageService;
+import com.zanxiang.game.data.serve.utils.Page;
+import com.zanxiang.module.util.pojo.ResultVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * @author tianhua
+ * @time 2023/9/8
+ * @Description  角色运营管理控制层接口
+ **/
+@Api(tags = "角色运营管理")
+@RestController
+@RequestMapping("/role")
+@Slf4j
+public class RoleManageController {
+
+    @Autowired
+    private IRoleManageService roleManageService;
+
+    @ApiOperation(value = "角色充值排行榜")
+    //@PreAuthorize(permissionKey = "roleManage:recharge:role")
+    @PostMapping("/rechargeRanking")
+    public ResultVO<Page<Map>> getRoleRechargeRanking(@RequestBody RoleRechargeRankingDTO dto) {
+        return ResultVO.ok(roleManageService.getRoleRechargeRanking(dto));
+    }
+
+    @ApiOperation(value = "角色战力排行榜")
+    //@PreAuthorize(permissionKey = "roleManage:combat:role")
+    @PostMapping("/combatRanking")
+    public ResultVO<Page<Map>> getRoleCombatRanking(@RequestBody RoleCombatRankingDTO dto) {
+        return ResultVO.ok(roleManageService.getRoleCombatRanking(dto));
+    }
+
+
+
+}

+ 152 - 2
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerDataListDTO.java

@@ -1,8 +1,10 @@
 package com.zanxiang.game.data.serve.pojo.dto;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.zanxiang.game.data.serve.pojo.base.BasePage;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDate;
 
@@ -14,16 +16,164 @@ import java.time.LocalDate;
 @Data
 public class PlayerDataListDTO extends BasePage {
 
+    /**
+     * 玩家id
+     */
+    @ApiModelProperty(notes = "玩家id")
+    private Long userId;
+
+    /**
+     * 玩家账号
+     */
+    @ApiModelProperty(notes = "玩家账号")
+    private String userName;
+
+    /**
+     * 玩家昵称
+     */
+    @ApiModelProperty(notes = "玩家昵称")
+    private String nickname;
+
+    /**
+     * 绑定手机号码
+     */
+    @ApiModelProperty(notes = "绑定手机号码")
+    private String mobile;
+
+    /**
+     * 注册IP
+     */
+    @ApiModelProperty(notes = "注册IP")
+    private String regIp;
+
+    /**
+     * 是否实名认证
+     */
+    @ApiModelProperty(notes = "是否实名认证")
+    private Boolean isAuth;
+
+    /**
+     * 玩家手机绑定状态
+     */
+    @ApiModelProperty(notes = "玩家手机绑定状态")
+    private Boolean isBindMobile;
+
+    /**
+     * cp名称对应的id
+     */
+    @ApiModelProperty(notes = "cp名称对应的id")
+    private Long cpId;
+
+    /**
+     * 游戏名称对应的id
+     */
+    @ApiModelProperty(notes = "游戏名称对应的id")
+    private Long gameId;
+
+    /**
+     * 游戏应用类型对应的id
+     */
+    @ApiModelProperty(notes = "游戏应用类型对应的id")
+    private Long gameCategoryId;
+
+    /**
+     * 最近充值开始时间
+     */
+    @ApiModelProperty(notes = "最近充值开始时间")
+    private LocalDate rechargeBeginDate;
+
+    /**
+     * 最近充值结束时间
+     */
+    @ApiModelProperty(notes = "最近充值结束时间")
+    private LocalDate rechargeEndDate;
+
+    /**
+     * 是否充值
+     */
+    @ApiModelProperty(notes = "是否充值, true : 是, false : 否")
+    private Boolean isRecharge;
+
+    /**
+     * 玩家状态, 1 为试玩状态 2为正常状态,3为冻结状态
+     */
+    @ApiModelProperty(notes = "玩家状态, 1 为试玩状态 2为正常状态,3为冻结状态")
+    private Integer status;
+
+    /**
+     * 注册渠道对应的id
+     */
+    @ApiModelProperty(notes = "注册渠道对应的id")
+    private Long channelId;
+
+    /**
+     * 归因推广账号
+     */
+    @ApiModelProperty(notes = "归因推广账号")
+    private String accountId;
+
+    /**
+     * 归因投放人员
+     */
+    @ApiModelProperty(notes = "归因投放人员")
+    private String pitcherId;
+
     /**
      * 注册开始时间
      */
-    @ApiModelProperty("注册开始时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty(value = "注册开始时间")
     private LocalDate beginDate;
 
     /**
      * 注册结束时间
      */
-    @ApiModelProperty("注册结束时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty(value = "注册结束时间")
     private LocalDate endDate;
 
+    @ApiModelProperty("充值到注册的最小间隔时间(分)")
+    private Long regPayIntervalTimeMin;
+
+    @ApiModelProperty("充值到注册的最大间隔时间(分)")
+    private Long regPayIntervalTimeMax;
+
+    /**
+     * 是否创角
+     */
+    @ApiModelProperty(notes = "是否创角")
+    private Boolean createRole;
+
+    /**
+     * 角色数量最小值
+     */
+    @ApiModelProperty(notes = "角色数量最小值")
+    private Integer roleCountMin;
+
+    /**
+     * 角色数量最大值
+     */
+    @ApiModelProperty(notes = "角色数量最大值")
+    private Integer roleCountMax;
+
+    /**
+     * 排序字段
+     */
+    @ApiModelProperty("排序字段")
+    private String sortFiled;
+
+    /**
+     * 排序方式
+     */
+    @ApiModelProperty("排序方式")
+    private String sortType;
+
+    /**
+     * SDK来源
+     */
+    @ApiModelProperty("SDK来源")
+    private String sourceSystem;
+
 }

+ 0 - 28
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerDataListTotalDTO.java

@@ -1,28 +0,0 @@
-package com.zanxiang.game.data.serve.pojo.dto;
-
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.time.LocalDate;
-
-/**
- * @author tianhua
- * @time 2023/9/6
- * @Description 前端玩家列表总计查询参数实体
- **/
-@Data
-public class PlayerDataListTotalDTO {
-
-    /**
-     * 注册开始时间
-     */
-    @ApiModelProperty("注册开始时间")
-    private LocalDate beginDate;
-
-    /**
-     * 注册结束时间
-     */
-    @ApiModelProperty("注册结束时间")
-    private LocalDate endDate;
-
-}

+ 160 - 4
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerRoleDataListDTO.java

@@ -1,8 +1,10 @@
 package com.zanxiang.game.data.serve.pojo.dto;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.zanxiang.game.data.serve.pojo.base.BasePage;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDate;
 
@@ -15,15 +17,169 @@ import java.time.LocalDate;
 public class PlayerRoleDataListDTO extends BasePage {
 
     /**
-     * 注册开始时间
+     * 玩家id
+     */
+    @ApiModelProperty(notes = "玩家id")
+    private Long userId;
+
+    /**
+     * 玩家账号
+     */
+    @ApiModelProperty(notes = "玩家账号")
+    private String userName;
+
+    /**
+     * 玩家昵称
+     */
+    @ApiModelProperty(notes = "玩家昵称")
+    private String nickname;
+
+    /**
+     * 注册IP
+     */
+    @ApiModelProperty(notes = "注册IP")
+    private String regIp;
+
+    /**
+     * 游戏区服
+     */
+    @ApiModelProperty(notes = "游戏区服")
+    private String serverName;
+
+    /**
+     * 游戏角色
+     */
+    @ApiModelProperty(notes = "游戏角色")
+    private String roleName;
+
+    /**
+     * cp名称对应的id
+     */
+    @ApiModelProperty(notes = "cp名称对应的id")
+    private Long cpId;
+
+    /**
+     * 游戏名称对应的id
+     */
+    @ApiModelProperty(notes = "游戏名称对应的id")
+    private Long gameId;
+
+    /**
+     * 游戏应用类型对应的id
+     */
+    @ApiModelProperty(notes = "游戏应用类型对应的id")
+    private Long gameCategoryId;
+
+    /**
+     * 注册渠道对应的id
+     */
+    @ApiModelProperty(notes = "注册渠道对应的id")
+    private Long channelId;
+
+    /**
+     * 归因推广账号
+     */
+    @ApiModelProperty(notes = "归因推广账号")
+    private String accountId;
+
+    /**
+     * 归因投放人员
+     */
+    @ApiModelProperty(notes = "归因投放人员")
+    private String pitcherId;
+
+    /**
+     * 操作系统对应的id
+     */
+    @ApiModelProperty(notes = "操作系统对应的id, 全部 : null或者不传")
+    private String os;
+
+    /**
+     * 是否充值
+     */
+    @ApiModelProperty(notes = "是否充值, true : 是, false : 否, 全部 : null或者不传")
+    private Boolean isRecharge;
+
+    /**
+     * 角色vip
+     */
+    @ApiModelProperty(notes = "角色vip, 全部 : null或者不传")
+    private Integer vipLevel;
+
+    /**
+     * 最近充值开始时间
+     */
+    @ApiModelProperty(notes = "最近充值开始时间")
+    private LocalDate rechargeBeginDate;
+
+    /**
+     * 最近充值结束时间
      */
-    @ApiModelProperty("注册开始时间")
+    @ApiModelProperty(notes = "最近充值结束时间")
+    private LocalDate rechargeEndDate;
+
+    /**
+     * 角色创建开始时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty(value = "角色创建开始时间")
     private LocalDate beginDate;
 
     /**
-     * 注册结束时间
+     * 角色创建结束时间
      */
-    @ApiModelProperty("注册结束时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty(value = "角色创建结束时间")
     private LocalDate endDate;
 
+    /**
+     * 最小角色等级
+     */
+    @ApiModelProperty(value = "最小角色等级")
+    private Long roleLevelMin;
+
+    /**
+     * 最大角色等级
+     */
+    @ApiModelProperty(value = "最大角色等级")
+    private Long roleLevelMax;
+
+    /**
+     * 注册开始时间
+     */
+    @ApiModelProperty(value = "注册开始时间")
+    private LocalDate regTimeBeginDate;
+
+    /**
+     * 注册结束时间
+     */
+    @ApiModelProperty(value = "注册结束时间")
+    private LocalDate regTimeEndDate;
+
+    @ApiModelProperty("充值到注册的间隔时间(分)")
+    private Long regPayIntervalTimeMin;
+
+    @ApiModelProperty("充值到注册的间隔时间(分)")
+    private Long regPayIntervalTimeMax;
+
+    /**
+     * 排序字段
+     */
+    @ApiModelProperty("排序字段")
+    private String sortFiled;
+
+    /**
+     * 排序方式
+     */
+    @ApiModelProperty("排序方式")
+    private String sortType;
+
+    /**
+     * SDK来源
+     */
+    @ApiModelProperty("SDK来源")
+    private String sourceSystem;
+
 }

+ 0 - 28
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerRoleDataListTotalDTO.java

@@ -1,28 +0,0 @@
-package com.zanxiang.game.data.serve.pojo.dto;
-
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.time.LocalDate;
-
-/**
- * @author tianhua
- * @time 2023/9/6
- * @Description 前端玩家角色列表总计查询参数实体
- **/
-@Data
-public class PlayerRoleDataListTotalDTO {
-
-    /**
-     * 注册开始时间
-     */
-    @ApiModelProperty("注册开始时间")
-    private LocalDate beginDate;
-
-    /**
-     * 注册结束时间
-     */
-    @ApiModelProperty("注册结束时间")
-    private LocalDate endDate;
-
-}

+ 59 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/RoleCombatRankingDTO.java

@@ -0,0 +1,59 @@
+package com.zanxiang.game.data.serve.pojo.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * @author tianhua
+ * @time 2023/9/11
+ * @Description 角色战力排行榜查询参数实体
+ **/
+@Data
+public class RoleCombatRankingDTO {
+
+    /**
+     * 开服时间(开始)
+     */
+    @ApiModelProperty(value = "开服时间(开始)")
+    private LocalDate beginDate;
+
+    /**
+     * 开服时间(结束)
+     */
+    @ApiModelProperty(value = "开服时间(结束)")
+    private LocalDate endDate;
+
+    /**
+     * 主游戏ID
+     */
+    @ApiModelProperty(value = "主游戏ID")
+    private Long gameId;
+
+    /**
+     * 区服ID(列表)
+     */
+    @ApiModelProperty(value = "区服ID(列表)")
+    private List<Long> serverIds;
+
+    /**
+     * 排名的范围
+     */
+    @ApiModelProperty(value = "排名的范围")
+    private Long rankingNum;
+
+    /**
+     * 排序字段
+     */
+    @ApiModelProperty(notes = "排序字段")
+    private String sortFiled;
+
+    /**
+     * 排序方式:升序asc;降序desc
+     */
+    @ApiModelProperty(notes = "排序方式:升序asc;降序desc")
+    private String sortType;
+
+}

+ 150 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/RoleRechargeRankingDTO.java

@@ -0,0 +1,150 @@
+package com.zanxiang.game.data.serve.pojo.dto;
+
+import com.zanxiang.game.data.serve.pojo.base.BasePage;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * @author tianhua
+ * @time 2023/9/11
+ * @Description 角色充值排行榜前端查询实体
+ **/
+@Data
+public class RoleRechargeRankingDTO extends BasePage {
+
+    /**
+     * SDK来源
+     */
+    @ApiModelProperty(value = "SDK来源")
+    private String sourceSystem;
+
+    /**
+     * 充值开始时间
+     */
+    @ApiModelProperty(value = "充值开始时间")
+    private LocalDate rechargeBeginDate;
+
+    /**
+     * 充值结束时间
+     */
+    @ApiModelProperty(value = "充值结束时间")
+    private LocalDate rechargeEndDate;
+
+    /**
+     * 子游戏ID
+     */
+    @ApiModelProperty(value = "子游戏ID")
+    private Long gameId;
+
+    /**
+     * 父游戏ID
+     */
+    @ApiModelProperty(value = "父游戏ID")
+    private Long parentGameId;
+
+    /**
+     * 区服ID(列表)
+     */
+    @ApiModelProperty(value = "区服ID(列表)")
+    private List<Long> serverIds;
+
+    /**
+     * 角色名
+     */
+    @ApiModelProperty(value = "角色名")
+    private String roleName;
+
+    /**
+     * 角色ID
+     */
+    @ApiModelProperty(value = "角色ID")
+    private String roleId;
+
+    /**
+     * 角色创建时间(开始)
+     */
+    @ApiModelProperty(value = "角色创建时间(开始)")
+    private LocalDate createRoleBeginDate;
+
+    /**
+     * 角色创建时间(结束)
+     */
+    @ApiModelProperty(value = "角色创建时间(结束)")
+    private LocalDate createRoleEndDate;
+
+    /**
+     * 角色VIP等级
+     */
+    @ApiModelProperty(value = "角色VIP等级")
+    private Integer vipLevel;
+
+    /**
+     * 邮件是否发送
+     */
+    @ApiModelProperty(value = "邮件是否发送: 1 -> 发送 ; 0 -> 不发送")
+    private Integer isSendMail;
+
+    /**
+     * 是否转端
+     */
+    @ApiModelProperty(value = "是否转端: 1 -> 转端 ; 0 -> 不转端")
+    private Integer isChange;
+
+    /**
+     * 企业微信号
+     */
+    @ApiModelProperty(value = "企业微信号")
+    private String weChatCompany;
+
+    /**
+     * 客户微信
+     */
+    @ApiModelProperty(value = "客户微信号")
+    private String weChat;
+
+    /**
+     * 客户手机
+     */
+    @ApiModelProperty(value = "客户手机号")
+    private String phone;
+
+    /**
+     * GS
+     */
+    @ApiModelProperty(value = "GS_ID")
+    private Long gsId;
+
+    /**
+     * 客服
+     */
+    @ApiModelProperty(value = "客服ID")
+    private Long customerServerId;
+
+    /**
+     * 投手
+     */
+    @ApiModelProperty(value = "投手ID")
+    private Long pitcherId;
+
+    /**
+     * 运营
+     */
+    @ApiModelProperty(value = "运营ID")
+    private Long operatorId;
+
+    /**
+     * 排序字段
+     */
+    @ApiModelProperty(notes = "排序字段")
+    private String sortFiled;
+
+    /**
+     * 排序方式:升序asc;降序desc
+     */
+    @ApiModelProperty(notes = "排序方式:升序asc;降序desc")
+    private String sortType;
+
+}

+ 238 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/entity/AdsRoleRechargeRanking.java

@@ -0,0 +1,238 @@
+package com.zanxiang.game.data.serve.pojo.entity;
+
+import lombok.Data;
+import org.nutz.dao.entity.annotation.Column;
+import org.nutz.dao.entity.annotation.PK;
+import org.nutz.dao.entity.annotation.Table;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@Table(AdsRoleRechargeRanking.TABLE_NAME)
+@PK({"id"})
+public class AdsRoleRechargeRanking implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "ads_role_recharge_ranking";
+     
+    /**
+    * 主键ID
+    */
+    private String id;
+    
+    /**
+    * 角色ID
+    */    
+    @Column
+    private String roleId;
+    
+    /**
+    * 游戏SDK
+    */    
+    @Column
+    private String sourceSystem;
+    
+    /**
+    * 游戏ID
+    */    
+    @Column
+    private Long gameId;
+    
+    /**
+    * 游戏名字
+    */    
+    @Column
+    private String gameName;
+    
+    /**
+    * 游戏应用类型
+    */    
+    @Column
+    private Long classify;
+    
+    /**
+    * 区服ID
+    */    
+    @Column
+    private Long serverId;
+    
+    /**
+    * 区服名字
+    */    
+    @Column
+    private String serverName;
+    
+    /**
+    * 合服ID
+    */    
+    @Column
+    private Long serverIdMerge;
+    
+    /**
+    * 合服名字
+    */    
+    @Column
+    private String serverNameMerge;
+    
+    /**
+    * 父游戏ID
+    */    
+    @Column
+    private Long parentGameId;
+    
+    /**
+    * 角色名称
+    */    
+    @Column
+    private String roleName;
+    
+    /**
+    * 角色创建时间
+    */    
+    @Column
+    private LocalDateTime createTime;
+    
+    /**
+    * 角色vip
+    */    
+    @Column
+    private Long roleVip;
+    
+    /**
+    * 角色等级
+    */    
+    @Column
+    private Long roleLevel;
+    
+    /**
+    * 角色战力
+    */    
+    @Column
+    private Long combatNum;
+    
+    /**
+    * 用户ID
+    */    
+    @Column
+    private Long userId;
+    
+    /**
+    * 用户账号
+    */    
+    @Column
+    private String username;
+    
+    /**
+    * 渠道ID
+    */    
+    @Column
+    private Long agentId;
+    
+    /**
+    * 渠道名字
+    */    
+    @Column
+    private String agentName;
+    
+    /**
+    * 用户注册时间
+    */    
+    @Column
+    private LocalDateTime regTime;
+    
+    /**
+    * 玩家操作系统
+    */    
+    @Column
+    private String os;
+    
+    /**
+    * 用户等级标签(暂无)
+    */    
+    @Column
+    private String userLabel;
+    
+    /**
+    * 用户最近充值游戏
+    */    
+    @Column
+    private Long userLastGameId;
+    
+    /**
+    * 用户最近充值游戏
+    */    
+    @Column
+    private Long userLastGameName;
+    
+    /**
+    * 用户最近充值时间
+    */    
+    @Column
+    private LocalDateTime userLastOrderTime;
+    
+    /**
+    * 角色最近充值时间
+    */    
+    @Column
+    private LocalDateTime roleLastOrderTime;
+    
+    /**
+    * 角色充值时间
+    */    
+    @Column
+    private LocalDate day;
+    
+    /**
+    * 角色今日充值
+    */    
+    @Column
+    private BigDecimal todayAmount;
+    
+    /**
+    * 角色首充
+    */    
+    @Column
+    private BigDecimal firstAmount;
+    
+    /**
+    * 角色累计充值
+    */    
+    @Column
+    private BigDecimal totalAmount;
+    
+    /**
+    * 角色累计充值次数
+    */    
+    @Column
+    private Long totalAmountCount;
+    
+    /**
+    * 角色充值平均单价
+    */    
+    @Column
+    private Long totalAvgAmount;
+    
+    /**
+    * 角色最近活跃时间
+    */    
+    @Column
+    private LocalDateTime roleActiveTime;
+    
+    /**
+    * 用户最近活跃时间
+    */    
+    @Column
+    private LocalDateTime userActiveTime;
+    
+    /**
+    * 父游戏名称
+    */    
+    @Column
+    private LocalDateTime parentGameName;
+    
+    
+}
+
+

+ 243 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/entity/TGameUser.java

@@ -0,0 +1,243 @@
+package com.zanxiang.game.data.serve.pojo.entity;
+
+import lombok.Data;
+import org.nutz.dao.entity.annotation.Column;
+import org.nutz.dao.entity.annotation.PK;
+import org.nutz.dao.entity.annotation.Table;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@Table(TGameUser.TABLE_NAME)
+@PK({"sourceSystem", "id"})
+public class TGameUser implements Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String TABLE_NAME = "dm_game_order.t_game_user";
+     
+    /**
+    * SDK来源
+    */
+    private String sourceSystem;
+    
+    /**
+    * id
+    */
+    private Long id;
+    
+    /**
+    * 用户名
+    */    
+    @Column
+    private String username;
+    
+    /**
+    * 昵称
+    */    
+    @Column
+    private String nickname;
+    
+    /**
+    * 注册手机号
+    */    
+    @Column
+    private String regMobile;
+    
+    /**
+    * 注册邮箱
+    */    
+    @Column
+    private String regEmail;
+    
+    /**
+    * 绑定邮箱
+    */    
+    @Column
+    private String email;
+    
+    /**
+    * 绑定手机号码
+    */    
+    @Column
+    private String mobile;
+    
+    /**
+    * 设备来源 mobile,android,iphone,ipad,web,pc,mac,wxapp
+    */    
+    @Column
+    private String fromDevice;
+    
+    /**
+    * 设备ID android 为imei ios 为idfa
+    */    
+    @Column
+    private String deviceId;
+    
+    /**
+    * 游戏ID
+    */    
+    @Column
+    private Integer gameId;
+    
+    /**
+    * 运营商ID
+    */    
+    @Column
+    private Integer opId;
+    
+    /**
+    * 所属渠道ID
+    */    
+    @Column
+    private Integer agentId;
+    
+    /**
+    * 渠道名称
+    */    
+    @Column
+    private String agentGame;
+    
+    /**
+    * 1 为试玩状态 2为正常状态,3为冻结状态
+    */    
+    @Column
+    private Integer status;
+    
+    /**
+    * 父Id
+    */    
+    @Column
+    private Integer parentMemId;
+    
+    /**
+    * 注册时间
+    */    
+    @Column
+    private LocalDateTime createTime;
+    
+    /**
+    * 更改时间
+    */    
+    @Column
+    private LocalDateTime upLocalDateTimeTime;
+    
+    /**
+    * 是否切换 1 切换 2不切换
+    */    
+    @Column
+    private Integer isSwitch;
+    
+    /**
+    * 切量时间 指定切量时间后的订单都会被切量
+    */    
+    @Column
+    private LocalDateTime switchTime;
+    
+    /**
+    * 切量金额 大于指定切量金额的订单都才被切量
+    */    
+    @Column
+    private Long switchMoney;
+    
+    /**
+    * 累计充值次数
+    */    
+    @Column
+    private Integer rechargeCount;
+    
+    /**
+    * 累计充值金额
+    */    
+    @Column
+    private BigDecimal rechargeMoney;
+    
+    /**
+    * 最近充值时间
+    */    
+    @Column
+    private LocalDateTime lastRechargeTime;
+    
+    /**
+    * 平台币余额
+    */    
+    @Column
+    private Double platformCoin;
+    
+    /**
+    * 创角数
+    */    
+    @Column
+    private Integer roleCount;
+    
+    /**
+    * 是否GS
+    */    
+    @Column
+    private Integer isGs;
+    
+    /**
+    * 拥有角色最高vip
+    */    
+    @Column
+    private Integer vipMax;
+    
+    /**
+    * 广告id
+    */    
+    @Column
+    private String adId;
+    
+    /**
+    * 计划ID
+    */    
+    @Column
+    private String promotionId;
+    
+    /**
+    * 项目ID(广告ID)
+    */    
+    @Column
+    private String projectId;
+    
+    /**
+    * 创意ID
+    */    
+    @Column
+    private String advertiserId;
+    
+    /**
+    * 分享用户id
+    */    
+    @Column
+    private Long shareUserId;
+    
+    /**
+    * 关联用户id
+    */    
+    @Column
+    private Long relationUserId;
+    
+    /**
+    * 关联用户建立时间
+    */    
+    @Column
+    private LocalDateTime relationCreateTime;
+    
+    /**
+    * 来源用户id
+    */    
+    @Column
+    private Long associationUserId;
+    
+    /**
+    * 用户注册IP
+    */    
+    @Column
+    private String ip;
+    
+  
+
+}
+
+

+ 87 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/enums/GameCategoryEnum.java

@@ -0,0 +1,87 @@
+package com.zanxiang.game.data.serve.pojo.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Objects;
+
+/**
+ * @author : tianhua
+ * @time : 2022-09-07
+ * @description : 游戏应用类型
+ */
+@Getter
+@AllArgsConstructor
+public enum GameCategoryEnum {
+
+    /**
+     * 微信小游戏
+     */
+    CATEGORY_WX_APPLET(6L, "wx_applet", "微信小游戏"),
+
+    /**
+     * h5游戏
+     */
+    CATEGORY_H5(5L, "h5", "h5游戏"),
+
+    /**
+     * IOSApp游戏
+     */
+    CATEGORY_IOS_APP(4L, "ios_app", "IOS APP"),
+
+    /**
+     * AndroidApp游戏
+     */
+    CATEGORY_ANDROID_APP(3L, "android_app", "Android APP"),
+
+    /**
+     * 抖音小游戏
+     */
+    CATEGORY_DY_APPLET(2L, "byte_applet", "抖音小游戏"),
+
+    /**
+     * APP
+     */
+    CATEGORY_APP(1L, "app", "APP");
+
+    /**
+     * 应用id
+     */
+    private Long id;
+
+    /**
+     * 游戏分类key
+     */
+    private String categoryKey;
+
+    /**
+     * 描述
+     */
+    private String name;
+
+    /**
+     * 被分类名字
+     *
+     * @param category 类别
+     * @return {@link String}
+     */
+    public static String getNameByCategory(Long category) {
+        GameCategoryEnum gameCategory = GameCategoryEnum.getGameCategory(category);
+        return gameCategory == null ? null : gameCategory.getName();
+    }
+
+    /**
+     * 获取游戏分类
+     *
+     * @param category 类别
+     * @return {@link String}
+     */
+    public static GameCategoryEnum getGameCategory(Long category) {
+        for (GameCategoryEnum gameCategoryEnum : GameCategoryEnum.values()) {
+            if (Objects.equals(gameCategoryEnum.getId(), category)) {
+                return gameCategoryEnum;
+            }
+        }
+        return null;
+    }
+}

+ 233 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/AdsRoleRechargeRanking.java

@@ -0,0 +1,233 @@
+package com.zanxiang.game.data.serve.pojo.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+public class AdsRoleRechargeRanking {
+     
+    /**
+    * 主键ID
+    */    
+    @ApiModelProperty(value = "主键ID")
+    private String id;
+    
+    /**
+    * 角色ID
+    */    
+    @ApiModelProperty(value = "角色ID")
+    private String roleId;
+    
+    /**
+    * 游戏SDK
+    */    
+    @ApiModelProperty(value = "游戏SDK")
+    private String sourceSystem;
+    
+    /**
+    * 游戏ID
+    */    
+    @ApiModelProperty(value = "游戏ID")
+    private Long gameId;
+    
+    /**
+    * 游戏名字
+    */    
+    @ApiModelProperty(value = "游戏名字")
+    private String gameName;
+    
+    /**
+    * 游戏应用类型
+    */    
+    @ApiModelProperty(value = "游戏应用类型")
+    private Long classify;
+    
+    /**
+    * 区服ID
+    */    
+    @ApiModelProperty(value = "区服ID")
+    private Long serverId;
+    
+    /**
+    * 区服名字
+    */    
+    @ApiModelProperty(value = "区服名字")
+    private String serverName;
+    
+    /**
+    * 合服ID
+    */    
+    @ApiModelProperty(value = "合服ID")
+    private Long serverIdMerge;
+    
+    /**
+    * 合服名字
+    */    
+    @ApiModelProperty(value = "合服名字")
+    private String serverNameMerge;
+    
+    /**
+    * 父游戏ID
+    */    
+    @ApiModelProperty(value = "父游戏ID")
+    private Long parentGameId;
+    
+    /**
+    * 角色名称
+    */    
+    @ApiModelProperty(value = "角色名称")
+    private String roleName;
+    
+    /**
+    * 角色创建时间
+    */    
+    @ApiModelProperty(value = "角色创建时间")
+    private LocalDateTime createTime;
+    
+    /**
+    * 角色vip
+    */    
+    @ApiModelProperty(value = "角色vip")
+    private Long roleVip;
+    
+    /**
+    * 角色等级
+    */    
+    @ApiModelProperty(value = "角色等级")
+    private Long roleLevel;
+    
+    /**
+    * 角色战力
+    */    
+    @ApiModelProperty(value = "角色战力")
+    private Long combatNum;
+    
+    /**
+    * 用户ID
+    */    
+    @ApiModelProperty(value = "用户ID")
+    private Long userId;
+    
+    /**
+    * 用户账号
+    */    
+    @ApiModelProperty(value = "用户账号")
+    private String username;
+    
+    /**
+    * 渠道ID
+    */    
+    @ApiModelProperty(value = "渠道ID")
+    private Long agentId;
+    
+    /**
+    * 渠道名字
+    */    
+    @ApiModelProperty(value = "渠道名字")
+    private String agentName;
+    
+    /**
+    * 用户注册时间
+    */    
+    @ApiModelProperty(value = "用户注册时间")
+    private LocalDateTime regTime;
+    
+    /**
+    * 玩家操作系统
+    */    
+    @ApiModelProperty(value = "玩家操作系统")
+    private String os;
+    
+    /**
+    * 用户等级标签(暂无)
+    */    
+    @ApiModelProperty(value = "用户等级标签(暂无)")
+    private String userLabel;
+    
+    /**
+    * 用户最近充值游戏
+    */    
+    @ApiModelProperty(value = "用户最近充值游戏")
+    private Long userLastGameId;
+    
+    /**
+    * 用户最近充值游戏
+    */    
+    @ApiModelProperty(value = "用户最近充值游戏")
+    private Long userLastGameName;
+    
+    /**
+    * 用户最近充值时间
+    */    
+    @ApiModelProperty(value = "用户最近充值时间")
+    private LocalDateTime userLastOrderTime;
+    
+    /**
+    * 角色最近充值时间
+    */    
+    @ApiModelProperty(value = "角色最近充值时间")
+    private LocalDateTime roleLastOrderTime;
+    
+    /**
+    * 角色充值时间
+    */    
+    @ApiModelProperty(value = "角色充值时间")
+    private LocalDate day;
+    
+    /**
+    * 角色今日充值
+    */    
+    @ApiModelProperty(value = "角色今日充值")
+    private BigDecimal todayAmount;
+    
+    /**
+    * 角色首充
+    */    
+    @ApiModelProperty(value = "角色首充")
+    private BigDecimal firstAmount;
+    
+    /**
+    * 角色累计充值
+    */    
+    @ApiModelProperty(value = "角色累计充值")
+    private BigDecimal totalAmount;
+    
+    /**
+    * 角色累计充值次数
+    */    
+    @ApiModelProperty(value = "角色累计充值次数")
+    private Long totalAmountCount;
+    
+    /**
+    * 角色充值平均单价
+    */    
+    @ApiModelProperty(value = "角色充值平均单价")
+    private Long totalAvgAmount;
+    
+    /**
+    * 角色最近活跃时间
+    */    
+    @ApiModelProperty(value = "角色最近活跃时间")
+    private LocalDateTime roleActiveTime;
+    
+    /**
+    * 用户最近活跃时间
+    */    
+    @ApiModelProperty(value = "用户最近活跃时间")
+    private LocalDateTime userActiveTime;
+    
+    /**
+    * 父游戏名称
+    */    
+    @ApiModelProperty(value = "父游戏名称")
+    private LocalDateTime parentGameName;
+    
+  
+    
+}
+
+

+ 188 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PlayerDataVO.java

@@ -1,9 +1,197 @@
 package com.zanxiang.game.data.serve.pojo.vo;
 
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
 /**
  * @author tianhua
  * @time 2023/9/6
  * @Description 返给前端的玩家列表实体(玩家列表、玩家列表总计使用)
  **/
+@Data
 public class PlayerDataVO {
+
+    /**
+     * 玩家id
+     */
+    @ApiModelProperty(notes = "玩家id")
+    private Long id;
+
+    /**
+     * 玩家账号
+     */
+    @ApiModelProperty(notes = "玩家账号")
+    private String username;
+
+    /**
+     * 玩家昵称
+     */
+    @ApiModelProperty(notes = "玩家昵称")
+    private String nickname;
+
+    /**
+     * 注册IP
+     */
+    @ApiModelProperty(notes = "注册IP")
+    private String regIp;
+
+    /**
+     * 注册时间
+     */
+    @ApiModelProperty(notes = "注册时间")
+    private LocalDateTime createTime;
+
+    /**
+     * 渠道id
+     */
+    @ApiModelProperty(notes = "渠道id")
+    private Long agentId;
+
+    /**
+     * 渠道名称
+     */
+    @ApiModelProperty(notes = "渠道名称")
+    private String agentName;
+
+    /**
+     * cpId
+     */
+    @ApiModelProperty(notes = "cpId")
+    private Long cpId;
+
+    /**
+     * cp名称
+     */
+    @ApiModelProperty(notes = "cp名称")
+    private String cpName;
+
+    /**
+     * 游戏id
+     */
+    @ApiModelProperty(notes = "游戏id")
+    private Long gameId;
+
+    /**
+     * 游戏名称
+     */
+    @ApiModelProperty(notes = "游戏名称")
+    private String gameName;
+
+    /**
+     * 游戏应用类型id
+     */
+    @ApiModelProperty(notes = "游戏应用类型id")
+    private Long gameCategoryId;
+
+    /**
+     * 游戏应用类型名称
+     */
+    @ApiModelProperty(notes = "游戏应用类型名称")
+    private String gameCategoryName;
+
+    /**
+     * 归因投放人员id
+     */
+    @ApiModelProperty(notes = "归因投放人员id")
+    private Long pitcherId;
+
+    /**
+     * 归因投放人员名字
+     */
+    @ApiModelProperty(notes = "归因投放人员名字")
+    private String pitcherName;
+
+    /**
+     * 归因推广账号id
+     */
+    @ApiModelProperty(notes = "归因推广账号id")
+    private Long accountId;
+
+    /**
+     * 归因推广账号类型(1:腾讯、2:头条)
+     */
+    @ApiModelProperty(notes = "归因推广账号类型")
+    private String accountType;
+
+    /**
+     * 绑定手机号码
+     */
+    @ApiModelProperty(notes = "绑定手机号码")
+    private String mobile;
+
+    /**
+     * 充值金额
+     */
+    @ApiModelProperty(notes = "充值金额")
+    private BigDecimal rechargeMoney;
+
+    /**
+     * 充值次数
+     */
+    @ApiModelProperty(notes = "充值次数")
+    private Integer rechargeCount;
+
+    /**
+     * 创角色数
+     */
+    @ApiModelProperty(notes = "创角色数")
+    private Integer roleCount;
+
+    /**
+     * 最近登录时间
+     */
+    @ApiModelProperty(notes = "最近登录时间")
+    private LocalDateTime updateTime;
+
+    /**
+     * 最近充值时间
+     */
+    @ApiModelProperty(notes = "最近充值时间")
+    private LocalDateTime lastRechargeTime;
+
+    /**
+     * 玩家状态:1 为试玩状态 2为正常状态,3为冻结状态
+     */
+    @ApiModelProperty(notes = "玩家状态:1 为试玩状态 2为正常状态,3为冻结状态")
+    private String status;
+
+    /**
+     * 最新游戏角色名称
+     */
+    @ApiModelProperty(notes = "最新游戏角色名称")
+    private String lastGameRoleName;
+
+    /**
+     * 注册充值时间差
+     */
+    @ApiModelProperty(notes = "注册充值时间差")
+    private Long regPayTimeDiff;
+
+    /**
+     * 关联游戏id
+     */
+    @ApiModelProperty(notes = "关联游戏id")
+    private Long relationGameId;
+
+    /**
+     * 关联游戏名称
+     */
+    @ApiModelProperty(notes = "关联游戏名称")
+    private String relationGameName;
+
+    /**
+     * 关联用户id
+     */
+    @ApiModelProperty(notes = "关联用户id")
+    private Long relationUserId;
+
+    /**
+     * 关联建立时间
+     */
+    @ApiModelProperty(notes = "关联建立时间")
+    private LocalDateTime relationCreateTime;
+
 }

+ 212 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/PlayerRoleDataVO.java

@@ -1,9 +1,221 @@
 package com.zanxiang.game.data.serve.pojo.vo;
 
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
 /**
  * @author tianhua
  * @time 2023/9/6
  * @Description 返给前端的玩家角色列表实体(玩家角色列表、玩家角色列表总计使用)
  **/
+@Data
 public class PlayerRoleDataVO {
+
+    /**
+     * 主键id
+     */
+    @ApiModelProperty(notes = "主键id")
+    private Long id;
+
+    /**
+     * 玩家id
+     */
+    @ApiModelProperty(notes = "玩家id")
+    private Long userId;
+
+    /**
+     * 玩家账号
+     */
+    @ApiModelProperty(notes = "玩家账号")
+    private String username;
+
+    /**
+     * 玩家昵称
+     */
+    @ApiModelProperty(notes = "玩家昵称")
+    private String nickname;
+
+    /**
+     * 注册IP
+     */
+    @ApiModelProperty(notes = "注册IP")
+    private String regIp;
+
+    /**
+     * 玩家注册时间
+     */
+    @ApiModelProperty(notes = "玩家注册时间")
+    private LocalDateTime regTime;
+
+    /**
+     * 注册渠道id
+     */
+    @ApiModelProperty(notes = "注册渠道id")
+    private Long agentId;
+
+    /**
+     * 注册渠道名称
+     */
+    @ApiModelProperty(notes = "注册渠道名称")
+    private String agentName;
+
+    /**
+     * cp标识id
+     */
+    @ApiModelProperty(notes = "cp标识id")
+    private Long cpId;
+
+    /**
+     * cp名称
+     */
+    @ApiModelProperty(notes = "cp名称")
+    private String cpName;
+
+    /**
+     * 游戏id
+     */
+    @ApiModelProperty(notes = "游戏id")
+    private Long gameId;
+
+    /**
+     * 游戏名称
+     */
+    @ApiModelProperty(notes = "游戏名称")
+    private String gameName;
+
+    /**
+     * 游戏应用类型id
+     */
+    @ApiModelProperty(notes = "游戏应用类型id")
+    private Long gameCategoryId;
+
+    /**
+     * 游戏应用类型名称
+     */
+    @ApiModelProperty(notes = "游戏应用类型名称")
+    private String gameCategoryName;
+
+    /**
+     * 原始服务器名称
+     */
+    @ApiModelProperty(notes = "原始服务器名称")
+    private String sourceServerName;
+
+    /**
+     * 游戏区服
+     */
+    @ApiModelProperty(notes = "游戏区服")
+    private String serverName;
+
+    /**
+     * 游戏角色
+     */
+    @ApiModelProperty(notes = "游戏角色")
+    private String roleName;
+
+    /**
+     * 游戏角色id
+     */
+    @ApiModelProperty(notes = "游戏角色id")
+    private String roleId;
+
+    /**
+     * 角色等级
+     */
+    @ApiModelProperty(notes = "角色等级")
+    private Long roleLevel;
+
+    /**
+     * 游戏战力
+     */
+    @ApiModelProperty(notes = "游戏战力")
+    private Long rolePower;
+
+    /**
+     * 角色vip
+     */
+    @ApiModelProperty(notes = "角色vip")
+    private Long roleVipLevel;
+
+    /**
+     * 操作系统
+     */
+    @ApiModelProperty(notes = "操作系统")
+    private String os;
+
+    /**
+     * 充值金额
+     */
+    @ApiModelProperty(notes = "充值金额")
+    private BigDecimal rechargeMoney;
+
+    /**
+     * 平台币余额
+     */
+    @ApiModelProperty(notes = "平台币余额")
+    private BigDecimal platformCoin;
+
+    /**
+     * 充值次数
+     */
+    @ApiModelProperty(notes = "充值次数")
+    private Integer rechargeCount;
+
+    /**
+     * 角色创建时间
+     */
+    @ApiModelProperty(notes = "角色创建时间")
+    private LocalDateTime createTime;
+
+    /**
+     * 最近登录时间
+     */
+    @ApiModelProperty(notes = "最近登录时间")
+    private LocalDateTime lastLoginTime;
+
+    /**
+     * 游戏角色更新时间
+     */
+    @ApiModelProperty(notes = "游戏角色更新时间")
+    private LocalDateTime updateTime;
+
+    /**
+     * 最近充值时间
+     */
+    @ApiModelProperty(notes = "最近充值时间")
+    private LocalDateTime lastRechargeTime;
+
+    /**
+     * 归因投放人员id
+     */
+    @ApiModelProperty(notes = "归因投放人员id")
+    private Long pitcherId;
+
+    /**
+     * 归因投放人员名字
+     */
+    @ApiModelProperty(notes = "归因投放人员名字")
+    private String pitcherName;
+
+    /**
+     * 归因推广账号id
+     */
+    @ApiModelProperty(notes = "归因推广账号id")
+    private Long accountId;
+
+    /**
+     * 归因推广账号类型(1:腾讯、2:头条)
+     */
+    @ApiModelProperty(notes = "归因推广账号类型(1:腾讯、2:头条)")
+    private Integer accountType;
+
+    /**
+     * 注册充值时间差
+     */
+    @ApiModelProperty(notes = "注册充值时间差")
+    private Long regPayTimeDiff;
+
 }

+ 0 - 16
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/IPlayerDataService.java

@@ -1,9 +1,7 @@
 package com.zanxiang.game.data.serve.service;
 
 import com.zanxiang.game.data.serve.pojo.dto.PlayerDataListDTO;
-import com.zanxiang.game.data.serve.pojo.dto.PlayerDataListTotalDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerRoleDataListDTO;
-import com.zanxiang.game.data.serve.pojo.dto.PlayerRoleDataListTotalDTO;
 import com.zanxiang.game.data.serve.pojo.vo.PlayerDataVO;
 import com.zanxiang.game.data.serve.pojo.vo.PlayerRoleDataVO;
 import com.zanxiang.game.data.serve.utils.Page;
@@ -22,13 +20,6 @@ public interface IPlayerDataService {
      */
     Page<PlayerDataVO> getPlayerDataList(PlayerDataListDTO dto);
 
-    /**
-     * 玩家列表总计一栏
-     * @param dto PlayerDataListTotalDTO
-     * @return PlayerDataVO
-     */
-    PlayerDataVO getPlayerDataListTotal(PlayerDataListTotalDTO dto);
-
     /**
      * 玩家角色列表
      * @param dto PlayerRoleDataListDTO
@@ -36,11 +27,4 @@ public interface IPlayerDataService {
      */
     Page<PlayerRoleDataVO> getPlayerRoleDataList(PlayerRoleDataListDTO dto);
 
-    /**
-     * 玩家角色列表总计一栏
-     * @param dto PlayerRoleDataListTotalDTO
-     * @return PlayerRoleDataVO
-     */
-    PlayerRoleDataVO getPlayerRoleDataListTotal(PlayerRoleDataListTotalDTO dto);
-
 }

+ 15 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/IRoleManageService.java

@@ -0,0 +1,15 @@
+package com.zanxiang.game.data.serve.service;
+
+import com.zanxiang.game.data.serve.pojo.dto.RoleCombatRankingDTO;
+import com.zanxiang.game.data.serve.pojo.dto.RoleRechargeRankingDTO;
+import com.zanxiang.game.data.serve.utils.Page;
+
+import java.util.Map;
+
+public interface IRoleManageService {
+
+    Page<Map> getRoleRechargeRanking(RoleRechargeRankingDTO dto);
+
+    Page<Map> getRoleCombatRanking(RoleCombatRankingDTO dto);
+
+}

+ 348 - 18
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PlayerDataServiceImpl.java

@@ -1,15 +1,29 @@
 package com.zanxiang.game.data.serve.service.impl;
 
+import com.zanxiang.game.data.serve.component.DataPowerComponent;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerDataListDTO;
-import com.zanxiang.game.data.serve.pojo.dto.PlayerDataListTotalDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerRoleDataListDTO;
-import com.zanxiang.game.data.serve.pojo.dto.PlayerRoleDataListTotalDTO;
+import com.zanxiang.game.data.serve.pojo.enums.GameCategoryEnum;
+import com.zanxiang.game.data.serve.pojo.enums.OrderByEnum;
 import com.zanxiang.game.data.serve.pojo.vo.PlayerDataVO;
 import com.zanxiang.game.data.serve.pojo.vo.PlayerRoleDataVO;
 import com.zanxiang.game.data.serve.service.IPlayerDataService;
 import com.zanxiang.game.data.serve.utils.Page;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.nutz.dao.Cnd;
+import org.nutz.dao.Dao;
+import org.nutz.dao.Sqls;
+import org.nutz.dao.pager.Pager;
+import org.nutz.dao.sql.Criteria;
+import org.nutz.dao.sql.Sql;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
 /**
  * @author tianhua
  * @time 2023/9/6
@@ -18,6 +32,11 @@ import org.springframework.stereotype.Service;
 @Service
 public class PlayerDataServiceImpl implements IPlayerDataService {
 
+    @Autowired
+    private Dao dao;
+    @Autowired
+    private DataPowerComponent dataPowerComponent;
+
     /**
      * 玩家列表
      * @param dto PlayerDataListDTO
@@ -25,17 +44,145 @@ public class PlayerDataServiceImpl implements IPlayerDataService {
      */
     @Override
     public Page<PlayerDataVO> getPlayerDataList(PlayerDataListDTO dto) {
-        return null;
-    }
+        List<Long> gameIds = dto.getGameId() == null ? dataPowerComponent.getSubGameIdList() : Collections.singletonList(dto.getGameId());
+        List<Long> pitcherIds = StringUtils.isBlank(dto.getPitcherId()) ? dataPowerComponent.getSubUserIdList() : Collections.singletonList(Long.valueOf(dto.getPitcherId()));
 
-    /**
-     * 玩家列表总计一栏
-     * @param dto PlayerDataListTotalDTO
-     * @return PlayerDataVO
-     */
-    @Override
-    public PlayerDataVO getPlayerDataListTotal(PlayerDataListTotalDTO dto) {
-        return null;
+        //创建查询条件
+        Criteria cri = Cnd.cri();
+        if (StringUtils.isNotBlank(dto.getSourceSystem())) {
+            cri.where().andEquals("source_system", dto.getSourceSystem());
+        }
+        if (dto.getUserId() != null) {
+            cri.where().andEquals("id", dto.getUserId());
+        }
+        if (StringUtils.isNotBlank(dto.getUserName())) {
+            cri.where().andLike("username", dto.getUserName());
+        }
+        if (StringUtils.isNotBlank(dto.getNickname())) {
+            cri.where().andLike("nickname", dto.getNickname());
+        }
+        if (StringUtils.isNotBlank(dto.getMobile())) {
+            cri.where().andEquals("mobile", dto.getMobile());
+        }
+        if (StringUtils.isNotBlank(dto.getRegIp())) {
+            cri.where().andEquals("reg_ip", dto.getRegIp());
+        }
+        if (pitcherIds != null) {
+            cri.where().andInList("pitcher_id", pitcherIds);
+        }
+        //判断是否绑定手机
+        if (BooleanUtils.isFalse(dto.getIsBindMobile())) {
+            cri.where().andIsNull("mobile");
+        }
+        if (BooleanUtils.isTrue(dto.getIsBindMobile())) {
+            cri.where().andNotIsNull("mobile").andNotEquals("mobile", "null");
+        }
+        //判断是否实名
+        if (BooleanUtils.isFalse(dto.getIsAuth())) {
+            //未实名
+            cri.where().andEquals("authentication", 0);
+        }
+        if (BooleanUtils.isTrue(dto.getIsAuth())) {
+            //实名
+            cri.where().andInList("authentication", List.of(1L, 2L));
+        }
+        if (dto.getCpId() != null) {
+            cri.where().andEquals("cp_id", dto.getCpId());
+        }
+        if (gameIds != null) {
+            cri.where().andInList("game_id", gameIds);
+        }
+        if (dto.getGameCategoryId() != null) {
+            cri.where().andEquals("game_category_id", dto.getGameCategoryId());
+        }
+        if (dto.getRechargeBeginDate() != null && dto.getRechargeEndDate() != null) {
+            //充值时间
+            cri.where().andBetween("last_recharge_time", dto.getRechargeBeginDate(), dto.getRechargeEndDate());
+        }
+        //判断是否充值
+        if (BooleanUtils.isFalse(dto.getIsRecharge())) {
+            //未充值 充值金额为0
+            cri.where().andEquals("recharge_money", 0);
+        }
+        if (BooleanUtils.isTrue(dto.getIsAuth())) {
+            //充值金额大于0
+            cri.where().andNotEquals("recharge_money", 0);
+        }
+        if (dto.getStatus() != null) {
+            cri.where().andEquals("status", dto.getStatus());
+        }
+        if (dto.getChannelId() != null) {
+            //渠道id
+            cri.where().andEquals("agent_id", dto.getChannelId());
+        }
+        if (StringUtils.isNotBlank(dto.getAccountId())) {
+            cri.where().andEquals("account_id", dto.getAccountId());
+        }
+        if (dto.getBeginDate() != null && dto.getEndDate() != null) {
+            //注册时间
+            cri.where().andBetween("create_time", dto.getBeginDate(), dto.getEndDate());
+        }
+        if (dto.getRegPayIntervalTimeMin() != null) {
+            //充值到注册的最小间隔时间(分)
+            cri.where().andGTE("TIMESTAMPDIFF(MINUTE, create_time, last_recharge_time)", dto.getRegPayIntervalTimeMin());
+        }
+        if (dto.getRegPayIntervalTimeMax() != null) {
+            //充值到注册的最大间隔时间(分)
+            cri.where().andLTE("TIMESTAMPDIFF(MINUTE, create_time, last_recharge_time)", dto.getRegPayIntervalTimeMax());
+        }
+        //判断是否创角
+        if (BooleanUtils.isFalse(dto.getCreateRole())) {
+            //未创角 创角数为0
+            cri.where().andEquals("role_count", 0);
+        }
+        if (BooleanUtils.isTrue(dto.getCreateRole())) {
+            //创角数大于0
+            cri.where().andNotEquals("role_count", 0);
+        }
+        if (dto.getRoleCountMin() != null) {
+            //创角最小数
+            cri.where().andGTE("role_count", dto.getRoleCountMin());
+        }
+        if (dto.getRoleCountMax() != null) {
+            //创角最大数
+            cri.where().andLTE("role_count", dto.getRoleCountMax());
+        }
+
+        //设置pager
+        Pager pager = dao.createPager(dto.getPageNum(), dto.getPageSize());
+        //设置查询的记录数
+        Sql countSql = Sqls.create(getPlayerDataListCountSql() + cri);
+        countSql.setCallback(Sqls.callback.integer());
+        dao.execute(countSql);
+        pager.setRecordCount(countSql.getInt());
+        //默认排序
+        if (StringUtils.isBlank(dto.getSortType())) {
+            dto.setSortType(OrderByEnum.DESC.getOrderType());
+        }
+        if (StringUtils.isBlank(dto.getSortFiled())) {
+            cri.getOrderBy().orderBy("update_time", dto.getSortType());
+        } else {
+            cri.getOrderBy().orderBy(dto.getSortFiled(), dto.getSortFiled());
+        }
+        //创建sql查询数据
+        Sql sql = Sqls.create(getPlayerDataListSql() + cri);
+        //sql设置pager
+        sql.setPager(pager);
+        //设置自定义回传对象
+        sql.setCallback(Sqls.callback.entities());
+        sql.setEntity(dao.getEntity(PlayerDataVO.class));
+        //执行sql
+        dao.execute(sql);
+        //处理结果
+        List<PlayerDataVO> list = sql.getList(PlayerDataVO.class).stream().map(vo -> {
+            //通过枚举得到游戏应用类型名称
+            if (vo.getGameCategoryId() != null) {
+                vo.setGameCategoryName(GameCategoryEnum.getNameByCategory(vo.getGameCategoryId()));
+            }
+            return vo;
+        }).collect(Collectors.toList());
+
+        return new Page<>(list, pager);
     }
 
     /**
@@ -49,13 +196,196 @@ public class PlayerDataServiceImpl implements IPlayerDataService {
     }
 
     /**
-     * 玩家角色列表总计一栏
-     * @param dto PlayerRoleDataListTotalDTO
-     * @return PlayerRoleDataVO
+     * 查询玩家列表数据SQL
+     * @return String
      */
-    @Override
-    public PlayerRoleDataVO getPlayerRoleDataListTotal(PlayerRoleDataListTotalDTO dto) {
-        return null;
+    private String getPlayerDataListSql() {
+        return """
+                SELECT
+                *
+                FROM (
+                    select
+                        a.source_system as source_system ,
+                        a.id as id ,
+                        a.username as username ,
+                        a.nickname as nickname ,
+                        a.ip as reg_ip,
+                        a.create_time as create_time ,
+                        a.agent_id as agent_id ,
+                        if(a.agent_id = 0, '自然量', c.agent_name) as agent_name ,
+                        f.id as cp_id ,
+                        f.cp_name as cp_name ,
+                        a.game_id as game_id ,
+                        e.game_name as game_name ,
+                        e.classify as game_category_id ,
+                        d.zx_pitcher_name as pitcher_name ,
+                        d.zx_pitcher_id as pitcher_id ,
+                        c.account_id as account_id,
+                        c.account_type as account_type,
+                        a.mobile as mobile ,
+                        IFNULL(i.amount, 0) as recharge_money ,
+                        IFNULL(i.amount_count, 0) as recharge_count,
+                        IFNULL(b.role_num, 0) as role_count,
+                        b.create_time as update_time ,
+                        b.last_recharge_time as last_recharge_time,
+                        a.status as status ,
+                        b.role_name as last_game_role_name ,
+                        h.id as relation_game_id ,
+                        h.game_name as relation_game_name ,
+                        a.relation_user_id as relation_user_id ,
+                        a.relation_create_time as relation_create_time ,
+                        TIMESTAMPDIFF(SECOND , a.create_time, b.last_recharge_time) as reg_pay_time_diff
+                    FROM dm_game_order.t_game_user a
+                    left join (
+                        select
+                            a.source_system ,
+                            a.user_id ,
+                            a.role_name ,
+                            a.create_time ,
+                            b.last_recharge_time ,
+                            a.num,
+                            c.role_num
+                            from (
+                                select
+                                        source_system ,
+                                        user_id ,
+                                        role_name ,
+                                        create_time ,
+                                        ROW_NUMBER() OVER(PARTITION BY user_id,source_system order by create_time desc) as num
+                                    from dm_game_order.t_user_login_log
+                                ) a
+                            left join (
+                                select
+                                        source_system as b_source_system,
+                                        user_id as b_user_id,
+                                        role_name as role_name,
+                                        last_recharge_time ,
+                                        ROW_NUMBER() OVER(PARTITION BY user_id,source_system order by last_recharge_time desc) as b_num
+                                from dm_game_order.t_game_user_role
+                                ) b on a.user_id = b.b_user_id and a.source_system = b.b_source_system and a.num= b.b_num
+                            left join (
+                                select
+                                        source_system as c_source_system,
+                                        user_id as c_user_id,
+                                        count(user_id) as role_num
+                                from dm_game_order.t_game_user_role
+                                group by user_id , source_system
+                            ) c on a.user_id = c.c_user_id and a.source_system = c.c_source_system
+                            WHERE a.num = 1
+                    )b on a.id =b.user_id and a.source_system = b.source_system
+                    left join dm_game_order.t_pitcher_agent c on a.agent_id =c.id and a.source_system = c.source_system
+                    left join dm_game_order.t_pitcher_map d on c.pitcher_id =d.zx_pitcher_id and c.source_system = d.source_system
+                    left join dm_game_order.t_game e on a.game_id =e.id  and a.source_system = e.source_system
+                    left join dm_game_order.t_cp f on e.cp_id  =f.id and e.source_system = f.source_system
+                    left join dm_game_order.t_game_user g on a.relation_user_id = g.id and a.source_system = g.source_system
+                    left join dm_game_order.t_game h on g.game_id = h.id and g.source_system = h.source_system
+                    LEFT JOIN (
+                        select
+                            user_id ,
+                            source_system ,
+                            SUM(real_amount) as amount ,
+                            COUNT(user_id) as amount_count
+                        from dm_game_order.t_game_order
+                        group by user_id , source_system
+                    ) i on a.id = i.user_id and a.source_system = i.source_system
+                ) k
+                """;
+    }
+
+    /**
+     * 查询记录的条数SQL
+     * @return String
+     */
+    private String getPlayerDataListCountSql() {
+        return """
+                SELECT
+                    COUNT(1)
+                FROM (
+                    select
+                        a.source_system as source_system ,
+                        a.id as id ,
+                        a.username as username ,
+                        a.nickname as nickname ,
+                        a.ip as reg_ip,
+                        a.create_time as create_time ,
+                        a.agent_id as agent_id ,
+                        if(a.agent_id = 0, '自然量', c.agent_name) as agent_name ,
+                        f.id as cp_id ,
+                        f.cp_name as cp_name ,
+                        a.game_id as game_id ,
+                        e.game_name as game_name ,
+                        e.classify as game_category_id ,
+                        d.zx_pitcher_name as pitcher_name ,
+                        d.zx_pitcher_id as pitcher_id ,
+                        c.account_id as account_id,
+                        c.account_type as account_type,
+                        a.mobile as mobile ,
+                        IFNULL(i.amount, 0) as recharge_money ,
+                        IFNULL(i.amount_count, 0) as recharge_count,
+                        IFNULL(b.role_num, 0) as role_count,
+                        b.create_time as update_time ,
+                        b.last_recharge_time as last_recharge_time,
+                        a.status as status ,
+                        b.role_name as last_game_role_name ,
+                        h.id as relation_game_id ,
+                        h.game_name as relation_game_name ,
+                        a.relation_user_id as relation_user_id ,
+                        a.relation_create_time as relation_create_time
+                    FROM dm_game_order.t_game_user a
+                    left join (
+                        select
+                            a.source_system ,
+                            a.user_id ,
+                            a.role_name ,
+                            a.create_time ,
+                            b.last_recharge_time ,
+                            a.num,
+                            c.role_num
+                            from (
+                                select
+                                        source_system ,
+                                        user_id ,
+                                        role_name ,
+                                        create_time ,
+                                        ROW_NUMBER() OVER(PARTITION BY user_id,source_system order by create_time desc) as num
+                                    from dm_game_order.t_user_login_log
+                                ) a
+                            left join (
+                                select
+                                        source_system as b_source_system,
+                                        user_id as b_user_id,
+                                        role_name as role_name,
+                                        last_recharge_time ,
+                                        ROW_NUMBER() OVER(PARTITION BY user_id,source_system order by last_recharge_time desc) as b_num
+                                from dm_game_order.t_game_user_role
+                                ) b on a.user_id = b.b_user_id and a.source_system = b.b_source_system and a.num= b.b_num
+                            left join (
+                                select
+                                        source_system as c_source_system,
+                                        user_id as c_user_id,
+                                        count(user_id) as role_num
+                                from dm_game_order.t_game_user_role
+                                group by user_id , source_system
+                            ) c on a.user_id = c.c_user_id and a.source_system = c.c_source_system
+                            WHERE a.num = 1
+                    )b on a.id =b.user_id and a.source_system = b.source_system
+                    left join dm_game_order.t_pitcher_agent c on a.agent_id =c.id and a.source_system = c.source_system
+                    left join dm_game_order.t_pitcher_map d on c.pitcher_id =d.zx_pitcher_id and c.source_system = d.source_system
+                    left join dm_game_order.t_game e on a.game_id =e.id  and a.source_system = e.source_system
+                    left join dm_game_order.t_cp f on e.cp_id  =f.id and e.source_system = f.source_system
+                    left join dm_game_order.t_game_user g on a.relation_user_id = g.id and a.source_system = g.source_system
+                    left join dm_game_order.t_game h on g.game_id = h.id and g.source_system = h.source_system
+                    LEFT JOIN (
+                        select
+                            user_id ,
+                            source_system ,
+                            SUM(real_amount) as amount ,
+                            COUNT(user_id) as amount_count
+                        from dm_game_order.t_game_order
+                        group by user_id , source_system
+                    ) i on a.id = i.user_id and a.source_system = i.source_system
+                ) k
+                """;
     }
 
 }

+ 802 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/RoleManageServiceImpl.java

@@ -0,0 +1,802 @@
+package com.zanxiang.game.data.serve.service.impl;
+
+import com.zanxiang.erp.base.ErpServer;
+import com.zanxiang.erp.base.rpc.ISysUserRpc;
+import com.zanxiang.game.data.serve.pojo.dto.RoleCombatRankingDTO;
+import com.zanxiang.game.data.serve.pojo.dto.RoleRechargeRankingDTO;
+import com.zanxiang.game.data.serve.pojo.enums.OrderByEnum;
+import com.zanxiang.game.data.serve.service.IRoleManageService;
+import com.zanxiang.game.data.serve.utils.Page;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.nutz.dao.Cnd;
+import org.nutz.dao.Dao;
+import org.nutz.dao.Sqls;
+import org.nutz.dao.pager.Pager;
+import org.nutz.dao.sql.Criteria;
+import org.nutz.dao.sql.Sql;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author tianhua
+ * @time 2023/9/8
+ * @Description 角色运营管理逻辑处理
+ **/
+@Service
+@Slf4j
+public class RoleManageServiceImpl implements IRoleManageService {
+
+    @Autowired
+    private Dao dao;
+
+    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
+    private ISysUserRpc sysUserRpc;
+
+    /**
+     * 角色充值排行榜
+     * @param dto RoleRechargeRankingDTO
+     * @return Page<List<Map<String, Object>>>
+     */
+    @Override
+    public Page<Map> getRoleRechargeRanking(RoleRechargeRankingDTO dto) {
+        //创建查询条件 给主表使用
+        Criteria criA = Cnd.cri();
+        if (dto.getGameId() != null) {
+            criA.where().andEquals("role_reg_game_id", dto.getGameId());
+        }
+        if (StringUtils.isNotBlank(dto.getSourceSystem())) {
+            criA.where().andEquals("source_system", dto.getSourceSystem());
+        }
+        if (StringUtils.isNotBlank(dto.getRoleId())) {
+            criA.where().andEquals("role_id", dto.getRoleId());
+        }
+        if (StringUtils.isNotBlank(dto.getRoleName())) {
+            criA.where().andLike("role_name", dto.getRoleName());
+        }
+        if (dto.getCreateRoleBeginDate() != null && dto.getCreateRoleEndDate() != null) {
+            //角色创建时间
+            criA.where().andBetween("role_create_time", dto.getCreateRoleBeginDate(), dto.getCreateRoleEndDate());
+        }
+        if (dto.getVipLevel() != null) {
+            criA.where().andEquals("vip_level", dto.getVipLevel());
+        }
+        if (dto.getIsSendMail() != null) {
+            criA.where().andEquals("is_send_mail", dto.getIsSendMail());
+        }
+        if (dto.getIsChange() != null) {
+            criA.where().andEquals("is_change", dto.getIsChange());
+        }
+        if (StringUtils.isNotBlank(dto.getWeChatCompany())) {
+            criA.where().andLike("we_chat_company", dto.getWeChatCompany());
+        }
+        if (StringUtils.isNotBlank(dto.getWeChat())) {
+            criA.where().andLike("we_chat", dto.getWeChat());
+        }
+        if (StringUtils.isNotBlank(dto.getPhone())) {
+            criA.where().andEquals("phone", dto.getPhone());
+        }
+        if (dto.getGsId() != null) {
+            criA.where().andEquals("gs_id", dto.getGsId());
+        }
+        if (dto.getPitcherId() != null) {
+            criA.where().andEquals("pitcher_id", dto.getPitcherId());
+        }
+        if (dto.getOperatorId() != null) {
+            criA.where().andEquals("operator_id", dto.getOperatorId());
+        }
+        if (dto.getCustomerServerId() != null) {
+            criA.where().andEquals("customer_server_id", dto.getCustomerServerId());
+        }
+        //给充值时间查询条件
+        Criteria criTodayAmount = Cnd.cri();
+        //查询充值成功的
+        criTodayAmount.where().andEquals("status", 2);
+        if (dto.getRechargeBeginDate() != null && dto.getRechargeEndDate() != null) {
+            //充值时间限制
+            criTodayAmount.where().andBetween("DATE(pay_time)", dto.getRechargeBeginDate(), dto.getRechargeEndDate());
+        }
+        //分页对象
+        Pager pager = dao.createPager(dto.getPageNum(), dto.getPageSize());
+        //查询总记录数
+        Sql countSql = Sqls.create(getCountNumSql(criA, criTodayAmount));
+        countSql.setCallback(Sqls.callback.integer());
+        dao.execute(countSql);
+        pager.setRecordCount(countSql.getInt());
+        //主表添加排序条件
+        if (StringUtils.isBlank(dto.getSortType())) {
+            dto.setSortType(OrderByEnum.DESC.getOrderType());
+        }
+        if (StringUtils.isBlank(dto.getSortFiled())) {
+            criA.getOrderBy().orderBy("amount", dto.getSortType());
+        } else {
+            criA.getOrderBy().orderBy(dto.getSortFiled(), dto.getSortType());
+        }
+        //创建sql
+        Sql sql = Sqls.create(getRoleRechargeRankingSql(criA, criTodayAmount));
+        sql.setCallback(Sqls.callback.maps());
+        sql.setPager(pager);
+        dao.execute(sql);
+        List<Map> list = sql.getList(Map.class).stream().map(map -> getNameById(map)).collect(Collectors.toList());
+
+        //返回结果
+        return new Page<>(list, pager);
+    }
+
+    /**
+     * 角色战力排行榜
+     * @param dto RoleCombatRankingDTO
+     * @return Page<List<Map<String, Object>>>
+     */
+    @Override
+    public Page<Map> getRoleCombatRanking(RoleCombatRankingDTO dto) {
+        return null;
+    }
+
+    /**
+     * 通过id获取 GS、运营、客服人员、投手名字
+     * @param dataMap dataMap
+     * @return String
+     */
+    private Map<String, Object> getNameById(Map<String, Object> dataMap){
+        //投手名
+        if (dataMap.get("put_user_id") != null) {
+            dataMap.put("put_user_name",
+                    sysUserRpc.getById(Long.valueOf((String) dataMap.get("put_user_id"))).getData().getNickname());
+        }
+        //运营人员名
+        if (dataMap.get("oper_user_id") != null) {
+            dataMap.put("oper_user_name",
+                    sysUserRpc.getById(Long.valueOf((String) dataMap.get("oper_user_id"))).getData().getNickname());
+        }
+        //GS人员名
+        if (dataMap.get("gs_id") != null) {
+            dataMap.put("gs_name",
+                    sysUserRpc.getById(Long.valueOf((String) dataMap.get("gs_id"))).getData().getNickname());
+        }
+        //客服人员名
+        if (dataMap.get("customer_service_id") != null) {
+            dataMap.put("customer_service_name",
+                    sysUserRpc.getById(Long.valueOf((String) dataMap.get("customer_service_id"))).getData().getNickname());
+        }
+
+        return dataMap;
+    }
+
+    /**
+     * 查询角色充值排行榜sql
+     * @param criA 主表查询条件
+     * @param criTodayAmount 当天充值金额相关的查询条件
+     * @return String
+     */
+    private String getRoleRechargeRankingSql(Criteria criA, Criteria criTodayAmount){
+        return """
+                SELECT
+                	*
+                FROM
+                (
+                	SELECT
+                		a.association_user_id as association_user_id, -- 来源的用户id
+                		a.source_system as source_system, -- sdk来源
+                		a.role_id as role_id, -- 角色id
+                		a.role_name as role_name, -- 角色名
+                		a.create_time as role_create_time, -- 角色创建时间
+                		a.os as os, -- 角色操作系统
+                		b.role_level as role_level, -- 角色等级
+                		b.combat_num as combat_num, -- 角色攻击力
+                		IFNULL(c.amount, 0) as amount, -- 角色累计充值金额
+                		IFNULL(c.amount_count, 0) as amount_count, -- 角色累计充值次数
+                		ROUND(IF(c.amount_count > 0, c.amount / c.amount_count, 0), 2) as avg_amount, -- 平均单价
+                		(CASE
+                			WHEN c.amount >= 0 and c.amount < 2000 THEN '1'
+                			WHEN c.amount >= 2000 and c.amount < 5000 THEN '2'
+                			WHEN c.amount >= 5000 and c.amount < 10000 THEN '3'
+                			WHEN c.amount >= 10000 and c.amount < 20000 THEN '4'
+                			WHEN c.amount >= 20000 and c.amount < 50000 THEN '5'
+                			WHEN c.amount >= 50000 THEN '6'
+                			ELSE '0'
+                			END) as vip_level, -- 角色vip等级
+                		a.game_id as role_reg_game_id, -- 角色注册游戏id
+                		d.game_name as role_reg_game_name, -- 角色注册游戏名
+                		d.classify as role_reg_game_classify, -- 角色注册游戏类型
+                		IFNULL(d.parent_id, a.game_id) as role_reg_parent_game_id, -- 角色注册游戏的父游戏id
+                		IFNULL(e.parent_game_name, d.game_name) as role_reg_parent_game_name, -- 角色注册游戏的父游戏名
+                		a.server_id as server_id, -- 角色所在区服id
+                		q.server_name as server_name, -- 角色所在区服名
+                		IFNULL(f.real_amount, 0) as role_last_amount, -- 角色最近充值金额
+                		f.pay_time as role_last_pay_time, -- 角色最近充值时间
+                		g.active_time as role_active_time, -- 角色最近活跃时间
+                		IFNULL(h.real_amount, 0) as role_first_amount, -- 角色首次充值金额
+                		p.today_amount as today_amount, -- 角色当天充值金额
+                		TIMESTAMPDIFF(SECOND, a.create_time, f.pay_time) as role_reg_pay_time, -- 角色创建充值时间差(秒)
+                		TIMESTAMPDIFF(SECOND, f.pay_time, NOW()) as role_pay_until_now, -- 角色最近充值距今(秒)
+                		a.user_id as user_id, -- 玩家id
+                	    i.username as username, -- 玩家名称
+                	    i.nickname as nickname, -- 玩家昵称
+                	    i.reg_mobile as reg_mobile, -- 玩家注册手机
+                	    i.reg_email as reg_email, -- 玩家注册邮箱
+                	    i.user_create_time as user_create_time, -- 玩家注册时间
+                	    i.user_reg_game_id as user_reg_game_id, -- 玩家注册游戏id
+                	    i.user_reg_game_name as user_reg_game_name, -- 玩家注册游戏名
+                	    i.agent_id as agent_id, -- 玩家注册渠道id
+                	    IF(i.agent_id = 0 , '自然量', i.agent_name) as agent_name, -- 玩家注册渠道名
+                	    i.put_user_id as put_user_id, -- 投手id
+                	    i.user_active_time as user_active_time, -- 玩家最近活跃时间
+                	    i.user_last_recharge_game_id as user_last_recharge_game_id, -- 玩家最近充值游戏id
+                	    i.user_last_recharge_game_name as user_last_recharge_game_name, -- 玩家最近充值游戏名
+                		i.user_pay_time as user_pay_time, -- 玩家最近充值时间
+                		TIMESTAMPDIFF(SECOND, i.user_create_time, i.user_pay_time) as user_reg_pay_time, -- 玩家注册充值时间差(秒)
+                		TIMESTAMPDIFF(SECOND, i.user_pay_time, NOW()) as user_pay_until_now, -- 玩家最近充值距今(秒)
+                		j.is_send_mail as is_send_mail, -- 是否发送邮件
+                		j.send_gift_id as send_gift_id, -- 最新发送礼包id
+                		j.is_change_game_type as is_change_game_type, -- 是否转端 1-是;0-否
+                		j.is_add_corp_wechat as is_add_corp_wechat, -- 是否添加企微 1-是; 0-否
+                		j.add_corp_user_id as add_corp_user_id, -- 企微号
+                		j.user_wechat as user_wechat, -- 客户微信号
+                		j.user_phone as user_phone, -- 客户手机号
+                		j.is_remove_game as is_remove_game, -- 是否退游 1-是;0-否
+                		j.is_wake_up as is_wake_up, -- 是否唤醒 1-是;0-否
+                		j.remark as remark, -- 备注
+                		j.gs_id as gs_id, -- GS_ID
+                		j.customer_service_id as customer_service_id, -- 客服ID
+                		j.oper_user_id as oper_user_id, -- 运营ID
+                		j.create_time as create_time, -- 创建时间
+                		j.create_by as create_by, -- 创建者
+                		j.update_time as update_time, -- 更新时间
+                		j.update_by as update_by, -- 更新者
+                		j.is_delete as is_delete -- 是否删除 1-删除;0-正常
+                	FROM
+                	(
+                		SELECT
+                			*
+                		FROM
+                		(
+                			SELECT
+                				-- 角色所在子游戏id、区服id、合服id、角色id、角色名、角色创建时间、角色操作系统os(取创建时间最早的信息)
+                				b.association_user_id ,
+                				a.source_system,
+                				a.user_id,
+                				a.game_id,
+                				a.server_id,
+                				a.role_id,
+                				a.role_name,
+                				a.create_time,
+                				a.os,
+                				ROW_NUMBER()over(partition by a.role_id , a.source_system order by a.create_time asc, a.user_id asc) as num
+                			FROM dm_game_order.t_game_user_role a
+                			LEFT JOIN dm_game_order.t_game_user b on a.source_system = b.source_system AND a.user_id = b.id
+                		) a
+                		WHERE num = 1
+                	) a
+                	LEFT JOIN (
+                		SELECT
+                			-- 角色等级、角色攻击力(取最新的信息)
+                			source_system,
+                			role_id,
+                			role_level,
+                			combat_num,
+                			ROW_NUMBER()over(partition by role_id , source_system order by update_time desc, user_id desc) as num
+                		FROM dm_game_order.t_game_user_role
+                	) b on a.source_system = b.source_system AND a.role_id = b.role_id AND b.num = 1
+                	LEFT JOIN (
+                		SELECT
+                			-- 累计充值金额、累计充值次数
+                	    	role_id,
+                	    	source_system,
+                	    	SUM(real_amount) as amount ,
+                	    	COUNT(user_id) as amount_count
+                		FROM dm_game_order.t_game_order
+                		WHERE status =2
+                		GROUP BY role_id , source_system
+                	) c on a.source_system = c.source_system AND a.role_id = c.role_id
+                	LEFT JOIN (
+                		SELECT
+                			-- 游戏名称、游戏类型、父游戏id
+                			source_system,
+                			id,
+                			game_name,
+                			classify,
+                			parent_id
+                		FROM dm_game_order.t_game
+                	) d on a.source_system = d.source_system AND a.game_id = d.id
+                	LEFT JOIN (
+                		SELECT
+                			-- 父游戏名称
+                			source_system,
+                			id,
+                			game_name as parent_game_name
+                		FROM dm_game_order.t_game
+                	) e on d.source_system = e.source_system AND d.parent_id = e.id
+                	LEFT JOIN (
+                		SELECT
+                			-- 角色最近充值时间、角色最近充值金额
+                			source_system,
+                			role_id,
+                			real_amount,
+                			pay_time,
+                			ROW_NUMBER()over(partition by role_id , source_system order by pay_time desc) as num
+                		FROM dm_game_order.t_game_order
+                		WHERE status =2
+                	) f on a.source_system = f.source_system AND a.role_id = f.role_id AND f.num = 1
+                	LEFT JOIN (
+                		-- 角色最近活跃时间
+                		SELECT
+                			source_system,
+                			role_id,
+                			active_time,
+                			ROW_NUMBER()over(partition by role_id , source_system order by active_time desc) as num
+                		FROM dm_game_order.t_active_log
+                	) g on a.source_system = g.source_system AND a.role_id = g.role_id AND g.num = 1
+                	LEFT JOIN (
+                		SELECT
+                			-- 角色首次充值金额
+                			source_system,
+                			role_id,
+                			real_amount,
+                			ROW_NUMBER()over(partition by role_id , source_system order by pay_time asc) as num
+                		FROM dm_game_order.t_game_order  WHERE status =2
+                	) h on a.source_system = h.source_system AND a.role_id = h.role_id AND h.num = 1
+                	LEFT JOIN (
+                		SELECT
+                			-- 角色当天充值金额
+                			source_system,
+                			role_id,
+                			SUM(real_amount) as today_amount
+                		FROM dm_game_order.t_game_order
+                """ + criTodayAmount +
+                """
+                		GROUP BY role_id ,source_system
+                	) p on a.source_system = p.source_system AND a.role_id = p.role_id
+                	LEFT JOIN (
+                		SELECT
+                			-- 区服名
+                			source_system ,
+                			game_id,
+                			server_id,
+                			server_name
+                		FROM dm_game_order.t_game_server
+                	) q on a.source_system = q.source_system AND a.game_id = q.game_id AND a.server_id = q.server_id
+                	LEFT JOIN (
+                		-- 玩家信息
+                		-- 玩家ID、玩家账号、玩家昵称、注册电话、注册邮箱、注册时间、注册游戏、注册渠道
+                		SELECT
+                			i.source_system as source_system,
+                	        i.association_user_id as association_user_id, -- 来源用户id
+                	        i.id as id, -- 玩家id
+                	        i.username as username,
+                	        i.nickname as nickname,
+                	        i.reg_mobile as reg_mobile,
+                	        i.reg_email as reg_email,
+                	        i.user_create_time as user_create_time,
+                	        i.user_reg_game_id as user_reg_game_id,
+                	        k.game_name as user_reg_game_name,
+                	        i.agent_id as agent_id,
+                	        IF(i.agent_id = 0 , '自然量', j.agent_name) as agent_name,
+                	        j.pitcher_id as put_user_id,
+                	        l.active_time as user_active_time,
+                	        m.user_last_recharge_game_id as user_last_recharge_game_id,
+                	        n.game_name as user_last_recharge_game_name, --
+                			m.pay_time as user_pay_time -- 玩家最近充值时间
+                		FROM
+                		(
+                			SELECT
+                				*
+                			FROM
+                			(
+                				SELECT
+                					source_system,
+                					association_user_id, -- 来源用户id
+                					id , -- 玩家id
+                					username ,
+                					nickname ,
+                					reg_mobile ,
+                					reg_email ,
+                					create_time as user_create_time,
+                					game_id as user_reg_game_id,
+                					agent_id ,
+                					ROW_NUMBER()over(partition by association_user_id, source_system order by create_time desc, id asc) as num
+                				FROM dm_game_order.t_game_user
+                			) z WHERE z.num = 1
+                		) i
+                		LEFT JOIN (
+                			SELECT
+                				-- 渠道名称
+                				source_system,
+                				id,
+                				agent_name,
+                				pitcher_id
+                			FROM dm_game_order.t_pitcher_agent
+                		) j ON i.agent_id = j.id AND i.source_system  = j.source_system
+                		LEFT JOIN (
+                			SELECT
+                				-- 玩家注册游戏名
+                				source_system,
+                				id,
+                				game_name
+                			FROM dm_game_order.t_game
+                		) k ON i.user_reg_game_id = k.id AND i.source_system = k.source_system
+                		LEFT JOIN (
+                			-- 玩家最近活跃时间
+                			SELECT
+                				association_user_id,
+                				b.source_system,
+                				b.active_time,
+                				ROW_NUMBER()over(partition by association_user_id, b.source_system order by active_time desc) as num
+                			FROM dm_game_order.t_game_user a
+                			RIGHT JOIN (
+                				SELECT
+                					source_system,
+                					user_id,
+                					active_time
+                				FROM dm_game_order.t_active_log
+                			) b ON a.source_system = b.source_system AND a.id = b.user_id
+                		) l ON i.association_user_id = l.association_user_id AND i.source_system = l.source_system AND l.num = 1
+                		LEFT JOIN (
+                			-- 玩家最近充值游戏、玩家最近充值时间
+                			SELECT
+                				association_user_id,
+                				b.*,
+                				ROW_NUMBER()over(partition by association_user_id, b.source_system order by pay_time desc) as num
+                			FROM dm_game_order.t_game_user a
+                			RIGHT JOIN (
+                				-- 玩家最近充值游戏id、最近充值时间
+                				SELECT
+                					source_system,
+                					user_id,
+                					game_id as user_last_recharge_game_id,
+                					pay_time
+                				FROM dm_game_order.t_game_order
+                				WHERE status = 2
+                			) b on a.id = b.user_id AND a.source_system = b.source_system
+                		) m on i.association_user_id = m.association_user_id AND i.source_system = m.source_system AND m.num = 1
+                		LEFT JOIN (
+                			SELECT
+                				-- 玩家最近充值游戏名
+                				source_system,
+                				id,
+                				game_name
+                			FROM dm_game_order.t_game
+                		) n ON m.user_last_recharge_game_id = n.id AND m.source_system = n.source_system
+                	) i on a.source_system = i.source_system AND a.association_user_id = i.association_user_id
+                	LEFT JOIN (
+                		SELECT
+                		    -- 操作表相关数据
+                		    source_system,
+                		    user_id,
+                		    role_id,
+                		    server_id,
+                		    game_id,
+                			is_send_mail, -- 是否发送邮件
+                            send_gift_id, -- 最新发送礼包id
+                            is_change_game_type, -- 是否转端 1-是;0-否
+                            is_add_corp_wechat, -- 是否添加企微 1-是; 0-否
+                            add_corp_user_id, -- 企微号
+                            user_wechat, -- 客户微信号
+                            user_phone, -- 客户手机号
+                            is_remove_game, -- 是否退游 1-是;0-否
+                            is_wake_up, -- 是否唤醒 1-是;0-否
+                            remark, -- 备注
+                            gs_id, -- GS_ID
+                            customer_service_id, -- 客服ID
+                            oper_user_id, -- 运营ID
+                            create_time, -- 创建时间
+                            create_by, -- 创建者
+                            update_time, -- 更新时间
+                            update_by, -- 更新者
+                            is_delete -- 是否删除 1-删除;0-正常
+                		FROM dm_game_order.t_role_operate
+                	) j on a.source_system = j.source_system AND a.association_user_id = j.user_id AND
+                	a.role_id = j.role_id AND a.server_id = j.server_id AND a.game_id = j.game_id
+                ) a
+                """ + criA;
+    }
+
+    /**
+     * 查询记录数
+     * @param criA 主表条件
+     * @param criTodayAmount 今日充值条件
+     * @return String
+     */
+    private String getCountNumSql(Criteria criA, Criteria criTodayAmount) {
+        return """
+                SELECT
+                	COUNT(1)
+                FROM
+                (
+                	SELECT
+                		a.association_user_id as association_user_id, -- 来源的用户id
+                		a.source_system as source_system, -- sdk来源
+                		a.role_id as role_id, -- 角色id
+                		a.role_name as role_name, -- 角色名
+                		a.create_time as role_create_time, -- 角色创建时间
+                		a.os as os, -- 角色操作系统
+                		b.role_level as role_level, -- 角色等级
+                		b.combat_num as combat_num, -- 角色攻击力
+                		IFNULL(c.amount, 0) as amount, -- 角色累计充值金额
+                		IFNULL(c.amount_count, 0) as amount_count, -- 角色累计充值次数
+                		ROUND(IF(c.amount_count > 0, c.amount / c.amount_count, 0), 2) as avg_amount, -- 平均单价
+                		(CASE
+                			WHEN c.amount >= 0 and c.amount < 2000 THEN '1'
+                			WHEN c.amount >= 2000 and c.amount < 5000 THEN '2'
+                			WHEN c.amount >= 5000 and c.amount < 10000 THEN '3'
+                			WHEN c.amount >= 10000 and c.amount < 20000 THEN '4'
+                			WHEN c.amount >= 20000 and c.amount < 50000 THEN '5'
+                			WHEN c.amount >= 50000 THEN '6'
+                			ELSE '0'
+                			END) as vip_level, -- 角色vip等级
+                		a.game_id as role_reg_game_id, -- 角色注册游戏id
+                		d.game_name as role_reg_game_name, -- 角色注册游戏名
+                		d.classify as role_reg_game_classify, -- 角色注册游戏类型
+                		IFNULL(d.parent_id, a.game_id) as role_reg_parent_game_id, -- 角色注册游戏的父游戏id
+                		IFNULL(e.parent_game_name, d.game_name) as role_reg_parent_game_name, -- 角色注册游戏的父游戏名
+                		a.server_id as server_id, -- 角色所在区服id
+                		q.server_name as server_name, -- 角色所在区服名
+                		IFNULL(f.real_amount, 0) as role_last_amount, -- 角色最近充值金额
+                		f.pay_time as role_last_pay_time, -- 角色最近充值时间
+                		g.active_time as role_active_time, -- 角色最近活跃时间
+                		IFNULL(h.real_amount, 0) as role_first_amount, -- 角色首次充值金额
+                		p.today_amount as today_amount, -- 角色当天充值金额
+                		TIMESTAMPDIFF(SECOND, a.create_time, f.pay_time) as role_reg_pay_time, -- 角色创建充值时间差(秒)
+                		TIMESTAMPDIFF(SECOND, f.pay_time, NOW()) as role_pay_until_now, -- 角色最近充值距今(秒)
+                		a.user_id as user_id, -- 玩家id
+                	    i.username as username, -- 玩家名称
+                	    i.nickname as nickname, -- 玩家昵称
+                	    i.reg_mobile as reg_mobile, -- 玩家注册手机
+                	    i.reg_email as reg_email, -- 玩家注册邮箱
+                	    i.user_create_time as user_create_time, -- 玩家注册时间
+                	    i.user_reg_game_id as user_reg_game_id, -- 玩家注册游戏id
+                	    i.user_reg_game_name as user_reg_game_name, -- 玩家注册游戏名
+                	    i.agent_id as agent_id, -- 玩家注册渠道id
+                	    IF(i.agent_id = 0 , '自然量', i.agent_name) as agent_name, -- 玩家注册渠道名
+                	    i.user_active_time as user_active_time, -- 玩家最近活跃时间
+                	    i.user_last_recharge_game_id as user_last_recharge_game_id, -- 玩家最近充值游戏id
+                	    i.user_last_recharge_game_name as user_last_recharge_game_name, -- 玩家最近充值游戏名
+                		i.user_pay_time as user_pay_time, -- 玩家最近充值时间
+                		TIMESTAMPDIFF(SECOND, i.user_create_time, i.user_pay_time) as user_reg_pay_time, -- 玩家注册充值时间差(秒)
+                		TIMESTAMPDIFF(SECOND, i.user_pay_time, NOW()) as user_pay_until_now, -- 玩家最近充值距今(秒)
+                		j.is_send_mail as is_send_mail, -- 是否发送邮件
+                		j.send_gift_id as send_gift_id, -- 最新发送礼包id
+                		j.is_change_game_type as is_change_game_type, -- 是否转端 1-是;0-否
+                		j.is_add_corp_wechat as is_add_corp_wechat, -- 是否添加企微 1-是; 0-否
+                		j.add_corp_user_id as add_corp_user_id, -- 企微号
+                		j.user_wechat as user_wechat, -- 客户微信号
+                		j.user_phone as user_phone, -- 客户手机号
+                		j.is_remove_game as is_remove_game, -- 是否退游 1-是;0-否
+                		j.is_wake_up as is_wake_up, -- 是否唤醒 1-是;0-否
+                		j.remark as remark, -- 备注
+                		j.gs_id as gs_id, -- GS_ID
+                		j.customer_service_id as customer_service_id, -- 客服ID
+                		j.oper_user_id as oper_user_id, -- 运营ID
+                		j.put_user_id as put_user_id, -- 投手ID
+                		j.create_time as create_time, -- 创建时间
+                		j.create_by as create_by, -- 创建者
+                		j.update_time as update_time, -- 更新时间
+                		j.update_by as update_by, -- 更新者
+                		j.is_delete as is_delete -- 是否删除 1-删除;0-正常
+                	FROM
+                	(
+                		SELECT
+                			*
+                		FROM
+                		(
+                			SELECT
+                				-- 角色所在子游戏id、区服id、合服id、角色id、角色名、角色创建时间、角色操作系统os(取创建时间最早的信息)
+                				b.association_user_id ,
+                				a.source_system,
+                				a.user_id,
+                				a.game_id,
+                				a.server_id,
+                				a.role_id,
+                				a.role_name,
+                				a.create_time,
+                				a.os,
+                				ROW_NUMBER()over(partition by a.role_id , a.source_system order by a.create_time asc, a.user_id asc) as num
+                			FROM dm_game_order.t_game_user_role a
+                			LEFT JOIN dm_game_order.t_game_user b on a.source_system = b.source_system AND a.user_id = b.id
+                		) a
+                		WHERE num = 1
+                	) a
+                	LEFT JOIN (
+                		SELECT
+                			-- 角色等级、角色攻击力(取最新的信息)
+                			source_system,
+                			role_id,
+                			role_level,
+                			combat_num,
+                			ROW_NUMBER()over(partition by role_id , source_system order by update_time desc, user_id desc) as num
+                		FROM dm_game_order.t_game_user_role
+                	) b on a.source_system = b.source_system AND a.role_id = b.role_id AND b.num = 1
+                	LEFT JOIN (
+                		SELECT
+                			-- 累计充值金额、累计充值次数
+                	    	role_id,
+                	    	source_system,
+                	    	SUM(real_amount) as amount ,
+                	    	COUNT(user_id) as amount_count
+                		FROM dm_game_order.t_game_order
+                		WHERE status =2
+                		GROUP BY role_id , source_system
+                	) c on a.source_system = c.source_system AND a.role_id = c.role_id
+                	LEFT JOIN (
+                		SELECT
+                			-- 游戏名称、游戏类型、父游戏id
+                			source_system,
+                			id,
+                			game_name,
+                			classify,
+                			parent_id
+                		FROM dm_game_order.t_game
+                	) d on a.source_system = d.source_system AND a.game_id = d.id
+                	LEFT JOIN (
+                		SELECT
+                			-- 父游戏名称
+                			source_system,
+                			id,
+                			game_name as parent_game_name
+                		FROM dm_game_order.t_game
+                	) e on d.source_system = e.source_system AND d.parent_id = e.id
+                	LEFT JOIN (
+                		SELECT
+                			-- 角色最近充值时间、角色最近充值金额
+                			source_system,
+                			role_id,
+                			real_amount,
+                			pay_time,
+                			ROW_NUMBER()over(partition by role_id , source_system order by pay_time desc) as num
+                		FROM dm_game_order.t_game_order
+                		WHERE status =2
+                	) f on a.source_system = f.source_system AND a.role_id = f.role_id AND f.num = 1
+                	LEFT JOIN (
+                		-- 角色最近活跃时间
+                		SELECT
+                			source_system,
+                			role_id,
+                			active_time,
+                			ROW_NUMBER()over(partition by role_id , source_system order by active_time desc) as num
+                		FROM dm_game_order.t_active_log
+                	) g on a.source_system = g.source_system AND a.role_id = g.role_id AND g.num = 1
+                	LEFT JOIN (
+                		SELECT
+                			-- 角色首次充值金额
+                			source_system,
+                			role_id,
+                			real_amount,
+                			ROW_NUMBER()over(partition by role_id , source_system order by pay_time asc) as num
+                		FROM dm_game_order.t_game_order  WHERE status =2
+                	) h on a.source_system = h.source_system AND a.role_id = h.role_id AND h.num = 1
+                	LEFT JOIN (
+                		SELECT
+                			-- 角色当天充值金额
+                			source_system,
+                			role_id,
+                			SUM(real_amount) as today_amount
+                		FROM dm_game_order.t_game_order
+                """ + criTodayAmount +
+                """
+                		GROUP BY role_id ,source_system
+                	) p on a.source_system = p.source_system AND a.role_id = p.role_id
+                	LEFT JOIN (
+                		SELECT
+                			-- 区服名
+                			source_system ,
+                			game_id,
+                			server_id,
+                			server_name
+                		FROM dm_game_order.t_game_server
+                	) q on a.source_system = q.source_system AND a.game_id = q.game_id AND a.server_id = q.server_id
+                	LEFT JOIN (
+                		-- 玩家信息
+                		-- 玩家ID、玩家账号、玩家昵称、注册电话、注册邮箱、注册时间、注册游戏、注册渠道
+                		SELECT
+                			i.source_system as source_system,
+                	        i.association_user_id as association_user_id, -- 来源用户id
+                	        i.id as id, -- 玩家id
+                	        i.username as username,
+                	        i.nickname as nickname,
+                	        i.reg_mobile as reg_mobile,
+                	        i.reg_email as reg_email,
+                	        i.user_create_time as user_create_time,
+                	        i.user_reg_game_id as user_reg_game_id,
+                	        k.game_name as user_reg_game_name,
+                	        i.agent_id as agent_id,
+                	        IF(i.agent_id = 0 , '自然量', j.agent_name) as agent_name,
+                	        l.active_time as user_active_time,
+                	        m.user_last_recharge_game_id as user_last_recharge_game_id,
+                	        n.game_name as user_last_recharge_game_name, --
+                			m.pay_time as user_pay_time -- 玩家最近充值时间
+                		FROM
+                		(
+                			SELECT
+                				*
+                			FROM
+                			(
+                				SELECT
+                					source_system,
+                					association_user_id, -- 来源用户id
+                					id , -- 玩家id
+                					username ,
+                					nickname ,
+                					reg_mobile ,
+                					reg_email ,
+                					create_time as user_create_time,
+                					game_id as user_reg_game_id,
+                					agent_id ,
+                					ROW_NUMBER()over(partition by association_user_id, source_system order by create_time desc, id asc) as num
+                				FROM dm_game_order.t_game_user
+                			) z WHERE z.num = 1
+                		) i
+                		LEFT JOIN (
+                			SELECT
+                				-- 渠道名称
+                				source_system,
+                				id,
+                				agent_name
+                			FROM dm_game_order.t_pitcher_agent
+                		) j ON i.agent_id = j.id AND i.source_system  = j.source_system
+                		LEFT JOIN (
+                			SELECT
+                				-- 玩家注册游戏名
+                				source_system,
+                				id,
+                				game_name
+                			FROM dm_game_order.t_game
+                		) k ON i.user_reg_game_id = k.id AND i.source_system = k.source_system
+                		LEFT JOIN (
+                			-- 玩家最近活跃时间
+                			SELECT
+                				association_user_id,
+                				b.source_system,
+                				b.active_time,
+                				ROW_NUMBER()over(partition by association_user_id, b.source_system order by active_time desc) as num
+                			FROM dm_game_order.t_game_user a
+                			RIGHT JOIN (
+                				SELECT
+                					source_system,
+                					user_id,
+                					active_time
+                				FROM dm_game_order.t_active_log
+                			) b ON a.source_system = b.source_system AND a.id = b.user_id
+                		) l ON i.association_user_id = l.association_user_id AND i.source_system = l.source_system AND l.num = 1
+                		LEFT JOIN (
+                			-- 玩家最近充值游戏、玩家最近充值时间
+                			SELECT
+                				association_user_id,
+                				b.*,
+                				ROW_NUMBER()over(partition by association_user_id, b.source_system order by pay_time desc) as num
+                			FROM dm_game_order.t_game_user a
+                			RIGHT JOIN (
+                				-- 玩家最近充值游戏id、最近充值时间
+                				SELECT
+                					source_system,
+                					user_id,
+                					game_id as user_last_recharge_game_id,
+                					pay_time
+                				FROM dm_game_order.t_game_order
+                				WHERE status = 2
+                			) b on a.id = b.user_id AND a.source_system = b.source_system
+                		) m on i.association_user_id = m.association_user_id AND i.source_system = m.source_system AND m.num = 1
+                		LEFT JOIN (
+                			SELECT
+                				-- 玩家最近充值游戏名
+                				source_system,
+                				id,
+                				game_name
+                			FROM dm_game_order.t_game
+                		) n ON m.user_last_recharge_game_id = n.id AND m.source_system = n.source_system
+                	) i on a.source_system = i.source_system AND a.association_user_id = i.association_user_id
+                	LEFT JOIN (
+                		SELECT
+                			*
+                		FROM dm_game_order.t_role_operate
+                	) j on a.source_system = j.source_system AND a.association_user_id = j.user_id AND
+                	a.role_id = j.role_id AND a.server_id = j.server_id AND a.game_id = j.game_id
+                ) a
+                """ + criA;
+    }
+
+}

+ 10 - 0
game-module/game-module-base/src/main/java/com/zanxiang/game/module/base/pojo/enums/GameAuthEnum.java

@@ -31,6 +31,16 @@ public enum GameAuthEnum {
      */
     PITCHER("PITCHER", "投手"),
 
+    /**
+     * 游戏GS
+     */
+    GS("GS", "游戏GS"),
+
+    /**
+     * 客服
+     */
+    CUSTOMER("CUSTOMER", "客服"),
+
     /**
      * 运营
      */

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

@@ -21,7 +21,7 @@ public class ManageApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(ManageApplication.class, args);
-        System.out.println("赞象Manage服务启动成功 <解决bug调试修改3> ( ´・・)ノ(._.`) \n" +
+        System.out.println("赞象Manage服务启动成功 <用户导安卓兼容> ( ´・・)ノ(._.`) \n" +
                 "___  ___  ___   _   _   ___  _____  _____ \n" +
                 "|  \\/  | / _ \\ | \\ | | / _ \\|  __ \\|  ___|\n" +
                 "| .  . |/ /_\\ \\|  \\| |/ /_\\ \\ |  \\/| |__  \n" +

+ 32 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/controller/GameServerController.java

@@ -2,10 +2,14 @@ package com.zanxiang.game.module.manage.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.zanxiang.erp.security.annotation.PreAuthorize;
+import com.zanxiang.game.module.manage.pojo.params.GameMergeServerParam;
 import com.zanxiang.game.module.manage.pojo.params.GameServerAddUpdateParam;
 import com.zanxiang.game.module.manage.pojo.params.GameServerListParam;
 import com.zanxiang.game.module.manage.pojo.vo.GameServerListVO;
+import com.zanxiang.game.module.manage.pojo.vo.GameServerVO;
+import com.zanxiang.game.module.manage.pojo.vo.GameSupperVO;
 import com.zanxiang.game.module.manage.service.IGameServerService;
+import com.zanxiang.game.module.manage.service.IGameSupperService;
 import com.zanxiang.module.util.pojo.ResultVO;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -16,6 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 /**
  * @author : lingfeng
  * @time : 2023-08-07
@@ -30,6 +36,9 @@ public class GameServerController {
     @Autowired
     private IGameServerService gameServerService;
 
+    @Autowired
+    private IGameSupperService gameSupperService;
+
     @ApiOperation(value = "新增或修改游戏区服")
     @PostMapping(value = "/add/or/update")
     @PreAuthorize(permissionKey = "manage:gameServer:addOrUpdate")
@@ -54,4 +63,27 @@ public class GameServerController {
         return ResultVO.ok(gameServerService.deleteById(id));
     }
 
+    @ApiOperation(value = "合服新增修改")
+    @PostMapping(value = "/merge/add/or/update")
+    @PreAuthorize(permissionKey = "manage:gameServer:mergeAddOrUpdate")
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = Boolean.class)})
+    public ResultVO<Boolean> mergeServerAddUpdate(@Validated @RequestBody GameMergeServerParam param) {
+        return ResultVO.ok(gameServerService.mergeServerAddUpdate(param));
+    }
+
+    @ApiOperation(value = "获取合服超父游戏列表")
+    @GetMapping(value = "/game/supper/list")
+    @PreAuthorize(permissionKey = "manage:gameServer:gameSupperList")
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = GameSupperVO.class)})
+    public ResultVO<List<GameSupperVO>> getGameSupperList() {
+        return ResultVO.ok(gameSupperService.getGameSupperList());
+    }
+
+    @ApiOperation(value = "获取未参与合服的区服列表")
+    @GetMapping(value = "/unMerge/server/list")
+    @PreAuthorize(permissionKey = "manage:gameServer:unMergeServer")
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = GameServerVO.class)})
+    public ResultVO<List<GameServerVO>> unMergeServerList(@RequestParam Long gameId) {
+        return ResultVO.ok(gameServerService.unMergeServerList(gameId));
+    }
 }

+ 2 - 2
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/controller/UserController.java

@@ -150,7 +150,7 @@ public class UserController {
     @PatchMapping(value = "/applet/to/h5")
     @PreAuthorize(permissionKey = "manage:user:appletToH5")
     @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = Boolean.class)})
-    public ResultVO<Boolean> appletToH5(@RequestParam Long userId, @RequestParam String mobile) {
-        return ResultVO.ok(userService.appletToH5(userId, mobile));
+    public ResultVO<Boolean> appletToH5(@RequestParam Long userId, @RequestParam String mobile, @RequestParam Integer type) {
+        return ResultVO.ok(userService.appletToH5(userId, mobile, type));
     }
 }

+ 15 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/GameDTO.java

@@ -91,4 +91,19 @@ public class GameDTO {
      * 更新时间
      */
     private LocalDateTime updateTime;
+
+    /**
+     * 超父游戏id
+     */
+    private Long superGameId;
+
+    /**
+     * 安卓游戏id
+     */
+    private Long androidGameId;
+
+    /**
+     * ios游戏id
+     */
+    private Long iosGameId;
 }

+ 60 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/params/GameMergeServerParam.java

@@ -0,0 +1,60 @@
+package com.zanxiang.game.module.manage.pojo.params;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-09-11
+ * @description : 游戏合并区服
+ */
+@Data
+public class GameMergeServerParam {
+
+    /**
+     * 主键id
+     */
+    @ApiModelProperty(notes = "主键id, 传则是修改, 不传则是新增")
+    private Long id;
+
+    /**
+     * 超父游戏id
+     */
+    @NotNull(message = "超父游戏id不可为空")
+    @ApiModelProperty(notes = "超父游戏id")
+    private Long gameId;
+
+    /**
+     * 合服的主服id
+     */
+    @NotBlank(message = "合服的主服id不可为空")
+    @ApiModelProperty(notes = "合服的主服id")
+    private String mainServerId;
+
+    /**
+     * 合并的区服id列表
+     */
+    @NotEmpty(message = "合并的区服id列表不可为空")
+    @ApiModelProperty(notes = "合并的区服id列表")
+    private List<String> serverIdList;
+
+    /**
+     * 合服区服名称
+     */
+    @NotBlank(message = "区服名称不可为空")
+    @ApiModelProperty(notes = "合服区服名称")
+    private String serverName;
+
+    /**
+     * 合服时间
+     */
+    @NotNull(message = "合服时间不可为空")
+    @ApiModelProperty(notes = "合服时间")
+    private LocalDateTime mergeTime;
+}

+ 2 - 2
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/params/IpBanAddParam.java

@@ -5,7 +5,7 @@ import lombok.Data;
 
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
-import java.util.List;
+import java.util.Set;
 
 /**
  * @author : lingfeng
@@ -26,5 +26,5 @@ public class IpBanAddParam {
      * ip列表
      */
     @NotEmpty(message = "ip列表不可为空")
-    private List<String> ipList;
+    private Set<String> ipList;
 }

+ 64 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/GameServerListVO.java

@@ -6,7 +6,9 @@ import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import javax.validation.constraints.NotBlank;
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * @author : lingfeng
@@ -72,4 +74,66 @@ public class GameServerListVO {
      */
     @ApiModelProperty(notes = "更新时间")
     private LocalDateTime updateTime;
+
+    /**
+     * 是否原始服
+     */
+    @ApiModelProperty(notes = "是否原始服")
+    private Boolean isSourceServer;
+
+    /**
+     * 合服的主服id
+     */
+    @ApiModelProperty(notes = "合服的主服id")
+    private String mainServerId;
+
+    /**
+     * 合服的主服名称
+     */
+    @ApiModelProperty(notes = "合服的主服名称")
+    private String mainServerName;
+
+    /**
+     * 是否参与合服
+     */
+    @ApiModelProperty(notes = "是否参与合服")
+    private Boolean isMerge;
+
+    /**
+     * 合服包含的子服列表
+     */
+    @ApiModelProperty(notes = "合服包含的子服列表")
+    private List<ServerBean> sonServerList;
+
+    /**
+     * 合服包含的原始服列表
+     */
+    @ApiModelProperty(notes = "合服包含的原始服列表")
+    private List<ServerBean> sourceServerList;
+
+    /**
+     * 合服时间
+     */
+    @ApiModelProperty(notes = "合服时间")
+    private LocalDateTime mergeTime;
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    @Builder
+    public static class ServerBean {
+
+        /**
+         * 区服id
+         */
+        @ApiModelProperty(notes = "区服id")
+        private String serverId;
+
+        /**
+         * 区服名称
+         */
+        @ApiModelProperty(notes = "区服名称")
+        private String serverName;
+
+    }
 }

+ 26 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/GameServerVO.java

@@ -0,0 +1,26 @@
+package com.zanxiang.game.module.manage.pojo.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-09-12
+ * @description : 游戏区服
+ */
+@Data
+public class GameServerVO {
+
+    /**
+     * 区服id
+     */
+    @ApiModelProperty(notes = "区服id")
+    private String serverId;
+
+    /**
+     * 区服名称
+     */
+    @ApiModelProperty(notes = "区服名称")
+    private String serverName;
+
+}

+ 25 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/GameSupperVO.java

@@ -0,0 +1,25 @@
+package com.zanxiang.game.module.manage.pojo.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-09-12
+ * @description : 超父游戏
+ */
+@Data
+public class GameSupperVO {
+
+    /**
+     * 游戏id
+     */
+    @ApiModelProperty(notes = "游戏id")
+    private Long id;
+
+    /**
+     * 游戏名称
+     */
+    @ApiModelProperty(notes = "游戏名称")
+    private String name;
+}

+ 19 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IGameServerService.java

@@ -2,12 +2,15 @@ package com.zanxiang.game.module.manage.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.module.manage.pojo.params.GameMergeServerParam;
 import com.zanxiang.game.module.manage.pojo.params.GameServerAddUpdateParam;
 import com.zanxiang.game.module.manage.pojo.params.GameServerListParam;
 import com.zanxiang.game.module.manage.pojo.vo.GameServerListVO;
+import com.zanxiang.game.module.manage.pojo.vo.GameServerVO;
 import com.zanxiang.game.module.mybatis.entity.GameServer;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author : lingfeng
@@ -48,4 +51,20 @@ public interface IGameServerService extends IService<GameServer> {
      * @return boolean
      */
     boolean deleteById(Long id);
+
+    /**
+     * 合服添加更新
+     *
+     * @param param 参数
+     * @return {@link Boolean}
+     */
+    Boolean mergeServerAddUpdate(GameMergeServerParam param);
+
+    /**
+     * 未参与合服的区服列表
+     *
+     * @param gameId 游戏id
+     * @return {@link List}<{@link GameServerVO}>
+     */
+    List<GameServerVO> unMergeServerList(Long gameId);
 }

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

@@ -0,0 +1,23 @@
+package com.zanxiang.game.module.manage.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.game.module.manage.pojo.vo.GameSupperVO;
+import com.zanxiang.game.module.mybatis.entity.GameSupper;
+
+import java.util.List;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-09-12
+ * @description :
+ */
+public interface IGameSupperService extends IService<GameSupper> {
+
+
+    /**
+     * 获取超父游戏
+     *
+     * @return {@link List}<{@link GameSupperVO}>
+     */
+    List<GameSupperVO> getGameSupperList();
+}

+ 2 - 1
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IUserService.java

@@ -26,9 +26,10 @@ public interface IUserService extends IService<User> {
      *
      * @param userId 用户id
      * @param mobile 移动
+     * @param type   类型
      * @return {@link Boolean}
      */
-    Boolean appletToH5(Long userId, String mobile);
+    Boolean appletToH5(Long userId, String mobile, Integer type);
 
     /**
      * 获取用户微信

+ 146 - 7
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/GameServerServiceImpl.java

@@ -2,6 +2,7 @@ package com.zanxiang.game.module.manage.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -9,13 +10,17 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zanxiang.erp.security.util.SecurityUtil;
 import com.zanxiang.game.module.base.pojo.enums.DeleteEnum;
 import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
+import com.zanxiang.game.module.manage.pojo.params.GameMergeServerParam;
 import com.zanxiang.game.module.manage.pojo.params.GameServerAddUpdateParam;
 import com.zanxiang.game.module.manage.pojo.params.GameServerListParam;
 import com.zanxiang.game.module.manage.pojo.vo.GameServerListVO;
+import com.zanxiang.game.module.manage.pojo.vo.GameServerVO;
 import com.zanxiang.game.module.manage.service.IGameAuthService;
 import com.zanxiang.game.module.manage.service.IGameServerService;
 import com.zanxiang.game.module.manage.service.IGameService;
+import com.zanxiang.game.module.manage.service.IGameSupperService;
 import com.zanxiang.game.module.mybatis.entity.GameServer;
+import com.zanxiang.game.module.mybatis.entity.GameSupper;
 import com.zanxiang.game.module.mybatis.mapper.GameServerMapper;
 import com.zanxiang.module.util.bean.BeanUtil;
 import com.zanxiang.module.util.exception.BaseException;
@@ -28,9 +33,8 @@ import reactor.util.function.Tuple2;
 
 import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -48,6 +52,9 @@ public class GameServerServiceImpl extends ServiceImpl<GameServerMapper, GameSer
     @Autowired
     private IGameAuthService gameAuthService;
 
+    @Autowired
+    private IGameSupperService gameSupperService;
+
     @Override
     public List<String> listServerId(Long gameId, String serverName) {
         if (Strings.isBlank(serverName)) {
@@ -85,6 +92,8 @@ public class GameServerServiceImpl extends ServiceImpl<GameServerMapper, GameSer
                 .isDelete(DeleteEnum.NO.getCode())
                 .createBy(param.getId() == null ? SecurityUtil.getUserId() : null)
                 .createTime(param.getId() == null ? LocalDateTime.now() : null)
+                .isSourceServer(Boolean.TRUE)
+                .isMerge(Boolean.FALSE)
                 .updateBy(SecurityUtil.getUserId())
                 .updateTime(LocalDateTime.now())
                 .build();
@@ -102,9 +111,16 @@ public class GameServerServiceImpl extends ServiceImpl<GameServerMapper, GameSer
         if (param.getGameId() != null && !gameIdList.contains(param.getGameId())) {
             return new Page<>();
         }
+        Long gameId = null;
+        if (param.getGameId() != null) {
+            GameDTO gameDTO = gameService.getById(param.getGameId());
+            if (gameDTO == null || gameDTO.getSuperGameId() == null) {
+                return new Page<>();
+            }
+            gameId = gameDTO.getSuperGameId();
+        }
         return page(param.toPage(), new QueryWrapper<GameServer>().lambda()
-                .in(GameServer::getGameId, gameIdList)
-                .eq(param.getGameId() != null, GameServer::getGameId, param.getGameId())
+                .eq(gameId != null, GameServer::getGameId, param.getGameId())
                 .eq(param.getServerId() != null, GameServer::getServerId, param.getServerId())
                 .like(Strings.isNotBlank(param.getServerName()), GameServer::getServerName, param.getServerName())
                 .like(Strings.isNotBlank(param.getNickName()), GameServer::getNickName, param.getNickName())
@@ -119,11 +135,134 @@ public class GameServerServiceImpl extends ServiceImpl<GameServerMapper, GameSer
             return null;
         }
         GameServerListVO gameServerListVO = BeanUtil.copy(gameServer, GameServerListVO.class);
-        GameDTO gameDTO = gameService.getById(gameServer.getGameId());
-        gameServerListVO.setGameName(gameDTO == null ? null : gameDTO.getName());
+        GameSupper gameSupper = gameSupperService.getById(gameServer.getGameId());
+        gameServerListVO.setGameName(gameSupper == null ? null : gameSupper.getName());
+        //原始区服, 直接返回
+        if (Objects.equals(gameServer.getIsSourceServer(), Boolean.TRUE)) {
+            return gameServerListVO;
+        }
+        //合服
+        List<String> serverIdList = new ArrayList<>();
+        String[] sonServerIdArray = null;
+        String[] sourceServerIdArray = null;
+        if (Strings.isNotBlank(gameServer.getMainServerId())) {
+            serverIdList.add(gameServer.getMainServerId());
+        }
+        if (Strings.isNotBlank(gameServer.getSonServerIds())) {
+            sonServerIdArray = gameServer.getSonServerIds().split(",");
+            Collections.addAll(serverIdList, sonServerIdArray);
+        }
+        if (Strings.isNotBlank(gameServer.getSourceServerIds())) {
+            sourceServerIdArray = gameServer.getSourceServerIds().split(",");
+            Collections.addAll(serverIdList, sourceServerIdArray);
+        }
+        //关联区服信息
+        Map<String, GameServer> gameServerMap = super.list(new LambdaQueryWrapper<GameServer>()
+                .in(GameServer::getServerId, serverIdList)
+        ).stream().collect(Collectors.toMap(GameServer::getServerId, Function.identity()));
+        //合服主服名称
+        if (Strings.isNotBlank(gameServer.getMainServerId())) {
+            GameServer mainServer = gameServerMap.get(gameServer.getMainServerId());
+            gameServerListVO.setMainServerName(mainServer == null ? null : mainServer.getServerName());
+        }
+        //合服子服列表
+        if (sonServerIdArray != null) {
+            List<GameServerListVO.ServerBean> sonServerList = new ArrayList<>();
+            for (String sonServerId : sonServerIdArray) {
+                GameServer sonServer = gameServerMap.get(sonServerId);
+                if (sonServer == null) {
+                    continue;
+                }
+                sonServerList.add(GameServerListVO.ServerBean.builder()
+                        .serverId(sonServerId)
+                        .serverName(sonServer.getServerName())
+                        .build());
+            }
+            gameServerListVO.setSonServerList(sonServerList);
+        }
+        //合服原始服列表
+        if (sourceServerIdArray != null) {
+            List<GameServerListVO.ServerBean> sourceServerList = new ArrayList<>();
+            for (String sourceServerId : sourceServerIdArray) {
+                GameServer sourceServer = gameServerMap.get(sourceServerId);
+                if (sourceServer != null) {
+                    sourceServerList.add(GameServerListVO.ServerBean.builder()
+                            .serverId(sourceServerId)
+                            .serverName(sourceServer.getServerName())
+                            .build());
+                }
+            }
+            gameServerListVO.setSourceServerList(sourceServerList);
+        }
         return gameServerListVO;
     }
 
+    @Override
+    public Boolean mergeServerAddUpdate(GameMergeServerParam param) {
+        List<GameServer> gameServerList = super.list(new LambdaQueryWrapper<GameServer>()
+                .eq(GameServer::getGameId, param.getGameId())
+                .in(GameServer::getServerId, param.getServerIdList()));
+        Set<String> sourceServerIds = new HashSet<>();
+        gameServerList.forEach(gameServer -> {
+            if (gameServer.getIsSourceServer()) {
+                sourceServerIds.add(gameServer.getServerId());
+                return;
+            }
+            if (Strings.isBlank(gameServer.getSourceServerIds())) {
+                Collections.addAll(sourceServerIds, gameServer.getSourceServerIds().split(","));
+            }
+        });
+        //新增
+        if (param.getId() == null) {
+            super.save(this.transform(param, sourceServerIds));
+        } else {
+            super.update(new LambdaUpdateWrapper<GameServer>()
+                    .set(GameServer::getGameId, param.getGameId())
+                    .set(GameServer::getMainServerId, param.getMainServerId())
+                    .set(GameServer::getSonServerIds, String.join(",", param.getServerIdList()))
+                    .set(GameServer::getSourceServerIds, String.join(",", sourceServerIds))
+                    .set(GameServer::getServerName, param.getServerName())
+                    .set(GameServer::getMergeTime, param.getMergeTime())
+                    .set(GameServer::getUpdateBy, SecurityUtil.getUserId())
+                    .set(GameServer::getUpdateTime, LocalDateTime.now())
+                    .eq(GameServer::getId, param.getId()));
+        }
+        return super.update(new LambdaUpdateWrapper<GameServer>()
+                .set(GameServer::getIsMerge, Boolean.TRUE)
+                .set(GameServer::getUpdateTime, LocalDateTime.now())
+                .in(GameServer::getServerId, param.getServerIdList()));
+    }
+
+    private GameServer transform(GameMergeServerParam param, Set<String> sourceServerIds) {
+        return GameServer.builder()
+                .gameId(param.getGameId())
+                .serverId(UUID.randomUUID().toString())
+                .serverName(param.getServerName())
+                .isSourceServer(Boolean.FALSE)
+                .mainServerId(param.getMainServerId())
+                .isMerge(Boolean.FALSE)
+                .sonServerIds(String.join(",", param.getServerIdList()))
+                .sourceServerIds(String.join(",", sourceServerIds))
+                .mergeTime(param.getMergeTime())
+                .startTime(param.getMergeTime())
+                .isDelete(DeleteEnum.NO.getCode())
+                .createBy(SecurityUtil.getUserId())
+                .createTime(LocalDateTime.now())
+                .updateBy(SecurityUtil.getUserId())
+                .updateTime(LocalDateTime.now())
+                .build();
+    }
+
+    @Override
+    public List<GameServerVO> unMergeServerList(Long gameId) {
+        return super.list(new LambdaQueryWrapper<GameServer>()
+                .select(GameServer::getServerId, GameServer::getServerName)
+                .eq(GameServer::getGameId, gameId)
+                .eq(GameServer::getIsMerge, Boolean.FALSE)
+        ).stream().map(gameServer -> BeanUtil.copy(gameServer, GameServerVO.class))
+                .collect(Collectors.toList());
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean deleteById(Long id) {

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

@@ -0,0 +1,31 @@
+package com.zanxiang.game.module.manage.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.game.module.manage.pojo.vo.GameSupperVO;
+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.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-09-12
+ * @description : 超父游戏
+ */
+@Slf4j
+@Service
+public class GameSupperServiceImpl extends ServiceImpl<GameSupperMapper, GameSupper> implements IGameSupperService {
+
+    @Override
+    public List<GameSupperVO> getGameSupperList() {
+        return super.list().stream()
+                .map(gameSupper -> BeanUtil.copy(gameSupper, GameSupperVO.class))
+                .collect(Collectors.toList());
+    }
+}

+ 2 - 1
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/IpBanServiceImpl.java

@@ -69,7 +69,8 @@ public class IpBanServiceImpl extends ServiceImpl<IpBanMapper, IpBan> implements
         List<IpBan> list = new ArrayList<>();
         param.getIpList().forEach(ip -> {
             //先查询是否已经存在
-            IpBan ipBan = super.getOne(new LambdaQueryWrapper<IpBan>().eq(IpBan::getIp, ip));
+            IpBan ipBan = super.getOne(new LambdaQueryWrapper<IpBan>()
+                    .eq(IpBan::getGameId, param.getGameId()).eq(IpBan::getIp, ip));
             if (ipBan == null) {
                 ipBan = IpBan.builder()
                         .ip(ip)

+ 22 - 7
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/UserServiceImpl.java

@@ -85,20 +85,32 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Boolean appletToH5(Long userId, String mobile) {
+    public Boolean appletToH5(Long userId, String mobile, Integer type) {
         //用户信息
         User user = super.getById(userId);
         if (user == null) {
             throw new BaseException("参数错误, 用户信息不存在");
         }
+        GameDTO gameDTO;
         //查询H5游戏
-        GameDTO h5GameDTO = gameService.getById(gameService.getById(user.getGameId()).getH5GameId());
-        if (h5GameDTO == null) {
-            throw new BaseException("参数错误, 关联H5游戏信息不存在");
+        if (type == 1) {
+            gameDTO = gameService.getById(gameService.getById(user.getGameId()).getH5GameId());
+        } else if (type == 2) {
+            //查询安卓游戏
+            gameDTO = gameService.getById(gameService.getById(user.getGameId()).getAndroidGameId());
+        } else if (type == 3) {
+            //查询ios游戏
+            gameDTO = gameService.getById(gameService.getById(user.getGameId()).getIosGameId());
+        } else {
+            throw new BaseException("参数错误, 导量类型不存在");
+        }
+        //判断关联游戏是否存在
+        if (gameDTO == null) {
+            throw new BaseException("参数错误, 关联导量游戏信息不存在");
         }
         //判断手机号是否被该游戏其他用户绑定
         int count = super.count(new LambdaQueryWrapper<User>()
-                .eq(User::getGameId, h5GameDTO.getId())
+                .eq(User::getGameId, gameDTO.getId())
                 .eq(User::getMobile, mobile));
         if (count > 0) {
             throw new BaseException("参数错误, 该手机号已被该游戏其他玩家信息绑定");
@@ -106,7 +118,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
         //复制用户信息
         User h5User = BeanUtil.copy(user, User.class);
         h5User.setId(null);
-        h5User.setGameId(h5GameDTO.getId());
+        h5User.setGameId(gameDTO.getId());
         h5User.setMobile(mobile);
         h5User.setRelationUserId(user.getId());
         h5User.setRelationCreateTime(LocalDateTime.now());
@@ -264,7 +276,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
         }
         //最近角色
         GameUserRole gameUserRole = gameUserRoleService.getLastGameUserRoleName(user.getId(), user.getGameId());
-        userListVO.setLastGameRoleName(gameUserRole == null ? null : gameUserRole.getRoleName());
+        if (gameUserRole != null) {
+            userListVO.setLastGameRoleName(gameUserRole.getRoleName());
+            userListVO.setUpdateTime(gameUserRole.getLastLoginTime());
+        }
         //注册充值时间差
         userListVO.setRegPayTimeDiff(DateUtils.getRegPayTimeDiff(userListVO.getCreateTime(), userListVO.getLastRechargeTime()));
         //设置关联游戏名称

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

@@ -106,4 +106,9 @@ public class Game implements Serializable {
      * H5游戏相关配置
      */
     private String h5GameConfig;
+
+    /**
+     * 超父游戏id
+     */
+    private Long superGameId;
 }

+ 30 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/GameServer.java

@@ -53,6 +53,36 @@ public class GameServer implements Serializable {
      */
     private LocalDateTime startTime;
 
+    /**
+     * 是否原始服
+     */
+    private Boolean isSourceServer;
+
+    /**
+     * 合服的主服id
+     */
+    private String mainServerId;
+
+    /**
+     * 是否参与合服
+     */
+    private Boolean isMerge;
+
+    /**
+     * 合服包含的子服列表
+     */
+    private String sonServerIds;
+
+    /**
+     * 合服包含的原始服列表
+     */
+    private String sourceServerIds;
+
+    /**
+     * 合服时间
+     */
+    private LocalDateTime mergeTime;
+
     /**
      * 1 删除  0 正常
      */

+ 58 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/GameSupper.java

@@ -0,0 +1,58 @@
+package com.zanxiang.game.module.mybatis.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-09-12
+ * @description : 超父游戏
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+@Builder
+@TableName("t_game_super")
+public class GameSupper implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * CP ID
+     */
+    private Long cpId;
+
+    /**
+     * 游戏名称
+     */
+    private String name;
+
+    /**
+     * 1 删除  0 正常
+     */
+    @TableLogic
+    private Integer isDelete;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+}

+ 12 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/mapper/GameSupperMapper.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.GameSupper;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-09-12
+ * @description :
+ */
+public interface GameSupperMapper extends BaseMapper<GameSupper> {
+}