@ -1,24 +1,17 @@
import React , { PureComponent , createElement } from 'react' ;
import React , { PureComponent , createElement } from 'react' ;
import PropTypes from 'prop-types' ;
import PropTypes from 'prop-types' ;
import pathToRegexp from 'path-to-regexp' ;
import { Breadcrumb , Tabs } from 'antd' ;
import { Breadcrumb , Tabs } from 'antd' ;
import classNames from 'classnames' ;
import classNames from 'classnames' ;
import styles from './index.less' ;
import styles from './index.less' ;
const { TabPane } = Tabs ;
const { TabPane } = Tabs ;
function getBreadcrumb ( breadcrumbNameMap , url ) {
function getBreadcrumb ( breadcrumbNameMap , url ) {
if ( breadcrumbNameMap [ url ] ) {
return breadcrumbNameMap [ url ] ;
}
const urlWithoutSplash = url . replace ( /\/$/ , '' ) ;
if ( breadcrumbNameMap [ urlWithoutSplash ] ) {
return breadcrumbNameMap [ urlWithoutSplash ] ;
}
let breadcrumb = { } ;
let breadcrumb = { } ;
Object . keys ( breadcrumbNameMap ) . forEach ( ( item ) => {
Object . keys ( breadcrumbNameMap ) . forEach ( ( item ) => {
const itemRegExpStr = ` ^ ${ item . replace ( /:[\w-]+/g , '[\\w-]+' ) } $ ` ;
if ( pathToRegexp ( item ) . test ( url ) ) {
const itemRegExp = new RegExp ( itemRegExpStr ) ;
if ( itemRegExp . test ( url ) ) {
breadcrumb = breadcrumbNameMap [ item ] ;
breadcrumb = breadcrumbNameMap [ item ] ;
}
}
} ) ;
} ) ;
@ -41,56 +34,32 @@ export default class PageHeader extends PureComponent {
return {
return {
routes : this . props . routes || this . context . routes ,
routes : this . props . routes || this . context . routes ,
params : this . props . params || this . context . params ,
params : this . props . params || this . context . params ,
l ocation: this . props . location || this . context . location ,
routerL ocation: this . props . location || this . context . location ,
breadcrumbNameMap : this . props . breadcrumbNameMap || this . context . breadcrumbNameMap ,
breadcrumbNameMap : this . props . breadcrumbNameMap || this . context . breadcrumbNameMap ,
} ;
} ;
} ;
} ;
itemRender = ( route , params , routes , paths ) => {
// Generated according to props
const { linkElement = 'a' } = this . props ;
conversionFromProps = ( ) => {
const last = routes . indexOf ( route ) === routes . length - 1 ;
return ( last || ! route . component )
? < span > { route . breadcrumbName } < / s p a n >
: createElement ( linkElement , {
href : paths . join ( '/' ) || '/' ,
to : paths . join ( '/' ) || '/' ,
} , route . breadcrumbName ) ;
}
render ( ) {
const { routes , params , location , breadcrumbNameMap } = this . getBreadcrumbProps ( ) ;
const {
const {
title , logo , action , content , extraContent ,
breadcrumbList , linkElement = 'a' ,
breadcrumbList , tabList , className , linkElement = 'a' ,
tabActiveKey ,
} = this . props ;
} = this . props ;
const clsString = classNames ( styles . pageHeader , className ) ;
return (
let breadcrumb ;
if ( breadcrumbList && breadcrumbList . length ) {
breadcrumb = (
< Breadcrumb className = { styles . breadcrumb } >
< Breadcrumb className = { styles . breadcrumb } >
{
{ breadcrumbList . map ( item => (
breadcrumbList . map ( item => (
< Breadcrumb . Item key = { item . title } >
< Breadcrumb . Item key = { item . title } >
{ item . href ? (
{ item . href ? ( createElement ( linkElement , {
createElement ( linkElement , {
[ linkElement === 'a' ? 'href' : 'to' ] : item . href ,
[ linkElement === 'a' ? 'href' : 'to' ] : item . href ,
} , item . title )
} , item . title ) ) : item . title }
) : item . title }
< / B r e a d c r u m b . I t e m >
< / B r e a d c r u m b . I t e m > )
) ) }
)
}
< / B r e a d c r u m b >
< / B r e a d c r u m b >
) ;
) ;
} else if ( routes && params ) {
}
breadcrumb = (
conversionFromLocation = ( routerLocation , breadcrumbNameMap ) => {
< Breadcrumb
const { linkElement = 'a' } = this . props ;
className = { styles . breadcrumb }
// Convert the path to an array
routes = { routes . filter ( route => route . breadcrumbName ) }
const pathSnippets = routerLocation . pathname . split ( '/' ) . filter ( i => i ) ;
params = { params }
// Loop data mosaic routing
itemRender = { this . itemRender }
/ >
) ;
} else if ( location && location . pathname ) {
const pathSnippets = location . pathname . split ( '/' ) . filter ( i => i ) ;
const extraBreadcrumbItems = pathSnippets . map ( ( _ , index ) => {
const extraBreadcrumbItems = pathSnippets . map ( ( _ , index ) => {
const url = ` / ${ pathSnippets . slice ( 0 , index + 1 ) . join ( '/' ) } ` ;
const url = ` / ${ pathSnippets . slice ( 0 , index + 1 ) . join ( '/' ) } ` ;
const currentBreadcrumb = getBreadcrumb ( breadcrumbNameMap , url ) ;
const currentBreadcrumb = getBreadcrumb ( breadcrumbNameMap , url ) ;
@ -105,27 +74,73 @@ export default class PageHeader extends PureComponent {
< / B r e a d c r u m b . I t e m >
< / B r e a d c r u m b . I t e m >
) : null ;
) : null ;
} ) ;
} ) ;
const breadcrumbItems = [ (
// Add home breadcrumbs to your head
extraBreadcrumbItems . unshift (
< Breadcrumb . Item key = "home" >
< Breadcrumb . Item key = "home" >
{ createElement ( linkElement , {
{ createElement ( linkElement , {
[ linkElement === 'a' ? 'href' : 'to' ] : '/' ,
[ linkElement === 'a' ? 'href' : 'to' ] : '/' } , '首页' ) }
} , '首页' ) }
< / B r e a d c r u m b . I t e m >
< / B r e a d c r u m b . I t e m >
) ] . concat ( extraBreadcrumbItems ) ;
) ;
breadcrumb = (
return (
< Breadcrumb className = { styles . breadcrumb } >
< Breadcrumb className = { styles . breadcrumb } >
{ b readcrumbItems }
{ extraB readcrumbItems}
< / B r e a d c r u m b >
< / B r e a d c r u m b >
) ;
) ;
} else {
}
breadcrumb = null ;
/ * *
* 将参数转化为面包屑
* Convert parameters into breadcrumbs
* /
conversionBreadcrumbList = ( ) => {
const { breadcrumbList } = this . props ;
const { routes , params , routerLocation , breadcrumbNameMap } = this . getBreadcrumbProps ( ) ;
if ( breadcrumbList && breadcrumbList . length ) {
return this . conversionFromProps ( ) ;
}
// 如果传入 routes 和 params 属性
// If pass routes and params attributes
if ( routes && params ) {
return (
< Breadcrumb
className = { styles . breadcrumb }
routes = { routes . filter ( route => route . breadcrumbName ) }
params = { params }
itemRender = { this . itemRender }
/ >
) ;
}
// 根据 location 生成 面包屑
// Generate breadcrumbs based on location
if ( location && location . pathname ) {
return this . conversionFromLocation ( routerLocation , breadcrumbNameMap ) ;
}
return null ;
}
// 渲染Breadcrumb 子节点
// Render the Breadcrumb child node
itemRender = ( route , params , routes , paths ) => {
const { linkElement = 'a' } = this . props ;
const last = routes . indexOf ( route ) === routes . length - 1 ;
return ( last || ! route . component )
? < span > { route . breadcrumbName } < / s p a n >
: createElement ( linkElement , {
href : paths . join ( '/' ) || '/' ,
to : paths . join ( '/' ) || '/' ,
} , route . breadcrumbName ) ;
}
}
render ( ) {
const {
title , logo , action , content , extraContent ,
tabList , className , tabActiveKey ,
} = this . props ;
const clsString = classNames ( styles . pageHeader , className ) ;
let tabDefaultValue ;
let tabDefaultValue ;
if ( tabActiveKey !== undefined && tabList ) {
if ( tabActiveKey !== undefined && tabList ) {
tabDefaultValue = tabList . filter ( item => item . default ) [ 0 ] || tabList [ 0 ] ;
tabDefaultValue = tabList . filter ( item => item . default ) [ 0 ] || tabList [ 0 ] ;
}
}
const breadcrumb = this . conversionBreadcrumbList ( ) ;
const activeKeyProps = {
const activeKeyProps = {
defaultActiveKey : tabDefaultValue && tabDefaultValue . key ,
defaultActiveKey : tabDefaultValue && tabDefaultValue . key ,
} ;
} ;