若依左侧一级菜单点击会消失
后端(Java):
ruoyi/src/main/java/com/ruoyi/common/constant/UserConstants.java:
/** 是否菜单外链(否) */ public static final String NO_FRAME = "1"; /** 菜单类型(目录) */ 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"; /** 校验返回结果码 */ public final static String UNIQUE = "0"; public final static String NOT_UNIQUE = "1";
ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java:
router.setHidden("1".equals(menu.getVisible())); router.setName(StringUtils.capitalize(menu.getPath())); router.setPath(getRouterPath(menu)); router.setComponent(StringUtils.isEmpty(menu.getComponent()) ? "Layout" : menu.getComponent()); router.setComponent(getComponent(menu)); router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); List<SysMenu> cMenus = menu.getChildren(); if (!cMenus.isEmpty() && cMenus.size() > 0 && "M".equals(menu.getMenuType())) if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { router.setAlwaysShow(true); router.setRedirect("noRedirect"); router.setChildren(buildMenus(cMenus)); } else if (isMeunFrame(menu)) { List<RouterVo> childrenList = new ArrayList<RouterVo>(); RouterVo children = new RouterVo(); children.setPath(menu.getPath()); children.setComponent(menu.getComponent()); children.setName(StringUtils.capitalize(menu.getPath())); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); childrenList.add(children); router.setChildren(childrenList); } routers.add(router); } return routers; @@ -297,14 +308,48 @@ public class SysMenuServiceImpl implements ISysMenuService public String getRouterPath(SysMenu menu) { String routerPath = menu.getPath(); // 非外链并且是一级目录 if (0 == menu.getParentId() && UserConstants.NO_FRAME.equals(menu.getIsFrame())) // 非外链并且是一级目录(类型为目录) if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) && UserConstants.NO_FRAME.equals(menu.getIsFrame())) { routerPath = "/" + menu.getPath(); } // 非外链并且是一级目录(类型为菜单) else if (isMeunFrame(menu)) { routerPath = StringUtils.EMPTY; } return routerPath; } /** * 获取组件信息 * * @param menu 菜单信息 * @return 组件信息 */ public String getComponent(SysMenu menu) { String component = UserConstants.LAYOUT; if (StringUtils.isNotEmpty(menu.getComponent()) && !isMeunFrame(menu)) { component = menu.getComponent(); } return component; } /** * 是否为菜单内部跳转 * * @param menu 菜单信息 * @return 结果 */ public boolean isMeunFrame(SysMenu menu) { return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) && menu.getIsFrame().equals(UserConstants.NO_FRAME); } /** * 根据父节点的ID获取所有子节点 *
前端:
ruoyi-ui/src/store/modules/permission.js:
import auth from '@/plugins/auth' import router, { constantRoutes, dynamicRoutes } from '@/router' import { getRouters } from '@/api/menu' import Layout from '@/layout/index' import ParentView from '@/components/ParentView' import InnerLink from '@/layout/components/InnerLink' const permission = { state: { routes: [], addRoutes: [], defaultRoutes: [], topbarRouters: [], sidebarRouters: [] }, mutations: { SET_ROUTES: (state, routes) => { state.addRoutes = routes state.routes = constantRoutes.concat(routes) }, SET_DEFAULT_ROUTES: (state, routes) => { state.defaultRoutes = constantRoutes.concat(routes) }, SET_TOPBAR_ROUTES: (state, routes) => { state.topbarRouters = routes }, SET_SIDEBAR_ROUTERS: (state, routes) => { state.sidebarRouters = routes }, }, actions: { // 生成路由 GenerateRoutes({ commit }) { return new Promise(resolve => { // 向后端请求路由数据 getRouters().then(res => { const sdata = JSON.parse(JSON.stringify(res.data)) const rdata = JSON.parse(JSON.stringify(res.data)) const sidebarRoutes = filterAsyncRouter(sdata) const rewriteRoutes = filterAsyncRouter(rdata, false, true) const asyncRoutes = filterDynamicRoutes(sdata); rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true }) router.addRoutes(asyncRoutes); commit('SET_ROUTES', rewriteRoutes) commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes)) commit('SET_DEFAULT_ROUTES', sidebarRoutes) commit('SET_TOPBAR_ROUTES', sidebarRoutes) resolve(rewriteRoutes) }) }) } } } // 遍历后台传来的路由字符串,转换为组件对象 function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { return asyncRouterMap.filter(route => { // console.log(route); // console.log(route.menuId); route.meta.menuId = route.menuId if (!route.path) { // 防止空路由出现的警告,设置默认path route.path = ''; } if (type && route.children) { route.children = filterChildren(route.children) } // console.log(route.menuId); if (route.component) { // Layout ParentView 组件特殊处理 if (route.component === 'Layout') { route.component = Layout } else if (route.component === 'ParentView') { route.component = ParentView } else if (route.component === 'InnerLink') { route.component = InnerLink } else { route.component = loadView(route.component) } } if (route.children != null && route.children && route.children.length) { route.children = filterAsyncRouter(route.children, route, type) } else { delete route['children'] delete route['redirect'] } return true }) } function filterChildren(childrenMap, lastRouter = false) { var children = [] childrenMap.forEach((el, index) => { if (el.children && el.children.length) { if (el.component === 'ParentView' && !lastRouter) { el.children.forEach(c => { c.path = el.path + '/' + c.path if (c.children && c.children.length) { children = children.concat(filterChildren(c.children, c)) return } children.push(c) }) return } } if (lastRouter) { el.path = lastRouter.path + '/' + el.path } children = children.concat(el) }) return children } // 动态路由遍历,验证是否具备权限 export function filterDynamicRoutes(routes) { const res = [] routes.forEach(route => { if (route.permissions) { if (auth.hasPermiOr(route.permissions)) { res.push(route) } } else if (route.roles) { if (auth.hasRoleOr(route.roles)) { res.push(route) } } }) return res } export const loadView = (view) => { if (process.env.NODE_ENV === 'development') { return (resolve) => require([`@/views/${view}`], resolve) } else { // 使用 import 实现生产环境的路由懒加载 // return () => import(`@/views/${view}`) return (resolve) => require([`@/views/${view}`], resolve) } } export default permission
src/layout/components/Sidebar/index.vue
<!-- <template>
<div :class="{ 'has-logo': showLogo }">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu :default-active="activeMenu" :collapse="isCollapse" :background-color="variables.menuBg"
:text-color="variables.menuText" :unique-opened="true" :active-text-color="variables.menuActiveText"
:collapse-transition="false" mode="vertical">
<sidebar-item v-for="route in permission_routes" :key="route.path" :index="route.menuId" :item="route"
:base-path="route.path" />
</el-menu>
</el-scrollbar>
</div>
</template> -->
<template>
<div :class="{ 'has-logo': showLogo }">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu :default-active="activeMenu" :collapse="isCollapse" :background-color="variables.menuBg"
:text-color="variables.menuText" :unique-opened="true" :active-text-color="variables.menuActiveText"
:collapse-transition="false" mode="vertical">
<sidebar-item v-for="(route, index) in permission_routes" :key="route.path + index" :item="route"
:base-path="route.path" />
</el-menu>
</el-scrollbar>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/assets/styles/variables.scss'
export default {
components: { SidebarItem, Logo },
computed: {
...mapGetters([
'permission_routes',
'sidebar'
]),
activeMenu() {
const route = this.$route;
// console.log(route);
const { meta, path } = route
if (meta.activeMenu) {
return meta.activeMenu
}
if(!route.meta.menuId) {
route.meta.menuId = route.matched[0].meta.menuId;
}
return path
},
showLogo() {
return this.$store.state.settings.sidebarLogo
},
variables() {
return variables
},
isCollapse() {
return !this.sidebar.opened
}
}
}
</script>
点击菜单的时候,判断是否有获取到菜单Id:
activeMenu() { const route = this.$route; // console.log(route); const { meta, path } = route if (meta.activeMenu) { return meta.activeMenu } if(!route.meta.menuId) { route.meta.menuId = route.matched[0].meta.menuId; } return path },

浙公网安备 33010602011771号