From b764ba1be8943c4bf2693f70e982a7b70d34cc40 Mon Sep 17 00:00:00 2001 From: lingniu Date: Sat, 18 Jul 2026 15:15:37 +0800 Subject: [PATCH] refine Semi UI mobile history tools --- .../web/src/v2/pages/HistoryPage.test.tsx | 17 ++++-- .../apps/web/src/v2/pages/HistoryPage.tsx | 31 +++++++++-- .../apps/web/src/v2/styles/workspace.css | 55 ++++++++++++++++--- 3 files changed, 84 insertions(+), 19 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 77c6b87c..c0dbd954 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 @@ -215,6 +215,9 @@ test('renders only selectable Semi history cards on mobile', async () => { expect(screen.queryByLabelText('表格密度')).not.toBeInTheDocument(); expect(view.container.querySelector('.v2-history-side')).not.toBeInTheDocument(); expect(mocks.historyExports).not.toHaveBeenCalled(); + expect(screen.getByRole('button', { name: '展开趋势' })).toHaveTextContent('趋势'); + expect(screen.getByRole('button', { name: '打开历史数据工具' })).toHaveTextContent('工具'); + expect(screen.queryByText('坐标、速度、里程及设备/服务时间通过基础校验')).not.toBeInTheDocument(); fireEvent.click(action); expect(action).toHaveAttribute('aria-pressed', 'true'); expect(action).toHaveAttribute('aria-expanded', 'true'); @@ -228,25 +231,27 @@ test('renders only selectable Semi history cards on mobile', async () => { expect(document.body.style.overflow).not.toBe('hidden'); expect(screen.queryByText('MOBILEVIN-evidence')).not.toBeInTheDocument(); - const exportJobsButton = screen.getByRole('button', { name: '查看导出任务' }); - fireEvent.click(exportJobsButton); + const toolsButton = screen.getByRole('button', { name: '打开历史数据工具' }); + fireEvent.click(toolsButton); + await waitFor(() => expect(toolsButton).toHaveAttribute('aria-expanded', 'true')); + fireEvent.click(screen.getByRole('menuitem', { name: /导出任务/ })); expect(await screen.findByRole('dialog', { name: '历史数据导出任务' })).toBeInTheDocument(); expect(document.querySelector('.v2-history-export-sidesheet')).toHaveClass('semi-sidesheet-bottom'); expect(document.querySelector('.v2-history-export-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(76dvh, 680px)' }); await waitFor(() => expect(mocks.historyExports).toHaveBeenCalledTimes(1)); expect(screen.getByText('暂无导出任务')).toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: '关闭历史数据导出任务' })); - expect(exportJobsButton).toHaveAttribute('aria-expanded', 'false'); + expect(toolsButton).toHaveAttribute('aria-expanded', 'false'); expect(document.body.style.overflow).not.toBe('hidden'); expect(screen.queryByText('暂无导出任务')).not.toBeInTheDocument(); - const columnSettingsButton = screen.getByRole('button', { name: '列设置' }); - fireEvent.click(columnSettingsButton); + fireEvent.click(toolsButton); + fireEvent.click(screen.getByRole('menuitem', { name: /字段设置/ })); expect(await screen.findByRole('dialog', { name: '列显示设置' })).toBeInTheDocument(); expect(document.querySelector('.v2-history-column-sidesheet')).toHaveClass('semi-sidesheet-bottom'); expect(document.querySelector('.v2-history-column-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(68dvh, 580px)' }); fireEvent.click(screen.getByRole('button', { name: '关闭列显示设置' })); - expect(columnSettingsButton).toHaveAttribute('aria-expanded', 'false'); + expect(toolsButton).toHaveAttribute('aria-expanded', 'false'); }); test('releases export job state immediately after leaving the history page', async () => { 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 fd48b95c..3111570b 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/HistoryPage.tsx @@ -1,6 +1,6 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { IconChevronRight, IconClose, IconDownload, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons'; -import { Button, Card, CardGroup, Checkbox, Descriptions, Empty, Input, Progress, Select, SideSheet, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui'; +import { Button, Card, CardGroup, Checkbox, Descriptions, Dropdown, Empty, Input, Progress, Select, SideSheet, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui'; import { FormEvent, KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import { api } from '../../api/client'; @@ -35,8 +35,12 @@ function historyQualityLabel(quality: string) { return quality || '未知'; } +function isHealthyHistoryQuality(quality: string) { + return quality === 'normal' || quality === 'good'; +} + function HistoryQualityTag({ quality }: { quality: string }) { - const color = quality === 'normal' || quality === 'good' ? 'green' : quality === 'error' || quality === 'critical' ? 'red' : 'orange'; + const color = isHealthyHistoryQuality(quality) ? 'green' : quality === 'error' || quality === 'critical' ? 'red' : 'orange'; return {historyQualityLabel(quality)}; } @@ -259,6 +263,7 @@ export default function HistoryPage() { const [trendExpanded, setTrendExpanded] = useState(false); const [filtersCollapsed, setFiltersCollapsed] = useState(true); const [exportJobsOpen, setExportJobsOpen] = useState(false); + const [mobileToolsOpen, setMobileToolsOpen] = useState(false); useEffect(() => { if (!mobileLayout) return; setLimit(MOBILE_HISTORY_PAGE_SIZE); @@ -424,11 +429,27 @@ export default function HistoryPage() { description={keywords.length ? `${(result?.total ?? 0).toLocaleString('zh-CN')} 条记录 · ${resultSummary?.vehicleCount ?? 0} 辆车辆 · ${summarySources}` : '选择车辆和时间范围后查询'} meta={{visibleMetrics.length} / {allMetrics.length} 字段{resultSummary ? {resultSummary.queryDurationMs} ms : null}} actionsClassName={`v2-history-result-actions${mobileLayout ? ' is-mobile-actions' : ''}`} - actions={<> + actions={mobileLayout ? <> + + + } onClick={() => { setMobileToolsOpen(false); setColumnSettingsOpen(true); }}>字段设置 + {exportAllowed ? } onClick={() => { setMobileToolsOpen(false); setExportJobsOpen(true); }}>导出任务 : null} + } onClick={() => { setMobileToolsOpen(false); void dataQuery.refetch(); }}>刷新数据 + } + > + + + : <> {exportAllowed ? : null} - {!mobileLayout ? setDensity(String(value) as typeof density)} optionList={[{ value: 'compact', label: '紧凑' }, { value: 'comfortable', label: '舒适' }]} /> )} + ?
{resultRows.map((row) => )}
: } {dataQuery.isPending && keywords.length ? 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 1f1f9385..0b91a468 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css @@ -6803,14 +6803,19 @@ } .v2-history-table-card .v2-workspace-panel-actions { - gap: 2px; + max-width: none; + gap: 6px; } .v2-history-table-card .v2-workspace-panel-actions > .semi-button { - width: 32px; - min-width: 32px; - min-height: 32px; - padding: 0; + width: auto; + min-width: 62px; + min-height: 36px; + border: 1px solid #dbe5f0; + border-radius: 8px; + background: #f7f9fc; + padding: 0 10px; + color: #536980; } .v2-history-table-card .v2-history-result-actions.is-mobile-actions > .semi-button .semi-button-content { @@ -6820,12 +6825,22 @@ } .v2-history-table-card .v2-history-result-actions.is-mobile-actions > .semi-button .semi-button-content-right { - display: none; + display: inline-flex; + margin-left: 5px; + color: inherit; + font-size: 10px; + font-weight: 700; } .v2-history-table-card .v2-history-result-actions.is-mobile-actions > .semi-button .semi-icon { color: #5f7188; - font-size: 16px; + font-size: 14px; + } + + .v2-history-table-card .v2-history-result-actions.is-mobile-actions > .v2-history-table-trend.is-expanded { + border-color: #b8d2f6; + background: #edf5ff; + color: var(--v2-blue); } .v2-history-table-card .v2-history-result-actions.is-mobile-actions > .v2-history-table-trend.is-expanded .semi-icon { @@ -6924,7 +6939,7 @@ .v2-history-mobile-list > .v2-history-mobile-card.semi-card { border-radius: 8px; box-shadow: none; - contain-intrinsic-size: auto 124px; + contain-intrinsic-size: auto 108px; } .v2-history-mobile-card-content { @@ -6993,6 +7008,30 @@ } } +.v2-history-mobile-tools-menu { + width: 168px; + min-width: 168px; + border: 1px solid #dbe4ef; + border-radius: 11px; + padding: 6px; + box-shadow: 0 18px 44px rgba(27, 45, 72, .16); +} + +.v2-history-mobile-tools-menu .semi-dropdown-item { + min-height: 42px; + border-radius: 8px; + padding-inline: 11px; + color: #445a72; + font-size: 11px; + font-weight: 650; +} + +.v2-history-mobile-tools-menu .semi-dropdown-item:hover, +.v2-history-mobile-tools-menu .semi-dropdown-item:focus-visible { + background: #edf5ff; + color: #1d64c5; +} + @media (max-width: 360px) { .v2-history-mobile-card-content dl { grid-template-columns: repeat(2, minmax(0, 1fr));