From 5b911aa342bc93abbe14662c73b5b7251096d1ef Mon Sep 17 00:00:00 2001 From: tangwei Date: Fri, 10 Apr 2026 11:09:38 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=B7=91=E9=80=9A=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3map=E8=BF=94=E5=9B=9E=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/enums/QecIntervalEnum.java | 36 ++ .../yfd/platform/common/enums/ShowEnum.java | 22 + .../controller/EngEqIntervalController.java | 10 +- .../impl/EngEqIntervalServiceImpl.java | 198 +++++---- .../yfd/platform/utils/QueryWrapperUtil.java | 408 +++++++++++++++++- .../src/main/resources/application-devtw.yml | 17 + 6 files changed, 576 insertions(+), 115 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/common/enums/QecIntervalEnum.java create mode 100644 backend/src/main/java/com/yfd/platform/common/enums/ShowEnum.java diff --git a/backend/src/main/java/com/yfd/platform/common/enums/QecIntervalEnum.java b/backend/src/main/java/com/yfd/platform/common/enums/QecIntervalEnum.java new file mode 100644 index 0000000..d23cbbd --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/common/enums/QecIntervalEnum.java @@ -0,0 +1,36 @@ +package com.yfd.platform.common.enums; + +public enum QecIntervalEnum { + QEC_STLL_1_DY95("QEC_STLL_1_DY95","生态流量达标率所在统计区间:>=95%"), + QEC_STLL_2_90AND95("QEC_STLL_2_90AND95","生态流量达标率所在统计区间:90%~95%"), + QEC_STLL_3_80AND90("QEC_STLL_3_80AND90","生态流量达标率所在统计区间:80%~90%"), + QEC_STLL_4_XY80("QEC_STLL_4_XY80","生态流量达标率所在统计区间:<80%"), + QEC_STLL_5_EMPTY("QEC_STLL_5_EMPTY","无生态流量数据"), + QEC_STLL_6_NOEQMN("QEC_STLL_6_NOEQMN","无生态流量要求"); + /** 变量类型 code */ + private String code; + + + /** 描述. */ + private String desc; + + + QecIntervalEnum(String code, String desc) { + this.code = code; + this.desc = desc; + } + + /** + * @return the code - {返回值描述信息}. + */ + public String getCode() { + return code; + } + + /** + * @return the desc - {返回值描述信息}. + */ + public String getDesc() { + return desc; + } +} diff --git a/backend/src/main/java/com/yfd/platform/common/enums/ShowEnum.java b/backend/src/main/java/com/yfd/platform/common/enums/ShowEnum.java new file mode 100644 index 0000000..c524c76 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/common/enums/ShowEnum.java @@ -0,0 +1,22 @@ +package com.yfd.platform.common.enums; + +public enum ShowEnum { + Q(1,"环评要求"), + M(2,"水利部要求"), + A(3,"多年平均流量10%"), + N(4,"无生态流量要求"); + private Integer code; + private String desc; + + ShowEnum(Integer code,String desc){ + this.code=code; + this.desc=desc; + } + + public Integer getCode(){ + return code; + } + public String getDesc(){ + return desc; + } +} diff --git a/backend/src/main/java/com/yfd/platform/eng/controller/EngEqIntervalController.java b/backend/src/main/java/com/yfd/platform/eng/controller/EngEqIntervalController.java index f05dfb4..aef8393 100644 --- a/backend/src/main/java/com/yfd/platform/eng/controller/EngEqIntervalController.java +++ b/backend/src/main/java/com/yfd/platform/eng/controller/EngEqIntervalController.java @@ -83,13 +83,11 @@ public class EngEqIntervalController { @Operation(summary = "生态流量达标率 小时统计(二级页面)") public ResponseResult getQgcHourKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { String kendoGroupCode = "EngEqHour"; -// KendoParamGroupServiceApi serviceApi = SpringContextHolder.getBean(KendoParamGroupServiceApi.class); -// String filter = serviceApi.getParamGroupConfigByCode(TenantContextHolder.getPlatformId(), kendoGroupCode); - Map filterResult = KendoUtil.getGroupResultMap(dataSourceRequest, null, EngEqIntervalController.class); +// Map filterResult = KendoUtil.getGroupResultMap(dataSourceRequest, null, EngEqIntervalController.class); String groupBy = KendoUtil.getGroupBy(dataSourceRequest); Page page = KendoUtil.getPage(dataSourceRequest); - DataSourceResult result = eqIntervalService.getQgcHourKendoListCust(dataSourceRequest, filterResult, page, groupBy); - eqIntervalService.processKendoGetListLoadResult(dataSourceRequest, result); + DataSourceResult result = eqIntervalService.getQgcHourKendoListCust(dataSourceRequest, null, page, groupBy); +// eqIntervalService.processKendoGetListLoadResult(dataSourceRequest, result); return ResponseResult.successData(result); } @@ -116,7 +114,7 @@ public class EngEqIntervalController { */ @PostMapping({"/qgc/getQgcStaticData"}) @Operation(summary = "生态流量达标率 区间范围统计(一级页面)") - @Log(module = "生态流量", value = "生态流量达标率统计") +// @Log(module = "生态流量", value = "生态流量达标率统计") public ResponseResult getQgcStaticData(@RequestBody DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptionsBase = dataSourceRequest.toDevRequest(); String type = QueryWrapperUtil.getFilterFieldValue(loadOptionsBase, "type"); diff --git a/backend/src/main/java/com/yfd/platform/eng/service/impl/EngEqIntervalServiceImpl.java b/backend/src/main/java/com/yfd/platform/eng/service/impl/EngEqIntervalServiceImpl.java index c1ed1d9..acc247d 100644 --- a/backend/src/main/java/com/yfd/platform/eng/service/impl/EngEqIntervalServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/eng/service/impl/EngEqIntervalServiceImpl.java @@ -6,8 +6,12 @@ import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; //import com.yfd.platform.common.DataSourceRequest; //import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.common.DynamicSQLMapper; +import com.yfd.platform.common.enums.QecIntervalEnum; +import com.yfd.platform.common.enums.ShowEnum; import com.yfd.platform.eng.domain.MsEngEq; import com.yfd.platform.eng.service.EngEqIntervalService; +import com.yfd.platform.utils.QueryWrapperUtil; import com.zny.dec.core.common.util.ObjectUtil; import com.zny.dec.core.common.util.StringUtil; import com.zny.dec.framework.kendo.entity.dto.devextreme.DataSourceLoadOptionsBase; @@ -16,6 +20,7 @@ import com.zny.dec.framework.kendo.entity.dto.kendo.DataSourceRequest; import com.zny.dec.framework.kendo.entity.dto.kendo.DataSourceResult; import com.zny.dec.framework.kendo.entity.mapping.GroupResult; import com.zny.dec.framework.kendo.mybatis.devExtreme.helper.GroupHelper; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.math.BigDecimal; @@ -26,7 +31,8 @@ import java.util.*; */ @Service public class EngEqIntervalServiceImpl implements EngEqIntervalService { - + @Resource + private DynamicSQLMapper dynamicSQLMapper; @Override public DataSourceResult processKendoList(DataSourceRequest dataSourceRequest, Map filterResult, Page page) { // 模拟数据,实际应该从数据库查询 @@ -47,47 +53,22 @@ public class EngEqIntervalServiceImpl implements EngEqIntervalService { DataSourceResult dataSourceResult = new DataSourceResult<>(); DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); StringBuilder sql = new StringBuilder(); - String kendoGroupCode="default"; - if (filterResult.get(kendoGroupCode) !=null && StringUtil.isNotBlank(filterResult.get(kendoGroupCode).getSelectSql())) { - sql.append(filterResult.get(kendoGroupCode).getSelectSql()); - sql.append(" FROM "); - sql.append("(select MSB.STCD,MSB.STNM as ENNM,MSB.BASESTEPSORT,MSB.SITESTEPSORT,MSB.RVCDSTEPSORT,MSB.RSTCDSTEPSORT ,MSB.BASE_NAME,MSB.BASE_ID,MSB.ORDER_INDEX orderIndex,MSB.HBRVCD ,MSB.HBRVCD_NAME,MSB.ADDVCD_NAME ,MSB.STTP_CODE,'ENG' as sttp,MSB.LGTD,MSB.LTTD,MSB.DTMEL ,MSB.TTPWR,MSB.NORMZ,MSB.DTIN_ENV,MSB.AVQ ,SQR.QEC_RATE,SQR.MWR_RATE,SQR.AVQ_RATE,SHR.QI,SHR.QO,SHR.RZ,SHR.QO_SUM,SHR.QI_SUM,(CASE WHEN SQR.STCD IS NULL and qecR.stcd is null THEN 'QEC_STLL_5_EMPTY' WHEN SQR.STCD IS NULL and qecR.stcd is not null THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.STCD IS NOT NULL AND SQR.QR = -2 THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.STCD IS NOT NULL AND SQR.QR = -1 THEN 'QEC_STLL_5_EMPTY' WHEN SQR.QEC_RATE >= 95 THEN 'QEC_STLL_1_DY95' WHEN SQR.QEC_RATE >= 90 AND 95 > SQR.QEC_RATE THEN 'QEC_STLL_2_90AND95' WHEN SQR.QEC_RATE >= 80 AND 90 > SQR.QEC_RATE THEN 'QEC_STLL_3_80AND90' WHEN 80 > SQR.QEC_RATE THEN 'QEC_STLL_4_XY80' END) AS QEC_INTERVAL ,(CASE WHEN SQR.STCD IS NULL and mwrR.stcd is null THEN 'QEC_STLL_5_EMPTY' WHEN SQR.STCD IS NULL and mwrR.stcd is not null THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.STCD IS NOT NULL AND SQR.MQR = -2 THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.STCD IS NOT NULL AND SQR.MQR = -1 THEN 'QEC_STLL_5_EMPTY' WHEN SQR.MWR_RATE >= 95 THEN 'QEC_STLL_1_DY95' WHEN SQR.MWR_RATE >= 90 AND 95 > SQR.MWR_RATE THEN 'QEC_STLL_2_90AND95' WHEN SQR.MWR_RATE >= 80 AND 90 > SQR.MWR_RATE THEN 'QEC_STLL_3_80AND90' WHEN 80 > SQR.MWR_RATE THEN 'QEC_STLL_4_XY80' END) AS MWR_INTERVAL ,(CASE WHEN MSB.AVQ is not null AND SQR.AVQ_RATE IS NULL THEN 'QEC_STLL_5_EMPTY' WHEN MSB.AVQ is null THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.AVQ_RATE >= 95 THEN 'QEC_STLL_1_DY95' WHEN SQR.AVQ_RATE >= 90 AND 95 > SQR.AVQ_RATE THEN 'QEC_STLL_2_90AND95' WHEN SQR.AVQ_RATE >= 80 AND 90 > SQR.AVQ_RATE THEN 'QEC_STLL_3_80AND90' WHEN 80 > SQR.AVQ_RATE THEN 'QEC_STLL_4_XY80' END) AS AVQ_INTERVAL ,(case when SQR.QEC_RATE is null and MSB.PRSC = 1 then 'eef_1_none' when SQR.QEC_RATE >=95 and MSB.PRSC = 1 then 'eef_1_1' when SQR.QEC_RATE >=90 and 95 > SQR.QEC_RATE and MSB.PRSC = 1 then 'eef_1_2' when SQR.QEC_RATE >=80 and 90 > SQR.QEC_RATE and MSB.PRSC = 1 then 'eef_1_3' when 80 > SQR.QEC_RATE and MSB.PRSC = 1 then 'eef_1_4' when SQR.QEC_RATE is null and MSB.PRSC in (2,3) then 'eef_2_none' when SQR.QEC_RATE >=95 and MSB.PRSC in (2,3) then 'eef_2_1' when SQR.QEC_RATE >=90 and 95 > SQR.QEC_RATE and MSB.PRSC in (2,3) then 'eef_2_2' when SQR.QEC_RATE >=80 and 90 > SQR.QEC_RATE and MSB.PRSC in (2,3) then 'eef_2_3' when 80 > SQR.QEC_RATE and MSB.PRSC in (2,3) then 'eef_2_4' end) as ANCHO_POINT_STATE ,(case when SQR.MWR_RATE is null and MSB.PRSC = 1 then 'eef_1_none' when SQR.MWR_RATE >=95 and MSB.PRSC = 1 then 'eef_1_1' when SQR.MWR_RATE >=90 and 95 > SQR.MWR_RATE and MSB.PRSC = 1 then 'eef_1_2' when SQR.MWR_RATE >=80 and 90 > SQR.MWR_RATE and MSB.PRSC = 1 then 'eef_1_3' when 80 > SQR.MWR_RATE and MSB.PRSC = 1 then 'eef_1_4' when SQR.MWR_RATE is null and MSB.PRSC in (2,3) then 'eef_2_none' when SQR.MWR_RATE >=95 and MSB.PRSC in (2,3) then 'eef_2_1' when SQR.MWR_RATE >=90 and 95 > SQR.MWR_RATE and MSB.PRSC in (2,3) then 'eef_2_2' when SQR.MWR_RATE >=80 and 90 > SQR.MWR_RATE and MSB.PRSC in (2,3) then 'eef_2_3' when 80 > SQR.MWR_RATE and MSB.PRSC in (2,3) then 'eef_2_4' end) as MWR_POINT_STATE ,(case when SQR.AVQ_RATE is null and MSB.PRSC = 1 then 'eef_1_none' when SQR.AVQ_RATE >=95 and MSB.PRSC = 1 then 'eef_1_1' when SQR.AVQ_RATE >=90 and 95 > SQR.AVQ_RATE and MSB.PRSC = 1 then 'eef_1_2' when SQR.AVQ_RATE >=80 and 90 > SQR.AVQ_RATE and MSB.PRSC = 1 then 'eef_1_3' when 80 > SQR.AVQ_RATE and MSB.PRSC = 1 then 'eef_1_4' when SQR.AVQ_RATE is null and MSB.PRSC in (2,3) then 'eef_2_none' when SQR.AVQ_RATE >=95 and MSB.PRSC in (2,3) then 'eef_2_1' when SQR.AVQ_RATE >=90 and 95 > SQR.AVQ_RATE and MSB.PRSC in (2,3) then 'eef_2_2' when SQR.AVQ_RATE >=80 and 90 > SQR.AVQ_RATE and MSB.PRSC in (2,3) then 'eef_2_3' when 80 > SQR.AVQ_RATE and MSB.PRSC in (2,3) then 'eef_2_4' end) as AVQ_POINT_STATE from V_MS_STBPRP_T MSB left join (select STCD ,(case when sum(case when SFDB =1 or SFDB =0 then 1 else 0 end) =0 then null else (sum(case when SFDB =1 then 1 else 0 end)/sum(case when SFDB =1 or SFDB =0 then 1 else 0 end)) end)*100 QEC_RATE ,(case when sum(case when MWR_SFDB =1 or MWR_SFDB =0 then 1 else 0 end) =0 then null else (sum(case when MWR_SFDB =1 then 1 else 0 end)/sum(case when MWR_SFDB =1 or MWR_SFDB =0 then 1 else 0 end)) end)*100 MWR_RATE ,(case when sum(case when AVQ_SFDB =1 or AVQ_SFDB =0 then 1 else 0 end) =0 then null else (sum(case when AVQ_SFDB =1 then 1 else 0 end)/sum(case when AVQ_SFDB =1 or AVQ_SFDB =0 then 1 else 0 end)) end)*100 AVQ_RATE ,case when count(1)=sum(case when SFDB =2 then 1 else 0 end) then -1 when count(1)=sum(case when SFDB =3 then 1 else 0 end) then -2 WHEN sum(CASE WHEN SFDB = 2 THEN 1 ELSE 0 END) >0 and count(1) = sum(CASE WHEN SFDB = 2 THEN 1 ELSE 0 END)+sum(CASE WHEN SFDB = 3 THEN 1 ELSE 0 END)+sum(CASE WHEN SFDB is null THEN 1 ELSE 0 END) then -1 WHEN sum(CASE WHEN SFDB = 2 THEN 1 ELSE 0 END) =0 and count(1) = sum(CASE WHEN SFDB = 2 THEN 1 ELSE 0 END)+sum(CASE WHEN SFDB = 3 THEN 1 ELSE 0 END)+sum(CASE WHEN SFDB is null THEN 1 ELSE 0 END) then -2 end qr ,case when count(1)=sum(case when MWR_SFDB =2 then 1 else 0 end) then -1 when count(1)=sum(case when MWR_SFDB =3 then 1 else 0 end) then -2 WHEN sum(CASE WHEN MWR_SFDB = 2 THEN 1 ELSE 0 END) >0 and count(1) = sum(CASE WHEN MWR_SFDB = 2 THEN 1 ELSE 0 END)+sum(CASE WHEN MWR_SFDB = 3 THEN 1 ELSE 0 END)+sum(CASE WHEN MWR_SFDB is null THEN 1 ELSE 0 END) then -1 WHEN sum(CASE WHEN MWR_SFDB = 2 THEN 1 ELSE 0 END) =0 and count(1) = sum(CASE WHEN MWR_SFDB = 2 THEN 1 ELSE 0 END)+sum(CASE WHEN MWR_SFDB = 3 THEN 1 ELSE 0 END)+sum(CASE WHEN MWR_SFDB is null THEN 1 ELSE 0 END) then -2 end mqr ,case when count(1)=sum(case when AVQ_SFDB =2 then 1 else 0 end) then -1 when count(1)=sum(case when AVQ_SFDB =3 then 1 else 0 end) then -2 end aqr from SD_QEC_R where 1=1 "); - if(filterResult.get("TM") !=null && StringUtil.isNotBlank(filterResult.get("TM").getGroupSql())){ - sql.append(" and ").append(filterResult.get("TM").getGroupSql()); - } - sql.append(" group by STCD) SQR on MSB.STCD=SQR.STCD left join (SELECT stcd, avg(QI) QI, avg(QO) QO, avg(qec) qec,avg(RZ) RZ,SUM(QI) QI_SUM,SUM(QO) QO_SUM from SD_HYDROPW_R where 1=1 "); - if(filterResult.get("TM") !=null && StringUtil.isNotBlank(filterResult.get("TM").getGroupSql())){ - sql.append(" and ").append(filterResult.get("TM").getGroupSql()); - } - sql.append(" group by STCD) SHR on SHR.STCD = MSB.STCD left join (select STCD from MS_STBPRP_T where is_deleted=0 and sttp_code ='ENG' and stcd not in (select distinct A.STCD from MS_WARN_RULE_STBPRP_B a INNER JOIN MS_WARN_RULE_DETAIL_B b ON a.RULE_ID = b.RULE_ID and b.is_deleted=0 INNER JOIN MS_WARN_RULE_B c ON c.ID = b.RULE_ID where a.is_deleted=0 and b.is_deleted=0 and c.RULE_TYPE in('EQMN') and c.is_deleted=0)) qecR on qecR.STCD =MSB.STCD left join (select STCD from MS_STBPRP_T where is_deleted=0 and sttp_code ='ENG' and stcd not in (select distinct A.STCD from MS_WARN_RULE_STBPRP_B a INNER JOIN MS_WARN_RULE_DETAIL_B b ON a.RULE_ID = b.RULE_ID and b.is_deleted=0 INNER JOIN MS_WARN_RULE_B c ON c.ID = b.RULE_ID where a.is_deleted=0 and b.is_deleted=0 and c.RULE_TYPE in('EQMNMWR') and c.is_deleted=0)) mwrR on mwrR.STCD =MSB.STCD where MSB.STTP_CODE='ENG' and MSB.DTIN=1 and MSB.IS_DELETED = 0 and MSB.BLDSTT_CCODE = 2 and MSB.RUN_STATE=4 )"); - sql.append(" where 1=1 "); - } - if (StrUtil.isNotBlank(filterResult.get(kendoGroupCode).getGroupSql())) { - sql.append(" and ").append(filterResult.get(kendoGroupCode).getGroupSql()); + sql.append("select AVQ_POINT_STATE as avqPointState, ENNM as ennm, RZ as rz, HBRVCD_NAME as hbrvcdName, QEC_INTERVAL as qecInterval, LTTD as lttd, BASE_ID as baseId, ANCHO_POINT_STATE as anchoPointState, HBRVCD as hbrvcd, MWR_RATE as mwrRate, SITESTEPSORT as siteStepSort, AVQ_INTERVAL as avqInterval, TTPWR as ttpwr, QI as qi, LGTD as lgtd, STTP_CODE as sttpCode, QEC_RATE as qecRate, BASESTEPSORT as baseStepSort, BASE_NAME as baseName, AVQ as avq, QO as qo, MWR_POINT_STATE as mwrPointState, QO_SUM as qoSum, orderIndex as orderindex, DTIN_ENV as dtinEnv, RVCDSTEPSORT as rvcdStepSort, sttp as sttp, AVQ_RATE as avqRate, DTMEL as dtmel, STCD as stcd, RSTCDSTEPSORT as rstcdStepSort, ADDVCD_NAME as addvcdName, QI_SUM as qiSum, MWR_INTERVAL as mwrInterval, NORMZ as normz"); + sql.append(" FROM "); + sql.append("(select MSB.STCD,MSB.STNM as ENNM,MSB.BASESTEPSORT,MSB.SITESTEPSORT,MSB.RVCDSTEPSORT,MSB.RSTCDSTEPSORT ,MSB.BASE_NAME,MSB.BASE_ID,MSB.ORDER_INDEX orderIndex,MSB.HBRVCD ,MSB.HBRVCD_NAME,MSB.ADDVCD_NAME ,MSB.STTP_CODE,'ENG' as sttp,MSB.LGTD,MSB.LTTD,MSB.DTMEL ,MSB.TTPWR,MSB.NORMZ,MSB.DTIN_ENV,MSB.AVQ ,SQR.QEC_RATE,SQR.MWR_RATE,SQR.AVQ_RATE,SHR.QI,SHR.QO,SHR.RZ,SHR.QO_SUM,SHR.QI_SUM,(CASE WHEN SQR.STCD IS NULL and qecR.stcd is null THEN 'QEC_STLL_5_EMPTY' WHEN SQR.STCD IS NULL and qecR.stcd is not null THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.STCD IS NOT NULL AND SQR.QR = -2 THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.STCD IS NOT NULL AND SQR.QR = -1 THEN 'QEC_STLL_5_EMPTY' WHEN SQR.QEC_RATE >= 95 THEN 'QEC_STLL_1_DY95' WHEN SQR.QEC_RATE >= 90 AND 95 > SQR.QEC_RATE THEN 'QEC_STLL_2_90AND95' WHEN SQR.QEC_RATE >= 80 AND 90 > SQR.QEC_RATE THEN 'QEC_STLL_3_80AND90' WHEN 80 > SQR.QEC_RATE THEN 'QEC_STLL_4_XY80' END) AS QEC_INTERVAL ,(CASE WHEN SQR.STCD IS NULL and mwrR.stcd is null THEN 'QEC_STLL_5_EMPTY' WHEN SQR.STCD IS NULL and mwrR.stcd is not null THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.STCD IS NOT NULL AND SQR.MQR = -2 THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.STCD IS NOT NULL AND SQR.MQR = -1 THEN 'QEC_STLL_5_EMPTY' WHEN SQR.MWR_RATE >= 95 THEN 'QEC_STLL_1_DY95' WHEN SQR.MWR_RATE >= 90 AND 95 > SQR.MWR_RATE THEN 'QEC_STLL_2_90AND95' WHEN SQR.MWR_RATE >= 80 AND 90 > SQR.MWR_RATE THEN 'QEC_STLL_3_80AND90' WHEN 80 > SQR.MWR_RATE THEN 'QEC_STLL_4_XY80' END) AS MWR_INTERVAL ,(CASE WHEN MSB.AVQ is not null AND SQR.AVQ_RATE IS NULL THEN 'QEC_STLL_5_EMPTY' WHEN MSB.AVQ is null THEN 'QEC_STLL_6_NOEQMN' WHEN SQR.AVQ_RATE >= 95 THEN 'QEC_STLL_1_DY95' WHEN SQR.AVQ_RATE >= 90 AND 95 > SQR.AVQ_RATE THEN 'QEC_STLL_2_90AND95' WHEN SQR.AVQ_RATE >= 80 AND 90 > SQR.AVQ_RATE THEN 'QEC_STLL_3_80AND90' WHEN 80 > SQR.AVQ_RATE THEN 'QEC_STLL_4_XY80' END) AS AVQ_INTERVAL ,(case when SQR.QEC_RATE is null and MSB.PRSC = 1 then 'eef_1_none' when SQR.QEC_RATE >=95 and MSB.PRSC = 1 then 'eef_1_1' when SQR.QEC_RATE >=90 and 95 > SQR.QEC_RATE and MSB.PRSC = 1 then 'eef_1_2' when SQR.QEC_RATE >=80 and 90 > SQR.QEC_RATE and MSB.PRSC = 1 then 'eef_1_3' when 80 > SQR.QEC_RATE and MSB.PRSC = 1 then 'eef_1_4' when SQR.QEC_RATE is null and MSB.PRSC in (2,3) then 'eef_2_none' when SQR.QEC_RATE >=95 and MSB.PRSC in (2,3) then 'eef_2_1' when SQR.QEC_RATE >=90 and 95 > SQR.QEC_RATE and MSB.PRSC in (2,3) then 'eef_2_2' when SQR.QEC_RATE >=80 and 90 > SQR.QEC_RATE and MSB.PRSC in (2,3) then 'eef_2_3' when 80 > SQR.QEC_RATE and MSB.PRSC in (2,3) then 'eef_2_4' end) as ANCHO_POINT_STATE ,(case when SQR.MWR_RATE is null and MSB.PRSC = 1 then 'eef_1_none' when SQR.MWR_RATE >=95 and MSB.PRSC = 1 then 'eef_1_1' when SQR.MWR_RATE >=90 and 95 > SQR.MWR_RATE and MSB.PRSC = 1 then 'eef_1_2' when SQR.MWR_RATE >=80 and 90 > SQR.MWR_RATE and MSB.PRSC = 1 then 'eef_1_3' when 80 > SQR.MWR_RATE and MSB.PRSC = 1 then 'eef_1_4' when SQR.MWR_RATE is null and MSB.PRSC in (2,3) then 'eef_2_none' when SQR.MWR_RATE >=95 and MSB.PRSC in (2,3) then 'eef_2_1' when SQR.MWR_RATE >=90 and 95 > SQR.MWR_RATE and MSB.PRSC in (2,3) then 'eef_2_2' when SQR.MWR_RATE >=80 and 90 > SQR.MWR_RATE and MSB.PRSC in (2,3) then 'eef_2_3' when 80 > SQR.MWR_RATE and MSB.PRSC in (2,3) then 'eef_2_4' end) as MWR_POINT_STATE ,(case when SQR.AVQ_RATE is null and MSB.PRSC = 1 then 'eef_1_none' when SQR.AVQ_RATE >=95 and MSB.PRSC = 1 then 'eef_1_1' when SQR.AVQ_RATE >=90 and 95 > SQR.AVQ_RATE and MSB.PRSC = 1 then 'eef_1_2' when SQR.AVQ_RATE >=80 and 90 > SQR.AVQ_RATE and MSB.PRSC = 1 then 'eef_1_3' when 80 > SQR.AVQ_RATE and MSB.PRSC = 1 then 'eef_1_4' when SQR.AVQ_RATE is null and MSB.PRSC in (2,3) then 'eef_2_none' when SQR.AVQ_RATE >=95 and MSB.PRSC in (2,3) then 'eef_2_1' when SQR.AVQ_RATE >=90 and 95 > SQR.AVQ_RATE and MSB.PRSC in (2,3) then 'eef_2_2' when SQR.AVQ_RATE >=80 and 90 > SQR.AVQ_RATE and MSB.PRSC in (2,3) then 'eef_2_3' when 80 > SQR.AVQ_RATE and MSB.PRSC in (2,3) then 'eef_2_4' end) as AVQ_POINT_STATE from V_MS_STBPRP_T MSB left join (select STCD ,(case when sum(case when SFDB =1 or SFDB =0 then 1 else 0 end) =0 then null else (sum(case when SFDB =1 then 1 else 0 end)/sum(case when SFDB =1 or SFDB =0 then 1 else 0 end)) end)*100 QEC_RATE ,(case when sum(case when MWR_SFDB =1 or MWR_SFDB =0 then 1 else 0 end) =0 then null else (sum(case when MWR_SFDB =1 then 1 else 0 end)/sum(case when MWR_SFDB =1 or MWR_SFDB =0 then 1 else 0 end)) end)*100 MWR_RATE ,(case when sum(case when AVQ_SFDB =1 or AVQ_SFDB =0 then 1 else 0 end) =0 then null else (sum(case when AVQ_SFDB =1 then 1 else 0 end)/sum(case when AVQ_SFDB =1 or AVQ_SFDB =0 then 1 else 0 end)) end)*100 AVQ_RATE ,case when count(1)=sum(case when SFDB =2 then 1 else 0 end) then -1 when count(1)=sum(case when SFDB =3 then 1 else 0 end) then -2 WHEN sum(CASE WHEN SFDB = 2 THEN 1 ELSE 0 END) >0 and count(1) = sum(CASE WHEN SFDB = 2 THEN 1 ELSE 0 END)+sum(CASE WHEN SFDB = 3 THEN 1 ELSE 0 END)+sum(CASE WHEN SFDB is null THEN 1 ELSE 0 END) then -1 WHEN sum(CASE WHEN SFDB = 2 THEN 1 ELSE 0 END) =0 and count(1) = sum(CASE WHEN SFDB = 2 THEN 1 ELSE 0 END)+sum(CASE WHEN SFDB = 3 THEN 1 ELSE 0 END)+sum(CASE WHEN SFDB is null THEN 1 ELSE 0 END) then -2 end qr ,case when count(1)=sum(case when MWR_SFDB =2 then 1 else 0 end) then -1 when count(1)=sum(case when MWR_SFDB =3 then 1 else 0 end) then -2 WHEN sum(CASE WHEN MWR_SFDB = 2 THEN 1 ELSE 0 END) >0 and count(1) = sum(CASE WHEN MWR_SFDB = 2 THEN 1 ELSE 0 END)+sum(CASE WHEN MWR_SFDB = 3 THEN 1 ELSE 0 END)+sum(CASE WHEN MWR_SFDB is null THEN 1 ELSE 0 END) then -1 WHEN sum(CASE WHEN MWR_SFDB = 2 THEN 1 ELSE 0 END) =0 and count(1) = sum(CASE WHEN MWR_SFDB = 2 THEN 1 ELSE 0 END)+sum(CASE WHEN MWR_SFDB = 3 THEN 1 ELSE 0 END)+sum(CASE WHEN MWR_SFDB is null THEN 1 ELSE 0 END) then -2 end mqr ,case when count(1)=sum(case when AVQ_SFDB =2 then 1 else 0 end) then -1 when count(1)=sum(case when AVQ_SFDB =3 then 1 else 0 end) then -2 end aqr from SD_QEC_R where 1=1 "); + Map params = QueryWrapperUtil.buildSqlConditionsByField(loadOptions); + if(StringUtil.isNotBlank(params.get("TM"))){ + sql.append(" and ").append(params.get("TM")); } - GroupingInfo[] group = dataSourceRequest.toDevRequest().getGroup(); - if (StrUtil.isNotBlank(groupBy)) - { - StringBuilder temp = new StringBuilder("select "); - List groupFields = new ArrayList<>(); - for (GroupingInfo item : group) - { - groupFields.add(item.getSelector()); - } - temp.append(StringUtil.join(groupFields)); - for (GroupingInfo item : group) - { - groupFields.add(item.getSelector()); - temp.append(",").append("count(*) as count_").append(item.getSelector()); - } - sql = temp.append(" from ( ").append(sql).append(" ) ").append(groupBy); - } - - if (StrUtil.isNotBlank(filterResult.get(kendoGroupCode).getOrderBySql())) { - sql.append(" ").append(filterResult.get(kendoGroupCode).getOrderBySql()); + sql.append(" group by STCD) SQR on MSB.STCD=SQR.STCD left join (SELECT stcd, avg(QI) QI, avg(QO) QO, avg(qec) qec,avg(RZ) RZ,SUM(QI) QI_SUM,SUM(QO) QO_SUM from SD_HYDROPW_R where 1=1 "); + if(StringUtil.isNotBlank(params.get("TM"))){ + sql.append(" and ").append(params.get("TM")); } + sql.append(" group by STCD) SHR on SHR.STCD = MSB.STCD left join (select STCD from MS_STBPRP_T where is_deleted=0 and sttp_code ='ENG' and stcd not in (select distinct A.STCD from MS_WARN_RULE_STBPRP_B a INNER JOIN MS_WARN_RULE_DETAIL_B b ON a.RULE_ID = b.RULE_ID and b.is_deleted=0 INNER JOIN MS_WARN_RULE_B c ON c.ID = b.RULE_ID where a.is_deleted=0 and b.is_deleted=0 and c.RULE_TYPE in('EQMN') and c.is_deleted=0)) qecR on qecR.STCD =MSB.STCD left join (select STCD from MS_STBPRP_T where is_deleted=0 and sttp_code ='ENG' and stcd not in (select distinct A.STCD from MS_WARN_RULE_STBPRP_B a INNER JOIN MS_WARN_RULE_DETAIL_B b ON a.RULE_ID = b.RULE_ID and b.is_deleted=0 INNER JOIN MS_WARN_RULE_B c ON c.ID = b.RULE_ID where a.is_deleted=0 and b.is_deleted=0 and c.RULE_TYPE in('EQMNMWR') and c.is_deleted=0)) mwrR on mwrR.STCD =MSB.STCD where MSB.STTP_CODE='ENG' and MSB.DTIN=1 and MSB.IS_DELETED = 0 and MSB.BLDSTT_CCODE = 2 and MSB.RUN_STATE=4 )"); + sql.append(" where 1=1 "); +// sql.append(" and select AVQ_POINT_STATE as avqPointState, ENNM as ennm, RZ as rz, HBRVCD_NAME as hbrvcdName, QEC_INTERVAL as qecInterval, LTTD as lttd, BASE_ID as baseId, ANCHO_POINT_STATE as anchoPointState, HBRVCD as hbrvcd, MWR_RATE as mwrRate, SITESTEPSORT as siteStepSort, AVQ_INTERVAL as avqInterval, TTPWR as ttpwr, QI as qi, LGTD as lgtd, STTP_CODE as sttpCode, QEC_RATE as qecRate, BASESTEPSORT as baseStepSort, BASE_NAME as baseName, AVQ as avq, QO as qo, MWR_POINT_STATE as mwrPointState, QO_SUM as qoSum, orderIndex as orderindex, DTIN_ENV as dtinEnv, RVCDSTEPSORT as rvcdStepSort, sttp as sttp, AVQ_RATE as avqRate, DTMEL as dtmel, STCD as stcd, RSTCDSTEPSORT as rstcdStepSort, ADDVCD_NAME as addvcdName, QI_SUM as qiSum, MWR_INTERVAL as mwrInterval, NORMZ as normz"); //非分组,求统计 List groupFields = new ArrayList<>(); if (CollUtil.isNotEmpty(dataSourceRequest.getAggregate()) && "average".equals(dataSourceRequest.getAggregate().get(0).getAggregate())){ @@ -99,65 +80,23 @@ public class EngEqIntervalServiceImpl implements EngEqIntervalService { temp.append(StringUtil.join(groupFields)); sql = temp.append(" from ( ").append(sql).append(" ) "); } - - //组装map参数 - Map map = new HashMap<>(); - for (String key : filterResult.keySet()) { - map.putAll(filterResult.get(key).getParamMap()); + if (CollUtil.isNotEmpty(dataSourceRequest.getAggregate()) && "average".equals(dataSourceRequest.getAggregate().get(0).getAggregate())){ + List> list = dynamicSQLMapper.pageAllList(page, sql.toString(), params); + dataSourceResult.setTotal(0); + for (Map objectMap : list) + { + for (DataSourceRequest.AggregateDescriptor item : dataSourceRequest.getAggregate()) + { + objectMap.put(item.getField(),objectMap.get(item.getField().toUpperCase())); + } + } + dataSourceResult.setData(list); + return dataSourceResult; } - -// if (StringUtil.isNotBlank(groupBy)){ -// List> list = microservicDynamicSQLMapper.pageAllList(page, sql.toString(), map); -// //是否扁平化分组 -// if (null != dataSourceRequest.getGroupResultFlat() && dataSourceRequest.getGroupResultFlat()) { -// dataSourceResult.setData((new GroupHelper()).faltGroup(list, Arrays.asList(group))); -// } else { -// dataSourceResult.setData((new GroupHelper()).group(list, Arrays.asList(group))); -// } -// dataSourceResult.setTotal(0); -// return dataSourceResult; -// } -// if (CollUtil.isNotEmpty(dataSourceRequest.getAggregate()) && "average".equals(dataSourceRequest.getAggregate().get(0).getAggregate())){ -// List> list = microservicDynamicSQLMapper.pageAllList(page, sql.toString(), map); -// dataSourceResult.setTotal(0); -// for (Map objectMap : list) -// { -// for (DataSourceRequest.AggregateDescriptor item : dataSourceRequest.getAggregate()) -// { -// objectMap.put(item.getField(),objectMap.get(item.getField().toUpperCase())); -// } -// } -// dataSourceResult.setData(list); -// return dataSourceResult; -// } -// List msEngEqs = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), map,MsEngEq.class); -// //查询最大削峰量 -// Map xfamountMaxMap = engfloodRService.getXfamountMax(dataSourceRequest); -// for (MsEngEq msEngEq : msEngEqs) -// { -// //处理最大削峰量 -// if (null != xfamountMaxMap.get(msEngEq.getStcd())) -// { -// msEngEq.setXfamountMax(xfamountMaxMap.get(msEngEq.getStcd())); -// } -// //处理枯水期补水总量 -// msEngEq.setFillWater(NumberUtil.sub(msEngEq.getQoSum(), msEngEq.getQiSum())); -// //处理最新一条数据 -// //查询最新一条数据的缓存 -// LastTmEngEqDataVo lastTmEngEqDataVo = redisHelper.fromJson(redisHelper.strGet("eqAnchorPointLastDate:"+msEngEq.getStcd()),LastTmEngEqDataVo.class); -// if (ObjectUtil.isNotEmpty(lastTmEngEqDataVo)){ -// lastTmEngEqDataVo.setStnm(msEngEq.getEnnm()); -// lastTmEngEqDataVo.setTtpwr(msEngEq.getTtpwr()); -// msEngEq.setLastTmEngEqDataVo(lastTmEngEqDataVo); -// } -// msEngEq.setSttpMap(msEngEq.getSttp()); -// msEngEq.setTitleName(msEngEq.getEnnm()); -// //处理eqtp -// msEngEq.setEqtp("QEC"); -// } -// SiteAvoidanceUtils.calcSiteMapLev(msEngEqs,null,MsEngEq::getStcd,MsEngEq::getLgtd,MsEngEq::getLttd,MsEngEq::getAnchoPointState,MsEngEq::setDistance); -// dataSourceResult.setData(msEngEqs); -// dataSourceResult.setTotal(ObjectUtil.isNotEmpty(page) ? page.getTotal() : (long) msEngEqs.size()); + List> mapList = dynamicSQLMapper.pageAllList(page, sql.toString(), params); +// List msEngEqs = convertToMsEngEqList(mapList); + dataSourceResult.setData(mapList); + dataSourceResult.setTotal(ObjectUtil.isNotEmpty(page) ? page.getTotal() : (long) mapList.size()); return dataSourceResult; } @@ -172,12 +111,69 @@ public class EngEqIntervalServiceImpl implements EngEqIntervalService { } @Override - public Map getQgcQecStaticData(Object dataList, String type) { - // 模拟统计数据,实际应该根据业务需求实现 + public Map getQgcQecStaticData(Object data, String type) { + List> newDataList = (List>)data; + + //生态达标率大于95%的电站数量(环保部) + Long qecCnt = newDataList.stream().filter(it->Objects.equals(it.get("QECINTERVAL"), QecIntervalEnum.QEC_STLL_1_DY95.getCode())).count(); + Long qecTcnt = newDataList.stream().filter(it->!Objects.equals(it.get("QECINTERVAL"), QecIntervalEnum.QEC_STLL_6_NOEQMN.getCode())).count(); + + //生态达标率大于95%的电站数量(水利部) + Long mwrCnt = newDataList.stream().filter(it->Objects.equals(it.get("MWRINTERVAL"),QecIntervalEnum.QEC_STLL_1_DY95.getCode())).count(); + Long mwrTcnt = newDataList.stream().filter(it->!Objects.equals(it.get("MWRINTERVAL"), QecIntervalEnum.QEC_STLL_6_NOEQMN.getCode())).count(); + + //生态达标率大于95%的电站数量(多年平均) + Long avqCnt = newDataList.stream().filter(it->Objects.equals(it.get("AVQINTERVAL"),QecIntervalEnum.QEC_STLL_1_DY95.getCode())).count(); + Long avqTcnt = newDataList.stream().filter(it->!Objects.equals(it.get("AVQINTERVAL"), QecIntervalEnum.QEC_STLL_6_NOEQMN.getCode())).count(); + + //无生态流量要求的电站数据 + Long noCnt = newDataList.stream().filter(it-> + Objects.equals(it.get("QECINTERVAL"),QecIntervalEnum.QEC_STLL_6_NOEQMN.getCode()) + && + Objects.equals(it.get("MWRINTERVAL"),QecIntervalEnum.QEC_STLL_6_NOEQMN.getCode()) + && + Objects.equals(it.get("AVQINTERVAL"),QecIntervalEnum.QEC_STLL_6_NOEQMN.getCode()) + ).count(); + Map result = new HashMap<>(); - result.put("totalCount", 0); - result.put("qualifiedCount", 0); - result.put("qualifiedRate", 0.0); + result.put("engCnt", newDataList.size()); + + List> qgcQecVos = new ArrayList<>(); + + Map qvo = new HashMap<>(); + qvo.put("qecTCnt", Math.toIntExact(qecTcnt)); + qvo.put("qecCnt", Math.toIntExact(qecCnt)); + qvo.put("code", QecIntervalEnum.QEC_STLL_1_DY95.getCode()); + qvo.put("desc", ShowEnum.Q.getDesc()+"_"+QecIntervalEnum.QEC_STLL_1_DY95.getDesc()); + qvo.put("type", ShowEnum.Q.getCode()); + qgcQecVos.add(qvo); + + Map mwrVo = new HashMap<>(); + mwrVo.put("qecTCnt", Math.toIntExact(mwrTcnt)); + mwrVo.put("qecCnt", Math.toIntExact(mwrCnt)); + mwrVo.put("code", QecIntervalEnum.QEC_STLL_1_DY95.getCode()); + mwrVo.put("desc", ShowEnum.M.getDesc()+"_"+QecIntervalEnum.QEC_STLL_1_DY95.getDesc()); + mwrVo.put("type", ShowEnum.M.getCode()); + qgcQecVos.add(mwrVo); + + Map avqVo = new HashMap<>(); + avqVo.put("qecTCnt", Math.toIntExact(avqTcnt)); + avqVo.put("qecCnt", Math.toIntExact(avqCnt)); + avqVo.put("code", QecIntervalEnum.QEC_STLL_1_DY95.getCode()); + avqVo.put("desc", ShowEnum.A.getDesc()+"_"+QecIntervalEnum.QEC_STLL_1_DY95.getDesc()); + avqVo.put("type", ShowEnum.A.getCode()); + qgcQecVos.add(avqVo); + + Map noVo = new HashMap<>(); + noVo.put("qecTCnt", Math.toIntExact(noCnt)); + noVo.put("qecCnt", Math.toIntExact(noCnt)); + noVo.put("code", QecIntervalEnum.QEC_STLL_6_NOEQMN.getCode()); + noVo.put("desc", QecIntervalEnum.QEC_STLL_6_NOEQMN.getDesc()); + noVo.put("type", ShowEnum.N.getCode()); + qgcQecVos.add(noVo); + + result.put("list", qgcQecVos); + return result; } } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/utils/QueryWrapperUtil.java b/backend/src/main/java/com/yfd/platform/utils/QueryWrapperUtil.java index 7d17396..ca1142c 100644 --- a/backend/src/main/java/com/yfd/platform/utils/QueryWrapperUtil.java +++ b/backend/src/main/java/com/yfd/platform/utils/QueryWrapperUtil.java @@ -1,5 +1,7 @@ package com.yfd.platform.utils; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo; @@ -7,16 +9,11 @@ import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.zny.dec.framework.kendo.entity.dto.devextreme.DataSourceLoadOptionsBase; + import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -523,6 +520,401 @@ public class QueryWrapperUtil { return result; } + /** + * 格式化日期时间值(适配Oracle和达梦数据库) + * + * @param value 日期字符串 + * @return 格式化后的SQL日期值 + */ + private static String formatDateTimeValue(String value) { + if (value == null || value.isEmpty()) { + return "NULL"; + } + + // 去除首尾空格 + value = value.trim(); + + // 判断是否包含时间部分 + if (value.length() == 10) { + // 只有日期部分: 2026-03-08 + // Oracle/达梦格式: TO_DATE('2026-03-08', 'YYYY-MM-DD') + return "TO_DATE('" + value + "', 'YYYY-MM-DD')"; + } else if (value.length() == 19) { + // 包含时间部分: 2026-03-08 00:00:00 + // Oracle/达梦格式: TO_DATE('2026-03-08 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + return "TO_DATE('" + value + "', 'YYYY-MM-DD HH24:MI:SS')"; + } else if (value.length() > 19) { + // 包含毫秒: 2026-03-08 00:00:00.000 + // Oracle/达梦格式: TO_TIMESTAMP('2026-03-08 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FF3') + return "TO_TIMESTAMP('" + value + "', 'YYYY-MM-DD HH24:MI:SS.FF3')"; + } else { + // 其他格式,尝试直接使用TO_DATE + return "TO_DATE('" + value + "', 'YYYY-MM-DD HH24:MI:SS')"; + } + } + + /** + * 构建单个字段的SQL条件(优化版,支持Oracle/达梦日期函数) + * + * @param field 字段名 + * @param operator 操作符 + * @param value 值 + * @param valueType 值类型 + * @return SQL条件字符串(包含字段名、操作符和值) + */ + private static String buildSingleCondition(String field, String operator, String value, String valueType) { + // 转换操作符 + String sqlOperator = convertOperator(operator); + + // 根据值类型格式化值 + String formattedValue; + + // 特殊处理日期类型的BETWEEN操作 + if (("date".equalsIgnoreCase(valueType) || "datetime".equalsIgnoreCase(valueType) || "timestamp".equalsIgnoreCase(valueType)) + && "BETWEEN".equals(sqlOperator)) { + formattedValue = formatBetweenDateValue(value, valueType); + } else { + formattedValue = formatValue(value, valueType, sqlOperator); + } + + // 构建SQL条件:字段 操作符 值 + return field + " " + sqlOperator + " " + formattedValue; + } + + /** + * 格式化BETWEEN操作符的日期值(Oracle/达梦优化) + * + * @param value 原始值(两个日期用逗号分隔) + * @param valueType 值类型 + * @return 格式化后的BETWEEN值 + */ + private static String formatBetweenDateValue(String value, String valueType) { + String[] values = value.split(","); + if (values.length != 2) { + return formatValue(value, valueType, "BETWEEN"); + } + + String startValue = values[0].trim(); + String endValue = values[1].trim(); + + String formattedStart = formatDateTimeValue(startValue); + String formattedEnd = formatDateTimeValue(endValue); + + return formattedStart + " AND " + formattedEnd; + } + + /** + * 从DataSourceLoadOptionsBase的filter中提取条件,按字段分组返回SQL条件Map + * + * @param loadOptions DataSourceLoadOptionsBase对象 + * @return Map<字段名, SQL条件字符串>,例如: {"dtin": "dtin = '1'", "tm": "(tm >= TO_DATE('2026-03-08 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND tm <= TO_DATE('2026-03-09 00:00:00', 'YYYY-MM-DD HH24:MI:SS'))"} + */ + public static Map buildSqlConditionsByField(DataSourceLoadOptionsBase loadOptions) { + Map fieldConditions = new LinkedHashMap<>(); + + if (loadOptions == null || loadOptions.getFilter() == null) { + return fieldConditions; + } + + Object filter = loadOptions.getFilter(); + + try { + // 将filter转换为JSONArray格式处理 + JSONArray filterArray = JSONUtil.parseArray(JSONUtil.toJsonStr(filter)); + parseFilterToArray(filterArray, fieldConditions); + + // 对所有字段的条件添加括号包裹,确保AND查询时的逻辑优先级正确 + fieldConditions.replaceAll((key, value) -> "(" + value + ")"); + } catch (Exception e) { + // 如果解析失败,记录日志但不影响主流程 + e.printStackTrace(); + } + + return fieldConditions; + } + /** + * 递归解析filter数组,将条件按字段分组存入Map + * + * @param filterArray filter数组 + * @param fieldConditions 存储字段条件的Map + */ + private static void parseFilterToArray(JSONArray filterArray, Map fieldConditions) { + if (filterArray == null || filterArray.isEmpty()) { + return; + } + + int i = 0; + + while (i < filterArray.size()) { + Object item = filterArray.get(i); + + // 跳过逻辑运算符 [ "and" ] 或 [ "or" ] + if (item instanceof JSONArray) { + JSONArray subArray = (JSONArray) item; + if (isLogicalOperator(subArray)) { + i++; + continue; + } + + // 判断是否是条件数组 [ "field", "operator", "value", "type" ] + if (isConditionArray(subArray)) { + String field = subArray.get(0).toString(); + String operator = subArray.get(1).toString(); + String value = subArray.get(2).toString(); + String valueType = subArray.size() > 3 ? subArray.get(3).toString() : "string"; + + // 生成SQL条件片段 + String sqlCondition = buildSingleCondition(field, operator, value, valueType); + + // 统一转换为大写作为key + String fieldKey = field.toUpperCase(); + + // 如果该字段已存在条件,则用 AND 连接 + if (fieldConditions.containsKey(fieldKey)) { + fieldConditions.put(fieldKey, fieldConditions.get(fieldKey) + " AND " + sqlCondition); + } else { + fieldConditions.put(fieldKey, sqlCondition); + } + i++; + continue; + } + } + + i++; + } + } + + /** + * 判断数组是否是逻辑运算符 + * + * @param array 待判断的数组 + * @return true表示是逻辑运算符数组 + */ + private static boolean isLogicalOperator(JSONArray array) { + if (array.size() == 1) { + String value = array.get(0).toString().toLowerCase(); + return "and".equals(value) || "or".equals(value); + } + return false; + } + + /** + * 判断数组是否是条件数组 + * 条件数组格式: [ "field", "operator", "value", "type" ] + * + * @param array 待判断的数组 + * @return true表示是条件数组 + */ + private static boolean isConditionArray(JSONArray array) { + return array.size() >= 3 && array.size() <= 4; + } + + /** + * 转换操作符为标准SQL操作符 + * + * @param operator 原始操作符 + * @return SQL操作符 + */ + private static String convertOperator(String operator) { + if (operator == null) { + return "="; + } + + switch (operator.toLowerCase()) { + case "=": + return "="; + case "<>": + case "!=": + return "<>"; + case ">": + return ">"; + case ">=": + return ">="; + case "<": + return "<"; + case "<=": + return "<="; + case "contains": + return "LIKE"; + case "startswith": + return "LIKE"; + case "endswith": + return "LIKE"; + case "in": + return "IN"; + case "not in": + return "NOT IN"; + case "between": + return "BETWEEN"; + default: + return operator; + } + } + + /** + * 根据值类型格式化SQL值 + * + * @param value 原始值 + * @param valueType 值类型 (string, number, date, boolean等) + * @param operator SQL操作符 + * @return 格式化后的SQL值 + */ + private static String formatValue(String value, String valueType, String operator) { + if (value == null || "null".equalsIgnoreCase(value)) { + return "NULL"; + } + + // 处理IN操作符 + if ("IN".equals(operator) || "NOT IN".equals(operator)) { + return formatInValue(value, valueType); + } + + // 处理BETWEEN操作符(非日期类型) + if ("BETWEEN".equals(operator) && !isDateType(valueType)) { + return formatBetweenValue(value, valueType); + } + + // 处理LIKE操作符 + if ("LIKE".equals(operator)) { + return formatLikeValue(value, valueType); + } + + // 根据类型格式化 + if (isDateType(valueType)) { + return formatDateTimeValue(value); + } + + switch (valueType.toLowerCase()) { + case "string": + return "'" + escapeSqlString(value) + "'"; + case "number": + case "int": + case "integer": + case "double": + case "float": + case "decimal": + return value; + case "boolean": + return Boolean.parseBoolean(value) ? "1" : "0"; + default: + return "'" + escapeSqlString(value) + "'"; + } + } + + /** + * 判断是否为日期类型 + * + * @param valueType 值类型 + * @return true表示是日期类型 + */ + private static boolean isDateType(String valueType) { + if (valueType == null) { + return false; + } + String type = valueType.toLowerCase(); + return "date".equals(type) || "datetime".equals(type) || "timestamp".equals(type); + } + + /** + * 格式化IN操作符的值 + * + * @param value 原始值 + * @param valueType 值类型 + * @return 格式化后的IN值列表 + */ + private static String formatInValue(String value, String valueType) { + // 假设值是逗号分隔的 + String[] values = value.split(","); + StringBuilder result = new StringBuilder("("); + + for (int i = 0; i < values.length; i++) { + if (i > 0) { + result.append(", "); + } + String v = values[i].trim(); + if (isDateType(valueType)) { + result.append(formatDateTimeValue(v)); + } else if ("string".equalsIgnoreCase(valueType)) { + result.append("'").append(escapeSqlString(v)).append("'"); + } else { + result.append(v); + } + } + + result.append(")"); + return result.toString(); + } + + /** + * 格式化BETWEEN操作符的值(非日期类型) + * + * @param value 原始值(两个值用逗号分隔) + * @param valueType 值类型 + * @return 格式化后的BETWEEN值 + */ + private static String formatBetweenValue(String value, String valueType) { + String[] values = value.split(","); + if (values.length != 2) { + return value; + } + + String startValue = values[0].trim(); + String endValue = values[1].trim(); + + String formattedStart = formatSingleValue(startValue, valueType); + String formattedEnd = formatSingleValue(endValue, valueType); + + return formattedStart + " AND " + formattedEnd; + } + + /** + * 格式化LIKE操作符的值 + * + * @param value 原始值 + * @param valueType 值类型 + * @return 格式化后的LIKE值 + */ + private static String formatLikeValue(String value, String valueType) { + // LIKE操作通常需要添加通配符 + if (!value.contains("%")) { + value = "%" + value + "%"; + } + return "'" + escapeSqlString(value) + "'"; + } + + /** + * 格式化单个值 + * + * @param value 原始值 + * @param valueType 值类型 + * @return 格式化后的值 + */ + private static String formatSingleValue(String value, String valueType) { + if (isDateType(valueType)) { + return formatDateTimeValue(value); + } else if ("string".equalsIgnoreCase(valueType)) { + return "'" + escapeSqlString(value) + "'"; + } else { + return value; + } + } + + /** + * 转义SQL字符串中的特殊字符 + * + * @param value 原始字符串 + * @return 转义后的字符串 + */ + private static String escapeSqlString(String value) { + if (value == null) { + return ""; + } + // 转义单引号 + return value.replace("'", "''"); + } + + + /** * 通用请求 DTO(用于承载分页与分组信息)。 *

diff --git a/backend/src/main/resources/application-devtw.yml b/backend/src/main/resources/application-devtw.yml index f59a149..be7a29c 100644 --- a/backend/src/main/resources/application-devtw.yml +++ b/backend/src/main/resources/application-devtw.yml @@ -39,6 +39,23 @@ logging: swagger-ui: enabled: true +mybatis-plus: + mapper-locations: classpath*:**/mapper/*Mapper.xml,classpath*:**/mapping/*Mapper.xml + global-config: + banner: false + db-config: + id-type: ASSIGN_ID + insert-strategy: not_null + update-strategy: not_null + select-strategy: not_empty + table-underline: true + logic-delete-value: 1 + logic-not-delete-value: 0 + logic-delete-field: isDeleted + configuration: + map-underscore-to-camel-case: true + cache-enabled: false + log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl # 登录相关配置 login: