refactor(icons): 迁移 views/Concept 目录图标到 lucide-react

- @chakra-ui/icons → lucide-react
- react-icons → lucide-react
- 处理 Box/BoxIcon 命名冲突
- 涉及 6 个组件文件

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-25 12:24:38 +08:00
parent 29f6701de3
commit d4e671428d
6 changed files with 228 additions and 193 deletions

View File

@@ -33,21 +33,21 @@ import {
useBreakpointValue, useBreakpointValue,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { import {
ChevronDownIcon, ChevronDown,
ChevronRightIcon, ChevronRight,
ExternalLinkIcon, ExternalLink,
ViewIcon, Eye,
CalendarIcon, Calendar,
} from '@chakra-ui/icons'; } from 'lucide-react';
import { import {
FaChartLine, LineChart,
FaArrowUp, ArrowUp,
FaArrowDown, ArrowDown,
FaHistory, History,
FaNewspaper, Newspaper as NewspaperIcon,
FaFileAlt, FileText,
FaClock, Clock,
} from 'react-icons/fa'; } from 'lucide-react';
import { keyframes } from '@emotion/react'; import { keyframes } from '@emotion/react';
dayjs.locale('zh-cn'); dayjs.locale('zh-cn');
@@ -179,13 +179,13 @@ const ConceptTimelineModal = ({
if (value > 0) { if (value > 0) {
return { return {
color: 'red', color: 'red',
icon: FaArrowUp, icon: ArrowUp,
text: `+${value.toFixed(2)}%` text: `+${value.toFixed(2)}%`
}; };
} else if (value < 0) { } else if (value < 0) {
return { return {
color: 'green', color: 'green',
icon: FaArrowDown, icon: ArrowDown,
text: `${value.toFixed(2)}%` text: `${value.toFixed(2)}%`
}; };
} else { } else {
@@ -691,7 +691,7 @@ const ConceptTimelineModal = ({
> >
<HStack spacing={{ base: 2, md: 4 }} flexWrap="wrap"> <HStack spacing={{ base: 2, md: 4 }} flexWrap="wrap">
<Icon <Icon
as={FaChartLine} as={LineChart}
boxSize={{ base: 4, md: 6 }} boxSize={{ base: 4, md: 6 }}
color="cyan.400" color="cyan.400"
/> />
@@ -815,7 +815,7 @@ const ConceptTimelineModal = ({
borderColor="red.400" borderColor="red.400"
flexShrink={0} flexShrink={0}
> >
<Icon as={FaArrowUp} color="red.400" boxSize={{ base: 2, md: 3 }} /> <Icon as={ArrowUp} color="red.400" boxSize={{ base: 2, md: 3 }} />
<Text fontSize={{ base: 'xs', md: 'sm' }} fontWeight="medium" color="whiteAlpha.900" whiteSpace="nowrap">上涨</Text> <Text fontSize={{ base: 'xs', md: 'sm' }} fontWeight="medium" color="whiteAlpha.900" whiteSpace="nowrap">上涨</Text>
</HStack> </HStack>
<HStack <HStack
@@ -828,7 +828,7 @@ const ConceptTimelineModal = ({
borderColor="green.400" borderColor="green.400"
flexShrink={0} flexShrink={0}
> >
<Icon as={FaArrowDown} color="green.400" boxSize={{ base: 2, md: 3 }} /> <Icon as={ArrowDown} color="green.400" boxSize={{ base: 2, md: 3 }} />
<Text fontSize={{ base: 'xs', md: 'sm' }} fontWeight="medium" color="whiteAlpha.900" whiteSpace="nowrap">下跌</Text> <Text fontSize={{ base: 'xs', md: 'sm' }} fontWeight="medium" color="whiteAlpha.900" whiteSpace="nowrap">下跌</Text>
</HStack> </HStack>
<HStack <HStack
@@ -874,7 +874,7 @@ const ConceptTimelineModal = ({
borderColor="whiteAlpha.200" borderColor="whiteAlpha.200"
> >
<Icon <Icon
as={FaHistory} as={History}
boxSize={24} boxSize={24}
color="purple.400" color="purple.400"
opacity={0.6} opacity={0.6}
@@ -928,7 +928,7 @@ const ConceptTimelineModal = ({
<VStack align="start" spacing={3} position="relative" zIndex={1}> <VStack align="start" spacing={3} position="relative" zIndex={1}>
<HStack spacing={3}> <HStack spacing={3}>
<Icon <Icon
as={CalendarIcon} as={Calendar}
boxSize={6} boxSize={6}
color="cyan.400" color="cyan.400"
/> />
@@ -991,7 +991,7 @@ const ConceptTimelineModal = ({
borderColor="blue.500" borderColor="blue.500"
> >
<HStack spacing={2}> <HStack spacing={2}>
<Icon as={FaNewspaper} color="blue.400" boxSize={5} /> <Icon as={Newspaper} color="blue.400" boxSize={5} />
<Text fontWeight="bold" fontSize="lg" color="blue.300"> <Text fontWeight="bold" fontSize="lg" color="blue.300">
{selectedDateData.events.filter(e => e.type === 'news').length} {selectedDateData.events.filter(e => e.type === 'news').length}
</Text> </Text>
@@ -1007,7 +1007,7 @@ const ConceptTimelineModal = ({
borderColor="green.500" borderColor="green.500"
> >
<HStack spacing={2}> <HStack spacing={2}>
<Icon as={FaFileAlt} color="green.400" boxSize={5} /> <Icon as={FileText} color="green.400" boxSize={5} />
<Text fontWeight="bold" fontSize="lg" color="green.300"> <Text fontWeight="bold" fontSize="lg" color="green.300">
{selectedDateData.events.filter(e => e.type === 'report').length} {selectedDateData.events.filter(e => e.type === 'report').length}
</Text> </Text>
@@ -1109,7 +1109,7 @@ const ConceptTimelineModal = ({
<HStack spacing={4} w="100%" justify="space-between" align="center" mt={1}> <HStack spacing={4} w="100%" justify="space-between" align="center" mt={1}>
{event.time && ( {event.time && (
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={FaClock} color="whiteAlpha.500" boxSize={3} /> <Icon as={Clock} color="whiteAlpha.500" boxSize={3} />
<Text fontSize="xs" color="whiteAlpha.500" fontWeight="medium"> <Text fontSize="xs" color="whiteAlpha.500" fontWeight="medium">
{formatDateTime(event.time)} {formatDateTime(event.time)}
</Text> </Text>
@@ -1120,7 +1120,7 @@ const ConceptTimelineModal = ({
size="sm" size="sm"
colorScheme={event.type === 'news' ? 'blue' : 'green'} colorScheme={event.type === 'news' ? 'blue' : 'green'}
variant="solid" variant="solid"
leftIcon={<ViewIcon />} leftIcon={<Eye size={16} />}
boxShadow="sm" boxShadow="sm"
_hover={{ _hover={{
transform: 'scale(1.05)', transform: 'scale(1.05)',
@@ -1175,7 +1175,7 @@ const ConceptTimelineModal = ({
borderColor="whiteAlpha.200" borderColor="whiteAlpha.200"
> >
<Icon <Icon
as={FaHistory} as={History}
boxSize={20} boxSize={20}
color="purple.400" color="purple.400"
opacity={0.6} opacity={0.6}
@@ -1286,7 +1286,7 @@ const ConceptTimelineModal = ({
size="sm" size="sm"
bg="whiteAlpha.100" bg="whiteAlpha.100"
color="white" color="white"
leftIcon={<ExternalLinkIcon />} leftIcon={<ExternalLink size={16} />}
onClick={() => { onClick={() => {
const url = formatUrl(selectedReport.content_url); const url = formatUrl(selectedReport.content_url);
if (url) { if (url) {
@@ -1379,7 +1379,7 @@ const ConceptTimelineModal = ({
size="sm" size="sm"
bg="whiteAlpha.100" bg="whiteAlpha.100"
color="white" color="white"
leftIcon={<ExternalLinkIcon />} leftIcon={<ExternalLink size={16} />}
onClick={() => window.open(selectedNews.url, '_blank')} onClick={() => window.open(selectedNews.url, '_blank')}
_hover={{ bg: 'whiteAlpha.200' }} _hover={{ bg: 'whiteAlpha.200' }}
> >

View File

@@ -16,8 +16,7 @@ import {
Flex, Flex,
Tooltip, Tooltip,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { ChevronRightIcon } from '@chakra-ui/icons'; import { ChevronRight, Filter, X, Home } from 'lucide-react';
import { FaFilter, FaTimes, FaHome } from 'react-icons/fa';
const BreadcrumbNav = ({ const BreadcrumbNav = ({
filter, filter,
@@ -139,7 +138,7 @@ const BreadcrumbNav = ({
py={1} py={1}
borderRadius="full" borderRadius="full"
> >
<Icon as={FaFilter} boxSize={3} /> <Icon as={Filter} boxSize={3} />
<Text fontSize="sm" fontWeight="bold"> <Text fontSize="sm" fontWeight="bold">
层级筛选 层级筛选
</Text> </Text>
@@ -161,7 +160,7 @@ const BreadcrumbNav = ({
alignItems="center" alignItems="center"
gap={1} gap={1}
> >
<Icon as={FaHome} boxSize={3} /> <Icon as={Home} boxSize={3} />
全部 全部
</Badge> </Badge>
</Tooltip> </Tooltip>
@@ -169,7 +168,7 @@ const BreadcrumbNav = ({
{/* 面包屑路径 */} {/* 面包屑路径 */}
{breadcrumbs.map((crumb, index) => ( {breadcrumbs.map((crumb, index) => (
<React.Fragment key={crumb.level}> <React.Fragment key={crumb.level}>
<Icon as={ChevronRightIcon} color={styles.chevron.color} boxSize={4} /> <Icon as={ChevronRight} color={styles.chevron.color} boxSize={4} />
<Badge <Badge
{...(isDarkMode ? {} : { colorScheme: styles.crumbBadge(crumb.level, index === breadcrumbs.length - 1).colorScheme })} {...(isDarkMode ? {} : { colorScheme: styles.crumbBadge(crumb.level, index === breadcrumbs.length - 1).colorScheme })}
bg={isDarkMode ? styles.crumbBadge(crumb.level, index === breadcrumbs.length - 1).bg : undefined} bg={isDarkMode ? styles.crumbBadge(crumb.level, index === breadcrumbs.length - 1).bg : undefined}
@@ -196,7 +195,7 @@ const BreadcrumbNav = ({
<Tooltip label="清除筛选" placement="top"> <Tooltip label="清除筛选" placement="top">
<IconButton <IconButton
size="sm" size="sm"
icon={<FaTimes />} icon={<X />}
{...(isDarkMode ? {} : { colorScheme: 'red' })} {...(isDarkMode ? {} : { colorScheme: 'red' })}
color={isDarkMode ? styles.clearBtn.color : undefined} color={isDarkMode ? styles.clearBtn.color : undefined}
variant="ghost" variant="ghost"

View File

@@ -37,14 +37,16 @@ import {
useToast, useToast,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { import {
FaArrowUp, ArrowUp,
FaArrowDown, ArrowDown,
FaChartLine, LineChart,
FaNewspaper, Newspaper,
FaRocket, Rocket,
FaCrown, Crown,
} from 'react-icons/fa'; Zap,
import { BsLightningFill, BsGraphUp, BsGraphDown } from 'react-icons/bs'; TrendingUp,
TrendingDown,
} from 'lucide-react';
const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => { const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
// 获取正确的API基础URL // 获取正确的API基础URL
@@ -274,7 +276,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
const tabsData = [ const tabsData = [
{ {
label: '涨幅榜', label: '涨幅榜',
icon: FaArrowUp, icon: ArrowUp,
color: 'red', color: 'red',
data: statsData.hot_concepts, data: statsData.hot_concepts,
renderItem: (item, index) => ( renderItem: (item, index) => (
@@ -314,7 +316,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
</Badge> </Badge>
{index === 0 && ( {index === 0 && (
<Icon <Icon
as={FaCrown} as={Crown}
position="absolute" position="absolute"
top="-8px" top="-8px"
right="-8px" right="-8px"
@@ -329,12 +331,12 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
</Text> </Text>
<HStack spacing={2} fontSize="xs" color="whiteAlpha.600"> <HStack spacing={2} fontSize="xs" color="whiteAlpha.600">
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={FaChartLine} boxSize={2.5} /> <Icon as={LineChart} boxSize={2.5} />
<Text>{item.stock_count}</Text> <Text>{item.stock_count}</Text>
</HStack> </HStack>
<Text>·</Text> <Text>·</Text>
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={FaNewspaper} boxSize={2.5} /> <Icon as={Newspaper} boxSize={2.5} />
<Text>{item.news_count}</Text> <Text>{item.news_count}</Text>
</HStack> </HStack>
</HStack> </HStack>
@@ -349,7 +351,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
px={2} px={2}
py={1} py={1}
> >
<Icon as={FaArrowUp} boxSize={2} mr={1} /> <Icon as={ArrowUp} boxSize={2} mr={1} />
{formatChange(item.change_pct)} {formatChange(item.change_pct)}
</Badge> </Badge>
</Flex> </Flex>
@@ -357,7 +359,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
}, },
{ {
label: '跌幅榜', label: '跌幅榜',
icon: FaArrowDown, icon: ArrowDown,
color: 'green', color: 'green',
data: statsData.cold_concepts, data: statsData.cold_concepts,
renderItem: (item, index) => ( renderItem: (item, index) => (
@@ -400,12 +402,12 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
</Text> </Text>
<HStack spacing={2} fontSize="xs" color="whiteAlpha.600"> <HStack spacing={2} fontSize="xs" color="whiteAlpha.600">
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={FaChartLine} boxSize={2.5} /> <Icon as={LineChart} boxSize={2.5} />
<Text>{item.stock_count}</Text> <Text>{item.stock_count}</Text>
</HStack> </HStack>
<Text>·</Text> <Text>·</Text>
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={FaNewspaper} boxSize={2.5} /> <Icon as={Newspaper} boxSize={2.5} />
<Text>{item.news_count}</Text> <Text>{item.news_count}</Text>
</HStack> </HStack>
</HStack> </HStack>
@@ -420,7 +422,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
px={2} px={2}
py={1} py={1}
> >
<Icon as={FaArrowDown} boxSize={2} mr={1} /> <Icon as={ArrowDown} boxSize={2} mr={1} />
{formatChange(item.change_pct)} {formatChange(item.change_pct)}
</Badge> </Badge>
</Flex> </Flex>
@@ -428,7 +430,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
}, },
{ {
label: '波动榜', label: '波动榜',
icon: BsLightningFill, icon: Zap,
color: 'purple', color: 'purple',
data: statsData.volatile_concepts, data: statsData.volatile_concepts,
renderItem: (item, index) => ( renderItem: (item, index) => (
@@ -468,7 +470,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
</Badge> </Badge>
{index === 0 && ( {index === 0 && (
<Icon <Icon
as={BsLightningFill} as={Zap}
position="absolute" position="absolute"
top="-8px" top="-8px"
right="-8px" right="-8px"
@@ -495,7 +497,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
px={2} px={2}
py={1} py={1}
> >
<Icon as={BsLightningFill} boxSize={2} mr={1} /> <Icon as={Zap} boxSize={2} mr={1} />
{item.volatility?.toFixed(1)}% {item.volatility?.toFixed(1)}%
</Badge> </Badge>
</Flex> </Flex>
@@ -503,7 +505,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
}, },
{ {
label: '连涨榜', label: '连涨榜',
icon: FaRocket, icon: Rocket,
color: 'cyan', color: 'cyan',
data: statsData.momentum_concepts, data: statsData.momentum_concepts,
renderItem: (item, index) => ( renderItem: (item, index) => (
@@ -543,7 +545,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
</Badge> </Badge>
{index === 0 && ( {index === 0 && (
<Icon <Icon
as={FaRocket} as={Rocket}
position="absolute" position="absolute"
top="-8px" top="-8px"
right="-8px" right="-8px"
@@ -570,7 +572,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
px={2} px={2}
py={1} py={1}
> >
<Icon as={FaRocket} boxSize={2} mr={1} /> <Icon as={Rocket} boxSize={2} mr={1} />
{item.consecutive_days} {item.consecutive_days}
</Badge> </Badge>
</Flex> </Flex>
@@ -620,7 +622,7 @@ const ConceptStatsPanel = ({ apiBaseUrl, onConceptClick }) => {
<Flex justify="space-between" align="center" w="full"> <Flex justify="space-between" align="center" w="full">
<HStack spacing={2}> <HStack spacing={2}>
<Box p={2} bg="whiteAlpha.100" borderRadius="lg" border="1px solid" borderColor="cyan.500"> <Box p={2} bg="whiteAlpha.100" borderRadius="lg" border="1px solid" borderColor="cyan.500">
<Icon as={FaChartLine} color="cyan.400" boxSize={4} /> <Icon as={LineChart} color="cyan.400" boxSize={4} />
</Box> </Box>
<VStack align="start" spacing={0}> <VStack align="start" spacing={0}>
<Heading size="sm" color="white" fontWeight="bold"> <Heading size="sm" color="white" fontWeight="bold">

View File

@@ -31,18 +31,18 @@ import {
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { keyframes } from '@emotion/react'; import { keyframes } from '@emotion/react';
import { import {
FaLayerGroup, Layers,
FaSync, RefreshCw,
FaExpand, Maximize2,
FaCompress, Minimize2,
FaHome, Home,
FaArrowUp, ArrowUp,
FaArrowDown, ArrowDown,
FaCircle, Circle,
FaTh, Grid3x3,
FaChevronRight, ChevronRight,
FaArrowLeft, ArrowLeft,
} from 'react-icons/fa'; } from 'lucide-react';
import { logger } from '../../../utils/logger'; import { logger } from '../../../utils/logger';
// 极光动画 - 黑金色主题 // 极光动画 - 黑金色主题
@@ -1052,7 +1052,7 @@ const ForceGraphView = ({
borderColor="whiteAlpha.100" borderColor="whiteAlpha.100"
> >
<VStack spacing={4}> <VStack spacing={4}>
<Icon as={FaLayerGroup} boxSize={16} color="gray.600" /> <Icon as={Layers} boxSize={16} color="gray.600" />
<Text color="gray.400">加载失败{error}</Text> <Text color="gray.400">加载失败{error}</Text>
<Button <Button
colorScheme="purple" colorScheme="purple"
@@ -1078,7 +1078,7 @@ const ForceGraphView = ({
<Tooltip label="返回上一层" placement="bottom"> <Tooltip label="返回上一层" placement="bottom">
<IconButton <IconButton
size="sm" size="sm"
icon={<FaArrowLeft />} icon={<ArrowLeft />}
onClick={handleGoBack} onClick={handleGoBack}
bg="whiteAlpha.100" bg="whiteAlpha.100"
color="white" color="white"
@@ -1104,7 +1104,7 @@ const ForceGraphView = ({
border="1px solid" border="1px solid"
borderColor="whiteAlpha.200" borderColor="whiteAlpha.200"
> >
<Icon as={FaTh} color="purple.300" /> <Icon as={Grid3x3} color="purple.300" />
<Text color="white" fontWeight="bold" fontSize="sm"> <Text color="white" fontWeight="bold" fontSize="sm">
概念矩形树图 概念矩形树图
</Text> </Text>
@@ -1123,7 +1123,7 @@ const ForceGraphView = ({
{breadcrumbItems.map((item, index) => ( {breadcrumbItems.map((item, index) => (
<HStack key={index} spacing={2}> <HStack key={index} spacing={2}>
{index > 0 && ( {index > 0 && (
<Icon as={FaChevronRight} color="whiteAlpha.400" boxSize={3} /> <Icon as={ChevronRight} color="whiteAlpha.400" boxSize={3} />
)} )}
<Text <Text
color={index === breadcrumbItems.length - 1 ? 'purple.300' : 'whiteAlpha.700'} color={index === breadcrumbItems.length - 1 ? 'purple.300' : 'whiteAlpha.700'}
@@ -1153,7 +1153,7 @@ const ForceGraphView = ({
<Tooltip label="返回全部" placement="left"> <Tooltip label="返回全部" placement="left">
<IconButton <IconButton
size="sm" size="sm"
icon={<FaHome />} icon={<Home />}
onClick={handleGoHome} onClick={handleGoHome}
bg="whiteAlpha.100" bg="whiteAlpha.100"
color="white" color="white"
@@ -1174,7 +1174,7 @@ const ForceGraphView = ({
<Tooltip label="刷新数据" placement="left"> <Tooltip label="刷新数据" placement="left">
<IconButton <IconButton
size="sm" size="sm"
icon={<FaSync />} icon={<RefreshCw />}
onClick={handleRefresh} onClick={handleRefresh}
isLoading={priceLoading} isLoading={priceLoading}
bg="whiteAlpha.100" bg="whiteAlpha.100"
@@ -1195,7 +1195,7 @@ const ForceGraphView = ({
<Tooltip label={isFullscreen ? '退出全屏' : '全屏'} placement="left"> <Tooltip label={isFullscreen ? '退出全屏' : '全屏'} placement="left">
<IconButton <IconButton
size="sm" size="sm"
icon={isFullscreen ? <FaCompress /> : <FaExpand />} icon={isFullscreen ? <Minimize2 /> : <Maximize2 />}
onClick={toggleFullscreen} onClick={toggleFullscreen}
bg="whiteAlpha.100" bg="whiteAlpha.100"
color="white" color="white"

View File

@@ -27,87 +27,87 @@ import {
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { keyframes } from '@emotion/react'; import { keyframes } from '@emotion/react';
import { import {
FaLayerGroup, Layers,
FaExpand, Maximize2,
FaCompress, Minimize2,
FaSync, RefreshCw,
FaHome, Home,
FaChevronRight, ChevronRight,
FaBrain, Brain,
FaMicrochip, Cpu,
FaRobot, Bot,
FaMobileAlt, Smartphone,
FaCar, Car,
FaBolt, Zap,
FaRocket, Rocket,
FaShieldAlt, Shield,
FaGlobe, Globe,
FaIndustry, Factory,
FaShoppingCart, ShoppingCart,
FaCoins, Coins,
FaHeartbeat, Heart,
FaAtom, Atom,
FaArrowUp, ArrowUp,
FaArrowDown, ArrowDown,
FaCubes, Box as BoxIcon,
FaServer, Server,
FaCode, Code,
FaMagic, Sparkles,
FaEye, Eye,
FaPlane, Plane,
FaSatellite, Satellite,
FaBatteryFull, BatteryFull,
FaSolarPanel, Sun,
FaTags, Tags,
FaExternalLinkAlt, ExternalLink,
} from 'react-icons/fa'; } from 'lucide-react';
import { logger } from '../../../utils/logger'; import { logger } from '../../../utils/logger';
// 一级分类图标映射 // 一级分类图标映射
const LV1_ICONS = { const LV1_ICONS = {
'人工智能': FaBrain, '人工智能': Brain,
'半导体': FaMicrochip, '半导体': Cpu,
'机器人': FaRobot, '机器人': Bot,
'消费电子': FaMobileAlt, '消费电子': Smartphone,
'智能驾驶与汽车': FaCar, '智能驾驶与汽车': Car,
'新能源与电力': FaBolt, '新能源与电力': Zap,
'空天经济': FaRocket, '空天经济': Rocket,
'国防军工': FaShieldAlt, '国防军工': Shield,
'政策与主题': FaGlobe, '政策与主题': Globe,
'周期与材料': FaIndustry, '周期与材料': Factory,
'大消费': FaShoppingCart, '大消费': ShoppingCart,
'数字经济与金融科技': FaCoins, '数字经济与金融科技': Coins,
'全球宏观与贸易': FaGlobe, '全球宏观与贸易': Globe,
'医药健康': FaHeartbeat, '医药健康': Heart,
'前沿科技': FaAtom, '前沿科技': Atom,
}; };
// 二级分类图标映射 // 二级分类图标映射
const LV2_ICONS = { const LV2_ICONS = {
'AI基础设施': FaServer, 'AI基础设施': Server,
'AI模型与软件': FaCode, 'AI模型与软件': Code,
'AI应用': FaMagic, 'AI应用': Sparkles,
'半导体设备': FaCubes, '半导体设备': BoxIcon,
'半导体材料': FaAtom, '半导体材料': Atom,
'芯片设计与制造': FaMicrochip, '芯片设计与制造': Cpu,
'先进封装': FaCubes, '先进封装': BoxIcon,
'人形机器人整机': FaRobot, '人形机器人整机': Bot,
'机器人核心零部件': FaCubes, '机器人核心零部件': BoxIcon,
'其他类型机器人': FaRobot, '其他类型机器人': Bot,
'智能终端': FaMobileAlt, '智能终端': Smartphone,
'XR与空间计算': FaEye, 'XR与空间计算': Eye,
'华为产业链': FaMobileAlt, '华为产业链': Smartphone,
'自动驾驶解决方案': FaCar, '自动驾驶解决方案': Car,
'智能汽车产业链': FaCar, '智能汽车产业链': Car,
'车路协同': FaCar, '车路协同': Car,
'新型电池技术': FaBatteryFull, '新型电池技术': BatteryFull,
'电力设备与电网': FaBolt, '电力设备与电网': Zap,
'清洁能源': FaSolarPanel, '清洁能源': Sun,
'低空经济': FaPlane, '低空经济': Plane,
'商业航天': FaSatellite, '商业航天': Satellite,
'无人作战与信息化': FaShieldAlt, '无人作战与信息化': Shield,
'海军装备': FaShieldAlt, '海军装备': Shield,
'军贸出海': FaGlobe, '军贸出海': Globe,
}; };
// 根据涨跌幅获取背景渐变色(涨红跌绿) // 根据涨跌幅获取背景渐变色(涨红跌绿)
@@ -151,10 +151,10 @@ const formatChangePercent = (value) => {
// 获取图标 // 获取图标
const getIcon = (name, level) => { const getIcon = (name, level) => {
if (level === 'lv1') return LV1_ICONS[name] || FaLayerGroup; if (level === 'lv1') return LV1_ICONS[name] || Layers;
if (level === 'lv2') return LV2_ICONS[name] || FaCubes; if (level === 'lv2') return LV2_ICONS[name] || Box;
if (level === 'lv3') return FaCubes; if (level === 'lv3') return Box;
return FaTags; return Tags;
}; };
// 从 API 返回的名称中提取纯名称 // 从 API 返回的名称中提取纯名称
@@ -352,7 +352,7 @@ const GlassCard = ({ item, onClick, size = 'normal' }) => {
{/* 外链图标 */} {/* 外链图标 */}
{isLeafConcept && ( {isLeafConcept && (
<Icon <Icon
as={FaExternalLinkAlt} as={ExternalLink}
boxSize={3} boxSize={3}
color="whiteAlpha.500" color="whiteAlpha.500"
/> />
@@ -372,7 +372,7 @@ const GlassCard = ({ item, onClick, size = 'normal' }) => {
<HStack spacing={1} align="center"> <HStack spacing={1} align="center">
{hasChange && (isPositive || isNegative) && ( {hasChange && (isPositive || isNegative) && (
<Icon <Icon
as={isPositive ? FaArrowUp : FaArrowDown} as={isPositive ? ArrowUp : ArrowDown}
boxSize={3} boxSize={3}
color={getChangeTextColor(item.avg_change_pct)} color={getChangeTextColor(item.avg_change_pct)}
/> />
@@ -766,7 +766,7 @@ const HierarchyView = ({
<Center h="400px" position="relative"> <Center h="400px" position="relative">
<AuroraBackground /> <AuroraBackground />
<VStack spacing={4} position="relative" zIndex={1}> <VStack spacing={4} position="relative" zIndex={1}>
<Icon as={FaLayerGroup} boxSize={16} color="gray.600" /> <Icon as={Layers} boxSize={16} color="gray.600" />
<Text color="gray.400">加载失败{error}</Text> <Text color="gray.400">加载失败{error}</Text>
<Button <Button
colorScheme="purple" colorScheme="purple"
@@ -787,7 +787,7 @@ const HierarchyView = ({
<Center h="400px" position="relative"> <Center h="400px" position="relative">
<AuroraBackground /> <AuroraBackground />
<VStack spacing={4} position="relative" zIndex={1}> <VStack spacing={4} position="relative" zIndex={1}>
<Icon as={FaLayerGroup} boxSize={16} color="gray.600" /> <Icon as={Layers} boxSize={16} color="gray.600" />
<Text color="gray.400">暂无层级数据</Text> <Text color="gray.400">暂无层级数据</Text>
</VStack> </VStack>
</Center> </Center>
@@ -832,14 +832,14 @@ const HierarchyView = ({
{breadcrumbs.map((crumb, index) => ( {breadcrumbs.map((crumb, index) => (
<React.Fragment key={index}> <React.Fragment key={index}>
{index > 0 && ( {index > 0 && (
<Icon as={FaChevronRight} color="whiteAlpha.400" boxSize={3} mx={1} /> <Icon as={ChevronRight} color="whiteAlpha.400" boxSize={3} mx={1} />
)} )}
<Button <Button
size="sm" size="sm"
variant="ghost" variant="ghost"
bg={index === breadcrumbs.length - 1 ? 'purple.500' : 'transparent'} bg={index === breadcrumbs.length - 1 ? 'purple.500' : 'transparent'}
color={index === breadcrumbs.length - 1 ? 'white' : 'whiteAlpha.700'} color={index === breadcrumbs.length - 1 ? 'white' : 'whiteAlpha.700'}
leftIcon={index === 0 ? <FaHome /> : undefined} leftIcon={index === 0 ? <Home /> : undefined}
onClick={() => handleBreadcrumbClick(crumb, index)} onClick={() => handleBreadcrumbClick(crumb, index)}
isDisabled={index === breadcrumbs.length - 1} isDisabled={index === breadcrumbs.length - 1}
fontWeight={index === breadcrumbs.length - 1 ? 'bold' : 'medium'} fontWeight={index === breadcrumbs.length - 1 ? 'bold' : 'medium'}
@@ -861,7 +861,7 @@ const HierarchyView = ({
<Tooltip label="刷新涨跌幅" placement="top"> <Tooltip label="刷新涨跌幅" placement="top">
<IconButton <IconButton
size="sm" size="sm"
icon={<FaSync />} icon={<RefreshCw />}
onClick={handleRefreshPrice} onClick={handleRefreshPrice}
isLoading={priceLoading} isLoading={priceLoading}
bg="whiteAlpha.100" bg="whiteAlpha.100"
@@ -876,7 +876,7 @@ const HierarchyView = ({
<Tooltip label={isFullscreen ? '退出全屏' : '全屏'} placement="top"> <Tooltip label={isFullscreen ? '退出全屏' : '全屏'} placement="top">
<IconButton <IconButton
size="sm" size="sm"
icon={isFullscreen ? <FaCompress /> : <FaExpand />} icon={isFullscreen ? <Minimize2 /> : <Maximize2 />}
onClick={toggleFullscreen} onClick={toggleFullscreen}
bg="whiteAlpha.100" bg="whiteAlpha.100"
color="white" color="white"

View File

@@ -79,9 +79,43 @@ import {
Collapse, Collapse,
useBreakpointValue, useBreakpointValue,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { SearchIcon, ViewIcon, CalendarIcon, ExternalLinkIcon, StarIcon, ChevronDownIcon, InfoIcon, CloseIcon, ChevronRightIcon } from '@chakra-ui/icons'; import {
import { FaThLarge, FaList, FaTags, FaChartLine, FaRobot, FaTable, FaHistory, FaBrain, FaLightbulb, FaRocket, FaShieldAlt, FaCalendarAlt, FaArrowUp, FaArrowDown, FaNewspaper, FaFileAlt, FaExpand, FaCompress, FaClock, FaLock, FaSitemap, FaLayerGroup, FaCube, FaProjectDiagram } from 'react-icons/fa'; Search,
import { BsGraphUp, BsLightningFill } from 'react-icons/bs'; Eye,
Calendar,
ExternalLink,
Star,
ChevronDown,
Info,
X,
ChevronRight,
LayoutGrid,
List,
Tags,
LineChart,
Bot,
Table2,
History,
Brain,
Lightbulb,
Rocket,
Shield,
CalendarDays,
ArrowUp,
ArrowDown,
Newspaper,
FileText,
Maximize2,
Minimize2,
Clock,
Lock,
GitBranch,
Layers,
Box as BoxIcon,
Network,
TrendingUp,
Zap,
} from 'lucide-react';
import { keyframes } from '@emotion/react'; import { keyframes } from '@emotion/react';
import ConceptTimelineModal from './ConceptTimelineModal'; import ConceptTimelineModal from './ConceptTimelineModal';
import ConceptStatsPanel from './components/ConceptStatsPanel'; import ConceptStatsPanel from './components/ConceptStatsPanel';
@@ -769,7 +803,7 @@ const ConceptCenter = () => {
return ( return (
<HStack spacing={2}> <HStack spacing={2}>
<Icon as={CalendarIcon} boxSize={3} color="blue.500" /> <Icon as={Calendar} boxSize={3} color="blue.500" />
<Text fontSize="xs" color="gray.600" fontWeight="medium"> <Text fontSize="xs" color="gray.600" fontWeight="medium">
添加于 {new Date(addedDate).toLocaleDateString('zh-CN')} 添加于 {new Date(addedDate).toLocaleDateString('zh-CN')}
</Text> </Text>
@@ -1021,7 +1055,7 @@ const ConceptCenter = () => {
<Flex align="center" justify="space-between"> <Flex align="center" justify="space-between">
<Box flex={1}> <Box flex={1}>
<HStack spacing={2} mb={{ base: 1, md: 2 }}> <HStack spacing={2} mb={{ base: 1, md: 2 }}>
<Icon as={FaChartLine} boxSize={3} color="purple.300" /> <Icon as={LineChart} boxSize={3} color="purple.300" />
<Text fontSize="xs" color="purple.200" fontWeight="bold"> <Text fontSize="xs" color="purple.200" fontWeight="bold">
热门个股 热门个股
</Text> </Text>
@@ -1068,7 +1102,7 @@ const ConceptCenter = () => {
</> </>
) : ( ) : (
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={FaLock} boxSize="10px" color="yellow.400" /> <Icon as={Lock} boxSize="10px" color="yellow.400" />
<Text fontSize="xs" color="yellow.400" fontWeight="medium"> <Text fontSize="xs" color="yellow.400" fontWeight="medium">
升级查看{concept.stocks.length}只个股 升级查看{concept.stocks.length}只个股
</Text> </Text>
@@ -1077,7 +1111,7 @@ const ConceptCenter = () => {
</HStack> </HStack>
</Box> </Box>
<Icon <Icon
as={hasFeatureAccess('hot_stocks') ? ChevronRightIcon : FaLock} as={hasFeatureAccess('hot_stocks') ? ChevronRight : FaLock}
color={hasFeatureAccess('hot_stocks') ? 'purple.300' : 'yellow.400'} color={hasFeatureAccess('hot_stocks') ? 'purple.300' : 'yellow.400'}
boxSize={4} boxSize={4}
/> />
@@ -1097,7 +1131,7 @@ const ConceptCenter = () => {
if (latestOutbreak) { if (latestOutbreak) {
return ( return (
<HStack spacing={2}> <HStack spacing={2}>
<Icon as={BsLightningFill} boxSize={3} color="orange.400" /> <Icon as={Zap} boxSize={3} color="orange.400" />
<Text fontSize="xs" color="orange.300" fontWeight="medium"> <Text fontSize="xs" color="orange.300" fontWeight="medium">
爆发于 {new Date(latestOutbreak).toLocaleDateString('zh-CN')} 爆发于 {new Date(latestOutbreak).toLocaleDateString('zh-CN')}
</Text> </Text>
@@ -1106,7 +1140,7 @@ const ConceptCenter = () => {
} else if (addedDate) { } else if (addedDate) {
return ( return (
<HStack spacing={2}> <HStack spacing={2}>
<Icon as={CalendarIcon} boxSize={3} color="cyan.400" /> <Icon as={Calendar} boxSize={3} color="cyan.400" />
<Text fontSize="xs" color="whiteAlpha.600" fontWeight="medium"> <Text fontSize="xs" color="whiteAlpha.600" fontWeight="medium">
添加于 {new Date(addedDate).toLocaleDateString('zh-CN')} 添加于 {new Date(addedDate).toLocaleDateString('zh-CN')}
</Text> </Text>
@@ -1202,7 +1236,7 @@ const ConceptCenter = () => {
border="1px solid" border="1px solid"
borderColor="whiteAlpha.100" borderColor="whiteAlpha.100"
> >
<Icon as={FaTags} boxSize={{ base: 6, md: 8 }} color="white" opacity={0.8} /> <Icon as={Tags} boxSize={{ base: 6, md: 8 }} color="white" opacity={0.8} />
{hasChange && ( {hasChange && (
<Badge <Badge
position="absolute" position="absolute"
@@ -1247,7 +1281,7 @@ const ConceptCenter = () => {
_hover={{ color: 'purple.300' }} _hover={{ color: 'purple.300' }}
transition="color 0.2s" transition="color 0.2s"
> >
<Icon as={FaChartLine} boxSize={4} color="purple.300" /> <Icon as={LineChart} boxSize={4} color="purple.300" />
<Text fontSize="sm" fontWeight="medium" color="whiteAlpha.800" _groupHover={{ color: 'purple.300' }}> <Text fontSize="sm" fontWeight="medium" color="whiteAlpha.800" _groupHover={{ color: 'purple.300' }}>
{concept.stock_count || 0} 只股票 {concept.stock_count || 0} 只股票
</Text> </Text>
@@ -1255,7 +1289,7 @@ const ConceptCenter = () => {
{hasChange && concept.price_info?.trade_date && ( {hasChange && concept.price_info?.trade_date && (
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={FaCalendarAlt} boxSize={4} color="cyan.400" /> <Icon as={CalendarDays} boxSize={4} color="cyan.400" />
<Text fontSize="sm" color="whiteAlpha.600"> <Text fontSize="sm" color="whiteAlpha.600">
{new Date(concept.price_info.trade_date).toLocaleDateString('zh-CN')} {new Date(concept.price_info.trade_date).toLocaleDateString('zh-CN')}
</Text> </Text>
@@ -1270,7 +1304,7 @@ const ConceptCenter = () => {
if (latestOutbreak) { if (latestOutbreak) {
return ( return (
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={BsLightningFill} boxSize={4} color="orange.400" /> <Icon as={Zap} boxSize={4} color="orange.400" />
<Text fontSize="sm" color="orange.300" fontWeight="medium"> <Text fontSize="sm" color="orange.300" fontWeight="medium">
爆发于 {new Date(latestOutbreak).toLocaleDateString('zh-CN')} 爆发于 {new Date(latestOutbreak).toLocaleDateString('zh-CN')}
</Text> </Text>
@@ -1279,7 +1313,7 @@ const ConceptCenter = () => {
} else if (addedDate) { } else if (addedDate) {
return ( return (
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={CalendarIcon} boxSize={4} color="cyan.400" /> <Icon as={Calendar} boxSize={4} color="cyan.400" />
<Text fontSize="sm" color="whiteAlpha.600"> <Text fontSize="sm" color="whiteAlpha.600">
添加于 {new Date(addedDate).toLocaleDateString('zh-CN')} 添加于 {new Date(addedDate).toLocaleDateString('zh-CN')}
</Text> </Text>
@@ -1297,7 +1331,7 @@ const ConceptCenter = () => {
<HStack spacing={3}> <HStack spacing={3}>
<Button <Button
size="sm" size="sm"
leftIcon={<ViewIcon />} leftIcon={<Eye size={16} />}
bg="whiteAlpha.100" bg="whiteAlpha.100"
color="white" color="white"
border="1px solid" border="1px solid"
@@ -1373,7 +1407,7 @@ const ConceptCenter = () => {
) : ( ) : (
<WrapItem> <WrapItem>
<HStack spacing={1}> <HStack spacing={1}>
<Icon as={FaLock} boxSize="8px" color="yellow.400" /> <Icon as={Lock} boxSize="8px" color="yellow.400" />
<Text fontSize="xs" color="yellow.400" fontWeight="medium"> <Text fontSize="xs" color="yellow.400" fontWeight="medium">
升级查看{concept.stocks.length} 升级查看{concept.stocks.length}
</Text> </Text>
@@ -1518,7 +1552,7 @@ const ConceptCenter = () => {
_hover={{ opacity: 1 }} _hover={{ opacity: 1 }}
transition="opacity 0.2s" transition="opacity 0.2s"
> >
<Icon as={InfoIcon} color="blue.300" boxSize={3} /> <Icon as={Info} color="blue.300" boxSize={3} />
<Text fontSize="xs" color="blue.200"> <Text fontSize="xs" color="blue.200">
数据更新至 {latestTradeDate.toLocaleDateString('zh-CN')} 数据更新至 {latestTradeDate.toLocaleDateString('zh-CN')}
</Text> </Text>
@@ -1585,7 +1619,7 @@ const ConceptCenter = () => {
{/* 标题区域 */} {/* 标题区域 */}
<VStack spacing={3} textAlign="center"> <VStack spacing={3} textAlign="center">
<HStack spacing={3} justify="center"> <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))" /> <Icon as={Brain} boxSize={10} color="cyan.300" filter="drop-shadow(0 0 10px rgba(6, 182, 212, 0.5))" />
</HStack> </HStack>
<VStack spacing={1}> <VStack spacing={1}>
@@ -1601,7 +1635,7 @@ const ConceptCenter = () => {
概念中心 概念中心
</Heading> </Heading>
<HStack spacing={2} justify="center"> <HStack spacing={2} justify="center">
<Icon as={FaClock} boxSize={3} color="cyan.200" /> <Icon as={Clock} boxSize={3} color="cyan.200" />
<Text fontSize="xs" fontWeight="medium" opacity={0.8}> <Text fontSize="xs" fontWeight="medium" opacity={0.8}>
数据约下午4点更新 数据约下午4点更新
</Text> </Text>
@@ -1627,21 +1661,21 @@ const ConceptCenter = () => {
boxShadow="0 8px 32px rgba(0, 0, 0, 0.3)" boxShadow="0 8px 32px rgba(0, 0, 0, 0.3)"
> >
<HStack spacing={2}> <HStack spacing={2}>
<Icon as={FaTags} boxSize={4} color="cyan.300" /> <Icon as={Tags} boxSize={4} color="cyan.300" />
<VStack spacing={0} align="start"> <VStack spacing={0} align="start">
<Text fontSize="xl" fontWeight="bold" color="cyan.300">500+</Text> <Text fontSize="xl" fontWeight="bold" color="cyan.300">500+</Text>
<Text fontSize="xs" opacity={0.7}>概念板块</Text> <Text fontSize="xs" opacity={0.7}>概念板块</Text>
</VStack> </VStack>
</HStack> </HStack>
<HStack spacing={2}> <HStack spacing={2}>
<Icon as={FaChartLine} boxSize={4} color="purple.300" /> <Icon as={LineChart} boxSize={4} color="purple.300" />
<VStack spacing={0} align="start"> <VStack spacing={0} align="start">
<Text fontSize="xl" fontWeight="bold" color="purple.300">5000+</Text> <Text fontSize="xl" fontWeight="bold" color="purple.300">5000+</Text>
<Text fontSize="xs" opacity={0.7}>相关个股</Text> <Text fontSize="xs" opacity={0.7}>相关个股</Text>
</VStack> </VStack>
</HStack> </HStack>
<HStack spacing={2}> <HStack spacing={2}>
<Icon as={BsLightningFill} boxSize={4} color="yellow.300" /> <Icon as={Zap} boxSize={4} color="yellow.300" />
<VStack spacing={0} align="start"> <VStack spacing={0} align="start">
<Text fontSize="xl" fontWeight="bold" color="yellow.300">24/7</Text> <Text fontSize="xl" fontWeight="bold" color="yellow.300">24/7</Text>
<Text fontSize="xs" opacity={0.7}>实时监控</Text> <Text fontSize="xs" opacity={0.7}>实时监控</Text>
@@ -1668,7 +1702,7 @@ const ConceptCenter = () => {
> >
<InputGroup size="lg" flex={1}> <InputGroup size="lg" flex={1}>
<InputLeftElement pointerEvents="none" h="full"> <InputLeftElement pointerEvents="none" h="full">
<Icon as={SearchIcon} color="purple.400" boxSize={5} /> <Icon as={Search} color="purple.400" boxSize={5} />
</InputLeftElement> </InputLeftElement>
<Input <Input
placeholder="搜索概念板块、个股、关键词..." placeholder="搜索概念板块、个股、关键词..."
@@ -1696,7 +1730,7 @@ const ConceptCenter = () => {
transform="translateY(-50%)" transform="translateY(-50%)"
size="sm" size="sm"
aria-label="清除搜索" aria-label="清除搜索"
icon={<CloseIcon />} icon={<X size={16} />}
variant="ghost" variant="ghost"
color="gray.500" color="gray.500"
borderRadius="full" borderRadius="full"
@@ -1711,7 +1745,7 @@ const ConceptCenter = () => {
borderRadius="0 50px 50px 0" borderRadius="0 50px 50px 0"
bgGradient="linear(135deg, #667eea 0%, #764ba2 100%)" bgGradient="linear(135deg, #667eea 0%, #764ba2 100%)"
color="white" color="white"
leftIcon={<SearchIcon />} leftIcon={<Search size={16} />}
_hover={{ _hover={{
bgGradient: 'linear(135deg, #5568d3 0%, #663a8e 100%)', bgGradient: 'linear(135deg, #5568d3 0%, #663a8e 100%)',
transform: 'scale(1.02)', transform: 'scale(1.02)',
@@ -1777,7 +1811,7 @@ const ConceptCenter = () => {
{/* 排序方式 - 仅在列表视图显示 */} {/* 排序方式 - 仅在列表视图显示 */}
{viewMode === 'list' && ( {viewMode === 'list' && (
<HStack spacing={4} align="center"> <HStack spacing={4} align="center">
<Icon as={FaTags} boxSize={4} color="purple.300" /> <Icon as={Tags} boxSize={4} color="purple.300" />
<Text fontWeight="bold" color="white">排序方式</Text> <Text fontWeight="bold" color="white">排序方式</Text>
<Select <Select
value={sortBy} value={sortBy}
@@ -1812,7 +1846,7 @@ const ConceptCenter = () => {
borderRadius="full" borderRadius="full"
boxShadow="0 0 10px rgba(59, 130, 246, 0.4)" boxShadow="0 0 10px rgba(59, 130, 246, 0.4)"
> >
<Icon as={InfoIcon} color="white" boxSize={3} /> <Icon as={Info} color="white" boxSize={3} />
<Text fontSize="xs" color="white" fontWeight="medium"> <Text fontSize="xs" color="white" fontWeight="medium">
智能排序 智能排序
</Text> </Text>
@@ -1896,7 +1930,7 @@ const ConceptCenter = () => {
{selectedDate && viewMode !== 'hierarchy' && viewMode !== 'force3d' && ( {selectedDate && viewMode !== 'hierarchy' && viewMode !== 'force3d' && (
<Box mb={4} p={3} bg="rgba(59, 130, 246, 0.2)" borderRadius="xl" borderLeft="4px solid" borderColor="blue.400"> <Box mb={4} p={3} bg="rgba(59, 130, 246, 0.2)" borderRadius="xl" borderLeft="4px solid" borderColor="blue.400">
<HStack> <HStack>
<Icon as={InfoIcon} color="blue.300" /> <Icon as={Info} color="blue.300" />
<Text fontSize="sm" color="whiteAlpha.800"> <Text fontSize="sm" color="whiteAlpha.800">
当前显示 <Text as="strong" color="cyan.300">{selectedDate.toLocaleDateString('zh-CN')}</Text> 当前显示 <Text as="strong" color="cyan.300">{selectedDate.toLocaleDateString('zh-CN')}</Text>
{searchQuery && <span>搜索词<Text as="strong" color="cyan.300">"{searchQuery}"</Text></span>} {searchQuery && <span>搜索词<Text as="strong" color="cyan.300">"{searchQuery}"</Text></span>}
@@ -2030,7 +2064,7 @@ const ConceptCenter = () => {
) : viewMode !== 'hierarchy' && viewMode !== 'force3d' ? ( ) : viewMode !== 'hierarchy' && viewMode !== 'force3d' ? (
<Center h="400px"> <Center h="400px">
<VStack spacing={6}> <VStack spacing={6}>
<Icon as={FaTags} boxSize={20} color="whiteAlpha.300" /> <Icon as={Tags} boxSize={20} color="whiteAlpha.300" />
<VStack spacing={2}> <VStack spacing={2}>
<Text fontSize="xl" color="white" fontWeight="medium">暂无概念数据</Text> <Text fontSize="xl" color="white" fontWeight="medium">暂无概念数据</Text>
<Text color="whiteAlpha.600"> <Text color="whiteAlpha.600">
@@ -2075,7 +2109,7 @@ const ConceptCenter = () => {
> >
<CardBody p={6}> <CardBody p={6}>
<VStack spacing={4} textAlign="center"> <VStack spacing={4} textAlign="center">
<Icon as={FaChartLine} boxSize={12} color="whiteAlpha.300" /> <Icon as={LineChart} boxSize={12} color="whiteAlpha.300" />
<VStack spacing={2}> <VStack spacing={2}>
<Heading size="md" color="white"> <Heading size="md" color="white">
概念统计中心 概念统计中心
@@ -2087,7 +2121,7 @@ const ConceptCenter = () => {
<Button <Button
bg="blue.500" bg="blue.500"
color="white" color="white"
leftIcon={<Icon as={FaRocket} />} leftIcon={<Icon as={Rocket} />}
onClick={() => { onClick={() => {
setUpgradeFeature('pro'); setUpgradeFeature('pro');
setUpgradeModalOpen(true); setUpgradeModalOpen(true);