|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import HeaderBar from './headerbar'; |
|
|
import { Layout } from '@douyinfe/semi-ui'; |
|
|
import SiderBar from './SiderBar'; |
|
|
import App from '../../App'; |
|
|
import FooterBar from './Footer'; |
|
|
import { ToastContainer } from 'react-toastify'; |
|
|
import React, { useContext, useEffect, useState } from 'react'; |
|
|
import { useIsMobile } from '../../hooks/common/useIsMobile'; |
|
|
import { useSidebarCollapsed } from '../../hooks/common/useSidebarCollapsed'; |
|
|
import { useTranslation } from 'react-i18next'; |
|
|
import { |
|
|
API, |
|
|
getLogo, |
|
|
getSystemName, |
|
|
showError, |
|
|
setStatusData, |
|
|
} from '../../helpers'; |
|
|
import { UserContext } from '../../context/User'; |
|
|
import { StatusContext } from '../../context/Status'; |
|
|
import { useLocation } from 'react-router-dom'; |
|
|
const { Sider, Content, Header } = Layout; |
|
|
|
|
|
const PageLayout = () => { |
|
|
const [, userDispatch] = useContext(UserContext); |
|
|
const [, statusDispatch] = useContext(StatusContext); |
|
|
const isMobile = useIsMobile(); |
|
|
const [collapsed, , setCollapsed] = useSidebarCollapsed(); |
|
|
const [drawerOpen, setDrawerOpen] = useState(false); |
|
|
const { i18n } = useTranslation(); |
|
|
const location = useLocation(); |
|
|
|
|
|
const cardProPages = [ |
|
|
'/console/channel', |
|
|
'/console/log', |
|
|
'/console/redemption', |
|
|
'/console/user', |
|
|
'/console/token', |
|
|
'/console/midjourney', |
|
|
'/console/task', |
|
|
'/console/models', |
|
|
'/pricing', |
|
|
]; |
|
|
|
|
|
const shouldHideFooter = cardProPages.includes(location.pathname); |
|
|
|
|
|
const shouldInnerPadding = |
|
|
location.pathname.includes('/console') && |
|
|
!location.pathname.startsWith('/console/chat') && |
|
|
location.pathname !== '/console/playground'; |
|
|
|
|
|
const isConsoleRoute = location.pathname.startsWith('/console'); |
|
|
const showSider = isConsoleRoute && (!isMobile || drawerOpen); |
|
|
|
|
|
useEffect(() => { |
|
|
if (isMobile && drawerOpen && collapsed) { |
|
|
setCollapsed(false); |
|
|
} |
|
|
}, [isMobile, drawerOpen, collapsed, setCollapsed]); |
|
|
|
|
|
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; |
|
|
} |
|
|
} |
|
|
const savedLang = localStorage.getItem('i18nextLng'); |
|
|
if (savedLang) { |
|
|
i18n.changeLanguage(savedLang); |
|
|
} |
|
|
}, [i18n]); |
|
|
|
|
|
return ( |
|
|
<Layout |
|
|
style={{ |
|
|
height: '100vh', |
|
|
display: 'flex', |
|
|
flexDirection: 'column', |
|
|
overflow: isMobile ? 'visible' : 'hidden', |
|
|
}} |
|
|
> |
|
|
<Header |
|
|
style={{ |
|
|
padding: 0, |
|
|
height: 'auto', |
|
|
lineHeight: 'normal', |
|
|
position: 'fixed', |
|
|
width: '100%', |
|
|
top: 0, |
|
|
zIndex: 100, |
|
|
}} |
|
|
> |
|
|
<HeaderBar |
|
|
onMobileMenuToggle={() => setDrawerOpen((prev) => !prev)} |
|
|
drawerOpen={drawerOpen} |
|
|
/> |
|
|
</Header> |
|
|
<Layout |
|
|
style={{ |
|
|
overflow: isMobile ? 'visible' : 'auto', |
|
|
display: 'flex', |
|
|
flexDirection: 'column', |
|
|
}} |
|
|
> |
|
|
{showSider && ( |
|
|
<Sider |
|
|
style={{ |
|
|
position: 'fixed', |
|
|
left: 0, |
|
|
top: '64px', |
|
|
zIndex: 99, |
|
|
border: 'none', |
|
|
paddingRight: '0', |
|
|
height: 'calc(100vh - 64px)', |
|
|
width: 'var(--sidebar-current-width)', |
|
|
}} |
|
|
> |
|
|
<SiderBar |
|
|
onNavigate={() => { |
|
|
if (isMobile) setDrawerOpen(false); |
|
|
}} |
|
|
/> |
|
|
</Sider> |
|
|
)} |
|
|
<Layout |
|
|
style={{ |
|
|
marginLeft: isMobile |
|
|
? '0' |
|
|
: showSider |
|
|
? 'var(--sidebar-current-width)' |
|
|
: '0', |
|
|
flex: '1 1 auto', |
|
|
display: 'flex', |
|
|
flexDirection: 'column', |
|
|
}} |
|
|
> |
|
|
<Content |
|
|
style={{ |
|
|
flex: '1 0 auto', |
|
|
overflowY: isMobile ? 'visible' : 'hidden', |
|
|
WebkitOverflowScrolling: 'touch', |
|
|
padding: shouldInnerPadding ? (isMobile ? '5px' : '24px') : '0', |
|
|
position: 'relative', |
|
|
}} |
|
|
> |
|
|
<App /> |
|
|
</Content> |
|
|
{!shouldHideFooter && ( |
|
|
<Layout.Footer |
|
|
style={{ |
|
|
flex: '0 0 auto', |
|
|
width: '100%', |
|
|
}} |
|
|
> |
|
|
<FooterBar /> |
|
|
</Layout.Footer> |
|
|
)} |
|
|
</Layout> |
|
|
</Layout> |
|
|
<ToastContainer /> |
|
|
</Layout> |
|
|
); |
|
|
}; |
|
|
|
|
|
export default PageLayout; |
|
|
|