fix: 增加小时和日表导出
This commit is contained in:
parent
f2564ceca9
commit
29105cf1f5
@ -169,6 +169,12 @@ public class QgcExportServiceImpl implements IQgcExportService {
|
||||
public void exportData(List<String> dataFields, List<String> months,
|
||||
List<String> stationCodes, boolean isDailyDimension,
|
||||
String tmDimension, HttpServletResponse response) {
|
||||
// hour/day 模式:仅导出原始数据,不做聚合处理
|
||||
if ("hour".equals(tmDimension) || "day".equals(tmDimension)) {
|
||||
exportRawData(dataFields, months, stationCodes, tmDimension, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 指标处理器匹配
|
||||
List<ExportIndicatorProcessor> processors = resolveProcessors(dataFields);
|
||||
if (processors.isEmpty()) {
|
||||
@ -1331,4 +1337,195 @@ public class QgcExportServiceImpl implements IQgcExportService {
|
||||
/** 小时达标率(百分比,仅水质指标使用) */
|
||||
private BigDecimal complianceRate;
|
||||
}
|
||||
|
||||
// ======================== hour/day 原始数据导出 ========================
|
||||
|
||||
/**
|
||||
* hour/day 模式:仅导出原始数据,不做汇总/达标率等聚合处理
|
||||
*/
|
||||
private void exportRawData(List<String> dataFields, List<String> months,
|
||||
List<String> stationCodes, String tmDimension,
|
||||
HttpServletResponse response) {
|
||||
if (months.isEmpty()) {
|
||||
log.warn("hour/day 模式需要传入时间范围参数");
|
||||
return;
|
||||
}
|
||||
boolean isDaily = "day".equals(tmDimension);
|
||||
|
||||
// 解析月份字段(如 "2026-05")→ 当月起止时间
|
||||
String monthStr = months.get(0);
|
||||
String startTime, endTime;
|
||||
if (monthStr.matches("\\d{4}-\\d{2}")) {
|
||||
// 月份格式:YYYY-MM → 当月1日 ~ 下月1日
|
||||
startTime = monthStr + "-01 00:00:00";
|
||||
// 计算下月
|
||||
int year = Integer.parseInt(monthStr.substring(0, 4));
|
||||
int month = Integer.parseInt(monthStr.substring(5, 7));
|
||||
if (month == 12) {
|
||||
endTime = (year + 1) + "-01-01 00:00:00";
|
||||
} else {
|
||||
endTime = year + "-" + String.format("%02d", month + 1) + "-01 00:00:00";
|
||||
}
|
||||
} else {
|
||||
startTime = monthStr;
|
||||
endTime = months.size() >= 2 ? months.get(1) : monthStr;
|
||||
if (!startTime.contains(":")) startTime += " 00:00:00";
|
||||
if (!endTime.contains(":")) endTime += " 23:59:59";
|
||||
}
|
||||
|
||||
// 1. 指标处理器(去掉日变幅 processor)
|
||||
List<ExportIndicatorProcessor> processors = resolveProcessors(dataFields).stream()
|
||||
.filter(p -> !p.isVariation())
|
||||
.toList();
|
||||
if (processors.isEmpty()) {
|
||||
log.warn("未找到匹配的指标处理器");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 电站映射
|
||||
Set<String> sttpTypes = processors.stream()
|
||||
.map(ExportIndicatorProcessor::getSttpType)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
StationResolution stationRes = resolveStations(stationCodes, sttpTypes);
|
||||
if (stationRes.displayNames.isEmpty()) return;
|
||||
|
||||
List<String> stationOrder = new ArrayList<>(stationRes.displayNames.keySet());
|
||||
|
||||
// 3. 文件名
|
||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||
String excelFileName = monthStr + (isDaily ? "日数据_" : "小时数据_") + timestamp;
|
||||
String zipFileName = getFileNamePrefix(tmDimension) + ".zip";
|
||||
|
||||
// 4. 构建 Sheet
|
||||
List<ExportZipUtil.SheetData> sheets = new ArrayList<>();
|
||||
for (ExportIndicatorProcessor processor : processors) {
|
||||
String sttp = processor.getSttpType();
|
||||
List<String> stcds = new ArrayList<>();
|
||||
Map<String, String> stcdDisplayMap = new LinkedHashMap<>();
|
||||
for (String rstcd : stationOrder) {
|
||||
String stcd = stationRes.getStcd(rstcd, sttp);
|
||||
if (stcd != null) {
|
||||
stcds.add(stcd);
|
||||
String name = stationRes.getDisplayName(rstcd, sttp);
|
||||
stcdDisplayMap.put(stcd, StrUtil.isNotBlank(name) ? name : stcd);
|
||||
}
|
||||
}
|
||||
if (stcds.isEmpty()) continue;
|
||||
|
||||
List<List<Object>> rows;
|
||||
List<String> headers;
|
||||
if (processor instanceof RwtProcessor) {
|
||||
rows = buildRwtRawSheetRows(stcds, stcdDisplayMap, startTime, endTime);
|
||||
headers = Arrays.asList("测站", "时间", "水深(m)", "水温(℃)");
|
||||
} else {
|
||||
rows = buildRawSheetRows(processor, stcds, stcdDisplayMap, startTime, endTime, isDaily);
|
||||
if (rows == null) continue;
|
||||
// 表头:时间 | 测站1 | 测站2 | ...
|
||||
headers = new ArrayList<>();
|
||||
headers.add("时间");
|
||||
for (String stcd : stcds) {
|
||||
headers.add(stcdDisplayMap.getOrDefault(stcd, stcd));
|
||||
}
|
||||
}
|
||||
|
||||
ExportZipUtil.SheetData sd = new ExportZipUtil.SheetData(processor.getSheetName(), headers, rows);
|
||||
sheets.add(sd);
|
||||
}
|
||||
|
||||
if (sheets.isEmpty()) {
|
||||
log.warn("hour/day 模式:没有可用数据");
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. ZIP 导出
|
||||
try {
|
||||
ExportZipUtil.exportToResponse(response, zipFileName,
|
||||
Collections.singletonList(new ExportZipUtil.ExcelData(excelFileName, sheets)));
|
||||
} catch (Exception e) {
|
||||
log.error("hour/day 导出失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建标准格式原始数据行(非 RWT)
|
||||
* 每行 = 一个时间点,列 = 各测站的原始值
|
||||
*/
|
||||
private List<List<Object>> buildRawSheetRows(ExportIndicatorProcessor processor,
|
||||
List<String> stcds,
|
||||
Map<String, String> stcdDisplayMap,
|
||||
String startTime, String endTime,
|
||||
boolean isDaily) {
|
||||
try {
|
||||
Date start = SDF.parse(startTime);
|
||||
Date end = SDF.parse(endTime);
|
||||
List<IndicatorDataRow> rawData = processor.queryRawData(stcds, start, end, isDaily);
|
||||
if (rawData == null || rawData.isEmpty()) return null;
|
||||
|
||||
// 按时间分组:timeKey → (stcd → value)
|
||||
Map<String, Map<String, BigDecimal>> timeMap = new LinkedHashMap<>();
|
||||
SimpleDateFormat timeFmt = new SimpleDateFormat(isDaily ? "yyyy-MM-dd" : "yyyy-MM-dd HH:mm:ss");
|
||||
for (IndicatorDataRow row : rawData) {
|
||||
String timeKey = timeFmt.format(row.getTm());
|
||||
timeMap.computeIfAbsent(timeKey, k -> new LinkedHashMap<>())
|
||||
.put(row.getStcd(), row.getValue());
|
||||
}
|
||||
|
||||
// 构建行数据(按时间排序,避免 LinkedHashMap 插入顺序导致乱序)
|
||||
List<List<Object>> rows = new ArrayList<>();
|
||||
List<String> sortedTimes = new ArrayList<>(timeMap.keySet());
|
||||
Collections.sort(sortedTimes);
|
||||
for (String timeKey : sortedTimes) {
|
||||
List<Object> row = new ArrayList<>();
|
||||
row.add(timeKey);
|
||||
Map<String, BigDecimal> stcdValMap = timeMap.get(timeKey);
|
||||
for (String stcd : stcds) {
|
||||
BigDecimal val = stcdValMap.get(stcd);
|
||||
row.add(val != null ? formatTemp(val) : "");
|
||||
}
|
||||
rows.add(row);
|
||||
}
|
||||
return rows;
|
||||
} catch (Exception e) {
|
||||
log.error("构建原始数据 Sheet 失败: {}", processor.getFieldName(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 RWT 垂向水温原始数据行
|
||||
* 格式:测站 | 时间 | 水深(m) | 水温(℃)
|
||||
*/
|
||||
private List<List<Object>> buildRwtRawSheetRows(List<String> stcds,
|
||||
Map<String, String> stcdDisplayMap,
|
||||
String startTime, String endTime) {
|
||||
try {
|
||||
List<Map<String, Object>> rawList = sdWtvtdaySMapper.selectDailyData(stcds, startTime, endTime);
|
||||
if (rawList == null || rawList.isEmpty()) return null;
|
||||
|
||||
SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd");
|
||||
List<List<Object>> rows = new ArrayList<>();
|
||||
for (Map<String, Object> map : rawList) {
|
||||
String stcd = (String) map.get("STCD");
|
||||
Object wthgObj = map.get("WTHG");
|
||||
Object vwtObj = map.get("VWT");
|
||||
Object dayNumObj = map.get("DAY_NUM");
|
||||
if (stcd == null || vwtObj == null) continue;
|
||||
|
||||
String displayName = stcdDisplayMap.getOrDefault(stcd, stcd);
|
||||
String depth = wthgObj != null ? formatNumberCell(formatNumber(wthgObj)) : "";
|
||||
BigDecimal vwt = toBigDecimal(vwtObj);
|
||||
|
||||
List<Object> row = new ArrayList<>();
|
||||
row.add(displayName);
|
||||
row.add(dayNumObj != null ? "第" + dayNumObj + "日" : "");
|
||||
row.add(depth);
|
||||
row.add(formatTemp(vwt));
|
||||
rows.add(row);
|
||||
}
|
||||
return rows;
|
||||
} catch (Exception e) {
|
||||
log.error("构建 RWT 原始数据失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user