Эх сурвалжийг харах

build cso企业报告由render服务模块化生成·

mamingxu 1 өдөр өмнө
parent
commit
029b4d8f4b

+ 3 - 4
easier-report-api/src/main/java/com/yaoyicloud/constant/enums/ModuleType.java

@@ -15,16 +15,16 @@ public enum ModuleType {
     CSO_HEADER("CSO_HEADER", "CSO封面模块"),
 
     CSO_PROMOTION_SUMMARY("CSO_PROMOTION_SUMMARY", "CSO推广总结模块"),
+    CSO_PROMOTION_DETAILS("CSO_PROMOTION_DETAILS", "CSO推广明细模块"),
+    CSO_APPENDIX("CSO_APPENDIX", "CSO签章"),
+
 
     PLATFORM_COMPANY_BASICINFO("PLATFORM_COMPANY_BASICINFO", "平台公司基本信息"),
     FOUNDATION_BASICINFO("FOUNDATION_BASICINFO", "基金会基本信息"),
     ASSOCIATION_BASICINFO("ASSOCIATION_BASICINFO", "学协会基本信息"),
-
     PUBLIC_RECORD("PUBLIC_RECORD", "公共记录"),
     PROJECT("PROJECT", "项目信息"),
     INTERESTCONFLICTS("INTERESTCONFLICTS", "利益冲突"),
-
-
     ANTIBRIBERY("ANTIBRIBERY", "反贿赂反腐败诚信保证"),
     COMMON("COMMON", "公共模块封面"),
     PLATFORM_COMPANY_FINANCIALINFO("PLATFORM_COMPANY_FINANCIALINFO", "平台公司财务"),
@@ -35,7 +35,6 @@ public enum ModuleType {
 
 
 
-
     PLATFORM_COMPANY_BASICINFO_NEW("PLATFORM_COMPANY_BASICINFO_NEW", "工商信息"),
     ANTIBRIBERY_NEW("ANTIBRIBERY_NEW", "其他风险"),
     PLATFORM_COMPANY_FINANCIALINFO_NEW("PLATFORM_COMPANY_FINANCIALINFO_NEW", "经营风险"),

+ 92 - 0
easier-report-biz/src/main/java/com/yaoyicloud/render/AbstractRender.java

@@ -11,6 +11,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -26,6 +27,7 @@ import com.deepoove.poi.XWPFTemplate;
 import com.deepoove.poi.config.Configure;
 import com.deepoove.poi.config.ConfigureBuilder;
 import com.deepoove.poi.data.ByteArrayPictureRenderData;
+import com.deepoove.poi.data.DocxRenderData;
 import com.deepoove.poi.data.HyperlinkTextRenderData;
 import com.deepoove.poi.data.PictureType;
 import com.deepoove.poi.data.style.PictureStyle;
@@ -41,11 +43,17 @@ import com.deepoove.poi.template.run.RunTemplate;
 import com.deepoove.poi.util.TableTools;
 import com.deepoove.poi.xwpf.BodyContainer;
 import com.deepoove.poi.xwpf.BodyContainerFactory;
+import com.deepoove.poi.xwpf.NiceXWPFDocument;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.yaoyicloud.tools.Util;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.pdfbox.Loader;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.rendering.PDFRenderer;
+import org.apache.poi.xwpf.usermodel.BodyElementType;
+import org.apache.poi.xwpf.usermodel.IBodyElement;
 import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
 import org.apache.poi.xwpf.usermodel.XWPFDocument;
 import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun;
@@ -57,6 +65,7 @@ import org.apache.poi.xwpf.usermodel.XWPFTableRow;
 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
 import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
+import org.w3c.dom.Node;
 
 import javax.imageio.ImageIO;
 
@@ -87,6 +96,8 @@ public abstract class AbstractRender {
      */
     protected String pdfResultPath;
 
+    protected String subTemplatePath;
+
     public AbstractRender(String cwd) {
         this.cwd = cwd;
     }
@@ -117,9 +128,58 @@ public abstract class AbstractRender {
                 throw new IOException("无法创建文件保存目录");
             }
         }
+
         Configure config = builder.build();
+        if (moduleType.equals("PromotionDetails")) {
+            this.subTemplatePath = "D:\\excel\\subtemplate.docx";
+            XWPFTemplate subTemplate = XWPFTemplate.compile(subTemplatePath, config).render(dataMap);
+            ByteArrayOutputStream nestOutput = new ByteArrayOutputStream();
+            subTemplate.write(nestOutput);
+            ByteArrayInputStream nestInput = new ByteArrayInputStream(nestOutput.toByteArray());
+            DocxRenderData docxRenderData = new DocxRenderData(nestInput);
+            dataMap.put("nestfile", docxRenderData);
+        }
         XWPFTemplate template =
             XWPFTemplate.compile(new ByteArrayInputStream(templateFileContent), config).render(dataMap);
+
+        NiceXWPFDocument xwpfDocument = template.getXWPFDocument();
+        List<XWPFTable> allTables = xwpfDocument.getAllTables();
+
+        int toDeleteLine = 0;
+        // 删除多余的表格
+        for (int i = 0; i < allTables.size(); i++) {
+            XWPFTable xwpfTable = allTables.get(i);
+            if (allTables.get(i).getRows().size() <= 1) {
+                Node domNode = xwpfTable.getCTTbl().getDomNode();
+                Node parentNode = domNode.getParentNode();
+                parentNode.removeChild(domNode);
+                toDeleteLine++;
+            }
+        }
+
+        // 删除空标题行
+        for (int i = xwpfDocument.getXWPFDocument().getBodyElements().size() - 1; i >= 0; i--) {
+            IBodyElement ele = xwpfDocument.getXWPFDocument().getBodyElements().get(i);
+            if (ele.getElementType().equals(BodyElementType.PARAGRAPH)) {
+                XWPFParagraph paragraph = (XWPFParagraph) ele;
+                if (paragraph.getText().contains("EMPTY")) {
+                    xwpfDocument.removeBodyElement(i);
+                    if (i - 1 < 0) {
+                        continue;
+                    }
+                    IBodyElement above = xwpfDocument.getXWPFDocument().getBodyElements().get(i - 1);
+                    if (!ele.getElementType().equals(BodyElementType.PARAGRAPH)) {
+                        continue;
+                    }
+                    XWPFParagraph paragraphAbove = (XWPFParagraph) above;
+                    if (paragraphAbove.getText().equals("")) {
+                        xwpfDocument.removeBodyElement(i - 1);
+                        i--;
+                    }
+                }
+            }
+        }
+
         template.writeToFile(reportTempWordFile);
         template.close();
 
@@ -1100,8 +1160,10 @@ public abstract class AbstractRender {
             }
         };
     }
