From 577ded4b3440c99b3b1ecc76bda55e25389ab818 Mon Sep 17 00:00:00 2001 From: ddcat1115 Date: Tue, 26 Dec 2017 00:39:39 +0800 Subject: [PATCH] Router config (#442) * adjust menu and router config * rebase master * remove invalid breadcrumb item * add nested layout * Some improvements * get name from menu.js * - use HOC to pass routerData instead of context --- .eslintrc | 2 +- src/common/menu.js | 134 ++++++++++++++++++ src/common/nav.js | 209 ----------------------------- src/common/router.js | 132 ++++++++++++++++++ src/components/PageHeader/index.js | 8 +- src/components/SiderMenu/index.js | 128 +++++++++++------- src/layouts/BasicLayout.js | 54 +++----- src/layouts/UserLayout.js | 28 ++-- src/router.js | 47 +------ src/routes/List/List.js | 19 ++- src/utils/utils.js | 40 ++++++ 11 files changed, 427 insertions(+), 374 deletions(-) create mode 100644 src/common/menu.js delete mode 100644 src/common/nav.js create mode 100644 src/common/router.js diff --git a/.eslintrc b/.eslintrc index ae9f2234..812519ed 100755 --- a/.eslintrc +++ b/.eslintrc @@ -53,6 +53,6 @@ } }, "settings": { - "polyfills": ["fetch"] + "polyfills": ["fetch", "promises"] } } diff --git a/src/common/menu.js b/src/common/menu.js new file mode 100644 index 00000000..cf9a4e72 --- /dev/null +++ b/src/common/menu.js @@ -0,0 +1,134 @@ +const menuData = [{ + name: 'dashborad', + icon: 'dashboard', + path: 'dashboard', + children: [{ + name: '分析页', + path: 'analysis', + }, { + name: '监控页', + path: 'monitor', + }, { + name: '工作台', + path: 'workplace', + // hideInMenu: true, + }], +}, { + name: '表单页', + icon: 'form', + path: 'form', + children: [{ + name: '基础表单', + path: 'basic-form', + }, { + name: '分步表单', + path: 'step-form', + }, { + name: '高级表单', + path: 'advanced-form', + }], +}, { + name: '列表页', + icon: 'table', + path: 'list', + children: [{ + name: '搜索列表', + icon: 'search', + path: 'search', + children: [{ + name: '搜索列表(项目)', + path: 'projects', + }, { + name: '搜索列表(应用)', + path: 'applications', + }, { + name: '搜索列表(文章)', + path: 'articles', + }], + }, { + name: '查询表格', + path: 'table-list', + }, { + name: '标准列表', + path: 'basic-list', + }, { + name: '卡片列表', + path: 'card-list', + }], +}, { + name: '详情页', + icon: 'profile', + path: 'profile', + children: [{ + name: '基础详情页', + path: 'basic', + }, { + name: '高级详情页', + path: 'advanced', + }], +}, { + name: '结果页', + icon: 'check-circle-o', + path: 'result', + children: [{ + name: '成功', + path: 'success', + }, { + name: '失败', + path: 'fail', + }], +}, { + name: '异常页', + icon: 'warning', + path: 'exception', + children: [{ + name: '403', + path: '403', + }, { + name: '404', + path: '404', + }, { + name: '500', + path: '500', + }], +}, { + name: '账户', + icon: 'user', + path: 'user', + children: [{ + name: '登录', + path: 'login', + }, { + name: '注册', + path: 'register', + }, { + name: '注册结果', + path: 'register-result', + }], +}, { + name: '使用文档', + icon: 'book', + path: 'http://pro.ant.design/docs/getting-started', + target: '_blank', +}]; + +function formatter(data, parentPath = '') { + const list = []; + data.forEach((item) => { + if (item.children) { + list.push({ + ...item, + path: `${parentPath}${item.path}`, + children: formatter(item.children, `${parentPath}${item.path}/`), + }); + } else { + list.push({ + ...item, + path: `${parentPath}${item.path}`, + }); + } + }); + return list; +} + +export const getMenuData = () => formatter(menuData); diff --git a/src/common/nav.js b/src/common/nav.js deleted file mode 100644 index 8c2ba424..00000000 --- a/src/common/nav.js +++ /dev/null @@ -1,209 +0,0 @@ -import dynamic from 'dva/dynamic'; - -// wrapper of dynamic -const dynamicWrapper = (app, models, component) => dynamic({ - app, - models: () => models.map(m => import(`../models/${m}.js`)), - component, -}); - -// nav data -export const getNavData = app => [ - { - component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')), - layout: 'BasicLayout', - name: '首页', // for breadcrumb - path: '/', - children: [ - { - name: 'Dashboard', - icon: 'dashboard', - path: 'dashboard', - children: [ - { - name: '分析页', - path: 'analysis', - component: dynamicWrapper(app, ['chart'], () => import('../routes/Dashboard/Analysis')), - }, - { - name: '监控页', - path: 'monitor', - component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Monitor')), - }, - { - name: '工作台', - path: 'workplace', - component: dynamicWrapper(app, ['project', 'activities', 'chart'], () => import('../routes/Dashboard/Workplace')), - }, - ], - }, - { - name: '表单页', - path: 'form', - icon: 'form', - children: [ - { - name: '基础表单', - path: 'basic-form', - component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/BasicForm')), - }, - { - name: '分步表单', - path: 'step-form', - component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm')), - children: [ - { - path: 'confirm', - component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step2')), - }, - { - path: 'result', - component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step3')), - }, - ], - }, - { - name: '高级表单', - path: 'advanced-form', - component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/AdvancedForm')), - }, - ], - }, - { - name: '列表页', - path: 'list', - icon: 'table', - children: [ - { - name: '查询表格', - path: 'table-list', - component: dynamicWrapper(app, ['rule'], () => import('../routes/List/TableList')), - }, - { - name: '标准列表', - path: 'basic-list', - component: dynamicWrapper(app, ['list'], () => import('../routes/List/BasicList')), - }, - { - name: '卡片列表', - path: 'card-list', - component: dynamicWrapper(app, ['list'], () => import('../routes/List/CardList')), - }, - { - name: '搜索列表', - path: 'search', - component: dynamicWrapper(app, [], () => import('../routes/List/List')), - children: [{ - name: '搜索列表(项目)', - path: 'projects', - component: dynamicWrapper(app, ['list'], () => import('../routes/List/Projects')), - }, { - name: '搜索列表(应用)', - path: 'applications', - component: dynamicWrapper(app, ['list'], () => import('../routes/List/Applications')), - }, { - name: '搜索列表(文章)', - path: 'articles', - component: dynamicWrapper(app, ['list'], () => import('../routes/List/Articles')), - }], - }, - ], - }, - { - name: '详情页', - path: 'profile', - icon: 'profile', - children: [ - { - name: '基础详情页', - path: 'basic', - component: dynamicWrapper(app, ['profile'], () => import('../routes/Profile/BasicProfile')), - }, - { - name: '高级详情页', - path: 'advanced', - component: dynamicWrapper(app, ['profile'], () => import('../routes/Profile/AdvancedProfile')), - }, - ], - }, - { - name: '结果', - path: 'result', - icon: 'check-circle-o', - children: [ - { - name: '成功', - path: 'success', - component: dynamicWrapper(app, [], () => import('../routes/Result/Success')), - }, - { - name: '失败', - path: 'fail', - component: dynamicWrapper(app, [], () => import('../routes/Result/Error')), - }, - ], - }, - { - name: '异常', - path: 'exception', - icon: 'warning', - children: [ - { - name: '403', - path: '403', - component: dynamicWrapper(app, [], () => import('../routes/Exception/403')), - }, - { - name: '404', - path: '404', - component: dynamicWrapper(app, [], () => import('../routes/Exception/404')), - }, - { - name: '500', - path: '500', - component: dynamicWrapper(app, [], () => import('../routes/Exception/500')), - }, - ], - }, - ], - }, - { - component: dynamicWrapper(app, [], () => import('../layouts/UserLayout')), - path: '/user', - layout: 'UserLayout', - children: [ - { - name: '帐户', - icon: 'user', - path: 'user', - children: [ - { - name: '登录', - path: 'login', - component: dynamicWrapper(app, ['login'], () => import('../routes/User/Login')), - }, - { - name: '注册', - path: 'register', - component: dynamicWrapper(app, ['register'], () => import('../routes/User/Register')), - }, - { - name: '注册结果', - path: 'register-result', - component: dynamicWrapper(app, [], () => import('../routes/User/RegisterResult')), - }, - ], - }, - ], - }, - { - component: dynamicWrapper(app, [], () => import('../layouts/BlankLayout')), - layout: 'BlankLayout', - children: { - name: '使用文档', - path: 'http://pro.ant.design/docs/getting-started', - target: '_blank', - icon: 'book', - }, - }, -]; diff --git a/src/common/router.js b/src/common/router.js new file mode 100644 index 00000000..08b9dde3 --- /dev/null +++ b/src/common/router.js @@ -0,0 +1,132 @@ +import React from 'react'; +import dynamic from 'dva/dynamic'; +import { getMenuData } from './menu'; + +// wrapper of dynamic +const dynamicWrapper = (app, models, component) => dynamic({ + app, + models: () => models.map(m => import(`../models/${m}.js`)), + // add routerData prop + component: () => { + const p = component(); + return new Promise((resolve, reject) => { + p.then((Comp) => { + resolve(props => ); + }).catch(err => reject(err)); + }); + }, +}); + +function getFlatMenuData(menus) { + let keys = {}; + menus.forEach((item) => { + if (item.children) { + keys[item.path] = item.name; + keys = { ...keys, ...getFlatMenuData(item.children) }; + } else { + keys[item.path] = item.name; + } + }); + return keys; +} + +export const getRouterData = (app) => { + const routerData = { + '/': { + component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')), + }, + '/dashboard/analysis': { + component: dynamicWrapper(app, ['chart'], () => import('../routes/Dashboard/Analysis')), + }, + '/dashboard/monitor': { + component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Monitor')), + }, + '/dashboard/workplace': { + component: dynamicWrapper(app, ['project', 'activities', 'chart'], () => import('../routes/Dashboard/Workplace')), + // hideInBreadcrumb: true, + // name: '工作台', + }, + '/form/basic-form': { + component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/BasicForm')), + }, + '/form/step-form': { + component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm')), + }, + '/form/step-form/confirm': { + component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step2')), + }, + '/form/step-form/result': { + component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step3')), + }, + '/form/advanced-form': { + component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/AdvancedForm')), + }, + '/list/table-list': { + component: dynamicWrapper(app, ['rule'], () => import('../routes/List/TableList')), + }, + '/list/basic-list': { + component: dynamicWrapper(app, ['list'], () => import('../routes/List/BasicList')), + }, + '/list/card-list': { + component: dynamicWrapper(app, ['list'], () => import('../routes/List/CardList')), + }, + '/list/search': { + component: dynamicWrapper(app, ['list'], () => import('../routes/List/List')), + }, + '/list/search/projects': { + component: dynamicWrapper(app, ['list'], () => import('../routes/List/Projects')), + }, + '/list/search/applications': { + component: dynamicWrapper(app, ['list'], () => import('../routes/List/Applications')), + }, + '/list/search/articles': { + component: dynamicWrapper(app, ['list'], () => import('../routes/List/Articles')), + }, + '/profile/basic': { + component: dynamicWrapper(app, ['profile'], () => import('../routes/Profile/BasicProfile')), + }, + '/profile/advanced': { + component: dynamicWrapper(app, ['profile'], () => import('../routes/Profile/AdvancedProfile')), + }, + '/result/success': { + component: dynamicWrapper(app, [], () => import('../routes/Result/Success')), + }, + '/result/fail': { + component: dynamicWrapper(app, [], () => import('../routes/Result/Error')), + }, + '/exception/403': { + component: dynamicWrapper(app, [], () => import('../routes/Exception/403')), + }, + '/exception/404': { + component: dynamicWrapper(app, [], () => import('../routes/Exception/404')), + }, + '/exception/500': { + component: dynamicWrapper(app, [], () => import('../routes/Exception/500')), + }, + '/user': { + component: dynamicWrapper(app, [], () => import('../layouts/UserLayout')), + }, + '/user/login': { + component: dynamicWrapper(app, ['login'], () => import('../routes/User/Login')), + }, + '/user/register': { + component: dynamicWrapper(app, ['register'], () => import('../routes/User/Register')), + }, + '/user/register-result': { + component: dynamicWrapper(app, [], () => import('../routes/User/RegisterResult')), + }, + // '/user/:id': { + // component: dynamicWrapper(app, [], () => import('../routes/User/SomeComponent')), + // }, + }; + // Get name from ./menu.js or just set it in the router data. + const menuData = getFlatMenuData(getMenuData()); + const routerDataWithName = {}; + Object.keys(routerData).forEach((item) => { + routerDataWithName[item] = { + ...routerData[item], + name: routerData[item].name || menuData[item.replace(/^\//, '')], + }; + }); + return routerDataWithName; +}; diff --git a/src/components/PageHeader/index.js b/src/components/PageHeader/index.js index af1d1814..eb0318b1 100644 --- a/src/components/PageHeader/index.js +++ b/src/components/PageHeader/index.js @@ -14,7 +14,7 @@ function getBreadcrumb(breadcrumbNameMap, url) { if (breadcrumbNameMap[urlWithoutSplash]) { return breadcrumbNameMap[urlWithoutSplash]; } - let breadcrumb = ''; + let breadcrumb = {}; Object.keys(breadcrumbNameMap).forEach((item) => { const itemRegExpStr = `^${item.replace(/:[\w-]+/g, '[\\w-]+')}$`; const itemRegExp = new RegExp(itemRegExpStr); @@ -78,15 +78,15 @@ export default class PageHeader extends PureComponent { const url = `/${pathSnippets.slice(0, index + 1).join('/')}`; const currentBreadcrumb = getBreadcrumb(breadcrumbNameMap, url); const isLinkable = (index !== pathSnippets.length - 1) && currentBreadcrumb.component; - return ( + return currentBreadcrumb.name && !currentBreadcrumb.hideInBreadcrumb ? ( {createElement( isLinkable ? linkElement : 'span', { [linkElement === 'a' ? 'href' : 'to']: url }, - currentBreadcrumb.name || url, + currentBreadcrumb.name, )} - ); + ) : null; }); const breadcrumbItems = [( diff --git a/src/components/SiderMenu/index.js b/src/components/SiderMenu/index.js index 768bdfad..fd015f5b 100644 --- a/src/components/SiderMenu/index.js +++ b/src/components/SiderMenu/index.js @@ -3,6 +3,7 @@ import { Layout, Menu, Icon } from 'antd'; import { Link } from 'dva/router'; import logo from '../../assets/logo.svg'; import styles from './index.less'; +import { getMenuData } from '../../common/menu'; const { Sider } = Layout; const { SubMenu } = Menu; @@ -10,8 +11,7 @@ const { SubMenu } = Menu; export default class SiderMenu extends PureComponent { constructor(props) { super(props); - // 把一级 Layout 的 children 作为菜单项 - this.menus = props.navData.reduce((arr, current) => arr.concat(current.children), []); + this.menus = getMenuData(); this.state = { openKeys: this.getDefaultCollapsedSubMenus(props), }; @@ -23,22 +23,49 @@ export default class SiderMenu extends PureComponent { }); } getDefaultCollapsedSubMenus(props) { - const currentMenuSelectedKeys = [...this.getCurrentMenuSelectedKeys(props)]; - currentMenuSelectedKeys.splice(-1, 1); + const { location: { pathname } } = props || this.props; + const snippets = pathname.split('/').slice(1, -1); + const currentPathSnippets = snippets.map((item, index) => { + const arr = snippets.filter((_, i) => i <= index); + return arr.join('/'); + }); + let currentMenuSelectedKeys = []; + currentPathSnippets.forEach((item) => { + currentMenuSelectedKeys = currentMenuSelectedKeys.concat(this.getSelectedMenuKeys(item)); + }); if (currentMenuSelectedKeys.length === 0) { return ['dashboard']; } return currentMenuSelectedKeys; } - getCurrentMenuSelectedKeys(props) { - const { location: { pathname } } = props || this.props; - const keys = pathname.split('/').slice(1); - if (keys.length === 1 && keys[0] === '') { - return [this.menus[0].key]; - } + getFlatMenuKeys(menus) { + let keys = []; + menus.forEach((item) => { + if (item.children) { + keys.push(item.path); + keys = keys.concat(this.getFlatMenuKeys(item.children)); + } else { + keys.push(item.path); + } + }); return keys; } - getNavMenuItems(menusData, parentPath = '') { + getSelectedMenuKeys = (path) => { + const flatMenuKeys = this.getFlatMenuKeys(this.menus); + + if (flatMenuKeys.indexOf(path.replace(/^\//, '')) > -1) { + return [path.replace(/^\//, '')]; + } + if (flatMenuKeys.indexOf(path.replace(/^\//, '').replace(/\/$/, '')) > -1) { + return [path.replace(/^\//, '').replace(/\/$/, '')]; + } + return flatMenuKeys.filter((item) => { + const itemRegExpStr = `^${item.replace(/:[\w-]+/g, '[\\w-]+')}$`; + const itemRegExp = new RegExp(itemRegExpStr); + return itemRegExp.test(path.replace(/^\//, '')); + }); + } + getNavMenuItems(menusData) { if (!menusData) { return []; } @@ -47,48 +74,50 @@ export default class SiderMenu extends PureComponent { return null; } let itemPath; - if (item.path.indexOf('http') === 0) { + if (item.path && item.path.indexOf('http') === 0) { itemPath = item.path; } else { - itemPath = `${parentPath}/${item.path || ''}`.replace(/\/+/g, '/'); + itemPath = `/${item.path || ''}`.replace(/\/+/g, '/'); } if (item.children && item.children.some(child => child.name)) { - return ( - - - {item.name} - - ) : item.name - } - key={item.key || item.path} - > - {this.getNavMenuItems(item.children, itemPath)} - - ); + return item.hideInMenu ? null : + ( + + + {item.name} + + ) : item.name + } + key={item.key || item.path} + > + {this.getNavMenuItems(item.children)} + + ); } const icon = item.icon && ; - return ( - - { - /^https?:\/\//.test(itemPath) ? ( - - {icon}{item.name} - - ) : ( - - {icon}{item.name} - - ) - } - - ); + return item.hideInMenu ? null : + ( + + { + /^https?:\/\//.test(itemPath) ? ( + + {icon}{item.name} + + ) : ( + + {icon}{item.name} + + ) + } + + ); }); } handleOpenChange = (openKeys) => { @@ -101,8 +130,7 @@ export default class SiderMenu extends PureComponent { }); } render() { - const { collapsed } = this.props; - + const { collapsed, location: { pathname } } = this.props; // Don't show popup menu when it is been collapsed const menuProps = collapsed ? {} : { openKeys: this.state.openKeys, @@ -128,7 +156,7 @@ export default class SiderMenu extends PureComponent { mode="inline" {...menuProps} onOpenChange={this.handleOpenChange} - selectedKeys={this.getCurrentMenuSelectedKeys()} + selectedKeys={this.getSelectedMenuKeys(pathname)} style={{ padding: '16px 0', width: '100%' }} > {this.getNavMenuItems(this.menus)} diff --git a/src/layouts/BasicLayout.js b/src/layouts/BasicLayout.js index 70453cc2..a5380d28 100644 --- a/src/layouts/BasicLayout.js +++ b/src/layouts/BasicLayout.js @@ -10,6 +10,7 @@ import GlobalHeader from '../components/GlobalHeader'; import GlobalFooter from '../components/GlobalFooter'; import SiderMenu from '../components/SiderMenu'; import NotFound from '../routes/Exception/404'; +import { getRoutes } from '../utils/utils'; const { Content } = Layout; @@ -38,56 +39,31 @@ class BasicLayout extends React.PureComponent { static childContextTypes = { location: PropTypes.object, breadcrumbNameMap: PropTypes.object, - routeData: PropTypes.array, } getChildContext() { - const { location, navData, getRouteData } = this.props; - const routeData = getRouteData('BasicLayout'); - const firstMenuData = navData.reduce((arr, current) => arr.concat(current.children), []); - const menuData = this.getMenuData(firstMenuData, ''); - const breadcrumbNameMap = {}; - - routeData.concat(menuData).forEach((item) => { - breadcrumbNameMap[item.path] = { - name: item.name, - component: item.component, - }; - }); - return { location, breadcrumbNameMap, routeData }; + const { location, routerData } = this.props; + return { + location, + breadcrumbNameMap: routerData, + }; } getPageTitle() { - const { location, getRouteData } = this.props; + const { routerData, location } = this.props; const { pathname } = location; let title = 'Ant Design Pro'; - getRouteData('BasicLayout').forEach((item) => { - if (item.path === pathname) { - title = `${item.name} - Ant Design Pro`; - } - }); + if (routerData[pathname] && routerData[pathname].name) { + title = `${routerData[pathname].name} - Ant Design Pro`; + } return title; } - getMenuData = (data, parentPath) => { - let arr = []; - data.forEach((item) => { - if (item.name) { - arr.push({ path: `${parentPath}/${item.path}`, name: item.name }); - } - if (item.children) { - arr = arr.concat(this.getMenuData(item.children, `${parentPath}/${item.path}`)); - } - }); - return arr; - } render() { const { - currentUser, collapsed, fetchingNotices, notices, getRouteData, navData, location, dispatch, + currentUser, collapsed, fetchingNotices, notices, routerData, match, location, dispatch, } = this.props; - const layout = ( @@ -103,19 +79,19 @@ class BasicLayout extends React.PureComponent {
{ - getRouteData('BasicLayout').map(item => + getRoutes(match.path, routerData).map(item => ( ) ) } - +
Copyright 2017 蚂蚁金服体验技术部出品; class UserLayout extends React.PureComponent { - static childContextTypes = { - location: PropTypes.object, - } - getChildContext() { - const { location } = this.props; - return { location }; - } getPageTitle() { - const { getRouteData, location } = this.props; + const { routerData, location } = this.props; const { pathname } = location; let title = 'Ant Design Pro'; - getRouteData('UserLayout').forEach((item) => { - if (item.path === pathname) { - title = `${item.name} - Ant Design Pro`; - } - }); + if (routerData[pathname] && routerData[pathname].name) { + title = `${routerData[pathname].name} - Ant Design Pro`; + } return title; } render() { - const { getRouteData } = this.props; - + const { routerData, match } = this.props; return (
@@ -55,13 +45,13 @@ class UserLayout extends React.PureComponent {
Ant Design 是西湖区最具影响力的 Web 设计规范
{ - getRouteData('UserLayout').map(item => + getRoutes(match.path, routerData).map(item => ( ) ) diff --git a/src/router.js b/src/router.js index 1c9ac52d..03f8528d 100644 --- a/src/router.js +++ b/src/router.js @@ -3,9 +3,7 @@ import { Router, Route, Switch } from 'dva/router'; import { LocaleProvider, Spin } from 'antd'; import zhCN from 'antd/lib/locale-provider/zh_CN'; import dynamic from 'dva/dynamic'; -import cloneDeep from 'lodash/cloneDeep'; -import { getNavData } from './common/nav'; -import { getPlainNode } from './utils/utils'; +import { getRouterData } from './common/router'; import styles from './index.less'; @@ -13,49 +11,16 @@ dynamic.setDefaultLoadingComponent(() => { return ; }); -function getRouteData(navData, path) { - if (!navData.some(item => item.layout === path) || - !(navData.filter(item => item.layout === path)[0].children)) { - return null; - } - const route = cloneDeep(navData.filter(item => item.layout === path)[0]); - const nodeList = getPlainNode(route.children); - return nodeList; -} - -function getLayout(navData, path) { - if (!navData.some(item => item.layout === path) || - !(navData.filter(item => item.layout === path)[0].children)) { - return null; - } - const route = navData.filter(item => item.layout === path)[0]; - return { - component: route.component, - layout: route.layout, - name: route.name, - path: route.path, - }; -} - function RouterConfig({ history, app }) { - const navData = getNavData(app); - const UserLayout = getLayout(navData, 'UserLayout').component; - const BasicLayout = getLayout(navData, 'BasicLayout').component; - - const passProps = { - app, - navData, - getRouteData: (path) => { - return getRouteData(navData, path); - }, - }; - + const routerData = getRouterData(app); + const UserLayout = routerData['/user'].component; + const BasicLayout = routerData['/'].component; return ( - } /> - } /> + } /> + } /> diff --git a/src/routes/List/List.js b/src/routes/List/List.js index 24c622d3..c35e2ec1 100644 --- a/src/routes/List/List.js +++ b/src/routes/List/List.js @@ -1,16 +1,12 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { routerRedux, Route, Switch } from 'dva/router'; +import { routerRedux, Route, Switch, Redirect } from 'dva/router'; import { connect } from 'dva'; import { Input } from 'antd'; import PageHeaderLayout from '../../layouts/PageHeaderLayout'; +import { getRoutes } from '../../utils/utils'; @connect() export default class SearchList extends Component { - static contextTypes = { - routeData: PropTypes.array, - }; - handleTabChange = (key) => { const { dispatch, match } = this.props; switch (key) { @@ -52,9 +48,8 @@ export default class SearchList extends Component { ); - const { match } = this.props; - const { routeData } = this.context; - const routes = routeData.filter(item => item.path === match.path)[0].children; + const { match, routerData } = this.props; + const routes = getRoutes(match.path, routerData); return ( ( ) ) } + ); diff --git a/src/utils/utils.js b/src/utils/utils.js index e0dfd715..ee479df5 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -92,3 +92,43 @@ export function digitUppercase(n) { return s.replace(/(零.)*零元/, '元').replace(/(零.)+/g, '零').replace(/^整$/, '零元整'); } + +function getRelation(str1, str2) { + if (str1 === str2) { + console.warn('Two path are equal!'); + } + const arr1 = str1.split('/'); + const arr2 = str2.split('/'); + if (arr2.every((item, index) => item === arr1[index])) { + return 1; + } else if (arr1.every((item, index) => item === arr2[index])) { + return 2; + } + return 3; +} + +export function getRoutes(path, routerData) { + let routes = Object.keys(routerData).filter(routePath => + routePath.indexOf(path) === 0 && routePath !== path); + routes = routes.map(item => item.replace(path, '')); + let renderArr = []; + renderArr.push(routes[0]); + for (let i = 1; i < routes.length; i += 1) { + let isAdd = false; + isAdd = renderArr.every(item => getRelation(item, routes[i]) === 3); + renderArr = renderArr.filter(item => getRelation(item, routes[i]) !== 1); + if (isAdd) { + renderArr.push(routes[i]); + } + } + const renderRoutes = renderArr.map((item) => { + const exact = !routes.some(route => route !== item && getRelation(route, item) === 1); + return { + key: `${path}${item}`, + path: `${path}${item}`, + component: routerData[`${path}${item}`].component, + exact, + }; + }); + return renderRoutes; +} -- GitLab