Skip to content

后台管理系统路由过滤

两种方案

前端控制

前端生成配置文件,后端返回权限.前端拿这个权限去匹对路由

路由在前端

后端控制(本文就是后者)

后端返回路由,前端依据这些路由去筛选出对应关系

过程

过程

  1. 通过后端获取到权限, 通过本地获取到全部路由

  2. 先过滤掉第一层取出父亲

  3. 第二步再过滤掉孩子

流程

1. 总方法

js
 generateRoutes(roles) {
     return new Promise((resolve) => {
      // 测试数据
        const routers = [
          "/testuser",
          "/testuser/create",
          "/testuser/update",
          "/testuser/del",
          "/testuser2/edit",
          "/testuser2",
          "/testuser2/create2",
          "/testuser2/update2",
          "/testuser3",
        ];
        // 路由总数据
        const allRouters = router.getRoutes();
        console.log(allRouters);
        // 先过滤开头
        const allRouters_All = this.changefirstRouter(allRouters, routers);
        // 再过滤孩子
        this.fenleiroutes(allRouters_All, routers);
        console.log(allRouters_All);
     })
 }

2. 过滤掉第一层

js
// 过滤开始 先过滤到第一层取出父亲
changefirstRouter(allRouters, routers) {
  const result = [];
  routers.forEach((item) => {
    const menu = item.split("/")[1];
    allRouters.forEach((item1) => {
      if (item1.path == "/" + menu) {
        if (result.length == 0) {
          result.push(item1);
        } else {
          if (!result.includes(item1)) {
            result.push(item1);
          }
        }
      }
    });
  });
  return result;
},

3. 过滤掉孩子

js
// 获取到分类下面的所有路由
fenleiroutes(allRouters, routers) {
  let path_url = ""; // 路由路径
  /* 获取到规则 */
  const roles = routers;
  for (let i = 0; i < allRouters.length; i++) {
    // 第一次遍历 获取所有的children
    if (allRouters[i].children) {
      // 如果有子集
      const arr = allRouters[i].children.filter((item, j) => {
        path_url = this.resolvePath(
          allRouters[i].path,
          allRouters[i].children[j].path
        );
        return roles.indexOf(path_url) !== -1; // 返回有权限的路由
      });

      allRouters[i].children = arr;
      // 第三层
      for (let m = 0; m < allRouters[i].children.length; m++) {
        if (allRouters[i].children[m].children) {
          // 判断权限中没有该子集,并且该子集 有子集
          this.fenleiroutes(allRouters[i].children); // 递归处理
        }
      }
    }
  }
},

// 合并路径
resolvePath(basePath, routePath) {
  return basePath + "/" + routePath;
},

若依更新路由

  • 两个文件

    • src/store/modules/user.js 获取用户信息

    • src/store/modules/permission.js 获取权限

修改 src/store/modules/permission.js

修改src/store/modules/permission.js

在 actions 里面增加方法,修改 generateRoutes

