Просмотр исходного кода

fix(web/layout): normalize HeaderBar -> headerbar (case)

t0ng7u 6 месяцев назад
Родитель
Сommit
5cbd9da3f5

+ 0 - 74
web/src/components/layout/HeaderBar/ActionButtons.jsx

@@ -1,74 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React from 'react';
-import NewYearButton from './NewYearButton';
-import NotificationButton from './NotificationButton';
-import ThemeToggle from './ThemeToggle';
-import LanguageSelector from './LanguageSelector';
-import UserArea from './UserArea';
-
-const ActionButtons = ({
-  isNewYear,
-  unreadCount,
-  onNoticeOpen,
-  theme,
-  onThemeToggle,
-  currentLang,
-  onLanguageChange,
-  userState,
-  isLoading,
-  isMobile,
-  isSelfUseMode,
-  logout,
-  navigate,
-  t,
-}) => {
-  return (
-    <div className='flex items-center gap-2 md:gap-3'>
-      <NewYearButton isNewYear={isNewYear} />
-
-      <NotificationButton
-        unreadCount={unreadCount}
-        onNoticeOpen={onNoticeOpen}
-        t={t}
-      />
-
-      <ThemeToggle theme={theme} onThemeToggle={onThemeToggle} t={t} />
-
-      <LanguageSelector
-        currentLang={currentLang}
-        onLanguageChange={onLanguageChange}
-        t={t}
-      />
-
-      <UserArea
-        userState={userState}
-        isLoading={isLoading}
-        isMobile={isMobile}
-        isSelfUseMode={isSelfUseMode}
-        logout={logout}
-        navigate={navigate}
-        t={t}
-      />
-    </div>
-  );
-};
-
-export default ActionButtons;

+ 0 - 81
web/src/components/layout/HeaderBar/HeaderLogo.jsx

@@ -1,81 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React from 'react';
-import { Link } from 'react-router-dom';
-import { Typography, Tag } from '@douyinfe/semi-ui';
-import SkeletonWrapper from '../components/SkeletonWrapper';
-
-const HeaderLogo = ({
-  isMobile,
-  isConsoleRoute,
-  logo,
-  logoLoaded,
-  isLoading,
-  systemName,
-  isSelfUseMode,
-  isDemoSiteMode,
-  t,
-}) => {
-  if (isMobile && isConsoleRoute) {
-    return null;
-  }
-
-  return (
-    <Link to='/' className='group flex items-center gap-2'>
-      <div className='relative w-8 h-8 md:w-8 md:h-8'>
-        <SkeletonWrapper loading={isLoading || !logoLoaded} type='image' />
-        <img
-          src={logo}
-          alt='logo'
-          className={`absolute inset-0 w-full h-full transition-all duration-200 group-hover:scale-110 rounded-full ${!isLoading && logoLoaded ? 'opacity-100' : 'opacity-0'}`}
-        />
-      </div>
-      <div className='hidden md:flex items-center gap-2'>
-        <div className='flex items-center gap-2'>
-          <SkeletonWrapper
-            loading={isLoading}
-            type='title'
-            width={120}
-            height={24}
-          >
-            <Typography.Title
-              heading={4}
-              className='!text-lg !font-semibold !mb-0'
-            >
-              {systemName}
-            </Typography.Title>
-          </SkeletonWrapper>
-          {(isSelfUseMode || isDemoSiteMode) && !isLoading && (
-            <Tag
-              color={isSelfUseMode ? 'purple' : 'blue'}
-              className='text-xs px-1.5 py-0.5 rounded whitespace-nowrap shadow-sm'
-              size='small'
-              shape='circle'
-            >
-              {isSelfUseMode ? t('自用模式') : t('演示站点')}
-            </Tag>
-          )}
-        </div>
-      </div>
-    </Link>
-  );
-};
-
-export default HeaderLogo;

+ 0 - 59
web/src/components/layout/HeaderBar/LanguageSelector.jsx

