“mitao”
2026-05-16 881332a25bcbbe3bebb696f6d0728fba559ef635
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
package com.estate.expert.admin.stat.report.builder;
 
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.ChartMultiSeriesRenderData;
import com.deepoove.poi.data.ChartSingleSeriesRenderData;
import com.deepoove.poi.data.Charts;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.estate.expert.admin.service.UserFileService;
import com.estate.expert.admin.stat.report.render.AbstractInfoTablePolicy;
import com.estate.expert.admin.stat.report.render.CheckInfoTablePolicy;
import com.estate.expert.admin.stat.report.render.CustomPictureRenderPolicy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.CollectionUtils;
 
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
 
/**
 * 第三方评估报告构建器
 */
public class SystemReportBuilder implements ReportBuilderBase {
 
    private static final String DEFAULT_TEMPLATE_FILE = "第三方评估报告.docx";
 
    protected UserFileService userFileService;
 
    private final String templateFile;
 
    public SystemReportBuilder(UserFileService userFileService) {
        this(userFileService, DEFAULT_TEMPLATE_FILE);
    }
 
    public SystemReportBuilder(UserFileService userFileService, String templateFile) {
        this.userFileService = userFileService;
        this.templateFile = templateFile;
    }
 
    /**
     * 构建第三方评估报告
     * @param data 数据
     * @param templateConfig 模板配置
     * @return 第三方评估报告
     */
    @Override
    public XWPFTemplate buildReport(JSONObject data, Map<String, Integer> templateConfig) {
        var res = new ClassPathResource("templates/" + templateFile);
 
        var viewConfig = templateConfig != null ? toViewConfig(templateConfig) : null;
        var builder = initConfig(viewConfig);
        var model = initModel(data);
 
        if(viewConfig != null)
            model.put("config", viewConfig);
 
        try {
            return XWPFTemplate.compile(res.getInputStream(), builder.build()).render(model);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
 
    /**
     * 转换视图配置
     * @param templateConfig 模板配置
     * @return 视图配置
     */
    private Map<String, Boolean> toViewConfig(Map<String, Integer> templateConfig){
        var map = new HashMap<String, Boolean>();
        for (var entry : templateConfig.entrySet()) {
            var value = entry.getValue();
            for(int i = 0; i < 2; i++){
                map.put(entry.getKey() + i, value == i);
            }
        }
        return map;
    }
 
    /**
     * 初始化配置
     * @param viewConfig 视图配置
     * @return 配置构建器
     */
    private ConfigureBuilder initConfig(Map<String, Boolean> viewConfig){
        ConfigureBuilder builder = Configure.builder();
        builder.bind("data.设备分组信息", new LoopRowTableRenderPolicy());
        builder.bind("data.评估结果.隐患等级分布.分项", new LoopRowTableRenderPolicy());
        builder.bind("分项评估",  new CheckInfoTablePolicy());
 
        var abstractStyle = viewConfig != null && viewConfig.get("检查综合评价情况样式0");
        builder.bind("data.评估结果.综合信息", new AbstractInfoTablePolicy(abstractStyle ? 0 : 1));
        builder.addPlugin('%', new CustomPictureRenderPolicy(userFileService));
        return builder;
    }
 
    /**
     * 初始化模型
     * @param data 数据
     * @return 模型
     */
    private Map<String, Object> initModel(JSONObject data){
        var dataMap = new HashMap<String, Object>();
        dataMap.put("data", data);
        dataMap.put("隐患等级分布饼图", buildErrorLevelPieChart(data));
        dataMap.put("隐患等级分布直方图", buildErrorLevelBarChart(data));
 
        initChart(data, dataMap);
        return dataMap;
    }
 
    /**
     * 初始化图表
     * @param data 数据
     * @param dataMap 数据映射
     */
    private void initChart(JSONObject data, Map<String, Object> dataMap){
        var evalResult = data.getJSONObject("评估结果");
        var checkCategories = evalResult.getJSONArray("检查项");
        if(checkCategories == null) return;
        var safetyCategories = new JSONArray();
        for (var c : checkCategories){
            var co = (JSONObject)c;
            var name = co.getString("名称");
            if(name != null && name.contains("安全"))
                safetyCategories.add(co);
            var pieChart = buildPieChart(co);
            if(pieChart!=null)
                co.put("问题分布饼图", pieChart);
            var barChart = buildBarChart(co);
            if(barChart!=null)
                co.put("问题分布直方图", barChart);
        }
        if(safetyCategories.isEmpty() && !checkCategories.isEmpty())
            safetyCategories.add(checkCategories.get(0));
        evalResult.put("安全检查项", safetyCategories);
    }
 
    /**
     * 构建饼图
     * @param c 数据
     * @return 饼图
     */
    private ChartSingleSeriesRenderData buildPieChart(JSONObject c) {
        var name = c.getString("名称");
        var title = name + "问题分布饼图";
 
        var checkInfos = getCheckInfos(c);
        if(CollectionUtils.isEmpty(checkInfos))
            return null;
        String [] categories = checkInfos.stream().map( item -> {
            var obj = (JSONObject)item;
            return obj.getString("类别") + " " + obj.getString("问题百分比");
        }).toArray(String[]::new);
 
        Integer[] values = checkInfos.stream().map( item -> {
            var obj = (JSONObject)item;
            return obj.getInteger("问题数量");
        }).toArray(Integer[]::new);
 
        return Charts.ofSingleSeries(title, categories)
                .series("数量", values)
                .create();
    }
 
    /**
     * 构建柱状图
     * @param c 数据
     * @return 柱状图
     */
    private ChartMultiSeriesRenderData buildBarChart(JSONObject c) {
        var name = c.getString("名称");
        var title = name + "问题分布直方图";
 
        var checkInfos = getCheckInfos(c);
        String [] categories = checkInfos.stream().map( item -> {
            var obj = (JSONObject)item;
            return obj.getString("类别");
        }).toArray(String[]::new);
 
        Integer[] values = checkInfos.stream().map( item -> {
            var obj = (JSONObject)item;
            return obj.getInteger("问题数量");
        }).toArray(Integer[]::new);
 
        return Charts.ofBar(title, categories)
                .addSeries("数量", values)
                .create();
    }
 
    /**
     * 获取检查信息
     * @param evalRes 评估结果
     * @return 检查信息
     */
    private JSONArray getCheckInfos(JSONObject evalRes){
        var result = new JSONArray();
        var categoryItems = evalRes.getJSONArray("分项评估");
        categoryItems.forEach( categoryItem -> {
            ((JSONObject)categoryItem).getJSONArray("分项").forEach( item -> {
                result.add(item);
            });
        });
 
        return result;
    }
 
    // 隐患等级分布饼图
    /**
     * 构建隐患等级分布饼图
     * @param data 数据
     * @return 隐患等级分布饼图
     */
    private ChartSingleSeriesRenderData buildErrorLevelPieChart(JSONObject data){
        var title = "隐患等级分布饼图";
        var checkInfos = data.getJSONObject("评估结果")
                .getJSONObject("隐患等级分布").getJSONArray("分项");
        if(checkInfos == null)
            return null;
        String [] categories = checkInfos.stream().map( item -> {
            var obj = (JSONObject)item;
            return obj.getString("隐患等级") + " " + obj.getString("比例");
        }).toArray(String[]::new);
 
        Integer[] values = checkInfos.stream().map( item -> {
            var obj = (JSONObject)item;
            return obj.getInteger("数量");
        }).toArray(Integer[]::new);
 
        return Charts.ofSingleSeries(title, categories)
                .series("数量", values)
                .create();
    }
 
    /**
     * 构建隐患等级分布直方图
     * @param data 数据
     * @return 隐患等级分布直方图
     */
    private ChartMultiSeriesRenderData buildErrorLevelBarChart(JSONObject data){
        var title = "隐患等级分布直方图";
        var checkInfos = data.getJSONObject("评估结果").getJSONObject("隐患等级分布").getJSONArray("分项");
        if(checkInfos == null)
            return null;
        String [] categories = checkInfos.stream().map( item -> {
            var obj = (JSONObject)item;
            return obj.getString("隐患等级") + " " + obj.getString("比例");
        }).toArray(String[]::new);
 
        Integer[] values = checkInfos.stream().map( item -> {
            var obj = (JSONObject)item;
            return obj.getInteger("数量");
        }).toArray(Integer[]::new);
 
        return Charts.ofBar(title, categories)
                .addSeries("数量", values)
                .create();
    }
}