import React, { PureComponent } from 'react';
import { Layout, Menu, Icon } from 'antd';
import { Link } from 'dva/router';
import styles from './index.less';
const { Sider } = Layout;
const { SubMenu } = Menu;
// Allow menu.js config icon as string or ReactNode
// icon: 'setting',
// icon: 'http://demo.com/icon.png',
// icon: ,
const getIcon = (icon) => {
if (typeof icon === 'string' && icon.indexOf('http') === 0) {
return ;
}
if (typeof icon === 'string') {
return ;
}
return icon;
};
export default class SiderMenu extends PureComponent {
constructor(props) {
super(props);
this.menus = props.menuData;
this.state = {
openKeys: this.getDefaultCollapsedSubMenus(props),
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.location.pathname !== this.props.location.pathname) {
this.setState({
openKeys: this.getDefaultCollapsedSubMenus(nextProps),
});
}
}
getDefaultCollapsedSubMenus(props) {
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));
});
if (currentMenuSelectedKeys.length === 0) {
return ['dashboard'];
}
return currentMenuSelectedKeys;
}
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);
}
});
return keys;
}
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(/^\//, '').replace(/\/$/, ''));
});
}
/**
* 判断是否是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 (
{icon}{name}
);
}
return (
{ this.props.onCollapse(true); } : undefined}
>
{icon}{name}
);
}
/**
* get SubMenu or Item
*/
getSubMenuOrItem=(item) => {
if (item.children && item.children.some(child => child.name)) {
return (
{getIcon(item.icon)}
{item.name}
) : item.name
}
key={item.key || item.path}
>
{this.getNavMenuItems(item.children)}
);
} else {
return (
{this.getMenuItemPath(item)}
);
}
}
/**
* 获得菜单子节点
* @memberof SiderMenu
*/
getNavMenuItems = (menusData) => {
if (!menusData) {
return [];
}
return menusData.map((item) => {
if (!item.name || item.hideInMenu) {
return null;
}
const ItemDom = this.getSubMenuOrItem(item);
return this.checkPermissionItem(item.authority, ItemDom);
});
}
// 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;
}
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() {
const { logo, collapsed, location: { pathname }, onCollapse } = 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(pathname);
if (!selectedKeys.length) {
selectedKeys = [openKeys[openKeys.length - 1]];
}
return (
Ant Design Pro
);
}
}