Procházet zdrojové kódy

build 暂时移除动态展示分数建议模块

mamingxu před 5 dny
rodič
revize
9c65d7f1c1
16 změnil soubory, kde provedl 326 přidání a 194 odebrání
  1. 85 0
      easier-report-biz/src/main/java/com/yaoyicloud/config/ReportPathManager.java
  2. 2 2
      easier-report-biz/src/main/java/com/yaoyicloud/config/SessionInterceptor.java
  3. 16 6
      easier-report-biz/src/main/java/com/yaoyicloud/controller/ReportUpdateController.java
  4. 16 0
      easier-report-biz/src/main/java/com/yaoyicloud/entity/ReportGenerationResult.java
  5. 30 30
      easier-report-biz/src/main/java/com/yaoyicloud/render/AbstractNewRender.java
  6. 6 5
      easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/AntiBriberyNewRender.java
  7. 6 5
      easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/BasicInfoNewRender.java
  8. 7 3
      easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/FinancialInfoNewRender.java
  9. 6 5
      easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/PublicRecordNewRender.java
  10. 22 13
      easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/TaxNewRender.java
  11. 2 1
      easier-report-biz/src/main/java/com/yaoyicloud/service/ReportUpdateService.java
  12. 1 6
      easier-report-biz/src/main/java/com/yaoyicloud/service/impl/ReportServiceImpl.java
  13. 117 84
      easier-report-biz/src/main/java/com/yaoyicloud/service/impl/ReportUpdateServiceImpl.java
  14. 7 3
      easier-report-biz/src/main/java/com/yaoyicloud/tools/DocxUtil.java
  15. 3 0
      easier-report-biz/src/main/proto/fxy.proto
  16. 0 31
      easier-report-biz/src/test/java/com/yaoyicloud/render/test/TestDocxOperations.java

+ 85 - 0
easier-report-biz/src/main/java/com/yaoyicloud/config/ReportPathManager.java

@@ -0,0 +1,85 @@
+package com.yaoyicloud.config;
+
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * 报告路径管理器
+ */
+@Component
+public class ReportPathManager {
+
+    // sessionId -> 报告路径队列(使用ConcurrentLinkedQueue保证有序且线程安全)
+    private final ConcurrentMap<String, ConcurrentLinkedQueue<String>> sessionReportMap = new ConcurrentHashMap<>();
+
+    /**
+     * 添加单个报告路径(按插入顺序有序)
+     */
+    public void addReportPath(String sessionId, String reportPath) {
+        // computeIfAbsent 确保原子性初始化
+        sessionReportMap.computeIfAbsent(sessionId, k -> new ConcurrentLinkedQueue<>())
+                .offer(reportPath);
+    }
+
+    /**
+     * 批量添加报告路径(按集合迭代顺序插入,保证整体有序性)
+     */
+    public void addReportPaths(String sessionId, Collection<String> reportPaths) {
+        ConcurrentLinkedQueue<String> queue = sessionReportMap.computeIfAbsent(sessionId, k -> new ConcurrentLinkedQueue<>());
+        queue.addAll(reportPaths);
+    }
+
+    /**
+     * 获取指定sessionId下的所有报告路径(按插入顺序返回)
+     */
+    public List<String> getReportPaths(String sessionId) {
+        ConcurrentLinkedQueue<String> queue = sessionReportMap.get(sessionId);
+        return queue != null ? new ArrayList<>(queue) : Collections.emptyList();
+    }
+
+    /**
+     * 检查sessionId是否存在
+     */
+    public boolean hasSession(String sessionId) {
+        return sessionReportMap.containsKey(sessionId);
+    }
+
+    /**
+     * 获取所有sessionId
+     */
+    public Set<String> getAllSessions() {
+        return sessionReportMap.keySet();
+    }
+
+    /**
+     * 获取所有报告路径的总数
+     */
+    public int getTotalReportCount() {
+        return sessionReportMap.values().stream()
+                .mapToInt(ConcurrentLinkedQueue::size)
+                .sum();
+    }
+
+    /**
+     * 移除指定sessionId及其所有报告路径
+     */
+    public List<String> removeSession(String sessionId) {
+        ConcurrentLinkedQueue<String> removedQueue = sessionReportMap.remove(sessionId);
+        return removedQueue != null ? new ArrayList<>(removedQueue) : Collections.emptyList();
+    }
+
+    /**
+     * 清空所有数据
+     */
+    public void clear() {
+        sessionReportMap.clear();
+    }
+}

