9 小时以前 9bad721754fe8bbe2e5f459d0706e0fefac569f3
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package cn.iocoder.yudao.module.qcreport.engine.context;
 
import cn.iocoder.yudao.module.qcreport.engine.QualityResult;
import lombok.Data;
import lombok.experimental.Accessors;
 
/**
 * 单个检验项。
 * <p>
 * 字段名与前端 {@code engine/context.ts} 的 ReportContextItem 保持一致,
 * 重复行的行内绑定写作 {@code {{item.itemName}}}。
 */
@Data
@Accessors(chain = true)
public class InspectionItem {
 
    private int index;
    private String itemCode = "";
    private String itemName = "";
    private String standardValue = "";
    private String actualValue = "";
    private String unit = "";
    /**
     * 「检测要求」文本:分组父项 = 指标上的公式,其余 = 单据上的标准要求。
     * <p>
     * 与 {@link #standardValue} 并存而不合并:两者的来源不同(单据行 vs 指标主数据),
     * 而分组父子项压根没有规格,只有公式。
     */
    private String requirement = "";
    /**
     * 检测方法,来自单据行(如 {@code GB 5009.3-2016} / {@code ANA.MTH-000036})。
     * <p>
     * 与 {@link #requirement} 并存而不合并:检测要求说的是「这一项要达到什么」,
     * 检测方法说的是「用什么办法测的」,原件里常各占一列。
     */
    private String checkMethod = "";
    /**
     * 分组信息,只有检验单带分组结构时才有值。
     * <p>
     * null 表示「这份报告没有分组」,{@link ReportContext#itemMap} 在这种情况下不放这个键,
     * 免得给没有分组的报告(以及冻结的对拍 fixture)带上一个恒为空的字段。
     */
    private Group group;
    /** 规格上限,判定器做区间判定时使用 */
    private Double upperLimit;
    /** 规格下限 */
    private Double lowerLimit;
    /** PASS / FAIL */
    private String result = "";
    /** 合格 / 不合格 / 待判定 / 无判定规则 */
    private String resultText = "";
    private String remark = "";
 
    /**
     * 分组信息:报告要把组名跨住整组所需的三个值。
     * <p>
     * 渲染期算不出这些:绑定的路径在数组上继续取属性会按元素 pluck(`group.children.length`
     * 取不到值),所以「这一组有几行」「这一格要不要让位」只能由上游逐项下发。
     * 字段在**每一个**检验项上都要有值(哪怕是空串):绑定的字段缺席时属性会被跳过,
     * 本该隐藏的合并格反而会露出来。
     */
    @Data
    @Accessors(chain = true)
    public static class Group {
 
        /** 「子项」列文本:组内子项 = 自己的名字,组头行与独立项 = 空串 */
        private String childName = "";
        /** 组名格的纵向合并行数:组的第一行 = 整组的行数,组内其余行与独立项 = 1 */
        private int span = 1;
        /**
         * 组名格的隐藏值:组内第一行 = 空串(可见,带合并行数),其余行 = `hidden`。
         * <p>
         * 字符串而不是布尔:`hidden` 属性靠「在不在」起作用(`hidden="false"` 照样隐藏),
         * 只有空串能表达「不输出这个属性 = 这一格可见」。
         */
        private String hidden = "";
 
        public Group copy() {
            return new Group().setChildName(childName).setSpan(span).setHidden(hidden);
        }
    }
 
    public InspectionItem copy() {
        return new InspectionItem()
                .setIndex(index).setItemCode(itemCode).setItemName(itemName)
                .setStandardValue(standardValue).setActualValue(actualValue).setUnit(unit)
                .setRequirement(requirement)
                .setCheckMethod(checkMethod)
                .setGroup(group == null ? null : group.copy())
                .setUpperLimit(upperLimit).setLowerLimit(lowerLimit)
                .setResult(result).setResultText(resultText).setRemark(remark);
    }
 
    /** 按判定结果写回 result / resultText,verdict 为 null 时置为待判定 */
    public InspectionItem applyResult(QualityResult verdict) {
        this.result = verdict == null ? "" : verdict.name();
        this.resultText = verdict == null ? QualityResult.PENDING_TEXT : verdict.text();
        return this;
    }
 
    /**
     * 没有判定依据:置为「无判定规则」。
     * <p>
     * 报告里常有「试样质量 m」「称量瓶 m0」这类只供公式取数的过程参数,它们没有规格也就无从判定;
     * 若照常算进分母,一份本来全合格的报告会因为几个过程参数被压成「待判定」。
     */
    public InspectionItem applyUndecidable() {
        this.result = "";
        this.resultText = QualityResult.UNDECIDABLE_TEXT;
        return this;
    }
 
}