Files
vf_react/src/views/Home/HomePage.js
2025-10-21 15:43:59 +08:00

430 lines
16 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// src/views/Home/HomePage.js - 专业投资分析平台
import React, { useEffect } from 'react';
import {
Box,
Container,
Heading,
Text,
Card,
CardBody,
Badge,
Button,
Flex,
VStack,
HStack,
SimpleGrid,
Link,
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';
export default function HomePage() {
const { user, isAuthenticated } = useAuth(); // ⚡ 移除 isLoading不再依赖它
const navigate = useNavigate();
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 });
const isMobile = useBreakpointValue({ base: true, md: false });
// 保留原有的调试信息
useEffect(() => {
logger.debug('HomePage', 'AuthContext状态', {
userId: user?.id,
username: user?.username,
nickname: user?.nickname,
isAuthenticated,
hasUser: !!user
});
}, [user?.id, isAuthenticated]); // 只依赖 user.id,避免无限循环
// 核心功能配置 - 5个主要功能
const coreFeatures = [
{
id: 'news-catalyst',
title: '新闻催化分析',
description: '实时新闻事件分析,捕捉市场催化因子',
icon: '📊',
color: 'yellow',
url: 'https://valuefrontier.cn/community',
badge: '核心',
featured: true
},
{
id: 'concepts',
title: '概念中心',
description: '热门概念与主题投资分析追踪',
icon: '🎯',
color: 'purple',
url: 'https://valuefrontier.cn/concepts',
badge: '热门'
},
{
id: 'stocks',
title: '个股信息汇总',
description: '全面的个股基本面信息整合',
icon: '📈',
color: 'blue',
url: 'https://valuefrontier.cn/stocks',
badge: '全面'
},
{
id: 'limit-analyse',
title: '涨停板块分析',
description: '涨停板数据深度分析与规律挖掘',
icon: '🚀',
color: 'green',
url: 'https://valuefrontier.cn/limit-analyse',
badge: '精准'
},
{
id: 'company',
title: '个股罗盘',
description: '个股全方位分析与投资决策支持',
icon: '🧭',
color: 'orange',
url: 'https://valuefrontier.cn/company?scode=688256',
badge: '专业'
},
{
id: 'trading-simulation',
title: '模拟盘交易',
description: '100万起始资金体验真实交易环境',
icon: '💰',
color: 'teal',
url: '/trading-simulation',
badge: '实战'
}
];
// 个人中心配置
// const personalCenter = {
// title: '个人中心',
// description: '账户管理与个人设置',
// icon: '👤',
// color: 'gray',
// url: 'https://valuefrontier.cn/home/center'
// };
// @TODO 如何区分内部链接和外部链接?
const handleProductClick = (url) => {
if (url.startsWith('http')) {
// 外部链接,直接打开
window.open(url, '_blank');
} else {
// 内部路由
navigate(url);
}
};
return (
<Box>
{/* 开发调试信息 */}
{/* {process.env.NODE_ENV === 'development' && (
<Box bg="rgba(0, 0, 0, 0.8)" color="yellow.200" p={2} fontSize="xs" zIndex={1000} position="relative">
认证: {isAuthenticated ? '✅' : '❌'} | 用户: {user?.nickname || '无'}
</Box>
)} */}
{/* Hero Section - 深色科技风格 */}
<Box
position="relative"
minH={heroHeight}
bg="linear-gradient(135deg, #0E0C15 0%, #15131D 50%, #252134 100%)"
overflow="hidden"
>
{/* 背景图片和装饰 - 优化:延迟加载 */}
<Box
position="absolute"
top="0"
right="0"
w="50%"
h="100%"
bgImage={imageLoaded ? `url(${heroBg})` : 'none'}
bgSize="cover"
bgPosition="center"
opacity={imageLoaded ? 0.3 : 0}
transition="opacity 0.5s ease-in"
_after={{
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(90deg, rgba(14, 12, 21, 0.9) 0%, rgba(14, 12, 21, 0.3) 100%)'
}}
/>
{/* 预加载背景图片 */}
<Box display="none">
<img
src={heroBg}
alt=""
onLoad={() => setImageLoaded(true)}
onError={() => setImageLoaded(true)}
/>
</Box>
{/* 装饰性几何图形 - 移动端隐藏 */}
{showDecorations && (
<>
<Box
position="absolute"
top="20%"
left="10%"
w={{ base: '100px', md: '150px', lg: '200px' }}
h={{ base: '100px', md: '150px', lg: '200px' }}
borderRadius="50%"
bg="rgba(255, 215, 0, 0.1)"
filter="blur(80px)"
className="float-animation"
/>
<Box
position="absolute"
bottom="30%"
right="20%"
w={{ base: '80px', md: '120px', lg: '150px' }}
h={{ base: '80px', md: '120px', lg: '150px' }}
borderRadius="50%"
bg="rgba(138, 43, 226, 0.1)"
filter="blur(60px)"
className="float-animation-reverse"
/>
</>
)}
<Container maxW="7xl" position="relative" zIndex={2} px={containerPx}>
<VStack spacing={{ base: 8, md: 12, lg: 16 }} align="stretch" minH={heroHeight} justify="center">
{/* 主标题区域 */}
<VStack spacing={{ base: 4, md: 5, lg: 6 }} textAlign="center" pt={{ base: 4, md: 6, lg: 8 }}>
<Heading
size={headingSize}
color="white"
fontWeight="900"
letterSpacing={headingLetterSpacing}
lineHeight="shorter"
>
智能投资分析平台
</Heading>
<Text fontSize={heroTextSize} color="whiteAlpha.800" maxW={{ base: '100%', md: '2xl', lg: '3xl' }} lineHeight="tall" px={{ base: 4, md: 0 }}>
专业投资研究工具助您把握市场机遇
</Text>
</VStack>
{/* 核心功能面板 */}
<Box pb={{ base: 8, md: 12 }}>
<VStack spacing={{ base: 6, md: 8 }}>
{/* 新闻催化分析 - 突出显示 */}
<Card
bg="transparent"
border="2px solid"
borderColor="yellow.400"
borderRadius={{ base: '2xl', md: '3xl' }}
overflow="hidden"
position="relative"
shadow="2xl"
w="100%"
_before={{
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(135deg, rgba(255, 215, 0, 0.1) 0%, rgba(255, 165, 0, 0.05) 100%)',
zIndex: 0
}}
>
<CardBody p={{ base: 6, md: 8 }} position="relative" zIndex={1}>
{isMobile ? (
/* 移动端:垂直布局 */
<VStack spacing={4} align="stretch">
<HStack spacing={4}>
<Box
p={3}
borderRadius="lg"
bg="yellow.400"
color="black"
>
<Text fontSize="2xl">{coreFeatures[0].icon}</Text>
</Box>
<VStack align="start" spacing={1} flex={1}>
<Heading size="lg" color="white">
{coreFeatures[0].title}
</Heading>
<Badge colorScheme="yellow" variant="solid" fontSize="xs">
{coreFeatures[0].badge}
</Badge>
</VStack>
</HStack>
<Text color="whiteAlpha.800" fontSize="md" lineHeight="tall">
{coreFeatures[0].description}
</Text>
<Button
colorScheme="yellow"
size="md"
borderRadius="full"
fontWeight="bold"
w="100%"
onClick={() => handleProductClick(coreFeatures[0].url)}
minH="44px"
>
进入功能
</Button>
</VStack>
) : (
/* 桌面端:横向布局 */
<Flex align="center" justify="space-between">
<HStack spacing={6}>
<Box
p={4}
borderRadius="xl"
bg="yellow.400"
color="black"
>
<Text fontSize="3xl">{coreFeatures[0].icon}</Text>
</Box>
<VStack align="start" spacing={2}>
<HStack>
<Heading size="xl" color="white">
{coreFeatures[0].title}
</Heading>
<Badge colorScheme="yellow" variant="solid" fontSize="sm">
{coreFeatures[0].badge}
</Badge>
</HStack>
<Text color="whiteAlpha.800" fontSize="lg" maxW="md">
{coreFeatures[0].description}
</Text>
</VStack>
</HStack>
<Button
colorScheme="yellow"
size="lg"
borderRadius="full"
fontWeight="bold"
onClick={() => handleProductClick(coreFeatures[0].url)}
>
进入功能
</Button>
</Flex>
)}
</CardBody>
</Card>
{/* 其他5个功能 */}
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={{ base: 4, md: 5, lg: 6 }} w="100%">
{coreFeatures.slice(1).map((feature) => (
<Card
key={feature.id}
bg="whiteAlpha.100"
backdropFilter="blur(10px)"
border="1px solid"
borderColor="whiteAlpha.200"
borderRadius={{ base: 'xl', md: '2xl' }}
cursor="pointer"
transition="all 0.3s ease"
_hover={{
bg: 'whiteAlpha.200',
borderColor: `${feature.color}.400`,
transform: 'translateY(-4px)',
shadow: '2xl'
}}
_active={{
bg: 'whiteAlpha.200',
borderColor: `${feature.color}.400`,
transform: 'translateY(-2px)'
}}
onClick={() => handleProductClick(feature.url)}
minH={{ base: 'auto', md: '180px' }}
>
<CardBody p={{ base: 5, md: 6 }}>
<VStack spacing={{ base: 3, md: 4 }} align="start" h="100%">
<HStack>
<Box
p={{ base: 2, md: 3 }}
borderRadius="lg"
bg={`${feature.color}.50`}
border="1px solid"
borderColor={`${feature.color}.200`}
>
<Text fontSize={{ base: 'xl', md: '2xl' }}>{feature.icon}</Text>
</Box>
<Badge colorScheme={feature.color} variant="solid" fontSize={{ base: 'xs', md: 'sm' }}>
{feature.badge}
</Badge>
</HStack>
<VStack align="start" spacing={{ base: 1, md: 2 }} flex={1}>
<Heading size={{ base: 'md', md: 'lg' }} color="white">
{feature.title}
</Heading>
<Text color="whiteAlpha.800" fontSize={{ base: 'xs', md: 'sm' }} lineHeight="tall">
{feature.description}
</Text>
</VStack>
<Button
colorScheme={feature.color}
size={{ base: 'md', md: 'sm' }}
variant="outline"
alignSelf="flex-end"
w={{ base: '100%', md: 'auto' }}
minH="44px"
onClick={(e) => {
e.stopPropagation();
handleProductClick(feature.url);
}}
>
使用
</Button>
</VStack>
</CardBody>
</Card>
))}
</SimpleGrid>
</VStack>
</Box>
</VStack>
</Container>
</Box>
{/* 底部区域 */}
<Box
bg="linear-gradient(135deg, #0E0C15 0%, #15131D 100%)"
py={{ base: 8, md: 12 }}
position="relative"
>
<Container maxW="7xl" position="relative" zIndex={1} px={containerPx}>
<VStack spacing={{ base: 4, md: 6 }} textAlign="center">
<Text color="whiteAlpha.600" fontSize={{ base: 'xs', md: 'sm' }}>
© 2024 价值前沿. 保留所有权利.
</Text>
<HStack spacing={{ base: 2, md: 4 }} fontSize="xs" color="whiteAlpha.500" flexWrap="wrap" justify="center">
<Link
href="https://beian.mps.gov.cn/#/query/webSearch?code=11010802046286"
isExternal
color="whiteAlpha.500"
_hover={{ color: 'whiteAlpha.700' }}
>
京公网安备11010802046286号
</Link>
<Text>京ICP备2025107343号-1</Text>
</HStack>
</VStack>
</Container>
</Box>
</Box>
);
}