/**
* Sidebar - 侧边栏导航组件(Task 1.3)
*
* 功能:
* - 分组导航菜单(创作工具 / 资源管理 / 系统)
* - 每个菜单项:图标 + 文字
* - 当前页面对应菜单项高亮(基于路由匹配)
* - 点击跳转路由
* - 折叠态:仅显示图标,隐藏文字(通过 SidebarContext 读取 collapsed 状态)
* - 响应式:移动端自动折叠
*/
import React, { useContext } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import {
DashboardOutlined,
VideoCameraOutlined,
FileOutlined,
AudioOutlined,
FileTextOutlined,
TrophyOutlined,
AppstoreOutlined,
HistoryOutlined,
ControlOutlined,
CrownOutlined,
} from "@ant-design/icons";
import { SidebarContext } from "./MainLayout";
import "./Sidebar.css";
/** 导航项定义 */
interface SidebarMenuItem {
key: string;
label: string;
path: string;
icon: React.ReactNode;
}
/** 导航分组定义 */
interface SidebarMenuGroup {
title: string;
items: SidebarMenuItem[];
}
/** 侧边栏导航分组 */
const MENU_GROUPS: SidebarMenuGroup[] = [
{
title: "创作工具",
items: [
{
key: "dashboard",
label: "首页",
path: "/dashboard",
icon: ,
},
{
key: "generate",
label: "一键生成",
path: "/generate",
icon: ,
},
],
},
{
title: "资源管理",
items: [
{
key: "assets",
label: "素材库",
path: "/assets",
icon: ,
},
{
key: "voices",
label: "配音库",
path: "/voices",
icon: ,
},
{
key: "titles",
label: "标题库",
path: "/titles",
icon: ,
},
{
key: "products",
label: "成片库",
path: "/products",
icon: ,
},
{
key: "templates",
label: "模板库",
path: "/templates",
icon: ,
},
],
},
{
title: "系统",
items: [
{
key: "history",
label: "任务历史",
path: "/history",
icon: ,
},
{
key: "admin",
label: "控制台",
path: "/admin",
icon: ,
},
{
key: "subscription",
label: "订阅管理",
path: "/subscription",
icon: ,
},
],
},
];
/** 判断菜单项是否激活 */
const isMenuItemActive = (pathname: string, path: string): boolean => {
if (path === "/dashboard") {
return pathname === "/" || pathname === "/dashboard";
}
return pathname.startsWith(path);
};
const Sidebar: React.FC = () => {
const { collapsed } = useContext(SidebarContext);
const location = useLocation();
const navigate = useNavigate();
const handleNavigate = (path: string) => {
navigate(path);
};
return (
{MENU_GROUPS.map((group) => (
{!collapsed && (
{group.title}
)}
{group.items.map((item) => {
const active = isMenuItemActive(location.pathname, item.path);
return (
- handleNavigate(item.path)}
>
{item.icon}
{!collapsed && (
{item.label}
)}
);
})}
))}
);
};
export default Sidebar;