Commit cf93019ce123bcaeefd471c0052814bd795f554b
1 parent
162bebf5
增加 get-routers 接口的相关方法,未完全完成
Showing
11 changed files
with
181 additions
and
22 deletions
ruoyi-ui/src/api/login.js
ruoyi-ui/src/api/menu.js
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.http
| ... | ... | @@ -13,6 +13,10 @@ Content-Type: application/json |
| 13 | 13 | GET {{baseUrl}}/get-info |
| 14 | 14 | Authorization: Bearer {{token}} |
| 15 | 15 | |
| 16 | +### 请求 /get-routers 接口 => 成功 | |
| 17 | +GET {{baseUrl}}/get-routers | |
| 18 | +Authorization: Bearer {{token}} | |
| 19 | + | |
| 16 | 20 | ### 请求 /druid/xxx 接口 => 失败 TODO 临时测试 |
| 17 | 21 | GET http://127.0.0.1:8080/druid/123 |
| 18 | 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 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.common.pojo.CommonResult; |
| 4 | 4 | import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO; |
| 5 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetRouterRespVO; | |
| 5 | 6 | import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginReqVO; |
| 6 | 7 | import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginRespVO; |
| 7 | 8 | import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; |
| ... | ... | @@ -12,6 +13,8 @@ import org.springframework.web.bind.annotation.*; |
| 12 | 13 | import javax.annotation.Resource; |
| 13 | 14 | import javax.validation.Valid; |
| 14 | 15 | |
| 16 | +import java.util.List; | |
| 17 | + | |
| 15 | 18 | import static cn.iocoder.dashboard.common.pojo.CommonResult.success; |
| 16 | 19 | import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserId; |
| 17 | 20 | import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserRoleIds; |
| ... | ... | @@ -39,4 +42,11 @@ public class SysAuthController { |
| 39 | 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 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.framework.security.core.LoginUser; |
| 4 | 4 | import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO; |
| 5 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetRouterRespVO; | |
| 5 | 6 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO; |
| 6 | 7 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO; |
| 7 | 8 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; |
| ... | ... | @@ -27,4 +28,6 @@ public interface SysAuthConvert { |
| 27 | 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 | 1 | package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.framework.mybatis.core.BaseDO; |
| 4 | -import com.baomidou.mybatisplus.annotation.TableField; | |
| 5 | 4 | import com.baomidou.mybatisplus.annotation.TableId; |
| 6 | 5 | import com.baomidou.mybatisplus.annotation.TableName; |
| 7 | 6 | import lombok.Data; |
| ... | ... | @@ -9,8 +8,6 @@ import lombok.EqualsAndHashCode; |
| 9 | 8 | |
| 10 | 9 | import javax.validation.constraints.NotBlank; |
| 11 | 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 | 92 | */ |
| 96 | 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 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.framework.security.core.service.SecurityFrameworkService; |
| 4 | 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 | 8 | import java.util.Set; |
| 7 | 9 | |
| 8 | 10 | /** |
| ... | ... | @@ -28,4 +30,16 @@ public interface SysAuthService extends SecurityFrameworkService { |
| 28 | 30 | */ |
| 29 | 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 | 5 | import cn.iocoder.dashboard.framework.security.config.SecurityProperties; |
| 6 | 6 | import cn.iocoder.dashboard.framework.security.core.LoginUser; |
| 7 | 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 | 10 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO; |
| 9 | 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 | 12 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; |
| 13 | 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 | 16 | import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; |
| 15 | 17 | import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService; |
| 16 | 18 | import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; |
| ... | ... | @@ -234,4 +236,38 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 234 | 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 | 4 | |
| 5 | 5 | import java.util.*; |
| 6 | 6 | import java.util.function.Function; |
| 7 | +import java.util.function.Predicate; | |
| 7 | 8 | import java.util.stream.Collectors; |
| 8 | 9 | |
| 9 | 10 | /** |
| ... | ... | @@ -17,6 +18,10 @@ public class CollectionUtils { |
| 17 | 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 | 25 | public static <T, U> List<U> convertList(List<T> from, Function<T, U> func) { |
| 21 | 26 | return from.stream().map(func).collect(Collectors.toList()); |
| 22 | 27 | } | ... | ... |