From 77a83cee8bfc6a66188e3ed95d23b9beab819229 Mon Sep 17 00:00:00 2001 From: ailanyin Date: Fri, 12 May 2023 17:21:44 +0800 Subject: [PATCH] add --- .../qiaoba/api/system/entity/vo/MetaVo.java | 68 +++++++ .../qiaoba/api/system/entity/vo/RouterVo.java | 66 +++++++ .../api/system/entity/vo/SysMenuVo.java | 25 +++ .../common/base/constants/BaseConstant.java | 10 ++ .../common/base/constants/MenuConstant.java | 56 ++++++ .../system/controller/SysLoginController.java | 16 +- .../system/controller/SysMenuController.java | 1 - .../module/system/mapper/SysMenuMapper.java | 8 + .../module/system/service/SysMenuService.java | 17 ++ .../service/impl/SysMenuServiceImpl.java | 15 ++ .../qiaoba/module/system/utils/MenuUtil.java | 166 ++++++++++++++++++ .../qiaoba/module/system/utils/TreeUtil.java | 83 +++++++++ .../main/resources/mapper/SysMenuMapper.xml | 11 ++ 13 files changed, 539 insertions(+), 3 deletions(-) create mode 100644 qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/MetaVo.java create mode 100644 qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/RouterVo.java create mode 100644 qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/MenuConstant.java create mode 100644 qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/utils/MenuUtil.java create mode 100644 qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/utils/TreeUtil.java diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/MetaVo.java b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/MetaVo.java new file mode 100644 index 0000000..0835a7b --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/MetaVo.java @@ -0,0 +1,68 @@ +package com.qiaoba.api.system.entity.vo; + +import cn.hutool.http.HttpUtil; +import lombok.Getter; +import lombok.Setter; + +/** + * 路由显示信息 + * + * @author ailanyin + * @version 1.0 + * @since 2022-09-22 04:20:28 + */ +@Getter +@Setter +public class MetaVo { + + /** + * 设置该路由在侧边栏和面包屑中展示的名字 + */ + private String title; + + /** + * 设置该路由的图标,对应路径src/assets/icons/svg + */ + private String icon; + + /** + * 设置为true,则不会被 缓存 + */ + private boolean noCache; + + /** + * 内链地址(http(s)://开头) + */ + private String link; + + public MetaVo() { + } + + public MetaVo(String title, String icon) { + this.title = title; + this.icon = icon; + } + + public MetaVo(String title, String icon, boolean noCache) { + this.title = title; + this.icon = icon; + this.noCache = noCache; + } + + public MetaVo(String title, String icon, String link) { + this.title = title; + this.icon = icon; + if (HttpUtil.isHttp(link) || HttpUtil.isHttps(link)) { + this.link = link; + } + } + + public MetaVo(String title, String icon, boolean noCache, String link) { + this.title = title; + this.icon = icon; + this.noCache = noCache; + if (HttpUtil.isHttp(link) || HttpUtil.isHttps(link)) { + this.link = link; + } + } +} diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/RouterVo.java b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/RouterVo.java new file mode 100644 index 0000000..a14a9ef --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/RouterVo.java @@ -0,0 +1,66 @@ +package com.qiaoba.api.system.entity.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * 路由配置信息 + * + * @author ailanyin + * @version 1.0 + * @since 2022-09-22 04:20:28 + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@Getter +@Setter +public class RouterVo { + + /** + * 路由名字 + */ + private String name; + + /** + * 路由地址 + */ + private String path; + + /** + * 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现 + */ + private boolean hidden; + + /** + * 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + */ + private String redirect; + + /** + * 组件地址 + */ + private String component; + + /** + * 路由参数:如 {"id": 1, "name": "ry"} + */ + private String query; + + /** + * 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + */ + private Boolean alwaysShow; + + /** + * 其他元素 + */ + private MetaVo meta; + + /** + * 子路由 + */ + private List children; + +} diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/SysMenuVo.java b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/SysMenuVo.java index acddd24..30bb40f 100644 --- a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/SysMenuVo.java +++ b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/vo/SysMenuVo.java @@ -45,6 +45,11 @@ public class SysMenuVo implements Serializable { */ private String component; + /** + * 路由参数 + */ + private String query; + /** * 显示状态(0隐藏 1显示) */ @@ -55,11 +60,31 @@ public class SysMenuVo implements Serializable { */ private String perms; + /** + * 路由地址 + */ + private String path; + /** * 菜单图标 */ private String icon; + /** + * 是否为外链(0否 1是) + */ + private String isFrame; + + /** + * 是否缓存(0不缓存 1缓存) + */ + private String isCache; + + /** + * 类型(M目录 C菜单 F按钮) + */ + private String menuType; + /** * 创建时间 */ diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java index 5b53377..8ee3f62 100644 --- a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java @@ -28,4 +28,14 @@ public class BaseConstant { * 默认的父ID = 0 */ public static final String DEFAULT_PARENT_ID_VALUE = "0"; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; } diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/MenuConstant.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/MenuConstant.java new file mode 100644 index 0000000..aad4d20 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/MenuConstant.java @@ -0,0 +1,56 @@ +package com.qiaoba.common.base.constants; + +/** + * 菜单常量 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 15:37:43 + */ +public class MenuConstant { + + /** + * 是否菜单外链(是) + */ + public static final String YES_FRAME = "1"; + + /** + * 是否菜单外链(否) + */ + public static final String NO_FRAME = "0"; + + /** + * 菜单类型(目录) + */ + public static final String TYPE_DIR = "M"; + + /** + * 菜单类型(菜单) + */ + public static final String TYPE_MENU = "C"; + + /** + * 菜单类型(按钮) + */ + public static final String TYPE_BUTTON = "F"; + + /** + * Layout组件标识 + */ + public final static String LAYOUT = "Layout"; + + /** + * ParentView组件标识 + */ + public final static String PARENT_VIEW = "ParentView"; + + /** + * InnerLink组件标识 + */ + public final static String INNER_LINK = "InnerLink"; + + /** + * 不重定向 + */ + public final static String NO_REDIRECT = "noRedirect"; +} diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysLoginController.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysLoginController.java index 736cc84..ff23662 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysLoginController.java +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysLoginController.java @@ -1,10 +1,16 @@ package com.qiaoba.module.system.controller; +import com.qiaoba.api.system.entity.SysMenu; +import com.qiaoba.api.system.entity.vo.SysMenuVo; import com.qiaoba.common.base.result.AjaxResult; +import com.qiaoba.module.system.service.SysMenuService; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + /** * 登录 * @@ -13,8 +19,12 @@ import org.springframework.web.bind.annotation.RestController; * @since 2023/5/5 9:43 */ @RestController +@RequiredArgsConstructor public class SysLoginController { + private final SysMenuService sysMenuService; + + @PostMapping("/login") public String login() { return "{\"msg\":\"操作成功\",\"code\":200,\"token\":\"eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjhhNjY4MGY1LTI0OTAtNDUyYi1hYzQ1LWE5YWI0MzQ0YTRlYyJ9.mTZr7TN1Jk2-_7zbeUbOBuHijVLiqY2QSbhcAIfWuX4oF22xGw_DpxOz3I2_-TLeYlJN4y2Gm1qmw6ricqCBqw\"}"; @@ -26,8 +36,10 @@ public class SysLoginController { } @GetMapping("/getRouters") - public String getRouters() { - return "{\"msg\":\"操作成功\",\"code\":200,\"data\":[{\"name\":\"System\",\"path\":\"/system\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统管理\",\"icon\":\"system\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"User\",\"path\":\"user\",\"hidden\":false,\"component\":\"system/user/index\",\"meta\":{\"title\":\"用户管理\",\"icon\":\"user\",\"noCache\":false,\"link\":null}},{\"name\":\"Role\",\"path\":\"role\",\"hidden\":false,\"component\":\"system/role/index\",\"meta\":{\"title\":\"角色管理\",\"icon\":\"peoples\",\"noCache\":false,\"link\":null}},{\"name\":\"Menu\",\"path\":\"menu\",\"hidden\":false,\"component\":\"system/menu/index\",\"meta\":{\"title\":\"菜单管理\",\"icon\":\"tree-table\",\"noCache\":false,\"link\":null}},{\"name\":\"Dept\",\"path\":\"dept\",\"hidden\":false,\"component\":\"system/dept/index\",\"meta\":{\"title\":\"部门管理\",\"icon\":\"tree\",\"noCache\":false,\"link\":null}},{\"name\":\"Post\",\"path\":\"post\",\"hidden\":false,\"component\":\"system/post/index\",\"meta\":{\"title\":\"岗位管理\",\"icon\":\"post\",\"noCache\":false,\"link\":null}},{\"name\":\"Dict\",\"path\":\"dict\",\"hidden\":false,\"component\":\"system/dict/index\",\"meta\":{\"title\":\"字典管理\",\"icon\":\"dict\",\"noCache\":false,\"link\":null}},{\"name\":\"Config\",\"path\":\"config\",\"hidden\":false,\"component\":\"system/config/index\",\"meta\":{\"title\":\"参数设置\",\"icon\":\"edit\",\"noCache\":false,\"link\":null}},{\"name\":\"Notice\",\"path\":\"notice\",\"hidden\":false,\"component\":\"system/notice/index\",\"meta\":{\"title\":\"通知公告\",\"icon\":\"message\",\"noCache\":false,\"link\":null}},{\"name\":\"Log\",\"path\":\"log\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"ParentView\",\"alwaysShow\":true,\"meta\":{\"title\":\"日志管理\",\"icon\":\"log\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Operlog\",\"path\":\"operlog\",\"hidden\":false,\"component\":\"monitor/operlog/index\",\"meta\":{\"title\":\"操作日志\",\"icon\":\"form\",\"noCache\":false,\"link\":null}},{\"name\":\"Logininfor\",\"path\":\"logininfor\",\"hidden\":false,\"component\":\"monitor/logininfor/index\",\"meta\":{\"title\":\"登录日志\",\"icon\":\"logininfor\",\"noCache\":false,\"link\":null}}]}]},{\"name\":\"Monitor\",\"path\":\"/monitor\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统监控\",\"icon\":\"monitor\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Online\",\"path\":\"online\",\"hidden\":false,\"component\":\"monitor/online/index\",\"meta\":{\"title\":\"在线用户\",\"icon\":\"online\",\"noCache\":false,\"link\":null}},{\"name\":\"Job\",\"path\":\"job\",\"hidden\":false,\"component\":\"monitor/job/index\",\"meta\":{\"title\":\"定时任务\",\"icon\":\"job\",\"noCache\":false,\"link\":null}},{\"name\":\"Druid\",\"path\":\"druid\",\"hidden\":false,\"component\":\"monitor/druid/index\",\"meta\":{\"title\":\"数据监控\",\"icon\":\"druid\",\"noCache\":false,\"link\":null}},{\"name\":\"Server\",\"path\":\"server\",\"hidden\":false,\"component\":\"monitor/server/index\",\"meta\":{\"title\":\"服务监控\",\"icon\":\"server\",\"noCache\":false,\"link\":null}},{\"name\":\"Cache\",\"path\":\"cache\",\"hidden\":false,\"component\":\"monitor/cache/index\",\"meta\":{\"title\":\"缓存监控\",\"icon\":\"redis\",\"noCache\":false,\"link\":null}},{\"name\":\"CacheList\",\"path\":\"cacheList\",\"hidden\":false,\"component\":\"monitor/cache/list\",\"meta\":{\"title\":\"缓存列表\",\"icon\":\"redis-list\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Tool\",\"path\":\"/tool\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统工具\",\"icon\":\"tool\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Build\",\"path\":\"build\",\"hidden\":false,\"component\":\"tool/build/index\",\"meta\":{\"title\":\"表单构建\",\"icon\":\"build\",\"noCache\":false,\"link\":null}},{\"name\":\"Gen\",\"path\":\"gen\",\"hidden\":false,\"component\":\"tool/gen/index\",\"meta\":{\"title\":\"代码生成\",\"icon\":\"code\",\"noCache\":false,\"link\":null}},{\"name\":\"Swagger\",\"path\":\"swagger\",\"hidden\":false,\"component\":\"tool/swagger/index\",\"meta\":{\"title\":\"系统接口\",\"icon\":\"swagger\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Http://ruoyi.vip\",\"path\":\"http://ruoyi.vip\",\"hidden\":false,\"component\":\"Layout\",\"meta\":{\"title\":\"若依官网\",\"icon\":\"guide\",\"noCache\":false,\"link\":\"http://ruoyi.vip\"}}]}"; + public Object getRouters() { + List sysMenuVos = sysMenuService.selectByUserId("1650123803828019202"); + return AjaxResult.success(sysMenuService.menusToRouters(sysMenuVos)); + //return "{\"msg\":\"操作成功\",\"code\":200,\"data\":[{\"name\":\"System\",\"path\":\"/system\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统管理\",\"icon\":\"system\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"User\",\"path\":\"user\",\"hidden\":false,\"component\":\"system/user/index\",\"meta\":{\"title\":\"用户管理\",\"icon\":\"user\",\"noCache\":false,\"link\":null}},{\"name\":\"Role\",\"path\":\"role\",\"hidden\":false,\"component\":\"system/role/index\",\"meta\":{\"title\":\"角色管理\",\"icon\":\"peoples\",\"noCache\":false,\"link\":null}},{\"name\":\"Menu\",\"path\":\"menu\",\"hidden\":false,\"component\":\"system/menu/index\",\"meta\":{\"title\":\"菜单管理\",\"icon\":\"tree-table\",\"noCache\":false,\"link\":null}},{\"name\":\"Dept\",\"path\":\"dept\",\"hidden\":false,\"component\":\"system/dept/index\",\"meta\":{\"title\":\"部门管理\",\"icon\":\"tree\",\"noCache\":false,\"link\":null}},{\"name\":\"Post\",\"path\":\"post\",\"hidden\":false,\"component\":\"system/post/index\",\"meta\":{\"title\":\"岗位管理\",\"icon\":\"post\",\"noCache\":false,\"link\":null}},{\"name\":\"Dict\",\"path\":\"dict\",\"hidden\":false,\"component\":\"system/dict/index\",\"meta\":{\"title\":\"字典管理\",\"icon\":\"dict\",\"noCache\":false,\"link\":null}},{\"name\":\"Config\",\"path\":\"config\",\"hidden\":false,\"component\":\"system/config/index\",\"meta\":{\"title\":\"参数设置\",\"icon\":\"edit\",\"noCache\":false,\"link\":null}},{\"name\":\"Notice\",\"path\":\"notice\",\"hidden\":false,\"component\":\"system/notice/index\",\"meta\":{\"title\":\"通知公告\",\"icon\":\"message\",\"noCache\":false,\"link\":null}},{\"name\":\"Log\",\"path\":\"log\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"ParentView\",\"alwaysShow\":true,\"meta\":{\"title\":\"日志管理\",\"icon\":\"log\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Operlog\",\"path\":\"operlog\",\"hidden\":false,\"component\":\"monitor/operlog/index\",\"meta\":{\"title\":\"操作日志\",\"icon\":\"form\",\"noCache\":false,\"link\":null}},{\"name\":\"Logininfor\",\"path\":\"logininfor\",\"hidden\":false,\"component\":\"monitor/logininfor/index\",\"meta\":{\"title\":\"登录日志\",\"icon\":\"logininfor\",\"noCache\":false,\"link\":null}}]}]},{\"name\":\"Monitor\",\"path\":\"/monitor\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统监控\",\"icon\":\"monitor\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Online\",\"path\":\"online\",\"hidden\":false,\"component\":\"monitor/online/index\",\"meta\":{\"title\":\"在线用户\",\"icon\":\"online\",\"noCache\":false,\"link\":null}},{\"name\":\"Job\",\"path\":\"job\",\"hidden\":false,\"component\":\"monitor/job/index\",\"meta\":{\"title\":\"定时任务\",\"icon\":\"job\",\"noCache\":false,\"link\":null}},{\"name\":\"Druid\",\"path\":\"druid\",\"hidden\":false,\"component\":\"monitor/druid/index\",\"meta\":{\"title\":\"数据监控\",\"icon\":\"druid\",\"noCache\":false,\"link\":null}},{\"name\":\"Server\",\"path\":\"server\",\"hidden\":false,\"component\":\"monitor/server/index\",\"meta\":{\"title\":\"服务监控\",\"icon\":\"server\",\"noCache\":false,\"link\":null}},{\"name\":\"Cache\",\"path\":\"cache\",\"hidden\":false,\"component\":\"monitor/cache/index\",\"meta\":{\"title\":\"缓存监控\",\"icon\":\"redis\",\"noCache\":false,\"link\":null}},{\"name\":\"CacheList\",\"path\":\"cacheList\",\"hidden\":false,\"component\":\"monitor/cache/list\",\"meta\":{\"title\":\"缓存列表\",\"icon\":\"redis-list\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Tool\",\"path\":\"/tool\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统工具\",\"icon\":\"tool\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Build\",\"path\":\"build\",\"hidden\":false,\"component\":\"tool/build/index\",\"meta\":{\"title\":\"表单构建\",\"icon\":\"build\",\"noCache\":false,\"link\":null}},{\"name\":\"Gen\",\"path\":\"gen\",\"hidden\":false,\"component\":\"tool/gen/index\",\"meta\":{\"title\":\"代码生成\",\"icon\":\"code\",\"noCache\":false,\"link\":null}},{\"name\":\"Swagger\",\"path\":\"swagger\",\"hidden\":false,\"component\":\"tool/swagger/index\",\"meta\":{\"title\":\"系统接口\",\"icon\":\"swagger\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Http://ruoyi.vip\",\"path\":\"http://ruoyi.vip\",\"hidden\":false,\"component\":\"Layout\",\"meta\":{\"title\":\"若依官网\",\"icon\":\"guide\",\"noCache\":false,\"link\":\"http://ruoyi.vip\"}}]}"; } @PostMapping("/logout") diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysMenuController.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysMenuController.java index c79ea63..5ab08f2 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysMenuController.java +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysMenuController.java @@ -4,7 +4,6 @@ import com.qiaoba.api.system.entity.SysMenu; import com.qiaoba.api.system.entity.param.SysMenuParam; import com.qiaoba.api.system.entity.vo.SysMenuVo; import com.qiaoba.common.base.result.AjaxResult; -import com.qiaoba.common.security.utils.SecurityUtil; import com.qiaoba.module.system.service.SysMenuService; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysMenuMapper.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysMenuMapper.java index 61f7e4e..dfb7cc9 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysMenuMapper.java +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysMenuMapper.java @@ -30,4 +30,12 @@ public interface SysMenuMapper extends BaseMapperPlus selectMenuIdsByRoleId(String roleId); + + /** + * 通过 userId 查询目录和菜单 + * + * @param userId userId + * @return list + */ + List selectByUserId(String userId); } diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysMenuService.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysMenuService.java index d124c63..59cca3c 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysMenuService.java +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysMenuService.java @@ -1,6 +1,8 @@ package com.qiaoba.module.system.service; import cn.hutool.core.lang.tree.Tree; +import com.qiaoba.api.system.entity.SysMenu; +import com.qiaoba.api.system.entity.vo.RouterVo; import com.qiaoba.api.system.entity.vo.SysMenuVo; import com.qiaoba.api.system.service.SysMenuApiService; @@ -31,4 +33,19 @@ public interface SysMenuService extends SysMenuApiService { * @return 选中菜单ID列表 */ List selectMenuIdsByRoleId(String roleId); + + /** + * 通过 userId 查询目录和菜单 + * @param userId userId + * @return list + */ + List selectByUserId(String userId); + + /** + * 菜单转路由 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + List menusToRouters(List menus); } diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysMenuServiceImpl.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysMenuServiceImpl.java index c46f9cd..2310468 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysMenuServiceImpl.java +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysMenuServiceImpl.java @@ -7,11 +7,13 @@ import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.qiaoba.api.system.entity.SysMenu; import com.qiaoba.api.system.entity.param.SysMenuParam; +import com.qiaoba.api.system.entity.vo.RouterVo; import com.qiaoba.api.system.entity.vo.SysMenuVo; import com.qiaoba.common.base.constants.BaseConstant; import com.qiaoba.common.base.exceptions.ServiceException; import com.qiaoba.module.system.mapper.SysMenuMapper; import com.qiaoba.module.system.service.SysMenuService; +import com.qiaoba.module.system.utils.MenuUtil; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -87,7 +89,20 @@ public class SysMenuServiceImpl implements SysMenuService { return sysMenuMapper.selectMenuIdsByRoleId(roleId); } + @Override + public List selectByUserId(String userId) { + return sysMenuMapper.selectByUserId(userId); + } + + @Override + public List menusToRouters(List menus) { + return MenuUtil.menusToRouters(menus); + } + + private boolean checkMenuNameNotUnique(SysMenu menu) { return sysMenuMapper.checkMenuNameUnique(menu) > 0; } + + } diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/utils/MenuUtil.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/utils/MenuUtil.java new file mode 100644 index 0000000..f177fc1 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/utils/MenuUtil.java @@ -0,0 +1,166 @@ +package com.qiaoba.module.system.utils; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import com.qiaoba.api.system.entity.vo.MetaVo; +import com.qiaoba.api.system.entity.vo.RouterVo; +import com.qiaoba.api.system.entity.vo.SysMenuVo; +import com.qiaoba.common.base.constants.BaseConstant; +import com.qiaoba.common.base.constants.MenuConstant; +import com.qiaoba.common.base.enums.BaseEnum; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * 菜单工具类 + * + * @author ailanyin + * @version 1.0 + * @since 2023/5/12 10:33 + */ +public class MenuUtil { + + public static List menusToRouters(List menus) { + List tree = TreeUtil.buildTree(menus, SysMenuVo.class, "menuId", "parentId", "children"); + List routers = new LinkedList(); + for (SysMenuVo menu : tree) { + RouterVo router = new RouterVo(); + router.setHidden(StrUtil.equals(BaseEnum.NO.getCode(), menu.getIsVisible())); + router.setName(MenuUtil.getRouteName(menu)); + router.setPath(MenuUtil.getRouterPath(menu)); + router.setComponent(MenuUtil.getComponent(menu)); + router.setQuery(menu.getQuery()); + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StrUtil.equals(BaseEnum.NO.getCode(), menu.getIsCache()), menu.getPath())); + List cMenus = menu.getChildren(); + if (CollUtil.isNotEmpty(cMenus) && MenuConstant.TYPE_DIR.equals(menu.getMenuType())) { + router.setAlwaysShow(true); + router.setRedirect(MenuConstant.NO_REDIRECT); + router.setChildren(menusToRouters(cMenus)); + } else if (MenuUtil.isMenuFrame(menu)) { + router.setMeta(null); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + children.setPath(menu.getPath()); + children.setComponent(menu.getComponent()); + children.setName(StrUtil.upperFirst(menu.getPath())); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StrUtil.equals(BaseEnum.NO.getCode(), menu.getIsCache()), menu.getPath())); + children.setQuery(menu.getQuery()); + childrenList.add(children); + router.setChildren(childrenList); + } else if (BaseConstant.DEFAULT_PARENT_ID_VALUE.equals(menu.getParentId()) && MenuUtil.isInnerLink(menu.getIsFrame(), menu.getPath())) { + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); + router.setPath("/"); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + String routerPath = MenuUtil.innerLinkReplaceEach(menu.getPath()); + children.setPath(routerPath); + children.setComponent(MenuConstant.INNER_LINK); + children.setName(StrUtil.upperFirst(routerPath)); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); + childrenList.add(children); + router.setChildren(childrenList); + } + routers.add(router); + } + return routers; + } + + /** + * 获取路由名称 + * + * @param menuVo 菜单信息 + * @return 路由名称 + */ + private static String getRouteName(SysMenuVo menuVo) { + // 首字母大写 + String routerName = StrUtil.upperFirst(menuVo.getPath()); + // 非外链并且是一级目录(类型为目录) + return isMenuFrame(menuVo) ? StrUtil.EMPTY : routerName; + } + + /** + * 是否为菜单内部跳转 + * + * @param menuVo 菜单信息 + * @return 结果 + */ + private static boolean isMenuFrame(SysMenuVo menuVo) { + return BaseConstant.DEFAULT_PARENT_ID_VALUE.equals(menuVo.getParentId()) && MenuConstant.TYPE_MENU.equals(menuVo.getMenuType()) + && menuVo.getIsFrame().equals(MenuConstant.NO_FRAME); + } + + /** + * 获取路由地址 + * + * @param menuVo 菜单信息 + * @return 路由地址 + */ + private static String getRouterPath(SysMenuVo menuVo) { + String routerPath = menuVo.getPath(); + // 内链打开外网方式 + if (!BaseConstant.DEFAULT_PARENT_ID_VALUE.equals(menuVo.getParentId()) && isInnerLink(menuVo.getIsFrame(), menuVo.getPath())) { + routerPath = innerLinkReplaceEach(routerPath); + } + // 非外链并且是一级目录(类型为目录) + if (BaseConstant.DEFAULT_PARENT_ID_VALUE.equals(menuVo.getParentId()) && MenuConstant.TYPE_DIR.equals(menuVo.getMenuType()) + && MenuConstant.NO_FRAME.equals(menuVo.getIsFrame())) { + routerPath = "/" + menuVo.getPath(); + } + // 非外链并且是一级目录(类型为菜单) + else if (isMenuFrame(menuVo)) { + routerPath = "/"; + } + return routerPath; + } + + /** + * 获取组件信息 + * + * @param menuVo 菜单信息 + * @return 组件信息 + */ + private static String getComponent(SysMenuVo menuVo) { + String component = MenuConstant.LAYOUT; + if (StrUtil.isNotEmpty(menuVo.getComponent()) && !isMenuFrame(menuVo)) { + component = menuVo.getComponent(); + } else if (StrUtil.isEmpty(menuVo.getComponent()) && !BaseConstant.DEFAULT_PARENT_ID_VALUE.equals(menuVo.getParentId()) && isInnerLink(menuVo.getIsFrame(), menuVo.getPath())) { + component = MenuConstant.INNER_LINK; + } else if (StrUtil.isEmpty(menuVo.getComponent()) && isParentView(menuVo.getParentId(), menuVo.getMenuType())) { + component = MenuConstant.PARENT_VIEW; + } + return component; + } + + /** + * 是否为内链组件 + * + * @param isFrame isFrame + * @param path path + * @return 结果 + */ + private static boolean isInnerLink(String isFrame, String path) { + return MenuConstant.NO_FRAME.equals(isFrame) && (HttpUtil.isHttp(path) || HttpUtil.isHttps(path)); + } + + /** + * 内链域名特殊字符替换 + */ + private static String innerLinkReplaceEach(String path) { + return path.replaceAll(BaseConstant.HTTP, "").replaceAll(BaseConstant.HTTPS, ""); + } + + /** + * 是否为parent_view组件 + * + * @param parentId parentId + * @param menuType menuType + * @return 结果 + */ + private static boolean isParentView(String parentId, String menuType) { + return !BaseConstant.DEFAULT_PARENT_ID_VALUE.equals(parentId) && MenuConstant.TYPE_DIR.equals(menuType); + } + +} diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/utils/TreeUtil.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/utils/TreeUtil.java new file mode 100644 index 0000000..0a4e168 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/utils/TreeUtil.java @@ -0,0 +1,83 @@ +package com.qiaoba.module.system.utils; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * 树工具类 遍历子节点 + * + * @author ailanyin + * @version 1.0 + * @since 2021-08-31 + */ +public class TreeUtil { + + public static List buildTree(List trees, Class clazz, String idFieldName, String parentIdFieldName, String childIdFieldName) { + List returnList = new ArrayList<>(); + List tempList = new ArrayList<>(); + for (T tree : trees) { + tempList.add(ReflectUtil.getFieldValue(tree, ReflectUtil.getField(clazz, idFieldName))); + } + + for (T tree : trees) { + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(ReflectUtil.getFieldValue(tree, ReflectUtil.getField(clazz, parentIdFieldName)))) { + recursionFn(trees, clazz, tree, idFieldName, parentIdFieldName, childIdFieldName); + returnList.add(tree); + } + } + + if (returnList.isEmpty()) { + returnList = trees; + } + + return returnList; + } + + /** + * 递归列表 + */ + private static void recursionFn(List list, Class clazz, T t, String idFieldName, String parentIdFieldName, String childIdFieldName) { + // 得到子节点列表 + List childList = getChildList(list, t, clazz, idFieldName, parentIdFieldName); + ReflectUtil.invoke(t, ReflectUtil.getMethodByName(clazz, getSetMethodName(childIdFieldName)), childList); + + for (T tChild : childList) { + if (hasChild(list, tChild, clazz, idFieldName, parentIdFieldName)) { + recursionFn(list, clazz, tChild, idFieldName, parentIdFieldName, childIdFieldName); + } + } + } + + private static String getSetMethodName(String field) { + return "set" + StrUtil.upperFirst(field); + } + + /** + * 得到子节点列表 + */ + private static List getChildList(List list, T t, Class clazz, String idFieldName, String parentIdFieldName) { + List childList = new ArrayList<>(); + for (T n : list) { + Object parentId = ReflectUtil.getFieldValue(n, ReflectUtil.getField(clazz, parentIdFieldName)); + Object id = ReflectUtil.getFieldValue(t, ReflectUtil.getField(clazz, idFieldName)); + if (ObjectUtil.isNotEmpty(parentId) && ObjectUtil.isNotEmpty(id) && parentId.toString().equals(id.toString())) { + childList.add(n); + } + + } + return childList; + } + + /** + * 判断是否有子节点 + */ + private static boolean hasChild(List list, T t, Class clazz, String idFieldName, String parentIdFieldName) { + return getChildList(list, t, clazz, idFieldName, parentIdFieldName).size() > 0; + } + +} diff --git a/qiaoba-modules/qiaoba-module-system/src/main/resources/mapper/SysMenuMapper.xml b/qiaoba-modules/qiaoba-module-system/src/main/resources/mapper/SysMenuMapper.xml index e3aaecd..440eff5 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/resources/mapper/SysMenuMapper.xml +++ b/qiaoba-modules/qiaoba-module-system/src/main/resources/mapper/SysMenuMapper.xml @@ -20,4 +20,15 @@ where rm.role_id = #{roleId} order by m.parent_id, m.order_num + +