瀏覽代碼

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

zhimo 1 年之前
父節點
當前提交
6b14076cae
共有 21 個文件被更改,包括 1638 次插入484 次删除
  1. 18 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/PlayerDataController.java
  2. 21 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerBannedListDTO.java
  3. 6 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerDataListDTO.java
  4. 108 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerLoginLogDataListDTO.java
  5. 12 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PromotionDayDTO.java
  6. 12 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PromotionDayTotalDTO.java
  7. 73 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/enums/DeviceTypeEnum.java
  8. 64 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/enums/LogTypeEnum.java
  9. 10 1
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/AdsOrderDetailVO.java
  10. 17 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/IPlayerDataService.java
  11. 258 14
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/AdsOrderDetailService.java
  12. 303 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PlayerDataServiceImpl.java
  13. 14 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PromotionDayServiceImpl.java
  14. 499 468
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/RoleManageServiceImpl.java
  15. 1 1
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/ManageApplication.java
  16. 11 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/controller/GameServerController.java
  17. 30 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/enums/GameServerExcelEnum.java
  18. 0 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/AgentListDTO.java
  19. 61 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/GameServerExcelDTO.java
  20. 12 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IGameServerService.java
  21. 108 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/GameServerServiceImpl.java

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

@@ -1,7 +1,9 @@
 package com.zanxiang.game.data.serve.controller;
 
 import com.zanxiang.erp.security.annotation.PreAuthorize;
+import com.zanxiang.game.data.serve.pojo.dto.PlayerBannedListDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerDataListDTO;
+import com.zanxiang.game.data.serve.pojo.dto.PlayerLoginLogDataListDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerRoleDataListDTO;
 import com.zanxiang.game.data.serve.pojo.vo.PlayerDataVO;
 import com.zanxiang.game.data.serve.pojo.vo.PlayerRoleDataVO;
@@ -17,6 +19,8 @@ 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/6
@@ -45,4 +49,18 @@ public class PlayerDataController {
         return ResultVO.ok(playerDataService.getPlayerRoleDataList(dto));
     }
 
+    @ApiOperation("玩家登陆日志列表")
+    @PreAuthorize(permissionKey = "playerData:player:loginLog")
+    @PostMapping("/login/list")
+    public ResultVO<Page<Map>> getPlayerLoginLogDataList(@RequestBody PlayerLoginLogDataListDTO dto) {
+        return ResultVO.ok(playerDataService.getPlayerLoginLogDataList(dto));
+    }
+
+    @ApiOperation("登陆IP玩家列表")
+    @PreAuthorize(permissionKey = "playerData:player:banned")
+    @PostMapping("/banned/list")
+    public ResultVO<Page<Map>> getPlayerBannedDataList(@RequestBody PlayerBannedListDTO dto) {
+        return ResultVO.ok(playerDataService.getPlayerBannedDataList(dto));
+    }
+
 }

+ 21 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerBannedListDTO.java

@@ -0,0 +1,21 @@
+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;
+
+/**
+ * @author tianhua
+ * @time 2023/10/8
+ * @Description
+ **/
+@Data
+public class PlayerBannedListDTO extends BasePage {
+
+    /**
+     * 登陆IP
+     */
+    @ApiModelProperty(value = "登陆IP")
+    private String ip;
+
+}

+ 6 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerDataListDTO.java

@@ -176,4 +176,10 @@ public class PlayerDataListDTO extends BasePage {
     @ApiModelProperty("SDK来源")
     private String sourceSystem;
 
+    /**
+     * 玩家最近游戏角色名
+     */
+    @ApiModelProperty(value = "玩家最近游戏角色名称")
+    private String roleName;
+
 }

+ 108 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PlayerLoginLogDataListDTO.java

@@ -0,0 +1,108 @@
+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/10/8
+ * @Description 前端查询用户登陆日志参数实体
+ **/
+@Data
+public class PlayerLoginLogDataListDTO extends BasePage {
+
+    /**
+     * 开始时间
+     */
+    @ApiModelProperty(value = "开始时间")
+    private LocalDate beginDate;
+
+    /**
+     * 登陆结束时间
+     */
+    @ApiModelProperty(value = "结束时间")
+    private LocalDate endDate;
+
+    /**
+     * SDK来源
+     */
+    @ApiModelProperty(value = "SDK来源")
+    private String sourceSystem;
+
+    /**
+     * 用户名
+     */
+    @ApiModelProperty(value = "用户名")
+    private String username;
+
+    /**
+     * 用户ID
+     */
+    @ApiModelProperty(value = "用户ID")
+    private Long userId;
+
+    /**
+     * 角色ID
+     */
+    @ApiModelProperty(value = "角色ID")
+    private Long roleId;
+
+    /**
+     * 角色名
+     */
+    @ApiModelProperty(value = "角色名")
+    private String roleName;
+
+    /**
+     * 游戏ID
+     */
+    @ApiModelProperty(value = "游戏ID")
+    private Long gameId;
+
+    /**
+     * 父游戏ID
+     */
+    @ApiModelProperty(value = "父游戏ID")
+    private Long parentGameId;
+
+    /**
+     * 游戏类型
+     */
+    @ApiModelProperty(value = "游戏类型")
+    private Long gameClassify;
+
+    /**
+     * 区服ID
+     */
+    @ApiModelProperty(value = "区服ID")
+    private List<String> serverId;
+
+    /**
+     * 操作系统
+     */
+    @ApiModelProperty(value = "操作系统")
+    private String os;
+
+    /**
+     * 登陆IP
+     */
+    @ApiModelProperty(value = "登陆IP")
+    private String ip;
+
+    /**
+     * 客户端类型:1-安卓APP;2-iosAPP;3-H5网页;4-小程序
+     */
+    @ApiModelProperty(value = "客户端类型:1-安卓APP;2-iosAPP;3-H5网页;4-小程序")
+    private Long deviceType;
+
+    /**
+     * 类型:0-注册;1-登陆;2-退出
+     */
+    @ApiModelProperty(value = "类型:0-注册;1-登陆;2-退出")
+    private Long type;
+
+}

+ 12 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PromotionDayDTO.java

@@ -128,4 +128,16 @@ public class PromotionDayDTO extends BasePage {
     @ApiModelProperty(notes = "排序方式:升序asc;降序desc")
     private String sortType;
 
+    /**
+     * 首日充值金额(最大值)
+     */
+    @ApiModelProperty(notes = "首日充值金额(最大值)")
+    private Long firstRechargeAmountMax;
+
+    /**
+     * 首日充值金额(最小值)
+     */
+    @ApiModelProperty(notes = "首日充值金额(最小值)")
+    private Long firstRechargeAmountMin;
+
 }

+ 12 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/PromotionDayTotalDTO.java

