feat(platform): show mileage confidence metrics
This commit is contained in:
@@ -202,6 +202,11 @@ export function Mileage({
|
||||
const anomalyRows = rows.filter((row) => row.anomalySeverity);
|
||||
const peakMileage = maxMileageRow(rows);
|
||||
const pageMileageTotal = rows.reduce((total, row) => total + row.dailyMileageKm, 0);
|
||||
const anomalyRate = rows.length > 0 ? (anomalyRows.length / rows.length) * 100 : 0;
|
||||
const peakMileageShare = pageMileageTotal > 0 && peakMileage ? (peakMileage.dailyMileageKm / pageMileageTotal) * 100 : 0;
|
||||
const pageCoverageRate = summary.recordCount > 0 ? (rows.length / summary.recordCount) * 100 : 0;
|
||||
const confidenceStatus = anomalyRows.length > 0 || pageCoverageRate < 100 ? '需复核' : '可用于 BI';
|
||||
const confidenceColor = confidenceStatus === '可用于 BI' ? 'green' as const : 'orange' as const;
|
||||
const maxDateMileage = Math.max(...dateSeries.map((item) => item.value), 0);
|
||||
const maxSourceMileage = Math.max(...sourceSeries.map((item) => item.value), 0);
|
||||
const filterSummary = [
|
||||
@@ -389,10 +394,13 @@ export function Mileage({
|
||||
</div>
|
||||
<div className="vp-stat-insight-grid">
|
||||
{[
|
||||
{ label: '统计可信度', value: confidenceStatus, color: confidenceColor, detail: anomalyRows.length > 0 ? '存在异常里程记录,建议先核对来源证据。' : '当前分页未发现异常记录。' },
|
||||
{ label: '异常率', value: formatPercent(anomalyRate), color: anomalyRows.length > 0 ? 'orange' as const : 'green' as const, detail: `${anomalyRows.length.toLocaleString()} / ${rows.length.toLocaleString()} 条明细命中异常标记。` },
|
||||
{ label: '最大单日占比', value: formatPercent(peakMileageShare), color: peakMileageShare > 50 ? 'orange' as const : 'blue' as const, detail: peakMileage ? `${peakMileage.plate || peakMileage.vin} 贡献最高单日里程。` : '暂无明细。' },
|
||||
{ label: '当前页里程', value: `${formatKm(pageMileageTotal)} km`, color: 'blue' as const, detail: '用于快速核对当前分页明细合计。' },
|
||||
{ label: '异常记录', value: anomalyRows.length.toLocaleString(), color: anomalyRows.length > 0 ? 'orange' as const : 'green' as const, detail: '来自异常标记,优先核对首末总里程和断链。' },
|
||||
{ label: '最大单日', value: peakMileage ? `${formatKm(peakMileage.dailyMileageKm)} km` : '-', color: 'blue' as const, detail: peakMileage ? `${peakMileage.plate || peakMileage.vin} / ${peakMileage.date}` : '暂无明细。' },
|
||||
{ label: '统计覆盖率', value: summary.recordCount > 0 ? formatPercent((rows.length / summary.recordCount) * 100) : '0%', color: 'grey' as const, detail: '当前分页记录数 / 全量统计记录数。' }
|
||||
{ label: '分页覆盖率', value: formatPercent(pageCoverageRate), color: pageCoverageRate >= 100 ? 'green' as const : 'grey' as const, detail: '当前分页记录数 / 全量统计记录数。' }
|
||||
].map((item) => (
|
||||
<Card key={item.label} bordered>
|
||||
<Tag color={item.color}>{item.label}</Tag>
|
||||
|
||||
@@ -5884,6 +5884,13 @@ test('shows mileage statistics workspace with trend source and definition', asyn
|
||||
expect(screen.getAllByText('1').length).toBeGreaterThanOrEqual(1);
|
||||
expect(screen.getByText('最大单日')).toBeInTheDocument();
|
||||
expect(screen.getByText('60 km')).toBeInTheDocument();
|
||||
expect(screen.getByText('统计可信度')).toBeInTheDocument();
|
||||
expect(screen.getByText('异常率')).toBeInTheDocument();
|
||||
expect(screen.getByText('25%')).toBeInTheDocument();
|
||||
expect(screen.getByText('最大单日占比')).toBeInTheDocument();
|
||||
expect(screen.getByText('42.9%')).toBeInTheDocument();
|
||||
expect(screen.getByText('分页覆盖率')).toBeInTheDocument();
|
||||
expect(screen.getByText('100%')).toBeInTheDocument();
|
||||
expect(screen.getByText('统计口径')).toBeInTheDocument();
|
||||
expect(screen.getByText((content) => content.includes('区间总值应等于各日里程之和'))).toBeInTheDocument();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user