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

@@ -31,7 +31,7 @@ function historyData(vin: string, plate: string, asOf: string): HistoryDataRespo
return {
category: 'location', columns: [metric], total: 1, limit: 50, offset: 0, asOf,
summary: { resultRows: 1, vehicleCount: 1, sources: ['JT808'], queryDurationMs: 12 },
rows: [{ id: `${vin}-row`, vin, plate, protocol: 'JT808', deviceTime: '2026-07-16 04:00:00', serverTime: '2026-07-16 04:00:01', quality: 'normal', evidenceId: `${vin}-evidence`, values: { speedKmh: 32 } }]
rows: [{ id: `${vin}-row`, vin, plate, protocol: 'JT808', deviceTime: '2026-07-16 04:00:00', serverTime: '2026-07-16 04:00:01', quality: 'normal', qualityReason: '坐标、速度、里程及设备/服务时间通过基础校验', evidenceId: `${vin}-evidence`, values: { speedKmh: 32 } }]
};
}
@@ -111,6 +111,10 @@ test('opens a working column visibility panel and preserves non-hideable identit
fireEvent.click(screen.getByRole('button', { name: '列设置' }));
expect(screen.getByRole('dialog', { name: '列显示设置' })).toBeInTheDocument();
fireEvent.change(screen.getByPlaceholderText('搜索字段名 / 字段 key'), { target: { value: 'soc' } });
expect(screen.getByRole('checkbox', { name: /SOC/ })).toBeInTheDocument();
expect(screen.queryByRole('checkbox', { name: /速度/ })).not.toBeInTheDocument();
fireEvent.change(screen.getByPlaceholderText('搜索字段名 / 字段 key'), { target: { value: '' } });
fireEvent.click(screen.getByRole('checkbox', { name: /速度/ }));
expect(screen.queryByRole('columnheader', { name: '速度 (km/h)' })).not.toBeInTheDocument();
expect(screen.getByRole('columnheader', { name: 'VIN' })).toBeInTheDocument();
@@ -139,3 +143,26 @@ test('keeps history readable without mounting operator-only export requests for
expect(mocks.historyExports).not.toHaveBeenCalled();
expect(mocks.createHistoryExport).not.toHaveBeenCalled();
});
test('uses selected chartable fields for trends and omits empty RAW evidence UI', async () => {
const totalMileageMetric = { key: 'totalMileageKm', label: '总里程', unit: 'km', category: 'location', valueType: 'number', defaultVisible: true };
const data = historyData('OLDVIN', '旧车牌', 'old-as-of');
data.columns = [metric, totalMileageMetric];
data.rows[0].evidenceId = undefined;
data.rows[0].values.totalMileageKm = 1234;
mocks.historyMetricCatalog.mockResolvedValue({ categories: [{ key: 'location', label: '位置数据' }], metrics: [metric, totalMileageMetric] });
mocks.historyData.mockResolvedValue(data);
mocks.historySeries.mockResolvedValue(historySeries('OLDVIN', '旧车牌', 'old-as-of'));
mocks.historyExports.mockResolvedValue([]);
renderPage();
expect((await screen.findAllByText('旧车牌')).length).toBeGreaterThan(0);
await waitFor(() => expect(mocks.historySeries).toHaveBeenCalled());
expect((mocks.historySeries.mock.calls[mocks.historySeries.mock.calls.length - 1]?.[0] as URLSearchParams).get('metrics')).toBe('speedKmh,totalMileageKm');
expect(screen.queryByText('RAW 证据')).not.toBeInTheDocument();
const mileageToggle = screen.getAllByTitle('点击取消显示').find((button) => button.textContent?.includes('总里程'));
expect(mileageToggle).toBeDefined();
fireEvent.click(mileageToggle!);
await waitFor(() => expect((mocks.historySeries.mock.calls[mocks.historySeries.mock.calls.length - 1]?.[0] as URLSearchParams).get('metrics')).toBe('speedKmh'));
});