yeg
2026-09-08 fdf140677f1ebf6a9964d158464eec09414b3d91
支持跨测试逐电池拼接统计
1个文件已修改
25 ■■■■■ 已修改文件
battery-business/src/main/java/com/battery/business/report/SpliceReportService.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
battery-business/src/main/java/com/battery/business/report/SpliceReportService.java
@@ -37,51 +37,42 @@
  return result.stream().sorted(Comparator.comparingLong(Candidate::startedAt)
      .thenComparingLong(value -> value.selection().testId())).toList();
 }
 /** 校验至少两个同组测试选择相同的参与电池集合,按提交顺序接续真实循环。 */
 /** 校验每个测试电池来源并按提交顺序逐段接续真实循环。 */
 public Matrix preview(List<SpliceReportRequest.Selection> selections) {
  if (selections == null || selections.size() < 2 || selections.contains(null)
      || new HashSet<>(selections).size() != selections.size())
   throw new ServiceException("请选择至少两个不重复的检测完成测试电池");
  Map<Long, TTest> loaded = new LinkedHashMap<>();
  Map<Long, List<TTestBattery>> selected = new LinkedHashMap<>();
  Long group = null;
  Map<SpliceReportRequest.Selection, TTestBattery> selected = new LinkedHashMap<>();
  for (var selection : selections) {
   if (selection.testId() == null || selection.testBatteryId() == null) throw new ServiceException("测试和电池身份不能为空");
   TTest test = loaded.computeIfAbsent(selection.testId(), tests::selectTestById);
   if (test == null || !"COMPLETED".equals(test.getTestStatus())) throw new ServiceException("仅可选择检测完成测试");
   TTestBattery battery = test.getBatteries().stream().filter(row -> selection.testBatteryId().equals(row.getTestBatteryId()))
       .findFirst().orElseThrow(() -> new ServiceException("电池不属于所选测试"));
   if (group == null) group = battery.getGroupId();
   if (!Objects.equals(group, battery.getGroupId())) throw new ServiceException("拼接测试必须属于同一电池组");
   selected.computeIfAbsent(selection.testId(), key -> new ArrayList<>()).add(battery);
  }
  if (selected.size() < 2) throw new ServiceException("请至少选择两个不同测试");
  Set<String> common = null;
  for (var batteries : selected.values()) {
   Set<String> names = new HashSet<>(batteries.stream().map(TTestBattery::getBatteryNo).toList());
   if (common == null) common = names;
   if (names.size() != batteries.size() || !common.equals(names)) throw new ServiceException("拼接测试必须选择相同的共同参与电池集合");
   selected.put(selection, battery);
  }
  List<Map<String, Object>> segments = new ArrayList<>();
  Set<Integer> mappedCycles = new TreeSet<>();
  Integer previousEnd = null;
  for (var entry : selected.entrySet()) {
   List<Map<String, Object>> cycles = data.cycles(entry.getKey()), steps = data.steps(entry.getKey()), records = data.records(entry.getKey());
   long testId = entry.getKey().testId();
   List<Map<String, Object>> cycles = data.cycles(testId), steps = data.steps(testId), records = data.records(testId);
   List<Map<String, Object>> current = new ArrayList<>();
   Set<Integer> sourceCycles = new TreeSet<>();
   for (TTestBattery battery : entry.getValue()) {
   for (TTestBattery battery : List.of(entry.getValue())) {
    var rows = batteryRows(cycles, battery);
    var stepRows = batteryRows(steps, battery);
    var nos = java.util.stream.Stream.of(rows, stepRows, batteryRows(records, battery)).flatMap(List::stream)
        .map(this::cycle).filter(no -> no > 0).distinct().sorted().toList();
    Map<String, Object> segment = new LinkedHashMap<>();
    segment.put("source", candidate(loaded.get(entry.getKey()), battery));
    segment.put("source", candidate(loaded.get(testId), battery));
    segment.put("cycles", rows); segment.put("steps", stepRows);
    segment.put("businessFields", battery.getFields());
    segment.put("originalCycleNos", nos); segment.put("statistics", statistics(rows, stepRows, nos));
    current.add(segment); sourceCycles.addAll(nos);
   }
   // 同一测试的全部电池共用偏移;首个非空段保留原号,后段首循环紧接前段末循环。
   // 每个测试电池独立计算偏移;空段不占用循环,各指标共用同一定位。
   int offset = previousEnd == null || sourceCycles.isEmpty() ? 0 : previousEnd + 1 - sourceCycles.iterator().next();
   current.forEach(segment -> segment.put("offset", offset));
   for (int no : sourceCycles) mappedCycles.add(no + offset);