// src/layouts/BasicLayout.tsx import React, { useState, useEffect } from 'react'; import ProLayout, { PageContainer } from '@ant-design/pro-layout'; import { Link, useLocation, useIntl } from 'umi'; import { connect } from 'dva'; import defaultSettings from '../../config/defaultSettings'; import routes from '../../config/router.config'; import { ConfigProvider, Breadcrumb } from 'antd'; import HeaderComponent from './Header'; import IconFont from '@/components/IconFont/IconFont'; import type { BreadcrumbState } from '@/models/breadcrumb'; import type { TabModelState } from '@/models/tab'; import { SupplierDetailModalProvider } from '@/components/SupplierDetailModalContext/SupplierDetailModalContext'; const MenuRender = (item: any, isSubMenu: boolean) => { const intl = useIntl(); return ( <> {isSubMenu ? ( {intl.formatMessage({ id: `menu.${item.name}` || '' })} ) : ( {intl.formatMessage({ id: `menu.${item.name}` || '' })} )} ); }; const BreadcrumbRender = ( routeBreadcrumb: any, intl: any, history: any, dynamicBreadcrumbName: string | null, ) => { const breadcrumbRoutes = routeBreadcrumb?.routes; return ( { history.push('/'); }} > {intl.formatMessage({ id: 'menu.首页' })} {breadcrumbRoutes?.map((item: any, index: number) => { // 判断是否是最后一个面包屑项且存在动态名称 const isLastItem = index === breadcrumbRoutes.length - 1; const displayName = isLastItem && dynamicBreadcrumbName ? dynamicBreadcrumbName : intl.formatMessage({ id: `menu.${item.breadcrumbName}` || '' }); return {displayName}; })} ); }; interface BasicLayoutProps { children: React.ReactNode; breadcrumb: BreadcrumbState; tab: TabModelState; dispatch: any; } function convertMenuData(menus: any[]): any[] { return menus.map(item => { // 保留 icon 字段,如果没有就给默认 const icon = item.icon || undefined; // 递归 children->routes let routes; if (item.routes && item.routes.length > 0) { routes = convertMenuData(item.routes); } // 国际化优先找 menu.name,否则直接显示 name return { ...item, icon, routes, // prolayout 只认 routes name: item.name, // 不要转 menu.xxx,MenuRender 时才转 }; }); } // 新增递归过滤函数 function filterMenusByLocalConfig(localMenus: any[], remoteMenus: any[], isRoot = true): any[] { if (!Array.isArray(localMenus) || !Array.isArray(remoteMenus)) return []; // 只在第一次递归时找 path: '/' 节点 if (isRoot) { const rootMenu = localMenus.find(m => m.path === '/' && Array.isArray(m.routes)); if (!rootMenu) return []; const filteredRoutes = filterMenusByLocalConfig(rootMenu.routes, remoteMenus, false); return [{ ...rootMenu, routes: filteredRoutes, }]; } // 子级对比,只需要对比 path 就行 const remotePathSet = new Set(remoteMenus.map(r => r.path).filter(Boolean)); return (localMenus as any[]).filter(local => local.path && remotePathSet.has(local.path) ).map(local => { const remote = remoteMenus.find(r => r.path === local.path); const localChildren = local.children || local.routes; const remoteChildren = remote?.children || remote?.routes; let newChildren: any[] = []; if ( localChildren && localChildren.length > 0 && remoteChildren && remoteChildren.length > 0 ) { newChildren = filterMenusByLocalConfig(localChildren, remoteChildren, false); } const node = { ...local }; if (local.children) { if (newChildren.length > 0) node.children = newChildren; else delete node.children; } if (local.routes) { if (newChildren.length > 0) node.routes = newChildren; else delete node.routes; } return node; }); } const BasicLayout: React.FC = (props) => { const { children, tab, dispatch } = props; const location = useLocation(); const intl = useIntl(); const handleTabChange = (key: string) => { dispatch({ type: 'tab/switchTab', payload: { key }, }); }; const handleTabEdit = (targetKey: any, action: string) => { if (action === 'remove') { dispatch({ type: 'tab/closeTab', payload: { key: targetKey }, }); } }; const [menuRoutes, setMenuRoutes] = useState([]); useEffect(() => { const menuStr = sessionStorage.getItem('menuList'); if (menuStr) { const menus = JSON.parse(menuStr); const filteredMenus = filterMenusByLocalConfig(routes, menus); console.log(filteredMenus,'filteredMenus'); const hasPersonalInfo = filteredMenus.some(item => item.path === '/PersonalInfo'); if (!hasPersonalInfo) { filteredMenus.push({ path: '/PersonalInfo', name: "个人中心", icon: 'icon-shouye', component: '@/pages/PersonalInfo', hideInMenu: true }); } setMenuRoutes(convertMenuData(filteredMenus)); } }, []); if (menuRoutes.length === 0) return null; return ( undefined} subMenuItemRender={(menuItemProps, defaultDom) => { return MenuRender(menuItemProps, true); }} menuItemRender={(item, dom) => { return MenuRender(item, false); }} location={location} fixSiderbar layout="mix" headerRender={() => { return ; }} > null, // breadcrumbRender: ({ breadcrumb: routeBreadcrumb }) => // BreadcrumbRender(routeBreadcrumb, intl, history, breadcrumb.breadcrumbName), }} // 将tab.tabList转换为需要的格式,添加国际化处理 tabList={tab.tabList.map((item) => ({ ...item, tab: typeof item.tab === 'string' ? intl.formatMessage({ id: `menu.${item.tab}` }) : item.tab, }))} tabProps={{ type: 'editable-card', hideAdd: true, activeKey: tab.activeKey, onChange: handleTabChange, onEdit: handleTabEdit, size: 'small', tabBarGutter: 6, renderTabBar: (propsTab, DefaultTabBar) => ( ), }} > {children} ); }; export default connect( ({ breadcrumb, tab }: { breadcrumb: BreadcrumbState; tab: TabModelState }) => ({ breadcrumb, tab, }), )(BasicLayout);