diff --git a/src/main/java/com/yunhai/userbase/repository/SysUserRepository.java b/src/main/java/com/yunhai/userbase/repository/SysUserRepository.java index 5fd440b..015d584 100644 --- a/src/main/java/com/yunhai/userbase/repository/SysUserRepository.java +++ b/src/main/java/com/yunhai/userbase/repository/SysUserRepository.java @@ -61,4 +61,26 @@ public interface SysUserRepository extends JpaRepository, JpaS @Param("name") String name, @Param("disabled") Integer disabled, Pageable pageable); + + /** + * 组上下文导出专用(原生 SQL,非分页):INNER JOIN 关联表后按 user_id 聚合, + * 仅返回「属于指定组范围」的用户(无组归属的用户天然被排除);超管(type=1)豁免 + * (type 为 NULL 视为非超管,一并保留)。入参 name 为可空:为空时跳过关键字过滤。 + * 排序按 user_id 升序,保证导出结果稳定。 + */ + @Query(value = + "SELECT u.id " + + "FROM sys_user u " + + "INNER JOIN sys_user_group_rel r ON r.user_id = u.id " + + "WHERE r.group_id IN (:groupIds) " + + " AND (:name IS NULL OR u.username LIKE CONCAT('%', :name, '%') " + + " OR u.real_name LIKE CONCAT('%', :name, '%') " + + " OR u.idcard LIKE CONCAT('%', :name, '%') " + + " OR u.phone = :name) " + + " AND (u.type IS NULL OR u.type != 1) " + + "GROUP BY u.id " + + "ORDER BY u.id ASC", + nativeQuery = true) + List findGroupUserIds(@Param("groupIds") List groupIds, + @Param("name") String name); } diff --git a/src/main/java/com/yunhai/userbase/service/impl/SysUserService.java b/src/main/java/com/yunhai/userbase/service/impl/SysUserService.java index 81667ea..a3ef3f5 100644 --- a/src/main/java/com/yunhai/userbase/service/impl/SysUserService.java +++ b/src/main/java/com/yunhai/userbase/service/impl/SysUserService.java @@ -500,15 +500,18 @@ public class SysUserService implements ISysUserService { */ @Override public void exportUsers(Integer groupId, Integer withSub, String name, HttpServletResponse response) throws IOException { - // 1. 解析组范围(含子孙)并查询范围内全部用户(不分页) - SysUserQuery query = new SysUserQuery(); - query.setGroupId(groupId); - query.setWithSub(withSub); - query.setName(name); - List users = sysUserRepository.findAll(buildSpecification(query)); + // 1. 解析组范围(含子孙),复用与列表一致的 INNER JOIN 原生 SQL 取范围内用户(含超管豁免),不分页。 + // 无组归属的用户被 INNER JOIN 天然排除;type=1 超管在 SQL 中显式豁免,永不导出。 + List groupIds = resolveGroupIds(groupId, withSub); + String nameKey = StringUtils.isNotBlank(name) ? name.trim() : null; + List userIds = sysUserRepository.findGroupUserIds(groupIds, nameKey); + List users = userIds.isEmpty() + ? Collections.emptyList() + : sysUserRepository.findAllById(userIds).stream() + .sorted(Comparator.comparing(SysUser::getId)) + .collect(Collectors.toList()); // 2. 批量取每个用户的主组(isMain=1),用于填充「组名 / 组id」参考列 - List userIds = users.stream().map(SysUser::getId).collect(Collectors.toList()); Map userMainGroup = resolveUserMainGroup(userIds); // 3. 批量取组名