package com.battery.business.service.impl; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.Date; import java.util.List; import java.util.Map; import org.springframework.stereotype.Service; import com.battery.business.mapper.TTestMapper; import com.battery.business.service.ITTestService; import com.battery.business.service.ITestDataQueryService; /** 三类数据直接读取尚存的持久化记录;修订在同一事实表内生效。 */ @Service public class TestDataQueryServiceImpl implements ITestDataQueryService { private final TTestMapper mapper; private final ITTestService tests; public TestDataQueryServiceImpl(TTestMapper mapper, ITTestService tests) { this.mapper = mapper; this.tests = tests; } /** 查询尚存实时采样与授权历史导入记录,保留检测柜和采集器各自的设备时间。 */ @Override public List> records(Long testId) { tests.selectTestById(testId); List> rows = normalizeApiTimes(mapper.selectPersistedFinalRealtimeRecords(testId)); for (Map row : rows) { Object extension = row.get("extensionMeasurementsJson"); if (extension != null) row.put("relativeTimeSeconds", com.alibaba.fastjson2.JSON.parseObject(extension.toString()).get("relativeTimeSeconds")); } return rows; } /** 查询尚存工步记录,包含设备统计与授权历史导入。 */ @Override public List> steps(Long testId) { tests.selectTestById(testId); List> rows = normalizeApiTimes(mapper.selectPersistedFinalStepRecords(testId)); for (Map row : rows) { Object extension = row.get("extensionMeasurementsJson"); if (extension == null) continue; Map values = com.alibaba.fastjson2.JSON.parseObject(extension.toString()); // 中值与历史峰谷值是不同测量,不将旧扩展字段回退映射为中值。 // 四组容量能量是设备工步层事实:单项列无法表达未确认方向时,调用方读这四组核对。 for (String field : List.of("stepDuration", "startVoltage", "chargeMedianVoltage", "dischargeMedianVoltage", "chargeCapacity", "dischargeCapacity", "chargeEnergy", "dischargeEnergy")) if (values.containsKey(field)) row.put(field, values.get(field)); } return rows; } /** 查询尚存循环记录,包含设备统计、工步层聚合与授权历史导入;携带来源类别供界面标注聚合来源。 */ @Override public List> cycles(Long testId) { tests.selectTestById(testId); return normalizeApiTimes(mapper.selectPersistedFinalCycleRecords(testId)); } private List> normalizeApiTimes(List> rows) { if (rows == null) return List.of(); // DATETIME(3) 保存 UTC,JDBC 返回的无时区值也必须按 UTC 转换,不能采用服务器默认时区。 for (Map row : rows) row.replaceAll((key, value) -> value instanceof Date date ? date.getTime() : value instanceof Instant instant ? instant.toEpochMilli() : value instanceof LocalDateTime time ? time.toInstant(ZoneOffset.UTC).toEpochMilli() : value); return rows; } }