fix: frontend routes

This commit is contained in:
tao.chen
2026-08-07 12:47:37 +08:00
parent d7934a42ab
commit 6f574073e3
12 changed files with 206 additions and 167 deletions
@@ -4,6 +4,8 @@ import Icon from "../../components/common/Icon";
import { UserManagementPage } from "../../components/admin/UserManagementPage";
import { ProjectManagementPage } from "../../components/admin/ProjectManagementPage";
import "../../styles/admin.css";
export function SystemAdminPage({
onNotify,
onConnectionChange,
@@ -0,0 +1,15 @@
import { useScriptWorkspaceStore } from "../platform/state/scriptWorkspaceStore";
import { useUiStore } from "../platform/state/uiStore";
import { SystemAdminPage } from "./SystemAdminPage";
export default function SystemAdminRoute() {
const setApiOnline = useScriptWorkspaceStore((s) => s.setApiOnline);
const pushToast = useUiStore((s) => s.pushToast);
return (
<SystemAdminPage
onNotify={pushToast}
onConnectionChange={setApiOnline}
/>
);
}
@@ -3,8 +3,6 @@ import { useNavigate } from "react-router";
import { DashboardPage } from "../../components/admin/DashboardPage";
import { useScriptWorkspaceStore } from "./state/scriptWorkspaceStore";
import "../../styles/dashboard.css";
export default function DashboardRoute() {
const scripts = useScriptWorkspaceStore((s) => s.scripts);
const apiOnline = useScriptWorkspaceStore((s) => s.apiOnline);
@@ -1,122 +0,0 @@
import { useEffect, useState } from "react";
import { Outlet, useLocation, useNavigate } from "react-router";
import { Sidebar } from "../../components/common/Sidebar";
import { Toast } from "../../components/common/Toast";
import { Topbar } from "../../components/common/Topbar";
import { useApi, useAuth } from "../../context/AuthContext";
import { useEditSessionLifecycle } from "./hooks/useEditSessionLifecycle";
import {
bindScriptWorkspaceApi,
editSessionHandle,
useScriptWorkspaceStore,
} from "./state/scriptWorkspaceStore";
import { useUiStore } from "./state/uiStore";
import "../../styles/platform.css";
type ActivePage = "home" | "scripts" | "schedules" | "system";
function pageFromPath(pathname: string): ActivePage {
const page = pathname.replace(/^\/+|\/+$/g, "");
return ["scripts", "schedules", "system"].includes(page)
? (page as ActivePage)
: "home";
}
function pathForPage(page: ActivePage): string {
return page === "home" ? "/workbench" : `/${page}`;
}
export default function ModelPlatformApp() {
const { currentWorkspace } = useAuth();
if (!currentWorkspace) {
return (
<div
className="app-shell"
style={{ display: "flex", alignItems: "center", justifyContent: "center" }}
>
<div style={{ textAlign: "center" }}>
<span style={{ fontSize: 18 }}></span>
</div>
</div>
);
}
return <AuthenticatedLayout />;
}
function AuthenticatedLayout() {
const api = useApi();
const location = useLocation();
const navigate = useNavigate();
const activePage = pageFromPath(location.pathname);
const auth = useAuth();
const {
user,
workspaces,
currentWorkspace,
setCurrentWorkspace,
logout,
} = auth;
const apiOnline = useScriptWorkspaceStore((s) => s.apiOnline);
const endEditing = useScriptWorkspaceStore((s) => s.endEditing);
const selectScript = useScriptWorkspaceStore((s) => s.selectScript);
const toast = useUiStore((s) => s.toast);
const dismissToast = useUiStore((s) => s.dismissToast);
const workspaceMenuOpen = useUiStore((s) => s.workspaceMenuOpen);
const setWorkspaceMenuOpen = useUiStore((s) => s.setWorkspaceMenuOpen);
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
// 绑定 api 到 script workspace store
useEffect(() => {
bindScriptWorkspaceApi(api);
return () => {
bindScriptWorkspaceApi(null);
};
}, [api]);
// 心跳 / cleanup / 切页结束编辑 / 卸载前释放
useEditSessionLifecycle({ activePage });
// toast 自动消失
useEffect(() => {
if (!toast) return;
const timer = window.setTimeout(dismissToast, 3200);
return () => window.clearTimeout(timer);
}, [toast, dismissToast]);
return (
<div className="app-shell">
<Sidebar
activePage={activePage}
collapsed={sidebarCollapsed}
onNavigate={(page) => navigate(pathForPage(page))}
onToggleCollapse={() => setSidebarCollapsed((v) => !v)}
onEndEditing={() => void endEditing(true)}
onSelectScript={selectScript}
editSessionRef={editSessionHandle}
/>
<main className="main-area">
<Topbar
activePage={activePage}
apiOnline={apiOnline}
user={user}
currentWorkspace={currentWorkspace!}
workspaces={workspaces}
workspaceMenuOpen={workspaceMenuOpen}
onSetWorkspaceMenuOpen={setWorkspaceMenuOpen}
onSetCurrentWorkspace={setCurrentWorkspace}
onLogout={logout}
/>
<Outlet />
</main>
<Toast toast={toast} />
</div>
);
}
@@ -0,0 +1,10 @@
import { Navigate } from "react-router";
/**
* 根路径 "/" 命中时直接跳到 /workbench。
* 抽出独立文件是为了不和 route("workbench", ...) 撞 route id
* (React Router v8 基于文件路径生成 id, 同一文件不能被两个路由引用)。
*/
export default function RootIndex() {
return <Navigate to="/workbench" replace />;
}