* feature_2025/251117_pref: (159 commits) feat: UI调整 feat: 将滚动事件移东到组件内部 feat: 去掉背景组件 feat: 拆分左侧栏、中间聊天区、右侧栏组件, Hooks 提取 feat: 简化主组件 index.js - 使用组件组合方式重构 feat: 创建 ChatArea 组件(含 MessageRenderer、ExecutionStepsDisplay 子组件) feat:拆分工具函数 feat: 拆分BackgroundEffects 背景渐变装饰层 feat: RightSidebar (~420 行) - 模型/工具/统计 Tab 面板(单文件) feat: LeftSidebar (~280 行) - 对话历史列表 + 用户信息卡片 feat: 修复bug pref:移除黑夜模式 feat: 修复警告 feat: 提取常量配置 feat: 修复ts报错 feat: StockChartModal.tsx 替换 KLine 实现 update pay function update pay function update pay function update pay function ...
205 lines
7.8 KiB
JavaScript
205 lines
7.8 KiB
JavaScript
import React, { useCallback, useState } from 'react';
|
||
import {
|
||
Box,
|
||
Flex,
|
||
Text,
|
||
Button,
|
||
Container,
|
||
useDisclosure,
|
||
HStack,
|
||
Icon,
|
||
Menu,
|
||
MenuButton,
|
||
MenuList,
|
||
MenuItem,
|
||
Badge,
|
||
Grid,
|
||
IconButton,
|
||
useBreakpointValue,
|
||
Spinner,
|
||
useColorMode,
|
||
useColorModeValue,
|
||
useToast,
|
||
} from '@chakra-ui/react';
|
||
import { ChevronDownIcon, HamburgerIcon, SunIcon, MoonIcon } from '@chakra-ui/icons';
|
||
import { FiStar, FiCalendar, FiUser, FiSettings, FiHome, FiLogOut } from 'react-icons/fi';
|
||
import { FaCrown } from 'react-icons/fa';
|
||
import { useNavigate, useLocation } from 'react-router-dom';
|
||
import { useAuth } from '../../contexts/AuthContext';
|
||
import { useAuthModal } from '../../hooks/useAuthModal';
|
||
import { logger } from '../../utils/logger';
|
||
import { getApiBase } from '../../utils/apiConfig';
|
||
import SubscriptionButton from '../Subscription/SubscriptionButton';
|
||
import { useNavigationEvents } from '../../hooks/useNavigationEvents';
|
||
|
||
// Phase 1 优化: 提取的子组件
|
||
import BrandLogo from './components/BrandLogo';
|
||
import LoginButton from './components/LoginButton';
|
||
import CalendarButton from './components/CalendarButton';
|
||
|
||
// Phase 2 优化: 使用 Redux 管理订阅数据
|
||
import { useSubscription } from '../../hooks/useSubscription';
|
||
|
||
// Phase 3 优化: 提取的用户菜单组件
|
||
import { DesktopUserMenu, TabletUserMenu } from './components/UserMenu';
|
||
|
||
// Phase 4 优化: 提取的导航菜单组件
|
||
import { DesktopNav, MoreMenu, PersonalCenterMenu } from './components/Navigation';
|
||
|
||
// Phase 5 优化: 提取的移动端抽屉菜单组件
|
||
import { MobileDrawer } from './components/MobileDrawer';
|
||
|
||
// Phase 6 优化: 提取的功能菜单组件和自定义 Hooks
|
||
import { WatchlistMenu, FollowingEventsMenu } from './components/FeatureMenus';
|
||
import { useWatchlist } from '../../hooks/useWatchlist';
|
||
import { useFollowingEvents } from '../../hooks/useFollowingEvents';
|
||
|
||
// Phase 7 优化: 提取的资料完整性、右侧功能区组件
|
||
import ProfileCompletenessAlert from './components/ProfileCompletenessAlert';
|
||
import { useProfileCompleteness } from '../../hooks/useProfileCompleteness';
|
||
import NavbarActions from './components/NavbarActions';
|
||
|
||
// Phase 4: MoreNavMenu 和 NavItems 组件已提取到 Navigation 目录
|
||
|
||
export default function HomeNavbar() {
|
||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||
const navigate = useNavigate();
|
||
const isMobile = useBreakpointValue({ base: true, md: false });
|
||
const isTablet = useBreakpointValue({ base: false, md: true, lg: false });
|
||
const isDesktop = useBreakpointValue({ base: false, md: false, lg: true });
|
||
const { user, isAuthenticated, logout, isLoading } = useAuth();
|
||
const { openAuthModal } = useAuthModal();
|
||
const { colorMode, toggleColorMode } = useColorMode();
|
||
const navbarBg = useColorModeValue('white', 'gray.800');
|
||
const navbarBorder = useColorModeValue('gray.200', 'gray.700');
|
||
const brandText = useColorModeValue('gray.800', 'white');
|
||
const brandHover = useColorModeValue('blue.600', 'blue.300');
|
||
const toast = useToast();
|
||
|
||
// 🎯 初始化导航埋点Hook
|
||
const navEvents = useNavigationEvents({ component: 'main_navbar' });
|
||
|
||
// ⚡ 提取 userId 为独立变量,避免 user 对象引用变化导致无限循环
|
||
const userId = user?.id;
|
||
const prevUserIdRef = React.useRef(userId);
|
||
const prevIsAuthenticatedRef = React.useRef(isAuthenticated);
|
||
|
||
// 添加调试信息 - 暂时注释以减少日志噪音
|
||
// logger.debug('HomeNavbar', '组件渲染状态', {
|
||
// hasUser: !!user,
|
||
// isAuthenticated,
|
||
// isLoading,
|
||
// userId: user?.id
|
||
// });
|
||
|
||
// 获取显示名称的函数
|
||
const getDisplayName = () => {
|
||
if (!user) return '';
|
||
return user.nickname || user.username || user.name || user.email || '用户';
|
||
};
|
||
|
||
// Phase 6: 自选股和关注事件逻辑已提取到自定义 Hooks
|
||
const { watchlistQuotes, followingEvents } = useWatchlist();
|
||
const { followingEvents: events } = useFollowingEvents();
|
||
// 注意:这里只需要数据用于 TabletUserMenu,实际的菜单组件会自己管理状态
|
||
|
||
// Phase 7: 资料完整性逻辑已提取到 useProfileCompleteness Hook
|
||
const {
|
||
profileCompleteness,
|
||
showAlert: showCompletenessAlert,
|
||
setShowAlert: setShowCompletenessAlert,
|
||
resetCompleteness
|
||
} = useProfileCompleteness({ isAuthenticated, user });
|
||
|
||
// 处理登出
|
||
const handleLogout = async () => {
|
||
try {
|
||
await logout();
|
||
// Phase 7: 使用 resetCompleteness 重置资料完整性状态
|
||
resetCompleteness();
|
||
// logout函数已经包含了跳转逻辑,这里不需要额外处理
|
||
} catch (error) {
|
||
logger.error('HomeNavbar', 'handleLogout', error, {
|
||
userId: user?.id
|
||
});
|
||
}
|
||
};
|
||
|
||
// Phase 2: 使用 Redux 订阅数据
|
||
const {
|
||
subscriptionInfo,
|
||
isSubscriptionModalOpen,
|
||
openSubscriptionModal,
|
||
closeSubscriptionModal
|
||
} = useSubscription();
|
||
|
||
// Phase 6: loadWatchlistQuotes, loadFollowingEvents, handleRemoveFromWatchlist,
|
||
// handleUnfollowEvent 已移至自定义 Hooks 中,由各自组件内部管理
|
||
|
||
// Phase 2: 加载订阅信息逻辑已移至 useSubscriptionData Hook
|
||
|
||
return (
|
||
<>
|
||
{/* 资料完整性提醒横幅 (Phase 7 优化) */}
|
||
{showCompletenessAlert && (
|
||
<ProfileCompletenessAlert
|
||
profileCompleteness={profileCompleteness}
|
||
onClose={() => setShowCompletenessAlert(false)}
|
||
onNavigateToSettings={() => navigate('/home/settings')}
|
||
/>
|
||
)}
|
||
|
||
<Box
|
||
position="fixed"
|
||
top={showCompletenessAlert ? "60px" : 0}
|
||
left={0}
|
||
right={0}
|
||
zIndex={1000}
|
||
bg={navbarBg}
|
||
backdropFilter="blur(10px)"
|
||
borderBottom="1px"
|
||
borderColor={navbarBorder}
|
||
py={{ base: 2, md: 3 }}
|
||
>
|
||
<Container maxW="container.xl" px={{ base: 3, md: 4 }}>
|
||
<Flex justify="space-between" align="center">
|
||
{/* Logo - 价小前投研 */}
|
||
<BrandLogo />
|
||
|
||
{/* 中间导航区域 - 响应式 (Phase 4 优化) */}
|
||
{isDesktop && (
|
||
// 桌面端:完整导航菜单(移动端和平板端的汉堡菜单已移至右侧)
|
||
<DesktopNav isAuthenticated={isAuthenticated} user={user} />
|
||
)}
|
||
|
||
{/* 右侧功能区 (Phase 7 优化) */}
|
||
<NavbarActions
|
||
isLoading={isLoading}
|
||
isAuthenticated={isAuthenticated}
|
||
user={user}
|
||
isDesktop={isDesktop}
|
||
isTablet={isTablet}
|
||
isMobile={isMobile}
|
||
onMenuOpen={onOpen}
|
||
handleLogout={handleLogout}
|
||
watchlistQuotes={watchlistQuotes}
|
||
followingEvents={followingEvents}
|
||
/>
|
||
</Flex>
|
||
</Container>
|
||
|
||
{/* 移动端抽屉菜单 (Phase 5 优化) */}
|
||
<MobileDrawer
|
||
isOpen={isOpen}
|
||
onClose={onClose}
|
||
isAuthenticated={isAuthenticated}
|
||
user={user}
|
||
handleLogout={handleLogout}
|
||
openAuthModal={openAuthModal}
|
||
/>
|
||
</Box>
|
||
|
||
{/* 投资日历 Modal - 已移至 CalendarButton 组件内部 */}
|
||
</>
|
||
);
|
||
} |