Files
shaguabijia-admin-web/src/app/(main)/layout.tsx
T
OuYingJun1024 631b243d4b Merge remote-tracking branch 'origin/main' into feat/ad-coin-ecpm-unit-audit
# Conflicts:
#	src/app/(main)/layout.tsx
2026-06-10 16:00:05 +08:00

114 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useEffect, useState } from 'react';
import { usePathname, useRouter } from 'next/navigation';
import {
DashboardOutlined,
FileSearchOutlined,
FlagOutlined,
FundProjectionScreenOutlined,
LogoutOutlined,
MessageOutlined,
MoneyCollectOutlined,
SettingOutlined,
TeamOutlined,
UserOutlined,
} from '@ant-design/icons';
import { Avatar, Dropdown, Layout, Menu } from 'antd';
import { clearAuth, getAdmin, getToken } from '@/lib/auth';
import type { AdminInfo } from '@/lib/types';
const { Sider, Header, Content } = Layout;
const MENU = [
{ key: '/dashboard', icon: <DashboardOutlined />, label: '数据大盘' },
{ key: '/users', icon: <UserOutlined />, label: '用户管理' },
{ key: '/withdraws', icon: <MoneyCollectOutlined />, label: '提现管理' },
{ key: '/price-reports', icon: <FlagOutlined />, label: '上报审核' },
{ key: '/feedbacks', icon: <MessageOutlined />, label: '反馈工单' },
{ key: '/ad-audit', icon: <FundProjectionScreenOutlined />, label: '金币审计' },
{ key: '/config', icon: <SettingOutlined />, label: '系统配置' },
{ key: '/admins', icon: <TeamOutlined />, label: '管理员', superOnly: true },
{ key: '/audit-logs', icon: <FileSearchOutlined />, label: '审计日志' },
];
export default function MainLayout({ children }: { children: React.ReactNode }) {
const router = useRouter();
const pathname = usePathname();
const [admin, setAdmin] = useState<AdminInfo | null>(null);
useEffect(() => {
if (!getToken()) {
router.replace('/login');
return;
}
setAdmin(getAdmin());
}, [router]);
if (!admin) return null; // 守卫期间不闪烁内容
const items = MENU.filter((m) => !m.superOnly || admin.role === 'super_admin').map((m) => ({
key: m.key,
icon: m.icon,
label: m.label,
}));
// 选中态:取路径一级(/users/123 → /users)
const selectedKey = '/' + (pathname.split('/')[1] || 'dashboard');
const logout = () => {
clearAuth();
router.replace('/login');
};
return (
<Layout style={{ minHeight: '100vh' }}>
<Sider theme="dark" breakpoint="lg" collapsible>
<div
style={{
height: 48,
margin: 16,
color: '#fff',
fontWeight: 600,
textAlign: 'center',
lineHeight: '48px',
}}
>
</div>
<Menu
theme="dark"
mode="inline"
selectedKeys={[selectedKey]}
items={items}
onClick={({ key }) => router.push(key)}
/>
</Sider>
<Layout>
<Header
style={{
background: '#fff',
padding: '0 24px',
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'center',
}}
>
<Dropdown
menu={{
items: [
{ key: 'logout', icon: <LogoutOutlined />, label: '退出登录', onClick: logout },
],
}}
>
<span style={{ cursor: 'pointer' }}>
<Avatar size="small" icon={<UserOutlined />} /> {admin.username}{admin.role}
</span>
</Dropdown>
</Header>
<Content style={{ margin: 24 }}>{children}</Content>
</Layout>
</Layout>
);
}