import React, { PureComponent, createElement } from 'react'; import PropTypes from 'prop-types'; import pathToRegexp from 'path-to-regexp'; import { Breadcrumb, Tabs } from 'antd'; import classNames from 'classnames'; import styles from './index.less'; const { TabPane } = Tabs; function getBreadcrumb(breadcrumbNameMap, url) { let breadcrumb = breadcrumbNameMap[url]; if (!breadcrumb) { Object.keys(breadcrumbNameMap).forEach((item) => { if (pathToRegexp(item).test(url)) { breadcrumb = breadcrumbNameMap[item]; } }); } return breadcrumb || {}; } export default class PageHeader extends PureComponent { static contextTypes = { routes: PropTypes.array, params: PropTypes.object, location: PropTypes.object, breadcrumbNameMap: PropTypes.object, }; onChange = (key) => { if (this.props.onTabChange) { this.props.onTabChange(key); } }; getBreadcrumbProps = () => { return { routes: this.props.routes || this.context.routes, params: this.props.params || this.context.params, routerLocation: this.props.location || this.context.location, breadcrumbNameMap: this.props.breadcrumbNameMap || this.context.breadcrumbNameMap, }; }; // Generated according to props conversionFromProps= () => { const { breadcrumbList, breadcrumbSeparator, linkElement = 'a', } = this.props; return ( {breadcrumbList.map(item => ( {item.href ? (createElement(linkElement, { [linkElement === 'a' ? 'href' : 'to']: item.href, }, item.title)) : item.title} ))} ); } conversionFromLocation = (routerLocation, breadcrumbNameMap) => { const { breadcrumbSeparator, linkElement = 'a' } = this.props; // Convert the path to an array const pathSnippets = routerLocation.pathname.split('/').filter(i => i); // Loop data mosaic routing const extraBreadcrumbItems = pathSnippets.map((_, index) => { const url = `/${pathSnippets.slice(0, index + 1).join('/')}`; const currentBreadcrumb = getBreadcrumb(breadcrumbNameMap, url); const isLinkable = (index !== pathSnippets.length - 1) && currentBreadcrumb.component; return currentBreadcrumb.name && !currentBreadcrumb.hideInBreadcrumb ? ( {createElement( isLinkable ? linkElement : 'span', { [linkElement === 'a' ? 'href' : 'to']: url }, currentBreadcrumb.name, )} ) : null; }); // Add home breadcrumbs to your head extraBreadcrumbItems.unshift( {createElement(linkElement, { [linkElement === 'a' ? 'href' : 'to']: '/' }, '首页')} ); return ( {extraBreadcrumbItems} ); } /** * 将参数转化为面包屑 * Convert parameters into breadcrumbs */ conversionBreadcrumbList = () => { const { breadcrumbList, breadcrumbSeparator } = 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 ( route.breadcrumbName)} params={params} itemRender={this.itemRender} separator={breadcrumbSeparator} /> ); } // 根据 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) ? {route.breadcrumbName} : createElement(linkElement, { href: paths.join('/') || '/', to: paths.join('/') || '/', }, route.breadcrumbName); } render() { const { title, logo, action, content, extraContent, tabList, className, tabActiveKey, tabBarExtraContent, } = this.props; const clsString = classNames(styles.pageHeader, className); let tabDefaultValue; if (tabActiveKey !== undefined && tabList) { tabDefaultValue = tabList.filter(item => item.default)[0] || tabList[0]; } const breadcrumb = this.conversionBreadcrumbList(); const activeKeyProps = { defaultActiveKey: tabDefaultValue && tabDefaultValue.key, }; if (tabActiveKey !== undefined) { activeKeyProps.activeKey = tabActiveKey; } return ( {breadcrumb} {logo && {logo}} {title && {title}} {action && {action}} {content && {content}} {extraContent && {extraContent}} { tabList && tabList.length && ( { tabList.map(item => ) } ) } ); } }