yeg
2026-09-08 c19dbe36f39315c5bc4d2b17f2969517b442d0ad
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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<SpliceField> 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<SpliceField> validate(List<SpliceField> fields, boolean resolveDefinitions)
    {
        if (fields == null || fields.size() > 100 || fields.contains(null)) throw new ServiceException("拼接字段结构无效");
        var names = new HashSet<String>(); var ids = new HashSet<Long>();
        var current = resolveDefinitions ? definitions.selectBatteryGroupFieldList(new TBatteryGroupField()) : List.<TBatteryGroupField>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<Template> list()
    {
        return jdbc.query("select template_id,template_name,fields_json,creator_name,updated_at_utc from t_splice_report_field_template where template_type='splice' order by template_name,template_id",
                (rs, index) -> new Template(rs.getLong(1), rs.getString(2), "splice", JSON.parseArray(rs.getString(3), SpliceField.class), rs.getString(4), rs.getTimestamp(5).getTime()));
    }
 
    /** 新增仅含字段结构的拼接模板,同名模板须显式更新。 */
    public long create(Request request, long userId, String userName)
    {
        var fields = validate(request.fields(), true);
        var key = new GeneratedKeyHolder();
        try
        {
            jdbc.update(connection -> {
                var statement = connection.prepareStatement("insert into t_splice_report_field_template(template_name,template_type,fields_json,creator_id,creator_name,created_at_utc,updated_at_utc) values(?,'splice',?,?,?,?,?)", java.sql.Statement.RETURN_GENERATED_KEYS);
                statement.setString(1, request.name().trim()); statement.setString(2, JSON.toJSONString(fields));
                statement.setLong(3, userId); statement.setString(4, userName);
                var now = new Timestamp(System.currentTimeMillis()); statement.setTimestamp(5, now); statement.setTimestamp(6, now);
                return statement;
            }, key);
            return key.getKey().longValue();
        }
        catch (org.springframework.dao.DuplicateKeyException error) { throw new ServiceException("模板名称已存在"); }
    }
 
    /** 修改仅影响后续主动应用,允许有编辑权限的其他创建人协作。 */
    public void update(long id, Request request)
    {
        var fields = validate(request.fields(), true);
        try
        {
            if (jdbc.update("update t_splice_report_field_template set template_name=?,fields_json=?,updated_at_utc=? where template_id=? and template_type='splice'",
                    request.name().trim(), JSON.toJSONString(fields), new Timestamp(System.currentTimeMillis()), id) == 0)
                throw new ServiceException("拼接字段模板不存在");
        }
        catch (org.springframework.dao.DuplicateKeyException error) { throw new ServiceException("模板名称已存在"); }
    }
}