Merge remote-tracking branch 'origin/main'

This commit is contained in:
wr
2026-04-02 10:45:08 +08:00
4 changed files with 271 additions and 29 deletions

View File

@@ -4,6 +4,8 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.njcn.common.pojo.exception.BusinessException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
/**
@@ -70,4 +72,55 @@ public class PublicDataUtils {
throw new BusinessException("时间格式不正确,请使用 yyyy-MM 格式");
}
}
/**
* 根据传入的月份字符串获取时间范围
* 如果传入的月份是当前月份返回该月1号到昨天
* 如果传入的月份不是当前月份,返回该月的第一天和最后一天
*
* @param timeStr 月份字符串格式yyyy-MM
* @return 包含 startTime 和 endTime 的数组格式yyyy-MM-dd
*/
/**
* 根据传入的月份字符串获取时间范围
* 如果传入的月份是当前月份,返回该月 1 号到昨天
* 如果传入的月份不是当前月份,返回该月的第一天和最后一天
*
* @param timeStr 月份字符串格式yyyy-MM
* @return 包含 startTime 和 endTime 的数组格式yyyy-MM-dd
*/
public static String[] calculateTimeRange(String timeStr) {
LocalDate now = LocalDate.now();
LocalDate inputMonth;
try {
// 解析传入的月份
inputMonth = LocalDate.parse(timeStr + "-01", DateTimeFormatter.ISO_LOCAL_DATE);
} catch (Exception e) {
throw new BusinessException("时间格式不正确,请使用 yyyy-MM 格式");
}
// 判断是否是当前月份
boolean isCurrentMonth = inputMonth.getYear() == now.getYear() &&
inputMonth.getMonthValue() == now.getMonthValue();
String startTime;
String endTime;
startTime = inputMonth.withDayOfMonth(1).format(DateTimeFormatter.ISO_LOCAL_DATE);
if (isCurrentMonth) {
// 如果今天是 1 号,则结束时间也为 1 号,避免时间范围无效
endTime = now.minusDays(1).format(DateTimeFormatter.ISO_LOCAL_DATE);
// 确保结束时间不小于开始时间
if (LocalDate.parse(endTime).isBefore(LocalDate.parse(startTime))) {
endTime = startTime;
}
} else {
// 如果不是当前月份,开始时间是该月 1 号,结束时间是该月最后一天
endTime = inputMonth.withDayOfMonth(inputMonth.lengthOfMonth()).format(DateTimeFormatter.ISO_LOCAL_DATE);
}
return new String[]{startTime, endTime};
}
}

View File

