Files
model-platform/frontend/app/components/common/Sidebar.tsx
T
2026-08-14 11:59:06 +08:00

87 lines
2.4 KiB
TypeScript

import Icon from "./Icon";
type ActivePage = "home" | "scripts" | "schedules" | "system";
type SidebarProps = {
activePage: ActivePage;
collapsed: boolean;
onNavigate: (page: ActivePage) => void;
onToggleCollapse: () => void;
onEndEditing?: () => void;
onSelectScript?: (scriptId: null) => void;
editSessionRef?: React.RefObject<unknown | null>;
isSystemAdmin?: boolean;
};
type NavigationItem = {
label: string;
icon: "home" | "script" | "schedule" | "settings";
page: ActivePage;
};
export function Sidebar({
activePage,
collapsed,
onNavigate,
onToggleCollapse,
onEndEditing,
onSelectScript,
editSessionRef,
isSystemAdmin = false,
}: SidebarProps) {
const handleNavigationClick = (page: ActivePage) => {
if (page !== "scripts") {
if (editSessionRef?.current) {
onEndEditing?.();
} else {
onSelectScript?.(null);
}
}
onNavigate(page);
};
// 根据管理员权限构建菜单项
const navigation: NavigationItem[] = [
{ label: "工作台", icon: "home", page: "home" },
{ label: "构建脚本", icon: "script", page: "scripts" },
{ label: "调度配置", icon: "schedule", page: "schedules" },
];
// 系统管理员才显示"系统管理"菜单
if (isSystemAdmin) {
navigation.push({ label: "系统管理", icon: "settings", page: "system" });
}
return (
<aside className={`sidebar${collapsed ? " is-collapsed" : ""}`}>
<div className="brand">
<span className="brand__mark"><Icon name="brand" size={31} /></span>
{!collapsed && <span className="brand__name">模型实验开发平台</span>}
</div>
{!collapsed && (
<nav className="navigation" aria-label="主导航">
{navigation.map((item) => (
<button
className={`nav-item${
item.page === activePage ? " nav-item--active" : ""
}`}
key={item.label}
type="button"
onClick={() => handleNavigationClick(item.page)}
>
<Icon name={item.icon} size={19} />
<span>{item.label}</span>
</button>
))}
</nav>
)}
<button className="sidebar-footer" type="button" onClick={onToggleCollapse}>
<Icon name="menu" size={19} />
<span>{collapsed ? "展开菜单" : "收起菜单"}</span>
</button>
</aside>
);
}