index.js 4.89 KB
Newer Older
偏右's avatar
偏右 committed
1 2 3 4 5
import React, { PureComponent } from 'react';
import { Layout, Menu, Icon } from 'antd';
import { Link } from 'dva/router';
import logo from '../../assets/logo.svg';
import styles from './index.less';
ddcat1115's avatar
ddcat1115 committed
6
import { getMenuData } from '../../common/menu';
偏右's avatar
偏右 committed
7 8 9 10 11 12 13

const { Sider } = Layout;
const { SubMenu } = Menu;

export default class SiderMenu extends PureComponent {
  constructor(props) {
    super(props);
ddcat1115's avatar
ddcat1115 committed
14
    this.menus = getMenuData();
偏右's avatar
偏右 committed
15 16 17 18 19 20 21 22 23 24 25
    this.state = {
      openKeys: this.getDefaultCollapsedSubMenus(props),
    };
  }
  onCollapse = (collapsed) => {
    this.props.dispatch({
      type: 'global/changeLayoutCollapsed',
      payload: collapsed,
    });
  }
  getDefaultCollapsedSubMenus(props) {
ddcat1115's avatar
ddcat1115 committed
26 27 28 29 30 31 32 33 34 35
    const { location: { pathname } } = props || this.props;
    const snippets = pathname.split('/').slice(1, -1);
    const currentPathSnippets = snippets.map((item, index) => {
      const arr = snippets.filter((_, i) => i <= index);
      return arr.join('/');
    });
    let currentMenuSelectedKeys = [];
    currentPathSnippets.forEach((item) => {
      currentMenuSelectedKeys = currentMenuSelectedKeys.concat(this.getSelectedMenuKeys(item));
    });
偏右's avatar
偏右 committed
36 37 38 39 40
    if (currentMenuSelectedKeys.length === 0) {
      return ['dashboard'];
    }
    return currentMenuSelectedKeys;
  }
ddcat1115's avatar
ddcat1115 committed
41 42 43 44 45 46 47 48 49 50
  getFlatMenuKeys(menus) {
    let keys = [];
    menus.forEach((item) => {
      if (item.children) {
        keys.push(item.path);
        keys = keys.concat(this.getFlatMenuKeys(item.children));
      } else {
        keys.push(item.path);
      }
    });
偏右's avatar
偏右 committed
51 52
    return keys;
  }
ddcat1115's avatar
ddcat1115 committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
  getSelectedMenuKeys = (path) => {
    const flatMenuKeys = this.getFlatMenuKeys(this.menus);

    if (flatMenuKeys.indexOf(path.replace(/^\//, '')) > -1) {
      return [path.replace(/^\//, '')];
    }
    if (flatMenuKeys.indexOf(path.replace(/^\//, '').replace(/\/$/, '')) > -1) {
      return [path.replace(/^\//, '').replace(/\/$/, '')];
    }
    return flatMenuKeys.filter((item) => {
      const itemRegExpStr = `^${item.replace(/:[\w-]+/g, '[\\w-]+')}$`;
      const itemRegExp = new RegExp(itemRegExpStr);
      return itemRegExp.test(path.replace(/^\//, ''));
    });
  }
  getNavMenuItems(menusData) {
偏右's avatar
偏右 committed
69 70 71 72 73 74 75 76
    if (!menusData) {
      return [];
    }
    return menusData.map((item) => {
      if (!item.name) {
        return null;
      }
      let itemPath;
ddcat1115's avatar
ddcat1115 committed
77
      if (item.path && item.path.indexOf('http') === 0) {
偏右's avatar
偏右 committed
78 79
        itemPath = item.path;
      } else {
ddcat1115's avatar
ddcat1115 committed
80
        itemPath = `/${item.path || ''}`.replace(/\/+/g, '/');
偏右's avatar
偏右 committed
81 82
      }
      if (item.children && item.children.some(child => child.name)) {
ddcat1115's avatar
ddcat1115 committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
        return item.hideInMenu ? null :
          (
            <SubMenu
              title={
                item.icon ? (
                  <span>
                    <Icon type={item.icon} />
                    <span>{item.name}</span>
                  </span>
                ) : item.name
              }
              key={item.key || item.path}
            >
              {this.getNavMenuItems(item.children)}
            </SubMenu>
          );
偏右's avatar
偏右 committed
99 100
      }
      const icon = item.icon && <Icon type={item.icon} />;
ddcat1115's avatar
ddcat1115 committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
      return item.hideInMenu ? null :
        (
          <Menu.Item key={item.key || item.path}>
            {
              /^https?:\/\//.test(itemPath) ? (
                <a href={itemPath} target={item.target}>
                  {icon}<span>{item.name}</span>
                </a>
              ) : (
                <Link
                  to={itemPath}
                  target={item.target}
                  replace={itemPath === this.props.location.pathname}
                >
                  {icon}<span>{item.name}</span>
                </Link>
              )
            }
          </Menu.Item>
        );
偏右's avatar
偏右 committed
121 122 123 124 125 126 127 128 129 130 131 132
    });
  }
  handleOpenChange = (openKeys) => {
    const lastOpenKey = openKeys[openKeys.length - 1];
    const isMainMenu = this.menus.some(
      item => lastOpenKey && (item.key === lastOpenKey || item.path === lastOpenKey)
    );
    this.setState({
      openKeys: isMainMenu ? [lastOpenKey] : [...openKeys],
    });
  }
  render() {
ddcat1115's avatar
ddcat1115 committed
133
    const { collapsed, location: { pathname } } = this.props;
偏右's avatar
偏右 committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    // Don't show popup menu when it is been collapsed
    const menuProps = collapsed ? {} : {
      openKeys: this.state.openKeys,
    };
    return (
      <Sider
        trigger={null}
        collapsible
        collapsed={collapsed}
        breakpoint="md"
        onCollapse={this.onCollapse}
        width={256}
        className={styles.sider}
      >
        <div className={styles.logo}>
          <Link to="/">
            <img src={logo} alt="logo" />
            <h1>Ant Design Pro</h1>
          </Link>
        </div>
        <Menu
          theme="dark"
          mode="inline"
          {...menuProps}
          onOpenChange={this.handleOpenChange}
ddcat1115's avatar
ddcat1115 committed
159
          selectedKeys={this.getSelectedMenuKeys(pathname)}
160
          style={{ padding: '16px 0', width: '100%' }}
偏右's avatar
偏右 committed
161 162 163 164 165 166 167
        >
          {this.getNavMenuItems(this.menus)}
        </Menu>
      </Sider>
    );
  }
}