fix: 新增综合导出水质达标率

This commit is contained in:
tangwei 2026-08-06 10:42:58 +08:00
parent 2837e9e28d
commit 73ae21a62b
5 changed files with 223 additions and 0 deletions

View File

@ -25,4 +25,18 @@ public interface SdWqRMapper extends BaseMapper<SdWqR> {
@Param("fieldName") String fieldName,
@Param("startTime") String startTime,
@Param("endTime") String endTime);
/**
* 查询水质达标数据小时级 STCD 聚合 SFDB=1 达标数SFDB IN (0,1) 总数
*/
List<Map<String, Object>> selectComplianceData(@Param("stcdList") List<String> stcdList,
@Param("startTime") String startTime,
@Param("endTime") String endTime);
/**
* 查询各测站不达标要素SFDB=0 时的 WQ_SFDBHN_YS
*/
List<Map<String, Object>> selectPollutants(@Param("stcdList") List<String> stcdList,
@Param("startTime") String startTime,
@Param("endTime") String endTime);
}

View File

@ -25,4 +25,11 @@ public interface SdWqdaySMapper extends BaseMapper<SdWqdayS> {
@Param("fieldName") String fieldName,
@Param("startTime") String startTime,
@Param("endTime") String endTime);
/**
* 查询水质达标数据日级 STCD 聚合 SFDB=1 达标数SFDB IN (0,1) 总数
*/
List<Map<String, Object>> selectComplianceData(@Param("stcdList") List<String> stcdList,
@Param("startTime") String startTime,
@Param("endTime") String endTime);
}

View File