@@ -1,59 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React from 'react';
-import { Button, Dropdown } from '@douyinfe/semi-ui';
-import { Languages } from 'lucide-react';
-import { CN, GB } from 'country-flag-icons/react/3x2';
-
-const LanguageSelector = ({ currentLang, onLanguageChange, t }) => {
-  return (
-    <Dropdown
-      position='bottomRight'
-      render={
-        <Dropdown.Menu className='!bg-semi-color-bg-overlay !border-semi-color-border !shadow-lg !rounded-lg dark:!bg-gray-700 dark:!border-gray-600'>
-          <Dropdown.Item
-            onClick={() => onLanguageChange('zh')}
-            className={`!flex !items-center !gap-2 !px-3 !py-1.5 !text-sm !text-semi-color-text-0 dark:!text-gray-200 ${currentLang === 'zh' ? '!bg-semi-color-primary-light-default dark:!bg-blue-600 !font-semibold' : 'hover:!bg-semi-color-fill-1 dark:hover:!bg-gray-600'}`}
-          >
-            <CN title='中文' className='!w-5 !h-auto' />
-            <span>中文</span>
-          </Dropdown.Item>
-          <Dropdown.Item
-            onClick={() => onLanguageChange('en')}
-            className={`!flex !items-center !gap-2 !px-3 !py-1.5 !text-sm !text-semi-color-text-0 dark:!text-gray-200 ${currentLang === 'en' ? '!bg-semi-color-primary-light-default dark:!bg-blue-600 !font-semibold' : 'hover:!bg-semi-color-fill-1 dark:hover:!bg-gray-600'}`}
-          >
-            <GB title='English' className='!w-5 !h-auto' />
-            <span>English</span>
-          </Dropdown.Item>
-        </Dropdown.Menu>
-      }
-    >
-      <Button
-        icon={<Languages size={18} />}
-        aria-label={t('切换语言')}
-        theme='borderless'
-        type='tertiary'
-        className='!p-1.5 !text-current focus:!bg-semi-color-fill-1 dark:focus:!bg-gray-700 !rounded-full !bg-semi-color-fill-0 dark:!bg-semi-color-fill-1 hover:!bg-semi-color-fill-1 dark:hover:!bg-semi-color-fill-2'
-      />
-    </Dropdown>
-  );
-};
-
-export default LanguageSelector;

+ 0 - 56
web/src/components/layout/HeaderBar/MobileMenuButton.jsx

@@ -1,56 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React from 'react';
-import { Button } from '@douyinfe/semi-ui';
-import { IconClose, IconMenu } from '@douyinfe/semi-icons';
-
-const MobileMenuButton = ({
-  isConsoleRoute,
-  isMobile,
-  drawerOpen,
-  collapsed,
-  onToggle,
-  t,
-}) => {
-  if (!isConsoleRoute || !isMobile) {
-    return null;
-  }
-
-  return (
-    <Button
-      icon={
-        (isMobile ? drawerOpen : collapsed) ? (
-          <IconClose className='text-lg' />
-        ) : (
-          <IconMenu className='text-lg' />
-        )
-      }
-      aria-label={
-        (isMobile ? drawerOpen : collapsed) ? t('关闭侧边栏') : t('打开侧边栏')
-      }
-      onClick={onToggle}
-      theme='borderless'
-      type='tertiary'
-      className='!p-2 !text-current focus:!bg-semi-color-fill-1 dark:focus:!bg-gray-700'
-    />
-  );
-};
-
-export default MobileMenuButton;

+ 0 - 88
web/src/components/layout/HeaderBar/Navigation.jsx

@@ -1,88 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React from 'react';
-import { Link } from 'react-router-dom';
-import SkeletonWrapper from '../components/SkeletonWrapper';
-
-const Navigation = ({
-  mainNavLinks,
-  isMobile,
-  isLoading,
-  userState,
-  pricingRequireAuth,
-}) => {
-  const renderNavLinks = () => {
-    const baseClasses =
-      'flex-shrink-0 flex items-center gap-1 font-semibold rounded-md transition-all duration-200 ease-in-out';
-    const hoverClasses = 'hover:text-semi-color-primary';
-    const spacingClasses = isMobile ? 'p-1' : 'p-2';
-
-    const commonLinkClasses = `${baseClasses} ${spacingClasses} ${hoverClasses}`;
-
-    return mainNavLinks.map((link) => {
-      const linkContent = <span>{link.text}</span>;
-
-      if (link.isExternal) {
-        return (
-          <a
-            key={link.itemKey}
-            href={link.externalLink}
-            target='_blank'
-            rel='noopener noreferrer'
-            className={commonLinkClasses}
-          >
-            {linkContent}
-          </a>
-        );
-      }
-
-      let targetPath = link.to;
-      if (link.itemKey === 'console' && !userState.user) {
-        targetPath = '/login';
-      }
-      if (link.itemKey === 'pricing' && pricingRequireAuth && !userState.user) {
-        targetPath = '/login';
-      }
-
-      return (
-        <Link key={link.itemKey} to={targetPath} className={commonLinkClasses}>
-          {linkContent}
-        </Link>
-      );
-    });
-  };
-
-  return (
-    <nav className='flex flex-1 items-center gap-1 lg:gap-2 mx-2 md:mx-4 overflow-x-auto whitespace-nowrap scrollbar-hide'>
-      <SkeletonWrapper
-        loading={isLoading}
-        type='navigation'
-        count={4}
-        width={60}
-        height={16}
-        isMobile={isMobile}
-      >
-        {renderNavLinks()}
-      </SkeletonWrapper>
-    </nav>
-  );
-};
-
-export default Navigation;

+ 0 - 62
web/src/components/layout/HeaderBar/NewYearButton.jsx

@@ -1,62 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React from 'react';
-import { Button, Dropdown } from '@douyinfe/semi-ui';
-import fireworks from 'react-fireworks';
-
-const NewYearButton = ({ isNewYear }) => {
-  if (!isNewYear) {
-    return null;
-  }
-
-  const handleNewYearClick = () => {
-    fireworks.init('root', {});
-    fireworks.start();
-    setTimeout(() => {
-      fireworks.stop();
-    }, 3000);
-  };
-
-  return (
-    <Dropdown
-      position='bottomRight'
-      render={
-        <Dropdown.Menu className='!bg-semi-color-bg-overlay !border-semi-color-border !shadow-lg !rounded-lg dark:!bg-gray-700 dark:!border-gray-600'>
-          <Dropdown.Item
-            onClick={handleNewYearClick}
-            className='!text-semi-color-text-0 hover:!bg-semi-color-fill-1 dark:!text-gray-200 dark:hover:!bg-gray-600'
-          >
-            Happy New Year!!! 🎉
-          </Dropdown.Item>
-        </Dropdown.Menu>
-      }
-    >
-      <Button
-        theme='borderless'
-        type='tertiary'
-        icon={<span className='text-xl'>🎉</span>}
-        aria-label='New Year'
-        className='!p-1.5 !text-current focus:!bg-semi-color-fill-1 dark:focus:!bg-gray-700 rounded-full'
-      />
-    </Dropdown>
-  );
-};
-
-export default NewYearButton;

+ 0 - 46
web/src/components/layout/HeaderBar/NotificationButton.jsx

@@ -1,46 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React from 'react';
-import { Button, Badge } from '@douyinfe/semi-ui';
-import { Bell } from 'lucide-react';
-
-const NotificationButton = ({ unreadCount, onNoticeOpen, t }) => {
-  const buttonProps = {
-    icon: <Bell size={18} />,
-    'aria-label': t('系统公告'),
-    onClick: onNoticeOpen,
-    theme: 'borderless',
-    type: 'tertiary',
-    className:
-      '!p-1.5 !text-current focus:!bg-semi-color-fill-1 dark:focus:!bg-gray-700 !rounded-full !bg-semi-color-fill-0 dark:!bg-semi-color-fill-1 hover:!bg-semi-color-fill-1 dark:hover:!bg-semi-color-fill-2',
-  };
-
-  if (unreadCount > 0) {
-    return (
-      <Badge count={unreadCount} type='danger' overflowCount={99}>
-        <Button {...buttonProps} />
-      </Badge>
-    );
-  }
-
-  return <Button {...buttonProps} />;
-};
-
-export default NotificationButton;

+ 0 - 109
web/src/components/layout/HeaderBar/ThemeToggle.jsx