@@ -115,4 +115,16 @@ public class PromotionDayTotalDTO {
     @ApiModelProperty(value = "游戏应用类型")
     private Long classify;
 
+    /**
+     * 首日充值金额(最大值)
+     */
+    @ApiModelProperty(notes = "首日充值金额(最大值)")
+    private Long firstRechargeAmountMax;
+
+    /**
+     * 首日充值金额(最小值)
+     */
+    @ApiModelProperty(notes = "首日充值金额(最小值)")
+    private Long firstRechargeAmountMin;
+
 }

+ 73 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/enums/DeviceTypeEnum.java

@@ -0,0 +1,73 @@
+package com.zanxiang.game.data.serve.pojo.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Objects;
+
+/**
+ * @author : tianhua
+ * @time : 2023-10-09
+ * @description : 客户端类型枚举
+ */
+@Getter
+@AllArgsConstructor
+public enum DeviceTypeEnum {
+
+    /**
+     * 安卓APP
+     */
+    ANDROID_APP(1, "安卓APP"),
+
+    /**
+     * 苹果iosAPP
+     */
+    IOS_APP(2, "iosAPP"),
+
+    /**
+     * H5网页
+     */
+    H5(3, "H5网页"),
+
+    /**
+     * 小程序
+     */
+    APPLET(4, "小程序");
+
+    /**
+     * 标识ID
+     */
+    private Integer id;
+
+    /**
+     * 类型名
+     */
+    private String name;
+
+    /**
+     * 获取客户端类型名字
+     *
+     * @param deviceTypeId id
+     * @return {@link String}
+     */
+    public static String getName(Integer deviceTypeId) {
+        DeviceTypeEnum deviceType = DeviceTypeEnum.getDeviceType(deviceTypeId);
+        return deviceType == null ? null : deviceType.getName();
+    }
+
+    /**
+     * 获取客户端类型枚举
+     *
+     * @param deviceTypeId id
+     * @return DeviceTypeEnum
+     */
+    public static DeviceTypeEnum getDeviceType(Integer deviceTypeId) {
+        for (DeviceTypeEnum deviceTypeEnum : DeviceTypeEnum.values()) {
+            if (Objects.equals(deviceTypeEnum.getId(), deviceTypeId)) {
+                return deviceTypeEnum;
+            }
+        }
+        return null;
+    }
+
+}

+ 64 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/enums/LogTypeEnum.java

