| | |
| | | @Transactional |
| | | public Map<String,Object> create(SpliceReportRequest request, long uid, String user) { |
| | | var settings = settings(request.settings(), true); |
| | | settings.putIfAbsent("sourceDetailOverrides", Map.of()); |
| | | Matrix matrix = freeze(preview(request.selections()), fields(settings)); |
| | | validateStatistics(settings, matrix.segments()); |
| | | validateSourceDetails(settings, matrix.segments()); |
| | | Map<String,Object> snapshot = new LinkedHashMap<>(); |
| | | snapshot.put("spliceMode", "battery-segments"); |
| | | snapshot.put("name", request.name().trim()); snapshot.put("description", request.description()); |
| | |
| | | var snapshot = current(id, request.baseVersionNo()); |
| | | var settings = settings(request.settings(), false); |
| | | validateStatistics(settings, segments(snapshot)); |
| | | validateSourceDetails(settings, segments(snapshot)); |
| | | snapshot.put("name", request.name().trim()); snapshot.put("description", request.description()); snapshot.put("settings", settings); |
| | | reports.append(id, request.baseVersionNo() + 1, request.name().trim(), snapshot.toJSONString(), uid, user, request.changeSummary().trim()); |
| | | return get(id, null); |
| | |
| | | var snapshot = current(id, base); |
| | | var selections = JSON.parseArray(snapshot.getString("selections"), SpliceReportRequest.Selection.class); |
| | | var settings = settings(snapshot.getJSONObject("settings"), false); |
| | | // 主动更新才启用独立来源详情;旧版本读取和普通编辑不隐式迁移。 |
| | | if (!settings.containsKey("sourceDetailOverrides")) { |
| | | // 旧版实验已按来源保存,可直接保留;旧字段人工值仍留在原报表字段,不按名称改绑共享身份。 |
| | | Map<String,Object> details = new LinkedHashMap<>(); |
| | | var experiments = JSON.parseObject(JSON.toJSONString(settings.getOrDefault("sourceExperimentNames", Map.of()))); |
| | | experiments.forEach((key, value) -> details.put(key, Map.of("experimentName", value))); |
| | | settings.put("sourceDetailOverrides", details); |
| | | } |
| | | Matrix matrix = freeze(preview(selections), fields(settings)); |
| | | validateSourceDetails(settings, matrix.segments()); |
| | | // 人工值绑定原循环身份,刷新只清理已不存在的循环,不按新的拼接循环号迁移。 |
| | | var overrides = JSON.parseObject(JSON.toJSONString(settings.getOrDefault("statisticValues", Map.of()))); |
| | | overrides.keySet().retainAll(statisticKeys(matrix.segments())); |
| | |
| | | return allowed; |
| | | } |
| | | |
| | | private void validateSourceDetails(Map<String,Object> settings, List<Map<String,Object>> segments) { |
| | | Object submitted = settings.get("sourceDetailOverrides"); |
| | | if (submitted == null) return; |
| | | if (!(submitted instanceof Map<?,?> overrides)) throw new ServiceException("详情调整格式无效"); |
| | | Set<String> sources = new HashSet<>(); |
| | | for (var segment : segments) { |
| | | var source = JSON.parseObject(JSON.toJSONString(segment.get("source")), Candidate.class); |
| | | sources.add(source.selection().testId() + "|" + source.selection().testBatteryId()); |
| | | } |
| | | // 详情按测试电池归属;名称与分类不解释为共享字段身份、单位或设备事实。 |
| | | if (!sources.containsAll(overrides.keySet())) throw new ServiceException("详情调整不属于所选测试电池"); |
| | | for (Object value : overrides.values()) { |
| | | if (!(value instanceof Map<?,?> override) || !Set.of("experimentName", "fieldValues").containsAll(override.keySet())) throw new ServiceException("详情调整无效"); |
| | | if (override.containsKey("experimentName") && (!(override.get("experimentName") instanceof String name) || name.length() > 500)) throw new ServiceException("实验名称无效"); |
| | | if (!override.containsKey("fieldValues")) continue; |
| | | if (!(override.get("fieldValues") instanceof Map<?,?> values)) throw new ServiceException("详情字段格式无效"); |
| | | for (var entry : values.entrySet()) { |
| | | if (!(entry.getKey() instanceof String key) || !key.matches("(?:battery|special)\\|.{1,100}") |
| | | || !(entry.getValue() instanceof String text) || text.length() > 500) throw new ServiceException("详情字段名称或值无效"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void validateStatistics(Map<String,Object> settings, List<Map<String,Object>> segments) { |
| | | Object submitted = settings.get("statisticValues"); |
| | | if (submitted == null) return; |