+
     /**
      * 【中文姓名】只显示最后一个汉字,其他隐藏为星号,比如:**梦
+     * 
      * @param fullName 姓名
      * @return 结果
      */
@@ -1114,6 +1176,7 @@ public abstract class AbstractRender {
 
     /**
      * 对字符串进行脱敏操作
+     * 
      * @param origin 原始字符串
      * @param prefixNoMaskLen 左侧需要保留几位明文字段
      * @param suffixNoMaskLen 右侧需要保留几位明文字段
@@ -1139,4 +1202,33 @@ public abstract class AbstractRender {
         }
         return sb.toString();
     }
+
+    /**
+     * 将map<string, json串>的结构中json串转为List<map<string,Object>>类型
+     */
+    protected void processJsonData(Map<String, Object> data, String key)  {
+        LinkedHashMap<String, String> jsonMap =
+            (LinkedHashMap<String, String>) data.get(key);
+
+        List<Map<String, Object>> listMap = new ArrayList<>();
+        ObjectMapper objectMapper = new ObjectMapper();
+
+        if (jsonMap != null) {
+            for (Map.Entry<String, String> entry : jsonMap.entrySet()) {
+                String jsonStr = entry.getValue();
+
+                Map<String, Object> taskMap = null;
+                try {
+                    taskMap = objectMapper.readValue(
+                        jsonStr,
+                        new TypeReference<Map<String, Object>>() {});
+                } catch (JsonProcessingException e) {
+                    throw new RuntimeException(e);
+                }
+                listMap.add(taskMap);
+
+            }
+        }
+        data.put(key, listMap);
+    }
 }

+ 80 - 0
easier-report-biz/src/main/java/com/yaoyicloud/render/cso/EntAppendixRender.java

@@ -0,0 +1,80 @@
+package com.yaoyicloud.render.cso;
+
+import java.io.IOException;
+import java.util.Map;
+import org.apache.commons.collections4.MapUtils;
+
+import com.deepoove.poi.config.Configure;
+import com.deepoove.poi.config.ConfigureBuilder;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.yaoyicloud.config.CommonDataCache;
+import com.yaoyicloud.config.FilerepoProperties;
+import com.yaoyicloud.render.AbstractRender;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public final class EntAppendixRender extends AbstractRender {
+    private final FilerepoProperties filerepoProperties;
+    private final CommonDataCache commonDataCache;
+
+    public EntAppendixRender(String cwd, FilerepoProperties filerepoProperties, CommonDataCache commonDataCache) {
+        super(cwd);
+        this.filerepoProperties = filerepoProperties;
+        this.commonDataCache = commonDataCache;
+    }
+
+    @Override
+    protected String getBasicPath() throws IOException {
+        return filerepoProperties.getBasePath();
+    }
+
+    @Override
+    protected String getReportImagePath() {
+        return filerepoProperties.getReportImagePath();
+    }
+
+    /**
+     *  Docx 渲染
+     * @param info 数据
+     * @param templateFileContent 模板内容
+     * @param relationId  用于查询缓存
+     * @return
+     * @throws IOException
+     */
+    public String renderDocx(String info, byte[] templateFileContent, String relationId) throws IOException {
+        log.info("开始渲染CSO企业报告签章模块,relationId: {}", relationId);
+
+        // 配置POI-TL渲染器
+        ConfigureBuilder builder = Configure.builder();
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map<String, Object> data = objectMapper.readValue(info, new TypeReference<Map<String, Object>>() {});
+
+        Map<String, Object> commonDataCacheData = commonDataCache.getData(relationId);
+        if (MapUtils.isNotEmpty(commonDataCacheData)) {
+            data.putAll(commonDataCacheData);
+        }
+
+        fillDefaultValues(data);
+        try {
+            // 渲染文档
+            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "Appendix");
+            log.info("渲染CSO企业报告签章模块成功,文件路径: {}", resultPath);
+            return resultPath;
+        } catch (Exception e) {
+            log.error("渲染CSO企业报告签章模块失败,relationId: {}", relationId, e);
+            throw new IOException("文档渲染失败", e);
+        }
+    }
+
+    /**
+     * 填充默认值,确保所有必要字段都存在
+     */
+    private void fillDefaultValues(Map<String, Object> data) {
+
+
+
+    }
+
+}

