调整文档路径
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { Layout, Menu, theme } from 'antd';
|
||||
import { useState } from 'react';
|
||||
import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
||||
import Login from './pages/Login';
|
||||
import SSOLogin from './pages/SSOLogin';
|
||||
import Services from './pages/Services';
|
||||
import Stats from './pages/Stats';
|
||||
import Tokens from './pages/Tokens';
|
||||
import { clearSession, getUserInfo } from './services/iamAuth';
|
||||
const { Header, Content, Sider } = Layout;
|
||||
|
||||
/** 登录守卫:sessionStorage 无 userToken 则跳登录页(携带来源路径,登录后回跳) */
|
||||
function RequireAuth({ children }: { children: React.ReactNode }) {
|
||||
const location = useLocation();
|
||||
const token = sessionStorage.getItem('userToken');
|
||||
if (!token) {
|
||||
return <Navigate to="/login" replace state={{ from: location.pathname + location.search }} />;
|
||||
}
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
function AppLayout() {
|
||||
const nav = useNavigate();
|
||||
const loc = useLocation();
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const {
|
||||
token: { colorBgContainer },
|
||||
} = theme.useToken();
|
||||
|
||||
const userInfo = getUserInfo();
|
||||
const displayName = userInfo?.userName || userInfo?.userId || '';
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<Sider collapsible collapsed={collapsed} onCollapse={setCollapsed}>
|
||||
<div
|
||||
style={{
|
||||
height: 48,
|
||||
margin: 12,
|
||||
color: '#fff',
|
||||
textAlign: 'center',
|
||||
lineHeight: '48px',
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
MCP Auth
|
||||
</div>
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="inline"
|
||||
selectedKeys={[loc.pathname]}
|
||||
items={[
|
||||
{ key: '/tokens', label: 'Token 管理' },
|
||||
{ key: '/services', label: '服务管理' },
|
||||
{ key: '/stats', label: '统计概览' },
|
||||
]}
|
||||
onClick={({ key }) => nav(key)}
|
||||
/>
|
||||
</Sider>
|
||||
<Layout>
|
||||
<Header
|
||||
style={{
|
||||
padding: '0 24px',
|
||||
background: colorBgContainer,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<span>MCP Token 鉴权管理后台</span>
|
||||
<span style={{ fontSize: 13, color: '#999' }}>
|
||||
{displayName} ·{' '}
|
||||
<a
|
||||
onClick={() => {
|
||||
clearSession();
|
||||
nav('/login', { replace: true });
|
||||
}}
|
||||
>
|
||||
退出
|
||||
</a>
|
||||
</span>
|
||||
</Header>
|
||||
<Content style={{ margin: 24 }}>
|
||||
<div
|
||||
style={{
|
||||
padding: 24,
|
||||
minHeight: 480,
|
||||
background: colorBgContainer,
|
||||
borderRadius: 8,
|
||||
}}
|
||||
>
|
||||
<Routes>
|
||||
<Route path="/tokens" element={<Tokens />} />
|
||||
<Route path="/services" element={<Services />} />
|
||||
<Route path="/stats" element={<Stats />} />
|
||||
<Route path="*" element={<Navigate to="/tokens" replace />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
// 路由变化时重渲染,重读 sessionStorage 登录态
|
||||
useLocation();
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route path="/sso-login" element={<SSOLogin />} />
|
||||
<Route path="/*" element={<RequireAuth><AppLayout /></RequireAuth>} />
|
||||
</Routes>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user