@@ -1,109 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React, { useMemo } from 'react';
-import { Button, Dropdown } from '@douyinfe/semi-ui';
-import { Sun, Moon, Monitor } from 'lucide-react';
-import { useActualTheme } from '../../../context/Theme';
-
-const ThemeToggle = ({ theme, onThemeToggle, t }) => {
-  const actualTheme = useActualTheme();
-
-  const themeOptions = useMemo(
-    () => [
-      {
-        key: 'light',
-        icon: <Sun size={18} />,
-        buttonIcon: <Sun size={18} />,
-        label: t('浅色模式'),
-        description: t('始终使用浅色主题'),
-      },
-      {
-        key: 'dark',
-        icon: <Moon size={18} />,
-        buttonIcon: <Moon size={18} />,
-        label: t('深色模式'),
-        description: t('始终使用深色主题'),
-      },
-      {
-        key: 'auto',
-        icon: <Monitor size={18} />,
-        buttonIcon: <Monitor size={18} />,
-        label: t('自动模式'),
-        description: t('跟随系统主题设置'),
-      },
-    ],
-    [t],
-  );
-
-  const getItemClassName = (isSelected) =>
-    isSelected
-      ? '!bg-semi-color-primary-light-default !font-semibold'
-      : 'hover:!bg-semi-color-fill-1';
-
-  const currentButtonIcon = useMemo(() => {
-    const currentOption = themeOptions.find((option) => option.key === theme);
-    return currentOption?.buttonIcon || themeOptions[2].buttonIcon;
-  }, [theme, themeOptions]);
-
-  return (
-    <Dropdown
-      position='bottomRight'
-      render={
-        <Dropdown.Menu>
-          {themeOptions.map((option) => (
-            <Dropdown.Item
-              key={option.key}
-              icon={option.icon}
-              onClick={() => onThemeToggle(option.key)}
-              className={getItemClassName(theme === option.key)}
-            >
-              <div className='flex flex-col'>
-                <span>{option.label}</span>
-                <span className='text-xs text-semi-color-text-2'>
-                  {option.description}
-                </span>
-              </div>
-            </Dropdown.Item>
-          ))}
-
-          {theme === 'auto' && (
-            <>
-              <Dropdown.Divider />
-              <div className='px-3 py-2 text-xs text-semi-color-text-2'>
-                {t('当前跟随系统')}:
-                {actualTheme === 'dark' ? t('深色') : t('浅色')}
-              </div>
-            </>
-          )}
-        </Dropdown.Menu>
-      }
-    >
-      <Button
-        icon={currentButtonIcon}
-        aria-label={t('切换主题')}
-        theme='borderless'
-        type='tertiary'
-        className='!p-1.5 !text-current focus:!bg-semi-color-fill-1 !rounded-full !bg-semi-color-fill-0 hover:!bg-semi-color-fill-1'
-      />
-    </Dropdown>
-  );
-};
-
-export default ThemeToggle;

+ 0 - 196
web/src/components/layout/HeaderBar/UserArea.jsx

