From 66a810ca3625fea2c133394991254695d2cd5be6 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 25 May 2026 10:17:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A2=9E=E5=8A=A0=E6=B0=B4=E8=B4=A8?= =?UTF-8?q?=E6=98=8E=E7=BB=86=E6=95=B0=E6=8D=AE=E6=9F=A5=E8=AF=A2=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wq/controller/EnvWqDataController.java | 6 + .../wq/service/impl/EnvWqDataServiceImpl.java | 489 +++++++++++++++++- 2 files changed, 483 insertions(+), 12 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/env/wq/controller/EnvWqDataController.java b/backend/src/main/java/com/yfd/platform/env/wq/controller/EnvWqDataController.java index ddff1bb..be6c330 100644 --- a/backend/src/main/java/com/yfd/platform/env/wq/controller/EnvWqDataController.java +++ b/backend/src/main/java/com/yfd/platform/env/wq/controller/EnvWqDataController.java @@ -29,6 +29,12 @@ public class EnvWqDataController { return ResponseResult.successData(envWqDataService.processKendoList(dataSourceRequest)); } + @PostMapping("/data/GetKendoListCust") + @Operation(summary = "水质明细数据查询") + public ResponseResult getDataKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(envWqDataService.processKendoList(dataSourceRequest)); + } + @PostMapping("/GetStbprpYsByStcd") @Operation(summary = "水质统计分析") public ResponseResult GetStbprpYsByStcd(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/env/wq/service/impl/EnvWqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/wq/service/impl/EnvWqDataServiceImpl.java index cce2aec..96932db 100644 --- a/backend/src/main/java/com/yfd/platform/env/wq/service/impl/EnvWqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/env/wq/service/impl/EnvWqDataServiceImpl.java @@ -12,6 +12,7 @@ import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.common.PageInfo; import com.yfd.platform.common.exception.BizException; +import com.yfd.platform.env.wq.entity.vo.EnvWqDataVo; import com.yfd.platform.env.wq.entity.vo.EnvWqVo; import com.yfd.platform.env.wq.entity.vo.WqBaseInfoVo; import com.yfd.platform.env.wq.entity.vo.WqVmsstbprptVo; @@ -25,9 +26,14 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.math.BigDecimal; +import java.util.Set; +import java.util.stream.Collectors; @Service public class EnvWqDataServiceImpl implements EnvWqDataService { @@ -41,14 +47,13 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { RequestHolder.getHttpServletRequest().getParameter(CommonConstant.CALCULATE_FLAG) ); - StringBuilder sql = new StringBuilder(buildEnvWqProcessBaseSql(calculated)); + StringBuilder sql = new StringBuilder(buildEnvWqDataBaseSql(calculated)); Map paramMap = new HashMap<>(); - if (calculated) { - paramMap.put("recordUser", SecurityUtils.getUserId()); - } - - String filterSql = buildEnvWqFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), - paramMap, new int[]{0}); + String filterSql = buildEnvWqDataFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); if (StrUtil.isNotBlank(filterSql)) { sql.append(" AND ").append(filterSql).append(" "); } @@ -57,7 +62,7 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { String groupBy = KendoUtil.getGroupBy(dataSourceRequest); GroupingInfo[] groupInfos = loadOptions.getGroup(); if (StrUtil.isNotBlank(groupBy) && groupInfos != null && groupInfos.length > 0) { - String groupedSql = buildEnvWqGroupSql(sql.toString(), dataSourceRequest, groupInfos); + String groupedSql = buildEnvWqDataGroupSql(sql.toString(), groupBy, groupInfos); List> list = microservicDynamicSQLMapper.pageAllList(null, groupedSql, paramMap); DataSourceResult result = new DataSourceResult(); if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { @@ -70,13 +75,14 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { return result; } - sql.append(buildEnvWqOrderBySql(dataSourceRequest.getSort())); + sql.append(buildEnvWqDataOrderBySql(dataSourceRequest.getSort())); PageInfo pageInfo = QgcQueryWrapperUtil.getPageInfo(loadOptions); Page page = pageInfo.getHasPageInfo() ? pageInfo.getPage() : null; - List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, EnvWqVo.class); - fillEnvWqDerivedFields(list, calculated); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, EnvWqDataVo.class); + fillEnvWqDataDerivedFields(list); + fillEnvWqDataLimit(list); - DataSourceResult result = new DataSourceResult<>(); + DataSourceResult result = new DataSourceResult<>(); result.setData(list); result.setTotal(page != null ? page.getTotal() : list.size()); result.setAggregates(new HashMap<>()); @@ -239,6 +245,465 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { return list.get(0); } + private String buildEnvWqDataBaseSql(boolean calculated) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("T.STCD AS stcd, ") + .append("T.RSTCD AS rstcd, ") + .append("T.STNM AS stnm, ") + .append("T.ST_CODE AS stCode, ") + .append("T.ST_NAME AS stName, ") + .append("T.ENNM AS ennm, ") + .append("T.TM AS tm, ") + .append("T.WTMP AS wtmp, ") + .append("T.PH AS ph, ") + .append("T.DOX AS dox, ") + .append("T.CODMN AS codmn, ") + .append("T.CODCR AS codcr, ") + .append("T.BOD5 AS bod5, ") + .append("T.NH3N AS nh3n, ") + .append("T.TP AS tp, ") + .append("T.TN AS tn, ") + .append("T.CU AS cu, ") + .append("T.ZN AS zn, ") + .append("T.F AS f, ") + .append("T.SE AS se, ") + .append("T.ARS AS ars, ") + .append("T.HG AS hg, ") + .append("T.CD AS cd, ") + .append("T.CR6 AS cr6, ") + .append("T.PB AS pb, ") + .append("T.CN AS cn, ") + .append("T.VLPH AS vlph, ") + .append("T.OIL AS oil, ") + .append("T.LAS AS las, ") + .append("T.S2 AS s2, ") + .append("T.FCG AS fcg, ") + .append("T.CL AS cl, ") + .append("T.SO4 AS so4, ") + .append("T.NO3 AS no3, ") + .append("T.THRD AS thrd, ") + .append("T.COND AS cond, ") + .append("T.FE AS fe, ") + .append("T.MN AS mn, ") + .append("T.AL AS al, ") + .append("T.CHLA AS chla, ") + .append("T.CLARITY AS clarity, ") + .append("T.TU AS tu, ") + .append("T.TOD AS tod, ") + .append("T.CYANO AS cyano, ") + .append("T.WQGRD AS wqgrd, ") + .append("T.WWQTG AS wwqtg, ") + .append("T.SFDB AS sfdb, ") + .append("T.WQ_SFDBHN_YS AS wqSfdbhnYs, ") + .append("T.BASE_ID AS baseId, ") + .append("T.BASE_NAME AS baseName, ") + .append("T.RVCD_NAME AS rvcdName, ") + .append("T.ADDVCD_NAME AS addvcdName, ") + .append("T.DTIN_TYPE AS dtinType, ") + .append("T.QI AS qi, ") + .append("T.QO AS qo, ") + .append("T.BASESTEPSORT AS baseStepSort, ") + .append("T.RVCDSTEPSORT AS rvcdStepSort, ") + .append("T.RSTCDSTEPSORT AS rstcdStepSort, ") + .append("T.SITESTEPSORT AS siteStepSort ") + .append("FROM (SELECT ") + .append("SWR.STCD, ") + .append("MSB.RSTCD, ") + .append("MSB.STNM, ") + .append("MSB.ST_CODE, ") + .append("MSB.ST_NAME, ") + .append("MSB.ENNM, ") + .append("SWR.TM, ") + .append("SWR.WTMP, SWR.PH, SWR.DOX, SWR.CODMN, SWR.CODCR, SWR.BOD5, ") + .append("SWR.NH3N, SWR.TP, SWR.TN, SWR.CU, SWR.ZN, SWR.F, SWR.SE, SWR.ARS, SWR.HG, SWR.CD, SWR.CR6, ") + .append("SWR.PB, SWR.CN, SWR.VLPH, SWR.OIL, SWR.LAS, SWR.S2, SWR.FCG, SWR.CL, SWR.SO4, SWR.NO3, SWR.THRD, ") + .append("SWR.COND, SWR.FE, SWR.MN, SWR.AL, SWR.CHLA, SWR.CLARITY, SWR.TU, SWR.TOD, SWR.CYANO, ") + .append("SWR.WQGRD, MSB.WWQTG, SWR.SFDB, SWR.WQ_SFDBHN_YS, ") + .append("MSB.BASE_ID, MSB.BASE_NAME, MSB.RVCD_NAME, MSB.ADDVCD_NAME, MSB.DTIN_TYPE, ") + .append("MSB.BASESTEPSORT, MSB.RVCDSTEPSORT, MSB.RSTCDSTEPSORT, MSB.SITESTEPSORT, ") + .append("MSB.TTPWR, MSB.STTP_CODE, "); + if (calculated) { + sql.append("CAST(NULL AS NUMBER(15,3)) AS QI, CAST(NULL AS NUMBER(15,3)) AS QO "); + } else { + sql.append("SHR.QI AS QI, SHR.QO AS QO "); + } + sql.append("FROM "); + if (calculated) { + sql.append("MS_WQCALCULATION_R SWR "); + } else { + sql.append("SD_WQ_R SWR "); + } + sql.append("INNER JOIN (").append(buildEnvWqDataStationBaseSql()).append(") MSB ON MSB.STCD = SWR.STCD "); + if (!calculated) { + sql.append("LEFT JOIN SD_HYDROPW_R SHR ON MSB.RSTCD = SHR.STCD AND SWR.TM = SHR.TM AND MSB.DTIN_TYPE = 0 ") + .append("WHERE SWR.TM <= SYSDATE ") + .append("AND (SWR.TASK_ID IS NULL OR SWR.TASK_ID = '' OR SWR.TASK_STATUS = 'Approved') "); + } else { + sql.append("WHERE 1 = 1 "); + } + sql.append(") T WHERE 1 = 1 "); + return sql.toString(); + } + + private String buildEnvWqDataStationBaseSql() { + return "SELECT " + + "wq.STCD, " + + "wq.RSTCD, " + + "wq.STNM, " + + "wq.FHSTCD AS ST_CODE, " + + "CAST(NULL AS VARCHAR2(200)) AS ST_NAME, " + + "eng.ENNM, " + + "eng.BASE_ID, " + + "hb.BASENAME AS BASE_NAME, " + + "rv.RVNM AS RVCD_NAME, " + + "addv.ADDVNM AS ADDVCD_NAME, " + + "wq.WWQTG, " + + "wq.DTIN_TYPE, " + + "siteAlong.SORT AS SITESTEPSORT, " + + "hb.ORDER_INDEX AS BASESTEPSORT, " + + "eng.TTPWR AS TTPWR, " + + "rstAlong.SORT AS RSTCDSTEPSORT, " + + "rvAlong.ORDER_INDEX AS RVCDSTEPSORT, " + + "wq.STTP AS STTP_CODE " + + "FROM SD_WQ_B_H wq " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + + "LEFT JOIN MS_ALONG_B rvAlong ON rvAlong.RVCD = eng.HBRVCD AND rvAlong.CODE = 'common' AND NVL(rvAlong.IS_DELETED, 0) = 0 " + + "LEFT JOIN (SELECT det.SORT, along.RVCD, det.STCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B along ON det.ALONG_ID = along.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(along.IS_DELETED, 0) = 0 AND along.CODE = 'common') rstAlong " + + " ON rstAlong.RVCD = eng.HBRVCD AND rstAlong.STCD = wq.RSTCD " + + "LEFT JOIN (SELECT det.SORT, along.RVCD, det.STCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B along ON det.ALONG_ID = along.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(along.IS_DELETED, 0) = 0 AND along.CODE = 'common') siteAlong " + + " ON siteAlong.RVCD = eng.HBRVCD AND siteAlong.STCD = wq.STCD " + + "WHERE wq.STTP = 'WQ' AND NVL(wq.IS_DELETED, 0) = 0"; + } + + private String buildEnvWqDataFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildEnvWqDataLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildEnvWqDataFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add(childSql); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return "(" + String.join(logic, conditions) + ")"; + } + + private String buildEnvWqDataLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapEnvWqDataColumn(filter.getField()); + if (StrUtil.isBlank(column) || filter.getValue() == null) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + String key = "envWqDataParam" + indexHolder[0]++; + boolean dateField = "tm".equals(filter.getField()); + switch (operator) { + case "eq": + paramMap.put(key, filter.getValue()); + return dateField ? column + " = TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS')" : column + " = #{map." + key + "}"; + case "neq": + paramMap.put(key, filter.getValue()); + return dateField ? column + " <> TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS')" : column + " <> #{map." + key + "}"; + case "gt": + paramMap.put(key, filter.getValue()); + return dateField ? column + " > TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS')" : column + " > #{map." + key + "}"; + case "gte": + paramMap.put(key, filter.getValue()); + return dateField ? column + " >= TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS')" : column + " >= #{map." + key + "}"; + case "lt": + paramMap.put(key, filter.getValue()); + return dateField ? column + " < TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS')" : column + " < #{map." + key + "}"; + case "lte": + paramMap.put(key, filter.getValue()); + return dateField ? column + " <= TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS')" : column + " <= #{map." + key + "}"; + case "contains": + paramMap.put(key, "%" + filter.getValue() + "%"); + return column + " LIKE #{map." + key + "}"; + default: + return ""; + } + } + + private String mapEnvWqDataColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "baseName" -> "T.BASE_NAME"; + case "stnm" -> "T.STNM"; + case "wwqtg" -> "T.WWQTG"; + case "baseId" -> "T.BASE_ID"; + case "rstcd" -> "T.RSTCD"; + case "ennm" -> "T.ENNM"; + case "stCode" -> "T.ST_CODE"; + case "stName" -> "T.ST_NAME"; + case "stcd" -> "T.STCD"; + case "tm" -> "T.TM"; + case "wqgrd" -> "T.WQGRD"; + case "ph" -> "T.PH"; + case "dox" -> "T.DOX"; + case "codmn" -> "T.CODMN"; + case "codcr" -> "T.CODCR"; + case "bod5" -> "T.BOD5"; + case "nh3n" -> "T.NH3N"; + case "tp" -> "T.TP"; + case "tn" -> "T.TN"; + case "cu" -> "T.CU"; + case "zn" -> "T.ZN"; + case "f" -> "T.F"; + case "se" -> "T.SE"; + case "ars" -> "T.ARS"; + case "hg" -> "T.HG"; + case "cd" -> "T.CD"; + case "cr6" -> "T.CR6"; + case "pb" -> "T.PB"; + case "cn" -> "T.CN"; + case "vlph" -> "T.VLPH"; + case "oil" -> "T.OIL"; + case "las" -> "T.LAS"; + case "s2" -> "T.S2"; + case "fcg" -> "T.FCG"; + case "cl" -> "T.CL"; + case "so4" -> "T.SO4"; + case "no3" -> "T.NO3"; + case "thrd" -> "T.THRD"; + case "cond" -> "T.COND"; + case "fe" -> "T.FE"; + case "mn" -> "T.MN"; + case "al" -> "T.AL"; + case "chla" -> "T.CHLA"; + case "clarity" -> "T.CLARITY"; + case "tu" -> "T.TU"; + case "cyano" -> "T.CYANO"; + case "sfdb" -> "T.SFDB"; + case "wtmp" -> "T.WTMP"; + case "dtinType" -> "T.DTIN_TYPE"; + case "tod" -> "T.TOD"; + case "wqSfdbhnYs" -> "T.WQ_SFDBHN_YS"; + case "siteStepSort" -> "T.SITESTEPSORT"; + case "baseStepSort" -> "T.BASESTEPSORT"; + case "ttpwr" -> "T.TTPWR"; + case "rstcdStepSort" -> "T.RSTCDSTEPSORT"; + case "sttpCode" -> "T.STTP_CODE"; + default -> null; + }; + } + + private String buildEnvWqDataGroupSql(String baseSql, String groupBy, GroupingInfo[] groupInfos) { + StringBuilder sql = new StringBuilder("SELECT "); + List groupFields = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + if (item != null && StrUtil.isNotBlank(item.getSelector())) { + groupFields.add(item.getSelector()); + } + } + sql.append(String.join(", ", groupFields)); + for (GroupingInfo item : groupInfos) { + sql.append(", COUNT(*) AS count_").append(item.getSelector()).append(" "); + } + sql.append("FROM (").append(baseSql).append(") T ").append(groupBy); + return sql.toString(); + } + + private String buildEnvWqDataOrderBySql(List sortList) { + if (sortList == null || sortList.isEmpty()) { + return ""; + } + StringBuilder sql = new StringBuilder(" ORDER BY "); + boolean appended = false; + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + if (sortDescriptor == null || StrUtil.isBlank(sortDescriptor.getField())) { + continue; + } + String column = mapEnvWqDataColumn(sortDescriptor.getField()); + if (column == null) { + continue; + } + if (appended) { + sql.append(", "); + } + sql.append(column).append(" ") + .append("desc".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"); + appended = true; + } + return appended ? sql.toString() : ""; + } + + private void fillEnvWqDataDerivedFields(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (EnvWqDataVo item : list) { + item.setWqgrdName(getWqLevelName(item.getWqgrd())); + item.setWwqtgName(getWqLevelName(item.getWwqtg())); + item.setSfdbName(getSfdbName(item.getSfdb())); + item.setWqSfdbhnYsName(convertWqFactors(item.getWqSfdbhnYs())); + } + } + + private void fillEnvWqDataLimit(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + String sql = "SELECT t2.YS AS ys, t2.MIN_VAL AS minVal, t2.MAX_VAL AS maxVal, t2.LVL AS lvl " + + "FROM MS_WARN_RULE_B t1 " + + "INNER JOIN MS_WARN_RULE_DETAIL_B t2 ON t1.ID = t2.RULE_ID " + + "WHERE t1.RULE_TYPE = 'WQLVL'"; + List> ruleList = microservicDynamicSQLMapper.pageAllList(null, sql, null); + if (CollUtil.isEmpty(ruleList)) { + return; + } + Map ruleDirectionMap = getWqLimitDirection(ruleList); + Map>> levelRuleMap = ruleList.stream() + .filter(item -> StrUtil.isNotBlank(asString(item.get("lvl")))) + .collect(Collectors.groupingBy(item -> asString(item.get("lvl")))); + + for (EnvWqDataVo item : list) { + if (StrUtil.isBlank(item.getWwqtg())) { + continue; + } + List> currentRules = levelRuleMap.get(item.getWwqtg()); + if (CollUtil.isEmpty(currentRules)) { + continue; + } + List> max = new ArrayList<>(); + List> min = new ArrayList<>(); + for (Map rule : currentRules) { + String ys = asString(rule.get("ys")); + Integer direction = ruleDirectionMap.get(ys); + Map maxMap = new LinkedHashMap<>(); + Map minMap = new LinkedHashMap<>(); + if (direction != null && direction == 2) { + maxMap.put(ys, rule.get("maxVal")); + minMap.put(ys, rule.get("minVal")); + max.add(maxMap); + min.add(minMap); + } else if (direction != null && direction == 1) { + minMap.put(ys, rule.get("minVal")); + min.add(minMap); + } else { + maxMap.put(ys, rule.get("maxVal")); + max.add(maxMap); + } + } + item.setMax(max); + item.setMin(min); + } + } + + private Map getWqLimitDirection(List> ruleList) { + Map>> grouped = ruleList.stream() + .collect(Collectors.groupingBy(item -> asString(item.get("ys")))); + Map result = new HashMap<>(); + for (Map.Entry>> entry : grouped.entrySet()) { + List> current = entry.getValue().stream() + .sorted(Comparator.comparing(item -> asBigDecimal(item.get("minVal")), Comparator.nullsLast(BigDecimal::compareTo))) + .collect(Collectors.toList()); + Set minSet = current.stream().map(item -> asBigDecimal(item.get("minVal"))).collect(Collectors.toSet()); + Set maxSet = current.stream().map(item -> asBigDecimal(item.get("maxVal"))).collect(Collectors.toSet()); + if (minSet.size() == 1 && maxSet.size() == 1) { + result.put(entry.getKey(), 2); + } else { + int first = Integer.parseInt(asString(current.get(0).get("lvl"))); + int last = Integer.parseInt(asString(current.get(current.size() - 1).get("lvl"))); + result.put(entry.getKey(), first > last ? 1 : 0); + } + } + return result; + } + + private String convertWqFactors(String raw) { + if (StrUtil.isBlank(raw)) { + return null; + } + Map factorMap = new LinkedHashMap<>(); + factorMap.put("WTMP", "水温"); + factorMap.put("PH", "pH"); + factorMap.put("DOX", "溶解氧"); + factorMap.put("CODMN", "高锰酸盐指数"); + factorMap.put("CODCR", "化学需氧量"); + factorMap.put("BOD5", "五日生化需氧量"); + factorMap.put("NH3N", "氨氮"); + factorMap.put("TP", "总磷"); + factorMap.put("TN", "总氮"); + factorMap.put("CU", "铜"); + factorMap.put("ZN", "锌"); + factorMap.put("F", "氟化物"); + factorMap.put("SE", "硒"); + factorMap.put("ARS", "砷"); + factorMap.put("HG", "汞"); + factorMap.put("CD", "镉"); + factorMap.put("CR6", "六价铬"); + factorMap.put("PB", "铅"); + factorMap.put("CN", "氰化物"); + factorMap.put("VLPH", "挥发酚"); + factorMap.put("OIL", "石油类"); + factorMap.put("LAS", "阴离子表面活性剂"); + factorMap.put("S2", "硫化物"); + factorMap.put("FCG", "粪大肠菌群"); + factorMap.put("CL", "氯化物"); + factorMap.put("SO4", "硫酸盐"); + factorMap.put("NO3", "硝酸盐氮"); + factorMap.put("THRD", "总硬度"); + factorMap.put("COND", "电导率"); + factorMap.put("FE", "铁"); + factorMap.put("MN", "锰"); + factorMap.put("AL", "铝"); + factorMap.put("CHLA", "叶绿素a"); + factorMap.put("CLARITY", "透明度"); + factorMap.put("TU", "浊度"); + factorMap.put("CYANO", "蓝绿藻"); + factorMap.put("TOD", "总需氧量"); + + List names = new ArrayList<>(); + for (String part : raw.split(",")) { + String key = StrUtil.trim(part).toUpperCase(); + if (StrUtil.isBlank(key)) { + continue; + } + names.add(factorMap.getOrDefault(key, key)); + } + return names.isEmpty() ? null : String.join(",", names); + } + + private String asString(Object value) { + return value == null ? null : String.valueOf(value); + } + + private BigDecimal asBigDecimal(Object value) { + if (value == null) { + return null; + } + if (value instanceof BigDecimal bigDecimal) { + return bigDecimal; + } + return new BigDecimal(String.valueOf(value)); + } + private String buildEnvWqProcessBaseSql(boolean calculated) { StringBuilder sql = new StringBuilder(); sql.append("SELECT ")