SysMenuServiceImpl.java 9.0 KB
Newer Older
H
haoxr 已提交
1
package com.youlai.system.service.impl;
H
hxrui 已提交
2

3
import cn.hutool.core.collection.CollectionUtil;
4
import cn.hutool.core.lang.Assert;
5
import cn.hutool.core.util.StrUtil;
H
hxrui 已提交
6
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
7
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
H
hxrui 已提交
8
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
9
import com.youlai.common.constant.SystemConstants;
10 11
import com.youlai.system.enums.MenuTypeEnum;
import com.youlai.common.enums.StatusEnum;
H
horizons 已提交
12
import com.youlai.common.web.model.Option;
13 14 15 16 17
import com.youlai.system.converter.MenuConverter;
import com.youlai.system.mapper.SysMenuMapper;
import com.youlai.system.pojo.bo.RouteBO;
import com.youlai.system.pojo.entity.SysMenu;
import com.youlai.system.pojo.query.MenuQuery;
H
haoxr 已提交
18
import com.youlai.system.service.SysMenuService;
19 20 21
import com.youlai.system.pojo.vo.menu.MenuVO;
import com.youlai.system.pojo.vo.menu.ResourceVO;
import com.youlai.system.pojo.vo.menu.RouteVO;
22
import lombok.RequiredArgsConstructor;
23
import org.springframework.cache.annotation.CacheEvict;
24
import org.springframework.cache.annotation.Cacheable;
H
hxrui 已提交
25 26
import org.springframework.stereotype.Service;

27 28
import java.util.*;
import java.util.stream.Collectors;
H
hxrui 已提交
29 30 31


/**
郝先瑞 已提交
32
 * 菜单业务实现类
33
 *
郝先瑞 已提交
34 35
 * @author haoxr
 * @date 2020/11/06
H
hxrui 已提交
36 37
 */
@Service
38
@RequiredArgsConstructor
郝先瑞 已提交
39
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
40
    private final MenuConverter menuConverter;
41

42
    /**
郝先瑞 已提交
43
     * 菜单表格树形列表
44
     */
H
hxrui 已提交
45
    @Override
46
    public List<MenuVO> listMenus(MenuQuery queryParams) {
郝先瑞 已提交
47
        List<SysMenu> menus = this.list(new LambdaQueryWrapper<SysMenu>()
48
                .like(StrUtil.isNotBlank(queryParams.getKeywords()), SysMenu::getName, queryParams.getKeywords())
郝先瑞 已提交
49
                .orderByAsc(SysMenu::getSort)
50
        );
H
hxrui 已提交
51

郝先瑞 已提交
52
        Set<Long> cacheMenuIds = menus.stream().map(menu -> menu.getId()).collect(Collectors.toSet());
H
hxrui 已提交
53

54
        List<MenuVO> list = menus.stream().map(menu -> {
郝先瑞 已提交
55 56 57 58
            Long parentId = menu.getParentId();
            // parentId不在当前菜单ID的列表,说明为顶级菜单ID,根据此ID作为递归的开始条件节点
            if (!cacheMenuIds.contains(parentId)) {
                cacheMenuIds.add(parentId);
59
                return recurMenus(parentId, menus);
郝先瑞 已提交
60
            }
61
            return new LinkedList<MenuVO>();
郝先瑞 已提交
62
        }).collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
63
        return list;
64 65
    }

H
hxrui 已提交
66
    /**
67
     * 保存菜单
68 69 70
     */
    @Override
    public boolean saveMenu(SysMenu menu) {
71 72
        String path = menu.getPath();

73 74 75 76 77 78 79 80 81
        MenuTypeEnum menuType = menu.getType();  // 菜单类型
        switch (menuType) {
            case CATALOG: // 目录
                Assert.isTrue(path.startsWith("/"), "目录路由路径格式错误,必须以/开始");
                menu.setComponent("Layout");
                break;
            case EXTLINK: // 外链
                menu.setComponent(null);
                break;
82 83
        }

郝先瑞 已提交
84
        boolean result = this.saveOrUpdate(menu);
85 86 87
        return result;
    }

88 89 90 91
    /**
     * 菜单下拉数据
     */
    @Override
92
    public List<Option> listMenuOptions() {
93
        List<SysMenu> menuList = this.list(new LambdaQueryWrapper<SysMenu>().orderByAsc(SysMenu::getSort));
94
        List<Option> menus = recurMenuOptions(SystemConstants.ROOT_NODE_ID, menuList);
95 96
        return menus;
    }
97

有来技术 已提交
98
    /**
99
     * 路由列表
有来技术 已提交
100 101
     */
    @Override
102
    @Cacheable(cacheNames = "system", key = "'routes'")
103
    public List<RouteVO> listRoutes() {
104 105 106
        List<RouteBO> menuList = this.baseMapper.listRoutes();
        List<RouteVO> routeList = recurRoutes(SystemConstants.ROOT_NODE_ID, menuList);
        return routeList;
有来技术 已提交
107 108 109 110 111 112 113 114 115
    }

    /**
     * 递归生成菜单路由层级列表
     *
     * @param parentId 父级ID
     * @param menuList 菜单列表
     * @return
     */
