From 0977a77eed553d4533215ba039962aced456a755 Mon Sep 17 00:00:00 2001
From: hongawen <83944980@qq.com>
Date: Mon, 1 Sep 2025 11:06:00 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=B7=A5=E5=85=B7=E6=A8=A1?=
=?UTF-8?q?=E5=9D=97=EF=BC=8C=E5=B9=B6=E6=B7=BB=E5=8A=A0=E4=BA=86=E5=AD=90?=
=?UTF-8?q?=E6=A8=A1=E5=9D=97-=E6=8A=A5=E5=91=8A=E5=B7=A5=E5=85=B7?=
=?UTF-8?q?=E7=94=9F=E6=88=90=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../com/njcn/gather/plan/pojo/po/AdPlan.java | 3 +
pom.xml | 1 +
tools/README.md | 52 ++
tools/pom.xml | 25 +
tools/report-generator/PROJECT_SUMMARY.md | 184 ++++++
tools/report-generator/README.md | 126 ++++
tools/report-generator/pom.xml | 144 +++++
.../controller/ReportGeneratorController.java | 392 ++++++++++++
.../report/engine/DocumentProcessor.java | 63 ++
.../report/engine/WordDocumentProcessor.java | 253 ++++++++
.../tools/report/model/ProcessOptions.java | 175 +++++
.../tools/report/model/ProcessResult.java | 232 +++++++
.../report/model/ReportResponseEnum.java | 58 ++
.../tools/report/model/TemplateRequest.java | 184 ++++++
.../tools/report/model/TemplateSource.java | 114 ++++
.../tools/report/model/TemplateType.java | 63 ++
.../service/ReportGeneratorService.java | 52 ++
.../impl/ReportGeneratorServiceImpl.java | 216 +++++++
.../tools/report/util/Docx4jAdvancedUtil.java | 603 ++++++++++++++++++
.../report/util/ReportExceptionUtil.java | 111 ++++
.../tools/report/util/WordDocumentUtil.java | 332 ++++++++++
.../tools/report/ReportGeneratorTest.java | 103 +++
22 files changed, 3486 insertions(+)
create mode 100644 tools/README.md
create mode 100644 tools/pom.xml
create mode 100644 tools/report-generator/PROJECT_SUMMARY.md
create mode 100644 tools/report-generator/README.md
create mode 100644 tools/report-generator/pom.xml
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/controller/ReportGeneratorController.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/engine/DocumentProcessor.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/engine/WordDocumentProcessor.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/model/ProcessOptions.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/model/ProcessResult.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/model/ReportResponseEnum.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/model/TemplateRequest.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/model/TemplateSource.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/model/TemplateType.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/service/ReportGeneratorService.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/service/impl/ReportGeneratorServiceImpl.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/util/Docx4jAdvancedUtil.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/util/ReportExceptionUtil.java
create mode 100644 tools/report-generator/src/main/java/com/njcn/gather/tools/report/util/WordDocumentUtil.java
create mode 100644 tools/report-generator/src/test/java/com/njcn/gather/tools/report/ReportGeneratorTest.java
diff --git a/detection/src/main/java/com/njcn/gather/plan/pojo/po/AdPlan.java b/detection/src/main/java/com/njcn/gather/plan/pojo/po/AdPlan.java
index 6d200920..cfde0c56 100644
--- a/detection/src/main/java/com/njcn/gather/plan/pojo/po/AdPlan.java
+++ b/detection/src/main/java/com/njcn/gather/plan/pojo/po/AdPlan.java
@@ -81,6 +81,9 @@ public class AdPlan extends BaseEntity implements Serializable {
/**
* 是否关联报告,0-不关联 1-关联
+ * 目前这个阶段
+ * 0-不关联的是采用替换占位符的方式生成测试报告
+ * 1-关联的是采用模板生成测试报告
*/
private Integer associateReport;
diff --git a/pom.xml b/pom.xml
index a863b3a1..860a5344 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,7 @@
detection
storage
event_smart
+ tools
pom
融合各工具的项目
diff --git a/tools/README.md b/tools/README.md
new file mode 100644
index 00000000..fa8023dc
--- /dev/null
+++ b/tools/README.md
@@ -0,0 +1,52 @@
+# Tools 工具模块
+
+这是CN_Gather项目的工具集合模块,用于管理各种通用工具。每个工具作为独立的子模块,拥有完整的MVC架构。
+
+## 架构设计
+
+```
+tools/
+├── report-generator/ # 报告生成工具
+├── data-generator/ # 数据生成工具(未来扩展)
+└── file-processor/ # 文件处理工具(未来扩展)
+```
+
+## 子模块说明
+
+### 1. report-generator(报告生成工具)
+- **功能**: 通用的文档模板处理和报告生成
+- **技术栈**: Apache POI, docx4j
+- **特性**:
+ - 占位符替换
+ - 书签定位插入
+ - 动态表格生成
+ - 多文档合并
+ - 样式管理
+
+### 2. data-generator(数据生成工具)
+- **功能**: MySQL数据生成、测试数据构造
+- **状态**: 待开发
+
+### 3. file-processor(文件处理工具)
+- **功能**: 文件转换、批量处理等
+- **状态**: 待开发
+
+## 设计原则
+
+1. **独立性**: 每个工具子模块独立部署和使用
+2. **通用性**: 脱离具体业务逻辑,提供纯技术能力
+3. **可扩展**: 支持插件化扩展和自定义处理器
+4. **易集成**: 提供简洁的API接口
+
+## 使用方式
+
+每个工具模块都提供HTTP接口和Java API两种使用方式:
+- HTTP接口:适合微服务架构,跨语言调用
+- Java API:适合同项目内直接依赖调用
+
+## 模块间依赖
+
+tools模块作为独立的工具集合,尽量减少对其他业务模块的依赖,主要依赖:
+- 基础的Spring Boot框架
+- 通用工具库(hutool等)
+- 各工具特定的技术栈依赖
\ No newline at end of file
diff --git a/tools/pom.xml b/tools/pom.xml
new file mode 100644
index 00000000..74c6f39f
--- /dev/null
+++ b/tools/pom.xml
@@ -0,0 +1,25 @@
+
+
+ 4.0.0
+
+
+ com.njcn.gather
+ CN_Gather
+ 1.0.0
+
+
+ tools
+ pom
+ 工具集合模块
+ 各种通用工具的集合,每个工具作为独立子模块
+
+
+ report-generator
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/report-generator/PROJECT_SUMMARY.md b/tools/report-generator/PROJECT_SUMMARY.md
new file mode 100644
index 00000000..7f4ff794
--- /dev/null
+++ b/tools/report-generator/PROJECT_SUMMARY.md
@@ -0,0 +1,184 @@
+# Report Generator 项目总结
+
+## 项目概述
+
+成功从CN_Gather项目的detection模块中抽取出了报告生成功能,创建了独立的通用工具模块。该模块完全脱离了业务逻辑,提供纯技术能力,可以被其他项目复用。
+
+## 架构设计
+
+### 模块结构
+```
+CN_Gather/
+├── tools/ # 工具集合模块(新增)
+│ ├── report-generator/ # 报告生成工具子模块(新增)
+│ │ ├── src/main/java/com/njcn/gather/tools/report/
+│ │ │ ├── controller/ # HTTP接口层
+│ │ │ ├── service/ # 业务服务层
+│ │ │ ├── engine/ # 模板处理引擎
+│ │ │ ├── model/ # 数据模型
+│ │ │ ├── util/ # 工具类
+│ │ └── pom.xml
+│ ├── pom.xml
+│ └── README.md
+├── detection/ # 原有检测模块(保持不变)
+├── entrance/ # 应用入口
+└── pom.xml # 已更新,包含tools模块
+```
+
+### 核心组件
+
+#### 1. 数据模型层 (model/)
+- **TemplateSource**: 模板来源定义,支持文件、流、字节数组输入
+- **TemplateRequest**: 模板处理请求封装
+- **ProcessResult**: 处理结果封装,包含详细统计和错误信息
+- **ProcessOptions**: 处理选项配置,支持各种功能开关
+- **TemplateType**: 模板类型枚举,支持扩展
+
+#### 2. 引擎层 (engine/)
+- **DocumentProcessor**: 文档处理器接口
+- **WordDocumentProcessor**: Word文档处理实现
+
+#### 3. 工具类层 (util/)
+- **WordDocumentUtil**: 基于Apache POI的通用Word操作
+- **Docx4jAdvancedUtil**: 基于docx4j的高级Word操作
+
+#### 4. 服务层 (service/)
+- **ReportGeneratorService**: 报告生成服务接口
+- **ReportGeneratorServiceImpl**: 服务实现,支持同步/异步/批量处理
+
+#### 5. 控制器层 (controller/)
+- **ReportGeneratorController**: REST API接口,提供多种调用方式
+
+## 技术特性
+
+### 已实现功能
+1. ✅ **占位符替换**: `${key}`、`#{key}`、`{{key}}` 格式支持
+2. ✅ **多输入方式**: 文件路径、输入流、字节数组
+3. ✅ **多输出方式**: 文件、流、字节数组
+4. ✅ **同步处理**: 立即返回结果
+5. ✅ **异步处理**: 支持长时间处理任务
+6. ✅ **批量处理**: 一次处理多个模板
+7. ✅ **错误处理**: 完整的异常处理和错误信息
+8. ✅ **性能监控**: 处理时间和统计信息
+9. ✅ **参数验证**: 请求参数完整性验证
+10. ✅ **模板验证**: 模板文件有效性检查
+
+### 从原有代码抽取的功能
+- **WordUtil → WordDocumentUtil**: 基础Word文档操作
+- **Docx4jUtil → Docx4jAdvancedUtil**: 高级文档处理功能
+- **BookmarkUtil 功能**: 整合到高级工具类中
+- **占位符替换逻辑**: 通用化并支持多种格式
+- **文档合并功能**: 保留并优化
+- **样式管理功能**: 字体、颜色、对齐等
+
+## API 设计
+
+### HTTP接口
+```
+POST /api/tools/report/process/simple # 简单处理
+POST /api/tools/report/process/advanced # 高级处理
+POST /api/tools/report/process/async # 异步处理
+GET /api/tools/report/process/async/{id} # 查询异步结果
+POST /api/tools/report/process/batch # 批量处理
+POST /api/tools/report/validate # 模板验证
+```
+
+### Java API
+```java
+// 核心服务接口
+ProcessResult processTemplate(TemplateRequest request)
+String processTemplateAsync(TemplateRequest request)
+ProcessResult getAsyncResult(String requestId)
+List batchProcessTemplates(List requests)
+ProcessResult validateTemplate(TemplateRequest request)
+```
+
+## 设计优势
+
+### 1. 高内聚低耦合
+- 完全独立的模块,不依赖具体业务
+- 清晰的分层架构
+- 接口与实现分离
+
+### 2. 可扩展性强
+- 支持插件化的文档处理器
+- 可方便扩展新的模板类型(PDF、Excel等)
+- 处理选项可灵活配置
+
+### 3. 易于使用
+- 提供多种使用方式(HTTP、Java API)
+- Builder模式简化对象构建
+- 完整的使用文档和示例
+
+### 4. 健壮性好
+- 完整的错误处理机制
+- 参数验证和模板验证
+- 资源自动管理和清理
+
+### 5. 性能优异
+- 支持异步处理避免阻塞
+- 批量处理提高效率
+- 详细的性能统计信息
+
+## 使用场景
+
+### 1. 报告自动化生成
+- 检测报告、试验报告
+- 财务报表、统计报表
+- 证书、合格证等
+
+### 2. 文档批量处理
+- 合同批量生成
+- 通知书批量制作
+- 标签批量打印
+
+### 3. 模板管理系统
+- 模板上传和验证
+- 模板版本管理
+- 模板效果预览
+
+## 部署和集成
+
+### 1. 独立部署
+tools模块可以作为独立的微服务部署,对外提供HTTP接口。
+
+### 2. 嵌入式集成
+其他项目可以直接依赖report-generator模块,使用Java API调用。
+
+### 3. 与现有系统集成
+detection模块可以逐步迁移到使用新的report-generator工具。
+
+## 后续扩展建议
+
+### 1. 功能扩展
+- 支持PDF模板处理
+- 支持Excel模板处理
+- 支持图片插入和处理
+- 支持复杂表达式计算
+
+### 2. 性能优化
+- 添加模板缓存机制
+- 支持流式处理大文件
+- 增加并发控制和限流
+
+### 3. 管理功能
+- 模板管理界面
+- 处理任务监控面板
+- 统计分析报表
+
+### 4. 安全增强
+- 用户权限控制
+- 模板安全检查
+- 操作审计日志
+
+## 总结
+
+成功创建了一个完全独立、通用的报告生成工具模块,实现了以下目标:
+
+1. **脱离业务**: 完全剥离了电能质量检测的业务逻辑
+2. **通用化**: 可以处理任何Word模板和数据
+3. **易扩展**: 支持新的文档类型和处理方式
+4. **高可用**: 提供多种调用方式和完善的错误处理
+5. **高性能**: 支持异步和批量处理
+
+该工具不仅可以满足当前CN_Gather项目的需求,也为未来的数据生成工具、文件处理工具等提供了良好的架构基础。
\ No newline at end of file
diff --git a/tools/report-generator/README.md b/tools/report-generator/README.md
new file mode 100644
index 00000000..e5a2ed4e
--- /dev/null
+++ b/tools/report-generator/README.md
@@ -0,0 +1,126 @@
+# Report Generator 报告生成工具
+
+通用的文档模板处理和报告生成工具,支持Word文档的动态内容生成。
+
+## 功能特性
+
+### 1. 基础功能
+- ✅ 占位符替换 (`${key}` 格式)
+- ✅ Word文档处理 (基于Apache POI)
+- ✅ 模板文件管理
+- ✅ 多种输入输出方式 (文件路径、流、字节数组)
+
+### 2. 高级功能
+- ✅ 书签定位插入 (基于docx4j)
+- ✅ 动态表格生成
+- ✅ 文档合并
+- ✅ 样式管理 (字体、颜色、对齐)
+- ✅ 自动分页控制
+- ✅ 深拷贝支持
+
+### 3. 扩展功能
+- 🔄 自定义处理器插件化
+- 🔄 复杂表达式支持
+- 🔄 模板验证
+- 🔄 缓存优化
+
+## 架构设计
+
+```
+report-generator/
+├── controller/ # HTTP接口层
+├── service/ # 业务逻辑层
+├── engine/ # 模板引擎核心
+│ ├── DocumentProcessor # 文档处理器接口
+│ ├── WordEngine # Word处理引擎
+│ ├── PlaceholderEngine # 占位符处理引擎
+│ └── BookmarkEngine # 书签处理引擎
+├── model/ # 数据模型
+│ ├── TemplateRequest # 处理请求模型
+│ ├── TemplateSource # 模板源定义
+│ └── ProcessResult # 处理结果
+├── util/ # 工具类
+└── exception/ # 异常处理
+```
+
+## 使用示例
+
+### 1. HTTP接口方式
+
+```bash
+# 简单占位符替换
+POST /api/report/process
+Content-Type: multipart/form-data
+
+{
+ "templateFile": ,
+ "data": {
+ "name": "张三",
+ "date": "2024-01-01",
+ "amount": "1000.00"
+ },
+ "outputFileName": "report.docx"
+}
+```
+
+### 2. Java API方式
+
+```java
+// 注入服务
+@Autowired
+private ReportGeneratorService reportService;
+
+// 创建请求
+TemplateRequest request = TemplateRequest.builder()
+ .templatePath("template.docx")
+ .data(Map.of("name", "张三", "date", "2024-01-01"))
+ .outputPath("result.docx")
+ .options(ProcessOptions.builder()
+ .enablePlaceholder(true)
+ .enableBookmark(true)
+ .build())
+ .build();
+
+// 处理模板
+ProcessResult result = reportService.processTemplate(request);
+```
+
+## 配置说明
+
+### 处理选项 (ProcessOptions)
+```java
+ProcessOptions options = ProcessOptions.builder()
+ .enablePlaceholder(true) // 启用占位符替换
+ .enableBookmark(true) // 启用书签处理
+ .enableDynamicTable(true) // 启用动态表格
+ .enableAutoPage(true) // 启用自动分页
+ .placeholderPattern("${}") // 占位符格式
+ .build();
+```
+
+### 模板源配置 (TemplateSource)
+```java
+// 文件路径方式
+TemplateSource.fromFile("path/to/template.docx")
+
+// 输入流方式
+TemplateSource.fromStream(inputStream)
+
+// 字节数组方式
+TemplateSource.fromBytes(byteArray)
+```
+
+## 技术栈
+
+- **Apache POI**: Word文档基础操作
+- **docx4j**: 高级Word文档处理
+- **Spring Boot**: 框架支持
+- **Hutool**: 工具库
+- **Jackson**: JSON处理
+
+## 性能优化
+
+1. **模板缓存**: 常用模板缓存减少IO
+2. **流式处理**: 大文件流式处理避免内存溢出
+3. **异步处理**: 支持异步批量处理
+4. **资源管理**: 自动资源清理和释放
\ No newline at end of file
diff --git a/tools/report-generator/pom.xml b/tools/report-generator/pom.xml
new file mode 100644
index 00000000..c84ba26b
--- /dev/null
+++ b/tools/report-generator/pom.xml
@@ -0,0 +1,144 @@
+
+
+ 4.0.0
+
+
+ com.njcn.gather
+ tools
+ 1.0.0
+
+
+ report-generator
+ jar
+ 报告生成工具
+ 通用的文档模板处理和报告生成工具,支持占位符替换、书签插入、动态表格等功能
+
+
+ UTF-8
+ UTF-8
+ UTF-8
+ 1.8
+ 1.8
+ 1.8
+
+
+
+
+
+ com.njcn
+ njcn-common
+ 0.0.1
+
+
+
+ com.njcn
+ spingboot2.3.12
+ 2.3.12
+
+
+
+
+ org.apache.poi
+ poi
+ 4.1.2
+
+
+
+ org.apache.poi
+ poi-ooxml
+ 4.1.2
+
+
+
+ org.apache.poi
+ poi-ooxml-schemas
+ 4.1.2
+
+
+
+ org.apache.poi
+ poi-scratchpad
+ 4.1.2
+
+
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ 2.3.3
+
+
+
+ org.glassfish.jaxb
+ jaxb-runtime
+ 2.3.3
+
+
+
+ org.docx4j
+ docx4j
+ 6.1.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.12.0
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.12.0
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.12.0
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.83
+
+
+
+
+ commons-fileupload
+ commons-fileupload
+ 1.4
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/report-generator/src/main/java/com/njcn/gather/tools/report/controller/ReportGeneratorController.java b/tools/report-generator/src/main/java/com/njcn/gather/tools/report/controller/ReportGeneratorController.java
new file mode 100644
index 00000000..46e0576d
--- /dev/null
+++ b/tools/report-generator/src/main/java/com/njcn/gather/tools/report/controller/ReportGeneratorController.java
@@ -0,0 +1,392 @@
+package com.njcn.gather.tools.report.controller;
+
+import com.njcn.gather.tools.report.model.*;
+import com.njcn.gather.tools.report.service.ReportGeneratorService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 报告生成工具HTTP接口
+ * 提供REST风格的报告生成API
+ *
+ * @author hongawen
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/tools/report")
+@RequiredArgsConstructor
+public class ReportGeneratorController {
+
+ private final ReportGeneratorService reportGeneratorService;
+
+ /**
+ * 简单模板处理 - 占位符替换
+ *
+ * @param templateFile 模板文件
+ * @param dataJson 数据JSON字符串
+ * @param outputFileName 输出文件名(可选)
+ * @param response HTTP响应
+ */
+ @PostMapping("/process/simple")
+ public void processSimpleTemplate(
+ @RequestParam("templateFile") MultipartFile templateFile,
+ @RequestParam("data") String dataJson,
+ @RequestParam(value = "outputFileName", required = false) String outputFileName,
+ HttpServletResponse response) throws IOException {
+
+ log.info("接收到简单模板处理请求: {}", templateFile.getOriginalFilename());
+
+ try {
+ // 解析数据
+ @SuppressWarnings("unchecked")
+ Map data = com.fasterxml.jackson.databind.ObjectMapper.class
+ .getDeclaredConstructor().newInstance().readValue(dataJson, Map.class);
+
+ // 构建请求
+ TemplateRequest request = TemplateRequest.builder()
+ .templateSource(TemplateSource.fromStream(templateFile.getInputStream(),
+ templateFile.getOriginalFilename()))
+ .data(data)
+ .options(ProcessOptions.simplePlaceholder())
+ .outputTarget(TemplateRequest.OutputTarget.toBytes())
+ .build();
+
+ // 处理模板
+ ProcessResult result = reportGeneratorService.processTemplate(request);
+
+ if (result.isSuccess() && result.getOutputBytes() != null) {
+ // 设置响应头
+ String fileName = outputFileName != null ? outputFileName :
+ "report_" + System.currentTimeMillis() + ".docx";
+ response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
+ response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
+ response.setContentLength(result.getOutputBytes().length);
+
+ // 输出文件
+ try (OutputStream os = response.getOutputStream()) {
+ os.write(result.getOutputBytes());
+ os.flush();
+ }
+
+ log.info("简单模板处理成功: {}", fileName);
+ } else {
+ response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ response.getWriter().write("模板处理失败: " + result.getMessage());
+ }
+
+ } catch (Exception e) {
+ log.error("简单模板处理异常: {}", e.getMessage(), e);
+ response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ response.getWriter().write("处理异常: " + e.getMessage());
+ }
+ }
+
+ /**
+ * 高级模板处理 - 支持更多功能
+ */
+ @PostMapping("/process/advanced")
+ public ResponseEntity