Files
toco-react-template/template/src/layout/index.tsx

97 lines
2.4 KiB
TypeScript
Raw Normal View History

2024-10-14 18:51:44 +08:00
import { setCurrentMenu, setHeadMenus } from '@/app/common';
import { useAppDispatch } from '@/app/hooks';
import SuspenseLayout from '@/components/suspense-layout';
import {
findFirstSubMenu,
findHeadMenuByHeadKey,
findHeadMenuBySideKey,
menuItems,
} from '@/utils/menu';
import { MenuProps } from '@df/toco-ui';
import { useCallback, useEffect } from 'react';
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
import Layout from './HeaderAndSider';
// import Layout from './HeaderAndFooter';
export type LayoutProps = {
children?: React.ReactNode;
onHeadMenuSelect?: MenuProps['onSelect'];
onSideMenuSelect?: MenuProps['onSelect'];
};
const LayoutRoot = () => {
const dispatch = useAppDispatch();
const location = useLocation();
const navigate = useNavigate();
// 设置head菜单
useEffect(() => {
dispatch(setHeadMenus(menuItems));
}, [dispatch]);
// 监听路由变化
useEffect(() => {
const key = location.pathname.replace(/^\//, '').replace(/\/$/, '');
const headMenu = findHeadMenuByHeadKey(key);
if (headMenu) {
// 一级页面
dispatch(
setCurrentMenu({
headKey: headMenu.key,
}),
);
} else {
// 非一级页面
const headMenu = findHeadMenuBySideKey(key);
dispatch(
setCurrentMenu({
headKey: headMenu?.key ?? '',
sideKey: key,
}),
);
}
}, [dispatch, location]);
const handleHeadMenuSelect: MenuProps['onSelect'] = useCallback(
({ item, key, keyPath, domEvent }) => {
const headMenu = findHeadMenuByHeadKey(key);
if (!headMenu) {
// 顶部嵌套的菜单即实际点击的sideMenu
navigate(key);
return;
}
if (!headMenu.children?.length) {
// 一级页面
navigate(key);
} else {
// 非一级页面点击一级菜单,主动跳转第一个子页面
const subMenu = findFirstSubMenu(headMenu);
if (subMenu) {
navigate(subMenu.key);
}
}
},
[navigate],
);
const handleSideMenuSelect: MenuProps['onSelect'] = useCallback(
({ item, key, keyPath, domEvent }) => {
navigate(key);
},
[navigate],
);
return (
<Layout
onHeadMenuSelect={handleHeadMenuSelect}
onSideMenuSelect={handleSideMenuSelect}
>
<SuspenseLayout>
<Outlet />
</SuspenseLayout>
</Layout>
);
};
export default LayoutRoot;