From 319728f976885087979b85cff385472dc82d852a Mon Sep 17 00:00:00 2001 From: lingniu Date: Mon, 20 Jul 2026 02:15:08 +0800 Subject: [PATCH] feat(web): unify track and history identity --- .../web/src/v2/pages/HistoryPage.test.tsx | 3 + .../apps/web/src/v2/pages/HistoryPage.tsx | 4 +- .../apps/web/src/v2/pages/TrackPage.test.tsx | 4 +- .../apps/web/src/v2/pages/TrackPage.tsx | 4 +- .../apps/web/src/v2/styles/workspace.css | 135 ++++++++++++++++++ 5 files changed, 147 insertions(+), 3 deletions(-) diff --git a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.test.tsx index bf573745..b59412f3 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.test.tsx @@ -138,6 +138,9 @@ test('clears stale rows, charts, and evidence as soon as the history scope chang expect(view.container.querySelector(`.${className}.semi-card`)).toBeInTheDocument(); } expect(view.container.querySelector('.v2-history-discovery-shell')).toContainElement(screen.getByLabelText('历史数据查询操作')); + expect(screen.getByLabelText('历史数据查询操作')).toHaveClass('has-identity'); + expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('历史证据'); + expect(screen.getByLabelText('历史数据查询操作').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument(); expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('遥测证据检索'); expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('07-16 00:00 – 07-16 05:00'); expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('位置数据'); diff --git a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx index 64f4efdd..ba573a4a 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx @@ -1,5 +1,5 @@ import { useMutation, useQuery, useQueryClient, type UseQueryResult } from '@tanstack/react-query'; -import { IconCalendar, IconChevronRight, IconClose, IconDownload, IconFilter, IconMapPin, IconMore, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons'; +import { IconCalendar, IconChevronRight, IconClose, IconDownload, IconFilter, IconHistory, IconMapPin, IconMore, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons'; import { Button, Card, CardGroup, Checkbox, Descriptions, Dropdown, Empty, Input, Progress, Select, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui'; import { FormEvent, KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; @@ -524,6 +524,8 @@ export default function HistoryPage() { } title="遥测证据检索" description="按车辆、时间和协议核验可追溯的历史数据" status={keywords.length ? `${keywords.length} 辆 · ${(result?.total ?? 0).toLocaleString('zh-CN')} 条` : '等待查询'} 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 06b52bb7..7d1644a2 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 @@ -176,7 +176,9 @@ test('renders a map-first replay workspace and connects stop, event, and panel i expect((await screen.findAllByText('粤A12345')).length).toBeGreaterThan(0); expect(view.container.querySelector('.v2-track-rail-shell.semi-card')).toBeInTheDocument(); - expect(screen.getByLabelText('轨迹查询任务栏')).toHaveClass('v2-workspace-command-bar', 'v2-track-query-header'); + expect(screen.getByLabelText('轨迹查询任务栏')).toHaveClass('v2-workspace-command-bar', 'v2-track-query-header', 'has-identity'); + expect(screen.getByLabelText('轨迹查询任务栏')).toHaveTextContent('轨迹回放'); + expect(screen.getByLabelText('轨迹查询任务栏').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument(); expect(screen.getByLabelText('轨迹查询任务栏')).toHaveTextContent('粤A12345'); expect(screen.getByLabelText('轨迹查询任务栏')).toHaveTextContent('3 点'); expect(view.container.querySelector('.v2-track-query-panel')).toHaveClass('is-collapsed'); 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 390637f9..13a76373 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx @@ -1,7 +1,7 @@ import { useQuery } from '@tanstack/react-query'; import { IconChevronLeft, IconChevronRight, IconClose, IconDownload, IconEyeClosed, - IconEyeOpened, IconList, IconMapPin, IconPause, IconPlay, IconRefresh, IconSearch + IconEyeOpened, IconList, IconMapPin, IconPause, IconPlay, IconRefresh, IconRoute, IconSearch } from '@douyinfe/semi-icons'; import { Button, Card, Descriptions, Empty, Input, List, Select, Slider, Tag } from '@douyinfe/semi-ui'; import { FormEvent, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; @@ -264,6 +264,8 @@ const TrackRail = memo(function TrackRail({ draft, track, summaryItems, loading, {showCommandBar ? } title={contextTitle} description={queryCollapsed ? `${appliedWindow} · ${appliedSource}` : '最长支持连续 7 天'} status={loading ? '读取中' : track ? `${track.points.length.toLocaleString('zh-CN')} 点` : '等待查询'} 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 0e97b5a6..607e803b 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css @@ -26750,3 +26750,138 @@ min-height: 21px; } } + +/* + * Track and history identity convergence. + * Keep the map and evidence table dominant while making the active task, + * object and query scope immediately recognizable across workspaces. + */ +.v2-track-query-panel .v2-track-query-header.has-identity.v2-workspace-command-bar { + min-height: 62px; + background: + radial-gradient(circle at 12% -80%, rgba(18, 104, 243, .12), transparent 52%), + linear-gradient(108deg, #fff 0%, #fbfdff 100%); + padding: 8px 7px 8px 10px; +} + +.v2-track-query-header.has-identity .v2-workspace-command-copy { + flex: 1 1 0; + gap: 7px; +} + +.v2-track-query-header.has-identity .v2-workspace-command-icon.semi-avatar { + width: 31px; + height: 31px; + flex-basis: 31px; + border-radius: 9px; + font-size: 13px; +} + +.v2-track-query-header.has-identity .v2-workspace-command-stack { + gap: 0; +} + +.v2-track-query-header.has-identity .v2-workspace-command-eyebrow { + color: #71839a; + font-size: 7px; + line-height: 9px; +} + +.v2-track-query-header.has-identity .v2-workspace-command-title { + color: #263a52; + font-size: 14px; + font-weight: 760; + line-height: 17px; +} + +.v2-track-query-header.has-identity .v2-workspace-command-description { + color: #8492a4; + font-size: 8px; + line-height: 11px; +} + +.v2-track-query-header.has-identity .v2-workspace-command-actions { + flex: 0 0 auto; + gap: 2px; +} + +.v2-track-query-header.has-identity .v2-workspace-command-actions > .semi-tag { + border-color: rgba(18, 104, 243, .08); + background: #eef5ff; + color: #245da8; +} + +.v2-history-discovery-shell > .v2-history-command-bar.has-identity { + min-height: 58px; + background: + radial-gradient(circle at 91% -100%, rgba(18, 104, 243, .1), transparent 42%), + linear-gradient(105deg, #fff 0%, #fbfdff 100%); + padding: 8px 10px 8px 12px; +} + +.v2-history-command-bar.has-identity .v2-workspace-command-copy { + min-width: 240px; +} + +.v2-history-command-bar.has-identity .v2-workspace-command-icon.semi-avatar { + width: 34px; + height: 34px; + flex-basis: 34px; + border-radius: 10px; + font-size: 14px; +} + +.v2-history-command-bar.has-identity .v2-workspace-command-stack { + gap: 0; +} + +.v2-history-command-bar.has-identity .v2-workspace-command-title { + color: #263a52; + font-size: 14px; + font-weight: 760; + line-height: 18px; +} + +.v2-history-command-bar.has-identity .v2-workspace-command-description { + color: #8290a3; + font-size: 9px; + line-height: 12px; +} + +.v2-history-command-bar.has-identity .v2-workspace-command-actions > .semi-tag { + border-color: rgba(18, 104, 243, .08); + background: #eef5ff; + color: #245da8; +} + +@media (min-width: 681px) and (max-width: 980px) { + .v2-history-command-bar.has-identity .v2-workspace-command-copy { + min-width: 190px; + } + + .v2-history-command-bar.has-identity .v2-workspace-command-description { + display: none; + } +} + +@media (max-width: 680px) { + .v2-history-discovery-shell > .v2-history-command-bar.has-identity { + min-height: 54px; + padding: 7px 9px; + } + + .v2-history-command-bar.has-identity .v2-workspace-command-copy { + min-width: 0; + } + + .v2-history-command-bar.has-identity .v2-workspace-command-icon.semi-avatar { + width: 32px; + height: 32px; + flex-basis: 32px; + } + + .v2-history-command-bar.has-identity .v2-workspace-command-description, + .v2-history-command-bar.has-identity .v2-workspace-command-meta { + display: none; + } +}