+ 2 - 2
easier-report-biz/src/main/java/com/yaoyicloud/config/SessionInterceptor.java

@@ -7,12 +7,12 @@ import org.springframework.web.servlet.ModelAndView;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
-import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 public class SessionInterceptor implements HandlerInterceptor {
 
-    public static final Map<String, String> SESSION_MAP = new HashMap<>();
+    public static final Map<String, String> SESSION_MAP = new ConcurrentHashMap<>();
 
     @Override
     public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response,

+ 16 - 6
easier-report-biz/src/main/java/com/yaoyicloud/controller/ReportUpdateController.java

@@ -2,7 +2,9 @@ package com.yaoyicloud.controller;
 
 
 import com.yaoyicloud.annotation.EasierLog;
+import com.yaoyicloud.config.ReportPathManager;
 import com.yaoyicloud.dto.ReportDTO;
+import com.yaoyicloud.entity.ReportGenerationResult;
 import com.yaoyicloud.service.ReportUpdateService;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -33,6 +35,7 @@ import static com.yaoyicloud.config.SessionInterceptor.SESSION_MAP;
 @Slf4j
 public class ReportUpdateController {
     private final ReportUpdateService reportService;
+    private final ReportPathManager reportPathManager;
     /**
      * 创建Plus版本审核报告
      *
@@ -48,7 +51,7 @@ public class ReportUpdateController {
         // 1. 解码文件并生成报告
         byte[] fileBytes = Base64.getDecoder().decode(resource.getReportTempFile());
         String relationId = request.getHeader("relationId");
-        String reportPath = reportService.createPlusVersionCheckReport(
+        ReportGenerationResult plusVersionCheckReport = reportService.createPlusVersionCheckReport(
                 resource.getReportType(),
                 resource.getData(),
                 fileBytes,
@@ -61,15 +64,22 @@ public class ReportUpdateController {
                 resource.getTenantName()
 
         );
-
         String sessionId = SESSION_MAP.get(relationId);
-        // 2. 线程安全地更新 Session 中的报告路径列表
 
-        // 3. 返回响应
+
+        // 3. 构建响应
         Map<String, Object> response = new HashMap<>();
-        response.put("reportResult", reportPath);
+        // 根据是否是最后一个模块决定返回哪个路径
+        if (plusVersionCheckReport.isLastModule() && plusVersionCheckReport.getMergedReportPath() != null) {
+            response.put("reportResult", plusVersionCheckReport.getMergedReportPath());
+            response.put("isFinalReport", true);
+            reportPathManager.removeSession(sessionId);
+        } else {
+            response.put("reportResult", plusVersionCheckReport.getModulePath());
+            response.put("isFinalReport", false);
+        }
+
         response.put("sessionId", sessionId);
-        response.put("reportResult", reportPath);
         return response;
     }
 }

+ 16 - 0
easier-report-biz/src/main/java/com/yaoyicloud/entity/ReportGenerationResult.java

@@ -0,0 +1,16 @@
+package com.yaoyicloud.entity;
+
+import lombok.Data;
+
+@Data
+public class ReportGenerationResult {
+    private String modulePath;          // 单个模块路径
+    private String mergedReportPath;    // 合并后的完整报告路径
+    private boolean isLastModule;       // 是否是最后一个模块
+
+    public ReportGenerationResult(String modulePath, String mergedReportPath, boolean isLastModule) {
+        this.modulePath = modulePath;
+        this.mergedReportPath = mergedReportPath;
+        this.isLastModule = isLastModule;
+    }
+}

+ 30 - 30
easier-report-biz/src/main/java/com/yaoyicloud/render/AbstractNewRender.java

@@ -99,7 +99,7 @@ public abstract class AbstractNewRender {
      */
     @SuppressWarnings("checkstyle:ParameterNumber")
     public final String renderDocx(Map<String, Object> dataMap, byte[] templateFileContent,
-        ConfigureBuilder builder, String relationId, String moduleType, Map<String, Object> specialMap)
+        ConfigureBuilder builder, String relationId, String moduleType)
         throws IOException {
 
         // 注: 报告模板的模板变量按照json序列化的结果命名
@@ -121,35 +121,35 @@ public abstract class AbstractNewRender {
         XWPFTemplate template =
             XWPFTemplate.compile(new ByteArrayInputStream(templateFileContent), config).render(dataMap);
 
-        ArrayList<String> templateDele = new ArrayList<>();
-        for (Map.Entry<String, Object> entry : specialMap.entrySet()) {
-            String key = entry.getKey();
-            Object value = entry.getValue();
-            if (value.equals("")) {
-                templateDele.add(key);
-            }
-        }
-        Map<String, String> keywordMap = new HashMap<>();
-        keywordMap.put("suggestion", "建议");
-        keywordMap.put("score", "分");
-        keywordMap.put("riskSummary", "-");
-        XWPFDocument doc = template.getXWPFDocument();
-        List<XWPFTable> tables = doc.getTables();
-        XWPFTable xwpfTable = tables.get(tables.size() - 1);
-        for (int i = xwpfTable.getNumberOfRows() - 1; i >= 0; i--) {
-            XWPFTableRow row = xwpfTable.getRow(i);
-            StringBuilder rowText = new StringBuilder();
-            for (XWPFTableCell cell : row.getTableCells()) {
-                rowText.append(cell.getText());
-            }
-            for (String codeKeyword : templateDele) {
-                String templateKeyword = keywordMap.get(codeKeyword);
-                if (rowText.toString().contains(templateKeyword)) {
-                    xwpfTable.removeRow(i);
-                    break;
-                }
-            }
-        }
+//        ArrayList<String> templateDele = new ArrayList<>();
+//        for (Map.Entry<String, Object> entry : specialMap.entrySet()) {
+//            String key = entry.getKey();
+//            Object value = entry.getValue();
+//            if (value.equals("")) {
+//                templateDele.add(key);
+//            }
+//        }
+//        Map<String, String> keywordMap = new HashMap<>();
+//        keywordMap.put("suggestion", "建议");
+//        keywordMap.put("score", "分");
+//        keywordMap.put("riskSummary", "-");
+//        XWPFDocument doc = template.getXWPFDocument();
+//        List<XWPFTable> tables = doc.getTables();
+//        XWPFTable xwpfTable = tables.get(tables.size() - 1);
+//        for (int i = xwpfTable.getNumberOfRows() - 1; i >= 0; i--) {
+//            XWPFTableRow row = xwpfTable.getRow(i);
+//            StringBuilder rowText = new StringBuilder();
+//            for (XWPFTableCell cell : row.getTableCells()) {
+//                rowText.append(cell.getText());
+//            }
+//            for (String codeKeyword : templateDele) {
+//                String templateKeyword = keywordMap.get(codeKeyword);
+//                if (rowText.toString().contains(templateKeyword)) {
+//                    xwpfTable.removeRow(i);
+//                    break;
+//                }
+//            }
+//        }
 
         template.writeToFile(reportTempWordFile);
         template.close();

+ 6 - 5
easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/AntiBriberyNewRender.java

@@ -81,13 +81,13 @@ public final class AntiBriberyNewRender extends AbstractNewRender {
             data.putAll(addtionalMap);
         }
         fillDefaultValues(data);
-        Map<String, Object> antiBriberySummary = (Map<String, Object>) data.get("antiBriberySummary");
-        String riskSummary = (String) antiBriberySummary.get("riskSummary");
-        antiBriberySummary.put("riskSummary", riskSummary == null || riskSummary.isEmpty() ? "-" : riskSummary);
+//        Map<String, Object> antiBriberySummary = (Map<String, Object>) data.get("antiBriberySummary");
+//        String riskSummary = (String) antiBriberySummary.get("riskSummary");
+//        antiBriberySummary.put("riskSummary", riskSummary == null || riskSummary.isEmpty() ? "-" : riskSummary);
 
         try {
             // 渲染文档
-            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "antiBribery", antiBriberySummary);
+            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "antiBribery");
             log.info("其他风险报告模块渲染成功,文件路径: {}", resultPath);
             return resultPath;
         } catch (Exception e) {
@@ -100,7 +100,8 @@ public final class AntiBriberyNewRender extends AbstractNewRender {
      * 填充默认值,确保所有必要字段都存在
      */
     private void fillDefaultValues(Map<String, Object> data) {
-
+        Map<String, Object> basicInfoSummary = (Map<String, Object>) data.get("basicInfoSummary");
+        basicInfoSummary.replaceAll((k, v) -> v.equals("") ? "-" : v);
 
     }
 

+ 6 - 5
easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/BasicInfoNewRender.java

@@ -79,13 +79,13 @@ public final class BasicInfoNewRender extends AbstractNewRender {
             data.putAll(addtionalMap);
         }
         fillBasicDefaultValues(data);
-        Map<String, Object> basicInfoSummary = (Map<String, Object>) data.get("basicInfoSummary");
-        basicInfoSummary.put("riskSummary",
-            basicInfoSummary.get("riskSummary").equals("") ? "-" : basicInfoSummary.get("riskSummary"));
+//        Map<String, Object> basicInfoSummary = (Map<String, Object>) data.get("basicInfoSummary");
+//        basicInfoSummary.put("riskSummary",
+//            basicInfoSummary.get("riskSummary").equals("") ? "-" : basicInfoSummary.get("riskSummary"));
         try {
             // 渲染文档
             String resultPath =
-                this.renderDocx(data, templateFileContent, builder, relationId, "basicInfo", basicInfoSummary);
+                this.renderDocx(data, templateFileContent, builder, relationId, "basicInfo");
             log.info("渲染工商信息报告模块成功,文件路径: {}", resultPath);
             return resultPath;
         } catch (Exception e) {
@@ -98,7 +98,8 @@ public final class BasicInfoNewRender extends AbstractNewRender {
      * 填充默认值,确保所有必要字段都存在
      */
     private void fillBasicDefaultValues(Map<String, Object> data) {
-
+        Map<String, Object> basicInfoSummary = (Map<String, Object>) data.get("publicRecordSummary");
+        basicInfoSummary.replaceAll((k, v) -> v.equals("") ? "-" : v);
         Map<String, Object> platformExt = (Map<String, Object>) data.get("platformExt");
         platformExt.replaceAll((k, v) -> v.equals("") ? "-" : v);
     }

+ 7 - 3
easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/FinancialInfoNewRender.java

@@ -76,11 +76,11 @@ public final class FinancialInfoNewRender extends AbstractNewRender {
             data.putAll(addtionalMap);
         }
         fillBasicDefaultValues(data);
-        Map<String, Object> financialSummary = (Map<String, Object>) data.get("financialSummary");
-        data.put("fiancescore", financialSummary.get("score"));
+//        Map<String, Object> financialSummary = (Map<String, Object>) data.get("financialSummary");
+//        data.put("fiancescore", financialSummary.get("score"));
         try {
             // 渲染文档
-            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "financialInfo", financialSummary);
+            String resultPath = this.renderDocx(data, templateFileContent, builder, relationId, "financialInfo");
             log.info("渲染财务模块成功,文件路径: {}", resultPath);
             return resultPath;
         } catch (Exception e) {
@@ -92,6 +92,10 @@ public final class FinancialInfoNewRender extends AbstractNewRender {
      * 填充默认值,确保所有必要字段都存在
      */
     private void fillBasicDefaultValues(Map<String, Object> data) {
+
+        Map<String, Object> basicInfoSummary = (Map<String, Object>) data.get("financialSummary");
+        basicInfoSummary.replaceAll((k, v) -> v.equals("") ? "-" : v);
+
         Object certReceived = data.get("certReceived");
         if (Objects.equals(certReceived, "-")) {
             data.put("certReceived", "否");

+ 6 - 5
easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/PublicRecordNewRender.java

@@ -82,13 +82,13 @@ public final class PublicRecordNewRender extends AbstractNewRender {
         }
         fillBasicDefaultValues(data);
 
-        Map<String, Object> publicRecordSummary = (Map<String, Object>) data.get("publicRecordSummary");
-publicRecordSummary.putIfAbsent("riskSummary", "-");
-publicRecordSummary.putIfAbsent("suggestion", "");
+        // Map<String, Object> publicRecordSummary = (Map<String, Object>) data.get("publicRecordSummary");
+        // publicRecordSummary.putIfAbsent("riskSummary", "-");
+        // publicRecordSummary.putIfAbsent("suggestion", "");
         try {
             // 渲染文档
             String resultPath =
-                this.renderDocx(data, templateFileContent, builder, relationId, "publicRecord", publicRecordSummary);
+                this.renderDocx(data, templateFileContent, builder, relationId, "publicRecord");
             log.info("渲染司法风险模块成功,文件路径: {}", resultPath);
             return resultPath;
         } catch (Exception e) {
@@ -101,7 +101,8 @@ publicRecordSummary.putIfAbsent("suggestion", "");
      * 填充默认值,确保所有必要字段都存在
      */
     private void fillBasicDefaultValues(Map<String, Object> data) {
-
+        Map<String, Object> basicInfoSummary = (Map<String, Object>) data.get("publicRecordSummary");
+        basicInfoSummary.replaceAll((k, v) -> v.equals("") ? "-" : v);
         List<Map<String, Object>> dishonestPersons = (List<Map<String, Object>>) data.get("dishonestPersons");
         if (CollectionUtils.isEmpty(dishonestPersons)) {
             Map<String, Object> defaultDishonestPerson = new HashMap<>();

+ 22 - 13
easier-report-biz/src/main/java/com/yaoyicloud/render/platform/update/TaxNewRender.java

@@ -7,6 +7,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
+import com.yaoyicloud.message.FxyProtos;
 import org.apache.commons.collections4.CollectionUtils;
 
 import com.deepoove.poi.config.Configure;
@@ -61,18 +62,25 @@ public final class TaxNewRender extends AbstractNewRender {
 
     public String renderDocx(String info, Map<String, Object> addtionalMap, byte[] templateFileContent,
         String relationId) throws IOException {
-        log.info("开始渲染司法风险模块,relationId: {}", relationId);
+        log.info("开始渲染税务风险模块,relationId: {}", relationId);
 
         // 配置POI-TL渲染器
         ConfigureBuilder builder = Configure.builder();
         RenderPolicy indicatorsRenderPolicy = this.indicatorsRenderPolicyToProtobuf();
 
-        builder.bind("dishonestPersons", indicatorsRenderPolicy);
-        builder.bind("judicialRiskChecks", indicatorsRenderPolicy);
-
-        builder.bind("severeViolations", indicatorsRenderPolicy);
+        builder.bind("taxationRiskChecks", indicatorsRenderPolicy);
+        builder.bind("taxPenalties", indicatorsRenderPolicy);
         builder.useSpringEL();
-
+        FxyProtos.PublicRecord.Builder publicRecordBuilder = FxyProtos.PublicRecord.newBuilder();
+        JsonFormat.parser().merge(info, publicRecordBuilder);
+        FxyProtos.PublicRecord defaultInstance = FxyProtos.PublicRecord.getDefaultInstance();
+        FxyProtos.PublicRecord mergedProto = defaultInstance.toBuilder()
+                .mergeFrom(publicRecordBuilder.build())
+                .build();
+
+        String completeJson = JsonFormat.printer()
+                .includingDefaultValueFields()
+                .print(mergedProto);
         ObjectMapper objectMapper = new ObjectMapper();
         Map<String, Object> data = objectMapper.readValue(info, new TypeReference<Map<String, Object>>() {});
         data.replaceAll((k, v) -> v.equals("") ? "-" : v);
@@ -82,17 +90,17 @@ public final class TaxNewRender extends AbstractNewRender {
         }
         fillBasicDefaultValues(data);
 
-        Map<String, Object> publicRecordSummary = (Map<String, Object>) data.get("publicRecordSummary");
-publicRecordSummary.putIfAbsent("riskSummary", "-");
-publicRecordSummary.putIfAbsent("suggestion", "");
+//        Map<String, Object> publicRecordSummary = (Map<String, Object>) data.get("publicRecordSummary");
+//publicRecordSummary.putIfAbsent("riskSummary", "-");
+//publicRecordSummary.putIfAbsent("suggestion", "");
         try {
             // 渲染文档
             String resultPath =
-                this.renderDocx(data, templateFileContent, builder, relationId, "publicRecord", publicRecordSummary);
-            log.info("渲染司法风险模块成功,文件路径: {}", resultPath);
+                this.renderDocx(data, templateFileContent, builder, relationId, "publicRecord");
+            log.info("渲染税务风险模块成功,文件路径: {}", resultPath);
             return resultPath;
         } catch (Exception e) {
-            log.error("渲染司法风险模块失败,relationId: {}", relationId, e);
+            log.error("渲染税务风险模块失败,relationId: {}", relationId, e);
             throw new IOException("文档渲染失败", e);
         }
     }
@@ -101,7 +109,8 @@ publicRecordSummary.putIfAbsent("suggestion", "");
      * 填充默认值,确保所有必要字段都存在
      */
     private void fillBasicDefaultValues(Map<String, Object> data) {
-
+        Map<String, Object> basicInfoSummary = (Map<String, Object>) data.get("publicRecordSummary");
+        basicInfoSummary.replaceAll((k, v) -> v.equals("") ? "-" : v);
         List<Map<String, Object>> dishonestPersons = (List<Map<String, Object>>) data.get("dishonestPersons");
         if (CollectionUtils.isEmpty(dishonestPersons)) {
             Map<String, Object> defaultDishonestPerson = new HashMap<>();

+ 2 - 1
easier-report-biz/src/main/java/com/yaoyicloud/service/ReportUpdateService.java

@@ -3,6 +3,7 @@ package com.yaoyicloud.service;
 
 import com.yaoyicloud.constant.enums.ModuleType;
 import com.yaoyicloud.constant.enums.ReportType;
+import com.yaoyicloud.entity.ReportGenerationResult;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -17,7 +18,7 @@ import javax.servlet.http.HttpServletRequest;
 public interface ReportUpdateService {
 
     @SuppressWarnings("checkstyle:ParameterNumber")
-    String createPlusVersionCheckReport(
+    ReportGenerationResult createPlusVersionCheckReport(
             ReportType reportType,
             String data,
             byte[] templateBytes,

+ 1 - 6
easier-report-biz/src/main/java/com/yaoyicloud/service/impl/ReportServiceImpl.java

@@ -13,12 +13,7 @@ import org.springframework.stereotype.Service;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 
-/**
- * 报告服务
- *
- * @author snows
- * @date 2024/10/12
- */
+
 @Slf4j
 @Service
 @RequiredArgsConstructor

+ 117 - 84
easier-report-biz/src/main/java/com/yaoyicloud/service/impl/ReportUpdateServiceImpl.java

@@ -1,15 +1,21 @@
 package com.yaoyicloud.service.impl;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.time.LocalDate;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import cn.hutool.core.util.IdUtil;
 import com.yaoyicloud.config.FilerepoProperties;
+import com.yaoyicloud.config.ReportPathManager;
 import com.yaoyicloud.constant.enums.ModuleType;
 import com.yaoyicloud.constant.enums.ReportType;
+import com.yaoyicloud.entity.ReportGenerationResult;
 import com.yaoyicloud.render.InterestConflictsRender;
 import com.yaoyicloud.render.ProjectInfoRender;
 import com.yaoyicloud.render.PublicRecordRender;
@@ -32,6 +38,9 @@ import com.yaoyicloud.render.platform.update.TaxNewRender;
 
 import com.yaoyicloud.service.ReportUpdateService;
 
+import com.yaoyicloud.tools.DocxUtil;
+
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
 import org.springframework.stereotype.Service;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -40,22 +49,33 @@ import javax.servlet.http.HttpServletRequest;
 
 import static com.yaoyicloud.config.SessionInterceptor.SESSION_MAP;
 
-/**
- * 报告服务
- *
- * @author snows
- * @date 2024/10/12
- */
 @Slf4j
 @Service
 @RequiredArgsConstructor
 public class ReportUpdateServiceImpl implements ReportUpdateService {
 
     private final FilerepoProperties filerepoProperties;
-
+    private final ReportPathManager reportPathManager;
+
+    /**
+     * 按配置项模块
+     * 
+     * @param reportType
+     * @param data
+     * @param templateBytes
+     * @param outputBasePath
+     * @param relationId
+     * @param request
+     * @param moduleType
+     * @param name
+     * @param level
+     * @param tenantName
+     * @return
+     * @throws Exception
+     */
     @SuppressWarnings("checkstyle:ReturnCount")
     @Override
-    public String createPlusVersionCheckReport(
+    public ReportGenerationResult createPlusVersionCheckReport(
         ReportType reportType, String data, byte[] templateBytes, String outputBasePath, Long relationId,
         HttpServletRequest request, ModuleType moduleType, String name, Integer level, String tenantName)
         throws Exception {
@@ -74,105 +94,118 @@ public class ReportUpdateServiceImpl implements ReportUpdateService {
 
         String sessionId = SESSION_MAP.get(relationId.toString());
 
+        // 处理指定模块
+        String reportPath = processModule(moduleType, data, processedData, templateBytes, sessionId, relationId);
+        reportPathManager.addReportPath(sessionId, reportPath);
+
+        String mergedReportPath = null;
+        boolean isLastModule = reportPath.contains("attachmentSection");
+
+        if (isLastModule) {
+            List<String> reportPaths = reportPathManager.getReportPaths(sessionId);
+            XWPFDocument targetDoc;
+            try (FileInputStream fis = new FileInputStream(reportPaths.get(0))) {
+                targetDoc = new XWPFDocument(fis);
+            }
+            List<XWPFDocument> sourceDocs = new ArrayList<>();
+            for (int i = 1; i < reportPaths.size(); i++) {
+                try (FileInputStream fis = new FileInputStream(reportPaths.get(i))) {
+                    sourceDocs.add(new XWPFDocument(fis));
+                }
+            }
+            String label = relationId + "_" + IdUtil.fastSimpleUUID();
+            mergedReportPath = filerepoProperties.getBasePath() + "/" + label + ".docx";
+            // 调用合并方法
+            DocxUtil.mergeDocx(targetDoc, sourceDocs, mergedReportPath, relationId);
+        }
+
+        return new ReportGenerationResult(reportPath, mergedReportPath, isLastModule);
+    }
+
+    /**
+     * 处理单个模块的报告生成
+     */
+    @SuppressWarnings("checkstyle:ParameterNumber")
+    private String processModule(ModuleType moduleType, String data, Map<String, Object> processedData,
+        byte[] templateBytes, String sessionId, Long relationId) throws Exception {
         String reportPath;
         switch (moduleType) {
             case ANTIBRIBERY:
-                reportPath =
-                    new AntiBriberyRender(sessionId, filerepoProperties).renderDocx(data, processedData, templateBytes,
-                        String.valueOf(relationId));
-                return reportPath;
+                reportPath = new AntiBriberyRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case ANTIBRIBERY_NEW:
-                reportPath =
-                    new AntiBriberyNewRender(sessionId, filerepoProperties).renderDocx(data, processedData, templateBytes,
-                        String.valueOf(relationId));
-                return reportPath;
+                reportPath = new AntiBriberyNewRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case PLATFORM_COMPANY_BASICINFO:
-                reportPath =
-                    new BasicInfoRender(sessionId, filerepoProperties).renderDocx(data, processedData, templateBytes,
-                        String.valueOf(relationId));
-                return reportPath;
+                reportPath = new BasicInfoRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case PLATFORM_COMPANY_ATTACHMENTSECTION:
-                reportPath =
-                    new AttachmentSectionRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                        templateBytes, String.valueOf(relationId));
-                return reportPath;
+                reportPath = new AttachmentSectionRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case ASSOCIATION_ATTACHMENTSECTION:
-                reportPath =
-                    new AssociationAttachmentSectionRender(sessionId, filerepoProperties).renderDocx(data,
-                        processedData,
-                        templateBytes, String.valueOf(relationId));
-                return reportPath;
+                reportPath = new AssociationAttachmentSectionRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case FOUNDATION_ATTACHMENTSECTION:
-                reportPath =
-                    new FoundationAttachmentSectionRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                        templateBytes, String.valueOf(relationId));
-                return reportPath;
+                reportPath = new FoundationAttachmentSectionRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case COMMON:
-                reportPath =
-                    new ServiceProviderInfoRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                        templateBytes, String.valueOf(relationId));
-                return reportPath;
+                reportPath = new ServiceProviderInfoRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case PLATFORM_COMPANY_FINANCIALINFO:
-                reportPath = new FinancialInfoRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                    templateBytes, String.valueOf(relationId));
-                return reportPath;
+                reportPath = new FinancialInfoRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case PLATFORM_COMPANY_FINANCIALINFO_NEW:
-                reportPath = new FinancialInfoNewRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                    templateBytes, String.valueOf(relationId));
-                return reportPath;
+                reportPath = new FinancialInfoNewRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case FOUNDATION_FINANCIALINFO:
-                reportPath =
-                    new FoundationfinancialInfoRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                        templateBytes, String.valueOf(relationId));
-                return reportPath;
+                reportPath = new FoundationfinancialInfoRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case PUBLIC_RECORD:
-                reportPath = new PublicRecordRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                    templateBytes, String.valueOf(relationId));
-                return reportPath;
+                reportPath = new PublicRecordRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case PUBLIC_RECORD_NEW:
-                reportPath = new PublicRecordNewRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                    templateBytes, String.valueOf(relationId));
-                return reportPath;
-
+                reportPath = new PublicRecordNewRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case PLATFORM_COMPANY_BASICINFO_NEW:
-                reportPath =
-                    new BasicInfoNewRender(sessionId, filerepoProperties).renderDocx(data, processedData, templateBytes,
-                        String.valueOf(relationId));
-                return reportPath;
-
+                reportPath = new BasicInfoNewRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case FOUNDATION_BASICINFO:
-                reportPath =
-                    new FoundationBasicInfoRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                        templateBytes,
-                        String.valueOf(relationId));
-                return reportPath;
+                reportPath = new FoundationBasicInfoRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case ASSOCIATION_BASICINFO:
-                reportPath =
-                    new AssociationBasicInfoRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                        templateBytes,
-                        String.valueOf(relationId));
-                return reportPath;
+                reportPath = new AssociationBasicInfoRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case PROJECT:
-                reportPath =
-                    new ProjectInfoRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                        templateBytes,
-                        String.valueOf(relationId));
-                return reportPath;
+                reportPath = new ProjectInfoRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case INTERESTCONFLICTS:
-                reportPath =
-                    new InterestConflictsRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                        templateBytes,
-                        String.valueOf(relationId));
-                return reportPath;
+                reportPath = new InterestConflictsRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             case TAX_NEW:
-                reportPath = new TaxNewRender(sessionId, filerepoProperties).renderDocx(data, processedData,
-                        templateBytes, String.valueOf(relationId));
-                return reportPath;
-
+                reportPath = new TaxNewRender(sessionId, filerepoProperties)
+                    .renderDocx(data, processedData, templateBytes, String.valueOf(relationId));
+                break;
             default:
                 throw new UnsupportedOperationException("Unsupported module type: " + moduleType);
-
         }
+        return reportPath;
     }
 
 }

+ 7 - 3
easier-report-biz/src/main/java/com/yaoyicloud/tools/DocxUtil.java

@@ -22,16 +22,19 @@ import org.apache.poi.xwpf.usermodel.XWPFTableRow;
 import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
 import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
 import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture;
-
-import com.deepoove.poi.xwpf.XWPFStructuredDocumentTag;
 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
 import org.openxmlformats.schemas.wordprocessingml.x2006.main.STStyleType;
 
+import com.deepoove.poi.xwpf.XWPFStructuredDocumentTag;
+
+
+
 public final class DocxUtil {
 
-    public static void mergeDocx(XWPFDocument target, List<XWPFDocument> sources, String outputPath)
+    public static void mergeDocx(XWPFDocument target, List<XWPFDocument> sources, String outputPath, Long relationId)
         throws InvalidFormatException, FileNotFoundException, IOException {
         mergeDocx(target, sources, outputPath, false);
+
     }
 
     public static void mergeDocx(XWPFDocument target, List<XWPFDocument> sources, String outputPath,
@@ -214,4 +217,5 @@ public final class DocxUtil {
         }
     }
 
+
 }

+ 3 - 0
easier-report-biz/src/main/proto/fxy.proto

@@ -253,6 +253,9 @@ message PublicRecord {
   repeated CheckItemDetail judicialRiskChecks = 7; // 司法风险
 
   repeated CheckItemDetail taxationRiskChecks = 8; //税务风险
+
+  optional string qualification = 9; //纳税人类型
+  optional string grade = 10; //纳税信用评级
 }
 
 message FinancialData {

+ 0 - 31
easier-report-biz/src/test/java/com/yaoyicloud/render/test/TestDocxOperations.java

@@ -1,31 +0,0 @@
-package com.yaoyicloud.render.test;
-
-import static org.junit.Assert.assertTrue;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.junit.Test;
-import com.yaoyicloud.tools.DocxUtil;
-
-public class TestDocxOperations {
-
-    @Test
-    public void testMergeDocx() throws IOException, InvalidFormatException {
-
-        // 直接使用文件路径创建FileInputStream
-        FileInputStream streamMerge = new FileInputStream("C:\\Users\\yyy\\dev\\yyc3\\easier-be\\temp\\560E3B64F6AB87FEC22EF84EDBC84272\\1930150383555809281_serviceProviderInfo.docx");
-        FileInputStream stream1 = new FileInputStream("C:\\Users\\yyy\\dev\\yyc3\\easier-be\\temp\\560E3B64F6AB87FEC22EF84EDBC84272\\1930150383555809281_publicRecord.docx");
-        FileInputStream stream2 = new FileInputStream("C:\\Users\\yyy\\dev\\yyc3\\easier-be\\temp\\560E3B64F6AB87FEC22EF84EDBC84272\\1930150383555809281_attachmentSection.docx");
-
-        DocxUtil.mergeDocx(new XWPFDocument(streamMerge),
-                List.of(new XWPFDocument(stream1),new XWPFDocument(stream2)),
-                "C:\\Users\\yyy\\Desktop\\11.docx");
-
-        assertTrue(true);
-    }
-
-}