99 lines
3.0 KiB
TypeScript
99 lines
3.0 KiB
TypeScript
import { Button, Input, Nav, Space, Tag, Toast } from '@douyinfe/semi-ui';
|
|
import {
|
|
IconActivity,
|
|
IconBarChartHStroked,
|
|
IconHistogram,
|
|
IconHome,
|
|
IconMapPin,
|
|
IconSearch,
|
|
IconServer,
|
|
IconSetting
|
|
} from '@douyinfe/semi-icons';
|
|
import type { ReactNode } from 'react';
|
|
import { useState } from 'react';
|
|
|
|
export type PageKey = 'dashboard' | 'vehicles' | 'realtime' | 'detail' | 'history' | 'mileage' | 'quality';
|
|
|
|
const navItems = [
|
|
{ itemKey: 'dashboard', text: '总览工作台', icon: <IconHome /> },
|
|
{ itemKey: 'vehicles', text: '车辆台账', icon: <IconServer /> },
|
|
{ itemKey: 'realtime', text: '实时状态', icon: <IconActivity /> },
|
|
{ itemKey: 'detail', text: '车辆详情', icon: <IconSetting /> },
|
|
{ itemKey: 'history', text: '历史查询', icon: <IconMapPin /> },
|
|
{ itemKey: 'mileage', text: '里程分析', icon: <IconBarChartHStroked /> },
|
|
{ itemKey: 'quality', text: '数据质量', icon: <IconHistogram /> }
|
|
];
|
|
|
|
function linkHealthClassName(count: number | null) {
|
|
if (count == null) {
|
|
return '';
|
|
}
|
|
return count > 0 ? 'vp-link-health-button-warning' : 'vp-link-health-button-ok';
|
|
}
|
|
|
|
export function AppShell({
|
|
activePage,
|
|
linkIssueCount,
|
|
onChange,
|
|
onVehicleSearch,
|
|
children
|
|
}: {
|
|
activePage: PageKey;
|
|
linkIssueCount: number | null;
|
|
onChange: (page: PageKey) => void;
|
|
onVehicleSearch: (keyword: string) => void;
|
|
children: ReactNode;
|
|
}) {
|
|
const [keyword, setKeyword] = useState('');
|
|
|
|
const search = () => {
|
|
const value = keyword.trim();
|
|
if (!value) {
|
|
Toast.warning('请输入 VIN / 车牌 / 手机号');
|
|
return;
|
|
}
|
|
onVehicleSearch(value);
|
|
};
|
|
|
|
return (
|
|
<div className="vp-app">
|
|
<div className="vp-shell">
|
|
<aside className="vp-sidebar">
|
|
<div className="vp-brand">
|
|
<span className="vp-brand-mark" />
|
|
<span>车辆数据中台</span>
|
|
</div>
|
|
<Nav
|
|
selectedKeys={[activePage]}
|
|
items={navItems}
|
|
onSelect={({ itemKey }) => onChange(itemKey as PageKey)}
|
|
style={{ maxWidth: '100%' }}
|
|
/>
|
|
</aside>
|
|
<main className="vp-main">
|
|
<header className="vp-topbar">
|
|
<Space spacing={12}>
|
|
<Input
|
|
prefix={<IconSearch />}
|
|
placeholder="搜索 VIN / 车牌 / 手机号"
|
|
value={keyword}
|
|
onChange={setKeyword}
|
|
onEnterPress={search}
|
|
style={{ width: 320 }}
|
|
/>
|
|
<Button theme="solid" type="primary" onClick={search}>查询车辆</Button>
|
|
</Space>
|
|
<Space spacing={12}>
|
|
<Tag color="blue">生产环境</Tag>
|
|
<Button size="small" className={linkHealthClassName(linkIssueCount)} onClick={() => onChange('quality')}>
|
|
{linkIssueCount == null ? '链路监控' : linkIssueCount > 0 ? `链路 ${linkIssueCount} 项关注` : '链路正常'}
|
|
</Button>
|
|
</Space>
|
|
</header>
|
|
{children}
|
|
</main>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|