基于Umi根据权限设置动态路由_顶部Menu_侧边栏

1,202 阅读3分钟

1.在app.js中全局监听路由变化

    //路由变化参数捕捉
    export function onRouteChange({ matchedRoutes }) {
      const g_app = getDvaApp();
      const route = matchedRoutes[matchedRoutes.length - 1]?.route;
      const url = history.location.pathname;
      g_app._store.dispatch({
        type: 'common/saveRouterUrl',
        payload: url,
      });
      g_app._store.dispatch({
        type: 'common/updateModel',
        payload: { configure: route },
      });
    }

2.在router.js中设置动态路由middleRouter

    import middleRouter from './src/utils/middleRouter';
    export default [
      { path: '/', component: '@/pages/Login/index' }, // 登录
      {
        component: '@/layouts/CommonLayout.js',
        routes: [
          { path: '/homePage', component: '@/pages/HomePage/index' }, // 首页
          { path: '/emptyPage', component: '@/pages/EmptyPage/index' }, // 无权限空白页
          ...middleRouter,
          { component: '@/pages/404' },
        ],
      },
      { component: '@/pages/404' },
    ];

3.middleRouter的层级不固定,功能包含路由权限和侧边栏是否展示

    export default [
      {
        // 数据模型
        path: '/management',
        auth: 'sjmx',
        name: '数据模型',
        routes: [
          {
            path: '/management/dataConnect',
            component: '@/pages/Management/DataConnect/index',
            showSlider: true, //展示侧边栏
            auth: 'sjmx_sjlj',
          }, //数据连接
          {
            path: '/management/dataModal',
            component: '@/pages/Management/DataModal/index',
            showSlider: true, //展示侧边栏
            auth: 'sjmx_sjmx',
          }, // 数据模型
        ],
      },
      {
        path: '/taskCenter',
        auth: 'rwzx',
        name: '任务中心',
        routes: [
          // 用户体系
          {
            path: '/taskCenter',
            showSlider: true, //展示侧边栏
            auth: 'rwzx_tbrw',
            routes: [
              {
                path: '/taskCenter/creatTask',
                component: '@/pages/TaskCenter/CreatTask/index',
                showSlider: true, //展示侧边栏
                auth: 'rwzx_tbrw_wcj',
              }, // 我创建
              {
                path: '/taskCenter/waitTask',
                component: '@/pages/TaskCenter/WaitTask/index',
                showSlider: true, //展示侧边栏
                auth: 'rwzx_tbrw_dtb',
              }, // 待填报任务
            ],
          },
        ],
      },
    ];

4.封装根据后端返回的权限列表,过滤出有权限的路由

    /* routes : 动态路由部分, transRouter: 权限列表 */
    
    const filterRouter = (routes, transRouter) => {
      const authRoutes = [];
      routes.forEach((route) => {
        if (transRouter.includes(route.auth)) {
          authRoutes.push(route);
          if (route.routes?.length) {
            route.routes = filterRouter(route.routes, transRouter);
          }
        }
      });
      return authRoutes;
    };

    export default filterRouter;

5.登录页面,跳转到过滤之后的路由的第一个

       dispatch({
          type: 'homePage/getUserAuth',
          payload: {
            ids: res.data.id,
          },
        }).then(async (res) => {
          if (res && res.status === 20000) {
            localStorage.setItem('auth', JSON.stringify(res.data));
            if (res.data.length != 0) {
              let targetRouter = authRouter(middleRouter, res.data);
              let originRouter = targetRouter.map((item) => {
                if (item.routes.length != 0) {
                  return item.routes[0].path;
                }
              });
              history.push(originRouter[0]);
            }
          } else {
            message.error('获取权限失败');
          }
        });

6.根据动态路由处理顶部Menu

      const findUrl = (data) => {
        if (data.routes?.length) {
          return findUrl(data.routes[0]);
        } else {
          return data.path;
        }
      };
      const auth = JSON.parse(localStorage.getItem('auth'));
      useEffect(() => {
          // 根据权限获取到的路由 
        let targetRouter = authRouter(middleRouter, auth);
        
        // 根据路由设置menu
        const transMenuList = targetRouter.map((item) => {
          return {
            name: item.name,
            key: item.path.substring(1),
            url: findUrl(item).substring(1),
          };
        });
        setMenuList(transMenuList); 
      }, []);

