import React, { useContext, useEffect, useState } from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { UserContext } from '../context/User'; import { useSetTheme, useTheme } from '../context/Theme'; import { useTranslation } from 'react-i18next'; import { API, getLogo, getSystemName, showSuccess } from '../helpers'; import fireworks from 'react-fireworks'; import { CN, GB } from 'country-flag-icons/react/3x2'; import { IconClose, IconMenu, IconLanguage, IconChevronDown, IconSun, IconMoon, } from '@douyinfe/semi-icons'; import { Avatar, Button, Dropdown, Tag, Typography, Skeleton, } from '@douyinfe/semi-ui'; import { stringToColor } from '../helpers/render'; import { StatusContext } from '../context/Status/index.js'; import { StyleContext } from '../context/Style/index.js'; const HeaderBar = () => { const { t, i18n } = useTranslation(); const [userState, userDispatch] = useContext(UserContext); const [statusState, statusDispatch] = useContext(StatusContext); const [styleState, styleDispatch] = useContext(StyleContext); const [isLoading, setIsLoading] = useState(true); let navigate = useNavigate(); const [currentLang, setCurrentLang] = useState(i18n.language); const [mobileMenuOpen, setMobileMenuOpen] = useState(false); 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 theme = useTheme(); const setTheme = useSetTheme(); const mainNavLinks = [ { text: t('首页'), itemKey: 'home', to: '/', }, { text: t('控制台'), itemKey: 'detail', to: '/detail', }, { text: t('定价'), itemKey: 'pricing', to: '/pricing', }, ...(docsLink ? [ { text: t('文档'), itemKey: 'docs', isExternal: true, externalLink: docsLink, }, ] : []), { text: t('关于'), itemKey: 'about', to: '/about', }, ]; async function logout() { await API.get('/api/user/logout'); showSuccess(t('注销成功!')); userDispatch({ type: 'logout' }); localStorage.removeItem('user'); navigate('/login'); setMobileMenuOpen(false); } const handleNewYearClick = () => { fireworks.init('root', {}); fireworks.start(); setTimeout(() => { fireworks.stop(); }, 3000); }; useEffect(() => { if (theme === 'dark') { document.body.setAttribute('theme-mode', 'dark'); document.documentElement.classList.add('dark'); } else { document.body.removeAttribute('theme-mode'); document.documentElement.classList.remove('dark'); } const iframe = document.querySelector('iframe'); if (iframe) { iframe.contentWindow.postMessage({ themeMode: theme }, '*'); } }, [theme, isNewYear]); useEffect(() => { const handleLanguageChanged = (lng) => { setCurrentLang(lng); const iframe = document.querySelector('iframe'); if (iframe) { iframe.contentWindow.postMessage({ lang: lng }, '*'); } }; i18n.on('languageChanged', handleLanguageChanged); return () => { i18n.off('languageChanged', handleLanguageChanged); }; }, [i18n]); useEffect(() => { // 模拟加载用户状态的过程 const timer = setTimeout(() => { setIsLoading(false); }, 500); return () => clearTimeout(timer); }, []); const handleLanguageChange = (lang) => { i18n.changeLanguage(lang); setMobileMenuOpen(false); }; const handleNavLinkClick = (itemKey) => { if (itemKey === 'home') { styleDispatch({ type: 'SET_INNER_PADDING', payload: false }); styleDispatch({ type: 'SET_SIDER', payload: false }); } else { styleDispatch({ type: 'SET_INNER_PADDING', payload: true }); if (!styleState.isMobile) { styleDispatch({ type: 'SET_SIDER', payload: true }); } } setMobileMenuOpen(false); }; const renderNavLinks = (isMobileView = false) => mainNavLinks.map((link) => { const commonLinkClasses = isMobileView ? 'flex items-center gap-1 p-3 w-full text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors font-semibold' : 'flex items-center gap-1 p-2 text-sm text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors rounded-md font-semibold'; const linkContent = ( {link.text} ); if (link.isExternal) { return ( handleNavLinkClick(link.itemKey)} > {linkContent} ); } return ( handleNavLinkClick(link.itemKey)} > {linkContent} ); }); const renderUserArea = () => { if (isLoading) { return (
); } if (userState.user) { return ( {t('退出')} } > ); } else { const showRegisterButton = !isSelfUseMode; const commonSizingAndLayoutClass = "flex items-center justify-center !py-[10px] !px-1.5"; const loginButtonSpecificStyling = "!bg-semi-color-fill-0 dark:!bg-semi-color-fill-1 hover:!bg-semi-color-fill-1 dark:hover:!bg-gray-700 transition-colors"; let loginButtonClasses = `${commonSizingAndLayoutClass} ${loginButtonSpecificStyling}`; let registerButtonClasses = `${commonSizingAndLayoutClass}`; const loginButtonTextSpanClass = "!text-xs !text-semi-color-text-1 dark:!text-gray-300 !p-1.5"; const registerButtonTextSpanClass = "!text-xs !text-white !p-1.5"; if (showRegisterButton) { if (styleState.isMobile) { loginButtonClasses += " !rounded-full"; } else { loginButtonClasses += " !rounded-l-full !rounded-r-none"; } registerButtonClasses += " !rounded-r-full !rounded-l-none"; } else { loginButtonClasses += " !rounded-full"; } return (
handleNavLinkClick('login')} className="flex"> {showRegisterButton && (
handleNavLinkClick('register')} className="flex -ml-px">
)}
); } }; return (
handleNavLinkClick('home')} className="flex items-center gap-2 group ml-2"> logo
{systemName} {(isSelfUseMode || isDemoSiteMode) && ( {isSelfUseMode ? t('自用模式') : t('演示站点')} )}
{(isSelfUseMode || isDemoSiteMode) && (
{isSelfUseMode ? t('自用模式') : t('演示站点')}
)}
{isNewYear && ( Happy New Year!!! 🎉 } >
); }; export default HeaderBar;