Commit 2da733ab authored by ZWT's avatar ZWT

feat(零碳): 长庆

1.修改极短期间开预测定时任务逻辑,解决优化后部分优化结果时间段过短问题;
2.修改心知天气气象数据获取及接收定时任务,解决天气数据通过邮件下载后,部分数据精度丢失问题;
3.修改首页各个接口逻辑,对小数类型字段进行处理,修改首页接口,增加小时保留两位四舍五入逻辑,同时解决线路详情接口部分查询逻辑报错问题;
4.能耗分析模块,能耗概览接口修改,修改查询逻辑,修改数据获取逻辑及绿电占比计算逻辑;
5.能耗分析模块,消纳曲线用电趋势接口修改,修改查询逻辑,修改数据获取逻辑及绿电占比计算逻辑;
6.能耗分析模块,用电详情接口修改,修改查询逻辑,修改数据获取逻辑及绿电占比计算逻辑;
7.修改首页先导实验井间开制度模块接口查询逻辑,解决极短期间开优化修改后没有第一次开井时间标识导致数据查询不出来问题;
8.基础间开制度新增修改接口逻辑修改,删除防冻堵对井口处理逻辑;
9.极短期间开优化算法修改,增加防冻堵井开井时间优化逻辑;
10.提供长庆通过日期获取当日间开优化结果接口开发,完成接口冒烟测试并添加线上接口文档;
11.提供长庆1天光伏出力预测结果接口开发,完成接口冒烟测试并添加线上接口文档;
12.提供长庆15天光伏出力预测结果接口开发,完成接口冒烟测试并添加线上接口文档;
13.修改极短期间开优化算法,优化防冻堵策略;
14.开发第三方历史天气导入功能;

BREAKING CHANGE: 无

Closes 无

