Просмотр исходного кода

基金会基本信息模块化构建

mamingxu 1 неделя назад
Родитель
Сommit
2d6d572f23

+ 117 - 43
easier-report-biz/src/main/java/com/yaoyicloud/render/AbstractRender.java

@@ -13,6 +13,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 import cn.hutool.core.lang.Pair;
@@ -87,7 +89,7 @@ public abstract class AbstractRender {
     /**
      * Docx 渲染
      *
-
+     * 
      * @param templateFileContent 模板内容
      * @return 本地文件目录
      * @throws IOException
@@ -99,7 +101,7 @@ public abstract class AbstractRender {
         String basicPath = this.getBasicPath();
         String reportImagePath = this.getReportImagePath();
         String label = relationId + "_" + moduleType;
-        //word导出位置
+        // word导出位置
         String reportTempWordFile = basicPath + "/" + cwd + "/" + label + ".docx";
         // 新增:创建文件夹
         File parentDir = new File(basicPath + "/" + cwd);
@@ -159,8 +161,78 @@ public abstract class AbstractRender {
         this.pdfResultPath = cwd + "/1.pdf";
         return this.pdfResultPath;
     }
+
     protected abstract String getBasicPath() throws IOException;
+
     protected abstract String getReportImagePath();
+
+    /**
+     * 针对于protobuf传递来的数据处理
+     * @return
+     */
+    protected RenderPolicy indicatorsRenderPolicyToProtobuf() {
+        return new LoopRowTableRenderPolicy() {
+            @Override
+            public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {
+                //获取模板中的变量如:[name]
+                ArrayList<String> strings = processElement(eleTemplate, data);
+                List<Map<String, Object>> processedData = null;
+                if (null != data && data instanceof Iterable) {
+                    processedData = (List<Map<String, Object>>) data;
+                    processedData.forEach(map -> {
+                        for (String string : strings) {
+                            Object o = map.get(string);
+                            if (null == o || "".equals(o)) {
+                                map.put(string, "-");
+                            }
+                        }
+                    });
+                }
+                // 调用父类渲染处理后的数据
+                super.render(eleTemplate, processedData, template);
+            }
+
+            private ArrayList<String> processElement(ElementTemplate eleTemplate, Object data) {
+                RunTemplate runTemplate = (RunTemplate) eleTemplate;
+                XWPFRun run = runTemplate.getRun();
+                XWPFTableCell tagCell = (XWPFTableCell) ((XWPFParagraph) run.getParent()).getBody();
+                XWPFTable table = tagCell.getTableRow().getTable();
+                StringBuilder textBuilder = new StringBuilder();
+
+                for (XWPFTableRow row : table.getRows()) {
+                    // 遍历行中的每一个单元格
+                    for (XWPFTableCell cell : row.getTableCells()) {
+                        // 提取单元格内的所有文本(包含段落、Run 等)
+                        for (XWPFParagraph para : cell.getParagraphs()) {
+                            for (XWPFRun r : para.getRuns()) {
+                                textBuilder.append(r.getText(0)); // 获取 Run 的文本
+                            }
+                        }
+                        textBuilder.append(" ");
+                    }
+                    textBuilder.append(" ");
+                }
+                ArrayList<String> strings = new ArrayList<>();
+                String string = textBuilder.toString();
+                String[] split = string.split(" ");
+                for (String s : split) {
+                    Pattern pattern = Pattern.compile("\\[(.*?)\\]");
+                    Matcher matcher = pattern.matcher(s);
+                    while (matcher.find()) {
+                        String contentInBracket = matcher.group(1);
+                        strings.add(contentInBracket);
+                    }
+                }
+                return strings;
+            }
+        };
+    }
+
+
+    /**
+     * 针对于json格式全量传输数据的列表处理 将默认值null转为“-”
+     * @return
+     */
     protected RenderPolicy indicatorsRenderPolicy() {
         return new LoopRowTableRenderPolicy() {
             @Override
@@ -179,8 +251,8 @@ public abstract class AbstractRender {
                 if (data instanceof List) {
                     // 处理List类型数据
                     return ((List<?>) data).stream()
-                            .map(this::processItem)
-                            .collect(Collectors.toList());
+                        .map(this::processItem)
+                        .collect(Collectors.toList());
                 }
 
                 return data;
@@ -195,16 +267,16 @@ public abstract class AbstractRender {
                 if (item instanceof Map) {
                     Map<?, ?> map = (Map<?, ?>) item;
                     return map.entrySet().stream()
-                            .collect(Collectors.toMap(
-                                    Map.Entry::getKey,
-                                    e -> e.getValue() == null ? "-" : e.getValue()
-                            ));
+                        .collect(Collectors.toMap(
+                            Map.Entry::getKey,
+                            e -> e.getValue() == null ? "-" : e.getValue()));
                 }
 
                 return item;
             }
         };
     }
+
     /**
      * 这些render policy类都应当是共享的 重要设计假设: data的类型cast都可以建立在json通用反序列化后的基本类型基础上。
      */
@@ -221,7 +293,7 @@ public abstract class AbstractRender {
                 if (StrUtil.isBlank(filename)) {
                     // uri render when no filename
                     TextRenderPolicy.Helper.renderTextRun(((RunTemplate) eleTemplate).getRun(),
-                            new HyperlinkTextRenderData(url, url));
+                        new HyperlinkTextRenderData(url, url));
                 } else if (filename.endsWith(".pdf")) {
                     // pdf render, replace data with bytestream
                     PDDocument document = null;
@@ -247,9 +319,9 @@ public abstract class AbstractRender {
 
                             // 准备POI-TL数据
                             ByteArrayPictureRenderData picData =
-                                    new ByteArrayPictureRenderData(stream.toByteArray(), PictureType.JPEG);
+                                new ByteArrayPictureRenderData(stream.toByteArray(), PictureType.JPEG);
                             Pair<Integer, Integer> targetSize =
-                                    calculateTargetSize(image.getWidth(), image.getHeight(), targetWidth);
+                                calculateTargetSize(image.getWidth(), image.getHeight(), targetWidth);
                             PictureStyle style = new PictureStyle();
                             style.setWidth(targetSize.getKey());
                             style.setHeight(targetSize.getValue());
@@ -258,7 +330,7 @@ public abstract class AbstractRender {
                         }
                     } catch (Exception e) {
                         throw new RenderException(
-                                "AttachmentRenderPolicy for " + eleTemplate + " error: " + e.getMessage(), e);
+                            "AttachmentRenderPolicy for " + eleTemplate + " error: " + e.getMessage(), e);
                     } finally {
                         if (document != null) {
                             try {
@@ -277,12 +349,13 @@ public abstract class AbstractRender {
                         ImageIO.write(image, getFileExtension(filename), stream);
                     } catch (IOException e) {
                         throw new RenderException(
-                                "AttachmentRenderPolicy for " + eleTemplate + " error: " + e.getMessage(), e);
+                            "AttachmentRenderPolicy for " + eleTemplate + " error: " + e.getMessage(), e);
                     }
 
                     ByteArrayPictureRenderData picData =
-                            new ByteArrayPictureRenderData(stream.toByteArray(), PictureType.suggestFileType(filename));
-                    Pair<Integer, Integer> targetSize = calculateTargetSize(image.getWidth(), image.getHeight(), targetWidth);
+                        new ByteArrayPictureRenderData(stream.toByteArray(), PictureType.suggestFileType(filename));
+                    Pair<Integer, Integer> targetSize =
+                        calculateTargetSize(image.getWidth(), image.getHeight(), targetWidth);
                     PictureStyle style = new PictureStyle();
                     style.setWidth(targetSize.getKey());
                     style.setHeight(targetSize.getValue());
@@ -313,7 +386,7 @@ public abstract class AbstractRender {
         };
     }
 
-    protected  RenderPolicy hyperlinkRenderPolicy() {
+    protected RenderPolicy hyperlinkRenderPolicy() {
         return new ParagraphRenderPolicy() {
             @Override
             public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {
@@ -335,7 +408,6 @@ public abstract class AbstractRender {
         };
     }
 
-
     protected RenderPolicy getScoreRenderPolicy() {
         RenderPolicy policy = new LoopRowTableRenderPolicy() {
             @SuppressWarnings("checkstyle:NestedForDepth")
@@ -344,7 +416,7 @@ public abstract class AbstractRender {
                 // 检查数据是否为空
                 if (data == null || (data instanceof Collection && ((Collection<?>) data).isEmpty())) {
                     // 数据为空时,删除整个表格
-                    //      removeTemplateTable(eleTemplate, template);
+                    // removeTemplateTable(eleTemplate, template);
                     return;
                 }
 
@@ -424,6 +496,7 @@ public abstract class AbstractRender {
         };
         return policy;
     }
+
     private List<String> getCellText(XWPFTableRow row) {
         List<String> texts = new ArrayList<>();
         if (row == null) {
@@ -446,6 +519,7 @@ public abstract class AbstractRender {
         CTTcPr ctPr = cttc.addNewTcPr();
         ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
     }
+
     /**
      * 这些render policy类都应当是共享的 重要设计假设: data的类型cast都可以建立在json通用反序列化后的基本类型基础上。
      */
@@ -478,7 +552,7 @@ public abstract class AbstractRender {
         }
 
         public LoopColumnStaticTableRenderPolicy(String prefix, String suffix, boolean onSameLine, boolean reverse,
-                                                 int valRowIndex) {
+            int valRowIndex) {
             this.prefix = prefix;
             this.suffix = suffix;
             this.onSameLine = onSameLine;
@@ -493,7 +567,7 @@ public abstract class AbstractRender {
             try {
                 if (!TableTools.isInsideTable(run)) {
                     throw new IllegalStateException(
-                            "The template tag " + runTemplate.getSource() + " must be inside a table");
+                        "The template tag " + runTemplate.getSource() + " must be inside a table");
                 }
                 XWPFTableCell tagCell = (XWPFTableCell) ((XWPFParagraph) run.getParent()).getBody();
                 XWPFTable table = tagCell.getTableRow().getTable();
@@ -554,7 +628,7 @@ public abstract class AbstractRender {
             try {
                 if (!TableTools.isInsideTable(run)) {
                     throw new IllegalStateException(
-                            "The template tag " + runTemplate.getSource() + " must be inside a table");
+                        "The template tag " + runTemplate.getSource() + " must be inside a table");
                 }
                 // Reserve the first two rows
                 XWPFTableCell tagCell = (XWPFTableCell) ((XWPFParagraph) run.getParent()).getBody();
@@ -564,14 +638,14 @@ public abstract class AbstractRender {
                 }
             } catch (Exception e) {
                 throw new RenderException(
-                        "LoopRowCutAndMergeFirstColTable for " + eleTemplate + " error: " + e.getMessage(), e);
+                    "LoopRowCutAndMergeFirstColTable for " + eleTemplate + " error: " + e.getMessage(), e);
             }
 
             // in case data not sorted by rank
             @SuppressWarnings("unchecked")
             List<Map<String, Object>> mpData = (List<Map<String, Object>>) data;
             mpData.sort((a, b) -> Integer.valueOf(a.getOrDefault("rank", "0").toString())
-                    - Integer.valueOf(b.getOrDefault("rank", "0").toString()));
+                - Integer.valueOf(b.getOrDefault("rank", "0").toString()));
 
             super.render(eleTemplate, data, template);
 
@@ -580,7 +654,7 @@ public abstract class AbstractRender {
                 Util.mergeFirstNColSimple(table, 1, 0);
             } catch (Exception e) {
                 throw new RenderException(
-                        "LoopRowCutAndMergeFirstColTable for " + eleTemplate + " error: " + e.getMessage(), e);
+                    "LoopRowCutAndMergeFirstColTable for " + eleTemplate + " error: " + e.getMessage(), e);
             }
         }
     }
@@ -607,28 +681,28 @@ public abstract class AbstractRender {
 
                 // 处理百分号并转换为数值
                 List<Double> processedValues = values.stream()
-                        .filter(Objects::nonNull)
-                        .map(v -> {
-                            if (v.endsWith("%")) {
-                                return v.substring(0, v.length() - 1);
-                            }
-                            return v;
-                        })
-                        .map(v -> {
-                            try {
-                                return Double.valueOf(v);
-                            } catch (NumberFormatException e) {
-                                return Double.NaN;
-                            }
-                        })
-                        .filter(v -> !Double.isNaN(v))
-                        .collect(Collectors.toList());
+                    .filter(Objects::nonNull)
+                    .map(v -> {
+                        if (v.endsWith("%")) {
+                            return v.substring(0, v.length() - 1);
+                        }
+                        return v;
+                    })
+                    .map(v -> {
+                        try {
+                            return Double.valueOf(v);
+                        } catch (NumberFormatException e) {
+                            return Double.NaN;
+                        }
+                    })
+                    .filter(v -> !Double.isNaN(v))
+                    .collect(Collectors.toList());
 
                 // 计算平均值并保留两位小数
                 double avg = processedValues.stream()
-                        .mapToDouble(Double::doubleValue)
-                        .average()
-                        .orElse(Double.NaN);
+                    .mapToDouble(Double::doubleValue)
+                    .average()
+                    .orElse(Double.NaN);
 
                 // 格式化结果
                 String formattedAvg;

+ 9 - 4
easier-report-biz/src/main/java/com/yaoyicloud/render/foundation/FoundationBasicInfoRender.java

@@ -1,6 +1,8 @@
 package com.yaoyicloud.render.foundation;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 import com.deepoove.poi.config.Configure;
@@ -16,6 +18,7 @@ import com.yaoyicloud.message.FxyProtos;
 import com.yaoyicloud.render.AbstractRender;
 
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 
 /**
  * BasicInfo渲染器
@@ -55,8 +58,8 @@ public final class FoundationBasicInfoRender extends AbstractRender {
 
         // 配置POI-TL渲染器
         ConfigureBuilder builder = Configure.builder();
-        RenderPolicy indicatorsRenderPolicy = this.indicatorsRenderPolicy();
-        builder.bind("basicInfoChecks", indicatorsRenderPolicy).bind("superiorAuthority", indicatorsRenderPolicy);
+        RenderPolicy indicatorsRenderPolicyToProtobuf = this.indicatorsRenderPolicyToProtobuf();
+        builder.bind("basicInfoChecks", indicatorsRenderPolicyToProtobuf).bind("superiorAuthority", indicatorsRenderPolicyToProtobuf);
         builder.addPlugin('^', this.pictureRenderPolicy());
         // 通过默认protobuf实例来填充不存在的key
         FxyProtos.BasicInfo.Builder basicInfoBuilder = FxyProtos.BasicInfo.newBuilder();
@@ -99,6 +102,7 @@ public final class FoundationBasicInfoRender extends AbstractRender {
         basicInfoSummary.replaceAll((k, v) -> v.equals("") ? "-" : v);
         Object netAsset = data.get("netAsset");
         data.put("netAsset", netAsset + "元人民币");
+
         Map<String, Object> foundationExt = (Map<String, Object>) data.get("foundationExt");
         if (foundationExt == null) {
             ObjectMapper objectMapper = new ObjectMapper();
@@ -109,12 +113,13 @@ public final class FoundationBasicInfoRender extends AbstractRender {
                 .print(foundationBasicInfoExt);
             foundationExt = objectMapper.readValue(print, new TypeReference<Map<String, Object>>() {});
             foundationExt.replaceAll((k, v) -> v.equals("") ? "-" : v);
+            data.put("foundationExt", foundationExt);
         }
 
         foundationExt.replaceAll((k, v) -> v.equals("") ? "-" : v);
 
-        Object lastYearSponsorshipDonationRatio = foundationExt.get("lastYearSponsorshipDonationRatio");
-        foundationExt.put("lastYearSponsorshipDonationRatio", lastYearSponsorshipDonationRatio + "万元人民币");
+        Object lastYearSponsorshipDonationRatio = foundationExt.get("lastYearDonationIncome");
+        foundationExt.put("lastYearDonationIncome", lastYearSponsorshipDonationRatio + "万元人民币");
         Object initialFund = foundationExt.get("initialFund");
         foundationExt.put("initialFund", initialFund + "万人民币");
 

BIN
easier-report-biz/src/test/resources/docx/foundataion_basic_info.docx