feat: 添加导航激活状态检测功能

- 使用 React Router 的 useLocation 钩子检测当前路径
- 为顶级导航菜单添加激活状态样式(蓝色背景 + 底部边框)
- 为下拉菜单项添加激活状态样式(蓝色背景 + 左侧边框)
- 支持桌面端和移动端抽屉菜单
- 解决用户无法感知当前导航位置的 UX 问题

激活路由映射:
- 高频跟踪: /community, /concepts
- 行情复盘: /limit-analyse, /stocks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-10-16 17:50:07 +08:00
parent 52bec7ce8a
commit 42acc8fac0

View File

@@ -34,7 +34,7 @@ import {
} from '@chakra-ui/react';
import { ChevronDownIcon, HamburgerIcon, SunIcon, MoonIcon } from '@chakra-ui/icons';
import { FiStar, FiCalendar } from 'react-icons/fi';
import { useNavigate } from 'react-router-dom';
import { useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from '../../contexts/AuthContext';
import { useAuthModal } from '../../contexts/AuthModalContext';
@@ -45,12 +45,28 @@ import { useAuthModal } from '../../contexts/AuthModalContext';
*/
const NavItems = ({ isAuthenticated, user }) => {
const navigate = useNavigate();
const location = useLocation();
// 辅助函数:判断导航项是否激活
const isActive = (paths) => {
return paths.some(path => location.pathname.includes(path));
};
if (isAuthenticated && user) {
return (
<HStack spacing={8}>
<Menu>
<MenuButton as={Button} variant="ghost" rightIcon={<ChevronDownIcon />}>
<MenuButton
as={Button}
variant="ghost"
rightIcon={<ChevronDownIcon />}
bg={isActive(['/community', '/concepts']) ? 'blue.50' : 'transparent'}
color={isActive(['/community', '/concepts']) ? 'blue.600' : 'inherit'}
fontWeight={isActive(['/community', '/concepts']) ? 'bold' : 'normal'}
borderBottom={isActive(['/community', '/concepts']) ? '2px solid' : 'none'}
borderColor="blue.600"
_hover={{ bg: isActive(['/community', '/concepts']) ? 'blue.100' : 'gray.50' }}
>
高频跟踪
</MenuButton>
<MenuList minW="260px" p={2}>
@@ -62,6 +78,10 @@ const NavItems = ({ isAuthenticated, user }) => {
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'}
>
<Flex justify="space-between" align="center">
<Text fontSize="sm">新闻催化分析</Text>
@@ -78,6 +98,10 @@ const NavItems = ({ isAuthenticated, user }) => {
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'}
>
<Flex justify="space-between" align="center">
<Text fontSize="sm">概念中心</Text>
@@ -89,7 +113,17 @@ const NavItems = ({ isAuthenticated, user }) => {
</Menu>
<Menu>
<MenuButton as={Button} variant="ghost" rightIcon={<ChevronDownIcon />}>
<MenuButton
as={Button}
variant="ghost"
rightIcon={<ChevronDownIcon />}
bg={isActive(['/limit-analyse', '/stocks']) ? 'blue.50' : 'transparent'}
color={isActive(['/limit-analyse', '/stocks']) ? 'blue.600' : 'inherit'}
fontWeight={isActive(['/limit-analyse', '/stocks']) ? 'bold' : 'normal'}
borderBottom={isActive(['/limit-analyse', '/stocks']) ? '2px solid' : 'none'}
borderColor="blue.600"
_hover={{ bg: isActive(['/limit-analyse', '/stocks']) ? 'blue.100' : 'gray.50' }}
>
行情复盘
</MenuButton>
<MenuList minW="260px" p={2}>
@@ -101,6 +135,10 @@ const NavItems = ({ isAuthenticated, user }) => {
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'}
>
<Flex justify="space-between" align="center">
<Text fontSize="sm">涨停分析</Text>
@@ -114,6 +152,10 @@ const NavItems = ({ isAuthenticated, user }) => {
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'}
>
<Flex justify="space-between" align="center">
<Text fontSize="sm">个股中心</Text>
@@ -809,6 +851,9 @@ export default function HomeNavbar() {
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>
@@ -826,6 +871,10 @@ export default function HomeNavbar() {
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>
@@ -845,6 +894,10 @@ export default function HomeNavbar() {
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>
@@ -867,6 +920,10 @@ export default function HomeNavbar() {
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>
@@ -883,6 +940,10 @@ export default function HomeNavbar() {
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>