Files
youlai-boot/src/main/java/com/youlai/system/service/impl/SysMenuServiceImpl.java
2022-10-24 07:50:54 +08:00

257 lines
8.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.youlai.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.system.common.constant.SystemConstants;
import com.youlai.system.common.enums.MenuTypeEnum;
import com.youlai.system.common.enums.StatusEnum;
import com.youlai.system.common.model.Option;
import com.youlai.system.converter.MenuConverter;
import com.youlai.system.mapper.SysMenuMapper;
import com.youlai.system.pojo.entity.SysMenu;
import com.youlai.system.pojo.po.RoutePO;
import com.youlai.system.pojo.vo.menu.MenuVO;
import com.youlai.system.pojo.vo.menu.ResourceVO;
import com.youlai.system.pojo.vo.menu.RouteVO;
import com.youlai.system.service.SysMenuService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 菜单业务实现类
*
* @author haoxr
* @date 2020/11/06
*/
@Service
@RequiredArgsConstructor
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
private final MenuConverter menuConverter;
/**
* 菜单表格树形列表
*/
@Override
public List<MenuVO> listMenus(String name) {
List<SysMenu> menus = this.list(new LambdaQueryWrapper<SysMenu>()
.like(StrUtil.isNotBlank(name), SysMenu::getName, name)
.orderByAsc(SysMenu::getSort)
);
Set<Long> cacheMenuIds = menus.stream().map(menu -> menu.getId()).collect(Collectors.toSet());
List<MenuVO> tableMenus = menus.stream().map(menu -> {
Long parentId = menu.getParentId();
// parentId不在当前菜单ID的列表说明为顶级菜单ID根据此ID作为递归的开始条件节点
if (!cacheMenuIds.contains(parentId)) {
cacheMenuIds.add(parentId);
return recurTableMenus(parentId, menus);
}
return new LinkedList<MenuVO>();
}).collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
return tableMenus;
}
/**
* 保存菜单
*/
@Override
public boolean saveMenu(SysMenu menu) {
String path = menu.getPath();
MenuTypeEnum menuType = menu.getType(); // 菜单类型
switch (menuType) {
case CATALOG: // 目录
Assert.isTrue(path.startsWith("/"), "目录路由路径格式错误,必须以/开始");
menu.setComponent("Layout");
break;
case EXTLINK: // 外链
menu.setComponent(null);
break;
}
boolean result = this.saveOrUpdate(menu);
return result;
}
/**
* 菜单下拉数据
*/
@Override
public List<Option> listMenuOptions() {
List<SysMenu> menuList = this.list(new LambdaQueryWrapper<SysMenu>().orderByAsc(SysMenu::getSort));
List<Option> menus = recurMenus(SystemConstants.ROOT_NODE_ID, menuList);
return menus;
}
/**
* 路由列表
*/
@Override
@Cacheable(cacheNames = "system", key = "'routes'")
public List<RouteVO> listRoutes() {
List<RoutePO> menuList = this.baseMapper.listRoutes();
List<RouteVO> routeList = recurRoutes(SystemConstants.ROOT_NODE_ID, menuList);
return routeList;
}
/**
* 递归生成菜单路由层级列表
*
* @param parentId 父级ID
* @param menuList 菜单列表
* @return
*/
private List<RouteVO> recurRoutes(Long parentId, List<RoutePO> menuList) {
List<RouteVO> list = new ArrayList<>();
Optional.ofNullable(menuList).ifPresent(menus -> menus.stream()
.filter(menu -> menu.getParentId().equals(parentId))
.forEach(menu -> {
RouteVO routeVO = new RouteVO();
MenuTypeEnum menuTypeEnum = menu.getType();
if (MenuTypeEnum.MENU.equals(menuTypeEnum)) {
routeVO.setName(menu.getPath()); // 根据name路由跳转 this.$router.push({name:xxx})
}
routeVO.setPath(menu.getPath()); // 根据path路由跳转 this.$router.push({path:xxx})
routeVO.setRedirect(menu.getRedirectUrl());
routeVO.setComponent(menu.getComponent());
RouteVO.Meta meta = new RouteVO.Meta();
meta.setTitle(menu.getName());
meta.setIcon(menu.getIcon());
meta.setRoles(menu.getRoles());
meta.setHidden(StatusEnum.DISABLE.getValue().equals(menu.getVisible()));
meta.setKeepAlive(true);
routeVO.setMeta(meta);
List<RouteVO> children = recurRoutes(menu.getId(), menuList);
// 含有子节点的目录设置为可见
boolean alwaysShow = CollectionUtil.isNotEmpty(children) && children.stream().anyMatch(item -> item.getMeta().getHidden().equals(false));
meta.setAlwaysShow(alwaysShow);
routeVO.setChildren(children);
list.add(routeVO);
}));
return list;
}
/**
* 获取菜单资源树形列表
*
* @return
*/
@Override
public List<ResourceVO> listResources() {
List<SysMenu> menuList = this.list(new LambdaQueryWrapper<SysMenu>()
.orderByAsc(SysMenu::getSort));
List<ResourceVO> resources = recurResources(SystemConstants.ROOT_NODE_ID, menuList);
return resources;
}
/**
* 修改菜单显示状态
*
* @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;
}
@Override
public Set<String> listRolePerms(Set<String> roles) {
Set<String> perms= this.baseMapper.listRolePerms(roles);
return perms;
}
/**
* 递归生成菜单表格层级列表
*
* @param parentId 父级ID
* @param menuList 菜单列表
* @return
*/
private List<MenuVO> recurTableMenus(Long parentId, List<SysMenu> menuList) {
List<MenuVO> tableMenus = Optional.ofNullable(menuList).orElse(new ArrayList<>())
.stream()
.filter(menu -> menu.getParentId().equals(parentId))
.map(entity -> {
MenuVO menuVO = menuConverter.entity2VO(entity);
List<MenuVO> children = recurTableMenus(entity.getId(), menuList);
menuVO.setChildren(children);
return menuVO;
}).collect(Collectors.toList());
return tableMenus;
}
/**
* 递归生成菜单下拉层级列表
*
* @param parentId 父级ID
* @param menuList 菜单列表
* @return
*/
private static List<Option> recurMenus(Long parentId, List<SysMenu> menuList) {
List<Option> menus = Optional.ofNullable(menuList).orElse(new ArrayList<>()).stream()
.filter(menu -> menu.getParentId().equals(parentId))
.map(menu -> new Option(menu.getId(), menu.getName(), recurMenus(menu.getId(), menuList)))
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
return menus;
}
/**
* 递归生成资源(菜单+权限)树形列表
*
* @param parentId 父级ID
* @param menuList 菜单列表
* @return
*/
private static List<ResourceVO> recurResources(Long parentId, List<SysMenu> menuList) {
List<ResourceVO> menus = Optional.ofNullable(menuList).orElse(new ArrayList<>()).stream()
.filter(menu -> menu.getParentId().equals(parentId))
.map(menu -> {
ResourceVO resourceVO = new ResourceVO();
resourceVO.setValue(menu.getId());
resourceVO.setLabel(menu.getName());
List<ResourceVO> children = recurResources(menu.getId(), menuList);
resourceVO.setChildren(children);
return resourceVO;
}).collect(Collectors.toList());
return menus;
}
/**
* 清理路由缓存
*/
@Override
@CacheEvict(cacheNames = "system", key = "'routes'")
public void cleanCache() {
}
}