mirror of
https://github.com/zuiidea/antd-admin
synced 2026-10-24 09:16:53 +00:00
handle FileName
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Breadcrumb, Icon } from 'antd'
|
||||
import styles from './Bread.less'
|
||||
import { menu } from '../../utils'
|
||||
|
||||
let pathSet = []
|
||||
const getPathSet = function (menuArray, parentPath) {
|
||||
parentPath = parentPath || '/'
|
||||
menuArray.forEach(item => {
|
||||
pathSet[(parentPath + item.key).replace(/\//g, '-').hyphenToHump()] = {
|
||||
path: parentPath + item.key,
|
||||
name: item.name,
|
||||
icon: item.icon || '',
|
||||
clickable: item.clickable === undefined,
|
||||
}
|
||||
if (item.child) {
|
||||
getPathSet(item.child, `${parentPath}${item.key}/`)
|
||||
}
|
||||
})
|
||||
}
|
||||
getPathSet(menu)
|
||||
|
||||
function Bread ({ location }) {
|
||||
let pathNames = []
|
||||
location.pathname.substr(1).split('/').forEach((item, key) => {
|
||||
if (key > 0) {
|
||||
pathNames.push((`${pathNames[key - 1]}-${item}`).hyphenToHump())
|
||||
} else {
|
||||
pathNames.push((`-${item}`).hyphenToHump())
|
||||
}
|
||||
})
|
||||
const breads = pathNames.map((item, key) => {
|
||||
if (!(item in pathSet)) {
|
||||
item = 'Dashboard'
|
||||
}
|
||||
return (
|
||||
<Breadcrumb.Item key={key} {...((pathNames.length - 1 === key) || !pathSet[item].clickable) ? '' : { href: `#${pathSet[item].path}` }}>
|
||||
{pathSet[item].icon
|
||||
? <Icon type={pathSet[item].icon} />
|
||||
: ''}
|
||||
<span>{pathSet[item].name}</span>
|
||||
</Breadcrumb.Item>
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={styles.bread}>
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item href="/"><Icon type="home" />
|
||||
<span>主页</span>
|
||||
</Breadcrumb.Item>
|
||||
{breads}
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Bread.propTypes = {
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Bread
|
||||
@@ -1,8 +0,0 @@
|
||||
@import "../vars.less";
|
||||
|
||||
.bread {
|
||||
height: 64px;
|
||||
line-height: 64px;
|
||||
padding: 0 24px;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import React from 'react'
|
||||
import styles from './Footer.less'
|
||||
import { config } from '../../utils'
|
||||
|
||||
const Footer = () => <div className={styles.footer}>
|
||||
{config.footerText}
|
||||
</div>
|
||||
|
||||
export default Footer
|
||||
@@ -1,12 +0,0 @@
|
||||
@import "../vars.less";
|
||||
|
||||
.footer {
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
background: #fff;
|
||||
box-shadow: @shadow-2;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Menu, Icon, Popover } from 'antd'
|
||||
import styles from './Header.less'
|
||||
import Menus from './Menu'
|
||||
|
||||
const SubMenu = Menu.SubMenu
|
||||
|
||||
function Header ({ user, logout, switchSider, siderFold, isNavbar, menuPopoverVisible, location, switchMenuPopover, navOpenKeys, changeOpenKeys }) {
|
||||
let handleClickMenu = e => e.key === 'logout' && logout()
|
||||
const menusProps = {
|
||||
siderFold: false,
|
||||
darkTheme: false,
|
||||
isNavbar,
|
||||
handleClickNavMenu: switchMenuPopover,
|
||||
location,
|
||||
navOpenKeys,
|
||||
changeOpenKeys,
|
||||
}
|
||||
return (
|
||||
<div className={styles.header}>
|
||||
{isNavbar
|
||||
? <Popover placement="bottomLeft" onVisibleChange={switchMenuPopover} visible={menuPopoverVisible} overlayClassName={styles.popovermenu} trigger="click" content={<Menus {...menusProps} />}>
|
||||
<div className={styles.button}>
|
||||
<Icon type="bars" />
|
||||
</div>
|
||||
</Popover>
|
||||
: <div className={styles.button} onClick={switchSider}>
|
||||
<Icon type={siderFold ? 'menu-unfold' : 'menu-fold'} />
|
||||
</div>}
|
||||
<div className={styles.rightWarpper}>
|
||||
<div className={styles.button}>
|
||||
<Icon type="mail" />
|
||||
</div>
|
||||
<Menu mode="horizontal" onClick={handleClickMenu}>
|
||||
<SubMenu style={{
|
||||
float: 'right',
|
||||
}} title={< span > <Icon type="user" />
|
||||
{user.name} < /span>}
|
||||
>
|
||||
<Menu.Item key="logout">
|
||||
<a>注销</a>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
user: PropTypes.object,
|
||||
logout: PropTypes.func,
|
||||
switchSider: PropTypes.func,
|
||||
siderFold: PropTypes.bool,
|
||||
isNavbar: PropTypes.bool,
|
||||
menuPopoverVisible: PropTypes.bool,
|
||||
location: PropTypes.object,
|
||||
switchMenuPopover: PropTypes.func,
|
||||
navOpenKeys: PropTypes.array,
|
||||
changeOpenKeys: PropTypes.func,
|
||||
}
|
||||
|
||||
export default Header
|
||||
@@ -1,57 +0,0 @@
|
||||
@import "../vars.less";
|
||||
|
||||
.header {
|
||||
:global .ant-menu-horizontal {
|
||||
& > .ant-menu-submenu {
|
||||
float: right;
|
||||
}
|
||||
border: none;
|
||||
display: inline-block;
|
||||
}
|
||||
box-shadow: @shadow-2;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 47px;
|
||||
background-color: #fff;
|
||||
|
||||
.rightWarpper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 47px;
|
||||
height: 47px;
|
||||
line-height: 47px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: @transition-ease-in;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
background-color: fade(@primary-color, 15%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popovermenu {
|
||||
width: 280px;
|
||||
margin-left: 6px;
|
||||
|
||||
:global .ant-popover-inner-content {
|
||||
padding: 0;
|
||||
|
||||
.ant-menu-inline .ant-menu-item,
|
||||
.ant-menu-vertical .ant-menu-item {
|
||||
border-right: 0;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.ant-menu-inline .ant-menu-item-selected,
|
||||
.ant-menu-inline .ant-menu-selected {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
@import "../vars.less";
|
||||
|
||||
.layout {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
|
||||
&.withnavbar {
|
||||
.main {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.fold {
|
||||
.sider {
|
||||
width: 42px;
|
||||
|
||||
.logo {
|
||||
img {
|
||||
width: 28px;
|
||||
margin: 6px 7px;
|
||||
}
|
||||
}
|
||||
|
||||
:global {
|
||||
.ant-menu-root {
|
||||
width: 100%;
|
||||
overflow: visible;
|
||||
|
||||
& > .ant-menu-item {
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
|
||||
.anticon {
|
||||
font-size: 14px;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& > .ant-menu-submenu {
|
||||
& > .ant-menu-submenu-title {
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
|
||||
.anticon {
|
||||
font-size: 14px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-left: 42px;
|
||||
}
|
||||
}
|
||||
|
||||
.sider {
|
||||
width: 224px;
|
||||
background: #3e3e3e;
|
||||
position: absolute;
|
||||
overflow: visible;
|
||||
padding-bottom: 24px;
|
||||
height: 100vh;
|
||||
transition: @transition-ease-out;
|
||||
box-shadow: @shadow-1;
|
||||
z-index: 520;
|
||||
color: #999;
|
||||
|
||||
&.light {
|
||||
background: #fff;
|
||||
|
||||
.switchtheme {
|
||||
background: #fff;
|
||||
border-top: solid 1px #f8f8f8;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
cursor: pointer;
|
||||
margin: 28px 0;
|
||||
transition: @transition-ease-out;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
margin-right: 8px;
|
||||
transition: @transition-ease-out;
|
||||
}
|
||||
|
||||
span {
|
||||
vertical-align: text-bottom;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.anticon {
|
||||
transition: @transition-ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
.switchtheme {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 48px;
|
||||
background-color: @dark-half;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 16px 0 24px;
|
||||
overflow: hidden;
|
||||
z-index: 1000;
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:global {
|
||||
.anticon {
|
||||
min-width: 14px;
|
||||
margin-right: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:global {
|
||||
.ant-menu-dark,
|
||||
.ant-menu-dark .ant-menu-sub {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.ant-menu-root {
|
||||
height: ~"calc(100vh - 144px)";
|
||||
overflow-x: hidden;
|
||||
border-right: none;
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
&.ant-menu-vertical {
|
||||
.ant-menu-sub {
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.ant-menu-submenu-active {
|
||||
.ant-menu-sub {
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
transition: @transition-ease-out;
|
||||
|
||||
.ant-menu-item,
|
||||
.ant-menu-submenu-title {
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-left: 224px;
|
||||
overflow: auto;
|
||||
height: 100vh;
|
||||
transition: @transition-ease-out;
|
||||
|
||||
:global {
|
||||
.content-inner {
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
box-shadow: @shadow-1;
|
||||
min-height: e("calc(100vh - 184px)");
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 24px;
|
||||
}
|
||||
|
||||
.content {
|
||||
min-height: e("calc(100vh - 184px)");
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:global .ant-menu-dark {
|
||||
color: #999;
|
||||
background-color: #3e3e3e;
|
||||
|
||||
.ant-menu-submenu-title:hover,
|
||||
.ant-menu-submenu:hover {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
.ant-menu-sub {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.ant-menu-submenu-selected {
|
||||
color: @primary-color;
|
||||
|
||||
&:not(.ant-menu-submenu-open) {
|
||||
background-color: @dark-half;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu-item,
|
||||
.ant-menu-submenu-title {
|
||||
& > a {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
&:hover > a {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.ant-menu-inline {
|
||||
.ant-menu-item-selected {
|
||||
background-color: @dark-half;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu-item-selected {
|
||||
color: @primary-color;
|
||||
background-color: @dark-half;
|
||||
|
||||
& > a {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: @dark-half;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.spin {
|
||||
:global .ant-spin-container {
|
||||
height: 100vh;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.layout {
|
||||
.main {
|
||||
.container {
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.bread {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.content {
|
||||
min-height: e("calc(100vh - 160px)");
|
||||
}
|
||||
|
||||
:global {
|
||||
.content-inner {
|
||||
padding: 12px;
|
||||
min-height: e("calc(100vh - 160px)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Menu, Icon } from 'antd'
|
||||
import { Link } from 'dva/router'
|
||||
import { menu } from '../../utils'
|
||||
|
||||
const topMenus = menu.map(item => item.key)
|
||||
const getMenus = function (menuArray, siderFold, parentPath = '/') {
|
||||
return menuArray.map(item => {
|
||||
const linkTo = parentPath + item.key
|
||||
if (item.child) {
|
||||
return (
|
||||
<Menu.SubMenu key={linkTo} title={<span>{item.icon ? <Icon type={item.icon} /> : ''}{siderFold && topMenus.indexOf(item.key) >= 0 ? '' : item.name}</span>}>
|
||||
{getMenus(item.child, siderFold, `${linkTo}/`)}
|
||||
</Menu.SubMenu>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Menu.Item key={linkTo}>
|
||||
|
||||
<Link to={linkTo}>
|
||||
{item.icon ? <Icon type={item.icon} /> : ''}
|
||||
{siderFold && topMenus.indexOf(item.key) >= 0 ? '' : item.name}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function Menus ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKeys, changeOpenKeys }) {
|
||||
const menuItems = getMenus(menu, siderFold)
|
||||
|
||||
const getAncestorKeys = (key) => {
|
||||
const map = {
|
||||
'/navigation/navigation2': ['/navigation'],
|
||||
}
|
||||
return map[key] || []
|
||||
}
|
||||
|
||||
const onOpenChange = (openKeys) => {
|
||||
const latestOpenKey = openKeys.find(key => !(navOpenKeys.indexOf(key) > -1))
|
||||
const latestCloseKey = navOpenKeys.find(key => !(openKeys.indexOf(key) > -1))
|
||||
let nextOpenKeys = []
|
||||
if (latestOpenKey) {
|
||||
nextOpenKeys = getAncestorKeys(latestOpenKey).concat(latestOpenKey)
|
||||
}
|
||||
if (latestCloseKey) {
|
||||
nextOpenKeys = getAncestorKeys(latestCloseKey)
|
||||
}
|
||||
changeOpenKeys(nextOpenKeys)
|
||||
}
|
||||
// 菜单栏收起时,不能操作openKeys
|
||||
let menuProps = !siderFold ? {
|
||||
onOpenChange,
|
||||
openKeys: navOpenKeys,
|
||||
} : {}
|
||||
|
||||
return (
|
||||
<Menu
|
||||
{...menuProps}
|
||||
mode={siderFold ? 'vertical' : 'inline'}
|
||||
theme={darkTheme ? 'dark' : 'light'}
|
||||
onClick={handleClickNavMenu}
|
||||
defaultSelectedKeys={[location.pathname !== '/' ? location.pathname : '/dashboard']}
|
||||
>
|
||||
{menuItems}
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
|
||||
Menus.propTypes = {
|
||||
siderFold: PropTypes.bool,
|
||||
darkTheme: PropTypes.bool,
|
||||
location: PropTypes.object,
|
||||
isNavbar: PropTypes.bool,
|
||||
handleClickNavMenu: PropTypes.func,
|
||||
navOpenKeys: PropTypes.array,
|
||||
changeOpenKeys: PropTypes.func,
|
||||
}
|
||||
|
||||
export default Menus
|
||||
@@ -1,39 +0,0 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Icon, Switch } from 'antd'
|
||||
import styles from './Layout.less'
|
||||
import { config } from '../../utils'
|
||||
import Menus from './Menu'
|
||||
|
||||
function Sider ({ siderFold, darkTheme, location, changeTheme, navOpenKeys, changeOpenKeys }) {
|
||||
const menusProps = {
|
||||
siderFold,
|
||||
darkTheme,
|
||||
location,
|
||||
navOpenKeys,
|
||||
changeOpenKeys,
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.logo}>
|
||||
<img alt={'logo'} src={config.logoSrc} />
|
||||
{siderFold ? '' : <span>{config.logoText}</span>}
|
||||
</div>
|
||||
<Menus {...menusProps} />
|
||||
{!siderFold ? <div className={styles.switchtheme}>
|
||||
<span><Icon type="bulb" />切换主题</span>
|
||||
<Switch onChange={changeTheme} defaultChecked={darkTheme} checkedChildren="黑" unCheckedChildren="白" />
|
||||
</div> : ''}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Sider.propTypes = {
|
||||
siderFold: PropTypes.bool,
|
||||
darkTheme: PropTypes.bool,
|
||||
location: PropTypes.object,
|
||||
changeTheme: PropTypes.func,
|
||||
navOpenKeys: PropTypes.array,
|
||||
changeOpenKeys: PropTypes.func,
|
||||
}
|
||||
|
||||
export default Sider
|
||||
@@ -1 +0,0 @@
|
||||
@import "../vars.less";
|
||||
@@ -1,8 +0,0 @@
|
||||
import Header from './Header'
|
||||
import Menu from './Menu'
|
||||
import Bread from './Bread'
|
||||
import Sider from './Sider'
|
||||
import Footer from './Footer'
|
||||
import styles from './Layout.less'
|
||||
|
||||
export { Header, Menu, Bread, Sider, Footer, styles }
|
||||
@@ -3,12 +3,12 @@ import DropOption from './DropOption'
|
||||
import Iconfont from './Iconfont'
|
||||
import Search from './Search'
|
||||
import Editor from './Editor'
|
||||
import * as Layout from './Layout/index.js'
|
||||
// import * as Layout from './Layout/index.js'
|
||||
|
||||
import layer from './layer'
|
||||
|
||||
export {
|
||||
Layout,
|
||||
// Layout,
|
||||
DataTable,
|
||||
DropOption,
|
||||
Iconfont,
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Breadcrumb, Icon } from 'antd'
|
||||
import styles from './Bread.less'
|
||||
import { menu } from '../../utils'
|
||||
|
||||
let pathSet = []
|
||||
const getPathSet = function (menuArray, parentPath) {
|
||||
parentPath = parentPath || '/'
|
||||
menuArray.forEach(item => {
|
||||
pathSet[(parentPath + item.key).replace(/\//g, '-').hyphenToHump()] = {
|
||||
path: parentPath + item.key,
|
||||
name: item.name,
|
||||
icon: item.icon || '',
|
||||
clickable: item.clickable === undefined,
|
||||
}
|
||||
if (item.child) {
|
||||
getPathSet(item.child, `${parentPath}${item.key}/`)
|
||||
}
|
||||
})
|
||||
}
|
||||
getPathSet(menu)
|
||||
|
||||
function Bread ({ location }) {
|
||||
let pathNames = []
|
||||
location.pathname.substr(1).split('/').forEach((item, key) => {
|
||||
if (key > 0) {
|
||||
pathNames.push((`${pathNames[key - 1]}-${item}`).hyphenToHump())
|
||||
} else {
|
||||
pathNames.push((`-${item}`).hyphenToHump())
|
||||
}
|
||||
})
|
||||
const breads = pathNames.map((item, key) => {
|
||||
if (!(item in pathSet)) {
|
||||
item = 'Dashboard'
|
||||
}
|
||||
return (
|
||||
<Breadcrumb.Item key={key} {...((pathNames.length - 1 === key) || !pathSet[item].clickable) ? '' : { href: `#${pathSet[item].path}` }}>
|
||||
{pathSet[item].icon
|
||||
? <Icon type={pathSet[item].icon} />
|
||||
: ''}
|
||||
<span>{pathSet[item].name}</span>
|
||||
</Breadcrumb.Item>
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={styles.bread}>
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item href="/"><Icon type="home" />
|
||||
<span>主页</span>
|
||||
</Breadcrumb.Item>
|
||||
{breads}
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Bread.propTypes = {
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Bread
|
||||
@@ -1,9 +0,0 @@
|
||||
import React from 'react'
|
||||
import styles from './Footer.less'
|
||||
import { config } from '../../utils'
|
||||
|
||||
const Footer = () => <div className={styles.footer}>
|
||||
{config.footerText}
|
||||
</div>
|
||||
|
||||
export default Footer
|
||||
@@ -1,63 +0,0 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Menu, Icon, Popover } from 'antd'
|
||||
import styles from './Header.less'
|
||||
import Menus from './Menu'
|
||||
|
||||
const SubMenu = Menu.SubMenu
|
||||
|
||||
function Header ({ user, logout, switchSider, siderFold, isNavbar, menuPopoverVisible, location, switchMenuPopover, navOpenKeys, changeOpenKeys }) {
|
||||
let handleClickMenu = e => e.key === 'logout' && logout()
|
||||
const menusProps = {
|
||||
siderFold: false,
|
||||
darkTheme: false,
|
||||
isNavbar,
|
||||
handleClickNavMenu: switchMenuPopover,
|
||||
location,
|
||||
navOpenKeys,
|
||||
changeOpenKeys,
|
||||
}
|
||||
return (
|
||||
<div className={styles.header}>
|
||||
{isNavbar
|
||||
? <Popover placement="bottomLeft" onVisibleChange={switchMenuPopover} visible={menuPopoverVisible} overlayClassName={styles.popovermenu} trigger="click" content={<Menus {...menusProps} />}>
|
||||
<div className={styles.button}>
|
||||
<Icon type="bars" />
|
||||
</div>
|
||||
</Popover>
|
||||
: <div className={styles.button} onClick={switchSider}>
|
||||
<Icon type={siderFold ? 'menu-unfold' : 'menu-fold'} />
|
||||
</div>}
|
||||
<div className={styles.rightWarpper}>
|
||||
<div className={styles.button}>
|
||||
<Icon type="mail" />
|
||||
</div>
|
||||
<Menu mode="horizontal" onClick={handleClickMenu}>
|
||||
<SubMenu style={{
|
||||
float: 'right',
|
||||
}} title={< span > <Icon type="user" />
|
||||
{user.name} < /span>}
|
||||
>
|
||||
<Menu.Item key="logout">
|
||||
<a>注销</a>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
user: PropTypes.object,
|
||||
logout: PropTypes.func,
|
||||
switchSider: PropTypes.func,
|
||||
siderFold: PropTypes.bool,
|
||||
isNavbar: PropTypes.bool,
|
||||
menuPopoverVisible: PropTypes.bool,
|
||||
location: PropTypes.object,
|
||||
switchMenuPopover: PropTypes.func,
|
||||
navOpenKeys: PropTypes.array,
|
||||
changeOpenKeys: PropTypes.func,
|
||||
}
|
||||
|
||||
export default Header
|
||||
@@ -1,80 +0,0 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Menu, Icon } from 'antd'
|
||||
import { Link } from 'dva/router'
|
||||
import { menu } from '../../utils'
|
||||
|
||||
const topMenus = menu.map(item => item.key)
|
||||
const getMenus = function (menuArray, siderFold, parentPath = '/') {
|
||||
return menuArray.map(item => {
|
||||
const linkTo = parentPath + item.key
|
||||
if (item.child) {
|
||||
return (
|
||||
<Menu.SubMenu key={linkTo} title={<span>{item.icon ? <Icon type={item.icon} /> : ''}{siderFold && topMenus.indexOf(item.key) >= 0 ? '' : item.name}</span>}>
|
||||
{getMenus(item.child, siderFold, `${linkTo}/`)}
|
||||
</Menu.SubMenu>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Menu.Item key={linkTo}>
|
||||
|
||||
<Link to={linkTo}>
|
||||
{item.icon ? <Icon type={item.icon} /> : ''}
|
||||
{siderFold && topMenus.indexOf(item.key) >= 0 ? '' : item.name}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function Menus ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKeys, changeOpenKeys }) {
|
||||
const menuItems = getMenus(menu, siderFold)
|
||||
|
||||
const getAncestorKeys = (key) => {
|
||||
const map = {
|
||||
'/navigation/navigation2': ['/navigation'],
|
||||
}
|
||||
return map[key] || []
|
||||
}
|
||||
|
||||
const onOpenChange = (openKeys) => {
|
||||
const latestOpenKey = openKeys.find(key => !(navOpenKeys.indexOf(key) > -1))
|
||||
const latestCloseKey = navOpenKeys.find(key => !(openKeys.indexOf(key) > -1))
|
||||
let nextOpenKeys = []
|
||||
if (latestOpenKey) {
|
||||
nextOpenKeys = getAncestorKeys(latestOpenKey).concat(latestOpenKey)
|
||||
}
|
||||
if (latestCloseKey) {
|
||||
nextOpenKeys = getAncestorKeys(latestCloseKey)
|
||||
}
|
||||
changeOpenKeys(nextOpenKeys)
|
||||
}
|
||||
// 菜单栏收起时,不能操作openKeys
|
||||
let menuProps = !siderFold ? {
|
||||
onOpenChange,
|
||||
openKeys: navOpenKeys,
|
||||
} : {}
|
||||
|
||||
return (
|
||||
<Menu
|
||||
{...menuProps}
|
||||
mode={siderFold ? 'vertical' : 'inline'}
|
||||
theme={darkTheme ? 'dark' : 'light'}
|
||||
onClick={handleClickNavMenu}
|
||||
defaultSelectedKeys={[location.pathname !== '/' ? location.pathname : '/dashboard']}
|
||||
>
|
||||
{menuItems}
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
|
||||
Menus.propTypes = {
|
||||
siderFold: PropTypes.bool,
|
||||
darkTheme: PropTypes.bool,
|
||||
location: PropTypes.object,
|
||||
isNavbar: PropTypes.bool,
|
||||
handleClickNavMenu: PropTypes.func,
|
||||
navOpenKeys: PropTypes.array,
|
||||
changeOpenKeys: PropTypes.func,
|
||||
}
|
||||
|
||||
export default Menus
|
||||
@@ -1,39 +0,0 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Icon, Switch } from 'antd'
|
||||
import styles from './Layout.less'
|
||||
import { config } from '../../utils'
|
||||
import Menus from './Menu'
|
||||
|
||||
function Sider ({ siderFold, darkTheme, location, changeTheme, navOpenKeys, changeOpenKeys }) {
|
||||
const menusProps = {
|
||||
siderFold,
|
||||
darkTheme,
|
||||
location,
|
||||
navOpenKeys,
|
||||
changeOpenKeys,
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.logo}>
|
||||
<img alt={'logo'} src={config.logoSrc} />
|
||||
{siderFold ? '' : <span>{config.logoText}</span>}
|
||||
</div>
|
||||
<Menus {...menusProps} />
|
||||
{!siderFold ? <div className={styles.switchtheme}>
|
||||
<span><Icon type="bulb" />切换主题</span>
|
||||
<Switch onChange={changeTheme} defaultChecked={darkTheme} checkedChildren="黑" unCheckedChildren="白" />
|
||||
</div> : ''}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Sider.propTypes = {
|
||||
siderFold: PropTypes.bool,
|
||||
darkTheme: PropTypes.bool,
|
||||
location: PropTypes.object,
|
||||
changeTheme: PropTypes.func,
|
||||
navOpenKeys: PropTypes.array,
|
||||
changeOpenKeys: PropTypes.func,
|
||||
}
|
||||
|
||||
export default Sider
|
||||
Reference in New Issue
Block a user