feat: refine responsive vehicle record
This commit is contained in:
@@ -231,7 +231,11 @@ function TelemetrySourceCell({ item }: { item: LatestTelemetryValue }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function telemetryRowKey(item?: LatestTelemetryValue) {
|
function telemetryRowKey(item?: LatestTelemetryValue) {
|
||||||
return `${item?.protocol ?? ''}-${item?.category ?? ''}-${item?.sourceField ?? ''}-${item?.frameId ?? ''}`;
|
return [
|
||||||
|
item?.protocol ?? '',
|
||||||
|
item?.sourceEndpoint ?? '',
|
||||||
|
item?.key || `${item?.category ?? ''}:${item?.sourceField ?? ''}`
|
||||||
|
].join('\u0000');
|
||||||
}
|
}
|
||||||
|
|
||||||
function TelemetryPanel({ data, pending, error }: { data?: LatestTelemetryResponse; pending: boolean; error?: string }) {
|
function TelemetryPanel({ data, pending, error }: { data?: LatestTelemetryResponse; pending: boolean; error?: string }) {
|
||||||
@@ -265,13 +269,13 @@ function TelemetryPanel({ data, pending, error }: { data?: LatestTelemetryRespon
|
|||||||
.map((key) => ({ key, label: categoryLabels.get(key) ?? key, count: indexed.valuesByProtocolCategory.get(`${activeProtocol}\u0000${key}`)?.length ?? 0 }));
|
.map((key) => ({ key, label: categoryLabels.get(key) ?? key, count: indexed.valuesByProtocolCategory.get(`${activeProtocol}\u0000${key}`)?.length ?? 0 }));
|
||||||
const activeCategory = indexed.valuesByProtocolCategory.has(`${activeProtocol}\u0000${selectedCategory}`) ? selectedCategory : categories[0]?.key ?? '';
|
const activeCategory = indexed.valuesByProtocolCategory.has(`${activeProtocol}\u0000${selectedCategory}`) ? selectedCategory : categories[0]?.key ?? '';
|
||||||
const visibleMetrics = indexed.valuesByProtocolCategory.get(`${activeProtocol}\u0000${activeCategory}`) ?? [];
|
const visibleMetrics = indexed.valuesByProtocolCategory.get(`${activeProtocol}\u0000${activeCategory}`) ?? [];
|
||||||
const columns = [
|
const columns = useMemo(() => [
|
||||||
{ title: '字段 / 协议映射', dataIndex: 'label', width: 260, render: (_: unknown, item: LatestTelemetryValue) => <TelemetryFieldCell item={item} /> },
|
{ title: '字段 / 协议映射', dataIndex: 'label', width: 260, render: (_: unknown, item: LatestTelemetryValue) => <TelemetryFieldCell item={item} /> },
|
||||||
{ title: '当前值', dataIndex: 'value', width: 170, render: (_: unknown, item: LatestTelemetryValue) => <TelemetryValueCell item={item} onInspect={setInspectedValue} /> },
|
{ title: '当前值', dataIndex: 'value', width: 170, render: (_: unknown, item: LatestTelemetryValue) => <TelemetryValueCell item={item} onInspect={setInspectedValue} /> },
|
||||||
{ title: '质量 / 新鲜度', dataIndex: 'quality', width: 170, render: (_: unknown, item: LatestTelemetryValue) => <TelemetryQualityCell item={item} /> },
|
{ title: '质量 / 新鲜度', dataIndex: 'quality', width: 170, render: (_: unknown, item: LatestTelemetryValue) => <TelemetryQualityCell item={item} /> },
|
||||||
{ title: '设备 / 接收时间', dataIndex: 'deviceTime', width: 230, render: (_: unknown, item: LatestTelemetryValue) => <TelemetryTimeCell item={item} /> },
|
{ title: '设备 / 接收时间', dataIndex: 'deviceTime', width: 230, render: (_: unknown, item: LatestTelemetryValue) => <TelemetryTimeCell item={item} /> },
|
||||||
{ title: '数据来源', dataIndex: 'protocol', width: 180, render: (_: unknown, item: LatestTelemetryValue) => <TelemetrySourceCell item={item} /> }
|
{ title: '数据来源', dataIndex: 'protocol', width: 180, render: (_: unknown, item: LatestTelemetryValue) => <TelemetrySourceCell item={item} /> }
|
||||||
];
|
], []);
|
||||||
const state = pending
|
const state = pending
|
||||||
? <div className="v2-telemetry-state" role="status"><strong>正在读取最新遥测</strong><span>按协议整理最新标量证据…</span></div>
|
? <div className="v2-telemetry-state" role="status"><strong>正在读取最新遥测</strong><span>按协议整理最新标量证据…</span></div>
|
||||||
: error
|
: error
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ describe('V2 production entry', () => {
|
|||||||
expect(corePageSources.VehiclePage).toContain('<List.Item className="v2-telemetry-mobile-item"');
|
expect(corePageSources.VehiclePage).toContain('<List.Item className="v2-telemetry-mobile-item"');
|
||||||
expect(corePageSources.VehiclePage).toContain('className="v2-telemetry-mobile-action"');
|
expect(corePageSources.VehiclePage).toContain('className="v2-telemetry-mobile-action"');
|
||||||
expect(corePageSources.VehiclePage).toContain("placement={mobileLayout ? 'bottom' : 'right'}");
|
expect(corePageSources.VehiclePage).toContain("placement={mobileLayout ? 'bottom' : 'right'}");
|
||||||
|
expect(corePageSources.VehiclePage).toContain("item?.sourceEndpoint ?? ''");
|
||||||
|
expect(corePageSources.VehiclePage).toContain('const columns = useMemo(() => [');
|
||||||
expect(corePageSources.VehiclePage).toContain('<List');
|
expect(corePageSources.VehiclePage).toContain('<List');
|
||||||
expect(corePageSources.VehiclePage).toContain('className="v2-event-list"');
|
expect(corePageSources.VehiclePage).toContain('className="v2-event-list"');
|
||||||
expect(corePageSources.VehiclePage).toContain('useMobileLayout');
|
expect(corePageSources.VehiclePage).toContain('useMobileLayout');
|
||||||
@@ -394,6 +396,10 @@ describe('V2 production entry', () => {
|
|||||||
expect(workspaceStyles).toContain('.v2-vehicle-directory-v3 .v2-mobile-filter-toggle-copy small {');
|
expect(workspaceStyles).toContain('.v2-vehicle-directory-v3 .v2-mobile-filter-toggle-copy small {');
|
||||||
expect(workspaceStyles).toContain('.v2-vehicle-mobile-filter-sidesheet.semi-sidesheet-bottom .semi-sidesheet-inner {');
|
expect(workspaceStyles).toContain('.v2-vehicle-mobile-filter-sidesheet.semi-sidesheet-bottom .semi-sidesheet-inner {');
|
||||||
expect(workspaceStyles).toContain('grid-template-columns: repeat(2, minmax(0, 1fr));');
|
expect(workspaceStyles).toContain('grid-template-columns: repeat(2, minmax(0, 1fr));');
|
||||||
|
expect(workspaceStyles).toContain('.v2-vehicle-record-v3 .v2-vehicle-command-card > .semi-card-body {');
|
||||||
|
expect(workspaceStyles).toContain('grid-template-columns: minmax(210px, .62fr) minmax(0, 1.38fr);');
|
||||||
|
expect(workspaceStyles).toContain('.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid {');
|
||||||
|
expect(workspaceStyles).toContain('.v2-vehicle-mobile-actions-sidesheet .v2-vehicle-mobile-actions-list {');
|
||||||
expect(corePageSources.MonitorPage).not.toContain('<select');
|
expect(corePageSources.MonitorPage).not.toContain('<select');
|
||||||
expect(corePageSources.MonitorPage).not.toContain('<textarea');
|
expect(corePageSources.MonitorPage).not.toContain('<textarea');
|
||||||
expect(corePageSources.MonitorPage).not.toContain('<button');
|
expect(corePageSources.MonitorPage).not.toContain('<button');
|
||||||
|
|||||||
@@ -16818,7 +16818,7 @@
|
|||||||
|
|
||||||
.v2-vehicle-record-v3.v2-vehicle-record-page {
|
.v2-vehicle-record-v3.v2-vehicle-record-page {
|
||||||
gap: 7px;
|
gap: 7px;
|
||||||
padding: 7px 7px 88px;
|
padding: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-vehicle-record-v3 .v2-vehicle-command-card.semi-card {
|
.v2-vehicle-record-v3 .v2-vehicle-command-card.semi-card {
|
||||||
@@ -18263,3 +18263,284 @@
|
|||||||
max-height: min(42dvh, 180px);
|
max-height: min(42dvh, 180px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Short landscape vehicle record.
|
||||||
|
* The shell already reserves the fixed mobile navigation. Split the command
|
||||||
|
* card into an identity/action rail and a live evidence canvas so the latest
|
||||||
|
* report remains visible before the user scrolls.
|
||||||
|
*/
|
||||||
|
@media (max-width: 900px) and (max-height: 480px) and (orientation: landscape) {
|
||||||
|
.v2-vehicle-record-v3.v2-vehicle-record-page {
|
||||||
|
gap: 7px;
|
||||||
|
padding: 6px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card > .semi-card-body {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(210px, .62fr) minmax(0, 1.38fr);
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-record-command.v2-workspace-command-bar {
|
||||||
|
min-height: 0;
|
||||||
|
align-content: start;
|
||||||
|
border-right: 1px solid #dfe7f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-workspace-command-copy {
|
||||||
|
min-height: 57px;
|
||||||
|
gap: 2px;
|
||||||
|
border-right: 0;
|
||||||
|
border-bottom: 1px solid #e4eaf2;
|
||||||
|
padding: 5px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-plate {
|
||||||
|
min-height: 29px;
|
||||||
|
padding-inline: 7px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .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 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-vin {
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-vin small {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-vin b {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-vin .semi-button {
|
||||||
|
width: 22px;
|
||||||
|
min-width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-workspace-command-actions {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-workspace-command-meta {
|
||||||
|
border-right: 0;
|
||||||
|
border-bottom: 1px solid #e7edf4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-meta {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-meta > span {
|
||||||
|
min-height: 35px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-meta > span + span {
|
||||||
|
border-top: 1px solid #edf1f6;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-meta small {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-meta strong {
|
||||||
|
margin-top: 1px;
|
||||||
|
font-size: 9px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .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 .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 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-actions {
|
||||||
|
min-height: 43px;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
gap: 4px;
|
||||||
|
padding: 5px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-actions > .semi-button {
|
||||||
|
min-height: 33px;
|
||||||
|
border-radius: 7px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-actions > .semi-button .semi-button-content {
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-actions > .semi-button .semi-button-content-left {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-header.v2-vehicle-record-command .v2-identity-actions > .semi-button .semi-button-content-right {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-live-section {
|
||||||
|
min-width: 0;
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-live-section > .v2-workspace-panel-header {
|
||||||
|
min-height: 36px;
|
||||||
|
padding: 4px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-live-section .v2-workspace-panel-copy > h5.semi-typography {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-live-section .v2-live-report-meta {
|
||||||
|
max-width: 64%;
|
||||||
|
font-size: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid > .v2-live-metric {
|
||||||
|
min-height: 58px;
|
||||||
|
border-top: 0;
|
||||||
|
border-left: 1px solid #e7edf4;
|
||||||
|
padding: 6px 7px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid > .v2-live-metric:nth-child(3n + 1) {
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid > .v2-live-metric:nth-child(n + 4) {
|
||||||
|
border-top: 1px solid #e7edf4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid > .v2-live-metric::after {
|
||||||
|
right: 7px;
|
||||||
|
left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid small {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid strong,
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-source-link {
|
||||||
|
margin-top: 3px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid strong.is-text {
|
||||||
|
font-size: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-primary-protocol.semi-tag {
|
||||||
|
min-height: 19px;
|
||||||
|
margin-top: 3px;
|
||||||
|
padding-inline: 5px;
|
||||||
|
font-size: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-source-link.semi-button {
|
||||||
|
height: 19px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-live-grid > .v2-live-metric > span:last-child {
|
||||||
|
margin-top: 3px;
|
||||||
|
font-size: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-current-location {
|
||||||
|
min-height: 37px;
|
||||||
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-current-location > span {
|
||||||
|
gap: 4px;
|
||||||
|
padding: 4px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-current-location > span + span {
|
||||||
|
border-top: 0;
|
||||||
|
border-left: 1px solid #e4eaf2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-current-location small,
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-current-location strong {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-record-v3 .v2-vehicle-command-card .v2-current-address-action.semi-button {
|
||||||
|
min-height: 25px;
|
||||||
|
padding-inline: 6px;
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet.semi-sidesheet-bottom .semi-sidesheet-inner {
|
||||||
|
height: 100dvh !important;
|
||||||
|
max-height: 100dvh;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet.semi-sidesheet-bottom .semi-sidesheet-header {
|
||||||
|
min-height: 56px;
|
||||||
|
padding: 7px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet.semi-sidesheet-bottom .semi-sidesheet-body {
|
||||||
|
padding: 9px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet.semi-sidesheet-bottom .semi-sidesheet-footer {
|
||||||
|
padding: 7px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet .v2-vehicle-mobile-actions-title {
|
||||||
|
gap: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet .v2-vehicle-mobile-actions-title > span {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet .v2-vehicle-mobile-actions-list {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet .v2-vehicle-mobile-actions-list > .semi-button {
|
||||||
|
min-height: 72px;
|
||||||
|
justify-content: center;
|
||||||
|
padding-inline: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet .v2-vehicle-mobile-actions-list > .semi-button .semi-button-content {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-vehicle-mobile-actions-sidesheet .v2-vehicle-mobile-actions-list > .semi-button .semi-button-content-right {
|
||||||
|
max-width: 100%;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
gap: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user