feat: update menu in the layout

1. Update the menu style to adjust the global nav display
2. Update the menu open keys when the url change: the menu will auto open the current url's father menu

Change-Id: I567db87e369264d9b1d1372332868267b478cf46
This commit is contained in:
Jingwei.Zhang 2022-11-09 12:30:28 +08:00
parent 985c03af95
commit e3543ed1b5
3 changed files with 108 additions and 20 deletions

View File

@ -177,11 +177,11 @@
} }
.logo { .logo {
// margin: @size-medium 38px;
float: left; float: left;
width: 190px;
height: @header-height; height: @header-height;
padding: 0 46px;
line-height: @header-height; line-height: @header-height;
text-align: center;
img { img {
height: 30px; height: 30px;

View File

@ -17,6 +17,7 @@ import { Menu, Tooltip } from 'antd';
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'; import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import { toJS } from 'mobx'; import { toJS } from 'mobx';
import { isString, isEqual } from 'lodash';
import classnames from 'classnames'; import classnames from 'classnames';
import { getPath } from 'utils/route-map'; import { getPath } from 'utils/route-map';
import styles from './index.less'; import styles from './index.less';
@ -34,6 +35,18 @@ export class LayoutMenu extends Component {
this.maxTitleLength = 17; this.maxTitleLength = 17;
} }
componentDidMount() {
this.init();
}
componentDidUpdate(prevProps) {
const { pathname } = this.props;
const { pathname: prevPathname } = prevProps;
if (prevPathname && pathname !== prevPathname) {
this.updateOpenKeysByRoute();
}
}
get menu() { get menu() {
return this.props.menu || []; return this.props.menu || [];
} }
@ -51,6 +64,13 @@ export class LayoutMenu extends Component {
return getPath({ key: realName, params, query }); return getPath({ key: realName, params, query });
} }
getOpenKeysByRoute() {
const { currentRoutes } = this.props;
const selectedKeys = this.getSelectedKeys(currentRoutes);
const currentOpenKeys = this.getCurrentOpenKeys(selectedKeys);
return currentOpenKeys;
}
get rootStore() { get rootStore() {
return this.props.rootStore; return this.props.rootStore;
} }
@ -78,7 +98,7 @@ export class LayoutMenu extends Component {
if (collapsed) { if (collapsed) {
const target = (e && e.target) || null; const target = (e && e.target) || null;
const className = target ? target.className || '' : ''; const className = target ? target.className || '' : '';
if (className.indexOf('trigger') < 0) { if (isString(className) && !className.includes('trigger')) {
this.setState({ this.setState({
hover: true, hover: true,
}); });
@ -107,7 +127,7 @@ export class LayoutMenu extends Component {
const { collapsed, hover } = this.state; const { collapsed, hover } = this.state;
if (collapsed && !hover) { if (collapsed && !hover) {
return ( return (
<Menu.Item key={item.key} className={styles['menu-item']}> <Menu.Item key={item.key} className={styles['menu-item-collapsed']}>
{item.icon} {item.icon}
</Menu.Item> </Menu.Item>
); );
@ -160,23 +180,56 @@ export class LayoutMenu extends Component {
); );
}; };
getFirstLevelKeys = (selectedKeys) => {
const fathers = this.menu.filter((it) => {
const { children = [] } = it;
if (!children.length) {
return selectedKeys.includes(it.key);
}
let hasFather = children.find((c) => selectedKeys.includes(c.key));
if (hasFather) {
return true;
}
children.forEach((c) => {
const { children: cc = [] } = c;
const child = cc.find((ccc) => selectedKeys.includes(ccc.key));
if (child) {
hasFather = true;
}
});
return hasFather;
});
return fathers.map((f) => f.key);
};
getSelectedKeysForMenu = (selectedKeys) => {
const { collapsed, hover } = this.state;
if (!collapsed || hover) {
return selectedKeys;
}
return this.getFirstLevelKeys(selectedKeys);
};
getCurrentOpenKeys = (selectedKeys) => {
return this.getFirstLevelKeys(selectedKeys);
};
renderMenu = (selectedKeys = []) => { renderMenu = (selectedKeys = []) => {
const { openKeys } = this.state; const { collapsed } = this.state;
const { openKeys: defaultOpenKeys } = this.rootStore; const { openKeys } = this.rootStore;
const newOpenKeys =
openKeys.length === 0 ? toJS(defaultOpenKeys) : openKeys;
const menuItems = this.menu const menuItems = this.menu
.map((item) => this.renderMenuItem(item)) .map((item) => this.renderMenuItem(item))
.filter((it) => it !== null); .filter((it) => it !== null);
const newSelectedKeys = this.getSelectedKeysForMenu(selectedKeys);
return ( return (
<Menu <Menu
theme="dark" theme="dark"
mode="inline" mode="inline"
className={styles.menu} className={collapsed ? styles['menu-collapsed'] : styles.menu}
defaultSelectedKeys={selectedKeys} defaultSelectedKeys={newSelectedKeys}
selectedKeys={selectedKeys} selectedKeys={newSelectedKeys}
openKeys={newOpenKeys} openKeys={openKeys}
onOpenChange={this.onOpenChange} onOpenChange={this.onOpenChange}
> >
{menuItems} {menuItems}
@ -192,9 +245,13 @@ export class LayoutMenu extends Component {
); );
const latestOpenKey = openKeys.find((key) => oldKeys.indexOf(key) === -1); const latestOpenKey = openKeys.find((key) => oldKeys.indexOf(key) === -1);
const newKeys = latestOpenKey ? [latestOpenKey] : []; const newKeys = latestOpenKey ? [latestOpenKey] : [];
this.rootStore.updateOpenKeys(newKeys); this.updateOpenKeys(newKeys);
};
updateOpenKeys = (keys) => {
this.rootStore.updateOpenKeys(keys);
this.setState({ this.setState({
openKeys: newKeys, openKeys: keys,
}); });
}; };
@ -211,6 +268,19 @@ export class LayoutMenu extends Component {
return []; return [];
}; };
updateOpenKeysByRoute() {
const currentOpenKeys = this.getOpenKeysByRoute();
const { openKeys: defaultOpenKeys } = this.rootStore;
if (!isEqual(currentOpenKeys, toJS(defaultOpenKeys))) {
this.init();
}
}
init() {
const currentOpenKeys = this.getOpenKeysByRoute();
this.updateOpenKeys(currentOpenKeys);
}
renderTrigger() { renderTrigger() {
const { collapsed } = this.state; const { collapsed } = this.state;
// const triggerIcon = <MenuUnfoldOutlined />; // const triggerIcon = <MenuUnfoldOutlined />;

View File

@ -19,7 +19,7 @@
.header-collapsed { .header-collapsed {
&:extend(.header); &:extend(.header);
padding-left: 88px; padding-left: 40px;
} }
.logo { .logo {
@ -252,16 +252,24 @@
left: 0; left: 0;
z-index: 1; z-index: 1;
width: 230px; width: 230px;
padding-top: 10px;
background-color: @sider-background; background-color: @sider-background;
transition: all 0.2s; transition: all 0.2s;
} }
.base-layout-sider-collapsed { .base-layout-sider-collapsed {
width: 88px; width: 40px;
transition: all 0.2s; transition: all 0.2s;
// &:hover {
// width: 220px; .menu-collapsed {
// } padding-right: 0;
padding-left: 0;
.menu-item-collapsed {
padding-left: 12px !important;
text-overflow: inherit;
}
}
} }
.base-layout-right { .base-layout-right {
@ -273,12 +281,22 @@
} }
.base-layout-right-collapsed { .base-layout-right-collapsed {
left: 88px; left: 40px;
} }
.base-layout-sider-hover { .base-layout-sider-hover {
width: 230px; width: 230px;
transition: all 0.2s; transition: all 0.2s;
.menu-collapsed {
padding-right: 14px;
padding-left: 14px;
.menu-item-collapsed {
padding-left: 48px !important;
text-overflow: ellipsis;
}
}
} }
.notice { .notice {