diff --git a/src/constants/homeFeatures.ts b/src/constants/homeFeatures.ts new file mode 100644 index 00000000..5781cc2a --- /dev/null +++ b/src/constants/homeFeatures.ts @@ -0,0 +1,66 @@ +// src/constants/homeFeatures.ts +// 首页功能特性配置 + +import type { Feature } from '@/types/home'; + +/** + * 核心功能特性列表 + * 第一个功能为特色功能,会以突出样式显示 + */ +export const CORE_FEATURES: Feature[] = [ + { + id: 'news-catalyst', + title: '新闻中心', + description: '实时新闻事件分析,捕捉市场催化因子', + icon: '📊', + color: 'yellow', + url: '/community', + badge: '核心', + featured: true + }, + { + id: 'concepts', + title: '概念中心', + description: '热门概念与主题投资分析追踪', + icon: '🎯', + color: 'purple', + url: '/concepts', + badge: '热门' + }, + { + id: 'stocks', + title: '个股信息汇总', + description: '全面的个股基本面信息整合', + icon: '📈', + color: 'blue', + url: '/stocks', + badge: '全面' + }, + { + id: 'limit-analyse', + title: '涨停板块分析', + description: '涨停板数据深度分析与规律挖掘', + icon: '🚀', + color: 'green', + url: '/limit-analyse', + badge: '精准' + }, + { + id: 'company', + title: '个股罗盘', + description: '个股全方位分析与投资决策支持', + icon: '🧭', + color: 'orange', + url: '/company?scode=688256', + badge: '专业' + }, + { + id: 'trading-simulation', + title: '模拟盘交易', + description: '100万起始资金,体验真实交易环境', + icon: '💰', + color: 'teal', + url: '/trading-simulation', + badge: '实战' + } +]; diff --git a/src/hooks/useHomeResponsive.ts b/src/hooks/useHomeResponsive.ts new file mode 100644 index 00000000..5a2f7f76 --- /dev/null +++ b/src/hooks/useHomeResponsive.ts @@ -0,0 +1,57 @@ +// src/hooks/useHomeResponsive.ts +// 首页响应式配置 Hook + +import { useBreakpointValue } from '@chakra-ui/react'; +import type { ResponsiveConfig } from '@/types/home'; + +/** + * 首页响应式配置 Hook + * 集中管理所有响应式断点值 + * + * @returns 响应式配置对象 + */ +export const useHomeResponsive = (): ResponsiveConfig => { + const heroHeight = useBreakpointValue({ + base: '60vh', + md: '80vh', + lg: '100vh' + }); + + const headingSize = useBreakpointValue({ + base: 'xl', + md: '3xl', + lg: '4xl' + }); + + const headingLetterSpacing = useBreakpointValue({ + base: '-1px', + md: '-1.5px', + lg: '-2px' + }); + + const heroTextSize = useBreakpointValue({ + base: 'md', + md: 'lg', + lg: 'xl' + }); + + const containerPx = useBreakpointValue({ + base: 10, + md: 10, + lg: 10 + }); + + const showDecorations = useBreakpointValue({ + base: false, + md: true + }); + + return { + heroHeight, + headingSize, + headingLetterSpacing, + heroTextSize, + containerPx, + showDecorations + }; +}; diff --git a/src/types/home.ts b/src/types/home.ts new file mode 100644 index 00000000..4a78c6ec --- /dev/null +++ b/src/types/home.ts @@ -0,0 +1,33 @@ +// src/types/home.ts +// HomePage 相关类型定义 + +/** + * 功能特性配置 + */ +export interface Feature { + id: string; + title: string; + description: string; + icon: string; + color: string; + url: string; + badge: string; + featured?: boolean; +} + +/** + * 响应式配置 + */ +export interface ResponsiveConfig { + heroHeight: string | undefined; + headingSize: string | undefined; + headingLetterSpacing: string | undefined; + heroTextSize: string | undefined; + containerPx: number | undefined; + showDecorations: boolean | undefined; +} + +/** + * 功能卡片点击处理函数类型 + */ +export type FeatureClickHandler = (feature: Feature) => void; diff --git a/src/views/Home/HomePage.js b/src/views/Home/HomePage.js deleted file mode 100755 index 26572b18..00000000 --- a/src/views/Home/HomePage.js +++ /dev/null @@ -1,379 +0,0 @@ -// src/views/Home/HomePage.js - 专业投资分析平台 -import React, { useEffect, useCallback } from 'react'; -import { - Box, - Container, - Heading, - Text, - Card, - CardBody, - Badge, - Button, - Flex, - VStack, - HStack, - SimpleGrid, - useBreakpointValue -} from '@chakra-ui/react'; -import { useAuth } from '../../contexts/AuthContext'; -import { useNavigate } from 'react-router-dom'; -import heroBg from '../../assets/img/BackgroundCard1.png'; -import '../../styles/home-animations.css'; -import { logger } from '../../utils/logger'; -import { usePostHogTrack } from '../../hooks/usePostHogRedux'; -import { ACQUISITION_EVENTS } from '../../lib/constants'; - -export default function HomePage() { - const { user, isAuthenticated } = useAuth(); // ⚡ 移除 isLoading,不再依赖它 - const navigate = useNavigate(); - const { track } = usePostHogTrack(); // PostHog 追踪 - const [imageLoaded, setImageLoaded] = React.useState(false); - - // 响应式配置 - const heroHeight = useBreakpointValue({ base: '60vh', md: '80vh', lg: '100vh' }); - const headingSize = useBreakpointValue({ base: 'xl', md: '3xl', lg: '4xl' }); - const headingLetterSpacing = useBreakpointValue({ base: '-1px', md: '-1.5px', lg: '-2px' }); - const heroTextSize = useBreakpointValue({ base: 'md', md: 'lg', lg: 'xl' }); - const containerPx = useBreakpointValue({ base: 10, md: 10, lg: 10 }); - const showDecorations = useBreakpointValue({ base: false, md: true }); - - // 保留原有的调试信息 - useEffect(() => { - logger.debug('HomePage', 'AuthContext状态', { - userId: user?.id, - username: user?.username, - nickname: user?.nickname, - isAuthenticated, - hasUser: !!user - }); - }, [user?.id, isAuthenticated]); // 只依赖 user.id,避免无限循环 - - // 🎯 PostHog 追踪:页面浏览 - useEffect(() => { - track(ACQUISITION_EVENTS.LANDING_PAGE_VIEWED, { - timestamp: new Date().toISOString(), - is_authenticated: isAuthenticated, - user_id: user?.id || null, - }); - }, [track, isAuthenticated, user?.id]); - - // 核心功能配置 - 5个主要功能 - const coreFeatures = [ - { - id: 'news-catalyst', - title: '新闻中心', - description: '实时新闻事件分析,捕捉市场催化因子', - icon: '📊', - color: 'yellow', - url: '/community', - badge: '核心', - featured: true - }, - { - id: 'concepts', - title: '概念中心', - description: '热门概念与主题投资分析追踪', - icon: '🎯', - color: 'purple', - url: '/concepts', - badge: '热门' - }, - { - id: 'stocks', - title: '个股信息汇总', - description: '全面的个股基本面信息整合', - icon: '📈', - color: 'blue', - url: '/stocks', - badge: '全面' - }, - { - id: 'limit-analyse', - title: '涨停板块分析', - description: '涨停板数据深度分析与规律挖掘', - icon: '🚀', - color: 'green', - url: '/limit-analyse', - badge: '精准' - }, - { - id: 'company', - title: '个股罗盘', - description: '个股全方位分析与投资决策支持', - icon: '🧭', - color: 'orange', - url: '/company?scode=688256', - badge: '专业' - }, - { - id: 'trading-simulation', - title: '模拟盘交易', - description: '100万起始资金,体验真实交易环境', - icon: '💰', - color: 'teal', - url: '/trading-simulation', - badge: '实战' - } - ]; - - // @TODO 如何区分内部链接和外部链接? - const handleProductClick = useCallback((feature) => { - // 🎯 PostHog 追踪:功能卡片点击 - track(ACQUISITION_EVENTS.FEATURE_CARD_CLICKED, { - feature_id: feature.id, - feature_title: feature.title, - feature_url: feature.url, - is_featured: feature.featured || false, - link_type: feature.url.startsWith('http') ? 'external' : 'internal', - }); - - // 原有导航逻辑 - if (feature.url.startsWith('http')) { - // 外部链接,直接打开 - window.open(feature.url, '_blank'); - } else { - // 内部路由 - navigate(feature.url); - } - }, [track, navigate]); - - return ( - - - {/* Hero Section - 深色科技风格 */} - - {/* 背景图片和装饰 - 优化:延迟加载 */} - - {/* 预加载背景图片 */} - - setImageLoaded(true)} - onError={() => setImageLoaded(true)} - /> - - - {/* 装饰性几何图形 - 移动端隐藏 */} - {showDecorations && ( - <> - - - - )} - - - - {/* 主标题区域 */} - - - 智能投资分析平台 - - - 专业投资研究工具,助您把握市场机遇 - - - - - {/* 核心功能面板 */} - - - - {/* 新闻中心 - 突出显示 */} - - - {/* 响应式布局:移动端纵向,桌面端横向 */} - - - - {coreFeatures[0].icon} - - - - - {coreFeatures[0].title} - - - {coreFeatures[0].badge} - - - - {coreFeatures[0].description} - - - - - - - - - {/* 其他5个功能 */} - - {coreFeatures.slice(1).map((feature) => ( - handleProductClick(feature)} - minH={{ base: 'auto', md: '180px' }} - > - - - - - {feature.icon} - - - {feature.badge} - - - - - - {feature.title} - - - {feature.description} - - - - - - - - ))} - - - - - - - - - ); -} \ No newline at end of file diff --git a/src/views/Home/HomePage.tsx b/src/views/Home/HomePage.tsx new file mode 100644 index 00000000..d13f78a4 --- /dev/null +++ b/src/views/Home/HomePage.tsx @@ -0,0 +1,139 @@ +// src/views/Home/HomePage.tsx +// 首页 - 专业投资分析平台 + +import React, { useEffect, useCallback, useState } from 'react'; +import { Box, Container, VStack, SimpleGrid } from '@chakra-ui/react'; +import { useNavigate } from 'react-router-dom'; +import { useAuth } from '@/contexts/AuthContext'; +import { usePostHogTrack } from '@/hooks/usePostHogRedux'; +import { useHomeResponsive } from '@/hooks/useHomeResponsive'; +import { ACQUISITION_EVENTS } from '@/lib/constants'; +import { CORE_FEATURES } from '@/constants/homeFeatures'; +import type { Feature } from '@/types/home'; +import { HeroBackground } from './components/HeroBackground'; +import { HeroHeader } from './components/HeroHeader'; +import { FeaturedFeatureCard } from './components/FeaturedFeatureCard'; +import { FeatureCard } from './components/FeatureCard'; +import '@/styles/home-animations.css'; + +/** + * 首页组件 + * 展示平台核心功能,引导用户探索各个功能模块 + */ +const HomePage: React.FC = () => { + const { user, isAuthenticated } = useAuth(); + const navigate = useNavigate(); + const { track } = usePostHogTrack(); + const [imageLoaded, setImageLoaded] = useState(false); + + // 响应式配置 + const { + heroHeight, + headingSize, + headingLetterSpacing, + heroTextSize, + containerPx, + showDecorations + } = useHomeResponsive(); + + // PostHog 追踪:页面浏览 + useEffect(() => { + track(ACQUISITION_EVENTS.LANDING_PAGE_VIEWED, { + timestamp: new Date().toISOString(), + is_authenticated: isAuthenticated, + user_id: user?.id || null, + }); + }, [track, isAuthenticated, user?.id]); + + // 功能卡片点击处理 + const handleFeatureClick = useCallback((feature: Feature) => { + // PostHog 追踪:功能卡片点击 + track(ACQUISITION_EVENTS.FEATURE_CARD_VIEWED, { + feature_id: feature.id, + feature_title: feature.title, + feature_url: feature.url, + is_featured: feature.featured || false, + link_type: feature.url.startsWith('http') ? 'external' : 'internal', + }); + + // 导航处理 + if (feature.url.startsWith('http')) { + window.open(feature.url, '_blank'); + } else { + navigate(feature.url); + } + }, [track, navigate]); + + // 背景图片加载完成回调 + const handleImageLoad = useCallback(() => { + setImageLoaded(true); + }, []); + + // 特色功能(第一个) + const featuredFeature = CORE_FEATURES[0]; + // 其他功能 + const regularFeatures = CORE_FEATURES.slice(1); + + return ( + + {/* Hero Section - 深色科技风格 */} + + {/* 背景装饰 */} + + + + + {/* 主标题区域 */} + + + {/* 核心功能面板 */} + + + {/* 特色功能卡片 - 新闻中心 */} + + + {/* 其他功能卡片 */} + + {regularFeatures.map((feature) => ( + + ))} + + + + + + + + ); +}; + +export default HomePage; diff --git a/src/views/Home/components/FeatureCard.tsx b/src/views/Home/components/FeatureCard.tsx new file mode 100644 index 00000000..c026f734 --- /dev/null +++ b/src/views/Home/components/FeatureCard.tsx @@ -0,0 +1,106 @@ +// src/views/Home/components/FeatureCard.tsx +// 普通功能卡片组件 + +import React from 'react'; +import { + Card, + CardBody, + VStack, + HStack, + Box, + Heading, + Text, + Badge, + Button +} from '@chakra-ui/react'; +import type { Feature, FeatureClickHandler } from '@/types/home'; + +interface FeatureCardProps { + feature: Feature; + onClick: FeatureClickHandler; +} + +/** + * 普通功能卡片组件 + * 用于展示除特色功能外的其他功能 + */ +export const FeatureCard: React.FC = ({ + feature, + onClick +}) => { + return ( + onClick(feature)} + minH={{ base: 'auto', md: '180px' }} + cursor="pointer" + > + + + + + {feature.icon} + + + {feature.badge} + + + + + + {feature.title} + + + {feature.description} + + + + + + + + ); +}; diff --git a/src/views/Home/components/FeaturedFeatureCard.tsx b/src/views/Home/components/FeaturedFeatureCard.tsx new file mode 100644 index 00000000..c4dd9731 --- /dev/null +++ b/src/views/Home/components/FeaturedFeatureCard.tsx @@ -0,0 +1,104 @@ +// src/views/Home/components/FeaturedFeatureCard.tsx +// 特色功能卡片组件(新闻中心) + +import React from 'react'; +import { + Card, + CardBody, + Flex, + Box, + VStack, + HStack, + Heading, + Text, + Badge, + Button +} from '@chakra-ui/react'; +import type { Feature, FeatureClickHandler } from '@/types/home'; + +interface FeaturedFeatureCardProps { + feature: Feature; + onClick: FeatureClickHandler; +} + +/** + * 特色功能卡片组件 + * 用于突出显示最重要的功能(如新闻中心) + */ +export const FeaturedFeatureCard: React.FC = ({ + feature, + onClick +}) => { + return ( + + + + + + {feature.icon} + + + + + {feature.title} + + + {feature.badge} + + + + {feature.description} + + + + + + + + ); +}; diff --git a/src/views/Home/components/HeroBackground.tsx b/src/views/Home/components/HeroBackground.tsx new file mode 100644 index 00000000..cc47dedb --- /dev/null +++ b/src/views/Home/components/HeroBackground.tsx @@ -0,0 +1,87 @@ +// src/views/Home/components/HeroBackground.tsx +// 首页英雄区背景装饰组件 + +import React from 'react'; +import { Box } from '@chakra-ui/react'; +import heroBg from '@assets/img/BackgroundCard1.png'; + +interface HeroBackgroundProps { + imageLoaded: boolean; + onImageLoad: () => void; + showDecorations: boolean | undefined; +} + +/** + * 首页英雄区背景组件 + * 包含背景图片和装饰性几何图形 + */ +export const HeroBackground: React.FC = ({ + imageLoaded, + onImageLoad, + showDecorations +}) => { + return ( + <> + {/* 背景图片 */} + + + {/* 预加载背景图片 */} + + + + + {/* 装饰性几何图形 - 移动端隐藏 */} + {showDecorations && ( + <> + + + + )} + + ); +}; diff --git a/src/views/Home/components/HeroHeader.tsx b/src/views/Home/components/HeroHeader.tsx new file mode 100644 index 00000000..502a6737 --- /dev/null +++ b/src/views/Home/components/HeroHeader.tsx @@ -0,0 +1,48 @@ +// src/views/Home/components/HeroHeader.tsx +// 首页主标题区域组件 + +import React from 'react'; +import { Heading, Text, VStack } from '@chakra-ui/react'; + +interface HeroHeaderProps { + headingSize: string | undefined; + headingLetterSpacing: string | undefined; + heroTextSize: string | undefined; +} + +/** + * 首页主标题区域组件 + * 包含主标题和副标题 + */ +export const HeroHeader: React.FC = ({ + headingSize, + headingLetterSpacing, + heroTextSize +}) => { + return ( + + + 智能投资分析平台 + + + 专业投资研究工具,助您把握市场机遇 + + + ); +};