| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | 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; |
| |
|