package com.battery.business.service.report;
|
|
import javax.sql.DataSource;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.stream.Collectors;
|
import com.alibaba.fastjson2.JSON;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.stereotype.Repository;
|
|
/** 化成身份与版本使用独立表,复用对比报表的事务内存储规则。 */
|
@Repository
|
public class FormationReportRepository extends ReportVersionRepository
|
{
|
private final JdbcTemplate jdbc;
|
public FormationReportRepository(DataSource dataSource) {
|
super(dataSource, "formation", "化成"); jdbc = new JdbcTemplate(dataSource);
|
}
|
|
public record SourceSummary(Summary report, int versionNo, List<Map<String, Object>> sources) { }
|
public record CycleCurve(Map<String, Object> selection, Map<String, Object> curve) { }
|
|
/** 列表只从保存版本投影来源名称,禁止传输或反序列化测量快照。 */
|
public List<SourceSummary> listSources() {
|
return jdbc.query("""
|
SELECT r.report_id,r.report_name,r.creator_name,r.created_at_utc,v.version_no,
|
JSON_EXTRACT(v.snapshot_json,'$.items[*].source')
|
FROM t_formation_report r JOIN t_formation_report_version v ON v.report_id=r.report_id
|
AND v.version_no=(SELECT MAX(v2.version_no) FROM t_formation_report_version v2 WHERE v2.report_id=r.report_id)
|
ORDER BY r.created_at_utc DESC,r.report_id DESC
|
""", (rs,index)->new SourceSummary(new Summary(rs.getLong(1),rs.getString(2),rs.getString(3),rs.getTimestamp(4).getTime()),
|
rs.getInt(5), parseSources(rs.getString(6))));
|
}
|
|
/** 首屏投影不含任何循环曲线,旧快照也按相同路径读取,不重写历史 JSON。 */
|
public Version page(long id, Integer versionNo) {
|
return getProjection(id, versionNo, objectProjection("v.snapshot_json",
|
List.of("name","description","cycleNos","settings","calculatedValues","units","displayUnits","curveMode")));
|
}
|
|
/** 版本号由首屏查询固定,后续字段查询不会混入并发产生的新版本。 */
|
public List<Map<String, Object>> pageItems(long id, int versionNo) {
|
String path = "CONCAT('$.items[',j.item_index-1,']')";
|
String fields = List.of("source","cycleNos","cycles","metrics","businessFields","chargeSteps").stream()
|
.map(key->"'"+key+"',JSON_EXTRACT(v.snapshot_json,CONCAT("+path+",'."+key+"'))").collect(Collectors.joining(","));
|
return jdbc.query("SELECT JSON_OBJECT("+fields+") FROM t_formation_report_version v "
|
+ "JOIN JSON_TABLE(v.snapshot_json,'$.items[*]' COLUMNS(item_index FOR ORDINALITY)) j ON TRUE "
|
+ "WHERE v.report_id=? AND v.version_no=? ORDER BY j.item_index",
|
(rs,index)->JSON.parseObject(rs.getString(1)),id,versionNo);
|
}
|
|
/** 只投影指定保存循环,保留采样的原始顺序、空值、单位和独立来源身份。 */
|
public List<CycleCurve> cycleCurves(long id, int versionNo, int cycleNo) {
|
return jdbc.query("""
|
SELECT JSON_EXTRACT(v.snapshot_json,CONCAT('$.items[',j.item_index-1,'].source.selection')),
|
JSON_EXTRACT(v.snapshot_json,CONCAT('$.items[',j.item_index-1,'].curves."',?,'"'))
|
FROM t_formation_report_version v
|
JOIN JSON_TABLE(v.snapshot_json,'$.items[*]' COLUMNS(item_index FOR ORDINALITY)) j ON TRUE
|
WHERE v.report_id=? AND v.version_no=? ORDER BY j.item_index
|
""", (rs,index)->new CycleCurve(JSON.parseObject(rs.getString(1)),JSON.parseObject(rs.getString(2))),cycleNo,id,versionNo);
|
}
|
|
private static String objectProjection(String document, List<String> keys) {
|
return "JSON_OBJECT("+keys.stream().map(key->"'"+key+"',JSON_EXTRACT("+document+",'$."+key+"')").collect(Collectors.joining(","))+")";
|
}
|
|
private static List<Map<String,Object>> parseSources(String json) {
|
if (json == null) return List.of();
|
return JSON.parseArray(json).stream().map(value->(Map<String,Object>)JSON.toJSON(value)).toList();
|
}
|
}
|