feat: basic layout and pages

- add basic layout with sidebar and main container
- add three menus in sidebar
- add people form page for post people
- add text and image input for recognize people info
- add people table page for show peoples
This commit is contained in:
2025-10-21 11:47:28 +08:00
parent 7c28eda415
commit ddb04ff15e
20 changed files with 1284 additions and 102 deletions

View File

@@ -0,0 +1,112 @@
import React from 'react';
import { Layout, Menu, Grid, Drawer, Button } from 'antd';
import { CodeOutlined, HomeOutlined, UnorderedListOutlined, AppstoreOutlined, MenuOutlined } from '@ant-design/icons';
import './SiderMenu.css';
const { Sider } = Layout;
// 新增:支持外部导航回调 + 受控选中态
type Props = { onNavigate?: (key: string) => void; selectedKey?: string };
const SiderMenu: React.FC<Props> = ({ onNavigate, selectedKey }) => {
const screens = Grid.useBreakpoint();
const isMobile = !screens.md;
const [collapsed, setCollapsed] = React.useState(false);
const [selectedKeys, setSelectedKeys] = React.useState<string[]>(['home']);
const [mobileOpen, setMobileOpen] = React.useState(false);
React.useEffect(() => {
setCollapsed(isMobile);
}, [isMobile]);
// 根据外部 selectedKey 同步选中态
React.useEffect(() => {
if (selectedKey) {
setSelectedKeys([selectedKey]);
}
}, [selectedKey]);
const items = [
{ key: 'home', label: '首页', icon: <HomeOutlined /> },
{ key: 'menu1', label: '资源列表', icon: <UnorderedListOutlined /> },
{ key: 'menu2', label: '菜单2', icon: <AppstoreOutlined /> },
];
// 移动端:使用 Drawer 覆盖主内容
if (isMobile) {
return (
<>
<Button
className="mobile-menu-trigger"
type="default"
icon={<MenuOutlined />}
onClick={() => setMobileOpen((open) => !open)}
/>
<Drawer
className="mobile-menu-drawer"
placement="left"
width="100%"
open={mobileOpen}
onClose={() => setMobileOpen(false)}
styles={{ body: { padding: 0 } }}
>
<div className="sider-header">
<CodeOutlined style={{ fontSize: 22 }} />
<div>
<div className="sider-title"></div>
<div className="sider-desc"></div>
</div>
</div>
<Menu
theme="dark"
mode="inline"
selectedKeys={selectedKeys}
onClick={({ key }) => {
const k = String(key);
setSelectedKeys([k]);
setMobileOpen(false); // 选择后自动收起
onNavigate?.(k);
}}
items={items}
/>
</Drawer>
</>
);
}
// PC 端:保持 Sider 行为不变
return (
<Sider
width={260}
collapsible
collapsed={collapsed}
onCollapse={(c) => setCollapsed(c)}
breakpoint="md"
collapsedWidth={64}
theme="dark"
>
<div className={`sider-header ${collapsed ? 'collapsed' : ''}`}>
<CodeOutlined style={{ fontSize: 22 }} />
{!collapsed && (
<div>
<div className="sider-title"></div>
<div className="sider-desc"></div>
</div>
)}
</div>
<Menu
theme="dark"
mode="inline"
selectedKeys={selectedKeys}
onClick={({ key }) => {
const k = String(key);
setSelectedKeys([k]);
onNavigate?.(k);
}}
items={items}
/>
</Sider>
);
};
export default SiderMenu;