123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- import React, { PureComponent } from 'react';
- // import { Layout, Menu, Icon } from 'antd';
- import { Layout, Menu, Icon, Spin } from 'antd';
- import pathToRegexp from 'path-to-regexp';
- import { Link } from 'dva/router';
- import styles from './index.less';
- import { urlToList } from '../_utils/pathTools';
-
- const { Sider } = Layout;
- const { SubMenu } = Menu;
-
- // Allow menu.js config icon as string or ReactNode
- // icon: 'setting',
- // icon: 'http://demo.com/icon.png',
- // icon: <Icon type="setting" />,
- const getIcon = icon => {
- if (typeof icon === 'string' && icon.indexOf('http') === 0) {
- return <img src={icon} alt="icon" className={`${styles.icon} sider-menu-item-img`} />;
- }
- if (typeof icon === 'string') {
- return <Icon type={icon} />;
- }
- return icon;
- };
-
- export const getMeunMatcheys = (flatMenuKeys, path) => {
- return flatMenuKeys.filter(item => {
- return pathToRegexp(item).test(path);
- });
- };
-
- export default class SiderMenu extends PureComponent {
- constructor(props) {
- super(props);
- // this.menus = props.menuData;
- this.flatMenuKeys = this.getFlatMenuKeys(props.menuData);
- this.state = {
- openKeys: this.getDefaultCollapsedSubMenus(props),
- };
- }
- componentWillReceiveProps(nextProps) {
- if (nextProps.location.pathname !== this.props.location.pathname) {
- this.setState({
- openKeys: this.getDefaultCollapsedSubMenus(nextProps),
- });
- }
- }
- /**
- * Convert pathname to openKeys
- * /list/search/articles = > ['list','/list/search']
- * @param props
- */
- getDefaultCollapsedSubMenus(props) {
- const { location: { pathname } } = props || this.props;
- return urlToList(pathname)
- .map(item => {
- // return getMeunMatcheys(this.flatMenuKeys, item)[0];
- return getMeunMatcheys(this.getFlatMenuKeys(props.menuData), item)[0];
- })
- .filter(item => item);
- }
- /**
- * Recursively flatten the data
- * [{path:string},{path:string}] => {path,path2}
- * @param menus
- */
- getFlatMenuKeys(menus) {
- let keys = [];
- menus.forEach(item => {
- if (item.children) {
- keys = keys.concat(this.getFlatMenuKeys(item.children));
- }
- keys.push(item.path);
- });
- return keys;
- }
- /**
- * 判断是否是http链接.返回 Link 或 a
- * Judge whether it is http link.return a or Link
- * @memberof SiderMenu
- */
- getMenuItemPath = item => {
- const itemPath = this.conversionPath(item.path);
- const icon = getIcon(item.icon);
- const { target, name } = item;
- // Is it a http link
- if (/^https?:\/\//.test(itemPath)) {
- return (
- <a href={itemPath} target={target}>
- {icon}
- <span>{name}</span>
- </a>
- );
- }
- return (
- <Link
- to={itemPath}
- target={target}
- replace={itemPath === this.props.location.pathname}
- onClick={
- this.props.isMobile
- ? () => {
- this.props.onCollapse(true);
- }
- : undefined
- }
- >
- {icon}
- <span>{name}</span>
- </Link>
- );
- };
- /**
- * get SubMenu or Item
- */
- getSubMenuOrItem = item => {
- if (item.children && item.children.some(child => child.name)) {
- const childrenItems = this.getNavMenuItems(item.children);
- // 当无子菜单时就不展示菜单
- if (childrenItems && childrenItems.length > 0) {
- return (
- <SubMenu
- title={
- item.icon ? (
- <span>
- {getIcon(item.icon)}
- <span>{item.name}</span>
- </span>
- ) : (
- item.name
- )
- }
- key={item.path}
- >
- {childrenItems}
- </SubMenu>
- );
- }
- return null;
- } else {
- return <Menu.Item key={item.path}>{this.getMenuItemPath(item)}</Menu.Item>;
- }
- };
- /**
- * 获得菜单子节点
- * @memberof SiderMenu
- */
- getNavMenuItems = menusData => {
- if (!menusData) {
- return [];
- }
- return menusData
- .filter(item => item.name && !item.hideInMenu)
- .map(item => {
- // make dom
- const ItemDom = this.getSubMenuOrItem(item);
- return this.checkPermissionItem(item.authority, ItemDom);
- })
- .filter(item => item);
- };
- // Get the currently selected menu
- getSelectedMenuKeys = () => {
- const { location: { pathname } } = this.props;
- // return urlToList(pathname).map(itemPath => getMeunMatcheys(this.flatMenuKeys, itemPath).pop());
- return urlToList(pathname).map(itemPath => getMeunMatcheys(this.getFlatMenuKeys(this.props.menuData), itemPath).pop());
- };
- // conversion Path
- // 转化路径
- conversionPath = path => {
- if (path && path.indexOf('http') === 0) {
- return path;
- } else {
- return `/${path || ''}`.replace(/\/+/g, '/');
- }
- };
- // permission to check
- checkPermissionItem = (authority, ItemDom) => {
- if (this.props.Authorized && this.props.Authorized.check) {
- const { check } = this.props.Authorized;
- return check(authority, ItemDom);
- }
- return ItemDom;
- };
- isMainMenu = key => {
- // return this.menus.some(item => key && (item.key === key || item.path === key));
- return this.props.menuData.some(item => key && (item.key === key || item.path === key));
- };
- handleOpenChange = openKeys => {
- const lastOpenKey = openKeys[openKeys.length - 1];
- const moreThanOne = openKeys.filter(openKey => this.isMainMenu(openKey)).length > 1;
- this.setState({
- openKeys: moreThanOne ? [lastOpenKey] : [...openKeys],
- });
- };
- render() {
- // const { logo, collapsed, onCollapse } = this.props;
- const { logo, collapsed, onCollapse, menuData } = this.props;
- const { openKeys } = this.state;
- // Don't show popup menu when it is been collapsed
- const menuProps = collapsed
- ? {}
- : {
- openKeys,
- };
- // if pathname can't match, use the nearest parent's key
- let selectedKeys = this.getSelectedMenuKeys();
- if (!selectedKeys.length) {
- selectedKeys = [openKeys[openKeys.length - 1]];
- }
- console.log('menuData: ', menuData);
-
- return (
- <Sider
- trigger={null}
- collapsible
- collapsed={collapsed}
- breakpoint="lg"
- onCollapse={onCollapse}
- width={256}
- className={styles.sider}
- >
- <div className={styles.logo} key="logo">
- <Link to="/">
- <img src={logo} alt="logo" />
- <h1>Ant Design Pro</h1>
- </Link>
- </div>
- {/* <Menu
- key="Menu"
- theme="dark"
- mode="inline"
- {...menuProps}
- onOpenChange={this.handleOpenChange}
- selectedKeys={selectedKeys}
- style={{ padding: '16px 0', width: '100%' }}
- >
- {this.getNavMenuItems(this.menus)}
- </Menu> */}
- <Spin spinning={menuData.length === 0}>
- <Menu
- key="Menu"
- theme="dark"
- mode="inline"
- {...menuProps}
- onOpenChange={this.handleOpenChange}
- selectedKeys={selectedKeys}
- style={{ padding: '16px 0', width: '100%' }}
- >
- {this.getNavMenuItems(menuData)}
- </Menu>
- </Spin>
- </Sider>
- );
- }
- }
|