Files
toco-react-template/src/layout/index.tsx
2025-05-06 15:57:04 +08:00

88 lines
2.3 KiB
TypeScript

import { Theme } from '@/app/enum';
import { useAppSelector } from '@/app/hooks';
import globalMessage from '@/app/message';
import { SettingOutlined } from '@ant-design/icons';
import { App, Button, Image, Popover } from '@toco-design/components';
import classNames from 'classnames';
import { useCallback, useEffect, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import styles from './index.module.css';
import { HeaderOnly, HeaderSider, SiderOnly } from './layouts';
import Settings from './settings';
import SuspenseLayout from './suspense-layout';
export enum LayoutType {
Default = 0,
Header = 1 << 1,
Sider = 1 << 2,
}
type LayoutProps = {
type?: LayoutType;
};
const Layout: React.FC<LayoutProps> = (props) => {
const { type: typeProp } = props;
const theme = useAppSelector((state) => state.common.theme);
const navigate = useNavigate();
const { message } = App.useApp();
useEffect(() => {
globalMessage.setMessage(message);
}, [message]);
const Component = useMemo(() => {
const type = typeProp ?? LayoutType.Default;
const hasHeader = type & LayoutType.Header;
const hasSider = type & LayoutType.Sider;
if (hasHeader && hasSider) {
return HeaderSider;
} else if (hasHeader) {
return HeaderOnly;
} else if (hasSider) {
return SiderOnly;
}
return HeaderSider;
}, [typeProp]);
const gotoHome = useCallback(() => {
navigate('/');
}, [navigate]);
return (
<SuspenseLayout>
<Component
theme={theme}
siderWidth={250}
logo={
<div
className={classNames(styles.logo, { dark: theme === Theme.DARK })}
onClick={gotoHome}
>
<Image
className={styles.icon}
preview={false}
src={
process.env.PUBLIC_URL +
(theme === Theme.DEFAULT ? '/logo.png' : '/logo_dark.png')
}
/>
</div>
}
extra={
<div
className={classNames(styles.extra, { dark: theme === Theme.DARK })}
>
<Popover content={<Settings />}>
<Button type="text">
<SettingOutlined />
</Button>
</Popover>
</div>
}
/>
</SuspenseLayout>
);
};
export default Layout;