Files
youlai-boot/src/main/java/com/youlai/system/service/impl/SysMenuServiceImpl.java
2023-03-07 23:55:41 +08:00

250 lines
8.2 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.pojo.entity.SysDept;
import com.youlai.system.pojo.form.MenuForm;
import com.youlai.system.pojo.vo.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.bo.RouteBO;
import com.youlai.system.pojo.query.MenuQuery;
import com.youlai.system.pojo.vo.MenuVO;
import com.youlai.system.pojo.vo.RouteVO;
import com.youlai.system.service.SysMenuService;
import lombok.RequiredArgsConstructor;
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(MenuQuery queryParams) {
List<SysMenu> menus = this.list(new LambdaQueryWrapper<SysMenu>()
.like(StrUtil.isNotBlank(queryParams.getKeywords()), SysMenu::getName, queryParams.getKeywords())
.orderByAsc(SysMenu::getSort)
);
Set<Long> cacheMenuIds = menus.stream()
.map(menu -> menu.getId())
.collect(Collectors.toSet());
List<MenuVO> list = menus.stream().map(menu -> {
Long parentId = menu.getParentId();
// parentId不在当前菜单ID的列表说明为顶级菜单ID根据此ID作为递归的开始节点
if (!cacheMenuIds.contains(parentId)) {
cacheMenuIds.add(parentId);
return recurMenus(parentId, menus);
}
return new LinkedList<MenuVO>();
}).collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
return list;
}
/**
* 保存菜单
*/
@Override
public boolean saveMenu(MenuForm menuForm) {
String path = menuForm.getPath();
MenuTypeEnum menuType = menuForm.getType(); // 菜单类型
switch (menuType) {
case CATALOG: // 目录
Assert.isTrue(path.startsWith("/"), "目录路由路径格式错误,必须以/开始");
menuForm.setComponent("Layout");
break;
case EXTLINK: // 外链
menuForm.setComponent(null);
break;
}
SysMenu entity = menuConverter.form2Entity(menuForm);
boolean result = this.saveOrUpdate(entity);
return result;
}
/**
* 菜单下拉数据
*/
@Override
public List<Option> listMenuOptions() {
List<SysMenu> menuList = this.list(new LambdaQueryWrapper<SysMenu>().orderByAsc(SysMenu::getSort));
List<Option> menus = recurMenuOptions(SystemConstants.ROOT_NODE_ID, menuList);
return menus;
}
/**
* 路由列表
*/
@Override
@Cacheable(cacheNames = "system", key = "'routes'")
public List<RouteVO> listRoutes() {
List<RouteBO> 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<RouteBO> 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);
routeVO.setChildren(children);
list.add(routeVO);
}));
return list;
}
/**
* 修改菜单显示状态
*
* @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;
}
/**
* 获取角色权限集合
*
* @param roles
* @return
*/
@Override
public Set<String> listRolePerms(Set<String> roles) {
Set<String> perms = this.baseMapper.listRolePerms(roles);
return perms;
}
/**
* 获取菜单表单数据
*
* @param id 菜单ID
* @return
*/
@Override
public MenuForm getMenuForm(Long id) {
SysMenu entity = this.getById(id);
MenuForm menuForm = menuConverter.entity2Form(entity);
return menuForm;
}
/**
* 删除菜单
*
* @param id 菜单ID
* @return
*/
@Override
public boolean deleteMenu(Long id) {
if (id != null) {
this.remove(new LambdaQueryWrapper<SysMenu>()
.eq(SysMenu::getId, id)
.or()
.apply("CONCAT (',',tree_path,',') LIKE CONCAT('%,',{0},',%')", id));
}
return true;
}
/**
* 递归生成菜单列表
*
* @param parentId 父级ID
* @param menuList 菜单列表
* @return
*/
private List<MenuVO> recurMenus(Long parentId, List<SysMenu> menuList) {
if (CollectionUtil.isEmpty(menuList)) {
return Collections.EMPTY_LIST;
}
List<MenuVO> menus = menuList.stream()
.filter(menu -> menu.getParentId().equals(parentId))
.map(entity -> {
MenuVO menuVO = menuConverter.entity2Vo(entity);
List<MenuVO> children = recurMenus(entity.getId(), menuList);
menuVO.setChildren(children);
return menuVO;
}).collect(Collectors.toList());
return menus;
}
/**
* 递归生成菜单下拉层级列表
*
* @param parentId 父级ID
* @param menuList 菜单列表
* @return
*/
private static List<Option> recurMenuOptions(Long parentId, List<SysMenu> menuList) {
if (CollectionUtil.isEmpty(menuList)) {
return Collections.EMPTY_LIST;
}
List<Option> menus = menuList.stream()
.filter(menu -> menu.getParentId().equals(parentId))
.map(menu -> new Option(menu.getId(), menu.getName(), recurMenuOptions(menu.getId(), menuList)))
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
return menus;
}
}