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 TradeDatePicker from '@components/TradeDatePicker';
|
||||||
import HotspotOverview from './components/HotspotOverview';
|
import HotspotOverview from './components/HotspotOverview';
|
||||||
import FlexScreen from './components/FlexScreen';
|
import FlexScreen from './components/FlexScreen';
|
||||||
|
import { HeroSection } from '@components/HeroSection';
|
||||||
import { echarts } from '@lib/echarts';
|
import { echarts } from '@lib/echarts';
|
||||||
import { logger } from '../../utils/logger';
|
import { logger } from '../../utils/logger';
|
||||||
import { getConceptHtmlUrl } from '../../utils/textUtils';
|
import { getConceptHtmlUrl } from '../../utils/textUtils';
|
||||||
@@ -623,240 +624,83 @@ const StockOverview = () => {
|
|||||||
zIndex={0}
|
zIndex={0}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section - 使用通用 HeroSection 组件 */}
|
||||||
<Box
|
<HeroSection
|
||||||
position="relative"
|
icon={TrendingUp}
|
||||||
bgGradient={heroBg}
|
title="个股中心"
|
||||||
color="white"
|
subtitle="实时追踪市场动态,洞察投资机会"
|
||||||
overflow="visible"
|
themePreset="purple"
|
||||||
pt={{ base: 20, md: 24 }}
|
themeColors={{
|
||||||
pb={{ base: 16, md: 20 }}
|
titleGradient: `linear(to-r, ${goldColor}, white)`,
|
||||||
borderBottom={`1px solid rgba(139, 92, 246, 0.3)`}
|
iconColor: goldColor,
|
||||||
borderRadius="xl"
|
statLabelColor: goldColor,
|
||||||
zIndex={1}
|
statCardBorder: `${goldColor}50`,
|
||||||
>
|
}}
|
||||||
{/* 背景装饰 */}
|
decorations={[
|
||||||
<Box
|
{
|
||||||
position="absolute"
|
type: 'glowOrbs',
|
||||||
top="-20%"
|
intensity: 0.4,
|
||||||
right="-10%"
|
orbs: [
|
||||||
width="40%"
|
{ top: '-20%', right: '-10%', size: '40%', color: `${goldColor}15`, blur: '60px' },
|
||||||
height="120%"
|
],
|
||||||
bg={`${goldColor}15`}
|
},
|
||||||
transform="rotate(12deg)"
|
]}
|
||||||
borderRadius="full"
|
search={{
|
||||||
filter="blur(60px)"
|
placeholder: '搜索股票代码、名称或拼音首字母...',
|
||||||
/>
|
showSearchButton: true,
|
||||||
|
searchButtonText: '搜索',
|
||||||
<Box px={6} position="relative">
|
maxWidth: '2xl',
|
||||||
<VStack spacing={8} align="center">
|
// 受控模式
|
||||||
<VStack spacing={4} textAlign="center" maxW="3xl">
|
value: searchQuery,
|
||||||
<HStack spacing={3}>
|
onChange: (value) => {
|
||||||
<Icon as={TrendingUp} boxSize={12} color={colorMode === 'dark' ? goldColor : 'white'} />
|
setSearchQuery(value);
|
||||||
<Heading
|
if (value && !searchQuery) {
|
||||||
as="h1"
|
trackSearchInitiated();
|
||||||
size="2xl"
|
}
|
||||||
fontWeight="bold"
|
debounceSearch(value);
|
||||||
bgGradient={colorMode === 'dark' ? `linear(to-r, ${goldColor}, white)` : 'none'}
|
},
|
||||||
bgClip={colorMode === 'dark' ? 'text' : 'none'}
|
onClear: handleClearSearch,
|
||||||
>
|
results: searchResults.map((stock) => ({
|
||||||
个股中心
|
id: stock.stock_code,
|
||||||
</Heading>
|
label: stock.stock_name,
|
||||||
</HStack>
|
subLabel: stock.stock_code,
|
||||||
|
extra: stock.pinyin_abbr?.toUpperCase(),
|
||||||
<Text fontSize="xl" opacity={0.9} color={colorMode === 'dark' ? 'gray.300' : 'white'}>
|
tags: stock.exchange ? [{ text: stock.exchange }] : [],
|
||||||
实时追踪市场动态,洞察投资机会
|
raw: stock,
|
||||||
</Text>
|
})),
|
||||||
</VStack>
|
isSearching: isSearching,
|
||||||
|
showDropdown: showResults,
|
||||||
{/* 搜索框 */}
|
onSearch: async () => [],
|
||||||
<Box w="100%" maxW="2xl" position="relative">
|
onResultSelect: (item, index) => handleSelectStock(item.raw, index),
|
||||||
<InputGroup
|
}}
|
||||||
size="lg"
|
stats={{
|
||||||
bg={searchBg}
|
columns: { base: 2, md: 4 },
|
||||||
borderRadius="full"
|
items: [
|
||||||
boxShadow="2xl"
|
{
|
||||||
border="2px solid"
|
key: 'marketCap',
|
||||||
borderColor={colorMode === 'dark' ? goldColor : 'transparent'}
|
label: 'A股总市值',
|
||||||
>
|
value: marketStats ? `${(marketStats.total_market_cap / 10000).toFixed(1)}万亿` : null,
|
||||||
<InputLeftElement pointerEvents="none">
|
},
|
||||||
<Search size={16} color={colorMode === 'dark' ? goldColor : 'gray.400'} />
|
{
|
||||||
</InputLeftElement>
|
key: 'amount',
|
||||||
<Input
|
label: '今日成交额',
|
||||||
placeholder="搜索股票代码、名称或拼音首字母..."
|
value: marketStats ? `${(marketStats.total_amount / 10000).toFixed(1)}万亿` : null,
|
||||||
value={searchQuery}
|
},
|
||||||
onChange={handleSearchChange}
|
{
|
||||||
borderRadius="full"
|
key: 'rising',
|
||||||
border="none"
|
label: '上涨家数',
|
||||||
color={textColor}
|
value: marketStats?.rising_count,
|
||||||
bg="transparent"
|
valueColor: '#ff4d4d',
|
||||||
_placeholder={{ color: colorMode === 'dark' ? 'gray.500' : 'gray.400' }}
|
},
|
||||||
_focus={{
|
{
|
||||||
boxShadow: 'none',
|
key: 'falling',
|
||||||
borderColor: 'transparent',
|
label: '下跌家数',
|
||||||
bg: colorMode === 'dark' ? 'whiteAlpha.50' : 'transparent'
|
value: marketStats?.falling_count,
|
||||||
}}
|
valueColor: 'green.400',
|
||||||
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>
|
|
||||||
|
|
||||||
{/* 主内容区 */}
|
{/* 主内容区 */}
|
||||||
<Box py={10} px={6} position="relative" zIndex={1}>
|
<Box py={10} px={6} position="relative" zIndex={1}>
|
||||||
|
|||||||
Reference in New Issue
Block a user