antdpro4+JS设置服务器菜单

本文介绍了如何在AntdPro4中结合JavaScript实现服务器动态获取并设置菜单的功能。在用户退出登录时,为了确保清空菜单数据,防止加载先前账号的菜单信息,文中提及了在`src/models/menu.js`中处理此逻辑,并详细讲解了如何调用`src/services/menu.js`中的API接口获取菜单,并在`src/layouts/basiclayout.jsx`中进行侧边栏的渲染。

src/moaels/menu.js

import { getMenuData } from '@/services/menu'
import { loginOut } from '@/services/api'

const MenuModel= {
  namespace: 'menu',
  state: {
    menuData: [],
    loading: true,
  },
  effects: {
    *fetchMenu(_, { call, put }) {
      const response = yield call(getMenuData)
      yield put({
        type: 'saveMenuData',
        payload: response.data,
      })
    },
    //清除保存的服务器菜单数据
    *clearMenu(_, { call, put }) {
      const response = yield call(loginOut)
      yield put({
        type: 'clearMenuData',
        payload: [],
      })
    }
  },
  reducers: {
    saveMenuData(state, action) {
      return {
        ...state,
        menuData: action.payload || [],
        loading: false,
      }
    },
    clearMenuData(state,action){
      return {
        ...state,
        menuData: [],
        loading: true,
      }
    }
  }
}

export default MenuModel

退出登录时需要清除保存的服务器菜单数据,不然登录其他账号会加载上个账号的菜单

const { dispatch} =this.props
    dispatch({
      type: 'menu/clearMenu',
    });

api接口
src/services/menu.js

import request from '@/utils/request'

export async function getMenuData() {
  return request('/api/menu')
}

侧边渲染
src/layouts/basiclayout.jsx

/**
 * Ant Design Pro v4 use `@ant-design/pro-layout` to handle Layout.
 * You can view component api by:
 * https://github.com/ant-design/ant-design-pro-layout
 */
import ProLayout, { DefaultFooter, SettingDrawer } from '@ant-design/pro-layout';
import React, { useEffect, useMemo, useRef } from 'react';
import { Link, useIntl, connect, history } from 'umi';
import { Result, Button } from 'antd';
import Authorized from '@/utils/Authorized';
import RightContent from '@/components/GlobalHeader/RightContent';
import { getMatchMenu } from '@umijs/route-utils';
import logo from '../assets/logo.svg';

const noMatch = (
  <Result
    status={403}
    title="403"
    subTitle="您暂时没有权限查看此页面。"
    extra={
      <Button type="primary">
        <Link to="/user/login">去登录</Link>
      </Button>
    }
  />
);

/**
 * use Authorized check all menu item
 */
// const menuDataRender = (menuList) =>
//   menuList.map((item) => {
//     item.name = item.code
//     const result = {
//       ...item,
//     };
//     if(item.routes){
//       const children = menuDataRender(item.children)
//       result.children = children
//     }
//     delete result.routes
//     return Authorized.check(item.authority, result);
//   });
const formatter = (data, parentAuthority, parentName) => {
  if (!data) {
    return undefined
  }
  return data
    .map(item => {
      if (!item.path) {
        return null
      }
      const name = item.code
      const result = {
        ...item,
        name,
        authority: item.authority || parentAuthority
      }
      if (item.routes) {
        const children = formatter(item.routes, item.authority)
        result.children = children
      }
      delete result.routes
      return result
    })
    .filter(item => item)
}
const defaultFooterDom = (
  <DefaultFooter copyright={`${new Date().getFullYear()} 广东高乐教育科技有限公司`} links={false} />
);

const BasicLayout = (props) => {
  const {
    dispatch,
    children,
    location = {
      pathname: '/',
    },
    menuData,
    loading,
    settings,
  } = props;
  const menuDataRef = useRef([]);
  useEffect(() => {
    if (dispatch) {
      dispatch({
        type: 'menu/fetchMenu',
      });
    }
  }, []);
  /**
   * init variables
   */

  const handleMenuCollapse = (payload) => {
    if (dispatch) {
      dispatch({
        type: 'global/changeLayoutCollapsed',
        payload,
      });
    }
  }; // get children authority

  const authorized = useMemo(
    () =>
      getMatchMenu(location.pathname || '/', menuDataRef.current).pop() || {
        authority: undefined,
      },
    [location.pathname],
  );
  const { formatMessage } = useIntl();
  return (
    <>
      <ProLayout
        logo={logo}
        formatMessage={formatMessage}
        {...props}
        {...settings}
        onCollapse={handleMenuCollapse}
        onMenuHeaderClick={() => history.push('/')}
        menuItemRender={(menuItemProps, defaultDom) => {
          if (menuItemProps.isUrl || !menuItemProps.path) {
            return defaultDom;
          }
          return <Link to={menuItemProps.path}>{defaultDom}</Link>;
        }}
        breadcrumbRender={(routers = []) => [
          {
            path: '/',
            breadcrumbName: formatMessage({
              id: 'menu.home',
            }),
          },
          ...routers,
        ]}
        itemRender={(route, params, routes, paths) => {
          const first = routes.indexOf(route) === 0;
          return first ? (
            <Link to={paths.join('/')}>{route.breadcrumbName}</Link>
          ) : (
            <span>{route.breadcrumbName}</span>
          );
        }}
        footerRender={() => defaultFooterDom}
        menuDataRender={() => formatter(menuData)}
        menu={{
          loading,
        }}
        rightContentRender={() => <RightContent />}
        postMenuData={(menuData) => {
        //这是权限判断,不去掉可能会页面403
        // menuDataRef.current = menuData || [];
        return menuData || [];
      }}
      >
        <Authorized authority={authorized.authority} noMatch={noMatch}>
          {children}
        </Authorized>
      </ProLayout>
    </>
  );
};

export default connect(({ global, settings, menu }) => ({
  collapsed: global.collapsed,
  menuData: menu.menuData,
  loading: menu.loading,
  settings
}))(BasicLayout);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值