handle FileName

This commit is contained in:
zuiidea
2017-03-24 11:56:26 +08:00
parent 4425a289e7
commit 930c8427e0
17 changed files with 2 additions and 887 deletions
-62
View File
@@ -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
-8
View File
@@ -1,8 +0,0 @@
@import "../vars.less";
.bread {
height: 64px;
line-height: 64px;
padding: 0 24px;
margin-bottom: -24px;
}
-9
View File
@@ -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
-12
View File
@@ -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%;
}
-63
View File
@@ -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
-57
View File
@@ -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;
}
}
}
-293
View File
@@ -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)");
}
}
}
}
}
-80
View File
@@ -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
-39
View File
@@ -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
View File
@@ -1 +0,0 @@
@import "../vars.less";
-8
View File
@@ -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 }
+2 -2
View File
@@ -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,
-62
View File
@@ -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
-9
View File
@@ -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
-63
View File
@@ -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
-80
View File
@@ -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
-39
View File
@@ -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