5 Commits

Author SHA1 Message Date
89667367ea 添加水印 2025-11-12 11:45:21 +08:00
92b95dd86d 微调 2025-11-11 13:18:42 +08:00
caozehui
6b7e38fef6 处理源未知异常 2025-11-10 14:45:23 +08:00
caozehui
f10debe2f2 比对-被检设备导入微调 2025-11-07 15:13:07 +08:00
caozehui
61f149b562 系数校准接收数据个数调整 2025-11-05 13:51:47 +08:00
11 changed files with 268 additions and 43 deletions

View File

@@ -439,6 +439,7 @@ public class SocketDevResponseService {
//告诉前端当前项开始了
WebSocketVO<Object> webSocketVO = new WebSocketVO<>();
FormalTestManager.currentIssue = sourceIssues.get(0);
String type = sourceIssues.get(0).getType();
if (ResultUnitEnum.P.getCode().equals(type)) {
sourceIssues.get(0).setType(ResultUnitEnum.V_ABSOLUTELY.getCode());
@@ -612,7 +613,7 @@ public class SocketDevResponseService {
private void assemblyEntity(List<DevData> deList, DevXiNumData.F F, DevXiNumData.GF startF, CoefficientVO coefficientVO, CoefficientVO.DevParameter devParameter) {
//表示接收完成,必须保证3个数
if (deList.size() >= 3) {
if (deList.size() >= 7) {
List<Double> aList = deList.stream().map(it -> it.getSqlData().get(0).getList().getA()).collect(Collectors.toList());
List<Double> bList = deList.stream().map(it -> it.getSqlData().get(0).getList().getB()).collect(Collectors.toList());
List<Double> cList = deList.stream().map(it -> it.getSqlData().get(0).getList().getC()).collect(Collectors.toList());
@@ -687,7 +688,7 @@ public class SocketDevResponseService {
*/
private Double reduceList(List<Double> valList) {
// valList.subList(0, 5).clear();
// valList.subList(valList.size() - 3, valList.size() - 1).clear();
valList.subList(valList.size() - 2, valList.size()).clear();
return valList.stream().mapToDouble(Double::doubleValue).average().getAsDouble();
}
@@ -953,6 +954,7 @@ public class SocketDevResponseService {
} else {
webSocketVO.setRequestId(sourceIssues.get(0).getType() + CnSocketUtil.START_TAG);
}
FormalTestManager.currentIssue = sourceIssues.get(0);
socketMsg.setData(JSON.toJSONString(sourceIssues.get(0)));
socketMsg.setRequestId(SourceOperateCodeEnum.FORMAL_REAL.getValue() + CnSocketUtil.STEP_TAG + type);
socketMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
@@ -1210,6 +1212,7 @@ public class SocketDevResponseService {
} else {
webSocketVO.setRequestId(sourceIssues.get(0).getType() + CnSocketUtil.START_TAG);
}
FormalTestManager.currentIssue = sourceIssues.get(0);
socketMsg.setData(JSON.toJSONString(sourceIssues.get(0)));
socketMsg.setRequestId(SourceOperateCodeEnum.FORMAL_REAL.getValue() + CnSocketUtil.STEP_TAG + type);
socketMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
@@ -1782,6 +1785,7 @@ public class SocketDevResponseService {
} else {
dataRule = DictDataEnum.SECTION_VALUE;
}
FormalTestManager.currentTestPlan = plan;
String code = dictDataService.getDictDataById(plan.getPattern()).getCode();
FormalTestManager.patternEnum = PatternEnum.getEnum(code);

View File

@@ -2,6 +2,7 @@ package com.njcn.gather.detection.handler;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.gather.detection.pojo.enums.SourceOperateCodeEnum;
import com.njcn.gather.detection.pojo.enums.SourceResponseCodeEnum;
import com.njcn.gather.detection.pojo.param.DevPhaseSequenceParam;
@@ -14,7 +15,12 @@ import com.njcn.gather.detection.util.socket.*;
import com.njcn.gather.detection.util.socket.websocket.WebServiceManager;
import com.njcn.gather.device.pojo.vo.PreDetection;
import com.njcn.gather.device.service.IPqDevService;
import com.njcn.gather.plan.pojo.po.AdPlanSource;
import com.njcn.gather.plan.service.IAdPlanSourceService;
import com.njcn.gather.result.pojo.enums.ResultUnitEnum;
import com.njcn.gather.script.pojo.po.SourceIssue;
import com.njcn.gather.source.pojo.po.SourceInitialize;
import com.njcn.gather.source.service.IPqSourceService;
import com.njcn.gather.system.pojo.enums.DicDataEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -56,6 +62,8 @@ public class SocketSourceResponseService {
* 设备信息服务,提供设备基础信息查询功能
*/
private final IPqDevService iPqDevService;
private final IAdPlanSourceService adPlanSourceService;
private final IPqSourceService pqSourceService;
/**
* Socket连接管理器负责管理设备和源的Socket连接
@@ -334,9 +342,9 @@ public class SocketSourceResponseService {
// 系数校验固定检测项:实时电压有效值和实时电流有效值
phaseSequenceParam.setDataType(Arrays.asList("real$VRMS", "real$IRMS"));
// 读取3次数据用于系数计算
phaseSequenceParam.setReadCount(3);
phaseSequenceParam.setReadCount(7); //3
// 忽略前4次数据等待测量稳定
phaseSequenceParam.setIgnoreCount(4);
phaseSequenceParam.setIgnoreCount(3); //4
socketMsg.setData(JSON.toJSONString(phaseSequenceParam));
SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
@@ -363,18 +371,32 @@ public class SocketSourceResponseService {
SocketMsg<String> socketMsg = new SocketMsg<>();
switch (dictDataEnumByCode) {
case SUCCESS:
//todo 前端推送收到的消息暂未处理好
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
//开始设备通讯检测(发送设备初始化)
Map<String, List<PreDetection>> map = new HashMap<>(1);
map.put("deviceList", FormalTestManager.devList);
String jsonString = JSON.toJSONString(map);
socketMsg.setRequestId(SourceOperateCodeEnum.YJC_SBTXJY.getValue());
socketMsg.setOperateCode(SourceOperateCodeEnum.DEV_INIT_GATHER_01.getValue());
socketMsg.setData(jsonString);
String json = JSON.toJSONString(socketMsg);
// 使用智能发送工具类,自动管理设备连接
socketManager.smartSendToDevice(param, json);
if (FormalTestManager.unknownError) {
FormalTestManager.unknownError = false;
//重新下发脚本
String type = FormalTestManager.currentIssue.getType();
if (ResultUnitEnum.P.getCode().equals(type)) {
FormalTestManager.currentIssue.setType(ResultUnitEnum.V_ABSOLUTELY.getCode());
}
socketMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue());
socketMsg.setData(JSON.toJSONString(FormalTestManager.currentIssue));
socketMsg.setRequestId(SourceOperateCodeEnum.FORMAL_REAL.getValue() + CnSocketUtil.STEP_TAG + type);
SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(socketMsg));
} else {
//todo 前端推送收到的消息暂未处理好
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
//开始设备通讯检测(发送设备初始化)
Map<String, List<PreDetection>> map = new HashMap<>(1);
map.put("deviceList", FormalTestManager.devList);
String jsonString = JSON.toJSONString(map);
socketMsg.setRequestId(SourceOperateCodeEnum.YJC_SBTXJY.getValue());
socketMsg.setOperateCode(SourceOperateCodeEnum.DEV_INIT_GATHER_01.getValue());
socketMsg.setData(jsonString);
String json = JSON.toJSONString(socketMsg);
// 使用智能发送工具类,自动管理设备连接
socketManager.smartSendToDevice(param, json);
}
break;
case UNPROCESSED_BUSINESS:
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
@@ -570,6 +592,10 @@ public class SocketSourceResponseService {
case UNPROCESSED_BUSINESS:
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
case UNKNOWN_ERROR: //-1源未知异常
CnSocketUtil.quitSendSource(param);
FormalTestManager.unknownError = true;
break;
default:
sendErrorAndQuit(param, socketDataMsg, dictDataEnumByCode);
break;
@@ -601,9 +627,23 @@ public class SocketSourceResponseService {
SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
switch (Objects.requireNonNull(dictDataEnumByCode)) {
case SUCCESS:
//通讯校验成功
SocketManager.removeUser(param.getUserPageId() + CnSocketUtil.SOURCE_TAG);
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
if (FormalTestManager.unknownError) {
//获取源初始化参数
AdPlanSource planSource = adPlanSourceService.getOne(new LambdaQueryWrapper<AdPlanSource>().eq(AdPlanSource::getPlanId, param.getPlanId()));
SourceInitialize sourceParam = pqSourceService.getSourceInitializeParam(planSource.getSourceId());
if (ObjectUtil.isNotNull(sourceParam)) {
SocketMsg<String> socketMsg1 = new SocketMsg<>();
socketMsg1.setRequestId(SourceOperateCodeEnum.YJC_YTXJY.getValue());
socketMsg1.setOperateCode(SourceOperateCodeEnum.INIT_GATHER.getValue());
socketMsg1.setData(JSON.toJSONString(sourceParam));
//使用智能发送工具类自动管理与源控程序的socket连接
socketManager.smartSendToSource(param, JSON.toJSONString(socketMsg1));
}
} else {
//通讯校验成功
SocketManager.removeUser(param.getUserPageId() + CnSocketUtil.SOURCE_TAG);
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
}
break;
case UNPROCESSED_BUSINESS:
break;
@@ -653,6 +693,8 @@ public class SocketSourceResponseService {
// 同步更新系数管理器中的设备列表
XiNumberManager.xiDevList = devList;
FormalTestManager.unknownError = false;
FormalTestManager.currentIssue = null;
}
}

View File

@@ -10,6 +10,7 @@ import com.njcn.gather.device.pojo.vo.PreDetection;
import com.njcn.gather.plan.pojo.enums.DataSourceEnum;
import com.njcn.gather.plan.pojo.po.AdPlan;
import com.njcn.gather.plan.pojo.po.AdPlanTestConfig;
import com.njcn.gather.script.pojo.po.SourceIssue;
import com.njcn.gather.system.dictionary.pojo.enums.DictDataEnum;
import java.util.ArrayList;
@@ -195,4 +196,11 @@ public class FormalTestManager {
public static boolean statisticsProtocol;
public static boolean voltageProtocol;
public static boolean unknownError;
/**
* 当前下发的脚本
*/
public static SourceIssue currentIssue;
}

View File

@@ -169,4 +169,24 @@ public class PqDevController extends BaseController {
Map<String, List<String>> result = pqDevService.listSelectOptions(pattern);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
@OperateInfo(info = LogEnum.BUSINESS_COMMON, operateType = OperateType.UPLOAD)
@PostMapping(value = "/ttt")
@ApiOperation("批量导入被检设备")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "被检设备数据文件", required = true),
@ApiImplicitParam(name = "patternId", value = "模式id", required = true)
})
public HttpResult ttt(@RequestParam("file") MultipartFile file, @RequestParam("patternId") String patternId, @RequestParam("planId") String planId, @RequestParam(value = "cover", defaultValue = "0") Integer cover, HttpServletResponse response) {
String methodDescribe = getMethodDescribe("ttt");
LogUtil.njcnDebug(log, "{},上传文件为:{}", methodDescribe, file.getOriginalFilename());
boolean fileType = FileUtil.judgeFileIsExcel(file.getOriginalFilename());
if (!fileType) {
throw new BusinessException(CommonResponseEnum.FILE_XLSX_ERROR);
}
if ("null".equals(planId)) {
planId = null;
}
return pqDevService.importDev(file, patternId, planId, response, cover);
}
}

View File

@@ -38,8 +38,8 @@ public class ContrastDevExcel implements Serializable {
@Pattern(regexp = PatternRegex.DEV_NAME_REGEX, message = DetectionValidMessage.NAME_FORMAT_ERROR)
private String name;
@Excel(name = "设备序列号*", width = 20, needMerge = true, orderNum = "5")
@NotBlank(message = DetectionValidMessage.FACTORYNO_NOT_BLANK)
@Excel(name = "设备序列号", width = 20, needMerge = true, orderNum = "5")
// @NotBlank(message = DetectionValidMessage.FACTORYNO_NOT_BLANK)
private String createId;
@Excel(name = "设备类型*", width = 20, needMerge = true, orderNum = "6")
@@ -91,8 +91,8 @@ public class ContrastDevExcel implements Serializable {
@NotNull(message = DetectionValidMessage.INSPECT_DATE_NOT_NULL)
private LocalDate inspectDate;
@Excel(name = "谐波系统设备id*", width = 30, needMerge = true, orderNum = "18")
@NotBlank(message = DetectionValidMessage.HARM_SYS_ID_NOT_BLANK)
@Excel(name = "谐波系统设备id", width = 30, needMerge = true, orderNum = "18")
// @NotBlank(message = DetectionValidMessage.HARM_SYS_ID_NOT_BLANK)
private String harmSysId;
@ExcelCollection(name = "监测点信息", orderNum = "19")

View File

@@ -68,6 +68,7 @@ import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author caozehui
@@ -1340,9 +1341,11 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
if (CollUtil.isNotEmpty(hasList)) {
importPqDev.setId(hasList.get(0).getId());
for (PqMonitorExcel pqMonitorExcel : pqMonitorExcelList) {
PqMonitor pqMonitor = BeanUtil.copyProperties(pqMonitorExcel, PqMonitor.class);
pqMonitor.setDevId(importPqDev.getId());
monitorList.add(pqMonitor);
PqMonitor monitor = BeanUtil.copyProperties(pqMonitorExcel, PqMonitor.class);
monitor.setDevId(importPqDev.getId());
monitor.setPt(pqMonitorExcel.getPt1() + StrUtil.C_COLON + pqMonitorExcel.getPt2());
monitor.setCt(pqMonitorExcel.getCt1() + StrUtil.C_COLON + pqMonitorExcel.getCt2());
monitorList.add(monitor);
}
importPqDev.setMonitorList(monitorList);
finalUpdateDevList.add(importPqDev);
@@ -1366,6 +1369,8 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
for (PqMonitorExcel pqMonitorExcel : pqMonitorExcelList) {
PqMonitor monitor = BeanUtil.copyProperties(pqMonitorExcel, PqMonitor.class);
monitor.setDevId(importPqDev.getId());
monitor.setPt(pqMonitorExcel.getPt1() + StrUtil.C_COLON + pqMonitorExcel.getPt2());
monitor.setCt(pqMonitorExcel.getCt1() + StrUtil.C_COLON + pqMonitorExcel.getCt2());
monitorList.add(monitor);
}
importPqDev.setMonitorList(monitorList);
@@ -1375,6 +1380,8 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
for (PqMonitorExcel pqMonitorExcel : pqMonitorExcelList) {
PqMonitor monitor = BeanUtil.copyProperties(pqMonitorExcel, PqMonitor.class);
monitor.setDevId(importPqDev.getId());
monitor.setPt(pqMonitorExcel.getPt1() + StrUtil.C_COLON + pqMonitorExcel.getPt2());
monitor.setCt(pqMonitorExcel.getCt1() + StrUtil.C_COLON + pqMonitorExcel.getCt2());
monitorList.add(monitor);
}
importPqDev.setMonitorList(monitorList);
@@ -1496,13 +1503,19 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
if (ObjectUtil.isNotNull(dictType)) {
dictDataList = dictDataService.getDictDataByTypeId(dictType.getId());
pullDown = new PullDown();
pullDown.setFirstCol(startCol + 24);
pullDown.setLastCol(startCol + 24);
pullDown.setFirstCol(startCol + 26);
pullDown.setLastCol(startCol + 26);
pullDown.setStrings(dictDataList.stream().map(DictData::getName).collect(Collectors.toList()));
pullDowns.add(pullDown);
}
pullDown = new PullDown();
pullDown.setFirstCol(startCol + 27);
pullDown.setLastCol(startCol + 27);
pullDown.setStrings(Stream.iterate(1, x -> x + 1).limit(10).map(String::valueOf).collect(Collectors.toList()));
pullDowns.add(pullDown);
return pullDowns;
}
@@ -1564,7 +1577,22 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
contrastDevExcels.forEach(contrastDevExcel -> {
List<PqMonitor> monitorList = pqMonitorService.listPqMonitorByDevIds(Collections.singletonList(contrastDevExcel.getId()));
pqMonitorService.visualizeMonitor(monitorList);
List<PqMonitorExcel> pqMonitorExcelList = BeanUtil.copyToList(monitorList, PqMonitorExcel.class);
List<PqMonitorExcel> pqMonitorExcelList = new ArrayList<>();
for (int i = 0; i < monitorList.size(); i++) {
PqMonitor pqMonitor = monitorList.get(i);
PqMonitorExcel pqMonitorExcel = BeanUtil.copyProperties(pqMonitor, PqMonitorExcel.class);
String pt = pqMonitor.getPt();
String[] split1 = pt.split(String.valueOf(StrUtil.C_COLON));
pqMonitorExcel.setPt1(split1[0]);
pqMonitorExcel.setPt2(split1[1]);
String ct = pqMonitor.getCt();
String[] split2 = ct.split(String.valueOf(StrUtil.C_COLON));
pqMonitorExcel.setCt1(split2[0]);
pqMonitorExcel.setCt2(split2[1]);
pqMonitorExcelList.add(pqMonitorExcel);
}
contrastDevExcel.setPqMonitorExcelList(pqMonitorExcelList);
});
}

View File

@@ -14,11 +14,11 @@ import javax.validation.constraints.NotNull;
@Data
public class PqMonitorExcel {
@Excel(name = "谐波系统监测点ID*", width = 20, orderNum = "1")
@NotBlank(message = DetectionValidMessage.MONITOR_ID_NOT_BLANK)
@Excel(name = "谐波系统监测点ID", width = 20, orderNum = "1")
// @NotBlank(message = DetectionValidMessage.MONITOR_ID_NOT_BLANK)
private String harmSysId;
@Excel(name = "所属母线*", width = 20, orderNum = "2")
@Excel(name = "母线名称*", width = 20, orderNum = "2")
@NotBlank(message = DetectionValidMessage.BELONG_LINE_NOT_BLANK)
private String busbar;
@@ -30,19 +30,27 @@ public class PqMonitorExcel {
@NotNull(message = DetectionValidMessage.MONITOR_NUM_NOT_NULL)
private Integer num;
@Excel(name = "PT变比(pt1:pt2)*", width = 20, orderNum = "5")
@Excel(name = "PT一次变比*", width = 20, orderNum = "5")
@NotBlank(message = DetectionValidMessage.PT_NOT_BLANK)
private String pt;
private String pt1;
@Excel(name = "CT变比(ct1:ct2)*", width = 20, orderNum = "6")
@Excel(name = "PT二次变比*", width = 20, orderNum = "6")
@NotBlank(message = DetectionValidMessage.PT_NOT_BLANK)
private String pt2;
@Excel(name = "CT一次变比*", width = 20, orderNum = "7")
@NotBlank(message = DetectionValidMessage.CT_NOT_BLANK)
private String ct;
private String ct1;
@Excel(name = "接线方式*", width = 20, orderNum = "7")
@Excel(name = "CT二次变比*", width = 20, orderNum = "8")
@NotBlank(message = DetectionValidMessage.CT_NOT_BLANK)
private String ct2;
@Excel(name = "接线方式*", width = 20, orderNum = "9")
@NotBlank(message = DetectionValidMessage.CONNECTION_NOT_BLANK)
private String connection;
@Excel(name = "统计间隔*", width = 10, orderNum = "8")
@Excel(name = "统计间隔*", width = 20, orderNum = "10")
@NotNull(message = DetectionValidMessage.STAT_INTERVAL_NOT_NULL)
private Integer statInterval;
}

View File

@@ -118,4 +118,11 @@ public interface IPqMonitorService extends IService<PqMonitor> {
* @return
*/
boolean removeByDevId(String devId);
/**
* 根据被检设备id和监测点编号获取监测点信息
* @param id 被检设备id
* @param monitorNum 监测点编号
*/
PqMonitor getByDevAndNum(String id, int monitorNum);
}

View File

@@ -432,4 +432,16 @@ public class PqMonitorServiceImpl extends ServiceImpl<PqMonitorMapper, PqMonitor
wrapper.eq("pq_monitor.Dev_Id", devId);
return this.remove(wrapper);
}
@Override
public PqMonitor getByDevAndNum(String devId, int monitorNum) {
QueryWrapper<PqMonitor> wrapper = new QueryWrapper<>();
wrapper.eq("pq_monitor.Dev_Id", devId)
.eq("pq_monitor.Num", monitorNum);
List<PqMonitor> pqMonitors = this.list(wrapper);
if(CollUtil.isNotEmpty(pqMonitors)){
return pqMonitors.get(0);
}
return null;
}
}

View File

@@ -39,6 +39,8 @@ import com.njcn.gather.device.service.IPqDevService;
import com.njcn.gather.device.service.IPqDevSubService;
import com.njcn.gather.err.pojo.po.PqErrSys;
import com.njcn.gather.err.service.IPqErrSysService;
import com.njcn.gather.monitor.pojo.po.PqMonitor;
import com.njcn.gather.monitor.service.IPqMonitorService;
import com.njcn.gather.plan.pojo.enums.DataSourceEnum;
import com.njcn.gather.plan.pojo.enums.PlanReportStateEnum;
import com.njcn.gather.plan.pojo.po.AdPlan;
@@ -179,6 +181,7 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
private final ISysUserService sysUserService;
private final IPqErrSysService pqErrSysService;
private final IAdPlanTestConfigService adPlanTestConfigService;
private final IPqMonitorService pqMonitorService;
@Resource
private RestTemplateUtil restTemplateUtil;
@@ -820,6 +823,14 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
pqDevVO.getGdName() != null ? pqDevVO.getGdName() : "未知供电公司",
pqDevVO.getSubName() != null ? pqDevVO.getSubName() : "未知电站",
pqDevVO.getName() != null ? pqDevVO.getName() : "未知设备");
// 判断是否需要在报告上输出水印
String leader = baseModelDataMap.get(BaseReportKeyEnum.AUDIT_BY.getKey());
String loginName = RequestUtil.getLoginNameByToken();
SysUser user = sysUserService.getUserByLoginName(loginName);
if (!leader.equals(user.getName())) {
log.info("当前用户不是审核人,添加非正式水印");
Docx4jUtil.addWatermarkToDocument(baseModelDocument, "非正式");
}
Docx4jUtil.cleanBlankPagesAndRedundantPageBreaks(baseModelDocument);
baseModelDocument.save(new File(dirPath.concat(File.separator).concat(fileName)));
this.updateDevAndPlanState(devId, devReportParam.getPlanId());
@@ -1157,7 +1168,7 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
// 插入回路号前,先换个页
todoInsertList.add(Docx4jUtil.createPageBreakParagraph());
// 回路标题
todoInsertList.add(getContrastLineTitle(contentMap, monitorNum, stepIndex, factory));
todoInsertList.add(getContrastLineTitle(contentMap, monitorNum, stepIndex, factory, pqDevVO));
int scriptIndex = 1;
for (ContrastTestResult contrastTestResult : contrastTestResults) {
// 比如电压 V
@@ -2016,7 +2027,7 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
// 委托方
String delegate = pqDevVO.getDelegate();
if (StrUtil.isNotBlank(delegate)) {
DictData delegateDictData = dictDataService.getDictDataById(pqDevVO.getManufacturer());
DictData delegateDictData = dictDataService.getDictDataById(pqDevVO.getDelegate());
if (ObjectUtil.isNotNull(delegateDictData)) {
baseModelMap.put(BaseReportKeyEnum.DELEGATE.getKey(), delegateDictData.getName());
} else {
@@ -2392,16 +2403,21 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
/**
* 创建回路标题到报告中
*/
private P getContrastLineTitle(Map<String, List<Docx4jUtil.HeadingContent>> contentMap, int monitorNum, int index, ObjectFactory factory) {
private P getContrastLineTitle(Map<String, List<Docx4jUtil.HeadingContent>> contentMap, int monitorNum, int index, ObjectFactory factory, PqDevVO pqDevVO) {
PqMonitor pqMonitor = pqMonitorService.getByDevAndNum(pqDevVO.getId(), monitorNum);
String monitorInfoName = "";
if (StrUtil.isNotBlank(pqDevVO.getSubName()) && Objects.nonNull(pqMonitor)) {
monitorInfoName = "(" + pqDevVO.getSubName() + "-" + pqMonitor.getName() + ")";
}
List<Docx4jUtil.HeadingContent> headingContents = contentMap.get(PowerIndexEnum.LINE_TITLE.getKey());
// 如果contentMap中有指定内容创建大纲级别为2的标题
if (CollUtil.isNotEmpty(headingContents)) {
return Docx4jUtil.createTitle(factory, 2, index + ".测量回路" + monitorNum,
return Docx4jUtil.createTitle(factory, 2, index + ".测量回路" + monitorNum + monitorInfoName,
"SimSun", 30, true);
}
// 没有模板配置时,创建默认样式段落
P titleParagraph = factory.createP();
Docx4jUtil.createTitle(factory, titleParagraph, "测量回路" + monitorNum,
Docx4jUtil.createTitle(factory, titleParagraph, "测量回路" + monitorNum + monitorInfoName,
28, true);
return titleParagraph;
}

View File

@@ -5,6 +5,7 @@ import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
@@ -27,6 +28,7 @@ import java.util.Map;
* @version 1.0
* @data 2025/3/26 13:47
*/
@Slf4j
public class Docx4jUtil {
/**
@@ -2139,5 +2141,83 @@ public class Docx4jUtil {
return specialCaseP;
}
/**
* 为Word文档添加水印
* 使用页眉方式但设置页眉高度为0确保不影响文档结构
*
* @param wordPackage Word文档包
* @param watermarkText 水印文字(如:"非正式"
* @throws Exception 添加水印失败时抛出异常
*/
public static void addWatermarkToDocument(WordprocessingMLPackage wordPackage, String watermarkText) throws Exception {
try {
MainDocumentPart mainDocumentPart = wordPackage.getMainDocumentPart();
ObjectFactory factory = new ObjectFactory();
// 创建页眉部分
org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart headerPart =
new org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart();
// 将页眉部分添加到文档并获取关系ID
org.docx4j.relationships.Relationship relationship = mainDocumentPart.addTargetPart(headerPart);
// 创建页眉对象
org.docx4j.wml.Hdr hdr = factory.createHdr();
// 创建段落
P paragraph = factory.createP();
// 创建Run
R run = factory.createR();
// 使用VML textbox方式创建水印文本绝对定位显示在页面中部
String vmlString = String.format(
"<w:pict xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" " +
"xmlns:v=\"urn:schemas-microsoft-com:vml\">" +
"<v:shape style=\"position:absolute;left:0;text-align:center;margin-left:0;margin-top:0;" +
"width:500pt;height:200pt;z-index:-251658240;" +
"mso-position-horizontal:center;mso-position-horizontal-relative:page;" +
"mso-position-vertical:center;mso-position-vertical-relative:page\" " +
"fillcolor=\"none\" stroked=\"f\">" +
"<v:textbox style=\"mso-fit-shape-to-text:t\">" +
"<w:txbxContent>" +
"<w:p><w:pPr><w:jc w:val=\"center\"/></w:pPr>" +
"<w:r><w:rPr>" +
"<w:color w:val=\"D8D8D8\"/>" +
"<w:sz w:val=\"240\"/>" +
"<w:szCs w:val=\"240\"/>" +
"<w:rFonts w:ascii=\"微软雅黑\" w:eastAsia=\"微软雅黑\" w:hAnsi=\"微软雅黑\"/>" +
"</w:rPr><w:t>%s</w:t></w:r></w:p>" +
"</w:txbxContent></v:textbox>" +
"</v:shape></w:pict>", watermarkText);
// 解析VML并添加到Run
Object vmlObject = XmlUtils.unmarshalString(vmlString);
run.getContent().add(vmlObject);
paragraph.getContent().add(run);
hdr.getContent().add(paragraph);
headerPart.setJaxbElement(hdr);
// 获取或创建节属性SectPr
SectPr sectPr = mainDocumentPart.getJaxbElement().getBody().getSectPr();
if (sectPr == null) {
sectPr = factory.createSectPr();
mainDocumentPart.getJaxbElement().getBody().setSectPr(sectPr);
}
// 创建页眉引用并关联到节属性
org.docx4j.wml.HeaderReference headerReference = factory.createHeaderReference();
headerReference.setId(relationship.getId());
headerReference.setType(org.docx4j.wml.HdrFtrRef.DEFAULT);
sectPr.getEGHdrFtrReferences().add(headerReference);
log.info("成功添加水印:{}", watermarkText);
} catch (Exception e) {
log.error("添加水印失败:{}", e.getMessage(), e);
throw new Exception("添加水印失败:" + e.getMessage(), e);
}
}
}