diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java index f4668f03..30979d90 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java @@ -40,6 +40,12 @@ public class FishPassageController { return ResponseResult.successData(fpRunService.processQgcSdfpssrKendoList(dataSourceRequest)); } + @PostMapping("/fpssTable/qgc/GetKendoListCust") + @Operation(summary = "过鱼设施监测数据查询") + public ResponseResult getQgcFpssTableKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fpRunService.processQgcFpssTableKendoList(dataSourceRequest)); + } + @PostMapping("/build/GetKendoListCust") @Operation(summary = "过鱼设施建设及接入情况统计") public ResponseResult getKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTableVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTableVo.java new file mode 100644 index 00000000..e336bf1b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTableVo.java @@ -0,0 +1,78 @@ +package com.yfd.platform.qgc_env.fp.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "过鱼设施监测数据") +public class FpTableVo { + + @Schema(description = "设施编码") + private String stcd; + + @Schema(description = "设施名称") + private String stnm; + + @Schema(description = "时间") + private String tm; + + @Schema(description = "鱼种类") + private String ftp; + + @Schema(description = "鱼类编码") + private String fishId; + + @Schema(description = "鱼尺寸") + private String fsz; + + @Schema(description = "鱼数量") + private String fcnt; + + @Schema(description = "鱼长度(cm)") + private String length; + + @Schema(description = "鱼宽度(cm)") + private String width; + + @Schema(description = "鱼速度(m/s)") + private String fishspeed; + + @Schema(description = "鱼游向") + private String direction; + + @Schema(description = "鱼游向名称") + private String directionName; + + @Schema(description = "水温(℃)") + private String temperature; + + @Schema(description = "流速(m/s)") + private String speed; + + @Schema(description = "轮廓图") + private String firstimgurl; + + @Schema(description = "短视频") + private String videourl; + + @Schema(description = "年份") + private String yr; + + @Schema(description = "鱼重量") + private String fwet; + + @Schema(description = "文件ID") + private String fid; + + @Schema(description = "上行过鱼数量(尾)") + private Long upFcnt; + + @Schema(description = "下行过鱼数量(尾)") + private Long downFcnt; + + @Schema(description = "数据来源") + private String dataSrc; + + @Schema(description = "监测方式:1=人工 2=自动(预留)") + private Integer mway; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java index 8b247f4d..48c3ce8b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java @@ -3,6 +3,7 @@ package com.yfd.platform.qgc_env.fp.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.qgc_env.fp.entity.vo.FpSdfpssrVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpTableVo; import com.yfd.platform.qgc_env.fp.entity.vo.YearFpStatisticsVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunPlanVo; @@ -14,5 +15,7 @@ public interface FpRunService { DataSourceResult processQgcSdfpssrKendoList(DataSourceRequest dataSourceRequest); + DataSourceResult processQgcFpssTableKendoList(DataSourceRequest dataSourceRequest); + List getYearFpStatic(String year); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index 80f480be..00b1c6e1 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -16,6 +16,7 @@ import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_env.fp.entity.vo.FpFtpStatisticsVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunPlanVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpSdfpssrVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpTableVo; import com.yfd.platform.qgc_env.fp.entity.vo.YearFpStatisticsVo; import com.yfd.platform.qgc_env.fp.service.FpRunService; import com.yfd.platform.utils.QgcQueryWrapperUtil; @@ -114,6 +115,19 @@ public class FpRunServiceImpl implements FpRunService { return queryQgcSdfpssrGroupList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult processQgcFpssTableKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + if (StrUtil.isBlank(stcd)) { + throw new BizException("过鱼设施(stcd)编码不能为空."); + } + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryQgcFpssTableDetailList(dataSourceRequest, loadOptions, stcd); + } + return queryQgcFpssTableGroupList(dataSourceRequest, loadOptions, stcd); + } + @Override public List getYearFpStatic(String year) { Map paramMap = new HashMap<>(); @@ -144,6 +158,468 @@ public class FpRunServiceImpl implements FpRunService { return new ArrayList<>(grouped.values()); } + private DataSourceResult queryQgcFpssTableDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions, + String stcdFilter) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildQgcFpssTableDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildQgcFpssTableCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + appendQgcFpssTableRequiredConditions(sql, paramMap, stcdFilter, loadOptions); + String filterSql = buildQgcFpssTableFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildQgcFpssTableOrderBySql(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, FpTableVo.class); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryQgcFpssTableGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions, + String stcdFilter) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + + StringBuilder sql = new StringBuilder("SELECT "); + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapQgcFpssTableColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapQgcFpssTableColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + String aggregateSql = buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField()); + if (StrUtil.isNotBlank(aggregateSql)) { + selectItems.add(aggregateSql); + } + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.YR AS YR"); + selectItems.add("COUNT(*) AS COUNT_YR"); + } + + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildQgcFpssTableCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + appendQgcFpssTableRequiredConditions(sql, paramMap, stcdFilter, loadOptions); + String filterSql = buildQgcFpssTableFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapQgcFpssTableColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildQgcFpssTableGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + 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(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + private void appendQgcFpssTableRequiredConditions(StringBuilder sql, + Map paramMap, + String stcdFilter, + DataSourceLoadOptionsBase loadOptions) { + List stcdValues = normalizeValues(stcdFilter); + if (stcdValues.isEmpty() && StrUtil.isNotBlank(stcdFilter)) { + stcdValues.add(StrUtil.trim(stcdFilter)); + } + if (!stcdValues.isEmpty()) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < stcdValues.size(); i++) { + String key = "fpssTableStcd" + i; + paramMap.put(key, stcdValues.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append(" AND t.STCD IN (").append(String.join(", ", placeholders)).append(") "); + } + + String tm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + if (StrUtil.isNotBlank(tm) && tm.contains(",")) { + String[] tmArr = tm.split(","); + if (tmArr.length > 1 && StrUtil.isNotBlank(tmArr[0]) && StrUtil.isNotBlank(tmArr[1])) { + paramMap.put("fpssTableTmStart", StrUtil.trim(tmArr[0])); + paramMap.put("fpssTableTmEnd", StrUtil.trim(tmArr[1])); + sql.append(" AND t.STRDT >= TO_DATE(#{map.fpssTableTmStart}, 'YYYY-MM-DD HH24:MI:SS') "); + sql.append(" AND t.ENDDT <= TO_DATE(#{map.fpssTableTmEnd}, 'YYYY-MM-DD HH24:MI:SS') "); + } + } + } + + private String buildQgcFpssTableCoreSql() { + return "SELECT " + + "manualData.STCD AS stcd, " + + "manualData.STNM AS stnm, " + + "manualData.TM AS tm, " + + "manualData.FTP AS ftp, " + + "manualData.FISHID AS fishId, " + + "manualData.FSZ AS fsz, " + + "manualData.YR AS yr, " + + "manualData.FCNT AS fcnt, " + + "manualData.LENGTH AS length, " + + "manualData.WIDTH AS width, " + + "manualData.FISHSPEED AS fishspeed, " + + "manualData.DIRECTION AS direction, " + + "manualData.DIRECTIONNAME AS directionName, " + + "manualData.UPFCNT AS upFcnt, " + + "manualData.DOWNFCNT AS downFcnt, " + + "manualData.TEMPERATURE AS temperature, " + + "manualData.SPEED AS speed, " + + "manualData.FIRSTIMGURL AS firstimgurl, " + + "manualData.VIDEOURL AS videourl, " + + "manualData.FWET AS fwet, " + + "manualData.FID AS fid, " + + "manualData.DATASRC AS dataSrc, " + + "manualData.MWAY AS mway, " + + "manualData.STRDT AS strdt, " + + "manualData.ENDDT AS enddt " + + "FROM ( " + + " SELECT t.STCD AS STCD, " + + " fp.STNM AS STNM, " + + " TO_CHAR(t.STRDT, 'YYYY-MM-DD HH24:MI:SS') AS TM, " + + " COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, fishDirect.NAME, t.FTP) AS FTP, " + + " t.FTP AS FISHID, " + + " t.FSZ AS FSZ, " + + " TO_CHAR(t.STRDT, 'YYYY') AS YR, " + + " TO_CHAR(t.FCNT) AS FCNT, " + + " CAST(NULL AS VARCHAR2(50)) AS LENGTH, " + + " CAST(NULL AS VARCHAR2(50)) AS WIDTH, " + + " CAST(NULL AS VARCHAR2(50)) AS FISHSPEED, " + + " TO_CHAR(t.DIRECTION) AS DIRECTION, " + + " CASE t.DIRECTION WHEN 0 THEN '上行' WHEN 1 THEN '下行' WHEN 2 THEN '上行折返' WHEN 3 THEN '下行折返' END AS DIRECTIONNAME, " + + " CASE WHEN t.DIRECTION = 0 THEN t.FCNT END AS UPFCNT, " + + " CASE WHEN t.DIRECTION = 1 THEN t.FCNT END AS DOWNFCNT, " + + " CAST(NULL AS VARCHAR2(50)) AS TEMPERATURE, " + + " CAST(NULL AS VARCHAR2(50)) AS SPEED, " + + " CAST(NULL AS VARCHAR2(255)) AS FIRSTIMGURL, " + + " CAST(NULL AS VARCHAR2(255)) AS VIDEOURL, " + + " t.FWET AS FWET, " + + " t.FID AS FID, " + + " CASE WHEN t.AI_STCD IS NULL THEN '人工填报' ELSE aiFp.STNM END AS DATASRC, " + + " 1 AS MWAY, " + + " t.STRDT AS STRDT, " + + " t.ENDDT AS ENDDT " + + " FROM SD_FPSS_R t " + + " LEFT JOIN SD_FPSS_B_H fp ON fp.STCD = t.STCD " + + " LEFT JOIN SD_FPSS_B_H aiFp ON aiFp.STCD = t.AI_STCD " + + " LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + " LEFT JOIN SD_FISHDICTORY_RLTN_B relRv ON relRv.FISH_ID = t.FTP AND relRv.RVCD = eng.HBRVCD AND NVL(relRv.IS_DELETED, 0) = 0 " + + " LEFT JOIN SD_FISHDICTORY_B fishRv ON fishRv.ID = relRv.ZY_FISH_ID AND NVL(fishRv.IS_DELETED, 0) = 0 AND NVL(fishRv.ENABLE, 1) = 1 " + + " LEFT JOIN SD_FISHDICTORY_RLTN_B relZy ON relZy.FISH_ID = t.FTP AND relZy.RVCD = 'ZY' AND NVL(relZy.IS_DELETED, 0) = 0 " + + " LEFT JOIN SD_FISHDICTORY_B fishZy ON fishZy.ID = relZy.ZY_FISH_ID AND NVL(fishZy.IS_DELETED, 0) = 0 AND NVL(fishZy.ENABLE, 1) = 1 " + + " LEFT JOIN SD_FISHDICTORY_B fishDirect ON fishDirect.ID = t.FTP AND NVL(fishDirect.IS_DELETED, 0) = 0 AND NVL(fishDirect.ENABLE, 1) = 1 " + + " WHERE (t.TASK_STATUS = 'Approved' OR t.TASK_STATUS IS NULL) " + + " AND NVL(t.IS_DELETED, 0) = 0 " + + " UNION ALL " + + " SELECT CAST(NULL AS VARCHAR2(36)) AS STCD, " + + " CAST(NULL AS VARCHAR2(64)) AS STNM, " + + " CAST(NULL AS VARCHAR2(19)) AS TM, " + + " CAST(NULL AS VARCHAR2(255)) AS FTP, " + + " CAST(NULL AS VARCHAR2(200)) AS FISHID, " + + " CAST(NULL AS VARCHAR2(256)) AS FSZ, " + + " CAST(NULL AS VARCHAR2(4)) AS YR, " + + " CAST(NULL AS VARCHAR2(20)) AS FCNT, " + + " CAST(NULL AS VARCHAR2(50)) AS LENGTH, " + + " CAST(NULL AS VARCHAR2(50)) AS WIDTH, " + + " CAST(NULL AS VARCHAR2(50)) AS FISHSPEED, " + + " CAST(NULL AS VARCHAR2(10)) AS DIRECTION, " + + " CAST(NULL AS VARCHAR2(20)) AS DIRECTIONNAME, " + + " CAST(NULL AS NUMBER(18,0)) AS UPFCNT, " + + " CAST(NULL AS NUMBER(18,0)) AS DOWNFCNT, " + + " CAST(NULL AS VARCHAR2(50)) AS TEMPERATURE, " + + " CAST(NULL AS VARCHAR2(50)) AS SPEED, " + + " CAST(NULL AS VARCHAR2(255)) AS FIRSTIMGURL, " + + " CAST(NULL AS VARCHAR2(255)) AS VIDEOURL, " + + " CAST(NULL AS VARCHAR2(50)) AS FWET, " + + " CAST(NULL AS VARCHAR2(1000)) AS FID, " + + " CAST(NULL AS VARCHAR2(64)) AS DATASRC, " + + " 2 AS MWAY, " + + " CAST(NULL AS TIMESTAMP) AS STRDT, " + + " CAST(NULL AS TIMESTAMP) AS ENDDT " + + " FROM DUAL WHERE 1 = 0 " + + ") manualData"; + } + + private String buildQgcFpssTableDetailSelectSql(List selectFields) { + Map selectMap = new LinkedHashMap<>(); + selectMap.put("stcd", "t.stcd AS stcd"); + selectMap.put("stnm", "t.stnm AS stnm"); + selectMap.put("tm", "t.tm AS tm"); + selectMap.put("ftp", "t.ftp AS ftp"); + selectMap.put("fishId", "t.fishId AS fishId"); + selectMap.put("fsz", "t.fsz AS fsz"); + selectMap.put("yr", "t.yr AS yr"); + selectMap.put("fcnt", "t.fcnt AS fcnt"); + selectMap.put("length", "t.length AS length"); + selectMap.put("width", "t.width AS width"); + selectMap.put("fishspeed", "t.fishspeed AS fishspeed"); + selectMap.put("direction", "t.direction AS direction"); + selectMap.put("directionName", "t.directionName AS directionName"); + selectMap.put("temperature", "t.temperature AS temperature"); + selectMap.put("speed", "t.speed AS speed"); + selectMap.put("firstimgurl", "t.firstimgurl AS firstimgurl"); + selectMap.put("videourl", "t.videourl AS videourl"); + selectMap.put("fwet", "t.fwet AS fwet"); + selectMap.put("fid", "t.fid AS fid"); + selectMap.put("upFcnt", "t.upFcnt AS upFcnt"); + selectMap.put("downFcnt", "t.downFcnt AS downFcnt"); + selectMap.put("dataSrc", "t.dataSrc AS dataSrc"); + selectMap.put("mway", "t.mway AS mway"); + selectMap.put("strdt", "t.strdt AS strdt"); + selectMap.put("enddt", "t.enddt AS enddt"); + + if (CollUtil.isEmpty(selectFields)) { + return String.join(", ", selectMap.values()); + } + List actualColumns = new ArrayList<>(); + for (String field : selectFields) { + String column = selectMap.get(field); + if (StrUtil.isNotBlank(column)) { + actualColumns.add(column); + } + } + if (actualColumns.isEmpty()) { + actualColumns.addAll(selectMap.values()); + } + return String.join(", ", actualColumns); + } + + private String buildQgcFpssTableFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildQgcFpssTableLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildQgcFpssTableFilterCondition(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 buildQgcFpssTableLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + if ("stcd".equalsIgnoreCase(field) || "tm".equalsIgnoreCase(field)) { + return ""; + } + + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("keyword".equalsIgnoreCase(field)) { + if (value == null || StrUtil.isBlank(String.valueOf(value))) { + return ""; + } + String key = "fpTableP" + indexHolder[0]++; + paramMap.put(key, "%" + String.valueOf(value).trim() + "%"); + return "(t.STNM LIKE #{map." + key + "} OR t.FTP LIKE #{map." + key + "} OR t.DATASRC LIKE #{map." + key + "})"; + } + + String column = mapQgcFpssTableColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + + boolean dateField = "strdt".equalsIgnoreCase(field) || "enddt".equalsIgnoreCase(field); + if ("in".equals(operator)) { + List values = normalizeValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "fpTableP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add(buildValueExpr(key, dateField, item)); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + + String key = "fpTableP" + indexHolder[0]++; + String valueExpr = buildValueExpr(key, dateField, value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, value); + yield column + " = " + valueExpr; + } + case "neq" -> { + paramMap.put(key, value); + yield column + " <> " + valueExpr; + } + case "contains" -> { + paramMap.put(key, "%" + value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + value); + yield column + " LIKE #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, value); + yield column + " > " + valueExpr; + } + case "gte" -> { + paramMap.put(key, value); + yield column + " >= " + valueExpr; + } + case "lt" -> { + paramMap.put(key, value); + yield column + " < " + valueExpr; + } + case "lte" -> { + paramMap.put(key, value); + yield column + " <= " + valueExpr; + } + default -> ""; + }; + } + + private String mapQgcFpssTableColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "t.STCD"; + case "stnm" -> "t.STNM"; + case "tm" -> "t.STRDT"; + case "ftp" -> "t.FTP"; + case "fishId" -> "t.FISHID"; + case "fsz" -> "t.FSZ"; + case "yr" -> "t.YR"; + case "fcnt" -> "t.FCNT"; + case "length" -> "t.LENGTH"; + case "width" -> "t.WIDTH"; + case "fishspeed" -> "t.FISHSPEED"; + case "direction" -> "t.DIRECTION"; + case "directionName" -> "t.DIRECTIONNAME"; + case "temperature" -> "t.TEMPERATURE"; + case "speed" -> "t.SPEED"; + case "firstimgurl" -> "t.FIRSTIMGURL"; + case "videourl" -> "t.VIDEOURL"; + case "fwet" -> "t.FWET"; + case "fid" -> "t.FID"; + case "upFcnt" -> "t.UPFCNT"; + case "downFcnt" -> "t.DOWNFCNT"; + case "dataSrc" -> "t.DATASRC"; + case "mway" -> "t.MWAY"; + case "strdt" -> "t.STRDT"; + case "enddt" -> "t.ENDDT"; + default -> null; + }; + } + + private String buildQgcFpssTableOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.STRDT DESC NULLS LAST"; + } + List orderColumns = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + if (sortDescriptor == null || StrUtil.isBlank(sortDescriptor.getField())) { + continue; + } + String column = mapQgcFpssTableColumn(sortDescriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) || "des".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + orderColumns.add(column + " " + dir + " NULLS LAST"); + } + if (orderColumns.isEmpty()) { + return " ORDER BY t.STRDT DESC NULLS LAST"; + } + return " ORDER BY " + String.join(", ", orderColumns); + } + + private String buildQgcFpssTableGroupOrderBySql(List groups) { + if (CollUtil.isEmpty(groups)) { + return ""; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapQgcFpssTableColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(descriptor.getDir()) || "des".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders); + } + private DataSourceResult queryQgcSdfpssrDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder();