refactor: menu component

This commit is contained in:
chenos 2020-12-11 12:34:50 +08:00
parent 5bb0d9f336
commit a604eed44d
7 changed files with 112 additions and 41 deletions

View File

@ -15,6 +15,13 @@ export default defineConfig({
'pathRewrite': { '^/api' : '/api' }, 'pathRewrite': { '^/api' : '/api' },
}, },
}, },
locale: {
default: 'zh-CN',
// antd: false,
// title: false,
baseNavigator: false,
baseSeparator: '-',
},
routes: [ routes: [
{ {
exact: false, exact: false,

View File

@ -0,0 +1,30 @@
import React from 'react';
import { Layout, Menu, Breadcrumb } from 'antd';
import { Link, useLocation } from 'umi';
import Icon from '@/components/icons';
function pathcamp(path1: string, path2: string) {
if (path1 === path2) {
return true;
}
return path1.indexOf(`${path2}/`) === 0;
}
export default (props: any) => {
const { items = [], ...restProps } = props;
const location = useLocation();
let paths = items.map(item => item.path);
return (
<Menu
defaultSelectedKeys={paths.filter(path => pathcamp(location.pathname, path)).concat(location.pathname)}
defaultOpenKeys={paths.filter(path => pathcamp(location.pathname, path)).concat(location.pathname)}
{...restProps}
>
{items.map(item => (
<Menu.Item key={item.path}>
<Link to={item.path}><Icon type={item.icon}/> {item.title}</Link>
</Menu.Item>
))}
</Menu>
);
};

View File

@ -0,0 +1,33 @@
import React from 'react';
import { Layout, Menu, Dropdown, Avatar } from 'antd';
import './style.less';
import { history, Link, request, useModel } from 'umi';
import { ProfileOutlined, LogoutOutlined, UserOutlined, CodeOutlined } from '@ant-design/icons';
import Icon from '@/components/icons';
const overlay = (
<Menu>
<Menu.Item disabled><ProfileOutlined /> </Menu.Item>
<Menu.Divider></Menu.Divider>
<Menu.Item onClick={async () => {
await request('/users:logout');
localStorage.removeItem('NOCOBASE_TOKEN');
(window as any).routesReload();
history.push('/login');;
// window.location.href = '/login';
}}><LogoutOutlined/> 退</Menu.Item>
</Menu>
);
export default (props: any) => {
const { initialState = {}, loading, error, refresh, setInitialState } = useModel('@@initialState');
return (
<div className={'avatar-dropdown-wrapper'}>
<Dropdown overlay={overlay} placement="bottomRight">
<span style={{display: 'block'}} className="dropdown-link" onClick={e => e.preventDefault()}>
<Avatar size={'small'} icon={<UserOutlined/>} style={{marginRight: 5}}/> {initialState.currentUser.nickname}
</span>
</Dropdown>
</div>
);
};

View File

@ -0,0 +1,13 @@
.avatar-dropdown-wrapper {
position: absolute;
right: 0;
color: rgba(255, 255, 255, 0.65);
&:hover {
color: #fff;
background-color: rgba(255, 255, 255, 0.1);
}
.dropdown-link {
padding-left: 20px;
padding-right: 20px;
}
}

View File

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import { Layout, Menu, Breadcrumb } from 'antd'; import { Layout, Breadcrumb } from 'antd';
import { Link } from 'umi'; import { Link } from 'umi';
import './style.less'; import './style.less';
import Icon from '@/components/icons'; import Menu from '@/components/menu';
export function SideMenuLayout(props: any) { export function SideMenuLayout(props: any) {
const { menu = [] } = props.page; const { menu = [] } = props.page;
@ -10,13 +10,7 @@ export function SideMenuLayout(props: any) {
return ( return (
<Layout style={{height: 'calc(100vh - 48px)'}}> <Layout style={{height: 'calc(100vh - 48px)'}}>
<Layout.Sider className={'nb-sider'} theme={'light'}> <Layout.Sider className={'nb-sider'} theme={'light'}>
<Menu mode={'inline'} defaultSelectedKeys={['2']}> <Menu items={menu} mode={'inline'}/>
{menu.map(item => (
<Menu.Item key={item.path}>
<Link to={item.path}><Icon type={item.icon}/> {item.title}</Link>
</Menu.Item>
))}
</Menu>
</Layout.Sider> </Layout.Sider>
<Layout.Content> <Layout.Content>
{props.children} {props.children}

View File

@ -1,45 +1,20 @@
import React from 'react'; import React from 'react';
import { Layout, Menu, Dropdown, Avatar } from 'antd'; import { Layout, Dropdown, Avatar } from 'antd';
import './style.less'; import './style.less';
import { history, Link, request, useModel } from 'umi'; import { history, Link, request, useModel } from 'umi';
import { UserOutlined } from '@ant-design/icons'; import { UserOutlined, CodeOutlined } from '@ant-design/icons';
import Icon from '@/components/icons'; import AvatarDropdown from '../AvatarDropdown';
import Menu from '@/components/menu';
const overlay = (
<Menu>
<Menu.Item disabled></Menu.Item>
<Menu.Divider></Menu.Divider>
<Menu.Item onClick={async () => {
await request('/users:logout');
localStorage.removeItem('NOCOBASE_TOKEN');
(window as any).routesReload();
history.push('/login');;
// window.location.href = '/login';
}}>退</Menu.Item>
</Menu>
);
export function TopMenuLayout(props: any) { export function TopMenuLayout(props: any) {
const { menu = [] } = props.page; const { menu = [] } = props.page;
const { initialState = {}, loading, error, refresh, setInitialState } = useModel('@@initialState');
return ( return (
<Layout style={{ height: '100vh' }}> <Layout style={{ height: '100vh' }}>
<Layout.Header style={{height: 48, lineHeight: '48px', padding: 0}} className="nb-header"> <Layout.Header style={{height: 48, lineHeight: '48px', padding: 0}} className="nb-header">
<div className="logo" style={{width: 200, height: 20, float: 'left'}}/> <div className="logo" style={{width: 200, height: 20, float: 'left'}}><CodeOutlined /> NocoBase</div>
<Menu style={{float: 'left'}} theme="dark" mode="horizontal" defaultSelectedKeys={['2']}> <Menu items={menu} className={'noco-top-menu'} style={{float: 'left'}} theme="dark" mode="horizontal">
{menu.map(item => (
<Menu.Item key={item.path}>
<Link to={item.path}><Icon type={item.icon}/>{item.title}</Link>
</Menu.Item>
))}
</Menu> </Menu>
<div className={'noco-user'} style={{position: 'absolute', right: 24, color: 'rgba(255, 255, 255, 0.65)'}}> <AvatarDropdown/>
<Dropdown overlay={overlay} placement="bottomRight">
<span className="nbui-dropdown-link" onClick={e => e.preventDefault()}>
<Avatar size={'small'} icon={<UserOutlined/>} style={{marginRight: 5}}/> {initialState.currentUser.nickname}
</span>
</Dropdown>
</div>
</Layout.Header> </Layout.Header>
<Layout.Content> <Layout.Content>
{props.children} {props.children}

View File

@ -0,0 +1,19 @@
.logo {
// font-family: 'Michroma', sans-serif;
color: rgba(255, 255, 255, 0.8);
padding-left: 28px;
font-size: 18px;
letter-spacing: 2px;
font-weight: 300;
}
body {
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.noco-top-menu.ant-menu-dark.ant-menu-horizontal > .ant-menu-item:hover,
.noco-top-menu.ant-menu.ant-menu-dark .ant-menu-item-selected,
.noco-top-menu.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected {
background-color: rgba(255, 255, 255, 0.1);
}