From af71468e63ac3d2798fd5e4d4031bfd0897d7836 Mon Sep 17 00:00:00 2001 From: lingniu Date: Sun, 19 Jul 2026 07:58:51 +0800 Subject: [PATCH] feat: unify mobile track workspace --- .../apps/web/src/v2/pages/TrackPage.test.tsx | 18 ++++-- .../apps/web/src/v2/pages/TrackPage.tsx | 62 +++++++++++++++---- .../apps/web/src/v2/productionEntry.test.ts | 3 + .../apps/web/src/v2/styles/workspace.css | 27 +++++++- 4 files changed, 89 insertions(+), 21 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 8abbb6c6..69151500 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 @@ -270,23 +270,28 @@ test('uses the shared Semi editor SideSheet for mobile track criteria and eviden return element; }); expect(sheet).toHaveClass('semi-sidesheet-inner'); + expect(sheet).toHaveAttribute('id', 'v2-track-mobile-workbench'); expect(document.querySelector('.v2-track-detail-sidesheet')).toHaveClass('v2-workspace-editor-sidesheet', 'semi-sidesheet-bottom'); 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.getByLabelText('轨迹查询任务栏')).toHaveTextContent('粤A12345'); + expect(screen.queryByLabelText('轨迹查询任务栏')).not.toBeInTheDocument(); expect(screen.queryByRole('textbox', { name: '搜索轨迹车辆' })).not.toBeInTheDocument(); - expect(screen.getByText('07-15 00:00 – 07-15 23:59 · 自动来源')).toBeInTheDocument(); - expect(screen.getByText('8 km · 1 个停留 · 3 个事件')).toBeInTheDocument(); - expect(sheet).toHaveStyle({ height: 'min(82dvh, 326px)' }); + expect(screen.getAllByText('07-15 00:00 – 07-15 23:59 · 自动来源')).toHaveLength(2); + expect(screen.getByRole('list', { name: '轨迹查询与明细摘要' })).toHaveTextContent('行程里程8 km00:20:00停留 / 事件1 / 3地图证据点数据点3时间窗完整'); + expect(screen.getByRole('button', { name: '修改轨迹查询' })).toHaveTextContent('修改查询'); + expect(screen.getByRole('button', { name: /查看地图$/ })).toBeInTheDocument(); + expect(sheet).toHaveStyle({ height: 'min(88dvh, 394px)' }); fireEvent.click(screen.getByRole('tab', { name: /事件点/ })); - await waitFor(() => expect(sheet).toHaveStyle({ height: 'min(82dvh, 450px)' })); + await waitFor(() => expect(sheet).toHaveStyle({ height: 'min(88dvh, 518px)' })); fireEvent.click(screen.getByRole('tab', { name: /停留点/ })); fireEvent.click(screen.getByRole('button', { name: /停留 00:05:00/ })); expect(view.container.querySelector('.v2-track-page')).toHaveClass('is-rail-collapsed'); fireEvent.click(screen.getByRole('button', { name: '打开轨迹详情' })); await screen.findByRole('dialog', { name: '轨迹查询与明细' }); - fireEvent.click(screen.getByRole('button', { name: '修改条件' })); + fireEvent.click(screen.getByRole('button', { name: '修改轨迹查询' })); expect(screen.getByRole('textbox', { name: '搜索轨迹车辆' })).toHaveValue('LTEST000000000001'); + expect(screen.getByRole('button', { name: '收起轨迹查询' })).toHaveTextContent('收起查询'); + expect(sheet).toHaveStyle({ height: 'min(88dvh, 780px)' }); expect(screen.getByRole('button', { name: '关闭轨迹查询与明细' })).toBeInTheDocument(); }); @@ -299,6 +304,7 @@ test('keeps one clear mobile query entry before a vehicle is selected', async () expect(screen.queryByRole('button', { name: '打开轨迹详情' })).not.toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: /选择车辆/ })); expect(await screen.findByRole('dialog', { name: '轨迹查询与明细' })).toBeInTheDocument(); + expect(screen.getByRole('list', { name: '轨迹查询与明细摘要' })).toHaveTextContent('查询状态待查询请先选择车辆'); expect(screen.getByRole('textbox', { name: '搜索轨迹车辆' })).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 fdb461d7..7788443a 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx @@ -39,8 +39,8 @@ const TRACK_SOURCE_OPTIONS = [ 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' }); -const TRACK_SHEET_MAX_HEIGHT_PX = 720; -const TRACK_SHEET_CHROME_HEIGHT_PX = 264; +const TRACK_SHEET_MAX_HEIGHT_PX = 780; +const TRACK_SHEET_CHROME_HEIGHT_PX = 332; const TRACK_SHEET_ROW_HEIGHT_PX = 62; function number(value: number, digits = 1) { @@ -120,11 +120,11 @@ function eventTone(type: string) { } function mobileTrackSheetHeight(track: TrackPlaybackResponse | undefined, queryCollapsed: boolean, tab: PanelTab) { - if (!track || !queryCollapsed || tab === 'overview') return `min(82dvh, ${TRACK_SHEET_MAX_HEIGHT_PX}px)`; + if (!track || !queryCollapsed || tab === 'overview') return `min(88dvh, ${TRACK_SHEET_MAX_HEIGHT_PX}px)`; const itemCount = tab === 'stops' ? track.stops.length : track.events.length; const visibleRows = itemCount ? Math.min(itemCount, 7) : 2; const contentHeight = Math.min(TRACK_SHEET_MAX_HEIGHT_PX, TRACK_SHEET_CHROME_HEIGHT_PX + visibleRows * TRACK_SHEET_ROW_HEIGHT_PX); - return `min(82dvh, ${contentHeight}px)`; + return `min(88dvh, ${contentHeight}px)`; } function VehiclePicker({ value, onChange, onSelect }: { value: string; onChange: (value: string) => void; onSelect: (vehicle: VehicleRow) => void }) { @@ -195,7 +195,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, showCommandBar, onDraft, onSubmit, onTab, onSelectIndex, onToggleQuery, onCollapse }: { draft: Draft; track?: TrackPlaybackResponse; loading: boolean; @@ -203,6 +203,7 @@ const TrackRail = memo(function TrackRail({ draft, track, loading, activeStopInd activeEventIndexes: readonly number[]; tab: PanelTab; queryCollapsed: boolean; + showCommandBar: boolean; onDraft: (draft: Draft) => void; onSubmit: (event: FormEvent) => void; onTab: (tab: PanelTab) => void; @@ -217,8 +218,8 @@ const TrackRail = memo(function TrackRail({ draft, track, loading, activeStopInd const contextTitle = queryCollapsed ? track?.plate || draft.keyword || '轨迹查询' : '轨迹查询'; return