js
    generateRoutes(roles) {
      return new Promise((resolve) => {
        // 向后端请求路由数据
        // getRouters().then((res) => {
        //   const sdata = JSON.parse(JSON.stringify(res.data));
        //   const rdata = JSON.parse(JSON.stringify(res.data));
        //   const defaultData = JSON.parse(JSON.stringify(res.data));
        //   const sidebarRoutes = filterAsyncRouter(sdata);
        //   const rewriteRoutes = filterAsyncRouter(rdata, false, true);
        //   const defaultRoutes = filterAsyncRouter(defaultData);
        //   const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
        //   asyncRoutes.forEach((route) => {
        //     router.addRoute(route);
        //   });
        //   this.setRoutes(rewriteRoutes);
        //   this.setSidebarRouters(constantRoutes.concat(sidebarRoutes));
        //   this.setDefaultRoutes(sidebarRoutes);
        //   this.setTopbarRoutes(defaultRoutes);
        //   resolve(rewriteRoutes);
        // });

        // 自己模拟路由
        const routers = this.getAllRouerPath(dynamicRoutes);
        // 目标数据
        const allRouters = router.getRoutes();
        // 先过滤开头
        const allRouters_All = this.changefirstRouter(allRouters, routers);
        // 再过滤孩子
        this.fenleiroutes(allRouters_All, routers);
        console.log(allRouters_All);
        const sdata = allRouters_All;
        const rdata = allRouters_All;
        const defaultData = allRouters_All;
        const sidebarRoutes = filterAsyncRouter(sdata);
        const rewriteRoutes = filterAsyncRouter(rdata, false, true);
        const defaultRoutes = filterAsyncRouter(defaultData);
        const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
        asyncRoutes.forEach((route) => {
          router.addRoute(route);
        });
        this.setRoutes(rewriteRoutes);
        this.setSidebarRouters(constantRoutes.concat(sidebarRoutes));
        this.setDefaultRoutes(sidebarRoutes);
        this.setTopbarRoutes(defaultRoutes);
        resolve(rewriteRoutes);
      });
    },

    // 过滤开始 先过滤到第一层取出父亲
    changefirstRouter(allRouters, routers) {
      const result = [];
      routers.forEach((item) => {
        const menu = item.split("/")[1];
        allRouters.forEach((item1) => {
          if (item1.path == "/" + menu) {
            if (result.length == 0) {
              result.push(item1);
            } else {
              if (!result.includes(item1)) {
                result.push(item1);
              }
            }
          }
        });
      });
      return result;
    },
    // 获取到分类下面的所有路由
    fenleiroutes(allRouters, routers) {
      let path_url = ""; // 路由路径
      /* 获取到规则 */
      const roles = routers;
      for (let i = 0; i < allRouters.length; i++) {
        // 第一次遍历 获取所有的children
        if (allRouters[i].children) {
          // 如果有子集
          const arr = allRouters[i].children.filter((item, j) => {
            path_url = this.resolvePath(
              allRouters[i].path,
              allRouters[i].children[j].path
            );
            return roles.indexOf(path_url) !== -1; // 返回有权限的路由
          });

          allRouters[i].children = arr;
          // 第三层
          for (let m = 0; m < allRouters[i].children.length; m++) {
            if (allRouters[i].children[m].children) {
              // 判断权限中没有该子集,并且该子集 有子集
              this.fenleiroutes(allRouters[i].children); // 递归处理
            }
          }
        }
      }
    },
    // 合并路径
    resolvePath(basePath, routePath) {
      return basePath + "/" + routePath;
    },
  • 修改 filterAsyncRouter 方法
js
// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
  return asyncRouterMap.filter((route) => {
    if (type && route.children) {
      route.children = filterChildren(route.children);
    }
    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 = 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;
  });
}

修改 src/store/modules/user.js

  • 修改用户信息
js
// 获取用户信息
getInfo() {
  return new Promise((resolve, reject) => {
    const result = {
      msg: "操作成功",
      code: 200,
      permissions: ["*:*:*"],
      roles: ["admin"],
      user: {
        userId: "1",
        userName: "admin",
        avatar:
          "https://dianyuan-public.oss-cn-shenzhen.aliyuncs.com/static/live/dianyuan_avatar.png",
      },
    };
    this.roles = result.roles;
    this.permissions = result.permissions;
    this.name = result.user.userName;
    this.avatar = result.user.avatar;
    this.id = result.user.userId;
    resolve(result);
    // getInfo()
    //   .then((res) => {
    //     const user = res.user;
    //     const avatar =
    //       user.avatar == "" || user.avatar == null
    //         ? defAva
    //         : import.meta.env.VITE_APP_BASE_API + user.avatar;

    //     if (res.roles && res.roles.length > 0) {
    //       // 验证返回的roles是否是一个非空数组
    //       this.roles = res.roles;
    //       this.permissions = res.permissions;
    //     } else {
    //       this.roles = ["ROLE_DEFAULT"];
    //     }
    //     this.id = user.userId;
    //     this.name = user.userName;
    //     this.avatar = avatar;

    //     resolve(res);
    //   })
    //   .catch((error) => {
    //     reject(error);
    //   });
  });
},