unify Semi UI track evidence
This commit is contained in:
@@ -8,10 +8,12 @@ import { FormEvent, memo, useCallback, useEffect, useMemo, useRef, useState } fr
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { api } from '../../api/client';
|
||||
import type { TrackPlaybackEvent, TrackPlaybackResponse, VehicleRow } from '../../api/types';
|
||||
import { protocolDisplayLabel } from '../domain/protocols';
|
||||
import { buildTrackRailSelection, downloadTrackCsv, formatDuration, sampledEventIndex, TRACK_ADDRESS_SETTLE_MS, trackAddressCoordinate, trackPlaybackInterval, type TrackAddressCoordinate } from '../domain/track';
|
||||
import { TrackMap } from '../map/TrackMap';
|
||||
import { InlineError } from '../shared/AsyncState';
|
||||
import { MonitorReturnBar } from '../shared/MonitorReturnBar';
|
||||
import { ProtocolTag } from '../shared/ProtocolTag';
|
||||
import { SegmentedTabs } from '../shared/SegmentedTabs';
|
||||
import { VehicleCandidateList } from '../shared/VehicleCandidateList';
|
||||
import { mergeVehicleCandidates } from '../shared/vehicleCandidates';
|
||||
@@ -28,6 +30,12 @@ type PanelTab = 'stops' | 'events' | 'overview';
|
||||
type Draft = { keyword: string; dateFrom: string; dateTo: string; protocol: string };
|
||||
type TrackPreset = 'today' | 'yesterday' | 'three-days';
|
||||
const EMPTY_INDEXES: readonly number[] = [];
|
||||
const TRACK_SOURCE_OPTIONS = [
|
||||
{ value: '', label: '自动选择最佳来源' },
|
||||
{ value: 'GB32960', label: `${protocolDisplayLabel('GB32960')} · 仪表盘里程` },
|
||||
{ value: 'JT808', label: `${protocolDisplayLabel('JT808')} · GPS 里程` },
|
||||
{ value: 'YUTONG_MQTT', label: `${protocolDisplayLabel('YUTONG_MQTT')} · 仪表盘里程` }
|
||||
];
|
||||
const numberFormatters = new Map<number, Intl.NumberFormat>();
|
||||
const timeFormatter = new Intl.DateTimeFormat('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
||||
const dateTimeFormatter = new Intl.DateTimeFormat('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false, month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
||||
@@ -167,7 +175,7 @@ function OverviewPanel({ track }: { track: TrackPlaybackResponse }) {
|
||||
</section>
|
||||
<section className="v2-track-overview-section v2-track-source-card">
|
||||
<WorkspacePanelHeader variant="compact" title="数据来源" meta={<Tag color="blue" type="light" size="small">{track.coverage.totalPoints.toLocaleString('zh-CN')} 个源点</Tag>} />
|
||||
<div className="v2-track-overview-card-body"><List className="v2-track-source-list">{track.sources.map((source) => <List.Item className="v2-track-source-item" key={source.protocol}><Tag color="blue" type="light" size="small">{source.protocol}</Tag><strong>{source.pointCount.toLocaleString('zh-CN')} 点</strong><small>{time(source.startTime)}–{time(source.endTime)}</small></List.Item>)}</List></div>
|
||||
<div className="v2-track-overview-card-body"><List className="v2-track-source-list">{track.sources.map((source) => <List.Item className="v2-track-source-item" key={source.protocol}><ProtocolTag className="v2-track-protocol-tag" protocol={source.protocol} compact /><strong>{source.pointCount.toLocaleString('zh-CN')} 点</strong><small>{time(source.startTime)}–{time(source.endTime)}</small></List.Item>)}</List></div>
|
||||
</section>
|
||||
<section className={`v2-track-overview-section v2-track-quality-card is-${track.quality.status}`}>
|
||||
<WorkspacePanelHeader variant="compact" title="轨迹质量" meta={<Tag color={track.quality.status === 'good' ? 'green' : 'orange'} type="light" size="small">{track.quality.status === 'good' ? '通过' : '需关注'}</Tag>} />
|
||||
@@ -194,7 +202,7 @@ const TrackRail = memo(function TrackRail({ draft, track, loading, activeStopInd
|
||||
const activePreset = trackPreset(draft);
|
||||
const choosePreset = (daysBack: number) => onDraft({ ...draft, ...trackWindow(daysBack, daysBack > 0) });
|
||||
const appliedWindow = `${draft.dateFrom.replace('T', ' ').slice(5)} – ${draft.dateTo.replace('T', ' ').slice(5)}`;
|
||||
const appliedSource = draft.protocol || '自动来源';
|
||||
const appliedSource = draft.protocol ? protocolDisplayLabel(draft.protocol) : '自动来源';
|
||||
const contextTitle = queryCollapsed ? track?.plate || draft.keyword || '轨迹查询' : '轨迹查询';
|
||||
return <aside className="v2-track-rail">
|
||||
<Card className="v2-track-rail-shell" bodyStyle={{ padding: 0 }}>
|
||||
@@ -228,7 +236,7 @@ const TrackRail = memo(function TrackRail({ draft, track, loading, activeStopInd
|
||||
<Button theme={activePreset === 'three-days' ? 'solid' : 'light'} aria-pressed={activePreset === 'three-days'} onClick={() => { const end = new Date(); const start = new Date(end); start.setDate(start.getDate() - 2); start.setHours(0, 0, 0, 0); onDraft({ ...draft, dateFrom: localDateTime(start), dateTo: localDateTime(end) }); }}>近 3 天</Button>
|
||||
</div>
|
||||
<div className="v2-track-date-grid"><label><span>开始时间</span><Input aria-label="开始时间" type="datetime-local" value={draft.dateFrom} onChange={(value) => onDraft({ ...draft, dateFrom: value })} /></label><label><span>结束时间</span><Input aria-label="结束时间" type="datetime-local" value={draft.dateTo} onChange={(value) => onDraft({ ...draft, dateTo: value })} /></label></div>
|
||||
<label><span id="track-source-label">数据来源</span><Select aria-labelledby="track-source-label" value={draft.protocol} onChange={(value) => onDraft({ ...draft, protocol: String(value) })} optionList={[{ value: '', label: '自动选择最佳来源' }, { value: 'GB32960', label: 'GB32960 · 仪表盘里程' }, { value: 'JT808', label: 'JT808 · GPS 里程' }, { value: 'YUTONG_MQTT', label: 'YUTONG · 仪表盘里程' }]} /></label>
|
||||
<label><span id="track-source-label">数据来源</span><Select aria-labelledby="track-source-label" value={draft.protocol} onChange={(value) => onDraft({ ...draft, protocol: String(value) })} optionList={TRACK_SOURCE_OPTIONS} /></label>
|
||||
<Button className="v2-track-query-button" theme="solid" htmlType="submit" icon={<IconSearch />} loading={loading} disabled={!draft.keyword.trim()}>查询轨迹</Button>
|
||||
</form> : null}
|
||||
</section>
|
||||
@@ -413,7 +421,7 @@ export default function TrackPage() {
|
||||
<span><small>总里程</small><strong>{number(current?.totalMileageKm ?? 0)}<em> km</em></strong></span>
|
||||
</div>
|
||||
<div className={`v2-track-current-evidence v2-track-current-coverage${track.coverage.complete ? '' : ' is-warning'}`}>
|
||||
<Tag color="blue" type="light" size="small">{current?.protocol || '未知来源'}</Tag>
|
||||
<ProtocolTag className="v2-track-protocol-tag" protocol={current?.protocol} compact />
|
||||
<span title={track.coverage.evidence}><i /><strong>{track.coverage.complete ? '时间窗完整' : '最新切片'}</strong></span>
|
||||
<em>{track.coverage.processedPoints.toLocaleString('zh-CN')} → {track.coverage.returnedPoints.toLocaleString('zh-CN')} 点</em>
|
||||
<small>{alarm(current?.alarmFlag)}</small>
|
||||
|
||||
Reference in New Issue
Block a user