feat: 导航UI调整
This commit is contained in:
@@ -43,7 +43,7 @@ import { logger } from '../../utils/logger';
|
|||||||
import { getApiBase } from '../../utils/apiConfig';
|
import { getApiBase } from '../../utils/apiConfig';
|
||||||
import SubscriptionButton from '../Subscription/SubscriptionButton';
|
import SubscriptionButton from '../Subscription/SubscriptionButton';
|
||||||
import SubscriptionModal from '../Subscription/SubscriptionModal';
|
import SubscriptionModal from '../Subscription/SubscriptionModal';
|
||||||
import CrownTooltip, { TooltipContent } from '../Subscription/CrownTooltip';
|
import { CrownIcon, TooltipContent } from '../Subscription/CrownTooltip';
|
||||||
|
|
||||||
/** 二级导航栏组件 - 显示当前一级菜单下的所有二级菜单项 */
|
/** 二级导航栏组件 - 显示当前一级菜单下的所有二级菜单项 */
|
||||||
const SecondaryNav = ({ showCompletenessAlert }) => {
|
const SecondaryNav = ({ showCompletenessAlert }) => {
|
||||||
@@ -186,6 +186,112 @@ const SecondaryNav = ({ showCompletenessAlert }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 中屏"更多"菜单 - 用于平板和小笔记本 */
|
||||||
|
const MoreNavMenu = ({ isAuthenticated, user }) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
// 辅助函数:判断导航项是否激活
|
||||||
|
const isActive = useCallback((paths) => {
|
||||||
|
return paths.some(path => location.pathname.includes(path));
|
||||||
|
}, [location.pathname]);
|
||||||
|
|
||||||
|
if (!isAuthenticated || !user) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu>
|
||||||
|
<MenuButton
|
||||||
|
as={Button}
|
||||||
|
variant="ghost"
|
||||||
|
rightIcon={<ChevronDownIcon />}
|
||||||
|
fontWeight="medium"
|
||||||
|
>
|
||||||
|
更多
|
||||||
|
</MenuButton>
|
||||||
|
<MenuList minW="300px" p={2}>
|
||||||
|
{/* 高频跟踪组 */}
|
||||||
|
<Text fontSize="xs" fontWeight="bold" px={3} py={2} color="gray.500">高频跟踪</Text>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => navigate('/community')}
|
||||||
|
borderRadius="md"
|
||||||
|
bg={location.pathname.includes('/community') ? 'blue.50' : 'transparent'}
|
||||||
|
>
|
||||||
|
<Flex justify="space-between" align="center" w="100%">
|
||||||
|
<Text fontSize="sm">新闻催化分析</Text>
|
||||||
|
<HStack spacing={1}>
|
||||||
|
<Badge size="sm" colorScheme="green">HOT</Badge>
|
||||||
|
<Badge size="sm" colorScheme="red">NEW</Badge>
|
||||||
|
</HStack>
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => navigate('/concepts')}
|
||||||
|
borderRadius="md"
|
||||||
|
bg={location.pathname.includes('/concepts') ? 'blue.50' : 'transparent'}
|
||||||
|
>
|
||||||
|
<Flex justify="space-between" align="center" w="100%">
|
||||||
|
<Text fontSize="sm">概念中心</Text>
|
||||||
|
<Badge size="sm" colorScheme="red">NEW</Badge>
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuDivider />
|
||||||
|
|
||||||
|
{/* 行情复盘组 */}
|
||||||
|
<Text fontSize="xs" fontWeight="bold" px={3} py={2} color="gray.500">行情复盘</Text>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => navigate('/limit-analyse')}
|
||||||
|
borderRadius="md"
|
||||||
|
bg={location.pathname.includes('/limit-analyse') ? 'blue.50' : 'transparent'}
|
||||||
|
>
|
||||||
|
<Flex justify="space-between" align="center" w="100%">
|
||||||
|
<Text fontSize="sm">涨停分析</Text>
|
||||||
|
<Badge size="sm" colorScheme="blue">FREE</Badge>
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => navigate('/stocks')}
|
||||||
|
borderRadius="md"
|
||||||
|
bg={location.pathname.includes('/stocks') ? 'blue.50' : 'transparent'}
|
||||||
|
>
|
||||||
|
<Flex justify="space-between" align="center" w="100%">
|
||||||
|
<Text fontSize="sm">个股中心</Text>
|
||||||
|
<Badge size="sm" colorScheme="green">HOT</Badge>
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => navigate('/trading-simulation')}
|
||||||
|
borderRadius="md"
|
||||||
|
bg={location.pathname.includes('/trading-simulation') ? 'blue.50' : 'transparent'}
|
||||||
|
>
|
||||||
|
<Flex justify="space-between" align="center" w="100%">
|
||||||
|
<Text fontSize="sm">模拟盘</Text>
|
||||||
|
<Badge size="sm" colorScheme="red">NEW</Badge>
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuDivider />
|
||||||
|
|
||||||
|
{/* AGENT社群组 */}
|
||||||
|
<Text fontSize="xs" fontWeight="bold" px={3} py={2} color="gray.500">AGENT社群</Text>
|
||||||
|
<MenuItem isDisabled cursor="not-allowed" color="gray.400">
|
||||||
|
<Text fontSize="sm" color="gray.400">今日热议</Text>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem isDisabled cursor="not-allowed" color="gray.400">
|
||||||
|
<Text fontSize="sm" color="gray.400">个股社区</Text>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuDivider />
|
||||||
|
|
||||||
|
{/* 联系我们 */}
|
||||||
|
<MenuItem isDisabled cursor="not-allowed" color="gray.400">
|
||||||
|
<Text fontSize="sm" color="gray.400">联系我们</Text>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/** 桌面端导航 - 完全按照原网站
|
/** 桌面端导航 - 完全按照原网站
|
||||||
* @TODO 添加逻辑 不展示导航case
|
* @TODO 添加逻辑 不展示导航case
|
||||||
* 1.未登陆状态 && 是首页
|
* 1.未登陆状态 && 是首页
|
||||||
@@ -360,6 +466,8 @@ export default function HomeNavbar() {
|
|||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isMobile = useBreakpointValue({ base: true, md: false });
|
const isMobile = useBreakpointValue({ base: true, md: false });
|
||||||
|
const isTablet = useBreakpointValue({ base: false, md: true, lg: false });
|
||||||
|
const isDesktop = useBreakpointValue({ base: false, md: false, lg: true });
|
||||||
const { user, isAuthenticated, logout, isLoading } = useAuth();
|
const { user, isAuthenticated, logout, isLoading } = useAuth();
|
||||||
const { openAuthModal } = useAuthModal();
|
const { openAuthModal } = useAuthModal();
|
||||||
const { colorMode, toggleColorMode } = useColorMode();
|
const { colorMode, toggleColorMode } = useColorMode();
|
||||||
@@ -746,15 +854,22 @@ export default function HomeNavbar() {
|
|||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
{/* 移动端菜单按钮 */}
|
{/* 中间导航区域 - 响应式 */}
|
||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
|
// 移动端:汉堡菜单
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<HamburgerIcon />}
|
icon={<HamburgerIcon />}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={onOpen}
|
onClick={onOpen}
|
||||||
aria-label="Open menu"
|
aria-label="Open menu"
|
||||||
/>
|
/>
|
||||||
) : <NavItems isAuthenticated={isAuthenticated} user={user} />}
|
) : isTablet ? (
|
||||||
|
// 中屏(平板):"更多"下拉菜单
|
||||||
|
<MoreNavMenu isAuthenticated={isAuthenticated} user={user} />
|
||||||
|
) : (
|
||||||
|
// 大屏(桌面):完整导航菜单
|
||||||
|
<NavItems isAuthenticated={isAuthenticated} user={user} />
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 右侧:日夜模式切换 + 登录/用户区 */}
|
{/* 右侧:日夜模式切换 + 登录/用户区 */}
|
||||||
<HStack spacing={{ base: 2, md: 4 }}>
|
<HStack spacing={{ base: 2, md: 4 }}>
|
||||||
@@ -774,8 +889,8 @@ export default function HomeNavbar() {
|
|||||||
) : isAuthenticated && user ? (
|
) : isAuthenticated && user ? (
|
||||||
// 已登录状态 - 用户菜单 + 功能菜单排列
|
// 已登录状态 - 用户菜单 + 功能菜单排列
|
||||||
<HStack spacing={{ base: 2, md: 3 }}>
|
<HStack spacing={{ base: 2, md: 3 }}>
|
||||||
{/* 自选股 - 移动端隐藏 */}
|
{/* 自选股 - 仅大屏显示 */}
|
||||||
{!isMobile && (
|
{isDesktop && (
|
||||||
<Menu onOpen={loadWatchlistQuotes}>
|
<Menu onOpen={loadWatchlistQuotes}>
|
||||||
<MenuButton
|
<MenuButton
|
||||||
as={Button}
|
as={Button}
|
||||||
@@ -852,8 +967,8 @@ export default function HomeNavbar() {
|
|||||||
</Menu>
|
</Menu>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 关注的事件 - 头像右侧 - 移动端隐藏 */}
|
{/* 关注的事件 - 仅大屏显示 */}
|
||||||
{!isMobile && (
|
{isDesktop && (
|
||||||
<Menu onOpen={loadFollowingEvents}>
|
<Menu onOpen={loadFollowingEvents}>
|
||||||
<MenuButton
|
<MenuButton
|
||||||
as={Button}
|
as={Button}
|
||||||
@@ -936,16 +1051,10 @@ export default function HomeNavbar() {
|
|||||||
</Menu>
|
</Menu>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 带会员标识的头像 - 点击打开订阅弹窗 */}
|
{/* 头像区域 - 响应式 */}
|
||||||
<Box
|
{isDesktop ? (
|
||||||
position="relative"
|
// 大屏:头像点击打开订阅弹窗
|
||||||
cursor="pointer"
|
<>
|
||||||
onClick={() => setIsSubscriptionModalOpen(true)}
|
|
||||||
>
|
|
||||||
{/* 会员图标徽章 - 使用独立的 CrownTooltip 组件 */}
|
|
||||||
<CrownTooltip subscriptionInfo={subscriptionInfo} />
|
|
||||||
|
|
||||||
{/* 头像 - 带会员等级边框和详细信息 Tooltip */}
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
label={<TooltipContent subscriptionInfo={subscriptionInfo} />}
|
label={<TooltipContent subscriptionInfo={subscriptionInfo} />}
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
@@ -957,6 +1066,12 @@ export default function HomeNavbar() {
|
|||||||
boxShadow="lg"
|
boxShadow="lg"
|
||||||
p={3}
|
p={3}
|
||||||
>
|
>
|
||||||
|
<Box
|
||||||
|
position="relative"
|
||||||
|
cursor="pointer"
|
||||||
|
onClick={() => setIsSubscriptionModalOpen(true)}
|
||||||
|
>
|
||||||
|
<CrownIcon subscriptionInfo={subscriptionInfo} />
|
||||||
<Avatar
|
<Avatar
|
||||||
size="sm"
|
size="sm"
|
||||||
name={getDisplayName()}
|
name={getDisplayName()}
|
||||||
@@ -975,10 +1090,61 @@ export default function HomeNavbar() {
|
|||||||
}}
|
}}
|
||||||
transition="all 0.2s"
|
transition="all 0.2s"
|
||||||
/>
|
/>
|
||||||
|
</Box>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
{isSubscriptionModalOpen && (
|
||||||
|
<SubscriptionModal
|
||||||
|
isOpen={isSubscriptionModalOpen}
|
||||||
|
onClose={() => setIsSubscriptionModalOpen(false)}
|
||||||
|
subscriptionInfo={subscriptionInfo}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
// 中屏:头像作为下拉菜单,包含所有功能
|
||||||
|
<Menu>
|
||||||
|
<MenuButton>
|
||||||
|
<Box position="relative">
|
||||||
|
<CrownIcon subscriptionInfo={subscriptionInfo} />
|
||||||
|
<Avatar
|
||||||
|
size="sm"
|
||||||
|
name={getDisplayName()}
|
||||||
|
src={user.avatar_url}
|
||||||
|
bg="blue.500"
|
||||||
|
border={subscriptionInfo.type !== 'free' ? '2.5px solid' : 'none'}
|
||||||
|
borderColor={
|
||||||
|
subscriptionInfo.type === 'max' ? '#667eea' :
|
||||||
|
subscriptionInfo.type === 'pro' ? '#667eea' : 'transparent'
|
||||||
|
}
|
||||||
|
_hover={{ transform: 'scale(1.05)' }}
|
||||||
|
transition="all 0.2s"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</MenuButton>
|
||||||
|
<MenuList minW="320px">
|
||||||
|
{/* 用户信息区 */}
|
||||||
|
<Box px={3} py={2} borderBottom="1px" borderColor={useColorModeValue('gray.200', 'gray.600')}>
|
||||||
|
<Text fontSize="sm" fontWeight="bold">{getDisplayName()}</Text>
|
||||||
|
<Text fontSize="xs" color="gray.500">{user.email}</Text>
|
||||||
|
{user.phone && (
|
||||||
|
<Text fontSize="xs" color="gray.500">{user.phone}</Text>
|
||||||
|
)}
|
||||||
|
{user.has_wechat && (
|
||||||
|
<Badge size="sm" colorScheme="green" mt={1}>微信已绑定</Badge>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* 订阅管理弹窗 - 只在打开时渲染 */}
|
{/* 订阅管理 */}
|
||||||
|
<MenuItem icon={<FaCrown />} onClick={() => setIsSubscriptionModalOpen(true)}>
|
||||||
|
<Flex justify="space-between" align="center" w="100%">
|
||||||
|
<Text>订阅管理</Text>
|
||||||
|
<Badge colorScheme={subscriptionInfo.type === 'free' ? 'gray' : 'purple'}>
|
||||||
|
{subscriptionInfo.type === 'max' ? 'MAX' :
|
||||||
|
subscriptionInfo.type === 'pro' ? 'PRO' : '免费版'}
|
||||||
|
</Badge>
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
{isSubscriptionModalOpen && (
|
{isSubscriptionModalOpen && (
|
||||||
<SubscriptionModal
|
<SubscriptionModal
|
||||||
isOpen={isSubscriptionModalOpen}
|
isOpen={isSubscriptionModalOpen}
|
||||||
@@ -987,7 +1153,53 @@ export default function HomeNavbar() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 个人中心下拉菜单 */}
|
<MenuDivider />
|
||||||
|
|
||||||
|
{/* 自选股 */}
|
||||||
|
<MenuItem icon={<FiStar />} onClick={() => navigate('/home/center')}>
|
||||||
|
<Flex justify="space-between" align="center" w="100%">
|
||||||
|
<Text>我的自选股</Text>
|
||||||
|
{watchlistQuotes && watchlistQuotes.length > 0 && (
|
||||||
|
<Badge>{watchlistQuotes.length}</Badge>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
{/* 自选事件 */}
|
||||||
|
<MenuItem icon={<FiCalendar />} onClick={() => navigate('/home/center')}>
|
||||||
|
<Flex justify="space-between" align="center" w="100%">
|
||||||
|
<Text>我的自选事件</Text>
|
||||||
|
{followingEvents && followingEvents.length > 0 && (
|
||||||
|
<Badge>{followingEvents.length}</Badge>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuDivider />
|
||||||
|
|
||||||
|
{/* 个人中心 */}
|
||||||
|
<MenuItem icon={<FiHome />} onClick={() => navigate('/home/center')}>
|
||||||
|
个人中心
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem icon={<FiUser />} onClick={() => navigate('/home/profile')}>
|
||||||
|
个人资料
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem icon={<FiSettings />} onClick={() => navigate('/home/settings')}>
|
||||||
|
账户设置
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuDivider />
|
||||||
|
|
||||||
|
{/* 退出登录 */}
|
||||||
|
<MenuItem icon={<FiLogOut />} onClick={handleLogout} color="red.500">
|
||||||
|
退出登录
|
||||||
|
</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</Menu>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 个人中心下拉菜单 - 仅大屏显示 */}
|
||||||
|
{isDesktop && (
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuButton
|
<MenuButton
|
||||||
as={Button}
|
as={Button}
|
||||||
@@ -1033,6 +1245,7 @@ export default function HomeNavbar() {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuList>
|
</MenuList>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
)}
|
||||||
</HStack>
|
</HStack>
|
||||||
) : (
|
) : (
|
||||||
// 未登录状态 - 单一按钮
|
// 未登录状态 - 单一按钮
|
||||||
|
|||||||
137
src/components/Subscription/CrownTooltip.js
Normal file
137
src/components/Subscription/CrownTooltip.js
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
// src/components/Subscription/CrownTooltip.js
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
VStack,
|
||||||
|
HStack,
|
||||||
|
Text,
|
||||||
|
Divider,
|
||||||
|
useColorModeValue
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tooltip 内容组件 - 显示详细的会员信息
|
||||||
|
* 导出此组件供头像也使用相同的 Tooltip 内容
|
||||||
|
*/
|
||||||
|
export const TooltipContent = ({ subscriptionInfo }) => {
|
||||||
|
const tooltipText = useColorModeValue('gray.700', 'gray.100');
|
||||||
|
const dividerColor = useColorModeValue('gray.200', 'gray.600');
|
||||||
|
const { type, days_left, is_active } = subscriptionInfo;
|
||||||
|
|
||||||
|
// 基础版用户
|
||||||
|
if (type === 'free') {
|
||||||
|
return (
|
||||||
|
<VStack spacing={2} align="stretch" minW="200px">
|
||||||
|
<Text fontSize="md" fontWeight="bold" color={tooltipText}>
|
||||||
|
✨ 基础版用户
|
||||||
|
</Text>
|
||||||
|
<Divider borderColor={dividerColor} />
|
||||||
|
<Text fontSize="sm" color={tooltipText} opacity={0.8}>
|
||||||
|
解锁更多高级功能
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="xs" color={tooltipText} opacity={0.6} textAlign="center" mt={1}>
|
||||||
|
点击头像升级会员
|
||||||
|
</Text>
|
||||||
|
</VStack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 付费用户
|
||||||
|
const isExpired = !is_active;
|
||||||
|
const isUrgent = days_left < 7;
|
||||||
|
const isWarning = days_left < 30;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<VStack spacing={2} align="stretch" minW="220px">
|
||||||
|
<HStack justify="space-between">
|
||||||
|
<Text fontSize="md" fontWeight="bold" color={tooltipText}>
|
||||||
|
{type === 'pro' ? '💎 Pro 会员' : '👑 Max 会员'}
|
||||||
|
</Text>
|
||||||
|
{isExpired && <Text fontSize="xs" color="red.500">已过期</Text>}
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
<Divider borderColor={dividerColor} />
|
||||||
|
|
||||||
|
{/* 状态信息 */}
|
||||||
|
{isExpired ? (
|
||||||
|
<HStack spacing={2}>
|
||||||
|
<Text fontSize="sm" color="red.500">❌</Text>
|
||||||
|
<Text fontSize="sm" color={tooltipText}>
|
||||||
|
会员已过期,续费恢复权益
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
) : (
|
||||||
|
<VStack spacing={1} align="stretch">
|
||||||
|
<HStack spacing={2}>
|
||||||
|
<Text fontSize="sm">
|
||||||
|
{isUrgent ? '⚠️' : isWarning ? '⏰' : '📅'}
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="sm" color={tooltipText}>
|
||||||
|
{isUrgent && <Text as="span" color="red.500" fontWeight="600">紧急! </Text>}
|
||||||
|
还有 <Text as="span" fontWeight="600" color={isUrgent ? 'red.500' : isWarning ? 'orange.500' : tooltipText}>{days_left}</Text> 天到期
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
<Text fontSize="xs" color={tooltipText} opacity={0.7} pl={6}>
|
||||||
|
享受全部高级功能
|
||||||
|
</Text>
|
||||||
|
</VStack>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 操作提示 */}
|
||||||
|
<Text fontSize="xs" color={tooltipText} opacity={0.6} textAlign="center" mt={1}>
|
||||||
|
{isExpired || isUrgent ? '点击头像立即续费' : '点击头像管理订阅'}
|
||||||
|
</Text>
|
||||||
|
</VStack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 皇冠图标组件 - 显示在头像左上角的会员标识(纯图标,无 Tooltip)
|
||||||
|
* Tooltip 由外层统一包裹
|
||||||
|
*
|
||||||
|
* @param {Object} subscriptionInfo - 订阅信息
|
||||||
|
* @param {string} subscriptionInfo.type - 订阅类型: 'free' | 'pro' | 'max'
|
||||||
|
*/
|
||||||
|
export function CrownIcon({ subscriptionInfo }) {
|
||||||
|
// 基础版用户不显示皇冠
|
||||||
|
if (subscriptionInfo.type === 'free') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
top="-8px"
|
||||||
|
left="-8px"
|
||||||
|
zIndex={2}
|
||||||
|
display="flex"
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
w="24px"
|
||||||
|
h="24px"
|
||||||
|
_hover={{
|
||||||
|
transform: 'scale(1.2)',
|
||||||
|
}}
|
||||||
|
transition="all 0.3s ease"
|
||||||
|
>
|
||||||
|
<Text fontSize="20px" filter="drop-shadow(0 2px 4px rgba(0,0,0,0.3))">
|
||||||
|
{subscriptionInfo.type === 'max' ? '👑' : '💎'}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
CrownIcon.propTypes = {
|
||||||
|
subscriptionInfo: PropTypes.shape({
|
||||||
|
type: PropTypes.oneOf(['free', 'pro', 'max']).isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
TooltipContent.propTypes = {
|
||||||
|
subscriptionInfo: PropTypes.shape({
|
||||||
|
type: PropTypes.oneOf(['free', 'pro', 'max']).isRequired,
|
||||||
|
days_left: PropTypes.number,
|
||||||
|
is_active: PropTypes.bool,
|
||||||
|
}).isRequired,
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user