116
    private List<RouteVO> recurRoutes(Long parentId, List<RouteBO> menuList) {
郝先瑞 已提交
117
        List<RouteVO> list = new ArrayList<>();
118 119
        Optional.ofNullable(menuList).ifPresent(menus -> menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
有来技术 已提交
120
                .forEach(menu -> {
郝先瑞 已提交
121
                    RouteVO routeVO = new RouteVO();
122 123 124 125

                    MenuTypeEnum menuTypeEnum = menu.getType();

                    if (MenuTypeEnum.MENU.equals(menuTypeEnum)) {
126
                        routeVO.setName(menu.getPath()); //  根据name路由跳转 this.$router.push({name:xxx})
127
                    }
128
                    routeVO.setPath(menu.getPath()); // 根据path路由跳转 this.$router.push({path:xxx})
H
haoxr 已提交
129
                    routeVO.setRedirect(menu.getRedirect());
郝先瑞 已提交
130
                    routeVO.setComponent(menu.getComponent());
有来技术 已提交
131

郝先瑞 已提交
132
                    RouteVO.Meta meta = new RouteVO.Meta();
有来技术 已提交
133 134 135
                    meta.setTitle(menu.getName());
                    meta.setIcon(menu.getIcon());
                    meta.setRoles(menu.getRoles());
136
                    meta.setHidden(StatusEnum.DISABLE.getValue().equals(menu.getVisible()));
137
                    meta.setKeepAlive(true);
138

郝先瑞 已提交
139
                    routeVO.setMeta(meta);
140
                    List<RouteVO> children = recurRoutes(menu.getId(), menuList);
141 142 143
                    // 含有子节点的目录设置为可见
                    boolean alwaysShow = CollectionUtil.isNotEmpty(children) && children.stream().anyMatch(item -> item.getMeta().getHidden().equals(false));
                    meta.setAlwaysShow(alwaysShow);
郝先瑞 已提交
144
                    routeVO.setChildren(children);
145

郝先瑞 已提交
146
                    list.add(routeVO);
有来技术 已提交
147 148 149
                }));
        return list;
    }
郝先瑞 已提交
150 151 152


    /**
郝先瑞 已提交
153
     * 获取菜单资源树形列表
郝先瑞 已提交
154 155 156 157
     *
     * @return
     */
    @Override
158 159 160
    public List<ResourceVO> listResources() {
        List<SysMenu> menuList = this.list(new LambdaQueryWrapper<SysMenu>()
                .orderByAsc(SysMenu::getSort));
161
        List<ResourceVO> resources = recurResources(SystemConstants.ROOT_NODE_ID, menuList);
162
        return resources;
郝先瑞 已提交
163 164
    }

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    /**
     * 修改菜单显示状态
     *
     * @param menuId  菜单ID
     * @param visible 是否显示(1->显示;2->隐藏)
     * @return
     */
    @Override
    public boolean updateMenuVisible(Long menuId, Integer visible) {
        boolean result = this.update(new LambdaUpdateWrapper<SysMenu>()
                .eq(SysMenu::getId, menuId)
                .set(SysMenu::getVisible, visible)
        );
        return result;
    }

181 182 183 184 185 186
    @Override
    public Set<String> listRolePerms(Set<String> roles) {
        Set<String> perms = this.baseMapper.listRolePerms(roles);
        return perms;
    }

郝先瑞 已提交
187
    /**
188
     * 递归生成菜单列表
郝先瑞 已提交
189 190 191 192 193
     *
     * @param parentId 父级ID
     * @param menuList 菜单列表
     * @return
     */
194 195 196 197 198 199
    private List<MenuVO> recurMenus(Long parentId, List<SysMenu> menuList) {
        if (CollectionUtil.isEmpty(menuList)) {
            return Collections.EMPTY_LIST;
        }

        List<MenuVO> menus = menuList.stream()
郝先瑞 已提交
200
                .filter(menu -> menu.getParentId().equals(parentId))
201 202
                .map(entity -> {
                    MenuVO menuVO = menuConverter.entity2VO(entity);
203
                    List<MenuVO> children = recurMenus(entity.getId(), menuList);
204 205
                    menuVO.setChildren(children);
                    return menuVO;
郝先瑞 已提交
206
                }).collect(Collectors.toList());
207
        return menus;
郝先瑞 已提交
208 209 210 211 212 213 214 215 216
    }

    /**
     * 递归生成菜单下拉层级列表
     *
     * @param parentId 父级ID
     * @param menuList 菜单列表
     * @return
     */
217 218 219 220 221 222
    private static List<Option> recurMenuOptions(Long parentId, List<SysMenu> menuList) {
        if (CollectionUtil.isEmpty(menuList)) {
            return Collections.EMPTY_LIST;
        }

        List<Option> menus = menuList.stream()
郝先瑞 已提交
223
                .filter(menu -> menu.getParentId().equals(parentId))
224
                .map(menu -> new Option(menu.getId(), menu.getName(), recurMenuOptions(menu.getId(), menuList)))
郝先瑞 已提交
225 226 227 228
                .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
        return menus;
    }

229
    /**
230
     * 递归生成资源(菜单+权限)树形列表
231 232 233 234 235
     *
     * @param parentId 父级ID
     * @param menuList 菜单列表
     * @return
     */
236 237 238 239 240 241
    private static List<ResourceVO> recurResources(Long parentId, List<SysMenu> menuList) {
        if (CollectionUtil.isEmpty(menuList)) {
            return Collections.EMPTY_LIST;
        }

        List<ResourceVO> menus = menuList.stream()
242 243
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> {
244 245 246
                    ResourceVO resourceVO = new ResourceVO();
                    resourceVO.setValue(menu.getId());
                    resourceVO.setLabel(menu.getName());
247

248
                    List<ResourceVO> children = recurResources(menu.getId(), menuList);
249
                    resourceVO.setChildren(children);
郝先瑞 已提交
250

251
                    return resourceVO;
252 253 254 255
                }).collect(Collectors.toList());
        return menus;
    }

郝先瑞 已提交
256 257 258 259 260 261 262 263 264

    /**
     * 清理路由缓存
     */
    @Override
    @CacheEvict(cacheNames = "system", key = "'routes'")
    public void cleanCache() {
    }

H
hxrui 已提交
265
}