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 (
-
+