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:
@@ -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' }}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user