diff --git a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java index 3cc06390..8c8c0bc2 100644 --- a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java @@ -119,6 +119,15 @@ public class SwaggerConfig { .build(); } + @Bean + public GroupedOpenApi groupEnvFprApi() { + return GroupedOpenApi.builder() + .group("3.5 全过程-生态环保数据服务-鱼类调查") + .packagesToScan("com.yfd.platform.qgc_env.fpr.controller") + .build(); + } + + diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/controller/FprMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/controller/FprMonitorController.java new file mode 100644 index 00000000..8a3b1c22 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/controller/FprMonitorController.java @@ -0,0 +1,29 @@ +package com.yfd.platform.qgc_env.fpr.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_env.fpr.service.FprMonitorService; +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; + +@RestController +@RequestMapping("/fpr") +@Tag(name = "鱼类调查装置站基础信息") +@Validated +public class FprMonitorController { + + @Resource + private FprMonitorService fprMonitorService; + + @PostMapping("/msstbprpt/GetKendoList") + @Operation(summary = "鱼类调查装置站基础列表") + public ResponseResult getMsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fprMonitorService.getMsstbprptList(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprMsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprMsstbprptVo.java new file mode 100644 index 00000000..3482b334 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprMsstbprptVo.java @@ -0,0 +1,170 @@ +package com.yfd.platform.qgc_env.fpr.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "鱼类调查装置站基础信息") +public class FprMsstbprptVo { + + @Schema(description = "主键ID") + private String id; + + @Schema(description = "是否删除") + private Integer isDeleted; + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "站点名称") + private String stnm; + + @Schema(description = "站类") + private String sttp; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "站类名称") + private String sttpName; + + @Schema(description = "站类全路径") + private String sttpFullPath; + + @Schema(description = "站类层级") + private Integer sttpTreeLevel; + + @Schema(description = "数据时间") + private Date tm; + + @Schema(description = "经度") + private Double lgtd; + + @Schema(description = "纬度") + private Double lttd; + + @Schema(description = "高程") + private Double elev; + + @Schema(description = "站址") + private String stlc; + + @Schema(description = "建成日期") + private Date jcdt; + + @Schema(description = "退役日期") + private Date wddt; + + @Schema(description = "简介") + private String introduce; + + @Schema(description = "LOGO") + private String logo; + + @Schema(description = "介绍弹窗图片") + private String inffile; + + @Schema(description = "是否启用") + private Integer usfl; + + @Schema(description = "是否接入") + private Integer dtin; + + @Schema(description = "是否接入名称") + private String dtinName; + + @Schema(description = "接入开始时间") + private Date dtinTm; + + @Schema(description = "监测方式") + private Integer mway; + + @Schema(description = "监测方式名称") + private String mwayName; + + @Schema(description = "监测指标") + private String stindx; + + @Schema(description = "排序") + private Integer orderIndex; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String ennm; + + @Schema(description = "所属基地编码") + private String baseId; + + @Schema(description = "所属基地名称") + private String baseName; + + @Schema(description = "所属基地流域编码") + private String hbrvcd; + + @Schema(description = "所属基地流域名称") + private String hbrvcdName; + + @Schema(description = "所属流域编码") + private String rvcd; + + @Schema(description = "所属流域名称") + private String rvcdName; + + @Schema(description = "用途") + private String purpose; + + @Schema(description = "观察方式") + private String observe; + + @Schema(description = "监测频次") + private Integer dtfrqcy; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "数据来源") + private String vlsr; + + @Schema(description = "数据来源时间") + private Date vlsrTm; + + @Schema(description = "建设状态") + private String bldstt; + + @Schema(description = "建设状态名称") + private String bldsttName; + + @Schema(description = "建设状态分类编码") + private String bldsttCcode; + + @Schema(description = "建设状态分类名称") + private String bldsttCcodeName; + + @Schema(description = "创建人") + private String recordUser; + + @Schema(description = "创建时间") + private Date recordTime; + + @Schema(description = "更新人") + private String modifyUser; + + @Schema(description = "更新时间") + private Date modifyTime; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "流域排序") + private Integer rvcdStepSort; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; + + @Schema(description = "站点排序") + private Integer siteStepSort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/FprMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/FprMonitorService.java new file mode 100644 index 00000000..3f387236 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/FprMonitorService.java @@ -0,0 +1,10 @@ +package com.yfd.platform.qgc_env.fpr.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_env.fpr.entity.vo.FprMsstbprptVo; + +public interface FprMonitorService { + + DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java new file mode 100644 index 00000000..9afabdf1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java @@ -0,0 +1,554 @@ +package com.yfd.platform.qgc_env.fpr.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.DataSourceLoadOptionsBase; +import com.yfd.platform.common.DataSourceRequest; +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.fpr.entity.vo.FprMsstbprptVo; +import com.yfd.platform.qgc_env.fpr.service.FprMonitorService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Service +public class FprMonitorServiceImpl implements FprMonitorService { + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Override + public DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + String filterSql = buildMsstbprptFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + StringBuilder groupedBaseSql = new StringBuilder("SELECT * FROM (") + .append(buildMsstbprptBaseSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + groupedBaseSql.append(" AND ").append(filterSql).append(" "); + } + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + String groupedSql = buildMsstbprptGroupSql(groupedBaseSql.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((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildMsstbprptDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildMsstbprptBaseSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildMsstbprptDetailOrderBySql(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, FprMsstbprptVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildMsstbprptBaseSql() { + return "SELECT " + + "CAST(NULL AS VARCHAR2(36)) AS id, " + + "NVL(src.IS_DELETED, 0) AS isDeleted, " + + "src.STCD AS stcd, " + + "src.STNM AS stnm, " + + "src.STTP AS sttp, " + + "src.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + + "src.TM AS tm, " + + "src.LGTD AS lgtd, " + + "src.LTTD AS lttd, " + + "src.ELEV AS elev, " + + "src.STLC AS stlc, " + + "src.JCDT AS jcdt, " + + "src.WDDT AS wddt, " + + "src.INTRODUCE AS introduce, " + + "src.LOGO AS logo, " + + "src.INFFILE AS inffile, " + + "src.USFL AS usfl, " + + "src.DTIN AS dtin, " + + "CASE WHEN NVL(src.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END AS dtinName, " + + "src.DTIN_TM AS dtinTm, " + + "src.MWAY AS mway, " + + "CASE WHEN NVL(src.MWAY, 0) = 1 THEN '人工' WHEN NVL(src.MWAY, 0) = 2 THEN '自动' ELSE NULL END AS mwayName, " + + "src.STINDX AS stindx, " + + "src.ORDER_INDEX AS orderIndex, " + + "src.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "src.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "src.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "src.RVCD AS rvcd, " + + "rv.RVNM AS rvcdName, " + + "src.PURPOSE AS purpose, " + + "src.OBSERVE AS observe, " + + "src.DTFRQCY AS dtfrqcy, " + + "src.REMARK AS remark, " + + "src.VLSR AS vlsr, " + + "src.VLSR_TM AS vlsrTm, " + + "TO_CHAR(src.BLDSTT_CODE) AS bldstt, " + + "CASE WHEN NVL(src.BLDSTT_CODE, 0) = 2 THEN '已建' WHEN NVL(src.BLDSTT_CODE, 0) = 1 THEN '在建' ELSE '未建/规划' END AS bldsttName, " + + "TO_CHAR(src.BLDSTT_CODE) AS bldsttCcode, " + + "CASE WHEN NVL(src.BLDSTT_CODE, 0) = 2 THEN '已建' WHEN NVL(src.BLDSTT_CODE, 0) = 1 THEN '在建' ELSE '未建/规划' END AS bldsttCcodeName, " + + "src.RECORD_USER AS recordUser, " + + "src.RECORD_TIME AS recordTime, " + + "src.MODIFY_USER AS modifyUser, " + + "src.MODIFY_TIME AS modifyTime, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(alongBase.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(engSort.SORT, 999999) AS rstcdStepSort, " + + "NVL(siteSort.SORT, NVL(src.ORDER_INDEX, 999999)) AS siteStepSort " + + "FROM SD_FPRD_B_H src " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = src.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = src.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = src.HBRVCD " + + " AND hbrv.BASEID = src.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 " + + " AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = src.RVCD " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = src.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 " + + " AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN MS_ALONG_B alongBase ON alongBase.RVCD = src.HBRVCD " + + " AND alongBase.CODE = 'common' " + + " AND NVL(alongBase.IS_DELETED, 0) = 0 " + + "LEFT JOIN ( " + + " SELECT det.STCD, det.SORT, along.RVCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B along ON det.ALONG_ID = along.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 " + + " AND NVL(along.IS_DELETED, 0) = 0 " + + " AND along.CODE = 'common' " + + ") engSort ON engSort.RVCD = src.HBRVCD AND engSort.STCD = src.RSTCD " + + "LEFT JOIN ( " + + " SELECT det.STCD, det.SORT, along.RVCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B along ON det.ALONG_ID = along.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 " + + " AND NVL(along.IS_DELETED, 0) = 0 " + + " AND along.CODE = 'common' " + + ") siteSort ON siteSort.RVCD = src.HBRVCD AND siteSort.STCD = src.STCD " + + "WHERE NVL(src.IS_DELETED, 0) = 0 "; + } + + private String buildMsstbprptDetailSelectSql(List selectFields) { + LinkedHashMap columnMap = buildMsstbprptSelectColumnMap(); + if (CollUtil.isEmpty(selectFields)) { + return String.join(", ", columnMap.values()); + } + List selectColumns = new ArrayList<>(); + for (String field : selectFields) { + String column = columnMap.get(field); + if (StrUtil.isNotBlank(column)) { + selectColumns.add(column); + } + } + return selectColumns.isEmpty() ? String.join(", ", columnMap.values()) : String.join(", ", selectColumns); + } + + private LinkedHashMap buildMsstbprptSelectColumnMap() { + LinkedHashMap columnMap = new LinkedHashMap<>(); + columnMap.put("id", "t.id AS id"); + columnMap.put("isDeleted", "t.isDeleted AS isDeleted"); + columnMap.put("stcd", "t.stcd AS stcd"); + columnMap.put("stnm", "t.stnm AS stnm"); + columnMap.put("sttp", "t.sttp AS sttp"); + columnMap.put("sttpCode", "t.sttpCode AS sttpCode"); + columnMap.put("sttpName", "t.sttpName AS sttpName"); + columnMap.put("sttpFullPath", "t.sttpFullPath AS sttpFullPath"); + columnMap.put("sttpTreeLevel", "t.sttpTreeLevel AS sttpTreeLevel"); + columnMap.put("tm", "t.tm AS tm"); + columnMap.put("lgtd", "t.lgtd AS lgtd"); + columnMap.put("lttd", "t.lttd AS lttd"); + columnMap.put("elev", "t.elev AS elev"); + columnMap.put("stlc", "t.stlc AS stlc"); + columnMap.put("jcdt", "t.jcdt AS jcdt"); + columnMap.put("wddt", "t.wddt AS wddt"); + columnMap.put("introduce", "t.introduce AS introduce"); + columnMap.put("logo", "t.logo AS logo"); + columnMap.put("inffile", "t.inffile AS inffile"); + columnMap.put("usfl", "t.usfl AS usfl"); + columnMap.put("dtin", "t.dtin AS dtin"); + columnMap.put("dtinName", "t.dtinName AS dtinName"); + columnMap.put("dtinTm", "t.dtinTm AS dtinTm"); + columnMap.put("mway", "t.mway AS mway"); + columnMap.put("mwayName", "t.mwayName AS mwayName"); + columnMap.put("stindx", "t.stindx AS stindx"); + columnMap.put("orderIndex", "t.orderIndex AS orderIndex"); + columnMap.put("rstcd", "t.rstcd AS rstcd"); + columnMap.put("ennm", "t.ennm AS ennm"); + columnMap.put("baseId", "t.baseId AS baseId"); + columnMap.put("baseName", "t.baseName AS baseName"); + columnMap.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + columnMap.put("hbrvcdName", "t.hbrvcdName AS hbrvcdName"); + columnMap.put("rvcd", "t.rvcd AS rvcd"); + columnMap.put("rvcdName", "t.rvcdName AS rvcdName"); + columnMap.put("purpose", "t.purpose AS purpose"); + columnMap.put("observe", "t.observe AS observe"); + columnMap.put("dtfrqcy", "t.dtfrqcy AS dtfrqcy"); + columnMap.put("remark", "t.remark AS remark"); + columnMap.put("vlsr", "t.vlsr AS vlsr"); + columnMap.put("vlsrTm", "t.vlsrTm AS vlsrTm"); + columnMap.put("bldstt", "t.bldstt AS bldstt"); + columnMap.put("bldsttName", "t.bldsttName AS bldsttName"); + columnMap.put("bldsttCcode", "t.bldsttCcode AS bldsttCcode"); + columnMap.put("bldsttCcodeName", "t.bldsttCcodeName AS bldsttCcodeName"); + columnMap.put("recordUser", "t.recordUser AS recordUser"); + columnMap.put("recordTime", "t.recordTime AS recordTime"); + columnMap.put("modifyUser", "t.modifyUser AS modifyUser"); + columnMap.put("modifyTime", "t.modifyTime AS modifyTime"); + columnMap.put("baseStepSort", "t.baseStepSort AS baseStepSort"); + columnMap.put("rvcdStepSort", "t.rvcdStepSort AS rvcdStepSort"); + columnMap.put("rstcdStepSort", "t.rstcdStepSort AS rstcdStepSort"); + columnMap.put("siteStepSort", "t.siteStepSort AS siteStepSort"); + return columnMap; + } + + private String buildMsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildMsstbprptLeafCondition(filter, paramMap, indexHolder); + } + if (filter.getFilters() == null || filter.getFilters().isEmpty()) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildMsstbprptFilterCondition(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 buildMsstbprptLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + + if ("keyword".equals(field)) { + if (value == null || StrUtil.isBlank(String.valueOf(value))) { + return ""; + } + String paramKey = "fprP" + indexHolder[0]++; + paramMap.put(paramKey, "%" + value + "%"); + return "(t.stcd LIKE #{map." + paramKey + "} " + + "OR t.stnm LIKE #{map." + paramKey + "} " + + "OR t.baseName LIKE #{map." + paramKey + "} " + + "OR t.ennm LIKE #{map." + paramKey + "} " + + "OR t.introduce LIKE #{map." + paramKey + "})"; + } + + String column = mapMsstbprptColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + if (isDateField(field)) { + return buildDateCondition(column, operator, value, paramMap, indexHolder, "fprP"); + } + 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 = "fprP" + indexHolder[0]++; + paramMap.put(paramKey, item); + placeholders.add("#{map." + paramKey + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String paramKey = "fprP" + 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 mapMsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "t.id"; + case "isDeleted" -> "t.isDeleted"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "sttp" -> "t.sttp"; + case "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "sttpFullPath" -> "t.sttpFullPath"; + case "sttpTreeLevel" -> "t.sttpTreeLevel"; + case "tm" -> "t.tm"; + case "lgtd" -> "t.lgtd"; + case "lttd" -> "t.lttd"; + case "elev" -> "t.elev"; + case "stlc" -> "t.stlc"; + case "jcdt" -> "t.jcdt"; + case "wddt" -> "t.wddt"; + case "introduce" -> "t.introduce"; + case "logo" -> "t.logo"; + case "inffile" -> "t.inffile"; + case "usfl" -> "t.usfl"; + case "dtin" -> "t.dtin"; + case "dtinName" -> "t.dtinName"; + case "dtinTm" -> "t.dtinTm"; + case "mway" -> "t.mway"; + case "mwayName" -> "t.mwayName"; + case "stindx" -> "t.stindx"; + case "orderIndex" -> "t.orderIndex"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "rvcd" -> "t.rvcd"; + case "rvcdName" -> "t.rvcdName"; + case "purpose" -> "t.purpose"; + case "observe" -> "t.observe"; + case "dtfrqcy" -> "t.dtfrqcy"; + case "remark" -> "t.remark"; + case "vlsr" -> "t.vlsr"; + case "vlsrTm" -> "t.vlsrTm"; + case "bldstt" -> "t.bldstt"; + case "bldsttName" -> "t.bldsttName"; + case "bldsttCcode" -> "t.bldsttCcode"; + case "bldsttCcodeName" -> "t.bldsttCcodeName"; + case "recordUser" -> "t.recordUser"; + case "recordTime" -> "t.recordTime"; + case "modifyUser" -> "t.modifyUser"; + case "modifyTime" -> "t.modifyTime"; + case "baseStepSort" -> "t.baseStepSort"; + case "rvcdStepSort" -> "t.rvcdStepSort"; + case "rstcdStepSort" -> "t.rstcdStepSort"; + case "siteStepSort" -> "t.siteStepSort"; + default -> null; + }; + } + + private String buildMsstbprptDetailOrderBySql(List sorts) { + List orderItems = new ArrayList<>(); + if (CollUtil.isNotEmpty(sorts)) { + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapMsstbprptColumn(sort.getField()); + 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 t.baseStepSort ASC NULLS LAST, t.rvcdStepSort ASC NULLS LAST, " + + "t.rstcdStepSort ASC NULLS LAST, t.siteStepSort ASC NULLS LAST, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String buildMsstbprptGroupSql(String detailSql, GroupingInfo[] groupInfos) { + if (groupInfos == null || groupInfos.length == 0) { + return detailSql; + } + List groupFields = new ArrayList<>(); + List selectItems = new ArrayList<>(); + List orderItems = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + if (item == null || StrUtil.isBlank(item.getSelector())) { + continue; + } + String selector = item.getSelector(); + String column = mapMsstbprptColumn(selector); + if (StrUtil.isBlank(column)) { + continue; + } + groupFields.add(column); + selectItems.add(column + " AS " + selector); + selectItems.add("COUNT(*) AS count_" + selector); + orderItems.add(column + (item.getDesc() ? " DESC" : " ASC")); + } + if (groupFields.isEmpty()) { + return "SELECT * FROM (" + detailSql + ") t WHERE 1 = 0"; + } + return "SELECT " + String.join(", ", selectItems) + + " FROM (" + detailSql + ") t GROUP BY " + String.join(", ", groupFields) + + " ORDER BY " + String.join(", ", orderItems); + } + + private List normalizeValues(Object value) { + List values = new ArrayList<>(); + if (value == null) { + return values; + } + if (value instanceof List list) { + values.addAll(list); + return values; + } + String text = StrUtil.trim(String.valueOf(value)); + if (StrUtil.isBlank(text)) { + return values; + } + if (text.startsWith("[") && text.endsWith("]")) { + text = text.substring(1, text.length() - 1); + } + for (String item : text.split(",")) { + String trimmed = StrUtil.trim(item); + if (StrUtil.isNotBlank(trimmed)) { + values.add(StrUtil.removeAll(trimmed, "\"")); + } + } + return values; + } + + private boolean isDateField(String field) { + return "tm".equals(field) + || "jcdt".equals(field) + || "wddt".equals(field) + || "dtinTm".equals(field) + || "vlsrTm".equals(field) + || "recordTime".equals(field) + || "modifyTime".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) { + 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) { + return value != null && value.length() > 10 ? "YYYY-MM-DD HH24:MI:SS" : "YYYY-MM-DD"; + } +}