update pay ui
This commit is contained in:
@@ -16,13 +16,14 @@ import {
|
|||||||
Flex,
|
Flex,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { ChevronRightIcon, CloseIcon } from '@chakra-ui/icons';
|
import { ChevronRightIcon } from '@chakra-ui/icons';
|
||||||
import { FaLayerGroup, FaFilter, FaTimes, FaHome } from 'react-icons/fa';
|
import { FaFilter, FaTimes, FaHome } from 'react-icons/fa';
|
||||||
|
|
||||||
const BreadcrumbNav = ({
|
const BreadcrumbNav = ({
|
||||||
filter,
|
filter,
|
||||||
onClearFilter,
|
onClearFilter,
|
||||||
onNavigate,
|
onNavigate,
|
||||||
|
isDarkMode = false,
|
||||||
}) => {
|
}) => {
|
||||||
// 如果没有筛选条件,不显示
|
// 如果没有筛选条件,不显示
|
||||||
if (!filter || (!filter.lv1 && !filter.lv2 && !filter.lv3)) {
|
if (!filter || (!filter.lv1 && !filter.lv2 && !filter.lv3)) {
|
||||||
@@ -56,14 +57,71 @@ const BreadcrumbNav = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 深色主题样式
|
||||||
|
const darkStyles = {
|
||||||
|
container: {
|
||||||
|
bg: 'rgba(15, 23, 42, 0.8)',
|
||||||
|
backdropFilter: 'blur(20px)',
|
||||||
|
borderColor: 'whiteAlpha.100',
|
||||||
|
},
|
||||||
|
filterBadge: {
|
||||||
|
bg: 'purple.500',
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
homeBadge: {
|
||||||
|
bg: 'whiteAlpha.100',
|
||||||
|
color: 'white',
|
||||||
|
_hover: { bg: 'whiteAlpha.200' },
|
||||||
|
},
|
||||||
|
chevron: { color: 'whiteAlpha.400' },
|
||||||
|
crumbBadge: (level, isLast) => ({
|
||||||
|
bg: level === 'lv1' ? 'purple.500' : level === 'lv2' ? 'blue.500' : 'cyan.500',
|
||||||
|
color: 'white',
|
||||||
|
}),
|
||||||
|
clearBtn: {
|
||||||
|
color: 'red.300',
|
||||||
|
_hover: { bg: 'whiteAlpha.100' },
|
||||||
|
},
|
||||||
|
hintText: { color: 'whiteAlpha.500' },
|
||||||
|
linkText: { color: 'purple.300' },
|
||||||
|
};
|
||||||
|
|
||||||
|
// 浅色主题样式
|
||||||
|
const lightStyles = {
|
||||||
|
container: {
|
||||||
|
bg: 'linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(168, 85, 247, 0.1) 100%)',
|
||||||
|
borderColor: 'purple.200',
|
||||||
|
},
|
||||||
|
filterBadge: {
|
||||||
|
bg: 'purple.500',
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
homeBadge: {
|
||||||
|
colorScheme: 'gray',
|
||||||
|
_hover: { bg: 'gray.200' },
|
||||||
|
},
|
||||||
|
chevron: { color: 'gray.400' },
|
||||||
|
crumbBadge: (level, isLast) => ({
|
||||||
|
colorScheme: level === 'lv1' ? 'purple' : level === 'lv2' ? 'blue' : 'cyan',
|
||||||
|
}),
|
||||||
|
clearBtn: {
|
||||||
|
colorScheme: 'red',
|
||||||
|
},
|
||||||
|
hintText: { color: 'gray.500' },
|
||||||
|
linkText: { color: 'purple.600' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = isDarkMode ? darkStyles : lightStyles;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
bg="linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(168, 85, 247, 0.1) 100%)"
|
bg={styles.container.bg}
|
||||||
|
backdropFilter={isDarkMode ? styles.container.backdropFilter : undefined}
|
||||||
borderRadius="xl"
|
borderRadius="xl"
|
||||||
p={{ base: 3, md: 4 }}
|
p={{ base: 3, md: 4 }}
|
||||||
mb={4}
|
mb={4}
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="purple.200"
|
borderColor={styles.container.borderColor}
|
||||||
>
|
>
|
||||||
<Flex
|
<Flex
|
||||||
align="center"
|
align="center"
|
||||||
@@ -75,8 +133,8 @@ const BreadcrumbNav = ({
|
|||||||
{/* 筛选图标 */}
|
{/* 筛选图标 */}
|
||||||
<HStack
|
<HStack
|
||||||
spacing={2}
|
spacing={2}
|
||||||
bg="purple.500"
|
bg={styles.filterBadge.bg}
|
||||||
color="white"
|
color={styles.filterBadge.color}
|
||||||
px={3}
|
px={3}
|
||||||
py={1}
|
py={1}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
@@ -90,15 +148,15 @@ const BreadcrumbNav = ({
|
|||||||
{/* 首页入口 */}
|
{/* 首页入口 */}
|
||||||
<Tooltip label="返回全部概念" placement="top">
|
<Tooltip label="返回全部概念" placement="top">
|
||||||
<Badge
|
<Badge
|
||||||
colorScheme="gray"
|
{...(isDarkMode ? {} : { colorScheme: 'gray' })}
|
||||||
|
bg={isDarkMode ? styles.homeBadge.bg : undefined}
|
||||||
|
color={isDarkMode ? styles.homeBadge.color : undefined}
|
||||||
px={3}
|
px={3}
|
||||||
py={1}
|
py={1}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
onClick={onClearFilter}
|
onClick={onClearFilter}
|
||||||
_hover={{
|
_hover={styles.homeBadge._hover}
|
||||||
bg: 'gray.200',
|
|
||||||
}}
|
|
||||||
display="flex"
|
display="flex"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
gap={1}
|
gap={1}
|
||||||
@@ -111,12 +169,11 @@ const BreadcrumbNav = ({
|
|||||||
{/* 面包屑路径 */}
|
{/* 面包屑路径 */}
|
||||||
{breadcrumbs.map((crumb, index) => (
|
{breadcrumbs.map((crumb, index) => (
|
||||||
<React.Fragment key={crumb.level}>
|
<React.Fragment key={crumb.level}>
|
||||||
<Icon as={ChevronRightIcon} color="gray.400" boxSize={4} />
|
<Icon as={ChevronRightIcon} color={styles.chevron.color} boxSize={4} />
|
||||||
<Badge
|
<Badge
|
||||||
colorScheme={
|
{...(isDarkMode ? {} : { colorScheme: styles.crumbBadge(crumb.level, index === breadcrumbs.length - 1).colorScheme })}
|
||||||
crumb.level === 'lv1' ? 'purple' :
|
bg={isDarkMode ? styles.crumbBadge(crumb.level, index === breadcrumbs.length - 1).bg : undefined}
|
||||||
crumb.level === 'lv2' ? 'blue' : 'cyan'
|
color={isDarkMode ? styles.crumbBadge(crumb.level, index === breadcrumbs.length - 1).color : undefined}
|
||||||
}
|
|
||||||
px={3}
|
px={3}
|
||||||
py={1}
|
py={1}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
@@ -140,21 +197,23 @@ const BreadcrumbNav = ({
|
|||||||
<IconButton
|
<IconButton
|
||||||
size="sm"
|
size="sm"
|
||||||
icon={<FaTimes />}
|
icon={<FaTimes />}
|
||||||
colorScheme="red"
|
{...(isDarkMode ? {} : { colorScheme: 'red' })}
|
||||||
|
color={isDarkMode ? styles.clearBtn.color : undefined}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
onClick={onClearFilter}
|
onClick={onClearFilter}
|
||||||
aria-label="清除筛选"
|
aria-label="清除筛选"
|
||||||
|
_hover={isDarkMode ? styles.clearBtn._hover : undefined}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{/* 筛选提示 */}
|
{/* 筛选提示 */}
|
||||||
<Text fontSize="xs" color="gray.500" mt={2}>
|
<Text fontSize="xs" color={styles.hintText.color} mt={2}>
|
||||||
当前显示「{breadcrumbs.map(b => b.label).join(' > ')}」分类下的概念,
|
当前显示「{breadcrumbs.map(b => b.label).join(' > ')}」分类下的概念,
|
||||||
<Text
|
<Text
|
||||||
as="span"
|
as="span"
|
||||||
color="purple.600"
|
color={styles.linkText.color}
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
fontWeight="medium"
|
fontWeight="medium"
|
||||||
onClick={onClearFilter}
|
onClick={onClearFilter}
|
||||||
|
|||||||
@@ -635,15 +635,19 @@ const ConceptCenter = () => {
|
|||||||
init();
|
init();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 概念卡片组件 - 科幻毛玻璃版
|
// 获取股票名称(兼容新旧API格式)
|
||||||
|
const getStockName = (stock) => stock.name || stock.stock_name || '未知';
|
||||||
|
const getStockCode = (stock) => stock.code || stock.stock_code || '';
|
||||||
|
|
||||||
|
// 概念卡片组件 - 深色毛玻璃版(HeroUI风格)
|
||||||
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;
|
||||||
// H5 端使用更紧凑的尺寸
|
// H5 端使用更紧凑的尺寸
|
||||||
const isMobile = useBreakpointValue({ base: true, md: false });
|
const isMobile = useBreakpointValue({ base: true, md: false });
|
||||||
const coverHeight = useBreakpointValue({ base: '100px', md: '180px' });
|
const coverHeight = useBreakpointValue({ base: '100px', md: '160px' });
|
||||||
const logoSize = useBreakpointValue({ base: '60px', md: '120px' });
|
const logoSize = useBreakpointValue({ base: '60px', md: '100px' });
|
||||||
|
|
||||||
// 生成随机涨幅数字背景
|
// 生成随机涨幅数字背景
|
||||||
const generateNumbersBackground = () => {
|
const generateNumbersBackground = () => {
|
||||||
@@ -663,22 +667,24 @@ const ConceptCenter = () => {
|
|||||||
<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="rgba(15, 23, 42, 0.8)"
|
||||||
|
backdropFilter="blur(20px)"
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
borderColor="transparent"
|
borderColor="whiteAlpha.100"
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
_hover={{
|
_hover={{
|
||||||
transform: 'translateY(-8px)',
|
transform: 'translateY(-6px)',
|
||||||
boxShadow: '0 20px 40px rgba(139, 92, 246, 0.3)',
|
boxShadow: '0 20px 40px rgba(139, 92, 246, 0.25)',
|
||||||
borderColor: 'purple.400',
|
borderColor: 'purple.500',
|
||||||
}}
|
}}
|
||||||
transition="all 0.3s"
|
transition="all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
|
||||||
position="relative"
|
position="relative"
|
||||||
boxShadow="0 4px 12px rgba(0, 0, 0, 0.1)"
|
boxShadow="0 4px 20px rgba(0, 0, 0, 0.3)"
|
||||||
|
borderRadius="2xl"
|
||||||
>
|
>
|
||||||
{/* 毛玻璃涨幅数字背景 */}
|
{/* 毛玻璃涨幅数字背景 */}
|
||||||
<Box position="relative" height={coverHeight} overflow="hidden">
|
<Box position="relative" height={coverHeight} overflow="hidden">
|
||||||
{/* 渐变背景层 */}
|
{/* 渐变背景层 - 涨红跌绿 */}
|
||||||
<Box
|
<Box
|
||||||
position="absolute"
|
position="absolute"
|
||||||
top={0}
|
top={0}
|
||||||
@@ -687,10 +693,10 @@ const ConceptCenter = () => {
|
|||||||
bottom={0}
|
bottom={0}
|
||||||
bgGradient={
|
bgGradient={
|
||||||
hasChange && changePercent > 0
|
hasChange && changePercent > 0
|
||||||
? "linear(135deg, #667eea 0%, #764ba2 100%)"
|
? "linear(135deg, rgba(153, 27, 27, 0.6) 0%, rgba(239, 68, 68, 0.4) 100%)"
|
||||||
: hasChange && changePercent < 0
|
: hasChange && changePercent < 0
|
||||||
? "linear(135deg, #f093fb 0%, #f5576c 100%)"
|
? "linear(135deg, rgba(20, 83, 45, 0.6) 0%, rgba(34, 197, 94, 0.4) 100%)"
|
||||||
: "linear(135deg, #4facfe 0%, #00f2fe 100%)"
|
: "linear(135deg, rgba(71, 85, 105, 0.6) 0%, rgba(100, 116, 139, 0.4) 100%)"
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -706,7 +712,7 @@ const ConceptCenter = () => {
|
|||||||
gridTemplateRows="repeat(6, 1fr)"
|
gridTemplateRows="repeat(6, 1fr)"
|
||||||
gap={2}
|
gap={2}
|
||||||
p={3}
|
p={3}
|
||||||
opacity={0.15}
|
opacity={0.1}
|
||||||
>
|
>
|
||||||
{backgroundNumbers.map((num, idx) => (
|
{backgroundNumbers.map((num, idx) => (
|
||||||
<Flex
|
<Flex
|
||||||
@@ -731,7 +737,7 @@ const ConceptCenter = () => {
|
|||||||
transform="translate(-50%, -50%)"
|
transform="translate(-50%, -50%)"
|
||||||
width={logoSize}
|
width={logoSize}
|
||||||
height={logoSize}
|
height={logoSize}
|
||||||
opacity={0.15}
|
opacity={0.1}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={`${process.env.PUBLIC_URL}/LOGO_badge.png`}
|
src={`${process.env.PUBLIC_URL}/LOGO_badge.png`}
|
||||||
@@ -742,35 +748,15 @@ const ConceptCenter = () => {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* 毛玻璃层 */}
|
{/* 高光效果 */}
|
||||||
<Box
|
<Box
|
||||||
position="absolute"
|
position="absolute"
|
||||||
top={0}
|
top={0}
|
||||||
left={0}
|
left={0}
|
||||||
right={0}
|
right={0}
|
||||||
bottom={0}
|
height="50%"
|
||||||
backdropFilter="blur(8px)"
|
bg="linear-gradient(180deg, rgba(255,255,255,0.08) 0%, transparent 100%)"
|
||||||
bg="rgba(255, 255, 255, 0.05)"
|
pointerEvents="none"
|
||||||
/>
|
|
||||||
|
|
||||||
{/* 渐变遮罩 */}
|
|
||||||
<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 */}
|
||||||
@@ -779,14 +765,14 @@ const ConceptCenter = () => {
|
|||||||
position="absolute"
|
position="absolute"
|
||||||
top={3}
|
top={3}
|
||||||
left={3}
|
left={3}
|
||||||
bg={changeColor === 'red' ? 'red.500' : changeColor === 'green' ? 'green.500' : 'gray.500'}
|
bg={changeColor === 'red' ? 'rgba(239, 68, 68, 0.9)' : changeColor === 'green' ? 'rgba(34, 197, 94, 0.9)' : 'rgba(100, 116, 139, 0.9)'}
|
||||||
color="white"
|
color="white"
|
||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
px={3}
|
px={3}
|
||||||
py={1}
|
py={1}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
fontWeight="bold"
|
fontWeight="bold"
|
||||||
boxShadow="0 4px 12px rgba(0, 0, 0, 0.3)"
|
boxShadow={`0 4px 12px rgba(${changeColor === 'red' ? '239, 68, 68' : changeColor === 'green' ? '34, 197, 94' : '100, 116, 139'}, 0.4)`}
|
||||||
display="flex"
|
display="flex"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
gap={1}
|
gap={1}
|
||||||
@@ -805,38 +791,36 @@ const ConceptCenter = () => {
|
|||||||
position="absolute"
|
position="absolute"
|
||||||
top={3}
|
top={3}
|
||||||
right={3}
|
right={3}
|
||||||
bg="rgba(255, 255, 255, 0.2)"
|
bg="rgba(0, 0, 0, 0.4)"
|
||||||
backdropFilter="blur(10px)"
|
backdropFilter="blur(10px)"
|
||||||
color="white"
|
color="white"
|
||||||
fontSize="xs"
|
fontSize="xs"
|
||||||
px={3}
|
px={3}
|
||||||
py={1}
|
py={1}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
fontWeight="bold"
|
fontWeight="medium"
|
||||||
boxShadow="0 4px 12px rgba(0, 0, 0, 0.2)"
|
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="whiteAlpha.300"
|
borderColor="whiteAlpha.200"
|
||||||
>
|
>
|
||||||
{concept.stock_count || 0} 只股票
|
{concept.stock_count || 0} 只股票
|
||||||
</Badge>
|
</Badge>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<CardBody p={{ base: 3, md: 4 }}>
|
<CardBody p={{ base: 3, md: 4 }} bg="transparent">
|
||||||
<VStack align="start" spacing={{ base: 1, md: 2 }}>
|
<VStack align="start" spacing={{ base: 1, md: 2 }}>
|
||||||
{/* 概念名称 */}
|
{/* 概念名称 */}
|
||||||
<Heading
|
<Heading
|
||||||
size={{ base: 'xs', md: 'sm' }}
|
size={{ base: 'xs', md: 'sm' }}
|
||||||
color="gray.800"
|
color="white"
|
||||||
noOfLines={1}
|
noOfLines={1}
|
||||||
bgGradient="linear(to-r, purple.600, pink.600)"
|
|
||||||
bgClip="text"
|
|
||||||
fontWeight="bold"
|
fontWeight="bold"
|
||||||
|
letterSpacing="0.02em"
|
||||||
>
|
>
|
||||||
{concept.concept}
|
{concept.concept}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
|
||||||
{/* 描述信息 - H5端显示1行 */}
|
{/* 描述信息 - H5端显示1行 */}
|
||||||
<Text color="gray.600" fontSize="xs" noOfLines={isMobile ? 1 : 2} minH={{ base: '16px', md: '32px' }}>
|
<Text color="whiteAlpha.600" fontSize="xs" noOfLines={isMobile ? 1 : 2} minH={{ base: '16px', md: '32px' }}>
|
||||||
{concept.description || '暂无描述信息'}
|
{concept.description || '暂无描述信息'}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
@@ -844,31 +828,34 @@ const ConceptCenter = () => {
|
|||||||
<Box
|
<Box
|
||||||
width="100%"
|
width="100%"
|
||||||
p={{ base: 2, md: 3 }}
|
p={{ base: 2, md: 3 }}
|
||||||
bg="linear-gradient(135deg, rgba(99, 102, 241, 0.05) 0%, rgba(168, 85, 247, 0.05) 100%)"
|
bg="whiteAlpha.50"
|
||||||
borderRadius="lg"
|
backdropFilter="blur(10px)"
|
||||||
|
borderRadius="xl"
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
onClick={(e) => handleViewStocks(e, concept)}
|
onClick={(e) => handleViewStocks(e, concept)}
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: 'linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(168, 85, 247, 0.1) 100%)',
|
bg: 'whiteAlpha.100',
|
||||||
transform: 'translateX(2px)',
|
transform: 'translateX(2px)',
|
||||||
}}
|
}}
|
||||||
transition="all 0.2s"
|
transition="all 0.2s"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="purple.100"
|
borderColor="whiteAlpha.100"
|
||||||
>
|
>
|
||||||
<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.500" />
|
<Icon as={FaChartLine} boxSize={3} color="purple.300" />
|
||||||
<Text fontSize="xs" color="purple.700" fontWeight="bold">
|
<Text fontSize="xs" color="purple.200" fontWeight="bold">
|
||||||
热门个股
|
热门个股
|
||||||
</Text>
|
</Text>
|
||||||
{!hasFeatureAccess('hot_stocks') && (
|
{!hasFeatureAccess('hot_stocks') && (
|
||||||
<Badge
|
<Badge
|
||||||
colorScheme="yellow"
|
bg="yellow.500"
|
||||||
|
color="gray.900"
|
||||||
size="sm"
|
size="sm"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
px={2}
|
px={2}
|
||||||
|
fontSize="xs"
|
||||||
>
|
>
|
||||||
🔒Pro
|
🔒Pro
|
||||||
</Badge>
|
</Badge>
|
||||||
@@ -881,24 +868,24 @@ const ConceptCenter = () => {
|
|||||||
<Tag
|
<Tag
|
||||||
key={idx}
|
key={idx}
|
||||||
size="sm"
|
size="sm"
|
||||||
bgGradient="linear(to-r, purple.500, pink.500)"
|
bg="purple.500"
|
||||||
color="white"
|
color="white"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
px={2}
|
px={2}
|
||||||
>
|
>
|
||||||
<TagLabel fontSize="xs">{stock.stock_name}</TagLabel>
|
<TagLabel fontSize="xs">{getStockName(stock)}</TagLabel>
|
||||||
</Tag>
|
</Tag>
|
||||||
))}
|
))}
|
||||||
{concept.stocks.length > 2 && (
|
{concept.stocks.length > 2 && (
|
||||||
<Text fontSize="xs" color="purple.600" fontWeight="bold">
|
<Text fontSize="xs" color="purple.300" fontWeight="bold">
|
||||||
+{concept.stocks.length - 2}
|
+{concept.stocks.length - 2}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<HStack spacing={1}>
|
<HStack spacing={1}>
|
||||||
<Icon as={FaLock} boxSize="10px" color="yellow.600" />
|
<Icon as={FaLock} boxSize="10px" color="yellow.400" />
|
||||||
<Text fontSize="xs" color="yellow.600" fontWeight="medium">
|
<Text fontSize="xs" color="yellow.400" fontWeight="medium">
|
||||||
升级查看{concept.stocks.length}只个股
|
升级查看{concept.stocks.length}只个股
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
@@ -907,32 +894,41 @@ const ConceptCenter = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
<Icon
|
<Icon
|
||||||
as={hasFeatureAccess('hot_stocks') ? ChevronRightIcon : FaLock}
|
as={hasFeatureAccess('hot_stocks') ? ChevronRightIcon : FaLock}
|
||||||
color={hasFeatureAccess('hot_stocks') ? 'purple.500' : 'yellow.600'}
|
color={hasFeatureAccess('hot_stocks') ? 'purple.300' : 'yellow.400'}
|
||||||
boxSize={4}
|
boxSize={4}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Divider borderColor="purple.100" my={{ base: 1, md: 0 }} />
|
<Divider borderColor="whiteAlpha.100" my={{ base: 1, md: 0 }} />
|
||||||
|
|
||||||
<Flex width="100%" justify="space-between" align="center">
|
<Flex width="100%" justify="space-between" align="center">
|
||||||
{formatAddedDate(concept)}
|
{/* 添加日期 - 深色主题适配 */}
|
||||||
|
{concept.created_at || concept.added_date || concept.happened_times?.[0] ? (
|
||||||
|
<HStack spacing={2}>
|
||||||
|
<Icon as={CalendarIcon} boxSize={3} color="cyan.400" />
|
||||||
|
<Text fontSize="xs" color="whiteAlpha.600" fontWeight="medium">
|
||||||
|
添加于 {new Date(concept.created_at || concept.added_date || concept.happened_times?.[0]).toLocaleDateString('zh-CN')}
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
) : <Box />}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
size={{ base: 'xs', md: 'sm' }}
|
size={{ base: 'xs', md: 'sm' }}
|
||||||
leftIcon={<FaHistory />}
|
leftIcon={<FaHistory />}
|
||||||
bgGradient="linear(to-r, purple.500, pink.500)"
|
bg="purple.500"
|
||||||
color="white"
|
color="white"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
onClick={(e) => handleViewContent(e, concept.concept, concept.concept_id)}
|
onClick={(e) => handleViewContent(e, concept.concept, concept.concept_id)}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
px={{ base: 2, md: 4 }}
|
px={{ base: 2, md: 4 }}
|
||||||
fontWeight="medium"
|
fontWeight="medium"
|
||||||
boxShadow="0 4px 12px rgba(139, 92, 246, 0.3)"
|
boxShadow="0 4px 12px rgba(139, 92, 246, 0.4)"
|
||||||
_hover={{
|
_hover={{
|
||||||
|
bg: 'purple.400',
|
||||||
transform: 'scale(1.05)',
|
transform: 'scale(1.05)',
|
||||||
boxShadow: '0 6px 16px rgba(139, 92, 246, 0.4)',
|
boxShadow: '0 6px 16px rgba(139, 92, 246, 0.5)',
|
||||||
}}
|
}}
|
||||||
transition="all 0.2s"
|
transition="all 0.2s"
|
||||||
>
|
>
|
||||||
@@ -949,7 +945,7 @@ const ConceptCenter = () => {
|
|||||||
left={0}
|
left={0}
|
||||||
right={0}
|
right={0}
|
||||||
height="2px"
|
height="2px"
|
||||||
bgGradient="linear(to-r, purple.400, pink.400, blue.400)"
|
bgGradient="linear(to-r, purple.500, pink.500, cyan.500)"
|
||||||
opacity={0}
|
opacity={0}
|
||||||
_groupHover={{ opacity: 1 }}
|
_groupHover={{ opacity: 1 }}
|
||||||
transition="opacity 0.3s"
|
transition="opacity 0.3s"
|
||||||
@@ -958,7 +954,7 @@ const ConceptCenter = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 概念列表项组件 - 列表视图
|
// 概念列表项组件 - 列表视图(深色主题版)
|
||||||
const ConceptListItem = ({ concept, position = 0 }) => {
|
const ConceptListItem = ({ 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);
|
||||||
@@ -968,38 +964,49 @@ const ConceptCenter = () => {
|
|||||||
<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="rgba(15, 23, 42, 0.8)"
|
||||||
|
backdropFilter="blur(20px)"
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
borderColor="gray.200"
|
borderColor="whiteAlpha.100"
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
|
borderRadius="2xl"
|
||||||
_hover={{
|
_hover={{
|
||||||
transform: 'translateX(4px)',
|
transform: 'translateX(4px)',
|
||||||
boxShadow: 'lg',
|
boxShadow: '0 8px 32px rgba(139, 92, 246, 0.25)',
|
||||||
borderColor: 'purple.300',
|
borderColor: 'purple.500',
|
||||||
}}
|
}}
|
||||||
transition="all 0.3s"
|
transition="all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
|
||||||
>
|
>
|
||||||
<CardBody p={6}>
|
<CardBody p={{ base: 4, md: 6 }}>
|
||||||
<Flex align="center" gap={6}>
|
<Flex align="center" gap={{ base: 3, md: 6 }} flexWrap={{ base: 'wrap', md: 'nowrap' }}>
|
||||||
{/* 左侧图标区域 */}
|
{/* 左侧图标区域 */}
|
||||||
<Box
|
<Box
|
||||||
width="80px"
|
width={{ base: '60px', md: '80px' }}
|
||||||
height="80px"
|
height={{ base: '60px', md: '80px' }}
|
||||||
borderRadius="xl"
|
borderRadius="xl"
|
||||||
bgGradient="linear(to-br, purple.100, pink.100)"
|
bg={hasChange
|
||||||
|
? changePercent > 0
|
||||||
|
? "linear-gradient(135deg, rgba(153, 27, 27, 0.6) 0%, rgba(239, 68, 68, 0.4) 100%)"
|
||||||
|
: changePercent < 0
|
||||||
|
? "linear-gradient(135deg, rgba(20, 83, 45, 0.6) 0%, rgba(34, 197, 94, 0.4) 100%)"
|
||||||
|
: "linear-gradient(135deg, rgba(71, 85, 105, 0.6) 0%, rgba(100, 116, 139, 0.4) 100%)"
|
||||||
|
: "linear-gradient(135deg, rgba(99, 102, 241, 0.4) 0%, rgba(168, 85, 247, 0.3) 100%)"
|
||||||
|
}
|
||||||
display="flex"
|
display="flex"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
position="relative"
|
position="relative"
|
||||||
flexShrink={0}
|
flexShrink={0}
|
||||||
|
border="1px solid"
|
||||||
|
borderColor="whiteAlpha.100"
|
||||||
>
|
>
|
||||||
<Icon as={FaTags} boxSize={8} color="purple.400" />
|
<Icon as={FaTags} boxSize={{ base: 6, md: 8 }} color="white" opacity={0.8} />
|
||||||
{hasChange && (
|
{hasChange && (
|
||||||
<Badge
|
<Badge
|
||||||
position="absolute"
|
position="absolute"
|
||||||
top={-2}
|
top={-2}
|
||||||
right={-2}
|
right={-2}
|
||||||
bg={changeColor === 'red' ? 'red.500' : changeColor === 'green' ? 'green.500' : 'gray.500'}
|
bg={changeColor === 'red' ? 'rgba(239, 68, 68, 0.9)' : changeColor === 'green' ? 'rgba(34, 197, 94, 0.9)' : 'rgba(100, 116, 139, 0.9)'}
|
||||||
color="white"
|
color="white"
|
||||||
fontSize="xs"
|
fontSize="xs"
|
||||||
px={2}
|
px={2}
|
||||||
@@ -1007,6 +1014,7 @@ const ConceptCenter = () => {
|
|||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
fontWeight="bold"
|
fontWeight="bold"
|
||||||
minW="auto"
|
minW="auto"
|
||||||
|
boxShadow={`0 2px 8px rgba(${changeColor === 'red' ? '239, 68, 68' : changeColor === 'green' ? '34, 197, 94' : '100, 116, 139'}, 0.4)`}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
as={changePercent > 0 ? FaArrowUp : changePercent < 0 ? FaArrowDown : null}
|
as={changePercent > 0 ? FaArrowUp : changePercent < 0 ? FaArrowDown : null}
|
||||||
@@ -1020,47 +1028,58 @@ const ConceptCenter = () => {
|
|||||||
|
|
||||||
{/* 中间内容区域 */}
|
{/* 中间内容区域 */}
|
||||||
<Box flex={1}>
|
<Box flex={1}>
|
||||||
<VStack align="start" spacing={3}>
|
<VStack align="start" spacing={{ base: 2, md: 3 }}>
|
||||||
<Heading size="md" color="gray.800" noOfLines={1}>
|
<Heading size={{ base: 'sm', md: 'md' }} color="white" noOfLines={1}>
|
||||||
{concept.concept}
|
{concept.concept}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
|
||||||
<Text color="gray.600" fontSize="sm" noOfLines={2}>
|
<Text color="whiteAlpha.600" fontSize="sm" noOfLines={2}>
|
||||||
{concept.description || '该概念板块涵盖相关技术、产业链和市场应用等多个维度的投资机会'}
|
{concept.description || '该概念板块涵盖相关技术、产业链和市场应用等多个维度的投资机会'}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<HStack spacing={4} flexWrap="wrap">
|
<HStack spacing={4} flexWrap="wrap">
|
||||||
<HStack spacing={1}>
|
<HStack spacing={1}>
|
||||||
<Icon as={FaChartLine} boxSize={4} color="purple.500" />
|
<Icon as={FaChartLine} boxSize={4} color="purple.300" />
|
||||||
<Text fontSize="sm" fontWeight="medium" color="gray.700">
|
<Text fontSize="sm" fontWeight="medium" color="whiteAlpha.800">
|
||||||
{concept.stock_count || 0} 只股票
|
{concept.stock_count || 0} 只股票
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
{hasChange && concept.price_info?.trade_date && (
|
{hasChange && concept.price_info?.trade_date && (
|
||||||
<HStack spacing={1}>
|
<HStack spacing={1}>
|
||||||
<Icon as={FaCalendarAlt} boxSize={4} color="blue.500" />
|
<Icon as={FaCalendarAlt} boxSize={4} color="cyan.400" />
|
||||||
<Text fontSize="sm" color="gray.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>
|
||||||
</HStack>
|
</HStack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{formatAddedDate(concept)}
|
{/* 添加日期 - 深色主题 */}
|
||||||
|
{(concept.created_at || concept.added_date || concept.happened_times?.[0]) && (
|
||||||
|
<HStack spacing={1}>
|
||||||
|
<Icon as={CalendarIcon} boxSize={4} color="cyan.400" />
|
||||||
|
<Text fontSize="sm" color="whiteAlpha.600">
|
||||||
|
添加于 {new Date(concept.created_at || concept.added_date || concept.happened_times?.[0]).toLocaleDateString('zh-CN')}
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
)}
|
||||||
</HStack>
|
</HStack>
|
||||||
</VStack>
|
</VStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* 右侧操作区域 */}
|
{/* 右侧操作区域 */}
|
||||||
<VStack spacing={3} align="end" flexShrink={0}>
|
<VStack spacing={3} align="end" flexShrink={0} display={{ base: 'none', md: 'flex' }}>
|
||||||
<HStack spacing={3}>
|
<HStack spacing={3}>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
leftIcon={<ViewIcon />}
|
leftIcon={<ViewIcon />}
|
||||||
colorScheme="blue"
|
bg="whiteAlpha.100"
|
||||||
variant="outline"
|
color="white"
|
||||||
|
border="1px solid"
|
||||||
|
borderColor="whiteAlpha.200"
|
||||||
onClick={(e) => handleViewStocks(e, concept)}
|
onClick={(e) => handleViewStocks(e, concept)}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
|
_hover={{ bg: 'whiteAlpha.200', borderColor: 'whiteAlpha.300' }}
|
||||||
>
|
>
|
||||||
查看个股
|
查看个股
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1068,10 +1087,12 @@ const ConceptCenter = () => {
|
|||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
leftIcon={<FaChartLine />}
|
leftIcon={<FaChartLine />}
|
||||||
colorScheme="purple"
|
bg="purple.500"
|
||||||
variant="solid"
|
color="white"
|
||||||
onClick={(e) => handleViewContent(e, concept.concept, concept.concept_id)}
|
onClick={(e) => handleViewContent(e, concept.concept, concept.concept_id)}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
|
boxShadow="0 4px 12px rgba(139, 92, 246, 0.4)"
|
||||||
|
_hover={{ bg: 'purple.400', boxShadow: '0 6px 16px rgba(139, 92, 246, 0.5)' }}
|
||||||
>
|
>
|
||||||
历史时间轴
|
历史时间轴
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1080,9 +1101,9 @@ const ConceptCenter = () => {
|
|||||||
{concept.stocks && concept.stocks.length > 0 && (
|
{concept.stocks && concept.stocks.length > 0 && (
|
||||||
<Box>
|
<Box>
|
||||||
<HStack spacing={1} mb={2}>
|
<HStack spacing={1} mb={2}>
|
||||||
<Text fontSize="xs" color="gray.500">热门个股</Text>
|
<Text fontSize="xs" color="whiteAlpha.500">热门个股</Text>
|
||||||
{!hasFeatureAccess('hot_stocks') && (
|
{!hasFeatureAccess('hot_stocks') && (
|
||||||
<Badge colorScheme="yellow" size="sm">
|
<Badge bg="yellow.500" color="gray.900" size="sm" fontSize="xs">
|
||||||
🔒需Pro
|
🔒需Pro
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
@@ -1092,14 +1113,14 @@ const ConceptCenter = () => {
|
|||||||
<>
|
<>
|
||||||
{concept.stocks.slice(0, 3).map((stock, idx) => (
|
{concept.stocks.slice(0, 3).map((stock, idx) => (
|
||||||
<WrapItem key={idx}>
|
<WrapItem key={idx}>
|
||||||
<Tag size="sm" colorScheme="purple" variant="subtle">
|
<Tag size="sm" bg="purple.500" color="white" borderRadius="full">
|
||||||
<TagLabel fontSize="xs">{stock.stock_name}</TagLabel>
|
<TagLabel fontSize="xs">{getStockName(stock)}</TagLabel>
|
||||||
</Tag>
|
</Tag>
|
||||||
</WrapItem>
|
</WrapItem>
|
||||||
))}
|
))}
|
||||||
{concept.stocks.length > 3 && (
|
{concept.stocks.length > 3 && (
|
||||||
<WrapItem>
|
<WrapItem>
|
||||||
<Text fontSize="xs" color="purple.600" fontWeight="medium">
|
<Text fontSize="xs" color="purple.300" fontWeight="medium">
|
||||||
+{concept.stocks.length - 3}更多
|
+{concept.stocks.length - 3}更多
|
||||||
</Text>
|
</Text>
|
||||||
</WrapItem>
|
</WrapItem>
|
||||||
@@ -1108,8 +1129,8 @@ const ConceptCenter = () => {
|
|||||||
) : (
|
) : (
|
||||||
<WrapItem>
|
<WrapItem>
|
||||||
<HStack spacing={1}>
|
<HStack spacing={1}>
|
||||||
<Icon as={FaLock} boxSize="8px" color="yellow.600" />
|
<Icon as={FaLock} boxSize="8px" color="yellow.400" />
|
||||||
<Text fontSize="xs" color="yellow.600" fontWeight="medium">
|
<Text fontSize="xs" color="yellow.400" fontWeight="medium">
|
||||||
升级查看{concept.stocks.length}只
|
升级查看{concept.stocks.length}只
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
@@ -1125,26 +1146,26 @@ const ConceptCenter = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 骨架屏组件
|
// 骨架屏组件 - 深色主题
|
||||||
const SkeletonCard = () => (
|
const SkeletonCard = () => (
|
||||||
<Card bg="white" borderWidth="1px" borderColor="gray.200">
|
<Card bg="rgba(15, 23, 42, 0.8)" borderWidth="1px" borderColor="whiteAlpha.100" borderRadius="2xl">
|
||||||
<Skeleton height="200px" />
|
<Skeleton height="160px" startColor="whiteAlpha.100" endColor="whiteAlpha.200" />
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<SkeletonText mt={4} noOfLines={4} spacing={4} />
|
<SkeletonText mt={4} noOfLines={4} spacing={4} startColor="whiteAlpha.100" endColor="whiteAlpha.200" />
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
||||||
// 日期选择组件 - 科幻风格
|
// 日期选择组件 - 深色主题
|
||||||
const DateSelector = () => (
|
const DateSelector = () => (
|
||||||
<Box
|
<Box
|
||||||
p={4}
|
p={4}
|
||||||
bg="rgba(255, 255, 255, 0.8)"
|
bg="rgba(15, 23, 42, 0.8)"
|
||||||
backdropFilter="blur(10px)"
|
backdropFilter="blur(20px)"
|
||||||
borderRadius="xl"
|
borderRadius="2xl"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="purple.100"
|
borderColor="whiteAlpha.100"
|
||||||
boxShadow="0 4px 20px rgba(139, 92, 246, 0.1)"
|
boxShadow="0 4px 20px rgba(0, 0, 0, 0.3)"
|
||||||
>
|
>
|
||||||
<Flex
|
<Flex
|
||||||
direction={{ base: 'column', lg: 'row' }}
|
direction={{ base: 'column', lg: 'row' }}
|
||||||
@@ -1165,17 +1186,18 @@ const ConceptCenter = () => {
|
|||||||
}}
|
}}
|
||||||
latestTradeDate={latestTradeDate}
|
latestTradeDate={latestTradeDate}
|
||||||
label="交易日期"
|
label="交易日期"
|
||||||
|
isDarkMode={true}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 快捷按钮保留在页面内 */}
|
{/* 快捷按钮 - 深色主题 */}
|
||||||
<ButtonGroup size="sm" variant="outline" flexWrap="wrap">
|
<ButtonGroup size="sm" variant="outline" flexWrap="wrap">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleQuickDateSelect(0)}
|
onClick={() => handleQuickDateSelect(0)}
|
||||||
borderColor="purple.300"
|
borderColor="whiteAlpha.300"
|
||||||
color="purple.600"
|
color="white"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: 'purple.50',
|
bg: 'whiteAlpha.100',
|
||||||
borderColor: 'purple.400',
|
borderColor: 'purple.400',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -1183,11 +1205,11 @@ const ConceptCenter = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleQuickDateSelect(1)}
|
onClick={() => handleQuickDateSelect(1)}
|
||||||
borderColor="purple.300"
|
borderColor="whiteAlpha.300"
|
||||||
color="purple.600"
|
color="white"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: 'purple.50',
|
bg: 'whiteAlpha.100',
|
||||||
borderColor: 'purple.400',
|
borderColor: 'purple.400',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -1195,11 +1217,11 @@ const ConceptCenter = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleQuickDateSelect(7)}
|
onClick={() => handleQuickDateSelect(7)}
|
||||||
borderColor="purple.300"
|
borderColor="whiteAlpha.300"
|
||||||
color="purple.600"
|
color="white"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: 'purple.50',
|
bg: 'whiteAlpha.100',
|
||||||
borderColor: 'purple.400',
|
borderColor: 'purple.400',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -1207,11 +1229,11 @@ const ConceptCenter = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleQuickDateSelect(30)}
|
onClick={() => handleQuickDateSelect(30)}
|
||||||
borderColor="purple.300"
|
borderColor="whiteAlpha.300"
|
||||||
color="purple.600"
|
color="white"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: 'purple.50',
|
bg: 'whiteAlpha.100',
|
||||||
borderColor: 'purple.400',
|
borderColor: 'purple.400',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -1223,7 +1245,7 @@ const ConceptCenter = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box minH="100vh" bg="linear-gradient(180deg, #f8f9ff 0%, #f0f2ff 100%)">
|
<Box minH="100vh" bg="linear-gradient(to-b, gray.900, slate.900, gray.900)">
|
||||||
{/* 导航栏已由 MainLayout 提供 */}
|
{/* 导航栏已由 MainLayout 提供 */}
|
||||||
|
|
||||||
{/* Hero Section - 精简版 */}
|
{/* Hero Section - 精简版 */}
|
||||||
@@ -1434,7 +1456,7 @@ const ConceptCenter = () => {
|
|||||||
</Container>
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* 主内容区域 */}
|
{/* 主内容区域 - 深色主题 */}
|
||||||
<Container maxW="container.xl" py={10}>
|
<Container maxW="container.xl" py={10}>
|
||||||
<Box mb={6}>
|
<Box mb={6}>
|
||||||
<DateSelector />
|
<DateSelector />
|
||||||
@@ -1447,11 +1469,12 @@ const ConceptCenter = () => {
|
|||||||
|
|
||||||
<Card
|
<Card
|
||||||
mb={8}
|
mb={8}
|
||||||
bg="rgba(255, 255, 255, 0.8)"
|
bg="rgba(15, 23, 42, 0.8)"
|
||||||
backdropFilter="blur(10px)"
|
backdropFilter="blur(20px)"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="purple.100"
|
borderColor="whiteAlpha.100"
|
||||||
boxShadow="0 4px 20px rgba(139, 92, 246, 0.1)"
|
boxShadow="0 4px 20px rgba(0, 0, 0, 0.3)"
|
||||||
|
borderRadius="2xl"
|
||||||
>
|
>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<Flex
|
<Flex
|
||||||
@@ -1461,16 +1484,25 @@ const ConceptCenter = () => {
|
|||||||
gap={4}
|
gap={4}
|
||||||
>
|
>
|
||||||
<HStack spacing={4} align="center">
|
<HStack spacing={4} align="center">
|
||||||
<Icon as={FaTags} boxSize={4} color="purple.500" />
|
<Icon as={FaTags} boxSize={4} color="purple.300" />
|
||||||
<Text fontWeight="bold" color="purple.700">排序方式:</Text>
|
<Text fontWeight="bold" color="white">排序方式:</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.400"
|
||||||
borderColor="purple.200"
|
borderColor="whiteAlpha.300"
|
||||||
borderRadius="lg"
|
borderRadius="lg"
|
||||||
fontWeight="medium"
|
fontWeight="medium"
|
||||||
|
color="white"
|
||||||
|
bg="whiteAlpha.50"
|
||||||
|
_hover={{ borderColor: 'purple.400' }}
|
||||||
|
sx={{
|
||||||
|
option: {
|
||||||
|
bg: 'gray.800',
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<option value="change_pct">涨跌幅</option>
|
<option value="change_pct">涨跌幅</option>
|
||||||
<option value="_score">相关度</option>
|
<option value="_score">相关度</option>
|
||||||
@@ -1482,15 +1514,14 @@ const ConceptCenter = () => {
|
|||||||
<Tooltip label="搜索时自动切换到相关度排序,以显示最匹配的结果。您也可以手动切换其他排序方式。">
|
<Tooltip label="搜索时自动切换到相关度排序,以显示最匹配的结果。您也可以手动切换其他排序方式。">
|
||||||
<HStack
|
<HStack
|
||||||
spacing={1}
|
spacing={1}
|
||||||
bg="blue.50"
|
bg="blue.500"
|
||||||
px={3}
|
px={3}
|
||||||
py={1}
|
py={1}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
border="1px solid"
|
boxShadow="0 0 10px rgba(59, 130, 246, 0.4)"
|
||||||
borderColor="blue.200"
|
|
||||||
>
|
>
|
||||||
<Icon as={InfoIcon} color="blue.500" boxSize={3} />
|
<Icon as={InfoIcon} color="white" boxSize={3} />
|
||||||
<Text fontSize="xs" color="blue.600" fontWeight="medium">
|
<Text fontSize="xs" color="white" fontWeight="medium">
|
||||||
智能排序
|
智能排序
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
@@ -1508,12 +1539,12 @@ const ConceptCenter = () => {
|
|||||||
setViewMode('hierarchy');
|
setViewMode('hierarchy');
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
bg={viewMode === 'hierarchy' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
|
bg={viewMode === 'hierarchy' ? 'purple.500' : 'transparent'}
|
||||||
color={viewMode === 'hierarchy' ? 'white' : 'purple.500'}
|
color={viewMode === 'hierarchy' ? 'white' : 'whiteAlpha.700'}
|
||||||
borderColor="purple.500"
|
borderColor="whiteAlpha.300"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: viewMode === 'hierarchy' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
|
bg: viewMode === 'hierarchy' ? 'purple.400' : 'whiteAlpha.100',
|
||||||
boxShadow: viewMode === 'hierarchy' ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
|
boxShadow: viewMode === 'hierarchy' ? '0 0 10px rgba(139, 92, 246, 0.4)' : 'none',
|
||||||
}}
|
}}
|
||||||
aria-label="层级图"
|
aria-label="层级图"
|
||||||
/>
|
/>
|
||||||
@@ -1527,12 +1558,12 @@ const ConceptCenter = () => {
|
|||||||
setViewMode('grid');
|
setViewMode('grid');
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
bg={viewMode === 'grid' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
|
bg={viewMode === 'grid' ? 'purple.500' : 'transparent'}
|
||||||
color={viewMode === 'grid' ? 'white' : 'purple.500'}
|
color={viewMode === 'grid' ? 'white' : 'whiteAlpha.700'}
|
||||||
borderColor="purple.500"
|
borderColor="whiteAlpha.300"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: viewMode === 'grid' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
|
bg: viewMode === 'grid' ? 'purple.400' : 'whiteAlpha.100',
|
||||||
boxShadow: viewMode === 'grid' ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
|
boxShadow: viewMode === 'grid' ? '0 0 10px rgba(139, 92, 246, 0.4)' : 'none',
|
||||||
}}
|
}}
|
||||||
aria-label="网格视图"
|
aria-label="网格视图"
|
||||||
/>
|
/>
|
||||||
@@ -1546,12 +1577,12 @@ const ConceptCenter = () => {
|
|||||||
setViewMode('list');
|
setViewMode('list');
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
bg={viewMode === 'list' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
|
bg={viewMode === 'list' ? 'purple.500' : 'transparent'}
|
||||||
color={viewMode === 'list' ? 'white' : 'purple.500'}
|
color={viewMode === 'list' ? 'white' : 'whiteAlpha.700'}
|
||||||
borderColor="purple.500"
|
borderColor="whiteAlpha.300"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: viewMode === 'list' ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
|
bg: viewMode === 'list' ? 'purple.400' : 'whiteAlpha.100',
|
||||||
boxShadow: viewMode === 'list' ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
|
boxShadow: viewMode === 'list' ? '0 0 10px rgba(139, 92, 246, 0.4)' : 'none',
|
||||||
}}
|
}}
|
||||||
aria-label="列表视图"
|
aria-label="列表视图"
|
||||||
/>
|
/>
|
||||||
@@ -1566,15 +1597,16 @@ const ConceptCenter = () => {
|
|||||||
filter={hierarchyFilter}
|
filter={hierarchyFilter}
|
||||||
onClearFilter={handleClearHierarchyFilter}
|
onClearFilter={handleClearHierarchyFilter}
|
||||||
onNavigate={handleNavigateHierarchy}
|
onNavigate={handleNavigateHierarchy}
|
||||||
|
isDarkMode={true}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{selectedDate && viewMode !== 'hierarchy' && (
|
{selectedDate && viewMode !== 'hierarchy' && (
|
||||||
<Box mb={4} p={3} bg="blue.50" borderRadius="md" borderLeft="4px solid" borderColor="blue.500">
|
<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.500" />
|
<Icon as={InfoIcon} color="blue.300" />
|
||||||
<Text fontSize="sm" color="blue.700">
|
<Text fontSize="sm" color="whiteAlpha.800">
|
||||||
当前显示 <strong>{selectedDate.toLocaleDateString('zh-CN')}</strong> 的概念涨跌幅数据
|
当前显示 <Text as="strong" color="cyan.300">{selectedDate.toLocaleDateString('zh-CN')}</Text> 的概念涨跌幅数据
|
||||||
{searchQuery && <span>,搜索词:<strong>"{searchQuery}"</strong></span>}
|
{searchQuery && <span>,搜索词:<Text as="strong" color="cyan.300">"{searchQuery}"</Text></span>}
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -1614,30 +1646,30 @@ const ConceptCenter = () => {
|
|||||||
<Center mt={12}>
|
<Center mt={12}>
|
||||||
<HStack
|
<HStack
|
||||||
spacing={3}
|
spacing={3}
|
||||||
bg="rgba(255, 255, 255, 0.8)"
|
bg="rgba(15, 23, 42, 0.8)"
|
||||||
backdropFilter="blur(10px)"
|
backdropFilter="blur(20px)"
|
||||||
px={6}
|
px={6}
|
||||||
py={3}
|
py={3}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="purple.100"
|
borderColor="whiteAlpha.100"
|
||||||
boxShadow="0 4px 20px rgba(139, 92, 246, 0.15)"
|
boxShadow="0 4px 20px rgba(0, 0, 0, 0.3)"
|
||||||
>
|
>
|
||||||
<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}
|
||||||
bgGradient="linear(to-r, purple.500, pink.500)"
|
bg="purple.500"
|
||||||
color="white"
|
color="white"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
_hover={{
|
_hover={{
|
||||||
bgGradient: 'linear(to-r, purple.600, pink.600)',
|
bg: 'purple.400',
|
||||||
boxShadow: '0 0 15px rgba(139, 92, 246, 0.4)',
|
boxShadow: '0 0 15px rgba(139, 92, 246, 0.5)',
|
||||||
}}
|
}}
|
||||||
_disabled={{
|
_disabled={{
|
||||||
bg: 'gray.200',
|
bg: 'whiteAlpha.100',
|
||||||
color: 'gray.400',
|
color: 'whiteAlpha.400',
|
||||||
cursor: 'not-allowed',
|
cursor: 'not-allowed',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -1655,15 +1687,15 @@ const ConceptCenter = () => {
|
|||||||
key={pageNum}
|
key={pageNum}
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => handlePageChange(pageNum)}
|
onClick={() => handlePageChange(pageNum)}
|
||||||
bg={pageNum === currentPage ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'transparent'}
|
bg={pageNum === currentPage ? 'purple.500' : 'transparent'}
|
||||||
color={pageNum === currentPage ? 'white' : 'purple.600'}
|
color={pageNum === currentPage ? 'white' : 'whiteAlpha.700'}
|
||||||
variant={pageNum === currentPage ? 'solid' : 'ghost'}
|
variant={pageNum === currentPage ? 'solid' : 'ghost'}
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
minW="40px"
|
minW="40px"
|
||||||
fontWeight="bold"
|
fontWeight="bold"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: pageNum === currentPage ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'purple.50',
|
bg: pageNum === currentPage ? 'purple.400' : 'whiteAlpha.100',
|
||||||
boxShadow: pageNum === currentPage ? '0 0 10px rgba(139, 92, 246, 0.3)' : 'none',
|
boxShadow: pageNum === currentPage ? '0 0 10px rgba(139, 92, 246, 0.4)' : 'none',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{pageNum}
|
{pageNum}
|
||||||
@@ -1676,17 +1708,17 @@ 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}
|
||||||
bgGradient="linear(to-r, purple.500, pink.500)"
|
bg="purple.500"
|
||||||
color="white"
|
color="white"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
_hover={{
|
_hover={{
|
||||||
bgGradient: 'linear(to-r, purple.600, pink.600)',
|
bg: 'purple.400',
|
||||||
boxShadow: '0 0 15px rgba(139, 92, 246, 0.4)',
|
boxShadow: '0 0 15px rgba(139, 92, 246, 0.5)',
|
||||||
}}
|
}}
|
||||||
_disabled={{
|
_disabled={{
|
||||||
bg: 'gray.200',
|
bg: 'whiteAlpha.100',
|
||||||
color: 'gray.400',
|
color: 'whiteAlpha.400',
|
||||||
cursor: 'not-allowed',
|
cursor: 'not-allowed',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -1698,10 +1730,10 @@ const ConceptCenter = () => {
|
|||||||
) : viewMode !== 'hierarchy' ? (
|
) : viewMode !== 'hierarchy' ? (
|
||||||
<Center h="400px">
|
<Center h="400px">
|
||||||
<VStack spacing={6}>
|
<VStack spacing={6}>
|
||||||
<Icon as={FaTags} boxSize={20} color="gray.300" />
|
<Icon as={FaTags} boxSize={20} color="whiteAlpha.300" />
|
||||||
<VStack spacing={2}>
|
<VStack spacing={2}>
|
||||||
<Text fontSize="xl" color="gray.600" fontWeight="medium">暂无概念数据</Text>
|
<Text fontSize="xl" color="white" fontWeight="medium">暂无概念数据</Text>
|
||||||
<Text color="gray.500">
|
<Text color="whiteAlpha.600">
|
||||||
{hierarchyFilter?.lv1
|
{hierarchyFilter?.lv1
|
||||||
? `「${[hierarchyFilter.lv1, hierarchyFilter.lv2, hierarchyFilter.lv3].filter(Boolean).join(' > ')}」分类下暂无数据`
|
? `「${[hierarchyFilter.lv1, hierarchyFilter.lv2, hierarchyFilter.lv3].filter(Boolean).join(' > ')}」分类下暂无数据`
|
||||||
: '请尝试其他搜索关键词或选择其他日期'
|
: '请尝试其他搜索关键词或选择其他日期'
|
||||||
@@ -1710,9 +1742,10 @@ const ConceptCenter = () => {
|
|||||||
{hierarchyFilter?.lv1 && (
|
{hierarchyFilter?.lv1 && (
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
colorScheme="purple"
|
bg="purple.500"
|
||||||
variant="outline"
|
color="white"
|
||||||
onClick={handleClearHierarchyFilter}
|
onClick={handleClearHierarchyFilter}
|
||||||
|
_hover={{ bg: 'purple.400' }}
|
||||||
>
|
>
|
||||||
清除筛选
|
清除筛选
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1730,27 +1763,36 @@ const ConceptCenter = () => {
|
|||||||
<ConceptStatsPanel
|
<ConceptStatsPanel
|
||||||
apiBaseUrl={API_BASE_URL}
|
apiBaseUrl={API_BASE_URL}
|
||||||
onConceptClick={handleConceptClick}
|
onConceptClick={handleConceptClick}
|
||||||
|
isDarkMode={true}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Card>
|
<Card
|
||||||
|
bg="rgba(15, 23, 42, 0.8)"
|
||||||
|
backdropFilter="blur(20px)"
|
||||||
|
border="1px solid"
|
||||||
|
borderColor="whiteAlpha.100"
|
||||||
|
borderRadius="2xl"
|
||||||
|
>
|
||||||
<CardBody p={6}>
|
<CardBody p={6}>
|
||||||
<VStack spacing={4} textAlign="center">
|
<VStack spacing={4} textAlign="center">
|
||||||
<Icon as={FaChartLine} boxSize={12} color="gray.300" />
|
<Icon as={FaChartLine} boxSize={12} color="whiteAlpha.300" />
|
||||||
<VStack spacing={2}>
|
<VStack spacing={2}>
|
||||||
<Heading size="md" color="gray.600">
|
<Heading size="md" color="white">
|
||||||
概念统计中心
|
概念统计中心
|
||||||
</Heading>
|
</Heading>
|
||||||
<Text fontSize="sm" color="gray.500">
|
<Text fontSize="sm" color="whiteAlpha.600">
|
||||||
此功能需要Pro版订阅才能使用
|
此功能需要Pro版订阅才能使用
|
||||||
</Text>
|
</Text>
|
||||||
</VStack>
|
</VStack>
|
||||||
<Button
|
<Button
|
||||||
colorScheme="blue"
|
bg="blue.500"
|
||||||
|
color="white"
|
||||||
leftIcon={<Icon as={FaRocket} />}
|
leftIcon={<Icon as={FaRocket} />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setUpgradeFeature('pro');
|
setUpgradeFeature('pro');
|
||||||
setUpgradeModalOpen(true);
|
setUpgradeModalOpen(true);
|
||||||
}}
|
}}
|
||||||
|
_hover={{ bg: 'blue.400', boxShadow: '0 0 15px rgba(59, 130, 246, 0.5)' }}
|
||||||
>
|
>
|
||||||
升级到Pro版
|
升级到Pro版
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user