refactor(ui): converge semi mobile vehicle record

This commit is contained in:
lingniu
2026-07-19 20:46:54 +08:00
parent f59148e260
commit 2b18a400b1
4 changed files with 268 additions and 28 deletions

View File

@@ -525,7 +525,11 @@ test('keeps protocol telemetry independent and explains mileage semantics', asyn
test('uses compact Semi telemetry evidence cards on mobile', async () => {
layout.mobile = true;
vi.spyOn(api, 'vehicleDetail').mockResolvedValue({ ...detail, sources: ['GB32960', 'JT808', 'YUTONG_MQTT'] });
vi.spyOn(api, 'vehicleDetail').mockResolvedValue({
...detail,
profile: { brandName: '测试品牌', modelName: '移动端完整车型名称' } as never,
sources: ['GB32960', 'JT808', 'YUTONG_MQTT']
});
vi.spyOn(api, 'vehicleRealtime').mockResolvedValue({ items: [initialRealtime], total: 1, limit: 1, offset: 0 });
vi.spyOn(api, 'latestTelemetry').mockResolvedValue({
vin: initialRealtime.vin,
@@ -553,6 +557,7 @@ test('uses compact Semi telemetry evidence cards on mobile', async () => {
expect(document.querySelector('.v2-telemetry-detail-protocol')).toHaveClass('semi-tag-cyan-light');
expect(screen.getByRole('button', { name: '关闭遥测字段详情' })).toBeInTheDocument();
expect(document.querySelector('.v2-vehicle-record-page')).toHaveClass('v2-vehicle-record-v3', 'is-mobile-layout');
expect(document.querySelector('.v2-identity-model strong')).toHaveAttribute('title', '测试品牌 / 移动端完整车型名称');
const mobileActions = screen.getByRole('group', { name: '车辆快捷操作' });
expect(mobileActions.querySelectorAll('.semi-button')).toHaveLength(3);
expect(mobileActions).toHaveTextContent('切换车辆轨迹回放更多');

View File

@@ -559,7 +559,7 @@ function VehicleRecord({ detail, liveRealtime, telemetry, telemetryPending, tele
</span>}
description={<span className="v2-identity-vin"><small>VIN</small><b>{detail.vin}</b><Button theme="borderless" aria-label="复制 VIN" title="复制 VIN" icon={<IconCopy />} onClick={() => navigator.clipboard?.writeText(detail.vin)} /></span>}
meta={<span className="v2-identity-meta">
<span className="v2-identity-model"><small> / </small><strong>{[detail.profile?.brandName, detail.profile?.modelName].filter(Boolean).join(' / ') || fmt(identity?.oem || realtime?.oem)}</strong></span>
<span className="v2-identity-model"><small> / </small><strong title={[detail.profile?.brandName, detail.profile?.modelName].filter(Boolean).join(' / ') || fmt(identity?.oem || realtime?.oem)}>{[detail.profile?.brandName, detail.profile?.modelName].filter(Boolean).join(' / ') || fmt(identity?.oem || realtime?.oem)}</strong></span>
<span className="v2-identity-source-context"><small></small><span className="v2-identity-sources">{detail.sources.length ? detail.sources.map((source) => <ProtocolTag key={source} protocol={source} compact />) : <Tag color="grey" type="light" size="small"></Tag>}</span></span>
</span>}
actions={<Suspense fallback={null}><VehicleActions actions={actions} mobile={mobileLayout} onSelect={navigate} /></Suspense>}

View File

@@ -25886,3 +25886,236 @@
white-space: nowrap;
}
}
/*
* Semi UI mobile vehicle record convergence.
* The first viewport keeps identity and four live facts intact, then brings
* the map forward by consolidating location, source evidence and section
* navigation into compact operational rows.
*/
@media (max-width: 680px) {
.v2-vehicle-record-v3.is-mobile-layout.v2-vehicle-record-page {
gap: 6px;
padding: 6px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-card.semi-card,
.v2-vehicle-record-v3.is-mobile-layout .v2-source-evidence.semi-card,
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-record-nav.semi-card,
.v2-vehicle-record-v3.is-mobile-layout .v2-single-map-card.semi-card {
border-color: #dce5ef;
border-radius: 10px;
box-shadow: 0 4px 16px rgba(31, 53, 80, .04);
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-workspace-command-copy {
min-height: 58px;
gap: 2px;
padding: 6px 9px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-primary {
gap: 6px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-plate {
min-height: 32px;
border-radius: 8px;
padding-inline: 8px;
font-size: 14px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-online-label.semi-tag {
min-height: 20px;
padding-inline: 6px;
font-size: 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-vin {
gap: 4px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-vin small,
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-vin b {
font-size: 9px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-vin .semi-button {
width: 24px;
min-width: 24px;
height: 24px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-meta {
grid-template-columns: minmax(0, 1fr) minmax(132px, auto);
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-meta > span {
min-height: 49px;
padding: 5px 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-meta small {
font-size: 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-meta strong {
display: -webkit-box;
margin-top: 2px;
overflow: hidden;
font-size: 10px;
line-height: 1.25;
white-space: normal;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-sources {
flex-wrap: nowrap;
gap: 3px;
margin-top: 2px;
overflow: hidden;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-sources .semi-tag {
min-height: 18px;
padding-inline: 4px;
font-size: 7px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-actions {
gap: 5px;
padding: 5px 7px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-actions > .semi-button {
min-height: 36px;
border-radius: 8px;
padding: 2px 5px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-actions > .semi-button .semi-button-content-left {
font-size: 13px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-actions > .semi-button .semi-button-content-right {
font-size: 10px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-section > .v2-workspace-panel-header {
min-height: 38px;
padding: 4px 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-section .v2-live-report-meta {
max-width: 64vw;
font-size: 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail.is-queue.has-context > .semi-card-body {
min-height: 96px;
grid-template-columns: minmax(0, 1fr);
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-list > span,
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-action.semi-button,
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-action .semi-button-content {
min-height: 48px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-list > span,
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-action .semi-button-content {
column-gap: 5px;
padding: 4px 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-list > span > strong,
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-action .semi-button-content > strong,
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-list > span.is-secondary > strong,
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-list > span.is-secondary .v2-workspace-metric-action strong {
overflow: visible;
font-size: 15px;
letter-spacing: -.025em;
line-height: 18px;
text-overflow: clip;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-list > span > em,
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-live-metric-rail .v2-workspace-metric-action .semi-button-content > em {
font-size: 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-card .v2-current-location {
min-height: 42px;
grid-template-columns: minmax(0, 1.14fr) minmax(124px, .86fr);
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-card .v2-current-location > span {
min-height: 42px;
gap: 4px;
padding: 4px 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-card .v2-current-location > span + span {
border-top: 0;
border-left: 1px solid #e4eaf2;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-card .v2-current-location small {
font-size: 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-card .v2-current-location strong {
overflow: hidden;
font-size: 9px;
text-overflow: ellipsis;
white-space: nowrap;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-command-card .v2-current-address-action.semi-button {
min-height: 28px;
border-radius: 7px;
padding-inline: 6px;
font-size: 9px;
}
.v2-vehicle-record-v3.is-mobile-layout > .v2-source-evidence.semi-card .v2-source-evidence-trigger {
min-height: 44px;
padding: 5px 8px;
}
.v2-vehicle-record-v3.is-mobile-layout > .v2-source-evidence .v2-source-evidence-trigger > div {
gap: 1px;
}
.v2-vehicle-record-v3.is-mobile-layout > .v2-source-evidence .v2-source-evidence-trigger strong {
font-size: 11px;
}
.v2-vehicle-record-v3.is-mobile-layout > .v2-source-evidence .v2-source-evidence-trigger span {
font-size: 8px;
}
.v2-vehicle-record-v3.is-mobile-layout > .v2-source-evidence .v2-source-evidence-trigger > .semi-button {
min-height: 30px;
border-radius: 7px;
padding-inline: 8px;
font-size: 9px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-record-nav .v2-workspace-panel-header {
min-height: 44px;
padding: 3px 5px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-vehicle-section-nav > .semi-button {
min-height: 36px;
border-radius: 7px;
font-size: 8px;
}
.v2-vehicle-record-v3.is-mobile-layout .v2-single-map-card > .semi-card-body > .v2-workspace-panel-header {
min-height: 44px;
padding: 5px 9px;
}
}