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 com.estate.expert.admin.stat.report.render.DeviceGroupTablePolicy; 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 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 toViewConfig(Map templateConfig){ var map = new HashMap(); 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 viewConfig){ ConfigureBuilder builder = Configure.builder(); builder.bind("data.设备分组信息", new DeviceGroupTablePolicy()); 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 initModel(JSONObject data){ var dataMap = new HashMap(); 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 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(); } }