fix: 管理后台页面修复

- AdminLayout: 侧边栏布局和导航修复
- dal.ts: 数据访问层 API 调用修复
- Dashboard: 仪表盘统计卡片和数据加载修复
- Backtest: 回测配置和结果展示修复
- LLMConfig: LLM 配置页面修复
- Predictions: 预测管理页面修复
This commit is contained in:
shangfangjian
2026-09-20 08:45:27 +08:00
parent 7b1457f0db
commit 78375d6e39
6 changed files with 223 additions and 182 deletions
+71 -46
View File
@@ -11,19 +11,31 @@ import { fetchAuthState, logout, UNAUTHORIZED_EVENT } from './api'
import { fetchHealth } from './dal'
import Login from './Login'
const NAV_ITEMS = [
// ── 观测(只读) ──
{ to: '/admin', label: '仪表盘', icon: '◇', end: true },
{ to: '/admin/eval', label: '评估', icon: '◈' },
{ to: '/admin/monitoring', label: '监控', icon: '' },
{ to: '/admin/logs', label: '日志', icon: '' },
// ── 操作(写入,需登录) ──
{ to: '/admin/predictions', label: '预测管理', icon: '◆' },
{ to: '/admin/collection', label: '数据采集', icon: '◈' },
{ to: '/admin/backtest', label: '回测', icon: '◉' },
{ to: '/admin/data-sources', label: '数据源', icon: '◫' },
{ to: '/admin/llm-config', label: 'LLM 配置', icon: '◬' },
{ to: '/admin/config', label: '系统配置', icon: '' },
const NAV_SECTIONS: { title: string; items: { to: string; label: string; icon: string; end?: boolean }[] }[] = [
{
title: '数据流水线',
items: [
{ to: '/admin/collection', label: '数据采集', icon: '' },
{ to: '/admin/predictions', label: '预测管理', icon: '' },
{ to: '/admin/backtest', label: '回测', icon: '◉' },
],
},
{
title: '评估与监控',
items: [
{ to: '/admin/eval', label: '评估', icon: '' },
{ to: '/admin/monitoring', label: '监控', icon: '◐' },
{ to: '/admin/logs', label: '日志', icon: '▤' },
],
},
{
title: '系统设置',
items: [
{ to: '/admin/data-sources', label: '数据源', icon: '◫' },
{ to: '/admin/llm-config', label: 'LLM 配置', icon: '◬' },
{ to: '/admin/config', label: '系统配置', icon: '◑' },
],
},
]
/** 报眉日期行,与前台同款式 */
@@ -139,45 +151,65 @@ export default function AdminLayout() {
<span className="text-2xs tracking-[0.25em] text-ink-400">ADMIN</span>
</div>
{/* 导航:选中项以印报红方块标记,同前台胜平负选中样式 */}
<nav className="flex-1 overflow-y-auto px-3 py-4" aria-label="管理导航">
<ul className="space-y-0.5">
{NAV_ITEMS.map(item => (
<li key={item.to}>
<NavLink
to={item.to}
end={item.end}
className={({ isActive }) =>
`flex min-h-[44px] items-center gap-2.5 px-3 py-2.5 text-sm transition-colors ${
isActive
? 'bg-press-wash/60 font-medium text-press'
: 'text-ink-500 hover:bg-paper-100 hover:text-ink-900'
}`
}
>
{({ isActive }) => (
<>
{/* 导航:分组 + 小节标题 */}
<nav className="flex-1 overflow-y-auto px-3 py-3" aria-label="管理导航">
{/* 仪表盘独立(始终第一项) */}
<NavLink
to="/admin"
end
className={({ isActive }) =>
`flex min-h-[40px] items-center gap-2.5 px-3 text-sm transition-colors ${
isActive
? 'bg-press-wash/60 font-medium text-press'
: 'text-ink-500 hover:bg-paper-100 hover:text-ink-900'
}`
}
>
<span className="text-base leading-none opacity-50" aria-hidden="true"></span>
</NavLink>
{NAV_SECTIONS.map(section => (
<div key={section.title} className="mt-4">
<p className="mb-1 px-3 text-2xs font-medium uppercase tracking-widest text-ink-400">
{section.title}
</p>
<ul className="space-y-0.5">
{section.items.map(item => (
<li key={item.to}>
<NavLink
to={item.to}
className={({ isActive }) =>
`flex min-h-[40px] items-center gap-2.5 px-3 text-sm transition-colors ${
isActive
? 'bg-press-wash/60 font-medium text-press'
: 'text-ink-500 hover:bg-paper-100 hover:text-ink-900'
}`
}
>
<span
className={`inline-block h-1.5 w-1.5 flex-shrink-0 ${isActive ? 'bg-press' : 'bg-transparent'}`}
className={`inline-block h-1.5 w-1.5 flex-shrink-0 ${
location.pathname.startsWith(item.to) ? 'bg-press' : 'bg-transparent'
}`}
aria-hidden="true"
/>
<span className="text-base leading-none opacity-50" aria-hidden="true">
{item.icon}
</span>
{item.label}
</>
)}
</NavLink>
</li>
))}
</ul>
</NavLink>
</li>
))}
</ul>
</div>
))}
</nav>
{/* 底部 */}
<div className="border-t border-ink-200 px-4 py-3">
<a
href="/"
className="flex min-h-[44px] items-center gap-2 text-xs text-ink-500 transition-colors hover:text-press"
className="flex min-h-[36px] items-center gap-2 text-xs text-ink-500 transition-colors hover:text-press"
>
<span aria-hidden="true"></span>
@@ -212,13 +244,6 @@ export default function AdminLayout() {
/>
{healthOk === null ? '检测中' : healthOk ? '系统正常' : '系统异常'}
</span>
<a
href="/"
className="text-press transition-colors hover:text-press-dark sm:hidden"
aria-label="返回前台"
>
</a>
<button
onClick={handleLogout}
className="text-ink-500 transition-colors hover:text-press"