new branch

This commit is contained in:
rayd1o
2026-03-07 13:06:37 +08:00
parent 3145ff083b
commit 4ada75ca14
64 changed files with 4324 additions and 35 deletions

View File

@@ -0,0 +1,99 @@
import { ReactNode } from 'react'
import { Layout, Menu, Typography, Button } from 'antd'
import {
DashboardOutlined,
DatabaseOutlined,
UserOutlined,
SettingOutlined,
BarChartOutlined,
MenuUnfoldOutlined,
} from '@ant-design/icons'
import { Link, useLocation } from 'react-router-dom'
import { useAuthStore } from '../../stores/auth'
const { Header, Sider, Content } = Layout
const { Text } = Typography
interface AppLayoutProps {
children: ReactNode
}
function AppLayout({ children }: AppLayoutProps) {
const location = useLocation()
const { user, logout } = useAuthStore()
const menuItems = [
{ key: '/', icon: <DashboardOutlined />, label: <Link to="/"></Link> },
{ key: '/datasources', icon: <DatabaseOutlined />, label: <Link to="/datasources"></Link> },
{ key: '/data', icon: <BarChartOutlined />, label: <Link to="/data"></Link> },
{ key: '/users', icon: <UserOutlined />, label: <Link to="/users"></Link> },
{ key: '/settings', icon: <SettingOutlined />, label: <Link to="/settings"></Link> },
]
return (
<Layout className="dashboard-layout">
<Sider
width={240}
collapsible
collapsed={false}
onCollapse={(collapsed) => {
const sider = document.querySelector('.dashboard-sider') as HTMLElement
if (sider) {
sider.style.width = collapsed ? '80px' : '240px'
sider.style.minWidth = collapsed ? '80px' : '240px'
sider.style.maxWidth = collapsed ? '80px' : '240px'
}
}}
className="dashboard-sider"
trigger={null}
breakpoint="lg"
onBreakpoint={(broken) => {
const sider = document.querySelector('.dashboard-sider') as HTMLElement
if (sider) {
sider.style.width = broken ? '80px' : '240px'
sider.style.minWidth = broken ? '80px' : '240px'
sider.style.maxWidth = broken ? '80px' : '240px'
}
}}
>
<div style={{ height: 64, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Text strong style={{ color: 'white', fontSize: 18 }}></Text>
</div>
<Menu
theme="dark"
mode="inline"
selectedKeys={[location.pathname]}
items={menuItems}
/>
</Sider>
<Layout>
<Header className="dashboard-header" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 16px' }}>
<Button
type="text"
icon={<MenuUnfoldOutlined />}
onClick={() => {
const sider = document.querySelector('.ant-layout-sider') as HTMLElement
if (sider) {
const currentWidth = sider.style.width || '240px'
const isCollapsed = currentWidth === '80px'
sider.style.width = isCollapsed ? '240px' : '80px'
sider.style.minWidth = isCollapsed ? '240px' : '80px'
sider.style.maxWidth = isCollapsed ? '240px' : '80px'
}
}}
style={{ fontSize: 16 }}
/>
<Text strong>, {user?.username}</Text>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<Button type="link" danger onClick={logout}>退</Button>
</div>
</Header>
<Content className="dashboard-content" style={{ padding: 24, minHeight: '100%', overflow: 'auto' }}>
{children}
</Content>
</Layout>
</Layout>
)
}
export default AppLayout