Files
rainblogweb/frontend/src/admin/main.jsx
T

127 lines
5.3 KiB
React
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.
import React, { lazy, Suspense, useEffect, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import Box from '@mui/material/Box';
import CircularProgress from '@mui/material/CircularProgress';
import { createMD3Theme } from './theme.js';
import './theme.css';
import { getToken } from '../api/client.js';
import { me } from '../api/auth.js';
import { getSettings } from '../api/settings.js';
import AdminLayout from './AdminLayout.jsx';
import Dashboard from './pages/Dashboard.jsx';
import Settings from './pages/Settings.jsx';
import CaptchaSettings from './pages/CaptchaSettings.jsx';
import ThemeSettings from './pages/ThemeSettings.jsx';
import Homepage from './pages/Homepage.jsx';
import EmailSettings from './pages/EmailSettings.jsx';
import BlogManage from './pages/BlogManage.jsx';
import CommentManage from './pages/CommentManage.jsx';
import ForumManage from './pages/ForumManage.jsx';
import PostManage from './pages/PostManage.jsx';
import RssManage from './pages/RssManage.jsx';
import Users from './pages/Users.jsx';
import Announcements from './pages/Announcements.jsx';
import Links from './pages/Links.jsx';
import Uploads from './pages/Uploads.jsx';
import ImportDb from './pages/ImportDb.jsx';
import TicketManage from './pages/TicketManage.jsx';
// 工作台独立分包:仅访问 /admin/workbench 时才加载(vite 自动 code-split
const Workbench = lazy(() => import('../tools/workbench/Workbench.jsx'));
// 生产:/admin/* 由后端 fallback 到 dist/admin.htmlPhase 6 需求),basename=/admin
// 开发:vite 多入口直接访问 /admin.htmlbasename 自适应为空。
const pathname = window.location.pathname;
const basename = (pathname === '/admin' || pathname.startsWith('/admin/')) ? '/admin' : '';
function AdminApp() {
const [status, setStatus] = useState('checking'); // checking | ok
const [primary, setPrimary] = useState('#6750a4');
// 深色模式跟随前台偏好:整页跳转后 data-theme 属性不保留,
// 以 localStorage 的 theme 为兜底(前台 theme.jsx 持久化同一 key)。
const dark = document.documentElement.getAttribute('data-theme') === 'dark'
|| localStorage.getItem('theme') === 'dark';
useEffect(() => {
if (dark) document.documentElement.setAttribute('data-theme', 'dark');
}, [dark]);
useEffect(() => {
const token = getToken();
if (!token) { window.location.href = '/login.html'; return; }
me()
.then((u) => {
if (u.role !== 'admin') {
window.alert('需要管理员权限');
window.location.href = '/';
return;
}
setStatus('ok');
})
.catch(() => { window.location.href = '/login.html'; });
getSettings()
.then((s) => { if (s.primary_color) setPrimary(s.primary_color); })
.catch(() => {});
}, []);
if (status !== 'ok') {
return (
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<CircularProgress />
</Box>
);
}
const theme = createMD3Theme({ mode: dark ? 'dark' : 'light', primary });
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<BrowserRouter basename={basename}>
<Routes>
{/* 工作台:独立全屏布局,不套 AdminLayout(自带 Toolbar+Sidebar+内容区);懒加载分包 */}
<Route
path="/workbench"
element={
<Suspense
fallback={
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh' }}>
<CircularProgress />
</Box>
}
>
<Workbench />
</Suspense>
}
/>
<Route element={<AdminLayout />}>
<Route index element={<Navigate to="/dashboard" replace />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
<Route path="/captcha" element={<CaptchaSettings />} />
<Route path="/theme" element={<ThemeSettings />} />
<Route path="/homepage" element={<Homepage />} />
<Route path="/email" element={<EmailSettings />} />
<Route path="/blog" element={<BlogManage />} />
<Route path="/comments" element={<CommentManage />} />
<Route path="/forum" element={<ForumManage />} />
<Route path="/posts" element={<PostManage />} />
<Route path="/rss" element={<RssManage />} />
<Route path="/users" element={<Users />} />
<Route path="/announcements" element={<Announcements />} />
<Route path="/links" element={<Links />} />
<Route path="/uploads" element={<Uploads />} />
<Route path="/import" element={<ImportDb />} />
<Route path="/tickets" element={<TicketManage />} />
<Route path="*" element={<Navigate to="/dashboard" replace />} />
</Route>
</Routes>
</BrowserRouter>
</ThemeProvider>
);
}
createRoot(document.getElementById('root')).render(<AdminApp />);