rebuild bread,menu,router

This commit is contained in:
zuiidea
2017-04-20 19:26:17 +08:00
parent cfd0172204
commit b6c3cb8a53
8 changed files with 251 additions and 145 deletions
+1
View File
@@ -35,6 +35,7 @@
"jsonp": "^0.2.1",
"less-vars-to-js": "^1.1.2",
"mockjs": "^1.0.1-beta3",
"path-to-regexp": "^1.7.0",
"rc-tween-one": "^1.0.0",
"redbox-react": "^1.2.10"
},
+30 -38
View File
@@ -3,46 +3,43 @@ import PropTypes from 'prop-types'
import { Breadcrumb, Icon } from 'antd'
import { Link } from 'dva/router'
import styles from './Bread.less'
import { menu } from '../../utils'
import pathToRegexp from 'path-to-regexp'
import { queryArray } 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,
const Bread = ({ location, menu }) => {
// 匹配当前路由
let pathArray = []
let current
for (let index in menu) {
if (menu[index].router && pathToRegexp(menu[index].router).exec(location.pathname)) {
current = menu[index]
break
}
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())
}
})
if (!current) {
return (<div className={styles.bread}>首页</div>)
}
const breadsArray = pathNames.filter(item => (item in pathSet))
const breads = breadsArray.map((item, key) => {
// 递归查找父级
const getPathArray = (item) => {
pathArray.unshift(item)
if (item.bpid) {
getPathArray(queryArray(menu, item.bpid, 'id'))
}
}
getPathArray(current)
const breads = pathArray.map((item, key) => {
const content = (
<span>{pathSet[item].icon
? <Icon type={pathSet[item].icon} style={{ marginRight: 4 }} />
: ''}{pathSet[item].name}</span>
<span>{item.icon
? <Icon type={item.icon} style={{ marginRight: 4 }} />
: ''}{item.name}</span>
)
return (
<Breadcrumb.Item key={key}>
{((breadsArray.length - 1) !== key && pathSet[item].clickable)
? <Link to={pathSet[item].path}>
{((pathArray.length - 1) !== key)
? <Link to={item.router}>
{content}
</Link>
: content}
@@ -53,12 +50,6 @@ function Bread ({ location }) {
return (
<div className={styles.bread}>
<Breadcrumb>
<Breadcrumb.Item >
<Link to="/dashboard">
<Icon type="home" />
<span>Home</span>
</Link>
</Breadcrumb.Item>
{breads}
</Breadcrumb>
</div>
@@ -66,6 +57,7 @@ function Bread ({ location }) {
}
Bread.propTypes = {
menu: PropTypes.array,
location: PropTypes.object,
}
+3 -1
View File
@@ -6,9 +6,10 @@ import Menus from './Menu'
const SubMenu = Menu.SubMenu
function Header ({ user, logout, switchSider, siderFold, isNavbar, menuPopoverVisible, location, switchMenuPopover, navOpenKeys, changeOpenKeys }) {
function Header ({ user, logout, switchSider, siderFold, isNavbar, menuPopoverVisible, location, switchMenuPopover, navOpenKeys, changeOpenKeys, menu }) {
let handleClickMenu = e => e.key === 'logout' && logout()
const menusProps = {
menu,
siderFold: false,
darkTheme: false,
isNavbar,
@@ -49,6 +50,7 @@ function Header ({ user, logout, switchSider, siderFold, isNavbar, menuPopoverVi
}
Header.propTypes = {
menu: PropTypes.array,
user: PropTypes.object,
logout: PropTypes.func,
switchSider: PropTypes.func,
+34 -23
View File
@@ -2,33 +2,43 @@ import React from 'react'
import PropTypes from 'prop-types'
import { Menu, Icon } from 'antd'
import { Link } from 'dva/router'
import { menu } from '../../utils'
import { arrayToTree } 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) {
const Menus = ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKeys, changeOpenKeys, menu }) => {
// 生成树状
const menuTree = arrayToTree(menu.filter(_ => _.mpid !== -1), 'id', 'mpid')
// 递归生成菜单
const getMenus = (menuTreeN, siderFoldN) => {
return menuTreeN.map(item => {
if (item.chindren) {
return (
<Menu.SubMenu
key={item.id}
title={<span>
{item.icon && <Icon type={item.icon} />}
{(!siderFoldN || menuTree.indexOf(item) < 0) && item.name}
</span>}
>
{getMenus(item.chindren, siderFoldN)}
</Menu.SubMenu>
)
}
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>
<Menu.Item key={item.id}>
<Link to={item.router}>
{item.icon && <Icon type={item.icon} />}
{(!siderFoldN || menuTree.indexOf(item) < 0) && item.name}
</Link>
</Menu.Item>
)
}
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>
)
})
}
})
}
const menuItems = getMenus(menuTree, siderFold)
function Menus ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKeys, changeOpenKeys }) {
const menuItems = getMenus(menu, siderFold)
// 保持选中
const getAncestorKeys = (key) => {
const map = {
'/navigation/navigation2': ['/navigation'],
@@ -60,7 +70,7 @@ function Menus ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKey
mode={siderFold ? 'vertical' : 'inline'}
theme={darkTheme ? 'dark' : 'light'}
onClick={handleClickNavMenu}
defaultSelectedKeys={[location.pathname !== '/' ? location.pathname : '/dashboard']}
defaultSelectedKeys={[location.pathname !== '/' ? location.pathname : menuTree[0].router]}
>
{menuItems}
</Menu>
@@ -68,6 +78,7 @@ function Menus ({ siderFold, darkTheme, location, handleClickNavMenu, navOpenKey
}
Menus.propTypes = {
menu: PropTypes.array,
siderFold: PropTypes.bool,
darkTheme: PropTypes.bool,
location: PropTypes.object,
+3 -1
View File
@@ -5,8 +5,9 @@ import styles from './Layout.less'
import { config } from '../../utils'
import Menus from './Menu'
function Sider ({ siderFold, darkTheme, location, changeTheme, navOpenKeys, changeOpenKeys }) {
function Sider ({ siderFold, darkTheme, location, changeTheme, navOpenKeys, changeOpenKeys, menu }) {
const menusProps = {
menu,
siderFold,
darkTheme,
location,
@@ -29,6 +30,7 @@ function Sider ({ siderFold, darkTheme, location, changeTheme, navOpenKeys, chan
}
Sider.propTypes = {
menu: PropTypes.array,
siderFold: PropTypes.bool,
darkTheme: PropTypes.bool,
location: PropTypes.object,
+9 -5
View File
@@ -2,17 +2,17 @@ import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'dva'
import { Layout } from '../components'
import { classnames, config } from '../utils'
import { classnames, config, menu } from '../utils'
import { Helmet } from 'react-helmet'
import '../themes/index.less'
const { Header, Bread, Footer, Sider, styles } = Layout
const App = ({ children, location, dispatch, app, loading }) => {
console.log(loading)
const App = ({ children, location, dispatch, app }) => {
const { user, siderFold, darkTheme, isNavbar, menuPopoverVisible, navOpenKeys } = app
const headerProps = {
menu,
user,
siderFold,
location,
@@ -34,6 +34,7 @@ const App = ({ children, location, dispatch, app, loading }) => {
}
const siderProps = {
menu,
siderFold,
darkTheme,
location,
@@ -47,6 +48,10 @@ const App = ({ children, location, dispatch, app, loading }) => {
},
}
const breadProps = {
menu,
}
if (config.openPages && config.openPages.indexOf(location.pathname) > -1) {
return <div>{children}</div>
}
@@ -65,7 +70,7 @@ const App = ({ children, location, dispatch, app, loading }) => {
</aside> : ''}
<div className={styles.main}>
<Header {...headerProps} />
<Bread location={location} />
<Bread {...breadProps} location={location} />
<div className={styles.container}>
<div className={styles.content}>
{children}
@@ -83,7 +88,6 @@ App.propTypes = {
location: PropTypes.object,
dispatch: PropTypes.func,
app: PropTypes.object,
loading: PropTypes.object,
}
export default connect(({ app, loading }) => ({ app, loading }))(App)
+49
View File
@@ -3,6 +3,7 @@ import menu from './menu'
import request from './request'
import classnames from 'classnames'
import { color } from './theme'
import lodash from 'lodash'
// 连字符转驼峰
String.prototype.hyphenToHump = function () {
@@ -52,6 +53,52 @@ const queryURL = (name) => {
return null
}
/**
* 数组内查询
* @param {array} array
* @param {String} id
* @param {String} keyAlias
* @return {Array}
*/
const queryArray = (array, key, keyAlias = 'key') => {
if (!(array instanceof Array)) {
return null
}
const item = array.filter(_ => _[keyAlias] === key)
if (item.length) {
return item[0]
}
return null
}
/**
* 数组格式转树状结构
* @param {array} array
* @param {String} id
* @param {String} pid
* @param {String} children
* @return {Array}
*/
const arrayToTree = (array, id = 'id', pid = 'pid', chindren = 'chindren') => {
let data = lodash.cloneDeep(array)
let result = []
let hash = {}
data.forEach((item, index) => {
hash[data[index][id]] = data[index]
})
data.forEach((item) => {
let hashVP = hash[item[pid]]
if (hashVP) {
!hashVP[chindren] && (hashVP[chindren] = [])
hashVP[chindren].push(item)
} else {
result.push(item)
}
})
return result
}
module.exports = {
config,
menu,
@@ -59,4 +106,6 @@ module.exports = {
color,
classnames,
queryURL,
queryArray,
arrayToTree,
}
+122 -77
View File
@@ -1,102 +1,147 @@
module.exports = [
{
key: 'dashboard',
name: 'Dashboard',
id: 1,
icon: 'laptop',
name: 'Dashboard',
router: '/dashboard',
},
{
key: 'users',
id: 2,
bpid: 1,
name: 'User Manage',
icon: 'user',
router: '/users',
},
{
key: 'request',
id: 3,
bpid: 1,
name: 'Request',
icon: 'api',
router: '/request',
},
{
key: 'UIElement',
id: 4,
bpid: 1,
name: 'UI Element',
icon: 'camera-o',
clickable: false,
child: [
{
key: 'iconfont',
name: 'IconFont',
icon: 'heart-o',
},
{
key: 'dataTable',
name: 'DataTable',
icon: 'database',
},
{
key: 'dropOption',
name: 'DropOption',
icon: 'bars',
},
{
key: 'search',
name: 'Search',
icon: 'search',
},
{
key: 'editor',
name: 'Editor',
icon: 'edit',
},
{
key: 'layer',
name: 'layer (Function)',
icon: 'credit-card',
},
],
},
{
key: 'chart',
id: 41,
bpid: 4,
mpid: 4,
name: 'IconFont',
icon: 'heart-o',
router: '/UIElement/iconfont',
},
{
id: 42,
bpid: 4,
mpid: 4,
name: 'DataTable',
icon: 'database',
router: '/UIElement/dataTable',
},
{
id: 43,
bpid: 4,
mpid: 4,
name: 'DropOption',
icon: 'bars',
router: '/UIElement/dropOption',
},
{
id: 44,
bpid: 4,
mpid: 4,
name: 'Search',
icon: 'search',
router: '/UIElement/search',
},
{
id: 45,
bpid: 4,
mpid: 4,
name: 'Editor',
icon: 'edit',
router: '/UIElement/editor',
},
{
id: 46,
bpid: 4,
mpid: 4,
name: 'layer (Function)',
icon: 'credit-card',
router: '/UIElement/layer',
},
{
id: 5,
bpid: 1,
name: 'Recharts',
icon: 'code-o',
child: [
{
key: 'lineChart',
name: 'LineChart',
icon: 'line-chart',
},
{
key: 'barChart',
name: 'BarChart',
icon: 'bar-chart',
},
{
key: 'areaChart',
name: 'AreaChart',
icon: 'area-chart',
},
],
},
{
key: 'navigation',
id: 51,
bpid: 5,
mpid: 5,
name: 'LineChart',
icon: 'line-chart',
router: '/chart/lineChart',
},
{
id: 52,
bpid: 5,
mpid: 5,
name: 'BarChart',
icon: 'bar-chart',
router: '/chart/lineChart',
},
{
id: 53,
bpid: 5,
mpid: 5,
name: 'AreaChart',
icon: 'area-chart',
router: '/chart/areaChart',
},
{
id: 6,
bpid: 1,
name: 'Test Navigation',
icon: 'setting',
child: [
{
key: 'navigation1',
name: 'Test Navigation1',
},
{
key: 'navigation2',
name: 'Test Navigation2',
child: [
{
key: 'navigation21',
name: 'Test Navigation21',
},
{
key: 'navigation22',
name: 'Test Navigation22',
},
],
},
],
},
{
id: 61,
bpid: 6,
mpid: 6,
name: 'Test Navigation1',
router: '/navigation/navigation1',
},
{
id: 62,
bpid: 6,
mpid: 6,
name: 'Test Navigation2',
router: '/navigation/navigation2',
},
{
id: 621,
bpid: 62,
mpid: 62,
name: 'Test Navigation21',
router: '/navigation/navigation2/navigation1',
},
{
id: 621,
bpid: 62,
mpid: 62,
name: 'Test Navigation21',
router: '/navigation/navigation2/navigation1',
},
{
id: 622,
bpid: 62,
mpid: 62,
name: 'Test Navigation22',
router: '/navigation/navigation2/navigation2',
},
]