Files
sundynix-agentix/sundynix-admin/src/routes.tsx
T
Blizzard a830ae2a04 feat(admin): 审计 & 安全事件页(T4.B 收尾)
- 新增「审计 & 安全」页(/audit,运维组):接 /admin/audit + /admin/guardrail-events
  - 安全事件:护栏拦截/灰区放行(kind 徽标 + 原因 + method/path + actor/ip/时间)
  - 操作审计:变更操作(方法配色徽标 + 路径 + 状态码着色 + actor/ip/时间)
  - 顶栏统计(操作留痕/护栏拦截/灰区) + 30s 自刷 + 手动刷新
- api.ts 增 listAudit / listGuardrailEvents + 类型
- 风格对齐重做后的服务状态页(中性克制)
- T4.B 整组完成(剩 HITL 审批明细可选小项)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 09:43:41 +08:00

115 lines
3.1 KiB
TypeScript

import { lazy, type ReactNode } from "react";
import { Soon } from "./components/Soon";
// 路由注册表 —— 控制台的单一事实源:导航 + 内容都从这里派生。
// 新增页面 = 在此加一条;real 页面用 lazy 懒加载(代码分割)。
const DashboardPage = lazy(() => import("./pages/DashboardPage").then((m) => ({ default: m.DashboardPage })));
const ModelsPage = lazy(() => import("./pages/ModelsPage").then((m) => ({ default: m.ModelsPage })));
const DatasourcesPage = lazy(() => import("./pages/DatasourcesPage").then((m) => ({ default: m.DatasourcesPage })));
const PricingPage = lazy(() => import("./pages/PricingPage").then((m) => ({ default: m.PricingPage })));
const StatusPage = lazy(() => import("./pages/StatusPage").then((m) => ({ default: m.StatusPage })));
const EvalsPage = lazy(() => import("./pages/EvalsPage").then((m) => ({ default: m.EvalsPage })));
const TenantsPage = lazy(() => import("./pages/TenantsPage").then((m) => ({ default: m.TenantsPage })));
const GuardrailsPage = lazy(() => import("./pages/GuardrailsPage").then((m) => ({ default: m.GuardrailsPage })));
const PromptsPage = lazy(() => import("./pages/PromptsPage").then((m) => ({ default: m.PromptsPage })));
const AuditPage = lazy(() => import("./pages/AuditPage").then((m) => ({ default: m.AuditPage })));
export interface RouteDef {
path: string;
label: string;
group: string;
ready?: boolean;
element: ReactNode;
}
export const routes: RouteDef[] = [
{
path: "/dashboard",
label: "概览",
group: "分析",
ready: true,
element: <DashboardPage />,
},
{
path: "/models",
label: "模型",
group: "配置",
ready: true,
element: <ModelsPage />,
},
{
path: "/datasources",
label: "数据源 & RAG",
group: "配置",
ready: true,
element: <DatasourcesPage />,
},
{
path: "/pricing",
label: "计价 & 预算",
group: "配置",
ready: true,
element: <PricingPage />,
},
{
path: "/prompts",
label: "提示词",
group: "配置",
ready: true,
element: <PromptsPage />,
},
{
path: "/status",
label: "服务状态",
group: "运维",
ready: true,
element: <StatusPage />,
},
{
path: "/evals",
label: "自动评测",
group: "运维",
ready: true,
element: <EvalsPage />,
},
{
path: "/audit",
label: "审计 & 安全",
group: "运维",
ready: true,
element: <AuditPage />,
},
{
path: "/tenants",
label: "租户 & 用户",
group: "平台",
ready: true,
element: <TenantsPage />,
},
{
path: "/guardrails",
label: "安全护栏",
group: "平台",
ready: true,
element: <GuardrailsPage />,
},
];
export const defaultPath = "/dashboard";
// 派生分组导航(保持注册顺序)。
export function navGroups(): Array<{ group: string; items: RouteDef[] }> {
const out: Array<{ group: string; items: RouteDef[] }> = [];
for (const r of routes) {
let g = out.find((x) => x.group === r.group);
if (!g) {
g = { group: r.group, items: [] };
out.push(g);
}
g.items.push(r);
}
return out;
}