yeg
2026-09-09 9e332b9ea5f0866cf7ac03db5736d10469e5ed4a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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();
    }
}