From a15e0b30a6bd4b18354f903ea9a51a6552b1e732 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Thu, 23 Apr 2026 18:34:40 +0800
Subject: [PATCH] 1

---
 trading-order-bean/src/main/java/com/yami/trading/bean/user/dto/UserAllRecomDto.java              |    6 +
 trading-order-admin/src/main/java/com/yami/trading/api/controller/ApiUserController.java          |    2 
 trading-order-service/src/main/resources/mapper/user/UserRecomMapper.xml                          |    9 ++
 trading-order-admin/src/main/java/com/yami/trading/api/controller/PromoteController.java          |  139 ++++++++++++++++++++++++++++++++++
 trading-order-common/src/main/java/com/yami/trading/common/constants/Constants.java               |   20 +++++
 trading-order-service/src/main/java/com/yami/trading/service/user/impl/QRGenerateServiceImpl.java |    8 +
 6 files changed, 177 insertions(+), 7 deletions(-)

diff --git a/trading-order-admin/src/main/java/com/yami/trading/api/controller/ApiUserController.java b/trading-order-admin/src/main/java/com/yami/trading/api/controller/ApiUserController.java
index f33025d..f08015b 100644
--- a/trading-order-admin/src/main/java/com/yami/trading/api/controller/ApiUserController.java
+++ b/trading-order-admin/src/main/java/com/yami/trading/api/controller/ApiUserController.java
@@ -615,7 +615,7 @@
                 map.put("url", "");
                 map.put("usercode_qr", "");
             } else {
-                map.put("url", Constants.WEB_URL + "/register.html?usercode=" + party.getUserCode());
+                map.put("url", Constants.buildRegisterInviteLink(party.getUserCode()));
                 // 生成二维码图片
                 qrGenerateService.generate(party.getUserCode());
                 map.put("usercode_qr", Constants.WEB_URL + "/public/showimg!showImg.action?imagePath=/qr/" + party.getUserCode() + ".png");
diff --git a/trading-order-admin/src/main/java/com/yami/trading/api/controller/PromoteController.java b/trading-order-admin/src/main/java/com/yami/trading/api/controller/PromoteController.java
index 921f831..5ddbe1c 100644
--- a/trading-order-admin/src/main/java/com/yami/trading/api/controller/PromoteController.java
+++ b/trading-order-admin/src/main/java/com/yami/trading/api/controller/PromoteController.java
@@ -1,7 +1,10 @@
 package com.yami.trading.api.controller;
 
 import com.yami.trading.bean.model.UserData;
+import com.yami.trading.bean.model.User;
+import com.yami.trading.bean.model.UserRecom;
 import com.yami.trading.bean.user.dto.ChildrenLever;
+import com.yami.trading.common.constants.Constants;
 import com.yami.trading.common.domain.Result;
 import com.yami.trading.common.exception.BusinessException;
 import com.yami.trading.common.exception.YamiShopBindException;
@@ -21,6 +24,7 @@
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 我的推广
@@ -38,8 +42,68 @@
     @Autowired
     protected SysparaService sysparaService;
 
+    @RequestMapping("api/promote!getInviteSummary.action")
+    public Result<?> getInviteSummary() {
+        String userId = SecurityUtils.getUser().getUserId();
+        Map<String, Object> data = buildInviteSummary(userId);
+        return Result.succeed(data);
+    }
+
+    @RequestMapping("api/promote!getInviteChildren.action")
+    public Result<?> getInviteChildren(HttpServletRequest request) {
+        String levelRaw = request.getParameter("level");
+        int level = StringUtils.isInteger(levelRaw) ? Integer.parseInt(levelRaw) : 1;
+        if (level < 1 || level > 2) {
+            throw new YamiShopBindException("代理层级错误");
+        }
+        String pageNoRaw = request.getParameter("page_no");
+        String pageSizeRaw = request.getParameter("page_size");
+        int pageNo = StringUtils.isInteger(pageNoRaw) && Integer.parseInt(pageNoRaw) > 0 ? Integer.parseInt(pageNoRaw) : 1;
+        int pageSize = StringUtils.isInteger(pageSizeRaw) && Integer.parseInt(pageSizeRaw) > 0 ? Integer.parseInt(pageSizeRaw) : 10;
+        pageSize = Math.min(pageSize, 100);
+
+        String userId = SecurityUtils.getUser().getUserId();
+        List<String> level1Ids = getDirectChildIds(userId);
+        List<String> targetIds;
+        if (level == 1) {
+            targetIds = level1Ids;
+        } else {
+            targetIds = new ArrayList<>();
+            for (String id : level1Ids) {
+                targetIds.addAll(getDirectChildIds(id));
+            }
+        }
+
+        List<Map<String, Object>> fullList = targetIds.stream().map(id -> {
+            User child = partyService.getById(id);
+            if (child == null) {
+                return null;
+            }
+            Map<String, Object> item = new HashMap<>();
+            item.put("user_id", child.getUserId());
+            item.put("username", maskUsername(child.getUserName()));
+            item.put("user_code", child.getUserCode());
+            item.put("create_time", child.getCreateTime());
+            item.put("direct_children_count", getDirectChildIds(child.getUserId()).size());
+            return item;
+        }).filter(Objects::nonNull).collect(Collectors.toList());
+
+        int total = fullList.size();
+        int from = Math.max((pageNo - 1) * pageSize, 0);
+        int to = Math.min(from + pageSize, total);
+        List<Map<String, Object>> pageList = from >= total ? Collections.emptyList() : fullList.subList(from, to);
+
+        Map<String, Object> data = new HashMap<>();
+        data.put("total", total);
+        data.put("level", level);
+        data.put("page_no", pageNo);
+        data.put("page_size", pageSize);
+        data.put("list", pageList);
+        return Result.succeed(data);
+    }
+
     @RequestMapping("api/promote!getPromote.action")
-    public Result getPromote(HttpServletRequest request) {
+    public Result<?> getPromote(HttpServletRequest request) {
         // 层级 1为第一级 1,2,3,4总共4级代理
         String  level_temp= request.getParameter("level");
         if (StringUtils.isNullOrEmpty(level_temp)
@@ -89,7 +153,7 @@
      * 交易所-数据总览-PC端
      */
     @RequestMapping( "api/promote!getPromoteData.action")
-    public Result getPromoteData(HttpServletRequest request) {
+    public Result<?> getPromoteData(HttpServletRequest request) {
         String partyId = SecurityUtils.getUser().getUserId();
         Map<String, String> dataMap = new HashMap<>();
         try {
@@ -145,4 +209,75 @@
 			}
 		}
 	}
+
+    private Map<String, Object> buildInviteSummary(String userId) {
+        User currentUser = partyService.getById(userId);
+        List<String> level1Ids = getDirectChildIds(userId);
+        List<String> level2Ids = new ArrayList<>();
+        for (String level1Id : level1Ids) {
+            level2Ids.addAll(getDirectChildIds(level1Id));
+        }
+        Map<String, Object> data = new HashMap<>();
+        String code = currentUser != null ? currentUser.getUserCode() : "";
+        data.put("invite_code", code);
+        data.put("invite_link", Constants.buildRegisterInviteLink(code));
+        data.put("total_count", level1Ids.size() + level2Ids.size());
+        data.put("tree", buildInviteTree(userId));
+        return data;
+    }
+
+    /**
+     * 两级邀请关系树:直接下级及其各自的下级(嵌套在 children 中)。
+     */
+    private List<Map<String, Object>> buildInviteTree(String rootUserId) {
+        List<Map<String, Object>> tree = new ArrayList<>();
+        for (String childId : getDirectChildIds(rootUserId)) {
+            User u = partyService.getById(childId);
+            if (u == null) {
+                continue;
+            }
+            Map<String, Object> node = inviteUserNode(u);
+            List<Map<String, Object>> children = new ArrayList<>();
+            for (String gcId : getDirectChildIds(childId)) {
+                User g = partyService.getById(gcId);
+                if (g != null) {
+                    children.add(inviteUserNode(g));
+                }
+            }
+            node.put("children", children);
+            tree.add(node);
+        }
+        return tree;
+    }
+
+    private Map<String, Object> inviteUserNode(User u) {
+        Map<String, Object> item = new HashMap<>();
+        item.put("user_id", u.getUserId());
+        item.put("username", maskUsername(u.getUserName()));
+        item.put("user_code", u.getUserCode());
+        item.put("create_time", u.getCreateTime());
+        return item;
+    }
+
+    private List<String> getDirectChildIds(String userId) {
+        List<UserRecom> list = userRecomService.findRecoms(userId);
+        if (list == null || list.isEmpty()) {
+            return Collections.emptyList();
+        }
+        return list.stream().map(UserRecom::getRecomUserId).filter(Objects::nonNull).collect(Collectors.toList());
+    }
+
+    private String maskUsername(String username) {
+        if (username == null) {
+            return "";
+        }
+        int len = username.length();
+        if (len <= 2) {
+            return username;
+        }
+        if (len <= 6) {
+            return username.substring(0, 1) + "***" + username.substring(len - 1);
+        }
+        return username.substring(0, 3) + "***" + username.substring(len - 2);
+    }
 }
diff --git a/trading-order-bean/src/main/java/com/yami/trading/bean/user/dto/UserAllRecomDto.java b/trading-order-bean/src/main/java/com/yami/trading/bean/user/dto/UserAllRecomDto.java
index 6f4e974..c1f6415 100644
--- a/trading-order-bean/src/main/java/com/yami/trading/bean/user/dto/UserAllRecomDto.java
+++ b/trading-order-bean/src/main/java/com/yami/trading/bean/user/dto/UserAllRecomDto.java
@@ -26,5 +26,11 @@
     @ApiModelProperty("推荐用户code")
     private  String recomUserCode;
 
+    @ApiModelProperty("一级下级人数")
+    private Integer level1Count;
+
+    @ApiModelProperty("二级下级人数")
+    private Integer level2Count;
+
     private  String roleNameDesc;
 }
diff --git a/trading-order-common/src/main/java/com/yami/trading/common/constants/Constants.java b/trading-order-common/src/main/java/com/yami/trading/common/constants/Constants.java
index 42be74e..0161341 100644
--- a/trading-order-common/src/main/java/com/yami/trading/common/constants/Constants.java
+++ b/trading-order-common/src/main/java/com/yami/trading/common/constants/Constants.java
@@ -18,6 +18,26 @@
 //
 	public static final String WEB_URL = ApplicationUtil.getProperty("web_url");
 
+	/**
+	 * H5/PC 哈希路由注册页邀请链接,避免 web_url 尾斜杠与路径拼接出现双斜杠。
+	 */
+	public static String normalizeWebUrl(String url) {
+		if (url == null) {
+			return "";
+		}
+		String s = url.trim();
+		while (s.endsWith("/")) {
+			s = s.substring(0, s.length() - 1);
+		}
+		return s;
+	}
+
+	public static String buildRegisterInviteLink(String userCode) {
+		String base = normalizeWebUrl(WEB_URL);
+		String code = userCode == null ? "" : String.valueOf(userCode).trim();
+		return base + "/#/register?usercode=" + code;
+	}
+
 	public static final String IMAGES_DIR = ApplicationUtil.getProperty("images.dir");
 
 	public static final String IMAGES_HTTP = ApplicationUtil.getProperty("images_http");
diff --git a/trading-order-service/src/main/java/com/yami/trading/service/user/impl/QRGenerateServiceImpl.java b/trading-order-service/src/main/java/com/yami/trading/service/user/impl/QRGenerateServiceImpl.java
index 158ea53..4bcb70a 100644
--- a/trading-order-service/src/main/java/com/yami/trading/service/user/impl/QRGenerateServiceImpl.java
+++ b/trading-order-service/src/main/java/com/yami/trading/service/user/impl/QRGenerateServiceImpl.java
@@ -33,10 +33,12 @@
     @Override
     public String generate(String content) {
         String image_name = "/qr/" + content + ".png";
-        content = Constants.WEB_URL + "/register.html?usercode=" + content;
+        final String userCode = content;
+        content = Constants.buildRegisterInviteLink(userCode);
         boolean openButton = sysparaService.find("short_url_open_button").getBoolean() ;
         if(openButton) {
-            content = sysparaService.find("agent_qr_url").getSvalue() + "/register.html?usercode=" + content;
+            String agentBase = Constants.normalizeWebUrl(sysparaService.find("agent_qr_url").getSvalue());
+            content = agentBase + "/#/register?usercode=" + userCode;
             boolean isCn = sysparaService.find("short_url_cn_button").getBoolean() ;
             if(isCn) {
                 content = shortUrlCn(content);
@@ -105,7 +107,7 @@
     @Override
     public String generate185(String content) {
         String image_name = "/qr/" + content + "2.png";
-        content = Constants.WEB_URL + "/register.html?usercode=" + content;
+        content = Constants.buildRegisterInviteLink(content);
         // String image_name = "/qr/" + UUIDGenerator.getUUID() + ".png";
         String filepath = Constants.IMAGES_DIR + image_name;
         File file = new File(filepath);
diff --git a/trading-order-service/src/main/resources/mapper/user/UserRecomMapper.xml b/trading-order-service/src/main/resources/mapper/user/UserRecomMapper.xml
index 07db239..7991dce 100644
--- a/trading-order-service/src/main/resources/mapper/user/UserRecomMapper.xml
+++ b/trading-order-service/src/main/resources/mapper/user/UserRecomMapper.xml
@@ -31,7 +31,14 @@
 
     <select id="listUserAll" resultType="com.yami.trading.bean.user.dto.UserAllRecomDto">
         SELECT u.user_id,u.user_name,u.user_code,u.role_name,ur.user_name AS 'recomUserName',
-        ur.user_code AS 'recomUserCode'  FROM tz_user u
+        ur.user_code AS 'recomUserCode',
+        (SELECT COUNT(1) FROM tz_user_recom r1 WHERE r1.user_id = u.user_id) AS level1Count,
+        (
+            SELECT COUNT(1)
+            FROM tz_user_recom r2
+            WHERE r2.user_id IN (SELECT r3.recom_user_id FROM tz_user_recom r3 WHERE r3.user_id = u.user_id)
+        ) AS level2Count
+        FROM tz_user u
         LEFT JOIN tz_user ur ON u.user_recom=ur.user_id
         where 1=1
 

--
Gitblit v1.9.3