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处存量)
This commit is contained in:
@@ -3,36 +3,71 @@
|
||||
*
|
||||
* 所有 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'
|
||||
import Dashboard from './pages/Dashboard'
|
||||
import CollectionPage from './pages/Collection'
|
||||
import DataCompletenessPage from './pages/DataCompleteness'
|
||||
import PredictionsPage from './pages/PredictionHistory'
|
||||
import BacktestPage from './pages/Backtest'
|
||||
import MonitoringPage from './pages/Monitoring'
|
||||
import SettingsPage from './pages/Settings'
|
||||
import LogsPage from './pages/Logs'
|
||||
import EvalPage from './pages/EvalPage'
|
||||
import DataPipelinePage from './pages/DataPipeline'
|
||||
|
||||
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: <Dashboard /> },
|
||||
{ path: 'collection', element: <CollectionPage /> },
|
||||
{ path: 'data-completeness', element: <DataCompletenessPage /> },
|
||||
{ path: 'data-pipeline', element: <DataPipelinePage /> },
|
||||
{ path: 'predictions', element: <PredictionsPage /> },
|
||||
{ path: 'backtest', element: <BacktestPage /> },
|
||||
{ path: 'monitoring', element: <MonitoringPage /> },
|
||||
{ path: 'settings', element: <SettingsPage /> },
|
||||
{ path: 'logs', element: <LogsPage /> },
|
||||
{ path: 'eval', element: <EvalPage /> },
|
||||
{ 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 /> },
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user