refactor(StockOverview): 迁移至 HeroSection 组件
- 使用通用 HeroSection 替换原有 Hero 区域代码 - 配置 purple 主题预设和自定义金色渐变 - 统计区显示市值、成交额、上涨/下跌家数 - 搜索框支持下拉结果选择 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,7 @@ import ConceptStocksModal from '@components/ConceptStocksModal';
|
||||
import TradeDatePicker from '@components/TradeDatePicker';
|
||||
import HotspotOverview from './components/HotspotOverview';
|
||||
import FlexScreen from './components/FlexScreen';
|
||||
import { HeroSection } from '@components/HeroSection';
|
||||
import { echarts } from '@lib/echarts';
|
||||
import { logger } from '../../utils/logger';
|
||||
import { getConceptHtmlUrl } from '../../utils/textUtils';
|
||||
@@ -623,240 +624,83 @@ const StockOverview = () => {
|
||||
zIndex={0}
|
||||
/>
|
||||
|
||||
{/* Hero Section */}
|
||||
<Box
|
||||
position="relative"
|
||||
bgGradient={heroBg}
|
||||
color="white"
|
||||
overflow="visible"
|
||||
pt={{ base: 20, md: 24 }}
|
||||
pb={{ base: 16, md: 20 }}
|
||||
borderBottom={`1px solid rgba(139, 92, 246, 0.3)`}
|
||||
borderRadius="xl"
|
||||
zIndex={1}
|
||||
>
|
||||
{/* 背景装饰 */}
|
||||
<Box
|
||||
position="absolute"
|
||||
top="-20%"
|
||||
right="-10%"
|
||||
width="40%"
|
||||
height="120%"
|
||||
bg={`${goldColor}15`}
|
||||
transform="rotate(12deg)"
|
||||
borderRadius="full"
|
||||
filter="blur(60px)"
|
||||
/>
|
||||
|
||||
<Box px={6} position="relative">
|
||||
<VStack spacing={8} align="center">
|
||||
<VStack spacing={4} textAlign="center" maxW="3xl">
|
||||
<HStack spacing={3}>
|
||||
<Icon as={TrendingUp} boxSize={12} color={colorMode === 'dark' ? goldColor : 'white'} />
|
||||
<Heading
|
||||
as="h1"
|
||||
size="2xl"
|
||||
fontWeight="bold"
|
||||
bgGradient={colorMode === 'dark' ? `linear(to-r, ${goldColor}, white)` : 'none'}
|
||||
bgClip={colorMode === 'dark' ? 'text' : 'none'}
|
||||
>
|
||||
个股中心
|
||||
</Heading>
|
||||
</HStack>
|
||||
|
||||
<Text fontSize="xl" opacity={0.9} color={colorMode === 'dark' ? 'gray.300' : 'white'}>
|
||||
实时追踪市场动态,洞察投资机会
|
||||
</Text>
|
||||
</VStack>
|
||||
|
||||
{/* 搜索框 */}
|
||||
<Box w="100%" maxW="2xl" position="relative">
|
||||
<InputGroup
|
||||
size="lg"
|
||||
bg={searchBg}
|
||||
borderRadius="full"
|
||||
boxShadow="2xl"
|
||||
border="2px solid"
|
||||
borderColor={colorMode === 'dark' ? goldColor : 'transparent'}
|
||||
>
|
||||
<InputLeftElement pointerEvents="none">
|
||||
<Search size={16} color={colorMode === 'dark' ? goldColor : 'gray.400'} />
|
||||
</InputLeftElement>
|
||||
<Input
|
||||
placeholder="搜索股票代码、名称或拼音首字母..."
|
||||
value={searchQuery}
|
||||
onChange={handleSearchChange}
|
||||
borderRadius="full"
|
||||
border="none"
|
||||
color={textColor}
|
||||
bg="transparent"
|
||||
_placeholder={{ color: colorMode === 'dark' ? 'gray.500' : 'gray.400' }}
|
||||
_focus={{
|
||||
boxShadow: 'none',
|
||||
borderColor: 'transparent',
|
||||
bg: colorMode === 'dark' ? 'whiteAlpha.50' : 'transparent'
|
||||
}}
|
||||
pr={searchQuery ? "3rem" : "1rem"}
|
||||
/>
|
||||
{searchQuery && (
|
||||
<InputRightElement>
|
||||
<IconButton
|
||||
size="sm"
|
||||
icon={<X size={16} />}
|
||||
variant="ghost"
|
||||
onClick={handleClearSearch}
|
||||
aria-label="清空搜索"
|
||||
color={colorMode === 'dark' ? goldColor : 'gray.600'}
|
||||
_hover={{
|
||||
bg: colorMode === 'dark' ? 'whiteAlpha.100' : 'gray.100'
|
||||
}}
|
||||
/>
|
||||
</InputRightElement>
|
||||
)}
|
||||
</InputGroup>
|
||||
|
||||
{/* 搜索结果下拉 */}
|
||||
<Collapse in={showResults} animateOpacity>
|
||||
<Box
|
||||
position="absolute"
|
||||
top="100%"
|
||||
left={0}
|
||||
right={0}
|
||||
mt={2}
|
||||
bg={searchBg}
|
||||
borderRadius="xl"
|
||||
boxShadow="2xl"
|
||||
border="1px solid"
|
||||
borderColor={borderColor}
|
||||
maxH="400px"
|
||||
overflowY="auto"
|
||||
zIndex={10}
|
||||
>
|
||||
{isSearching ? (
|
||||
<Center p={4}>
|
||||
<Spinner color={accentColor} />
|
||||
</Center>
|
||||
) : searchResults.length > 0 ? (
|
||||
<List spacing={0}>
|
||||
{searchResults.map((stock, index) => (
|
||||
<ListItem
|
||||
key={stock.stock_code}
|
||||
p={4}
|
||||
cursor="pointer"
|
||||
_hover={{ bg: hoverBg }}
|
||||
onClick={() => handleSelectStock(stock, index)}
|
||||
borderBottomWidth={index < searchResults.length - 1 ? "1px" : "0"}
|
||||
borderColor={borderColor}
|
||||
>
|
||||
<Flex align="center" justify="space-between">
|
||||
<VStack align="start" spacing={1} flex={1}>
|
||||
<Text fontWeight="bold" color={textColor}>{stock.stock_name}</Text>
|
||||
<HStack spacing={2}>
|
||||
<Text fontSize="sm" color={subTextColor}>{stock.stock_code}</Text>
|
||||
{stock.pinyin_abbr && (
|
||||
<Text fontSize="xs" color={subTextColor}>({stock.pinyin_abbr.toUpperCase()})</Text>
|
||||
)}
|
||||
{stock.exchange && (
|
||||
<Tag
|
||||
size="sm"
|
||||
bg={colorMode === 'dark' ? '#2a2a2a' : 'blue.50'}
|
||||
color={colorMode === 'dark' ? goldColor : 'blue.600'}
|
||||
border="1px solid"
|
||||
borderColor={colorMode === 'dark' ? goldColor : 'blue.200'}
|
||||
>
|
||||
{stock.exchange}
|
||||
</Tag>
|
||||
)}
|
||||
</HStack>
|
||||
</VStack>
|
||||
<Button
|
||||
size="sm"
|
||||
rightIcon={<ArrowRight size={16} />}
|
||||
variant="ghost"
|
||||
colorScheme={colorMode === 'dark' ? 'yellow' : 'purple'}
|
||||
_hover={{
|
||||
bg: colorMode === 'dark' ? 'whiteAlpha.100' : 'purple.50'
|
||||
}}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
</Flex>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
) : (
|
||||
<Center p={4}>
|
||||
<Text color={subTextColor}>未找到相关股票</Text>
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
</Collapse>
|
||||
</Box>
|
||||
|
||||
{/* 统计数据 - 使用市场统计API数据 */}
|
||||
<SimpleGrid columns={{ base: 2, md: 4 }} spacing={6} w="100%" maxW="4xl">
|
||||
<Stat
|
||||
textAlign="center"
|
||||
bg={colorMode === 'dark' ? 'whiteAlpha.100' : 'whiteAlpha.800'}
|
||||
p={4}
|
||||
borderRadius="lg"
|
||||
border={colorMode === 'dark' ? `1px solid ${goldColor}50` : 'none'}
|
||||
>
|
||||
<StatLabel color={colorMode === 'dark' ? goldColor : 'purple.700'} fontWeight="bold">A股总市值</StatLabel>
|
||||
<StatNumber fontSize="2xl" color={colorMode === 'dark' ? 'white' : 'purple.800'}>
|
||||
{marketStats ?
|
||||
`${(marketStats.total_market_cap / 10000).toFixed(1)}万亿`
|
||||
: '-'
|
||||
}
|
||||
</StatNumber>
|
||||
</Stat>
|
||||
<Stat
|
||||
textAlign="center"
|
||||
bg={colorMode === 'dark' ? 'whiteAlpha.100' : 'whiteAlpha.800'}
|
||||
p={4}
|
||||
borderRadius="lg"
|
||||
border={colorMode === 'dark' ? `1px solid ${goldColor}50` : 'none'}
|
||||
>
|
||||
<StatLabel color={colorMode === 'dark' ? goldColor : 'purple.700'} fontWeight="bold">今日成交额</StatLabel>
|
||||
<StatNumber fontSize="2xl" color={colorMode === 'dark' ? 'white' : 'purple.800'}>
|
||||
{marketStats ?
|
||||
`${(marketStats.total_amount / 10000).toFixed(1)}万亿`
|
||||
: '-'
|
||||
}
|
||||
</StatNumber>
|
||||
</Stat>
|
||||
<Stat
|
||||
textAlign="center"
|
||||
bg={colorMode === 'dark' ? 'whiteAlpha.100' : 'whiteAlpha.800'}
|
||||
p={4}
|
||||
borderRadius="lg"
|
||||
border={colorMode === 'dark' ? `1px solid ${goldColor}50` : 'none'}
|
||||
>
|
||||
<StatLabel color={colorMode === 'dark' ? goldColor : 'purple.700'} fontWeight="bold">上涨家数</StatLabel>
|
||||
<StatNumber fontSize="2xl" color={colorMode === 'dark' ? '#ff4d4d' : 'red.500'}>
|
||||
{marketStats && marketStats.rising_count !== undefined && marketStats.rising_count !== null ?
|
||||
marketStats.rising_count.toLocaleString() : '-'
|
||||
}
|
||||
</StatNumber>
|
||||
</Stat>
|
||||
<Stat
|
||||
textAlign="center"
|
||||
bg={colorMode === 'dark' ? 'whiteAlpha.100' : 'whiteAlpha.800'}
|
||||
p={4}
|
||||
borderRadius="lg"
|
||||
border={colorMode === 'dark' ? `1px solid ${goldColor}50` : 'none'}
|
||||
>
|
||||
<StatLabel color={colorMode === 'dark' ? goldColor : 'purple.700'} fontWeight="bold">下跌家数</StatLabel>
|
||||
<StatNumber fontSize="2xl" color="green.400">
|
||||
{marketStats && marketStats.falling_count !== undefined && marketStats.falling_count !== null ?
|
||||
marketStats.falling_count.toLocaleString() : '-'
|
||||
}
|
||||
</StatNumber>
|
||||
</Stat>
|
||||
</SimpleGrid>
|
||||
</VStack>
|
||||
</Box>
|
||||
</Box>
|
||||
{/* Hero Section - 使用通用 HeroSection 组件 */}
|
||||
<HeroSection
|
||||
icon={TrendingUp}
|
||||
title="个股中心"
|
||||
subtitle="实时追踪市场动态,洞察投资机会"
|
||||
themePreset="purple"
|
||||
themeColors={{
|
||||
titleGradient: `linear(to-r, ${goldColor}, white)`,
|
||||
iconColor: goldColor,
|
||||
statLabelColor: goldColor,
|
||||
statCardBorder: `${goldColor}50`,
|
||||
}}
|
||||
decorations={[
|
||||
{
|
||||
type: 'glowOrbs',
|
||||
intensity: 0.4,
|
||||
orbs: [
|
||||
{ top: '-20%', right: '-10%', size: '40%', color: `${goldColor}15`, blur: '60px' },
|
||||
],
|
||||
},
|
||||
]}
|
||||
search={{
|
||||
placeholder: '搜索股票代码、名称或拼音首字母...',
|
||||
showSearchButton: true,
|
||||
searchButtonText: '搜索',
|
||||
maxWidth: '2xl',
|
||||
// 受控模式
|
||||
value: searchQuery,
|
||||
onChange: (value) => {
|
||||
setSearchQuery(value);
|
||||
if (value && !searchQuery) {
|
||||
trackSearchInitiated();
|
||||
}
|
||||
debounceSearch(value);
|
||||
},
|
||||
onClear: handleClearSearch,
|
||||
results: searchResults.map((stock) => ({
|
||||
id: stock.stock_code,
|
||||
label: stock.stock_name,
|
||||
subLabel: stock.stock_code,
|
||||
extra: stock.pinyin_abbr?.toUpperCase(),
|
||||
tags: stock.exchange ? [{ text: stock.exchange }] : [],
|
||||
raw: stock,
|
||||
})),
|
||||
isSearching: isSearching,
|
||||
showDropdown: showResults,
|
||||
onSearch: async () => [],
|
||||
onResultSelect: (item, index) => handleSelectStock(item.raw, index),
|
||||
}}
|
||||
stats={{
|
||||
columns: { base: 2, md: 4 },
|
||||
items: [
|
||||
{
|
||||
key: 'marketCap',
|
||||
label: 'A股总市值',
|
||||
value: marketStats ? `${(marketStats.total_market_cap / 10000).toFixed(1)}万亿` : null,
|
||||
},
|
||||
{
|
||||
key: 'amount',
|
||||
label: '今日成交额',
|
||||
value: marketStats ? `${(marketStats.total_amount / 10000).toFixed(1)}万亿` : null,
|
||||
},
|
||||
{
|
||||
key: 'rising',
|
||||
label: '上涨家数',
|
||||
value: marketStats?.rising_count,
|
||||
valueColor: '#ff4d4d',
|
||||
},
|
||||
{
|
||||
key: 'falling',
|
||||
label: '下跌家数',
|
||||
value: marketStats?.falling_count,
|
||||
valueColor: 'green.400',
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 主内容区 */}
|
||||
<Box py={10} px={6} position="relative" zIndex={1}>
|
||||
|
||||
Reference in New Issue
Block a user