Files
Profeto/frontend/src/admin/routes.tsx
T
shangfangjian f71f29b4cb fix(frontend): 按审计报告修复全部17项问题,数据层迁至 src/api/
P0(4): 假数据清除(avg_latency_ms:2400→null,无端点字段改null)、假进度条改诚实的不确定态、
  公共页不再反向依赖 admin(api/public.ts)、PredictProgress 重写
P1(6): 23处 any 归零(对齐后端 Pydantic 契约新增 PredictionMatchRef/HealthProbe 等)、
  a11y(aria-live 0→4,htmlFor 1→17,aria-describedby/invalid 补齐)、App.tsx 抽 SiteLayout、
  路由级 lazy+代码分割(首屏 315KB→238KB)、index.html 补 SEO/favicon/OG、死代码清理(AdminIcon 抽出)
P2(7): Login/index.css 裸色值令牌化、groupByDate useMemo、滚动监听统一、原生控件基元化、
  useLeagues 静默失败补告警、路由级 ErrorBoundary

另修复审计未列问题:
- Monitoring todos 过滤器 t!==false 放行 null 导致整页崩溃 → Boolean(t) 真值过滤
- Collection 渲染期 Date.now()(react-hooks/purity 捕获)→ 计时器 effect
- bg-press-wash/60 透明度修饰符静默失效 → RGB 三元组 + 构建期令牌守卫(下个提交接入)

工程化:数据层 dal/api/types(1047行)git mv 至 src/api/,admin 留 @deprecated 兼容壳,
  21 个引用方直指新路径;tsconfig 开启 noUnusedLocals/noUnusedParameters(清理9处存量)
2026-09-22 23:45:06 +08:00

77 lines
2.9 KiB
TypeScript

/**
* Admin 后台 - 路由配置
*
* 所有 Admin 页面的路由定义,使用嵌套路由。
* 挂载路径: /admin/*
*
* 全部页面采用 `lazy` 动态导入。
*
* 此前这里是 10 个静态 import:App.tsx 引入 adminRoutes 就把
* Dashboard/Collection/Logs/Eval/Backtest/Settings/Monitoring/
* DataCompleteness/DataPipeline/PredictionHistory 连同它们的
* 数据访问层一次性拉进首屏 —— 一个只想看赛程的匿名访客,
* 要为完整的后台界面付出流量。改为 lazy 后,后台代码只在实际
* 访问 /admin/* 时才下载。
*
* AdminLayout 保持静态引入:它是所有后台页面的公共外壳,
* 若也 lazy 则会与页面 chunk 形成串行请求(先下载 layout,
* 再下载页面),反而更慢。
*/
import { lazy, Suspense } from 'react'
import type { ReactNode } from 'react'
import { Navigate } from 'react-router-dom'
import AdminLayout from './AdminLayout'
const Dashboard = lazy(() => import('./pages/Dashboard'))
const CollectionPage = lazy(() => import('./pages/Collection'))
const DataCompletenessPage = lazy(() => import('./pages/DataCompleteness'))
const DataPipelinePage = lazy(() => import('./pages/DataPipeline'))
const PredictionsPage = lazy(() => import('./pages/PredictionHistory'))
const BacktestPage = lazy(() => import('./pages/Backtest'))
const MonitoringPage = lazy(() => import('./pages/Monitoring'))
const SettingsPage = lazy(() => import('./pages/Settings'))
const LogsPage = lazy(() => import('./pages/Logs'))
const EvalPage = lazy(() => import('./pages/EvalPage'))
/**
* 页面级懒加载的兜底:后台各页共用。
* 保持极简,避免后台切换时出现大块占位跳动。
*/
function AdminPageFallback() {
return (
<div className="flex min-h-[40vh] items-center justify-center">
<span className="text-xs text-ink-400" role="status" aria-live="polite">
加载中…
</span>
</div>
)
}
/** 用 Suspense 包住单个后台页面 */
function page(node: ReactNode): ReactNode {
return <Suspense fallback={<AdminPageFallback />}>{node}</Suspense>
}
export const adminRoutes = [
{
path: '/admin',
element: <AdminLayout />,
children: [
{ index: true, element: page(<Dashboard />) },
{ path: 'collection', element: page(<CollectionPage />) },
{ path: 'data-completeness', element: page(<DataCompletenessPage />) },
{ path: 'data-pipeline', element: page(<DataPipelinePage />) },
{ path: 'predictions', element: page(<PredictionsPage />) },
{ path: 'backtest', element: page(<BacktestPage />) },
{ path: 'monitoring', element: page(<MonitoringPage />) },
{ path: 'settings', element: page(<SettingsPage />) },
{ path: 'logs', element: page(<LogsPage />) },
{ path: 'eval', element: page(<EvalPage />) },
{ path: '*', element: <Navigate to="/admin" replace /> },
],
},
]
export { adminRoutes as default }