需求描述:/admin/display 需要无需管理员登录即可直接查看多项目公开运行状态。 实现思路:新增公开字段白名单接口与独立大屏页面,移除该路由的管理员会话依赖,同时保留 /api/admin/overview 的鉴权并补充隐私、路由和页面回归测试。 验证:Go 全量测试通过;前端 18 个测试文件共 59 项通过,TypeScript 检查通过。
60 lines
3.9 KiB
TypeScript
60 lines
3.9 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import { BrowserRouter, Navigate, Route, Routes, useLocation } from "react-router-dom";
|
|
import { AuthProvider, useAuth } from "./auth/AuthContext";
|
|
import { LoadingState } from "./components/Feedback";
|
|
import { AdminPage } from "./pages/AdminPage";
|
|
import { DisplayPage } from "./pages/DisplayPage";
|
|
import { PublicDisplayCenterPage } from "./pages/PublicDisplayCenterPage";
|
|
import { LoginPage } from "./pages/LoginPage";
|
|
import { HistoryPage } from "./pages/HistoryPage";
|
|
import { StaffPage } from "./pages/StaffPage";
|
|
import { VisitorPage } from "./pages/VisitorPage";
|
|
import { VisitorLookupPage } from "./pages/VisitorLookupPage";
|
|
import { VisitorPhonePage } from "./pages/VisitorPhonePage";
|
|
|
|
function RequireStaff({ children }: { children: ReactNode }) {
|
|
const { user, loading } = useAuth();
|
|
const location = useLocation();
|
|
if (loading) return <main className="route-loading"><LoadingState label="正在确认访问权限" /></main>;
|
|
if (!user) return <Navigate to="/staff/login" replace state={{ from: `${location.pathname}${location.search}` }} />;
|
|
return children;
|
|
}
|
|
|
|
function RequireAdmin({ children }: { children: ReactNode }) {
|
|
const { user, loading } = useAuth();
|
|
if (loading) return <main className="route-loading"><LoadingState label="正在确认管理权限" /></main>;
|
|
if (!user) return <Navigate to="/admin/login" replace />;
|
|
return children;
|
|
}
|
|
|
|
export function App() {
|
|
return (
|
|
<BrowserRouter>
|
|
<Routes>
|
|
<Route path="/" element={<Navigate to="/staff" replace />} />
|
|
<Route path="/login" element={<Navigate to="/staff/login" replace />} />
|
|
<Route path="/staff/login" element={<AuthProvider portal="staff"><LoginPage portal="staff" /></AuthProvider>} />
|
|
<Route path="/staff" element={<AuthProvider portal="staff"><RequireStaff><StaffPage /></RequireStaff></AuthProvider>} />
|
|
<Route path="/staff/tickets" element={<AuthProvider portal="staff"><RequireStaff><StaffPage /></RequireStaff></AuthProvider>} />
|
|
<Route path="/staff/me" element={<AuthProvider portal="staff"><RequireStaff><StaffPage /></RequireStaff></AuthProvider>} />
|
|
<Route path="/staff/verify" element={<Navigate to="/staff" replace />} />
|
|
<Route path="/visitor" element={<VisitorLookupPage />} />
|
|
<Route path="/visitor/phone" element={<VisitorPhonePage />} />
|
|
<Route path="/visitor/:token" element={<VisitorPage />} />
|
|
<Route path="/display/:token" element={<DisplayPage />} />
|
|
<Route path="/admin/login" element={<AuthProvider portal="admin"><LoginPage portal="admin" /></AuthProvider>} />
|
|
<Route path="/admin" element={<AuthProvider portal="admin"><RequireAdmin><AdminPage /></RequireAdmin></AuthProvider>} />
|
|
<Route path="/admin/history" element={<AuthProvider portal="admin"><RequireAdmin><HistoryPage /></RequireAdmin></AuthProvider>} />
|
|
<Route path="/admin/projects" element={<AuthProvider portal="admin"><RequireAdmin><AdminPage /></RequireAdmin></AuthProvider>} />
|
|
<Route path="/admin/projects/new" element={<AuthProvider portal="admin"><RequireAdmin><AdminPage /></RequireAdmin></AuthProvider>} />
|
|
<Route path="/admin/projects/:projectId" element={<AuthProvider portal="admin"><RequireAdmin><AdminPage /></RequireAdmin></AuthProvider>} />
|
|
<Route path="/admin/accounts" element={<AuthProvider portal="admin"><RequireAdmin><AdminPage /></RequireAdmin></AuthProvider>} />
|
|
<Route path="/admin/accounts/new" element={<AuthProvider portal="admin"><RequireAdmin><AdminPage /></RequireAdmin></AuthProvider>} />
|
|
<Route path="/admin/accounts/:accountId" element={<AuthProvider portal="admin"><RequireAdmin><AdminPage /></RequireAdmin></AuthProvider>} />
|
|
<Route path="/admin/display" element={<PublicDisplayCenterPage />} />
|
|
<Route path="*" element={<Navigate to="/" replace />} />
|
|
</Routes>
|
|
</BrowserRouter>
|
|
);
|
|
}
|