@@ -0,0 +1,64 @@
+package com.zanxiang.game.data.serve.pojo.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author : tianhua
+ * @time : 2023-10-09
+ * @description : 登陆类型
+ */
+@Getter
+@AllArgsConstructor
+public enum LogTypeEnum {
+
+    /**
+     * 注册
+     */
+    LOGIN_REG(0, "注册"),
+
+    /**
+     * 登录
+     */
+    LOGIN_IN(1, "登录"),
+
+    /**
+     * 退出
+     */
+    LOGIN_OUT(2, "退出");
+
+    /**
+     * 标识ID
+     */
+    private Integer id;
+
+    /**
+     * 类型
+     */
+    private String name;
+
+    /**
+     * 获取登陆枚举
+     * @param logTypeId 登陆类型ID
+     * @return LogTypeEnum
+     */
+    public static LogTypeEnum getLogTypeEnum(Integer logTypeId) {
+        for (LogTypeEnum logTypeEnum : LogTypeEnum.values()) {
+            if (logTypeEnum.id.equals(logTypeId)) {
+                return logTypeEnum;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 获取登陆类型的名字
+     * @param logTypeId 登陆类型id
+     * @return String
+     */
+    public static String getLogTypeName(Integer logTypeId) {
+        LogTypeEnum logTypeEnum = LogTypeEnum.getLogTypeEnum(logTypeId);
+        return logTypeEnum == null ? null : logTypeEnum.getName();
+    }
+
+}

+ 10 - 1
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/vo/AdsOrderDetailVO.java

@@ -109,7 +109,7 @@ public class AdsOrderDetailVO {
     @ApiModelProperty(notes = "支付方式名称")
     private String payway;
 
-    @ApiModelProperty(notes = "支付场景")
+    @ApiModelProperty(notes = "支付场景:支付类型, 1:PC, 2: h5支付, 3: App支付, 4: 小程序支付, 5: 米大师支付")
     private String payScene;
 
     @ApiModelProperty(notes = "收款账户")
@@ -157,4 +157,13 @@ public class AdsOrderDetailVO {
     @ApiModelProperty(notes = "cp最后通知时间")
     private LocalDateTime lastCpNotifyTime;
 
+    @ApiModelProperty(notes = "原始服务器名")
+    private String sourceServerName;
+
+    @ApiModelProperty(notes = "注册充值时间差(秒)")
+    private Long regUntilPay;
+
+    @ApiModelProperty(notes = "最近充值时间距今(秒)")
+    private Long payUntilNow;
+
 }

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

@@ -1,11 +1,15 @@
 package com.zanxiang.game.data.serve.service;
 
+import com.zanxiang.game.data.serve.pojo.dto.PlayerBannedListDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerDataListDTO;
+import com.zanxiang.game.data.serve.pojo.dto.PlayerLoginLogDataListDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerRoleDataListDTO;
 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;
 
+import java.util.Map;
+
 /**
  * @author tianhua
  * @time 2023/9/6
@@ -27,4 +31,17 @@ public interface IPlayerDataService {
      */
     Page<PlayerRoleDataVO> getPlayerRoleDataList(PlayerRoleDataListDTO dto);
 
+    /**
+     * 玩家登陆日志列表
+     * @param dto PlayerLoginLogDataListDTO
+     * @return Page<Map>
+     */
+    Page<Map> getPlayerLoginLogDataList(PlayerLoginLogDataListDTO dto);
+
+    /**
+     * 封禁玩家列表
+     * @param dto PlayerBannedListDTO
+     * @return Page<Map>
+     */
+    Page<Map> getPlayerBannedDataList(PlayerBannedListDTO dto);
 }

+ 258 - 14
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/AdsOrderDetailService.java

@@ -1,5 +1,6 @@
 package com.zanxiang.game.data.serve.service.impl;
 
+import com.google.common.base.CaseFormat;
 import com.zanxiang.erp.security.util.SecurityUtil;
 import com.zanxiang.game.data.serve.component.DataPowerComponent;
 import com.zanxiang.game.data.serve.pojo.dto.AdsOrderDetailDTO;
@@ -47,7 +48,6 @@ public class AdsOrderDetailService implements IAdsOrderDetailService {
             // 只有管理员才能查看全部数据
             dto.setPitcherId(SecurityUtil.getUserId().toString());
         }
-        Pager pager = dto.toPage();
         Criteria cri = Cnd.cri();
         if (StringUtils.isNotBlank(dto.getSourceSystem())) {
             cri.where().andEquals("source_system", dto.getSourceSystem());
@@ -121,19 +121,35 @@ public class AdsOrderDetailService implements IAdsOrderDetailService {
         if (dto.getRegPayIntervalTimeMax() != null) {
             cri.where().andLTE("TIMESTAMPDIFF(MINUTE, reg_time, pay_time)", dto.getRegPayIntervalTimeMax());
         }
+
+        //pager
+        Pager pager = dto.toPage();
+        Sql countSql = Sqls.create(getCountSql() + 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("day", dto.getSortType())
-                    .orderBy("order_create_time", dto.getSortType());
+            cri.getOrderBy().orderBy("day", dto.getSortType());
+            cri.getOrderBy().orderBy("order_create_time", dto.getSortType());
         } else {
-            cri.getOrderBy().orderBy(dto.getSortFiled(), dto.getSortType());
+            cri.getOrderBy().orderBy(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, dto.getSortFiled()), dto.getSortType());
         }
-        List<AdsOrderDetailVO> records = dao.query(AdsOrderDetail.class, cri, pager).stream().map(this::toVO).collect(Collectors.toList());
-        pager.setRecordCount(dao.count(AdsOrderDetail.class, cri));
-        return new Page<>(records, pager);
+
+        Sql sql = Sqls.create(getOrderDetailSql() + cri);
+        sql.setCallback(Sqls.callback.entities());
+        sql.setEntity(dao.getEntity(AdsOrderDetailVO.class));
+        sql.setPager(pager);
+        //执行获取结果
+        dao.execute(sql);
+        List<AdsOrderDetailVO> list = sql.getList(AdsOrderDetailVO.class);
+
+        return new Page<>(list, pager);
     }
 
     @Override
@@ -217,13 +233,7 @@ public class AdsOrderDetailService implements IAdsOrderDetailService {
         if (dto.getRegPayIntervalTimeMax() != null) {
             cri.where().andLTE("TIMESTAMPDIFF(MINUTE, reg_time, pay_time)", dto.getRegPayIntervalTimeMax());
         }
-        Sql sql = Sqls.create("""
-                SELECT
-                    IFNULL(SUM(amount), 0) as amount,
-                    IFNULL(SUM(real_amount), 0) as real_amount
-                FROM
-                    game_ads.ads_order_detail
-                """ + cri);
+        Sql sql = Sqls.create(getOrderDetailTotalSql() + cri);
         sql.setCallback(Sqls.callback.entity());
         sql.setEntity(dao.getEntity(AdsOrderDetailTotalVO.class));
         dao.execute(sql);
@@ -278,5 +288,239 @@ public class AdsOrderDetailService implements IAdsOrderDetailService {
         return BeanUtil.copy(tPayCallCpLog, OrderCPDetailVO.class);
     }
 
+    /**
+     * 查询订单列表sql
+     * @return String
+     */
+    private String getOrderDetailSql() {
+        return """
+                SELECT
+                	*
+                FROM (
+                	SELECT
+                		a.id, -- 主键id
+                		a.source_system , -- SDK来源
+                		DATE(a.create_time) as `day`, -- 订单创建日期
+                		a.order_id , -- 商户订单号ID
+                		a.cp_order_id , -- cp订单号
+                		a.merchant_order_no , -- 第三方支付订单号
+                		a.user_id as game_user_id, -- 玩家ID
+                		b.username , -- 玩家账号
+                		b.nickname , -- 玩家昵称
+                		b.create_time as reg_time, -- 玩家注册时间
+                		a.agent_id , -- 玩家注册渠道ID
+                		IF(a.agent_id = 0, '自然量', c.agent_name) as agent_name,-- 注册渠道名
+                		b.game_id , -- 玩家注册游戏ID
+                		g.game_name , -- 玩家注册游戏名
+                		g.classify , -- 玩家注册游戏类型
+                		a.cp_id , -- CPID
+                		e.cp_name ,-- cp名
+                		c.pitcher_id as zx_pitcher_id, -- 投手ID
+                		d.zx_pitcher_name , -- 投手名
+                		a.game_id as order_game_id, -- 玩家充值游戏ID
+                		f.game_name as order_game_name,-- 玩家充值游戏名
+                		f.classify as order_game_classify,-- 玩家充值游戏类型
+                		a.product_id , -- 充值商品ID
+                		a.product_name , -- 充值商品名称
+                		a.amount , -- 订单金额
+                		a.real_amount , -- 订单实付金额
+                		a.payway , -- 支付方式ID、支付方式名
+                		a.pay_device as pay_scene,-- 支付场景ID、支付场景名
+                		a.status as order_status, -- 支付状态
+                		a.cp_status , -- cp通知状态
+                		a.last_notify_time as last_cp_notify_time , -- cp最后通知时间
+                		a.merchant_no as pay_account_id, -- 收款账户
+                		a.server_id , -- 角色所属游戏区服ID
+                		IFNULL(h.server_name, a.server_name) as source_server_name , -- 原始区服名
+                		a.server_name , -- 角色所属游戏区服名
+                		a.role_id , -- 角色ID
+                		a.role_name , -- 角色名
+                		a.role_level , -- 角色等级
+                		a.role_vip , -- 角色VIP等级
+                		a.os , -- 操作系统
+                		a.is_switch as order_is_switch, -- 是否切量
+                		a.create_time as order_create_time, -- 下单时间
+                		a.pay_time,  -- 支付时间
+                		TIMESTAMPDIFF(SECOND, b.create_time, a.pay_time) as reg_until_pay, -- 注册充值时间差
+                		TIMESTAMPDIFF(SECOND, a.pay_time, NOW()) as pay_until_now, -- 最近充值时间距今(秒)
+                		IF(a.status = 2, IF(a.create_time = i.create_time, 1, 0), 0) as is_first_recharge -- 是否首充
+                	FROM dm_game_order.t_game_order a
+                	LEFT JOIN dm_game_order.t_game_user b on a.source_system = b.source_system AND a.user_id = b.id
+                	LEFT JOIN dm_game_order.t_pitcher_agent c on a.source_system = c.source_system AND a.agent_id = c.id
+                	LEFT JOIN dm_game_order.t_pitcher_map d on c.source_system = d.source_system AND c.pitcher_id = d.zx_pitcher_id
+                	LEFT JOIN dm_game_order.t_cp e on a.source_system = e.source_system AND a.cp_id = e.id
+                	LEFT JOIN dm_game_order.t_game f on a.source_system = f.source_system AND a.game_id = f.id
+                	LEFT JOIN dm_game_order.t_game g on b.source_system = g.source_system AND b.game_id = g.id
+                	LEFT JOIN dm_game_order.t_game_server_merge h on a.source_system = h.source_system AND a.server_id = h.server_id AND g.super_game_id = h.game_id
+                	LEFT JOIN (
+                		SELECT
+                			source_system ,
+                			user_id ,
+                			order_id ,
+                			create_time ,
+                			ROW_NUMBER()over(partition by source_system , user_id order by create_time ASC) as num
+                		FROM dm_game_order.t_game_order
+                		WHERE status = 2
+                	) i on a.source_system = i.source_system AND a.user_id = i.user_id AND i.num = 1
+                ) a
+                """;
+    }
+
+    /**
+     * 查询订单列表记录数sql
+     * @return String
+     */
+    private String getCountSql() {
+        return """
+                SELECT
+                	COUNT(1)
+                FROM (
+                	SELECT
+                		a.id, -- 主键id
+                		a.source_system , -- SDK来源
+                		DATE(a.create_time) as `day`, -- 订单创建日期
+                		a.order_id , -- 商户订单号ID
+                		a.cp_order_id , -- cp订单号
+                		a.merchant_order_no , -- 第三方支付订单号
+                		a.user_id as game_user_id, -- 玩家ID
+                		b.username , -- 玩家账号
+                		b.nickname , -- 玩家昵称
+                		b.create_time as reg_time, -- 玩家注册时间
+                		a.agent_id , -- 玩家注册渠道ID
+                		IF(a.agent_id = 0, '自然量', c.agent_name) as agent_name,-- 注册渠道名
+                		b.game_id , -- 玩家注册游戏ID
+                		g.game_name , -- 玩家注册游戏名
+                		g.classify , -- 玩家注册游戏类型
+                		a.cp_id , -- CPID
+                		e.cp_name ,-- cp名
+                		c.pitcher_id as zx_pitcher_id, -- 投手ID
+                		d.zx_pitcher_name , -- 投手名
+                		a.game_id as order_game_id, -- 玩家充值游戏ID
+                		f.game_name as order_game_name,-- 玩家充值游戏名
+                		f.classify as order_game_classify,-- 玩家充值游戏类型
+                		a.product_id , -- 充值商品ID
+                		a.product_name , -- 充值商品名称
+                		a.amount , -- 订单金额
+                		a.real_amount , -- 订单实付金额
+                		a.payway , -- 支付方式ID、支付方式名
+                		a.pay_device as pay_scene,-- 支付场景ID、支付场景名
+                		a.status as order_status, -- 支付状态
+                		a.cp_status , -- cp通知状态
+                		a.last_notify_time as last_cp_notify_time , -- cp最后通知时间
+                		a.merchant_no as pay_account_id, -- 收款账户
+                		a.server_id , -- 角色所属游戏区服ID
+                		IFNULL(h.server_name, a.server_name) as source_server_name , -- 原始区服名
+                		a.server_name , -- 角色所属游戏区服名
+                		a.role_id , -- 角色ID
+                		a.role_name , -- 角色名
+                		a.role_level , -- 角色等级
+                		a.role_vip , -- 角色VIP等级
+                		a.os , -- 操作系统
+                		a.is_switch as order_is_switch, -- 是否切量
+                		a.create_time as order_create_time, -- 下单时间
+                		a.pay_time,  -- 支付时间
+                		TIMESTAMPDIFF(SECOND, b.create_time, a.pay_time) as reg_until_pay, -- 注册充值时间差
+                		TIMESTAMPDIFF(SECOND, a.pay_time, NOW()) as pay_until_now, -- 最近充值时间距今(秒)
+                		IF(a.status = 2, IF(a.create_time = i.create_time, 1, 0), 0) as is_first_recharge -- 是否首充
+                	FROM dm_game_order.t_game_order a
+                	LEFT JOIN dm_game_order.t_game_user b on a.source_system = b.source_system AND a.user_id = b.id
+                	LEFT JOIN dm_game_order.t_pitcher_agent c on a.source_system = c.source_system AND a.agent_id = c.id
+                	LEFT JOIN dm_game_order.t_pitcher_map d on c.source_system = d.source_system AND c.pitcher_id = d.zx_pitcher_id
+                	LEFT JOIN dm_game_order.t_cp e on a.source_system = e.source_system AND a.cp_id = e.id
+                	LEFT JOIN dm_game_order.t_game f on a.source_system = f.source_system AND a.game_id = f.id
+                	LEFT JOIN dm_game_order.t_game g on b.source_system = g.source_system AND b.game_id = g.id
+                	LEFT JOIN dm_game_order.t_game_server_merge h on a.source_system = h.source_system AND a.server_id = h.server_id AND g.super_game_id = h.game_id
+                	LEFT JOIN (
+                		SELECT
+                			source_system ,
+                			user_id ,
+                			order_id ,
+                			create_time ,
+                			ROW_NUMBER()over(partition by source_system , user_id order by create_time ASC) as num
+                		FROM dm_game_order.t_game_order
+                		WHERE status = 2
+                	) i on a.source_system = i.source_system AND a.user_id = i.user_id AND i.num = 1
+                ) a
+                """;
+    }
+
+    /**
+     * 查询订单总计
+     * @return String
+     */
+    private String getOrderDetailTotalSql() {
+        return """
+                SELECT
+                	SUM(amount) as amount,
+                	SUM(real_amount) as real_amount
+                FROM (
+                	SELECT
+                		a.id, -- 主键id
+                		a.source_system , -- SDK来源
+                		DATE(a.create_time) as `day`, -- 订单创建日期
+                		a.order_id , -- 商户订单号ID
+                		a.cp_order_id , -- cp订单号
+                		a.merchant_order_no , -- 第三方支付订单号
+                		a.user_id as game_user_id, -- 玩家ID
+                		b.username , -- 玩家账号
+                		b.nickname , -- 玩家昵称
+                		b.create_time as reg_time, -- 玩家注册时间
+                		a.agent_id , -- 玩家注册渠道ID
+                		IF(a.agent_id = 0, '自然量', c.agent_name) as agent_name,-- 注册渠道名
+                		b.game_id , -- 玩家注册游戏ID
+                		g.game_name , -- 玩家注册游戏名
+                		g.classify , -- 玩家注册游戏类型
+                		a.cp_id , -- CPID
+                		e.cp_name ,-- cp名
+                		c.pitcher_id as zx_pitcher_id, -- 投手ID
+                		d.zx_pitcher_name , -- 投手名
+                		a.game_id as order_game_id, -- 玩家充值游戏ID
+                		f.game_name as order_game_name,-- 玩家充值游戏名
+                		f.classify as order_game_classify,-- 玩家充值游戏类型
+                		a.product_id , -- 充值商品ID
+                		a.product_name , -- 充值商品名称
+                		a.amount , -- 订单金额
+                		a.real_amount , -- 订单实付金额
+                		a.payway , -- 支付方式ID、支付方式名
+                		a.pay_device as pay_scene,-- 支付场景ID、支付场景名
+                		a.status as order_status, -- 支付状态
+                		a.cp_status , -- cp通知状态
+                		a.last_notify_time as last_cp_notify_time , -- cp最后通知时间
+                		a.merchant_no as pay_account_id, -- 收款账户
+                		a.server_id , -- 角色所属游戏区服ID
+                		IFNULL(h.server_name, a.server_name) as source_server_name , -- 原始区服名
+                		a.server_name , -- 角色所属游戏区服名
+                		a.role_id , -- 角色ID
+                		a.role_name , -- 角色名
+                		a.role_level , -- 角色等级
+                		a.role_vip , -- 角色VIP等级
+                		a.os , -- 操作系统
+                		a.is_switch as order_is_switch, -- 是否切量
+                		a.create_time as order_create_time, -- 下单时间
+                		a.pay_time,  -- 支付时间
+                		TIMESTAMPDIFF(SECOND, b.create_time, a.pay_time) as reg_until_pay, -- 注册充值时间差
+                		TIMESTAMPDIFF(SECOND, a.pay_time, NOW()) as pay_until_now, -- 最近充值时间距今(秒)
+                		IF(a.status = 2, IF(a.create_time = i.create_time, 1, 0), 0) as is_first_recharge -- 是否首充
+                	FROM dm_game_order.t_game_order a
+                	LEFT JOIN dm_game_order.t_game_user b on a.source_system = b.source_system AND a.user_id = b.id
+                	LEFT JOIN dm_game_order.t_pitcher_agent c on a.source_system = c.source_system AND a.agent_id = c.id
+                	LEFT JOIN dm_game_order.t_pitcher_map d on c.source_system = d.source_system AND c.pitcher_id = d.zx_pitcher_id
+                	LEFT JOIN dm_game_order.t_cp e on a.source_system = e.source_system AND a.cp_id = e.id
+                	LEFT JOIN dm_game_order.t_game f on a.source_system = f.source_system AND a.game_id = f.id
+                	LEFT JOIN dm_game_order.t_game g on b.source_system = g.source_system AND b.game_id = g.id
+                	LEFT JOIN dm_game_order.t_game_server_merge h on a.source_system = h.source_system AND a.server_id = h.server_id AND g.super_game_id = h.game_id
+                	LEFT JOIN (
+                		SELECT
+                			source_system ,
+                			user_id ,
+                			order_id ,
+                			create_time ,
+                			ROW_NUMBER()over(partition by source_system , user_id order by create_time ASC) as num
+                		FROM dm_game_order.t_game_order
+                		WHERE status = 2
+                	) i on a.source_system = i.source_system AND a.user_id = i.user_id AND i.num = 1
+                ) a
+                """;
+    }
 
 }

+ 303 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PlayerDataServiceImpl.java

@@ -1,14 +1,20 @@
 package com.zanxiang.game.data.serve.service.impl;
 
 import com.zanxiang.game.data.serve.component.DataPowerComponent;
+import com.zanxiang.game.data.serve.pojo.dto.PlayerBannedListDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerDataListDTO;
+import com.zanxiang.game.data.serve.pojo.dto.PlayerLoginLogDataListDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PlayerRoleDataListDTO;
+import com.zanxiang.game.data.serve.pojo.enums.DeviceTypeEnum;
 import com.zanxiang.game.data.serve.pojo.enums.GameCategoryEnum;
+import com.zanxiang.game.data.serve.pojo.enums.LogTypeEnum;
 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 lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.nutz.dao.Cnd;
@@ -20,8 +26,10 @@ import org.nutz.dao.sql.Sql;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -30,6 +38,7 @@ import java.util.stream.Collectors;
  * @Description 玩家数据的逻辑实现层
  **/
 @Service
+@Slf4j
 public class PlayerDataServiceImpl implements IPlayerDataService {
 
     @Autowired
@@ -61,6 +70,9 @@ public class PlayerDataServiceImpl implements IPlayerDataService {
         if (StringUtils.isNotBlank(dto.getNickname())) {
             cri.where().andLike("nickname", dto.getNickname());
         }
+        if (StringUtils.isNotBlank(dto.getRoleName())) {
+            cri.where().andLike("last_game_role_name", dto.getRoleName());
+        }
         if (StringUtils.isNotBlank(dto.getMobile())) {
             cri.where().andEquals("mobile", dto.getMobile());
         }
@@ -326,6 +338,144 @@ public class PlayerDataServiceImpl implements IPlayerDataService {
         return new Page<>(list, pager);
     }
 
+    /**
+     * 玩家登陆日志列表
+     * @param dto PlayerLoginLogDataListDTO
+     * @return Page<Map>
+     */
+    @Override
+    public Page<Map> getPlayerLoginLogDataList(PlayerLoginLogDataListDTO dto) {
+        //查询条件
+        Criteria cri = Cnd.cri();
+        if (StringUtils.isNotBlank(dto.getSourceSystem())) {
+            cri.where().andEquals("source_system", dto.getSourceSystem());
+        }
+        if (dto.getBeginDate() != null && dto.getEndDate() != null) {
+            //日期查询条件
+            cri.where().andBetween("DATE(dt)", dto.getBeginDate(), dto.getEndDate());
+        }
+        if (StringUtils.isNotBlank(dto.getUsername())) {
+            cri.where().andEquals("username", dto.getUsername());
+        }
+        if (dto.getUserId() != null) {
+            cri.where().andEquals("user_id", dto.getUserId());
+        }
+        if (dto.getGameId() != null) {
+            cri.where().andEquals("game_id", dto.getGameId());
+        }
+        if (dto.getGameClassify() != null) {
+            cri.where().andEquals("classify", dto.getGameClassify());
+        }
+        if (dto.getParentGameId() != null) {
+            cri.where().andEquals("parent_game_id", dto.getParentGameId());
+        }
+        if (dto.getRoleId() != null) {
+            cri.where().andEquals("role_id", dto.getRoleId());
+        }
+        if (StringUtils.isNotBlank(dto.getRoleName())) {
+            cri.where().andEquals("role_name", dto.getRoleName());
+        }
+        if (CollectionUtils.isNotEmpty(dto.getServerId())) {
+            cri.where().andIn("server_id", dto.getServerId().toArray(String[]::new));
+        }
+        if (StringUtils.isNotBlank(dto.getOs())) {
+            cri.where().andEquals("os", dto.getOs());
+        }
+        if (dto.getDeviceType() != null) {
+            cri.where().andEquals("device_type", dto.getDeviceType());
+        }
+        if (dto.getType() != null) {
+            cri.where().andEquals("log_type", dto.getType());
+        }
+        if (StringUtils.isNotBlank(dto.getIp())) {
+            cri.where().andEquals("ip", dto.getIp());
+        }
+        //分页
+        Pager pager = dao.createPager(dto.getPageNum(), dto.getPageSize());
+        //获取记录数
+        Sql countSql = Sqls.create(getPlayerLoginLogDataCountSql() + cri);
+        countSql.setCallback(Sqls.callback.integer());
+        dao.execute(countSql);
+        pager.setRecordCount(countSql.getInt());
+
+        //添加默认排序
+        cri.getOrderBy().orderBy("dt", OrderByEnum.DESC.getOrderType());
+        //创建SQL语句
+        Sql sql = Sqls.create(getPlayerLoginLogDataSql() + cri);
+        sql.setCallback(Sqls.callback.maps());
+        sql.setPager(pager);
+        //获取结果
+        dao.execute(sql);
+        List<Map> list = sql.getList(Map.class).stream().map( map -> {
+            //获取游戏类型
+            String gameClassify = GameCategoryEnum.getNameByCategory(Long.valueOf((Integer)map.get("classify")));
+            if (StringUtils.isNotBlank(gameClassify)) {
+                map.put("classify", gameClassify);
+            }
+            //获取客户端类型
+            String deviceType = DeviceTypeEnum.getName((Integer) map.get("device_type"));
+            if (StringUtils.isNotBlank(deviceType)) {
+                map.put("device_type", deviceType);
+            }
+            //获取登陆类型
+            String logTypeName = LogTypeEnum.getLogTypeName((Integer) map.get("log_type"));
+            if (StringUtils.isNotBlank(logTypeName)) {
+                map.put("log_type", logTypeName);
+            }
+
+            return map;
+        }).collect(Collectors.toList());
+
+        return new Page<>(list, pager);
+    }
+
+    /**
+     * 登陆IP玩家列表
+     * @param dto PlayerBannedListDTO
+     * @return Page<Map>
+     */
+    @Override
+    public Page<Map> getPlayerBannedDataList(PlayerBannedListDTO dto) {
+        Criteria cri = Cnd.cri();
+        if (StringUtils.isBlank(dto.getIp())) {
+            return null;
+        }
+        cri.where().andEquals("ip", dto.getIp());
+        cri.where().andEquals("source_system", "ZX_ONE");
+        //查询出所有玩家的ID
+        Sql findUserIdSql = Sqls.create("""
+                SELECT
+                	DISTINCT user_id
+                FROM dm_game_order.t_user_login_log
+                """ + cri);
+        findUserIdSql.setCallback(Sqls.callback.longs());
+        dao.execute(findUserIdSql);
+        //执行结果
+        Collection userIds = findUserIdSql.getObject(Collection.class);
+        //分页
+        Pager pager = dao.createPager(dto.getPageNum(), dto.getPageSize());
+        //查询出用户列表
+        Criteria userMapCri = Cnd.cri();
+        userMapCri.where().andEquals("source_system", "ZX_ONE");
+        userMapCri.where().andInList("user_id", userIds.stream().toList());
+
+        //查询记录数
+        Sql userMapCountSql = Sqls.create(getUserMapCountSql() + userMapCri);
+        userMapCountSql.setCallback(Sqls.callback.integer());
+        dao.execute(userMapCountSql);
+        pager.setRecordCount(userMapCountSql.getInt());
+
+        //查询结果
+        Sql userMapSql = Sqls.create(getUserMapSql() + userMapCri);
+        userMapSql.setCallback(Sqls.callback.maps());
+        userMapSql.setPager(pager);
+        dao.execute(userMapSql);
+        List<Map> list = userMapSql.getList(Map.class);
+
+        return new Page<>(list, pager);
+    }
+
+
     /**
      * 查询玩家列表数据SQL
      * @return String
@@ -746,4 +896,157 @@ public class PlayerDataServiceImpl implements IPlayerDataService {
                 """;
     }
 
+    /**
+     * 玩家登陆日志查询列表
+     * @return String
+     */
+    private String getPlayerLoginLogDataSql() {
+        return """
+                SELECT
+                	*
+                FROM (
+                	SELECT
+                		a.source_system , -- SDK来源
+                		a.id , -- 主键id
+                		a.create_time as dt, -- 时间
+                		c.username , -- 玩家账号
+                		a.user_id , -- 用户id
+                		a.game_id , -- 登陆游戏id
+                		b.game_name , -- 登陆游戏名
+                		b.classify , -- 游戏类型
+                		IFNULL(b.parent_id, a.game_id ) as parent_game_id , -- 父游戏id
+                		IFNULL(e.game_name, b.game_name) as parent_game_name, -- 父游戏名
+                		b.super_game_id , -- 超父游戏id
+                		a.role_id , -- 角色id
+                		a.role_name , -- 角色名
+                		d.server_id , -- 区服id
+                		d.server_name , -- 区服名
+                		f.server_name as source_server_name, -- 原始区服名
+                		a.os , -- 操作系统
+                		a.ip , -- 登陆ip
+                		a.device_type , -- 客户端类型
+                		a.`type` as log_type -- 登陆类型 0-注册;1-登陆;2-退出
+                	FROM dm_game_order.t_user_login_log a
+                	LEFT JOIN dm_game_order.t_game b on a.source_system = b.source_system AND a.game_id = b.id
+                	LEFT JOIN dm_game_order.t_game_user c on a.source_system = c.source_system AND a.user_id = c.id
+                	LEFT JOIN dm_game_order.t_game_user_role d on a.source_system = d.source_system AND a.user_id = d.user_id AND a.role_id = d.role_id
+                	LEFT JOIN dm_game_order.t_game e on b.source_system = e.source_system AND b.parent_id = e.id
+                	LEFT JOIN dm_game_order.t_game_server_merge f on a.source_system = f.source_system AND b.super_game_id = f.game_id AND d.server_id = f.server_id
+                ) a
+                """;
+    }
+
+    /**
+     * 玩家登陆日志记录数
+     * @return String
+     */
+    private String getPlayerLoginLogDataCountSql() {
+        return """
+                SELECT
+                    COUNT(1)
+                FROM (
+                        SELECT
+                        *
+                    FROM (
+                        SELECT
+                            a.source_system , -- SDK来源
+                            a.id , -- 主键id
+                            a.create_time as dt, -- 时间
+                            c.username , -- 玩家账号
+                            a.user_id , -- 用户id
+                            a.game_id , -- 登陆游戏id
+                            b.game_name , -- 登陆游戏名
+                            b.classify , -- 游戏类型
+                            IFNULL(b.parent_id, a.game_id ) as parent_game_id , -- 父游戏id
+                            IFNULL(e.game_name, b.game_name) as parent_game_name, -- 父游戏名
+                            b.super_game_id , -- 超父游戏id
+                            a.role_id , -- 角色id
+                            a.role_name , -- 角色名
+                            d.server_id , -- 区服id
+                            d.server_name , -- 区服名
+                            f.server_name , -- 原始区服名
+                            a.os , -- 操作系统
+                            a.ip , -- 登陆ip
+                            a.device_type , -- 客户端类型
+                            a.`type` as log_type -- 登陆类型 0-注册;1-登陆;2-退出
+                        FROM dm_game_order.t_user_login_log a
+                        LEFT JOIN dm_game_order.t_game b on a.source_system = b.source_system AND a.game_id = b.id
+                        LEFT JOIN dm_game_order.t_game_user c on a.source_system = c.source_system AND a.user_id = c.id
+                        LEFT JOIN dm_game_order.t_game_user_role d on a.source_system = d.source_system AND a.user_id = d.user_id AND a.role_id = d.role_id
+                        LEFT JOIN dm_game_order.t_game e on b.source_system = e.source_system AND b.parent_id = e.id
+                        LEFT JOIN dm_game_order.t_game_server_merge f on a.source_system = f.source_system AND b.super_game_id = f.game_id AND d.server_id = f.server_id
+                    ) a
+                ) a
+                """;
+    }
+
+    /**
+     * 获取所有用户sql
+     * @return String
+     */
+    private String getUserMapSql() {
+        return """
+                SELECT
+                    *
+                FROM (
+                    SELECT
+                    	a.source_system ,
+                    	a.id as user_id,
+                    	a.username ,
+                    	a.nickname ,
+                    	a.status ,
+                    	b.role_id ,
+                    	b.role_name
+                    FROM dm_game_order.t_game_user a
+                    LEFT JOIN (
+                    	SELECT
+                    		source_system ,
+                    		user_id ,
+                    		role_id ,
+                    		role_name ,
+                    		ROW_NUMBER() OVER(PARTITION BY user_id,source_system order by create_time desc) as num
+                    	FROM dm_game_order.t_user_login_log
+                    	WHERE NOT role_id = 'null'
+                    ) b on a.source_system = b.source_system AND a.id = b.user_id AND b.num = 1
+                ) a
+                """;
+    }
+
+    /**
+     * 获取所有用户记录数sql
+     * @return String
+     */
+    private String getUserMapCountSql() {
+        return """
+                SELECT
+                    COUNT(1)
+                FROM (
+                    SELECT
+                        *
+                    FROM (
+                        SELECT
+                            a.source_system ,
+                            a.id as user_id,
+                            a.username ,
+                            a.nickname ,
+                            a.status ,
+                            b.role_id ,
+                            b.role_name
+                        FROM dm_game_order.t_game_user a
+                        LEFT JOIN (
+                            SELECT
+                                source_system ,
+                                user_id ,
+                                role_id ,
+                                role_name ,
+                                ROW_NUMBER() OVER(PARTITION BY user_id,source_system order by create_time desc) as num
+                            FROM dm_game_order.t_user_login_log
+                            WHERE NOT role_id = 'null'
+                        ) b on a.source_system = b.source_system AND a.id = b.user_id AND b.num = 1
+                    ) a
+                ) a
+                """;
+    }
+
+
 }

+ 14 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/PromotionDayServiceImpl.java

@@ -272,6 +272,13 @@ public class PromotionDayServiceImpl implements IAdsPromotionDayService {
         if (StringUtils.isNotBlank(dto.getSourceSystem())) {
             cri.where().andEquals("source_system", dto.getSourceSystem());
         }
+        //首日充值金额筛选
+        if (dto.getFirstRechargeAmountMin() != null) {
+            cri.where().andGTE("first_new_user_amount", dto.getFirstRechargeAmountMin());
+        }
+        if (dto.getFirstRechargeAmountMax() != null) {
+            cri.where().andLTE("first_new_user_amount", dto.getFirstRechargeAmountMax());
+        }
         //创建sql
         Sql promotionDayTotalSql = Sqls.create(promotionDayTotalSql() + cri);
         //设置回传对象
@@ -806,6 +813,13 @@ public class PromotionDayServiceImpl implements IAdsPromotionDayService {
             cri.where().andEquals("source_system", dto.getSourceSystem());
         }
         if (needGroupBy) {
+            //只作用于主表查询,首日充值金额筛选
+            if (dto.getFirstRechargeAmountMin() != null) {
+                cri.where().andGTE("first_new_user_amount", dto.getFirstRechargeAmountMin());
+            }
+            if (dto.getFirstRechargeAmountMax() != null) {
+                cri.where().andLTE("first_new_user_amount", dto.getFirstRechargeAmountMax());
+            }
             //拼接分组条件
             cri.getGroupBy().groupBy("promotion_id");
         }

File diff suppressed because it is too large
+ 499 - 468
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/RoleManageServiceImpl.java


+ 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修改> ( ´・・)ノ(._.`) \n" +
+        System.out.println("赞象Manage服务启动成功 <区服新增excel方式上线> ( ´・・)ノ(._.`) \n" +
                 "___  ___  ___   _   _   ___  _____  _____ \n" +
                 "|  \\/  | / _ \\ | \\ | | / _ \\|  __ \\|  ___|\n" +
                 "| .  . |/ /_\\ \\|  \\| |/ /_\\ \\ |  \\/| |__  \n" +

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

@@ -2,6 +2,7 @@ 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.enums.GameServerExcelEnum;
 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;
@@ -19,6 +20,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -39,6 +41,15 @@ public class GameServerController {
     @Autowired
     private IGameSupperService gameSupperService;
 
+    @ApiOperation(value = "新增原始服合服excel")
+    @PostMapping(value = "/add/excel")
+    @PreAuthorize(permissionKey = "manage:gameServer:addExcel")
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = Boolean.class)})
+    public ResultVO<Boolean> addOrUpdate(MultipartFile multipartFile, @RequestParam Long gameId,
+                                         @RequestParam GameServerExcelEnum gameServerExcelEnum) {
+        return ResultVO.ok(gameServerService.gameServerExcelImport(multipartFile, gameServerExcelEnum, gameId));
+    }
+
     @ApiOperation(value = "新增或修改游戏区服")
     @PostMapping(value = "/add/or/update")
     @PreAuthorize(permissionKey = "manage:gameServer:addOrUpdate")

+ 30 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/enums/GameServerExcelEnum.java

@@ -0,0 +1,30 @@
+package com.zanxiang.game.module.manage.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-10-10
+ * @description : 游戏区服excel
+ */
+@Getter
+@AllArgsConstructor
+public enum GameServerExcelEnum {
+
+    /**
+     * 添加区服
+     */
+    SERVER_ADD("SERVER_ADD"),
+
+    /**
+     * 合并区服
+     */
+    SERVER_MERGE("SERVER_ADD");
+
+    /**
+     * 文件类型
+     */
+    private String value;
+
+}

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


+ 61 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/GameServerExcelDTO.java

@@ -0,0 +1,61 @@
+package com.zanxiang.game.module.manage.pojo.dto;
+
+import com.zanxiang.module.util.excel.ExcelAnno;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-10-10
+ * @description : 游戏区服excel
+ */
+@Data
+public class GameServerExcelDTO {
+
+    /**
+     * 区服名称
+     */
+    @ExcelAnno(title = "区服名称")
+    private String serverName;
+
+    // -------- 新增原始服字段 --------
+
+    /**
+     * 区服id
+     */
+    @ExcelAnno(title = "区服ID")
+    private String serverId;
+
+    /**
+     * 开服时间
+     */
+    @ExcelAnno(title = "开服时间", stringToDateFormat = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime startTime;
+
+    /**
+     * 区服冠名
+     */
+    @ExcelAnno(title = "区服冠名")
+    private String nickName;
+
+    // -------- 合服字段 --------
+
+    /**
+     * 合服id列表
+     */
+    @ExcelAnno(title = "合区id列表")
+    private String serverIds;
+
+    /**
+     * 合服主服id
+     */
+    @ExcelAnno(title = "合服主服id")
+    private String mainServerId;
+
+    /**
+     * 合服时间
+     */
+    @ExcelAnno(title = "合服时间", stringToDateFormat = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime mergeTime;
+}

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

@@ -2,12 +2,14 @@ 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.enums.GameServerExcelEnum;
 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 org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -18,6 +20,16 @@ import java.util.List;
  */
 public interface IGameServerService extends IService<GameServer> {
 
+    /**
+     * 区服excel提交
+     *
+     * @param multipartFile        文件流
+     * @param gameServerExcelEnum  操作类型枚举
+     * @param gameId               游戏id
+     * @return {@link Boolean}
+     */
+    Boolean gameServerExcelImport(MultipartFile multipartFile, GameServerExcelEnum gameServerExcelEnum, Long gameId);
+
     /**
      * 列表名字
      *

+ 108 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/GameServerServiceImpl.java

@@ -9,7 +9,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 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.enums.GameServerExcelEnum;
 import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
+import com.zanxiang.game.module.manage.pojo.dto.GameServerExcelDTO;
 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;
@@ -23,14 +25,17 @@ 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.excel.ExcelUtil;
 import com.zanxiang.module.util.exception.BaseException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.logging.log4j.util.Strings;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 import reactor.util.function.Tuple2;
 
+import java.io.IOException;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.util.*;
@@ -55,6 +60,109 @@ public class GameServerServiceImpl extends ServiceImpl<GameServerMapper, GameSer
     @Autowired
     private IGameSupperService gameSupperService;
 
+    @Override
+    public Boolean gameServerExcelImport(MultipartFile multipartFile, GameServerExcelEnum gameServerExcelEnum, Long gameId) {
+        StringBuilder stringBuilder = new StringBuilder();
+        List<GameServerExcelDTO> gameServerExcelList;
+        //文件流转换
+        try {
+            gameServerExcelList = ExcelUtil.importFromStream(multipartFile.getInputStream(), GameServerExcelDTO.class, stringBuilder);
+        } catch (IOException e) {
+            throw new BaseException(stringBuilder.toString());
+        }
+        //原始区服添加
+        if (Objects.equals(gameServerExcelEnum, GameServerExcelEnum.SERVER_ADD)) {
+            List<GameServer> gameServerList = new ArrayList<>();
+            gameServerExcelList.forEach(excelDTO -> {
+                //判断单游戏内区服id不可重复
+                if (super.count(new LambdaQueryWrapper<GameServer>()
+                        .eq(GameServer::getGameId, gameId)
+                        .eq(GameServer::getServerId, excelDTO.getServerId())
+                ) > 0) {
+                    throw new BaseException("该游戏区服id : " + excelDTO.getServerId() + "已存在, 禁止重复添加");
+                }
+                gameServerList.add(this.transform(excelDTO, gameId));
+            });
+            return super.saveBatch(gameServerList);
+        }
+        //合服添加
+        List<GameServer> gameServerList = new ArrayList<>();
+        List<String> mergeSerIdList = new ArrayList<>();
+        gameServerExcelList.forEach(excelDTO -> {
+            Set<String> sonServerIdList = Arrays.stream(excelDTO.getServerIds().split(",")).collect(Collectors.toSet());
+            List<GameServer> sonServerList = super.list(new LambdaQueryWrapper<GameServer>()
+                    .eq(GameServer::getGameId, gameId)
+                    .eq(GameServer::getIsMerge, Boolean.FALSE)
+                    .in(GameServer::getServerId, sonServerIdList));
+            if (CollectionUtils.isEmpty(sonServerList)) {
+                throw new BaseException("合服子服列表查询为空, 请检查子服列表是否存在错误id, 或者是否包含已参与过合服的区服");
+            }
+            if (!sonServerIdList.contains(excelDTO.getMainServerId())) {
+                throw new BaseException("合服主服id : " + excelDTO.getMainServerId() + "不存在子服id列表中, 请检查数据");
+            }
+            if (sonServerIdList.size() != sonServerList.size()) {
+                List<String> collect = sonServerList.stream().map(GameServer::getServerId).collect(Collectors.toList());
+                List<String> list = sonServerIdList.stream().filter(son -> !collect.contains(son)).collect(Collectors.toList());
+                throw new BaseException("提交的子服中存在错误的区服id : " + list.toString());
+            }
+            Set<String> sourceServerIds = new HashSet<>();
+            sonServerList.forEach(gameServer -> {
+                if (gameServer.getIsSourceServer()) {
+                    sourceServerIds.add(gameServer.getServerId());
+                    return;
+                }
+                if (Strings.isNotBlank(gameServer.getSourceServerIds())) {
+                    Collections.addAll(sourceServerIds, gameServer.getSourceServerIds().split(","));
+                }
+            });
+            gameServerList.add(this.transform(excelDTO, sonServerIdList, sourceServerIds, gameId));
+            mergeSerIdList.addAll(sonServerIdList);
+        });
+        super.saveBatch(gameServerList);
+        return super.update(new LambdaUpdateWrapper<GameServer>()
+                .set(GameServer::getIsMerge, Boolean.TRUE)
+                .set(GameServer::getUpdateTime, LocalDateTime.now())
+                .eq(GameServer::getGameId, gameId)
+                .in(GameServer::getServerId, mergeSerIdList));
+    }
+
+    private GameServer transform(GameServerExcelDTO excelDTO, Long gameId) {
+        return GameServer.builder()
+                .gameId(gameId)
+                .serverId(excelDTO.getServerId())
+                .serverName(excelDTO.getServerName())
+                .nickName(excelDTO.getNickName())
+                .startTime(excelDTO.getStartTime())
+                .isDelete(DeleteEnum.NO.getCode())
+                .createBy(SecurityUtil.getUserId())
+                .createTime(LocalDateTime.now())
+                .isSourceServer(Boolean.TRUE)
+                .isMerge(Boolean.FALSE)
+                .updateBy(SecurityUtil.getUserId())
+                .updateTime(LocalDateTime.now())
+                .build();
+    }
+
+    private GameServer transform(GameServerExcelDTO excelDTO, Set<String> sonServerIds, Set<String> sourceServerIds, Long gameId) {
+        return GameServer.builder()
+                .gameId(gameId)
+                .serverId(UUID.randomUUID().toString())
+                .serverName(excelDTO.getServerName())
+                .isSourceServer(Boolean.FALSE)
+                .mainServerId(excelDTO.getMainServerId())
+                .isMerge(Boolean.FALSE)
+                .sonServerIds(String.join(",", sonServerIds))
+                .sourceServerIds(String.join(",", sourceServerIds))
+                .mergeTime(excelDTO.getMergeTime())
+                .startTime(excelDTO.getMergeTime())
+                .isDelete(DeleteEnum.NO.getCode())
+                .createBy(SecurityUtil.getUserId())
+                .createTime(LocalDateTime.now())
+                .updateBy(SecurityUtil.getUserId())
+                .updateTime(LocalDateTime.now())
+                .build();
+    }
+
     @Override
     public List<String> listServerId(Long gameId, String serverName) {
         if (Strings.isBlank(serverName)) {

Some files were not shown because too many files changed in this diff