[skip ci]
parent 1a12f9a6
package pps.core.base.config.excel;
/**
* excel动态选择
*
* @author ZWT
* @date 2024/05/07
*/
public interface ExcelDynamicSelect {
/**
* 获取动态生成的下拉框可选数据
*
* @return 动态生成的下拉框可选数据
*/
String[] getSource();
}
\ No newline at end of file
package pps.core.base.config.excel;
import java.lang.annotation.*;
/**
* 标注导出的列为下拉框类型,并为下拉框设置内容
*
* @author ZWT
* @date 2024/05/07
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelSelected {
/**
* 固定下拉内容
*/
String[] source() default {};
/**
* 动态下拉内容
*/
Class<? extends ExcelDynamicSelect>[] sourceClass() default {};
/**
* 设置下拉框的起始行,默认为第二行
*/
int firstRow() default 1;
/**
* 设置下拉框的结束行,默认为最后一行
*/
int lastRow() default 0x10000;
}
\ No newline at end of file
package pps.core.base.config.excel;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* excel选定解析
*
* @author ZWT
* @date 2024/05/07
*/
@Data
@Slf4j
public class ExcelSelectedResolve {
/**
* 下拉内容
*/
private String[] source;
/**
* 设置下拉框的起始行,默认为第二行
*/
private int firstRow;
/**
* 设置下拉框的结束行,默认为最后一行
*/
private int lastRow;
public String[] resolveSelectedSource(ExcelSelected excelSelected) {
if (excelSelected == null) {
return null;
}
// 获取固定下拉框的内容
String[] source = excelSelected.source();
if (source.length > 0) {
return source;
}
// 获取动态下拉框的内容
Class<? extends ExcelDynamicSelect>[] classes = excelSelected.sourceClass();
if (classes.length > 0) {
try {
ExcelDynamicSelect excelDynamicSelect = classes[0].newInstance();
String[] dynamicSelectSource = excelDynamicSelect.getSource();
if (dynamicSelectSource != null && dynamicSelectSource.length > 0) {
return dynamicSelectSource;
}
} catch (InstantiationException | IllegalAccessException e) {
log.error("解析动态下拉框数据异常", e);
}
}
return null;
}
}
\ No newline at end of file
package pps.core.base.config.excel;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import java.util.Map;
/**
* 选定工作表写入处理程序
*
* @author ZWT
* @date 2024/05/07
*/
@Data
@AllArgsConstructor
public class SelectedSheetWriteHandler implements SheetWriteHandler {
private final Map<Integer, ExcelSelectedResolve> selectedMap;
/**
* 设置阈值,避免生成的导入模板下拉值获取不到,可自行设置数量大小
*/
private static final Integer LIMIT_NUMBER = 25;
/**
* Called before create the sheet
*/
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
/**
* Called after the sheet is created
*/
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
// 这里可以对cell进行任何操作
Sheet sheet = writeSheetHolder.getSheet();
DataValidationHelper helper = sheet.getDataValidationHelper();
selectedMap.forEach((k, v) -> {
// 设置下拉列表的行: 首行,末行,首列,末列
CellRangeAddressList rangeList = new CellRangeAddressList(v.getFirstRow(), v.getLastRow(), k, k);
// 如果下拉值总数大于25,则使用一个新sheet存储,避免生成的导入模板下拉值获取不到
if (v.getSource().length > LIMIT_NUMBER) {
//定义sheet的名称
//1.创建一个隐藏的sheet 名称为 hidden + k
String sheetName = "hidden" + k;
Workbook workbook = writeWorkbookHolder.getWorkbook();
Sheet hiddenSheet = workbook.createSheet(sheetName);
for (int i = 0, length = v.getSource().length; i < length; i++) {
// 开始的行数i,列数k
hiddenSheet.createRow(i).createCell(k).setCellValue(v.getSource()[i]);
}
Name category1Name = workbook.createName();
category1Name.setNameName(sheetName);
String excelLine = getExcelLine(k);
// =hidden!$H:$1:$H$50 sheet为hidden的 H1列开始H50行数据获取下拉数组
String refers = "=" + sheetName + "!$" + excelLine + "$1:$" + excelLine + "$" + (v.getSource().length + 1);
// 将刚才设置的sheet引用到你的下拉列表中
DataValidationConstraint constraint = helper.createFormulaListConstraint(refers);
DataValidation dataValidation = helper.createValidation(constraint, rangeList);
writeSheetHolder.getSheet().addValidationData(dataValidation);
// 设置存储下拉列值得sheet为隐藏
int hiddenIndex = workbook.getSheetIndex(sheetName);
if (!workbook.isSheetHidden(hiddenIndex)) {
workbook.setSheetHidden(hiddenIndex, true);
}
}
// 设置下拉列表的值
DataValidationConstraint constraint = helper.createExplicitListConstraint(v.getSource());
// 设置约束
DataValidation validation = helper.createValidation(constraint, rangeList);
// 阻止输入非下拉选项的值
validation.setErrorStyle(DataValidation.ErrorStyle.STOP);
validation.setShowErrorBox(true);
// validation.setSuppressDropDownArrow(true);
validation.createErrorBox("提示", "请输入下拉选项中的内容");
sheet.addValidationData(validation);
});
}
/**
* 返回excel列标A-Z-AA-ZZ
*
* @param num 列数
* @return java.lang.String
*/
private String getExcelLine(int num) {
String line = "";
int first = num / 26;
int second = num % 26;
if (first > 0) {
line = (char) ('A' + first - 1) + "";
}
line += (char) ('A' + second) + "";
return line;
}
}
\ No newline at end of file
package pps.core.base.service;
import com.alibaba.excel.write.metadata.WriteSheet;
import pps.core.base.service.data.base_excel.ExcelPhotovoltaicPlantTemplate;
import pps.core.base.utils.EasyExcelUtil;
import xstartup.annotation.XService;
import xstartup.annotation.XText;
import xstartup.base.XContext;
import xstartup.data.XServiceResult;
import xstartup.feature.api.annotation.XApiPost;
/**
* excel导入导出
*
* @author ZWT
* @date 2024/05/07 09:49
*/
@XText("Excel")
@XService
public class ExcelService {
@XText("光伏电站模板导出")
@XApiPost(anonymous = true)
public XServiceResult templatePhotovoltaicPlant(XContext context) {
WriteSheet writeSheet = EasyExcelUtil.writeSelectedSheet(ExcelPhotovoltaicPlantTemplate.class, 0, "光伏电站");
return XServiceResult.OK;
}
}
package pps.core.base.service;
import pps.cloud.system.service.SysOrganizationCloudService;
import pps.cloud.system.service.data.GetAllOuListByOuIdInput;
import pps.cloud.system.service.data.GetSysOrganizationViewOutput;
import pps.core.base.config.excel.ExcelDynamicSelect;
import xstartup.base.XSelfServiceContext;
import xstartup.data.XListResult;
/**
* 采油厂下拉选
*
* @author ZWT
* @date 2024/05/07 10:28
*/
public class OilExtractionPlantImpl implements ExcelDynamicSelect {
@Override
public String[] getSource() {
XSelfServiceContext build = XSelfServiceContext.build(SysOrganizationCloudService.class);
SysOrganizationCloudService bean = build.getBean(SysOrganizationCloudService.class);
GetAllOuListByOuIdInput input = new GetAllOuListByOuIdInput();
input.setOuId("446285aa-ac58-435e-84af-19fc62a8267f");
XListResult<GetSysOrganizationViewOutput> allListByOuId = bean.getAllListByOuId(build, input);
return new String[0];
}
}
\ No newline at end of file
package pps.core.base.service.data.base_excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import pps.core.base.config.excel.ExcelSelected;
import pps.core.base.service.OilExtractionPlantImpl;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* excel光伏电站模板
*
* @author ZWT
* @date 2024/05/07
*/
@Data
@HeadRowHeight(20)
@ContentRowHeight(18)
public class ExcelPhotovoltaicPlantTemplate implements Serializable {
private static final long serialVersionUID = -9069694443646671657L;
/**
* 采油厂名称
*/
@ExcelSelected(sourceClass = OilExtractionPlantImpl.class)
@ExcelProperty(index = 0, value = "采油厂名称")
@ColumnWidth(45)
private String ouName;
/**
* 电站名称
*/
@ExcelProperty(index = 1, value = "电站名称")
@ColumnWidth(45)
private String stationName;
/**
* 逆变器出厂编号
*/
@ExcelProperty(index = 2, value = "逆变器出厂编号")
@ColumnWidth(45)
private String makerNumber;
/**
* 逆变器规格型号
*/
@ExcelProperty(index = 3, value = "逆变器规格型号")
@ColumnWidth(45)
private String photovoltaicModelName;
/**
* 安装倾角(°)
*/
@ExcelProperty(index = 4, value = "安装倾角(°)")
@ColumnWidth(45)
private BigDecimal mountingAngle;
/**
* 装机总量(KWP)
*/
@ExcelProperty(index = 5, value = "装机总量(KWP)")
@ColumnWidth(45)
private BigDecimal totalPower;
/**
* 阵列朝向
*/
@ExcelProperty(index = 6, value = "阵列朝向")
@ColumnWidth(45)
private BigDecimal arrayOrientation;
/**
* 经度(°)
*/
@ExcelProperty(index = 7, value = "经度(°)")
@ColumnWidth(45)
private BigDecimal longitude;
/**
* 纬度(°)
*/
@ExcelProperty(index = 8, value = "纬度(°)")
@ColumnWidth(45)
private BigDecimal latitude;
/**
* 高程(m)
*/
@ExcelProperty(index = 9, value = "高程(m)")
@ColumnWidth(45)
private BigDecimal elevation;
// private Integer areaCode;
}
\ No newline at end of file
package pps.core.base.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import pps.core.base.config.excel.ExcelSelected;
import pps.core.base.config.excel.ExcelSelectedResolve;
import pps.core.base.config.excel.SelectedSheetWriteHandler;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 简单excel实用程序
*
* @author ZWT
* @date 2024/05/07
*/
@Slf4j
public class EasyExcelUtil {
/**
* 创建即将导出的sheet页(sheet页中含有带下拉框的列)
*
* @param head 导出的表头信息和配置
* @param sheetNo sheet索引
* @param sheetName sheet名称
* @param <T> 泛型
* @return sheet页
*/
public static <T> WriteSheet writeSelectedSheet(Class<T> head, Integer sheetNo, String sheetName) {
Map<Integer, ExcelSelectedResolve> selectedMap = resolveSelectedAnnotation(head);
return EasyExcel.writerSheet(sheetNo, sheetName)
.head(head)
.registerWriteHandler(new SelectedSheetWriteHandler(selectedMap))
.build();
}
/**
* 解析表头类中的下拉注解
*
* @param head 表头类
* @param <T> 泛型
* @return Map<下拉框列索引, 下拉框内容> map
*/
private static <T> Map<Integer, ExcelSelectedResolve> resolveSelectedAnnotation(Class<T> head) {
Map<Integer, ExcelSelectedResolve> selectedMap = new HashMap<>(64);
// getDeclaredFields(): 返回全部声明的属性;getFields(): 返回public类型的属性
Field[] fields = head.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
// 解析注解信息
ExcelSelected selected = field.getAnnotation(ExcelSelected.class);
ExcelProperty property = field.getAnnotation(ExcelProperty.class);
if (selected != null) {
ExcelSelectedResolve excelSelectedResolve = new ExcelSelectedResolve();
String[] source = excelSelectedResolve.resolveSelectedSource(selected);
if (source != null && source.length > 0) {
excelSelectedResolve.setSource(source);
excelSelectedResolve.setFirstRow(selected.firstRow());
excelSelectedResolve.setLastRow(selected.lastRow());
if (property != null && property.index() >= 0) {
selectedMap.put(property.index(), excelSelectedResolve);
} else {
selectedMap.put(i, excelSelectedResolve);
}
}
}
}
return selectedMap;
}
public static boolean isIDNumber(String IDNumber) {
if (IDNumber == null || "".equals(IDNumber)) {
return false;
}
// 定义判别用户身份证号的正则表达式(15位或者18位,最后一位可以为字母)
String regularExpression = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|" +
"(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";
//假设18位身份证号码:41000119910101123X 410001 19910101 123X
//^开头
//[1-9] 第一位1-9中的一个 4
//\\d{5} 五位数字 10001(前六位省市县地区)
//(18|19|20) 19(现阶段可能取值范围18xx-20xx年)
//\\d{2} 91(年份)
//((0[1-9])|(10|11|12)) 01(月份)
//(([0-2][1-9])|10|20|30|31)01(日期)
//\\d{3} 三位数字 123(第十七位奇数代表男,偶数代表女)
//[0-9Xx] 0123456789Xx其中的一个 X(第十八位为校验值)
//$结尾
//假设15位身份证号码:410001910101123 410001 910101 123
//^开头
//[1-9] 第一位1-9中的一个 4
//\\d{5} 五位数字 10001(前六位省市县地区)
//\\d{2} 91(年份)
//((0[1-9])|(10|11|12)) 01(月份)
//(([0-2][1-9])|10|20|30|31)01(日期)
//\\d{3} 三位数字 123(第十五位奇数代表男,偶数代表女),15位身份证不含X
//$结尾
boolean matches = IDNumber.matches(regularExpression);
//判断第18位校验值
if (matches) {
if (IDNumber.length() == 18) {
try {
char[] charArray = IDNumber.toCharArray();
//前十七位加权因子
int[] idCardWi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
//这是除以11后,可能产生的11位余数对应的验证码
String[] idCardY = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
int sum = 0;
for (int i = 0; i < idCardWi.length; i++) {
int current = Integer.parseInt(String.valueOf(charArray[i]));
int count = current * idCardWi[i];
sum += count;
}
char idCardLast = charArray[17];
int idCardMod = sum % 11;
if (idCardY[idCardMod].equalsIgnoreCase(String.valueOf(idCardLast))) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
return false;
}
return matches;
}
public static boolean isMobile(String phone) {
Pattern p;
Matcher m;
boolean b = false;
// 验证手机号
String s2 = "^[1](([3|5|6|7|8|9][\\d])|([4][4,5,6,7,8,9])|([6][2,5,6,7])|([7][^9])|([9][1,8,9]))[\\d]{8}$";
if (StringUtils.isNotBlank(phone)) {
p = Pattern.compile(s2);
m = p.matcher(phone);
b = m.matches();
}
return b;
}
}
\ No newline at end of file
......@@ -27,7 +27,7 @@ public class ThirdActivePowerJob implements XJob {
* @param xContext x上下文
* @return {@link XServiceResult}
*/
@XCronTrigger(value = TaskConstant.TEN_MINUTES)
@XCronTrigger(value = XCronTrigger.PRE_10S)
@Override
public XServiceResult execute(XContext xContext) {
xContext.getLogger().info("------ ThirdActivePowerJob start:{}", System.currentTimeMillis());
......
......@@ -69,8 +69,12 @@ public class ThirdDataAccessCloudServiceImpl implements IThirdDataAccessCloudSer
LambdaQueryWrapper<ThirdActivePowerEnt> queryWrapper = new LambdaQueryWrapper<ThirdActivePowerEnt>()
.select(ThirdActivePowerEnt::getId);
for (GetThirdActivePowerViewOutput o : outputs) {
photovoltaicPower = o.getPhotovoltaicPower().abs();
meterPower = o.getMeterPower().abs();
photovoltaicPower = Optional.ofNullable(o.getPhotovoltaicPower())
.orElse(BigDecimal.ZERO)
.abs();
meterPower = Optional.ofNullable(o.getMeterPower())
.orElse(BigDecimal.ZERO)
.abs();
dtoList.add(
ThirdActivePowerView.builder()
.stationName(o.getStationName())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment