feat(history): align fields quality and exports

This commit is contained in:
lingniu
2026-07-16 16:46:10 +08:00
parent 17c4591040
commit a2722e4afd
13 changed files with 273 additions and 66 deletions

View File

@@ -580,6 +580,9 @@ func TestHistoryExportRunsAsControlledAsyncJob(t *testing.T) {
if len(body) < 3 || string(body[:3]) != "\xEF\xBB\xBF" {
t.Fatalf("CSV should include UTF-8 BOM")
}
if !strings.Contains(string(body), "数据质量,质量原因,证据ID") {
t.Fatalf("CSV should explain platform quality: %q", body[:min(len(body), 512)])
}
return
}
time.Sleep(10 * time.Millisecond)
@@ -671,6 +674,39 @@ func TestRawMetricMetadataKeepsProtocolAndUnit(t *testing.T) {
}
}
func TestHistoryQualityReasonsExplainLocationRawAndMileageWarnings(t *testing.T) {
quality, reason := historyLocationQuality(HistoryLocationRow{Longitude: 0, Latitude: 0, SpeedKmh: 30, DeviceTime: "2026-07-14 09:29:58", ServerTime: "2026-07-14 09:29:59"})
if quality != "warning" || !strings.Contains(reason, "坐标") {
t.Fatalf("invalid coordinate should be explained: %s %s", quality, reason)
}
quality, reason = historyRawQuality(RawFrameRow{DeviceTime: "2026-07-14 09:29:58", ServerTime: "2026-07-14 09:29:59", ParseStatus: "failed", ParseError: "checksum"})
if quality != "warning" || !strings.Contains(reason, "checksum") {
t.Fatalf("parse failure should retain detail: %s %s", quality, reason)
}
quality, reason = historyMileageQuality(DailyMileageRow{StartMileageKm: 100, EndMileageKm: 130, DailyMileageKm: 12})
if quality != "warning" || !strings.Contains(reason, "不一致") {
t.Fatalf("mileage mismatch should be explained: %s %s", quality, reason)
}
}
func TestMergeDiscoveredRawMetricsScansFetchedScope(t *testing.T) {
rows := []HistoryDataRow{
{Values: map[string]any{"frameType": "realtime"}},
{Values: map[string]any{"gb32960.vehicle.soc_percent": 88}},
}
columns := mergeDiscoveredRawMetrics(historyRawMetrics(), rows)
found := false
for _, column := range columns {
if column.Key == "gb32960.vehicle.soc_percent" {
found = true
break
}
}
if !found {
t.Fatalf("discovered field outside the visible page should remain selectable: %+v", columns)
}
}
func TestBuildLatestTelemetryResponseUsesCatalogAndNewestSourceEvidence(t *testing.T) {
now := time.Date(2026, 7, 14, 9, 30, 0, 0, time.FixedZone("Asia/Shanghai", 8*60*60))
definitions := []MetricDefinition{