From 219323e0fcf0a0cd5f105be5e6a587a8df2a7efa Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 18 May 2026 16:19:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=87=BA=E5=85=A5?= =?UTF-8?q?=E5=BA=93=E6=B0=B4=E6=B8=A9=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/MicroservicDynamicSQLMapper.java | 85 +++-- .../controller/SdRvwtSInOutOneController.java | 41 +++ .../yfd/platform/env/entity/vo/SdRvwtSVO.java | 56 +++ .../yfd/platform/env/entity/vo/StcdVo.java | 21 ++ .../env/mapper/SdRvwtSInOutOneMapper.java | 60 ++++ .../env/service/SdRvwtSInOutOneService.java | 15 + .../impl/SdRvwtSInOutOneServiceImpl.java | 338 ++++++++++++++++++ 7 files changed, 593 insertions(+), 23 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/env/controller/SdRvwtSInOutOneController.java create mode 100644 backend/src/main/java/com/yfd/platform/env/entity/vo/SdRvwtSVO.java create mode 100644 backend/src/main/java/com/yfd/platform/env/entity/vo/StcdVo.java create mode 100644 backend/src/main/java/com/yfd/platform/env/mapper/SdRvwtSInOutOneMapper.java create mode 100644 backend/src/main/java/com/yfd/platform/env/service/SdRvwtSInOutOneService.java create mode 100644 backend/src/main/java/com/yfd/platform/env/service/impl/SdRvwtSInOutOneServiceImpl.java 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 930d806..28ac057 100644 --- a/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java +++ b/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java @@ -1,28 +1,37 @@ package com.yfd.platform.common; +import cn.hutool.core.bean.BeanUtil; +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.List; +import java.util.Map; +import java.util.ArrayList; +import java.lang.reflect.Constructor; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; -import java.util.List; -import java.util.Map; - @Mapper public interface MicroservicDynamicSQLMapper { + @Select({""}) + List> pageAllList(Page page, @Param("sql") String sql, @Param("map") Map map); - @Select({"${sql}"}) - List> pageAllList(Page page, String sql, @Param("map") Map map); + default List pageAllListWithResultType(Page page, + String sql, + Map map, + Class resultType) { + return convertList(pageAllList(page, sql, map), resultType); + } - @Select({"${sql}"}) - List pageAllListWithResultType(Page page, @Param("sql") String sql, @Param("map") Map map, @Param("resultType") Class resultType); + @Select({""}) + List> getAllList(@Param("sql") String sql, @Param("map") Map map); - @Select({"${sql}"}) - List getAllList(String sql, @Param("map") Map map); - - @Select({"${sql}"}) - List getAllListWithResultType(@Param("sql") String sql, @Param("map") Map map, @Param("resultType") Class resultType); + default List getAllListWithResultType(String sql, + Map map, + Class resultType) { + return convertList(getAllList(sql, map), resultType); + } @Select({"select count(1) count from ${sql} and ${ew.sqlSegment}"}) Integer count(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @@ -31,31 +40,36 @@ public interface MicroservicDynamicSQLMapper { Integer countNoWrapper(@Param("select") String select, @Param("sql") String sql); @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) - List pageList(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> pageList(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); - @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) - List pageListWithResultType(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper, @Param("resultType") Class resultType); + default List pageListWithResultType(Page page, + String select, + String sql, + QueryWrapper queryWrapper, + Class resultType) { + return convertList(pageList(page, select, sql, queryWrapper), resultType); + } @Select({"select ${select} from ${sql} ${ew.sqlSegment}"}) - List pageNoFilterList(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> pageNoFilterList(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @Select({"select ${select} from ${sql}"}) - List pageListNoWrapper(Page page, @Param("select") String select, @Param("sql") String sql); + List> pageListNoWrapper(Page page, @Param("select") String select, @Param("sql") String sql); @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) - List getList(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> getList(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) - List getListWithResultType(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> getListWithResultType(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @Select({"select ${select} from ${table} where ${condition}"}) - List getSingleTableList(@Param("select") String select, @Param("table") String table, @Param("condition") String condition); + List> getSingleTableList(@Param("select") String select, @Param("table") String table, @Param("condition") String condition); @Select({"select ${select} from ${sql} ${ew.sqlSegment}"}) - List getNoFilterList(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> getNoFilterList(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @Select({"select ${select} from ${sql}"}) - List getListNoWrapper(@Param("select") String select, @Param("sql") String sql); + List> getListNoWrapper(@Param("select") String select, @Param("sql") String sql); @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) Map totalSummary(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @@ -77,4 +91,29 @@ public interface MicroservicDynamicSQLMapper { @Select({"select ${info} from ${joinsql} group by ${info}"}) List getGroup(@Param("info") String info, @Param("joinsql") String joinsql); -} \ No newline at end of file + + static List convertList(List> sourceList, Class resultType) { + List resultList = new ArrayList<>(); + if (sourceList == null || sourceList.isEmpty()) { + return resultList; + } + CopyOptions copyOptions = CopyOptions.create() + .setIgnoreCase(true) + .setIgnoreError(true); + for (Map row : sourceList) { + R bean = BeanUtil.fillBeanWithMap(row, createTargetBean(resultType), copyOptions); + resultList.add(bean); + } + return resultList; + } + + static R createTargetBean(Class resultType) { + try { + Constructor constructor = resultType.getDeclaredConstructor(); + constructor.setAccessible(true); + return constructor.newInstance(); + } catch (Exception e) { + throw new IllegalStateException("动态SQL结果映射失败,目标类型必须提供无参构造器: " + resultType.getName(), e); + } + } +} diff --git a/backend/src/main/java/com/yfd/platform/env/controller/SdRvwtSInOutOneController.java b/backend/src/main/java/com/yfd/platform/env/controller/SdRvwtSInOutOneController.java new file mode 100644 index 0000000..0fcc63c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/controller/SdRvwtSInOutOneController.java @@ -0,0 +1,41 @@ +package com.yfd.platform.env.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.env.service.SdRvwtSInOutOneService; +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("/sw/inOutOne") +@Tag(name = "出入库水温一级折线图") +@Validated +public class SdRvwtSInOutOneController { + + @Resource + private SdRvwtSInOutOneService sdRvwtSInOutOneService; + + @PostMapping("/GetKendoListCust") + @Operation(summary = "查询出入库水温一级列表") + public ResponseResult getKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdRvwtSInOutOneService.processKendoList(dataSourceRequest)); + } + + @PostMapping("/details") + @Operation(summary = "一次性返回出库水温和入库水温详情") + public ResponseResult getDetails(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdRvwtSInOutOneService.getDetails(dataSourceRequest)); + } + + @PostMapping("/default/stcd") + @Operation(summary = "获取出入库水温默认有数据的电站") + public ResponseResult getDefaultStcd(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdRvwtSInOutOneService.getDefaultStcd(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/SdRvwtSVO.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdRvwtSVO.java new file mode 100644 index 0000000..065ccaf --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdRvwtSVO.java @@ -0,0 +1,56 @@ +package com.yfd.platform.env.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldNameConstants; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +@Getter +@Setter +@FieldNameConstants +@Schema(description = "出入库水温数据VO") +public class SdRvwtSVO implements Serializable { + + private static final long serialVersionUID = 1L; + + public static final String DWTP_IWT = "IWT"; + + public static final String DWTP_DWT = "DWT"; + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "站名") + private String stnm; + + @Schema(description = "时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date dt; + + @Schema(description = "时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date tm; + + @Schema(description = "水温") + private BigDecimal wt; + + @Schema(description = "类型:IWT=入库,DWT=出库") + private String dwtp; + + @Schema(description = "所属电站入库水温编码") + private String engIwtCode; + + @Schema(description = "所属电站出库水温编码") + private String engDwtCode; + + @Schema(description = "入库水温值") + private BigDecimal iwtValue; + + @Schema(description = "出库水温值") + private BigDecimal dwtValue; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/StcdVo.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/StcdVo.java new file mode 100644 index 0000000..a2eea88 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/StcdVo.java @@ -0,0 +1,21 @@ +package com.yfd.platform.env.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +@Getter +@Setter +@Schema(description = "默认电站信息") +public class StcdVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "站名") + private String stnm; +} diff --git a/backend/src/main/java/com/yfd/platform/env/mapper/SdRvwtSInOutOneMapper.java b/backend/src/main/java/com/yfd/platform/env/mapper/SdRvwtSInOutOneMapper.java new file mode 100644 index 0000000..8c695a1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/mapper/SdRvwtSInOutOneMapper.java @@ -0,0 +1,60 @@ +package com.yfd.platform.env.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.env.entity.vo.SdRvwtSVO; +import com.yfd.platform.env.entity.vo.StcdVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.Date; +import java.util.List; + +@Mapper +public interface SdRvwtSInOutOneMapper extends BaseMapper { + + @Select("SELECT STCD AS stcd, ENG_IWT_CODE AS engIwtCode, ENG_DWT_CODE AS engDwtCode " + + "FROM SD_PRWTRLTN_B " + + "WHERE IS_DELETED = 0 AND STCD = #{stcd}") + SdRvwtSVO getRelationByEngStcd(@Param("stcd") String stcd); + + @Select({ + "" + }) + List getDefaultStcd(@Param("baseIdList") List baseIdList, + @Param("rvcdList") List rvcdList, + @Param("startTime") Date startTime, + @Param("endTime") Date endTime); +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/SdRvwtSInOutOneService.java b/backend/src/main/java/com/yfd/platform/env/service/SdRvwtSInOutOneService.java new file mode 100644 index 0000000..dad16f7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/SdRvwtSInOutOneService.java @@ -0,0 +1,15 @@ +package com.yfd.platform.env.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.env.entity.vo.SdRvwtSVO; +import com.yfd.platform.env.entity.vo.StcdVo; + +public interface SdRvwtSInOutOneService { + + DataSourceResult processKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult getDetails(DataSourceRequest dataSourceRequest); + + DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdRvwtSInOutOneServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdRvwtSInOutOneServiceImpl.java new file mode 100644 index 0000000..58971a1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdRvwtSInOutOneServiceImpl.java @@ -0,0 +1,338 @@ +package com.yfd.platform.env.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.common.*; +import com.yfd.platform.env.entity.vo.SdRvwtSVO; +import com.yfd.platform.env.entity.vo.StcdVo; +import com.yfd.platform.env.mapper.SdRvwtSInOutOneMapper; +import com.yfd.platform.env.service.SdRvwtSInOutOneService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Service +public class SdRvwtSInOutOneServiceImpl extends ServiceImpl implements SdRvwtSInOutOneService { + + private static final String TYPE_IWT = "IWT"; + + private static final String TYPE_DWT = "DWT"; + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Resource + private SdRvwtSInOutOneMapper sdRvwtSInOutOneMapper; + + @Override + public DataSourceResult processKendoList(DataSourceRequest dataSourceRequest) { + return doProcessKendoList(dataSourceRequest, null, null); + } + + @Override + public DataSourceResult getDetails(DataSourceRequest dataSourceRequest) { + DataSourceResult dwtResult = doProcessKendoList(dataSourceRequest, true, TYPE_DWT); + DataSourceResult iwtResult = doProcessKendoList(dataSourceRequest, true, TYPE_IWT); + + List dList = dwtResult.getData() == null ? new ArrayList<>() : dwtResult.getData(); + List iList = iwtResult.getData() == null ? new ArrayList<>() : iwtResult.getData(); + + LinkedHashMap resultMap = new LinkedHashMap<>(); + String sortField = getPrimarySortField(dataSourceRequest.getSort()); + if ("dwtValue".equals(sortField)) { + mergeDetailList(resultMap, dList, TYPE_DWT); + mergeDetailList(resultMap, iList, TYPE_IWT); + } else { + mergeDetailList(resultMap, iList, TYPE_IWT); + mergeDetailList(resultMap, dList, TYPE_DWT); + } + + List resultList = new ArrayList<>(resultMap.values()); + DataSourceResult result = new DataSourceResult<>(); + result.setData(resultList); + long total = dwtResult.getTotal() != 0 ? dwtResult.getTotal() + : (iwtResult.getTotal() != 0 ? iwtResult.getTotal() : resultList.size()); + result.setTotal(total); + return result; + } + + @Override + public DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + Date[] timeRange = parseTimeRange(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm")); + List baseIdList = splitFilterValues(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId")); + List rvcdList = splitFilterValues(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rvcd")); + + List resultList = sdRvwtSInOutOneMapper.getDefaultStcd( + baseIdList, + rvcdList, + timeRange[0], + timeRange[1] + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(resultList); + result.setTotal(resultList.size()); + return result; + } + + private DataSourceResult doProcessKendoList(DataSourceRequest dataSourceRequest, + Boolean forceDetail, + String forceType) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String engStcd = normalizeFilterValue(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd")); + String relationStcd = firstNotBlank( + engStcd, + normalizeFilterValue(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "engIwtCode")), + normalizeFilterValue(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "engDwtCode")) + ); + String url = normalizeFilterValue(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "url")); + boolean isDetail = forceDetail != null ? forceDetail : "details".equals(url); + + String tableName = isDetail ? "SD_WTRV_R" : "SD_WTRVDAY_S"; + String timeColumn = isDetail ? "SWS.TM" : "SWS.DT"; + Date[] timeRange = parseTimeRange(resolveTimeFilterValue(loadOptions)); + List baseIdList = splitFilterValues(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId")); + List rvcdList = splitFilterValues(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rvcd")); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT SWT.STCD AS stcd, ") + .append("SWT.STNM AS stnm, ") + .append(timeColumn).append(" AS tm, ") + .append(timeColumn).append(" AS dt, ") + .append("SWS.WT AS wt, ") + .append("REL.ENG_IWT_CODE AS engIwtCode, ") + .append("REL.ENG_DWT_CODE AS engDwtCode ") + .append("FROM (") + .append(" SELECT SPR.STCD, SPR.ENG_IWT_CODE, SPR.ENG_DWT_CODE ") + .append(" FROM SD_PRWTRLTN_B SPR ") + .append(" WHERE SPR.IS_DELETED = 0 "); + + Map paramMap = new HashMap<>(); + if (StrUtil.isNotBlank(relationStcd)) { + paramMap.put("relationStcd", relationStcd); + sql.append(" AND SPR.STCD = #{map.relationStcd} "); + } + sql.append(") REL ") + .append("INNER JOIN SD_ENGINFO_B_H SEG ON SEG.STCD = REL.STCD ") + .append("INNER JOIN ").append(tableName).append(" SWS ON SWS.STCD IN (REL.ENG_IWT_CODE, REL.ENG_DWT_CODE) ") + .append("INNER JOIN SD_WT_B_H SWT ON SWT.STCD = SWS.STCD ") + .append("WHERE SWS.IS_DELETED = 0 ") + .append("AND SWT.IS_DELETED = 0 ") + .append("AND SWT.USFL = 1 ") + .append("AND SWT.MWAY = 2 ") + .append("AND SWT.STTP = 'WTRV' ") + .append("AND SEG.USFL = 1 "); + if (timeRange[0] != null && timeRange[1] != null) { + paramMap.put("startTime", timeRange[0]); + paramMap.put("endTime", timeRange[1]); + sql.append("AND ").append(timeColumn).append(" >= #{map.startTime} ") + .append("AND ").append(timeColumn).append(" <= #{map.endTime} "); + } + + if (isDetail) { + appendDetailCondition(sql, forceType); + } else { + appendInCondition(sql, paramMap, "SEG.BASE_ID", "baseId", baseIdList); + appendInCondition(sql, paramMap, "SEG.RVCD", "rvcd", rvcdList); + } + + sql.append(buildOrderBySql(dataSourceRequest.getSort(), timeColumn)); + Page page = buildPage(loadOptions); + List resultList = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, SdRvwtSVO.class); + + if (!isDetail) { + fillDwtp(resultList); + } + + DataSourceResult result = new DataSourceResult<>(); + result.setData(resultList); + result.setTotal(ObjectUtil.isNotEmpty(page) ? page.getTotal() : resultList.size()); + return result; + } + + private void appendDetailCondition(StringBuilder sql, String forceType) { + if (TYPE_IWT.equals(forceType)) { + sql.append("AND SWT.STCD = REL.ENG_IWT_CODE "); + } else if (TYPE_DWT.equals(forceType)) { + sql.append("AND SWT.STCD = REL.ENG_DWT_CODE "); + } + } + + private void fillDwtp(List voList) { + for (SdRvwtSVO vo : voList) { + if (StrUtil.isNotBlank(vo.getStcd()) + && StrUtil.isNotBlank(vo.getEngIwtCode()) + && vo.getStcd().equals(vo.getEngIwtCode())) { + vo.setDwtp(SdRvwtSVO.DWTP_IWT); + } else if (StrUtil.isNotBlank(vo.getStcd()) + && StrUtil.isNotBlank(vo.getEngDwtCode()) + && vo.getStcd().equals(vo.getEngDwtCode())) { + vo.setDwtp(SdRvwtSVO.DWTP_DWT); + } + } + } + + private void mergeDetailList(LinkedHashMap resultMap, List sourceList, String type) { + for (SdRvwtSVO source : sourceList) { + Date key = source.getTm(); + SdRvwtSVO target = resultMap.computeIfAbsent(key, item -> { + SdRvwtSVO vo = new SdRvwtSVO(); + vo.setDt(item); + vo.setTm(item); + return vo; + }); + if (TYPE_IWT.equals(type)) { + target.setIwtValue(source.getWt()); + } else if (TYPE_DWT.equals(type)) { + target.setDwtValue(source.getWt()); + } + } + } + + private Page buildPage(DataSourceLoadOptionsBase loadOptions) { + PageInfo pageInfo = QgcQueryWrapperUtil.getPageInfo(loadOptions); + if (Boolean.TRUE.equals(pageInfo.getHasPageInfo())) { + return pageInfo.getPage(); + } + return null; + } + + private String buildOrderBySql(List sortList, String timeColumn) { + List orderColumns = new ArrayList<>(); + if (sortList != null) { + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + String field = sortDescriptor.getField(); + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + if ("tm".equals(field) || "dt".equals(field)) { + orderColumns.add(timeColumn + " " + dir); + } else if ("wt".equals(field) || "iwtValue".equals(field) || "dwtValue".equals(field)) { + orderColumns.add("SWS.WT " + dir); + } else if ("stcd".equals(field)) { + orderColumns.add("SWS.STCD " + dir); + } else if ("stnm".equals(field)) { + orderColumns.add("SWT.STNM " + dir); + } + } + } + if (orderColumns.isEmpty()) { + return " ORDER BY tm ASC"; + } + return " ORDER BY " + String.join(", ", orderColumns); + } + + private String getPrimarySortField(List sortList) { + if (sortList == null || sortList.isEmpty()) { + return null; + } + return sortList.get(0).getField(); + } + + private List pagingMemoryList(List sourceList, DataSourceRequest dataSourceRequest) { + int skip = Math.max(dataSourceRequest.getSkip(), 0); + int take = dataSourceRequest.getTake(); + if (take <= 0) { + return sourceList; + } + if (skip >= sourceList.size()) { + return new ArrayList<>(); + } + int end = Math.min(skip + take, sourceList.size()); + return new ArrayList<>(sourceList.subList(skip, end)); + } + + private void appendInCondition(StringBuilder sql, + Map paramMap, + String columnName, + String keyPrefix, + List valueList) { + if (valueList == null || valueList.isEmpty()) { + return; + } + sql.append("AND ").append(columnName).append(" IN ("); + for (int i = 0; i < valueList.size(); i++) { + String key = keyPrefix + i; + paramMap.put(key, valueList.get(i)); + if (i > 0) { + sql.append(", "); + } + sql.append("#{map.").append(key).append("}"); + } + sql.append(") "); + } + + private List splitFilterValues(String value) { + String filterValue = normalizeFilterValue(value); + List resultList = new ArrayList<>(); + if (StrUtil.isBlank(filterValue)) { + return resultList; + } + String[] values = filterValue.split(","); + for (String item : values) { + String valueItem = item == null ? null : item.trim(); + if (StrUtil.isNotBlank(valueItem) && !resultList.contains(valueItem)) { + resultList.add(valueItem); + } + } + return resultList; + } + + private String normalizeFilterValue(String value) { + if (StrUtil.isBlank(value)) { + return null; + } + return value.replace("[", "") + .replace("]", "") + .replace("\"", "") + .replace("'", "") + .trim(); + } + + private Date[] parseTimeRange(String timeValue) { + String filterValue = normalizeFilterValue(timeValue); + if (StrUtil.isBlank(filterValue)) { + return new Date[]{null, null}; + } + String[] values = filterValue.split(","); + if (values.length == 0) { + return new Date[]{null, null}; + } + Date startTime = DateUtil.parse(values[0].trim()); + Date endTime = values.length > 1 ? DateUtil.parse(values[1].trim()) : startTime; + if (startTime.after(endTime)) { + Date temp = startTime; + startTime = endTime; + endTime = temp; + } + return new Date[]{startTime, endTime}; + } + + private String resolveTimeFilterValue(DataSourceLoadOptionsBase loadOptions) { + String timeValue = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + if (StrUtil.isBlank(normalizeFilterValue(timeValue))) { + timeValue = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "dt"); + } + return timeValue; + } + + private String firstNotBlank(String... values) { + if (values == null) { + return null; + } + for (String value : values) { + if (StrUtil.isNotBlank(value)) { + return value; + } + } + return null; + } +}