报表添加合格率sheet

This commit is contained in:
2026-07-22 09:43:03 +08:00
parent 321e4bace8
commit 9e26cc2f24
11 changed files with 386 additions and 140 deletions

View File

@@ -36,7 +36,7 @@ import com.njcn.harmonic.pojo.vo.MonitorOverLimitVO;
import com.njcn.harmonic.pojo.vo.OverAreaLimitVO;
import com.njcn.harmonic.pojo.vo.OverAreaVO;
import com.njcn.harmonic.pojo.vo.WarningSubstationVO;
import com.njcn.harmonic.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.service.IAnalyzeService;
import com.njcn.poi.excel.ExcelUtil;
import com.njcn.supervision.pojo.param.user.UserReportParam;
@@ -50,7 +50,6 @@ import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.File;
import java.math.BigDecimal;

View File

@@ -10,7 +10,6 @@ import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.biz.pojo.param.DeptGetLineParam;
import com.njcn.device.pq.api.GeneralDeviceInfoClient;
import com.njcn.device.pq.api.LineFeignClient;
import com.njcn.device.pq.pojo.bo.BaseLineInfo;
import com.njcn.device.pq.pojo.po.LineDetail;
import com.njcn.device.pq.pojo.vo.AreaLineInfoVO;
import com.njcn.harmonic.mapper.*;
@@ -27,7 +26,7 @@ import com.njcn.harmonic.pojo.vo.hebeinorth.EvaluationVo;
import com.njcn.harmonic.common.mapper.RStatDataIDMapper;
import com.njcn.harmonic.common.mapper.RStatDataInharmVDMapper;
import com.njcn.harmonic.common.mapper.RStatDataVDMapper;
import com.njcn.harmonic.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.service.hebeinorth.IGridService;
import com.njcn.harmonic.util.ComAssesUtil;
import com.njcn.harmonic.util.TimeUtil;

View File

@@ -59,7 +59,7 @@ import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.vo.PollutionSubstationVO;
import com.njcn.harmonic.pojo.vo.PollutionVO;
import com.njcn.harmonic.pojo.vo.SubstationVo;
import com.njcn.harmonic.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.service.PollutionSubstationService;
import com.njcn.poi.excel.ExcelUtil;
import com.njcn.supervision.pojo.param.SensitiveUserParam;

View File

@@ -19,7 +19,7 @@ import com.njcn.harmonic.pojo.param.TotalLimitStatisticsDetailsQueryParam;
import com.njcn.harmonic.pojo.param.TotalLimitStatisticsParam;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.vo.*;
import com.njcn.harmonic.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.service.IRStatLimitRateDService;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.pojo.po.DictData;

View File

@@ -21,7 +21,7 @@ import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.vo.MonitorOverLimitVO;
import com.njcn.harmonic.pojo.vo.SteadyExceedRateCensusVO;
import com.njcn.harmonic.pojo.vo.SteadyExceedRateVO;
import com.njcn.harmonic.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.service.SteadyExceedRateService;
import com.njcn.harmonic.utils.PubUtils;
import com.njcn.influx.pojo.constant.InfluxDBTableConstant;

View File

@@ -14,7 +14,7 @@ import com.njcn.device.pq.enums.LineBaseEnum;
import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.pq.pojo.param.DeviceInfoParam;
import com.njcn.device.pq.pojo.vo.LineDetailVO;
import com.njcn.harmonic.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.mapper.SteadyQualifyMapper;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.vo.SteadyQualifyCensusVO;
@@ -24,7 +24,6 @@ import com.njcn.harmonic.service.SteadyQualifyService;
import com.njcn.harmonic.utils.PubUtils;
import com.njcn.supervision.pojo.param.user.UserReportParam;
import com.njcn.supervision.pojo.vo.user.UserLedgerVO;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

View File

@@ -33,7 +33,7 @@ import com.njcn.harmonic.pojo.po.day.RStatLimitTargetDPO;
import com.njcn.harmonic.pojo.vo.MonitorLimitRateVO;
import com.njcn.harmonic.pojo.vo.PwLimitDataVO;
import com.njcn.harmonic.pojo.vo.RStatLimitTargetVO;
import com.njcn.harmonic.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.service.IRStatLimitTargetDService;
import com.njcn.harmonic.service.majornetwork.RStatLimitService;
import com.njcn.system.pojo.enums.StatisticsEnum;

View File

@@ -33,7 +33,7 @@ import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.po.upload.*;
import com.njcn.harmonic.pojo.vo.upload.DimBusBarVO;
import com.njcn.harmonic.pojo.vo.upload.UploadEvaluationDataVo;
import com.njcn.harmonic.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.service.upload.IEvaluationDataService;
import com.njcn.harmonic.service.upload.IRUploadDataLogService;
import com.njcn.system.api.DicDataFeignClient;

View File