@@ -1,196 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React from 'react';
-import { Link } from 'react-router-dom';
-import { Avatar, Button, Dropdown, Typography } from '@douyinfe/semi-ui';
-import { ChevronDown } from 'lucide-react';
-import {
-  IconExit,
-  IconUserSetting,
-  IconCreditCard,
-  IconKey,
-} from '@douyinfe/semi-icons';
-import { stringToColor } from '../../../helpers';
-import SkeletonWrapper from '../components/SkeletonWrapper';
-
-const UserArea = ({
-  userState,
-  isLoading,
-  isMobile,
-  isSelfUseMode,
-  logout,
-  navigate,
-  t,
-}) => {
-  if (isLoading) {
-    return (
-      <SkeletonWrapper
-        loading={true}
-        type='userArea'
-        width={50}
-        isMobile={isMobile}
-      />
-    );
-  }
-
-  if (userState.user) {
-    return (
-      <Dropdown
-        position='bottomRight'
-        render={
-          <Dropdown.Menu className='!bg-semi-color-bg-overlay !border-semi-color-border !shadow-lg !rounded-lg dark:!bg-gray-700 dark:!border-gray-600'>
-            <Dropdown.Item
-              onClick={() => {
-                navigate('/console/personal');
-              }}
-              className='!px-3 !py-1.5 !text-sm !text-semi-color-text-0 hover:!bg-semi-color-fill-1 dark:!text-gray-200 dark:hover:!bg-blue-500 dark:hover:!text-white'
-            >
-              <div className='flex items-center gap-2'>
-                <IconUserSetting
-                  size='small'
-                  className='text-gray-500 dark:text-gray-400'
-                />
-                <span>{t('个人设置')}</span>
-              </div>
-            </Dropdown.Item>
-            <Dropdown.Item
-              onClick={() => {
-                navigate('/console/token');
-              }}
-              className='!px-3 !py-1.5 !text-sm !text-semi-color-text-0 hover:!bg-semi-color-fill-1 dark:!text-gray-200 dark:hover:!bg-blue-500 dark:hover:!text-white'
-            >
-              <div className='flex items-center gap-2'>
-                <IconKey
-                  size='small'
-                  className='text-gray-500 dark:text-gray-400'
-                />
-                <span>{t('令牌管理')}</span>
-              </div>
-            </Dropdown.Item>
-            <Dropdown.Item
-              onClick={() => {
-                navigate('/console/topup');
-              }}
-              className='!px-3 !py-1.5 !text-sm !text-semi-color-text-0 hover:!bg-semi-color-fill-1 dark:!text-gray-200 dark:hover:!bg-blue-500 dark:hover:!text-white'
-            >
-              <div className='flex items-center gap-2'>
-                <IconCreditCard
-                  size='small'
-                  className='text-gray-500 dark:text-gray-400'
-                />
-                <span>{t('钱包管理')}</span>
-              </div>
-            </Dropdown.Item>
-            <Dropdown.Item
-              onClick={logout}
-              className='!px-3 !py-1.5 !text-sm !text-semi-color-text-0 hover:!bg-semi-color-fill-1 dark:!text-gray-200 dark:hover:!bg-red-500 dark:hover:!text-white'
-            >
-              <div className='flex items-center gap-2'>
-                <IconExit
-                  size='small'
-                  className='text-gray-500 dark:text-gray-400'
-                />
-                <span>{t('退出')}</span>
-              </div>
-            </Dropdown.Item>
-          </Dropdown.Menu>
-        }
-      >
-        <Button
-          theme='borderless'
-          type='tertiary'
-          className='flex items-center gap-1.5 !p-1 !rounded-full hover:!bg-semi-color-fill-1 dark:hover:!bg-gray-700 !bg-semi-color-fill-0 dark:!bg-semi-color-fill-1 dark:hover:!bg-semi-color-fill-2'
-        >
-          <Avatar
-            size='extra-small'
-            color={stringToColor(userState.user.username)}
-            className='mr-1'
-          >
-            {userState.user.username[0].toUpperCase()}
-          </Avatar>
-          <span className='hidden md:inline'>
-            <Typography.Text className='!text-xs !font-medium !text-semi-color-text-1 dark:!text-gray-300 mr-1'>
-              {userState.user.username}
-            </Typography.Text>
-          </span>
-          <ChevronDown
-            size={14}
-            className='text-xs text-semi-color-text-2 dark:text-gray-400'
-          />
-        </Button>
-      </Dropdown>
-    );
-  } 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 (isMobile) {
-        loginButtonClasses += ' !rounded-full';
-      } else {
-        loginButtonClasses += ' !rounded-l-full !rounded-r-none';
-      }
-      registerButtonClasses += ' !rounded-r-full !rounded-l-none';
-    } else {
-      loginButtonClasses += ' !rounded-full';
-    }
-
-    return (
-      <div className='flex items-center'>
-        <Link to='/login' className='flex'>
-          <Button
-            theme='borderless'
-            type='tertiary'
-            className={loginButtonClasses}
-          >
-            <span className={loginButtonTextSpanClass}>{t('登录')}</span>
-          </Button>
-        </Link>
-        {showRegisterButton && (
-          <div className='hidden md:block'>
-            <Link to='/register' className='flex -ml-px'>
-              <Button
-                theme='solid'
-                type='primary'
-                className={registerButtonClasses}
-              >
-                <span className={registerButtonTextSpanClass}>{t('注册')}</span>
-              </Button>
-            </Link>
-          </div>
-        )}
-      </div>
-    );
-  }
-};
-
-export default UserArea;

