refine Semi UI operations diagnosis cockpit
This commit is contained in:
@@ -300,7 +300,13 @@ test('fuzzy searches a vehicle and renders all source diagnosis evidence', async
|
||||
fireEvent.click(candidateButton);
|
||||
expect(await screen.findByText('当前推荐 G7')).toBeInTheDocument();
|
||||
expect(screen.getByText('1 个来源')).toBeInTheDocument();
|
||||
expect(screen.getByRole('group', { name: '车辆来源诊断概览' })).toHaveClass('v2-source-summary-region');
|
||||
expect(document.querySelector('.v2-source-summary-region > .v2-source-summary.semi-card-group')).toBeInTheDocument();
|
||||
expect(document.querySelectorAll('.v2-source-summary-card.semi-card')).toHaveLength(4);
|
||||
expect(document.querySelector('.v2-source-summary-card.is-vehicle')).toHaveTextContent('粤A00001');
|
||||
expect(document.querySelector('.v2-source-summary-card.is-recommended')).toHaveTextContent('G7');
|
||||
expect(document.querySelector('.v2-source-summary-card.is-source-health')).toHaveClass('is-warning');
|
||||
expect(document.querySelector('.v2-source-summary-card.is-policy')).toHaveTextContent('v1');
|
||||
expect(document.querySelectorAll('.v2-source-summary-card')[1]?.querySelector('.semi-tag')).toHaveTextContent('JT808');
|
||||
expect(screen.getByText('推荐说明').closest('.semi-card')).toHaveClass('v2-source-recommendation');
|
||||
expect(screen.getByText('最近策略审计').closest('.semi-card')).toHaveClass('v2-source-audit');
|
||||
@@ -378,6 +384,9 @@ test('allows provider maintenance but keeps canonical source policy read only',
|
||||
expect(document.querySelector('.v2-source-table')).not.toBeInTheDocument();
|
||||
expect(document.querySelector('.v2-source-mobile-card.semi-card')).toBeInTheDocument();
|
||||
expect(document.querySelector('.v2-source-mobile-descriptions.semi-descriptions')).toBeInTheDocument();
|
||||
expect(screen.getByRole('group', { name: '车辆来源诊断概览' })).toHaveClass('v2-source-summary-region');
|
||||
expect(document.querySelector('.v2-source-summary-region > .v2-source-summary.semi-card-group')).toBeInTheDocument();
|
||||
expect(document.querySelectorAll('.v2-source-summary-card.semi-card')).toHaveLength(4);
|
||||
expect(screen.getByText('优先级 100')).toBeInTheDocument();
|
||||
expect(screen.queryByLabelText('JT808 优先级')).not.toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole('button', { name: '维护提供方' }));
|
||||
|
||||
@@ -306,12 +306,14 @@ function SourceDiagnosticWorkspace() {
|
||||
{!selected ? <Empty className="v2-source-empty" title="先选择一辆车" description="将展示所有协议和同协议多终端、推荐原因、上报周期与可审计策略。" /> : null}
|
||||
{selected && diagnostic.isPending ? <div className="v2-source-loading" role="status"><Spin size="large" /><strong>正在读取来源证据</strong><span>只查询当前车辆,不会扫描整车队。</span></div> : null}
|
||||
{data ? <>
|
||||
<div className="v2-source-summary">
|
||||
<Card className="v2-source-summary-card"><small>车辆</small><strong>{data.evidence.plate || selected?.plate || '未绑定车牌'}</strong><span>{data.evidence.vin}</span></Card>
|
||||
<Card className="v2-source-summary-card"><small>当前推荐</small><strong>{data.evidence.recommendedLocationLabel || '暂无推荐'}</strong><Tag color="blue" type="light" size="small">{data.evidence.recommendedLocationProtocol || '—'}</Tag></Card>
|
||||
<Card className={`v2-source-summary-card${data.evidence.locationConflict ? ' is-warning' : ' is-ok'}`}><small>来源状态</small><strong>{data.evidence.locationSources.filter((item) => item.online).length} / {data.evidence.locationSources.length} 在线</strong><span>{data.evidence.locationConflict ? `位置冲突 ${number(data.evidence.conflictDistanceM)}m` : '未发现实时位置冲突'}</span></Card>
|
||||
<Card className="v2-source-summary-card"><small>策略版本</small><strong>v{data.policy.version}</strong><span>{data.policy.updatedAt ? <>{data.policy.updatedBy} · <PlatformTime className="v2-ops-time" value={data.policy.updatedAt} sourceZone="utc" /></> : '尚无人工调整'}</span></Card>
|
||||
</div>
|
||||
<section className="v2-source-summary-region" role="group" aria-label="车辆来源诊断概览">
|
||||
<CardGroup className="v2-source-summary" type="grid" spacing={10}>
|
||||
<Card className="v2-source-summary-card is-vehicle"><small>车辆</small><strong>{data.evidence.plate || selected?.plate || '未绑定车牌'}</strong><span>{data.evidence.vin}</span></Card>
|
||||
<Card className="v2-source-summary-card is-recommended"><small>当前推荐</small><strong>{data.evidence.recommendedLocationLabel || '暂无推荐'}</strong><Tag color="blue" type="light" size="small">{data.evidence.recommendedLocationProtocol || '—'}</Tag></Card>
|
||||
<Card className={`v2-source-summary-card is-source-health${data.evidence.locationConflict ? ' is-warning' : ' is-ok'}`}><small>来源状态</small><strong>{data.evidence.locationSources.filter((item) => item.online).length} / {data.evidence.locationSources.length} 在线</strong><span>{data.evidence.locationConflict ? `位置冲突 ${number(data.evidence.conflictDistanceM)}m` : '未发现实时位置冲突'}</span></Card>
|
||||
<Card className="v2-source-summary-card is-policy"><small>策略版本</small><strong>v{data.policy.version}</strong><span>{data.policy.updatedAt ? <>{data.policy.updatedBy} · <PlatformTime className="v2-ops-time" value={data.policy.updatedAt} sourceZone="utc" /></> : '尚无人工调整'}</span></Card>
|
||||
</CardGroup>
|
||||
</section>
|
||||
<Card className="v2-source-recommendation"><header><Tag color="blue" type="light" size="small">推荐说明</Tag><span>{data.refreshHint}</span></header><p>{data.recommendationReason}</p></Card>
|
||||
{!editable ? <div className="v2-source-readonly"><Tag color="orange" type="light" size="small">只读权限</Tag><span>当前账号可查看诊断证据;只有管理员可以调整启停和优先级。</span></div> : null}
|
||||
{mobileLayout
|
||||
|
||||
@@ -287,7 +287,9 @@ describe('V2 production entry', () => {
|
||||
expect(corePageSources.OperationsPage).not.toContain('<dl><div><dt>生产数据模式</dt>');
|
||||
expect(corePageSources.OperationsPage).toContain('<Empty className="v2-source-empty"');
|
||||
expect(corePageSources.OperationsPage).toContain('<Spin size="large"');
|
||||
expect(corePageSources.OperationsPage).toContain('<Card className="v2-source-summary-card"');
|
||||
expect(corePageSources.OperationsPage).toContain('<CardGroup className="v2-source-summary"');
|
||||
expect(corePageSources.OperationsPage).toContain('<Card className="v2-source-summary-card is-vehicle"');
|
||||
expect(corePageSources.OperationsPage).toContain('<Card className="v2-source-summary-card is-recommended"');
|
||||
expect(corePageSources.OperationsPage).toContain('<Card className={`v2-source-summary-card');
|
||||
expect(corePageSources.OperationsPage).toContain('<Card className="v2-source-recommendation"');
|
||||
expect(corePageSources.OperationsPage).toContain('<Card className="v2-source-audit"');
|
||||
|
||||
@@ -12492,6 +12492,101 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Semi UI single-vehicle diagnosis cockpit.
|
||||
* Preserve the four-column desktop scan while keeping source evidence inside
|
||||
* the first mobile viewport instead of spending it on four full-width cards.
|
||||
*/
|
||||
.v2-source-summary.semi-card-group {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.v2-source-summary-region {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.v2-source-summary-card.is-recommended.semi-card {
|
||||
border-color: #c8dbf6;
|
||||
background: linear-gradient(145deg, #f2f7ff 0%, #fff 72%);
|
||||
box-shadow: inset 0 3px #2f6fe4, 0 5px 16px rgba(31, 53, 80, .045);
|
||||
}
|
||||
|
||||
.v2-source-summary-card.is-recommended strong {
|
||||
color: #185fbf;
|
||||
}
|
||||
|
||||
@media (max-width: 1180px) and (min-width: 681px) {
|
||||
.v2-source-summary.semi-card-group {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 680px) {
|
||||
.v2-source-summary.semi-card-group {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 6px;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.v2-source-summary-card > .semi-card-body {
|
||||
min-height: 74px;
|
||||
padding: 9px 10px;
|
||||
}
|
||||
|
||||
.v2-source-summary-card small,
|
||||
.v2-source-summary-card > .semi-card-body > span:not(.semi-tag) {
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.v2-source-summary-card strong {
|
||||
margin-block: 5px 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.v2-source-summary-card .semi-tag {
|
||||
min-height: 19px;
|
||||
padding-inline: 7px;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.v2-source-summary-card.is-ok,
|
||||
.v2-source-summary-card.is-warning {
|
||||
box-shadow: inset 0 3px #22a878, 0 5px 16px rgba(31, 53, 80, .045);
|
||||
}
|
||||
|
||||
.v2-source-summary-card.is-warning {
|
||||
box-shadow: inset 0 3px #e8a12b, 0 5px 16px rgba(31, 53, 80, .045);
|
||||
}
|
||||
|
||||
.v2-source-recommendation.semi-card {
|
||||
margin: 8px 10px;
|
||||
border-left-width: 3px;
|
||||
}
|
||||
|
||||
.v2-source-recommendation > .semi-card-body {
|
||||
padding: 9px 10px;
|
||||
}
|
||||
|
||||
.v2-source-recommendation header {
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.v2-source-recommendation header span {
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
font-size: 9px;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.v2-source-recommendation p {
|
||||
margin-top: 6px;
|
||||
font-size: 10px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Semi UI mileage workspace convergence.
|
||||
* Keep a single query/summary surface, one table scroll owner and the same
|
||||
|
||||
Reference in New Issue
Block a user