1
0
Files
nex/frontend/src/components/AppLayout/index.tsx
lanyuanxiaoyao 8eea30ea11 feat: 统一品牌标识、关于页面三卡片布局与版本诊断功能
- 统一品牌为 Nex:侧边栏、托盘 tooltip、HTML 标题、favicon (PNG 替代 SVG)
- 重构关于页面为三卡片布局(品牌/版本/链接),版本状态 Tag 绝对定位右上角
- 新增 GET /api/version 后端接口,返回 version/commit/build_time
- 新增前端版本一致性诊断:匹配/不匹配/不可判断三种状态
- 同步 delta specs 到主 specs 并归档变更
2026-05-05 03:28:22 +08:00

117 lines
3.3 KiB
TypeScript

import { useState } from 'react'
import { Outlet, useLocation, useNavigate } from 'react-router'
import {
ServerIcon,
ChartLineIcon,
SettingIcon,
InfoCircleIcon,
ChevronLeftIcon,
ChevronRightIcon,
} from 'tdesign-icons-react'
import { Layout, Menu, Button } from 'tdesign-react'
import { APP_NAME } from '@/constants/app'
const { MenuItem } = Menu
export function AppLayout() {
const location = useLocation()
const navigate = useNavigate()
const [collapsed, setCollapsed] = useState(false)
const getPageTitle = () => {
if (location.pathname === '/providers') return '供应商管理'
if (location.pathname === '/stats') return '用量统计'
if (location.pathname === '/settings') return '设置'
if (location.pathname === '/about') return '关于'
return APP_NAME
}
const asideWidth = collapsed ? '64px' : '232px'
return (
<Layout style={{ minHeight: '100vh' }}>
<Layout.Aside
width={asideWidth}
style={{
overflow: 'hidden',
height: '100vh',
position: 'fixed',
left: 0,
top: 0,
bottom: 0,
}}
>
<Menu
value={location.pathname}
onChange={(value) => navigate(value as string)}
collapsed={collapsed}
width={['232px', '64px']}
logo={
<div
style={{
height: 64,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 10,
fontSize: '1.25rem',
fontWeight: 600,
}}
>
<img src='/icon.png' alt={`${APP_NAME} logo`} style={{ width: 28, height: 28 }} />
{!collapsed && APP_NAME}
</div>
}
operations={
<Button
aria-label={collapsed ? '展开侧边栏' : '收起侧边栏'}
variant='text'
shape='square'
icon={collapsed ? <ChevronRightIcon /> : <ChevronLeftIcon />}
onClick={() => setCollapsed(!collapsed)}
/>
}
style={{ height: '100%' }}
>
<MenuItem value='/providers' icon={<ServerIcon />}>
</MenuItem>
<MenuItem value='/stats' icon={<ChartLineIcon />}>
</MenuItem>
<MenuItem value='/settings' icon={<SettingIcon />}>
</MenuItem>
<MenuItem value='/about' icon={<InfoCircleIcon />}>
</MenuItem>
</Menu>
</Layout.Aside>
<Layout style={{ marginLeft: asideWidth }}>
<Layout.Header
style={{
padding: '0 2rem',
background: 'var(--td-bg-color-container)',
display: 'flex',
alignItems: 'center',
borderBottom: '1px solid var(--td-component-stroke)',
}}
>
<h1 style={{ margin: 0, fontSize: '1.25rem' }}>{getPageTitle()}</h1>
</Layout.Header>
<Layout.Content
style={{
padding: '2rem',
maxWidth: '1400px',
width: '100%',
margin: '0 auto',
boxSizing: 'border-box',
}}
>
<Outlet />
</Layout.Content>
</Layout>
</Layout>
)
}