侧边栏图标统一为线条SVG + hover品牌色过渡
- 新增 Icon 组件:8种线条风格 SVG 图标(collection/chart/target/repeat等) - 统一 stroke-width:1.5,hover 加粗到 2 - hover 时颜色平滑过渡到品牌色(press red) - 添加 .nav-icon 和 .nav-icon-wrap CSS 类 - 活跃/悬停态:opacity 0.5→1,stroke-width 1.5→2 Co-Authored-By: new-provider/LongCat-2.0 <<EMAIL>>
This commit is contained in:
co-authored by
new-provider/LongCat-2.0 <
parent
ad184e1b82
commit
857a21910b
@@ -12,6 +12,82 @@ import { fetchHealth } from './dal'
|
||||
import Login from './Login'
|
||||
import { useCommandPalette, CommandPalette } from './useCommandPalette'
|
||||
|
||||
// 线条风格 SVG 图标组件
|
||||
function Icon({ name }: { name: string }) {
|
||||
const common = 'nav-icon'
|
||||
switch (name) {
|
||||
case 'collection':
|
||||
return (
|
||||
<svg className={common} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
|
||||
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
|
||||
<line x1="12" y1="22.08" x2="12" y2="12" />
|
||||
</svg>
|
||||
)
|
||||
case 'chart':
|
||||
return (
|
||||
<svg className={common} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
|
||||
<line x1="18" y1="20" x2="18" y2="10" />
|
||||
<line x1="12" y1="20" x2="12" y2="4" />
|
||||
<line x1="6" y1="20" x2="6" y2="14" />
|
||||
</svg>
|
||||
)
|
||||
case 'target':
|
||||
return (
|
||||
<svg className={common} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<circle cx="12" cy="12" r="6" />
|
||||
<circle cx="12" cy="12" r="2" />
|
||||
</svg>
|
||||
)
|
||||
case 'repeat':
|
||||
return (
|
||||
<svg className={common} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polyline points="17 1 21 5 17 9" />
|
||||
<path d="M3 11V9a4 4 0 0 1 4-4h14" />
|
||||
<polyline points="7 23 3 19 7 15" />
|
||||
<path d="M21 13v2a4 4 0 0 1-4 4H3" />
|
||||
</svg>
|
||||
)
|
||||
case 'eval':
|
||||
return (
|
||||
<svg className={common} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
<line x1="16" y1="13" x2="8" y2="13" />
|
||||
<line x1="16" y1="17" x2="8" y2="17" />
|
||||
<polyline points="10 9 9 9 8 9" />
|
||||
</svg>
|
||||
)
|
||||
case 'monitor':
|
||||
return (
|
||||
<svg className={common} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
|
||||
<line x1="8" y1="21" x2="16" y2="21" />
|
||||
<line x1="12" y1="17" x2="12" y2="21" />
|
||||
</svg>
|
||||
)
|
||||
case 'settings':
|
||||
return (
|
||||
<svg className={common} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68 1.65 1.65 0 0 0 10 3.17V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0-4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
||||
</svg>
|
||||
)
|
||||
case 'logs':
|
||||
return (
|
||||
<svg className={common} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
<line x1="8" y1="13" x2="16" y2="13" />
|
||||
<line x1="8" y1="17" x2="16" y2="17" />
|
||||
</svg>
|
||||
)
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const NAV_PAGES: Array<{ to: string; label: string; group: string }> = [
|
||||
{ to: '/admin', label: '仪表盘', group: '概览' },
|
||||
{ to: '/admin/collection', label: '数据采集', group: '数据流水线' },
|
||||
@@ -37,29 +113,28 @@ const ROUTE_LABELS: Record<string, string> = {
|
||||
'/admin/eval': '评估',
|
||||
}
|
||||
|
||||
const NAV_SECTIONS: { title: string; items: { to: string; label: string; icon: string; end?: boolean }[] }[] = [
|
||||
const NAV_SECTIONS: { title: string; items: Array<{ to: string; label: string; icon: string }> }[] = [
|
||||
{
|
||||
title: '数据流水线',
|
||||
items: [
|
||||
{ to: '/admin/collection', label: '数据采集', icon: '◈' },
|
||||
{ to: '/admin/data-completeness', label: '数据完整性', icon: '◫' },
|
||||
{ to: '/admin/predictions', label: '预测管理', icon: '◆' },
|
||||
{ to: '/admin/backtest', label: '回测', icon: '◉' },
|
||||
{ to: '/admin/collection', label: '数据采集', icon: 'collection' },
|
||||
{ to: '/admin/data-completeness', label: '数据完整性', icon: 'chart' },
|
||||
{ to: '/admin/predictions', label: '预测管理', icon: 'target' },
|
||||
{ to: '/admin/backtest', label: '回测', icon: 'repeat' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '评估与监控',
|
||||
items: [
|
||||
{ to: '/admin/eval', label: '评估', icon: '◈' },
|
||||
{ to: '/admin/monitoring', label: '监控', icon: '◐' },
|
||||
{ to: '/admin/logs', label: '日志', icon: '▤' },
|
||||
{ to: '/admin/eval', label: '评估', icon: 'eval' },
|
||||
{ to: '/admin/monitoring', label: '监控', icon: 'monitor' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '系统设置',
|
||||
items: [
|
||||
{ to: '/admin/settings', label: '设置', icon: '◑' },
|
||||
{ to: '/admin/logs', label: '日志', icon: '▤' },
|
||||
{ to: '/admin/settings', label: '设置', icon: 'settings' },
|
||||
{ to: '/admin/logs', label: '日志', icon: 'logs' },
|
||||
],
|
||||
},
|
||||
]
|
||||
@@ -227,14 +302,14 @@ export default function AdminLayout() {
|
||||
to="/admin"
|
||||
end
|
||||
className={({ isActive }) =>
|
||||
`flex min-h-[40px] items-center gap-2.5 border-l-4 px-3 text-sm transition-all duration-300 ${
|
||||
`nav-icon-wrap flex min-h-[40px] items-center gap-2.5 border-l-4 px-3 text-sm transition-all duration-300 ${
|
||||
isActive
|
||||
? 'border-press bg-press-wash/60 font-medium text-press'
|
||||
? 'border-press bg-press-wash/60 font-medium text-press active'
|
||||
: 'border-transparent text-ink-500 hover:bg-paper-100 hover:text-ink-900'
|
||||
}`
|
||||
}
|
||||
>
|
||||
<span className="text-base leading-none opacity-50" aria-hidden="true">◇</span>
|
||||
<Icon name="chart" />
|
||||
仪表盘
|
||||
</NavLink>
|
||||
|
||||
@@ -249,16 +324,14 @@ export default function AdminLayout() {
|
||||
<NavLink
|
||||
to={item.to}
|
||||
className={({ isActive }) =>
|
||||
`flex min-h-[40px] items-center gap-2.5 border-l-4 px-3 pb-1 text-sm transition-all duration-300 ${
|
||||
`nav-icon-wrap flex min-h-[40px] items-center gap-2.5 border-l-4 px-3 text-sm transition-all duration-300 ${
|
||||
isActive
|
||||
? 'border-press bg-press-wash/60 font-medium text-press nav-tab-active'
|
||||
? 'border-press bg-press-wash/60 font-medium text-press active'
|
||||
: 'border-transparent text-ink-500 hover:bg-paper-100 hover:text-ink-900'
|
||||
}`
|
||||
}
|
||||
>
|
||||
<span className="text-base leading-none opacity-50" aria-hidden="true">
|
||||
{item.icon}
|
||||
</span>
|
||||
<Icon name={item.icon} />
|
||||
{item.label}
|
||||
</NavLink>
|
||||
</li>
|
||||
|
||||
@@ -157,6 +157,22 @@
|
||||
.skeleton {
|
||||
@apply animate-pulse rounded-none bg-ink-200;
|
||||
}
|
||||
|
||||
/* ── 侧边栏图标:统一样式 + hover过渡到品牌色 ── */
|
||||
.nav-icon {
|
||||
width: 1.125rem;
|
||||
height: 1.125rem;
|
||||
stroke-width: 1.5;
|
||||
flex-shrink: 0;
|
||||
opacity: 0.5;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.nav-icon-wrap:hover .nav-icon,
|
||||
.nav-icon-wrap.active .nav-icon {
|
||||
opacity: 1;
|
||||
color: #9E1B1B;
|
||||
stroke-width: 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Admin 后台 ──
|
||||
|
||||
Reference in New Issue
Block a user