Commit cf93019ce123bcaeefd471c0052814bd795f554b

Authored by YunaiV
1 parent 162bebf5

增加 get-routers 接口的相关方法,未完全完成

ruoyi-ui/src/api/login.js
@@ -18,7 +18,7 @@ export function login(username, password, code, uuid) { @@ -18,7 +18,7 @@ export function login(username, password, code, uuid) {
18 // 获取用户详细信息 18 // 获取用户详细信息
19 export function getInfo() { 19 export function getInfo() {
20 return request({ 20 return request({
21 - url: '/getInfo', 21 + url: '/get-info',
22 method: 'get' 22 method: 'get'
23 }) 23 })
24 } 24 }
ruoyi-ui/src/api/menu.js
@@ -3,7 +3,7 @@ import request from '@/utils/request' @@ -3,7 +3,7 @@ import request from '@/utils/request'
3 // 获取路由 3 // 获取路由
4 export const getRouters = () => { 4 export const getRouters = () => {
5 return request({ 5 return request({
6 - url: '/getRouters', 6 + url: '/get-routers',
7 method: 'get' 7 method: 'get'
8 }) 8 })
9 -}  
10 \ No newline at end of file 9 \ No newline at end of file
  10 +}
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.http
@@ -13,6 +13,10 @@ Content-Type: application/json @@ -13,6 +13,10 @@ Content-Type: application/json
13 GET {{baseUrl}}/get-info 13 GET {{baseUrl}}/get-info
14 Authorization: Bearer {{token}} 14 Authorization: Bearer {{token}}
15 15
  16 +### 请求 /get-routers 接口 => 成功
  17 +GET {{baseUrl}}/get-routers
  18 +Authorization: Bearer {{token}}
  19 +
16 ### 请求 /druid/xxx 接口 => 失败 TODO 临时测试 20 ### 请求 /druid/xxx 接口 => 失败 TODO 临时测试
17 GET http://127.0.0.1:8080/druid/123 21 GET http://127.0.0.1:8080/druid/123
18 Authorization: Bearer {{token}} 22 Authorization: Bearer {{token}}
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java
@@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.auth; @@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.auth;
2 2
3 import cn.iocoder.dashboard.common.pojo.CommonResult; 3 import cn.iocoder.dashboard.common.pojo.CommonResult;
4 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO; 4 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO;
  5 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetRouterRespVO;
5 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginReqVO; 6 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginReqVO;
6 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginRespVO; 7 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginRespVO;
7 import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; 8 import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService;
@@ -12,6 +13,8 @@ import org.springframework.web.bind.annotation.*; @@ -12,6 +13,8 @@ import org.springframework.web.bind.annotation.*;
12 import javax.annotation.Resource; 13 import javax.annotation.Resource;
13 import javax.validation.Valid; 14 import javax.validation.Valid;
14 15
  16 +import java.util.List;
  17 +
15 import static cn.iocoder.dashboard.common.pojo.CommonResult.success; 18 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
16 import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserId; 19 import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserId;
17 import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserRoleIds; 20 import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserRoleIds;
@@ -39,4 +42,11 @@ public class SysAuthController { @@ -39,4 +42,11 @@ public class SysAuthController {
39 return success(respVO); 42 return success(respVO);
40 } 43 }
41 44
  45 + @ApiOperation("获得菜单 Vue 路由")
  46 + @GetMapping("get-routers")
  47 + public CommonResult<List<SysAuthGetRouterRespVO>> getRouters() {
  48 + List<SysAuthGetRouterRespVO> respVOList = authService.getRouters(getLoginUserId(), getLoginUserRoleIds());
  49 + return success(respVOList);
  50 + }
  51 +
42 } 52 }
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/SysAuthGetRouterRespVO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.auth.vo;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * 路由配置信息
  9 + *
  10 + * @author ruoyi
  11 + */
  12 +@Data
  13 +public class SysAuthGetRouterRespVO {
  14 +
  15 + /**
  16 + * 菜单编号
  17 + */
  18 + private Long menuId;
  19 + /**
  20 + * 父菜单编号
  21 + */
  22 + private Long parentId;
  23 +
  24 + /**
  25 + * 路由名字
  26 + */
  27 + private String name;
  28 +
  29 + /**
  30 + * 路由地址
  31 + */
  32 + private String path;
  33 +
  34 + /**
  35 + * 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现
  36 + */
  37 + private boolean hidden;
  38 +
  39 + /**
  40 + * 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
  41 + */
  42 + private String redirect;
  43 +
  44 + /**
  45 + * 组件地址
  46 + */
  47 + private String component;
  48 +
  49 + /**
  50 + * 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
  51 + */
  52 + private Boolean alwaysShow;
  53 +
  54 + /**
  55 + * 其他元素
  56 + */
  57 + private MetaVO meta;
  58 +
  59 + /**
  60 + * 子路由
  61 + */
  62 + private List<SysAuthGetRouterRespVO> children;
  63 +
  64 + @Data
  65 + public static class MetaVO {
  66 +
  67 + /**
  68 + * 设置该路由在侧边栏和面包屑中展示的名字
  69 + */
  70 + private String title;
  71 +
  72 + /**
  73 + * 设置该路由的图标,对应路径src/assets/icons/svg
  74 + */
  75 + private String icon;
  76 +
  77 + /**
  78 + * 设置为true,则不会被 <keep-alive>缓存
  79 + */
  80 + private boolean noCache;
  81 +
  82 + }
  83 +
  84 +}
