From fb7cb4c6d6fe5cda43355d409a2b9779f6323d4a Mon Sep 17 00:00:00 2001 From: lingniu Date: Sat, 18 Jul 2026 08:49:29 +0800 Subject: [PATCH] refine Semi UI track replay details --- .../apps/web/src/v2/pages/TrackPage.test.tsx | 23 +++++++++++++++---- .../apps/web/src/v2/pages/TrackPage.tsx | 15 +++++++----- 2 files changed, 28 insertions(+), 10 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 8f774eff..42d30b7d 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 @@ -106,7 +106,7 @@ test('keeps committed track criteria authoritative to same-route navigation and expect((await screen.findAllByText('粤A12345')).length).toBeGreaterThan(0); expect(screen.getByTestId('track-map')).toHaveAttribute('data-point-count', '3'); expect(screen.queryByRole('textbox', { name: '搜索轨迹车辆' })).not.toBeInTheDocument(); - expect(screen.getByText(/07-15 00:00/)).toBeInTheDocument(); + expect(screen.getAllByText(/07-15 00:00/).length).toBeGreaterThan(0); fireEvent.click(screen.getByRole('button', { name: '修改条件' })); expect(screen.getByRole('textbox', { name: '搜索轨迹车辆' })).toHaveValue('LTEST000000000001'); @@ -225,8 +225,8 @@ test('renders a map-first replay workspace and connects stop, event, and panel i expect(screen.queryByRole('textbox', { name: '搜索轨迹车辆' })).not.toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: '隐藏查询与明细' })); - expect(screen.getByRole('button', { name: '展开查询与明细' })).toBeInTheDocument(); - fireEvent.click(screen.getByRole('button', { name: '展开查询与明细' })); + expect(screen.getByRole('button', { name: '打开轨迹详情' })).toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: '打开轨迹详情' })); expect(screen.getByRole('button', { name: '隐藏查询与明细' })).toBeInTheDocument(); await waitFor(() => expect(mocks.trackPlayback).toHaveBeenCalledTimes(1)); @@ -246,7 +246,7 @@ test('uses a Semi bottom SideSheet for mobile track criteria and evidence', asyn expect((await screen.findAllByText('粤A12345')).length).toBeGreaterThan(0); expect(view.container.querySelector('.v2-track-page')).toHaveClass('is-mobile-layout', 'is-rail-collapsed'); expect(view.container.querySelector('.v2-track-page > .v2-track-stage')).toBeInTheDocument(); - fireEvent.click(screen.getByRole('button', { name: '展开查询与明细' })); + fireEvent.click(screen.getByRole('button', { name: '打开轨迹详情' })); const sheet = await waitFor(() => { const element = document.querySelector('.v2-track-detail-sidesheet .semi-sidesheet-inner'); @@ -255,9 +255,24 @@ test('uses a Semi bottom SideSheet for mobile track criteria and evidence', asyn }); expect(sheet).toHaveClass('semi-sidesheet-inner'); expect(document.querySelector('.v2-track-detail-sidesheet .v2-track-rail')).toBeInTheDocument(); + expect(document.querySelector('.v2-track-detail-sidesheet .v2-track-query-summary')).not.toBeInTheDocument(); + expect(screen.getByText('07-15 00:00 – 07-15 23:59 · 自动来源')).toBeInTheDocument(); + expect(screen.getByText('8 km · 1 个停留 · 3 个事件')).toBeInTheDocument(); expect(screen.getByRole('button', { name: '关闭轨迹查询与明细' })).toBeInTheDocument(); }); +test('keeps one clear mobile query entry before a vehicle is selected', async () => { + Object.defineProperty(window, 'matchMedia', { configurable: true, value: vi.fn(() => ({ matches: true, addEventListener: vi.fn(), removeEventListener: vi.fn() })) }); + const client = new QueryClient({ defaultOptions: { queries: { retry: false } } }); + render(); + + expect(await screen.findByRole('button', { name: /选择车辆/ })).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: '打开轨迹详情' })).not.toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: /选择车辆/ })); + expect(await screen.findByRole('dialog', { name: '轨迹查询与明细' })).toBeInTheDocument(); + expect(screen.getByRole('textbox', { name: '搜索轨迹车辆' })).toBeInTheDocument(); +}); + test('coalesces rapid track scrubbing into one address lookup for the final point', async () => { const client = new QueryClient({ defaultOptions: { queries: { retry: false } } }); render(); 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 d7f1b160..b21e3913 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx @@ -175,7 +175,7 @@ function OverviewPanel({ track }: { track: TrackPlaybackResponse }) { ; } -const TrackRail = memo(function TrackRail({ draft, track, loading, activeStopIndexes, activeEventIndexes, tab, queryCollapsed, onDraft, onSubmit, onTab, onSelectIndex, onToggleQuery, onCollapse }: { +const TrackRail = memo(function TrackRail({ draft, track, loading, activeStopIndexes, activeEventIndexes, tab, queryCollapsed, mobileLayout, onDraft, onSubmit, onTab, onSelectIndex, onToggleQuery, onCollapse }: { draft: Draft; track?: TrackPlaybackResponse; loading: boolean; @@ -183,6 +183,7 @@ const TrackRail = memo(function TrackRail({ draft, track, loading, activeStopInd activeEventIndexes: readonly number[]; tab: PanelTab; queryCollapsed: boolean; + mobileLayout: boolean; onDraft: (draft: Draft) => void; onSubmit: (event: FormEvent) => void; onTab: (tab: PanelTab) => void; @@ -192,13 +193,15 @@ 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 || '自动来源'; return