优化部分代码
This commit is contained in:
@@ -76,6 +76,21 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.docx4j/docx4j -->
|
<!-- https://mvnrepository.com/artifact/org.docx4j/docx4j -->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.docx4j</groupId>-->
|
||||||
|
<!-- <artifactId>docx4j-core</artifactId>-->
|
||||||
|
<!-- <version>8.3.8</version>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.xml.bind</groupId>
|
||||||
|
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||||
|
<version>2.3.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jaxb</groupId>
|
||||||
|
<artifactId>jaxb-runtime</artifactId>
|
||||||
|
<version>2.3.3</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.docx4j</groupId>
|
<groupId>org.docx4j</groupId>
|
||||||
<artifactId>docx4j</artifactId>
|
<artifactId>docx4j</artifactId>
|
||||||
|
|||||||
@@ -30,8 +30,9 @@ public enum BaseReportKeyEnum {
|
|||||||
MONTH("month","月份"),
|
MONTH("month","月份"),
|
||||||
DAY("day","日"),
|
DAY("day","日"),
|
||||||
YEAR_MONTH_DAY("year-month-day","年-月-日"),
|
YEAR_MONTH_DAY("year-month-day","年-月-日"),
|
||||||
TEMPERATURE("temperature","温度"),
|
TEMPERATURE("temp","温度"),
|
||||||
HUMIDITY("humidity","相对湿度");
|
HUMIDITY("hum","相对湿度"),
|
||||||
|
DELEGATE("delegate","委托方");
|
||||||
|
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.njcn.gather.report.pojo.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hongawen
|
||||||
|
* @version 1.0
|
||||||
|
* @data 2025/5/22 9:46
|
||||||
|
*/
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计文档锚点类型
|
||||||
|
*
|
||||||
|
* @author hongawen
|
||||||
|
* @version 1.0
|
||||||
|
* @data 2025/3/24 18:42
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum BookmarkEnum {
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
BookmarkEnum(String key, String desc, Integer sort) {
|
||||||
|
this.key = key;
|
||||||
|
this.desc = desc;
|
||||||
|
this.sort = sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key找到适配的枚举
|
||||||
|
*
|
||||||
|
* @param key 枚举的key
|
||||||
|
* @return 匹配的枚举实例,如果没有找到则返回null
|
||||||
|
*/
|
||||||
|
public static BookmarkEnum getByKey(String key) {
|
||||||
|
for (BookmarkEnum bookmarkEnum : BookmarkEnum.values()) {
|
||||||
|
if (bookmarkEnum.getKey().equalsIgnoreCase(key)) {
|
||||||
|
return bookmarkEnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,9 +16,9 @@ public enum PowerIndexEnum {
|
|||||||
FREQ("FREQ", "频率"),
|
FREQ("FREQ", "频率"),
|
||||||
V("V", "电压"),
|
V("V", "电压"),
|
||||||
I("I", "电流"),
|
I("I", "电流"),
|
||||||
IMBV("IMBV", "三相电压不平衡度"),
|
IMBV("IMBV", "负序电压不平衡度"),
|
||||||
IMBA("IMBA", "三相电流不平衡度"),
|
IMBA("IMBA", "负序电流不平衡度"),
|
||||||
F("F", "闪变"),
|
F("F", "短时电压闪变"),
|
||||||
HP("HP", "谐波有功功率"),
|
HP("HP", "谐波有功功率"),
|
||||||
HV("HV", "谐波电压"),
|
HV("HV", "谐波电压"),
|
||||||
HI("HI", "谐波电流"),
|
HI("HI", "谐波电流"),
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import com.njcn.gather.report.pojo.result.SingleTestResult;
|
|||||||
import com.njcn.gather.report.pojo.vo.Bookmark;
|
import com.njcn.gather.report.pojo.vo.Bookmark;
|
||||||
import com.njcn.gather.report.pojo.vo.PqReportVO;
|
import com.njcn.gather.report.pojo.vo.PqReportVO;
|
||||||
import com.njcn.gather.report.service.IPqReportService;
|
import com.njcn.gather.report.service.IPqReportService;
|
||||||
|
import com.njcn.gather.report.utils.BookmarkUtil;
|
||||||
import com.njcn.gather.report.utils.Docx4jUtil;
|
import com.njcn.gather.report.utils.Docx4jUtil;
|
||||||
import com.njcn.gather.report.utils.WordUtil;
|
import com.njcn.gather.report.utils.WordUtil;
|
||||||
import com.njcn.gather.result.service.IResultService;
|
import com.njcn.gather.result.service.IResultService;
|
||||||
@@ -71,10 +72,14 @@ import com.njcn.web.factory.PageFactory;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.poi.xwpf.usermodel.*;
|
import org.apache.poi.xwpf.usermodel.*;
|
||||||
|
import org.docx4j.TraversalUtil;
|
||||||
|
import org.docx4j.finders.RangeFinder;
|
||||||
import org.docx4j.jaxb.Context;
|
import org.docx4j.jaxb.Context;
|
||||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||||
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
||||||
import org.docx4j.wml.*;
|
import org.docx4j.wml.*;
|
||||||
|
import org.docx4j.wml.CTBookmark;
|
||||||
|
import org.docx4j.wml.Document;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -611,7 +616,8 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
baseDocumentPart.variableReplace(baseModelDataMap);
|
baseDocumentPart.variableReplace(baseModelDataMap);
|
||||||
// 获取数据模版页内容,根据脚本动态组装数据页内容
|
// 获取数据模版页内容,根据脚本动态组装数据页内容
|
||||||
MainDocumentPart detailDocumentPart = detailModelDocument.getMainDocumentPart();
|
MainDocumentPart detailDocumentPart = detailModelDocument.getMainDocumentPart();
|
||||||
dealDataModelScattered(baseDocumentPart, detailDocumentPart, devReportParam, pqDevVO);
|
// dealDataModelScattered(baseDocumentPart, detailDocumentPart, devReportParam, pqDevVO);
|
||||||
|
dealDataModelScatteredByBookmark(baseDocumentPart, detailDocumentPart, devReportParam, pqDevVO);
|
||||||
// 保存新的文档
|
// 保存新的文档
|
||||||
String dirPath = reportPath.concat(File.separator).concat(devType.getName());
|
String dirPath = reportPath.concat(File.separator).concat(devType.getName());
|
||||||
// 确保目录存在
|
// 确保目录存在
|
||||||
@@ -626,6 +632,107 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过提前在模板文档里埋下书签
|
||||||
|
* 1、目录信息
|
||||||
|
* 2、准确度测试详情
|
||||||
|
* 3、测试结果页
|
||||||
|
* 上述3个锚点位置不固定,可能结果页在通用信息中间,也有可能在文档最末端。
|
||||||
|
* 注:当存在目录信息时,目录最后生成。
|
||||||
|
*
|
||||||
|
* @param baseDocumentPart 通用信息文档
|
||||||
|
* @param detailDocumentPart 数据项模板文档
|
||||||
|
* @param devReportParam 测试报告参数
|
||||||
|
* @param pqDevVO 被检设备
|
||||||
|
*/
|
||||||
|
private void dealDataModelScatteredByBookmark(MainDocumentPart baseDocumentPart, MainDocumentPart detailDocumentPart, DevReportParam devReportParam, PqDevVO pqDevVO) {
|
||||||
|
// 查找 base 文档中所有书签
|
||||||
|
List<BookmarkUtil.BookmarkInfo> bookmarks = BookmarkUtil.findAllBookmarks(baseDocumentPart);
|
||||||
|
if (CollUtil.isNotEmpty(bookmarks)) {
|
||||||
|
// 转换为枚举,便于排序,防止结论性的书签在文档的前面
|
||||||
|
List<BookmarkEnum> bookmarkEnums = new ArrayList<>();
|
||||||
|
for (BookmarkUtil.BookmarkInfo info : bookmarks) {
|
||||||
|
String name = info.bookmark.getName();
|
||||||
|
BookmarkEnum bookmarkEnum = BookmarkEnum.getByKey(name);
|
||||||
|
if (Objects.nonNull(bookmarkEnum)) {
|
||||||
|
bookmarkEnums.add(bookmarkEnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 从结构上分析,处理的顺序:
|
||||||
|
* 1、数据项
|
||||||
|
* 2、结果信息
|
||||||
|
* 3、目录信息
|
||||||
|
* 所以要先先获取的书签进行操作排序
|
||||||
|
* */
|
||||||
|
Collections.sort(bookmarkEnums);
|
||||||
|
// 定义个结果,以便存在结果信息的书签
|
||||||
|
Map<String/*指标名称*/, List<Boolean/*以回路的顺序填充结果*/>> resultMap = new HashMap<>();
|
||||||
|
List<Object> todoInsertList = new ArrayList<>();
|
||||||
|
BookmarkUtil.BookmarkInfo bookmarkInfo = null;
|
||||||
|
// 书签在文档的位置
|
||||||
|
for (int i = 0; i < bookmarkEnums.size(); i++) {
|
||||||
|
BookmarkEnum bookmarkEnum = bookmarkEnums.get(i);
|
||||||
|
switch (bookmarkEnum) {
|
||||||
|
case DATA_LINE:
|
||||||
|
// 获取标签信息
|
||||||
|
bookmarkInfo = BookmarkUtil.getBookmarkInfo(BookmarkEnum.DATA_LINE.getKey(), bookmarks);
|
||||||
|
todoInsertList = dealDataLine(detailDocumentPart, devReportParam, pqDevVO, resultMap);
|
||||||
|
if (Objects.nonNull(bookmarkInfo) && CollectionUtil.isNotEmpty(todoInsertList)) {
|
||||||
|
BookmarkUtil.insertElement(bookmarkInfo, todoInsertList);
|
||||||
|
BookmarkUtil.removeBookmark(bookmarkInfo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DATA_SCRIPT:
|
||||||
|
break;
|
||||||
|
case TEST_RESULT_DEV:
|
||||||
|
// 判断是否已经处理过数据了,有了结论性的描述
|
||||||
|
if (CollUtil.isEmpty(resultMap)) {
|
||||||
|
dealDataLine(baseDocumentPart, devReportParam, pqDevVO, resultMap);
|
||||||
|
}
|
||||||
|
bookmarkInfo = BookmarkUtil.getBookmarkInfo(BookmarkEnum.TEST_RESULT_DEV.getKey(), bookmarks);
|
||||||
|
todoInsertList = dealTestResultLine(baseDocumentPart, detailDocumentPart, devReportParam, resultMap, DocAnchorEnum.TEST_RESULT_DEV);
|
||||||
|
if (Objects.nonNull(bookmarkInfo) && CollectionUtil.isNotEmpty(todoInsertList)) {
|
||||||
|
BookmarkUtil.insertElement(bookmarkInfo, todoInsertList);
|
||||||
|
BookmarkUtil.removeBookmark(bookmarkInfo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TEST_RESULT_LINE:
|
||||||
|
// 判断是否已经处理过数据了,有了结论性的描述
|
||||||
|
if (CollUtil.isEmpty(resultMap)) {
|
||||||
|
dealDataLine(baseDocumentPart, devReportParam, pqDevVO, resultMap);
|
||||||
|
}
|
||||||
|
bookmarkInfo = BookmarkUtil.getBookmarkInfo(BookmarkEnum.TEST_RESULT_LINE.getKey(), bookmarks);
|
||||||
|
todoInsertList = dealTestResultLine(baseDocumentPart, detailDocumentPart, devReportParam, resultMap, DocAnchorEnum.TEST_RESULT_LINE);
|
||||||
|
if (Objects.nonNull(bookmarkInfo) && CollectionUtil.isNotEmpty(todoInsertList)) {
|
||||||
|
BookmarkUtil.insertElement(bookmarkInfo, todoInsertList);
|
||||||
|
BookmarkUtil.removeBookmark(bookmarkInfo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TEST_RESULT_DETAIL:
|
||||||
|
// 判断是否已经处理过数据了,有了结论性的描述
|
||||||
|
if (CollUtil.isEmpty(resultMap)) {
|
||||||
|
dealDataLine(baseDocumentPart, devReportParam, pqDevVO, resultMap);
|
||||||
|
}
|
||||||
|
bookmarkInfo = BookmarkUtil.getBookmarkInfo(BookmarkEnum.TEST_RESULT_LINE.getKey(), bookmarks);
|
||||||
|
todoInsertList = dealTestResultLine(baseDocumentPart, detailDocumentPart, devReportParam, resultMap, DocAnchorEnum.TEST_RESULT_DETAIL);
|
||||||
|
if (Objects.nonNull(bookmarkInfo) && CollectionUtil.isNotEmpty(todoInsertList)) {
|
||||||
|
BookmarkUtil.insertElement(bookmarkInfo, todoInsertList);
|
||||||
|
BookmarkUtil.removeBookmark(bookmarkInfo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CATALOG:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用基础信息文档里可能会存在的书签锚点
|
* 通用基础信息文档里可能会存在的书签锚点
|
||||||
* 1、目录信息
|
* 1、目录信息
|
||||||
@@ -728,7 +835,7 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
ObjectFactory factory = Context.getWmlObjectFactory();
|
ObjectFactory factory = Context.getWmlObjectFactory();
|
||||||
// 结论
|
// 结论
|
||||||
P newParagraph = factory.createP();
|
P newParagraph = factory.createP();
|
||||||
Docx4jUtil.createTitle(factory, newParagraph, "检测结论", 28, true);
|
Docx4jUtil.createTitle(factory, newParagraph, "检测结论", 24, true);
|
||||||
//插入段落
|
//插入段落
|
||||||
paragraphs.add(position++, newParagraph);
|
paragraphs.add(position++, newParagraph);
|
||||||
// 源文档的内容
|
// 源文档的内容
|
||||||
@@ -757,8 +864,10 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
List<Integer> centerFlag = new ArrayList<>();
|
||||||
|
centerFlag.add(0);
|
||||||
|
Tr titleRow = Docx4jUtil.createCustomRow(factory, title, "Arial", "宋体", 21, true, centerFlag);
|
||||||
|
|
||||||
Tr titleRow = Docx4jUtil.createCustomRow(factory, title, "SimSun", "宋体", 21, true, false);
|
|
||||||
table.getContent().add(titleRow);
|
table.getContent().add(titleRow);
|
||||||
// 处理业务数据
|
// 处理业务数据
|
||||||
resultMap.forEach((key, value) -> {
|
resultMap.forEach((key, value) -> {
|
||||||
@@ -790,7 +899,7 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Tr tempRow = Docx4jUtil.createCustomRow(factory, cellValues, "SimSun", "宋体", 21, false, false);
|
Tr tempRow = Docx4jUtil.createCustomRow(factory, cellValues, "Arial", "宋体", 21, false, centerFlag);
|
||||||
table.getContent().add(tempRow);
|
table.getContent().add(tempRow);
|
||||||
});
|
});
|
||||||
TblPr tblPr = Docx4jUtil.getTblPr(factory);
|
TblPr tblPr = Docx4jUtil.getTblPr(factory);
|
||||||
@@ -807,6 +916,103 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如何处理结果性数据进文档,各省级平台的结果表格不一致,如何做到一致
|
||||||
|
*
|
||||||
|
* @param baseDocumentPart 基础模板文档
|
||||||
|
* @param detailDocumentPart 数据模板文档
|
||||||
|
* @param resultMap 各测试项的结果
|
||||||
|
*/
|
||||||
|
private List<Object> dealTestResultLine(MainDocumentPart baseDocumentPart, MainDocumentPart detailDocumentPart, DevReportParam devReportParam, Map<String, List<Boolean>> resultMap, DocAnchorEnum docAnchorEnum) {
|
||||||
|
List<Object> todoInsertList = new ArrayList<>();
|
||||||
|
// 先判断数据有没有,如果没有,则不处理
|
||||||
|
if (CollUtil.isEmpty(resultMap.get(PowerIndexEnum.UNKNOWN.getKey()))) {
|
||||||
|
ObjectFactory factory = Context.getWmlObjectFactory();
|
||||||
|
// 源文档的内容
|
||||||
|
// 创建表格(示例为3列,列数可任意调整)
|
||||||
|
Tbl table = factory.createTbl();
|
||||||
|
List<List<Boolean>> tempResultList = new ArrayList<>(resultMap.values());
|
||||||
|
int lineNum = tempResultList.get(0).size();
|
||||||
|
// 处理表头
|
||||||
|
List<String> title = new ArrayList<>();
|
||||||
|
title.add("检测项目");
|
||||||
|
switch (docAnchorEnum) {
|
||||||
|
case TEST_RESULT_DEV:
|
||||||
|
title.add("结论");
|
||||||
|
break;
|
||||||
|
case TEST_RESULT_LINE:
|
||||||
|
for (int i = 1; i < lineNum + 1; i++) {
|
||||||
|
title.add("测量回路" + i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TEST_RESULT_DETAIL:
|
||||||
|
for (int i = 1; i < lineNum + 1; i++) {
|
||||||
|
title.add("测量回路" + i);
|
||||||
|
}
|
||||||
|
title.add("结论");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
List<Integer> centerFlag = new ArrayList<>();
|
||||||
|
centerFlag.add(0);
|
||||||
|
Tr titleRow = Docx4jUtil.createCustomRow(factory, title, "Arial", "宋体", 21, true, centerFlag);
|
||||||
|
table.getContent().add(titleRow);
|
||||||
|
|
||||||
|
// 处理业务数据
|
||||||
|
List<PqScriptDtlDataVO> pqScriptDtlsList = pqScriptDtlsService.getScriptDtlsDataList(devReportParam.getScriptId());
|
||||||
|
pqScriptDtlsList.sort(Comparator.comparing(PqScriptDtlDataVO::getScriptIndex));
|
||||||
|
Set<String> scriptCodeSet = new HashSet<>();
|
||||||
|
for (PqScriptDtlDataVO pqScriptDtlDataVO : pqScriptDtlsList) {
|
||||||
|
String scriptCode = pqScriptDtlDataVO.getScriptCode();
|
||||||
|
if (scriptCodeSet.contains(scriptCode)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
scriptCodeSet.add(scriptCode);
|
||||||
|
}
|
||||||
|
List<Boolean> value = resultMap.get(scriptCode);
|
||||||
|
List<String> cellValues = new ArrayList<>();
|
||||||
|
PowerIndexEnum indexEnum = PowerIndexEnum.getByKey(scriptCode);
|
||||||
|
if (indexEnum != null) {
|
||||||
|
if (scriptCode.equals(PowerIndexEnum.VOLTAGE.getKey())) {
|
||||||
|
cellValues.add(indexEnum.getDesc());
|
||||||
|
} else {
|
||||||
|
cellValues.add(indexEnum.getDesc().concat("测量准确度"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cellValues.add(PowerIndexEnum.UNKNOWN.getDesc().concat("测量准确度"));
|
||||||
|
}
|
||||||
|
// 判断是否有不合格的
|
||||||
|
List<Boolean> totalValue = value.stream().filter(item -> !item).collect(Collectors.toList());
|
||||||
|
String total = !totalValue.isEmpty() ? "不合格" : "合格";
|
||||||
|
switch (docAnchorEnum) {
|
||||||
|
case TEST_RESULT_DEV:
|
||||||
|
cellValues.add(total);
|
||||||
|
break;
|
||||||
|
case TEST_RESULT_LINE:
|
||||||
|
for (int i = 0; i < value.size(); i++) {
|
||||||
|
cellValues.add(value.get(i) ? "合格" : "不合格");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TEST_RESULT_DETAIL:
|
||||||
|
for (int i = 0; i < value.size(); i++) {
|
||||||
|
cellValues.add(value.get(i) ? "合格" : "不合格");
|
||||||
|
}
|
||||||
|
cellValues.add(total);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Tr tempRow = Docx4jUtil.createCustomRow(factory, cellValues, "Arial", "宋体", 21, false, centerFlag);
|
||||||
|
table.getContent().add(tempRow);
|
||||||
|
}
|
||||||
|
TblPr tblPr = Docx4jUtil.getTblPr(factory);
|
||||||
|
table.setTblPr(tblPr);
|
||||||
|
todoInsertList.add(table);
|
||||||
|
}
|
||||||
|
return todoInsertList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理以回路为维度的数据项
|
* 处理以回路为维度的数据项
|
||||||
@@ -895,6 +1101,87 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理以回路为维度的数据项,书签占位符的方式
|
||||||
|
*
|
||||||
|
* @param detailModelDocument 数据项模板
|
||||||
|
* @param devReportParam 测试报告参数
|
||||||
|
* @param pqDevVO 被检设备
|
||||||
|
*/
|
||||||
|
private List<Object> dealDataLine(MainDocumentPart detailModelDocument, DevReportParam devReportParam, PqDevVO pqDevVO, Map<String, List<Boolean>> resultMap) {
|
||||||
|
List<Object> todoInsertList = new ArrayList<>();
|
||||||
|
// 以回路维度处理数据项
|
||||||
|
Integer devChns = pqDevVO.getDevChns();
|
||||||
|
ObjectFactory factory = new ObjectFactory();
|
||||||
|
// 读取该计划的检测大项组装数据内容
|
||||||
|
List<PqScriptDtlDataVO> pqScriptDtlsList = pqScriptDtlsService.getScriptDtlsDataList(devReportParam.getScriptId());
|
||||||
|
Map<String, List<PqScriptDtlDataVO>> scriptMap = pqScriptDtlsList.stream().collect(Collectors.groupingBy(PqScriptDtlDataVO::getScriptCode, LinkedHashMap::new, Collectors.toList()));
|
||||||
|
List<Object> allContent = detailModelDocument.getContent();
|
||||||
|
List<Docx4jUtil.HeadingContent> headingContents = Docx4jUtil.extractHeading5Contents(allContent);
|
||||||
|
Map<String, List<Docx4jUtil.HeadingContent>> contentMap = headingContents.stream().collect(Collectors.groupingBy(Docx4jUtil.HeadingContent::getHeadingText, Collectors.toList()));
|
||||||
|
for (int i = 0; i < devChns; i++) {
|
||||||
|
// 回路标题
|
||||||
|
P titleParagraph = factory.createP();
|
||||||
|
Integer lineNo = i + 1;
|
||||||
|
Docx4jUtil.createTitle(factory, titleParagraph, "测量回路" + lineNo, 28, true);
|
||||||
|
todoInsertList.add(titleParagraph);
|
||||||
|
// 依次处理大项文档内容
|
||||||
|
Iterator<Map.Entry<String, List<PqScriptDtlDataVO>>> iterator = scriptMap.entrySet().iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<String, List<PqScriptDtlDataVO>> next = iterator.next();
|
||||||
|
String scriptCode = next.getKey();
|
||||||
|
List<PqScriptDtlDataVO> dtlScriptItemList = next.getValue();
|
||||||
|
List<Docx4jUtil.HeadingContent> tempContent = contentMap.get(scriptCode);
|
||||||
|
// 获取需要填充keys,索引0对应的段落key,索引1对应的表格key
|
||||||
|
List<List<String>> keys = Docx4jUtil.getFillKeys(tempContent);
|
||||||
|
// 段落keys值赋值
|
||||||
|
List<String> pKeys = keys.get(0);
|
||||||
|
Map<String, String> pKeyValueMap = resultService.getParagraphKeysValue(scriptCode, pKeys);
|
||||||
|
List<String> tableKeys = keys.get(1);
|
||||||
|
/* tableKeys值赋值,注:由于谐波类检测数据与非谐波检测类数据的区别,此处要做区分
|
||||||
|
* 1、谐波类每个scriptIndex对应一个Excel表格
|
||||||
|
* 2、非谐波类则是一个误差范围对应一个Excel表格
|
||||||
|
*/
|
||||||
|
SingleTestResult singleTestResult = null;
|
||||||
|
// 根据code找到名称
|
||||||
|
List<Boolean> scriptResult = resultMap.get(scriptCode);
|
||||||
|
boolean needFill = false;
|
||||||
|
if (CollUtil.isEmpty(scriptResult)) {
|
||||||
|
scriptResult = new ArrayList<>();
|
||||||
|
needFill = true;
|
||||||
|
} else if (scriptResult.size() < lineNo) {
|
||||||
|
needFill = true;
|
||||||
|
}
|
||||||
|
if (PowerConstant.TIME.contains(scriptCode)) {
|
||||||
|
// 谐波类,以scriptIndex区分
|
||||||
|
Map<Integer, List<PqScriptDtlDataVO>> scriptIndexMap = dtlScriptItemList.stream().collect(Collectors.groupingBy(PqScriptDtlDataVO::getScriptIndex));
|
||||||
|
for (List<PqScriptDtlDataVO> scriptDtlDataItem : scriptIndexMap.values()) {
|
||||||
|
singleTestResult = resultService.getFinalContent(scriptDtlDataItem, devReportParam.getPlanCode(), pqDevVO.getId(), lineNo, tableKeys);
|
||||||
|
List<Object> tempList = fillContentInTemplate(singleTestResult.getDetail(), tempContent, factory, pKeyValueMap, tableKeys);
|
||||||
|
todoInsertList.addAll(tempList);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非谐波类
|
||||||
|
singleTestResult = resultService.getFinalContent(dtlScriptItemList, devReportParam.getPlanCode(), pqDevVO.getId(), lineNo, tableKeys);
|
||||||
|
List<Object> tempList = fillContentInTemplate(singleTestResult.getDetail(), tempContent, factory, pKeyValueMap, tableKeys);
|
||||||
|
todoInsertList.addAll(tempList);
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(singleTestResult) && needFill) {
|
||||||
|
singleTestResult.setScriptCode(scriptCode);
|
||||||
|
scriptResult.add(singleTestResult.isQualified());
|
||||||
|
resultMap.put(scriptCode, scriptResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果经过一顿处理后,结果性数据集合还是空,塞个特殊数据进去,避免嵌套循环
|
||||||
|
if (CollUtil.isEmpty(resultMap)) {
|
||||||
|
resultMap.put(PowerIndexEnum.UNKNOWN.getKey(), Collections.singletonList(false));
|
||||||
|
}
|
||||||
|
return todoInsertList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将查询的所有有效数据填充到模板中
|
* 将查询的所有有效数据填充到模板中
|
||||||
*/
|
*/
|
||||||
@@ -926,20 +1213,24 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
P paragraph = (P) object;
|
P paragraph = (P) object;
|
||||||
// 获取该段落的样式
|
// 获取该段落的样式
|
||||||
RPr rPr = Docx4jUtil.getTcPrFromParagraph(paragraph);
|
RPr rPr = Docx4jUtil.getTcPrFromParagraph(paragraph);
|
||||||
|
PPr pPr = paragraph.getPPr();
|
||||||
String textFromP = Docx4jUtil.getTextFromP(paragraph);
|
String textFromP = Docx4jUtil.getTextFromP(paragraph);
|
||||||
if (StrUtil.isNotBlank(textFromP)) {
|
if (StrUtil.isNotBlank(textFromP)) {
|
||||||
|
String text = "";
|
||||||
|
if (textFromP.equalsIgnoreCase(ItemReportKeyEnum.SCRIPT_DETAIL.getKey())) {
|
||||||
|
text = value1.get(0).get(ItemReportKeyEnum.SCRIPT_DETAIL.getKey());
|
||||||
|
} else if (textFromP.startsWith(ItemReportKeyEnum.NAME.getKey())) {
|
||||||
// 如果是段落内容,渲染段落内容
|
// 如果是段落内容,渲染段落内容
|
||||||
String[] splitP = textFromP.split(StrPool.DASHED);
|
String[] splitP = textFromP.split(StrPool.DASHED);
|
||||||
String text = "";
|
|
||||||
for (String item : splitP) {
|
for (String item : splitP) {
|
||||||
if (StrUtil.isNotBlank(pKeyValueMap.get(item))) {
|
if (StrUtil.isNotBlank(pKeyValueMap.get(item))) {
|
||||||
text = text.concat(pKeyValueMap.get(item));
|
text = text.concat(pKeyValueMap.get(item));
|
||||||
} else if (item.equalsIgnoreCase(ItemReportKeyEnum.ERROR_SCOPE.getKey())) {
|
} else if (item.equalsIgnoreCase(ItemReportKeyEnum.ERROR_SCOPE.getKey())) {
|
||||||
text = text.concat("(").concat("最大允许误差:").concat(key1).concat(")");
|
text = text.concat("(").concat("最大允许误差:").concat(key1).concat(")");
|
||||||
}
|
}
|
||||||
// 目前段落只有名称+误差范围,如果有补充后续在这里加。todo...
|
|
||||||
}
|
}
|
||||||
Docx4jUtil.addPContent(factory, innerP, text, rPr);
|
}
|
||||||
|
Docx4jUtil.addPContent(factory, innerP, text, rPr,pPr);
|
||||||
}
|
}
|
||||||
//插入段落
|
//插入段落
|
||||||
paragraphs.add(position++, innerP);
|
paragraphs.add(position++, innerP);
|
||||||
@@ -978,15 +1269,13 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
// 纵向表格暂不考虑
|
// 纵向表格暂不考虑
|
||||||
}
|
}
|
||||||
// 插入段落,处理下样式
|
// 插入段落,处理下样式
|
||||||
|
|
||||||
|
|
||||||
paragraphs.add(position++, copiedTableElement);
|
paragraphs.add(position++, copiedTableElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 全部渲染完毕后,添加几个换行
|
// 全部渲染完毕后,添加几个换行
|
||||||
P p = factory.createP();
|
P p = factory.createP();
|
||||||
Docx4jUtil.addBr(factory, p, 1);
|
// Docx4jUtil.addBr(factory, p, 1);
|
||||||
paragraphs.add(position++, p);
|
// paragraphs.add(position++, p);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -996,6 +1285,116 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将查询的所有有效数据填充到集合中,待后续填充文档
|
||||||
|
*/
|
||||||
|
private List<Object> fillContentInTemplate(Map<String, List<Map<String, List<Map<String, String>>>>> finalContent, List<Docx4jUtil.HeadingContent> tempContent,
|
||||||
|
ObjectFactory factory, Map<String, String> pKeyValueMap, List<String> tableKeys) {
|
||||||
|
List<Object> todoInsertList = new ArrayList<>();
|
||||||
|
if (CollUtil.isNotEmpty(finalContent)) {
|
||||||
|
Iterator<Map.Entry<String, List<Map<String, List<Map<String, String>>>>>> iterator1 = finalContent.entrySet().iterator();
|
||||||
|
while (iterator1.hasNext()) {
|
||||||
|
Map.Entry<String, List<Map<String, List<Map<String, String>>>>> next1 = iterator1.next();
|
||||||
|
// 此处的key是影响量的文字描述
|
||||||
|
String key = next1.getKey();
|
||||||
|
List<Map<String, List<Map<String, String>>>> value = next1.getValue();
|
||||||
|
for (Map<String, List<Map<String, String>>> stringListMap : value) {
|
||||||
|
Iterator<Map.Entry<String, List<Map<String, String>>>> iterator2 = stringListMap.entrySet().iterator();
|
||||||
|
while (iterator2.hasNext()) {
|
||||||
|
Map.Entry<String, List<Map<String, String>>> next2 = iterator2.next();
|
||||||
|
// 此处的key是误差范围
|
||||||
|
String key1 = next2.getKey();
|
||||||
|
List<Map<String, String>> value1 = next2.getValue();
|
||||||
|
// 填充模板内容
|
||||||
|
if (CollUtil.isNotEmpty(tempContent)) {
|
||||||
|
// 读取该表下模板里面的内容,并动态赋值渲染文档
|
||||||
|
Docx4jUtil.HeadingContent headingContent = tempContent.get(0);
|
||||||
|
for (Object object : headingContent.getSubContent()) {
|
||||||
|
// 段落
|
||||||
|
if (object instanceof P) {
|
||||||
|
P innerP = factory.createP();
|
||||||
|
// 如果是段落,渲染段落内容
|
||||||
|
P paragraph = (P) object;
|
||||||
|
// 获取该段落的样式
|
||||||
|
RPr rPr = Docx4jUtil.getTcPrFromParagraph(paragraph);
|
||||||
|
PPr pPr = paragraph.getPPr();
|
||||||
|
String textFromP = Docx4jUtil.getTextFromP(paragraph);
|
||||||
|
if (StrUtil.isNotBlank(textFromP)) {
|
||||||
|
String text = "";
|
||||||
|
if (textFromP.equalsIgnoreCase(ItemReportKeyEnum.SCRIPT_DETAIL.getKey())) {
|
||||||
|
text = value1.get(0).get(ItemReportKeyEnum.SCRIPT_DETAIL.getKey());
|
||||||
|
System.out.println(text);
|
||||||
|
} else if (textFromP.startsWith(ItemReportKeyEnum.NAME.getKey())) {
|
||||||
|
// 如果是段落内容,渲染段落内容
|
||||||
|
String[] splitP = textFromP.split(StrPool.DASHED);
|
||||||
|
for (String item : splitP) {
|
||||||
|
if (StrUtil.isNotBlank(pKeyValueMap.get(item))) {
|
||||||
|
text = text.concat(pKeyValueMap.get(item));
|
||||||
|
} else if (item.equalsIgnoreCase(ItemReportKeyEnum.ERROR_SCOPE.getKey())) {
|
||||||
|
text = text.concat("(").concat("最大允许误差:").concat(key1).concat(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Docx4jUtil.addPContent(factory, innerP, text, rPr,pPr);
|
||||||
|
}
|
||||||
|
//插入段落
|
||||||
|
todoInsertList.add(innerP);
|
||||||
|
} else if (object instanceof JAXBElement) {
|
||||||
|
// 表格需要注意深拷贝,避免修改了原对象
|
||||||
|
JAXBElement<Tbl> temp = (JAXBElement<Tbl>) object;
|
||||||
|
JAXBElement<Tbl> copiedTableElement;
|
||||||
|
try {
|
||||||
|
copiedTableElement = Docx4jUtil.deepCopyTbl(temp);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
// 解析表格并插入对应数据,最关键的是得知道表格是横向还是纵向以及表头占了几行
|
||||||
|
Tbl tbl = copiedTableElement.getValue();
|
||||||
|
// 获取表格的行
|
||||||
|
List<Object> rows = tbl.getContent();
|
||||||
|
boolean isRow = Docx4jUtil.judgeTableCross(rows.get(0));
|
||||||
|
if (isRow) {
|
||||||
|
// 获取现有行的样式
|
||||||
|
Tr headerRow = (Tr) tbl.getContent().get(0);
|
||||||
|
// 设置表头行属性
|
||||||
|
TrPr headerTrPr = factory.createTrPr();
|
||||||
|
headerRow.setTrPr(headerTrPr);
|
||||||
|
|
||||||
|
// 获取现有行的样式
|
||||||
|
Tr existingRow = (Tr) tbl.getContent().get(rows.size() - 1);
|
||||||
|
// 获取现有样式
|
||||||
|
TrPr trPr = existingRow.getTrPr();
|
||||||
|
JAXBElement<Tc> element = (JAXBElement<Tc>) existingRow.getContent().get(0);
|
||||||
|
TcPr tcPr = element.getValue().getTcPr();
|
||||||
|
TblWidth cellWidth = factory.createTblWidth();
|
||||||
|
cellWidth.setType("dxa");
|
||||||
|
cellWidth.setW(BigInteger.valueOf(5000 / tableKeys.size()));
|
||||||
|
tcPr.setTcW(cellWidth);
|
||||||
|
tbl.getContent().remove(existingRow);
|
||||||
|
// 迭代增加行,需要填充的表格keys在tableKeys集合中
|
||||||
|
for (Map<String, String> stringStringMap : value1) {
|
||||||
|
Tr newRow = Docx4jUtil.createCustomRow(factory, stringStringMap, tableKeys, trPr, tcPr, true);
|
||||||
|
tbl.getContent().add(newRow);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 纵向表格暂不考虑
|
||||||
|
}
|
||||||
|
// 插入段落,处理下样式
|
||||||
|
todoInsertList.add(copiedTableElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 全部渲染完毕后,添加几个换行
|
||||||
|
// P p = factory.createP();
|
||||||
|
// Docx4jUtil.addBr(factory, p, 1);
|
||||||
|
// todoInsertList.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return todoInsertList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateDevAndPlanState(String devId, String planId) {
|
private void updateDevAndPlanState(String devId, String planId) {
|
||||||
// 将改设备的报告生成状态调整为已生成
|
// 将改设备的报告生成状态调整为已生成
|
||||||
@@ -1146,6 +1545,24 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
} else {
|
} else {
|
||||||
baseModelMap.put(prefix + BaseReportKeyEnum.MANUFACTURER.getKey() + suffix, StrPool.TAB);
|
baseModelMap.put(prefix + BaseReportKeyEnum.MANUFACTURER.getKey() + suffix, StrPool.TAB);
|
||||||
}
|
}
|
||||||
|
// 委托方
|
||||||
|
String delegate = pqDevVO.getDelegate();
|
||||||
|
if(StrUtil.isNotBlank(delegate)){
|
||||||
|
DictData delegateDictData = dictDataService.getDictDataById(pqDevVO.getManufacturer());
|
||||||
|
if (ObjectUtil.isNotNull(delegateDictData)) {
|
||||||
|
baseModelMap.put(prefix + BaseReportKeyEnum.DELEGATE.getKey() + suffix, dictData.getName());
|
||||||
|
} else {
|
||||||
|
baseModelMap.put(prefix + BaseReportKeyEnum.DELEGATE.getKey() + suffix, StrPool.TAB);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
baseModelMap.put(prefix + BaseReportKeyEnum.DELEGATE.getKey() + suffix, StrPool.TAB);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实验室温度
|
||||||
|
baseModelMap.put(prefix + BaseReportKeyEnum.TEMPERATURE.getKey() + suffix, Objects.isNull(pqDevVO.getTemperature()) ? StrPool.TAB : pqDevVO.getTemperature().toString());
|
||||||
|
// 实验室湿度
|
||||||
|
baseModelMap.put(prefix + BaseReportKeyEnum.TEMPERATURE.getKey() + suffix, Objects.isNull(pqDevVO.getTemperature()) ? StrPool.TAB : pqDevVO.getTemperature().toString());
|
||||||
|
|
||||||
// 样品编号
|
// 样品编号
|
||||||
baseModelMap.put(prefix + BaseReportKeyEnum.SAMPLE_ID.getKey() + suffix, StrUtil.isEmpty(pqDevVO.getSampleId()) ? StrPool.TAB : pqDevVO.getSampleId());
|
baseModelMap.put(prefix + BaseReportKeyEnum.SAMPLE_ID.getKey() + suffix, StrUtil.isEmpty(pqDevVO.getSampleId()) ? StrPool.TAB : pqDevVO.getSampleId());
|
||||||
// 收样日期
|
// 收样日期
|
||||||
@@ -2047,32 +2464,6 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
|
||||||
String path = "F:\\gitea\\fusionForce\\CN_Gather\\entrance\\src\\main\\resources\\model\\BaseDataModel.docx";
|
|
||||||
FileInputStream dataModelFis = new FileInputStream(new File(path));
|
|
||||||
XWPFDocument dataModelDocumentTemp = new XWPFDocument(dataModelFis);
|
|
||||||
Map<String, String> dataModelMap = new HashMap<>(16);
|
|
||||||
dataModelMap.put("${CreateId}", "123");
|
|
||||||
dataModelMap.put("${total}", "123");
|
|
||||||
dataModelMap.put("${count}", "1");
|
|
||||||
dataModelMap.put("${57Ua}", "123456");
|
|
||||||
dataModelMap.put("${Uha1}", "123456");
|
|
||||||
dataModelMap.put("${Uha2}", "123456");
|
|
||||||
WordUtil.replacePlaceholdersInParagraphs(dataModelDocumentTemp, dataModelMap);
|
|
||||||
WordUtil.replacePlaceholdersInTables(dataModelDocumentTemp, dataModelMap);
|
|
||||||
//最终文件输出的路径
|
|
||||||
FileOutputStream out = new FileOutputStream("C:\\Users\\hongawen\\Desktop\\testModel\\BaseDataModel" + DateUtil.format(new Date(), DatePattern.CHINESE_DATE_TIME_PATTERN) + ".docx");
|
|
||||||
// 4. 保存新的Word文档
|
|
||||||
try {
|
|
||||||
dataModelDocumentTemp.write(out);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new BusinessException("生成报告文件失败");
|
|
||||||
}
|
|
||||||
out.close();
|
|
||||||
System.out.println("报告生成成功!");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取测试小项的index
|
* 获取测试小项的index
|
||||||
* 注:测试项下发的ABCT的index均是一样的
|
* 注:测试项下发的ABCT的index均是一样的
|
||||||
|
|||||||
@@ -0,0 +1,293 @@
|
|||||||
|
package com.njcn.gather.report.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import com.njcn.gather.report.pojo.enums.BookmarkEnum;
|
||||||
|
import com.njcn.gather.report.pojo.enums.PowerIndexEnum;
|
||||||
|
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||||
|
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
||||||
|
import org.docx4j.wml.*;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBElement;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归查找所有书签,并在书签处插入内容
|
||||||
|
*/
|
||||||
|
public class BookmarkUtil {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 书签信息
|
||||||
|
*/
|
||||||
|
public static class BookmarkInfo {
|
||||||
|
public CTBookmark bookmark;
|
||||||
|
public P parentParagraph;
|
||||||
|
public ContentAccessor parentContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归查找所有书签
|
||||||
|
*/
|
||||||
|
public static List<BookmarkInfo> findAllBookmarks(ContentAccessor contentAccessor) {
|
||||||
|
List<BookmarkInfo> result = new ArrayList<>();
|
||||||
|
for (Object obj : contentAccessor.getContent()) {
|
||||||
|
Object realObj = (obj instanceof JAXBElement) ? ((JAXBElement<?>) obj).getValue() : obj;
|
||||||
|
if (realObj instanceof P) {
|
||||||
|
P p = (P) realObj;
|
||||||
|
for (Object o2 : p.getContent()) {
|
||||||
|
Object realO2 = (o2 instanceof JAXBElement) ? ((JAXBElement<?>) o2).getValue() : o2;
|
||||||
|
if (realO2 instanceof CTBookmark) {
|
||||||
|
BookmarkInfo info = new BookmarkInfo();
|
||||||
|
info.bookmark = (CTBookmark) realO2;
|
||||||
|
info.parentParagraph = p;
|
||||||
|
info.parentContainer = contentAccessor;
|
||||||
|
result.add(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (realObj instanceof ContentAccessor) {
|
||||||
|
result.addAll(findAllBookmarks((ContentAccessor) realObj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在书签后插入段落
|
||||||
|
*/
|
||||||
|
public static void insertParagraphsAfter(BookmarkInfo info, P paragraph) {
|
||||||
|
List<Object> parentContent = info.parentContainer.getContent();
|
||||||
|
int idx = parentContent.indexOf(info.parentParagraph);
|
||||||
|
parentContent.add(idx + 1, paragraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在书签后插入表格
|
||||||
|
*/
|
||||||
|
public static void insertTableAfter(BookmarkInfo info, Tbl table) {
|
||||||
|
List<Object> parentContent = info.parentContainer.getContent();
|
||||||
|
int idx = parentContent.indexOf(info.parentParagraph);
|
||||||
|
parentContent.add(idx + 1, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在书签后插入元素,可能是段落、表格、图片、书签等
|
||||||
|
*/
|
||||||
|
public static void insertElement(BookmarkInfo info, List<Object> elements) {
|
||||||
|
List<Object> parentContent = info.parentContainer.getContent();
|
||||||
|
int idx = parentContent.indexOf(info.parentParagraph);
|
||||||
|
// 遍历元素,如果是通道回路这种大标题需要新起一个空的文档页
|
||||||
|
for (int i = 0; i < elements.size(); i++) {
|
||||||
|
Object element = elements.get(i);
|
||||||
|
if (element instanceof P) {
|
||||||
|
P p = (P) element;
|
||||||
|
String textFromP = Docx4jUtil.getTextFromP(p);
|
||||||
|
if (textFromP.contains("测量回路")) {
|
||||||
|
if (!textFromP.contains("1")) {
|
||||||
|
// 另起一页
|
||||||
|
P pagePara = Docx4jUtil.getPageBreak();
|
||||||
|
idx = idx + 1;
|
||||||
|
parentContent.add(idx, pagePara);
|
||||||
|
}
|
||||||
|
idx = idx + 1;
|
||||||
|
parentContent.add(idx, p);
|
||||||
|
} else if (textFromP.startsWith(PowerIndexEnum.IMBV.getDesc())
|
||||||
|
|| textFromP.startsWith(PowerIndexEnum.HV.getDesc())
|
||||||
|
|| textFromP.startsWith(PowerIndexEnum.HI.getDesc())
|
||||||
|
|
||||||
|
) {
|
||||||
|
// 另起一页
|
||||||
|
P pagePara = Docx4jUtil.getPageBreak();
|
||||||
|
idx = idx + 1;
|
||||||
|
parentContent.add(idx, pagePara);
|
||||||
|
idx = idx + 1;
|
||||||
|
parentContent.add(idx, element);
|
||||||
|
}else if(textFromP.startsWith("注:基波电流幅值5.000A,基波频率50.0Hz,各次间谐波电流含有率均为3.0%。")){
|
||||||
|
idx = idx + 1;
|
||||||
|
parentContent.add(idx, element);
|
||||||
|
P pagePara = Docx4jUtil.getPageBreak();
|
||||||
|
idx = idx + 1;
|
||||||
|
parentContent.add(idx, pagePara);
|
||||||
|
} else {
|
||||||
|
idx = idx + 1;
|
||||||
|
parentContent.add(idx, element);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
idx = idx + 1;
|
||||||
|
parentContent.add(idx, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除文档中的空白页
|
||||||
|
* @param docx 要处理的Word文档
|
||||||
|
*/
|
||||||
|
public static void removeBlankPages(MainDocumentPart mainDocumentPart) {
|
||||||
|
// 获取文档主体
|
||||||
|
Document document = mainDocumentPart.getJaxbElement();
|
||||||
|
Body body = document.getBody();
|
||||||
|
|
||||||
|
// 获取所有段落
|
||||||
|
List<Object> paragraphs = body.getContent();
|
||||||
|
|
||||||
|
// 用于标记是否在空白页中
|
||||||
|
boolean inBlankPage = false;
|
||||||
|
// 用于存储要删除的段落
|
||||||
|
List<P> paragraphsToRemove = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Object paragraph : paragraphs) {
|
||||||
|
if (paragraph instanceof P){
|
||||||
|
P paragraphtemp = (P) paragraph;
|
||||||
|
// 检查段落是否为空
|
||||||
|
boolean isEmpty = isParagraphEmpty(paragraphtemp);
|
||||||
|
|
||||||
|
if (isEmpty) {
|
||||||
|
if (!inBlankPage) {
|
||||||
|
inBlankPage = true;
|
||||||
|
}
|
||||||
|
paragraphsToRemove.add(paragraphtemp);
|
||||||
|
} else {
|
||||||
|
inBlankPage = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除空白段落
|
||||||
|
for (P paragraph : paragraphsToRemove) {
|
||||||
|
body.getContent().remove(paragraph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查段落是否为空
|
||||||
|
* @param paragraph 要检查的段落
|
||||||
|
* @return 如果段落为空返回true,否则返回false
|
||||||
|
*/
|
||||||
|
private static boolean isParagraphEmpty(P paragraph) {
|
||||||
|
// 检查段落是否包含分节符
|
||||||
|
if (paragraph.getPPr() != null && paragraph.getPPr().getSectPr() != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查段落中的文本内容
|
||||||
|
for (Object obj : paragraph.getContent()) {
|
||||||
|
if (obj instanceof R) {
|
||||||
|
R run = (R) obj;
|
||||||
|
// 在3.3.4版本中,使用getContent()获取文本内容
|
||||||
|
for (Object runContent : run.getContent()) {
|
||||||
|
if (runContent instanceof Text) {
|
||||||
|
Text text = (Text) runContent;
|
||||||
|
if (text.getValue() != null && !text.getValue().trim().isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在插入前检查目标位置是否有分页符
|
||||||
|
*
|
||||||
|
* @param position 目标位置
|
||||||
|
* @return 是否包含分页符
|
||||||
|
*/
|
||||||
|
private static boolean hasPageBreak(Object position) {
|
||||||
|
if (position instanceof P) {
|
||||||
|
P paragraph = (P) position;
|
||||||
|
for (Object run : paragraph.getContent()) {
|
||||||
|
if (run instanceof R) {
|
||||||
|
R r = (R) run;
|
||||||
|
for (Object element : r.getContent()) {
|
||||||
|
if (element instanceof Br && ((Br) element).getType() != null
|
||||||
|
&& ((Br) element).getType().equals("page")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除书签
|
||||||
|
*
|
||||||
|
* @param bookmarkInfo 书签信息
|
||||||
|
*/
|
||||||
|
public static void removeBookmark(BookmarkUtil.BookmarkInfo bookmarkInfo) {
|
||||||
|
try {
|
||||||
|
// 获取书签所在的段落
|
||||||
|
P paragraph = bookmarkInfo.parentParagraph;
|
||||||
|
|
||||||
|
// 遍历段落内容,找到并删除书签开始和结束标记
|
||||||
|
List<Object> paragraphContent = new ArrayList<>(paragraph.getContent());
|
||||||
|
for (Object obj : paragraphContent) {
|
||||||
|
if (obj instanceof JAXBElement) {
|
||||||
|
JAXBElement<?> element = (JAXBElement<?>) obj;
|
||||||
|
Object value = element.getValue();
|
||||||
|
|
||||||
|
// 删除书签开始标记
|
||||||
|
if (value instanceof CTBookmark) {
|
||||||
|
paragraph.getContent().remove(obj);
|
||||||
|
}
|
||||||
|
// 删除书签结束标记
|
||||||
|
else if (value instanceof CTMarkupRange) {
|
||||||
|
paragraph.getContent().remove(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 ObjectFactory 创建表格
|
||||||
|
*
|
||||||
|
* @param factory ObjectFactory 实例
|
||||||
|
* @param data 二维数组,表格内容
|
||||||
|
* @return Tbl 表格对象
|
||||||
|
*/
|
||||||
|
public static Tbl createTable(ObjectFactory factory, String[][] data) {
|
||||||
|
Tbl table = factory.createTbl();
|
||||||
|
for (String[] rowData : data) {
|
||||||
|
Tr row = factory.createTr();
|
||||||
|
for (String cellData : rowData) {
|
||||||
|
Tc cell = factory.createTc();
|
||||||
|
P para = factory.createP();
|
||||||
|
R run = factory.createR();
|
||||||
|
Text text = factory.createText();
|
||||||
|
text.setValue(cellData);
|
||||||
|
run.getContent().add(text);
|
||||||
|
para.getContent().add(run);
|
||||||
|
cell.getContent().add(para);
|
||||||
|
row.getContent().add(cell);
|
||||||
|
}
|
||||||
|
table.getContent().add(row);
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定标签的标签信息
|
||||||
|
*
|
||||||
|
* @param key 标签名
|
||||||
|
* @param bookmarks 所有标签信息
|
||||||
|
*/
|
||||||
|
public static BookmarkInfo getBookmarkInfo(String key, List<BookmarkInfo> bookmarks) {
|
||||||
|
BookmarkUtil.BookmarkInfo bookmarkInfo = null;
|
||||||
|
for (BookmarkUtil.BookmarkInfo info : bookmarks) {
|
||||||
|
String name = info.bookmark.getName();
|
||||||
|
if (key.equalsIgnoreCase(name)) {
|
||||||
|
bookmarkInfo = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bookmarkInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,19 +5,12 @@ import cn.hutool.core.text.StrPool;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.njcn.gather.report.pojo.constant.ReportConstant;
|
import com.njcn.gather.report.pojo.constant.ReportConstant;
|
||||||
import com.njcn.gather.report.pojo.enums.DocAnchorEnum;
|
import com.njcn.gather.report.pojo.enums.DocAnchorEnum;
|
||||||
import com.njcn.gather.report.pojo.vo.Bookmark;
|
|
||||||
import org.docx4j.XmlUtils;
|
import org.docx4j.XmlUtils;
|
||||||
import org.docx4j.jaxb.Context;
|
|
||||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||||
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
|
||||||
import org.docx4j.wml.*;
|
import org.docx4j.wml.*;
|
||||||
|
|
||||||
import javax.xml.bind.JAXBElement;
|
import javax.xml.bind.JAXBElement;
|
||||||
import javax.xml.bind.JAXBException;
|
|
||||||
import javax.xml.bind.Marshaller;
|
|
||||||
import javax.xml.bind.Unmarshaller;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -244,13 +237,14 @@ public class Docx4jUtil {
|
|||||||
/**
|
/**
|
||||||
* 段落中添加内容
|
* 段落中添加内容
|
||||||
*/
|
*/
|
||||||
public static void addPContent(ObjectFactory factory, P paragraph, String content, RPr rPr) {
|
public static void addPContent(ObjectFactory factory, P paragraph, String content, RPr rPr,PPr ppr) {
|
||||||
R run = factory.createR();
|
R run = factory.createR();
|
||||||
Text text = factory.createText();
|
Text text = factory.createText();
|
||||||
text.setValue(content);
|
text.setValue(content);
|
||||||
run.setRPr(rPr);
|
run.setRPr(rPr);
|
||||||
run.getContent().add(text);
|
run.getContent().add(text);
|
||||||
paragraph.getContent().add(run);
|
paragraph.getContent().add(run);
|
||||||
|
paragraph.setPPr(ppr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -347,6 +341,20 @@ public class Docx4jUtil {
|
|||||||
text.setValue(value);
|
text.setValue(value);
|
||||||
run.getContent().add(text);
|
run.getContent().add(text);
|
||||||
paragraph.getContent().add(run);
|
paragraph.getContent().add(run);
|
||||||
|
// 字体
|
||||||
|
// 设置字体
|
||||||
|
RPr rPr = factory.createRPr();
|
||||||
|
RFonts rFonts = factory.createRFonts();
|
||||||
|
if (containsChinese(value)) {
|
||||||
|
rFonts.setEastAsia("宋体");
|
||||||
|
rFonts.setAscii("宋体");
|
||||||
|
rFonts.setHAnsi("宋体");
|
||||||
|
} else {
|
||||||
|
rFonts.setEastAsia("Arial");
|
||||||
|
rFonts.setAscii("Arial");
|
||||||
|
rFonts.setHAnsi("Arial");
|
||||||
|
}
|
||||||
|
rPr.setRFonts(rFonts);
|
||||||
// 设置段落居中
|
// 设置段落居中
|
||||||
if (centerFlag) {
|
if (centerFlag) {
|
||||||
PPr pPr = factory.createPPr();
|
PPr pPr = factory.createPPr();
|
||||||
@@ -356,13 +364,17 @@ public class Docx4jUtil {
|
|||||||
paragraph.setPPr(pPr);
|
paragraph.setPPr(pPr);
|
||||||
}
|
}
|
||||||
if (value.equals("不合格")) {
|
if (value.equals("不合格")) {
|
||||||
RPr rPr = factory.createRPr();
|
|
||||||
Color color = factory.createColor();
|
Color color = factory.createColor();
|
||||||
// 红色
|
// 红色
|
||||||
color.setVal("FF0000");
|
color.setVal("FF0000");
|
||||||
rPr.setColor(color);
|
rPr.setColor(color);
|
||||||
run.setRPr(rPr);
|
run.setRPr(rPr);
|
||||||
}
|
}
|
||||||
|
HpsMeasure sz = factory.createHpsMeasure();
|
||||||
|
// 10号字体 = 20 half-points
|
||||||
|
sz.setVal(new BigInteger("20"));
|
||||||
|
rPr.setSz(sz);
|
||||||
|
|
||||||
cell.getContent().add(paragraph);
|
cell.getContent().add(paragraph);
|
||||||
cell.setTcPr(tcPr);
|
cell.setTcPr(tcPr);
|
||||||
row.getContent().add(cell);
|
row.getContent().add(cell);
|
||||||
@@ -372,6 +384,24 @@ public class Docx4jUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断字符串是否包含中文
|
||||||
|
* @param str 需要判断的字符串
|
||||||
|
* @return 是否包含中文
|
||||||
|
*/
|
||||||
|
private static boolean containsChinese(String str) {
|
||||||
|
if (str == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (char c : str.toCharArray()) {
|
||||||
|
if (Character.UnicodeScript.of(c) == Character.UnicodeScript.HAN) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据已知信息创建新行
|
* 根据已知信息创建新行
|
||||||
*
|
*
|
||||||
@@ -383,9 +413,10 @@ public class Docx4jUtil {
|
|||||||
* @param boldFlag 是否加粗
|
* @param boldFlag 是否加粗
|
||||||
* @param centerFlag 是否居中
|
* @param centerFlag 是否居中
|
||||||
*/
|
*/
|
||||||
public static Tr createCustomRow(ObjectFactory factory, List<String> cellValues, String ascFontStyle,String eastFontStyle, Integer size, boolean boldFlag, boolean centerFlag) {
|
public static Tr createCustomRow(ObjectFactory factory, List<String> cellValues, String ascFontStyle, String eastFontStyle, Integer size, boolean boldFlag, List<Integer> centerFlag) {
|
||||||
Tr row = factory.createTr();
|
Tr row = factory.createTr();
|
||||||
for (String value : cellValues) {
|
for (int i = 0; i < cellValues.size(); i++) {
|
||||||
|
String value = cellValues.get(i);
|
||||||
Tc cell = factory.createTc();
|
Tc cell = factory.createTc();
|
||||||
P paragraph = factory.createP();
|
P paragraph = factory.createP();
|
||||||
R run = factory.createR();
|
R run = factory.createR();
|
||||||
@@ -394,7 +425,7 @@ public class Docx4jUtil {
|
|||||||
run.getContent().add(text);
|
run.getContent().add(text);
|
||||||
paragraph.getContent().add(run);
|
paragraph.getContent().add(run);
|
||||||
// 设置段落居中
|
// 设置段落居中
|
||||||
if (centerFlag) {
|
if (!centerFlag.contains(i)) {
|
||||||
PPr pPr = factory.createPPr();
|
PPr pPr = factory.createPPr();
|
||||||
Jc jc = factory.createJc();
|
Jc jc = factory.createJc();
|
||||||
jc.setVal(JcEnumeration.CENTER);
|
jc.setVal(JcEnumeration.CENTER);
|
||||||
@@ -408,7 +439,7 @@ public class Docx4jUtil {
|
|||||||
color.setVal("FF0000");
|
color.setVal("FF0000");
|
||||||
rPr.setColor(color);
|
rPr.setColor(color);
|
||||||
}
|
}
|
||||||
if(boldFlag){
|
if (boldFlag) {
|
||||||
BooleanDefaultTrue bold = factory.createBooleanDefaultTrue();
|
BooleanDefaultTrue bold = factory.createBooleanDefaultTrue();
|
||||||
rPr.setB(bold);
|
rPr.setB(bold);
|
||||||
}
|
}
|
||||||
@@ -425,9 +456,20 @@ public class Docx4jUtil {
|
|||||||
rPr.setSz(fontSize);
|
rPr.setSz(fontSize);
|
||||||
// 中文字号
|
// 中文字号
|
||||||
rPr.setSzCs(fontSize);
|
rPr.setSzCs(fontSize);
|
||||||
|
|
||||||
run.setRPr(rPr);
|
run.setRPr(rPr);
|
||||||
cell.getContent().add(paragraph);
|
cell.getContent().add(paragraph);
|
||||||
|
// 设置单元格边距
|
||||||
|
TcPr cellProperties = factory.createTcPr();
|
||||||
|
cell.setTcPr(cellProperties);
|
||||||
|
// 设置单元格上下边距(单位:缇)
|
||||||
|
TcMar mar = factory.createTcMar();
|
||||||
|
TblWidth top = factory.createTblWidth();
|
||||||
|
top.setW(BigInteger.valueOf(100));
|
||||||
|
mar.setTop(top);
|
||||||
|
TblWidth bottom = factory.createTblWidth();
|
||||||
|
bottom.setW(BigInteger.valueOf(100));
|
||||||
|
mar.setBottom(bottom);
|
||||||
|
cellProperties.setTcMar(mar);
|
||||||
row.getContent().add(cell);
|
row.getContent().add(cell);
|
||||||
}
|
}
|
||||||
return row;
|
return row;
|
||||||
@@ -448,7 +490,6 @@ public class Docx4jUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 存储Heading 5及其子内容的辅助类
|
// 存储Heading 5及其子内容的辅助类
|
||||||
public static class HeadingContent {
|
public static class HeadingContent {
|
||||||
private String headingText;
|
private String headingText;
|
||||||
@@ -471,6 +512,38 @@ public class Docx4jUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定书签在文档段落中的位置索引
|
||||||
|
*
|
||||||
|
* @param documentPart 主文档部分
|
||||||
|
* @param bookmarkName 书签名称
|
||||||
|
* @return 段落索引,找不到返回 -1
|
||||||
|
*/
|
||||||
|
public static int getParagraphPosition(MainDocumentPart documentPart, String bookmarkName) {
|
||||||
|
List<Object> content = documentPart.getContent();
|
||||||
|
for (int i = 0; i < content.size(); i++) {
|
||||||
|
Object obj = content.get(i);
|
||||||
|
// 只处理段落
|
||||||
|
if (obj instanceof P) {
|
||||||
|
P paragraph = (P) obj;
|
||||||
|
// 提取段落纯文本
|
||||||
|
String text = getTextFromP(paragraph).trim();
|
||||||
|
if (text.startsWith("#{") && text.endsWith("}")) {
|
||||||
|
// 提取书签名
|
||||||
|
String name = text.substring(2, text.length() - 1);
|
||||||
|
if (name.equals(bookmarkName)) {
|
||||||
|
// 返回段落索引
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 找不到返回 -1
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取段落在文档中的位置
|
* 获取段落在文档中的位置
|
||||||
*/
|
*/
|
||||||
@@ -534,4 +607,27 @@ public class Docx4jUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分页符
|
||||||
|
*/
|
||||||
|
public static P getPageBreak() {
|
||||||
|
try {
|
||||||
|
ObjectFactory factory = new ObjectFactory();
|
||||||
|
// 创建分页符
|
||||||
|
R run = factory.createR();
|
||||||
|
Br br = factory.createBr();
|
||||||
|
br.setType(STBrType.PAGE);
|
||||||
|
// 直接添加 br 对象
|
||||||
|
run.getContent().add(br);
|
||||||
|
// 创建包含分页符的段落
|
||||||
|
P pageBreakParagraph = factory.createP();
|
||||||
|
pageBreakParagraph.getContent().add(run);
|
||||||
|
return pageBreakParagraph;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1015,10 +1015,8 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
double timeDouble = Math.round(harmNum);
|
double timeDouble = Math.round(harmNum);
|
||||||
int timeInt = (int) timeDouble;
|
int timeInt = (int) timeDouble;
|
||||||
// 填充结果数据
|
// 填充结果数据
|
||||||
fillThreePhaseData(singleResult, timeInt, keyFillMap);
|
fillThreePhaseData(singleResult, timeInt, keyFillMap, scriptCode);
|
||||||
if (!keyFillMap.get(ItemReportKeyEnum.ERROR_SCOPE.getKey()).equals("/")) {
|
|
||||||
keyFillMapList.add(keyFillMap);
|
keyFillMapList.add(keyFillMap);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
if (CollUtil.isNotEmpty(keyFillMapList)) {
|
if (CollUtil.isNotEmpty(keyFillMapList)) {
|
||||||
// 按次数排序
|
// 按次数排序
|
||||||
@@ -1045,11 +1043,9 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
List<Map<String, String>> keyFillMapList = new ArrayList<>();
|
List<Map<String, String>> keyFillMapList = new ArrayList<>();
|
||||||
for (AdNonHarmonicResult adNonHarmonicResult : nonHarmList) {
|
for (AdNonHarmonicResult adNonHarmonicResult : nonHarmList) {
|
||||||
Map<String, String> keyFillMap = new HashMap<>(16);
|
Map<String, String> keyFillMap = new HashMap<>(16);
|
||||||
fillThreePhaseData(adNonHarmonicResult, null, keyFillMap);
|
fillThreePhaseData(adNonHarmonicResult, null, keyFillMap, scriptCode);
|
||||||
if (!keyFillMap.get(ItemReportKeyEnum.ERROR_SCOPE.getKey()).equals("/")) {
|
|
||||||
keyFillMapList.add(keyFillMap);
|
keyFillMapList.add(keyFillMap);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (CollUtil.isNotEmpty(keyFillMapList)) {
|
if (CollUtil.isNotEmpty(keyFillMapList)) {
|
||||||
// 需要对所有的填充进行按误差范围分组
|
// 需要对所有的填充进行按误差范围分组
|
||||||
Map<String, List<Map<String, String>>> errorScoperMap = keyFillMapList.stream()
|
Map<String, List<Map<String, String>>> errorScoperMap = keyFillMapList.stream()
|
||||||
@@ -1075,11 +1071,9 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
for (AdNonHarmonicResult adNonHarmonicResult : nonHarmList) {
|
for (AdNonHarmonicResult adNonHarmonicResult : nonHarmList) {
|
||||||
Map<String, String> keyFillMap = new HashMap<>(8);
|
Map<String, String> keyFillMap = new HashMap<>(8);
|
||||||
fillTPhaseData(adNonHarmonicResult, null, keyFillMap);
|
fillTPhaseData(adNonHarmonicResult, null, keyFillMap);
|
||||||
if (!keyFillMap.get(ItemReportKeyEnum.ERROR_SCOPE.getKey()).equals("/")) {
|
|
||||||
keyFillMapList.add(keyFillMap);
|
keyFillMapList.add(keyFillMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (CollUtil.isNotEmpty(keyFillMapList)) {
|
if (CollUtil.isNotEmpty(keyFillMapList)) {
|
||||||
// 需要对所有填充进行按误差范围分组
|
// 需要对所有填充进行按误差范围分组
|
||||||
Map<String, List<Map<String, String>>> errorScoperMap = keyFillMapList.stream()
|
Map<String, List<Map<String, String>>> errorScoperMap = keyFillMapList.stream()
|
||||||
@@ -1120,7 +1114,7 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
* @param timeInt 谐波类需要传指定次数
|
* @param timeInt 谐波类需要传指定次数
|
||||||
* @param keyFillMap 待填充的集合Map
|
* @param keyFillMap 待填充的集合Map
|
||||||
*/
|
*/
|
||||||
private void fillThreePhaseData(Object singleResult, Integer timeInt, Map<String, String> keyFillMap) {
|
private void fillThreePhaseData(Object singleResult, Integer timeInt, Map<String, String> keyFillMap, String scriptCode) {
|
||||||
DetectionData tempA = getResultData(singleResult, timeInt, PowerConstant.PHASE_A);
|
DetectionData tempA = getResultData(singleResult, timeInt, PowerConstant.PHASE_A);
|
||||||
DetectionData tempB = getResultData(singleResult, timeInt, PowerConstant.PHASE_B);
|
DetectionData tempB = getResultData(singleResult, timeInt, PowerConstant.PHASE_B);
|
||||||
DetectionData tempC = getResultData(singleResult, timeInt, PowerConstant.PHASE_C);
|
DetectionData tempC = getResultData(singleResult, timeInt, PowerConstant.PHASE_C);
|
||||||
@@ -1129,50 +1123,64 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
testA = "/", testB = "/", testC = "/",
|
testA = "/", testB = "/", testC = "/",
|
||||||
errorA = "/", errorB = "/", errorC = "/",
|
errorA = "/", errorB = "/", errorC = "/",
|
||||||
resultA = "/", resultB = "/", resultC = "/", result = "/",
|
resultA = "/", resultB = "/", resultC = "/", result = "/",
|
||||||
errorScope = "/", unit = "";
|
errorScope = "/", unit = "", scriptDetail = "/";
|
||||||
|
|
||||||
if (Objects.nonNull(tempA) && (PowerConstant.DATA_RANGE.contains(tempA.getIsData()))) {
|
if (Objects.nonNull(tempA)) {
|
||||||
standardA = PubUtils.doubleRoundStr(4, tempA.getResultData());
|
standardA = PubUtils.doubleRoundStr(4, tempA.getResultData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempA.getResultData());
|
||||||
testA = PubUtils.doubleRoundStr(4, tempA.getData());
|
testA = PubUtils.doubleRoundStr(4, tempA.getData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempA.getData());
|
||||||
|
if (Objects.nonNull(tempA.getErrorData())) {
|
||||||
errorA = PubUtils.doubleRoundStr(4, tempA.getErrorData().doubleValue());
|
errorA = PubUtils.doubleRoundStr(4, tempA.getErrorData().doubleValue());
|
||||||
resultA = tempA.getIsData() == 1 ? "合格" : "不合格";
|
|
||||||
errorScope = tempA.getRadius();
|
|
||||||
unit = tempA.getUnit();
|
|
||||||
standard = PubUtils.doubleRoundStr(4, tempA.getResultData());
|
|
||||||
}
|
}
|
||||||
if (Objects.nonNull(tempB) && (PowerConstant.DATA_RANGE.contains(tempB.getIsData()))) {
|
resultA = tempA.getIsData() == 1 ? "合格" : tempA.getIsData() == 0 ? "不合格" : "/";
|
||||||
standardB = PubUtils.doubleRoundStr(4, tempB.getResultData());
|
errorScope = tempA.getRadius() == null ? "/" : tempA.getRadius();
|
||||||
testB = PubUtils.doubleRoundStr(4, tempB.getData());
|
unit = tempA.getUnit() == null ? "" : tempA.getUnit();
|
||||||
|
standard = PubUtils.doubleRoundStr(4, tempA.getResultData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempA.getResultData());
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(tempB)) {
|
||||||
|
standardB = PubUtils.doubleRoundStr(4, tempB.getResultData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempB.getResultData());
|
||||||
|
testB = PubUtils.doubleRoundStr(4, tempB.getData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempB.getData());
|
||||||
|
if (Objects.nonNull(tempB.getErrorData())) {
|
||||||
errorB = PubUtils.doubleRoundStr(4, tempB.getErrorData().doubleValue());
|
errorB = PubUtils.doubleRoundStr(4, tempB.getErrorData().doubleValue());
|
||||||
resultB = tempB.getIsData() == 1 ? "合格" : "不合格";
|
}
|
||||||
|
resultB = tempB.getIsData() == 1 ? "合格" : tempB.getIsData() == 0 ? "不合格" : "/";
|
||||||
if (errorScope.equals("/")) {
|
if (errorScope.equals("/")) {
|
||||||
errorScope = tempB.getRadius();
|
errorScope = tempB.getRadius() == null ? "/" : tempB.getRadius();
|
||||||
}
|
}
|
||||||
if (StrUtil.isBlank(unit)) {
|
if (StrUtil.isBlank(unit)) {
|
||||||
unit = tempB.getUnit();
|
unit = tempB.getUnit() == null ? "" : tempB.getUnit();
|
||||||
}
|
}
|
||||||
if (standard.equals("/")) {
|
if (standard.equals("/")) {
|
||||||
standard = PubUtils.doubleRoundStr(4, tempB.getResultData());
|
standard = PubUtils.doubleRoundStr(4, tempB.getResultData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempB.getResultData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Objects.nonNull(tempC) && (PowerConstant.DATA_RANGE.contains(tempC.getIsData()))) {
|
if (Objects.nonNull(tempC)) {
|
||||||
standardC = PubUtils.doubleRoundStr(4, tempC.getResultData());
|
standardC = PubUtils.doubleRoundStr(4, tempC.getResultData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempC.getResultData());
|
||||||
testC = PubUtils.doubleRoundStr(4, tempC.getData());
|
testC = PubUtils.doubleRoundStr(4, tempC.getData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempC.getData());
|
||||||
|
if (Objects.nonNull(tempC.getErrorData())) {
|
||||||
errorC = PubUtils.doubleRoundStr(4, tempC.getErrorData().doubleValue());
|
errorC = PubUtils.doubleRoundStr(4, tempC.getErrorData().doubleValue());
|
||||||
resultC = tempC.getIsData() == 1 ? "合格" : "不合格";
|
}
|
||||||
|
resultC = tempC.getIsData() == 1 ? "合格" : tempC.getIsData() == 0 ? "不合格" : "/";
|
||||||
if (errorScope.equals("/")) {
|
if (errorScope.equals("/")) {
|
||||||
errorScope = tempC.getRadius();
|
errorScope = tempC.getRadius() == null ? "/" : tempC.getRadius();
|
||||||
}
|
}
|
||||||
if (StrUtil.isBlank(unit)) {
|
if (StrUtil.isBlank(unit)) {
|
||||||
unit = tempC.getUnit();
|
unit = tempC.getUnit() == null ? "" : tempC.getUnit();
|
||||||
}
|
}
|
||||||
if (standard.equals("/")) {
|
if (standard.equals("/")) {
|
||||||
standard = PubUtils.doubleRoundStr(4, tempC.getResultData());
|
standard = PubUtils.doubleRoundStr(4, tempC.getResultData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempC.getResultData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (scriptCode.equalsIgnoreCase("I")) {
|
||||||
|
resultA = "/";
|
||||||
|
resultB = "/";
|
||||||
|
resultC = "/";
|
||||||
|
}
|
||||||
if (standardA.equals(standardB) && standardA.equals(standardC)) {
|
if (standardA.equals(standardB) && standardA.equals(standardC)) {
|
||||||
standard = standardA;
|
standard = standardA;
|
||||||
}
|
}
|
||||||
|
// 处理脚本输出
|
||||||
|
scriptDetail = dealScriptDetail(scriptCode, standard);
|
||||||
|
keyFillMap.put(ItemReportKeyEnum.SCRIPT_DETAIL.getKey(), scriptDetail);
|
||||||
// 标准值
|
// 标准值
|
||||||
keyFillMap.put(ItemReportKeyEnum.STANDARD.getKey(), standard);
|
keyFillMap.put(ItemReportKeyEnum.STANDARD.getKey(), standard);
|
||||||
keyFillMap.put(ItemReportKeyEnum.STANDARD_A.getKey(), standardA);
|
keyFillMap.put(ItemReportKeyEnum.STANDARD_A.getKey(), standardA);
|
||||||
@@ -1200,6 +1208,45 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
keyFillMap.put(ItemReportKeyEnum.ERROR_SCOPE.getKey(), errorScope);
|
keyFillMap.put(ItemReportKeyEnum.ERROR_SCOPE.getKey(), errorScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 针对浙江杭州处理脚本输出细节,todo... 需要更改更合理的方式,现在算是写死的了部分
|
||||||
|
* 目前浙江这边就是(间)谐波电压/电流
|
||||||
|
*/
|
||||||
|
private String dealScriptDetail(String scriptCode, String standard) {
|
||||||
|
String scriptDetail = "";
|
||||||
|
PowerIndexEnum powerIndexEnum = PowerIndexEnum.getByKey(scriptCode);
|
||||||
|
if (powerIndexEnum != null) {
|
||||||
|
switch (powerIndexEnum) {
|
||||||
|
case HV:
|
||||||
|
case HSV:
|
||||||
|
// 注:基波电压幅值57.74V,基波频率50.0Hz。
|
||||||
|
scriptDetail = "注:基波电压幅值57.74V,基波频率50.0Hz。";
|
||||||
|
break;
|
||||||
|
case HI:
|
||||||
|
// 电流是幅值,需要与5A得出百分比
|
||||||
|
try {
|
||||||
|
String temp = PubUtils.doubleRoundStr(1, (Double.parseDouble(standard) / 5.0) * 100);
|
||||||
|
scriptDetail = "注:基波电流幅值5.000A,基波频率50.0Hz,各次谐波电流含有率均为" + temp + "%。";
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("dealScriptDetail error:{}", e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HSI:
|
||||||
|
// 电流是幅值,需要与5A得出百分比
|
||||||
|
try {
|
||||||
|
String temp = PubUtils.doubleRoundStr(1, (Double.parseDouble(standard) / 5.0) * 100);
|
||||||
|
scriptDetail = "注:基波电流幅值5.000A,基波频率50.0Hz,各次间谐波电流含有率均为" + temp + "%。";
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("dealScriptDetail error:{}", e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scriptDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* T相的相关数据处理,非暂态数据
|
* T相的相关数据处理,非暂态数据
|
||||||
@@ -1212,13 +1259,15 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
private void fillTPhaseData(Object singleResult, Integer timeInt, Map<String, String> keyFillMap) {
|
private void fillTPhaseData(Object singleResult, Integer timeInt, Map<String, String> keyFillMap) {
|
||||||
String standard = "/", test = "/", error = "/", result = "/", errorScope = "/", unit = "";
|
String standard = "/", test = "/", error = "/", result = "/", errorScope = "/", unit = "";
|
||||||
DetectionData tempT = getResultData(singleResult, timeInt, PowerConstant.PHASE_T);
|
DetectionData tempT = getResultData(singleResult, timeInt, PowerConstant.PHASE_T);
|
||||||
if (Objects.nonNull(tempT) && PowerConstant.DATA_RANGE.contains(tempT.getIsData())) {
|
if (Objects.nonNull(tempT)) {
|
||||||
standard = PubUtils.doubleRoundStr(4, tempT.getResultData());
|
standard = PubUtils.doubleRoundStr(4, tempT.getResultData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempT.getResultData());
|
||||||
test = PubUtils.doubleRoundStr(4, tempT.getData());
|
test = PubUtils.doubleRoundStr(4, tempT.getData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempT.getData());
|
||||||
|
if (Objects.nonNull(tempT.getErrorData())) {
|
||||||
error = PubUtils.doubleRoundStr(4, tempT.getErrorData().doubleValue());
|
error = PubUtils.doubleRoundStr(4, tempT.getErrorData().doubleValue());
|
||||||
result = tempT.getIsData() == 1 ? "合格" : "不合格";
|
}
|
||||||
unit = tempT.getUnit();
|
result = tempT.getIsData() == 1 ? "合格" : tempT.getIsData() == 0 ? "不合格" : "/";
|
||||||
errorScope = tempT.getRadius();
|
unit = tempT.getUnit() == null ? "" : tempT.getUnit();
|
||||||
|
errorScope = tempT.getRadius() == null ? "/" : tempT.getRadius();
|
||||||
}
|
}
|
||||||
keyFillMap.put(ItemReportKeyEnum.STANDARD.getKey(), standard);
|
keyFillMap.put(ItemReportKeyEnum.STANDARD.getKey(), standard);
|
||||||
keyFillMap.put(ItemReportKeyEnum.TEST.getKey(), test);
|
keyFillMap.put(ItemReportKeyEnum.TEST.getKey(), test);
|
||||||
@@ -1249,11 +1298,13 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
DictTree temp = dictTreeService.getById(adType);
|
DictTree temp = dictTreeService.getById(adType);
|
||||||
if (temp.getCode().equalsIgnoreCase("MAG")) {
|
if (temp.getCode().equalsIgnoreCase("MAG")) {
|
||||||
// 特征幅值
|
// 特征幅值
|
||||||
if (Objects.nonNull(tempT) && PowerConstant.DATA_RANGE.contains(tempT.getIsData())) {
|
if (Objects.nonNull(tempT)) {
|
||||||
standardMag = PubUtils.doubleRoundStr(4, tempT.getResultData());
|
standardMag = PubUtils.doubleRoundStr(4, tempT.getResultData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempT.getResultData());
|
||||||
testMag = PubUtils.doubleRoundStr(4, tempT.getData());
|
testMag = PubUtils.doubleRoundStr(4, tempT.getData()) == null ? "/" : PubUtils.doubleRoundStr(4, tempT.getData());
|
||||||
|
if (Objects.nonNull(tempT.getErrorData())) {
|
||||||
errorMag = PubUtils.doubleRoundStr(4, tempT.getErrorData().doubleValue());
|
errorMag = PubUtils.doubleRoundStr(4, tempT.getErrorData().doubleValue());
|
||||||
resultMag = tempT.getIsData() == 1 ? "合格" : "不合格";
|
}
|
||||||
|
resultMag = tempT.getIsData() == 1 ? "合格" : tempT.getIsData() == 0 ? "不合格" : "/";
|
||||||
unitMag = tempT.getUnit();
|
unitMag = tempT.getUnit();
|
||||||
errorScopeMag = tempT.getRadius();
|
errorScopeMag = tempT.getRadius();
|
||||||
}
|
}
|
||||||
@@ -1271,12 +1322,24 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (Objects.nonNull(tempT.getResultData())) {
|
||||||
standardDur = PubUtils.doubleRoundStr(4, tempT.getResultData());
|
standardDur = PubUtils.doubleRoundStr(4, tempT.getResultData());
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(tempT.getData())) {
|
||||||
testDur = PubUtils.doubleRoundStr(4, tempT.getData());
|
testDur = PubUtils.doubleRoundStr(4, tempT.getData());
|
||||||
errorDur = PubUtils.doubleRoundStr(4, tempT.getErrorData().doubleValue());
|
}
|
||||||
|
if (Objects.nonNull(tempT.getErrorData())) {
|
||||||
|
testDur = PubUtils.doubleRoundStr(4, tempT.getErrorData().doubleValue());
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(tempT.getIsData())) {
|
||||||
resultDur = tempT.getIsData() == 1 ? "合格" : "不合格";
|
resultDur = tempT.getIsData() == 1 ? "合格" : "不合格";
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(tempT.getUnit())) {
|
||||||
unitDur = tempT.getUnit();
|
unitDur = tempT.getUnit();
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(tempT.getRadius())) {
|
||||||
errorScopeDur = tempT.getRadius();
|
errorScopeDur = tempT.getRadius();
|
||||||
|
}
|
||||||
if (timeUnit.equalsIgnoreCase("ms")) {
|
if (timeUnit.equalsIgnoreCase("ms")) {
|
||||||
// 如果是ms,上述的一些数据需要重新处理
|
// 如果是ms,上述的一些数据需要重新处理
|
||||||
if (!standardDur.equalsIgnoreCase("/")) {
|
if (!standardDur.equalsIgnoreCase("/")) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ spring:
|
|||||||
datasource:
|
datasource:
|
||||||
druid:
|
druid:
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://192.168.1.24:13306/pqs91001?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT
|
url: jdbc:mysql://192.168.1.24:13306/pqs91003?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT
|
||||||
username: root
|
username: root
|
||||||
password: njcnpqs
|
password: njcnpqs
|
||||||
# url: jdbc:mysql://localhost:3306/pqs91001?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT
|
# url: jdbc:mysql://localhost:3306/pqs91001?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT
|
||||||
|
|||||||
Reference in New Issue
Block a user