Просмотр исходного кода

获取团队信息的基础逻辑应该好了

skyfffire 1 месяц назад
Родитель
Сommit
25174776ca

+ 2 - 2
src/main/java/common/model/base/BaseOrder.java

@@ -61,14 +61,14 @@ public abstract class BaseOrder<M extends BaseOrder<M>> extends Model<M> impleme
 		return getLong("nftt_id");
 	}
 	/**
-	 * 订单状态:0=已取消, 10=待支付, 20=预购待确认, 30=预购成功, 40=已支付, 50=已发货/已确权, 60=已完成, 70=退款中, 80=退款成功, 90=退款失败
+	 * 订单状态:100=已取消, 10=待支付, 20=预购待确认, 30=预购成功, 40=已支付, 50=已发货/已确权, 60=已完成, 70=退款中, 80=退款成功, 90=退款失败
 	 */
 	public void setOrderStatus(java.lang.Integer orderStatus) {
 		set("order_status", orderStatus);
 	}
 	
 	/**
-	 * 订单状态:0=已取消, 10=待支付, 20=预购待确认, 30=预购成功, 40=已支付, 50=已发货/已确权, 60=已完成, 70=退款中, 80=退款成功, 90=退款失败
+	 * 订单状态:100=已取消, 10=待支付, 20=预购待确认, 30=预购成功, 40=已支付, 50=已发货/已确权, 60=已完成, 70=退款中, 80=退款成功, 90=退款失败
 	 */
 	public java.lang.Integer getOrderStatus() {
 		return getInt("order_status");

+ 26 - 0
src/main/java/common/model/base/BaseUser.java

@@ -203,6 +203,32 @@ public abstract class BaseUser<M extends BaseUser<M>> extends Model<M> implement
 	public java.lang.String getBsnAccountAddress() {
 		return getStr("bsn_account_address");
 	}
+	/**
+	 * 是否是有效用户(充值并购买过至少1枚NFT)
+	 */
+	public void setIsEffective(java.lang.Integer isEffective) {
+		set("is_effective", isEffective);
+	}
+	
+	/**
+	 * 是否是有效用户(充值并购买过至少1枚NFT)
+	 */
+	public java.lang.Integer getIsEffective() {
+		return getInt("is_effective");
+	}
+	/**
+	 * 成为有效用户的时间
+	 */
+	public void setEffectiveTime(java.lang.Long effectiveTime) {
+		set("effective_time", effectiveTime);
+	}
+	
+	/**
+	 * 成为有效用户的时间
+	 */
+	public java.lang.Long getEffectiveTime() {
+		return getLong("effective_time");
+	}
 	public void setCreateTime(java.lang.Long createTime) {
 		set("create_time", createTime);
 	}

+ 7 - 0
src/main/java/modules/order/OrderService.java

@@ -382,6 +382,13 @@ public class OrderService {
 
                             order.update();
                             AppConfig.LOGGER.info("该订单已确权:{}", order);
+                            
+                            // 该用户如果没有标记为有效账户进行标记
+                            if (user.getIsEffective() == 0) {
+                                user.setIsEffective(1);
+                                user.setEffectiveTime(System.currentTimeMillis());
+                                user.update();
+                            }
 
                             // 异步执行分润过程
                             AppConfig.TaskScheduler.submit(new UserTeamShareTask(order, userService));

+ 7 - 0
src/main/java/modules/user/UserController.java

@@ -135,6 +135,7 @@ public class UserController extends MyController {
         user.set("pwd_md5_md5", HashKit.md5(pwd));
         user.set("integral", 0);
         user.set("is_deleted", 0); // 0表示未禁用
+        user.set("is_effective", 0); // 0表示不是有效账户
 
         // 5. 调用服务层进行用户保存
         renderJson(service.saveUser(user));
@@ -499,6 +500,12 @@ public class UserController extends MyController {
         renderJson(MyRet.ok("已成功登出。"));
     }
 
+    @Before(LoginInterceptor.class)
+    @RequiredRoleInterface({UserController.ROLE_SUPER_ADMIN})
+    public void teamInfoByAdmin() {
+        renderJson(service.teamInfoByAdmin());
+    }
+
     /**
      * 更新用户的方法,传什么更新什么,不传就不更新,id必须传
      */

+ 116 - 6
src/main/java/modules/user/UserService.java

@@ -3,13 +3,15 @@ package modules.user;
 import com.alibaba.fastjson.JSONObject;
 import com.jfinal.kit.StrKit;
 import com.jfinal.plugin.activerecord.Db;
+import com.jfinal.plugin.activerecord.Record;
 import common.jfinal.AppConfig;
 import common.model.User;
 import common.utils.bsn.BsnSDK;
 import common.utils.http.MyRet;
 import common.utils.hyg.HygSDK;
 
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 public class UserService {
     public String hello() {
@@ -94,11 +96,11 @@ public class UserService {
         return Db.queryStr(sql, token);
     }
 
-    public String findWorkidByToken(String token) {
-        String sql = "select workid from t_user where token = ?";
-
-        return Db.queryStr(sql, token);
-    }
+//    public String findWorkidByToken(String token) {
+//        String sql = "select workid from t_user where token = ?";
+//
+//        return Db.queryStr(sql, token);
+//    }
 
     public User findUserById(String id) {
         String sql = "select * from t_user where id = ?";
@@ -188,4 +190,112 @@ public class UserService {
             return User.dao.find(fullSql, searchKeyWord, searchKeyWord, searchKeyWord, offset, pageSize);
         }
     }
+
+    public MyRet teamInfoByAdmin() {
+        // 1. 查询所有推荐人ID及其有效下级用户数量
+        String queryReferrerStatsSql = "SELECT referrer_id, COUNT(id) AS valid_user_count " +
+                "FROM t_user " +
+                "WHERE is_effective = 1 AND referrer_id IS NOT NULL " +
+                "GROUP BY referrer_id HAVING COUNT(id) > 0";
+        AppConfig.LOGGER.info("执行 SQL 查询推荐人统计: {}", queryReferrerStatsSql);
+        List<Record> referrerStatsRecords = Db.find(queryReferrerStatsSql);
+
+        if (referrerStatsRecords.isEmpty()) {
+            AppConfig.LOGGER.info("没有符合条件的推荐人。");
+            return MyRet.fail("还没人推荐过任何人是有效用户。");
+        }
+
+        // 提取所有唯一的 referrer_id,并转换为 List 方便分批
+        List<Long> eligibleReferrerIdsList = referrerStatsRecords.stream()
+                .map(record -> record.getLong("referrer_id"))
+                .distinct() // 确保唯一,虽然 Set 已经保证了
+                .collect(Collectors.toList());
+        AppConfig.LOGGER.info("符合条件的推荐人ID数量: {}", eligibleReferrerIdsList.size());
+
+        // 转换为 Map,方便通过 referrer_id 查找 valid_user_count (这个 Map 仍然需要)
+        Map<Long, Integer> referrerValidUserCountMap = referrerStatsRecords.stream()
+                .collect(Collectors.toMap(
+                        record -> record.getLong("referrer_id"),
+                        record -> record.getLong("valid_user_count").intValue()
+                ));
+
+        // ******** 2. 分批查询所有推荐人 User 对象,并直接整合 valid_user_count 到 User 对象中 ********
+        final int BATCH_QUERY_SIZE = 1000;
+        List<User> finalReferrerList = new ArrayList<>(eligibleReferrerIdsList.size()); // 最终的推荐人 User 对象列表
+
+        AppConfig.LOGGER.info("开始分批查询推荐人 User 对象并整合 valid_referred_count...");
+        for (int i = 0; i < eligibleReferrerIdsList.size(); i += BATCH_QUERY_SIZE) {
+            List<Long> subListReferrerIds = eligibleReferrerIdsList.subList(i, Math.min(i + BATCH_QUERY_SIZE, eligibleReferrerIdsList.size()));
+            String subInSql = subListReferrerIds.stream().map(String::valueOf).collect(Collectors.joining(","));
+
+            List<User> currentBatchUsers = User.dao.find("SELECT id, mobile_number, balance FROM t_user WHERE id IN (" + subInSql + ")");
+
+            for (User referrer : currentBatchUsers) {
+                // 直接在这里将 valid_user_count 整合进去
+                Integer validUserCount = referrerValidUserCountMap.get(referrer.getId());
+                if (validUserCount != null) {
+                    referrer.put("valid_referred_count", validUserCount);
+                }
+            }
+            finalReferrerList.addAll(currentBatchUsers);
+            AppConfig.LOGGER.debug("已查询推荐人批次 {} 总已查询用户数: {}", i, finalReferrerList.size());
+        }
+        AppConfig.LOGGER.info("推荐人 User 对象查询并整合完毕,共查询到 {} 个推荐人。", finalReferrerList.size());
+
+        // ******** 3. 分批查询所有被推荐用户(下级用户),并按推荐人 ID 分组 ********
+        AppConfig.LOGGER.info("开始分批查询所有被推荐用户(下级用户)并分组...");
+        // 存储所有被推荐用户的数据,Key为referrer_id,Value为该referrer_id推荐的User的Map列表
+        Map<Long, List<Map<String, Object>>> allReferredUsersByReferrerId = new HashMap<>();
+
+        for (int i = 0; i < eligibleReferrerIdsList.size(); i += BATCH_QUERY_SIZE) {
+            List<Long> subListReferrerIds = eligibleReferrerIdsList.subList(i, Math.min(i + BATCH_QUERY_SIZE, eligibleReferrerIdsList.size()));
+            String subInReferrerSql = subListReferrerIds.stream().map(String::valueOf).collect(Collectors.joining(","));
+
+            String queryReferredUsersSql = "SELECT id, mobile_number, effective_time, referrer_id " +
+                    "FROM t_user " +
+                    "WHERE is_effective = 1 " + // 确保是有效用户
+                    "AND referrer_id IN (" + subInReferrerSql + ")" +
+                    "ORDER BY effective_time ASC";
+
+            List<Record> referredUserRecords = Db.find(queryReferredUsersSql);
+
+            // 将 Record 转换为 Map<String, Object> 并按 referrer_id 分组
+            for (Record record : referredUserRecords) {
+                Long currentReferrerId = record.getLong("referrer_id");
+                Map<String, Object> referredUser = new HashMap<>();
+                referredUser.put("id", record.getLong("id"));
+                referredUser.put("mobile_number", record.getStr("mobile_number"));
+                referredUser.put("effective_time", record.getLong("effective_time"));
+
+                allReferredUsersByReferrerId.computeIfAbsent(currentReferrerId, k -> new ArrayList<>()).add(referredUser);
+            }
+        }
+        AppConfig.LOGGER.info("所有被推荐用户查询并分组完毕。共找到被推荐用户 {} 条。",
+                allReferredUsersByReferrerId.values().stream().mapToInt(List::size).sum());
+
+        // ******** 4. 将被推荐用户列表整合到推荐人 User 对象中 ********
+        AppConfig.LOGGER.info("开始将下级用户列表整合到推荐人 User 对象...");
+        for (User referrer : finalReferrerList) { // 遍历已经整合了 valid_referred_count 的推荐人列表
+            Long referrerId = referrer.getId();
+            List<Map<String, Object>> referredUsers = allReferredUsersByReferrerId.getOrDefault(referrerId, Collections.emptyList()); // 使用 getOrDefault 避免 NPE
+
+            referrer.put("referred_users", referredUsers); // put 进去一个 List<Map<String, Object>>
+            AppConfig.LOGGER.info("推荐人: {}", referrer.toJson());
+            AppConfig.LOGGER.debug("推荐人 {} 已关联 {} 个被推荐用户。", referrerId, referredUsers.size());
+
+            for (Map<String, Object> ru : referredUsers) {
+                AppConfig.LOGGER.info("     - ID:{}, 手机号:{}, 有效时间:{}", ru.get("id"), ru.get("mobile_number"), ru.get("effective_time"));
+            }
+        }
+
+        AppConfig.LOGGER.info("直推网络查询与构建完成。");
+        // ******** 分批查询 User 对象结束 ********
+
+        // 筛选出直推人数大于10人的组,每个用户按第10位被推荐人(下级)的有效时间进行从小到大排序
+
+        // 筛选出直推人数大于5人的组,每个用户按第5位被推荐人(下级)的有效时间进行从小到大排序
+        // 筛选出直推人数大于2人的组,每个用户按第2位被推荐人(下级)的有效时间进行从小到大排序
+
+        return MyRet.ok("查询成功");
+    }
 }

+ 2 - 2
src/main/java/modules/user/UserTeamShareTask.java

@@ -278,7 +278,7 @@ public class UserTeamShareTask implements Runnable {
     /**
      * 第四类、持有者激励分润,这个最复杂最后做,可能需要为user加一个时间戳字段
      */
-    public void class4() {}
+//    public void class4() {}
     
     @Override
     public void run() {
@@ -289,7 +289,7 @@ public class UserTeamShareTask implements Runnable {
                 this.class1();
                 this.class2();
                 this.class3();
-                this.class4();
+//                this.class4();
                 return true; // 事务成功
             } catch (Exception e) {
                 AppConfig.LOGGER.error("订单分润处理异常,订单ID: {}, 错误: {}", order.getLong("id"), e.getMessage(), e);

+ 5 - 0
src/test/rest/UserControllerTest.http

@@ -95,6 +95,11 @@ dl-token: {{dl_token_var}}
   "verify_code": "7734"
 }
 
+### 【超级管理员】获取团队信息
+POST {{ baseUrl }}/user/teamInfoByAdmin
+Content-Type: application/json
+dl-token: {{dl_token_var}}
+
 ### 【超级管理员】更新用户的方法,传什么更新什么,不传就不更新,id必须传
 POST {{ baseUrl }}/user/updateByAdmin
 Content-Type: application/json