From fd5e16c36c7aadf146be62b7b42f002785ff9e8f Mon Sep 17 00:00:00 2001 From: lingniu Date: Sat, 18 Jul 2026 22:05:21 +0800 Subject: [PATCH] unify Semi UI track evidence --- .../apps/web/src/v2/pages/TrackPage.test.tsx | 8 +++++++- .../apps/web/src/v2/pages/TrackPage.tsx | 16 ++++++++++++---- .../apps/web/src/v2/styles/v2.css | 4 ++-- .../apps/web/src/v2/styles/workspace.css | 4 ++++ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.test.tsx index 6f24a4d8..1907745e 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.test.tsx @@ -185,7 +185,8 @@ test('renders a map-first replay workspace and connects stop, event, and panel i expect(view.container.querySelector('.v2-track-current-card.semi-card')).toBeInTheDocument(); expect(view.container.querySelector('.v2-track-current-coverage')).toBeInTheDocument(); expect(view.container.querySelectorAll('.v2-track-current-metrics > span')).toHaveLength(4); - expect(view.container.querySelector('.v2-track-current-evidence')).toHaveTextContent('JT808时间窗完整3 → 3 点报警 —'); + expect(view.container.querySelector('.v2-track-current-evidence')).toHaveTextContent('JT/T 808时间窗完整3 → 3 点报警 —'); + expect(view.container.querySelector('.v2-track-current-evidence .v2-track-protocol-tag')).toHaveClass('semi-tag-cyan-light'); expect(view.container.querySelector('.v2-track-coverage-float')).not.toBeInTheDocument(); expect(screen.getByRole('toolbar', { name: '地图轨迹工具' })).toBeInTheDocument(); expect(view.container.querySelector('.v2-track-playback-dock.semi-card')).toBeInTheDocument(); @@ -216,6 +217,8 @@ test('renders a map-first replay workspace and connects stop, event, and panel i expect(view.container.querySelector('.v2-track-overview-descriptions.semi-descriptions')).toBeInTheDocument(); expect(view.container.querySelector('.v2-track-source-list.semi-list')).toBeInTheDocument(); expect(view.container.querySelectorAll('.v2-track-source-item.semi-list-item')).toHaveLength(1); + expect(view.container.querySelector('.v2-track-source-item .v2-track-protocol-tag')).toHaveTextContent('JT/T 808'); + expect(view.container.querySelector('.v2-track-source-item .v2-track-protocol-tag')).toHaveClass('semi-tag-cyan-light'); expect(screen.getByText('完整点集').closest('.semi-tag')).toBeInTheDocument(); expect(screen.getByText('通过').closest('.semi-tag')).toBeInTheDocument(); @@ -228,6 +231,9 @@ test('renders a map-first replay workspace and connects stop, event, and panel i fireEvent.click(screen.getByRole('button', { name: '修改条件' })); expect(screen.getByRole('textbox', { name: '搜索轨迹车辆' })).toHaveValue('LTEST000000000001'); + expect(screen.getByRole('option', { name: 'GB/T 32960 · 仪表盘里程' })).toBeInTheDocument(); + expect(screen.getByRole('option', { name: 'JT/T 808 · GPS 里程' })).toBeInTheDocument(); + expect(screen.getByRole('option', { name: '宇通 MQTT · 仪表盘里程' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: '收起条件' })).toHaveAttribute('aria-expanded', 'true'); fireEvent.click(screen.getByRole('button', { name: '收起条件' })); expect(screen.queryByRole('textbox', { name: '搜索轨迹车辆' })).not.toBeInTheDocument(); diff --git a/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx index a1ba3836..6704617f 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx @@ -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(); 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 }) {
{track.coverage.totalPoints.toLocaleString('zh-CN')} 个源点} /> -
{track.sources.map((source) => {source.protocol}{source.pointCount.toLocaleString('zh-CN')} 点{time(source.startTime)}–{time(source.endTime)})}
+
{track.sources.map((source) => {source.pointCount.toLocaleString('zh-CN')} 点{time(source.startTime)}–{time(source.endTime)})}
{track.quality.status === 'good' ? '通过' : '需关注'}} /> @@ -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
@@ -413,7 +421,7 @@ export default function TrackPage() { 总里程{number(current?.totalMileageKm ?? 0)} km
- {current?.protocol || '未知来源'} + {track.coverage.complete ? '时间窗完整' : '最新切片'} {track.coverage.processedPoints.toLocaleString('zh-CN')} → {track.coverage.returnedPoints.toLocaleString('zh-CN')} 点 {alarm(current?.alarmFlag)} diff --git a/vehicle-data-platform/apps/web/src/v2/styles/v2.css b/vehicle-data-platform/apps/web/src/v2/styles/v2.css index 4bf98d91..fe294e2c 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/v2.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/v2.css @@ -8906,7 +8906,7 @@ button, a { -webkit-tap-highlight-color: transparent; } background: linear-gradient(135deg, #f8fafc 0%, #f4f8fd 100%); padding: 8px 9px; } -.v2-track-source-item .semi-tag { width: max-content; max-width: 100%; overflow: hidden; border-radius: 6px; font-size: 8px; text-overflow: ellipsis; white-space: nowrap; } +.v2-track-source-item .v2-track-protocol-tag.semi-tag { width: max-content; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .v2-track-source-item > strong { color: #3e526a; font-size: 10px; text-align: right; font-variant-numeric: tabular-nums; } .v2-track-source-item > small { grid-column: 1 / -1; color: #8795a7; font-size: 8px; font-variant-numeric: tabular-nums; } @@ -8917,7 +8917,7 @@ button, a { -webkit-tap-highlight-color: transparent; } .v2-track-evidence-list button small, .v2-track-evidence-list .v2-track-list-action .semi-button-content > em { font-size: 10px; } .v2-track-source-list .v2-track-source-item.semi-list-item { min-height: 54px; padding: 9px 10px; } - .v2-track-source-item .semi-tag, + .v2-track-source-item .v2-track-protocol-tag.semi-tag, .v2-track-source-item > small { font-size: 9px; } .v2-track-source-item > strong { font-size: 11px; } } diff --git a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css index 722ae7f7..280bb108 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css @@ -814,6 +814,10 @@ font-size: 10px; } +.v2-track-current-evidence .v2-track-protocol-tag.semi-tag { + border-radius: 999px; +} + .v2-track-current-evidence > span { display: inline-flex; min-width: 0;