src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java
@@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.convert.auth; @@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.convert.auth;
2 2
3 import cn.iocoder.dashboard.framework.security.core.LoginUser; 3 import cn.iocoder.dashboard.framework.security.core.LoginUser;
4 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO; 4 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO;
  5 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetRouterRespVO;
5 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO; 6 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
6 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO; 7 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
7 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; 8 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
@@ -27,4 +28,6 @@ public interface SysAuthConvert { @@ -27,4 +28,6 @@ public interface SysAuthConvert {
27 return respVO; 28 return respVO;
28 } 29 }
29 30
  31 + SysAuthGetRouterRespVO convertTreeNode(SysMenuDO menu);
  32 +
30 } 33 }
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysMenuDO.java
1 package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission; 1 package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
2 2
3 import cn.iocoder.dashboard.framework.mybatis.core.BaseDO; 3 import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
4 -import com.baomidou.mybatisplus.annotation.TableField;  
5 import com.baomidou.mybatisplus.annotation.TableId; 4 import com.baomidou.mybatisplus.annotation.TableId;
6 import com.baomidou.mybatisplus.annotation.TableName; 5 import com.baomidou.mybatisplus.annotation.TableName;
7 import lombok.Data; 6 import lombok.Data;
@@ -9,8 +8,6 @@ import lombok.EqualsAndHashCode; @@ -9,8 +8,6 @@ import lombok.EqualsAndHashCode;
9 8
10 import javax.validation.constraints.NotBlank; 9 import javax.validation.constraints.NotBlank;
11 import javax.validation.constraints.Size; 10 import javax.validation.constraints.Size;
12 -import java.util.ArrayList;  
13 -import java.util.List;  
14 11
15 /** 12 /**
16 * 菜单权限表 13 * 菜单权限表
@@ -95,18 +92,4 @@ public class SysMenuDO extends BaseDO { @@ -95,18 +92,4 @@ public class SysMenuDO extends BaseDO {
95 */ 92 */
96 private String icon; 93 private String icon;
97 94
98 - // TODO 芋艿:非存储字段,需要提出  
99 -  
100 - /**  
101 - * 父菜单名称  
102 - */  
103 - @TableField(exist = false)  
104 - private String parentName;  
105 -  
106 - /**  
107 - * 子菜单  
108 - */  
109 - @TableField(exist = false)  
110 - private List<SysMenuDO> children = new ArrayList<SysMenuDO>();  
111 -  
112 } 95 }
src/main/java/cn/iocoder/dashboard/modules/system/enums/permission/MenuIdEnum.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.enums.permission;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * Menu 编号枚举
  8 + */
  9 +@Getter
  10 +@AllArgsConstructor
  11 +public enum MenuIdEnum {
  12 +
  13 + /**
  14 + * 根节点
  15 + */
  16 + ROOT(0L);
  17 +
  18 + private final Long id;
  19 +
  20 +}
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthService.java
@@ -2,7 +2,9 @@ package cn.iocoder.dashboard.modules.system.service.auth; @@ -2,7 +2,9 @@ package cn.iocoder.dashboard.modules.system.service.auth;
2 2
3 import cn.iocoder.dashboard.framework.security.core.service.SecurityFrameworkService; 3 import cn.iocoder.dashboard.framework.security.core.service.SecurityFrameworkService;
4 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO; 4 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO;
  5 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetRouterRespVO;
5 6
  7 +import java.util.List;
6 import java.util.Set; 8 import java.util.Set;
7 9
8 /** 10 /**
@@ -28,4 +30,16 @@ public interface SysAuthService extends SecurityFrameworkService { @@ -28,4 +30,16 @@ public interface SysAuthService extends SecurityFrameworkService {
28 */ 30 */
29 SysAuthGetInfoRespVO getInfo(Long userId, Set<Long> roleIds); 31 SysAuthGetInfoRespVO getInfo(Long userId, Set<Long> roleIds);
30 32
  33 + /**
  34 + * 获得用户的菜单 Vue 路由
  35 + *
  36 + * 这里传输 roleIds 参数的原因,是该参数是从 LoginUser 缓存中获取到的,而我们校验权限时也是从 LoginUser 缓存中获取 roleIds
  37 + * 通过这样的方式,保持一致
  38 + *
  39 + * @param userId 用户编号
  40 + * @param roleIds 用户拥有的角色编号数组
  41 + * @return 菜单 Vue 路由
  42 + */
  43 + List<SysAuthGetRouterRespVO> getRouters(Long userId, Set<Long> roleIds);
  44 +
