diff --git a/src/components/Navbars/components/UserMenu/DesktopUserMenu.js b/src/components/Navbars/components/UserMenu/DesktopUserMenu.js index ffd98434..7c9c1aee 100644 --- a/src/components/Navbars/components/UserMenu/DesktopUserMenu.js +++ b/src/components/Navbars/components/UserMenu/DesktopUserMenu.js @@ -5,40 +5,9 @@ import React, { memo } from 'react'; import { Tooltip, useColorModeValue } from '@chakra-ui/react'; import UserAvatar from './UserAvatar'; import SubscriptionModal from '../../../Subscription/SubscriptionModal'; +import { TooltipContent } from '../../../Subscription/CrownTooltip'; import { useSubscription } from '../../../../hooks/useSubscription'; -/** - * Tooltip 内容组件 - * 显示用户订阅信息和剩余天数 - */ -const TooltipContent = memo(({ subscriptionInfo }) => { - const getSubscriptionBadgeText = () => { - if (!subscriptionInfo || !subscriptionInfo.type) { - return '免费版'; - } - - const type = subscriptionInfo.type.toLowerCase(); - - switch (type) { - case 'max': - return subscriptionInfo.is_active - ? `Max版 (剩余 ${subscriptionInfo.days_left || 0} 天)` - : 'Max版 (已过期)'; - case 'pro': - return subscriptionInfo.is_active - ? `Pro版 (剩余 ${subscriptionInfo.days_left || 0} 天)` - : 'Pro版 (已过期)'; - case 'free': - default: - return '免费版 (点击升级)'; - } - }; - - return getSubscriptionBadgeText(); -}); - -TooltipContent.displayName = 'TooltipContent'; - /** * 桌面版用户菜单组件 * 大屏幕 (md+) 显示,头像点击打开订阅弹窗 @@ -70,11 +39,13 @@ const DesktopUserMenu = memo(({ user }) => { boxShadow="lg" p={3} > - + + + {isSubscriptionModalOpen && ( diff --git a/src/components/Navbars/components/UserMenu/UserAvatar.js b/src/components/Navbars/components/UserMenu/UserAvatar.js index 45338ea3..0ac08e3d 100644 --- a/src/components/Navbars/components/UserMenu/UserAvatar.js +++ b/src/components/Navbars/components/UserMenu/UserAvatar.js @@ -1,41 +1,9 @@ // src/components/Navbars/components/UserMenu/UserAvatar.js // 用户头像组件 - 带皇冠图标和订阅边框 -import React, { memo } from 'react'; +import React, { memo, forwardRef } from 'react'; import { Box, Avatar } from '@chakra-ui/react'; -import { FaCrown } from 'react-icons/fa'; - -/** - * 皇冠图标组件 - * @param {Object} props.subscriptionInfo - 订阅信息 - */ -const CrownIcon = memo(({ subscriptionInfo }) => { - if (!subscriptionInfo || subscriptionInfo.type === 'free') { - return null; - } - - const crownColor = subscriptionInfo.type === 'max' - ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' - : '#667eea'; - - return ( - - - - ); -}); - -CrownIcon.displayName = 'CrownIcon'; +import { CrownIcon } from '../../../Subscription/CrownTooltip'; /** * 用户头像组件 @@ -47,14 +15,15 @@ CrownIcon.displayName = 'CrownIcon'; * @param {string} props.size - 头像大小 (默认 'sm') * @param {Function} props.onClick - 点击回调 * @param {Object} props.hoverStyle - 悬停样式 + * @param {React.Ref} ref - 用于 Tooltip 和 MenuButton 的 ref */ -const UserAvatar = memo(({ +const UserAvatar = forwardRef(({ user, subscriptionInfo, size = 'sm', onClick, hoverStyle = {} -}) => { +}, ref) => { // 获取显示名称 const getDisplayName = () => { if (user.nickname) return user.nickname; @@ -71,7 +40,7 @@ const UserAvatar = memo(({ return 'transparent'; }; - // 默认悬停样式 + // 默认悬停样式 - 头像始终可交互(在 Tooltip 或 MenuButton 中) const defaultHoverStyle = { transform: 'scale(1.05)', boxShadow: subscriptionInfo.type !== 'free' @@ -80,7 +49,12 @@ const UserAvatar = memo(({ }; return ( - +