fix(Navbar): 优化用户头像悬停交互和订阅信息显示
- 将 Tooltip 改为 Popover 组件,支持鼠标悬停到弹出内容上 - 用户现在可以正常悬停到"点击头像管理订阅"提示 - 订阅信息新增到期日期显示,用户无需自己计算到期时间 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,13 @@
|
|||||||
// 桌面版用户菜单 - 头像点击跳转到订阅页面
|
// 桌面版用户菜单 - 头像点击跳转到订阅页面
|
||||||
|
|
||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
import { Tooltip, useColorModeValue } from '@chakra-ui/react';
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverTrigger,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverArrow,
|
||||||
|
useColorModeValue
|
||||||
|
} from '@chakra-ui/react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import UserAvatar from './UserAvatar';
|
import UserAvatar from './UserAvatar';
|
||||||
import { TooltipContent } from '../../../Subscription/CrownTooltip';
|
import { TooltipContent } from '../../../Subscription/CrownTooltip';
|
||||||
@@ -19,25 +25,22 @@ const DesktopUserMenu = memo(({ user }) => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { subscriptionInfo } = useSubscription();
|
const { subscriptionInfo } = useSubscription();
|
||||||
|
|
||||||
const tooltipBg = useColorModeValue('white', 'gray.800');
|
const popoverBg = useColorModeValue('white', 'gray.800');
|
||||||
const tooltipBorderColor = useColorModeValue('gray.200', 'gray.600');
|
const popoverBorderColor = useColorModeValue('gray.200', 'gray.600');
|
||||||
|
|
||||||
const handleAvatarClick = () => {
|
const handleAvatarClick = () => {
|
||||||
navigate('/home/pages/account/subscription');
|
navigate('/home/pages/account/subscription');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Popover
|
||||||
label={<TooltipContent subscriptionInfo={subscriptionInfo} />}
|
trigger="hover"
|
||||||
placement="bottom"
|
placement="bottom-end"
|
||||||
hasArrow
|
openDelay={100}
|
||||||
bg={tooltipBg}
|
closeDelay={200}
|
||||||
borderRadius="lg"
|
gutter={8}
|
||||||
border="1px solid"
|
|
||||||
borderColor={tooltipBorderColor}
|
|
||||||
boxShadow="lg"
|
|
||||||
p={3}
|
|
||||||
>
|
>
|
||||||
|
<PopoverTrigger>
|
||||||
<span>
|
<span>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
user={user}
|
user={user}
|
||||||
@@ -45,7 +48,21 @@ const DesktopUserMenu = memo(({ user }) => {
|
|||||||
onClick={handleAvatarClick}
|
onClick={handleAvatarClick}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</PopoverTrigger>
|
||||||
|
<PopoverContent
|
||||||
|
bg={popoverBg}
|
||||||
|
borderRadius="lg"
|
||||||
|
border="1px solid"
|
||||||
|
borderColor={popoverBorderColor}
|
||||||
|
boxShadow="lg"
|
||||||
|
p={3}
|
||||||
|
w="auto"
|
||||||
|
_focus={{ outline: 'none' }}
|
||||||
|
>
|
||||||
|
<PopoverArrow bg={popoverBg} />
|
||||||
|
<TooltipContent subscriptionInfo={subscriptionInfo} />
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,23 @@ import PropTypes from 'prop-types';
|
|||||||
export const TooltipContent = ({ subscriptionInfo }) => {
|
export const TooltipContent = ({ subscriptionInfo }) => {
|
||||||
const tooltipText = useColorModeValue('gray.700', 'gray.100');
|
const tooltipText = useColorModeValue('gray.700', 'gray.100');
|
||||||
const dividerColor = useColorModeValue('gray.200', 'gray.600');
|
const dividerColor = useColorModeValue('gray.200', 'gray.600');
|
||||||
const { type, days_left, is_active } = subscriptionInfo;
|
const { type, days_left, is_active, end_date } = subscriptionInfo;
|
||||||
|
|
||||||
|
// 格式化到期日期
|
||||||
|
const formatEndDate = (dateStr) => {
|
||||||
|
if (!dateStr) return null;
|
||||||
|
try {
|
||||||
|
const date = new Date(dateStr);
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const formattedEndDate = formatEndDate(end_date);
|
||||||
|
|
||||||
// 基础版用户
|
// 基础版用户
|
||||||
if (type === 'free') {
|
if (type === 'free') {
|
||||||
@@ -72,7 +88,12 @@ export const TooltipContent = ({ subscriptionInfo }) => {
|
|||||||
还有 <Text as="span" fontWeight="600" color={isUrgent ? 'red.500' : isWarning ? 'orange.500' : tooltipText}>{days_left}</Text> 天到期
|
还有 <Text as="span" fontWeight="600" color={isUrgent ? 'red.500' : isWarning ? 'orange.500' : tooltipText}>{days_left}</Text> 天到期
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
<Text fontSize="xs" color={tooltipText} opacity={0.7} pl={6}>
|
{formattedEndDate && (
|
||||||
|
<Text fontSize="xs" color={tooltipText} opacity={0.8} pl={6}>
|
||||||
|
到期日:<Text as="span" fontWeight="500">{formattedEndDate}</Text>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
<Text fontSize="xs" color={tooltipText} opacity={0.6} pl={6}>
|
||||||
享受全部高级功能
|
享受全部高级功能
|
||||||
</Text>
|
</Text>
|
||||||
</VStack>
|
</VStack>
|
||||||
@@ -133,5 +154,6 @@ TooltipContent.propTypes = {
|
|||||||
type: PropTypes.oneOf(['free', 'pro', 'max']).isRequired,
|
type: PropTypes.oneOf(['free', 'pro', 'max']).isRequired,
|
||||||
days_left: PropTypes.number,
|
days_left: PropTypes.number,
|
||||||
is_active: PropTypes.bool,
|
is_active: PropTypes.bool,
|
||||||
|
end_date: PropTypes.string,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -620,13 +620,6 @@ export default function ProfilePage() {
|
|||||||
{user?.last_seen ? new Date(user.last_seen).toLocaleDateString() : '未知'}
|
{user?.last_seen ? new Date(user.last_seen).toLocaleDateString() : '未知'}
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
<HStack justify="space-between" w="full">
|
|
||||||
<Text fontSize="sm" color="gray.600">账户状态</Text>
|
|
||||||
<Badge colorScheme={user?.status === 'active' ? 'green' : 'gray'}>
|
|
||||||
{user?.status === 'active' ? '正常' : '未激活'}
|
|
||||||
</Badge>
|
|
||||||
</HStack>
|
|
||||||
</VStack>
|
</VStack>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Reference in New Issue
Block a user