@@ -39,10 +39,8 @@ import com.njcn.system.pojo.po.EleEpdPqd;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.*;
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;
@@ -311,6 +309,8 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
}
}
private String saveReport(JSONArray jsonArray, Map<String, Object> dataMap) {
String filePath = "";
Workbook workbook = new XSSFWorkbook();
@@ -322,46 +322,118 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
Sheet sheet = workbook.createSheet(sheetName);
if (data != null) {
List<CellRangeAddress> mergeRegions = new ArrayList<>();
List<MergedCellInfo> mergedCellInfos = new ArrayList<>();
if (data != null && !data.isEmpty()) {
boolean hasMergeMark = false;
for (int j = 0; j < data.size(); j++) {
Row row = sheet.createRow(j);
JSONArray rowData = data.getJSONArray(j);
if (rowData != null) {
for (int k = 0; k < rowData.size(); k++) {
Cell cell = row.createCell(k);
JSONObject cellObj = rowData.getJSONObject(k);
if (cellObj != null && !cellObj.isEmpty()) {
Object v = cellObj.get("v");
if (v != null) {
Object vData = dataMap.get(v);
if (vData != null) {
if (vData instanceof String) {
cell.setCellValue((String) vData);
} else if (vData instanceof Number) {
cell.setCellValue(((Number) vData).doubleValue());
} else if (vData instanceof Boolean) {
cell.setCellValue((Boolean) vData);
} else {
cell.setCellValue(vData.toString());
if (cellObj == null || cellObj.isEmpty()) {
continue;
}
JSONObject mc = cellObj.getJSONObject("mc");
if (mc != null && !mc.isEmpty()) {
hasMergeMark = true;
Integer rs = mc.getInt("rs");
Integer cs = mc.getInt("cs");
Integer mr = mc.getInt("r");
Integer mcCol = mc.getInt("c");
if (rs != null && cs != null && mr != null && mcCol != null) {
if (mr == j && mcCol == k) {
int endRow = j + rs - 1;
int endCol = k + cs - 1;
if (endRow > j || endCol > k) {
mergeRegions.add(new CellRangeAddress(j, endRow, k, endCol));
MergedCellInfo info = new MergedCellInfo();
info.row = j;
info.col = k;
info.cellObj = cellObj;
mergedCellInfos.add(info);
}
} else {
if (v instanceof String) {
cell.setCellValue((String) v);
} else if (v instanceof Number) {
cell.setCellValue(((Number) v).doubleValue());
} else if (v instanceof Boolean) {
cell.setCellValue((Boolean) v);
} else {
cell.setCellValue(v.toString());
}
continue;
}
}
}
Cell cell = row.createCell(k);
Object v = cellObj.get("v");
if (v != null) {
Object vData = dataMap.get(v);
if (vData != null) {
setCellValue(cell, vData);
} else {
setCellValue(cell, v);
}
}
}
}
}
if (!hasMergeMark) {
detectAndMergeCells(data, mergeRegions, mergedCellInfos);
}
}
for (CellRangeAddress mergeRegion : mergeRegions) {
try {
sheet.addMergedRegion(mergeRegion);
} catch (Exception e) {
log.warn("添加合并单元格失败:{}", mergeRegion.formatAsString());
}
}
for (MergedCellInfo info : mergedCellInfos) {
Row row = sheet.getRow(info.row);
if (row != null) {
Cell cell = row.getCell(info.col);
if (cell != null) {
CellStyle style = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
Font font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 11);
style.setFont(font);
style.setWrapText(true);
if (Objects.equals(cell.getStringCellValue(),"非谐波统计报表")
|| Objects.equals(cell.getStringCellValue(),"谐波电压统计报表")
|| Objects.equals(cell.getStringCellValue(),"谐波电流统计报表")) {
font.setFontHeightInPoints((short) 18);
font.setBold(true);
}
if (Objects.equals(cell.getStringCellValue(),"有效值")
|| Objects.equals(cell.getStringCellValue(),"功率")
|| Objects.equals(cell.getStringCellValue(),"电压闪变")
|| Objects.equals(cell.getStringCellValue(),"畸变率")
|| Objects.equals(cell.getStringCellValue(),"电压偏差")
|| Objects.equals(cell.getStringCellValue(),"频率")
|| Objects.equals(cell.getStringCellValue(),"三相不平衡度")
|| Objects.equals(cell.getStringCellValue(),"谐波电压含有率")
|| Objects.equals(cell.getStringCellValue(),"谐波电流幅值")) {
font.setFontHeightInPoints((short) 15);
font.setBold(true);
}
cell.setCellStyle(style);
}
}
}
}
@@ -384,6 +456,106 @@ public class CustomReportTableServiceImpl implements CustomReportTableService {
return filePath;
}
/**
* 检测并合并单元格(当没有 mc 标记时)
*/
private void detectAndMergeCells(JSONArray data, List<CellRangeAddress> mergeRegions,
List<MergedCellInfo> mergedCellInfos) {
int rows = data.size();
if (rows == 0) return;
int cols = 0;
JSONArray firstRow = data.getJSONArray(0);
if (firstRow != null) {
cols = firstRow.size();
}
boolean[][] merged = new boolean[rows][cols];
for (int j = 0; j < rows; j++) {
JSONArray rowData = data.getJSONArray(j);
if (rowData == null) continue;
for (int k = 0; k < rowData.size(); k++) {
if (merged[j][k]) continue;
JSONObject cellObj = rowData.getJSONObject(k);
if (cellObj == null || cellObj.isEmpty()) continue;
Object v = cellObj.get("v");
if (v == null || StrUtil.isBlank(v.toString())) continue;
int mergeEndRow = j;
int mergeEndCol = k;
for (int r = j + 1; r < rows; r++) {
JSONArray nextRow = data.getJSONArray(r);
if (nextRow == null || k >= nextRow.size()) break;
JSONObject nextCellObj = nextRow.getJSONObject(k);
if (nextCellObj == null || nextCellObj.isEmpty()) break;
Object nextV = nextCellObj.get("v");
if (nextV == null || !String.valueOf(v).equals(String.valueOf(nextV))) break;
mergeEndRow = r;
merged[r][k] = true;
}
for (int c = k + 1; c < cols; c++) {
if (j >= rowData.size()) break;
JSONObject rightCellObj = rowData.getJSONObject(c);
if (rightCellObj == null || rightCellObj.isEmpty()) break;
Object rightV = rightCellObj.get("v");
if (rightV == null || !String.valueOf(v).equals(String.valueOf(rightV))) break;
mergeEndCol = c;
merged[j][c] = true;
}
if (mergeEndRow > j || mergeEndCol > k) {
mergeRegions.add(new CellRangeAddress(j, mergeEndRow, k, mergeEndCol));
MergedCellInfo info = new MergedCellInfo();
info.row = j;
info.col = k;
info.cellObj = cellObj;
mergedCellInfos.add(info);
}
}
}
}
/**
* 设置单元格值
*/
private void setCellValue(Cell cell, Object value) {
if (value == null) {
return;
}
if (value instanceof String) {
cell.setCellValue((String) value);
} else if (value instanceof Number) {
cell.setCellValue(((Number) value).doubleValue());
} else if (value instanceof Boolean) {
cell.setCellValue((Boolean) value);
} else if (value instanceof Date) {
cell.setCellValue((Date) value);
} else {
cell.setCellValue(value.toString());
}
}
/**
* 合并单元格信息内部类
*/
private static class MergedCellInfo {
int row;
int col;
JSONObject cellObj;
}
/**
* 处理