refactor(ui): converge semi mobile vehicle record
This commit is contained in:
@@ -525,7 +525,11 @@ test('keeps protocol telemetry independent and explains mileage semantics', asyn
|
|||||||
|
|
||||||
test('uses compact Semi telemetry evidence cards on mobile', async () => {
|
test('uses compact Semi telemetry evidence cards on mobile', async () => {
|
||||||
layout.mobile = true;
|
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, 'vehicleRealtime').mockResolvedValue({ items: [initialRealtime], total: 1, limit: 1, offset: 0 });
|
||||||
vi.spyOn(api, 'latestTelemetry').mockResolvedValue({
|
vi.spyOn(api, 'latestTelemetry').mockResolvedValue({
|
||||||
vin: initialRealtime.vin,
|
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(document.querySelector('.v2-telemetry-detail-protocol')).toHaveClass('semi-tag-cyan-light');
|
||||||
expect(screen.getByRole('button', { name: '关闭遥测字段详情' })).toBeInTheDocument();
|
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-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: '车辆快捷操作' });
|
const mobileActions = screen.getByRole('group', { name: '车辆快捷操作' });
|
||||||
expect(mobileActions.querySelectorAll('.semi-button')).toHaveLength(3);
|
expect(mobileActions.querySelectorAll('.semi-button')).toHaveLength(3);
|
||||||
expect(mobileActions).toHaveTextContent('切换车辆轨迹回放更多');
|
expect(mobileActions).toHaveTextContent('切换车辆轨迹回放更多');
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ function VehicleRecord({ detail, liveRealtime, telemetry, telemetryPending, tele
|
|||||||
</span>}
|
</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>}
|
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">
|
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 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>}
|
</span>}
|
||||||
actions={<Suspense fallback={null}><VehicleActions actions={actions} mobile={mobileLayout} onSelect={navigate} /></Suspense>}
|
actions={<Suspense fallback={null}><VehicleActions actions={actions} mobile={mobileLayout} onSelect={navigate} /></Suspense>}
|
||||||
|
|||||||
@@ -25886,3 +25886,236 @@
|
|||||||
white-space: nowrap;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,48 +1,50 @@
|
|||||||
# 全局监控列表 Semi UI Design QA
|
# 单车详情移动端 Semi UI Design QA
|
||||||
|
|
||||||
- source visual truth: 生产版本 `e944b797` 的 `/monitor?mode=list`
|
- source visual truth: 生产版本 `f59148e2` 的 `/vehicles/LB9A32A26R0LS1489`
|
||||||
- source screenshots:
|
- source screenshots:
|
||||||
- desktop: `/tmp/semi-continuous-audit-20260719/04-monitor-list-desktop.png`
|
- directory desktop: `/tmp/semi-goal-audit-20260719-next/01-vehicle-directory-desktop.png`
|
||||||
- mobile: `/tmp/semi-continuous-audit-20260719/05-monitor-list-mobile.png`
|
- detail desktop: `/tmp/semi-goal-audit-20260719-next/02-vehicle-detail-desktop.png`
|
||||||
|
- detail mobile: `/tmp/semi-goal-audit-20260719-next/03-vehicle-detail-mobile.png`
|
||||||
- implementation screenshots:
|
- implementation screenshots:
|
||||||
- desktop: `/tmp/semi-continuous-audit-20260719/07-monitor-list-desktop-after.png`
|
- detail mobile: `/tmp/semi-goal-audit-20260719-next/04-vehicle-detail-mobile-after.png`
|
||||||
- mobile: `/tmp/semi-continuous-audit-20260719/06-monitor-list-mobile-after.png`
|
- detail desktop: `/tmp/semi-goal-audit-20260719-next/05-vehicle-detail-desktop-after.png`
|
||||||
- comparison evidence:
|
- comparison evidence:
|
||||||
- mobile before/after: `/tmp/semi-continuous-audit-20260719/monitor-mobile-comparison.png`
|
- mobile before/after: `/tmp/semi-goal-audit-20260719-next/vehicle-detail-mobile-comparison.png`
|
||||||
- viewport and state:
|
- viewport and state:
|
||||||
- desktop `1440 × 900`
|
- desktop `1440 × 900`
|
||||||
- mobile `390 × 844`
|
- mobile `390 × 844`
|
||||||
- 使用管理员生产数据,共 `1,024` 辆授权车辆
|
- 使用管理员生产数据与同一辆车 `粤AGP3506`
|
||||||
- 列表视图、第一页、每页 `50` 辆
|
|
||||||
|
|
||||||
## Fidelity Ledger
|
## Fidelity Ledger
|
||||||
|
|
||||||
| Surface | Required fidelity | Implementation evidence | Result |
|
| Surface | Required fidelity | Implementation evidence | Result |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Monitoring workflow | 搜索、筛选、地图/列表切换、分页和实时刷新周期不能被视觉重构改变。 | 保留原查询、路由和轮询实现,只重组列表渲染与响应式样式。 | Preserved. |
|
| Vehicle identity | 车牌、在线状态、VIN、品牌车型和三类协议来源必须完整。 | 保留原任务栏结构;车型允许两行且提供完整 `title`,协议标签保持 Semi Tag 色彩语义。 | Improved. |
|
||||||
| Fleet hierarchy | 车辆总数、当前在线、行驶和告警必须优先;今日上报与无实时位置属于辅助证据。 | 手机端主指标采用清晰的 `2 × 2` 网格;辅助指标独立放在底部并压缩大数。 | Improved. |
|
| Live evidence | 速度、SOC、总里程和当日里程不能被截断或隐藏。 | 修正移动端带上下文指标轨道的网格优先级;四项指标获得完整宽度,实测全部 `clipped=false`。 | Fixed. |
|
||||||
| Vehicle evidence | 车牌、VIN、速度、当日里程、总里程、协议和位置必须在一眼可扫范围内。 | 手机卡片固定为身份、三项核心证据、位置三层;桌面继续使用连续 Semi Table。 | Improved. |
|
| First viewport | 首屏必须尽快进入地图,不能被重复卡片和过高操作区占满。 | 身份、动作、位置、来源入口和章节导航收敛;地图顶部由 `652px` 提前至 `569px`。 | Improved. |
|
||||||
| Mobile density | 单屏车辆数需要显著增加,但不牺牲字段可辨认性。 | 卡片高度从约 `147px` 降至 `109px`;列表视口可容纳约 `4.05` 张卡片,截图中从约 `2.5` 辆提升到 `4` 辆。 | Improved. |
|
| Location workflow | 当前坐标、按需地址解析和车辆实时跟随必须保留。 | 坐标与解析按钮合并成一行;未增加自动逆地理编码,地图和实时轮询逻辑未改。 | Preserved. |
|
||||||
| Realtime performance | 高频刷新不能让全部车辆卡片无差别重绘。 | 移动卡片使用字段级 `memo` 比较;不可见卡片继续使用 `content-visibility` 和固有尺寸占位。 | Improved. |
|
| Source evidence | 总里程、当日里程和“查看全部来源”仍需打开同一证据面板。 | 实测总里程按钮打开 Semi Bottom SideSheet,日期和来源证据可见,关闭后恢复页面。 | Passed. |
|
||||||
| Address cost | 地理位置不得随列表刷新自动消耗逆地理编码 API。 | 经纬度始终可见;地址仍由用户点击“解析位置”后按需请求。 | Preserved. |
|
| Section navigation | 实时位置、最近事件、实时遥测和车辆主档必须可达。 | 四个 Semi Button 保留可访问名称;点击实时位置后目标区域获得焦点。 | Passed. |
|
||||||
| Asset fidelity | 品牌和图标不得用临时图形替代。 | 沿用生产 Logo、Semi Icon、Card、Button、Table、Tag 与 Pagination。 | Preserved. |
|
| Desktop stability | 移动端收敛不能造成桌面布局回退。 | `1440 × 900` 桌面截图保持原信息结构,横向溢出 `0px`。 | Preserved. |
|
||||||
|
| Asset fidelity | 品牌、地图和图标不得由临时资产代替。 | 继续使用生产 Logo、高德地图、Semi Icon、Card、Button、Tag 与 SideSheet。 | Preserved. |
|
||||||
|
|
||||||
## Interaction And Accessibility Checks
|
## Interaction And Accessibility Checks
|
||||||
|
|
||||||
- 手机端“筛选”可展开并可通过“收起”恢复列表;
|
- 页面根节点保留“车牌 + 车辆档案”的可访问标签;
|
||||||
- 地图/列表使用原有可访问 tab 语义,车辆卡片具有“车牌 + 实时数据”标签;
|
- 总里程和当日里程继续以有名称的按钮进入来源证据;
|
||||||
- “地图”和“解析位置”按钮均保留车辆级可访问名称;
|
- 来源证据 SideSheet 可打开、读取并通过“关闭来源证据”退出;
|
||||||
- `390px` 视口文档横向溢出为 `0px`,主指标和辅助指标无裁切;
|
- 章节导航点击后执行平滑滚动并将焦点交给目标区域;
|
||||||
- 移动卡片实测高度 `109px`,第一页仍渲染 `50` 辆并由内部列表滚动;
|
- `390px` 与 `1440px` 视口横向溢出均为 `0px`;
|
||||||
- 控制台未发现本次改动产生的运行时异常;仅保留 Semi UI 在 React StrictMode 下既有的 `findDOMNode` 弃用警告。
|
- 生产数据下总里程、当日里程、速度和 SOC 均无视觉裁切;
|
||||||
|
- 控制台未发现本次改动产生的运行时异常。
|
||||||
|
|
||||||
## Comparison History
|
## Comparison History
|
||||||
|
|
||||||
### Pass 1 — fixed
|
### Pass 1 — fixed
|
||||||
|
|
||||||
- 生产手机端的“今日上报”和“无实时位置”数值被截断,信息层级与主要车队指标混在一起。
|
- 原移动端指标轨道仍被通用 `has-context` 网格分成两列,隐藏的来源上下文占用一半宽度,导致总里程显示为 `80,27…`。
|
||||||
- 生产车辆卡片纵向留白过多,`390 × 844` 首屏只能看到约 `2.5` 辆。
|
- 当前修复将四项实时指标恢复到完整宽度的 `2 × 2` 网格,并压缩重复的纵向间距。
|
||||||
- 已将辅助指标改成完整的紧凑数值,将每辆车的协议、里程与坐标收拢到固定证据网格。
|
- 同视口并排对比确认地图在首屏获得约 `83px` 的额外可见空间,车型和里程信息完整。
|
||||||
- 并排对比后未发现 P0、P1 或 P2 视觉与交互问题。
|
- 未发现 P0、P1 或 P2 视觉与交互问题。
|
||||||
|
|
||||||
final result: passed
|
final result: passed
|
||||||
|
|||||||
Reference in New Issue
Block a user