diff --git a/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupVo.java b/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupVo.java
index 2bf51f8..f23137d 100644
--- a/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupVo.java
+++ b/src/main/java/com/yunhai/userbase/model/sysgroup/SysGroupVo.java
@@ -20,6 +20,13 @@ public class SysGroupVo {
private Integer status;
/** 包含子组(2026-10-21):1=部门列表含下级部门 / 0=仅本级;BeanUtils 同名拷贝,null 视为 1 由前端兜底 */
private Integer includeChildren;
+ /** 直属成员数(部门表格「人员」列);口径同 oapi 部门目录:sys_user_group_rel 按 groupId 计数,不排除转出。 */
+ private Long memberCount;
+ /**
+ * 直属成员姓名预览,最多 {@code SysGroupService.MEMBER_PREVIEW_LIMIT} 个。
+ * 完整名单不走这里(部门可能上百人),前端点「查看全部」调 /api/sysuser/List?groupId=xxx。
+ */
+ private List memberNames = new ArrayList<>();
/** 子组(递归);默认空列表,避免 JSON 序列化出现 null。 */
private List children = new ArrayList<>();
}
diff --git a/src/main/java/com/yunhai/userbase/service/impl/SysGroupService.java b/src/main/java/com/yunhai/userbase/service/impl/SysGroupService.java
index 6c06808..0bac0c0 100644
--- a/src/main/java/com/yunhai/userbase/service/impl/SysGroupService.java
+++ b/src/main/java/com/yunhai/userbase/service/impl/SysGroupService.java
@@ -63,6 +63,13 @@ public class SysGroupService implements ISysGroupService {
/** 开放接口/oapi 写操作无登录态时使用的审计人哨兵值(非真实用户ID),用于兜底 create_user/update_user 的 NOT NULL 约束。 */
private static final int SYSTEM_USER_ID = 0;
+ /**
+ * 部门表格「人员」列的姓名预览上限。
+ * 表格最多显示 3 个名字 + 计数,tooltip 展示这份预览;部门上百人时不把这些名字塞进 getTree 响应,
+ * 完整名单由前端点「查看全部」走 /api/sysuser/List?groupId=xxx 分页取。
+ */
+ static final int MEMBER_PREVIEW_LIMIT = 50;
+
/**
* 层级类型约束:父类型 -> 允许直接创建的子类型集合。
* key 为 {@code null} 表示「根节点(教育云中心)」。
@@ -363,7 +370,9 @@ public class SysGroupService implements ISysGroupService {
Map> childrenMap = snapshot.getChildrenMap();
// 从根(pid=0)开始组装树
List roots = childrenMap.getOrDefault(ROOT_PARENT_ID, new ArrayList<>());
- return roots.stream().map(r -> buildNode(r, childrenMap)).collect(Collectors.toList());
+ List tree = roots.stream().map(r -> buildNode(r, childrenMap)).collect(Collectors.toList());
+ fillMemberStats(tree);
+ return tree;
}
@Override
@@ -375,7 +384,83 @@ public class SysGroupService implements ISysGroupService {
if (scope == null || scope.isSuper()) {
return getTree();
}
- return buildTrimmedTree(scope, snapshot.getAll(), false);
+ List tree = buildTrimmedTree(scope, snapshot.getAll(), false);
+ fillMemberStats(tree);
+ return tree;
+ }
+
+ /**
+ * 给树节点补直属成员数与前 N 个姓名预览(部门表格「人员」列)。
+ * 口径与 oapi 部门目录一致:sys_user_group_rel 按 groupId 计数,不排除转出;
+ * 整棵树只发两次查询(关联表 in + 用户表 in),不受节点数影响。
+ */
+ private void fillMemberStats(List tree) {
+ List groupIds = new ArrayList<>();
+ collectGroupIds(tree, groupIds);
+ if (groupIds.isEmpty()) {
+ return;
+ }
+ List rels = sysUserGroupRelRepository.findByGroupIdIn(groupIds);
+ if (rels == null || rels.isEmpty()) {
+ return;
+ }
+ Map> relByGroup = new HashMap<>();
+ Set userIds = new HashSet<>();
+ for (SysUserGroupRel rel : rels) {
+ if (rel.getGroupId() == null || rel.getUserId() == null) {
+ continue;
+ }
+ relByGroup.computeIfAbsent(rel.getGroupId(), k -> new ArrayList<>()).add(rel.getUserId());
+ userIds.add(rel.getUserId());
+ }
+ Map nameById = new HashMap<>();
+ for (SysUser user : sysUserRepository.findAllById(userIds)) {
+ nameById.put(user.getId(),
+ StringUtils.hasText(user.getRealName()) ? user.getRealName() : user.getAccount());
+ }
+ Map voById = new HashMap<>();
+ collectVoById(tree, voById);
+ for (Map.Entry> entry : relByGroup.entrySet()) {
+ SysGroupVo vo = voById.get(entry.getKey());
+ if (vo == null) {
+ continue;
+ }
+ List members = entry.getValue();
+ vo.setMemberCount((long) members.size());
+ List preview = new ArrayList<>();
+ for (Integer uid : members) {
+ if (preview.size() >= MEMBER_PREVIEW_LIMIT) {
+ break;
+ }
+ String name = nameById.get(uid);
+ if (name != null) {
+ preview.add(name);
+ }
+ }
+ vo.setMemberNames(preview);
+ }
+ }
+
+ private void collectGroupIds(List nodes, List out) {
+ for (SysGroupVo vo : nodes) {
+ if (vo.getId() != null) {
+ out.add(vo.getId());
+ }
+ if (vo.getChildren() != null) {
+ collectGroupIds(vo.getChildren(), out);
+ }
+ }
+ }
+
+ private void collectVoById(List nodes, Map out) {
+ for (SysGroupVo vo : nodes) {
+ if (vo.getId() != null) {
+ out.put(vo.getId(), vo);
+ }
+ if (vo.getChildren() != null) {
+ collectVoById(vo.getChildren(), out);
+ }
+ }
}
@Override