feat: build vehicle data platform and production pipeline

This commit is contained in:
lingniu
2026-07-14 12:35:33 +08:00
parent b452be3b94
commit bb59303a4b
270 changed files with 88016 additions and 1975 deletions

View File

@@ -0,0 +1,88 @@
import {
IconAlarm,
IconBarChartHStroked,
IconBox,
IconChevronLeft,
IconHelpCircle,
IconHome,
IconMapPin,
IconSearch,
IconSetting,
IconUser,
IconExit
} from '@douyinfe/semi-icons';
import { useState } from 'react';
import { NavLink, Outlet, useLocation } from 'react-router-dom';
import { usePlatformSession } from '../auth/AuthGate';
const navigation = [
{ to: '/monitor', label: '全局监控', icon: IconHome },
{ to: '/vehicles', label: '车辆查询', icon: IconSearch },
{ to: '/tracks', label: '轨迹回放', icon: IconMapPin },
{ to: '/history', label: '历史数据', icon: IconBarChartHStroked },
{ to: '/alerts', label: '告警中心', icon: IconAlarm },
{ to: '/access', label: '接入管理', icon: IconBox }
];
const pageNames: Record<string, string> = {
monitor: '全局监控',
vehicles: '车辆查询',
tracks: '轨迹回放',
history: '历史数据',
alerts: '告警中心',
access: '接入管理',
operations: '运维质量'
};
export function AppShell() {
const location = useLocation();
const section = location.pathname.split('/')[1] || 'monitor';
const { session, logout } = usePlatformSession();
const roleLabel = { viewer: '只读', operator: '处置员', admin: '管理员' }[session.role];
return (
<div className="v2-shell">
<Sidebar />
<div className="v2-main">
<header className="v2-topbar">
<h1>{pageNames[section] ?? '车辆数据中台'}</h1>
<div className="v2-topbar-actions">
<button type="button" aria-label="帮助"><IconHelpCircle /></button>
<span className="v2-current-user"><IconUser /><b>{session.name}</b><small>{roleLabel}</small></span>
<button type="button" aria-label="退出登录" title="退出登录" onClick={logout}><IconExit /></button>
</div>
</header>
<main className="v2-content"><Outlet /></main>
</div>
</div>
);
}
function Sidebar() {
const [collapsed, setCollapsed] = useState(false);
return (
<aside className={`v2-sidebar${collapsed ? ' is-collapsed' : ''}`}>
<div className="v2-brand">
<span className="v2-brand-mark"><IconBox size="large" /></span>
<strong></strong>
</div>
<nav className="v2-navigation" aria-label="主导航">
{navigation.map(({ to, label, icon: Icon }) => (
<NavLink key={to} to={to} className={({ isActive }) => `v2-nav-item ${isActive ? 'is-active' : ''}`}>
<Icon size="large" />
<span className="v2-nav-label">{label}</span>
</NavLink>
))}
</nav>
<NavLink to="/operations" className={({ isActive }) => `v2-nav-item v2-nav-operations ${isActive ? 'is-active' : ''}`}>
<IconSetting size="large" />
<span className="v2-nav-label"></span>
</NavLink>
<button className="v2-collapse" type="button" onClick={() => setCollapsed((value) => !value)} aria-label={collapsed ? '展开侧栏' : '收起侧栏'}>
<IconChevronLeft />
<span></span>
</button>
</aside>
);
}