refactor: menu component
This commit is contained in:
parent
5bb0d9f336
commit
a604eed44d
@ -15,6 +15,13 @@ export default defineConfig({
|
||||
'pathRewrite': { '^/api' : '/api' },
|
||||
},
|
||||
},
|
||||
locale: {
|
||||
default: 'zh-CN',
|
||||
// antd: false,
|
||||
// title: false,
|
||||
baseNavigator: false,
|
||||
baseSeparator: '-',
|
||||
},
|
||||
routes: [
|
||||
{
|
||||
exact: false,
|
||||
|
30
packages/app/src/components/menu/index.tsx
Normal file
30
packages/app/src/components/menu/index.tsx
Normal 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>
|
||||
);
|
||||
};
|
33
packages/app/src/components/pages/AvatarDropdown/index.tsx
Normal file
33
packages/app/src/components/pages/AvatarDropdown/index.tsx
Normal 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>
|
||||
);
|
||||
};
|
13
packages/app/src/components/pages/AvatarDropdown/style.less
Normal file
13
packages/app/src/components/pages/AvatarDropdown/style.less
Normal 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;
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { Layout, Menu, Breadcrumb } from 'antd';
|
||||
import { Layout, Breadcrumb } from 'antd';
|
||||
import { Link } from 'umi';
|
||||
import './style.less';
|
||||
import Icon from '@/components/icons';
|
||||
import Menu from '@/components/menu';
|
||||
|
||||
export function SideMenuLayout(props: any) {
|
||||
const { menu = [] } = props.page;
|
||||
@ -10,13 +10,7 @@ export function SideMenuLayout(props: any) {
|
||||
return (
|
||||
<Layout style={{height: 'calc(100vh - 48px)'}}>
|
||||
<Layout.Sider className={'nb-sider'} theme={'light'}>
|
||||
<Menu mode={'inline'} defaultSelectedKeys={['2']}>
|
||||
{menu.map(item => (
|
||||
<Menu.Item key={item.path}>
|
||||
<Link to={item.path}><Icon type={item.icon}/> {item.title}</Link>
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
<Menu items={menu} mode={'inline'}/>
|
||||
</Layout.Sider>
|
||||
<Layout.Content>
|
||||
{props.children}
|
||||
|
@ -1,45 +1,20 @@
|
||||
import React from 'react';
|
||||
import { Layout, Menu, Dropdown, Avatar } from 'antd';
|
||||
import { Layout, Dropdown, Avatar } from 'antd';
|
||||
import './style.less';
|
||||
import { history, Link, request, useModel } from 'umi';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
import Icon from '@/components/icons';
|
||||
|
||||
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>
|
||||
);
|
||||
import { UserOutlined, CodeOutlined } from '@ant-design/icons';
|
||||
import AvatarDropdown from '../AvatarDropdown';
|
||||
import Menu from '@/components/menu';
|
||||
|
||||
export function TopMenuLayout(props: any) {
|
||||
const { menu = [] } = props.page;
|
||||
const { initialState = {}, loading, error, refresh, setInitialState } = useModel('@@initialState');
|
||||
return (
|
||||
<Layout style={{ height: '100vh' }}>
|
||||
<Layout.Header style={{height: 48, lineHeight: '48px', padding: 0}} className="nb-header">
|
||||
<div className="logo" style={{width: 200, height: 20, float: 'left'}}/>
|
||||
<Menu style={{float: 'left'}} theme="dark" mode="horizontal" defaultSelectedKeys={['2']}>
|
||||
{menu.map(item => (
|
||||
<Menu.Item key={item.path}>
|
||||
<Link to={item.path}><Icon type={item.icon}/>{item.title}</Link>
|
||||
</Menu.Item>
|
||||
))}
|
||||
<div className="logo" style={{width: 200, height: 20, float: 'left'}}><CodeOutlined /> NocoBase</div>
|
||||
<Menu items={menu} className={'noco-top-menu'} style={{float: 'left'}} theme="dark" mode="horizontal">
|
||||
</Menu>
|
||||
<div className={'noco-user'} style={{position: 'absolute', right: 24, color: 'rgba(255, 255, 255, 0.65)'}}>
|
||||
<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>
|
||||
<AvatarDropdown/>
|
||||
</Layout.Header>
|
||||
<Layout.Content>
|
||||
{props.children}
|
||||
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user