Files
new-api/web/src/components/layout/PageLayout.js
2025-06-06 21:17:08 +08:00

164 lines
4.6 KiB
JavaScript

import HeaderBar from './HeaderBar.js';
import { Layout } from '@douyinfe/semi-ui';
import SiderBar from './SiderBar.js';
import App from '../../App.js';
import FooterBar from './Footer.js';
import { ToastContainer } from 'react-toastify';
import React, { useContext, useEffect } from 'react';
import { useStyle } from '../../context/Style/index.js';
import { useTranslation } from 'react-i18next';
import { API, getLogo, getSystemName, showError, setStatusData } from '../../helpers/index.js';
import { UserContext } from '../../context/User/index.js';
import { StatusContext } from '../../context/Status/index.js';
import { useLocation } from 'react-router-dom';
const { Sider, Content, Header, Footer } = Layout;
const PageLayout = () => {
const [userState, userDispatch] = useContext(UserContext);
const [statusState, statusDispatch] = useContext(StatusContext);
const { state: styleState } = useStyle();
const { i18n } = useTranslation();
const location = useLocation();
const shouldHideFooter = location.pathname === '/console/playground' || location.pathname.startsWith('/console/chat');
const shouldInnerPadding = location.pathname.includes('/console') &&
!location.pathname.startsWith('/console/chat') &&
location.pathname !== '/console/playground';
const loadUser = () => {
let user = localStorage.getItem('user');
if (user) {
let data = JSON.parse(user);
userDispatch({ type: 'login', payload: data });
}
};
const loadStatus = async () => {
try {
const res = await API.get('/api/status');
const { success, data } = res.data;
if (success) {
statusDispatch({ type: 'set', payload: data });
setStatusData(data);
} else {
showError('Unable to connect to server');
}
} catch (error) {
showError('Failed to load status');
}
};
useEffect(() => {
loadUser();
loadStatus().catch(console.error);
let systemName = getSystemName();
if (systemName) {
document.title = systemName;
}
let logo = getLogo();
if (logo) {
let linkElement = document.querySelector("link[rel~='icon']");
if (linkElement) {
linkElement.href = logo;
}
}
// 从localStorage获取上次使用的语言
const savedLang = localStorage.getItem('i18nextLng');
if (savedLang) {
i18n.changeLanguage(savedLang);
}
}, [i18n]);
return (
<Layout
style={{
height: '100vh',
display: 'flex',
flexDirection: 'column',
overflow: styleState.isMobile ? 'visible' : 'hidden',
}}
>
<Header
style={{
padding: 0,
height: 'auto',
lineHeight: 'normal',
position: 'fixed',
width: '100%',
top: 0,
zIndex: 100,
}}
>
<HeaderBar />
</Header>
<Layout
style={{
marginTop: '64px',
height: 'calc(100vh - 64px)',
overflow: styleState.isMobile ? 'visible' : 'auto',
display: 'flex',
flexDirection: 'column',
}}
>
{styleState.showSider && (
<Sider
style={{
position: 'fixed',
left: 0,
top: '64px',
zIndex: 99,
border: 'none',
paddingRight: '0',
height: 'calc(100vh - 64px)',
}}
>
<SiderBar />
</Sider>
)}
<Layout
style={{
marginLeft: styleState.isMobile
? '0'
: styleState.showSider
? styleState.siderCollapsed
? '60px'
: '180px'
: '0',
transition: 'margin-left 0.3s ease',
flex: '1 1 auto',
display: 'flex',
flexDirection: 'column',
}}
>
<Content
style={{
flex: '1 0 auto',
overflowY: styleState.isMobile ? 'visible' : 'auto',
WebkitOverflowScrolling: 'touch',
padding: shouldInnerPadding ? '24px' : '0',
position: 'relative',
marginTop: styleState.isMobile ? '2px' : '0',
}}
>
<App />
</Content>
{!shouldHideFooter && (
<Layout.Footer
style={{
flex: '0 0 auto',
width: '100%',
}}
>
<FooterBar />
</Layout.Footer>
)}
</Layout>
</Layout>
<ToastContainer />
</Layout>
);
};
export default PageLayout;