feat(rstatlimitrate): 添加越限程度、日趋势图和日历数据查询接口

This commit is contained in:
贾同学
2025-11-14 16:30:17 +08:00
parent 9d32ca05df
commit 9659aa257a
12 changed files with 1186 additions and 6 deletions

View File

@@ -0,0 +1,62 @@
package com.njcn.harmonic.rstatlimitrate.controller;
import cn.hutool.json.JSONArray;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.enums.common.LogEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.HttpResultUtil;
import com.njcn.harmonic.pojo.param.LimitCalendarQueryParam;
import com.njcn.harmonic.pojo.param.LimitExtentDayQueryParam;
import com.njcn.harmonic.pojo.param.LimitExtentQueryParam;
import com.njcn.harmonic.pojo.vo.LimitCalendarVO;
import com.njcn.harmonic.pojo.vo.LimitExtentVO;
import com.njcn.harmonic.rstatlimitrate.service.IRStatLimitRateDetailDService;
import com.njcn.web.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Validated
@RestController
@RequiredArgsConstructor
@Api(tags = "合格率统计日表详细(越限详情)")
public class RStatLimitRateDetailDController extends BaseController {
private final IRStatLimitRateDetailDService limitRateDetailDService;
@PostMapping("/limitRateDetailD/limitExtentData")
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
@ApiOperation("获取指标越限程度数据")
public HttpResult<List<LimitExtentVO>> limitExtentData(@RequestBody LimitExtentQueryParam queryParam) {
String methodDescribe = getMethodDescribe("limitExtentData");
List<LimitExtentVO> result = limitRateDetailDService.limitExtentData(queryParam);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
@PostMapping("/limitRateDetailD/limitExtentDayData")
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
@ApiOperation("获取指标日趋势图数据")
public HttpResult<JSONArray> limitExtentDayData(@RequestBody LimitExtentDayQueryParam queryParam) {
String methodDescribe = getMethodDescribe("limitExtentDayData");
JSONArray result = limitRateDetailDService.limitExtentDayData(queryParam);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
@PostMapping("/limitRateDetailD/limitCalendarData")
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
@ApiOperation("获取指标越限明细日历数据")
public HttpResult<List<LimitCalendarVO>> limitCalendarData(@RequestBody LimitCalendarQueryParam queryParam) {
String methodDescribe = getMethodDescribe("limitCalendarData");
List<LimitCalendarVO> result = limitRateDetailDService.limitCalendarData(queryParam);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
}

View File

@@ -0,0 +1,9 @@
package com.njcn.harmonic.rstatlimitrate.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDetailDPO;
public interface RStatLimitRateDetailDMapper extends BaseMapper<RStatLimitRateDetailDPO> {
}

View File

@@ -0,0 +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.rstatlimitrate.mapper.RStatLimitRateDetailDMapper">
</mapper>

View File

@@ -0,0 +1,23 @@
package com.njcn.harmonic.rstatlimitrate.service;
import cn.hutool.json.JSONArray;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.harmonic.pojo.param.LimitCalendarQueryParam;
import com.njcn.harmonic.pojo.param.LimitExtentDayQueryParam;
import com.njcn.harmonic.pojo.param.LimitExtentQueryParam;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDetailDPO;
import com.njcn.harmonic.pojo.vo.LimitCalendarVO;
import com.njcn.harmonic.pojo.vo.LimitExtentVO;
import java.util.List;
public interface IRStatLimitRateDetailDService extends IService<RStatLimitRateDetailDPO> {
List<LimitExtentVO> limitExtentData(LimitExtentQueryParam param);
JSONArray limitExtentDayData(LimitExtentDayQueryParam param);
List<LimitCalendarVO> limitCalendarData(LimitCalendarQueryParam param);
}

View File

@@ -0,0 +1,379 @@
package com.njcn.harmonic.rstatlimitrate.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.csdevice.api.CsLineFeignClient;
import com.njcn.csdevice.pojo.po.CsLinePO;
import com.njcn.device.biz.pojo.po.Overlimit;
import com.njcn.device.pq.api.OverLimitClient;
import com.njcn.harmonic.pojo.param.LimitCalendarQueryParam;
import com.njcn.harmonic.pojo.param.LimitExtentDayQueryParam;
import com.njcn.harmonic.pojo.param.LimitExtentQueryParam;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDetailDPO;
import com.njcn.harmonic.pojo.vo.LimitCalendarVO;
import com.njcn.harmonic.pojo.vo.LimitExtentVO;
import com.njcn.harmonic.rstatlimitrate.mapper.RStatLimitRateDetailDMapper;
import com.njcn.harmonic.rstatlimitrate.service.IRStatLimitRateDetailDService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
@RequiredArgsConstructor
@Service
public class RStatLimitRateDetailDServiceImpl extends ServiceImpl<RStatLimitRateDetailDMapper, RStatLimitRateDetailDPO> implements IRStatLimitRateDetailDService {
private final CsLineFeignClient csLineFeignClient;
private final OverLimitClient overLimitClient;
@Override
public List<LimitExtentVO> limitExtentData(LimitExtentQueryParam param) {
List<LimitExtentVO> result = new ArrayList<>();
LimitExtentVO flicker = new LimitExtentVO();
flicker.setCode("flicker");
flicker.setName("闪变");
LimitExtentVO uharm = new LimitExtentVO();
uharm.setCode("uharm");
uharm.setName("谐波电压");
LimitExtentVO iharm = new LimitExtentVO();
iharm.setCode("iharm");
iharm.setName("谐波电流");
LimitExtentVO voltageDev = new LimitExtentVO();
voltageDev.setCode("voltageDev");
voltageDev.setName("电压偏差");
LimitExtentVO ubalance = new LimitExtentVO();
ubalance.setCode("ubalance");
ubalance.setName("电压三相不平衡");
List<RStatLimitRateDetailDPO> detailList = this.list(new LambdaQueryWrapper<RStatLimitRateDetailDPO>()
.ge(StrUtil.isNotBlank(param.getSearchBeginTime()), RStatLimitRateDetailDPO::getTime, param.getSearchBeginTime())
.le(StrUtil.isNotBlank(param.getSearchEndTime()), RStatLimitRateDetailDPO::getTime, param.getSearchEndTime())
.orderByAsc(RStatLimitRateDetailDPO::getTime)
);
if (CollUtil.isNotEmpty(detailList)) {
List<String> lineIds = detailList.stream().map(RStatLimitRateDetailDPO::getLineId).distinct().collect(Collectors.toList());
List<Overlimit> overlimitList = overLimitClient.getOverLimitByLineIds(lineIds).getData();
Map<String, Pair<Float, RStatLimitRateDetailDPO>> findResult = findMaxValueHandle(detailList);
// 闪变
Pair<Float, RStatLimitRateDetailDPO> flickerResult = findResult.get(flicker.getCode());
setLimitExtentInfo(flicker, flickerResult);
// 电压偏差
Pair<Float, RStatLimitRateDetailDPO> voltageDevResult = findResult.get(voltageDev.getCode());
setLimitExtentInfo(voltageDev, voltageDevResult);
// 谐波电压
String uharmKey = findResult.keySet().stream().filter(code -> code.startsWith("uharm")).findFirst().orElse("uharm");
Pair<Float, RStatLimitRateDetailDPO> uharmResult = findResult.get(uharmKey);
setLimitExtentInfo(uharm, uharmResult);
uharm.setCode(uharmKey);
String iharmKey = findResult.keySet().stream().filter(code -> code.startsWith("iharm")).findFirst().orElse("iharm");
// 谐波电流
Pair<Float, RStatLimitRateDetailDPO> iharmResult = findResult.get(iharmKey);
setLimitExtentInfo(iharm, iharmResult);
iharm.setCode(iharmKey);
// 电压三相不平衡
Pair<Float, RStatLimitRateDetailDPO> ubalanceResult = findResult.get(ubalance.getCode());
setLimitExtentInfo(ubalance, ubalanceResult);
if (CollUtil.isNotEmpty(overlimitList)) {
// 取所有监测点中的最大闪变限值,作为闪变国际限值
float flickerMaxOverlimit = (float) overlimitList.stream().mapToDouble(Overlimit::getFlicker).max().orElse(0.0F);
float voltageDevMaxOverlimit = (float) overlimitList.stream().mapToDouble(Overlimit::getVoltageDev).max().orElse(0.0F);
float ubalanceMaxOverlimit = (float) overlimitList.stream().mapToDouble(Overlimit::getUbalance).max().orElse(0.0F);
float iharmMaxOverlimit = 0.0F;
float uharmMaxOverlimit = 0.0F;
for (Overlimit overlimit : overlimitList) {
JSONObject entries = JSONUtil.parseObj(overlimit);
for (Map.Entry<String, Object> entry : entries.entrySet()) {
String key = entry.getKey();
if (key.startsWith("uharm")) {
Object value = entry.getValue();
if (value instanceof Number) {
uharmMaxOverlimit = Math.max(uharmMaxOverlimit, ((Number) value).floatValue());
}
} else if (key.startsWith("iharm")) {
Object value = entry.getValue();
if (value instanceof Number) {
iharmMaxOverlimit = Math.max(iharmMaxOverlimit, ((Number) value).floatValue());
}
}
}
}
flicker.setInternationalValue(flickerMaxOverlimit);
voltageDev.setInternationalValue(voltageDevMaxOverlimit);
ubalance.setInternationalValue(ubalanceMaxOverlimit);
iharm.setInternationalValue(iharmMaxOverlimit);
uharm.setInternationalValue(uharmMaxOverlimit);
}
}
result.add(flicker);
result.add(uharm);
result.add(iharm);
result.add(voltageDev);
result.add(ubalance);
return result;
}
@Override
public JSONArray limitExtentDayData(LimitExtentDayQueryParam param) {
List<RStatLimitRateDetailDPO> records = this.page(new Page<>(1, 1),
new LambdaQueryWrapper<RStatLimitRateDetailDPO>()
.eq(RStatLimitRateDetailDPO::getLineId, param.getLineId())
.eq(RStatLimitRateDetailDPO::getTime, param.getTime())
).getRecords();
String code = param.getCode();
if (CollUtil.isNotEmpty(records)) {
RStatLimitRateDetailDPO detail = records.get(0);
JSONObject entries = JSONUtil.parseObj(detail);
for (Map.Entry<String, Object> entry : entries.entrySet()) {
String key = entry.getKey();
if (key.endsWith("Overtime")) {
Object value = entry.getValue();
if (StrUtil.equals(code, key)) {
return JSONUtil.parseArray(value);
} else if (key.startsWith(code)) {
return JSONUtil.parseArray(value);
}
}
}
}
return JSONUtil.createArray();
}
@Override
public List<LimitCalendarVO> limitCalendarData(LimitCalendarQueryParam param) {
List<LimitCalendarVO> result = new ArrayList<>();
List<RStatLimitRateDetailDPO> detailList = this.list(new LambdaQueryWrapper<RStatLimitRateDetailDPO>()
.ge(StrUtil.isNotBlank(param.getSearchBeginTime()), RStatLimitRateDetailDPO::getTime, param.getSearchBeginTime())
.le(StrUtil.isNotBlank(param.getSearchEndTime()), RStatLimitRateDetailDPO::getTime, param.getSearchEndTime())
.orderByAsc(RStatLimitRateDetailDPO::getTime)
);
if (CollUtil.isEmpty(detailList)) {
return result;
}
Map<LocalDate, List<RStatLimitRateDetailDPO>> detailMap = detailList.stream().collect(Collectors.groupingBy(RStatLimitRateDetailDPO::getTime));
LimitCalendarVO calendarVO;
for (Map.Entry<LocalDate, List<RStatLimitRateDetailDPO>> entry : detailMap.entrySet()) {
calendarVO = new LimitCalendarVO();
LocalDate time = entry.getKey();
calendarVO.setTime(time);
int status = 0;
List<String> items = new ArrayList<>();
List<RStatLimitRateDetailDPO> dayDetailList = entry.getValue();
for (RStatLimitRateDetailDPO detail : dayDetailList) {
String lineId = detail.getLineId();
List<Overlimit> overlimitList = overLimitClient.getOverLimitByLineIds(Collections.singletonList(lineId)).getData();
Overlimit overlimit = overlimitList.stream().findFirst().orElse(null);
JSONObject entries = JSONUtil.parseObj(detail);
for (Map.Entry<String, Object> dayEntry : entries.entrySet()) {
String key = dayEntry.getKey();
if (key.endsWith("Overtime")) {
Object data = dayEntry.getValue();
// 有数据有越限
if (ObjectUtil.isNotEmpty(data)) {
status = 1;
String description = getDescription(key);
if (StrUtil.isNotBlank(description) && !items.contains(description)) {
items.add(description);
}
float maxValue = parseMaxValueFromJsonArray(data);
if (overlimit != null) {
JSONObject overlimitJSON = JSONUtil.parseObj(overlimit);
String itemKey = StrUtil.sub(key, 0, key.length() - 8);
float limitValue = overlimitJSON.getFloat(itemKey);
if (limitValue != 0) {
float overlimitPercent = (maxValue - limitValue) / limitValue * 100;
if (overlimitPercent >= 80) {
status = 2;
}
}
}
}
}
}
}
calendarVO.setItems(items);
calendarVO.setStatus(status);
result.add(calendarVO);
}
result.sort(Comparator.comparing(LimitCalendarVO::getTime));
return result;
}
/**
* 设置LimitExtentVO的最大值和相关信息
*/
private void setLimitExtentInfo(LimitExtentVO limitExtentVO, Pair<Float, RStatLimitRateDetailDPO> result) {
float maxValue = result.getKey();
limitExtentVO.setMaxValue(maxValue);
RStatLimitRateDetailDPO maxDetail = result.getValue();
if (maxDetail != null) {
limitExtentVO.setTime(maxDetail.getTime());
CsLinePO maxLinePO = csLineFeignClient.getById(maxDetail.getLineId()).getData();
if (maxLinePO != null) {
limitExtentVO.setLineName(maxLinePO.getName());
limitExtentVO.setLineId(maxLinePO.getLineId());
}
}
}
/**
* 查找数据中的最大值及其对应的记录
*
* @param detailList 数据列表
* @return 包含最大值和对应记录的Pair对象
*/
private Map<String, Pair<Float, RStatLimitRateDetailDPO>> findMaxValueHandle(List<RStatLimitRateDetailDPO> detailList) {
Map<String, Pair<Float, RStatLimitRateDetailDPO>> result = new HashMap<>();
RStatLimitRateDetailDPO flickerMaxDetail = null;
float flickerMaxValue = 0.0000F;
RStatLimitRateDetailDPO voltageDevMaxDetail = null;
float voltageDevMaxValue = 0.0000F;
RStatLimitRateDetailDPO ubalanceMaxDetail = null;
float ubalanceMaxValue = 0.0000F;
RStatLimitRateDetailDPO uharmMaxDetail = null;
float uharmMaxValue = 0.0000F;
String uharmMaxKey = ""; // 记录uharm最大值对应的key
RStatLimitRateDetailDPO iharmMaxDetail = null;
float iharmMaxValue = 0.0000F;
String iharmMaxKey = ""; // 记录iharm最大值对应的key
for (RStatLimitRateDetailDPO po : detailList) {
String flickerOvertime = po.getFlickerOvertime();
String voltageDevOvertime = po.getVoltageDevOvertime();
String ubalanceOvertime = po.getUbalanceOvertime();
if (StrUtil.isNotBlank(flickerOvertime)) {
float dayFlickerMaxValue = parseMaxValueFromJsonArray(flickerOvertime);
if (dayFlickerMaxValue > flickerMaxValue) {
flickerMaxValue = dayFlickerMaxValue;
flickerMaxDetail = po;
}
}
if (StrUtil.isNotBlank(voltageDevOvertime)) {
float dayVoltageDevMaxValue = parseMaxValueFromJsonArray(voltageDevOvertime);
if (dayVoltageDevMaxValue > voltageDevMaxValue) {
voltageDevMaxValue = dayVoltageDevMaxValue;
voltageDevMaxDetail = po;
}
}
if (StrUtil.isNotBlank(ubalanceOvertime)) {
float dayUbalanceMaxValue = parseMaxValueFromJsonArray(ubalanceOvertime);
if (dayUbalanceMaxValue > ubalanceMaxValue) {
ubalanceMaxValue = dayUbalanceMaxValue;
ubalanceMaxDetail = po;
}
}
JSONObject entries = JSONUtil.parseObj(po);
float dayUharmMaxValue = 0.0000F;
String dayUharmMaxKey = ""; // 当前记录中uharm的最大值key
float dayIharmMaxValue = 0.0000F;
String dayIharmMaxKey = ""; // 当前记录中iharm的最大值key
for (Map.Entry<String, Object> entry : entries.entrySet()) {
String key = entry.getKey();
if (key.endsWith("Overtime")) {
if (key.startsWith("uharm")) {
Object value = entry.getValue();
if (ObjectUtil.isNotEmpty(value)) {
float timeMaxValue = parseMaxValueFromJsonArray(value);
// 取次数最大的未当天的最大值
dayUharmMaxValue = Math.max(dayUharmMaxValue, timeMaxValue);
dayUharmMaxKey = key;
}
}
if (key.startsWith("iharm")) {
Object value = entry.getValue();
if (ObjectUtil.isNotEmpty(value)) {
float timeMaxValue = parseMaxValueFromJsonArray(value);
// 取次数最大的为当天的最大值
dayIharmMaxValue = Math.max(dayIharmMaxValue, timeMaxValue);
dayIharmMaxKey = key;
}
}
}
}
if (dayUharmMaxValue > uharmMaxValue) {
uharmMaxValue = dayUharmMaxValue;
uharmMaxDetail = po;
uharmMaxKey = dayUharmMaxKey; // 记录产生最大值的key
}
if (dayIharmMaxValue > iharmMaxValue) {
iharmMaxValue = dayIharmMaxValue;
iharmMaxDetail = po;
iharmMaxKey = dayIharmMaxKey; // 记录产生最大值的key
}
}
result.put("flicker", Pair.of(flickerMaxValue, flickerMaxDetail));
result.put("voltageDev", Pair.of(voltageDevMaxValue, voltageDevMaxDetail));
result.put("ubalance", Pair.of(ubalanceMaxValue, ubalanceMaxDetail));
result.put(uharmMaxKey.isEmpty() ? "uharm" : uharmMaxKey, Pair.of(uharmMaxValue, uharmMaxDetail));
result.put(iharmMaxKey.isEmpty() ? "iharm" : iharmMaxKey, Pair.of(iharmMaxValue, iharmMaxDetail));
return result;
}
/**
* 从JSON数组字符串中解析出最大值
*
* @param value JSON数组字符串
* @return 解析出的最大值
*/
private float parseMaxValueFromJsonArray(Object value) {
JSONArray overtimeArray = JSONUtil.parseArray(value);
float maxValue = 0.0000F;
for (Object data : overtimeArray) {
JSONObject entries = JSONUtil.parseObj(data);
String values = entries.getStr("value");
float currentValue = (float) StrUtil.split(values, StrUtil.COMMA)
.stream()
.mapToDouble(Float::parseFloat)
.max()
.orElse(0.0000F);
maxValue = Math.max(maxValue, currentValue);
}
return maxValue;
}
private String getDescription(String key) {
if (StrUtil.equals(key, "flickerOvertime")) {
return "闪变越限";
}
if (StrUtil.equals(key, "freqDevOvertime")) {
return "频率偏差越限";
}
if (StrUtil.equals(key, "voltageDevOvertime")) {
return "电压偏差越限";
}
if (StrUtil.equals(key, "ubalanceOvertime")) {
return "三相电压不平衡越限";
}
// 电压
if (StrUtil.startWith(key, "uharm")) {
return "谐波电压越限";
}
// 电流
if (StrUtil.startWith(key, "iharm")) {
return "谐波电流越限";
}
return null;
}
}