From 8291f5ea6948b86b52f86f6afaf710a96b35aba4 Mon Sep 17 00:00:00 2001 From: lingniu Date: Sat, 18 Jul 2026 03:52:05 +0800 Subject: [PATCH] refine Semi UI vehicle evidence hierarchy --- .../web/src/v2/pages/MonitorPage.test.tsx | 5 +- .../apps/web/src/v2/pages/MonitorPage.tsx | 10 +- .../web/src/v2/pages/VehiclePage.test.tsx | 3 + .../apps/web/src/v2/styles/v2.css | 76 ++++++++---- .../apps/web/src/v2/styles/workspace.css | 109 ++++++++++-------- 5 files changed, 128 insertions(+), 75 deletions(-) diff --git a/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.test.tsx index 73fa847e..70e29684 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.test.tsx @@ -149,8 +149,11 @@ test('starts without a selection and supports expand, collapse, reselection, and for (const name of ['最新上报', '实时状态', '车辆信息']) { expect(screen.getByRole('heading', { name, level: 5 })).toBeInTheDocument(); } - expect(screen.getByText('车辆最近一次有效实时数据')).toBeInTheDocument(); expect(screen.getByText('身份、车型与来源覆盖')).toBeInTheDocument(); + expect(view.container.querySelector('.v2-report-summary')).toHaveTextContent('平台接收时间'); + expect(view.container.querySelector('.v2-report-summary')).toHaveTextContent('主协议JT808'); + expect(view.container.querySelector('.v2-metric-grid > div:first-child')).toHaveTextContent('速度42'); + expect(view.container.querySelector('.v2-metric-grid > div:nth-child(4)')).toHaveTextContent('今日里程18.6km'); expect(view.container.querySelector('.v2-status-text')).toHaveClass('semi-tag'); expect(screen.getByRole('button', { name: '取消选择车辆' })).toHaveClass('semi-button'); expect(screen.getByRole('button', { name: '查看总里程全部来源' })).toHaveClass('semi-button', 'v2-metric-source-link'); 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 80a9a3b0..ac6e7508 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/MonitorPage.tsx @@ -268,11 +268,13 @@ function VehicleDetailCard({ {relativeFreshness(vehicle.lastSeen)}} /> -
平台接收时间{vehicle.lastSeen || '暂无上报'}
-
主协议{vehicle.primaryProtocol || '未知'}接入来源{accessSource || '待补充'}
+
+ 平台接收时间{vehicle.lastSeen || '暂无上报'} + 主协议{vehicle.primaryProtocol || '未知'} + 接入来源{accessSource || '待补充'} +
坐标
位置
{hasRealtimeLocation(vehicle) ? address?.formattedAddress || '位置解析中' : '暂无实时位置'}
@@ -291,7 +293,7 @@ function VehicleDetailCard({
{mileageLabel}
今日里程
状态{statusLabel(status)}
-
当前告警{formatNumber(activeAlerts?.total ?? 0)}
+
0 ? 'has-alerts' : ''}>当前告警{formatNumber(activeAlerts?.total ?? 0)}
{gbHighlights.length ?
{gbHighlights.map((item) =>
{item.label}{formatTelemetryValue(item.value, item.displayValue)}{item.unit}
)}
: null} diff --git a/vehicle-data-platform/apps/web/src/v2/pages/VehiclePage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/VehiclePage.test.tsx index 76e1d7d4..2f3f87e1 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/VehiclePage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/VehiclePage.test.tsx @@ -81,6 +81,9 @@ test('polls lightweight single-vehicle realtime data and passes its report inter expect(commandCard).toHaveClass('semi-card', 'v2-vehicle-command-card', 'v2-live-overview'); expect(screen.getByRole('list', { name: '车辆实时指标' })).toHaveClass('v2-live-grid'); expect(commandCard?.querySelectorAll('.v2-live-grid > [role="listitem"]')).toHaveLength(6); + expect(commandCard?.querySelector('.v2-live-grid > div:first-child')).toHaveTextContent('速度'); + expect(commandCard?.querySelector('.v2-live-grid > div:nth-child(2)')).toHaveTextContent('SOC'); + expect(commandCard?.querySelector('.v2-live-grid > div:nth-child(4)')).toHaveTextContent('当日里程'); expect(screen.getByRole('heading', { name: '最新上报', level: 5 })).toBeInTheDocument(); expect(screen.getByRole('heading', { name: '实时位置', level: 5 })).toBeInTheDocument(); expect(screen.getByRole('heading', { name: '最近事件', level: 5 })).toBeInTheDocument(); diff --git a/vehicle-data-platform/apps/web/src/v2/styles/v2.css b/vehicle-data-platform/apps/web/src/v2/styles/v2.css index e057e5e4..c2b5c8fc 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/v2.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/v2.css @@ -8816,31 +8816,37 @@ button, a { -webkit-tap-highlight-color: transparent; } border-bottom-color: #dce9f8; background: #f5f9ff; } -.v2-detail-report-time { +.v2-report-summary { + display: grid; + grid-template-columns: minmax(0,1.45fr) minmax(0,.8fr) minmax(0,1fr); + gap: 0; + overflow: hidden; margin: 9px 10px 0; - border: 1px solid #e2ebf6; - border-radius: 8px; - background: #fff; + border: 1px solid #dce7f4; + border-radius: 9px; + background: #f8fafd; +} +.v2-report-summary > span { + min-width: 0; padding: 8px 9px; } -.v2-detail-report-time small, -.v2-detail-report-time strong { display: block; } -.v2-detail-report-time small { color: #7186a1; font-size: 8px; } -.v2-detail-report-time strong { - margin-top: 4px; +.v2-report-summary > span + span { border-left: 1px solid #e3eaf3; } +.v2-report-summary small, +.v2-report-summary strong, +.v2-report-summary b { + display: block; overflow: hidden; - color: #153f73; - font-size: 12px; - font-variant-numeric: tabular-nums; text-overflow: ellipsis; white-space: nowrap; } -.v2-detail-report-source { display: grid; grid-template-columns: .8fr 1.2fr; gap: 6px; margin: 6px 10px 0; } -.v2-detail-report-source > span { min-width: 0; border-radius: 7px; background: #f5f8fc; padding: 6px 8px; } -.v2-detail-report-source small, -.v2-detail-report-source b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.v2-detail-report-source small { color: #7c8da3; font-size: 8px; } -.v2-detail-report-source b { margin-top: 3px; color: #345679; font-size: 10px; } +.v2-report-summary small { color: #7186a1; font-size: 8px; } +.v2-report-summary strong { + margin-top: 4px; + color: #153f73; + font-size: 12px; + font-variant-numeric: tabular-nums; +} +.v2-report-summary b { margin-top: 4px; color: #345679; font-size: 10px; } .v2-detail-report .v2-detail-list { margin: 5px 10px 8px; } .v2-detail-report .v2-detail-list > div { min-height: 24px; grid-template-columns: 44px minmax(0,1fr); align-items: center; padding-block: 3px; } .v2-detail-report .v2-detail-list dd { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } @@ -8851,6 +8857,30 @@ button, a { -webkit-tap-highlight-color: transparent; } border-color: #e0e7f0; border-radius: 8px; } +.v2-detail-section > .v2-metric-grid > div { + position: relative; + min-height: 68px; + padding: 10px 11px 9px; +} +.v2-detail-section > .v2-metric-grid > div::after { + position: absolute; + right: 11px; + bottom: 0; + left: 11px; + height: 2px; + border-radius: 999px 999px 0 0; + background: #dce5ef; + content: ""; +} +.v2-detail-section > .v2-metric-grid > div:nth-child(1)::after { background: #78a9ef; } +.v2-detail-section > .v2-metric-grid > div:nth-child(2)::after { background: #65bf94; } +.v2-detail-section > .v2-metric-grid > div:nth-child(3)::after { background: #79a7ea; } +.v2-detail-section > .v2-metric-grid > div:nth-child(4)::after { background: #2f7de9; } +.v2-detail-section > .v2-metric-grid > div:nth-child(5)::after { background: #43b77d; } +.v2-detail-section > .v2-metric-grid > .has-alerts::after { background: #eb6d70; } +.v2-detail-section > .v2-metric-grid > div:nth-child(4) strong, +.v2-detail-section > .v2-metric-grid > div:nth-child(4) .v2-metric-source-link { color: #1268df; } +.v2-detail-section > .v2-metric-grid > .has-alerts strong { color: #c84349; } .v2-detail-section > .v2-gb-highlight-grid { margin: 0 10px 10px; } @@ -8899,7 +8929,8 @@ button, a { -webkit-tap-highlight-color: transparent; } .v2-detail-section > .v2-workspace-panel-header .v2-workspace-panel-meta { font-size: 10px; } - .v2-detail-report-time strong { font-size: 13px; } + .v2-report-summary { grid-template-columns: minmax(0,1.35fr) minmax(0,.8fr) minmax(0,1fr); } + .v2-report-summary strong { font-size: 13px; } .v2-detail-list > div { font-size: 10px; } .v2-metric-grid small { font-size: 9px; } .v2-metric-grid strong, @@ -9022,8 +9053,11 @@ button, a { -webkit-tap-highlight-color: transparent; } .v2-monitor-mobile-cards dd.is-today, .v2-monitor-mobile-protocol { color: #1268df; font-weight: 750; } .v2-monitor-mobile-cards > .v2-monitor-mobile-card.semi-card { contain-intrinsic-size: auto 190px; } - .v2-detail-report-time strong { font-size: 13px; } - .v2-detail-report-source b { font-size: 11px; } + .v2-report-summary { + grid-template-columns: minmax(0,1.3fr) minmax(0,.85fr) minmax(0,1fr); + } + .v2-report-summary strong { font-size: 13px; } + .v2-report-summary b { font-size: 11px; } .v2-mileage-page { height: 100%; min-height: 0; gap: 6px; overflow: hidden; padding: 7px; } .v2-mileage-query-panel { flex: 0 0 auto; padding: 0; } 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 25734dc3..3b1de103 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css @@ -4845,7 +4845,7 @@ .v2-vehicle-command-header { display: grid; - grid-template-columns: minmax(310px, .9fr) minmax(360px, 1.15fr) minmax(360px, auto); + grid-template-columns: minmax(270px, .78fr) minmax(320px, 1.08fr) minmax(300px, .9fr); align-items: stretch; background: #fff; } @@ -4857,18 +4857,18 @@ align-content: center; align-items: center; justify-content: start; - gap: 8px 10px; - padding: 18px 20px; + gap: 7px 10px; + padding: 14px 16px; } .v2-vehicle-command-header .v2-plate { - min-height: 42px; + min-height: 40px; border-color: #b9d2fb; border-radius: 9px; background: #edf4ff; - padding-inline: 14px; + padding-inline: 13px; color: var(--v2-blue); - font-size: 18px; + font-size: 17px; letter-spacing: .01em; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .65); } @@ -4931,19 +4931,19 @@ gap: 0; border: 0; border-left: 1px solid #e4eaf2; - padding: 16px 0; + padding: 12px 0; } .v2-vehicle-command-header .v2-identity-meta > div { min-width: 0; - padding: 0 20px; + padding: 0 16px; } .v2-vehicle-command-header .v2-identity-meta > div + div { margin: 0; border: 0; border-left: 1px solid #e7edf4; - padding: 0 20px; + padding: 0 16px; } .v2-vehicle-command-header .v2-identity-meta small { @@ -4955,7 +4955,7 @@ .v2-vehicle-command-header .v2-identity-meta strong { display: block; - margin-top: 7px; + margin-top: 6px; overflow: hidden; color: #2c4057; font-size: 12px; @@ -4969,7 +4969,7 @@ min-width: 0; flex-wrap: wrap; gap: 5px; - margin: 7px 0 0; + margin: 6px 0 0; } .v2-vehicle-command-header .v2-identity-meta .semi-tag { @@ -4984,21 +4984,23 @@ .v2-vehicle-command-header .v2-identity-actions { display: flex; min-width: 0; + grid-column: auto; flex-wrap: wrap; align-content: center; justify-content: flex-end; - gap: 7px; + gap: 6px; border-left: 1px solid #e4eaf2; - padding: 15px 18px; + padding: 12px 14px; } .v2-vehicle-command-header .v2-identity-actions > .semi-button { - min-width: 100px; - min-height: 38px; + width: auto; + min-width: 88px; + min-height: 34px; flex: 0 1 auto; border-radius: 8px; - padding-inline: 12px; - font-size: 11px; + padding-inline: 10px; + font-size: 10px; font-weight: 650; } @@ -5014,10 +5016,10 @@ } .v2-vehicle-live-section > .v2-workspace-panel-header { - min-height: 58px; + min-height: 48px; border-bottom: 1px solid #e6ecf3; background: #f8fafd; - padding: 10px 16px; + padding: 8px 14px; } .v2-vehicle-live-section .v2-live-report-meta { @@ -5036,10 +5038,10 @@ .v2-vehicle-command-card .v2-live-grid > div { position: relative; min-width: 0; - min-height: 104px; + min-height: 88px; border-top: 0; border-left: 1px solid #e7edf4; - padding: 15px 16px 14px; + padding: 12px 14px 11px; } .v2-vehicle-command-card .v2-live-grid > div:first-child { @@ -5056,18 +5058,20 @@ .v2-vehicle-command-card .v2-live-grid > div::after { position: absolute; - right: 16px; + right: 14px; bottom: 0; - left: 16px; - height: 3px; + left: 14px; + height: 2px; border-radius: 999px 999px 0 0; background: #dce5ef; content: ""; } -.v2-vehicle-command-card .v2-live-grid > div:nth-child(-n + 4)::after { - background: #8eb6f3; -} +.v2-vehicle-command-card .v2-live-grid > div:nth-child(1)::after { background: #78a9ef; } +.v2-vehicle-command-card .v2-live-grid > div:nth-child(2)::after { background: #65bf94; } +.v2-vehicle-command-card .v2-live-grid > div:nth-child(3)::after { background: #79a7ea; } +.v2-vehicle-command-card .v2-live-grid > div:nth-child(4)::after { background: #2f7de9; } +.v2-vehicle-command-card .v2-live-grid > div:nth-child(6)::after { background: #43b77d; } .v2-vehicle-command-card .v2-live-grid small { color: #6c7d92; @@ -5077,9 +5081,9 @@ .v2-vehicle-command-card .v2-live-grid strong, .v2-vehicle-command-card .v2-live-source-link { - margin-top: 9px; + margin-top: 7px; color: #213950; - font-size: 22px; + font-size: 20px; font-weight: 750; letter-spacing: -.025em; line-height: 1; @@ -5107,7 +5111,7 @@ .v2-vehicle-command-card .v2-live-grid > div > span:last-child { display: block; - margin-top: 8px; + margin-top: 6px; overflow: hidden; color: #8996a7; font-size: 9px; @@ -5117,14 +5121,14 @@ } .v2-vehicle-command-card .v2-current-location { - min-height: 58px; + min-height: 48px; grid-template-columns: minmax(310px, .8fr) minmax(420px, 1.2fr); border-top: 1px solid #e4eaf2; background: #f8fafd; } .v2-vehicle-command-card .v2-current-location > span { - padding: 9px 16px; + padding: 7px 14px; } .v2-vehicle-command-card .v2-current-location small { @@ -5160,7 +5164,7 @@ font-size: 9px; } -@media (max-width: 1400px) { +@media (max-width: 1180px) { .v2-vehicle-command-header { grid-template-columns: minmax(300px, .85fr) minmax(0, 1.15fr); } @@ -5172,12 +5176,12 @@ overflow-x: auto; border-top: 1px solid #e4eaf2; border-left: 0; - padding: 9px 14px; + padding: 8px 12px; scrollbar-width: thin; } .v2-vehicle-command-header .v2-identity-actions > .semi-button { - min-width: 118px; + min-width: 112px; flex: 0 0 auto; } } @@ -5276,20 +5280,20 @@ } .v2-vehicle-command-header .v2-identity-primary { - padding: 13px 13px 11px; + padding: 10px 12px 8px; } .v2-vehicle-command-header .v2-plate { - min-height: 38px; + min-height: 36px; padding-inline: 12px; - font-size: 16px; + font-size: 15px; } .v2-vehicle-command-header .v2-identity-meta { grid-template-columns: minmax(0, 1.15fr) minmax(120px, .85fr); border-top: 1px solid #e7edf4; border-left: 0; - padding: 10px 0; + padding: 8px 0; } .v2-vehicle-command-header .v2-identity-meta > div { @@ -5320,7 +5324,7 @@ display: flex; grid-template-columns: none; gap: 6px; - padding: 7px 10px; + padding: 6px 10px; scrollbar-width: none; } @@ -5337,7 +5341,7 @@ } .v2-vehicle-live-section > .v2-workspace-panel-header { - min-height: 52px; + min-height: 46px; padding: 8px 11px; } @@ -5351,16 +5355,16 @@ } .v2-vehicle-command-card .v2-live-grid > div { - min-width: 138px; - min-height: 94px; - flex-basis: 138px; - padding: 13px 12px 12px; + min-width: 134px; + min-height: 88px; + flex-basis: 134px; + padding: 11px 12px 10px; } .v2-vehicle-command-card .v2-live-grid strong, .v2-vehicle-command-card .v2-live-source-link { - margin-top: 8px; - font-size: 20px; + margin-top: 7px; + font-size: 19px; } .v2-vehicle-command-card .v2-current-location { @@ -5368,8 +5372,8 @@ } .v2-vehicle-command-card .v2-current-location > span { - min-height: 46px; - padding: 8px 11px; + min-height: 38px; + padding: 5px 11px; } .v2-vehicle-command-card .v2-current-location > span + span { @@ -5378,7 +5382,9 @@ } .v2-vehicle-record-nav .v2-workspace-panel-header { + min-height: 50px; grid-template-columns: auto minmax(0, 1fr); + padding-block: 5px; } .v2-vehicle-record-nav .v2-workspace-panel-copy > h5.semi-typography { @@ -5396,6 +5402,11 @@ .v2-vehicle-record-page .v2-single-map-card { min-height: 330px; } + + .v2-vehicle-record-page > .v2-source-evidence .v2-source-evidence-trigger { + min-height: 54px; + padding-block: 7px; + } } /*