+ 8 - 2
easier-report-biz/src/main/java/com/yaoyicloud/render/cso/EntHeaderSectionRender.java

@@ -9,6 +9,7 @@ import java.util.concurrent.ConcurrentMap;
 import cn.hutool.core.date.DateUtil;
 import com.deepoove.poi.config.Configure;
 import com.deepoove.poi.config.ConfigureBuilder;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.protobuf.util.JsonFormat;
@@ -85,12 +86,16 @@ public final class EntHeaderSectionRender extends AbstractRender {
         commonData.put("serviceEndDate", data.get("serviceEndDate"));
         commonData.put("sensitiveFlag", data.get("sensitiveFlag"));
         commonData.put("scorePackageName", data.get("scorePackageName"));
+        commonData.put("entrustingCompany", data.get("entrustingCompany"));
+        commonData.put("taskFinishTime", data.get("taskFinishTime"));
+        commonData.put("serviceCompany", data.get("serviceCompany"));
+
 
         commonDataCache.addData(relationId, commonData);
         fillDefaultValues(data);
         try {
             // 渲染文档
-            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "HeaderSection");
+            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "Header");
             log.info("渲染CSO企业报告封面模块成功,文件路径: {}", resultPath);
             return resultPath;
         } catch (Exception e) {
@@ -102,7 +107,8 @@ public final class EntHeaderSectionRender extends AbstractRender {
     /**
      * 填充默认值,确保所有必要字段都存在
      */
-    private void fillDefaultValues(Map<String, Object> data) {
+    private void fillDefaultValues(Map<String, Object> data)  {
+        processJsonData(data, "drugDetails");
 
     }
 

+ 170 - 0
easier-report-biz/src/main/java/com/yaoyicloud/render/cso/EntPromotionDetailsRender.java

@@ -0,0 +1,170 @@
+package com.yaoyicloud.render.cso;
+
+import java.io.IOException;
+
+import java.util.Map;
+import com.deepoove.poi.policy.RenderPolicy;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.commons.collections4.MapUtils;
+
+import com.deepoove.poi.config.Configure;
+import com.deepoove.poi.config.ConfigureBuilder;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.protobuf.util.JsonFormat;
+import com.yaoyicloud.config.CommonDataCache;
+import com.yaoyicloud.config.FilerepoProperties;
+import com.yaoyicloud.message.CSOProtos;
+import com.yaoyicloud.render.AbstractRender;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public final class EntPromotionDetailsRender extends AbstractRender {
+    private final FilerepoProperties filerepoProperties;
+    private final CommonDataCache commonDataCache;
+
+    public EntPromotionDetailsRender(String cwd, FilerepoProperties filerepoProperties,
+        CommonDataCache commonDataCache) {
+        super(cwd);
+        this.filerepoProperties = filerepoProperties;
+        this.commonDataCache = commonDataCache;
+    }
+
+    @Override
+    protected String getBasicPath() throws IOException {
+        return filerepoProperties.getBasePath();
+    }
+
+    @Override
+    protected String getReportImagePath() {
+        return filerepoProperties.getReportImagePath();
+    }
+
+    /**
+     * Docx 渲染
+     * 
+     * @param info 数据
+     * @param templateFileContent 模板内容
+     * @param relationId 用于查询缓存
+     * @return
+     * @throws IOException
+     */
+    public String renderDocx(String info, byte[] templateFileContent, String relationId) throws IOException {
+        log.info("开始渲染CSO企业报告推广明细模块,relationId: {}", relationId);
+
+        CSOProtos.PromotionDetails.Builder promotionSummary = CSOProtos.PromotionDetails.newBuilder();
+        JsonFormat.parser().merge(info, promotionSummary);
+
+        CSOProtos.PromotionDetails defaultInstance = CSOProtos.PromotionDetails.getDefaultInstance();
+        CSOProtos.PromotionDetails mergedProto = defaultInstance.toBuilder()
+            .mergeFrom(promotionSummary.build())
+            .build();
+
+        String completeJson = JsonFormat.printer()
+            .includingDefaultValueFields()
+            .print(mergedProto);
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map<String, Object> data = objectMapper.readValue(completeJson, new TypeReference<Map<String, Object>>() {});
+        // 将用户积分数据添加到渲染数据中
+        Map<String, Object> commonDataCacheData = commonDataCache.getData(relationId);
+        if (MapUtils.isNotEmpty(commonDataCacheData)) {
+            data.putAll(commonDataCacheData);
+        }
+
+        fillDefaultValues(data);
+
+        ConfigureBuilder builder = Configure.builder();
+        RenderPolicy policy = this.indicatorsRenderPolicyToProtobuf();
+        builder.bind("userTasks", policy);
+        builder.bind("tasks", policy);
+        builder.bind("meetingList", policy);
+        builder.bind("taskType515253List", policy);
+        builder.bind("taskType55List", policy);
+        builder.bind("taskType5657List", policy);
+        builder.bind("taskType811List", policy);
+        builder.bind("taskType910List", policy);
+        builder.bind("policyInfoCollectList", policy);
+        builder.bind("competingProductsInfoCollectList", policy);
+        builder.bind("inventoryInfoCollectList", policy);
+        builder.bind("taskType16List", policy);
+        builder.bind("taskType18List", policy);
+        builder.bind("taskType15List", policy);
+        builder.bind("taskType45List", policy);
+        builder.bind("taskType54List", policy);
+        builder.bind("taskType74List", policy);
+        builder.bind("taskType75List", policy);
+        builder.bind("taskType76List", policy);
+        builder.bind("taskType7879List", policy);
+        builder.bind("taskType80List", policy);
+        builder.bind("taskType81List", policy);
+        builder.bind("taskType38List", policy);
+        builder.bind("taskType394041List", policy);
+        builder.bind("taskType46List", policy);
+        builder.bind("taskType47484950List", policy);
+        builder.bind("taskType19List", policy);
+        builder.bind("taskType343536List", policy);
+        builder.bind("taskType87List", policy);
+        builder.bind("taskType86List", policy);
+        builder.bind("taskType85List", policy);
+        builder.bind("customerVisitList", policy);
+        builder.bind("taskType424344List", policy);
+        try {
+            // 渲染文档
+            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "PromotionDetails");
+            log.info("渲染CSO企业报告推广明细模块成功,文件路径: {}", resultPath);
+            return resultPath;
+        } catch (Exception e) {
+            log.error("渲染CSO企业报告推广明细模块失败,relationId: {}", relationId, e);
+            throw new IOException("文档渲染失败", e);
+        }
+    }
+
+    /**
+     * 填充默认值,确保所有必要字段都存在
+     */
+    @SuppressWarnings("checkstyle:MethodLength")
+    private void fillDefaultValues(Map<String, Object> data)  {
+        processJsonData(data, "userTasks");
+        processJsonData(data, "tasks");
+        processJsonData(data, "meetingList");
+        processJsonData(data, "taskType515253List");
+        processJsonData(data, "taskType55List");
+        processJsonData(data, "taskType5657List");
+        processJsonData(data, "taskType811List");
+        processJsonData(data, "taskType910List");
+        processJsonData(data, "policyInfoCollectList");
+        processJsonData(data, "competingProductsInfoCollectList");
+        processJsonData(data, "inventoryInfoCollectList");
+        processJsonData(data, "taskType16List");
+        processJsonData(data, "taskType18List");
+        processJsonData(data, "taskType15List");
+        processJsonData(data, "taskType45List");
+        processJsonData(data, "taskType54List");
+        processJsonData(data, "taskType74List");
+        processJsonData(data, "taskType75List");
+        processJsonData(data, "taskType76List");
+        processJsonData(data, "taskType7879List");
+        processJsonData(data, "taskType80List");
+        processJsonData(data, "taskType81List");
+        processJsonData(data, "taskType38List");
+        processJsonData(data, "taskType394041List");
+        processJsonData(data, "taskType46List");
+        processJsonData(data, "taskType47484950List");
+        processJsonData(data, "taskType19List");
+        processJsonData(data, "taskType343536List");
+        processJsonData(data, "taskType85List");
+        processJsonData(data, "taskType86List");
+        processJsonData(data, "taskType87List");
+        processJsonData(data, "customerVisitList");
+        processJsonData(data, "taskType424344List");
+        processJsonData(data, "taskType801List");
+
+
+
+
+
+    }
+}
+

+ 7 - 6
easier-report-biz/src/main/java/com/yaoyicloud/render/cso/EntPromotionSectionRender.java → easier-report-biz/src/main/java/com/yaoyicloud/render/cso/EntPromotionSummaryRender.java

@@ -9,6 +9,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import com.google.protobuf.Value;
 import org.apache.commons.collections4.MapUtils;
 
 import com.deepoove.poi.config.Configure;
@@ -28,12 +29,12 @@ import com.yaoyicloud.render.AbstractRender;
 import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
-public final class EntPromotionSectionRender extends AbstractRender {
+public final class EntPromotionSummaryRender extends AbstractRender {
     private final FilerepoProperties filerepoProperties;
     private final CommonDataCache commonDataCache;
 
-    public EntPromotionSectionRender(String cwd, FilerepoProperties filerepoProperties,
-        CommonDataCache commonDataCache) {
+    public EntPromotionSummaryRender(String cwd, FilerepoProperties filerepoProperties,
+                                     CommonDataCache commonDataCache) {
         super(cwd);
         this.filerepoProperties = filerepoProperties;
         this.commonDataCache = commonDataCache;
@@ -76,7 +77,7 @@ public final class EntPromotionSectionRender extends AbstractRender {
             ListValue listValue = ListValue.parseFrom(byteString);
             // 转换为List<Integer>
             List<Integer> scoreList = listValue.getValuesList().stream()
-                .map(value -> (int) value.getNumberValue())
+                    .map(value -> (int) value.getNumberValue())
                 .collect(Collectors.toList());
             userScoreMap.put(userId, scoreList);
         }
@@ -114,7 +115,7 @@ public final class EntPromotionSectionRender extends AbstractRender {
         builder.bind("task_promotioner_quality_5_4_1_last", lastRowDaynamicPolicy);
         try {
             // 渲染文档
-            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "PromotionSection");
+            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "PromotionSummary");
             log.info("渲染CSO企业报告推广总结模块成功,文件路径: {}", resultPath);
             return resultPath;
         } catch (Exception e) {
@@ -146,7 +147,7 @@ public final class EntPromotionSectionRender extends AbstractRender {
         Map<String, List<Integer>> userScoreMap = (Map<String, List<Integer>>) data.get("userScoreMap");
         Long scoreSum = 0L;
         for (Map.Entry<String, List<Integer>> stringListEntry : userScoreMap.entrySet()) {
-            scoreSum = stringListEntry.getValue().stream().mapToLong(Long::valueOf).sum();
+            scoreSum += stringListEntry.getValue().stream().mapToLong(Long::valueOf).sum();
         }
 
         Map<String, String> userNameMap = taskTypeMetas.stream()

+ 20 - 12
easier-report-biz/src/main/java/com/yaoyicloud/service/impl/CsoReportServiceImpl.java

@@ -11,9 +11,8 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.yaoyicloud.render.cso.EntHeaderSectionRender;
-import com.yaoyicloud.render.cso.EntPromotionSectionRender;
-import com.yaoyicloud.service.CsoReportService;
+import com.yaoyicloud.render.cso.EntAppendixRender;
+import com.yaoyicloud.render.cso.EntPromotionDetailsRender;
 import org.apache.poi.xwpf.usermodel.XWPFDocument;
 import org.springframework.stereotype.Service;
 
@@ -22,7 +21,9 @@ import com.yaoyicloud.config.FilerepoProperties;
 import com.yaoyicloud.config.ReportPathManager;
 import com.yaoyicloud.constant.enums.ModuleType;
 import com.yaoyicloud.entity.ReportGenerationResult;
-
+import com.yaoyicloud.render.cso.EntHeaderSectionRender;
+import com.yaoyicloud.render.cso.EntPromotionSummaryRender;
+import com.yaoyicloud.service.CsoReportService;
 import com.yaoyicloud.tools.DocxUtil;
 
 import cn.hutool.core.util.IdUtil;
@@ -54,19 +55,26 @@ public class CsoReportServiceImpl implements CsoReportService {
                     .renderDocx(data, templateBytes, String.valueOf(relationId));
                 break;
             case CSO_PROMOTION_SUMMARY:
-                reportPath = new EntPromotionSectionRender(sessionId, filerepoProperties, commonDataCache)
-                        .renderDocx(data, templateBytes, String.valueOf(relationId));
+                reportPath = new EntPromotionSummaryRender(sessionId, filerepoProperties, commonDataCache)
+                    .renderDocx(data, templateBytes, String.valueOf(relationId));
+                break;
+            case CSO_PROMOTION_DETAILS:
+                reportPath = new EntPromotionDetailsRender(sessionId, filerepoProperties, commonDataCache)
+                    .renderDocx(data, templateBytes, String.valueOf(relationId));
+                break;
+            case CSO_APPENDIX:
+                reportPath = new EntAppendixRender(sessionId, filerepoProperties, commonDataCache)
+                    .renderDocx(data, templateBytes, String.valueOf(relationId));
                 break;
-
             default:
                 throw new UnsupportedOperationException("Unsupported module type: " + moduleType);
         }
         return reportPath;
     }
 
-
     @Override
-    public ReportGenerationResult createCsoCheckReport(String data, byte[] templateBytes, Long relationId, ModuleType moduleType) throws Exception {
+    public ReportGenerationResult createCsoCheckReport(String data, byte[] templateBytes, Long relationId,
+        ModuleType moduleType) throws Exception {
         // 1. 将字节流模版写入临时文件
         File tempTemplateFile = File.createTempFile("template_", ".docx");
         try (FileOutputStream fos = new FileOutputStream(tempTemplateFile)) {
@@ -75,8 +83,8 @@ public class CsoReportServiceImpl implements CsoReportService {
 
         // 获取或初始化计数器
         AtomicInteger counter = moduleCounters.computeIfAbsent(
-                relationId,
-                k -> new AtomicInteger(1));
+            relationId,
+            k -> new AtomicInteger(1));
         String sessionId = SESSION_MAP.get(relationId.toString());
         String reportPath = null;
 
@@ -86,7 +94,7 @@ public class CsoReportServiceImpl implements CsoReportService {
         counter.incrementAndGet();
 
         String mergedReportPath = null;
-        boolean isLastModule = reportPath.contains("attachmentSection");
+        boolean isLastModule = reportPath.contains("Appendix");
 
         if (isLastModule) {
             List<String> reportPaths = reportPathManager.getReportPaths(sessionId);

+ 0 - 1
easier-report-biz/src/main/java/com/yaoyicloud/service/impl/ReportUpdateServiceImpl.java

@@ -82,7 +82,6 @@ public class ReportUpdateServiceImpl implements ReportUpdateService {
 
         String mergedReportPath = null;
         boolean isLastModule = reportPath.contains("attachmentSection");
-
         if (isLastModule) {
             List<String> reportPaths = reportPathManager.getReportPaths(sessionId);
             XWPFDocument targetDoc;

+ 0 - 84
easier-report-biz/src/main/proto/CsoEntReport.proto

@@ -1,84 +0,0 @@
-syntax = "proto3";
-
-package report;
-
-option java_package = "com.yaoyicloud.message";
-option java_outer_classname = "CSOProtos";
-
-// 报告基础信息(封面数据)
-message ReportHeader {
-  optional string report_id = 1; // 报告ID
-  optional string report_create_time = 2; // 生成时间
-  optional string entrusting_project_time = 3; // 委托项目时间
-  optional string entrusting_company = 4; // 委托公司
-  optional string service_company = 5; // 服务公司
-  optional string drugs = 6; // 服务品种
-  optional string task_finish_time = 7; // 任务完成时间
-  optional int32 total_package_score = 8; // 积分包值
-  optional int32 total_approved_score = 11; // 审核通过总值
-  repeated DrugDetail drug_details = 12; // 产品列表(表格数据)
-  optional  string score_package_name = 13; // 积分包名称
-  optional  int32 task_user_names = 14; // 积分包推广人数
-  optional  int32 submited_task_score = 15; // 总提交积分
-  optional  string create_time = 16;         //创建时间
-  optional  string service_end_date = 17;         //完成时间
-  optional bool sensitiveFlag = 18; // 是否脱敏
-
-}
-
-// 产品明细
-message DrugDetail {
-  optional int32 index = 1; // 序号
-  optional string drug_name = 2; // 商品名称
-  optional string generic_name = 3; // 通用名
-  optional string drug_dose = 4; // 剂型
-  optional string drug_guige = 5; // 规格
-  optional string drug_ent_name = 6; // 生产企业
-}
-
-// 3.推广总结
-message PromotionSummary {
-  optional  string create_time = 2; // 发包时间
-  optional  string service_end_date = 3; // 完成时间
-  optional  string task_user_names = 4; // 推广人员列表
-  optional  int32 task_promotioner_quality_5_4_1_submittedCnt = 5; // 总提交任务数
-  optional  int32 task_promotioner_quality_5_4_1_approvedCnt = 7; // 审核通过任务数
-  optional  int32 submited_task_score = 9; // 总提交积分
-  optional  int32 total_approved_score = 11; // 审核通过积分
-  repeated TaskStatisticsByType task_stats_by_type = 22;
-  repeated TaskStatisticsByPerson task_stats_by_person = 23;
-  repeated TaskTypeMeta task_type_metas = 24;
-  map<string, int32> starTaskMap = 25; //本次推广服务项目中完成最多的任务 和任务次数
-  //optional int64 scoreSum =26; //所有任务的总积分之和
-  map<string, bytes> userSubmittedScoreMap = 27;  // 用户id 和 积分列表
-}
-
-// 任务统计信息
-message TaskStatistics {
-  int32 count = 1;                  // 推广次数
-  int64 score = 2;                  // 推广积分值
-  repeated string promotioners = 3; // 推广人员ID集合
-  map<string, int32> mpProductCount = 4; // 产品ID到数量的映射
-}
-
-// 按任务类型的统计信息 (对应 mpTaskStat)
-message TaskStatisticsByType {
-  map<string, TaskStatistics> task_stats = 1; // 任务类型ID -> 统计信息
-  // repeated TaskTypeMeta task_type_metas = 2;
-}
-
-// 按用户和任务类型的统计信息 (对应 mpTaskStatbyPerson)
-message TaskStatisticsByPerson {
-  map<string, TaskStatisticsByType> user_stats = 1; // 用户ID -> 用户任务统计
-  // repeated TaskTypeMeta task_type_metas = 2;
-
-}
-//任务类型的元数据(关联ID与名称)
-message TaskTypeMeta {
-  string task_type_id = 1;        // 任务类型ID(主键)
-  string parent_name = 2;         // 父分类名(如“医疗终端客户拜访”)
-  string child_name = 3;          // 子任务类型名(如“医疗终端客户拜访”)
-  string user_id = 4;             //推广人id
-  string user_name = 5;          //推广人
-
-}

+ 173 - 0
easier-report-biz/src/main/proto/cso.proto

@@ -0,0 +1,173 @@
+syntax = "proto3";
+
+package report;
+
+option java_package = "com.yaoyicloud.message";
+option java_outer_classname = "CSOProtos";
+
+// 1. 报告基础信息(封面数据)
+message ReportHeader {
+  optional string report_id = 1; // 报告ID
+  optional string entrusting_project_time = 2; // 委托项目时间
+  optional string entrusting_company = 3; // 委托公司
+  optional string service_company = 4; // 服务公司
+  optional string drugs = 5; // 服务品种
+  optional string task_finish_time = 6; // 任务完成时间
+  optional int32 total_package_score = 7; // 积分包值
+  optional int32 total_approved_score = 8; // 审核通过总值
+  map<string, string> drug_details = 9; // 产品列表(表格数据)
+  optional string score_package_name = 10; // 积分包名称
+  optional int32 task_user_names = 11; // 积分包推广人数
+  optional int32 submited_task_score = 12; // 总提交积分
+  optional string create_time = 13; // 创建时间
+  optional string service_end_date = 14; // 完成时间
+  optional bool sensitiveFlag = 15; // 是否脱敏
+}
+
+// 2. 推广明细
+message PromotionDetails {
+  // 2.1 推广人员任务信息
+  map<string, string> user_tasks = 1;
+  // 2.2 任务明细
+  map<string, string> tasks = 2;
+
+  // 2.3 专项任务汇总表相关
+  map<string, string> customer_visit_list = 3; // 客户拜访明细
+  optional string customer_visit_title = 4; // 客户拜访标题
+
+  map<string, string> meeting_list = 5; // 会议举办明细
+  optional string meeting_title = 6; // 会议举办标题
+
+  map<string, string> task_type_51_52_53_list = 7; // 任务类型51/52/53明细
+  optional string task_type_51_52_53_title = 8; // 任务类型51/52/53标题
+
+  map<string, string> task_type_55_list = 9; // 任务类型55明细
+  optional string task_type_55_title = 10; // 任务类型55标题
+
+  map<string, string> task_type8_11_list = 11; // 任务类型8/11明细
+  optional string task_type_8_11_title = 12; // 任务类型8/11标题
+
+  map<string, string> task_type_9_10_list = 13; // 任务类型9/10明细
+  optional string task_type_9_10_title = 14; // 任务类型9/10标题
+
+  map<string, string> policy_info_collect_list = 15; // 政策信息收集明细
+  optional string policy_info_collect_title = 16; // 政策信息收集标题
+
+  map<string, string> competing_products_info_collect_list = 17; // 竞品信息收集明细
+  optional string competing_products_info_collect_title = 18; // 竞品信息收集标题
+
+  map<string, string> inventory_info_collect_list = 19; // 库存信息收集明细
+  optional string inventory_info_collect_title = 20; // 库存信息收集标题
+
+  map<string, string> task_type_16_list = 21; // 任务类型16明细
+  optional string task_type_16_title = 22; // 任务类型16标题
+
+  map<string, string> task_type_18_list = 23; // 任务类型18明细
+  optional string task_type_18_title = 24; // 任务类型18标题
+
+  map<string, string> task_type_15_list = 25; // 任务类型15明细
+  optional string task_type_15_title = 26; // 任务类型15标题
+
+  map<string, string> task_type45_list = 27; // 任务类型45明细
+  optional string task_type45_title = 28; // 任务类型45标题
+
+  map<string, string> task_type_54_list = 29; // 任务类型54明细
+  optional string task_type_54_title = 30; // 任务类型54标题
+
+  map<string, string> task_type74_list = 31; // 任务类型74明细
+  optional string task_type74_title = 32; // 任务类型74标题
+
+  map<string, string> task_type_75_list = 33; // 任务类型75明细
+  optional string task_type_75_title = 34; // 任务类型75标题
+
+  map<string, string> task_type_76_list = 35; // 任务类型76明细
+  optional string task_type_76_title = 36; // 任务类型76标题
+
+  map<string, string> task_type_78_79_list = 37; // 任务类型78/79明细
+  optional string task_type_78_79_title = 38; // 任务类型78/79标题
+
+  map<string, string> task_type_80_list = 39; // 任务类型80明细
+  optional string task_type_80_title = 40; // 任务类型80标题
+
+  map<string, string> task_type_81_list = 41; // 任务类型81明细
+  optional string task_type_81_title = 42; // 任务类型81标题
+
+  optional string task_type801_title = 43; // 任务类型801标题
+  map<string, string> task_type801_list = 45; // 任务类型801明细
+
+  map<string, string> task_type38_list = 46; // 任务类型38明细
+  optional string task_type38_title = 47; // 任务类型38标题
+
+  map<string, string> task_type39_40_41_list = 48; // 任务类型39/40/41明细
+  optional string task_type39_40_41_title = 49; // 任务类型39/40/41标题
+
+  map<string, string> task_type42_43_44_list = 50; // 任务类型42/43/44明细
+  optional string task_type42_43_44_title = 51; // 任务类型42/43/44标题
+
+  map<string, string> task_type46_list = 52; // 任务类型46明细
+  optional string task_type46_title = 53; // 任务类型46标题
+
+  map<string, string> task_type47_48_49_50_list = 54; // 任务类型47/48/49/50明细
+  optional string task_type47_48_49_50_title = 55; // 任务类型47/48/49/50标题
+
+  map<string, string> task_type_19_list = 56; // 任务类型19明细
+  optional string task_type_19_title = 57; // 任务类型19标题
+
+  map<string, string> task_type_34_35_36_list = 58; // 任务类型34/35/36明细
+  optional string task_type_34_35_36_title = 59; // 任务类型34/35/36标题
+
+  map<string, string> task_type_85_list = 60; // 任务类型85明细
+  optional string task_type_85_title = 61; // 任务类型85标题
+
+  map<string, string> task_type_86_list = 62; // 任务类型86明细
+  optional string task_type_86_title = 63; // 任务类型86标题
+
+  map<string, string> task_type_87_list = 64; // 任务类型87明细
+  optional string task_type_87_title = 65; // 任务类型87标题
+
+  map<string, string> task_type_56_57_list = 66; // 任务类型5657明细
+  optional string task_type_56_57_title = 67; // 任务类型5657标题
+}
+
+// 3. 推广总结
+message PromotionSummary {
+  optional string create_time = 1; // 发包时间
+  optional string service_end_date = 2; // 完成时间
+  optional string task_user_names = 3; // 推广人员列表
+  optional int32 task_promotioner_quality_5_4_1_submittedCnt = 4; // 总提交任务数
+  optional int32 task_promotioner_quality_5_4_1_approvedCnt = 5; // 审核通过任务数
+  optional int32 submited_task_score = 6; // 总提交积分
+  optional int32 total_approved_score = 7; // 审核通过积分
+  repeated TaskStatisticsByType task_stats_by_type = 8;
+  repeated TaskStatisticsByPerson task_stats_by_person = 9;
+  repeated TaskTypeMeta task_type_metas = 10;
+  map<string, int32> starTaskMap = 11; // 本次推广服务项目中完成最多的任务和任务次数
+  map<string, bytes> userSubmittedScoreMap = 12; // 用户id和积分列表
+}
+
+// 4. 任务统计信息
+message TaskStatistics {
+  int32 count = 1; // 推广次数
+  int64 score = 2; // 推广积分值
+  repeated string promotioners = 3; // 推广人员ID集合
+  map<string, int32> mpProductCount = 4; // 产品ID到数量的映射
+}
+
+// 5. 按任务类型的统计信息 (对应 mpTaskStat)
+message TaskStatisticsByType {
+  map<string, TaskStatistics> task_stats = 1; // 任务类型ID -> 统计信息
+}
+
+// 6. 按用户和任务类型的统计信息 (对应 mpTaskStatbyPerson)
+message TaskStatisticsByPerson {
+  map<string, TaskStatisticsByType> user_stats = 1; // 用户ID -> 用户任务统计
+}
+
+// 7. 任务类型的元数据(关联ID与名称)
+message TaskTypeMeta {
+  string task_type_id = 1; // 任务类型ID(主键)
+  string parent_name = 2; // 父分类名(如“医疗终端客户拜访”)
+  string child_name = 3; // 子任务类型名(如“医疗终端客户拜访”)
+  string user_id = 4; // 推广人id
+  string user_name = 5; // 推广人
+}

+ 3 - 0
easier-report-biz/src/main/resources/application.yml

@@ -118,3 +118,6 @@ easier:
     pdf:
       rootPath: C:/Users/yyy/dev/yyc3/easier-be
 
+template:
+  subTemplate: subtemplate.docx
+  path: /excel/pre/

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 4683 - 1265
logs/easier-report-biz/debug.log


Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно