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-15 16:58:54 +08:00
|
|
|
|
import type { BreadcrumbState } from '@/models/breadcrumb';
|
|
|
|
|
import { SupplierDetailModalProvider } from '@/components/SupplierDetailModalContext/SupplierDetailModalContext';
|
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
|
|
|
|
// 递归交集过滤函数
|
2025-07-15 16:58:54 +08:00
|
|
|
|
function filterMenuByRouter(routes: any, menuRoutes: any) {
|
|
|
|
|
return routes.reduce((result: any, route: any) => {
|
2025-07-15 09:07:43 +08:00
|
|
|
|
// 只看有 name 的节点
|
2025-07-15 16:58:54 +08:00
|
|
|
|
const menu = menuRoutes.find((m) => m.name === route.name);
|
2025-07-15 09:07:43 +08:00
|
|
|
|
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-15 16:58:54 +08:00
|
|
|
|
const BreadcrumbRender = (
|
|
|
|
|
routeBreadcrumb: any,
|
|
|
|
|
intl: any,
|
|
|
|
|
history: any,
|
|
|
|
|
dynamicBreadcrumbName: string | null,
|
|
|
|
|
) => {
|
2025-07-03 14:40:22 +08:00
|
|
|
|
const breadcrumbRoutes = routeBreadcrumb?.routes;
|
2025-07-01 14:18:23 +08:00
|
|
|
|
return (
|
|
|
|
|
<Breadcrumb>
|
|
|
|
|
<Breadcrumb.Item
|
|
|
|
|
onClick={() => {
|
|
|
|
|
history.push('/');
|
|
|
|
|
}}
|
|
|
|
|
>
|
2025-07-15 16:58:54 +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) => {
|
|
|
|
|
// 判断是否是最后一个面包屑项且存在动态名称
|
2025-07-15 16:58:54 +08:00
|
|
|
|
const isLastItem = index === breadcrumbRoutes.length - 1;
|
|
|
|
|
const displayName =
|
|
|
|
|
isLastItem && dynamicBreadcrumbName
|
|
|
|
|
? dynamicBreadcrumbName
|
|
|
|
|
: intl.formatMessage({ id: `menu.${item.breadcrumbName}` || '' });
|
2025-07-03 14:40:22 +08:00
|
|
|
|
|
2025-07-15 16:58:54 +08:00
|
|
|
|
return <Breadcrumb.Item key={item.path}>{displayName}</Breadcrumb.Item>;
|
2025-07-01 14:18:23 +08:00
|
|
|
|
})}
|
|
|
|
|
</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);
|
2025-07-15 16:58:54 +08:00
|
|
|
|
|
2025-07-15 09:07:43 +08:00
|
|
|
|
setMenuRoutes(finalMenus);
|
|
|
|
|
}
|
|
|
|
|
}, []);
|
|
|
|
|
|
2025-07-01 14:18:23 +08:00
|
|
|
|
return (
|
|
|
|
|
<ConfigProvider>
|
2025-07-15 16:58:54 +08:00
|
|
|
|
<SupplierDetailModalProvider>
|
|
|
|
|
<ProLayout
|
|
|
|
|
{...defaultSettings}
|
|
|
|
|
route={{ routes }}
|
|
|
|
|
// route={{ routes: menuRoutes }}
|
|
|
|
|
subMenuItemRender={(menuItemProps, defaultDom) => {
|
|
|
|
|
return MenuRender(menuItemProps, true);
|
|
|
|
|
}}
|
|
|
|
|
menuItemRender={(item, dom) => {
|
|
|
|
|
return MenuRender(item, false);
|
|
|
|
|
}}
|
|
|
|
|
location={location}
|
|
|
|
|
fixSiderbar
|
|
|
|
|
layout="mix"
|
|
|
|
|
headerRender={() => {
|
|
|
|
|
return <HeaderComponent />;
|
2025-07-01 14:18:23 +08:00
|
|
|
|
}}
|
|
|
|
|
>
|
2025-07-15 16:58:54 +08:00
|
|
|
|
<PageContainer
|
|
|
|
|
ghost={true}
|
|
|
|
|
header={{
|
|
|
|
|
title: false,
|
|
|
|
|
breadcrumbRender: ({ breadcrumb: routeBreadcrumb }) =>
|
|
|
|
|
BreadcrumbRender(routeBreadcrumb, intl, history, breadcrumb.breadcrumbName),
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{children}
|
|
|
|
|
</PageContainer>
|
|
|
|
|
</ProLayout>
|
|
|
|
|
</SupplierDetailModalProvider>
|
2025-07-01 14:18:23 +08:00
|
|
|
|
</ConfigProvider>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-03 14:40:22 +08:00
|
|
|
|
export default connect(({ breadcrumb }: { breadcrumb: BreadcrumbState }) => ({
|
2025-07-15 16:58:54 +08:00
|
|
|
|
breadcrumb,
|
2025-07-03 14:40:22 +08:00
|
|
|
|
}))(BasicLayout);
|