diff --git a/detection/pom.xml b/detection/pom.xml
index e6be0098..b615de17 100644
--- a/detection/pom.xml
+++ b/detection/pom.xml
@@ -74,6 +74,29 @@
poi-ooxml
4.1.2
+
+
+
+ org.docx4j
+ docx4j
+ 3.3.4
+
+
+ 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
+
+
diff --git a/detection/src/main/java/com/njcn/gather/detection/pojo/vo/DetectionData.java b/detection/src/main/java/com/njcn/gather/detection/pojo/vo/DetectionData.java
index bbfcb2f6..e65b73be 100644
--- a/detection/src/main/java/com/njcn/gather/detection/pojo/vo/DetectionData.java
+++ b/detection/src/main/java/com/njcn/gather/detection/pojo/vo/DetectionData.java
@@ -20,7 +20,7 @@ public class DetectionData {
private Double num;
/**
- * 是否是符合数据(1.合格 2.不合格 3.网络超时 4.无法处理 5.不参与误差比较)
+ * 1.合格 2.不合格 3.网络超时 4.无法处理 5.不参与误差比较
*/
private Integer isData;
diff --git a/detection/src/main/java/com/njcn/gather/device/service/impl/PqDevServiceImpl.java b/detection/src/main/java/com/njcn/gather/device/service/impl/PqDevServiceImpl.java
index d42c7290..822133bd 100644
--- a/detection/src/main/java/com/njcn/gather/device/service/impl/PqDevServiceImpl.java
+++ b/detection/src/main/java/com/njcn/gather/device/service/impl/PqDevServiceImpl.java
@@ -43,6 +43,7 @@ import com.njcn.gather.system.dictionary.service.IDictDataService;
import com.njcn.gather.system.dictionary.service.IDictTypeService;
import com.njcn.gather.type.pojo.po.DevType;
import com.njcn.gather.type.service.IDevTypeService;
+import com.njcn.gather.user.user.service.ISysUserService;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.ExcelUtil;
import com.njcn.web.utils.PoiUtil;
@@ -75,6 +76,7 @@ public class PqDevServiceImpl extends ServiceImpl implements
private final IDevTypeService devTypeService;
private final ISysTestConfigService sysTestConfigService;
private final IDictTypeService dictTypeService;
+ private final ISysUserService userService;
@Override
public Page listPqDevs(PqDevParam.QueryParam queryParam) {
@@ -390,6 +392,7 @@ public class PqDevServiceImpl extends ServiceImpl implements
return CheckStateEnum.UNCHECKED.getValue();
}
+//
// @Override
// public List getPieData(String planId) {
// List pqDevList = this.lambdaQuery().eq(PqDev::getPlanId, planId).eq(PqDev::getState, DataStateEnum.ENABLE.getCode()).list();
@@ -411,6 +414,9 @@ public class PqDevServiceImpl extends ServiceImpl implements
@Override
public PqDevVO getPqDevById(String id) {
PqDev pqDev = this.getById(id);
+ if(StrUtil.isNotBlank(pqDev.getCheckBy())){
+ pqDev.setCheckBy(userService.getById(pqDev.getCheckBy()).getName());
+ }
PqDevVO pqDevVO = new PqDevVO();
BeanUtil.copyProperties(pqDev, pqDevVO);
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/constant/PowerConstant.java b/detection/src/main/java/com/njcn/gather/report/pojo/constant/PowerConstant.java
new file mode 100644
index 00000000..9e85a35e
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/constant/PowerConstant.java
@@ -0,0 +1,77 @@
+package com.njcn.gather.report.pojo.constant;
+
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 电能质量指标常用的一些常量池
+ *
+ * @author hongawen
+ * @version 1.0
+ * @data 2025/3/27 11:11
+ */
+public interface PowerConstant {
+
+ /**
+ * 有三相的指标
+ */
+ List THREE_PHASE = Arrays.asList("V", "HV", "HI", "HP", "HSV", "HSI", "I", "P", "F");
+
+ /**
+ * T相指标
+ */
+ List T_PHASE = Arrays.asList("VOLTAGE", "IMBV", "IMBA");
+
+
+ /**
+ * 有次数的指标
+ */
+ List TIME = Arrays.asList("HV", "HI", "HP", "HSV", "HSI");
+
+ /**
+ * 没有次数的指标
+ */
+ List NO_TIME = Arrays.asList("V", "I", "P", "VOLTAGE", "IMBV", "IMBA", "F");
+
+ /**
+ * 有数据范围
+ */
+ List DATA_RANGE = Arrays.asList(1, 2);
+
+ /**
+ * 暂态符号
+ */
+ String VOLTAGE = "VOLTAGE";
+
+ /**
+ * A相
+ */
+ String PHASE_A = "A";
+
+ /**
+ * B相
+ */
+ String PHASE_B = "B";
+
+ /**
+ * C相
+ */
+ String PHASE_C = "C";
+
+ /**
+ * T相
+ */
+ String PHASE_T = "T";
+
+ /**
+ * 电流单位
+ */
+ String CURRENT_UNIT = "A";
+
+ /**
+ * 电压单位
+ */
+ String VOLTAGE_UNIT = "V";
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/constant/ReportConstant.java b/detection/src/main/java/com/njcn/gather/report/pojo/constant/ReportConstant.java
new file mode 100644
index 00000000..3b4cfc8b
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/constant/ReportConstant.java
@@ -0,0 +1,22 @@
+package com.njcn.gather.report.pojo.constant;
+
+/**
+ *
+ * 报告相关的一些常量
+ *
+ * @author hongawen
+ * @version 1.0
+ * @data 2025/4/3 13:44
+ */
+public interface ReportConstant {
+
+ /**
+ * docx文档后缀
+ */
+ String DOCX = ".docx";
+
+ /**
+ * 报告模板中书签的起始标识
+ */
+ String BOOKMARK_START = "#{";
+}
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/enums/AffectEnum.java b/detection/src/main/java/com/njcn/gather/report/pojo/enums/AffectEnum.java
new file mode 100644
index 00000000..0eaf122d
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/enums/AffectEnum.java
@@ -0,0 +1,43 @@
+package com.njcn.gather.report.pojo.enums;
+
+import lombok.Getter;
+
+/**
+ * 影响量枚举
+ * @author hongawen
+ * @version 1.0
+ * @data 2025/3/27 21:07
+ */
+@Getter
+public enum AffectEnum {
+
+
+ BASE("base", "额定工作条件下的检测"),
+ VOL("vol", "电压对XX测量的影响"),
+ FREQ("freq", "频率对XX测量的影响"),
+ HARM("single", "谐波对XX测量的影响");
+
+ private String key;
+
+ private String desc;
+
+ AffectEnum(String key, String desc) {
+ this.key = key;
+ this.desc = desc;
+ }
+
+ /**
+ * 根据key找到适配的枚举
+ *
+ * @param key 枚举的key
+ * @return 匹配的枚举实例,如果没有找到则返回null
+ */
+ public static AffectEnum getByKey(String key) {
+ for (AffectEnum affectEnum : AffectEnum.values()) {
+ if (affectEnum.getKey().equalsIgnoreCase(key)) {
+ return affectEnum;
+ }
+ }
+ return null;
+ }
+}
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/enums/BaseReportKeyEnum.java b/detection/src/main/java/com/njcn/gather/report/pojo/enums/BaseReportKeyEnum.java
new file mode 100644
index 00000000..25a0b829
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/enums/BaseReportKeyEnum.java
@@ -0,0 +1,42 @@
+package com.njcn.gather.report.pojo.enums;
+
+import lombok.Getter;
+
+/**
+ *
+ * 本枚举用于记录模板中关键字的含义
+ * 比如 ${manufacturer} 对应的设备厂家
+ *
+ * @author hongawen
+ * @version 1.0
+ * @data 2025/3/24 14:34
+ *
+ * */
+@Getter
+public enum BaseReportKeyEnum {
+
+ DEV_TYPE("devType","设备型号、规格"),
+ DEV_CODE("createId","装置编号"),
+ POWER("power","工作电源"),
+ DEV_CURR("devCurr","额定电流"),
+ DEV_VOLT("devVolt","额定电压"),
+ COUNT("count","通道数"),
+ MANUFACTURER("manufacturer","设备厂家、制造厂商"),
+ SAMPLE_ID("sampleId","样品编号"),
+ ARRIVED_DATE("arrivedDate","收样日期"),
+ TEST_DATE("testDate","检测日期"),
+ INSPECTOR("inspector","检测员"),
+ YEAR("year","年份"),
+ MONTH("month","月份"),
+ DAY("day","日"),
+ YEAR_MONTH_DAY("year-month-day","年-月-日");
+
+ private String key;
+
+ private String desc;
+
+ BaseReportKeyEnum(String key, String desc) {
+ this.key = key;
+ this.desc = desc;
+ }
+}
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/enums/DocAnchorEnum.java b/detection/src/main/java/com/njcn/gather/report/pojo/enums/DocAnchorEnum.java
new file mode 100644
index 00000000..9e3143dd
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/enums/DocAnchorEnum.java
@@ -0,0 +1,50 @@
+package com.njcn.gather.report.pojo.enums;
+
+import lombok.Getter;
+
+/**
+ * 统计文档锚点类型
+ *
+ * @author hongawen
+ * @version 1.0
+ * @data 2025/3/24 18:42
+ */
+@Getter
+public enum DocAnchorEnum {
+
+
+ DATA_LINE("#{data:line}", "准确度数据展示区域,以测试回路维度展示", 1),
+ DATA_SCRIPT("#{data:script}", "准确度数据展示区域,以检测项维度展示", 1),
+ TEST_RESULT_DEV("#{testResult:dev}", "检测结论,仅有设备结论", 2),
+ TEST_RESULT_LINE("#{testResult:line}", "检测结论,仅有回路结论", 2),
+ TEST_RESULT_DETAIL("#{testResult:detail}", "检测结论,包含回路、设备结论", 2),
+ CATALOG("#{catalog}", "目录信息", 3);
+
+ private String key;
+
+ private String desc;
+
+ private Integer sort;
+
+ DocAnchorEnum(String key, String desc, Integer sort) {
+ this.key = key;
+ this.desc = desc;
+ this.sort = sort;
+ }
+
+ /**
+ * 根据key找到适配的枚举
+ *
+ * @param key 枚举的key
+ * @return 匹配的枚举实例,如果没有找到则返回null
+ */
+ public static DocAnchorEnum getByKey(String key) {
+ for (DocAnchorEnum docAnchorEnum : DocAnchorEnum.values()) {
+ if (docAnchorEnum.getKey().equalsIgnoreCase(key)) {
+ return docAnchorEnum;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/enums/ItemReportKeyEnum.java b/detection/src/main/java/com/njcn/gather/report/pojo/enums/ItemReportKeyEnum.java
new file mode 100644
index 00000000..b7e1f068
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/enums/ItemReportKeyEnum.java
@@ -0,0 +1,70 @@
+package com.njcn.gather.report.pojo.enums;
+
+import lombok.Getter;
+
+/**
+ * 检测项模版枚举
+ * @author hongawen
+ * @version 1.0
+ * @data 2025/3/27 10:24
+ */
+@Getter
+public enum ItemReportKeyEnum {
+
+ NAME("name", "检测项,比如:频率"),
+ NAME_DETAIL("nameDetail", "检测项详细,比如:频率测量准确度"),
+ ERROR_SCOPE("errorScope", "误差范围,注:在段落中时需加上(),表格中无需添加"),
+ ERROR_SCOPE_MAG("errorScopeMag", "特征幅值:误差范围"),
+ ERROR_SCOPE_DUR("errorScopeDur", "持续时间:误差范围"),
+ SCRIPT_DETAIL("scriptDetail", "脚本输出明细。比如:基波电压UN=57.74V,f=50Hz,谐波含有率Uh=10%UN=5.774V"),
+ TIME("time", "次数"),
+ STANDARD("standard", "标准值"),
+ STANDARD_A("standardA", "A相标准值"),
+ STANDARD_B("standardB", "B相标准值"),
+ STANDARD_C("standardC", "C相标准值"),
+ STANDARD_MAG("standardMag", "特征幅值的标准值"),
+ STANDARD_DUR("standardDur_ms", "持续时间的标准值"),
+ TEST("test", "测试值"),
+ TEST_MAG("testMag", "特征幅值测试值"),
+ TEST_DUR("testDur_ms", "持续时间测试值"),
+ TEST_A("testA", "A相测试值"),
+ TEST_B("testB", "B相测试值"),
+ TEST_C("testC", "C相测试值"),
+ ERROR("error", "误差"),
+ ERROR_MAG("errorMag", "特征幅值误差"),
+ ERROR_DUR("errorDur_ms", "持续时间误差"),
+ ERROR_A("errorA", "A相误差"),
+ ERROR_B("errorB", "B相误差"),
+ ERROR_C("errorC", "C相误差"),
+ RESULT("result", "结论 比如:合格/不合格"),
+ RESULT_A("resultA", "结论 比如:合格/不合格"),
+ RESULT_B("resultB", "结论 比如:合格/不合格"),
+ RESULT_C("resultC", "结论 比如:合格/不合格"),
+ RESULT_MAG("resultMag", "特征幅值结论 比如:合格/不合格"),
+ RESULT_DUR("resultDur", "持续时间结论 比如:合格/不合格");
+
+ private String key;
+
+ private String desc;
+
+ ItemReportKeyEnum(String key, String desc) {
+ this.key = key;
+ this.desc = desc;
+ }
+
+ /**
+ * 根据key找到适配的枚举
+ *
+ * @param key 枚举的key
+ * @return 匹配的枚举实例,如果没有找到则返回null
+ */
+ public static ItemReportKeyEnum getByKey(String key) {
+ for (ItemReportKeyEnum itemReportKetEnum : ItemReportKeyEnum.values()) {
+ if (itemReportKetEnum.getKey().equalsIgnoreCase(key)) {
+ return itemReportKetEnum;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/enums/PowerIndexEnum.java b/detection/src/main/java/com/njcn/gather/report/pojo/enums/PowerIndexEnum.java
new file mode 100644
index 00000000..5fbc0ee8
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/enums/PowerIndexEnum.java
@@ -0,0 +1,52 @@
+package com.njcn.gather.report.pojo.enums;
+
+import lombok.Getter;
+
+/**
+ * 电能质量测试大项枚举
+ * @author hongawen
+ * @version 1.0
+ * @data 2025/3/27 18:29
+ */
+@Getter
+public enum PowerIndexEnum {
+
+
+ UNKNOWN("UNKNOWN", "未知指标"),
+ FREQ("FREQ", "频率"),
+ V("V", "电压"),
+ I("I", "电流"),
+ IMBV("IMBV", "三相电压不平衡度"),
+ IMBA("IMBA", "三相电流不平衡度"),
+ F("F", "闪变"),
+ HP("HP", "谐波有功功率"),
+ HV("HV", "谐波电压"),
+ HI("HI", "谐波电流"),
+ HSV("HSV", "间谐波电压"),
+ HSI("HSI", "间谐波电流"),
+ VOLTAGE("VOLTAGE", "电压暂降、暂升及短时中断");
+
+ private String key;
+
+ private String desc;
+
+ PowerIndexEnum(String key, String desc) {
+ this.key = key;
+ this.desc = desc;
+ }
+
+ /**
+ * 根据key找到适配的枚举
+ *
+ * @param key 枚举的key
+ * @return 匹配的枚举实例,如果没有找到则返回null
+ */
+ public static PowerIndexEnum getByKey(String key) {
+ for (PowerIndexEnum powerIndexEnum : PowerIndexEnum.values()) {
+ if (powerIndexEnum.getKey().equalsIgnoreCase(key)) {
+ return powerIndexEnum;
+ }
+ }
+ return null;
+ }
+}
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/enums/ReportResponseEnum.java b/detection/src/main/java/com/njcn/gather/report/pojo/enums/ReportResponseEnum.java
index ffbbf832..2892943e 100644
--- a/detection/src/main/java/com/njcn/gather/report/pojo/enums/ReportResponseEnum.java
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/enums/ReportResponseEnum.java
@@ -22,7 +22,9 @@ public enum ReportResponseEnum {
FILE_RENAME_FAILED("A012011", "文件重命名失败"),
REPORT_NAME_PATTERN_ERROR("A012012","报告名称格式错误,可包含中文、字母、数字、中划线、点号、空格,长度不能超过32个字符"),
REPORT_VERSION_PATTERN_ERROR("A012013","报告版本号格式错误,可包含中文、字母、数字、中划线、点号、空格,长度不能超过32个字符"),
- FILE_SIZE_ERROR("A012014","文件大小不能超过5MB" );
+ FILE_SIZE_ERROR("A012014","文件大小不能超过5MB" ),
+ GENERATE_REPORT_ERROR("A012015","生成报告失败"),
+ ;
private String code;
private String message;
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/result/SingleTestResult.java b/detection/src/main/java/com/njcn/gather/report/pojo/result/SingleTestResult.java
new file mode 100644
index 00000000..ef9bf48b
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/result/SingleTestResult.java
@@ -0,0 +1,40 @@
+package com.njcn.gather.report.pojo.result;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * 测试大项的检测结果
+ *
+ * @author hongawen
+ * @version 1.0
+ * @data 2025/4/7 20:17
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SingleTestResult implements Serializable {
+
+ /**
+ * 大项名称
+ */
+ private String scriptCode;
+
+ /**
+ * 是否合格
+ */
+ private boolean qualified;
+
+
+ /**
+ * 细节集合
+ */
+ private Map>>>> detail;
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/report/pojo/vo/Bookmark.java b/detection/src/main/java/com/njcn/gather/report/pojo/vo/Bookmark.java
new file mode 100644
index 00000000..1a4fc8c6
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/report/pojo/vo/Bookmark.java
@@ -0,0 +1,39 @@
+package com.njcn.gather.report.pojo.vo;
+
+import com.njcn.gather.report.pojo.enums.DocAnchorEnum;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author hongawen
+ * @version 1.0
+ * @data 2025/4/7 15:36
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Bookmark implements Serializable,Comparable{
+
+ /**
+ * 在文档中段落的索引
+ */
+ private Integer index;
+
+ /**
+ * 对应枚举
+ */
+ private DocAnchorEnum docAnchorEnum;
+
+
+ /**
+ * 根据书签的排序字段进行排序
+ * @param bookmark the object to be compared.
+ */
+ @Override
+ public int compareTo(Bookmark bookmark) {
+ return Integer.compare(this.docAnchorEnum.getSort(), bookmark.docAnchorEnum.getSort());
+ }
+}
diff --git a/detection/src/main/java/com/njcn/gather/report/service/impl/PqReportServiceImpl.java b/detection/src/main/java/com/njcn/gather/report/service/impl/PqReportServiceImpl.java
index 04db917a..5f79ab45 100644
--- a/detection/src/main/java/com/njcn/gather/report/service/impl/PqReportServiceImpl.java
+++ b/detection/src/main/java/com/njcn/gather/report/service/impl/PqReportServiceImpl.java
@@ -1,5 +1,6 @@
package com.njcn.gather.report.service.impl;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
@@ -28,18 +29,24 @@ import com.njcn.gather.plan.service.IAdPlanService;
import com.njcn.gather.pojo.enums.DetectionResponseEnum;
import com.njcn.gather.report.mapper.PqReportMapper;
import com.njcn.gather.report.pojo.DevReportParam;
-import com.njcn.gather.report.pojo.enums.ReportResponseEnum;
+import com.njcn.gather.report.pojo.constant.PowerConstant;
+import com.njcn.gather.report.pojo.constant.ReportConstant;
+import com.njcn.gather.report.pojo.enums.*;
import com.njcn.gather.report.pojo.param.ReportParam;
import com.njcn.gather.report.pojo.po.CellEntity;
import com.njcn.gather.report.pojo.po.PqReport;
+import com.njcn.gather.report.pojo.result.SingleTestResult;
+import com.njcn.gather.report.pojo.vo.Bookmark;
import com.njcn.gather.report.pojo.vo.PqReportVO;
import com.njcn.gather.report.service.IPqReportService;
+import com.njcn.gather.report.utils.Docx4jUtil;
import com.njcn.gather.report.utils.WordUtil;
import com.njcn.gather.result.pojo.param.ResultParam;
import com.njcn.gather.result.pojo.vo.ResultVO;
import com.njcn.gather.result.service.IResultService;
import com.njcn.gather.script.pojo.po.PqScriptCheckData;
import com.njcn.gather.script.pojo.po.PqScriptDtls;
+import com.njcn.gather.script.pojo.vo.PqScriptDtlDataVO;
import com.njcn.gather.script.service.IPqScriptCheckDataService;
import com.njcn.gather.script.service.IPqScriptDtlsService;
import com.njcn.gather.storage.pojo.param.SingleNonHarmParam;
@@ -56,22 +63,25 @@ import com.njcn.gather.system.dictionary.service.IDictTreeService;
import com.njcn.gather.system.pojo.enums.DicDataEnum;
import com.njcn.gather.type.pojo.po.DevType;
import com.njcn.gather.type.service.IDevTypeService;
-import com.njcn.gather.user.user.pojo.po.SysUser;
import com.njcn.gather.user.user.service.ISysUserService;
import com.njcn.web.factory.PageFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
+import org.docx4j.jaxb.Context;
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
+import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
+import org.docx4j.wml.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBElement;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
@@ -229,10 +239,9 @@ public class PqReportServiceImpl extends ServiceImpl i
// 删除对应的文件
this.deleteFile(ids);
- boolean result = this.lambdaUpdate().in(CollectionUtil.isNotEmpty(ids), PqReport::getId, ids)
+ return this.lambdaUpdate().in(CollectionUtil.isNotEmpty(ids), PqReport::getId, ids)
.set(PqReport::getState, DataStateEnum.DELETED.getCode())
.update();
- return result;
}
@Override
@@ -497,62 +506,76 @@ public class PqReportServiceImpl extends ServiceImpl i
@Override
public void generateReport(DevReportParam devReportParam) {
AdPlan plan = adPlanService.getById(devReportParam.getPlanId());
- if (StrUtil.isNotBlank(plan.getReportTemplateId())) {
+ if (plan.getAssociateReport() == 1) {
this.generateReportByPlan(plan, devReportParam);
- } else {
- // 根据设备类型找到报告模板
- PqDevVO pqDevVO = iPqDevService.getPqDevById(devReportParam.getDevId());
- if (Objects.isNull(pqDevVO)) {
- throw new BusinessException("请检查装置是否存在!");
- }
- // 获取设备型号
- DevType devType = devTypeService.getById(pqDevVO.getDevType());
- if (Objects.isNull(devType)) {
- throw new BusinessException("设备类型缺失,请联系管理员!");
- }
- DictData reportName = devTypeService.getReportName(pqDevVO.getDevType());
- if (Objects.isNull(reportName)) {
- throw new BusinessException("报告模板缺失,请联系管理员!");
- }
- // 读取模板文件
- ClassPathResource resource = new ClassPathResource("/model/" + reportName.getCode() + ".docx");
- try (InputStream inputStream = resource.getInputStream()) {
- // 加载Word文档
- XWPFDocument baseModelDocument = new XWPFDocument(inputStream);
- // 处理基础模版中的信息
- dealBaseModel(baseModelDocument, pqDevVO, devType);
- // 处理数据页中的信息
- dealDataModel(baseModelDocument, devReportParam, pqDevVO);
- // 处理需要输出的目录地址 基础路径+设备类型+装置编号.docx
- // 最终文件输出的路径
- String dirPath = reportPath.concat(File.separator).concat(devType.getName());
- ensureDirectoryExists(dirPath); // 确保目录存在
- FileOutputStream out = new FileOutputStream(dirPath.concat(File.separator).concat(pqDevVO.getCreateId()).concat(".docx"));
- // 4. 保存新的Word文档
- try {
- baseModelDocument.write(out);
- } catch (IOException e) {
- throw new BusinessException("生成报告文件失败");
- }
- out.close();
+ } else if (plan.getAssociateReport() == 0) {
+ this.generateReportByDevType(plan, devReportParam);
+ }
+ }
- System.out.println("报告生成成功!");
- this.updateDevAndPlanState(devReportParam.getDevId(), devReportParam.getPlanId());
+ /**
+ * 根据设备类型生成报告
+ * 注:该方法目前仅支持楼下出厂检测场景,属于模板占位符替换方式,后期可能会有调整
+ *
+ * @param plan 计划信息
+ * @param devReportParam 被检设备信息
+ */
+ private void generateReportByDevType(AdPlan plan, DevReportParam devReportParam) {
+ // 根据设备类型找到报告模板
+ PqDevVO pqDevVO = iPqDevService.getPqDevById(devReportParam.getDevId());
+ if (Objects.isNull(pqDevVO)) {
+ throw new BusinessException(ReportResponseEnum.DEVICE_NOT_EXIST);
+ }
+ // 获取设备型号
+ DevType devType = devTypeService.getById(pqDevVO.getDevType());
+ if (Objects.isNull(devType)) {
+ throw new BusinessException(ReportResponseEnum.DEVICE_TYPE_NOT_EXIST);
+ }
+ DictData reportName = devTypeService.getReportName(pqDevVO.getDevType());
+ if (Objects.isNull(reportName)) {
+ throw new BusinessException(ReportResponseEnum.REPORT_TEMPLATE_NOT_EXIST);
+ }
+ // 读取模板文件
+ ClassPathResource resource = new ClassPathResource("/model/" + reportName.getCode() + ReportConstant.DOCX);
+ try (InputStream inputStream = resource.getInputStream()) {
+ // 加载Word文档
+ XWPFDocument baseModelDocument = new XWPFDocument(inputStream);
+ // 处理基础模版中的信息
+ Map baseModelDataMap = dealBaseModelData(pqDevVO, devType, "${", "}");
+ // 替换模板中的信息,避免信息丢失,段落和表格均参与替换
+ WordUtil.replacePlaceholders(baseModelDocument, baseModelDataMap);
+ // 处理数据页中的信息
+ dealDataModel(baseModelDocument, devReportParam, pqDevVO);
+ // 处理需要输出的目录地址 基础路径+设备类型+装置编号.docx
+ // 最终文件输出的路径
+ String dirPath = reportPath.concat(File.separator).concat(devType.getName());
+ // 确保目录存在
+ ensureDirectoryExists(dirPath);
+ FileOutputStream out = new FileOutputStream(dirPath.concat(File.separator).concat(pqDevVO.getCreateId()).concat(".docx"));
+ // 4. 保存新的Word文档
+ try {
+ baseModelDocument.write(out);
} catch (IOException e) {
- log.error("生成报告文件失败", e);
- throw new RuntimeException(e);
+ throw new BusinessException(ReportResponseEnum.GENERATE_REPORT_ERROR);
}
+ out.close();
+
+ this.updateDevAndPlanState(devReportParam.getDevId(), devReportParam.getPlanId());
+ } catch (IOException e) {
+ log.error(ReportResponseEnum.GENERATE_REPORT_ERROR.getMessage(), e);
+ throw new BusinessException(ReportResponseEnum.GENERATE_REPORT_ERROR);
}
}
/**
* 根据计划绑定的报告模板生成报告
+ * 注:该方法目前属于同用信息占位符替换,数据页为面向对象动态填充拼凑方式
*
- * @param plan
- * @param devReportParam
+ * @param plan 计划信息
+ * @param devReportParam 设备信息
*/
private void generateReportByPlan(AdPlan plan, DevReportParam devReportParam) {
- // 根据设备类型找到报告模板
+ // 准备被检设备的基础信息
PqDevVO pqDevVO = iPqDevService.getPqDevById(devReportParam.getDevId());
if (Objects.isNull(pqDevVO)) {
throw new BusinessException(ReportResponseEnum.DEVICE_NOT_EXIST);
@@ -566,41 +589,397 @@ public class PqReportServiceImpl extends ServiceImpl i
if (Objects.isNull(report)) {
throw new BusinessException(ReportResponseEnum.REPORT_TEMPLATE_NOT_EXIST);
}
-
- FileSystemResource resource = new FileSystemResource(report.getBasePath());
- try (InputStream inputStream = resource.getInputStream()) {
- // 加载Word文档
- XWPFDocument baseModelDocument = new XWPFDocument(inputStream);
- // 处理基础模版中的信息
- dealBaseModel(baseModelDocument, pqDevVO, devType);
- // 处理数据页中的信息
- dealDataModelZJ(baseModelDocument, devReportParam, pqDevVO);
- // 处理需要输出的目录地址 基础路径+设备类型+装置编号.docx
- // 最终文件输出的路径
+ try {
+ WordprocessingMLPackage baseModelDocument = WordprocessingMLPackage.load(new File(report.getBasePath()));
+ WordprocessingMLPackage detailModelDocument = WordprocessingMLPackage.load(new File(report.getDetailPath()));
+ // 获取文档基础部分,并替换占位符
+ MainDocumentPart baseDocumentPart = baseModelDocument.getMainDocumentPart();
+ Map baseModelDataMap = dealBaseModelData(pqDevVO, devType, "", "");
+ baseDocumentPart.variableReplace(baseModelDataMap);
+ // 获取数据模版页内容,根据脚本动态组装数据页内容
+ MainDocumentPart detailDocumentPart = detailModelDocument.getMainDocumentPart();
+ dealDataModelScattered(baseDocumentPart, detailDocumentPart, devReportParam, pqDevVO);
+ // 保存新的文档
String dirPath = reportPath.concat(File.separator).concat(devType.getName());
- ensureDirectoryExists(dirPath); // 确保目录存在
- FileOutputStream out = new FileOutputStream(dirPath.concat(File.separator).concat(pqDevVO.getCreateId()).concat(".docx"));
- // 4. 保存新的Word文档
- try {
- baseModelDocument.write(out);
- } catch (IOException e) {
- throw new BusinessException("生成报告文件失败");
- }
- out.close();
-
- System.out.println("报告生成成功!");
-
- this.updateDevAndPlanState(devReportParam.getDevId(), devReportParam.getPlanId());
- } catch (IOException e) {
- log.error("生成报告文件失败", e);
- throw new RuntimeException(e);
+ // 确保目录存在
+ ensureDirectoryExists(dirPath);
+ baseModelDocument.save(new File(dirPath.concat(File.separator).concat(pqDevVO.getCreateId()).concat(ReportConstant.DOCX)));
+ } catch (Exception e) {
+ log.error(ReportResponseEnum.GENERATE_REPORT_ERROR.getMessage(), e);
+ throw new BusinessException(ReportResponseEnum.GENERATE_REPORT_ERROR);
}
}
+ /**
+ * 通用基础信息文档里可能会存在的书签锚点
+ * 1、目录信息
+ * 2、准确度测试详情
+ * 3、测试结果页
+ * 上述3个锚点位置不固定,可能结果页在通用信息中间,也有可能在文档最末端。
+ * 注:当存在目录信息时,目录最后生成。
+ *
+ * @param baseDocumentPart 通用信息文档
+ * @param detailDocumentPart 数据项模板文档
+ * @param devReportParam 测试报告参数
+ * @param pqDevVO 被检设备
+ */
+ private void dealDataModelScattered(MainDocumentPart baseDocumentPart, MainDocumentPart detailDocumentPart, DevReportParam devReportParam, PqDevVO pqDevVO) {
+ // 查找 base 文档中所有以#{开始的书签所在的段落,并收集整理
+ List