diff --git a/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java b/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java index 59e435bd..319f2ffd 100644 --- a/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java +++ b/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java @@ -5,6 +5,8 @@ import cn.hutool.core.bean.copier.CopyOptions; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; + +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.ArrayList; @@ -49,6 +51,20 @@ public interface MicroservicDynamicSQLMapper { return convertList(allList, resultType); } + default List getSingleColumnList(String sql, Map paramMap) { + List> rows = getAllList(sql, paramMap); + if (rows == null || rows.isEmpty()) { + return Collections.emptyList(); + } + List result = new ArrayList<>(rows.size()); + for (Map row : rows) { + // 获取第一个值并转为字符串 + Object firstValue = row.values().iterator().next(); + result.add(firstValue == null ? null : firstValue.toString()); + } + return result; + } + @Select({"select count(1) count from ${sql} and ${ew.sqlSegment}"}) Integer count(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 520e3752..be1aa4b8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -1504,7 +1504,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl getEvnmAutoMonitorList(DataSourceRequest dataSourceRequest); DataSourceResult qecRateCount(DataSourceRequest dataSourceRequest); + + DataSourceResult getDefaultYear(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index d470ba6e..e0582bb7 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -3327,6 +3327,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { "'ENG' AS sttpCode, " + "'电站' AS sttpName, " + "eng.STCD AS stcd, " + + "pbh.TTPWR AS ttpwr, " + "eng.ENNM AS stnm, " + "eng.ENNM AS ennm, " + "eng.BASE_ID AS baseId, " + @@ -3346,6 +3347,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + "NVL(eng.ORDER_INDEX, 999999) AS siteStepSort " + "FROM SD_ENGINFO_B_H eng " + + "INNER JOIN SD_PWR_B_H pbh ON pbh.STCD= eng.STCD " + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD AND hbrv.BASEID = eng.BASE_ID " + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + @@ -5440,6 +5442,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { case "sttpCode" -> "t.sttpCode"; case "sttpName" -> "t.sttpName"; case "stcd" -> "t.stcd"; + case "ttpwr" -> "t.ttpwr"; case "stnm" -> "t.stnm"; case "ennm" -> "t.ennm"; case "baseId" -> "t.baseId"; @@ -5802,4 +5805,48 @@ public class EngEqDataServiceImpl implements EngEqDataService { default -> null; }; } + + @Override + public DataSourceResult getDefaultYear(DataSourceRequest dataSourceRequest) { + DataSourceResult dataSourceResult = new DataSourceResult<>(); + List resultList = new ArrayList<>(); + dataSourceResult.setData(resultList); + dataSourceResult.setTotal(resultList.size()); + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String sttpCode = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "sttpCode"); + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(sttpCode)) { + return dataSourceResult; + } + + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + + String sql = switch (sttpCode) { + case "DW" -> "SELECT MAX(TM) AS TM FROM SD_DW_R WHERE STCD = #{map.stcd} AND NVL(IS_DELETED, 0) = 0"; + case "EQ" -> "SELECT MAX(TM) AS TM FROM SD_EQ_R WHERE STCD = #{map.stcd} AND NVL(IS_DELETED, 0) = 0"; + case "FB" -> "SELECT MAX(TM) AS TM FROM SD_ENGFR_R WHERE STCD = #{map.stcd} AND NVL(IS_DELETED, 0) = 0"; + case "VA" -> "SELECT MAX(TM) AS TM FROM SD_VA_R WHERE STCD = #{map.stcd} AND NVL(IS_DELETED, 0) = 0"; + case "VP" -> "SELECT MAX(TM) AS TM FROM SD_VP_R WHERE STCD = #{map.stcd} AND NVL(IS_DELETED, 0) = 0"; + default -> ""; + }; + + if (StrUtil.isBlank(sql)) { + return dataSourceResult; + } + + List> allList = microservicDynamicSQLMapper.getAllList(sql, paramMap); + if (CollUtil.isEmpty(allList)) { + return dataSourceResult; + } + Map map = allList.get(0); + if (map == null) { + return dataSourceResult; + } + Object tm = map.getOrDefault("TM", ""); + if (tm != null && StrUtil.isNotBlank(tm.toString())) { + resultList.add(tm.toString()); + } + return dataSourceResult; + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java index 9d05bd9f..7fa6c42f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java @@ -132,4 +132,18 @@ public class FbStationController { public ResponseResult getResearchKendoList(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getResearchKendoList(dataSourceRequest)); } + + @PostMapping("/fishhatchrecr/fish/GetKendoListCust") + @Operation(summary = "(全过程)增殖站二级页面: 过程图-产卵和孵化") + public ResponseResult getFishhatchrecrFishKendoListCust( + @Parameter(description = "类型:1-鱼卵数量,2-出苗数量") @RequestParam("type") Integer type, + @RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishhatchrecrFishKendoListCust(type, dataSourceRequest)); + } + + @PostMapping("/fishbreedr/fish/GetKendoListCust") + @Operation(summary = "(全过程)增殖站二级页面: 过程图-鱼苗") + public ResponseResult getFishbreedrFishKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishbreedrFishKendoListCust(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FishbreedRVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FishbreedRVo.java new file mode 100644 index 00000000..1d184777 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FishbreedRVo.java @@ -0,0 +1,15 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +@Data +public class FishbreedRVo { + + private String tm; + + private String ftp; + + private String ftpName; + + private String counts; +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FishhatchrecRVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FishhatchrecRVo.java new file mode 100644 index 00000000..9e767b51 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FishhatchrecRVo.java @@ -0,0 +1,17 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +@Data +public class FishhatchrecRVo { + + private String tm; + + private String ftp; + + private String ftpName; + + private String eggcount; + + private String outcount; +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/HeadColunmsVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/HeadColunmsVo.java new file mode 100644 index 00000000..9093d280 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/HeadColunmsVo.java @@ -0,0 +1,52 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class HeadColunmsVo { + + private String dataIndex; + + private String title; + + private Boolean visible = true; + + private String key; + + private String unit; + + private boolean merge; + + private String dataType; + + private String dataFormat; + + private List children; + + public HeadColunmsVo(String title, String dataIndex) { + this.title = title; + this.dataIndex = dataIndex; + } + + public HeadColunmsVo(String dataIndex, String title, Boolean visible, String key, boolean merge, List children) { + this.dataIndex = dataIndex; + this.title = title; + this.visible = visible; + this.key = key; + this.merge = merge; + this.children = children; + } + + public HeadColunmsVo setDataType(String dataType) { + this.dataType = dataType; + return this; + } + + public HeadColunmsVo setDataFormat(String dataFormat) { + this.dataFormat = dataFormat; + return this; + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/TableVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/TableVo.java new file mode 100644 index 00000000..5bd4141b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/TableVo.java @@ -0,0 +1,27 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +import java.util.List; + +@Data +public class TableVo { + + private List columns; + + private Object dataSource; + + private Long total; + + private Integer wtDeviceType; + + public TableVo() { + } + + public TableVo(List dataSource, Long total) { + this.dataSource = dataSource; + if (total != null) { + this.total = total; + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index 1bada486..77cd39aa 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -16,6 +16,7 @@ import com.yfd.platform.qgc_env.fb.entity.vo.FbStInfoResultVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStationStaticsDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.YearRpStatisticsVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStationOverviewSecondVo; +import com.yfd.platform.qgc_env.fb.entity.vo.TableVo; import java.util.List; import java.util.Map; @@ -57,4 +58,8 @@ public interface FbStationService { DataSourceResult getOverviewSecond(DataSourceRequest dataSourceRequest); DataSourceResult getQgcOverviewSecond(DataSourceRequest dataSourceRequest); + + DataSourceResult getFishhatchrecrFishKendoListCust(Integer type, DataSourceRequest dataSourceRequest); + + DataSourceResult getFishbreedrFishKendoListCust(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index a3e50842..d3df7885 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -30,6 +30,10 @@ import com.yfd.platform.qgc_env.fb.entity.vo.FbStInfoResultVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStationOverviewSecondVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStationStaticsDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStationStaticsRawVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FishbreedRVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FishhatchrecRVo; +import com.yfd.platform.qgc_env.fb.entity.vo.HeadColunmsVo; +import com.yfd.platform.qgc_env.fb.entity.vo.TableVo; import com.yfd.platform.qgc_env.fb.entity.vo.YearRpStatisticsVo; import com.yfd.platform.qgc_env.fb.service.FbStationService; import com.yfd.platform.utils.QgcQueryWrapperUtil; @@ -4103,4 +4107,469 @@ public class FbStationServiceImpl implements FbStationService { } values.add(text); } + + @Override + public DataSourceResult getFishhatchrecrFishKendoListCust(Integer type, DataSourceRequest dataSourceRequest) { + DataSourceResult dataSourceResult = new DataSourceResult<>(); + String unit = type == 1 ? "(万粒)" : "(万尾)"; + + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT tm, ") + .append("LISTAGG(TO_CHAR(ftp), ',') WITHIN GROUP (ORDER BY ftp) AS ftp, ") + .append("LISTAGG(TO_CHAR(NAME), ',') WITHIN GROUP (ORDER BY ftp) AS ftpName, ") + .append("LISTAGG(eggcount, ',') WITHIN GROUP (ORDER BY ftp) AS eggcount, ") + .append("LISTAGG(outcount, ',') WITHIN GROUP (ORDER BY ftp) AS outcount ") + .append("FROM (") + .append("SELECT ") + .append("TO_CHAR(tm, 'YYYY-MM') AS tm, ftp, ") + .append("CASE WHEN NAME IS NULL THEN TO_NCHAR(ftp) ELSE NAME END AS NAME, ") + .append("CASE WHEN SUM(eggcount) IS NULL THEN '-' ELSE RTRIM(TO_CHAR(SUM(eggcount), 'FM999999999999990.99'), '.') END AS eggcount, ") + .append("CASE WHEN SUM(outcount) IS NULL THEN '-' ELSE RTRIM(TO_CHAR(SUM(outcount), 'FM999999999999990.99'), '.') END AS outcount ") + .append("FROM (") + .append("SELECT ") + .append("t.tm, ") + .append("CASE WHEN fishViewZy.ZY_FISH_ID IS NULL THEN t.ftp ELSE fishViewZy.ZY_FISH_ID END AS ftp, ") + .append("CASE WHEN fishViewZy.NAME IS NULL THEN fishViewRv.NAME ELSE fishViewZy.NAME END AS NAME, ") + .append("t.eggcount, ") + .append("t.outcount ") + .append("FROM SD_FBFISHHATCHREC_R t ") + .append("LEFT JOIN SD_FBRD_B_H fb ON t.stcd = fb.STCD ") + .append("LEFT JOIN V_SD_FISHDICTORY_B fishViewRv ON t.FTP = fishViewRv.FISH_ID AND fb.HBRVCD = fishViewRv.RVCD ") + .append("LEFT JOIN V_SD_FISHDICTORY_B fishViewZy ON t.FTP = fishViewZy.FISH_ID AND fishViewZy.RVCD = 'ZY' ") + .append("WHERE NVL(t.IS_DELETED, 0) = 0 "); + + appendFishhatchrecrFishFilterConditions(sql, dataSourceRequest, paramMap); + + sql.append(") GROUP BY TO_CHAR(tm, 'YYYY-MM'), ftp, NAME ") + .append(") GROUP BY tm ") + .append("ORDER BY tm DESC "); + + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, FishhatchrecRVo.class + ); + + long total = page != null ? page.getTotal() : list.size(); + TableVo tableVo = buildFishhatchrecrFishTableVo(list, total, type, unit); + dataSourceResult.setData(Collections.singletonList(tableVo)); + dataSourceResult.setTotal(total); + dataSourceResult.setAggregates(new HashMap<>()); + return dataSourceResult; + } + + private void appendFishhatchrecrFishFilterConditions(StringBuilder sql, + DataSourceRequest dataSourceRequest, + Map paramMap) { + if (dataSourceRequest == null || dataSourceRequest.getFilter() == null) { + return; + } + String filterSql = buildFishhatchrecrFishFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + } + + private String buildFishhatchrecrFishFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildFishhatchrecrFishLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFishhatchrecrFishFilterCondition(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 buildFishhatchrecrFishLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + String column = mapFishhatchrecrFishColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator)) { + List values = normalizeQgcBsmfRValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "hatchFishP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String key = "hatchFishP" + indexHolder[0]++; + Object normalizedValue = normalizeFishhatchrecrFishValue(field, value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalizedValue); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalizedValue); + yield column + " <> #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + normalizedValue); + yield column + " LIKE #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalizedValue); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalizedValue); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalizedValue); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalizedValue); + yield column + " <= #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapFishhatchrecrFishColumn(String field) { + return switch (field) { + case "stcd" -> "t.STCD"; + case "ftp" -> "t.FTP"; + case "fishsrc" -> "t.FISHSRC"; + case "tm" -> "t.TM"; + case "rstcd" -> "fb.RSTCD"; + case "baseId" -> "fb.BASE_ID"; + case "hbrvcd" -> "fb.HBRVCD"; + default -> ""; + }; + } + + private Object normalizeFishhatchrecrFishValue(String field, Object value) { + if (value == null) { + return null; + } + if ("tm".equalsIgnoreCase(field) && value instanceof String text) { + return parseDateTimeSafely(text); + } + return value; + } + + private TableVo buildFishhatchrecrFishTableVo(List list, long total, Integer type, String unit) { + TableVo tableVo = new TableVo(); + List> resultData = new ArrayList<>(); + List columns = new ArrayList<>(); + Map fishMap = new LinkedHashMap<>(); + + if (CollUtil.isNotEmpty(list)) { + for (FishhatchrecRVo vo : list) { + Map rowMap = new LinkedHashMap<>(); + rowMap.put("tm", vo.getTm()); + + List ftpList = splitCsv(vo.getFtp()); + List ftpNameList = splitCsv(vo.getFtpName()); + List eggCountList = splitCsv(vo.getEggcount()); + List outCountList = splitCsv(vo.getOutcount()); + + int size = Math.min(ftpList.size(), Math.min(ftpNameList.size(), + Math.min(eggCountList.size(), outCountList.size()))); + + for (int i = 0; i < size; i++) { + String ftp = ftpList.get(i); + String ftpName = ftpNameList.get(i); + String value = type == 1 ? eggCountList.get(i) : outCountList.get(i); + rowMap.put(ftp, "-".equals(value) ? null : value); + fishMap.putIfAbsent(ftp, ftpName); + } + resultData.add(rowMap); + } + } + + columns.add(new HeadColunmsVo("tm", "时间", true, "tm", false, new ArrayList<>()) + .setDataType("date") + .setDataFormat("yyyy-MM")); + for (Map.Entry entry : fishMap.entrySet()) { + columns.add(new HeadColunmsVo(entry.getKey(), entry.getValue() + unit, true, entry.getKey(), false, new ArrayList<>())); + } + + tableVo.setColumns(columns); + tableVo.setDataSource(resultData); + tableVo.setTotal(total); + return tableVo; + } + + @Override + public DataSourceResult getFishbreedrFishKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceResult dataSourceResult = new DataSourceResult<>(); + + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT tm,\n") + .append("LISTAGG(TO_CHAR(ftp), ',') WITHIN GROUP (ORDER BY ftp) AS ftp,\n") + .append("LISTAGG(TO_CHAR(NAME), ',') WITHIN GROUP (ORDER BY ftp) AS ftpName,\n") + .append("LISTAGG(counts, ',') WITHIN GROUP (ORDER BY ftp) AS counts\n") + .append("FROM (\n") + .append("SELECT \n") + .append("to_CHAR(tm,'YYYY-MM') AS tm, ftp, CASE WHEN NAME IS NULL THEN TO_NCHAR(ftp) ELSE NAME END AS NAME, CASE WHEN SUM(counts) IS NULL THEN '-' ELSE TO_CHAR(SUM(counts)) END AS counts\n") + .append("FROM (\n") + .append("SELECT\n") + .append("\tt.tm,\n") + .append("\tCASE WHEN f.ZY_FISH_ID IS NULL THEN t.ftp ELSE f.ZY_FISH_ID END AS ftp,\n") + .append("\tCASE WHEN f.NAME IS NULL THEN TO_NCHAR(t.ftp) ELSE f.NAME END AS NAME,\n") + .append("\tt.counts\n") + .append("FROM\n") + .append("\t(\n") + .append("\tSELECT\n") + .append("\t\tstcd,\n") + .append("\t\tftp AS ftp,\n") + .append("\t\tcounts AS counts,\n") + .append("\t\ttm AS tm\n") + .append("\tFROM\n") + .append("\t\tSD_FBFISHBREED_R\n") + .append("\tWHERE\n") + .append("\t\tNVL(is_deleted, 0) = 0 "); + + appendFishbreedrFishFilterConditions(sql, dataSourceRequest, paramMap); + + sql.append(") t\n") + .append("LEFT JOIN SD_FBRD_B_H s ON\n") + .append("\tt.stcd = s.STCD\n") + .append("LEFT JOIN V_SD_FISHDICTORY_B f ON\n") + .append("\tt.FTP = f.FISH_ID\n") + .append("\tAND (s.HBRVCD = f.RVCD\n") + .append("\t\tOR f.RVCD = 'ZY')\n") + .append(") GROUP BY to_CHAR(tm,'YYYY-MM'), ftp, NAME\n") + .append(") GROUP BY tm\n") + .append("ORDER BY TM DESC"); + + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, FishbreedRVo.class + ); + + long total = page != null ? page.getTotal() : list.size(); + TableVo tableVo = buildFishbreedrFishTableVo(list, total); + dataSourceResult.setData(Collections.singletonList(tableVo)); + dataSourceResult.setTotal(total); + dataSourceResult.setAggregates(new HashMap<>()); + return dataSourceResult; + } + + private void appendFishbreedrFishFilterConditions(StringBuilder sql, + DataSourceRequest dataSourceRequest, + Map paramMap) { + if (dataSourceRequest == null || dataSourceRequest.getFilter() == null) { + return; + } + String filterSql = buildFishbreedrFishFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + } + + private String buildFishbreedrFishFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildFishbreedrFishLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFishbreedrFishFilterCondition(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 buildFishbreedrFishLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + String column = mapFishbreedrFishColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator)) { + List values = normalizeQgcBsmfRValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "breedFishP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String key = "breedFishP" + indexHolder[0]++; + Object normalizedValue = normalizeFishbreedrFishValue(field, value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalizedValue); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalizedValue); + yield column + " <> #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + normalizedValue); + yield column + " LIKE #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalizedValue); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalizedValue); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalizedValue); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalizedValue); + yield column + " <= #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapFishbreedrFishColumn(String field) { + return switch (field) { + case "stcd" -> "STCD"; + case "ftp" -> "t.FTP"; + case "counts" -> "t.COUNTS"; + case "tm" -> "TM"; + case "rstcd" -> "s.RSTCD"; + case "baseId" -> "s.BASE_ID"; + case "hbrvcd" -> "s.HBRVCD"; + default -> ""; + }; + } + + private Object normalizeFishbreedrFishValue(String field, Object value) { + if (value == null) { + return null; + } + if ("tm".equalsIgnoreCase(field) && value instanceof String text) { + return parseDateTimeSafely(text); + } + return value; + } + + private TableVo buildFishbreedrFishTableVo(List list, long total) { + TableVo tableVo = new TableVo(); + List> resultData = new ArrayList<>(); + List columns = new ArrayList<>(); + Map fishMap = new LinkedHashMap<>(); + + if (CollUtil.isNotEmpty(list)) { + for (FishbreedRVo vo : list) { + Map rowMap = new LinkedHashMap<>(); + rowMap.put("tm", vo.getTm()); + + List ftpList = splitCsv(vo.getFtp()); + List ftpNameList = splitCsv(vo.getFtpName()); + List countsList = splitCsv(vo.getCounts()); + + int size = Math.min(ftpList.size(), Math.min(ftpNameList.size(), countsList.size())); + + for (int i = 0; i < size; i++) { + String ftp = ftpList.get(i); + String ftpName = ftpNameList.get(i); + String countStr = countsList.get(i); + rowMap.put(ftp, "-".equals(countStr) ? null : countStr); + fishMap.putIfAbsent(ftp, ftpName); + } + resultData.add(rowMap); + } + } + + columns.add(new HeadColunmsVo("tm", "时间", true, "tm", false, new ArrayList<>()) + .setDataType("date") + .setDataFormat("yyyy-MM")); + for (Map.Entry entry : fishMap.entrySet()) { + columns.add(new HeadColunmsVo(entry.getKey(), entry.getValue() + "(尾)", true, entry.getKey(), false, new ArrayList<>())); + } + + tableVo.setColumns(columns); + tableVo.setDataSource(resultData); + tableVo.setTotal(total); + return tableVo; + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VapConstructionController.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VapConstructionController.java index ffa9a01e..ef34b630 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VapConstructionController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VapConstructionController.java @@ -64,4 +64,16 @@ public class VapConstructionController { public ResponseResult getVarKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(vpConstructionService.processVarKendoList(dataSourceRequest)); } + + @PostMapping("/var/year/GetKendoListCust") + @Operation(summary = "动物救助站数据年份列表") + public ResponseResult getVarYearKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vpConstructionService.getVarYearList(dataSourceRequest)); + } + + @PostMapping("/vpr/year/GetKendoListCust") + @Operation(summary = "珍稀植物园数据年份列表") + public ResponseResult getVprYearKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vpConstructionService.getVprYearList(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java index 28de636f..0a362f81 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java @@ -23,4 +23,8 @@ public interface VpConstructionService { DataSourceResult processVacKendoList(DataSourceRequest dataSourceRequest); DataSourceResult processVarKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult getVarYearList(DataSourceRequest dataSourceRequest); + + DataSourceResult getVprYearList(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java index fe46774a..e0bc4ccf 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java @@ -1814,4 +1814,98 @@ public class VpConstructionServiceImpl implements VpConstructionService { } return " ORDER BY " + String.join(", ", orderItems); } + + @Override + public DataSourceResult getVarYearList(DataSourceRequest dataSourceRequest) { + DataSourceResult dataSourceResult = new DataSourceResult<>(); + DataSourceLoadOptionsBase loadOptionsBase = dataSourceRequest.toDevRequest(); + String baseId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptionsBase, "baseId"); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptionsBase, "stcd"); + String rstcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptionsBase, "rstcd"); + + StringBuilder sql = new StringBuilder("SELECT TO_CHAR(r.TM, 'YYYY') year FROM SD_VA_R r " + + "LEFT JOIN SD_VABASIC_B svb ON r.TETP = svb.ID " + + "LEFT JOIN SD_VA_B_H a ON a.STCD = r.STCD WHERE NVL(r.IS_DELETED, 0) = 0 "); + + if (StrUtil.isNotBlank(baseId)) { + sql.append(" AND a.BASE_ID = #{map.baseId} "); + } + if (StrUtil.isNotBlank(stcd)) { + sql.append(" AND a.STCD = #{map.stcd} "); + } + if (StrUtil.isNotBlank(rstcd)) { + sql.append(" AND a.RSTCD = #{map.rstcd} "); + } + sql.append(" GROUP BY TO_CHAR(r.TM, 'YYYY') ORDER BY TO_CHAR(r.TM, 'YYYY') DESC "); + + Map paramMap = new HashMap<>(); + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("baseId", baseId); + } + if (StrUtil.isNotBlank(stcd)) { + paramMap.put("stcd", stcd); + } + if (StrUtil.isNotBlank(rstcd)) { + paramMap.put("rstcd", rstcd); + } + + Page page = KendoUtil.getPage(dataSourceRequest); + List> list = microservicDynamicSQLMapper.pageAllList(page, sql.toString(), paramMap); + List yList = new ArrayList<>(); + for (Map it : list) { + if (it.get("YEAR") != null && StrUtil.isNotBlank(it.get("YEAR").toString())) { + yList.add(it.get("YEAR").toString()); + } + } + dataSourceResult.setData(yList); + dataSourceResult.setTotal(page != null ? page.getTotal() : (long) yList.size()); + return dataSourceResult; + } + + @Override + public DataSourceResult getVprYearList(DataSourceRequest dataSourceRequest) { + DataSourceResult dataSourceResult = new DataSourceResult<>(); + DataSourceLoadOptionsBase loadOptionsBase = dataSourceRequest.toDevRequest(); + String baseId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptionsBase, "baseId"); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptionsBase, "stcd"); + String rstcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptionsBase, "rstcd"); + + StringBuilder sql = new StringBuilder("SELECT TO_CHAR(r.TM, 'YYYY') year FROM SD_VP_R r " + + "LEFT JOIN SD_VPBASIC_B svb ON r.PLANT_ID = svb.ID " + + "LEFT JOIN SD_VP_B_H a ON a.STCD = r.STCD WHERE NVL(r.IS_DELETED, 0) = 0 "); + + if (StrUtil.isNotBlank(baseId)) { + sql.append(" AND a.BASE_ID = #{map.baseId} "); + } + if (StrUtil.isNotBlank(stcd)) { + sql.append(" AND a.STCD = #{map.stcd} "); + } + if (StrUtil.isNotBlank(rstcd)) { + sql.append(" AND a.RSTCD = #{map.rstcd} "); + } + sql.append(" GROUP BY TO_CHAR(r.TM, 'YYYY') ORDER BY TO_CHAR(r.TM, 'YYYY') DESC "); + + Map paramMap = new HashMap<>(); + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("baseId", baseId); + } + if (StrUtil.isNotBlank(stcd)) { + paramMap.put("stcd", stcd); + } + if (StrUtil.isNotBlank(rstcd)) { + paramMap.put("rstcd", rstcd); + } + + Page page = KendoUtil.getPage(dataSourceRequest); + List> list = microservicDynamicSQLMapper.pageAllList(page, sql.toString(), paramMap); + List yList = new ArrayList<>(); + for (Map it : list) { + if (it.get("YEAR") != null && StrUtil.isNotBlank(it.get("YEAR").toString())) { + yList.add(it.get("YEAR").toString()); + } + } + dataSourceResult.setData(yList); + dataSourceResult.setTotal(page != null ? page.getTotal() : (long) yList.size()); + return dataSourceResult; + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java index 00421006..ebb0f33c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java @@ -74,4 +74,10 @@ public class WarnDataController { public ResponseResult getWarnStcdKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(warnDataService.getWarnStcdKendoListCust(dataSourceRequest)); } + + @PostMapping("/ai/com/qgc/aiFile/GetKendoListCust") + @Operation(summary = "全过程AI识别监测日历表(文件)") + public ResponseResult getAiFileKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiFileKendoListCust(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiFileVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiFileVo.java new file mode 100644 index 00000000..c4d2abce --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiFileVo.java @@ -0,0 +1,43 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + +/** + * AI文件列表VO - 全过程AI识别监测日历表(文件) + * + * @author Generated + * @since 2025-07-01 + */ +@Data +public class AiFileVo { + + private String stcd; + + private String stnm; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date tm; + + private String fid; + + private String rstcd; + + private String ennm; + + private String stCode; + + private String stName; + + private Integer baseStepSort; + + private Integer rvcdStepSort; + + private Integer rstcdStepSort; + + private Integer siteStepSort; + + private Integer dataType; +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java index eccdcb72..66f942ff 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java @@ -8,6 +8,7 @@ import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiFileVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; import com.yfd.platform.qgc_env.warn.entity.vo.StcdWarnStateVo; @@ -32,4 +33,6 @@ public interface WarnDataService { DataSourceResult getAlarmPointKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getWarnStcdKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getAiFileKendoListCust(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java index efd22964..1928c9ed 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java @@ -13,6 +13,7 @@ import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.qgc_env.warn.entity.vo.AlarmPointVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiFileVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiRecordVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; @@ -356,6 +357,254 @@ public class WarnDataServiceImpl implements WarnDataService { return result; } + @Override + public DataSourceResult getAiFileKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String tm = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + String rstcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String type = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "type"); + String dataType = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "dataType"); + + Date startTime = null, endTime = null; + if (StrUtil.isNotBlank(tm)) { + String[] ll = tm.split(","); + if (ll.length == 2) { + startTime = DateUtil.parse(ll[0]); + endTime = DateUtil.parse(ll[1]); + if (startTime.after(endTime)) { + Date tmp = startTime; + startTime = endTime; + endTime = tmp; + } + } + } + + if (StrUtil.isNotBlank(rstcd)) { + rstcd = rstcd.replace("[", "").replace("]", "").replaceAll("\"", "'"); + } + + Map paramMap = new HashMap<>(); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT * FROM ("); + sql.append(buildAiFileHeartbeatSql(baseId, type, rstcd, stcd, startTime, endTime, paramMap, "hb")); + sql.append(" UNION "); + sql.append(buildAiFileComSql(baseId, type, rstcd, stcd, startTime, endTime, paramMap, "ac")); + sql.append(") WHERE 1=1 "); + + if (StrUtil.isNotBlank(dataType)) { + paramMap.put("dataType", Integer.parseInt(dataType)); + sql.append("AND DATA_TYPE = #{map.dataType} "); + } + + sql.append(buildAiFileOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + AiFileVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page == null ? list.size() : page.getTotal()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildAiFileHeartbeatSql(String baseId, String type, String rstcd, String stcd, + Date startTime, Date endTime, Map paramMap, String keyPrefix) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("a.STCD AS STCD, ") + .append("b.RSTCD AS RSTCD, ") + .append("eng.ENNM AS ENNM, ") + .append("b.STCD AS STCODE, ") + .append("b.STNM AS STNAME, ") + .append("hb.ORDER_INDEX AS BASESTEPSORT, ") + .append("along.ORDER_INDEX AS RVCDSTEPSORT, ") + .append("rstSort.SORT AS RSTCDSTEPSORT, ") + .append("siteSort.SORT AS SITESTEPSORT, ") + .append("b.STNM AS STNM, ") + .append("a.TM AS TM, "); + + if (StrUtil.isNotBlank(type)) { + if ("AI_5001".equals(type) || "AI_50011".equals(type)) { + sql.append("3 AS DATA_TYPE, "); + } else { + sql.append("1 AS DATA_TYPE, "); + } + } else { + sql.append("1 AS DATA_TYPE, "); + } + + sql.append("REGEXP_SUBSTR(a.FID, '[^,]+', 1, LEVEL) AS FID "); + sql.append("FROM SD_AIHEARTBEAT_R a "); + sql.append("INNER JOIN SD_AIMONITOR_B_H b ON a.STCD = b.STCD AND NVL(b.IS_DELETED, 0) = 0 AND b.STTP LIKE 'AI_%' "); + sql.append("LEFT JOIN SD_ENGINFO_B_H eng ON b.RSTCD = eng.STCD AND NVL(eng.IS_DELETED, 0) = 0 "); + sql.append("LEFT JOIN SD_HYDROBASE hb ON b.BASE_ID = hb.BASEID AND NVL(hb.IS_DELETED, 0) = 0 "); + sql.append("LEFT JOIN MS_ALONG_B along ON b.HBRVCD = along.RVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 "); + sql.append("LEFT JOIN (SELECT det.SORT, cfg.RVCD, det.STCD FROM MS_ALONGDET_B det INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common') rstSort ON rstSort.RVCD = b.HBRVCD AND rstSort.STCD = b.RSTCD "); + sql.append("LEFT JOIN (SELECT det.SORT, cfg.RVCD, det.STCD FROM MS_ALONGDET_B det INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common') siteSort ON siteSort.RVCD = b.HBRVCD AND siteSort.STCD = b.STCD "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); + sql.append("AND a.FID NOT LIKE '%ORA-%' AND a.FID NOT LIKE '%Out%' "); + + if (StrUtil.isNotBlank(type)) { + if ("AI_50011".equals(type)) { + sql.append("AND b.STTP = 'AI_5001' "); + } else { + sql.append("AND b.STTP = '").append(type).append("' "); + } + } + if (StrUtil.isNotBlank(baseId)) { + paramMap.put(keyPrefix + "BaseId", baseId); + sql.append("AND b.BASE_ID = #{map.").append(keyPrefix).append("BaseId} "); + } + if (StrUtil.isNotBlank(stcd)) { + paramMap.put(keyPrefix + "Stcd", stcd); + sql.append("AND b.STCD = #{map.").append(keyPrefix).append("Stcd} "); + } + if (StrUtil.isNotBlank(rstcd)) { + sql.append("AND b.RSTCD IN (").append(rstcd).append(") "); + } + if (startTime != null) { + paramMap.put(keyPrefix + "StartTime", startTime); + sql.append("AND a.TM >= #{map.").append(keyPrefix).append("StartTime} "); + } + if (endTime != null) { + paramMap.put(keyPrefix + "EndTime", endTime); + sql.append("AND a.TM <= #{map.").append(keyPrefix).append("EndTime} "); + } + + sql.append("CONNECT BY REGEXP_SUBSTR(a.FID, '[^,]+', 1, LEVEL) IS NOT NULL "); + sql.append("AND PRIOR a.ID = a.ID "); + sql.append("AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL"); + + return sql.toString(); + } + + private String buildAiFileComSql(String baseId, String type, String rstcd, String stcd, + Date startTime, Date endTime, Map paramMap, String keyPrefix) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("a.STCD AS STCD, ") + .append("b.RSTCD AS RSTCD, ") + .append("eng.ENNM AS ENNM, ") + .append("b.STCD AS STCODE, ") + .append("b.STNM AS STNAME, ") + .append("hb.ORDER_INDEX AS BASESTEPSORT, ") + .append("along.ORDER_INDEX AS RVCDSTEPSORT, ") + .append("rstSort.SORT AS RSTCDSTEPSORT, ") + .append("siteSort.SORT AS SITESTEPSORT, ") + .append("b.STNM AS STNM, ") + .append("a.TM AS TM, "); + + if (StrUtil.isNotBlank(type)) { + if ("AI_5001".equals(type) || "AI_50011".equals(type)) { + sql.append("(CASE WHEN a.TYPE = 'AI_5001' AND (a.IS_BIG_DEBRIS_AREA IS NULL OR a.IS_BIG_DEBRIS_AREA = 0) THEN 4 WHEN a.TYPE = 'AI_5001' AND a.IS_BIG_DEBRIS_AREA > 0 THEN 5 END) AS DATA_TYPE, "); + } else { + sql.append("2 AS DATA_TYPE, "); + } + } else { + sql.append("2 AS DATA_TYPE, "); + } + + sql.append("REGEXP_SUBSTR(a.FID, '[^,]+', 1, LEVEL) AS FID "); + sql.append("FROM SD_AICOM_R a "); + sql.append("INNER JOIN SD_AIMONITOR_B_H b ON a.STCD = b.STCD AND NVL(b.IS_DELETED, 0) = 0 AND b.STTP LIKE 'AI_%' "); + sql.append("LEFT JOIN SD_ENGINFO_B_H eng ON b.RSTCD = eng.STCD AND NVL(eng.IS_DELETED, 0) = 0 "); + sql.append("LEFT JOIN SD_HYDROBASE hb ON b.BASE_ID = hb.BASEID AND NVL(hb.IS_DELETED, 0) = 0 "); + sql.append("LEFT JOIN MS_ALONG_B along ON b.HBRVCD = along.RVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 "); + sql.append("LEFT JOIN (SELECT det.SORT, cfg.RVCD, det.STCD FROM MS_ALONGDET_B det INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common') rstSort ON rstSort.RVCD = b.HBRVCD AND rstSort.STCD = b.RSTCD "); + sql.append("LEFT JOIN (SELECT det.SORT, cfg.RVCD, det.STCD FROM MS_ALONGDET_B det INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common') siteSort ON siteSort.RVCD = b.HBRVCD AND siteSort.STCD = b.STCD "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); + sql.append("AND (a.TASK_STATUS IS NULL OR a.TASK_STATUS = 'Approved') "); + sql.append("AND a.FID NOT LIKE '%ORA-%' AND a.FID NOT LIKE '%Out%' "); + + if (StrUtil.isNotBlank(type)) { + if ("AI_50011".equals(type)) { + paramMap.put(keyPrefix + "Type", "AI_5001"); + sql.append("AND a.TYPE = #{map.").append(keyPrefix).append("Type} "); + } else { + paramMap.put(keyPrefix + "Type", type); + sql.append("AND a.TYPE = #{map.").append(keyPrefix).append("Type} "); + } + } + if (StrUtil.isNotBlank(baseId)) { + paramMap.put(keyPrefix + "BaseId", baseId); + sql.append("AND b.BASE_ID = #{map.").append(keyPrefix).append("BaseId} "); + } + if (StrUtil.isNotBlank(stcd)) { + paramMap.put(keyPrefix + "Stcd", stcd); + sql.append("AND b.STCD = #{map.").append(keyPrefix).append("Stcd} "); + } + if (StrUtil.isNotBlank(rstcd)) { + sql.append("AND b.RSTCD IN (").append(rstcd).append(") "); + } + if (startTime != null) { + paramMap.put(keyPrefix + "StartTime", startTime); + sql.append("AND a.TM >= #{map.").append(keyPrefix).append("StartTime} "); + } + if (endTime != null) { + paramMap.put(keyPrefix + "EndTime", endTime); + sql.append("AND a.TM <= #{map.").append(keyPrefix).append("EndTime} "); + } + + sql.append("CONNECT BY REGEXP_SUBSTR(a.FID, '[^,]+', 1, LEVEL) IS NOT NULL "); + sql.append("AND PRIOR a.ID = a.ID "); + sql.append("AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL"); + + return sql.toString(); + } + + private String buildAiFileOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY STCD, TM DESC "; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor item : sortList) { + if (item == null || StrUtil.isBlank(item.getField())) { + continue; + } + String column = mapAiFileColumn(item.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(item.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + return " ORDER BY STCD, TM DESC "; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String mapAiFileColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "STCD"; + case "stnm" -> "STNM"; + case "tm" -> "TM"; + case "fid" -> "FID"; + case "rstcd" -> "RSTCD"; + case "ennm" -> "ENNM"; + case "stCode" -> "STCODE"; + case "stName" -> "STNAME"; + case "baseStepSort" -> "BASESTEPSORT"; + case "rvcdStepSort" -> "RVCDSTEPSORT"; + case "rstcdStepSort" -> "RSTCDSTEPSORT"; + case "siteStepSort" -> "SITESTEPSORT"; + case "dataType" -> "DATA_TYPE"; + default -> null; + }; + } + private AiDmRunVo buildAiDmRunVo(Map row) { if (row == null || row.isEmpty()) { return null; diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/controller/WeFishController.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/controller/WeFishController.java index b9a881bb..d5f145ee 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wte/controller/WeFishController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/controller/WeFishController.java @@ -7,10 +7,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/wte") @@ -158,4 +155,34 @@ public class WeFishController { public ResponseResult getTeSpecialAnimalList(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(weFishService.getTeSpecialAnimalList(dataSourceRequest)); } + + @GetMapping("/we/wer/getWeDefaultData") + @Operation(summary = "查询水生生态断面的年份及是否鱼类,水温,水质,流速数据") + public ResponseResult getWeDefaultData(@RequestParam("stcd") String stcd) { + return ResponseResult.successData(weFishService.getWeDefaultData(stcd)); + } + + @GetMapping("/we/wer/getWeYr") + @Operation(summary = "查询水生生态断面有数据的年份") + public ResponseResult getWeYr(@RequestParam("stcd") String stcd) { + return ResponseResult.successData(weFishService.getWeYr(stcd)); + } + + @PostMapping("/we/wewtr/GetKendoListCust") + @Operation(summary = "水生生态调查-水温数据列表") + public ResponseResult getWeWtR(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWeWtR(dataSourceRequest)); + } + + @PostMapping("/we/wewqr/GetKendoListCust") + @Operation(summary = "水生生态调查-水质数据列表") + public ResponseResult getWeWqR(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWeWqR(dataSourceRequest)); + } + + @PostMapping("/we/fvR/GetKendoListCust") + @Operation(summary = "水生生态调查-流速数据列表") + public ResponseResult getWeFvR(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWeFvR(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeDefaultDataVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeDefaultDataVo.java new file mode 100644 index 00000000..afaafca0 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeDefaultDataVo.java @@ -0,0 +1,16 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "水生生态断面默认数据实体类") +public class WeDefaultDataVo { + + private String yr; + private Integer hasFtp; + private Integer hasFv; + private Integer hasWq; + private Integer hasWt; + +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFvVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFvVo.java new file mode 100644 index 00000000..0db148d6 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFvVo.java @@ -0,0 +1,15 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +public class WeFvVo { + private String dcpc; + private String stcd; + private Date tm; + private BigDecimal flowrate; + private String fid; +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWqVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWqVo.java new file mode 100644 index 00000000..6600e9c2 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWqVo.java @@ -0,0 +1,51 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +public class WeWqVo { + private String stcd; + private String dcpc; + private String name; + private Date tm; + private BigDecimal ph; + private BigDecimal dox; + private BigDecimal codmn; + private BigDecimal codcr; + private BigDecimal bod5; + private BigDecimal nh3n; + private BigDecimal tp; + private BigDecimal tn; + private BigDecimal cu; + private BigDecimal zn; + private BigDecimal f; + private BigDecimal se; + private BigDecimal ars; + private BigDecimal hg; + private BigDecimal cd; + private BigDecimal cr6; + private BigDecimal pb; + private BigDecimal cn; + private BigDecimal vlph; + private BigDecimal oil; + private BigDecimal las; + private BigDecimal s2; + private BigDecimal fcg; + private BigDecimal cl; + private BigDecimal so4; + private BigDecimal no3; + private BigDecimal thrd; + private BigDecimal cond; + private BigDecimal fe; + private BigDecimal mn; + private BigDecimal al; + private BigDecimal chla; + private BigDecimal clarity; + private BigDecimal tu; + private BigDecimal cyano; + private String fid; + private Integer parameter; +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWtVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWtVo.java new file mode 100644 index 00000000..70bffdb7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWtVo.java @@ -0,0 +1,18 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +public class WeWtVo { + + private String dcpc; + + private String stcd; + + private Date tm; + + private BigDecimal wt; +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/WeFishService.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/WeFishService.java index fe6da23e..ba33bd32 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/WeFishService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/WeFishService.java @@ -2,24 +2,7 @@ package com.yfd.platform.qgc_env.wte.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListStatQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeCompareBarTableVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeEnvmAutoMonitorVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishDetailVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishHbbQgcDetailVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeMsstbprptVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPageTableVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPointQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatTabVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishTQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeStaticsVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeTeSpecialAnimalVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeVmsstbprptVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaDefaultVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaYearQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.*; import java.util.List; import java.util.Map; @@ -71,4 +54,14 @@ public interface WeFishService { DataSourceResult getQgcWeFishPoint(DataSourceRequest dataSourceRequest); DataSourceResult getTeSpecialAnimalList(DataSourceRequest dataSourceRequest); + + List getWeDefaultData(String stcd); + + DataSourceResult getWeYr(String stcd); + + DataSourceResult getWeWtR(DataSourceRequest dataSourceRequest); + + DataSourceResult getWeWqR(DataSourceRequest dataSourceRequest); + + DataSourceResult getWeFvR(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java index d6fa20be..35996aa1 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java @@ -10,29 +10,9 @@ import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.common.GroupHelper; import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; -import com.yfd.platform.qgc_env.wte.entity.vo.WeCompareBarHeadColumnVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeCompareBarTableVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeCompareBarVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeEnvmAutoMonitorVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListStatQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishDetailVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishHbbQgcDetailVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPageQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPageTableVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeMsstbprptVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPointQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatTabVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeFishTQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeRvcdYearVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeStaticsVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeTeSpecialAnimalVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeVmsstbprptVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaDefaultVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaQgcVo; -import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaYearQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.*; import com.yfd.platform.qgc_env.wte.service.WeFishService; +import com.yfd.platform.utils.KendoUtil; import com.yfd.platform.utils.QgcQueryWrapperUtil; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -1123,6 +1103,585 @@ public class WeFishServiceImpl implements WeFishService { return result; } + @Override + public List getWeDefaultData(String stcd) { + String sql = "SELECT\n" + + "\ta.stcd,\n" + + "\tTO_CHAR( a.TM, 'yyyy' ) AS yr,\n" + + "CASE\n" + + "\t\t\n" + + "\t\tWHEN COUNT( b.ID ) > 0 THEN\n" + + "\t\t1 ELSE 0 \n" + + "\tEND AS hasFtp,\n" + + "CASE\n" + + "\t\t\n" + + "\t\tWHEN COUNT( c.ID ) > 0 THEN\n" + + "\t\t1 ELSE 0 \n" + + "\tEND AS hasFv,\n" + + "CASE\n" + + "\t\t\n" + + "\t\tWHEN COUNT( d.ID ) > 0 THEN\n" + + "\t\t1 ELSE 0 \n" + + "\tEND AS hasWq,\n" + + "CASE\n" + + "\t\t\n" + + "\t\tWHEN COUNT( e.ID ) > 0 THEN\n" + + "\t\t1 ELSE 0 \n" + + "\tEND AS hasWt \n" + + "FROM\n" + + "\tSD_WE_R a\n" + + "\tLEFT JOIN SD_WEFISH_R b ON a.ID = b.WER_ID \n" + + "\tAND b.IS_DELETED = 0\n" + + "\tLEFT JOIN SD_WEFV_R c ON a.ID = c.WER_ID \n" + + "\tAND c.IS_DELETED = 0\n" + + "\tLEFT JOIN SD_WEWQ_R d ON a.ID = d.WER_ID \n" + + "\tAND d.IS_DELETED = 0\n" + + "\tLEFT JOIN SD_WEWT_R e ON a.ID = e.WER_ID \n" + + "\tAND e.IS_DELETED = 0 \n" + + "WHERE\n" + + "\t1 = 1 \n" + + "\tAND a.IS_DELETED = 0 \n" + + "\tAND a.stcd = #{map.stcd} \n" + + "GROUP BY\n" + + "\ta.stcd,\n" + + "\tTO_CHAR( a.TM, 'yyyy' ) \n" + + "ORDER BY\n" + + "\tTO_CHAR( a.TM, 'yyyy' ) DESC,\n" + + "\ta.stcd\n" + + "\n"; + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + List oneBySqlWithResultType = microservicDynamicSQLMapper.getAllListWithResultType(sql, paramMap, WeDefaultDataVo.class); + return oneBySqlWithResultType; + } + + @Override + public DataSourceResult getWeYr(String stcd) { + DataSourceResult dataSourceResult = new DataSourceResult(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT TO_CHAR(TM, 'yyyy') AS yr FROM SD_WE_R ") + .append("WHERE NVL(IS_DELETED, 0) = 0 AND NVL(STATUS, 1) = 1 "); + if (StrUtil.isNotBlank(stcd)) { + sql.append("AND STCD = #{map.stcd} "); + } + sql.append("GROUP BY TO_CHAR(TM, 'yyyy') ") + .append("ORDER BY TO_CHAR(TM, 'yyyy') DESC"); + + Map paramMap = new HashMap<>(); + if (StrUtil.isNotBlank(stcd)) { + paramMap.put("stcd", stcd); + } + List yrList = microservicDynamicSQLMapper.getSingleColumnList(sql.toString(), paramMap); + dataSourceResult.setData(yrList); + dataSourceResult.setTotal(yrList == null ? 0L : yrList.size()); + return dataSourceResult; + } + + @Override + public DataSourceResult getWeWtR(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + Map paramMap = new HashMap<>(); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t.DCPC, t.STCD, t1.WT AS wt, t.TM FROM SD_WE_R t ") + .append("INNER JOIN SD_WEWT_R t1 ON t.ID = t1.WER_ID ") + .append("WHERE NVL(t.IS_DELETED, 0) = 0 AND NVL(t1.IS_DELETED, 0) = 0 "); + + String filterSql = buildWeWtFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + String groupBy = KendoUtil.getGroupBy(dataSourceRequest); + if (StrUtil.isNotBlank(groupBy)) { + List groupFields = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + if (item != null && StrUtil.isNotBlank(item.getSelector())) { + groupFields.add(item.getSelector()); + } + } + StringBuilder temp = new StringBuilder(); + temp.append("SELECT ").append(String.join(",", groupFields)).append(", count(*) as "); + if (groupInfos.length > 1) { + temp.append("count"); + } else { + temp.append("count_").append(String.join("_", groupFields)); + } + String groupedSql = temp.append(" FROM ( ").append(sql).append(" ) ").append(groupBy).toString(); + List> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + } + + sql.append(buildWeWtOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, WeWtVo.class); + + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildWeWtFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeWtLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeWtFilterCondition(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 buildWeWtLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeWtColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeFishQgcValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + boolean isDateField = "t.tm".equals(column); + for (Object value : values) { + String paramKey = "weWtParam" + indexHolder[0]++; + paramMap.put(paramKey, value); + if (isDateField) { + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + placeholders.add("TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"); + } else { + placeholders.add("TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"); + } + } else { + placeholders.add("#{map." + paramKey + "}"); + } + } + String prefix = "ni".equals(operator) ? "NOT " : ""; + return column + " " + prefix + "IN (" + String.join(", ", placeholders) + ")"; + } + String paramKey = "weWtParam" + indexHolder[0]++; + paramMap.put(paramKey, filter.getValue()); + boolean isDateField = "t.tm".equals(column); + String valueExpr; + if (isDateField) { + String text = String.valueOf(filter.getValue()).trim(); + if (text.length() <= 10) { + valueExpr = "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } else { + valueExpr = "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + } else { + valueExpr = "#{map." + paramKey + "}"; + } + return switch (operator) { + case "lt", "lessthan" -> column + " < " + valueExpr; + case "lte", "lessthanorequals" -> column + " <= " + valueExpr; + case "gt", "greaterthan" -> column + " > " + valueExpr; + case "gte", "greaterthanorequals" -> column + " >= " + valueExpr; + case "ne", "notequals" -> column + " <> " + valueExpr; + case "contains", "doesnotcontain", "startswith", "endswith" -> { + String pattern = switch (operator) { + case "contains" -> "%#{map." + paramKey + "}%"; + case "doesnotcontain" -> "%#{map." + paramKey + "}%"; + case "startswith" -> "#{map." + paramKey + "}%"; + case "endswith" -> "%#{map." + paramKey + "}"; + default -> "%#{map." + paramKey + "}%"; + }; + String likePrefix = "doesnotcontain".equals(operator) ? "NOT " : ""; + yield column + " " + likePrefix + "LIKE " + pattern; + } + default -> column + " = " + valueExpr; + }; + } + + private String mapWeWtColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field.toLowerCase()) { + case "dcpc" -> "t.dcpc"; + case "stcd" -> "t.stcd"; + case "wt" -> "t1.wt"; + case "tm" -> "t.tm"; + default -> null; + }; + } + + private String buildWeWtOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY t.tm DESC NULLS LAST, t.stcd ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeWtColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return " ORDER BY t.tm DESC NULLS LAST, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + @Override + public DataSourceResult getWeWqR(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + Map paramMap = new HashMap<>(); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t.DCPC, t.STCD, t1.TM, t1.NAME, t1.PH, t1.DOX, t1.CODMN, t1.CODCR, t1.BOD5, t1.NH3N ") + .append(", t1.TP, t1.TN, t1.CU, t1.ZN, t1.F, t1.SE, t1.ARS, t1.HG, t1.CD, t1.CR6, t1.PB, t1.CN, t1.VLPH, t1.OIL ") + .append(", t1.LAS, t1.S2, t1.FCG, t1.CL, t1.SO4, t1.NO3, t1.THRD, t1.COND, t1.FE, t1.MN, t1.AL, t1.CHLA ") + .append(", t1.CLARITY, t1.TU, t1.CYANO, t1.FID, t1.PARAMETER ") + .append("FROM SD_WE_R t ") + .append("INNER JOIN SD_WEWQ_R t1 ON t.ID = t1.WER_ID ") + .append("WHERE NVL(t.IS_DELETED, 0) = 0 AND NVL(t1.IS_DELETED, 0) = 0 "); + + String filterSql = buildWeWqFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + String groupBy = KendoUtil.getGroupBy(dataSourceRequest); + if (StrUtil.isNotBlank(groupBy)) { + List groupFields = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + if (item != null && StrUtil.isNotBlank(item.getSelector())) { + groupFields.add(item.getSelector()); + } + } + StringBuilder temp = new StringBuilder(); + temp.append("SELECT ").append(String.join(",", groupFields)).append(", count(*) as "); + if (groupInfos.length > 1) { + temp.append("count"); + } else { + temp.append("count_").append(String.join("_", groupFields)); + } + String groupedSql = temp.append(" FROM ( ").append(sql).append(" ) ").append(groupBy).toString(); + List> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + } + + sql.append(buildWeWqOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, WeWqVo.class); + + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildWeWqFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + List conditions = new ArrayList<>(); + List filters = filter.getFilters(); + if (CollUtil.isNotEmpty(filters)) { + for (DataSourceRequest.FilterDescriptor child : filters) { + String condition = buildWeWqFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(condition)) { + conditions.add(condition); + } + } + } else { + String leafCondition = buildWeWqLeafCondition(filter, paramMap, indexHolder); + if (StrUtil.isNotBlank(leafCondition)) { + conditions.add(leafCondition); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return "(" + String.join(logic, conditions) + ")"; + } + + private String buildWeWqLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeWqColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeFishQgcValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + boolean isDateField = "t1.tm".equals(column); + for (Object value : values) { + String paramKey = "weWqParam" + indexHolder[0]++; + paramMap.put(paramKey, value); + if (isDateField) { + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + placeholders.add("TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"); + } else { + placeholders.add("TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"); + } + } else { + placeholders.add("#{map." + paramKey + "}"); + } + } + String prefix = "ni".equals(operator) ? "NOT " : ""; + return column + " " + prefix + "IN (" + String.join(", ", placeholders) + ")"; + } + String paramKey = "weWqParam" + indexHolder[0]++; + paramMap.put(paramKey, filter.getValue()); + boolean isDateField = "t1.tm".equals(column); + String valueExpr; + if (isDateField) { + String text = String.valueOf(filter.getValue()).trim(); + if (text.length() <= 10) { + valueExpr = "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } else { + valueExpr = "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + } else { + valueExpr = "#{map." + paramKey + "}"; + } + return switch (operator) { + case "lt", "lessthan" -> column + " < " + valueExpr; + case "lte", "lessthanorequals" -> column + " <= " + valueExpr; + case "gt", "greaterthan" -> column + " > " + valueExpr; + case "gte", "greaterthanorequals" -> column + " >= " + valueExpr; + case "ne", "notequals" -> column + " <> " + valueExpr; + case "contains", "doesnotcontain", "startswith", "endswith" -> { + String pattern = switch (operator) { + case "contains" -> "%#{map." + paramKey + "}%"; + case "doesnotcontain" -> "%#{map." + paramKey + "}%"; + case "startswith" -> "#{map." + paramKey + "}%"; + case "endswith" -> "%#{map." + paramKey + "}"; + default -> "%#{map." + paramKey + "}%"; + }; + String likePrefix = "doesnotcontain".equals(operator) ? "NOT " : ""; + yield column + " " + likePrefix + "LIKE " + pattern; + } + default -> column + " = " + valueExpr; + }; + } + + private String mapWeWqColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field.toLowerCase()) { + case "dcpc" -> "t.dcpc"; + case "stcd" -> "t.stcd"; + case "name" -> "t1.name"; + case "tm" -> "t1.tm"; + case "ph" -> "t1.ph"; + case "dox" -> "t1.dox"; + case "codmn" -> "t1.codmn"; + case "codcr" -> "t1.codcr"; + case "bod5" -> "t1.bod5"; + case "nh3n" -> "t1.nh3n"; + case "tp" -> "t1.tp"; + case "tn" -> "t1.tn"; + case "cu" -> "t1.cu"; + case "zn" -> "t1.zn"; + case "f" -> "t1.f"; + case "se" -> "t1.se"; + case "ars" -> "t1.ars"; + case "hg" -> "t1.hg"; + case "cd" -> "t1.cd"; + case "cr6" -> "t1.cr6"; + case "pb" -> "t1.pb"; + case "cn" -> "t1.cn"; + case "vlph" -> "t1.vlph"; + case "oil" -> "t1.oil"; + case "las" -> "t1.las"; + case "s2" -> "t1.s2"; + case "fcg" -> "t1.fcg"; + case "cl" -> "t1.cl"; + case "so4" -> "t1.so4"; + case "no3" -> "t1.no3"; + case "thrd" -> "t1.thrd"; + case "cond" -> "t1.cond"; + case "fe" -> "t1.fe"; + case "mn" -> "t1.mn"; + case "al" -> "t1.al"; + case "chla" -> "t1.chla"; + case "clarity" -> "t1.clarity"; + case "tu" -> "t1.tu"; + case "cyano" -> "t1.cyano"; + case "fid" -> "t1.fid"; + case "parameter" -> "t1.parameter"; + default -> null; + }; + } + + private String buildWeWqOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY t1.tm DESC NULLS LAST, t.stcd ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeWqColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return " ORDER BY t1.tm DESC NULLS LAST, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + @Override + public DataSourceResult getWeFvR(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t.DCPC, t.STCD, t1.TM, t1.FLOW_RATE AS flowrate, t1.FID ") + .append("FROM SD_WE_R t ") + .append("INNER JOIN SD_WEFV_R t1 ON t.ID = t1.WER_ID ") + .append("WHERE NVL(t.IS_DELETED, 0) = 0 AND NVL(t1.IS_DELETED, 0) = 0 "); + + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapWeFvColumn + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + String groupSql = QgcQueryWrapperUtil.buildGroupSql(dataSourceRequest, sql); + if (StrUtil.isNotBlank(groupSql)) { + List> rows = microservicDynamicSQLMapper.getAllList(groupSql, paramMap); + return QgcQueryWrapperUtil.buildGroupResult(dataSourceRequest, rows); + } + + sql.append(QgcQueryWrapperUtil.buildOrderBySql( + dataSourceRequest == null ? null : dataSourceRequest.getSort(), + this::mapWeFvColumn, + "t1.TM DESC NULLS LAST, t.STCD ASC" + )); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, WeFvVo.class); + + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String mapWeFvColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field.toLowerCase()) { + case "dcpc" -> "t.dcpc"; + case "stcd" -> "t.stcd"; + case "tm" -> "t1.tm"; + case "flowrate" -> "t1.flow_rate"; + case "fid" -> "t1.fid"; + default -> null; + }; + } + private String buildWeFishQgcGroupSql(String baseSql, GroupingInfo[] groupInfos) { if (groupInfos == null || groupInfos.length == 0) { return baseSql; diff --git a/backend/src/main/java/com/yfd/platform/utils/QgcQueryWrapperUtil.java b/backend/src/main/java/com/yfd/platform/utils/QgcQueryWrapperUtil.java index 3554573d..62a60bab 100644 --- a/backend/src/main/java/com/yfd/platform/utils/QgcQueryWrapperUtil.java +++ b/backend/src/main/java/com/yfd/platform/utils/QgcQueryWrapperUtil.java @@ -37,6 +37,11 @@ public class QgcQueryWrapperUtil { return FIELDNULL.contains(columName) ? "00000000-0000-0000-0000-000000000000" : null; } + @FunctionalInterface + public interface ColumnMapper { + String apply(String field); + } + public static String getFilterFieldValue(DataSourceLoadOptionsBase loadOptions, String fieldName) { try { JsonElement jsonElement = (new JsonParser()).parse(JSONUtil.toJsonStr(loadOptions.getFilter())); @@ -702,6 +707,239 @@ public class QgcQueryWrapperUtil { } + + + public static String buildFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder, + ColumnMapper columnMapper) { + if (filter == null) { + return ""; + } + List conditions = new ArrayList<>(); + List filters = filter.getFilters(); + if (CollectionUtil.isNotEmpty(filters)) { + for (DataSourceRequest.FilterDescriptor child : filters) { + String condition = buildFilterCondition(child, paramMap, indexHolder, columnMapper); + if (StrUtil.isNotBlank(condition)) { + conditions.add(condition); + } + } + } else { + String leafCondition = buildLeafCondition(filter, paramMap, indexHolder, columnMapper); + if (StrUtil.isNotBlank(leafCondition)) { + conditions.add(leafCondition); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return "(" + String.join(logic, conditions) + ")"; + } + + private static String buildLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder, + ColumnMapper columnMapper) { + String column = columnMapper.apply(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + boolean isDateField = isDateColumn(column); + for (Object value : values) { + String paramKey = "param" + indexHolder[0]++; + paramMap.put(paramKey, value); + if (isDateField) { + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + placeholders.add("TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"); + } else { + placeholders.add("TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"); + } + } else { + placeholders.add("#{map." + paramKey + "}"); + } + } + String prefix = "ni".equals(operator) ? "NOT " : ""; + return column + " " + prefix + "IN (" + String.join(", ", placeholders) + ")"; + } + String paramKey = "param" + indexHolder[0]++; + paramMap.put(paramKey, filter.getValue()); + boolean isDateField = isDateColumn(column); + String valueExpr; + if (isDateField) { + String text = String.valueOf(filter.getValue()).trim(); + if (text.length() <= 10) { + valueExpr = "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } else { + valueExpr = "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + } else { + valueExpr = "#{map." + paramKey + "}"; + } + return switch (operator) { + case "lt", "lessthan" -> column + " < " + valueExpr; + case "lte", "lessthanorequals" -> column + " <= " + valueExpr; + case "gt", "greaterthan" -> column + " > " + valueExpr; + case "gte", "greaterthanorequals" -> column + " >= " + valueExpr; + case "ne", "notequals" -> column + " <> " + valueExpr; + case "contains", "doesnotcontain", "startswith", "endswith" -> { + String pattern = switch (operator) { + case "contains" -> "%#{map." + paramKey + "}%"; + case "doesnotcontain" -> "%#{map." + paramKey + "}%"; + case "startswith" -> "#{map." + paramKey + "}%"; + case "endswith" -> "%#{map." + paramKey + "}"; + default -> "%#{map." + paramKey + "}%"; + }; + String likePrefix = "doesnotcontain".equals(operator) ? "NOT " : ""; + yield column + " " + likePrefix + "LIKE " + pattern; + } + default -> column + " = " + valueExpr; + }; + } + + private static List normalizeValues(Object value) { + List result = new ArrayList<>(); + if (value == null) { + return result; + } + if (value instanceof List) { + for (Object item : (List) value) { + if (item != null && StrUtil.isNotBlank(item.toString())) { + result.add(item); + } + } + } else if (StrUtil.isNotBlank(value.toString())) { + result.add(value); + } + return result; + } + + private static boolean isDateColumn(String column) { + if (StrUtil.isBlank(column)) { + return false; + } + String lowerColumn = column.toLowerCase(); + return lowerColumn.contains(".tm") || lowerColumn.contains(".time") || lowerColumn.contains(".date"); + } + + public static String buildOrderBySql(List sorts, + ColumnMapper columnMapper, + String defaultOrderBy) { + if (CollectionUtil.isEmpty(sorts)) { + return StrUtil.isNotBlank(defaultOrderBy) ? " ORDER BY " + defaultOrderBy : ""; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = columnMapper.apply(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return StrUtil.isNotBlank(defaultOrderBy) ? " ORDER BY " + defaultOrderBy : ""; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + public static String buildGroupSql(DataSourceRequest dataSourceRequest, StringBuilder sql) { + if (CollectionUtil.isEmpty(dataSourceRequest.getGroup())) { + return null; + } + String groupBy = KendoUtil.getGroupBy(dataSourceRequest); + if (StrUtil.isBlank(groupBy)) { + return null; + } + List groupFields = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor item : dataSourceRequest.getGroup()) { + if (item != null && StrUtil.isNotBlank(item.getField())) { + groupFields.add(item.getField()); + } + } + StringBuilder temp = new StringBuilder(); + temp.append("SELECT ").append(String.join(",", groupFields)).append(", count(*) as "); + if (groupFields.size() > 1) { + temp.append("count"); + } else { + temp.append("count_").append(String.join("_", groupFields)); + } + return temp.append(" FROM ( ").append(sql).append(" ) ").append(groupBy).toString(); + } + + public static DataSourceResult buildGroupResult(DataSourceRequest dataSourceRequest, + List> rows) { + DataSourceResult result = new DataSourceResult<>(); + List groupingInfos = convertToGroupingInfo(dataSourceRequest.getGroup()); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, groupingInfos)); + } else { + result.setData((List) (List) new GroupHelper().group(rows, groupingInfos)); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private static List convertToGroupingInfo(List groupDescriptors) { + List groupingInfos = new ArrayList<>(); + if (CollectionUtil.isEmpty(groupDescriptors)) { + return groupingInfos; + } + for (DataSourceRequest.GroupDescriptor groupDescriptor : groupDescriptors) { + GroupingInfo groupingInfo = new GroupingInfo(); + groupingInfo.setSelector(groupDescriptor.getField()); + String dir = groupDescriptor.getDir(); + String normalizedDir = StrUtil.isBlank(dir) ? "" : dir.toLowerCase(); + if ("des".equals(normalizedDir)) { + normalizedDir = "desc"; + } + if (StrUtil.isBlank(normalizedDir)) { + groupingInfo.setDesc(false); + } else if (normalizedDir.equals("asc")) { + groupingInfo.setDesc(false); + } else if (normalizedDir.equals("desc")) { + groupingInfo.setDesc(true); + } + groupingInfo.setNeedSortFlag(groupDescriptor.getNeedSortFlag()); + List aggregateDescriptors = groupDescriptor.getAggregates(); + if (CollectionUtil.isNotEmpty(aggregateDescriptors)) { + for (DataSourceRequest.AggregateDescriptor aggregateDescriptor : aggregateDescriptors) { + SummaryInfo summaryInfo = new SummaryInfo(); + summaryInfo.setSelector(aggregateDescriptor.getField()); + summaryInfo.setSummaryType(aggregateDescriptor.getAggregate()); + groupingInfo.getSummaryInfos().add(summaryInfo); + } + } + groupingInfos.add(groupingInfo); + } + return groupingInfos; + } + static { FIELDNULL.add("parentId"); }