7.根据权限处理侧边栏Menu

    import { useEffect, useState } from 'react';
    import { history, useSelector } from 'umi';
    import { SolutionOutlined, UserOutlined } from '@ant-design/icons';
    import { Layout, Menu } from 'antd';
    import silderBtn from '../../../public/silderBtn.png';
    import dataConnect from '../../assets/silder/dataConnect.png';
    import dataModal from '../../assets/silder/dataModal.png';
    import formManage from '../../assets/silder/formManage.png';
    import processDesign from '../../assets/silder/processDesign.png';
    import personalCenter from '../../assets/silder/personalCenter.png';
    import styles from './index.less';
    const CommonSlider = () => {
      const { Sider } = Layout;
      const { SubMenu } = Menu;
      const { location } = history;
      const { pathname } = location;
      const configure = useSelector((state) => state.common.configure);
      const [activeKey, setActiveKey] = useState('');
      const [activeSubKey, setActiveSubKey] = useState([]);
      const [collapsed, setCollapsed] = useState(false);
      const hideInfo = history.location.query?.hideInfo;
      useEffect(() => {
        // 我创建页面需要用到待填报页面,此时侧边路由不需要跳转
        if (!hideInfo) {
          setActiveKey(pathname.slice(1));
          setActiveSubKey([pathname.split('/').slice(1, 2).join('/')]);
        }
      }, [pathname]);

      // const auth = ['sjzx_bdgl', 'sjzx_bdsj', 'sjmx_sjmx'];
      const auth = JSON.parse(localStorage.getItem('auth'));
      // 设计中心
      const designCenterMenuList = [
        {
          name: '表单管理',
          icon: (
            <img src={formManage} style={{ width: '16px', height: '16px' }}></img>
          ),
          url: 'designCenter/formManage',
          auth: 'sjzx_bdgl',
        },
        {
          name: '表单设计',
          icon: (
            <img
              src={processDesign}
              style={{ width: '16px', height: '16px' }}
            ></img>
          ),
          url: 'designCenter/formDesign',
          auth: 'sjzx_bdsj',
        },
      ];

      // 任务中心
      const taskCenterMenuList = [
        {
          name: '填报任务',
          icon: (
            <img
              src={personalCenter}
              style={{ width: '16px', height: '16px' }}
            ></img>
          ),
          url: 'taskCenter',
          auth: 'rwzx_tbrw',
          children: [
            {
              name: '我创建任务',
              icon: '',
              url: 'taskCenter/creatTask',
              auth: 'rwzx_tbrw_wcj',
            },
            {
              name: '待填报任务',
              icon: '',
              url: 'taskCenter/waitTask',
              auth: 'rwzx_tbrw_dtb',
            },
          ],
        },
      ];

      // 数据模型
      const ManagementList = [
        {
          name: '数据连接',
          icon: (
            <img src={dataConnect} style={{ width: '16px', height: '16px' }}></img>
          ),
          url: 'management/dataConnect',
          auth: 'sjmx_sjlj',
        },
        {
          name: '数据模型',
          icon: (
            <img src={dataModal} style={{ width: '16px', height: '16px' }}></img>
          ),
          url: 'management/dataModal',
          auth: 'sjmx_sjmx',
        },
      ];

      const settingList = [
        {
          name: '组织管理',
          icon: (
            <img src={dataConnect} style={{ width: '16px', height: '16px' }}></img>
          ),
          url: 'systemSetting/originSystem',
          auth: 'xtsz_zzgl',
        },
        {
          name: '用户管理',
          icon: (
            <img src={dataConnect} style={{ width: '16px', height: '16px' }}></img>
          ),
          url: 'systemSetting/userSystem',
          auth: 'xtsz_yhgl',
        },
        {
          name: '角色管理',
          icon: (
            <img src={dataModal} style={{ width: '16px', height: '16px' }}></img>
          ),
          url: 'systemSetting/roleSystem',
          auth: 'xtsz_jsgl',
        },
        {
          name: '平台名称设置',
          icon: (
            <img src={dataModal} style={{ width: '16px', height: '16px' }}></img>
          ),
          url: 'systemSetting/platformName',
          auth: 'xtsz_ptmcsz',
        },
      ];

      const changeMenuItem = (item) => {
        history.push(`/${item.key}`);
      };
      const menuList = (Url) => {
        switch (Url) {
          case 'designCenter':
            return designCenterMenuList;
          case 'taskCenter':
            return taskCenterMenuList;
          case 'management':
            return ManagementList;
          case 'systemSetting':
            return settingList;
          default:
            break;
        }
      };

      const clickSubMenu = ({ key }) => {
        if (activeSubKey[0] === key) {
          setActiveSubKey([]);
        } else {
          setActiveSubKey([key]);
        }
      };

      return (
        <Sider className={styles.siderBackground} collapsed={collapsed}>
          <div className={styles.toggle}>
            {collapsed ? (
              <div
                onClick={() => {
                  setCollapsed(false);
                }}
                className={styles.openMenu}
              >
                <img src={silderBtn} alt="" />
              </div>
            ) : (
              <div
                onClick={() => {
                  setCollapsed(true);
                }}
                className={styles.closeMenu}
              >
                <img src={silderBtn} alt="" />
              </div>
            )}
          </div>
          <Menu
            mode="inline"
            openKeys={activeSubKey}
            selectedKeys={[activeKey]}
            className={styles.menuStyles}
            onClick={changeMenuItem}
            key={configure.path}
            defaultSelectedKeys={
              configure.showSlider
                ? menuList(configure.path.split('/')[1])[0].url
                : null
            }
          >
            {menuList(configure.path?.split('/')[1]).map((item) => {
              if (!item.children && auth.includes(item.auth)) {
                return (
                  <Menu.Item key={item.url} icon={item.icon}>
                    {item.name}
                  </Menu.Item>
                );
              } else {
                if (auth.includes(item.auth)) {
                  return (
                    <SubMenu
                      title={item.name}
                      icon={item.icon}
                      key={item.url}
                      onTitleClick={clickSubMenu}
                    >
                      {item.children.map((res, index) => {
                        if (auth.includes(res.auth)) {
                          return <Menu.Item key={res.url}>{res.name}</Menu.Item>;
                        }
                      })}
                    </SubMenu>
                  );
                }
              }
            })}
          </Menu>
        </Sider>
      );
    };

    export default CommonSlider;