update pay function

This commit is contained in:
2025-11-23 09:01:00 +08:00
parent 173ddb985d
commit 04c13f3a6c
2 changed files with 456 additions and 1822 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -693,139 +693,235 @@ const ConceptCenter = () => {
init(); init();
}, []); }, []);
// 概念卡片组件 - 优化 // 概念卡片组件 - 科幻毛玻璃
const ConceptCard = ({ concept, position = 0 }) => { const ConceptCard = ({ concept, position = 0 }) => {
const changePercent = concept.price_info?.avg_change_pct; const changePercent = concept.price_info?.avg_change_pct;
const changeColor = getChangeColor(changePercent); const changeColor = getChangeColor(changePercent);
const hasChange = changePercent !== null && changePercent !== undefined; const hasChange = changePercent !== null && changePercent !== undefined;
// 生成随机涨幅数字背景
const generateNumbersBackground = () => {
const numbers = [];
for (let i = 0; i < 30; i++) {
const isPositive = Math.random() > 0.5;
const value = (Math.random() * 15).toFixed(2);
const sign = isPositive ? '+' : '-';
numbers.push(`${sign}${value}%`);
}
return numbers;
};
const backgroundNumbers = generateNumbersBackground();
return ( return (
<Card <Card
cursor="pointer" cursor="pointer"
onClick={() => handleConceptClick(concept.concept_id, concept.concept, concept, position)} onClick={() => handleConceptClick(concept.concept_id, concept.concept, concept, position)}
bg="white" bg="white"
borderWidth="1px" borderWidth="1px"
borderColor="gray.200" borderColor="transparent"
overflow="hidden" overflow="hidden"
_hover={{ _hover={{
transform: 'translateY(-8px)', transform: 'translateY(-8px)',
boxShadow: 'xl', boxShadow: '0 20px 40px rgba(139, 92, 246, 0.3)',
borderColor: 'purple.300', borderColor: 'purple.400',
}} }}
transition="all 0.3s" transition="all 0.3s"
position="relative" position="relative"
boxShadow="0 4px 12px rgba(0, 0, 0, 0.1)"
> >
{/* 毛玻璃涨幅数字背景 */}
<Box position="relative" height="180px" overflow="hidden"> <Box position="relative" height="180px" overflow="hidden">
<Image {/* 渐变背景层 */}
src={defaultImage}
alt={concept.concept}
height="100%"
width="100%"
objectFit="cover"
fallback={
<Box
height="100%"
bgGradient="linear(to-br, purple.100, pink.100)"
display="flex"
alignItems="center"
justifyContent="center"
>
<Icon as={FaTags} boxSize={12} color="purple.300" opacity={0.5} />
</Box>
}
/>
<Box <Box
position="absolute" position="absolute"
top={0} top={0}
left={0} left={0}
right={0} right={0}
bottom={0} bottom={0}
bgGradient="linear(to-t, blackAlpha.700, transparent)" bgGradient={
hasChange && changePercent > 0
? "linear(135deg, #667eea 0%, #764ba2 100%)"
: hasChange && changePercent < 0
? "linear(135deg, #f093fb 0%, #f5576c 100%)"
: "linear(135deg, #4facfe 0%, #00f2fe 100%)"
}
/> />
{hasChange && ( {/* 数字矩阵层 */}
<Badge <Box
position="absolute" position="absolute"
top={3} top={0}
left={3} left={0}
bg={changeColor === 'red' ? 'red.500' : changeColor === 'green' ? 'green.500' : 'gray.500'} right={0}
color="white" bottom={0}
fontSize="sm" display="grid"
px={2} gridTemplateColumns="repeat(5, 1fr)"
py={1} gridTemplateRows="repeat(6, 1fr)"
borderRadius="full" gap={2}
fontWeight="bold" p={3}
boxShadow="lg" opacity={0.15}
display="flex"
alignItems="center"
gap={1}
animation={Math.abs(changePercent) > 5 ? `${pulseAnimation} 2s infinite` : 'none'}
> >
<Icon {backgroundNumbers.map((num, idx) => (
as={changePercent > 0 ? FaArrowUp : changePercent < 0 ? FaArrowDown : null} <Flex
boxSize={3} key={idx}
/> align="center"
{formatChangePercent(changePercent)} justify="center"
</Badge> fontSize="xs"
)} fontWeight="bold"
color="white"
transform={`rotate(${Math.random() * 20 - 10}deg)`}
>
{num}
</Flex>
))}
</Box>
{/* 毛玻璃层 */}
<Box
position="absolute"
top={0}
left={0}
right={0}
bottom={0}
backdropFilter="blur(8px)"
bg="rgba(255, 255, 255, 0.05)"
/>
{/* 渐变遮罩 */}
<Box
position="absolute"
top={0}
left={0}
right={0}
bottom={0}
bgGradient="linear(to-t, rgba(0,0,0,0.6), transparent)"
/>
{/* 发光边框效果 */}
<Box
position="absolute"
top={0}
left={0}
right={0}
height="2px"
bgGradient="linear(to-r, transparent, rgba(255,255,255,0.5), transparent)"
/>
{/* 右上角股票数量徽章 */}
<Badge <Badge
position="absolute" position="absolute"
top={3} top={3}
right={3} right={3}
bgGradient="linear(to-r, purple.500, pink.500)" bg="rgba(255, 255, 255, 0.2)"
backdropFilter="blur(10px)"
color="white" color="white"
fontSize="xs" fontSize="xs"
px={2} px={3}
py={1} py={1}
borderRadius="full" borderRadius="full"
fontWeight="bold" fontWeight="bold"
boxShadow="md" boxShadow="0 4px 12px rgba(0, 0, 0, 0.2)"
border="1px solid"
borderColor="whiteAlpha.300"
> >
{concept.stock_count || 0} 只股票 {concept.stock_count || 0} 只股票
</Badge> </Badge>
</Box> </Box>
<CardBody p={4}> <CardBody p={4}>
<VStack align="start" spacing={2}> <VStack align="start" spacing={3}>
<Heading size="sm" color="gray.800" noOfLines={1}> {/* 概念名称 */}
<Heading
size="sm"
color="gray.800"
noOfLines={1}
bgGradient="linear(to-r, purple.600, pink.600)"
bgClip="text"
fontWeight="bold"
>
{concept.concept} {concept.concept}
</Heading> </Heading>
{/* 描述信息 */}
<Text color="gray.600" fontSize="xs" noOfLines={2} minH="32px"> <Text color="gray.600" fontSize="xs" noOfLines={2} minH="32px">
{concept.description || '暂无描述信息'} {concept.description || '暂无描述信息'}
</Text> </Text>
{/* 涨跌幅信息卡片 */}
{hasChange && concept.price_info?.trade_date && ( {hasChange && concept.price_info?.trade_date && (
<HStack spacing={3} fontSize="xs" color="gray.500" w="100%"> <Box
<Text>交易日期: {new Date(concept.price_info.trade_date).toLocaleDateString('zh-CN')}</Text> w="100%"
<Spacer /> p={2}
<Text fontWeight="bold" color={`${changeColor}.600`}> borderRadius="md"
bgGradient={
changePercent > 0
? "linear(to-r, rgba(139, 92, 246, 0.1), rgba(168, 85, 247, 0.05))"
: "linear(to-r, rgba(236, 72, 153, 0.1), rgba(251, 113, 133, 0.05))"
}
border="1px solid"
borderColor={changePercent > 0 ? "purple.200" : "pink.200"}
>
<Flex align="center" justify="space-between">
<HStack spacing={2}>
<Icon
as={FaCalendarAlt}
boxSize={3}
color={changePercent > 0 ? "purple.500" : "pink.500"}
/>
<Text fontSize="xs" color="gray.600">
{new Date(concept.price_info.trade_date).toLocaleDateString('zh-CN')}
</Text>
</HStack>
<HStack spacing={1}>
<Icon
as={changePercent > 0 ? FaArrowUp : FaArrowDown}
boxSize={3}
color={changePercent > 0 ? "red.500" : "green.500"}
/>
<Text
fontWeight="bold"
fontSize="sm"
color={changePercent > 0 ? "red.500" : "green.500"}
>
{formatChangePercent(changePercent)} {formatChangePercent(changePercent)}
</Text> </Text>
</HStack> </HStack>
</Flex>
</Box>
)} )}
{concept.stocks && concept.stocks.length > 0 && ( {concept.stocks && concept.stocks.length > 0 && (
<Box <Box
width="100%" width="100%"
p={2} p={3}
bg="gray.50" bg="linear-gradient(135deg, rgba(99, 102, 241, 0.05) 0%, rgba(168, 85, 247, 0.05) 100%)"
borderRadius="md" borderRadius="lg"
cursor="pointer" cursor="pointer"
onClick={(e) => handleViewStocks(e, concept)} onClick={(e) => handleViewStocks(e, concept)}
_hover={{ bg: 'gray.100' }} _hover={{
transition="background 0.2s" bg: 'linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(168, 85, 247, 0.1) 100%)',
transform: 'translateX(2px)',
}}
transition="all 0.2s"
border="1px solid"
borderColor="purple.100"
> >
<Flex align="center" justify="space-between"> <Flex align="center" justify="space-between">
<Box flex={1}> <Box flex={1}>
<HStack spacing={2} mb={1}> <HStack spacing={2} mb={2}>
<Text fontSize="xs" color="gray.600" fontWeight="medium"> <Icon as={FaChartLine} boxSize={3} color="purple.500" />
<Text fontSize="xs" color="purple.700" fontWeight="bold">
热门个股 热门个股
</Text> </Text>
{!hasFeatureAccess('hot_stocks') && ( {!hasFeatureAccess('hot_stocks') && (
<Badge colorScheme="yellow" size="sm"> <Badge
🔒需Pro colorScheme="yellow"
size="sm"
borderRadius="full"
px={2}
>
🔒Pro
</Badge> </Badge>
)} )}
</HStack> </HStack>
@@ -833,13 +929,20 @@ const ConceptCenter = () => {
{hasFeatureAccess('hot_stocks') ? ( {hasFeatureAccess('hot_stocks') ? (
<> <>
{concept.stocks.slice(0, 2).map((stock, idx) => ( {concept.stocks.slice(0, 2).map((stock, idx) => (
<Tag key={idx} size="sm" colorScheme="purple" variant="subtle"> <Tag
key={idx}
size="sm"
bgGradient="linear(to-r, purple.500, pink.500)"
color="white"
borderRadius="full"
px={2}
>
<TagLabel fontSize="xs">{stock.stock_name}</TagLabel> <TagLabel fontSize="xs">{stock.stock_name}</TagLabel>
</Tag> </Tag>
))} ))}
{concept.stocks.length > 2 && ( {concept.stocks.length > 2 && (
<Text fontSize="xs" color="purple.600" fontWeight="medium"> <Text fontSize="xs" color="purple.600" fontWeight="bold">
+{concept.stocks.length - 2}更多 +{concept.stocks.length - 2}
</Text> </Text>
)} )}
</> </>
@@ -862,36 +965,41 @@ const ConceptCenter = () => {
</Box> </Box>
)} )}
<Divider /> <Divider borderColor="purple.100" />
<Flex width="100%" justify="space-between" align="center"> <Flex width="100%" justify="space-between" align="center">
{formatHappenedTimes(concept.happened_times)} {formatHappenedTimes(concept.happened_times)}
<Button <Button
size="sm" size="sm"
leftIcon={<FaChartLine />} // 改成时间轴图标 leftIcon={<FaHistory />}
colorScheme="purple" // 改成紫色主题 bgGradient="linear(to-r, purple.500, pink.500)"
color="white"
variant="solid" variant="solid"
onClick={(e) => handleViewContent(e, concept.concept, concept.concept_id)} // 传入concept_id onClick={(e) => handleViewContent(e, concept.concept, concept.concept_id)}
borderRadius="full" borderRadius="full"
px={4} px={4}
fontWeight="medium" fontWeight="medium"
boxShadow="sm" boxShadow="0 4px 12px rgba(139, 92, 246, 0.3)"
_hover={{ transform: 'scale(1.05)', boxShadow: 'md' }} _hover={{
transform: 'scale(1.05)',
boxShadow: '0 6px 16px rgba(139, 92, 246, 0.4)',
}}
transition="all 0.2s" transition="all 0.2s"
> >
历史时间轴 {/* 改按钮文字 */} 时间轴
</Button> </Button>
</Flex> </Flex>
</VStack> </VStack>
</CardBody> </CardBody>
{/* 顶部发光条 */}
<Box <Box
position="absolute" position="absolute"
top={0} top={0}
left={0} left={0}
right={0} right={0}
height="3px" height="2px"
bgGradient="linear(to-r, purple.400, pink.400, blue.400)" bgGradient="linear(to-r, purple.400, pink.400, blue.400)"
opacity={0} opacity={0}
_groupHover={{ opacity: 1 }} _groupHover={{ opacity: 1 }}
@@ -1078,216 +1186,241 @@ const ConceptCenter = () => {
</Card> </Card>
); );
// 日期选择组件 // 日期选择组件 - 科幻风格
const DateSelector = () => ( const DateSelector = () => (
<HStack spacing={4} p={4} bg="white" borderRadius="lg" shadow="sm"> <Box
<Icon as={FaCalendarAlt} color="purple.500" /> p={4}
<Text fontWeight="medium" color="gray.700">交易日期</Text> bg="rgba(255, 255, 255, 0.8)"
backdropFilter="blur(10px)"
borderRadius="xl"
border="1px solid"
borderColor="purple.100"
boxShadow="0 4px 20px rgba(139, 92, 246, 0.1)"
>
<Flex
direction={{ base: 'column', lg: 'row' }}
align={{ base: 'stretch', lg: 'center' }}
gap={4}
>
<HStack spacing={3}>
<Icon as={FaCalendarAlt} color="purple.500" boxSize={5} />
<Text fontWeight="bold" color="purple.700">交易日期</Text>
</HStack>
<Input <Input
type="date" type="date"
value={selectedDate ? selectedDate.toISOString().split('T')[0] : ''} value={selectedDate ? selectedDate.toISOString().split('T')[0] : ''}
onChange={handleDateChange} onChange={handleDateChange}
max={new Date().toISOString().split('T')[0]} max={new Date().toISOString().split('T')[0]}
width="200px" width={{ base: '100%', lg: '200px' }}
focusBorderColor="purple.500" focusBorderColor="purple.500"
borderColor="purple.200"
borderRadius="lg"
fontWeight="medium"
/> />
<ButtonGroup size="sm" variant="outline"> <ButtonGroup size="sm" variant="outline" flexWrap="wrap">
<Button onClick={() => handleQuickDateSelect(0)} colorScheme="purple"> <Button
onClick={() => handleQuickDateSelect(0)}
borderColor="purple.300"
color="purple.600"
borderRadius="full"
_hover={{
bg: 'purple.50',
borderColor: 'purple.400',
}}
>
今天 今天
</Button> </Button>
<Button onClick={() => handleQuickDateSelect(1)} colorScheme="purple"> <Button
onClick={() => handleQuickDateSelect(1)}
borderColor="purple.300"
color="purple.600"
borderRadius="full"
_hover={{
bg: 'purple.50',
borderColor: 'purple.400',
}}
>
昨天 昨天
</Button> </Button>
<Button onClick={() => handleQuickDateSelect(7)} colorScheme="purple"> <Button
onClick={() => handleQuickDateSelect(7)}
borderColor="purple.300"
color="purple.600"
borderRadius="full"
_hover={{
bg: 'purple.50',
borderColor: 'purple.400',
}}
>
一周前 一周前
</Button> </Button>
<Button onClick={() => handleQuickDateSelect(30)} colorScheme="purple"> <Button
onClick={() => handleQuickDateSelect(30)}
borderColor="purple.300"
color="purple.600"
borderRadius="full"
_hover={{
bg: 'purple.50',
borderColor: 'purple.400',
}}
>
一月前 一月前
</Button> </Button>
</ButtonGroup> </ButtonGroup>
{latestTradeDate && ( {latestTradeDate && (
<Tooltip label="数据库中最新的交易日期"> <Tooltip label="数据库中最新的交易日期">
<HStack spacing={2} ml={4}> <HStack
<Icon as={InfoIcon} color="blue.500" /> spacing={2}
<Text fontSize="sm" color="blue.600"> bg="blue.50"
最新数据: {latestTradeDate.toLocaleDateString('zh-CN')} px={3}
py={1.5}
borderRadius="full"
border="1px solid"
borderColor="blue.200"
>
<Icon as={InfoIcon} color="blue.500" boxSize={3} />
<Text fontSize="sm" color="blue.600" fontWeight="medium">
最新: {latestTradeDate.toLocaleDateString('zh-CN')}
</Text> </Text>
</HStack> </HStack>
</Tooltip> </Tooltip>
)} )}
</HStack> </Flex>
</Box>
); );
return ( return (
<Box minH="100vh" bg="gray.50"> <Box minH="100vh" bg="linear-gradient(180deg, #f8f9ff 0%, #f0f2ff 100%)">
{/* 导航栏已由 MainLayout 提供 */} {/* 导航栏已由 MainLayout 提供 */}
{/* Hero Section */} {/* Hero Section - 精简版 */}
<Box <Box
position="relative" position="relative"
bgGradient="linear(135deg, #667eea 0%, #764ba2 100%)" bgGradient="linear(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%)"
color="white" color="white"
overflow="hidden" overflow="hidden"
> >
{/* 科幻网格背景 */}
<Box <Box
position="absolute" position="absolute"
top="-50%" top="0"
left="-50%" left="0"
width="200%" right="0"
height="200%" bottom="0"
bgImage="radial-gradient(circle, rgba(255,255,255,0.1) 1px, transparent 1px)" bgImage="linear-gradient(rgba(99, 102, 241, 0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(99, 102, 241, 0.1) 1px, transparent 1px)"
bgSize="50px 50px" bgSize="40px 40px"
animation={`${floatAnimation} 20s ease-in-out infinite`}
opacity={0.3} opacity={0.3}
/> />
{/* 发光球体 */}
<Box <Box
position="absolute" position="absolute"
top="10%" top="20%"
right="10%" right="10%"
width="300px" width="200px"
height="300px" height="200px"
borderRadius="full" borderRadius="full"
bgGradient="radial(purple.300, transparent)" bgGradient="radial(circle, rgba(139, 92, 246, 0.4), transparent 70%)"
filter="blur(40px)" filter="blur(40px)"
opacity={0.6}
/> />
<Box <Box
position="absolute" position="absolute"
bottom="10%" bottom="10%"
left="5%" left="10%"
width="400px" width="250px"
height="400px" height="250px"
borderRadius="full" borderRadius="full"
bgGradient="radial(pink.300, transparent)" bgGradient="radial(circle, rgba(59, 130, 246, 0.3), transparent 70%)"
filter="blur(60px)" filter="blur(50px)"
opacity={0.5}
/> />
<Container maxW="container.xl" position="relative" py={{ base: 12, md: 20 }}> <Container maxW="container.xl" position="relative" py={{ base: 8, md: 12 }}>
<VStack spacing={8}> <VStack spacing={6}>
<VStack spacing={4} textAlign="center"> {/* 标题区域 */}
<HStack spacing={4} justify="center"> <VStack spacing={3} textAlign="center">
<Icon as={FaBrain} boxSize={16} color="yellow.300" /> <HStack spacing={3} justify="center">
<Icon as={FaBrain} boxSize={10} color="cyan.300" filter="drop-shadow(0 0 10px rgba(6, 182, 212, 0.5))" />
</HStack> </HStack>
<VStack spacing={2}> <VStack spacing={1}>
<Heading <Heading
as="h1" as="h1"
size="2xl" fontSize={{ base: "3xl", md: "4xl" }}
fontWeight="black" fontWeight="black"
bgGradient="linear(to-r, white, yellow.200)" bgGradient="linear(to-r, cyan.200, purple.200, pink.200)"
bgClip="text" bgClip="text"
letterSpacing="tight" letterSpacing="tight"
lineHeight="shorter" textShadow="0 0 30px rgba(147, 197, 253, 0.3)"
> >
概念中心 概念中心
</Heading> </Heading>
<HStack spacing={2} justify="center"> <HStack spacing={2} justify="center">
<Icon as={FaClock} boxSize={4} color="yellow.200" /> <Icon as={FaClock} boxSize={3} color="cyan.200" />
<Text fontSize="sm" fontWeight="medium" opacity={0.95}> <Text fontSize="xs" fontWeight="medium" opacity={0.8}>
约下午4点更新 数据约下午4点更新
</Text> </Text>
</HStack> </HStack>
<Text fontSize="2xl" fontWeight="medium" opacity={0.95}>
大模型辅助的信息整理与呈现平台
</Text>
<Text fontSize="lg" opacity={0.8} maxW="3xl" lineHeight="tall">
以大模型协助汇聚与清洗多源信息结合自主训练的领域知识图谱
<br />
并由资深分析师进行人工整合与校准提供结构化参考信息
</Text>
</VStack>
</VStack> </VStack>
<SimpleGrid columns={{ base: 2, md: 4 }} spacing={6} w="full" maxW="4xl"> <Text fontSize="md" opacity={0.7} maxW="2xl">
<VStack AI驱动的概念板块分析平台 · 实时追踪市场热点 · 智能挖掘投资机会
</Text>
</VStack>
{/* 核心数据展示 */}
<HStack
spacing={6}
divider={<Box w="1px" h="30px" bg="whiteAlpha.300" />}
bg="whiteAlpha.100" bg="whiteAlpha.100"
backdropFilter="blur(10px)" backdropFilter="blur(10px)"
p={6} px={8}
borderRadius="xl" py={3}
borderRadius="full"
border="1px solid" border="1px solid"
borderColor="whiteAlpha.300" borderColor="whiteAlpha.300"
spacing={3} boxShadow="0 8px 32px rgba(0, 0, 0, 0.3)"
> >
<Icon as={BsLightningFill} boxSize={8} color="yellow.300" /> <HStack spacing={2}>
<Text fontWeight="bold" fontSize="lg">实时更新</Text> <Icon as={FaTags} boxSize={4} color="cyan.300" />
<Text fontSize="sm" opacity={0.8} textAlign="center"> <VStack spacing={0} align="start">
毫秒级数据同步 <Text fontSize="xl" fontWeight="bold" color="cyan.300">500+</Text>
</Text> <Text fontSize="xs" opacity={0.7}>概念板块</Text>
</VStack>
<VStack
bg="whiteAlpha.100"
backdropFilter="blur(10px)"
p={6}
borderRadius="xl"
border="1px solid"
borderColor="whiteAlpha.300"
spacing={3}
>
<Icon as={FaRocket} boxSize={8} color="cyan.300" />
<Text fontWeight="bold" fontSize="lg">智能追踪</Text>
<Text fontSize="sm" opacity={0.8} textAlign="center">
算法智能追踪
</Text>
</VStack>
<VStack
bg="whiteAlpha.100"
backdropFilter="blur(10px)"
p={6}
borderRadius="xl"
border="1px solid"
borderColor="whiteAlpha.300"
spacing={3}
>
<Icon as={FaLightbulb} boxSize={8} color="orange.300" />
<Text fontWeight="bold" fontSize="lg">深度分析</Text>
<Text fontSize="sm" opacity={0.8} textAlign="center">
多维度数据挖掘
</Text>
</VStack>
<VStack
bg="whiteAlpha.100"
backdropFilter="blur(10px)"
p={6}
borderRadius="xl"
border="1px solid"
borderColor="whiteAlpha.300"
spacing={3}
>
<Icon as={FaShieldAlt} boxSize={8} color="green.300" />
<Text fontWeight="bold" fontSize="lg">专业可靠</Text>
<Text fontSize="sm" opacity={0.8} textAlign="center">
权威数据源保障
</Text>
</VStack>
</SimpleGrid>
<HStack spacing={8} divider={<Divider orientation="vertical" height="40px" borderColor="whiteAlpha.400" />}>
<VStack>
<Text fontSize="3xl" fontWeight="bold" color="yellow.300">500+</Text>
<Text fontSize="sm" opacity={0.8}>概念板块</Text>
</VStack>
<VStack>
<Text fontSize="3xl" fontWeight="bold" color="cyan.300">5000+</Text>
<Text fontSize="sm" opacity={0.8}>相关个股</Text>
</VStack>
<VStack>
<Text fontSize="3xl" fontWeight="bold" color="pink.300">24/7</Text>
<Text fontSize="sm" opacity={0.8}>全天候监控</Text>
</VStack> </VStack>
</HStack> </HStack>
<HStack spacing={2}>
<Icon as={FaChartLine} boxSize={4} color="purple.300" />
<VStack spacing={0} align="start">
<Text fontSize="xl" fontWeight="bold" color="purple.300">5000+</Text>
<Text fontSize="xs" opacity={0.7}>相关个股</Text>
</VStack>
</HStack>
<HStack spacing={2}>
<Icon as={BsLightningFill} boxSize={4} color="yellow.300" />
<VStack spacing={0} align="start">
<Text fontSize="xl" fontWeight="bold" color="yellow.300">24/7</Text>
<Text fontSize="xs" opacity={0.7}>实时监控</Text>
</VStack>
</HStack>
</HStack>
{/* 搜索框 */}
<Box w="100%" maxW="3xl"> <Box w="100%" maxW="3xl">
<VStack spacing={2}> <VStack spacing={2}>
<Box w="100%" position="relative"> <Box w="100%" position="relative">
<HStack spacing={0} w="100%" boxShadow="2xl" borderRadius="full" overflow="hidden" bg="white"> <HStack
spacing={0}
w="100%"
boxShadow="0 8px 32px rgba(0, 0, 0, 0.4)"
borderRadius="full"
overflow="hidden"
bg="rgba(255, 255, 255, 0.95)"
backdropFilter="blur(10px)"
border="1px solid"
borderColor="whiteAlpha.400"
>
<InputGroup size="lg" flex={1}> <InputGroup size="lg" flex={1}>
<InputLeftElement pointerEvents="none"> <InputLeftElement pointerEvents="none">
<SearchIcon color="gray.400" /> <SearchIcon color="gray.400" />
@@ -1330,7 +1463,8 @@ const ConceptCenter = () => {
bgGradient="linear(to-r, purple.500, pink.500)" bgGradient="linear(to-r, purple.500, pink.500)"
color="white" color="white"
_hover={{ _hover={{
bgGradient: 'linear(to-r, purple.600, pink.600)' bgGradient: 'linear(to-r, purple.600, pink.600)',
boxShadow: '0 0 20px rgba(168, 85, 247, 0.4)'
}} }}
_active={{ _active={{
bgGradient: 'linear(to-r, purple.700, pink.700)', bgGradient: 'linear(to-r, purple.700, pink.700)',
@@ -1349,7 +1483,7 @@ const ConceptCenter = () => {
</HStack> </HStack>
</Box> </Box>
{searchQuery && sortBy === '_score' && ( {searchQuery && sortBy === '_score' && (
<Text fontSize="xs" color="yellow.200" opacity={0.9}> <Text fontSize="xs" color="cyan.200" opacity={0.9}>
正在搜索 "{searchQuery}"已自动切换到相关度排序 正在搜索 "{searchQuery}"已自动切换到相关度排序
</Text> </Text>
)} )}
@@ -1370,7 +1504,14 @@ const ConceptCenter = () => {
{/* 左侧概念卡片区域 */} {/* 左侧概念卡片区域 */}
<Box flex={1}> <Box flex={1}>
<Card mb={8} shadow="sm"> <Card
mb={8}
bg="rgba(255, 255, 255, 0.8)"
backdropFilter="blur(10px)"
border="1px solid"
borderColor="purple.100"
boxShadow="0 4px 20px rgba(139, 92, 246, 0.1)"
>
<CardBody> <CardBody>
<Flex <Flex
direction={{ base: 'column', md: 'row' }} direction={{ base: 'column', md: 'row' }}
@@ -1379,12 +1520,16 @@ const ConceptCenter = () => {
gap={4} gap={4}
> >
<HStack spacing={4} align="center"> <HStack spacing={4} align="center">
<Text fontWeight="medium" color="gray.700">排序方式</Text> <Icon as={FaTags} boxSize={4} color="purple.500" />
<Text fontWeight="bold" color="purple.700">排序方式</Text>
<Select <Select
value={sortBy} value={sortBy}
onChange={(e) => handleSortChange(e.target.value)} onChange={(e) => handleSortChange(e.target.value)}
width="200px" width="200px"
focusBorderColor="purple.500" focusBorderColor="purple.500"
borderColor="purple.200"
borderRadius="lg"
fontWeight="medium"
> >
<option value="change_pct">涨跌幅</option> <option value="change_pct">涨跌幅</option>
<option value="_score">相关度</option> <option value="_score">相关度</option>
@@ -1393,9 +1538,17 @@ const ConceptCenter = () => {
</Select> </Select>
{searchQuery && sortBy === '_score' && ( {searchQuery && sortBy === '_score' && (
<Tooltip label="搜索时自动切换到相关度排序,以显示最匹配的结果。您也可以手动切换其他排序方式。"> <Tooltip label="搜索时自动切换到相关度排序,以显示最匹配的结果。您也可以手动切换其他排序方式。">
<HStack spacing={1}> <HStack
<Icon as={InfoIcon} color="blue.500" boxSize={4} /> spacing={1}
<Text fontSize="sm" color="blue.600"> bg="blue.50"
px={3}
py={1}
borderRadius="full"
border="1px solid"
borderColor="blue.200"
>
<Icon as={InfoIcon} color="blue.500" boxSize={3} />
<Text fontSize="xs" color="blue.600" fontWeight="medium">
智能排序 智能排序
</Text> </Text>
</HStack> </HStack>
@@ -1412,10 +1565,13 @@ const ConceptCenter = () => {
setViewMode('grid'); setViewMode('grid');
} }
}} }}
bg={viewMode === 'grid' ? 'purple.500' : 'transparent'} bg={viewMode === 'grid' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
color={viewMode === 'grid' ? 'white' : 'purple.500'} color={viewMode === 'grid' ? 'white' : 'purple.500'}
borderColor="purple.500" borderColor="purple.500"
_hover={{ bg: viewMode === 'grid' ? 'purple.600' : 'purple.50' }} _hover={{
bg: viewMode === 'grid' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
boxShadow: viewMode === 'grid' ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
}}
aria-label="网格视图" aria-label="网格视图"
/> />
<IconButton <IconButton
@@ -1426,10 +1582,13 @@ const ConceptCenter = () => {
setViewMode('list'); setViewMode('list');
} }
}} }}
bg={viewMode === 'list' ? 'purple.500' : 'transparent'} bg={viewMode === 'list' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
color={viewMode === 'list' ? 'white' : 'purple.500'} color={viewMode === 'list' ? 'white' : 'purple.500'}
borderColor="purple.500" borderColor="purple.500"
_hover={{ bg: viewMode === 'list' ? 'purple.600' : 'purple.50' }} _hover={{
bg: viewMode === 'list' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
boxShadow: viewMode === 'list' ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
}}
aria-label="列表视图" aria-label="列表视图"
/> />
</ButtonGroup> </ButtonGroup>
@@ -1474,18 +1633,39 @@ const ConceptCenter = () => {
)} )}
<Center mt={12}> <Center mt={12}>
<HStack spacing={2}> <HStack
spacing={3}
bg="rgba(255, 255, 255, 0.8)"
backdropFilter="blur(10px)"
px={6}
py={3}
borderRadius="full"
border="1px solid"
borderColor="purple.100"
boxShadow="0 4px 20px rgba(139, 92, 246, 0.15)"
>
<Button <Button
size="sm" size="sm"
onClick={() => handlePageChange(Math.max(1, currentPage - 1))} onClick={() => handlePageChange(Math.max(1, currentPage - 1))}
isDisabled={currentPage === 1} isDisabled={currentPage === 1}
colorScheme="purple" bgGradient="linear(to-r, purple.500, pink.500)"
variant="outline" color="white"
variant="solid"
borderRadius="full"
_hover={{
bgGradient: 'linear(to-r, purple.600, pink.600)',
boxShadow: '0 0 15px rgba(139, 92, 246, 0.4)',
}}
_disabled={{
bg: 'gray.200',
color: 'gray.400',
cursor: 'not-allowed',
}}
> >
上一页 上一页
</Button> </Button>
<HStack> <HStack spacing={2}>
{[...Array(Math.min(5, totalPages))].map((_, i) => { {[...Array(Math.min(5, totalPages))].map((_, i) => {
const pageNum = currentPage <= 3 ? i + 1 : const pageNum = currentPage <= 3 ? i + 1 :
currentPage >= totalPages - 2 ? totalPages - 4 + i : currentPage >= totalPages - 2 ? totalPages - 4 + i :
@@ -1496,8 +1676,16 @@ const ConceptCenter = () => {
key={pageNum} key={pageNum}
size="sm" size="sm"
onClick={() => handlePageChange(pageNum)} onClick={() => handlePageChange(pageNum)}
colorScheme="purple" bg={pageNum === currentPage ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
variant={pageNum === currentPage ? 'solid' : 'outline'} color={pageNum === currentPage ? 'white' : 'purple.600'}
variant={pageNum === currentPage ? 'solid' : 'ghost'}
borderRadius="full"
minW="40px"
fontWeight="bold"
_hover={{
bg: pageNum === currentPage ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
boxShadow: pageNum === currentPage ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
}}
> >
{pageNum} {pageNum}
</Button> </Button>
@@ -1509,8 +1697,19 @@ const ConceptCenter = () => {
size="sm" size="sm"
onClick={() => handlePageChange(Math.min(totalPages, currentPage + 1))} onClick={() => handlePageChange(Math.min(totalPages, currentPage + 1))}
isDisabled={currentPage === totalPages} isDisabled={currentPage === totalPages}
colorScheme="purple" bgGradient="linear(to-r, purple.500, pink.500)"
variant="outline" color="white"
variant="solid"
borderRadius="full"
_hover={{
bgGradient: 'linear(to-r, purple.600, pink.600)',
boxShadow: '0 0 15px rgba(139, 92, 246, 0.4)',
}}
_disabled={{
bg: 'gray.200',
color: 'gray.400',
cursor: 'not-allowed',
}}
> >
下一页 下一页
</Button> </Button>