| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import { useState, useEffect, useContext, useCallback, useMemo } from 'react'; |
| | import { useNavigate, useLocation } from 'react-router-dom'; |
| | import { useTranslation } from 'react-i18next'; |
| | import { UserContext } from '../../context/User'; |
| | import { StatusContext } from '../../context/Status'; |
| | import { useSetTheme, useTheme, useActualTheme } from '../../context/Theme'; |
| | import { getLogo, getSystemName, API, showSuccess } from '../../helpers'; |
| | import { useIsMobile } from './useIsMobile'; |
| | import { useSidebarCollapsed } from './useSidebarCollapsed'; |
| | import { useMinimumLoadingTime } from './useMinimumLoadingTime'; |
| |
|
| | export const useHeaderBar = ({ onMobileMenuToggle, drawerOpen }) => { |
| | const { t, i18n } = useTranslation(); |
| | const [userState, userDispatch] = useContext(UserContext); |
| | const [statusState] = useContext(StatusContext); |
| | const isMobile = useIsMobile(); |
| | const [collapsed, toggleCollapsed] = useSidebarCollapsed(); |
| | const [logoLoaded, setLogoLoaded] = useState(false); |
| | const navigate = useNavigate(); |
| | const [currentLang, setCurrentLang] = useState(i18n.language); |
| | const location = useLocation(); |
| |
|
| | const loading = statusState?.status === undefined; |
| | const isLoading = useMinimumLoadingTime(loading, 200); |
| |
|
| | const systemName = getSystemName(); |
| | const logo = getLogo(); |
| | const currentDate = new Date(); |
| | const isNewYear = currentDate.getMonth() === 0 && currentDate.getDate() === 1; |
| |
|
| | const isSelfUseMode = statusState?.status?.self_use_mode_enabled || false; |
| | const docsLink = statusState?.status?.docs_link || ''; |
| | const isDemoSiteMode = statusState?.status?.demo_site_enabled || false; |
| |
|
| | |
| | const headerNavModulesConfig = statusState?.status?.HeaderNavModules; |
| |
|
| | |
| | const headerNavModules = useMemo(() => { |
| | if (headerNavModulesConfig) { |
| | try { |
| | const modules = JSON.parse(headerNavModulesConfig); |
| |
|
| | |
| | if (typeof modules.pricing === 'boolean') { |
| | modules.pricing = { |
| | enabled: modules.pricing, |
| | requireAuth: false, |
| | }; |
| | } |
| |
|
| | return modules; |
| | } catch (error) { |
| | console.error('解析顶栏模块配置失败:', error); |
| | return null; |
| | } |
| | } |
| | return null; |
| | }, [headerNavModulesConfig]); |
| |
|
| | |
| | const pricingRequireAuth = useMemo(() => { |
| | if (headerNavModules?.pricing) { |
| | return typeof headerNavModules.pricing === 'object' |
| | ? headerNavModules.pricing.requireAuth |
| | : false; |
| | } |
| | return false; |
| | }, [headerNavModules]); |
| |
|
| | const isConsoleRoute = location.pathname.startsWith('/console'); |
| |
|
| | const theme = useTheme(); |
| | const actualTheme = useActualTheme(); |
| | const setTheme = useSetTheme(); |
| |
|
| | |
| | useEffect(() => { |
| | setLogoLoaded(false); |
| | if (!logo) return; |
| | const img = new Image(); |
| | img.src = logo; |
| | img.onload = () => setLogoLoaded(true); |
| | }, [logo]); |
| |
|
| | |
| | useEffect(() => { |
| | try { |
| | const iframe = document.querySelector('iframe'); |
| | const cw = iframe && iframe.contentWindow; |
| | if (cw) { |
| | cw.postMessage({ themeMode: actualTheme }, '*'); |
| | } |
| | } catch (e) { |
| | |
| | } |
| | }, [actualTheme]); |
| |
|
| | |
| | useEffect(() => { |
| | const handleLanguageChanged = (lng) => { |
| | setCurrentLang(lng); |
| | try { |
| | const iframe = document.querySelector('iframe'); |
| | const cw = iframe && iframe.contentWindow; |
| | if (cw) { |
| | cw.postMessage({ lang: lng }, '*'); |
| | } |
| | } catch (e) { |
| | |
| | } |
| | }; |
| |
|
| | i18n.on('languageChanged', handleLanguageChanged); |
| | return () => { |
| | i18n.off('languageChanged', handleLanguageChanged); |
| | }; |
| | }, [i18n]); |
| |
|
| | |
| | const logout = useCallback(async () => { |
| | await API.get('/api/user/logout'); |
| | showSuccess(t('注销成功!')); |
| | userDispatch({ type: 'logout' }); |
| | localStorage.removeItem('user'); |
| | navigate('/login'); |
| | }, [navigate, t, userDispatch]); |
| |
|
| | const handleLanguageChange = useCallback( |
| | (lang) => { |
| | i18n.changeLanguage(lang); |
| | }, |
| | [i18n], |
| | ); |
| |
|
| | const handleThemeToggle = useCallback( |
| | (newTheme) => { |
| | if ( |
| | !newTheme || |
| | (newTheme !== 'light' && newTheme !== 'dark' && newTheme !== 'auto') |
| | ) { |
| | return; |
| | } |
| | setTheme(newTheme); |
| | }, |
| | [setTheme], |
| | ); |
| |
|
| | const handleMobileMenuToggle = useCallback(() => { |
| | if (isMobile) { |
| | onMobileMenuToggle(); |
| | } else { |
| | toggleCollapsed(); |
| | } |
| | }, [isMobile, onMobileMenuToggle, toggleCollapsed]); |
| |
|
| | return { |
| | |
| | userState, |
| | statusState, |
| | isMobile, |
| | collapsed, |
| | logoLoaded, |
| | currentLang, |
| | location, |
| | isLoading, |
| | systemName, |
| | logo, |
| | isNewYear, |
| | isSelfUseMode, |
| | docsLink, |
| | isDemoSiteMode, |
| | isConsoleRoute, |
| | theme, |
| | drawerOpen, |
| | headerNavModules, |
| | pricingRequireAuth, |
| |
|
| | |
| | logout, |
| | handleLanguageChange, |
| | handleThemeToggle, |
| | handleMobileMenuToggle, |
| | navigate, |
| | t, |
| | }; |
| | }; |
| |
|