@@ -1,4 +1,4 @@
package com.njcn.harmonic.mapper;
package com.njcn.harmonic.common.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.njcn.harmonic.mapper.RStatLimitRateDMapper">
<mapper namespace="com.njcn.harmonic.common.mapper.RStatLimitRateDMapper">
<select id="getSumPassRate" resultType="com.njcn.harmonic.pojo.vo.RStatLimitRateDVO">
SELECT

View File

@@ -7,6 +7,7 @@ import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONConfig;
@@ -14,17 +15,21 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONTokener;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.harmonic.common.mapper.ExcelRptTempMapper;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.common.pojo.dto.DeviceUnitCommDTO;
import com.njcn.harmonic.common.service.CustomReportTableService;
import com.njcn.harmonic.enums.HarmonicResponseEnum;
import com.njcn.harmonic.pojo.dto.ReportTemplateDTO;
import com.njcn.harmonic.pojo.param.ReportSearchParam;
import com.njcn.harmonic.pojo.po.ExcelRptTemp;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.po.day.RStatLimitTargetDPO;
import com.njcn.influx.constant.InfluxDbSqlConstant;
import com.njcn.influx.pojo.constant.InfluxDBTableConstant;
import com.njcn.influx.utils.InfluxDbUtils;
@@ -45,9 +50,11 @@ import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Service;
import javax.annotation.PreDestroy;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
@@ -73,6 +80,7 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
private final EpdFeignClient epdFeignClient;
private final FileStorageUtil fileStorageUtil;
private final DicDataFeignClient dicDataFeignClient;
private final RStatLimitRateDMapper rStatLimitRateDMapper;
private final InfluxDbUtils influxDbUtils;
private final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
@@ -218,8 +226,8 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
try {
future.get(); // 这会阻塞直到任务完成或抛出异常
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
log.error("自定义报表多线程查询流程出错!错误信息{}", e.getMessage());
throw new BusinessException(CommonResponseEnum.FAIL,"自定义报表多线程查询流程出错!");
}
}
@@ -673,8 +681,8 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
try {
future.get(); // 这会阻塞直到任务完成或抛出异常
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
log.error("自定义报表多线程查询流程出错!错误信息{}", e.getMessage());
throw new BusinessException(CommonResponseEnum.FAIL,"自定义报表多线程查询流程出错!");
}
}
@@ -687,6 +695,196 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
}
/**
* 合格率sheet组装
* @param reportSearchParam
* @return
*/
public Map<String, String> assemblePassRateResult(ReportSearchParam reportSearchParam) {
Map<String, String> resultMap = new HashMap<>();
// 1. 查询数据
LambdaQueryWrapper<RStatLimitRateDPO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RStatLimitRateDPO::getLineId, reportSearchParam.getLineId())
.between(RStatLimitRateDPO::getTime, reportSearchParam.getStartTime(), reportSearchParam.getEndTime());
List<RStatLimitRateDPO> list = rStatLimitRateDMapper.selectList(wrapper);
if (CollUtil.isEmpty(list)) {
return resultMap;
}
// 2. 按相分组
Map<String, List<RStatLimitRateDPO>> phaseMap = list.stream()
.collect(Collectors.groupingBy(item -> item.getPhasicType() == null ? "" : item.getPhasicType()));
RStatLimitRateDPO A = assRStatLimitRateDPO(phaseMap.getOrDefault("A", Collections.emptyList()), false);
RStatLimitRateDPO B = assRStatLimitRateDPO(phaseMap.getOrDefault("B", Collections.emptyList()), false);
RStatLimitRateDPO C = assRStatLimitRateDPO(phaseMap.getOrDefault("C", Collections.emptyList()), false);
RStatLimitRateDPO T = assRStatLimitRateDPO(phaseMap.getOrDefault("T", Collections.emptyList()), true);
if (getVal(A.getAllTime()) <= 0 || getVal(B.getAllTime()) <= 0 || getVal(C.getAllTime()) <= 0) {
return resultMap;
}
// 3. 工具:计算合过率
java.util.function.BiFunction<Integer, Integer, Double> calc = (overtime, total) -> {
int ot = overtime == null ? 0 : overtime;
int tt = total == null ? 0 : total;
return tt <= 0 ? 0 : (1 - ot * 1.0 / tt) * 100;
};
java.util.function.DoubleFunction<String> fmt = d -> BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP).toString();
// 4. 通用处理把三项通过率算出来put到map
java.util.function.BiFunction<String, java.util.function.Function<RStatLimitRateDPO, Integer>, Void> process = (name, getter) -> {
double a = calc.apply(getter.apply(A), A.getAllTime());
double b = calc.apply(getter.apply(B), B.getAllTime());
double c = calc.apply(getter.apply(C), C.getAllTime());
resultMap.put("$" + name + "#A#pass$", fmt.apply(a));
resultMap.put("$" + name + "#B#pass$", fmt.apply(b));
resultMap.put("$" + name + "#C#pass$", fmt.apply(c));
resultMap.put("$" + name + "#all$", fmt.apply(Math.min(a, Math.min(b, c))));
return null;
};
// 5. 电压偏差
process.apply("voltageDevOvertime", RStatLimitRateDPO::getVoltageDevOvertime);
// 6. 电压谐波畸变率
process.apply("uaberranceOvertime", RStatLimitRateDPO::getUaberranceOvertime);
// 7. T相三相不平衡 + 频率偏差
double ubalance = calc.apply(T.getUbalanceOvertime(), A.getAllTime());
double freqDev = calc.apply(T.getFreqDevOvertime(), A.getAllTime());
resultMap.put("$ubalanceOvertime$", fmt.apply(ubalance));
resultMap.put("$freqDevOvertime$", fmt.apply(freqDev));
// 8. 谐波 2~25电压 + 电流)
for (int i = 2; i <= 25; i++) {
// 电压谐波
String uField = "uharm" + i + "Overtime";
double ua = calc.apply(getField(A, uField), A.getAllTime());
double ub = calc.apply(getField(B, uField), B.getAllTime());
double uc = calc.apply(getField(C, uField), C.getAllTime());
resultMap.put("$" + uField + "#A#pass$", fmt.apply(ua));
resultMap.put("$" + uField + "#B#pass$", fmt.apply(ub));
resultMap.put("$" + uField + "#C#pass$", fmt.apply(uc));
resultMap.put("$" + uField + "#all$", fmt.apply(Math.min(ua, Math.min(ub, uc))));
// 电流谐波
String iField = "iharm" + i + "Overtime";
double ia = calc.apply(getField(A, iField), A.getAllTime());
double ib = calc.apply(getField(B, iField), B.getAllTime());
double ic = calc.apply(getField(C, iField), C.getAllTime());
resultMap.put("$" + iField + "#A#pass$", fmt.apply(ia));
resultMap.put("$" + iField + "#B#pass$", fmt.apply(ib));
resultMap.put("$" + iField + "#C#pass$", fmt.apply(ic));
resultMap.put("$" + iField + "#all$", fmt.apply(Math.min(ia, Math.min(ib, ic))));
}
// 9. 各相总次数
resultMap.put("$harmOvertime#A#num$", String.valueOf(getVal(A.getAllTime())));
resultMap.put("$harmOvertime#B#num$", String.valueOf(getVal(B.getAllTime())));
resultMap.put("$harmOvertime#C#num$", String.valueOf(getVal(C.getAllTime())));
// 10. 闪变(单独处理,因为分母是 flickerAllTime
if (getVal(A.getFlickerAllTime()) > 0 && getVal(B.getFlickerAllTime()) > 0 && getVal(C.getFlickerAllTime()) > 0) {
double fa = calc.apply(A.getFlickerOvertime(), A.getFlickerAllTime());
double fb = calc.apply(B.getFlickerOvertime(), B.getFlickerAllTime());
double fc = calc.apply(C.getFlickerOvertime(), C.getFlickerAllTime());
resultMap.put("$flickerOvertime#A#pass$", fmt.apply(fa));
resultMap.put("$flickerOvertime#B#pass$", fmt.apply(fb));
resultMap.put("$flickerOvertime#C#pass$", fmt.apply(fc));
resultMap.put("$flickerOvertime#all$", fmt.apply(Math.min(fa, Math.min(fb, fc))));
resultMap.put("$flickerOvertime#A#num$", String.valueOf(getVal(A.getFlickerAllTime())));
resultMap.put("$flickerOvertime#B#num$", String.valueOf(getVal(B.getFlickerAllTime())));
resultMap.put("$flickerOvertime#C#num$", String.valueOf(getVal(C.getFlickerAllTime())));
}
return resultMap;
}
// ========== 两个小工具方法 ==========
private int getVal(Integer v) {
return v == null ? 0 : v;
}
private Integer getField(RStatLimitRateDPO obj, String fieldName) {
try {
Field f = RStatLimitRateDPO.class.getDeclaredField(fieldName);
f.setAccessible(true);
return (Integer) f.get(obj);
} catch (Exception e) {
return 0;
}
}
private double limitPassRateForMap(Map<String, String> resultMap, RStatLimitRateDPO obj, String fieldName, String phase) {
double tem = 0;
try {
Field fieldA = obj.getClass().getDeclaredField(fieldName);
fieldA.setAccessible(true);
int valA = (int) fieldA.get(obj);
tem = (1 - valA * 1.0 / obj.getAllTime()) * 100;
BigDecimal vA = new BigDecimal(tem).setScale(2, RoundingMode.HALF_UP);
String keyA = "$" + fieldName + "#" + phase + "#pass$";
resultMap.put(keyA, vA.toString());
} catch (Exception e) {
e.printStackTrace();
}
return tem;
}
private RStatLimitRateDPO assRStatLimitRateDPO(List<RStatLimitRateDPO> limitRateA, boolean allFlag) {
RStatLimitRateDPO a = new RStatLimitRateDPO();
for (RStatLimitRateDPO b : limitRateA) {
a.setAllTime(addInt(a.getAllTime(), b.getAllTime()));
if (allFlag) {
a.setFreqDevOvertime(addInt(a.getFreqDevOvertime(), b.getFreqDevOvertime()));
a.setUbalanceOvertime(addInt(a.getUbalanceOvertime(), b.getUbalanceOvertime()));
return a;
}
a.setFlickerAllTime(addInt(a.getFlickerAllTime(), b.getFlickerAllTime()));
a.setFlickerOvertime(addInt(a.getFlickerOvertime(), b.getFlickerOvertime()));
a.setUaberranceOvertime(addInt(a.getUaberranceOvertime(), b.getUaberranceOvertime()));
a.setVoltageDevOvertime(addInt(a.getVoltageDevOvertime(), b.getVoltageDevOvertime()));
// uharm2~25 用循环简化
for (int i = 2; i <= 25; i++) {
String fieldName = "uharm" + i + "Overtime";
try {
Field field = RStatLimitRateDPO.class.getDeclaredField(fieldName);
field.setAccessible(true);
Integer valA = (Integer) field.get(a);
Integer valB = (Integer) field.get(b);
field.set(a, addInt(valA, valB));
} catch (Exception e) {
e.printStackTrace();
}
}
// iharm2~25 用循环简化
for (int i = 2; i <= 25; i++) {
String fieldName = "iharm" + i + "Overtime";
try {
Field field = RStatLimitRateDPO.class.getDeclaredField(fieldName);
field.setAccessible(true);
Integer valA = (Integer) field.get(a);
Integer valB = (Integer) field.get(b);
field.set(a, addInt(valA, valB));
} catch (Exception e) {
e.printStackTrace();
}
}
}
return a;
}
// 安全相加方法
private Integer addInt(Integer a, Integer b) {
return (a == null ? 0 : a) + (b == null ? 0 : b);
}
/**
* 解析模板
*
@@ -698,6 +896,7 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
//通过文件服务器获取
jsonArray.forEach(item -> {
JSONObject jsonObject = (JSONObject) item;
if (!"合格率".equals(jsonObject.getStr("name"))) {
JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA);
itemArr.forEach((it) -> {
if (Objects.nonNull(it) && !"null".equals(it.toString())) {
@@ -756,6 +955,7 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
}
}
});
}
});
} catch (Exception e) {
throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_JSON);
@@ -1447,6 +1647,54 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
//2、把itemName的value赋给v和m
jsonArray.forEach(item -> {
JSONObject jsonObject = (JSONObject) item;
if ("合格率".equals(jsonObject.getStr("name"))) {
//新增合格率sheet处理
Map<String, String> rateMap = assemblePassRateResult(reportSearchParam);
JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA);
itemArr.forEach((it) -> {
if (Objects.nonNull(it) && !"null".equals(it.toString())) {
//获取到1列
JSONObject data = (JSONObject) it;
JSONObject son = (JSONObject) data.get(V);
if (son.containsKey(V)) {
String v = son.getStr(V);
if (v.charAt(0) == '&') {
//结论
String tem = v.replace(STR_THREE, "").toUpperCase();
if (!finalTerminalMap.isEmpty()) {
if ("STATIS_TIME".equals(tem)) {
//如何时间是大于当前时间则用当前时间
String localTime = InfluxDbSqlConstant.END_TIME;
LocalDate localDate = LocalDateTimeUtil.parseDate(reportSearchParam.getEndTime(), DatePattern.NORM_DATE_PATTERN);
LocalDate nowDate = LocalDate.now();
if (nowDate.isAfter(localDate)) {
son.set(V, reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + reportSearchParam.getEndTime() + localTime);
} else {
localTime = " " + LocalTime.now().format(DatePattern.NORM_TIME_FORMATTER);
son.set(V, reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + nowDate + localTime);
}
} else {
//台账信息
son.set(V, finalTerminalMap.getOrDefault(tem, "/"));
}
}
} else if (v.charAt(0) == '$') {
if (rateMap.containsKey(v)) {
String val = rateMap.get(v);
son.set(V,val);
if(v.contains("#all$")){
if(Double.parseDouble(val) < 98){
son.set("fc", "#990000");
}
}
}
}
}
}
});
} else {
JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA);
itemArr.forEach((it) -> {
if (Objects.nonNull(it) && !"null".equals(it.toString())) {
@@ -1515,6 +1763,7 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
}
}
});
}
});
}
}