根据后端返回的菜单权限来修改路由(动态路由)

功能描述

根据后端给到的菜单权限code来判断该用户拥有哪些菜单权限,并将该用户有权限的菜单显示出来,没有权限的则隐藏;其次,因为每个菜单是通过路由加载,如果该用户没有某个菜单的权限,不仅不显示该菜单而且也不能访问该菜单下的路由(即在浏览器地址栏输入没有权限的菜单路由会直接跳转到404页面)

代码实现

@/router/routes.js文件是用来存所有菜单的所有路由信息

import Base from "../../views/base.vue"; //基础布局,上左右结构

/**
 * @type { import("vue-router").RouteRecordRaw[] }
 */
export default [
  {
    path: "/test",
    name: "base",
    component: Base,
    redirect: "/test/page1",
    children: [
	  {
	    path: "/test/page1", //一级菜单
	    name: "Page1",
	    meta: {
	      permissionCode: "menu_page1"
	    },
	    redirect: "/test/page1/page11"
	  },
	  {
	    path: "/test/page1/page11", //二级菜单
	    name: "Page11",
	    meta: {
	      permissionCode: "menu_page1_page11"
	    },
	    component: () => import("@/views/page1/page11")
	  },
	  {
	    path: "/test/page2", //一级菜单
	    name: "Page2",
	    meta: {
	      permissionCode: "menu_page2"
	    },
	    redirect: "/test/page1/page22"
	  },
	  {
	    path: "/test/page2/page22", //二级菜单
	    name: "Page22",
	    meta: {
	      permissionCode: "menu_page2_page22"
	    },
	    component: () => import("@/views/page2/page2")
	  }
	  ......
    ]
  }
];

@/router/index.js 路由文件

import { createRouter, createWebHistory } from "vue-router";
import setRouterGuards from "./guards";
const systemRoutes = [];

export const resetRouter = (systemRoutes) => {
  const routes = [
    {
      path: "/",
      redirect: "/login"
    },
    {
      path: "/login",
      name: "mainLogin",
      component: () => import("@/views/login")
    },
    {
      path: "/logout",
      name: "mainLogout",
      component: () => import("@/views/logout")
    },
    {
      path: "/404",
      name: "main404",
      component: () => import("@/views/error/404")
    },
    {
      path: "/:catchAll(.*)",
      redirect: "/404"
    },
    ...systemRoutes
  ];

  const router = createRouter({
    history: createWebHistory("/"),
    routes
  });

  setRouterGuards(router);
  return router;
};
export default resetRouter(systemRoutes);

登录获取权限后组装动态路由

import router, { resetRouter } from "@/router";
import routes from "@/router/routes";
import { cloneDeep } from "lodash";

function GetUserInfo () {
	//用户密码登录后获取权限菜单 
	//menuAuth = ["menu_page1","menu_page1_page11","menu_page2","menu_page2_page22"...]
	.....
	//动态路由组装
	let tempRoutes = cloneDeep(routes[0].children);
	let newRoutes = cloneDeep(routes);
	 tempRoutes?.map((m) => {
	   if (m.meta?.permissionCode) {
	     let isExist = menuAuth.some((p) => m.meta?.permissionCode === p);
	     if (!isExist) {
	       let index = newRoutes[0].children.findIndex((r) => m.path === r.path);
	       index > -1 ? newRoutes[0].children.splice(index, 1) : null;
	     }
	   }
	 });
	 newRoutes[0].redirect = newRoutes[0].children[0].path;
	 //添加路由前先重置路由
	 router.matcher = resetRouter([]).matcher;
	 newRoutes.forEach((m) => router.addRoute(m));
	 ......
	 //存储用户信息及权限后进入系统
}

OK,这样动态路由就加载完成了。

注意

问题:刷新页面后,有权限访问的页面也变成了404,原因是登录时对已有权限的路由进行添加到系统路由中,但刷新页面后main.js文件也会重新加载,路由就会恢复默认没有添加routes的状态,导致访问所有的菜单都是404。
解决方法:在main.js实例化路由之前,首先判断当前系统是否已登录,如果已经登录那么就直接从store中取出已经持久化存储的权限菜单menuAuth,进行再次添加相关的路由信息。
main.js

import store from "./store";
import router, { resetRouter } from "@/router";
import routes from "@/router/routes";
import { cloneDeep } from "lodash";
......
let instance = null;
function checkRouter() {
  let menuAuth = store?.state?.user?.menuAuth || [];
  if (menuAuth?.length) {
    //动态路由组装
    let tempRoutes = cloneDeep(routes[0].children);
    let newRoutes = cloneDeep(routes);
    tempRoutes?.map((m) => {
      if (m.meta?.permissionCode) {
        let isExist = menuAuth.some((p) => m.meta?.permissionCode === p);
        if (!isExist) {
          let index = newRoutes[0].children.findIndex((r) => m.path === r.path);
          index > -1 ? newRoutes[0].children.splice(index, 1) : null;
        }
      }
    });
    newRoutes[0].redirect = newRoutes[0].children[0].path;
    //添加路由前先重置路由
    router.matcher = resetRouter([]).matcher;
    newRoutes.forEach((m) => router.addRoute(m));
  }
}
function render(props = {}) {
  const { container } = props;
  instance = plugin(createApp(App));
  checkRouter(); //重新鉴权路由
  instance
    .use(store)
    .use(router)
    .use(i18n)
    .use(Table)
    .use(Button)
    .use(Input)
    .mount(container ? container.querySelector("#app") : "#app");
}
......
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值