+ 0 - 132
web/src/components/layout/HeaderBar/index.jsx

@@ -1,132 +0,0 @@
-/*
-Copyright (C) 2025 QuantumNous
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-For commercial licensing, please contact support@quantumnous.com
-*/
-
-import React from 'react';
-import { useHeaderBar } from '../../../hooks/common/useHeaderBar';
-import { useNotifications } from '../../../hooks/common/useNotifications';
-import { useNavigation } from '../../../hooks/common/useNavigation';
-import NoticeModal from '../NoticeModal';
-import MobileMenuButton from './MobileMenuButton';
-import HeaderLogo from './HeaderLogo';
-import Navigation from './Navigation';
-import ActionButtons from './ActionButtons';
-
-const HeaderBar = ({ onMobileMenuToggle, drawerOpen }) => {
-  const {
-    userState,
-    statusState,
-    isMobile,
-    collapsed,
-    logoLoaded,
-    currentLang,
-    isLoading,
-    systemName,
-    logo,
-    isNewYear,
-    isSelfUseMode,
-    docsLink,
-    isDemoSiteMode,
-    isConsoleRoute,
-    theme,
-    headerNavModules,
-    pricingRequireAuth,
-    logout,
-    handleLanguageChange,
-    handleThemeToggle,
-    handleMobileMenuToggle,
-    navigate,
-    t,
-  } = useHeaderBar({ onMobileMenuToggle, drawerOpen });
-
-  const {
-    noticeVisible,
-    unreadCount,
-    handleNoticeOpen,
-    handleNoticeClose,
-    getUnreadKeys,
-  } = useNotifications(statusState);
-
-  const { mainNavLinks } = useNavigation(t, docsLink, headerNavModules);
-
-  return (
-    <header className='text-semi-color-text-0 sticky top-0 z-50 transition-colors duration-300 bg-white/75 dark:bg-zinc-900/75 backdrop-blur-lg'>
-      <NoticeModal
-        visible={noticeVisible}
-        onClose={handleNoticeClose}
-        isMobile={isMobile}
-        defaultTab={unreadCount > 0 ? 'system' : 'inApp'}
-        unreadKeys={getUnreadKeys()}
-      />
-
-      <div className='w-full px-2'>
-        <div className='flex items-center justify-between h-16'>
-          <div className='flex items-center'>
-            <MobileMenuButton
-              isConsoleRoute={isConsoleRoute}
-              isMobile={isMobile}
-              drawerOpen={drawerOpen}
-              collapsed={collapsed}
-              onToggle={handleMobileMenuToggle}
-              t={t}
-            />
-
-            <HeaderLogo
-              isMobile={isMobile}
-              isConsoleRoute={isConsoleRoute}
-              logo={logo}
-              logoLoaded={logoLoaded}
-              isLoading={isLoading}
-              systemName={systemName}
-              isSelfUseMode={isSelfUseMode}
-              isDemoSiteMode={isDemoSiteMode}
-              t={t}
-            />
-          </div>
-
-          <Navigation
-            mainNavLinks={mainNavLinks}
-            isMobile={isMobile}
-            isLoading={isLoading}
-            userState={userState}
-            pricingRequireAuth={pricingRequireAuth}
-          />
-
-          <ActionButtons
-            isNewYear={isNewYear}
-            unreadCount={unreadCount}
-            onNoticeOpen={handleNoticeOpen}
-            theme={theme}
-            onThemeToggle={handleThemeToggle}
-            currentLang={currentLang}
-            onLanguageChange={handleLanguageChange}
-            userState={userState}
-            isLoading={isLoading}
-            isMobile={isMobile}
-            isSelfUseMode={isSelfUseMode}
-            logout={logout}
-            navigate={navigate}
-            t={t}
-          />
-        </div>
-      </div>
-    </header>
-  );
-};
-
-export default HeaderBar;