31 } 45 }
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java
@@ -5,12 +5,14 @@ import cn.hutool.core.util.StrUtil; @@ -5,12 +5,14 @@ import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.dashboard.framework.security.config.SecurityProperties; 5 import cn.iocoder.dashboard.framework.security.config.SecurityProperties;
6 import cn.iocoder.dashboard.framework.security.core.LoginUser; 6 import cn.iocoder.dashboard.framework.security.core.LoginUser;
7 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO; 7 import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO;
  8 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetRouterRespVO;
  9 +import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;
8 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO; 10 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
9 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO; 11 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
10 -import cn.iocoder.dashboard.modules.system.enums.user.UserStatus;  
11 -import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;  
12 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; 12 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
13 import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO; 13 import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO;
  14 +import cn.iocoder.dashboard.modules.system.enums.permission.MenuIdEnum;
  15 +import cn.iocoder.dashboard.modules.system.enums.user.UserStatus;
14 import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; 16 import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService;
15 import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService; 17 import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService;
16 import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; 18 import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
@@ -234,4 +236,38 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -234,4 +236,38 @@ public class SysAuthServiceImpl implements SysAuthService {
234 return SysAuthConvert.INSTANCE.convert(user, roleList, menuList); 236 return SysAuthConvert.INSTANCE.convert(user, roleList, menuList);
235 } 237 }
236 238
  239 + @Override
  240 + public List<SysAuthGetRouterRespVO> getRouters(Long userId, Set<Long> roleIds) {
  241 + // TODO 芋艿:去除 F 的类型,去除 禁用 的
  242 + List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(roleIds);
  243 + // 转换成 Tree 结构返回
  244 + return buildRouterTree(menuList);
  245 + }
  246 +
  247 + private static List<SysAuthGetRouterRespVO> buildRouterTree(List<SysMenuDO> menuList) {
  248 + // 排序,保证菜单的有序性
  249 + menuList = new ArrayList<>(menuList); // 使用 ArrayList 套一下,因为 menuList 是不可修改的 List
  250 + menuList.sort(Comparator.comparing(SysMenuDO::getOrderNum));
  251 + // 构建菜单树
  252 + // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。
  253 + Map<Long, SysAuthGetRouterRespVO> treeNodeMap = new LinkedHashMap<>();
  254 + menuList.forEach(menu -> treeNodeMap.put(menu.getMenuId(), SysAuthConvert.INSTANCE.convertTreeNode(menu)));
  255 + // 处理父子关系
  256 + treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(MenuIdEnum.ROOT.getId())).forEach((childNode) -> {
  257 + // 获得父节点
  258 + SysAuthGetRouterRespVO parentNode = treeNodeMap.get(childNode.getParentId());
  259 + if (parentNode == null) {
  260 + log.error("[buildRouterTree][resource({}) 找不到父资源({})]", childNode.getMenuId(), childNode.getParentId());
  261 + return;
  262 + }
  263 + // 将自己添加到父节点中
  264 + if (parentNode.getChildren() == null) {
  265 + parentNode.setChildren(new ArrayList<>());
  266 + }
  267 + parentNode.getChildren().add(childNode);
  268 + });
  269 + // 获得到所有的根节点
  270 + return CollectionUtils.filterList(treeNodeMap.values(), node -> MenuIdEnum.ROOT.getId().equals(node.getParentId()));
  271 + }
  272 +
237 } 273 }
src/main/java/cn/iocoder/dashboard/util/collection/CollectionUtils.java
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil; @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
4 4
5 import java.util.*; 5 import java.util.*;
6 import java.util.function.Function; 6 import java.util.function.Function;
  7 +import java.util.function.Predicate;
7 import java.util.stream.Collectors; 8 import java.util.stream.Collectors;
8 9
9 /** 10 /**
@@ -17,6 +18,10 @@ public class CollectionUtils { @@ -17,6 +18,10 @@ public class CollectionUtils {
17 return new HashSet<>(Arrays.asList(objs)); 18 return new HashSet<>(Arrays.asList(objs));
18 } 19 }
19 20
  21 + public static <T> List<T> filterList(Collection<T> from, Predicate<T> predicate) {
  22 + return from.stream().filter(predicate).collect(Collectors.toList());
  23 + }
  24 +
20 public static <T, U> List<U> convertList(List<T> from, Function<T, U> func) { 25 public static <T, U> List<U> convertList(List<T> from, Function<T, U> func) {
21 return from.stream().map(func).collect(Collectors.toList()); 26 return from.stream().map(func).collect(Collectors.toList());
22 } 27 }