package com.xiaopeng.operation.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.feignClient.account.SysGroupMenuClient;
import com.xiaopeng.api.feignClient.account.SysRoleClient;
import com.xiaopeng.api.feignClient.account.SysUserRoleClient;
import com.xiaopeng.api.model.account.SysRole;
import com.xiaopeng.api.model.account.SysUserRole;
import com.xiaopeng.api.model.operation.SysMenu;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.security.service.TokenService;
import com.xiaopeng.operation.mapper.SysMenuMapper;
import com.xiaopeng.operation.service.ISysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* 菜单权限表 服务实现类
*
*
* @author mitao
* @since 2026-02-03
*/
@Slf4j
@Service
public class SysMenuServiceImpl extends ServiceImpl implements ISysMenuService {
@Autowired
private TokenService tokenService;
@Autowired
private SysUserRoleClient sysUserRoleClient;
@Autowired
private SysRoleClient sysRoleClient;
@Autowired
private SysGroupMenuClient sysGroupMenuClient;
/**
* 根据菜单ID列表查询菜单列表
*
* @param menuIds 菜单ID列表
* @return 菜单列表
*/
@Override
public List selectMenusByMenuIds(List menuIds) {
if (menuIds == null || menuIds.isEmpty()) {
return new ArrayList<>();
}
// 使用 MyBatis-Plus 的 listByIds 方法批量查询
return this.listByIds(menuIds);
}
@Override
public List getMenuTree() {
List all = list();
if (all == null || all.isEmpty()) {
return Collections.emptyList();
}
// 1) 按 parentId 分组(M/C/F 都先放进去,后面再按类型筛)
Map> childrenMap = all.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(m -> m.getParentId() == null ? 0L : m.getParentId()));
// 2) 找到根目录:通常 parentId = 0 或 null 的目录(M)
List roots = childrenMap.getOrDefault(0L, Collections.emptyList()).stream()
.filter(m -> "M".equals(m.getMenuType()))
.sorted(Comparator.comparing(SysMenu::getOrderNum, Comparator.nullsLast(Integer::compareTo)))
.collect(Collectors.toList());
// 3) 递归挂载:M 下挂 C;C 下挂 F(也允许 C 下还有 C,或 M 下还有 M,按你的数据结构来)
for (SysMenu root : roots) {
fillChildren(root, childrenMap);
}
return roots;
}
private void fillChildren(SysMenu node, Map> childrenMap) {
Long id = node.getId();
if (id == null) {
node.setChildren(Collections.emptyList());
return;
}
List rawChildren = childrenMap.getOrDefault(id, Collections.emptyList());
if (rawChildren.isEmpty()) {
node.setChildren(Collections.emptyList());
return;
}
// 根据你的层级规则过滤子节点:
// - M 只能挂 M/C(看你业务,很多系统 M 下是 C)
// - C 只能挂 F(按钮)或(有些系统 C 下还能挂 C)
// - F 一般不挂任何子节点
String type = node.getMenuType();
List children = rawChildren.stream()
.filter(Objects::nonNull)
.filter(child -> {
if ("M".equals(type)) {
return "M".equals(child.getMenuType()) || "C".equals(child.getMenuType());
}
if ("C".equals(type)) {
return "F".equals(child.getMenuType()); // 若允许 C 下还有 C,可改为:return "C".equals(...) || "F".equals(...)
}
return false; // F 不再往下挂
})
.sorted(Comparator.comparing(SysMenu::getOrderNum, Comparator.nullsLast(Integer::compareTo)))
.collect(Collectors.toList());
node.setChildren(children);
// 继续递归
for (SysMenu child : children) {
fillChildren(child, childrenMap);
}
}
@Override
public List getPermission() {
try {
// 1. 获取当前登录用户ID
Long userId = tokenService.getLoginUser().getUserid();
if (userId == null) {
log.warn("获取当前登录用户ID失败");
return Collections.emptyList();
}
// 2. 查询用户角色关联
R userRoleResult = sysUserRoleClient.selectSysUserRoleByUserId(userId);
if (userRoleResult == null || userRoleResult.getCode() != 200 || userRoleResult.getData() == null) {
log.warn("查询用户角色关联失败, userId={}", userId);
return Collections.emptyList();
}
Long roleId = userRoleResult.getData().getRoleId();
if (roleId == null) {
log.warn("用户未关联角色, userId={}", userId);
return Collections.emptyList();
}
// 3. 查询角色信息
R roleResult = sysRoleClient.getRoleById(roleId);
if (roleResult == null || roleResult.getCode() != 200 || roleResult.getData() == null) {
log.warn("查询角色信息失败, roleId={}", roleId);
return Collections.emptyList();
}
Long groupId = roleResult.getData().getGroupId();
if (groupId == null) {
log.warn("角色未关联权限组, roleId={}", roleId);
return Collections.emptyList();
}
// 4. 查询权限组关联的菜单ID列表
R> menuIdsResult = sysGroupMenuClient.selectMenuIdsByGroupId(groupId);
if (menuIdsResult == null || menuIdsResult.getCode() != 200 || menuIdsResult.getData() == null) {
log.warn("查询权限组菜单ID列表失败, groupId={}", groupId);
return Collections.emptyList();
}
List menuIds = menuIdsResult.getData();
if (menuIds.isEmpty()) {
log.info("权限组未关联菜单, groupId={}", groupId);
return Collections.emptyList();
}
// 5. 查询菜单详情
List menus = this.listByIds(menuIds);
log.info("查询用户权限菜单成功, userId={}, menuCount={}", userId, menus.size());
return menus;
} catch (Exception e) {
log.error("查询用户权限菜单异常", e);
return Collections.emptyList();
}
}
}