From fd0e11d1e4585a6c64f186fc01bcd9b67cd0955e Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 11 Jun 2026 18:00:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8A=A8=E7=89=A9=E6=95=91=E5=8A=A9?= =?UTF-8?q?=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VapConstructionController.java | 6 + .../qgc_env/vap/entity/vo/VpVarVo.java | 64 ++++ .../vap/service/VpConstructionService.java | 3 + .../impl/VpConstructionServiceImpl.java | 351 ++++++++++++++++++ 4 files changed, 424 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpVarVo.java 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 ef4924a8..ffa9a01e 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 @@ -58,4 +58,10 @@ public class VapConstructionController { public ResponseResult getVacKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(vpConstructionService.processVacKendoList(dataSourceRequest)); } + + @PostMapping("/var/GetKendoListCust") + @Operation(summary = "动物救助情况") + public ResponseResult getVarKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vpConstructionService.processVarKendoList(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpVarVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpVarVo.java new file mode 100644 index 00000000..80eeb789 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpVarVo.java @@ -0,0 +1,64 @@ +package com.yfd.platform.qgc_env.vap.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "动物救助情况") +public class VpVarVo { + + @Schema(description = "主键") + private String id; + + @Schema(description = "测站编码") + private String stcd; + + @Schema(description = "所属基地ID") + private String baseId; + + @Schema(description = "测站名称") + private String stnm; + + @JsonFormat(pattern = "yyyy-MM-dd") + @Schema(description = "放生日期") + private Date tm; + + @Schema(description = "陆生生态类型") + private String tetp; + + @Schema(description = "救助数量") + private Integer tecnt; + + @Schema(description = "放生地点") + private String stlc; + + @Schema(description = "放生照片") + private String fpth; + + @Schema(description = "文件ID") + private String fid; + + @Schema(description = "平台ID") + private String platformId; + + @Schema(description = "部门ID") + private String departmentId; + + @Schema(description = "是否暂存") + private Integer isTempStorage; + + @Schema(description = "年度") + private String year; + + @Schema(description = "描述") + private String description; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "站点排序") + private Integer siteStepSort; +} 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 0cddcfec..28de636f 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 @@ -3,6 +3,7 @@ package com.yfd.platform.qgc_env.vap.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinIntDetailVo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpVarVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpStInfoResultVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpVacVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpWvaRunVo; @@ -20,4 +21,6 @@ public interface VpConstructionService { DataSourceResult processWvaKendoList(DataSourceRequest dataSourceRequest); DataSourceResult processVacKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult processVarKendoList(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 0328ba0e..e7323320 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 @@ -11,6 +11,7 @@ import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.common.PageInfo; import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinIntDetailVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpConstructionSituationVo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpVarVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpVacVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpStBaseInfoVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpStInfoResultVo; @@ -256,6 +257,275 @@ public class VpConstructionServiceImpl implements VpConstructionService { return result; } + @Override + public DataSourceResult processVarKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + PageInfo pageInfo = loadOptions == null ? new PageInfo() : QgcQueryWrapperUtil.getPageInfo(loadOptions); + Page page = pageInfo.getHasPageInfo() ? pageInfo.getPage() : null; + + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(buildVarBaseSql()); + String filterSql = buildVarFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql); + } + + String groupBy = dataSourceRequest == null ? null : KendoUtil.getGroupBy(dataSourceRequest); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + if (StrUtil.isNotBlank(groupBy) && groupInfos != null && groupInfos.length > 0) { + String groupedSql = buildVarGroupSql(sql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.pageAllList(null, groupedSql, paramMap); + DataSourceResult result = new DataSourceResult(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData(new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData(new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + sql.append(buildVarOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, VpVarVo.class + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildVarBaseSql() { + return "SELECT " + + "r.ID AS id, " + + "va.STCD AS stcd, " + + "va.BASE_ID AS baseId, " + + "va.STNM AS stnm, " + + "r.TM AS tm, " + + "basic.NAME AS tetp, " + + "r.TECNT AS tecnt, " + + "r.STLC AS stlc, " + + "r.FPTH AS fpth, " + + "r.FID AS fid, " + + "CAST(NULL AS VARCHAR2(36)) AS platformId, " + + "CAST(NULL AS VARCHAR2(36)) AS departmentId, " + + "CAST(NULL AS NUMBER(1,0)) AS isTempStorage, " + + "TO_CHAR(r.TM, 'YYYY') AS year, " + + "r.DESCRIPTION AS description, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(va.ORDER_INDEX, 999999) AS siteStepSort " + + "FROM SD_VA_B_H va " + + "LEFT JOIN SD_VA_R r ON r.STCD = va.STCD AND NVL(r.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_VABASIC_B basic ON basic.ID = r.TETP AND NVL(basic.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = va.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "WHERE va.STTP = 'VA' AND NVL(va.IS_DELETED, 0) = 0 "; + } + + private String buildVarFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildVarLeafCondition(filter, paramMap, indexHolder); + } + if (CollectionUtils.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildVarFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + return String.join("or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND ", conditions); + } + + private String buildVarLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + Object value = filter.getValue(); + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + + if ("keyword".equals(field)) { + if (value == null || StrUtil.isBlank(String.valueOf(value))) { + return ""; + } + String paramKey = "varParam" + indexHolder[0]++; + paramMap.put(paramKey, "%" + value + "%"); + return "(va.STNM LIKE #{map." + paramKey + "} OR basic.NAME LIKE #{map." + paramKey + "} " + + "OR r.STLC LIKE #{map." + paramKey + "} OR r.DESCRIPTION LIKE #{map." + paramKey + "})"; + } + + String column = mapVarColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + if (isDateField(field)) { + return buildDateCondition(column, operator, value, paramMap, indexHolder, "varParam"); + } + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator)) { + List values = normalizeValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String paramKey = "varParam" + indexHolder[0]++; + paramMap.put(paramKey, item); + placeholders.add("#{map." + paramKey + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + + String paramKey = "varParam" + indexHolder[0]++; + switch (operator) { + case "eq": + paramMap.put(paramKey, value); + return column + " = #{map." + paramKey + "}"; + case "neq": + paramMap.put(paramKey, value); + return column + " <> #{map." + paramKey + "}"; + case "contains": + paramMap.put(paramKey, "%" + value + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "startswith": + paramMap.put(paramKey, value + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "endswith": + paramMap.put(paramKey, "%" + value); + return column + " LIKE #{map." + paramKey + "}"; + case "gt": + paramMap.put(paramKey, value); + return column + " > #{map." + paramKey + "}"; + case "gte": + paramMap.put(paramKey, value); + return column + " >= #{map." + paramKey + "}"; + case "lt": + paramMap.put(paramKey, value); + return column + " < #{map." + paramKey + "}"; + case "lte": + paramMap.put(paramKey, value); + return column + " <= #{map." + paramKey + "}"; + default: + return ""; + } + } + + private String buildVarGroupSql(String detailSql, GroupingInfo[] groupInfos) { + List groupFields = new ArrayList<>(); + List orderItems = new ArrayList<>(); + StringBuilder sql = new StringBuilder("SELECT "); + boolean first = true; + for (GroupingInfo item : groupInfos) { + if (item == null || StrUtil.isBlank(item.getSelector())) { + continue; + } + String selector = item.getSelector(); + if (!isVarGroupSupported(selector)) { + continue; + } + if (!first) { + sql.append(", "); + } + sql.append("t.").append(selector).append(" AS ").append(selector) + .append(", COUNT(*) AS count_").append(selector); + groupFields.add("t." + selector); + orderItems.add("t." + selector + (item.getDesc() ? " DESC" : " ASC")); + first = false; + } + if (groupFields.isEmpty()) { + return "SELECT * FROM (" + detailSql + ") t WHERE 1 = 0"; + } + sql.append(" FROM (").append(detailSql).append(") t GROUP BY ") + .append(String.join(", ", groupFields)); + if (!orderItems.isEmpty()) { + sql.append(" ORDER BY ").append(String.join(", ", orderItems)); + } + return sql.toString(); + } + + private boolean isVarGroupSupported(String selector) { + return "stcd".equals(selector) + || "baseId".equals(selector) + || "stnm".equals(selector) + || "tm".equals(selector) + || "tetp".equals(selector) + || "tecnt".equals(selector) + || "stlc".equals(selector) + || "fpth".equals(selector) + || "fid".equals(selector) + || "year".equals(selector) + || "description".equals(selector); + } + + private String mapVarColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + Map columnMap = new HashMap<>(); + columnMap.put("id", "r.ID"); + columnMap.put("stcd", "va.STCD"); + columnMap.put("baseId", "va.BASE_ID"); + columnMap.put("stnm", "va.STNM"); + columnMap.put("tm", "r.TM"); + columnMap.put("tetp", "basic.NAME"); + columnMap.put("tecnt", "r.TECNT"); + columnMap.put("stlc", "r.STLC"); + columnMap.put("fpth", "r.FPTH"); + columnMap.put("fid", "r.FID"); + columnMap.put("year", "TO_CHAR(r.TM, 'YYYY')"); + columnMap.put("description", "r.DESCRIPTION"); + return columnMap.get(field); + } + + private String buildVarOrderBySql(List sorts) { + if (sorts == null || sorts.isEmpty()) { + return " ORDER BY NVL(hb.ORDER_INDEX, 999999) ASC, NVL(va.ORDER_INDEX, 999999) ASC, r.TM DESC NULLS LAST, va.STCD ASC"; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapVarColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + column = switch (sort.getField()) { + case "baseStepSort" -> "hb.ORDER_INDEX"; + case "siteStepSort" -> "va.ORDER_INDEX"; + default -> null; + }; + } + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + direction + " NULLS LAST"); + } + if (orderItems.isEmpty()) { + return " ORDER BY NVL(hb.ORDER_INDEX, 999999) ASC, NVL(va.ORDER_INDEX, 999999) ASC, r.TM DESC NULLS LAST, va.STCD ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + private String buildVacBaseSql(boolean isZoo) { String baseIdExpr = isZoo ? "CASE WHEN va.BASE_ID IS NULL THEN 'null' ELSE va.BASE_ID END" : "va.BASE_ID"; String dtinExpr = isZoo ? "CASE WHEN va.DTIN IS NULL THEN '400' ELSE TO_CHAR(va.DTIN) END" : "TO_CHAR(va.DTIN)"; @@ -334,6 +604,9 @@ public class VpConstructionServiceImpl implements VpConstructionService { if (StrUtil.isBlank(column)) { return ""; } + if (isDateField(field)) { + return buildDateCondition(column, operator, value, paramMap, indexHolder, "vacParam"); + } if ("isnull".equals(operator)) { return column + " IS NULL"; } @@ -583,6 +856,9 @@ public class VpConstructionServiceImpl implements VpConstructionService { if (StrUtil.isBlank(column)) { return ""; } + if (isDateField(field)) { + return buildDateCondition(column, operator, value, paramMap, indexHolder, "wvaParam"); + } if ("isnull".equals(operator)) { return column + " IS NULL"; } @@ -855,6 +1131,9 @@ public class VpConstructionServiceImpl implements VpConstructionService { if (StrUtil.isBlank(column)) { return ""; } + if (isDateField(field)) { + return buildDateCondition(column, operator, value, paramMap, indexHolder, "vpParam"); + } if ("isnull".equals(operator)) { return column + " IS NULL"; } @@ -1040,6 +1319,75 @@ public class VpConstructionServiceImpl implements VpConstructionService { return values; } + private boolean isDateField(String field) { + return "tm".equals(field) + || "ststdt".equals(field) + || "esstdt".equals(field) + || "jcdt".equals(field) + || "stdsdt".equals(field) + || "pststdt".equals(field) + || "pesstdt".equals(field) + || "swdt".equals(field) + || "wddt".equals(field) + || "dtinTm".equals(field); + } + + private String buildDateCondition(String column, + String operator, + Object value, + Map paramMap, + int[] indexHolder, + String paramPrefix) { + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if (value == null || StrUtil.isBlank(String.valueOf(value))) { + return ""; + } + String dateValue = normalizeDateValue(String.valueOf(value)); + if (StrUtil.isBlank(dateValue)) { + return ""; + } + String paramKey = paramPrefix + indexHolder[0]++; + paramMap.put(paramKey, dateValue); + String dateExpr = "TO_DATE(#{map." + paramKey + "}, '" + resolveOracleDateFormat(dateValue) + "')"; + return switch (operator) { + case "eq" -> column + " = " + dateExpr; + case "neq" -> column + " <> " + dateExpr; + case "gt" -> column + " > " + dateExpr; + case "gte" -> column + " >= " + dateExpr; + case "lt" -> column + " < " + dateExpr; + case "lte" -> column + " <= " + dateExpr; + default -> ""; + }; + } + + private String normalizeDateValue(String value) { + if (StrUtil.isBlank(value)) { + return value; + } + String normalized = StrUtil.trim(value); + if (normalized.contains("T")) { + normalized = normalized.replace("T", " "); + } + if (normalized.endsWith("Z")) { + normalized = normalized.substring(0, normalized.length() - 1); + } + int dotIndex = normalized.indexOf('.'); + if (dotIndex > 0) { + normalized = normalized.substring(0, dotIndex); + } + return normalized; + } + + private String resolveOracleDateFormat(String value) { + String normalized = StrUtil.blankToDefault(value, ""); + return normalized.length() > 10 ? "YYYY-MM-DD HH24:MI:SS" : "YYYY-MM-DD"; + } + private String buildVmsstbprptBaseSql() { return "SELECT " + "vp.STCD AS id, " + @@ -1273,6 +1621,9 @@ public class VpConstructionServiceImpl implements VpConstructionService { } String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); Object value = filter.getValue(); + if (isDateField(filter.getField())) { + return buildDateCondition(column, operator, value, paramMap, indexHolder, "vpMsParam"); + } if ("isnull".equals(operator)) { return column + " IS NULL"; }