@ -180,6 +180,8 @@ public class QgcExportServiceImpl implements IQgcExportService {
if (mr == null) continue;
List<ExportZipUtil.SheetData> sheets = new ArrayList<>();
// 判断是否包含水质指标后续用于追加 WQ 合规 Sheet
boolean hasWqIndicator = false;
for (ExportIndicatorProcessor processor : processors) {
List<List<Object>> rows;
// QEC 自定义三栏达标率格式
@ -223,6 +225,33 @@ public class QgcExportServiceImpl implements IQgcExportService {
));
}
sheets.add(sd);
if ("WQ".equals(sttp)) {
hasWqIndicator = true;
}
}
}
// 若包含水质指标追加 WQ 合规 Sheet
if (hasWqIndicator) {
List<List<Object>> complianceRows = buildWqComplianceSheet(mr, stationOrder, stationRes);
if (complianceRows != null) {
List<String> complianceHeaders = new ArrayList<>();
complianceHeaders.add("水质站");
complianceHeaders.add("小时");
complianceHeaders.add("");
complianceHeaders.add("");
complianceHeaders.add("日均");
complianceHeaders.add("");
complianceHeaders.add("");
complianceHeaders.add("主要污染物");
ExportZipUtil.SheetData sd = new ExportZipUtil.SheetData("水质达标率", complianceHeaders, complianceRows);
sd.setHeaderRowCount(1);
sd.setMergedRegions(Arrays.asList(
new int[]{0, 1, 0, 0}, // "水质站" 合并 row 0-1
new int[]{0, 0, 1, 3}, // "小时" 合并 col 1-3
new int[]{0, 0, 4, 6} // "日均" 合并 col 4-6
));
sheets.add(sd);
}
}
@ -449,6 +478,126 @@ public class QgcExportServiceImpl implements IQgcExportService {
try { return Integer.parseInt(v.toString()); } catch (Exception e) { return -1; }
}
// ======================== WQ 水质达标率 Sheet双表头 ========================
/**
* 构建水质达标率 Sheet 的数据行不含标题行标题由调用方放入 headers
* <p>
* 返回的 rows[0] 是子标题行|达标数|总数|达标率(%)|达标数|总数|达标率(%)|后续为电站数据行
*/
private List<List<Object>> buildWqComplianceSheet(
MonthRange mr, List<String> stationOrder, StationResolution stationRes) {
String sttp = "WQ";
Map<String, String> rstcdToStcd = new LinkedHashMap<>();
for (String rstcd : stationOrder) {
String stcd = stationRes.getStcd(rstcd, sttp);
if (stcd != null) {
rstcdToStcd.put(rstcd, stcd);
}
}
if (rstcdToStcd.isEmpty()) {
log.warn("水质达标率未找到 STTP=WQ 的测站数据");
return null;
}
List<String> uniqueStcds = rstcdToStcd.values().stream().distinct().toList();
String startStr = SDF.format(mr.getStart());
String endStr = SDF.format(mr.getEnd());
// 查询小时达标数据
List<Map<String, Object>> hourlyData = sdWqRMapper.selectComplianceData(uniqueStcds, startStr, endStr);
// 查询日均达标数据
List<Map<String, Object>> dailyData = sdWqdaySMapper.selectComplianceData(uniqueStcds, startStr, endStr);
// 查询主要污染物
List<Map<String, Object>> pollutantData = sdWqRMapper.selectPollutants(uniqueStcds, startStr, endStr);
// STCD 索引达标统计
Map<String, Map<String, Object>> hourlyMap = new LinkedHashMap<>();
for (Map<String, Object> m : hourlyData) {
hourlyMap.put((String) m.get("STCD"), m);
}
Map<String, Map<String, Object>> dailyMap = new LinkedHashMap<>();
for (Map<String, Object> m : dailyData) {
dailyMap.put((String) m.get("STCD"), m);
}
// STCD 聚合污染物去重后用逗号分隔
Map<String, Set<String>> pollutantSetMap = new LinkedHashMap<>();
for (Map<String, Object> m : pollutantData) {
String stcd = (String) m.get("STCD");
String pol = (String) m.get("POLLUTANT");
if (pol != null && !pol.isEmpty()) {
pollutantSetMap.computeIfAbsent(stcd, k -> new LinkedHashSet<>()).add(pol);
}
}
// ======== Row 0: 子标题行 ========
List<Object> subRow = new ArrayList<>();
subRow.add("");
subRow.add("达标数");
subRow.add("总数");
subRow.add("达标率(%)");
subRow.add("达标数");
subRow.add("总数");
subRow.add("达标率(%)");
subRow.add("");
List<List<Object>> rows = new ArrayList<>();
rows.add(subRow);
// ======== 数据行 ========
for (String rstcd : stationOrder) {
String stcd = rstcdToStcd.get(rstcd);
if (stcd == null) continue;
String displayName = stationRes.getDisplayName(rstcd, sttp);
Map<String, Object> hStat = hourlyMap.get(stcd);
Map<String, Object> dStat = dailyMap.get(stcd);
List<Object> row = new ArrayList<>();
row.add(displayName != null ? displayName : rstcd);
// 小时达标
appendComplianceCell(row, hStat);
// 日均达标
appendComplianceCell(row, dStat);
// 主要污染物
Set<String> pollutants = pollutantSetMap.get(stcd);
row.add(pollutants != null && !pollutants.isEmpty()
? String.join(",", pollutants) : "");
rows.add(row);
}
return rows;
}
/**
* 将达标统计 Map 的达标数/总数/达标率追加到 row
*/
private void appendComplianceCell(List<Object> row, Map<String, Object> stat) {
if (stat == null) {
row.add("");
row.add("");
row.add("");
return;
}
Object compliantObj = stat.get("COMPLIANT_CNT");
Object totalObj = stat.get("TOTAL_CNT");
long compliant = compliantObj instanceof Number ? ((Number) compliantObj).longValue() : 0;
long total = totalObj instanceof Number ? ((Number) totalObj).longValue() : 0;
row.add(compliant);
row.add(total);
if (total > 0) {
BigDecimal rate = BigDecimal.valueOf(compliant * 100.0 / total);
row.add(rate.setScale(2, RoundingMode.HALF_UP).toPlainString());
} else {
row.add("");
}
}
/** 分部达标统计 */
private static class ComplianceStats {
String dailyHb, dailySl, dailyDn;

View File

@ -24,4 +24,39 @@
AND ${fieldName} IS NOT NULL
</select>
<!-- 水质小时达标率统计:按 STCD 聚合 SFDB=1 达标数、总数 -->
<select id="selectComplianceData" resultType="java.util.HashMap">
SELECT
STCD,
SUM(CASE WHEN SFDB = 1 THEN 1 ELSE 0 END) AS COMPLIANT_CNT,
SUM(CASE WHEN SFDB IN (0, 1) THEN 1 ELSE 0 END) AS TOTAL_CNT
FROM SD_WQ_R
WHERE IS_DELETED = 0
AND STCD IN
<foreach collection="stcdList" item="stcd" open="(" separator="," close=")">
#{stcd}
</foreach>
AND TM &gt;= TO_DATE(#{startTime}, 'YYYY-MM-DD HH24:MI:SS')
AND TM &lt; TO_DATE(#{endTime}, 'YYYY-MM-DD HH24:MI:SS')
AND SFDB IS NOT NULL
GROUP BY STCD
</select>
<!-- 查询各测站主要污染物SFDB=0 时的 WQ_SFDBHN_YS -->
<select id="selectPollutants" resultType="java.util.HashMap">
SELECT
STCD,
WQ_SFDBHN_YS AS POLLUTANT
FROM SD_WQ_R
WHERE IS_DELETED = 0
AND SFDB = 0
AND WQ_SFDBHN_YS IS NOT NULL
AND STCD IN
<foreach collection="stcdList" item="stcd" open="(" separator="," close=")">
#{stcd}
</foreach>
AND TM &gt;= TO_DATE(#{startTime}, 'YYYY-MM-DD HH24:MI:SS')
AND TM &lt; TO_DATE(#{endTime}, 'YYYY-MM-DD HH24:MI:SS')
</select>
</mapper>

View File

@ -23,4 +23,22 @@
AND ${fieldName} IS NOT NULL
</select>
<!-- 水质日均达标率统计:按 STCD 聚合 SFDB=1 达标数、总数 -->
<select id="selectComplianceData" resultType="java.util.HashMap">
SELECT
STCD,
SUM(CASE WHEN SFDB = 1 THEN 1 ELSE 0 END) AS COMPLIANT_CNT,
SUM(CASE WHEN SFDB IN (0, 1) THEN 1 ELSE 0 END) AS TOTAL_CNT
FROM SD_WQDAY_S
WHERE IS_DELETED = 0
AND STCD IN
<foreach collection="stcdList" item="stcd" open="(" separator="," close=")">
#{stcd}
</foreach>
AND DT &gt;= TO_DATE(#{startTime}, 'YYYY-MM-DD HH24:MI:SS')
AND DT &lt; TO_DATE(#{endTime}, 'YYYY-MM-DD HH24:MI:SS')
AND SFDB IS NOT NULL
GROUP BY STCD
</select>
</mapper>