From 39d9cb54038bd2f7a150b4a7059f4c05bb0e7a7f Mon Sep 17 00:00:00 2001 From: lingniu Date: Thu, 17 Sep 2026 18:48:48 +0800 Subject: [PATCH] feat(web): simplify vehicle workspace with Apple-inspired design --- vehicle-data-platform/apps/web/src/main.tsx | 4 + .../apps/web/src/v2/layout/AppShell.test.tsx | 6 +- .../apps/web/src/v2/layout/AppShell.tsx | 6 - .../apps/web/src/v2/pages/AccessPage.test.tsx | 1 - .../apps/web/src/v2/pages/AccessPage.tsx | 2 - .../apps/web/src/v2/pages/AlertsPage.test.tsx | 1 + .../apps/web/src/v2/pages/AlertsPage.tsx | 9 +- .../web/src/v2/pages/HistoryPage.test.tsx | 5 +- .../apps/web/src/v2/pages/HistoryPage.tsx | 14 +- .../apps/web/src/v2/pages/MonitorPage.tsx | 2 +- .../web/src/v2/pages/OperationsPage.test.tsx | 7 +- .../apps/web/src/v2/pages/OperationsPage.tsx | 2 - .../web/src/v2/pages/ReconciliationCenter.tsx | 20 +- .../apps/web/src/v2/pages/StatisticsPage.tsx | 4 +- .../apps/web/src/v2/pages/TrackPage.test.tsx | 7 +- .../apps/web/src/v2/pages/TrackPage.tsx | 40 +- .../apps/web/src/v2/pages/UsersPage.test.tsx | 2 - .../apps/web/src/v2/pages/UsersPage.tsx | 5 +- .../apps/web/src/v2/pages/VehiclePage.tsx | 13 +- .../src/v2/pages/VehicleSearchWorkspace.tsx | 3 +- .../apps/web/src/v2/productionEntry.test.ts | 20 +- .../src/v2/shared/WorkspacePanelHeader.tsx | 4 +- .../web/src/v2/styles/apple-data-pages.css | 442 ++++++++++++++++++ .../web/src/v2/styles/apple-governance.css | 419 +++++++++++++++++ .../web/src/v2/styles/apple-map-pages.css | 241 ++++++++++ .../web/src/v2/styles/apple-workspace.css | 317 +++++++++++++ .../apps/web/src/v2/styles/foundation.css | 34 +- .../apps/web/src/v2/styles/users.css | 81 ++-- .../design/apple-design-20260917/ui-review.md | 70 +++ 29 files changed, 1612 insertions(+), 169 deletions(-) create mode 100644 vehicle-data-platform/apps/web/src/v2/styles/apple-data-pages.css create mode 100644 vehicle-data-platform/apps/web/src/v2/styles/apple-governance.css create mode 100644 vehicle-data-platform/apps/web/src/v2/styles/apple-map-pages.css create mode 100644 vehicle-data-platform/apps/web/src/v2/styles/apple-workspace.css create mode 100644 vehicle-data-platform/docs/design/apple-design-20260917/ui-review.md diff --git a/vehicle-data-platform/apps/web/src/main.tsx b/vehicle-data-platform/apps/web/src/main.tsx index 315ce1da..a3e3fcc7 100644 --- a/vehicle-data-platform/apps/web/src/main.tsx +++ b/vehicle-data-platform/apps/web/src/main.tsx @@ -7,6 +7,10 @@ import './v2/styles/workspace.css'; import './v2/styles/foundation.css'; import './v2/styles/experience.css'; import './v2/styles/event-center.css'; +import './v2/styles/apple-workspace.css'; +import './v2/styles/apple-data-pages.css'; +import './v2/styles/apple-governance.css'; +import './v2/styles/apple-map-pages.css'; if ('scrollRestoration' in window.history) { window.history.scrollRestoration = 'manual'; diff --git a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx index 4db07e44..171555ce 100644 --- a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.test.tsx @@ -115,10 +115,8 @@ test('opens contextual help for the active module and closes it without navigati expect(screen.getByRole('dialog', { name: '全局监控' })).toHaveTextContent('筛选会自动生效'); expect(document.querySelector('.v2-help-sheet')).toHaveClass('v2-workspace-help-sidesheet'); - const helpSummary = screen.getByRole('list', { name: '全局监控摘要' }); - expect(helpSummary).toHaveTextContent('页面目标快速完成'); - expect(helpSummary).toHaveTextContent('建议步骤3 项'); - expect(helpSummary).toHaveTextContent('快捷关闭Esc'); + expect(screen.getByRole('dialog', { name: '全局监控' })).toHaveTextContent('查看全车队实时位置、状态和最新上报。'); + expect(document.querySelectorAll('.v2-help-panel ol > li')).toHaveLength(3); expect(document.querySelector('.v2-help-overview.semi-card')).toBeInTheDocument(); expect(screen.getByText('建议操作')).toBeInTheDocument(); expect(help).toHaveAttribute('aria-expanded', 'true'); diff --git a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx index 6d69bb1a..3d23abbb 100644 --- a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx +++ b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx @@ -86,18 +86,12 @@ function ContextHelp({ section, visible, mobile, onClose }: { section: string; v title={title} description="当前页面帮助与推荐操作" badge={`${content.tips.length} 项建议`} - summaryItems={[ - { label: '页面目标', value: '快速完成', detail: '保留当前任务状态', tone: 'primary' }, - { label: '建议步骤', value: `${content.tips.length} 项`, detail: '按顺序执行' }, - { label: '快捷关闭', value: 'Esc', detail: '随时返回页面' } - ]} footerNote="关闭帮助不会改变当前筛选、地图或任务状态" primaryAction={{ label: '返回当前页面', onClick: onClose }} onCancel={onClose} >
- 页面目标 {content.summary}
建议操作{content.tips.length} 项
diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.test.tsx index 918013f9..ff9b3057 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.test.tsx @@ -127,7 +127,6 @@ test('removes old access rows immediately when the vehicle filter scope changes' expect(await screen.findByText('旧接入车牌')).toBeInTheDocument(); expect(screen.getByRole('heading', { name: '接入健康工作台', level: 5 })).toBeInTheDocument(); expect(screen.getByLabelText('接入管理操作')).toHaveClass('v2-workspace-command-bar', 'v2-access-command-bar', 'has-identity'); - expect(screen.getByLabelText('接入管理操作')).toHaveTextContent('来源治理'); expect(screen.getByLabelText('接入管理操作').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument(); expect(view.container.querySelector('.v2-access-discovery-shell')).toBeInTheDocument(); for (const className of ['v2-access-filter-card-v3', 'v2-access-table-v3']) { diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.tsx index f5fd0cab..23921ffc 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/AccessPage.tsx @@ -601,7 +601,6 @@ export default function AccessPage() { } title="接入健康工作台" description={mobileLayout @@ -679,7 +678,6 @@ export default function AccessPage() {
}, { title: '发生时间', dataIndex: 'triggeredAt', className: 'is-triggered-at', width: 124, render: (value: string) => }, { title: '事件来源 / 自动化', dataIndex: 'ruleName', className: 'is-rule', width: 154, render: (value: string, event: AlertEvent) => {isNativeAlarm(event) ? '车辆原生告警' : value} }, - { title: '执行状态', dataIndex: 'status', className: 'is-status', width: 92, render: (_: AlertEvent['status'], event: AlertEvent) => }, + { title: '执行状态', dataIndex: 'status', className: 'is-status', width: 92, fixed: 'right' as const, render: (_: AlertEvent['status'], event: AlertEvent) => }, ]; return compact ? allColumns.map((column) => ({ ...column, width: COMPACT_ALERT_COLUMN_WIDTHS[column.dataIndex] ?? column.width })) @@ -352,6 +352,7 @@ const AlertEventTable = memo(function AlertEventTable({ rows, selectedID, compac return width + column.width, 0) }} dataSource={rows} rowKey="id" pagination={false} @@ -378,7 +379,7 @@ function EventInspector({ event, loading = false, detailError, note, acting, act ; const normalized = toVehicleEvent(event); return - {!sheet ? - {rule.archivedAt ? 只读 : toggle.mutate(rule)} />} + {rule.archivedAt ? 只读 : } v{rule.version} )} {rulesLoading ? : rulesError ? 重新加载} /> : !filteredRules.length ? : } title={search || protocolFilter || statusFilter !== 'all' ? '没有匹配的自动化' : lifecycle === 'archived' ? '暂无审计归档' : '暂无自动化'} description={search || protocolFilter || statusFilter !== 'all' ? '换一个名称、协议或状态筛选试试。' : lifecycle === 'archived' ? '停用规则可在详情中带原因归档,并在这里恢复。' : '创建第一条事件自动化。'} /> : null} 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 9c061120..5a4e6521 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 @@ -577,10 +577,7 @@ 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('查询条件'); expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('07-16 00:00 – 07-16 05:00'); expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('位置数据'); 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 530eec2f..4b81f8f3 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx @@ -1894,10 +1894,8 @@ export default function HistoryPage() { } - title="遥测证据检索" - description="按车辆、时间和协议核验可追溯的历史数据" + title="查询条件" + description="选择车辆和时间,查询历史上报" status={keywords.length ? `${keywords.length} 辆 · ${(result?.total ?? 0).toLocaleString('zh-CN')} 条` : '等待查询'} statusColor={keywords.length ? 'blue' : 'grey'} meta={keywords.length ? @@ -2029,8 +2027,6 @@ export default function HistoryPage() { setTrendExpanded((value) => !value)} onRetry={() => { void seriesQuery.refetch(); }} /> {activeRawSegment ? `${rawSegments.find((segment) => segment.key === activeRawSegment)?.label} · ${displayMetrics.length - 2} 字段` : `${activeFieldViewName} · ${visibleMetrics.length} / ${allMetrics.length} 字段`}{resultSummary ? 查询 {resultSummary.queryDurationMs} ms : null}} @@ -2096,15 +2092,9 @@ export default function HistoryPage() { /> : } title="选择车辆,开始核验历史证据" description="一次最多查询 5 台车辆,结果会保留协议来源、质量说明与 RAW 证据。" - steps={mobileLayout ? undefined : [ - { icon: , title: '选择车辆', description: '支持车牌、VIN 与批量粘贴' }, - { icon: , title: '确认时间', description: '按上海时区精确到分钟' }, - { icon: , title: '核验数据', description: '位置、RAW 与日里程统一检索' } - ]} action={} /> : null} diff --git a/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.tsx index 6f419d91..57a788ed 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.tsx @@ -620,7 +620,7 @@ export default function MonitorPage() { {mode === 'map' ?
车辆列表{batchSearchPending ? '查询中' : `${formatNumber(vehicles.data?.total ?? visibleRows.length)} 辆`}
-
1 ? batchStatusTitle : undefined}>{searchTerms.length > 1 ? batchStatus : deferredKeyword ? `正在筛选“${deferredKeyword}”` : '按最新上报排序'}
+
1 ? batchStatusTitle : undefined}>{searchTerms.length > 1 ? batchStatus : deferredKeyword ? `正在筛选“${deferredKeyword}”` : '最新上报优先'}
{vehicles.isLoading || batchSearchPending ?
{batchSearchPending ? `正在查找 ${searchTerms.length} 辆车` : '加载车辆'}
: null} {!vehicles.isLoading && !vehicles.isError && !batchSearchPending && visibleRows.length === 0 ? : null} diff --git a/vehicle-data-platform/apps/web/src/v2/pages/OperationsPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/OperationsPage.test.tsx index 4580698c..add546b7 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/OperationsPage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/OperationsPage.test.tsx @@ -79,7 +79,6 @@ test('renders reconciliation queue, loads evidence on demand and records review expect(await screen.findByText('质量问题队列')).toBeInTheDocument(); expect(screen.getByRole('heading', { name: '运行与数据质量', level: 5 })).toBeInTheDocument(); expect(screen.getByLabelText('运维质量操作')).toHaveClass('v2-workspace-command-bar', 'v2-ops-command-bar', 'has-identity'); - expect(screen.getByLabelText('运维质量操作')).toHaveTextContent('运行治理'); expect(screen.getByLabelText('运维质量操作').querySelector('.v2-workspace-command-icon.semi-avatar')).toBeInTheDocument(); expect(screen.getByRole('button', { name: '刷新全局证据' })).toHaveClass('v2-workspace-mobile-tool-button', 'is-muted'); const navigation = screen.getByRole('navigation', { name: '运维质量视图' }); @@ -294,7 +293,11 @@ test('renders only the compact mobile reconciliation surface and defers secondar expect(toolbar).not.toHaveClass('is-mobile-collapsed'); expect(screen.queryByText('近 30 天趋势')).not.toBeInTheDocument(); - fireEvent.click(screen.getByRole('button', { name: '30 天趋势' })); + fireEvent.click(screen.getByRole('button', { name: '质量问题更多操作' })); + expect(await screen.findByRole('menuitem', { name: '批量处置' })).toBeInTheDocument(); + expect(screen.getByRole('menuitem', { name: /导出当前筛选/ })).toBeInTheDocument(); + expect(screen.getByRole('menuitem', { name: /刷新结果/ })).toBeInTheDocument(); + fireEvent.click(screen.getByRole('menuitem', { name: /30 天趋势/ })); expect(await screen.findByRole('dialog', { name: '30 天差异趋势' })).toBeInTheDocument(); expect(document.querySelector('.v2-reconcile-trend-sidesheet')).toHaveClass('semi-sidesheet-bottom', 'v2-workspace-detail-sidesheet'); expect(document.querySelector('.v2-reconcile-trend-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(72dvh, 620px)' }); diff --git a/vehicle-data-platform/apps/web/src/v2/pages/OperationsPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/OperationsPage.tsx index f731e03b..d325599f 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/OperationsPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/OperationsPage.tsx @@ -598,7 +598,6 @@ export default function OperationsPage() { } tone="health" title="运行与数据质量" @@ -634,7 +633,6 @@ export default function OperationsPage() { {readiness.isError ? readiness.refetch()} /> : null} + actions={mobileLayout ? + {!batchMode && scope === 'current' ? { setMobileActionsOpen(false); enterBatchMode('operate'); }}>批量处置 : null} + {!batchMode && administrator ? : } onClick={() => { setMobileActionsOpen(false); enterBatchMode('lifecycle'); }}>{scope === 'archived' ? '批量恢复' : '批量归档'} : null} + {!batchMode ? } disabled={!page?.total || exportIssues.isPending} onClick={() => { setMobileActionsOpen(false); exportIssues.mutate(); }}>{exportIssues.isPending ? '正在导出…' : '导出当前筛选'} : null} + {scope === 'current' ? } onClick={() => { setMobileActionsOpen(false); toggleTrend(); }}>30 天趋势 : null} + } disabled={summary.isFetching || issues.isFetching} onClick={() => { setMobileActionsOpen(false); refresh(); }}>刷新结果 + } + > : <> {!batchMode && scope === 'current' ? : null} {!batchMode && administrator ? : null} {!batchMode ? : null} diff --git a/vehicle-data-platform/apps/web/src/v2/pages/StatisticsPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/StatisticsPage.tsx index f4d21a12..2454934c 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/StatisticsPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/StatisticsPage.tsx @@ -1349,8 +1349,6 @@ export default function StatisticsPage() {
{hasVehicles ? `${totalVehicles} 辆` : `${displayVehicles.length} / ${totalVehicles} 辆`}{dates.length} 个自然日} @@ -1370,6 +1368,6 @@ export default function StatisticsPage() {
{totalVehicles > PAGE_SIZE ? : {hasVehicles ? '已选择' : '共'} {totalVehicles.toLocaleString('zh-CN')} 辆车辆{exportFeedback ? ` · ${exportFeedback}` : ''}}
setHydrogenEvidenceTarget(undefined)} /> -
数据更新时间:{statistics.data?.asOf || '—'}来源优先级:{criteria.sources.filter((source) => source.enabled).map((source) => source.protocol).join(' > ')}当前筛选复用 1 分钟 · 离开后释放明细
+
数据更新时间:{statistics.data?.asOf || '—'}来源优先级:{criteria.sources.filter((source) => source.enabled).map((source) => source.protocol).join(' > ')}按上海时区统计自然日
; } 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 6f91ab8c..278e2ba1 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 @@ -160,6 +160,9 @@ test('explains an empty selected-vehicle time window without asking to select th expect(screen.getByText('车辆已选定,可调整时间范围或数据来源后重新查询。')).toBeInTheDocument(); expect(screen.queryByText('先选择车辆,再开始轨迹回放')).not.toBeInTheDocument(); expect(screen.getByRole('button', { name: '修改查询' })).toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: '修改查询' })); + expect(screen.getByRole('textbox', { name: '搜索轨迹车辆' })).toHaveValue('LTEST000000000001'); + expect(screen.getByRole('button', { name: /查询轨迹/ })).toBeEnabled(); }); test('distinguishes a failed vehicle lookup from an empty result and retries in place', async () => { @@ -456,8 +459,8 @@ test('keeps one clear mobile query entry before a vehicle is selected', async () expect(screen.queryByRole('button', { name: '打开轨迹详情' })).not.toBeInTheDocument(); expect(screen.queryByRole('toolbar', { name: '地图轨迹工具' })).not.toBeInTheDocument(); expect(screen.queryByRole('slider', { name: '轨迹播放进度' })).not.toBeInTheDocument(); - expect(screen.getByRole('slider', { name: '轨迹播放进度,等待查询结果' })).toBeDisabled(); - expect(view.container.querySelector('.v2-track-playback-dock.is-empty')).toBeInTheDocument(); + expect(screen.queryByRole('slider', { name: '轨迹播放进度,等待查询结果' })).not.toBeInTheDocument(); + expect(view.container.querySelector('.v2-track-playback-dock')).not.toBeInTheDocument(); expect(view.container.querySelector('.v2-workspace-empty-guide-eyebrow')).not.toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: /选择车辆/ })); expect(await screen.findByRole('dialog', { 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 bc35730d..113bf373 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/TrackPage.tsx @@ -135,7 +135,7 @@ function trackSummaryItems(track?: TrackPlaybackResponse): WorkspaceQueueMetricR return [ { label: distanceLabel, - value: track ? `${number(track.summary.distanceKm)} km` : '—', + value: track ? <>{number(track.summary.distanceKm)} km : '—', note: track ? formatDuration(track.summary.durationSeconds) : '等待查询', tone: 'primary', emphasis: 'primary' @@ -291,18 +291,18 @@ const TrackRail = memo(function TrackRail({ draft, applied, track, summaryItems, ], []).map((preset) => ({ ...preset, active: activePreset === preset.key })); const compactAppliedWindow = compactTrackWindowLabel(applied.dateFrom, applied.dateTo); const appliedSource = applied.protocol ? protocolDisplayLabel(applied.protocol) : '自动来源'; - const contextTitle = queryCollapsed ? track?.plate || applied.keyword || '轨迹查询' : '轨迹查询'; + const contextTitle = queryCollapsed ? track?.plate || applied.keyword || '查询条件' : '查询条件'; return ; }); @@ -479,6 +478,11 @@ export default function TrackPage() { }, [mobileLayout, selectIndex]); const collapseRail = useCallback(() => setRailCollapsed(true), []); const toggleQuery = useCallback(() => setQueryCollapsed((value) => !value), []); + const openEmptyQuery = useCallback(() => { + setQueryCollapsed(false); + setRailCollapsed(false); + window.requestAnimationFrame(() => document.querySelector('.v2-track-query input')?.focus()); + }, []); const togglePlayback = () => { if (points.length < 2) return; if (!playing && boundedIndex >= points.length - 1) setActiveIndex(0); @@ -601,12 +605,7 @@ export default function TrackPage() { icon={} title={emptyTrackTitle} description={emptyTrackDescription} - steps={emptyTrackHasVehicle ? undefined : [ - { icon: , title: '选择车辆', description: '车牌或 VIN 精确定位' }, - { icon: , title: '确认来源', description: '自动选择最佳定位来源' }, - { icon: , title: '播放核验', description: '逐点查看速度、里程与事件' } - ]} - action={} + action={} />} {query.isFetching ? : null} @@ -628,17 +627,6 @@ export default function TrackPage() { - : null}
; diff --git a/vehicle-data-platform/apps/web/src/v2/pages/UsersPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/UsersPage.test.tsx index 758c43af..ae903d46 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/UsersPage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/UsersPage.test.tsx @@ -158,7 +158,6 @@ test('deduplicates vehicle candidates by VIN and renders granted vehicles plate const customer = await screen.findByRole('button', { name: /选择客户 华东客户/ }); 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('变更最多 30 秒生效'); @@ -170,7 +169,6 @@ test('deduplicates vehicle candidates by VIN and renders granted vehicles plate expect(view.container.querySelector('.v2-user-list.semi-card')).toBeInTheDocument(); expect(view.container.querySelector('.v2-user-filter-panel.v2-workspace-filter-panel.semi-card')).toBeInTheDocument(); expect(view.container.querySelector('.v2-customer-list.semi-list')).toBeInTheDocument(); - expect(screen.getByRole('row', { name: '客户账号目录列' })).toHaveTextContent('客户账号菜单权限车辆权限最近登录访问状态'); const directoryMetrics = screen.getByRole('list', { name: '客户权限目录统计' }); expect(directoryMetrics.closest('.v2-user-directory-metric-rail')).toHaveClass('v2-workspace-metric-rail', 'is-queue'); expect(directoryMetrics.querySelectorAll(':scope > [role="listitem"]')).toHaveLength(4); diff --git a/vehicle-data-platform/apps/web/src/v2/pages/UsersPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/UsersPage.tsx index 13b64949..9376e9a7 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/UsersPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/UsersPage.tsx @@ -754,7 +754,6 @@ export default function UsersPage() { } tone="authority" title="客户访问治理" @@ -901,7 +900,7 @@ export default function UsersPage() { description="创建客户账号后,可在这里配置菜单和车辆范围。" action={} /> : <> - {visibleCustomers.length ?
+ {visibleCustomers.length ?