Skip to content

Latest commit

 

History

History
379 lines (279 loc) · 7.54 KB

menu.md

File metadata and controls

379 lines (279 loc) · 7.54 KB

路由-菜单-权限

基本套路

在开发新程序,主要步骤如下

  • router.config.js 中定义路由与菜单。(不建议定义权限)
  • /api/auth_routesAPI函数中返回每个路由对应的菜单。
  • 后面会根据每个人,登陆的author来自动显示菜单与路由权限

举例:api/auth_routes定义

/list只能由user用户来访问

export default {
  '/api/auth_routes': {
    '/form/advanced-form': { authority: ['admin', 'user'] },
    '/list': { authority: ['user'] },
  },
};

参考文档

官方说明

  • 带参数的路由

代码分析-menu.js

1:得到当前目录routes

例如得到了path:'/'的 routes

{
  path: '/',
  component: '../layouts/BasicLayout',
  Routes: ['src/pages/Authorized'],
  routes: [
    // dashboard
    { path: '/', redirect: '/dashboard/analysis', authority: ['admin', 'u
    {
      path: '/dashboard',
      name: 'dashboard',
      icon: 'dashboard',
      routes: [
        {
          path: '/dashboard/analysis',
          name: 'analysis',
          component: './Dashboard/Analysis',
        },
        {
          path: '/dashboard/monitor',
          name: 'monitor',
          component: './Dashboard/Monitor',
        },
        {
          path: '/dashboard/workplace',
          name: 'workplace',
          component: './Dashboard/Workplace',
        },
      ],
    },
}    

2:通过formatter函数得到改造后的菜单

const memoizeOneFormatter = memoizeOne(formatter, isEqual);
const originalMenuData = memoizeOneFormatter(routes, authority, path);

实际上调用了formatter函数。

使用的第三方函数库

得到这么一个对象

[
  {
    "path": "/dashboard",
    "name": "Dashboard",
    "icon": "dashboard",
    "locale": "menu.dashboard",
    "children": [
      {
        "path": "/dashboard/analysis",
        "name": "分析页",
        "exact": true,
        "locale": "menu.dashboard.analysis"
      },
      {
        "path": "/dashboard/monitor",
        "name": "监控页",
        "exact": true,
        "locale": "menu.dashboard.monitor"
      },
      {
        "path": "/dashboard/workplace",
        "name": "工作台",
        "exact": true,
        "locale": "menu.dashboard.workplace"
      }
    ]
  },

程序逻辑

  • Map For循环传入的routes得到每个item
    • 如果item的name与path为空,就返回Null
    • 生成locale
      • 如果(parentName && parentName !== '/') ,那么前面要添加上parentName,主要是子菜单。
      • 否则的话,locale= 前面添加上menu。主要是顶级菜单
    • 生成name,主要是中文或多语言的name
      • 如果启动多语言,那么就formatMessage
    • 组装result
      • 保留原有的项目
      • 替换如下
        • name
        • locale(新追加)
        • authority(如果没有就取父节点的,如果有就拿自己的)
      • 判断当前item是否有子routes,如果有就将resultchildren复制
        • 如果有,就递归的调用,并得到结果。
  • .filter(item => item)过滤到空的数据

3:过滤原始菜单filterMenuData得到menuData

函数逻辑

  • 过滤掉那些name为空,并且,hideInMenu=false的数据
  • 循环数据,Authorized.check,过滤掉那些不符合权限的数据
    • Authorized.check使用说明
[
  {
    "path": "/dashboard",
    "name": "Dashboard",
    "icon": "dashboard",
    "locale": "menu.dashboard",
    "children": [
      {
        "path": "/dashboard/analysis",
        "name": "分析页",
        "exact": true,
        "locale": "menu.dashboard.analysis"
      },
      {
        "path": "/dashboard/workplace",
        "name": "工作台",
        "exact": true,
        "locale": "menu.dashboard.workplace"
      }
    ]
  },
]

4:得到面包屑 memoizeOneGetBreadcrumbNameMap

{
  "/dashboard/analysis": {
    "path": "/dashboard/analysis",
    "name": "分析页",
    "exact": true,
    "locale": "menu.dashboard.analysis"
  },
  "/dashboard/monitor": {
    "path": "/dashboard/monitor",
    "name": "监控页",
    "authority": [
      "user"
    ],
    "exact": true,
    "locale": "menu.dashboard.monitor"
  },
  "/dashboard/workplace": {
    "path": "/dashboard/workplace",
    "name": "工作台",
    "exact": true,
    "locale": "menu.dashboard.workplace"
  },
  "/dashboard": {
    "path": "/dashboard",
    "name": "Dashboard",
    "icon": "dashboard",
    "locale": "menu.dashboard",
    "children": [
      {
        "path": "/dashboard/analysis",
        "name": "分析页",
        "exact": true,
        "locale": "menu.dashboard.analysis"
      },
      {
        "path": "/dashboard/monitor",
        "name": "监控页",
        "authority": [
          "user"
        ],
        "exact": true,
        "locale": "menu.dashboard.monitor"
      },
      {
        "path": "/dashboard/workplace",
        "name": "工作台",
        "exact": true,
        "locale": "menu.dashboard.workplace"
      }
    ]
  },
}  

代码分析-app.js

app.js的官方说明

获得指定的权限

export function render(oldRender) {
  fetch('/api/auth_routes')
    .then(res => res.json())
    .then(
      ret => {
        authRoutes = ret;
        oldRender();
      },
      () => {
        oldRender();
      }
    );
}

修改路由

function ergodicRoutes(routes, authKey, authority) {
  routes.forEach(element => {
    if (element.path === authKey) {
      if (!element.authority) element.authority = []; // eslint-disable-line
      Object.assign(element.authority, authority || []);
    } else if (element.routes) {
      ergodicRoutes(element.routes, authKey, authority);
    }
    return element;
  });
}

export function patchRoutes(routes) {
  Object.keys(authRoutes).map(authKey =>
    ergodicRoutes(routes, authKey, authRoutes[authKey].authority)
  );
  window.g_routes = routes;
}

老的版本

老的版本会根据服务器得到菜单值

import fetch from 'dva/fetch';

export const dva = {
  config: {
    onError(err) {
      err.preventDefault();
    },
  },
};

let authRoutes = {};

function ergodicRoutes(routes, authKey, authority) {
  routes.forEach(element => {
    if (element.path === authKey) {
      if (!element.authority) element.authority = []; // eslint-disable-line
      Object.assign(element.authority, authority || []);
    } else if (element.routes) {
      ergodicRoutes(element.routes, authKey, authority);
    }
    return element;
  });
}

export function patchRoutes(routes) {
  Object.keys(authRoutes).map(authKey =>
    ergodicRoutes(routes, authKey, authRoutes[authKey].authority)
  );
  window.g_routes = routes;
}

export function render(oldRender) {
  fetch('/api/auth_routes')
    .then(res => res.json())
    .then(
      ret => {
        authRoutes = ret;
        oldRender();
      },
      () => {
        oldRender();
      }
    );
}