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 1907745e..e59c0e4b 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 @@ -276,6 +276,10 @@ test('uses a Semi bottom SideSheet for mobile track criteria and evidence', asyn 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)' }); + fireEvent.click(screen.getByRole('tab', { name: /事件点/ })); + await waitFor(() => expect(sheet).toHaveStyle({ height: 'min(82dvh, 450px)' })); + 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: '打开轨迹详情' })); 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 6704617f..4208af26 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx @@ -39,6 +39,9 @@ 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_ROW_HEIGHT_PX = 62; function number(value: number, digits = 1) { let formatter = numberFormatters.get(digits); @@ -116,6 +119,14 @@ function eventTone(type: string) { return 'info'; } +function mobileTrackSheetHeight(track: TrackPlaybackResponse | undefined, queryCollapsed: boolean, tab: PanelTab) { + if (!track || !queryCollapsed || tab === 'overview') return `min(82dvh, ${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)`; +} + function VehiclePicker({ value, onChange, onSelect }: { value: string; onChange: (value: string) => void; onSelect: (vehicle: VehicleRow) => void }) { const [open, setOpen] = useState(false); const [debounced, setDebounced] = useState(value.trim()); @@ -390,7 +401,7 @@ export default function TrackPage() { className="v2-track-detail-sidesheet" visible={!railCollapsed} placement="bottom" - height="min(82dvh, 720px)" + height={mobileTrackSheetHeight(track, queryCollapsed, panelTab)} aria-label="轨迹查询与明细" title={
轨迹查询与明细{track ? `${number(track.summary.distanceKm)} km · ${track.stops.length} 个停留 · ${track.events.length} 个事件` : '选择车辆和时间范围'}
} footer={null} 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 45cfcd19..14d2295d 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css @@ -3217,6 +3217,88 @@ } } +@media (max-width: 700px) and (max-height: 500px) and (orientation: landscape) { + .v2-track-current-card.semi-card, + .v2-track-page.is-rail-collapsed .v2-track-current-card.semi-card { + top: 6px; + right: auto; + bottom: auto; + left: 8px; + width: min(318px, 48vw); + min-width: 0; + border-radius: 10px; + } + + .v2-track-current-card .v2-workspace-panel-header { + min-height: 42px; + padding: 5px 8px; + } + + .v2-track-current-card .v2-workspace-panel-meta .semi-tag { + min-width: 40px; + padding-inline: 6px; + font-size: 9px; + } + + .v2-track-current-card > .semi-card-body > .v2-track-current-metrics > span { + padding: 5px 6px; + } + + .v2-track-current-card > .semi-card-body > .v2-track-current-metrics small { + font-size: 8px; + } + + .v2-track-current-card > .semi-card-body > .v2-track-current-metrics strong { + margin-top: 2px; + font-size: 12px; + } + + .v2-track-current-card > .semi-card-body > .v2-track-current-evidence { + min-height: 32px; + gap: 5px; + padding: 4px 7px; + } + + .v2-track-current-evidence > em { + display: none; + } + + .v2-track-stage-tools { + top: 6px; + right: 8px; + } + + .v2-track-page.is-mobile-layout .v2-track-playback-dock.semi-card, + .v2-track-page.is-mobile-layout .v2-track-playback-dock > .semi-card-body { + min-height: 88px; + } + + .v2-track-page.is-mobile-layout .v2-track-playback-dock > .semi-card-body { + gap: 6px; + padding: 6px 8px !important; + } + + .v2-track-page.is-mobile-layout .v2-track-progress-slider.semi-slider-wrapper { + margin-block: 6px 2px; + } + + .v2-track-stage:has(.v2-track-current-card) .v2-track-rail-expand { + top: 52px; + right: 8px; + bottom: auto; + left: auto; + min-width: 126px; + min-height: 38px; + padding: 5px 8px; + transform: none; + } + + .v2-track-rail-expand.semi-button .semi-icon { + width: 26px; + height: 26px; + } +} + /* Mileage workspace refinement: expose the active source strategy and keep the * mobile matrix dense without sacrificing the fixed plate/period columns. */ .v2-mileage-source-trigger .semi-button-content {