99 lines
4.4 KiB
React
99 lines
4.4 KiB
React
import { StrictMode } from "react";
|
||
import { createRoot } from "react-dom/client";
|
||
import { HashRouter, Navigate, Route, Routes, useLocation } from "react-router";
|
||
import { Refine } from "@refinedev/core";
|
||
import { dataProvider } from "./dataProvider";
|
||
import { CreatorHubLayout } from "./Layout";
|
||
import { LoginPage } from "./LoginPage";
|
||
import { AccountCreatePage, AccountDetail, AccountList } from "./AccountsPage";
|
||
import { AuditPage } from "./AuditPage";
|
||
import { BrowserCreatePage, BrowserDetail, BrowserList } from "./BrowsersPage";
|
||
import { BrowserVersionList } from "./BrowserVersionsPage";
|
||
import { DraftPage } from "./DraftPage";
|
||
import { GatewayList } from "./GatewaysPage";
|
||
import { NetworkExitDetail, NetworkExitList } from "./NetworkExitsPage";
|
||
import { TaskDetail, TaskList } from "./TasksPage";
|
||
import { AttemptDetail } from "./TracePages";
|
||
import { AccountEditPage } from "./AccountEditPage";
|
||
import { CreatorCompetitorsPage } from "./CreatorCompetitorsPage";
|
||
import { CreatorSettingsPage } from "./CreatorSettingsPage";
|
||
import { CreatorWorkbenchPage } from "./CreatorWorkbenchPage";
|
||
import "remixicon/fonts/remixicon.css";
|
||
import "./styles.css";
|
||
|
||
// 开发阶段认证仅由页面层掌握:401 会清除凭证并跳转登录;localStorage 为空时直接展示登录页。
|
||
// 不用 useState:HashRouter 的 pushState/replaceState 不触发 hashchange,状态会在导航后过期;
|
||
// 改为每次渲染直接读 localStorage,登录后 navigate 引发重渲染即可拿到新状态。
|
||
const authed = () => localStorage.getItem("creatorhub.auth") !== null;
|
||
|
||
function AuthGate({ children }) {
|
||
const { pathname } = useLocation();
|
||
const loggedIn = authed();
|
||
if (!loggedIn && pathname !== "/login")
|
||
return <Navigate to="/login" replace />;
|
||
if (loggedIn && pathname === "/login")
|
||
return <Navigate to="/accounts" replace />;
|
||
return children;
|
||
}
|
||
|
||
createRoot(document.getElementById("root")).render(
|
||
<StrictMode>
|
||
<HashRouter>
|
||
<Refine dataProvider={dataProvider} options={{ syncWithLocation: false }}>
|
||
<AuthGate>
|
||
<Routes>
|
||
<Route path="/login" element={<LoginPage />} />
|
||
<Route element={<CreatorHubLayout />}>
|
||
<Route path="/" element={<Navigate to="/accounts" replace />} />
|
||
<Route path="/accounts" element={<AccountList />} />
|
||
<Route path="/accounts/new" element={<AccountCreatePage />} />
|
||
<Route path="/accounts/:id" element={<AccountDetail />} />
|
||
<Route path="/accounts/:id/edit" element={<AccountEditPage />} />
|
||
<Route
|
||
path="/creator/competitors"
|
||
element={<CreatorCompetitorsPage />}
|
||
/>
|
||
<Route
|
||
path="/creator/competitors/:id"
|
||
element={<CreatorCompetitorsPage />}
|
||
/>
|
||
<Route path="/competitors" element={<CreatorCompetitorsPage />} />
|
||
<Route
|
||
path="/competitors/:id"
|
||
element={<CreatorCompetitorsPage />}
|
||
/>
|
||
<Route
|
||
path="/creator/workbench"
|
||
element={<CreatorWorkbenchPage />}
|
||
/>
|
||
<Route path="/workbench" element={<CreatorWorkbenchPage />} />
|
||
<Route
|
||
path="/creator/settings"
|
||
element={<CreatorSettingsPage />}
|
||
/>
|
||
<Route path="/tasks" element={<TaskList />} />
|
||
<Route path="/tasks/:id" element={<TaskDetail />} />
|
||
<Route path="/audit" element={<AuditPage />} />
|
||
<Route path="/network-exits" element={<NetworkExitList />} />
|
||
<Route
|
||
path="/network-exits/:id"
|
||
element={<NetworkExitDetail />}
|
||
/>
|
||
<Route path="/browsers" element={<BrowserList />} />
|
||
<Route path="/browsers/new" element={<BrowserCreatePage />} />
|
||
<Route path="/browsers/:id" element={<BrowserDetail />} />
|
||
<Route
|
||
path="/browser-versions"
|
||
element={<BrowserVersionList />}
|
||
/>
|
||
<Route path="/gateways" element={<GatewayList />} />
|
||
<Route path="/drafts/:id" element={<DraftPage />} />
|
||
<Route path="/attempts/:id" element={<AttemptDetail />} />
|
||
</Route>
|
||
</Routes>
|
||
</AuthGate>
|
||
</Refine>
|
||
</HashRouter>
|
||
</StrictMode>,
|
||
);
|