- 修正 API 响应类型,增加 ProjectResponse 包装类型 - ConfigProvider 配置中文 locale (zhCN) - 生产入口启用 ErrorBoundary,使用 Result 组件 - ReactQueryDevtools 仅开发环境渲染 - Sider 增加 collapsible 配置,使用 antd 默认折叠行为 - 项目页面拆分为 ProjectToolbar/ProjectTable/ProjectFormModal - 搜索改用 Input.Search,表单增加 whitespace 校验 - 404/ErrorBoundary/Dashboard 使用 antd Result/Typography/Card/Descriptions - 清理未使用的 ProtectedRoute 和冗余样式类 - styles.css 仅保留必要布局样式,无 antd 内部类覆盖 - 更新测试覆盖,避免依赖 antd 内部类名 - 更新 docs/development/frontend.md 开发规范
33 lines
923 B
TypeScript
33 lines
923 B
TypeScript
import type { MenuProps } from "antd";
|
|
|
|
import { Menu } from "antd";
|
|
import { useLocation, useNavigate } from "react-router";
|
|
|
|
import { MENU_ITEMS } from "../../menu";
|
|
|
|
type MenuItem = Required<MenuProps>["items"][number];
|
|
|
|
export function Sidebar() {
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
|
|
const currentPath = location.pathname;
|
|
const currentItem = MENU_ITEMS.find((item) => item.path === currentPath);
|
|
const selectedKeys = currentItem ? [currentItem.value] : [];
|
|
|
|
const menuItems: MenuItem[] = MENU_ITEMS.map((item) => ({
|
|
icon: item.icon,
|
|
key: item.value,
|
|
label: item.label,
|
|
}));
|
|
|
|
const handleMenuClick: MenuProps["onClick"] = ({ key }) => {
|
|
const item = MENU_ITEMS.find((i) => i.value === key);
|
|
if (item) {
|
|
void navigate(item.path);
|
|
}
|
|
};
|
|
|
|
return <Menu items={menuItems} mode="inline" onClick={handleMenuClick} selectedKeys={selectedKeys} />;
|
|
}
|