import { Button, Input, Nav, Space, Tag, Toast } from '@douyinfe/semi-ui'; import { IconActivity, IconBarChartHStroked, IconHistogram, IconHome, IconMapPin, IconSearch, IconServer, IconSetting, IconBell, IconPulse } from '@douyinfe/semi-icons'; import type { ReactNode } from 'react'; import { useState } from 'react'; import type { VehicleSourceConsistency, VehicleServiceStatus } from '../api/types'; import { isAMapConfigured } from '../config/appConfig'; export type PageKey = 'dashboard' | 'vehicles' | 'map' | 'realtime' | 'detail' | 'history' | 'history-query' | 'mileage' | 'alert-events' | 'quality' | 'notification-rules' | 'ops-quality'; const navGroups = [ { title: '实时运营', audience: '客户', description: '地图看车、在线监控、异常优先', items: [ { itemKey: 'dashboard', text: '运营总览', icon: }, { itemKey: 'map', text: '实时地图', icon: }, { itemKey: 'realtime', text: '实时监控', icon: } ] }, { title: '车辆服务', audience: '客户', description: '按 VIN、车牌、手机号管理车辆', items: [ { itemKey: 'vehicles', text: '车辆中心', icon: }, { itemKey: 'detail', text: '车辆档案', icon: } ] }, { title: '轨迹统计', audience: '客户', description: '回放轨迹、统计查询、导出数据', items: [ { itemKey: 'history', text: '轨迹回放', icon: }, { itemKey: 'mileage', text: '统计查询', icon: }, { itemKey: 'history-query', text: '数据导出', icon: } ] }, { title: '告警通知', audience: '客户', description: '断链、离线、定位异常和通知升级', items: [ { itemKey: 'alert-events', text: '告警事件', icon: }, { itemKey: 'notification-rules', text: '通知规则', icon: } ] }, { title: '接入运维', audience: '内部', description: '客户主流程外查看链路质量', items: [ { itemKey: 'ops-quality', text: '运维质量', icon: } ] } ]; const customerPrimaryPath = [ { label: '车辆地图', page: 'map' as const }, { label: '轨迹回放', page: 'history' as const }, { label: '统计查询', page: 'mileage' as const }, { label: '数据导出', page: 'history-query' as const }, { label: '告警通知', page: 'alert-events' as const } ]; const customerTaskPath = [ { label: '地图看车', question: '车辆在哪里', page: 'map' as const }, { label: '轨迹回放', question: '这段时间怎么跑', page: 'history' as const }, { label: '统计查询', question: '里程怎么算', page: 'mileage' as const }, { label: '数据导出', question: '证据怎么给客户', page: 'history-query' as const }, { label: '告警通知', question: '异常谁处理', page: 'alert-events' as const } ]; function linkHealthClassName(count: number | null) { if (count == null) { return ''; } return count > 0 ? 'vp-link-health-button-warning' : 'vp-link-health-button-ok'; } function alertButtonLabel(linkIssueCount: number | null, activeRuleCount?: number | null, p0RuleCount?: number | null) { const activeCount = Number.isFinite(Number(activeRuleCount)) ? Number(activeRuleCount) : 0; const p0Count = Number.isFinite(Number(p0RuleCount)) ? Number(p0RuleCount) : 0; if (p0Count > 0) { return `告警事件 P0 ${p0Count.toLocaleString()} / 活跃 ${activeCount.toLocaleString()}`; } if (activeCount > 0) { return `告警事件 ${activeCount.toLocaleString()}类规则`; } if (linkIssueCount == null) { return '告警事件'; } return linkIssueCount > 0 ? `告警事件 ${linkIssueCount}项关注` : '告警事件正常'; } function alertButtonClassName(linkIssueCount: number | null, activeRuleCount?: number | null, p0RuleCount?: number | null) { const activeCount = Number.isFinite(Number(activeRuleCount)) ? Number(activeRuleCount) : 0; const p0Count = Number.isFinite(Number(p0RuleCount)) ? Number(p0RuleCount) : 0; if (p0Count > 0 || activeCount > 0 || (linkIssueCount ?? 0) > 0) { return 'vp-link-health-button-warning'; } return linkHealthClassName(linkIssueCount); } function customerStatusTitle(title?: string) { if (!title) { return ''; } return title === '来源不完整' ? '数据通道不完整' : title; } function dateText(offsetDays = 0) { const date = new Date(); date.setHours(0, 0, 0, 0); date.setDate(date.getDate() + offsetDays); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } export function AppShell({ activePage, linkIssueCount, activeAlertRuleCount, p0AlertRuleCount, platformRelease, currentVehicleStatus, currentVehicleLabel, currentVehicleConsistency, customerTimeWindow, onCustomerTimeWindowChange, onCopyCustomerScope, onChange, onCustomerTask, onVehicleSearch, children }: { activePage: PageKey; linkIssueCount: number | null; activeAlertRuleCount?: number | null; p0AlertRuleCount?: number | null; platformRelease?: string; currentVehicleStatus?: VehicleServiceStatus; currentVehicleLabel?: string; currentVehicleConsistency?: VehicleSourceConsistency; customerTimeWindow?: Record; onCustomerTimeWindowChange?: (filters: Record) => void; onCopyCustomerScope?: () => void; onChange: (page: PageKey) => void; onCustomerTask?: (page: PageKey) => void; onVehicleSearch: (keyword: string) => void | Promise; children: ReactNode; }) { const [keyword, setKeyword] = useState(''); const [searching, setSearching] = useState(false); const amapConfigured = isAMapConfigured(); const alertLabel = alertButtonLabel(linkIssueCount, activeAlertRuleCount, p0AlertRuleCount); const alertClassName = alertButtonClassName(linkIssueCount, activeAlertRuleCount, p0AlertRuleCount); const selectedPage = activePage === 'quality' ? 'alert-events' : activePage; const dateFrom = customerTimeWindow?.dateFrom ?? ''; const dateTo = customerTimeWindow?.dateTo ?? ''; const applyTimeWindowPreset = (days: number) => { onCustomerTimeWindowChange?.({ dateFrom: dateText(-(days - 1)), dateTo: dateText() }); }; const search = () => { const value = keyword.trim(); if (!value) { Toast.warning('请输入 VIN / 车牌 / 手机号'); return; } setSearching(true); Promise.resolve(onVehicleSearch(value)).finally(() => setSearching(false)); }; const quickActions = [ { label: '地图', ariaLabel: '顶部地图态势', page: 'map' as const }, { label: '监控', ariaLabel: '顶部实时监控', page: 'realtime' as const }, { label: '轨迹', ariaLabel: '顶部轨迹回放', page: 'history' as const }, { label: '统计', ariaLabel: '顶部统计查询', page: 'mileage' as const }, { label: '导出', ariaLabel: '顶部数据导出', page: 'history-query' as const }, { label: '告警', ariaLabel: '顶部告警事件', page: 'alert-events' as const } ]; return (
} placeholder="搜索 VIN / 车牌 / 手机号" value={keyword} onChange={setKeyword} onEnterPress={search} style={{ width: 320 }} />
{currentVehicleLabel ? {currentVehicleLabel} : null} {currentVehicleStatus ? ( 当前车辆:{customerStatusTitle(currentVehicleStatus.title)} ) : null} {currentVehicleConsistency ? ( 一致性:{customerStatusTitle(currentVehicleConsistency.title) || `${currentVehicleConsistency.onlineSourceCount}/${currentVehicleConsistency.sourceCount} 数据通道`} ) : null} {amapConfigured ? '高德地图就绪' : '高德地图待配置'}
{quickActions.map((item) => ( ))}
{platformRelease ? 版本 {platformRelease} : null}
{children}
); }