有系统开发需求可私信我提供帮助哦 ~
部分
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
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.tool4j.boot.common.Constants;
import com.tool4j.boot.common.MenuTypeEnum;
import com.tool4j.boot.common.StatusEnum;
import com.tool4j.boot.entity.SysMenu;
import com.tool4j.boot.entity.SysUser;
import com.tool4j.boot.entity.params.MenuForm;
import com.tool4j.boot.entity.params.MenuQuery;
import com.tool4j.boot.entity.params.Option;
import com.tool4j.boot.entity.vo.MenuVO;
import com.tool4j.boot.entity.vo.RouteBO;
import com.tool4j.boot.entity.vo.RouteVO;
import com.tool4j.boot.mapper.SysMenuMapper;
import com.tool4j.boot.service.SysMenuService;
import com.tool4j.boot.service.SysUserService;
import com.tool4j.boot.util.UserPermission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;/*** 菜单业务实现类** @author haoxr* @since 2020/11/06*/
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {@Autowiredprivate SysMenuMapper sysMenuMapper;@Autowiredprivate SysUserService userService;/*** 菜单列表** @param queryParams {@link MenuQuery}*/@Overridepublic List<MenuVO> listMenus(MenuQuery queryParams) {List<SysMenu> menus = this.list(new LambdaQueryWrapper<SysMenu>().like(StrUtil.isNotBlank(queryParams.getKeywords()), SysMenu::getName, queryParams.getKeywords()).orderByAsc(SysMenu::getSort));// 获取所有菜单IDSet<Long> menuIds = menus.stream().map(SysMenu::getId).collect(Collectors.toSet());// 获取所有父级IDSet<Long> parentIds = menus.stream().map(SysMenu::getParentId).collect(Collectors.toSet());// 获取根节点ID(递归的起点),即父节点ID中不包含在部门ID中的节点,注意这里不能拿顶级菜单 O 作为根节点,因为菜单筛选的时候 O 会被过滤掉List<Long> rootIds = parentIds.stream().filter(id -> !menuIds.contains(id)).collect(Collectors.toList());// 使用递归函数来构建菜单树return rootIds.stream().flatMap(rootId -> buildMenuTree(rootId, menus).stream()).collect(Collectors.toList());}/*** 递归生成菜单列表** @param parentId 父级ID* @param menuList 菜单列表* @return 菜单列表*/private List<MenuVO> buildMenuTree(Long parentId, List<SysMenu> menuList) {return CollectionUtil.emptyIfNull(menuList).stream().filter(menu -> menu.getParentId().equals(parentId)).map(entity -> {MenuVO menuVO = BeanUtil.copyProperties(entity, MenuVO.class);List<MenuVO> children = buildMenuTree(entity.getId(), menuList);menuVO.setChildren(children);return menuVO;}).collect(Collectors.toList());}/*** 菜单下拉数据*/@Overridepublic List<Option> listMenuOptions() {List<SysMenu> menuList = this.list(new LambdaQueryWrapper<SysMenu>().orderByAsc(SysMenu::getSort));return buildMenuOptions(Constants.ROOT_NODE_ID, menuList);}/*** 递归生成菜单下拉层级列表** @param parentId 父级ID* @param menuList 菜单列表* @return 菜单下拉列表*/private List<Option> buildMenuOptions(Long parentId, List<SysMenu> menuList) {List<Option> menuOptions = new ArrayList<>();for (SysMenu menu : menuList) {if (menu.getParentId().equals(parentId)) {Option option = new Option(menu.getId(), menu.getName());List<Option> subMenuOptions = buildMenuOptions(menu.getId(), menuList);if (!subMenuOptions.isEmpty()) {option.setChildren(subMenuOptions);}menuOptions.add(option);}}return menuOptions;}/*** 获取路由列表*/@Overridepublic List<RouteVO> listRoutes() {SysUser user = userService.findByUserId(UserPermission.get());List<RouteBO> menuList = sysMenuMapper.listRoutes(user.getRoleId());return buildRoutes(Constants.ROOT_NODE_ID, menuList);}/*** 递归生成菜单路由层级列表** @param parentId 父级ID* @param menuList 菜单列表* @return 路由层级列表*/private List<RouteVO> buildRoutes(Long parentId, List<RouteBO> menuList) {List<RouteVO> routeList = new ArrayList<>();for (RouteBO menu : menuList) {if (menu.getParentId().equals(parentId)) {RouteVO routeVO = toRouteVo(menu);List<RouteVO> children = buildRoutes(menu.getId(), menuList);if (!children.isEmpty()) {routeVO.setChildren(children);}routeList.add(routeVO);}}return routeList;}/*** 根据RouteBO创建RouteVO*/private RouteVO toRouteVo(RouteBO routeBO) {RouteVO routeVO = new RouteVO();String routeName = StringUtils.capitalize(StrUtil.toCamelCase(routeBO.getPath(), '-')); // 路由 name 需要驼峰,首字母大写routeVO.setName(routeName); // 根据name路由跳转 this.$router.push({name:xxx})routeVO.setPath(routeBO.getPath()); // 根据path路由跳转 this.$router.push({path:xxx})routeVO.setRedirect(routeBO.getRedirect());routeVO.setComponent(routeBO.getComponent());RouteVO.Meta meta = new RouteVO.Meta();meta.setTitle(routeBO.getName());meta.setIcon(routeBO.getIcon());meta.setRoles(routeBO.getRoles());meta.setHidden(StatusEnum.DISABLE.getValue().equals(routeBO.getVisible()));// 【菜单】是否开启页面缓存if (MenuTypeEnum.MENU.getValue().equals(routeBO.getType())&& ObjectUtil.equals(routeBO.getKeepAlive(), 1)) {meta.setKeepAlive(true);}// 【目录】只有一个子路由是否始终显示if (MenuTypeEnum.CATALOG.getValue().equals(routeBO.getType())&& ObjectUtil.equals(routeBO.getAlwaysShow(), 1)) {meta.setAlwaysShow(true);}routeVO.setMeta(meta);return routeVO;}/*** 新增/修改菜单*/@Override@CacheEvict(cacheNames = "menu", key = "'routes'")public boolean saveMenu(MenuForm menuForm) {MenuTypeEnum menuType = menuForm.getType();if (menuType == MenuTypeEnum.CATALOG) { // 如果是外链String path = menuForm.getPath();if (menuForm.getParentId() == 0 && !path.startsWith("/")) {menuForm.setPath("/" + path); // 一级目录需以 / 开头}menuForm.setComponent("Layout");} else if (menuType == MenuTypeEnum.EXTLINK) { // 如果是目录menuForm.setComponent(null);}SysMenu entity = BeanUtil.copyProperties(menuForm, SysMenu.class);String treePath = generateMenuTreePath(menuForm.getParentId());entity.setTreePath(treePath);return this.saveOrUpdate(entity);}/*** 部门路径生成** @param parentId 父ID* @return 父节点路径以英文逗号(, )分割,eg: 1,2,3*/private String generateMenuTreePath(Long parentId) {if (Constants.ROOT_NODE_ID.equals(parentId)) {return String.valueOf(parentId);} else {SysMenu parent = this.getById(parentId);return parent != null ? parent.getTreePath() + "," + parent.getId() : null;}}/*** 修改菜单显示状态** @param menuId 菜单ID* @param visible 是否显示(1->显示;2->隐藏)* @return 是否修改成功*/@Override@CacheEvict(cacheNames = "menu", key = "'routes'")public boolean updateMenuVisible(Long menuId, Integer visible) {return this.update(new LambdaUpdateWrapper<SysMenu>().eq(SysMenu::getId, menuId).set(SysMenu::getVisible, visible));}/*** 获取角色权限(Code)集合** @param roles 角色Code集合* @return 权限集合*/@Overridepublic Set<String> listRolePerms(Set<String> roles) {return sysMenuMapper.listRolePerms(roles);}/*** 获取菜单表单数据** @param id 菜单ID* @return 菜单表单数据*/@Overridepublic MenuForm getMenuForm(Long id) {SysMenu entity = this.getById(id);return BeanUtil.copyProperties(entity, MenuForm.class);}/*** 删除菜单** @param id 菜单ID* @return 是否删除成功*/@Override@CacheEvict(cacheNames = "menu", key = "'routes'")public boolean deleteMenu(Long id) {return this.remove(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getId, id).or().apply("CONCAT (',',tree_path,',') LIKE CONCAT('%,',{0},',%')", id));}}