“mitao”
2026-02-14 904447d37a7ea9e3fadf1b56badc0ddbcf210bd0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package com.xiaopeng.operation.service.impl;
 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.SysMenu;
import com.xiaopeng.operation.mapper.SysMenuMapper;
import com.xiaopeng.operation.service.ISysMenuService;
import org.springframework.stereotype.Service;
 
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author mitao
 * @since 2026-02-03
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {
 
    /**
     * 根据菜单ID列表查询菜单列表
     *
     * @param menuIds 菜单ID列表
     * @return 菜单列表
     */
    @Override
    public List<SysMenu> selectMenusByMenuIds(List<Long> menuIds) {
        if (menuIds == null || menuIds.isEmpty()) {
            return new ArrayList<>();
        }
 
        // 使用 MyBatis-Plus 的 listByIds 方法批量查询
        return this.listByIds(menuIds);
    }
 
    @Override
    public List<SysMenu> getMenuTree() {
        List<SysMenu> all = list();
        if (all == null || all.isEmpty()) {
            return Collections.emptyList();
        }
 
        // 1) 按 parentId 分组(M/C/F 都先放进去,后面再按类型筛)
        Map<Long, List<SysMenu>> childrenMap = all.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(m -> m.getParentId() == null ? 0L : m.getParentId()));
 
        // 2) 找到根目录:通常 parentId = 0 或 null 的目录(M)
        List<SysMenu> 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<Long, List<SysMenu>> childrenMap) {
        Long id = node.getId();
        if (id == null) {
            node.setChildren(Collections.emptyList());
            return;
        }
 
        List<SysMenu> 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<SysMenu> 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<SysMenu> getPermission() {
        return Collections.emptyList();
    }
}