Files
fe_supplier_frontend/src/layouts/BasicLayout.tsx

153 lines
4.7 KiB
TypeScript
Raw Normal View History

2025-07-01 14:18:23 +08:00
// src/layouts/BasicLayout.tsx
2025-07-15 09:07:43 +08:00
import React, { useEffect, useState } from 'react';
2025-07-01 14:18:23 +08:00
import ProLayout, { PageContainer } from '@ant-design/pro-layout';
import { Link, useLocation, useIntl, useHistory } from 'umi';
2025-07-03 14:40:22 +08:00
import { connect } from 'dva';
2025-07-01 14:18:23 +08:00
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';
2025-07-03 14:40:22 +08:00
import { BreadcrumbState } from '@/models/breadcrumb';
2025-07-01 14:18:23 +08:00
const MenuRender = (item: any, isSubMenu: boolean) => {
const intl = useIntl();
return (
<>
{isSubMenu ? (
<span className="ant-pro-menu-item">
<IconFont type={item.icon as string} />
<span className="ant-pro-menu-item-title">
{intl.formatMessage({ id: `menu.${item.name}` || '' })}
</span>
</span>
) : (
<Link className="ant-pro-menu-item" key={item.path} to={item.path || '/'} innerRef={null}>
<IconFont type={item.icon as string} />
<span className="ant-pro-menu-item-title">
{intl.formatMessage({ id: `menu.${item.name}` || '' })}
</span>
</Link>
)}
</>
);
};
2025-07-15 09:07:43 +08:00
// 递归交集过滤函数
function filterMenuByRouter(routes:any, menuRoutes:any) {
return routes.reduce((result:any, route:any) => {
// 只看有 name 的节点
const menu = menuRoutes.find(m => m.name === route.name);
if (menu) {
// 匹配到后,递归处理 children
let children = [];
if (route.children && menu.children) {
children = filterMenuByRouter(route.children, menu.children);
}
// 构建新节点,保留原 router.config.ts 路径等信息(比如 path, icon, ...其它字段)
result.push({
...route,
// ...menu, // 可按需决定是否 menu 字段覆盖 route 字段(比如 path
// children: children.length > 0 ? children : undefined
});
}
return result;
}, []);
}
2025-07-03 14:40:22 +08:00
const BreadcrumbRender = (routeBreadcrumb: any, intl: any, history: any, dynamicBreadcrumbName: string | null) => {
const breadcrumbRoutes = routeBreadcrumb?.routes;
2025-07-01 14:18:23 +08:00
return (
<Breadcrumb>
<Breadcrumb.Item
onClick={() => {
history.push('/');
}}
>
2025-07-03 14:40:22 +08:00
<span style={{ cursor: 'pointer' }}>
{intl.formatMessage({ id: 'menu.首页' })}
</span>
2025-07-01 14:18:23 +08:00
</Breadcrumb.Item>
2025-07-03 14:40:22 +08:00
{breadcrumbRoutes?.map((item: any, index: number) => {
// 判断是否是最后一个面包屑项且存在动态名称
const isLastItem = index === (breadcrumbRoutes.length - 1);
const displayName = (isLastItem && dynamicBreadcrumbName)
? dynamicBreadcrumbName
: intl.formatMessage({ id: `menu.${item.breadcrumbName}` || '' });
2025-07-01 14:18:23 +08:00
return (
<Breadcrumb.Item key={item.path}>
2025-07-03 14:40:22 +08:00
{displayName}
2025-07-01 14:18:23 +08:00
</Breadcrumb.Item>
);
})}
</Breadcrumb>
);
};
2025-07-03 14:40:22 +08:00
interface BasicLayoutProps {
children: React.ReactNode;
breadcrumb: BreadcrumbState;
}
const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
const { children, breadcrumb } = props;
2025-07-01 14:18:23 +08:00
const location = useLocation();
const intl = useIntl();
const history = useHistory();
2025-07-15 09:07:43 +08:00
const [menuRoutes, setMenuRoutes] = useState<any[]>([]);
useEffect(() => {
const menuStr = sessionStorage.getItem('menuList');
if (menuStr) {
const menusFromApi = JSON.parse(menuStr);
// routes是本地静态路由menusFromApi是接口菜单
const finalMenus = filterMenuByRouter(routes, menusFromApi);
console.log(finalMenus);
setMenuRoutes(finalMenus);
}
}, []);
2025-07-01 14:18:23 +08:00
return (
<ConfigProvider>
<ProLayout
{...defaultSettings}
route={{ routes }}
2025-07-15 09:07:43 +08:00
// route={{ routes: menuRoutes }}
2025-07-01 14:18:23 +08:00
subMenuItemRender={(menuItemProps, defaultDom) => {
return MenuRender(menuItemProps, true);
}}
menuItemRender={(item, dom) => {
return MenuRender(item, false);
}}
location={location}
fixSiderbar
layout="mix"
headerRender={() => {
return <HeaderComponent />;
}}
>
<PageContainer
ghost={true}
header={{
title: false,
2025-07-03 14:40:22 +08:00
breadcrumbRender: ({ breadcrumb: routeBreadcrumb }) =>
BreadcrumbRender(routeBreadcrumb, intl, history, breadcrumb.breadcrumbName),
2025-07-01 14:18:23 +08:00
}}
>
2025-07-03 14:40:22 +08:00
{children}
2025-07-01 14:18:23 +08:00
</PageContainer>
</ProLayout>
</ConfigProvider>
);
};
2025-07-03 14:40:22 +08:00
export default connect(({ breadcrumb }: { breadcrumb: BreadcrumbState }) => ({
breadcrumb
}))(BasicLayout);