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