3 Commits

Author SHA1 Message Date
xy
6089be6b4a feat(report): 电压暂降事件报告导出功能优化 2026-06-05 11:16:15 +08:00
xy
eb89472670 微调 2026-06-04 18:28:51 +08:00
xy
56cd9a05c3 feat(echarts): 添加波形图绘制功能支持
- 新增drawWavePic方法用于绘制波形图
- 实现null数据段压缩算法,确保图表性能优化
- 添加markLine和markArea功能显示null段边界标记
- 集成到WavePicComponent组件中支持瞬时和RMS波形图生成
- 修复RestTemplate对Hutool JSON对象的支持问题
- 优化WaveUtil工具类处理空值数据逻辑
2026-06-04 18:27:47 +08:00
7 changed files with 1098 additions and 65 deletions

View File

@@ -1,11 +1,7 @@
package com.njcn.echarts.json; package com.njcn.echarts.json;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import cn.hutool.json.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.njcn.echarts.pojo.bo.TolerateData; import com.njcn.echarts.pojo.bo.TolerateData;
import com.njcn.echarts.pojo.constant.PicCommonData; import com.njcn.echarts.pojo.constant.PicCommonData;
import org.icepear.echarts.Option; import org.icepear.echarts.Option;
@@ -29,7 +25,6 @@ import org.icepear.echarts.render.Engine;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -43,6 +38,17 @@ import java.util.stream.Collectors;
public class LineGenerator { public class LineGenerator {
private final static Engine ENGINE = new Engine(); private final static Engine ENGINE = new Engine();
// null段在图表上的固定视觉宽度数据点数量
private static final int NULL_PLACEHOLDER_COUNT = 90;
// 压缩结果
private static class CompressedResult {
// 压缩后的数据
List<List<Float>> data;
// 每个null段的[起始索引, 结束索引](占位点范围)
List<int[]> nullRegionIndices;
// null段边界处的真实x值entry, exit交替
List<Float> nullBoundaryRealXValues;
}
/*** /***
@@ -529,6 +535,478 @@ public class LineGenerator {
return ENGINE.renderJsonOption(instantOption); return ENGINE.renderJsonOption(instantOption);
} }
public static String generateWaveOption(String title, List<List<Float>> aValue, List<List<Float>> bValue, List<List<Float>> cValue, String unit, Float max, Float min, String a, String b, String c, List<String> colors, Boolean isOpen, Double lastTime, List<Float> sharedNullBoundaryXValues, Integer nPush) {
DecimalFormat df1 = new DecimalFormat("#.00");
// 压缩null数据如果有共享边界则用共享边界否则独立压缩
CompressedResult aCompressed;
CompressedResult bCompressed;
CompressedResult cCompressed;
if (sharedNullBoundaryXValues != null && !sharedNullBoundaryXValues.isEmpty()) {
aCompressed = compressNullDataWithSharedBoundaries(aValue, sharedNullBoundaryXValues);
bCompressed = compressNullDataWithSharedBoundaries(bValue, sharedNullBoundaryXValues);
cCompressed = compressNullDataWithSharedBoundaries(cValue, sharedNullBoundaryXValues);
} else {
aCompressed = compressNullData(aValue);
bCompressed = compressNullData(bValue);
cCompressed = compressNullData(cValue);
}
Option instantOption = new Option();
//取消渲染动画
instantOption.setAnimation(false);
//背景色
instantOption.setBackgroundColor(PicCommonData.PIC_BACK_COLOR);
//标题
instantOption.setTitle(new Title()
.setText(title)
.setLeft(PicCommonData.CENTER)
.setTextStyle(new Label().setFontSize(14))
);
//配置颜色
instantOption.setColor(colors.toArray(new String[colors.size()]));
//配置图例
if (isOpen) {
instantOption.setLegend(new Legend().setData(new String[]{a, b}).setLeft("10px"));
} else {
instantOption.setLegend(new Legend().setData(new String[]{a, b, c}).setLeft("10px"));
}
//上下左右的图内间距
instantOption.setGrid(new Grid().setTop("60px").setLeft("70px").setRight("40px").setBottom("10%"));
//横坐标(使用压缩后的数据)
instantOption.setXAxis(new ValueAxis().setName("ms")
.setSplitLine(new SplitLine().setShow(false))
.setAxisLine(new AxisLine().setOnZero(false))
.setType("category")
.setMinInterval(1)
);
//纵坐标
instantOption.setYAxis(new ValueAxis()
.setName(unit)
.setMax(df1.format(max * 1.1))
.setMin(df1.format(min * 1.1))
.setPosition(PicCommonData.LEFT)
.setAxisLine(new AxisLine().setShow(false).setOnZero(false))
);
//数据信息(使用压缩后的数据)
LineSeries aSeries = new LineSeries()
.setName(a)
.setSmooth(true)
.setSymbol("none")
.setConnectNulls(false)
.setData(aCompressed.data);
LineSeries bSeries = new LineSeries()
.setName(b)
.setSmooth(true)
.setSymbol("none")
.setConnectNulls(false)
.setData(bCompressed.data);
LineSeries cSeries = new LineSeries()
.setName(c)
.setSmooth(true)
.setSymbol("none")
.setConnectNulls(false)
.setData(cCompressed.data);
instantOption.setSeries(new LineSeries[]{aSeries, bSeries, cSeries});
// 渲染基础JSON
String jsonStr = ENGINE.renderJsonOption(instantOption);
cn.hutool.json.JSONObject optionJson = JSONUtil.parseObj(jsonStr);
cn.hutool.json.JSONArray seriesArray = optionJson.getJSONArray("series");
// 隐藏x轴默认标签设置boundaryGap=false只通过markLine显示关键节点
Object xAxisRaw = optionJson.get("xAxis");
cn.hutool.json.JSONObject xAxisJson;
if (xAxisRaw instanceof cn.hutool.json.JSONArray) {
xAxisJson = ((cn.hutool.json.JSONArray) xAxisRaw).getJSONObject(0);
} else {
xAxisJson = (cn.hutool.json.JSONObject) xAxisRaw;
}
cn.hutool.json.JSONObject axisLabelJson = new cn.hutool.json.JSONObject();
axisLabelJson.set("show", false);
xAxisJson.set("axisLabel", axisLabelJson);
xAxisJson.set("boundaryGap", false);
// 添加null markLine/markArea基于压缩后的数据
addNullMarkLinesForCategoryAxis(seriesArray.getJSONObject(0), aCompressed, lastTime);
addNullMarkLinesForCategoryAxis(seriesArray.getJSONObject(1), bCompressed, lastTime);
addNullMarkLinesForCategoryAxis(seriesArray.getJSONObject(2), cCompressed, lastTime);
// 在第一个series追加自定义横坐标标签markLine
addAxisLabelMarkLines(seriesArray.getJSONObject(0), aCompressed, lastTime, nPush);
return optionJson.toString();
}
/** 提取null边界的真实x值供其他数据集共享使用 */
public static List<Float> extractNullBoundaryXValues(List<List<Float>> data) {
List<Integer> boundaries = findNullSegmentBoundaryIndices(data);
List<Float> xValues = new ArrayList<>();
for (int idx : boundaries) {
xValues.add(data.get(idx).get(0));
}
return xValues;
}
/** 使用共享的null边界x值来压缩数据确保不同数据集压缩结果结构一致 */
private static CompressedResult compressNullDataWithSharedBoundaries(List<List<Float>> originalData, List<Float> sharedBoundaryXValues) {
if (sharedBoundaryXValues == null || sharedBoundaryXValues.isEmpty()) {
return compressNullData(originalData);
}
// 用共享的x值找到本数据集中对应的索引
List<Integer> boundaries = new ArrayList<>();
for (Float x : sharedBoundaryXValues) {
boundaries.add(findClosestValidIndex(originalData, x));
}
CompressedResult result = new CompressedResult();
result.data = new ArrayList<>();
result.nullRegionIndices = new ArrayList<>();
result.nullBoundaryRealXValues = new ArrayList<>(sharedBoundaryXValues);
int srcIdx = 0;
for (int b = 0; b < boundaries.size(); b += 2) {
int entryBoundary = boundaries.get(b);
int exitBoundary = boundaries.get(b + 1);
while (srcIdx <= entryBoundary) {
result.data.add(originalData.get(srcIdx));
srcIdx++;
}
int nullStartIdx = result.data.size();
float entryX = sharedBoundaryXValues.get(b);
float exitX = sharedBoundaryXValues.get(b + 1);
for (int p = 0; p < NULL_PLACEHOLDER_COUNT; p++) {
List<Float> point = new ArrayList<>();
point.add(entryX + (exitX - entryX) * p / NULL_PLACEHOLDER_COUNT);
point.add(null);
result.data.add(point);
}
int nullEndIdx = result.data.size() - 1;
result.nullRegionIndices.add(new int[]{nullStartIdx, nullEndIdx});
srcIdx = exitBoundary;
}
while (srcIdx < originalData.size()) {
result.data.add(originalData.get(srcIdx));
srcIdx++;
}
return result;
}
/**
* 压缩null数据删除所有null数据点替换为固定NULL_PLACEHOLDER_COUNT个占位点
* 这样null段在图表上永远只占固定视觉宽度前后有效数据正常展开
*/
private static CompressedResult compressNullData(List<List<Float>> originalData) {
List<Integer> boundaries = findNullSegmentBoundaryIndices(originalData);
CompressedResult result = new CompressedResult();
result.data = new ArrayList<>();
result.nullRegionIndices = new ArrayList<>();
result.nullBoundaryRealXValues = new ArrayList<>();
if (boundaries.isEmpty()) {
result.data.addAll(originalData);
return result;
}
int srcIdx = 0;
for (int b = 0; b < boundaries.size(); b += 2) {
// 最后一个有效点的索引null段入口边界
int entryBoundary = boundaries.get(b);
// 第一个恢复有效点的索引null段出口边界
int exitBoundary = boundaries.get(b + 1);
// 复制有效数据从srcIdx到entryBoundary
while (srcIdx <= entryBoundary) {
result.data.add(originalData.get(srcIdx));
srcIdx++;
}
// 记录边界真实x值
result.nullBoundaryRealXValues.add(originalData.get(entryBoundary).get(0));
result.nullBoundaryRealXValues.add(originalData.get(exitBoundary).get(0));
// 插入固定数量的null占位点
int nullStartIdx = result.data.size();
float entryX = originalData.get(entryBoundary).get(0);
float exitX = originalData.get(exitBoundary).get(0);
for (int p = 0; p < NULL_PLACEHOLDER_COUNT; p++) {
List<Float> point = new ArrayList<>();
point.add(entryX + (exitX - entryX) * p / NULL_PLACEHOLDER_COUNT);
point.add(null);
result.data.add(point);
}
int nullEndIdx = result.data.size() - 1;
result.nullRegionIndices.add(new int[]{nullStartIdx, nullEndIdx});
// 跳过原始null数据点srcIdx跳到exitBoundary
srcIdx = exitBoundary;
}
// 复制最后一个null段之后的剩余有效数据
while (srcIdx < originalData.size()) {
result.data.add(originalData.get(srcIdx));
srcIdx++;
}
return result;
}
/**
* 在压缩数据中查找最接近目标x值的有效数据点索引跳过null点
*/
private static int findClosestValidIndex(List<List<Float>> data, float targetX) {
int closestIdx = -1;
float minDiff = Float.MAX_VALUE;
for (int i = 0; i < data.size(); i++) {
Float y = data.get(i).get(1);
if (y == null) continue;
float diff = Math.abs(data.get(i).get(0) - targetX);
if (diff < minDiff) {
minDiff = diff;
closestIdx = i;
}
}
return closestIdx;
}
private static void addAxisLabelMarkLines(cn.hutool.json.JSONObject seriesObj, CompressedResult compressed, Double lastTime, Integer nPush) {
boolean hasNull = !compressed.nullRegionIndices.isEmpty();
// 收集需要标注的横坐标位置:[数据索引, 显示的时间值]
List<int[]> labelPositions = new ArrayList<>();
// 开头ms始终显示
labelPositions.add(new int[]{findClosestValidIndex(compressed.data, -nPush), -nPush});
// 0ms始终显示
labelPositions.add(new int[]{findClosestValidIndex(compressed.data, 0f), 0});
// npush ms仅在有null时显示
if (hasNull) {
labelPositions.add(new int[]{findClosestValidIndex(compressed.data, nPush), nPush});
}
// null段边界真实时间值仅在有null时显示
if (hasNull) {
for (Float realX : compressed.nullBoundaryRealXValues) {
int idx = findClosestValidIndex(compressed.data, realX);
if (idx >= 0) {
labelPositions.add(new int[]{idx, (int) Math.round(realX)});
}
}
}
// lastTime始终显示
if (lastTime != null) {
labelPositions.add(new int[]{findClosestValidIndex(compressed.data, lastTime.floatValue()), lastTime.intValue()});
}
// 最后一组数据(始终显示,数据结束位置横坐标)
if (lastTime != null) {
float lastTime20 = lastTime.floatValue() + nPush;
int lastTime20Idx = findClosestValidIndex(compressed.data, lastTime20);
if (lastTime20Idx >= 0) {
labelPositions.add(new int[]{(lastTime20Idx-2), (int) Math.round(lastTime20)});
}
}
// 获取或创建markLine
cn.hutool.json.JSONObject existingMarkLine = seriesObj.getJSONObject("markLine");
cn.hutool.json.JSONArray markLineData;
if (existingMarkLine == null) {
// 无null的情况自己创建markLine包含虚线和横坐标标签
markLineData = new cn.hutool.json.JSONArray();
// x=0 虚线
int zeroIdx = findClosestValidIndex(compressed.data, 0f);
if (zeroIdx >= 0) {
cn.hutool.json.JSONObject zeroLine = new cn.hutool.json.JSONObject();
zeroLine.set("xAxis", zeroIdx);
cn.hutool.json.JSONObject zeroLabel = new cn.hutool.json.JSONObject();
zeroLabel.set("show", false);
zeroLine.set("label", zeroLabel);
markLineData.add(zeroLine);
}
// lastTime 虚线
if (lastTime != null) {
int lastTimeIdx = findClosestValidIndex(compressed.data, lastTime.floatValue());
if (lastTimeIdx >= 0) {
cn.hutool.json.JSONObject lastTimeLine = new cn.hutool.json.JSONObject();
lastTimeLine.set("xAxis", lastTimeIdx);
cn.hutool.json.JSONObject lastTimeLabelObj = new cn.hutool.json.JSONObject();
lastTimeLabelObj.set("show", false);
lastTimeLine.set("label", lastTimeLabelObj);
markLineData.add(lastTimeLine);
}
}
// 先收集所有标签到markLineData
for (int[] pos : labelPositions) {
cn.hutool.json.JSONObject line = new cn.hutool.json.JSONObject();
line.set("xAxis", pos[0]);
cn.hutool.json.JSONObject lineLineStyle = new cn.hutool.json.JSONObject();
lineLineStyle.set("width", 0);
line.set("lineStyle", lineLineStyle);
cn.hutool.json.JSONObject lineLabel = new cn.hutool.json.JSONObject();
lineLabel.set("show", true);
lineLabel.set("formatter", String.valueOf(pos[1]));
lineLabel.set("position", "start");
lineLabel.set("color", "#333");
lineLabel.set("fontSize", 10);
line.set("label", lineLabel);
markLineData.add(line);
}
// 最后一次性设置到markLine和series
existingMarkLine = new cn.hutool.json.JSONObject();
existingMarkLine.set("symbol", new String[]{"none", "none"});
cn.hutool.json.JSONObject lineStyle = new cn.hutool.json.JSONObject();
lineStyle.set("type", "dashed");
lineStyle.set("color", "#999");
lineStyle.set("width", 1);
existingMarkLine.set("lineStyle", lineStyle);
cn.hutool.json.JSONObject globalLabel = new cn.hutool.json.JSONObject();
globalLabel.set("show", false);
existingMarkLine.set("label", globalLabel);
existingMarkLine.set("data", markLineData);
seriesObj.set("markLine", existingMarkLine);
} else {
// 有null的情况追加标签到已有的markLine
markLineData = existingMarkLine.getJSONArray("data");
for (int[] pos : labelPositions) {
cn.hutool.json.JSONObject line = new cn.hutool.json.JSONObject();
line.set("xAxis", pos[0]);
cn.hutool.json.JSONObject lineLineStyle = new cn.hutool.json.JSONObject();
lineLineStyle.set("width", 0);
line.set("lineStyle", lineLineStyle);
cn.hutool.json.JSONObject lineLabel = new cn.hutool.json.JSONObject();
lineLabel.set("show", true);
lineLabel.set("formatter", String.valueOf(pos[1]));
lineLabel.set("position", "start");
lineLabel.set("color", "#333");
lineLabel.set("fontSize", 10);
line.set("label", lineLabel);
markLineData.add(line);
}
}
}
private static List<Integer> findNullSegmentBoundaryIndices(List<List<Float>> data) {
List<Integer> indices = new ArrayList<>();
boolean inNullSegment = false;
for (int i = 0; i < data.size(); i++) {
Float y = data.get(i).get(1);
if (y == null) {
if (!inNullSegment) {
indices.add(i > 0 ? i - 1 : i);
inNullSegment = true;
}
} else {
if (inNullSegment) {
indices.add(i);
inNullSegment = false;
}
}
}
if (inNullSegment) {
indices.add(data.size() - 1);
}
return indices;
}
private static void addNullMarkLinesForCategoryAxis(cn.hutool.json.JSONObject seriesObj, CompressedResult compressed, Double lastTime) {
if (compressed.nullRegionIndices.isEmpty()) {
return;
}
cn.hutool.json.JSONArray markLineData = new cn.hutool.json.JSONArray();
// x=0 虚线
int zeroIdx = findClosestValidIndex(compressed.data, 0f);
if (zeroIdx >= 0) {
cn.hutool.json.JSONObject zeroLine = new cn.hutool.json.JSONObject();
zeroLine.set("xAxis", zeroIdx);
cn.hutool.json.JSONObject zeroLabel = new cn.hutool.json.JSONObject();
zeroLabel.set("show", false);
zeroLine.set("label", zeroLabel);
markLineData.add(zeroLine);
}
// null段边界的垂直虚线
for (int r = 0; r < compressed.nullRegionIndices.size(); r++) {
int[] region = compressed.nullRegionIndices.get(r);
int nullStartIdx = region[0]; // 第一个占位点索引
int nullEndIdx = region[1]; // 最后一个占位点索引
// 入口虚线nullStartIdx - 1null前最后一个有效数据点
cn.hutool.json.JSONObject entryLine = new cn.hutool.json.JSONObject();
entryLine.set("xAxis", nullStartIdx - 1);
cn.hutool.json.JSONObject entryLabel = new cn.hutool.json.JSONObject();
entryLabel.set("show", false);
entryLine.set("label", entryLabel);
markLineData.add(entryLine);
// 出口虚线nullEndIdxnull后第一个有效数据点
cn.hutool.json.JSONObject exitLine = new cn.hutool.json.JSONObject();
exitLine.set("xAxis", nullEndIdx);
cn.hutool.json.JSONObject exitLabel = new cn.hutool.json.JSONObject();
exitLabel.set("show", false);
exitLine.set("label", exitLabel);
markLineData.add(exitLine);
}
// 时间持续时间结束的数据点
if (lastTime != null) {
int lastTimeIdx = findClosestValidIndex(compressed.data, lastTime.floatValue());
if (lastTimeIdx >= 0) {
cn.hutool.json.JSONObject lastTimeLine = new cn.hutool.json.JSONObject();
lastTimeLine.set("xAxis", lastTimeIdx);
cn.hutool.json.JSONObject lastTimeLabel = new cn.hutool.json.JSONObject();
lastTimeLabel.set("show", false);
lastTimeLine.set("label", lastTimeLabel);
markLineData.add(lastTimeLine);
}
}
cn.hutool.json.JSONObject markLine = new cn.hutool.json.JSONObject();
markLine.set("symbol", new String[]{"none", "none"});
cn.hutool.json.JSONObject lineStyle = new cn.hutool.json.JSONObject();
lineStyle.set("type", "dashed");
lineStyle.set("color", "#999");
lineStyle.set("width", 1);
markLine.set("lineStyle", lineStyle);
cn.hutool.json.JSONObject globalLabel = new cn.hutool.json.JSONObject();
globalLabel.set("show", false);
markLine.set("label", globalLabel);
markLine.set("data", markLineData);
seriesObj.set("markLine", markLine);
// markArea - 灰色背景覆盖null区域从入口边界到出口边界
cn.hutool.json.JSONArray markAreaData = new cn.hutool.json.JSONArray();
for (int r = 0; r < compressed.nullRegionIndices.size(); r++) {
int[] region = compressed.nullRegionIndices.get(r);
int nullStartIdx = region[0];
int nullEndIdx = region[1];
cn.hutool.json.JSONArray areaPair = new cn.hutool.json.JSONArray();
cn.hutool.json.JSONObject start = new cn.hutool.json.JSONObject();
start.set("xAxis", nullStartIdx - 1); // 从入口边界有效数据点
cn.hutool.json.JSONObject end = new cn.hutool.json.JSONObject();
end.set("xAxis", nullEndIdx); // 到出口边界有效数据点
areaPair.add(start);
areaPair.add(end);
markAreaData.add(areaPair);
}
cn.hutool.json.JSONObject markArea = new cn.hutool.json.JSONObject();
cn.hutool.json.JSONObject itemStyle = new cn.hutool.json.JSONObject();
itemStyle.set("color", "rgba(180, 180, 180, 0.2)");
itemStyle.set("borderWidth", 0);
markArea.set("itemStyle", itemStyle);
markArea.set("data", markAreaData);
seriesObj.set("markArea", markArea);
}
/** /**
* @param title 标题 * @param title 标题
* @param values 数据值 * @param values 数据值

View File

@@ -10,9 +10,10 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.*; import java.util.List;
import java.util.Map;
import java.util.Objects;
/** /**
* @author hongawen * @author hongawen
@@ -55,7 +56,6 @@ public class DrawPicUtil {
return Objects.requireNonNull(picResult.getBody()).indexOf("image/png") > 0 ? picResult.getBody() : ""; return Objects.requireNonNull(picResult.getBody()).indexOf("image/png") > 0 ? picResult.getBody() : "";
} }
/*** /***
* @author hongawen * @author hongawen
* 绘制波形图 * 绘制波形图
@@ -77,6 +77,11 @@ public class DrawPicUtil {
return drawPic(instantJson, width, height); return drawPic(instantJson, width, height);
} }
public String drawWavePic(String title, List<List<Float>> aValue, List<List<Float>> bValue, List<List<Float>> cValue, String unit, Float max, Float min, String a, String b, String c, List<String> colors, Boolean isOpen, Double lastTime, List<Float> sharedNullBoundaryXValues,Integer nPush) {
String instantJson = LineGenerator.generateWaveOption(title, aValue, bValue, cValue, unit, max, min, a, b, c, colors, isOpen, lastTime, sharedNullBoundaryXValues,nPush);
return drawPic(instantJson, 0, 0);
}
/*** /***
* 绘制itic曲线图 * 绘制itic曲线图

View File

@@ -1,10 +1,9 @@
package com.njcn.event.file.component; package com.njcn.event.file.component;
import cn.hutool.core.img.ImgUtil; import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import com.njcn.common.pojo.exception.BusinessException; import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.FileUtil; import com.njcn.common.utils.FileUtil;
import com.njcn.echarts.json.LineGenerator;
import com.njcn.echarts.pojo.constant.PicCommonData; import com.njcn.echarts.pojo.constant.PicCommonData;
import com.njcn.echarts.util.DrawPicUtil; import com.njcn.echarts.util.DrawPicUtil;
import com.njcn.event.file.pojo.bo.WaveDataDetail; import com.njcn.event.file.pojo.bo.WaveDataDetail;
@@ -12,21 +11,17 @@ import com.njcn.event.file.pojo.dto.WaveDataDTO;
import com.njcn.event.file.pojo.enums.WaveFileResponseEnum; import com.njcn.event.file.pojo.enums.WaveFileResponseEnum;
import com.njcn.oss.constant.OssPath; import com.njcn.oss.constant.OssPath;
import com.njcn.oss.utils.FileStorageUtil; import com.njcn.oss.utils.FileStorageUtil;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import sun.awt.image.BufferedImageGraphicsConfig; import sun.awt.image.BufferedImageGraphicsConfig;
import javax.imageio.ImageIO;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.util.Base64;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author hongawen * @author hongawen
@@ -49,36 +44,39 @@ public class WavePicComponent {
* @date 2023/9/21 15:32 * @date 2023/9/21 15:32
* @return String 文件地址 * @return String 文件地址
*/ */
public String generateInstantImageZl(List<WaveDataDetail> waveDataDetails) { public String generateInstantImageZl(Integer nPush, List<WaveDataDetail> waveDataDetails, Double lastTime) {
String firstPic = null, secondPic = null, thirdPic = null, forthPic = null; String firstPic = null, secondPic = null, thirdPic = null, forthPic = null;
WaveDataDetail waveDataDetail0 = waveDataDetails.get(0);
// 从instantData提取null边界x值作为共享参考与Shun图保持一致
List<Float> sharedNullBoundaries = LineGenerator.extractNullBoundaryXValues(waveDataDetail0.getInstantData().getAValue());
for (WaveDataDetail waveDataDetail : waveDataDetails) { for (WaveDataDetail waveDataDetail : waveDataDetails) {
if (waveDataDetail.getChannelName().toUpperCase().startsWith("SU")) { if (waveDataDetail.getChannelName().toUpperCase().startsWith("SU")) {
firstPic = drawPicUtil.drawWavePic("电压-电网侧", waveDataDetail.getInstantData().getAValue(), firstPic = drawPicUtil.drawWavePic("电压-电网侧", waveDataDetail.getInstantData().getAValue(),
waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(), waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(), waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen() waveDataDetail.getColors(), waveDataDetail.getIsOpen(),lastTime,sharedNullBoundaries,nPush
); );
} else if (waveDataDetail.getChannelName().toUpperCase().startsWith("SI")) { } else if (waveDataDetail.getChannelName().toUpperCase().startsWith("SI")) {
thirdPic = drawPicUtil.drawWavePic("电流-电网侧", waveDataDetail.getInstantData().getAValue(), thirdPic = drawPicUtil.drawWavePic("电流-电网侧", waveDataDetail.getInstantData().getAValue(),
waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(), waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(), waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen() waveDataDetail.getColors(), waveDataDetail.getIsOpen(),lastTime,sharedNullBoundaries,nPush
); );
} else if (waveDataDetail.getChannelName().toUpperCase().startsWith("LU")) { } else if (waveDataDetail.getChannelName().toUpperCase().startsWith("LU")) {
secondPic = drawPicUtil.drawWavePic("电压-负载侧", waveDataDetail.getInstantData().getAValue(), secondPic = drawPicUtil.drawWavePic("电压-负载侧", waveDataDetail.getInstantData().getAValue(),
waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(), waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(), waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen() waveDataDetail.getColors(), waveDataDetail.getIsOpen(),lastTime,sharedNullBoundaries,nPush
); );
} else { } else {
forthPic = drawPicUtil.drawWavePic("电流-负载侧", waveDataDetail.getInstantData().getAValue(), forthPic = drawPicUtil.drawWavePic("电流-负载侧", waveDataDetail.getInstantData().getAValue(),
waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(), waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(), waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen() waveDataDetail.getColors(), waveDataDetail.getIsOpen(),lastTime,sharedNullBoundaries,nPush
); );
} }
} }
@@ -91,36 +89,39 @@ public class WavePicComponent {
* @date 2023/9/21 15:32 * @date 2023/9/21 15:32
* @return String 文件地址 * @return String 文件地址
*/ */
public String generateRmsImageZl(List<WaveDataDetail> waveDataDetails) { public String generateRmsImageZl(Integer nPush, List<WaveDataDetail> waveDataDetails, Double lastTime) {
String firstPic = null, secondPic = null, thirdPic = null, forthPic = null; String firstPic = null, secondPic = null, thirdPic = null, forthPic = null;
WaveDataDetail waveDataDetail0 = waveDataDetails.get(0);
// 从instantData提取null边界x值作为共享参考与Shun图保持一致
List<Float> sharedNullBoundaries = LineGenerator.extractNullBoundaryXValues(waveDataDetail0.getInstantData().getAValue());
for (WaveDataDetail waveDataDetail : waveDataDetails) { for (WaveDataDetail waveDataDetail : waveDataDetails) {
if (waveDataDetail.getChannelName().toUpperCase().startsWith("SU")) { if (waveDataDetail.getChannelName().toUpperCase().startsWith("SU")) {
firstPic = drawPicUtil.drawWavePic("电压-电网侧", waveDataDetail.getRmsData().getAValue(), firstPic = drawPicUtil.drawWavePic("电压-电网侧", waveDataDetail.getRmsData().getAValue(),
waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(), waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(), waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen() waveDataDetail.getColors(), waveDataDetail.getIsOpen(),lastTime,sharedNullBoundaries,nPush
); );
} else if (waveDataDetail.getChannelName().toUpperCase().startsWith("SI")) { } else if (waveDataDetail.getChannelName().toUpperCase().startsWith("SI")) {
thirdPic = drawPicUtil.drawWavePic("电流-电网侧", waveDataDetail.getRmsData().getAValue(), thirdPic = drawPicUtil.drawWavePic("电流-电网侧", waveDataDetail.getRmsData().getAValue(),
waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(), waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(), waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen() waveDataDetail.getColors(), waveDataDetail.getIsOpen(),lastTime,sharedNullBoundaries,nPush
); );
} else if (waveDataDetail.getChannelName().toUpperCase().startsWith("LU")) { } else if (waveDataDetail.getChannelName().toUpperCase().startsWith("LU")) {
secondPic = drawPicUtil.drawWavePic("电压-负载侧", waveDataDetail.getRmsData().getAValue(), secondPic = drawPicUtil.drawWavePic("电压-负载侧", waveDataDetail.getRmsData().getAValue(),
waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(), waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(), waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen() waveDataDetail.getColors(), waveDataDetail.getIsOpen(),lastTime,sharedNullBoundaries,nPush
); );
} else { } else {
forthPic = drawPicUtil.drawWavePic("电流-负载侧", waveDataDetail.getRmsData().getAValue(), forthPic = drawPicUtil.drawWavePic("电流-负载侧", waveDataDetail.getRmsData().getAValue(),
waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(), waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(), waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen() waveDataDetail.getColors(), waveDataDetail.getIsOpen(),lastTime,sharedNullBoundaries,nPush
); );
} }
} }
@@ -209,6 +210,47 @@ public class WavePicComponent {
return picPath; return picPath;
} }
/***
* 绘制瞬时波形图 App端用来绘制图片会去掉部分数据只保留开始数据 结束数据
* @author xy
* @return String 文件地址
*/
public String generateImageShun(Integer nPush, List<WaveDataDetail> waveDataDetails, Double lastTime) {
String picPath = null;
WaveDataDetail waveDataDetail = waveDataDetails.get(0);
// 从instantData提取null边界x值作为共享参考
List<Float> sharedNullBoundaries = LineGenerator.extractNullBoundaryXValues(waveDataDetail.getInstantData().getAValue());
String firstPic = drawPicUtil.drawWavePic(getTitle(waveDataDetail.getChannelName()), waveDataDetail.getInstantData().getAValue(),
waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen(), lastTime, sharedNullBoundaries,nPush
);
String secondPic;
if (waveDataDetails.size() == 1) {
if (firstPic.contains(PicCommonData.PNG_PREFIX)) {
firstPic = firstPic.replace(PicCommonData.PNG_PREFIX, "");
}
byte[] bytes = Base64.getDecoder().decode(firstPic);
picPath = fileStorageUtil.uploadStream(new ByteArrayInputStream(bytes), OssPath.EVENT_WAVE_PIC, FileUtil.generateFileName("png"));
} else if (waveDataDetails.size() == 2) {
waveDataDetail = waveDataDetails.get(1);
secondPic = drawPicUtil.drawWavePic(getTitle(waveDataDetail.getChannelName()), waveDataDetail.getInstantData().getAValue(),
waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen(), lastTime, sharedNullBoundaries,nPush
);
picPath = composeImage(firstPic, secondPic);
}
return picPath;
}
public String getTitle(String channelName) {
return channelName.toUpperCase().startsWith("U1") ? "电压" : "电流";
}
/*** /***
* 绘制RMS波形图 * 绘制RMS波形图
* @author hongawen * @author hongawen
@@ -248,6 +290,44 @@ public class WavePicComponent {
return picPath; return picPath;
} }
/***
* 绘制RMS波形图 App端用来绘制图片会去掉部分数据只保留开始数据 结束数据
* @author xy
* @return String 文件地址
*/
public String generateImageRms(Integer nPush, List<WaveDataDetail> waveDataDetails, Double lastTime) {
String picPath = null;
WaveDataDetail waveDataDetail = waveDataDetails.get(0);
// 从instantData提取null边界x值作为共享参考与Shun图保持一致
List<Float> sharedNullBoundaries = LineGenerator.extractNullBoundaryXValues(waveDataDetail.getInstantData().getAValue());
String firstPic = drawPicUtil.drawWavePic(getTitle(waveDataDetail.getChannelName()), waveDataDetail.getRmsData().getAValue(),
waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen(), lastTime, sharedNullBoundaries,nPush
);
String secondPic;
if (waveDataDetails.size() == 1) {
if (firstPic.contains(PicCommonData.PNG_PREFIX)) {
firstPic = firstPic.replace(PicCommonData.PNG_PREFIX, "");
}
byte[] bytes = Base64.getDecoder().decode(firstPic);
picPath = fileStorageUtil.uploadStream(new ByteArrayInputStream(bytes), OssPath.EVENT_WAVE_PIC, FileUtil.generateFileName("png"));
} else if (waveDataDetails.size() == 2) {
waveDataDetail = waveDataDetails.get(1);
secondPic = drawPicUtil.drawWavePic(getTitle(waveDataDetail.getChannelName()), waveDataDetail.getRmsData().getAValue(),
waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(),
waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(),
waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(),
waveDataDetail.getColors(), waveDataDetail.getIsOpen(), lastTime, sharedNullBoundaries,nPush
);
picPath = composeImage(firstPic, secondPic);
}
return picPath;
}
/*** /***
* 合成图片 * 合成图片
* @author hongawen * @author hongawen

View File

@@ -7,6 +7,7 @@ import com.njcn.event.file.pojo.dto.WaveDataDTO;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* @author hongawen * @author hongawen
@@ -80,28 +81,49 @@ public class WaveUtil {
//根据相别来确认标题的名称 //根据相别来确认标题的名称
for (int m = 0; m < iPhase; m++) { for (int m = 0; m < iPhase; m++) {
if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("A")) { if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("A")) {
float tmpShunFirstA = sunData.get(j).get(iPhase * i + m + 1) * xishu; if (Objects.isNull(sunData.get(j).get(iPhase * i + m + 1))) {
shunFirstA = tmpShunFirstA; sAValue.add(new ArrayList<Float>() {{
sAValue.add(new ArrayList<Float>() {{ add(x);
add(x); add(null);
add(tmpShunFirstA); }});
}}); } else {
float tmpShunFirstA = sunData.get(j).get(iPhase * i + m + 1) * xishu;
shunFirstA = tmpShunFirstA;
sAValue.add(new ArrayList<Float>() {{
add(x);
add(tmpShunFirstA);
}});
}
} }
if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("B")) { if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("B")) {
float tmpShunFirstB = sunData.get(j).get(iPhase * i + m + 1) * xishu; if (Objects.isNull(sunData.get(j).get(iPhase * i + m + 1))) {
shunFirstB = tmpShunFirstB; sBValue.add(new ArrayList<Float>() {{
sBValue.add(new ArrayList<Float>() {{ add(x);
add(x); add(null);
add(tmpShunFirstB); }});
}}); } else {
float tmpShunFirstB = sunData.get(j).get(iPhase * i + m + 1) * xishu;
shunFirstB = tmpShunFirstB;
sBValue.add(new ArrayList<Float>() {{
add(x);
add(tmpShunFirstB);
}});
}
} }
if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("C")) { if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("C")) {
float tmpShunFirstC = sunData.get(j).get(iPhase * i + m + 1) * xishu; if (Objects.isNull(sunData.get(j).get(iPhase * i + m + 1))) {
shunFirstC = tmpShunFirstC; sCValue.add(new ArrayList<Float>() {{
sCValue.add(new ArrayList<Float>() {{ add(x);
add(x); add(null);
add(tmpShunFirstC); }});
}}); } else {
float tmpShunFirstC = sunData.get(j).get(iPhase * i + m + 1) * xishu;
shunFirstC = tmpShunFirstC;
sCValue.add(new ArrayList<Float>() {{
add(x);
add(tmpShunFirstC);
}});
}
} }
} }
sfMax = getMax(sfMax, shunFirstA, shunFirstB, shunFirstC); sfMax = getMax(sfMax, shunFirstA, shunFirstB, shunFirstC);
@@ -124,28 +146,50 @@ public class WaveUtil {
//根据相别来确认标题的名称 //根据相别来确认标题的名称
for (int m = 0; m < iPhase; m++) { for (int m = 0; m < iPhase; m++) {
if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("A")) { if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("A")) {
float tmpRmsFirstA = rmsData.get(k).get(iPhase * i + m + 1) * xishu; if (Objects.isNull(rmsData.get(k).get(iPhase * i + m + 1))) {
rmsFirstA = tmpRmsFirstA; rAValue.add(new ArrayList<Float>() {{
rAValue.add(new ArrayList<Float>() {{ add(x);
add(x); add(null);
add(tmpRmsFirstA); }});
}}); } else {
float tmpRmsFirstA = rmsData.get(k).get(iPhase * i + m + 1) * xishu;
rmsFirstA = tmpRmsFirstA;
rAValue.add(new ArrayList<Float>() {{
add(x);
add(tmpRmsFirstA);
}});
}
} }
if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("B")) { if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("B")) {
float tmpRmsFirstB = rmsData.get(k).get(iPhase * i + m + 1) * xishu; if (Objects.isNull(rmsData.get(k).get(iPhase * i + m + 1))) {
rmsFirstB = tmpRmsFirstB; rBValue.add(new ArrayList<Float>() {{
rBValue.add(new ArrayList<Float>() {{ add(x);
add(x); add(null);
add(tmpRmsFirstB); }});
}}); } else {
float tmpRmsFirstB = rmsData.get(k).get(iPhase * i + m + 1) * xishu;
rmsFirstB = tmpRmsFirstB;
rBValue.add(new ArrayList<Float>() {{
add(x);
add(tmpRmsFirstB);
}});
}
} }
if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("C")) { if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("C")) {
float tmpRmsFirstC = rmsData.get(k).get(iPhase * i + m + 1) * xishu; if (Objects.isNull(rmsData.get(k).get(iPhase * i + m + 1))) {
rmsFirstC = tmpRmsFirstC; rCValue.add(new ArrayList<Float>() {{
rCValue.add(new ArrayList<Float>() {{ add(x);
add(x); add(null);
add(tmpRmsFirstC); }});
}}); } else {
float tmpRmsFirstC = rmsData.get(k).get(iPhase * i + m + 1) * xishu;
rmsFirstC = tmpRmsFirstC;
rCValue.add(new ArrayList<Float>() {{
add(x);
add(tmpRmsFirstC);
}});
}
} }
} }
rfMax = getMax(sfMax, rmsFirstA, rmsFirstB, rmsFirstC); rfMax = getMax(sfMax, rmsFirstA, rmsFirstB, rmsFirstC);

View File

@@ -1,5 +1,8 @@
package com.njcn.web.utils; package com.njcn.web.utils;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.*; import org.springframework.http.*;
@@ -149,7 +152,8 @@ public class RestTemplateUtil {
* @return ResponseEntity 响应对象封装类 * @return ResponseEntity 响应对象封装类
*/ */
public static <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType) { public static <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType) {
return restTemplate.postForEntity(url, requestBody, responseType); Object actualBody = convertHutoolJsonToStandard(requestBody);
return restTemplate.postForEntity(url, actualBody, responseType);
} }
/** /**
@@ -162,7 +166,8 @@ public class RestTemplateUtil {
* @return ResponseEntity 响应对象封装类 * @return ResponseEntity 响应对象封装类
*/ */
public static <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType, Object... uriVariables) { public static <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType, Object... uriVariables) {
return restTemplate.postForEntity(url, requestBody, responseType, uriVariables); Object actualBody = convertHutoolJsonToStandard(requestBody);
return restTemplate.postForEntity(url, actualBody, responseType, uriVariables);
} }
/** /**
@@ -175,7 +180,21 @@ public class RestTemplateUtil {
* @return ResponseEntity 响应对象封装类 * @return ResponseEntity 响应对象封装类
*/ */
public static <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) { public static <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
return restTemplate.postForEntity(url, requestBody, responseType, uriVariables); Object actualBody = convertHutoolJsonToStandard(requestBody);
return restTemplate.postForEntity(url, actualBody, responseType, uriVariables);
}
private static Object convertHutoolJsonToStandard(Object requestBody) {
if (requestBody instanceof JSONObject || requestBody instanceof JSONArray) {
try {
com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
return objectMapper.readValue(JSONUtil.toJsonStr(requestBody), Object.class);
} catch (Exception e) {
log.warn("Hutool JSON转标准结构失败尝试直接使用字符串", e);
return requestBody;
}
}
return requestBody;
} }
/** /**

View File

@@ -20,6 +20,13 @@ public interface CommMonitorEventReportService {
void getLineExport(ExportParam exportParam, LineDetailDataCommDTO lineDetailDataCommDTO, HttpServletResponse response); void getLineExport(ExportParam exportParam, LineDetailDataCommDTO lineDetailDataCommDTO, HttpServletResponse response);
/**
* 暂降事件报告
* @param exportParam
* @param lineDetailDataCommDTO
* @param response
*/
void getWlLineExport(ExportParam exportParam, LineDetailDataCommDTO lineDetailDataCommDTO, HttpServletResponse response);
/** /**
* 暂态事件报告 * 暂态事件报告

View File

@@ -479,6 +479,389 @@ public class CommMonitorEventReportServiceImpl implements CommMonitorEventReport
} }
@Override
public void getWlLineExport(ExportParam exportParam, LineDetailDataCommDTO lineDetailData, HttpServletResponse response) {
//创建word文档(poi生成word)
XWPFDocument doc = new XWPFDocument(); //创建Word文件
//设置标题样式
WordUtils.setHeadingStyle(doc);
XWPFParagraph p = doc.createParagraph(); //新建一个段落
//设置对齐
p.setAlignment(ParagraphAlignment.CENTER);
p.setVerticalAlignment(TextAlignment.CENTER);
XWPFRun r = p.createRun();//创建段落文本
r.addBreak();
r.addBreak();
r.addBreak();
r.addBreak();
r.addBreak();
r.addBreak();
r.setText("");
r.setBold(true);//设置为粗体
r.setFontSize(14);//字体大小
r.addBreak();
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.CENTER);
XWPFRun r1 = p.createRun();//创建段落文本
r1.setText("电压暂降事件分析报告");
r1.setBold(true);//设置为粗体
r1.setFontSize(36);//字体大小
r1.addBreak();
r1.addBreak();
r1.addBreak();
r1.addBreak();
r1.addBreak();
r1.addBreak();
r1.addBreak();
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.CENTER);
XWPFRun r2 = p.createRun();//创建段落文本
//获取当前时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy 年 MM 月 dd 日");
String time = dateFormat.format(date);
r2.setText("日期: " + time);
r2.setBold(true);//设置为粗体
r2.setFontSize(14);//字体大小
r2.addBreak();
r2.addBreak();
r2.addBreak();
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.CENTER);
XWPFRun r3 = p.createRun();//创建段落文本
r3.setText("电压暂降事件区域报告");
r3.setFontSize(24);//字体大小
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.LEFT);
createTitle(doc, "1. 引言", "标题 1", 0, 15);
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.BOTH);
XWPFRun r5 = p.createRun();//创建段落文本
r5.setText("对所选中区间内电压暂降事件进行分析,能够直观清晰查看响应的暂降事件信息。");
r5.setFontSize(11);//字体大小
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.LEFT);
createTitle(doc, "2. 报告分析对象", "标题 1", 0, 15);
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.BOTH);
XWPFRun r7 = p.createRun();//创建段落文本
r7.setText(exportParam.getLineName());
r7.setFontSize(11);//字体大小
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.LEFT);
createTitle(doc, "3. 报告分析时间", "标题 1", 0, 15);
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.BOTH);
XWPFRun r9 = p.createRun();//创建段落文本
r9.setText(exportParam.getSearchBeginTime() + "" + exportParam.getSearchEndTime());
r9.setFontSize(11);//字体大小
p = doc.createParagraph(); //新建一个段落
p.setAlignment(ParagraphAlignment.LEFT);
createTitle(doc, "4. 总汇信息", "标题 1", 0, 15);
//查询参数
StatisticsParam param = new StatisticsParam(exportParam.getLineId(), exportParam.getSearchBeginTime(), exportParam.getSearchEndTime(), exportParam.getFlag());
//获取暂降原因字典
List<DictData> reasonData = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.EVENT_REASON.getName()).getData();
//获取暂降类型字典
List<DictData> typeData = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.EVENT_TYPE.getName()).getData();
//influxdb查询结果pqs_eventdetail表
List<EventDetail> info = info(param, true);
//记录数
int i = 1;
//1.监测点信息
if (exportParam.isXq()) {
createTitle(doc, "4." + i + " 监测点信息", "标题 2", 200, 15);
XWPFTable table = createTable(doc);
XWPFParagraph centerParagraph = WordUtils.getCenterParagraph(doc);
insertRow(doc, table, centerParagraph, true, "项目", "描述");
insertRow(doc, table, centerParagraph, false, "监测点名称", lineDetailData.getLineName());
insertRow(doc, table, centerParagraph, false, "电压等级", lineDetailData.getScale());
insertRow(doc, table, centerParagraph, false, "PT变比", lineDetailData.getPt());
insertRow(doc, table, centerParagraph, false, "CT变比", lineDetailData.getCt());
insertRow(doc, table, centerParagraph, false, "协议容量", lineDetailData.getDealCapacity() + "");
insertRow(doc, table, centerParagraph, false, "设备容量", lineDetailData.getDevCapacity() + "");
insertRow(doc, table, centerParagraph, false, "最小短路容量", lineDetailData.getShortCapacity() + "");
insertRow(doc, table, centerParagraph, false, "接线方式", lineDetailData.getPtType());
if (exportParam.getType() == 0) {
insertRow(doc, table, centerParagraph, false, "基准容量", lineDetailData.getStandardCapacity() + "");
}
i++;
}
//2.暂降事件暂降事件列表和暂降点图
//2.1.判断列表和点图是否是要导出
if (exportParam.isLb() || exportParam.isSjdF47() || exportParam.isSjdITIC()) {
List<EventDetail> plot = eventReportService.getPlot(info, reasonData, typeData);
//暂降事件列表
if (exportParam.isLb()) {
createTitle(doc, "4." + i + " 暂降事件列表", "标题 2", 200, 15);
XWPFTable table = createTable(doc);
XWPFParagraph centerParagraph = WordUtils.getCenterParagraph(doc);
insertRow(doc, table, centerParagraph, true, "序号", "暂降发生时刻", "暂降幅值(%)", "持续时间(s)", "暂降类型", "暂降原因", "严重度");
for (int j = 0; j < plot.size(); j++) {
EventDetail eventDetail = plot.get(j);
String s = eventDetail.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
insertRow(doc, table, centerParagraph, false, j + 1 + "", s, BigDecimal.valueOf(eventDetail.getFeatureAmplitude() * 100).setScale(2, RoundingMode.HALF_UP).toString(), eventDetail.getDuration() + "", Objects.isNull(eventDetail.getAdvanceType()) ? "/" : eventDetail.getAdvanceType(), Objects.isNull(eventDetail.getAdvanceReason()) ? "/" : eventDetail.getAdvanceReason(), Objects.isNull(eventDetail.getSeverity()) ? "/" : eventDetail.getSeverity() + "");
}
i++;
}
//暂降事件点图
if (exportParam.isSjdF47() || exportParam.isSjdITIC()) {
ArrayList<List<Double>> ass = getAss(plot);
createTitle(doc, "4." + i + " 暂降事件点图", "标题 2", 200, 15);
int two = 1;
if (exportParam.isSjdITIC()) {
createTitle(doc, "4." + i + "." + two + " ITIC 曲线", "标题 3", 400, 15);
String itic = drawPicUtil.drawItic(ass);
createPic(doc, itic, "ITIC曲线");
two++;
}
if (exportParam.isSjdF47()) {
createTitle(doc, "4." + i + "." + two + " F47 曲线", "标题 3", 400, 15);
String f47 = drawPicUtil.drawF47(ass);
createPic(doc, f47, "SEMI F47曲线");
two++;
}
i++;
}
}
//3.暂降密度
if (exportParam.isMdbg() || exportParam.isMdtx()) {
createTitle(doc, "4." + i + " 暂降密度", "标题 2", 200, 15);
int two = 1;
if (exportParam.isMdtx()) {
createTitle(doc, "4." + i + "." + two + " 暂降密度点图", "标题 3", 400, 15);
Integer[][] eventDensityData = eventReportService.getCoords(info);
String str = drawPicUtil.drawEventDensity(eventDensityData);
createPic(doc, str, "暂降密度图");
two++;
}
if (exportParam.isMdbg()) {
XWPFParagraph centerParagraph = WordUtils.getCenterParagraph(doc);
createTitle(doc, "4." + i + "." + two + " DISDIP 表格:国际发配电联盟(UNIPEDE)", "标题 3", 400, 15);
// List<DISDIPVO> eventDisdip = eventAnalysisService.eventDisdip(new StatisticsParam(exportParam.getLineId(), exportParam.getSearchBeginTime(), exportParam.getSearchEndTime(),exportParam.getFlag()));
List<DISDIPVO> eventDisdip = eventReportService.eventDisdip(info);
XWPFTable table1 = createTable(doc);
insertRow(doc, table1, centerParagraph, true, "剩余电压", "20ms", "100ms", "500ms", "1s", "3s", "20s", "60s", "180s");
for (int j = 0; j < eventDisdip.size(); j++) {
DISDIPVO disdipvo = eventDisdip.get(j);
insertRow(doc, table1, centerParagraph, false, disdipvo.getName(), disdipvo.getTwentyMs(), disdipvo.getOneHundredMs(), disdipvo.getFiveHundredMs(), disdipvo.getOneS(), disdipvo.getThreeS(), disdipvo.getTwentyS(), disdipvo.getSixtyS(), disdipvo.getOneEightyS());
}
two++;
createTitle(doc, "4." + i + "." + two + " IEC 61000-4-11:(用电终端的电压暂降抗度)", "标题 3", 400, 15);
// List<IEC411VO> iec411VOS = eventAnalysisService.IEC411(new StatisticsParam(exportParam.getLineId(), exportParam.getSearchBeginTime(), exportParam.getSearchEndTime(),exportParam.getFlag()));
List<IEC411VO> iec411VOS = eventReportService.IEC411(info);
XWPFTable table2 = createTable(doc);
insertRow(doc, table2, centerParagraph, true, "剩余电压", "10~20ms", "20~100ms", "0.1~0.2s", "0.2~0.5s", "0.5~1s", ">1s");
for (int j = 0; j < iec411VOS.size(); j++) {
IEC411VO iec411VO = iec411VOS.get(j);
insertRow(doc, table2, centerParagraph, false, iec411VO.getName(), iec411VO.getTenTwentyMs(), iec411VO.getTwentyOneHundredMs(), iec411VO.getZeroPiontOneTwoS(), iec411VO.getZeroPiontTwoFiveS(), iec411VO.getZeroPiontFive1S(), iec411VO.getGreater1S());
}
two++;
createTitle(doc, "4." + i + "." + two + " IEC 61000-2-8:(公共电网电压暂降测量统计)", "标题 3", 400, 15);
// List<IEC28VO> iec28VOS = eventAnalysisService.IEC28(new StatisticsParam(exportParam.getLineId(), exportParam.getSearchBeginTime(), exportParam.getSearchEndTime(),exportParam.getFlag()));
List<IEC28VO> iec28VOS = eventReportService.IEC28(info);
XWPFTable table3 = createTable(doc);
insertRow(doc, table3, centerParagraph, true, "剩余电压", "0.02~0.1s", "0.1~0.25s", "0.25~0.5s", "0.5s~1s", "1~3s", "3~20s", "20~60s", "60~180s");
for (int j = 0; j < iec28VOS.size(); j++) {
IEC28VO iec28VO = iec28VOS.get(j);
insertRow(doc, table3, centerParagraph, false, iec28VO.getName(), iec28VO.getQ(), iec28VO.getW(), iec28VO.getE(), iec28VO.getR(), iec28VO.getT(), iec28VO.getY(), iec28VO.getU(), iec28VO.getI());
}
two++;
}
i++;
}
//4.暂降幅值概率分布
if (exportParam.isGlfbfz() || exportParam.isGlfbsj()) {
createTitle(doc, "4." + i + " 暂降幅值概率分布图", "标题 2", 200, 15);
// ProbabilityVO probabilityVO = eventAnalysisService.getProbabilityDistribution(new StatisticsParam(exportParam.getLineId(), exportParam.getSearchBeginTime(), exportParam.getSearchEndTime(),exportParam.getFlag()));
ProbabilityVO probabilityVO = eventReportService.getProbabilityDistribution(info);
int two = 1;
if (exportParam.isGlfbfz()) {
createTitle(doc, "4." + i + "." + two + " 暂降幅值的概率分函数", "标题 3", 400, 15);
List<String> ybardata = probabilityVO.getPereventvalue();
List<String> ylinedata = probabilityVO.getEventvalue();
String fz = drawPicUtil.drawEventAmplitude(ylinedata, ybardata);
createPic(doc, fz, "暂降幅值的概率分布函数");
two++;
}
if (exportParam.isGlfbsj()) {
createTitle(doc, "4." + i + "." + two + " 持续时间的概率分函数", "标题 3", 400, 15);
List<String> ybardata = probabilityVO.getPersisttime();
List<String> ylinedata = probabilityVO.getSisttime();
String sj = drawPicUtil.drawPersistentTime(ylinedata, ybardata);
createPic(doc, sj, "持续时间的概率分布函数");
two++;
}
i++;
}
//5.月份统计
if (exportParam.isTjbg() || exportParam.isTjtx()) {
createTitle(doc, "4." + i + " 月份统计", "标题 2", 200, 15);
int two = 1;
List<TimeVO> reasonTypeTime = eventAnalysisService.getReasonTypeTime(param);
//暂时时间端按月查询不能查询
// List<TimeVO> reasonTypeTime = eventReportService.getReasonTypeTime(param,null);
if (exportParam.isTjtx()) {
createTitle(doc, "4." + i + "." + two + " 月份统计图", "标题 3", 400, 15);
List<Integer> count = new ArrayList<>();
List<String> name = new ArrayList<>();
if (exportParam.getFlag() == 0) {
for (TimeVO timeVO : reasonTypeTime) {
name.add(timeVO.getMonth() + "");
count.add(Integer.parseInt(timeVO.getTimes()));
}
} else {
for (TimeVO timeVO : reasonTypeTime) {
name.add(timeVO.getDay() + "");
count.add(Integer.parseInt(timeVO.getTimes()));
}
}
String yftj = drawPicUtil.drawMonth(name, count, reasonTypeTime.get(0).getYear(), exportParam.getFlag());
createPic(doc, yftj, "月份统计图");
two++;
}
if (exportParam.isTjbg()) {
XWPFParagraph centerParagraph = WordUtils.getCenterParagraph(doc);
createTitle(doc, "4." + i + "." + two + " 时间统计表格", "标题 3", 400, 15);
XWPFTable table1 = createTable(doc);
if (exportParam.getFlag() == 0) {
insertRow(doc, table1, centerParagraph, true, "时间(月)", "电压暂降次数");
} else {
insertRow(doc, table1, centerParagraph, true, "时间(天)", "电压暂降次数");
}
if (exportParam.getFlag() == 0) {
for (int j = 0; j < reasonTypeTime.size(); j++) {
TimeVO timeVO = reasonTypeTime.get(j);
insertRow(doc, table1, centerParagraph, false, timeVO.getMonth(), timeVO.getTimes());
}
} else {
for (int j = 0; j < reasonTypeTime.size(); j++) {
TimeVO timeVO = reasonTypeTime.get(j);
insertRow(doc, table1, centerParagraph, false, timeVO.getFulltime(), timeVO.getTimes());
}
}
two++;
}
i++;
}
//6.原因统计
//6.1整合提出查询语句
Boolean fly = exportParam.isYybg() || exportParam.isYytx() || exportParam.isLxbg() || exportParam.isLxtx();
if (fly) {
List<DictData> tempDictType = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.EVENT_STATIS.getCode()).getData();
List<String> typeIds = tempDictType.stream().filter(x -> DicDataEnum.VOLTAGE_DIP.getCode().equals(x.getCode()) || DicDataEnum.SHORT_INTERRUPTIONS.getCode().equals(x.getCode()))
.map(DictData::getId).collect(Collectors.toList());
List<EventDetail> tempInfo = info.stream().filter(temp -> typeIds.contains(temp.getEventType())).collect(Collectors.toList());
StatisticVO statistic = eventReportService.getStatistic(tempInfo, reasonData, typeData);
if (exportParam.isYybg() || exportParam.isYytx()) {
createTitle(doc, "4." + i + " 原因统计", "标题 2", 200, 15);
// StatisticVO statistic = eventAnalysisService.getStatistic(new StatisticsParam(exportParam.getLineId(), exportParam.getSearchBeginTime(), exportParam.getSearchEndTime(),exportParam.getFlag()));
int two = 1;
if (exportParam.isYytx()) {
createTitle(doc, "4." + i + "." + two + " 原因统计图", "标题 3", 400, 15);
List<String> xdata = new ArrayList<>();
List<Map<String, Object>> reasonList = new ArrayList<>();
List<ReasonsVO> reason = statistic.getReason();
for (ReasonsVO reasonsVO : reason) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("value", reasonsVO.getTimes());
map.put("name", reasonsVO.getReason());
reasonList.add(map);
xdata.add(reasonsVO.getReason());
}
String tr = drawPicUtil.drawReason(xdata, reasonList);
createPic(doc, tr, "暂降原因图");
two++;
}
if (exportParam.isYybg()) {
XWPFParagraph centerParagraph = WordUtils.getCenterParagraph(doc);
createTitle(doc, "4." + i + "." + two + " 原因统计表格", "标题 3", 400, 15);
XWPFTable table1 = createTable(doc);
insertRow(doc, table1, centerParagraph, true, "暂降原因", "电压暂降次数");
List<ReasonsVO> reason = statistic.getReason();
for (int j = 0; j < reason.size(); j++) {
ReasonsVO reasonsVO = reason.get(j);
insertRow(doc, table1, centerParagraph, false, reasonsVO.getReason(), reasonsVO.getTimes() + "");
}
two++;
}
i++;
}
//7.类型统计
if (exportParam.isLxbg() || exportParam.isLxtx()) {
createTitle(doc, "4." + i + " 类型统计", "标题 2", 200, 15);
// StatisticVO statistic = eventAnalysisService.getStatistic(new StatisticsParam(exportParam.getLineId(), exportParam.getSearchBeginTime(), exportParam.getSearchEndTime(),exportParam.getFlag()));
int two = 1;
if (exportParam.isLxtx()) {
createTitle(doc, "4." + i + "." + two + " 类型统计图", "标题 3", 400, 15);
List<String> xdata = new ArrayList<>();
List<TypesVO> types = statistic.getTypes();
List<Map<String, Object>> reasonList = new ArrayList<>();
for (TypesVO type : types) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("value", type.getTimes());
map.put("name", type.getType());
reasonList.add(map);
xdata.add(type.getType());
}
String tr = drawPicUtil.drawType(xdata, reasonList);
createPic(doc, tr, "暂降类型图");
two++;
}
if (exportParam.isLxbg()) {
createTitle(doc, "4." + i + "." + two + " 类型统计表格", "标题 3", 400, 15);
XWPFParagraph centerParagraph = WordUtils.getCenterParagraph(doc);
XWPFTable table1 = createTable(doc);
insertRow(doc, table1, centerParagraph, true, "暂降原因", "电压暂降次数");
List<TypesVO> types = statistic.getTypes();
for (int j = 0; j < types.size(); j++) {
TypesVO typesVO = types.get(j);
insertRow(doc, table1, centerParagraph, false, typesVO.getType(), typesVO.getTimes() + "");
}
two++;
}
i++;
}
}
try {
ServletOutputStream outputStream = response.getOutputStream();
String fileName = URLEncoder.encode(exportParam.getLineName() + ".docx", "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
response.setContentType("application/octet-stream;charset=UTF-8");
doc.write(outputStream);
outputStream.close();
} catch (Exception e) {
throw new BusinessException(CommonResponseEnum.FAIL, "导出监测点暂降报告异常");
}
}
/** /**
* 创建标题 * 创建标题
@@ -598,6 +981,23 @@ public class CommMonitorEventReportServiceImpl implements CommMonitorEventReport
return BeanUtil.copyToList(info, EventDetail.class); return BeanUtil.copyToList(info, EventDetail.class);
} }
private List<EventDetail> info(StatisticsParam statisticsParam, Boolean dip) {
// 构建查询条件
LambdaQueryWrapper<RmpEventDetailPO> queryWrapper = new LambdaQueryWrapper<RmpEventDetailPO>()
.eq(RmpEventDetailPO::getMeasurementPointId, statisticsParam.getLineIndex())
.ge(StrUtil.isNotBlank(statisticsParam.getStartTime()), RmpEventDetailPO::getStartTime, DateUtil.beginOfDay(DateUtil.parse(statisticsParam.getStartTime())))
.le(StrUtil.isNotBlank(statisticsParam.getEndTime()), RmpEventDetailPO::getStartTime, DateUtil.endOfDay(DateUtil.parse(statisticsParam.getEndTime())))
.orderByDesc(RmpEventDetailPO::getStartTime);
if (dip) {
List<DictData> data = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.EVENT_STATIS.getCode()).getData();
List<String> typeList = data.stream().filter(it->it.getCode().equals(DicDataEnum.VOLTAGE_DIP.getCode()) || it.getCode().equals(DicDataEnum.SHORT_INTERRUPTIONS.getCode())).map(DictData::getId).collect(Collectors.toList()); List<TimeVO> list = new ArrayList<>();
queryWrapper.in(RmpEventDetailPO::getEventType, typeList);
}
// 数据暂降查询
List<RmpEventDetailPO> info = rmpEventDetailMapper.selectList(queryWrapper);
return BeanUtil.copyToList(info, EventDetail.class);
}
/** /**
* 生成暂降事件报告 * 生成暂降事件报告