package com.battery.business.report; import java.sql.Timestamp; import java.util.HashSet; import java.util.List; import javax.sql.DataSource; import com.alibaba.fastjson2.JSON; import com.battery.business.domain.TBatteryGroupField; import com.battery.business.service.ITBatteryGroupFieldService; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.ruoyi.common.exception.ServiceException; import jakarta.validation.Valid; import jakarta.validation.constraints.*; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.stereotype.Service; /** 拼接模板独立存储,应用与修改均不回写任何已保存报表。 */ @Service public class SpliceFieldTemplateService { private final JdbcTemplate jdbc; private final ITBatteryGroupFieldService definitions; public SpliceFieldTemplateService(DataSource source, ITBatteryGroupFieldService definitions) { jdbc = new JdbcTemplate(source); this.definitions = definitions; } public record Template(long id, String name, String type, List fields, String creator, long updatedAt) { } public record Request(@NotBlank @Size(max = 100) String name, @NotNull @Size(min = 1, max = 100) List<@NotNull @Valid SpliceField> fields) { /** 模板不能保存报表来源或人工填写值。 */ @JsonAnySetter public void rejectUnknown(String field, Object value) { throw new ServiceException("拼接模板不允许提交属性:" + field); } } /** 校验字段身份;普通编辑只使用冻结身份,不依赖仍然存在的共享定义。 */ public List validate(List fields, boolean resolveDefinitions) { if (fields == null || fields.size() > 100 || fields.contains(null)) throw new ServiceException("拼接字段结构无效"); var names = new HashSet(); var ids = new HashSet(); var current = resolveDefinitions ? definitions.selectBatteryGroupFieldList(new TBatteryGroupField()) : List.of(); return fields.stream().map(field -> { if (!names.add(field.name())) throw new ServiceException("拼接字段不能重复"); Long id = field.fieldDefinitionId(); // 控制台字段只有名称;没有明确共享身份时不得凭同名绑定组字段。 if ("battery".equals(field.category()) && resolveDefinitions && id != null) id = current.stream().filter(item -> item.getFieldId().equals(field.fieldDefinitionId())) .findFirst().orElseThrow(() -> new ServiceException("共享字段不存在:" + field.name())).getFieldId(); if (id != null && !ids.add(id)) throw new ServiceException("共享字段不能重复"); return new SpliceField(field.name(), field.category(), field.unit(), id, field.displayName()); }).toList(); } /** 返回拼接所属类型的全部模板,保持字段保存顺序。 */ public List