diff --git a/backend/src/main/java/com/yfd/platform/qgc_export/domain/StationMapping.java b/backend/src/main/java/com/yfd/platform/qgc_export/domain/StationMapping.java
index 61af0b13..c8f58ee6 100644
--- a/backend/src/main/java/com/yfd/platform/qgc_export/domain/StationMapping.java
+++ b/backend/src/main/java/com/yfd/platform/qgc_export/domain/StationMapping.java
@@ -27,4 +27,8 @@ public class StationMapping implements Serializable {
/** 测站类型(如 ZQ=河道水情, XX=生态流量等),用于区分同一电站下不同类型的测站 */
@TableField("STTP")
private String sttp;
+
+ /** 测站名称 */
+ @TableField("STNM")
+ private String stnm;
}
diff --git a/backend/src/main/java/com/yfd/platform/qgc_export/service/impl/QgcExportServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_export/service/impl/QgcExportServiceImpl.java
index ea60381c..5ad37af1 100644
--- a/backend/src/main/java/com/yfd/platform/qgc_export/service/impl/QgcExportServiceImpl.java
+++ b/backend/src/main/java/com/yfd/platform/qgc_export/service/impl/QgcExportServiceImpl.java
@@ -27,29 +27,30 @@ import java.util.*;
import java.util.stream.Collectors;
/**
- * 综合导出服务实现
+ * 综合导出服务实现(月度报表)
*
* 格式:每月一个 Excel 文件 → ZIP 下载。
- * 每个 Excel 含多个 Sheet(每个指标一个 Sheet),每行是一个统计指标。
+ * 每个 Excel 含多个 Sheet(每个指标一个 Sheet)。
+ *
+ *
Sheet 结构
+ *
+ * 日期 | 班多 | 羊曲 ← 表头(Row 0:第一列=日期,后面列=测站名称)
+ * 01 | 2757.711 | 2709.839 ← 每日数据(Row 1~31)
+ * 02 | 2757.806 | 2709.794
+ * ...
+ * 31 | 2757.751 | 2709.714
+ * 日均最低 | 2757.549 | 2709.565 ← 汇总指标(7行)
+ * 日均最高 | 2757.879 | 2709.903
+ * 月内最低 | 2756.979 | 2709.463
+ * 月内最低时间 | 31日 08时 | 27日 08时
+ * 月内最高 | 2758.003 | 2709.983
+ * 月内最高时间 | 12日 16时 | 24日 16时
+ * 月均 | 2757.751 | 2757.751
+ *
*
* 电站→测站映射(STTP 类型区分)
* 同一电站(RSTCD)在 V_MS_STBPRP_T 视图中可能有多个测站(STCD),
- * 不同类型的指标需要不同类型的测站数据。通过 {@link ExportIndicatorProcessor#getSttpType()}
- * 区分:
- *
- * - V/Q/Z 河道水情 → STTP="ZQ"
- * - QEC 生态流量 → STTP=待定
- *
- *
- *
- * 日期 | 电站A | 电站B
- * 日均最低 | 0.523 | 0.612
- * 日均最高 | 1.234 | 1.456
- * 月内最低 | 0.412 | 0.523
- * 月内最低时间 | 2026-08-15 03:00:00 | 2026-08-14 05:30:00
- * 月内最高 | 2.156 | 2.345
- * 月内最高时间 | 2026-08-03 12:00:00 | 2026-08-20 18:45:00
- *
+ * 不同类型的指标需要不同类型的测站数据。通过 {@link ExportIndicatorProcessor#getSttpType()} 区分。
*/
@Service
public class QgcExportServiceImpl implements IQgcExportService {
@@ -71,11 +72,12 @@ public class QgcExportServiceImpl implements IQgcExportService {
@Resource
private ZProcessor zProcessor;
- private static final SimpleDateFormat SDF_DATETIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ /** 时间格式:dd日 HH时(如 "31日 08时") */
+ private static final SimpleDateFormat SDF_TIME = new SimpleDateFormat("dd日 HH时");
- /** 行标题:6 个统计指标 */
+ /** 汇总指标行标签(7个) */
private static final List INDICATOR_LABELS = Collections.unmodifiableList(
- Arrays.asList("日均最低", "日均最高", "月内最低", "月内最低时间", "月内最高", "月内最高时间"));
+ Arrays.asList("日均最低", "日均最高", "月内最低", "月内最低时间", "月内最高", "月内最高时间", "月均"));
@Override
public void exportData(List dataFields, List months,
@@ -96,15 +98,15 @@ public class QgcExportServiceImpl implements IQgcExportService {
// 3. 电站 → 测站映射(按 STTP 类型分别获取)
StationResolution stationRes = resolveStations(stationCodes, sttpTypes);
- if (stationRes.stationNames.isEmpty()) {
+ if (stationRes.displayNames.isEmpty()) {
log.warn("未找到任何电站映射数据,导出取消");
return;
}
- // 4. 电站顺序 + 名称
- List stationOrder = new ArrayList<>(stationRes.stationNames.keySet());
- List stationNames = stationOrder.stream()
- .map(stationRes::getStationName)
+ // 4. 电站顺序 + 列标题(测站名称)
+ List stationOrder = new ArrayList<>(stationRes.displayNames.keySet());
+ List headerNames = stationOrder.stream()
+ .map(stationRes::getDisplayName)
.toList();
// 5. 每月一个 ExcelData
@@ -115,13 +117,11 @@ public class QgcExportServiceImpl implements IQgcExportService {
List sheets = new ArrayList<>();
for (ExportIndicatorProcessor processor : processors) {
- // 查询 + 聚合这一个月的数据(使用该处理器对应的 STTP 测站)
- List> rows = buildIndicatorRows(
- processor, mr, stationOrder, stationRes);
+ List> rows = buildSheetRows(processor, mr, stationOrder, stationRes);
if (rows != null) {
List headers = new ArrayList<>();
- headers.add("日期"); // 表头第一列 = 日期
- headers.addAll(stationNames);
+ headers.add("日期");
+ headers.addAll(headerNames);
sheets.add(new ExportZipUtil.SheetData(processor.getSheetName(), headers, rows));
}
}
@@ -135,32 +135,21 @@ public class QgcExportServiceImpl implements IQgcExportService {
log.warn("没有可导出的数据");
return;
}
- String fileNamePrefix = getFileNamePrefix(tmDimension);
- // 6. 委托 ExportZipUtil 导出 ZIP
- String zipFileName = fileNamePrefix + ".zip";
-// String zipFileName = fileNamePrefix + System.currentTimeMillis() + ".zip";
+
+ String zipFileName = getFileNamePrefix(tmDimension) + ".zip";
ExportZipUtil.exportToResponse(response, zipFileName, excelList);
}
- // 根据维度类型返回文件名称前缀
- private static String getFileNamePrefix(String tmDimension) {
- return switch (tmDimension) {
- case "year" -> "年度报表";
- case "month" -> "月度报表";
- case "day" -> "日度报表";
- case "hour" -> "小时报表";
- default -> "未知";
- };
- }
-
- // ======================== 构建单个指标的 Sheet 数据 ========================
+ // ======================== 构建 Sheet 数据 ========================
/**
- * 查询并聚合一个月的数据,组装成 SheetData 的 rows
- *
- * 使用 processor.getSttpType() 映射到正确的测站编码。
+ * 查询一个月的数据并组装为一个 Sheet 的全部行:
+ *
+ * - 日数据行(01~31):每天每电站一个值
+ * - 汇总指标行(7行):日均最低、日均最高、月内最低、月内最低时间、月内最高、月内最高时间、月均
+ *
*/
- private List> buildIndicatorRows(
+ private List> buildSheetRows(
ExportIndicatorProcessor processor, MonthRange mr,
List stationOrder, StationResolution stationRes) {
@@ -180,22 +169,38 @@ public class QgcExportServiceImpl implements IQgcExportService {
return null;
}
- // 去重 STCD 用于查询
List uniqueStcds = rstcdToStcd.values().stream().distinct().toList();
- // 查询日表数据(用于日均最低/最高)
+ // 查询日表 + 小时表数据
List dailyRows = processor.queryRawData(uniqueStcds, mr.getStart(), mr.getEnd(), true);
- // 查询小时表数据(用于月内最低/最高)
List hourlyRows = processor.queryRawData(uniqueStcds, mr.getStart(), mr.getEnd(), false);
- // 按电站聚合
+ // 汇总聚合
Map aggMap = aggregate(dailyRows, hourlyRows, rstcdToStcd);
- // 组装 6 行
- List> rows = new ArrayList<>(6);
- for (int i = 0; i < 6; i++) {
+ // 日数据按 (stcd, day) 索引
+ Map> dailyByStcd = indexDailyByDay(dailyRows);
+
+ List> rows = new ArrayList<>();
+
+ // ---- 日数据行 ----
+ int daysInMonth = getDaysInMonth(mr);
+ for (int d = 1; d <= daysInMonth; d++) {
List