340 lines
16 KiB
JavaScript
340 lines
16 KiB
JavaScript
// src/components/Navbars/components/MobileDrawer/MobileDrawer.js
|
|
// 移动端抽屉菜单组件
|
|
|
|
import React, { memo } from 'react';
|
|
import {
|
|
Drawer,
|
|
DrawerOverlay,
|
|
DrawerContent,
|
|
DrawerCloseButton,
|
|
DrawerHeader,
|
|
DrawerBody,
|
|
VStack,
|
|
HStack,
|
|
Box,
|
|
Text,
|
|
Button,
|
|
Badge,
|
|
Link,
|
|
Divider,
|
|
Avatar,
|
|
useColorMode,
|
|
useColorModeValue
|
|
} from '@chakra-ui/react';
|
|
import { SunIcon, MoonIcon } from '@chakra-ui/icons';
|
|
import { useNavigate, useLocation } from 'react-router-dom';
|
|
|
|
/**
|
|
* 移动端抽屉菜单组件
|
|
* 包含完整的导航菜单和用户功能
|
|
*
|
|
* @param {Object} props
|
|
* @param {boolean} props.isOpen - Drawer 是否打开
|
|
* @param {Function} props.onClose - 关闭 Drawer 的回调
|
|
* @param {boolean} props.isAuthenticated - 用户是否已登录
|
|
* @param {Object} props.user - 用户信息
|
|
* @param {Function} props.handleLogout - 退出登录回调
|
|
* @param {Function} props.openAuthModal - 打开登录弹窗回调
|
|
*/
|
|
const MobileDrawer = memo(({
|
|
isOpen,
|
|
onClose,
|
|
isAuthenticated,
|
|
user,
|
|
handleLogout,
|
|
openAuthModal
|
|
}) => {
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
const { colorMode, toggleColorMode } = useColorMode();
|
|
const userBgColor = useColorModeValue('gray.50', 'whiteAlpha.100');
|
|
const contactTextColor = useColorModeValue('gray.500', 'gray.300');
|
|
const emailTextColor = useColorModeValue('gray.500', 'gray.300');
|
|
|
|
// 获取显示名称
|
|
const getDisplayName = () => {
|
|
if (!user) return '用户';
|
|
if (user.nickname) return user.nickname;
|
|
if (user.username) return user.username;
|
|
if (user.email) return user.email.split('@')[0];
|
|
if (user.phone) return user.phone;
|
|
return '用户';
|
|
};
|
|
|
|
// 导航点击处理
|
|
const handleNavigate = (path) => {
|
|
navigate(path);
|
|
onClose();
|
|
};
|
|
|
|
return (
|
|
<Drawer isOpen={isOpen} placement="right" onClose={onClose}>
|
|
<DrawerOverlay />
|
|
<DrawerContent>
|
|
<DrawerCloseButton />
|
|
<DrawerHeader>
|
|
<HStack>
|
|
<Text>菜单</Text>
|
|
{isAuthenticated && user && (
|
|
<Badge colorScheme="green" ml={2}>已登录</Badge>
|
|
)}
|
|
</HStack>
|
|
</DrawerHeader>
|
|
<DrawerBody>
|
|
<VStack spacing={4} align="stretch">
|
|
{/* 移动端:日夜模式切换 */}
|
|
<Button
|
|
leftIcon={colorMode === 'light' ? <MoonIcon /> : <SunIcon />}
|
|
variant="ghost"
|
|
justifyContent="flex-start"
|
|
onClick={toggleColorMode}
|
|
size="sm"
|
|
>
|
|
切换到{colorMode === 'light' ? '深色' : '浅色'}模式
|
|
</Button>
|
|
|
|
{/* 移动端用户信息 */}
|
|
{isAuthenticated && user && (
|
|
<>
|
|
<Box p={3} bg={userBgColor} borderRadius="md">
|
|
<HStack>
|
|
<Avatar
|
|
size="sm"
|
|
name={getDisplayName()}
|
|
src={user.avatar_url}
|
|
bg="blue.500"
|
|
/>
|
|
<Box>
|
|
<Text fontSize="sm" fontWeight="bold">{getDisplayName()}</Text>
|
|
<Text fontSize="xs" color={emailTextColor}>{user.email}</Text>
|
|
</Box>
|
|
</HStack>
|
|
</Box>
|
|
<Divider />
|
|
</>
|
|
)}
|
|
|
|
{/* 首页链接 */}
|
|
<Link
|
|
onClick={() => handleNavigate('/home')}
|
|
py={2}
|
|
px={3}
|
|
borderRadius="md"
|
|
_hover={{ bg: 'gray.100' }}
|
|
cursor="pointer"
|
|
color="blue.500"
|
|
fontWeight="bold"
|
|
bg={location.pathname === '/home' ? 'blue.50' : 'transparent'}
|
|
borderLeft={location.pathname === '/home' ? '3px solid' : 'none'}
|
|
borderColor="blue.600"
|
|
>
|
|
<Text fontSize="md">🏠 首页</Text>
|
|
</Link>
|
|
|
|
<Divider />
|
|
|
|
{/* 高频跟踪 */}
|
|
<Box>
|
|
<Text fontWeight="bold" mb={2}>高频跟踪</Text>
|
|
<VStack spacing={2} align="stretch">
|
|
<Link
|
|
onClick={() => handleNavigate('/community')}
|
|
py={1}
|
|
px={3}
|
|
borderRadius="md"
|
|
_hover={{ bg: 'gray.100' }}
|
|
cursor="pointer"
|
|
bg={location.pathname.includes('/community') ? 'blue.50' : 'transparent'}
|
|
borderLeft={location.pathname.includes('/community') ? '3px solid' : 'none'}
|
|
borderColor="blue.600"
|
|
fontWeight={location.pathname.includes('/community') ? 'bold' : 'normal'}
|
|
>
|
|
<HStack justify="space-between">
|
|
<Text fontSize="sm">事件中心</Text>
|
|
<HStack spacing={1}>
|
|
<Badge size="xs" colorScheme="green">HOT</Badge>
|
|
<Badge size="xs" colorScheme="red">NEW</Badge>
|
|
</HStack>
|
|
</HStack>
|
|
</Link>
|
|
<Link
|
|
onClick={() => handleNavigate('/concepts')}
|
|
py={1}
|
|
px={3}
|
|
borderRadius="md"
|
|
_hover={{ bg: 'gray.100' }}
|
|
cursor="pointer"
|
|
bg={location.pathname.includes('/concepts') ? 'blue.50' : 'transparent'}
|
|
borderLeft={location.pathname.includes('/concepts') ? '3px solid' : 'none'}
|
|
borderColor="blue.600"
|
|
fontWeight={location.pathname.includes('/concepts') ? 'bold' : 'normal'}
|
|
>
|
|
<HStack justify="space-between">
|
|
<Text fontSize="sm">概念中心</Text>
|
|
<Badge size="xs" colorScheme="red">NEW</Badge>
|
|
</HStack>
|
|
</Link>
|
|
</VStack>
|
|
</Box>
|
|
|
|
<Divider />
|
|
|
|
{/* 行情复盘 */}
|
|
<Box>
|
|
<Text fontWeight="bold" mb={2}>行情复盘</Text>
|
|
<VStack spacing={2} align="stretch">
|
|
<Link
|
|
onClick={() => handleNavigate('/limit-analyse')}
|
|
py={1}
|
|
px={3}
|
|
borderRadius="md"
|
|
_hover={{ bg: 'gray.100' }}
|
|
cursor="pointer"
|
|
bg={location.pathname.includes('/limit-analyse') ? 'blue.50' : 'transparent'}
|
|
borderLeft={location.pathname.includes('/limit-analyse') ? '3px solid' : 'none'}
|
|
borderColor="blue.600"
|
|
fontWeight={location.pathname.includes('/limit-analyse') ? 'bold' : 'normal'}
|
|
>
|
|
<HStack justify="space-between">
|
|
<Text fontSize="sm">涨停分析</Text>
|
|
<Badge size="xs" colorScheme="blue">FREE</Badge>
|
|
</HStack>
|
|
</Link>
|
|
<Link
|
|
onClick={() => handleNavigate('/stocks')}
|
|
py={1}
|
|
px={3}
|
|
borderRadius="md"
|
|
_hover={{ bg: 'gray.100' }}
|
|
cursor="pointer"
|
|
bg={location.pathname.includes('/stocks') ? 'blue.50' : 'transparent'}
|
|
borderLeft={location.pathname.includes('/stocks') ? '3px solid' : 'none'}
|
|
borderColor="blue.600"
|
|
fontWeight={location.pathname.includes('/stocks') ? 'bold' : 'normal'}
|
|
>
|
|
<HStack justify="space-between">
|
|
<Text fontSize="sm">个股中心</Text>
|
|
<Badge size="xs" colorScheme="green">HOT</Badge>
|
|
</HStack>
|
|
</Link>
|
|
<Link
|
|
onClick={() => handleNavigate('/trading-simulation')}
|
|
py={1}
|
|
px={3}
|
|
borderRadius="md"
|
|
_hover={{ bg: 'gray.100' }}
|
|
cursor="pointer"
|
|
bg={location.pathname.includes('/trading-simulation') ? 'blue.50' : 'transparent'}
|
|
borderLeft={location.pathname.includes('/trading-simulation') ? '3px solid' : 'none'}
|
|
borderColor="blue.600"
|
|
fontWeight={location.pathname.includes('/trading-simulation') ? 'bold' : 'normal'}
|
|
>
|
|
<HStack justify="space-between">
|
|
<Text fontSize="sm">模拟盘</Text>
|
|
<Badge size="xs" colorScheme="red">NEW</Badge>
|
|
</HStack>
|
|
</Link>
|
|
</VStack>
|
|
</Box>
|
|
|
|
<Divider />
|
|
|
|
{/* AGENT社群 */}
|
|
<Box>
|
|
<Text fontWeight="bold" mb={2}>AGENT社群</Text>
|
|
<VStack spacing={2} align="stretch">
|
|
<Link
|
|
onClick={() => handleNavigate('/agent-chat')}
|
|
py={1}
|
|
px={3}
|
|
borderRadius="md"
|
|
_hover={{ bg: 'gray.100' }}
|
|
cursor="pointer"
|
|
bg={location.pathname.includes('/agent-chat') ? 'blue.50' : 'transparent'}
|
|
borderLeft={location.pathname.includes('/agent-chat') ? '3px solid' : 'none'}
|
|
borderColor="blue.600"
|
|
fontWeight={location.pathname.includes('/agent-chat') ? 'bold' : 'normal'}
|
|
>
|
|
<HStack justify="space-between">
|
|
<Text fontSize="sm">AI聊天助手</Text>
|
|
<HStack spacing={1}>
|
|
<Badge size="xs" colorScheme="green">AI</Badge>
|
|
<Badge size="xs" colorScheme="red">NEW</Badge>
|
|
</HStack>
|
|
</HStack>
|
|
</Link>
|
|
<Link
|
|
onClick={() => handleNavigate('/value-forum')}
|
|
py={1}
|
|
px={3}
|
|
borderRadius="md"
|
|
_hover={{ bg: 'gray.50' }}
|
|
bg={location.pathname.includes('/value-forum') ? 'blue.50' : 'transparent'}
|
|
>
|
|
<HStack justify="space-between">
|
|
<Text fontSize="sm">价值论坛</Text>
|
|
<HStack spacing={1}>
|
|
<Badge size="xs" colorScheme="yellow">黑金</Badge>
|
|
<Badge size="xs" colorScheme="red">NEW</Badge>
|
|
</HStack>
|
|
</HStack>
|
|
</Link>
|
|
<Link
|
|
py={1}
|
|
px={3}
|
|
borderRadius="md"
|
|
_hover={{}}
|
|
cursor="not-allowed"
|
|
color="gray.400"
|
|
pointerEvents="none"
|
|
>
|
|
<Text fontSize="sm" color="gray.400">个股社区</Text>
|
|
</Link>
|
|
</VStack>
|
|
</Box>
|
|
|
|
<Divider />
|
|
|
|
{/* 联系我们 */}
|
|
<Box>
|
|
<Text fontWeight="bold" mb={2}>联系我们</Text>
|
|
<Text fontSize="sm" color={contactTextColor}>敬请期待</Text>
|
|
</Box>
|
|
|
|
{/* 移动端登录/登出按钮 */}
|
|
<Divider />
|
|
{isAuthenticated && user ? (
|
|
<Button
|
|
colorScheme="red"
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={() => {
|
|
handleLogout();
|
|
onClose();
|
|
}}
|
|
>
|
|
🚪 退出登录
|
|
</Button>
|
|
) : (
|
|
<Button
|
|
colorScheme="blue"
|
|
size="sm"
|
|
onClick={() => {
|
|
openAuthModal();
|
|
onClose();
|
|
}}
|
|
>
|
|
🔐 登录 / 注册
|
|
</Button>
|
|
)}
|
|
</VStack>
|
|
</DrawerBody>
|
|
</DrawerContent>
|
|
</Drawer>
|
|
);
|
|
});
|
|
|
|
MobileDrawer.displayName = 'MobileDrawer';
|
|
|
|
export default MobileDrawer;
|