From 021d2b2e150edeac4238a0671c6557998a6f02e7 Mon Sep 17 00:00:00 2001 From: tangwei Date: Fri, 7 Aug 2026 18:05:13 +0800 Subject: [PATCH 01/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yfd/platform/config/SecurityConfig.java | 4 +- .../controller/SdEngMonitorController.java | 9 + .../qgc_base/domain/vo/EngVmsstbprptVo.java | 40 +++ .../qgc_base/domain/vo/RstcdTreeInfoVo.java | 33 +++ .../qgc_base/domain/vo/StcdItemVo.java | 51 ++++ .../qgc_base/mapper/VMsStbprpTMapper.java | 33 +++ .../qgc_base/service/ISdEngInfoBHService.java | 7 + .../service/impl/SdEngInfoBHServiceImpl.java | 230 ++++++++++++------ 8 files changed, 329 insertions(+), 78 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/RstcdTreeInfoVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/StcdItemVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/mapper/VMsStbprpTMapper.java diff --git a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java index cc93de85..10903a7e 100644 --- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -70,7 +70,7 @@ public class SecurityConfig { .requestMatchers("/base/operationLog/**").permitAll() // .requestMatchers("/system/**").permitAll() .requestMatchers("/qgcExport/**").permitAll() -// .requestMatchers("/eng/**").permitAll() + .requestMatchers("/eng/**").permitAll() .requestMatchers("/eq/**").permitAll() // .requestMatchers("/env/**").permitAll() // .requestMatchers("/warn/**").permitAll() @@ -78,7 +78,7 @@ public class SecurityConfig { // .requestMatchers("/overview/**").permitAll() // .requestMatchers("/wt/**").permitAll() // .requestMatchers("/fb/**").permitAll() -// .requestMatchers("/base/**").permitAll() + .requestMatchers("/base/**").permitAll() // .requestMatchers("/zq/**").permitAll() // .requestMatchers("/wq/**").permitAll() // .requestMatchers("/wte/**").permitAll() diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java index 0101357d..501965bb 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java @@ -1,8 +1,10 @@ package com.yfd.platform.qgc_base.controller; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_base.domain.vo.EngRsvrcscdBVo; +import com.yfd.platform.qgc_base.domain.vo.RstcdTreeInfoVo; import com.yfd.platform.qgc_base.service.ISdEngInfoBHService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -75,4 +77,11 @@ public class SdEngMonitorController { public ResponseResult getQgcRvcdList(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(engInfoBHService.getQgcRvcdList(dataSourceRequest)); } + + @PostMapping("/engTree/GetKendoList") + @Operation(summary = "树形结构数据信息 电站沿程排序") + public ResponseResult getEngTreeKendoList(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = engInfoBHService.getEngTreeByAlong(dataSourceRequest); + return ResponseResult.successData(result); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index efd19e93..477912d4 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java @@ -124,4 +124,44 @@ public class EngVmsstbprptVo implements Serializable { private Integer rvcdStepSort; private Integer rstcdStepSort; private Integer siteStepSort; + + + + /** 上游码头位置 */ + private String updcklc; + /** 上游码头型式 */ + private String updcktp; + /** 下游码头位置 */ + private String downdcklc; + /** 下游码头型式 */ + private String downdcktp; + /*** 过鱼时间*/ + private String psfishtm; + /*** 过鱼对象*/ + private String psfishtyp; + /*** 断面尺寸(长*宽*高)*/ + private String syjsz; + /** 运鱼设施方式 */ + private String jyyyyfs; + /** 过鱼规模 */ + private Long psfishcnt; + /** 集鱼槽进口高程 */ + private String syjhg; + /** 集鱼槽数量 */ + private Integer syjcnt; + /** 集鱼槽流量 */ + private String syjq; + /** 集鱼槽水深 */ + private String syjwdp; + /** 运行时间 */ + private String runtm; + /** 集诱鱼方式 */ + private String syjjyyfs; + /** 投资:单位:亿元 */ + private BigDecimal inv; + /** 数据监测频次 */ + private Integer dtfrqcy; + /** 主要过鱼月份(多个月份用,隔开),主要过鱼月份(多个月份用,隔开),主要过鱼月份(多个月份用,隔开),主要过鱼月份(多个月份用,隔开) */ + private String fpssmnmon; + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/RstcdTreeInfoVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/RstcdTreeInfoVo.java new file mode 100644 index 00000000..cf375025 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/RstcdTreeInfoVo.java @@ -0,0 +1,33 @@ +package com.yfd.platform.qgc_base.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * 沿程树形节点:按电站(RSTCD)分组 + */ +@Data +@Schema(description = "沿程树形电站节点") +public class RstcdTreeInfoVo { + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "沿程排序") + private Integer sort; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "下属测站列表") + private List items = new ArrayList<>(); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/StcdItemVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/StcdItemVo.java new file mode 100644 index 00000000..9e9f4249 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/StcdItemVo.java @@ -0,0 +1,51 @@ +package com.yfd.platform.qgc_base.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 测站条目 — V_MS_STBPRP_T 视图中提取的测站字段 + */ +@Data +@Schema(description = "沿程树形测站条目") +public class StcdItemVo { + + @Schema(description = "测站编码") + private String stcd; + + @Schema(description = "测站名称") + private String stnm; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "站类名称") + private String sttpName; + + @Schema(description = "监测方式名称") + private String mwayName; + + @Schema(description = "监测方式:1=人工 2=自动") + private Integer mway; + + @Schema(description = "经度") + private String lgtd; + + @Schema(description = "纬度") + private String lttd; + + @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; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/VMsStbprpTMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/VMsStbprpTMapper.java new file mode 100644 index 00000000..e0ccff9a --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/VMsStbprpTMapper.java @@ -0,0 +1,33 @@ +package com.yfd.platform.qgc_base.mapper; + +import com.yfd.platform.qgc_base.domain.vo.StcdItemVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * V_MS_STBPRP_T 视图 Mapper + */ +@Mapper +public interface VMsStbprpTMapper { + + /** + * 查询视图中的测站沿程数据,按站类编码过滤 + */ + @Select("") + List selectBySttpCodes(@Param("sttpCodes") List sttpCodes); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java index 88af134a..d0247d7b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java @@ -17,6 +17,8 @@ import com.yfd.platform.qgc_base.domain.vo.EngPointVo; import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo; import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; +import com.yfd.platform.qgc_base.domain.vo.RstcdTreeInfoVo; + import java.util.List; import java.util.Map; import java.util.Set; @@ -101,4 +103,9 @@ public interface ISdEngInfoBHService extends IService { DataSourceResult getRsvrcscdBRvcdList(DataSourceRequest dataSourceRequest); DataSourceResult getQgcRvcdList(DataSourceRequest dataSourceRequest); + + /** + * 树形结构数据信息 电站沿程排序 + */ + DataSourceResult getEngTreeByAlong(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 03472886..5cf5e126 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -23,23 +23,11 @@ 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_base.domain.vo.*; import com.yfd.platform.qgc_data.domain.SysUserDataScope; import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper; import com.yfd.platform.qgc_base.domain.SdEngInfoBH; -import com.yfd.platform.qgc_base.domain.vo.DataScopeApplyResult; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; -import com.yfd.platform.qgc_base.domain.vo.EngAlarmPointVo; -import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo; -import com.yfd.platform.qgc_base.domain.vo.EngEiaapprovalVo; -import com.yfd.platform.qgc_base.domain.vo.EngOperatVo; -import com.yfd.platform.qgc_base.domain.vo.EngQgcRvcdVo; -import com.yfd.platform.qgc_base.domain.vo.EngRsvrcscdBVo; -import com.yfd.platform.qgc_base.domain.vo.EngRsvrcscdRvcdVo; -import com.yfd.platform.qgc_base.domain.vo.EngPointVo; -import com.yfd.platform.qgc_base.domain.vo.EngStbprpDataVo; -import com.yfd.platform.qgc_base.domain.vo.EngStBaseInfoVo; -import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo; -import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; import com.yfd.platform.qgc_base.service.IDataScopeFilterService; import com.yfd.platform.qgc_base.service.IMsOperationLogService; @@ -149,6 +137,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl queryPageList(Page page, String ennm, String rvcd, String baseId, String hycd) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -1002,75 +993,25 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl checkResult = microservicDynamicSQLMapper.getOneBySql(checkSql, Collections.singletonMap("stcd", stcd)); + String sttpCode = checkResult != null ? (String) checkResult.get("STTP_CODE") : null; + + if (!"ENG".equals(sttpCode)) { + // 非 ENG:直接从 V_MS_STBPRP_T 视图返回 + String viewSql = "SELECT * FROM V_MS_STBPRP_T WHERE STCD = #{map.stcd} AND IS_DELETED = 0"; + return microservicDynamicSQLMapper.getOneBySqlWithResultType(viewSql, Collections.singletonMap("stcd", stcd), EngVmsstbprptVo.class); + } + + // ENG 走原有逻辑 StringBuilder sql = new StringBuilder(); sql.append("SELECT *") - .append(" FROM (") .append(buildVmsstbprptViewSqlNew()) .append(") t WHERE 1 = 1 AND t.STCD = #{map.stcd}"); - EngVmsstbprptVo vo = microservicDynamicSQLMapper.getOneBySqlWithResultType(sql.toString(), Collections.singletonMap("stcd", stcd), EngVmsstbprptVo.class); -// SdEngInfoBH entity = this.getById(stcd); -// if (entity == null) { -// return null; -// } -// -// EngBaseInfoVo vo = new EngBaseInfoVo(); -// BeanUtil.copyProperties(entity, vo); -// vo.setId(entity.getStcd()); -// vo.setStnm(entity.getEnnm()); -// -// String sql = "SELECT " + -// "sttp.ID AS sttp, " + -// "sttp.STTP_CODE AS sttpCode, " + -// "sttp.STTP_NAME AS sttpName, " + -// "sttp.FULL_PATH AS sttpFullPath, " + -// "sttp.TREE_LEVEL AS sttpTreeLevel, " + -// "hb.BASENAME AS baseName, " + -// "hbrv.HBRVNM AS hbrvcdName, " + -// "rv.RVNM AS rvcdName, " + -// "rv.PATH AS rvcdFullPath, " + -// "addv.ADDVNM AS addvcdName, " + -// "addv.PATH AS addvcdFullPath, " + -// "country.COUNTRY_NAME AS countryName, " + -// "hy.HYNM AS hynm, " + -// "topHy.HYNM AS topHynm " + -// "FROM SD_ENGINFO_B_H eng " + -// "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = 'ENG' " + -// " AND NVL(sttp.IS_DELETED, 0) = 0 " + -// " AND NVL(sttp.ENABLE, 1) = 1 " + -// "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID " + -// "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD AND hbrv.BASEID = eng.BASE_ID " + -// " AND NVL(hbrv.ENABLED, 1) = 1 " + -// "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + -// "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + -// "LEFT JOIN SD_COUNTRY_B country ON country.COUNTRY_ID = eng.COUNTRY AND NVL(country.ENABLED, 1) = 1 " + -// "LEFT JOIN SD_HYCD_DIC hy ON hy.HYCD = eng.HYCD " + -// "LEFT JOIN SD_HYCD_DIC topHy ON topHy.HYCD = eng.TOP_HYCD " + -// "WHERE eng.STCD = #{map.stcd}"; -// -// EngBaseInfoVo extra = microservicDynamicSQLMapper.getOneBySqlWithResultType( -// sql, java.util.Collections.singletonMap("stcd", stcd), EngBaseInfoVo.class); -// if (extra != null) { -// BeanUtil.copyProperties(extra, vo, CopyOptions.create().setIgnoreNullValue(true)); -// } -// -// vo.setSttpCode("ENG"); -// vo.setBlprdCode(entity.getBlprd() == null ? null : String.valueOf(entity.getBlprd())); -// vo.setBlprdCcode(entity.getBlprd() == null ? null : String.valueOf(entity.getBlprd())); -// vo.setBlprdName(resolveBlprdName(entity.getBlprd())); -// vo.setBlprdCname(vo.getBlprdName()); -// vo.setDtinName(resolveDtinName(entity.getDtin())); -// vo.setBldsttName(resolveBldsttName(entity.getBldstt())); -// vo.setBldsttCcode(entity.getBldsttCode() == null ? null : String.valueOf(entity.getBldsttCode())); -// vo.setBldsttCcodeName(resolveBldsttCodeName(entity.getBldsttCode())); -// vo.setDvtpName(resolveDvtpName(entity.getDvtp())); -// vo.setRgcpName(resolveRgcpName(entity.getRgcp())); -// vo.setEngtpName(resolveEngtpName(entity.getEngtp())); -// vo.setPrscName(resolvePrscName(entity.getPrsc())); -// vo.setScrscName(resolveScrscName(entity.getScrsc())); -// vo.setPrgrName(resolvePrgrName(entity.getPrgr())); - return vo; + return microservicDynamicSQLMapper.getOneBySqlWithResultType(sql.toString(), Collections.singletonMap("stcd", stcd), EngVmsstbprptVo.class); } @@ -4128,4 +4069,141 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl getEngTreeByAlong( + DataSourceRequest dataSourceRequest) { + DataSourceResult result = new DataSourceResult<>(); + result.setAggregates(new HashMap<>()); + + if (dataSourceRequest == null) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } + + // 从请求 filter 中提取 STTP 过滤条件,用于限定站类范围 + List sttpCodes = extractSttpCodesFromRequest(dataSourceRequest); + + // 查询 V_MS_STBPRP_T 视图 + List allItems = + vMsStbprpTMapper.selectBySttpCodes(sttpCodes); + + if (CollUtil.isEmpty(allItems)) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } + + // 构建树形结构:按 RSTCD 分组 + Map> groupedMap = new LinkedHashMap<>(); + + for (StcdItemVo item : allItems) { + String rstcd = StrUtil.blankToDefault(item.getRstcd(), ""); + // 处理逗号分隔的多个 RSTCD(一个测站关联多个电站) + if (rstcd.contains(",")) { + for (String singleRstcd : rstcd.split(",")) { + String r = singleRstcd.trim(); + if (StrUtil.isNotBlank(r)) { + groupedMap.computeIfAbsent(r, k -> new ArrayList<>()).add(item); + } + } + } else if (StrUtil.isNotBlank(rstcd)) { + groupedMap.computeIfAbsent(rstcd, k -> new ArrayList<>()).add(item); + } else { + // 无电站归属 → other + groupedMap.computeIfAbsent("other", k -> new ArrayList<>()).add(item); + } + } + + // 转换为树节点列表 + List treeList = new ArrayList<>(); + + for (Map.Entry> entry : groupedMap.entrySet()) { + String rstcd = entry.getKey(); + List items = entry.getValue(); + + RstcdTreeInfoVo node = + new RstcdTreeInfoVo(); + + if ("other".equals(rstcd)) { + node.setRstcd("other"); + node.setEnnm("其它"); + } else { + node.setRstcd(rstcd); + // 从测站数据中取电站名称 + String ennm = items.stream() + .map(StcdItemVo::getEnnm) + .filter(StrUtil::isNotBlank) + .findFirst().orElse(rstcd); + node.setEnnm(ennm); + } + + // 取第一个测站的排序和基地信息 + StcdItemVo first = items.get(0); + node.setSort(first.getOrderIndex()); + node.setBaseId(first.getBaseId()); + node.setBaseName(first.getBaseName()); + node.setItems(items); + + treeList.add(node); + } + + result.setData(treeList); + result.setTotal(treeList.size()); + return result; + } + + /** + * 从 DataSourceRequest 的 filter 中提取 STTP 过滤码 + */ + private List extractSttpCodesFromRequest(DataSourceRequest request) { + if (request == null || request.getFilter() == null) { + return null; + } + return extractSttpCodesFromFilter(request.getFilter()); + } + + private List extractSttpCodesFromFilter(DataSourceRequest.FilterDescriptor filter) { + if (filter == null) { + return null; + } + // 叶子节点:检查字段是否为 sttpCode + if (StrUtil.isNotBlank(filter.getField())) { + if ("sttpCode".equals(filter.getField()) || "sttp_code".equalsIgnoreCase(filter.getField())) { + if ("in".equalsIgnoreCase(filter.getOperator())) { + Object val = filter.getValue(); + if (val instanceof List list) { + return list.stream() + .filter(Objects::nonNull) + .map(Object::toString) + .filter(StrUtil::isNotBlank) + .map(String::trim) + .collect(Collectors.toList()); + } + if (val instanceof Object[] arr) { + return Arrays.stream(arr) + .filter(Objects::nonNull) + .map(Object::toString) + .filter(StrUtil::isNotBlank) + .map(String::trim) + .collect(Collectors.toList()); + } + } + } + return null; + } + // 递归子节点 + if (CollUtil.isNotEmpty(filter.getFilters())) { + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + List codes = extractSttpCodesFromFilter(child); + if (codes != null) { + return codes; + } + } + } + return null; + } } From a0da42122320f51c402eb3cad9f18dbcb422df95 Mon Sep 17 00:00:00 2001 From: tangwei Date: Fri, 7 Aug 2026 18:44:51 +0800 Subject: [PATCH 02/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E5=A2=9E?= =?UTF-8?q?=E5=80=BC=E7=AB=99=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_base/domain/vo/EngVmsstbprptVo.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index 477912d4..eec23777 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java @@ -164,4 +164,27 @@ public class EngVmsstbprptVo implements Serializable { /** 主要过鱼月份(多个月份用,隔开),主要过鱼月份(多个月份用,隔开),主要过鱼月份(多个月份用,隔开),主要过鱼月份(多个月份用,隔开) */ private String fpssmnmon; + /** 放流对象 */ + private String zzfldx; + /** 放流对象 */ + private String zzfldxName; + /** 放流地点 */ + private String zzflfllc; + private String zzflfllcName; + /** 生产工艺 */ + private String zzflgy; + /** 建设地点 */ + private String zzfljslc; + /** 养殖模式 */ + private String zzflyzms; + /** 养殖模式 */ + private String zzflyzmsName; + /** 放流规模 */ + private Integer zzflcnt; + /** 标记方式 */ + private String zzflbjfs; + /** 承担放流任务 */ + private String zzflrw; + /** 工程等级 */ + private Integer zzfllvl; } From 8a561d937631d1cd02e641af1b9db8c618c21f13 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 10 Aug 2026 10:39:45 +0800 Subject: [PATCH 03/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E7=AB=99?= =?UTF-8?q?=E7=82=B9=E6=9F=A5=E8=AF=A2=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_base/domain/vo/EngVmsstbprptVo.java | 43 +++++++++++++++++++ .../service/impl/SdEngInfoBHServiceImpl.java | 2 +- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index eec23777..dc3bf624 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java @@ -1,5 +1,6 @@ package com.yfd.platform.qgc_base.domain.vo; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -187,4 +188,46 @@ public class EngVmsstbprptVo implements Serializable { private String zzflrw; /** 工程等级 */ private Integer zzfllvl; + /** 放流时间 */ + private Date zzfltm; + /** 总占地面积 */ + private BigDecimal zzflar; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date ststdt; + /** 保护方式 */ + private String protmthd; + /** 保护对象 */ + private String protobj; + /** 面积 */ + private BigDecimal area; + /** 地点 */ + private String lsdwlc; + /** 基荷发电工况 */ + private BigDecimal jhfdgk; + /** 发电流量 */ + private BigDecimal fdll; + + /** 天然河流平均水温 */ + private BigDecimal nravwt; + /** 叠梁门式进水口的门叶数量 */ + private Integer dlmcnt; + /** 叠梁门式进水口的单节门叶高度 */ + private String dlmhg; + /** 天然河流最高温月份多年平均水温 */ + private BigDecimal nrmxavwt; + /** 天然河流最低温月份多年平均水温 */ + private BigDecimal nrmnavwt; + /** 建成后坝下平均水温 */ + private BigDecimal dnavwt; + /** 建成后坝下最高温月份多年平均水温 */ + private BigDecimal dnmxavwt; + /** 建成后坝下最低温月份多年平均水温 */ + private BigDecimal dnmnavwt; + /** 顶部高程 */ + private BigDecimal frntwllhg; + /** 翻板门顶部高程 */ + private BigDecimal fbmdbgc; + /** 叠梁门式进水口的最大淹没水深 */ + private BigDecimal dlmmxwdp; + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 5cf5e126..a2da3dcc 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -1001,7 +1001,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl Date: Mon, 10 Aug 2026 14:15:31 +0800 Subject: [PATCH 04/44] =?UTF-8?q?feat:=20=E8=8E=B7=E5=8F=96=E7=9B=91?= =?UTF-8?q?=E6=B5=8B=E7=82=B9=E6=B0=B4=E6=B8=A9=E5=8F=98=E5=8C=96=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=9C=89=E6=95=B0=E6=8D=AE=E7=9A=84=E6=96=AD=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SdEngInfoBHServiceImpl.java | 16 +- .../wt/controller/SdWTMonitorController.java | 6 + .../wt/entity/vo/WtrvDefaultStcdVo.java | 21 +++ .../wt/service/SdWtMonitorService.java | 5 + .../service/impl/SdWtMonitorServiceImpl.java | 166 ++++++++++++++++-- 5 files changed, 192 insertions(+), 22 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvDefaultStcdVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index a2da3dcc..f7c00095 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -4085,11 +4085,17 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl sttpCodes = extractSttpCodesFromRequest(dataSourceRequest); - +// List sttpCodes = extractSttpCodesFromRequest(dataSourceRequest); + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String sttpCode = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "sttpCode"); + if(StrUtil.isBlank(sttpCode)){ + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } // 查询 V_MS_STBPRP_T 视图 - List allItems = - vMsStbprpTMapper.selectBySttpCodes(sttpCodes); + List allItems = + vMsStbprpTMapper.selectBySttpCodes(List.of(sttpCode)); if (CollUtil.isEmpty(allItems)) { result.setData(new ArrayList<>()); @@ -4142,7 +4148,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl getFacilityPointKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getEngTempPointListKendoListCust(DataSourceRequest dataSourceRequest); + + /** + * 获取监测点水温变化默认有数据的断面 + */ + DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java index 2f825c50..3abd3358 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java @@ -7,23 +7,7 @@ import com.yfd.platform.common.*; import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.vo.DataScopeApplyResult; import com.yfd.platform.qgc_base.service.IDataScopeFilterService; -import com.yfd.platform.qgc_env.wt.entity.vo.DfltkwFacilityCountVo; -import com.yfd.platform.qgc_env.wt.entity.vo.FishSpawnVo; -import com.yfd.platform.qgc_env.wt.entity.vo.RstcdTreeInfoVo; -import com.yfd.platform.qgc_env.wt.entity.vo.SdMonthDetailVO; -import com.yfd.platform.qgc_env.wt.entity.vo.SdYearDetailVO; -import com.yfd.platform.qgc_env.wt.entity.vo.SdWtBaseInfoVO; -import com.yfd.platform.qgc_env.wt.entity.vo.SdWtMonitorCountVO; -import com.yfd.platform.qgc_env.wt.entity.vo.SttpInfoVo; -import com.yfd.platform.qgc_env.wt.entity.vo.WbsbVo; -import com.yfd.platform.qgc_env.wt.entity.vo.WtBaseInfoVo; -import com.yfd.platform.qgc_env.wt.entity.vo.WtFishVo; -import com.yfd.platform.qgc_env.wt.entity.vo.WtTreeStcdVo; -import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendResultVo; -import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendSaveVo; -import com.yfd.platform.qgc_env.wt.entity.vo.WtrvVo; -import com.yfd.platform.qgc_env.wt.entity.vo.DwSlowFacilityMapVO; -import com.yfd.platform.qgc_env.wt.entity.vo.WaterTempMapVO; +import com.yfd.platform.qgc_env.wt.entity.vo.*; import com.yfd.platform.qgc_env.wt.mapper.SdWtMonitorMapper; import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils; import com.yfd.platform.qgc_env.wt.service.SdWtMonitorService; @@ -3114,4 +3098,152 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { }; } + @Override + public DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest) { + DataSourceResult result = new DataSourceResult(); + result.setAggregates(new HashMap<>()); + + if (dataSourceRequest == null) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } + + // 解析请求中的过滤参数 + Map sqlWhereMap = new HashMap<>(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest.getFilter(); + if (filter != null) { + parseDefaultStcdFilter(filter, sqlWhereMap); + } + + Object startTime = sqlWhereMap.get("tm"); + Object endTime = sqlWhereMap.get("tm_1"); + Object mway = sqlWhereMap.get("mway"); + Object rstcd = sqlWhereMap.get("rstcd"); + Object baseId = sqlWhereMap.get("base_id"); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT * FROM (") + .append("SELECT stb.STCD, stb.STNM, stb.ORDER_INDEX AS orderIndex ") + .append("FROM SD_WTRV_R wt ") + .append("INNER JOIN SD_WT_B_H stb ON wt.STCD = stb.STCD ") + .append("AND stb.STTP = 'WTRV' ") + .append("AND stb.IS_DELETED = 0 ") + .append("WHERE wt.IS_DELETED = 0 "); + + // 时间范围 + if (startTime != null && StrUtil.isNotBlank(startTime.toString())) { + sql.append("AND wt.TM >= ").append(startTime).append(" "); + } + if (endTime != null && StrUtil.isNotBlank(endTime.toString())) { + sql.append("AND wt.TM <= ").append(endTime).append(" "); + } + + // 电站编码 + if (rstcd != null && StrUtil.isNotBlank(rstcd.toString())) { + String rstcdStr = rstcd.toString(); + if ("('')".equals(rstcdStr)) { + sql.append("AND stb.RSTCD IN ('') "); + } else if (rstcdStr.contains(",")) { + sql.append("AND stb.RSTCD IN ").append(rstcdStr).append(" "); + } else { + sql.append("AND stb.RSTCD = ").append(rstcdStr).append(" "); + } + } + + // 基地编码 + if (baseId != null && StrUtil.isNotBlank(baseId.toString())) { + sql.append("AND stb.BASE_ID = ").append(baseId).append(" "); + } + + // 监测方式 + if (mway != null && StrUtil.isNotBlank(mway.toString())) { + sql.append("AND stb.MWAY = ").append(mway).append(" "); + } + + sql.append("ORDER BY wt.TM DESC"); + + // 前端排序 + List sort = dataSourceRequest.getSort(); + if (sort != null && !sort.isEmpty()) { + sql.append(") ORDER BY "); + for (int i = 0; i < sort.size(); i++) { + sql.append(sort.get(i).getField()).append(" ").append(sort.get(i).getDir()); + if (i < sort.size() - 1) { + sql.append(","); + } + } + } else { + sql.append(")"); + } + sql.append(" WHERE ROWNUM = 1"); + + List dataList = microservicDynamicSQLMapper + .pageAllListWithResultType(null, sql.toString(), null, WtrvDefaultStcdVo.class); + + result.setData(dataList); + result.setTotal(dataList != null ? dataList.size() : 0L); + return result; + } + + /** + * 解析 DataSourceRequest filter 为 SQL 值格式,类似旧系统 SqlUtil.getWhereCondition + */ + private void parseDefaultStcdFilter(DataSourceRequest.FilterDescriptor filter, + Map sqlWhereMap) { + if (filter == null) { + return; + } + if (filter.getFilters() != null && !filter.getFilters().isEmpty()) { + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + parseDefaultStcdFilter(child, sqlWhereMap); + } + return; + } + if (StrUtil.isBlank(filter.getField())) { + return; + } + String field = StrUtil.toUnderlineCase(filter.getField()); + Object value = filter.getValue(); + if (value == null) { + return; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + String processedValue = formatDefaultStcdValue(operator, value, filter.getDataType()); + + // 同名字段自动追加 _1 后缀 + if (sqlWhereMap.containsKey(field)) { + int idx = 1; + while (sqlWhereMap.containsKey(field + "_" + idx)) { + idx++; + } + field = field + "_" + idx; + } + sqlWhereMap.put(field, processedValue); + } + + private String formatDefaultStcdValue(String operator, Object value, String dataType) { + if (value == null) { + return null; + } + if ("in".equals(operator)) { + // 将列表转为 ('a','b','c') 格式 + List list = normalizeToList(value); + return "(" + list.stream() + .map(v -> "'" + String.valueOf(v).trim() + "'") + .collect(Collectors.joining(",")) + ")"; + } + if ("date".equalsIgnoreCase(dataType)) { + String text = String.valueOf(value).trim().replace("T", " "); + if (text.length() <= 10) { + return "TO_DATE('" + text.replace("'", "''") + "', 'YYYY-MM-DD')"; + } + return "TO_DATE('" + text.replace("'", "''") + "', 'YYYY-MM-DD HH24:MI:SS')"; + } + if ("string".equalsIgnoreCase(dataType) || value instanceof String) { + return "'" + String.valueOf(value).trim().replace("'", "''") + "'"; + } + return String.valueOf(value).trim(); + } + } From 9608b91f92c5678f4755c65bb29193e61bcc10d7 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 10 Aug 2026 14:34:38 +0800 Subject: [PATCH 05/44] =?UTF-8?q?feat:=20=E7=9B=91=E6=B5=8B=E7=82=B9?= =?UTF-8?q?=E6=B0=B4=E6=B8=A9=E5=8F=98=E5=8C=96=EF=BC=88=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E6=97=B6=E6=AE=B5=20+=20=E5=8E=BB=E5=B9=B4=E5=90=8C=E6=9C=9F?= =?UTF-8?q?=E5=AF=B9=E6=AF=94=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wt/controller/SdWTMonitorController.java | 6 ++ .../platform/qgc_env/wt/entity/vo/WtrvVo.java | 26 ++++-- .../wt/service/SdWtMonitorService.java | 5 ++ .../service/impl/SdWtMonitorServiceImpl.java | 82 +++++++++++++++++++ 4 files changed, 111 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java index f48b8d2c..8f521bb6 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java @@ -339,4 +339,10 @@ public class SdWTMonitorController { public ResponseResult getWtrvDefaultStcd(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(sdWtMonitorService.getDefaultStcd(dataSourceRequest)); } + + @PostMapping("/wtrv/GetKendoListCust") + @Operation(summary = "监测点水温变化(当前时段 + 去年同期对比)") + public ResponseResult getWtrvKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtMonitorService.getWtRV(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvVo.java index 0324eb4c..1666c325 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvVo.java @@ -1,28 +1,38 @@ package com.yfd.platform.qgc_env.wt.entity.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; import java.util.Date; +/** + * 监测点水温变化数据 VO(当前水温 + 去年同期月均/最高/最低对比) + */ @Data +@Schema(description = "监测点水温变化数据") public class WtrvVo { + @Schema(description = "测站编码") private String stcd; + @Schema(description = "数据时间") private Date tm; -// private Boolean isIoWtrv; - - private Boolean ioWtrv; - - private Boolean hasRstcdWtvt; - + @Schema(description = "水温") private BigDecimal wt; - private BigDecimal avgwt; - + @Schema(description = "去年同期最低水温") private BigDecimal minwt; + @Schema(description = "去年同期最高水温") private BigDecimal maxwt; + + @Schema(description = "去年同期平均水温") + private BigDecimal avgwt; + + @Schema(description = "是否是出入库水温站") + private boolean isIoWtrv;//是否是出入库水温站 + @Schema(description = "关联的电站是否有垂向水温站") + private boolean hasRstcdWtvt;//关联的电站是否有垂向水温站 } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java index d7ebd7f6..540ccefb 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java @@ -62,4 +62,9 @@ public interface SdWtMonitorService { * 获取监测点水温变化默认有数据的断面 */ DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest); + + /** + * 获取监测点水温变化数据(当前时段 + 去年同期对比) + */ + DataSourceResult getWtRV(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java index 3abd3358..0b5d9ac6 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java @@ -1,5 +1,8 @@ package com.yfd.platform.qgc_env.wt.service.impl; +import cn.hutool.core.date.DateField; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -3098,6 +3101,85 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { }; } + @Override + public DataSourceResult getWtRV(DataSourceRequest dataSourceRequest) { + DataSourceResult result = new DataSourceResult<>(); + result.setAggregates(new HashMap<>()); + + if (dataSourceRequest == null) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } + + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String tm = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + + if (StrUtil.isBlank(tm) || StrUtil.isBlank(stcd)) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } + + // 解析时间范围(逗号分隔:startTime,endTime) + String[] tmList = tm.split(","); + String startTime = tmList[0]; + String endTime = tmList[1]; + + DateTime startDate = DateUtil.parse(startTime, DatePattern.NORM_DATETIME_PATTERN); + DateTime endDate = DateUtil.parse(endTime, DatePattern.NORM_DATETIME_PATTERN); + String startTimeFormatted = DateUtil.format(startDate, DatePattern.NORM_DATETIME_PATTERN); + String endTimeFormatted = DateUtil.format(endDate, DatePattern.NORM_DATETIME_PATTERN); + + // 去年同期时间范围(-12个月) + String lastYearStartTime = DateUtil.offset(startDate, DateField.MONTH, -12).toString(); + String lastYearEndTime = DateUtil.offset(endDate, DateField.MONTH, -12).toString(); + + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + paramMap.put("startTime", startTimeFormatted); + paramMap.put("endTime", endTimeFormatted); + paramMap.put("lastYearStartTime", lastYearStartTime); + paramMap.put("lastYearEndTime", lastYearEndTime); + + String sql = "SELECT " + + "t1.STCD AS stcd, " + + "t1.TM AS tm, " + + "t1.WT AS wt, " + + "t2.MINWT AS minwt, " + + "t2.MAXWT AS maxwt, " + + "t2.AVGWT AS avgwt " + + "FROM SD_WTRV_R t1 " + + "LEFT JOIN ( " + + " SELECT " + + " TO_CHAR(TM, 'YYYY') AS YEAR, " + + " TO_CHAR(TM, 'MM') AS MON, " + + " ROUND(AVG(WT), 2) AS AVGWT, " + + " MAX(WT) AS MAXWT, " + + " MIN(WT) AS MINWT " + + " FROM SD_WTRV_R " + + " WHERE STCD = #{map.stcd} " + + " AND NVL(IS_DELETED, 0) = 0 " + + " AND TM >= TO_TIMESTAMP(#{map.lastYearStartTime}, 'YYYY-MM-DD HH24:MI:SS') " + + " AND TM <= TO_TIMESTAMP(#{map.lastYearEndTime}, 'YYYY-MM-DD HH24:MI:SS') " + + " GROUP BY TO_CHAR(TM, 'YYYY'), TO_CHAR(TM, 'MM') " + + ") t2 ON TO_CHAR(ADD_MONTHS(t1.TM, -12), 'YYYY') = t2.YEAR " + + " AND TO_CHAR(t1.TM, 'MM') = t2.MON " + + "WHERE t1.STCD = #{map.stcd} " + + " AND NVL(t1.IS_DELETED, 0) = 0 " + + " AND t1.TM >= TO_TIMESTAMP(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS') " + + " AND t1.TM <= TO_TIMESTAMP(#{map.endTime}, 'YYYY-MM-DD HH24:MI:SS') " + + "ORDER BY t1.TM"; + + List dataList = microservicDynamicSQLMapper + .pageAllListWithResultType(null, sql, paramMap, WtrvVo.class); + + result.setData(dataList); + result.setTotal(dataList != null ? dataList.size() : 0L); + return result; + } + @Override public DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest) { DataSourceResult result = new DataSourceResult(); From 9add0769b90ecf91a92bafd94cbdcbc22c9fcfd8 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 10 Aug 2026 16:19:10 +0800 Subject: [PATCH 06/44] =?UTF-8?q?feat:=20=E8=8E=B7=E5=8F=96=E6=B0=B4?= =?UTF-8?q?=E8=B4=A8=E8=BE=BE=E6=A0=87=E7=8E=87=E9=BB=98=E8=AE=A4=E6=9C=89?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=9A=84=E7=94=B5=E7=AB=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_base/domain/SdEngInfoBHRequest.java | 2 +- .../service/impl/SdEngInfoBHServiceImpl.java | 2 + .../wq/controller/EnvWqDataController.java | 6 ++ .../qgc_env/wq/entity/vo/WqDefaultStcdVo.java | 22 +++++++ .../qgc_env/wq/service/EnvWqDataService.java | 6 ++ .../wq/service/impl/EnvWqDataServiceImpl.java | 59 +++++++++++++++++++ 6 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/wq/entity/vo/WqDefaultStcdVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java index 4a7f7127..ceb43999 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java @@ -14,7 +14,7 @@ public class SdEngInfoBHRequest { private String hbrvcd; private String rvcd; private String reachcd; - private List basIds; + private List baseIds; private List hbrvcds; private List rvcds; // private List rvcds; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index f7c00095..07bd92ea 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -198,6 +198,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl selectForDropdownCached(SdEngInfoBHRequest sdEngInfoBHRequest) { String baseId = sdEngInfoBHRequest.getBaseId(); + List baseIds = sdEngInfoBHRequest.getBaseIds(); String hbrvcd = sdEngInfoBHRequest.getHbrvcd(); String ennm = sdEngInfoBHRequest.getEnnm(); String rvcd = sdEngInfoBHRequest.getRvcd(); @@ -210,6 +211,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl getAnchorPointKendoListCust(DataSourceRequest dataSourceRequest); + /** + * 获取水质达标率默认有数据的电站 + */ + DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest); + void wqLastData(JobBaseAo ao); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java index 4d553f10..a330286c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java @@ -4997,4 +4997,63 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { redisCacheUtil.setString("wqLastDate:" + wqDataVo.getStcd(), JSONUtil.toJsonStr(wqDataVo)); } } + + @Override + public DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest) { + DataSourceResult result = new DataSourceResult<>(); + result.setAggregates(new HashMap<>()); + + if (dataSourceRequest == null) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } + + // 构建过滤条件 + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapWqDefaultStcdColumn + ); + + String sql = "SELECT sb.STCD AS stcd, sb.STNM AS stnm " + + "FROM MS_WQ_T wq " + + "INNER JOIN SD_WQ_B_H sb ON wq.STCD = sb.STCD " + + "WHERE sb.STTP = 'WQ' " + + " AND sb.USFL = 1 " + + " AND NVL(sb.IS_DELETED, 0) = 0 " + + " AND NVL(wq.IS_DELETED, 0) = 0 "; + + // 拼接动态过滤条件 + if (StrUtil.isNotBlank(filterSql)) { + sql += " AND " + filterSql + " "; + } + + sql += " AND ROWNUM = 1"; + + List dataList = microservicDynamicSQLMapper + .pageAllListWithResultType(null, sql, paramMap, WqDefaultStcdVo.class); + + result.setData(dataList); + result.setTotal(dataList != null ? dataList.size() : 0L); + return result; + } + + /** + * 水质默认电站过滤字段映射 + */ + private String mapWqDefaultStcdColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field.toLowerCase()) { + case "tm" -> "wq.TM"; + case "stcd" -> "sb.STCD"; + case "base_id", "baseid" -> "sb.BASE_ID"; + case "rstcd" -> "sb.RSTCD"; + default -> null; + }; + } } From b8e8fc5eaf5c68d1dca87d39273be71d26b5ab2b Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 10 Aug 2026 17:45:18 +0800 Subject: [PATCH 07/44] =?UTF-8?q?fix:=20=E5=85=A8=E8=BF=87=E7=A8=8B?= =?UTF-8?q?=E8=BF=87=E9=B1=BC=E7=BB=9F=E8=AE=A1=E6=80=BB=E6=95=B0=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yfd/platform/config/SecurityConfig.java | 20 ++--- .../qgc_base/domain/vo/EngVmsstbprptVo.java | 15 ++++ .../fp/controller/FishPassageController.java | 4 +- .../qgc_env/fp/service/FpRunService.java | 2 +- .../fp/service/impl/FpRunServiceImpl.java | 89 +++++++++++-------- 5 files changed, 80 insertions(+), 50 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java index 10903a7e..3883e656 100644 --- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -65,26 +65,26 @@ public class SecurityConfig { .requestMatchers("/system/user/auditUser").permitAll() .requestMatchers("/register/accessToken").permitAll() .requestMatchers("/api/oauth2/oauth/token").permitAll() - .requestMatchers("/dict/cache/**").permitAll() - .requestMatchers("/sys/psbmodulelbb/**").permitAll() - .requestMatchers("/base/operationLog/**").permitAll() +// .requestMatchers("/dict/cache/**").permitAll() +// .requestMatchers("/sys/psbmodulelbb/**").permitAll() +// .requestMatchers("/base/operationLog/**").permitAll() // .requestMatchers("/system/**").permitAll() - .requestMatchers("/qgcExport/**").permitAll() +// .requestMatchers("/qgcExport/**").permitAll() .requestMatchers("/eng/**").permitAll() - .requestMatchers("/eq/**").permitAll() +// .requestMatchers("/eq/**").permitAll() // .requestMatchers("/env/**").permitAll() // .requestMatchers("/warn/**").permitAll() // .requestMatchers("/threedroamb/**").permitAll() // .requestMatchers("/overview/**").permitAll() -// .requestMatchers("/wt/**").permitAll() -// .requestMatchers("/fb/**").permitAll() - .requestMatchers("/base/**").permitAll() + .requestMatchers("/wt/**").permitAll() + .requestMatchers("/fb/**").permitAll() +// .requestMatchers("/base/**").permitAll() // .requestMatchers("/zq/**").permitAll() -// .requestMatchers("/wq/**").permitAll() + .requestMatchers("/wq/**").permitAll() // .requestMatchers("/wte/**").permitAll() // .requestMatchers("/vd/**").permitAll() // .requestMatchers("/vap/**").permitAll() -// .requestMatchers("/fp/**").permitAll() + .requestMatchers("/fp/**").permitAll() // .requestMatchers("/fpr/**").permitAll() // .requestMatchers("/fh/**").permitAll() // .requestMatchers("/data/**").permitAll() diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index dc3bf624..384e18a4 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java @@ -230,4 +230,19 @@ public class EngVmsstbprptVo implements Serializable { /** 叠梁门式进水口的最大淹没水深 */ private BigDecimal dlmmxwdp; + + /** 保护范围 */ + private String qxdbhfw; + /** 保护对象 */ + private String protobjName; + /** 保护外围长度 */ + private BigDecimal qxdbhwwcd; + /** 保护长度 */ + private BigDecimal qxdbhcd; + /** 保护河段 */ + private String bhhd; + /** 保护河流 */ + private String bhhl; + /** 保护核心长度 */ + private BigDecimal qxdbhhxcd; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java index be3b1a60..dd46b13d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java @@ -127,7 +127,7 @@ public class FishPassageController { @GetMapping("/run/qgc/year/GetYearFpStatistics") @Operation(summary = "全过程过鱼统计总数,根据基地分组") - public ResponseResult getYearFpStatic(@RequestParam("year") String year) { - return ResponseResult.successData(fpRunService.getYearFpStatic(year)); + public ResponseResult getYearFpStatic(@RequestParam("year") String year,@RequestParam(value = "stcd",required = false) String stcd) { + return ResponseResult.successData(fpRunService.getYearFpStatic(year,stcd)); } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java index 42b1054d..77a40565 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java @@ -31,5 +31,5 @@ public interface FpRunService { DataSourceResult getFishSelect(DataSourceRequest dataSourceRequest); - List getYearFpStatic(String year); + List getYearFpStatic(String year,String stcd); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index 1cf4c621..f0e2b67f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -309,7 +309,7 @@ public class FpRunServiceImpl implements FpRunService { String sql = buildQgcFpRunAnalysisDataSql(dataSourceRequest == null ? null : dataSourceRequest.getSort()); Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions); List rows = microservicDynamicSQLMapper.pageAllListWithResultType( - page,sql, + page, sql, paramMap, FpRunAnalysisVo.class ); @@ -359,11 +359,14 @@ public class FpRunServiceImpl implements FpRunService { } @Override - public List getYearFpStatic(String year) { + public List getYearFpStatic(String year, String stcd) { Map paramMap = new HashMap<>(); paramMap.put("year", StrUtil.trim(year)); + if (StrUtil.isNotBlank(stcd)) { + paramMap.put("stcd", StrUtil.trim(stcd)); + } List rows = microservicDynamicSQLMapper.getAllListWithResultType( - buildYearFpStatisticsSql(), + buildYearFpStatisticsSql(null,stcd), paramMap, FpFtpStatisticsVo.class ); @@ -1134,11 +1137,11 @@ public class FpRunServiceImpl implements FpRunService { String key = "fbFishRunP" + indexHolder[0]++; paramMap.put(key, text); return switch (operator) { - case "eq" -> "t.FLYR = TO_CHAR(TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY')"; + case "eq" -> "t.FLYR = TO_CHAR(TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY')"; case "neq" -> "t.FLYR <> TO_CHAR(TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY')"; - case "gt" -> "t.FLYR > TO_CHAR(TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY')"; + case "gt" -> "t.FLYR > TO_CHAR(TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY')"; case "gte" -> "t.FLYR >= TO_CHAR(TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY')"; - case "lt" -> "t.FLYR < TO_CHAR(TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY')"; + case "lt" -> "t.FLYR < TO_CHAR(TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY')"; case "lte" -> "t.FLYR <= TO_CHAR(TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY')"; default -> ""; }; @@ -1221,7 +1224,7 @@ public class FpRunServiceImpl implements FpRunService { } private DataSourceResult queryQgcFpssrlAiRDetailList(DataSourceRequest dataSourceRequest, - DataSourceLoadOptionsBase loadOptions) { + DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); sql.append("SELECT ") .append(buildQgcFpssrlDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) @@ -1321,7 +1324,7 @@ public class FpRunServiceImpl implements FpRunService { } private DataSourceResult queryQgcFpssrlAiRGroupList(DataSourceRequest dataSourceRequest, - DataSourceLoadOptionsBase loadOptions) { + DataSourceLoadOptionsBase loadOptions) { List groups = dataSourceRequest.getGroup(); GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); @@ -2644,36 +2647,48 @@ public class FpRunServiceImpl implements FpRunService { "WHERE t.STCD = #{map.stcd}"; } - private String buildYearFpStatisticsSql() { - return "SELECT eng.BASE_ID AS baseId, " + - " hb.BASENAME AS baseName, " + - " a.FTP AS ftp, " + - " COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, a.FTP) AS fishName, " + - " SUM(a.FCNT) AS fcnt " + - "FROM SD_FPSS_R a " + - "INNER JOIN ( " + - " SELECT STCD, MAX(RSTCD) AS RSTCD " + - " FROM SD_FPSS_B_H " + - " GROUP BY STCD " + - ") fpss ON fpss.STCD = a.STCD " + - "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fpss.RSTCD " + - "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID " + - "LEFT JOIN SD_FISHDICTORY_RLTN_B relRv ON relRv.FISH_ID = a.FTP " + - " AND relRv.RVCD = eng.HBRVCD " + - " AND relRv.IS_DELETED = 0 " + - "LEFT JOIN SD_FISHDICTORY_B fishRv ON fishRv.ID = NVL(relRv.ZY_FISH_ID, relRv.FISH_ID) " + - " AND fishRv.IS_DELETED = 0 " + - "LEFT JOIN SD_FISHDICTORY_RLTN_B relZy ON relZy.FISH_ID = a.FTP " + - " AND relZy.RVCD = 'ZY' " + - " AND relZy.IS_DELETED = 0 " + - "LEFT JOIN SD_FISHDICTORY_B fishZy ON fishZy.ID = NVL(relZy.ZY_FISH_ID, relZy.FISH_ID) " + - " AND fishZy.IS_DELETED = 0 " + - "WHERE NVL(a.IS_DELETED, 0) = 0 " + - " AND (#{map.year} IS NULL OR #{map.year} = '' OR TO_CHAR(a.STRDT, 'YYYY') = #{map.year}) " + - "GROUP BY eng.BASE_ID, hb.BASENAME, a.FTP, COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, a.FTP) " + - "ORDER BY eng.BASE_ID, a.FTP"; - } + private String buildYearFpStatisticsSql(String year, String stcd) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT eng.BASE_ID AS baseId, ") + .append("hb.BASENAME AS baseName, ") + .append("a.FTP AS ftp, ") + .append("COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, a.FTP) AS fishName, ") + .append("SUM(a.FCNT) AS fcnt ") + .append("FROM SD_FPSS_R a ") + .append("INNER JOIN ( ") + .append(" SELECT STCD, MAX(RSTCD) AS RSTCD ") + .append(" FROM SD_FPSS_B_H ") + .append(" GROUP BY STCD ") + .append(") fpss ON fpss.STCD = a.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fpss.RSTCD ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID ") + .append("LEFT JOIN SD_FISHDICTORY_RLTN_B relRv ON relRv.FISH_ID = a.FTP ") + .append(" AND relRv.RVCD = eng.HBRVCD ") + .append(" AND relRv.IS_DELETED = 0 ") + .append("LEFT JOIN SD_FISHDICTORY_B fishRv ON fishRv.ID = NVL(relRv.ZY_FISH_ID, relRv.FISH_ID) ") + .append(" AND fishRv.IS_DELETED = 0 ") + .append("LEFT JOIN SD_FISHDICTORY_RLTN_B relZy ON relZy.FISH_ID = a.FTP ") + .append(" AND relZy.RVCD = 'ZY' ") + .append(" AND relZy.IS_DELETED = 0 ") + .append("LEFT JOIN SD_FISHDICTORY_B fishZy ON fishZy.ID = NVL(relZy.ZY_FISH_ID, relZy.FISH_ID) ") + .append(" AND fishZy.IS_DELETED = 0 ") + .append("WHERE NVL(a.IS_DELETED, 0) = 0 "); + + // 年份条件(用占位符) + sql.append("AND (#{map.year} IS NULL OR #{map.year} = '' OR TO_CHAR(a.STRDT, 'YYYY') = #{map.year}) "); + + // 动态拼接 STCD 条件 + if (stcd != null && !stcd.isEmpty()) { + sql.append("AND a.STCD = #{map.stcd} "); + } + + sql.append("GROUP BY eng.BASE_ID, hb.BASENAME, a.FTP, ") + .append("COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, a.FTP) ") + .append("ORDER BY eng.BASE_ID, a.FTP"); + + return sql.toString(); + } private String buildFpFishSelectSql() { return "SELECT DISTINCT t.ID AS id, t.NAME AS name " + "FROM ( " + From e3e3bd3c88ba51e7353afa00809f4da066579f3e Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 08:26:52 +0800 Subject: [PATCH 08/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_base/domain/MsOperationLog.java | 3 ++ .../qgc_base/domain/vo/EngVmsstbprptVo.java | 1 + .../impl/MsOperationLogServiceImpl.java | 40 +++++++++++-------- .../zq/service/impl/ZqMonitorServiceImpl.java | 8 ++-- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java index 04d9e34a..a3ca94c7 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java @@ -36,4 +36,7 @@ public class MsOperationLog implements Serializable { @TableField("RECORD_ID") private String recordId; + @TableField("OPERATION_TYPE") + private String operationType; + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index 384e18a4..e92d5a90 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java @@ -25,6 +25,7 @@ public class EngVmsstbprptVo implements Serializable { private String rvcdFullPath; private String stcd; private String stnm; + private String rstcd; private String ennm; private String baseId; private String baseName; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java index 52b84801..54b55936 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -287,7 +287,7 @@ public class MsOperationLogServiceImpl extends ServiceImpl details = new ArrayList<>(); @@ -323,7 +323,7 @@ public class MsOperationLogServiceImpl extends ServiceImpl details = new ArrayList<>(); @@ -360,7 +360,7 @@ public class MsOperationLogServiceImpl extends ServiceImpl details = new ArrayList<>(); @@ -390,11 +390,11 @@ public class MsOperationLogServiceImpl extends ServiceImpl details = new ArrayList<>(); @@ -457,7 +458,7 @@ public class MsOperationLogServiceImpl extends ServiceImpl details = new ArrayList<>(); @@ -489,7 +490,7 @@ public class MsOperationLogServiceImpl extends ServiceImpl codeToNameFieldMap = buildCodeToNameFieldMap(codeToNameMetaList); - MsOperationLog mainLog = buildMainLog(tableName, recordId, "新增", source); + MsOperationLog mainLog = buildMainLog(tableName, recordId, "新增", source,"01"); msOperationLogMapper.insert(mainLog); List details = new ArrayList<>(); @@ -507,7 +508,9 @@ public class MsOperationLogServiceImpl extends ServiceImpl details = new ArrayList<>(); @@ -560,7 +563,7 @@ public class MsOperationLogServiceImpl extends ServiceImpl codeToNameFieldMap = buildCodeToNameFieldMap(codeToNameMetaList); - MsOperationLog mainLog = buildMainLog(tableName, recordId, "修改", source); + MsOperationLog mainLog = buildMainLog(tableName, recordId, "修改", source,"02"); msOperationLogMapper.insert(mainLog); List details = new ArrayList<>(); @@ -604,7 +607,7 @@ public class MsOperationLogServiceImpl extends ServiceImpl codeToNameFieldMap = buildCodeToNameFieldMap(codeToNameMetaList); - MsOperationLog mainLog = buildMainLog(tableName, recordId, "删除", source); + MsOperationLog mainLog = buildMainLog(tableName, recordId, "删除", source,"03"); msOperationLogMapper.insert(mainLog); List details = new ArrayList<>(); @@ -622,7 +625,9 @@ public class MsOperationLogServiceImpl extends ServiceImpl(); } LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(MsOperationLogDetail::getMainId, mainId); + wrapper.eq(MsOperationLogDetail::getMainId, mainId) + .notIn(MsOperationLogDetail::getFieldCode, + "recordUser", "recordTime", "modifyUser", "modifyTime", + "isDeleted", "deleteUser", "deleteTime"); return msOperationLogDetailMapper.selectList(wrapper); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java index 972a77e1..f956532c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java @@ -2219,13 +2219,13 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { selectMap.put("rstcd", "t.RSTCD AS rstcd"); selectMap.put("ennm", "eng.ENNM AS ennm"); selectMap.put("baseId", "eng.BASE_ID AS baseId"); - selectMap.put("baseName", "hb.BASENAME AS baseName"); +// selectMap.put("baseName", "hb.BASENAME AS baseName"); selectMap.put("hbrvcd", "eng.HBRVCD AS hbrvcd"); - selectMap.put("hbrvcdName", "hbrv.HBRVNM AS hbrvcdName"); +// selectMap.put("hbrvcdName", "hbrv.HBRVNM AS hbrvcdName"); selectMap.put("rvcd", "eng.RVCD AS rvcd"); - selectMap.put("rvcdName", "rv.RVNM AS rvcdName"); +// selectMap.put("rvcdName", "rv.RVNM AS rvcdName"); selectMap.put("addvcd", "eng.ADDVCD AS addvcd"); - selectMap.put("addvcdName", "addv.ADDVNM AS addvcdName"); +// selectMap.put("addvcdName", "addv.ADDVNM AS addvcdName"); selectMap.put("fhstcd", "t.FHSTCD AS fhstcd"); selectMap.put("ispro", "t.ISPRO AS ispro"); selectMap.put("project", "t.PROJECT AS project"); From 13d0c52a847091377723361a9c061f6f9acbc968 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 09:07:05 +0800 Subject: [PATCH 09/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E6=9F=A5=E8=AF=A2bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_base/domain/MsOperationLog.java | 6 + .../impl/MsOperationLogServiceImpl.java | 120 ++++++++++++++++++ .../service/impl/SdEngInfoBHServiceImpl.java | 2 +- 3 files changed, 127 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java index a3ca94c7..13f1f80b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java @@ -39,4 +39,10 @@ public class MsOperationLog implements Serializable { @TableField("OPERATION_TYPE") private String operationType; + /** + * 操作记录的名称(瞬态字段,不持久化,由后端查询后填充) + */ + @TableField(exist = false) + private String recordName; + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java index 54b55936..f60f4a7b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.annotation.FieldChinese; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.qgc_base.domain.MsOperationLog; import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; import com.yfd.platform.qgc_base.domain.SdEngInfoBH; @@ -20,6 +21,7 @@ import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -32,11 +34,28 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +@Slf4j @Service public class MsOperationLogServiceImpl extends ServiceImpl implements IMsOperationLogService { private static final String ENG_TABLE_NAME = "SD_ENGINFO_B_H"; + /** + * 表名 → (主键列, 名称列) 配置映射 + * 默认:主键列 = STCD,名称列 = STNM,无需显式配置 + * 仅在主键列或名称列与默认不同的情况下才需配置 + */ + private record TableNameConfig(String pkColumn, String nameColumn) {} + private static final Map TABLE_NAME_CONFIG_MAP = new HashMap<>(); + static { + // Engine Info: 名称列是 ENNM 而非 STNM + TABLE_NAME_CONFIG_MAP.put("SD_ENGINFO_B_H", new TableNameConfig("STCD", "ENNM")); + // Hydro Base: 主键列是 BASEID,名称列是 BASENAME + TABLE_NAME_CONFIG_MAP.put("SD_HYDROBASE", new TableNameConfig("BASEID", "BASENAME")); + // Fish Dictionary: 需确认结构后配置 + TABLE_NAME_CONFIG_MAP.put("SD_FISHDICTORY_B", new TableNameConfig("ID", "NAME")); + } + private static final Map ENG_FIELD_MEANING_MAP = new LinkedHashMap<>(); // 标准日期时间格式器 private static final DateTimeFormatter DATETIME_FORMATTER = @@ -282,6 +301,9 @@ public class MsOperationLogServiceImpl extends ServiceImpl queryPageList(DataSourceRequest request) { Page msOperationLogPage = DataSourceRequestUtil.executeQuery(request, MsOperationLog.class, this); + // 批量解析操作记录名称 + batchResolveRecordNames(msOperationLogPage.getRecords()); return msOperationLogPage; } + /** + * 批量解析操作记录的名称 + * 按 tableName 分组后,每张表一次批量查询名称 + */ + private void batchResolveRecordNames(List records) { + if (records == null || records.isEmpty()) { + return; + } + + // 按 tableName 分组,收集 recordId + Map> tableRecordIdsMap = new LinkedHashMap<>(); + for (MsOperationLog log : records) { + if (StrUtil.isNotBlank(log.getTableName()) && StrUtil.isNotBlank(log.getRecordId())) { + tableRecordIdsMap.computeIfAbsent(log.getTableName(), k -> new ArrayList<>()) + .add(log.getRecordId()); + } + } + + // 每个表批量查询名称 + for (Map.Entry> entry : tableRecordIdsMap.entrySet()) { + String tableName = entry.getKey(); + List recordIds = entry.getValue(); + if (recordIds.isEmpty()) { + continue; + } + + // 获取表配置 + TableNameConfig config = TABLE_NAME_CONFIG_MAP.get(tableName); + String pkColumn; + String nameColumn; + if (config != null) { + pkColumn = config.pkColumn(); + nameColumn = config.nameColumn(); + } else { + // 默认:主键列 = STCD,名称列 = STNM + pkColumn = "STCD"; + nameColumn = "STNM"; + } + + // 去重后构建 IN 参数 + Set distinctIds = new LinkedHashSet<>(recordIds); + Map paramMap = new HashMap<>(); + String inPlaceholders = buildInPlaceholders(distinctIds, paramMap); + + // 注意:如果配置的表在数据库中不存在,跳过 + try { + String sql = "SELECT " + pkColumn + " AS pkVal, " + nameColumn + " AS nameVal " + + "FROM " + tableName + + " WHERE " + pkColumn + " IN (" + inPlaceholders + ")" + + " AND NVL(IS_DELETED, 0) = 0"; + List> results = microservicDynamicSQLMapper.getAllList(sql, paramMap); + + // 构建 pkVal → nameVal 映射 + Map nameMap = new HashMap<>(); + for (Map row : results) { + Object pkObj = row.get("PKVAL"); + Object nameObj = row.get("NAMEVAL"); + if (pkObj != null && nameObj != null) { + nameMap.put(String.valueOf(pkObj), String.valueOf(nameObj)); + } + } + + // 回填 recordName + for (MsOperationLog log : records) { + if (tableName.equals(log.getTableName())) { + String name = nameMap.get(log.getRecordId()); + if (name != null) { + log.setRecordName(name); + } + } + } + } catch (Exception e) { + // 表不存在或查询失败时静默跳过 + log.warn("批量解析记录名称失败, tableName={}", tableName, e); + } + } + } + + /** + * 构建 IN 子句占位符,如 #{map.p0}, #{map.p1}, ... + */ + private String buildInPlaceholders(Set ids, Map paramMap) { + StringBuilder sb = new StringBuilder(); + int i = 0; + for (String id : ids) { + if (i > 0) { + sb.append(", "); + } + String key = "p" + i; + sb.append("#{map.").append(key).append("}"); + paramMap.put(key, id); + i++; + } + return sb.toString(); + } + @Override public List getDetailByMainId(String mainId) { if (StringUtils.isBlank(mainId)) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 07bd92ea..0ae3d892 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -53,7 +53,7 @@ import java.util.stream.Collectors; */ @Service public class SdEngInfoBHServiceImpl extends ServiceImpl implements ISdEngInfoBHService { - private static final String TABLE_NAME = "SD_FISHDICTORY_B"; + private static final String TABLE_NAME = "SD_ENGINFO_B_H"; private static final Map ENG_CODE_NAME_FIELD_MAP = new LinkedHashMap<>(); @Resource private RedisCacheUtil redisCacheUtil; From 5073285d73241facdac74d17d95de07fbd3b770e Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 09:42:53 +0800 Subject: [PATCH 10/44] =?UTF-8?q?fix:=20=E6=9F=A5=E8=AF=A2=E6=B0=B4?= =?UTF-8?q?=E6=B8=A9=E6=8C=87=E5=AE=9A=E6=97=B6=E9=97=B4=E6=9C=89=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=9A=84=E7=AB=99=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wt/controller/SdWTMonitorController.java | 6 + .../wt/entity/vo/WtvtDefaultStcdVo.java | 44 ++++++ .../wt/service/SdWtMonitorService.java | 6 + .../service/impl/SdWtMonitorServiceImpl.java | 127 ++++++++++++++++++ 4 files changed, 183 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtvtDefaultStcdVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java index 8f521bb6..65bf1e58 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java @@ -334,6 +334,12 @@ public class SdWTMonitorController { return ResponseResult.successData(sdWtMonitorService.getEngTempPointListKendoListCust(dataSourceRequest)); } + @PostMapping("/sdrvwts/default/stcd") + @Operation(summary = "查询水温指定时间有数据的站点(垂向水温)") + public ResponseResult getSdrvwtsDefaultStcd(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtMonitorService.getWtvtDefaultStcd(dataSourceRequest)); + } + @PostMapping("/wtrv/default/stcd") @Operation(summary = "获取监测点水温变化默认有数据的断面") public ResponseResult getWtrvDefaultStcd(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtvtDefaultStcdVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtvtDefaultStcdVo.java new file mode 100644 index 00000000..2ce513cd --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtvtDefaultStcdVo.java @@ -0,0 +1,44 @@ +package com.yfd.platform.qgc_env.wt.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 垂向水温默认有数据的站点 VO + */ +@Data +@Schema(description = "垂向水温默认站点信息") +public class WtvtDefaultStcdVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "站名") + private String stnm; + + @Schema(description = "经度") + private BigDecimal lgtd; + + @Schema(description = "纬度") + private BigDecimal lttd; + + @Schema(description = "水温监测断面设备类型:1=浮动式 2=固定式") + private Integer wtDeviceType; + + @Schema(description = "所属基地编码") + private String baseId; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "站点排序") + private Integer siteStepSort; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java index 540ccefb..badd4c3f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java @@ -9,6 +9,7 @@ import com.yfd.platform.qgc_env.wt.entity.vo.SdMonthDetailVO; import com.yfd.platform.qgc_env.wt.entity.vo.SdYearDetailVO; import com.yfd.platform.qgc_env.wt.entity.vo.SttpInfoVo; import com.yfd.platform.qgc_env.wt.entity.vo.WbsbVo; +import com.yfd.platform.qgc_env.wt.entity.vo.WtvtDefaultStcdVo; import com.yfd.platform.qgc_env.wt.entity.vo.WtBaseInfoVo; import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendSaveVo; import com.yfd.platform.qgc_env.wt.entity.vo.WtrvVo; @@ -58,6 +59,11 @@ public interface SdWtMonitorService { DataSourceResult getEngTempPointListKendoListCust(DataSourceRequest dataSourceRequest); + /** + * 查询水温指定时间有数据的站点(垂向水温) + */ + List getWtvtDefaultStcd(DataSourceRequest dataSourceRequest); + /** * 获取监测点水温变化默认有数据的断面 */ diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java index 0b5d9ac6..c4f98b49 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java @@ -3101,6 +3101,133 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { }; } + @Override + public List getWtvtDefaultStcd(DataSourceRequest dataSourceRequest) { + if (dataSourceRequest == null) { + return new ArrayList<>(); + } + + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String tm = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + String mway = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "mway"); + String baseId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String rstcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String year = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "year"); + + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + + if (StrUtil.isNotBlank(year)) { + // ==================== 电站专题-垂向水温 ==================== + sql.append("SELECT t1.STCD AS stcd, t1.STNM AS stnm, ") + .append("t1.LGTD AS lgtd, t1.LTTD AS lttd, ") + .append("sb.WT_DEVICE_TYPE AS wtDeviceType ") + .append("FROM V_MS_STBPRP_T t1 ") + .append("INNER JOIN SD_WTVTDRTP_S t2 ON t1.STCD = t2.STCD ") + .append("LEFT JOIN SD_WT_B_H sb ON t1.STCD = sb.STCD ") + .append("WHERE t1.STTP_CODE = 'WTVT' AND t1.USFL = 1 ") + .append("AND t2.WTHG IS NOT NULL AND t2.VWT IS NOT NULL ") + .append("AND NVL(t2.IS_DELETED, 0) = 0 ") + .append("AND t2.DRTP = 'YEAR' ") + .append("AND t2.YEAR = #{map.year} "); + paramMap.put("year", year); + + if (StrUtil.isNotBlank(mway)) { + sql.append("AND t1.MWAY = #{map.mway} "); + paramMap.put("mway", mway); + } + if (StrUtil.isNotBlank(baseId)) { + sql.append("AND t1.BASE_ID = #{map.baseId} "); + paramMap.put("baseId", baseId); + } + if (StrUtil.isNotBlank(rstcd)) { + sql.append("AND t1.RSTCD = #{map.rstcd} "); + paramMap.put("rstcd", rstcd); + } + + sql.append("GROUP BY t1.STCD, t1.STNM, t1.LTTD, t1.LGTD, sb.WT_DEVICE_TYPE"); + + return microservicDynamicSQLMapper.getAllListWithResultType( + sql.toString(), paramMap, WtvtDefaultStcdVo.class); + + } else { + // ==================== 水温管理-垂向水温 ==================== + // 查询有数据的垂向水温测站(年度维度) + List hasDataWtvtList = new ArrayList<>(); + String dataSql = "SELECT DISTINCT STCD FROM SD_WTVTDRTP_S " + + "WHERE DRTP = 'YEAR' AND NVL(IS_DELETED, 0) = 0 " + + "AND VWT IS NOT NULL AND WTHG IS NOT NULL"; + List> wtvtList = microservicDynamicSQLMapper.getAllList(dataSql, null); + if (wtvtList != null && !wtvtList.isEmpty()) { + for (Map row : wtvtList) { + Object stcdObj = row.get("STCD"); + if (stcdObj != null) { + hasDataWtvtList.add(String.valueOf(stcdObj)); + } + } + } + if (hasDataWtvtList.isEmpty()) { + return new ArrayList<>(); + } + + // 解析时间范围 + String startTime = ""; + String endTime = ""; + if (StrUtil.isNotBlank(tm)) { + String[] tmList = tm.split(","); + startTime = tmList[0]; + endTime = tmList[1]; + } + + sql.append("SELECT * FROM ( "); + sql.append("SELECT t1.STCD AS stcd, t1.STNM AS stnm, ") + .append("t1.LGTD AS lgtd, t1.LTTD AS lttd, ") + .append("t1.BASE_ID AS baseId, t1.BASESTEPSORT AS baseStepSort, ") + .append("t1.SITESTEPSORT AS siteStepSort, t1.rstcdStepSort AS rstcdStepSort, ") + .append("sb.WT_DEVICE_TYPE AS wtDeviceType, ") + .append("CASE WHEN t3.SORT IS NULL THEN -1 ELSE t3.SORT END AS SORT ") + .append("FROM V_MS_STBPRP_T t1 ") + .append("LEFT JOIN (SELECT DISTINCT STCD, 1 AS SORT FROM SD_WTVTDAY_S "); + if (StrUtil.isNotBlank(startTime)) { + sql.append("WHERE DT >= TO_TIMESTAMP(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS') ") + .append("AND DT <= TO_TIMESTAMP(#{map.endTime}, 'YYYY-MM-DD HH24:MI:SS') ") + .append("AND NVL(IS_DELETED, 0) = 0 "); + paramMap.put("startTime", startTime); + paramMap.put("endTime", endTime); + } else { + sql.append("WHERE NVL(IS_DELETED, 0) = 0 "); + } + sql.append(") t3 ON t1.STCD = t3.STCD ") + .append("LEFT JOIN SD_WT_B_H sb ON t1.STCD = sb.STCD ") + .append("WHERE t1.STTP_CODE = 'WTVT' AND t1.USFL = 1 "); + + if (StrUtil.isNotBlank(mway)) { + sql.append("AND t1.MWAY = #{map.mway} "); + paramMap.put("mway", mway); + } + if (StrUtil.isNotBlank(baseId)) { + sql.append("AND t1.BASE_ID = #{map.baseId} "); + paramMap.put("baseId", baseId); + } + + sql.append("GROUP BY t1.STCD, t1.STNM, t1.LTTD, t1.LGTD, t1.BASE_ID, ") + .append("t1.BASESTEPSORT, t1.SITESTEPSORT, t1.rstcdStepSort, t3.SORT, sb.WT_DEVICE_TYPE "); + sql.append(") ORDER BY baseStepSort ASC, rstcdStepSort ASC, siteStepSort ASC, SORT DESC"); + + List resultList = microservicDynamicSQLMapper + .getAllListWithResultType(sql.toString(), paramMap, WtvtDefaultStcdVo.class); + + // 用 hasDataWtvtList 过滤有数据的测站 + if (resultList != null) { + resultList = resultList.stream() + .filter(vo -> hasDataWtvtList.contains(vo.getStcd())) + .collect(java.util.stream.Collectors.toList()); + } + + return resultList != null ? resultList : new ArrayList<>(); + } + } + @Override public DataSourceResult getWtRV(DataSourceRequest dataSourceRequest) { DataSourceResult result = new DataSourceResult<>(); From 11db0be2920d20e0eb76bf3ec5ece068a92f22a3 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 10:10:26 +0800 Subject: [PATCH 11/44] =?UTF-8?q?fix:=20=E6=96=B0=E5=A2=9E=E6=B0=B4?= =?UTF-8?q?=E6=B8=A9=E7=AB=99=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SdAiboxBHServiceImpl.java | 11 ++++ .../impl/SdAimonitorBHServiceImpl.java | 15 +++-- .../service/impl/SdArtsgBHServiceImpl.java | 11 +++- .../service/impl/SdDwBHServiceImpl.java | 15 +++-- .../service/impl/SdEngInfoBHServiceImpl.java | 9 +++ .../service/impl/SdEqBHServiceImpl.java | 15 +++-- .../service/impl/SdFbrdBHServiceImpl.java | 11 +++- .../service/impl/SdFhbtBHServiceImpl.java | 15 +++-- .../service/impl/SdFpssBHServiceImpl.java | 15 +++-- .../service/impl/SdOpinfoBHServiceImpl.java | 15 +++-- .../service/impl/SdOtteBHServiceImpl.java | 11 +++- .../service/impl/SdOtweBHServiceImpl.java | 11 +++- .../service/impl/SdSonarBHServiceImpl.java | 15 +++-- .../service/impl/SdTeBHServiceImpl.java | 11 +++- .../service/impl/SdVaBHServiceImpl.java | 15 +++-- .../service/impl/SdVdinfoBServiceImpl.java | 10 +++- .../service/impl/SdVpBHServiceImpl.java | 15 +++-- .../service/impl/SdWeBHServiceImpl.java | 11 +++- .../service/impl/SdWqBHServiceImpl.java | 15 +++-- .../service/impl/SdWtBHServiceImpl.java | 15 +++-- .../platform/utils/StcdUniqueValidator.java | 56 +++++++++++++++++++ 21 files changed, 255 insertions(+), 62 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/utils/StcdUniqueValidator.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAiboxBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAiboxBHServiceImpl.java index ed8fdd92..e44b24d4 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAiboxBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAiboxBHServiceImpl.java @@ -1,9 +1,11 @@ package com.yfd.platform.qgc_base.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdAiboxBH; import com.yfd.platform.qgc_base.mapper.SdAiboxBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; @@ -12,6 +14,7 @@ import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.StcdUniqueValidator; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,6 +34,9 @@ public class SdAiboxBHServiceImpl extends ServiceImpl @@ -71,6 +77,11 @@ public class SdAiboxBHServiceImpl extends ServiceImpl CODE_TO_NAME_META_LIST = new ArrayList<>(); static { @@ -57,6 +57,11 @@ public class SdAimonitorBHServiceImpl extends ServiceImpl @@ -64,6 +68,11 @@ public class SdArtsgBHServiceImpl extends ServiceImpl impleme @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -66,6 +66,11 @@ public class SdDwBHServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdDwBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 0ae3d892..597827e0 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -23,6 +23,7 @@ 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.common.exception.BizException; import com.yfd.platform.qgc_base.domain.vo.*; import com.yfd.platform.qgc_data.domain.SysUserDataScope; import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper; @@ -134,6 +135,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl impleme @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -66,6 +66,11 @@ public class SdEqBHServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdEqBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFbrdBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFbrdBHServiceImpl.java index 976942db..0e78c200 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFbrdBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFbrdBHServiceImpl.java @@ -1,8 +1,10 @@ package com.yfd.platform.qgc_base.service.impl; +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.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdFbrdBH; import com.yfd.platform.qgc_base.mapper.SdFbrdBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; @@ -10,6 +12,7 @@ import com.yfd.platform.qgc_base.service.ISdFbrdBHService; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; +import com.yfd.platform.utils.StcdUniqueValidator; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,7 +30,8 @@ public class SdFbrdBHServiceImpl extends ServiceImpl i @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -63,6 +67,11 @@ public class SdFbrdBHServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdFbrdBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFhbtBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFhbtBHServiceImpl.java index b4949034..c6d4f7c9 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFhbtBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFhbtBHServiceImpl.java @@ -1,17 +1,16 @@ package com.yfd.platform.qgc_base.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdFhbtBH; import com.yfd.platform.qgc_base.mapper.SdFhbtBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdFhbtBHService; -import com.yfd.platform.utils.CodeToNameMetadataBo; -import com.yfd.platform.utils.DataSourceRequestUtil; -import com.yfd.platform.utils.DictCodeToNameConverter; -import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -30,7 +29,8 @@ public class SdFhbtBHServiceImpl extends ServiceImpl i @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -67,6 +67,11 @@ public class SdFhbtBHServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdFhbtBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java index 3a09c579..a0ac0133 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java @@ -1,10 +1,12 @@ package com.yfd.platform.qgc_base.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdEngInfoBH; import com.yfd.platform.qgc_base.domain.SdFpssBH; import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; @@ -14,10 +16,7 @@ import com.yfd.platform.qgc_base.service.ISdFpssBHService; import com.yfd.platform.qgc_data.domain.SysUserDataScope; import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper; import com.yfd.platform.system.service.IAdminAuthService; -import com.yfd.platform.utils.CodeToNameMetadataBo; -import com.yfd.platform.utils.DataSourceRequestUtil; -import com.yfd.platform.utils.DictCodeToNameConverter; -import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @@ -42,7 +41,8 @@ public class SdFpssBHServiceImpl extends ServiceImpl i @Resource private IMsOperationLogService msOperationLogService; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -213,6 +213,11 @@ public class SdFpssBHServiceImpl extends ServiceImpl i @Override public boolean add(SdFpssBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOpinfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOpinfoBHServiceImpl.java index d7d35a7e..8fc5ade3 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOpinfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOpinfoBHServiceImpl.java @@ -1,17 +1,16 @@ package com.yfd.platform.qgc_base.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdOpinfoBH; import com.yfd.platform.qgc_base.mapper.SdOpinfoBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdOpinfoBHService; -import com.yfd.platform.utils.CodeToNameMetadataBo; -import com.yfd.platform.utils.DataSourceRequestUtil; -import com.yfd.platform.utils.DictCodeToNameConverter; -import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -30,7 +29,8 @@ public class SdOpinfoBHServiceImpl extends ServiceImpl @@ -67,6 +67,11 @@ public class SdOpinfoBHServiceImpl extends ServiceImpl i @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -66,6 +70,11 @@ public class SdOtteBHServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdOtteBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtweBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtweBHServiceImpl.java index 266c4bb4..f7cadf09 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtweBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtweBHServiceImpl.java @@ -1,8 +1,10 @@ package com.yfd.platform.qgc_base.service.impl; +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.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdOtweBH; import com.yfd.platform.qgc_base.mapper.SdOtweBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; @@ -10,6 +12,7 @@ import com.yfd.platform.qgc_base.service.ISdOtweBHService; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; +import com.yfd.platform.utils.StcdUniqueValidator; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,7 +29,8 @@ public class SdOtweBHServiceImpl extends ServiceImpl i private IMsOperationLogService msOperationLogService; @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -64,6 +68,11 @@ public class SdOtweBHServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdOtweBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdSonarBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdSonarBHServiceImpl.java index 24438e9a..b1a5c16c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdSonarBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdSonarBHServiceImpl.java @@ -1,17 +1,16 @@ package com.yfd.platform.qgc_base.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdSonarBH; import com.yfd.platform.qgc_base.mapper.SdSonarBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdSonarBHService; -import com.yfd.platform.utils.CodeToNameMetadataBo; -import com.yfd.platform.utils.DataSourceRequestUtil; -import com.yfd.platform.utils.DictCodeToNameConverter; -import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,7 +28,8 @@ public class SdSonarBHServiceImpl extends ServiceImpl @@ -69,6 +69,11 @@ public class SdSonarBHServiceImpl extends ServiceImpl impleme private IMsOperationLogService msOperationLogService; @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -64,6 +68,11 @@ public class SdTeBHServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdTeBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVaBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVaBHServiceImpl.java index 3e81ad52..74c4c63a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVaBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVaBHServiceImpl.java @@ -1,17 +1,16 @@ package com.yfd.platform.qgc_base.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdVaBH; import com.yfd.platform.qgc_base.mapper.SdVaBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdVaBHService; -import com.yfd.platform.utils.CodeToNameMetadataBo; -import com.yfd.platform.utils.DataSourceRequestUtil; -import com.yfd.platform.utils.DictCodeToNameConverter; -import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,7 +28,8 @@ public class SdVaBHServiceImpl extends ServiceImpl impleme private IMsOperationLogService msOperationLogService; @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -65,6 +65,11 @@ public class SdVaBHServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdVaBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVdinfoBServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVdinfoBServiceImpl.java index 02d1be85..0f43ff9b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVdinfoBServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVdinfoBServiceImpl.java @@ -4,6 +4,7 @@ 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.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdVdinfoB; import com.yfd.platform.qgc_base.mapper.SdVdinfoBMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; @@ -11,6 +12,7 @@ import com.yfd.platform.qgc_base.service.ISdVdinfoBService; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; +import com.yfd.platform.utils.StcdUniqueValidator; import jakarta.annotation.Resource; import org.checkerframework.checker.units.qual.C; import org.springframework.stereotype.Service; @@ -28,7 +30,8 @@ public class SdVdinfoBServiceImpl extends ServiceImpl @@ -67,6 +70,11 @@ public class SdVdinfoBServiceImpl extends ServiceImpl impleme private IMsOperationLogService msOperationLogService; @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -65,6 +65,11 @@ public class SdVpBHServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdVpBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWeBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWeBHServiceImpl.java index 63c4040d..a95bcbe2 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWeBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWeBHServiceImpl.java @@ -1,8 +1,10 @@ package com.yfd.platform.qgc_base.service.impl; +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.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdWeBH; import com.yfd.platform.qgc_base.mapper.SdWeBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; @@ -10,6 +12,7 @@ import com.yfd.platform.qgc_base.service.ISdWeBHService; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; +import com.yfd.platform.utils.StcdUniqueValidator; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,7 +30,8 @@ public class SdWeBHServiceImpl extends ServiceImpl impleme @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -66,6 +70,11 @@ public class SdWeBHServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdWeBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWqBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWqBHServiceImpl.java index 1dbbf910..846dfc2a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWqBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWqBHServiceImpl.java @@ -1,17 +1,16 @@ package com.yfd.platform.qgc_base.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdWqBH; import com.yfd.platform.qgc_base.mapper.SdWqBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdWqBHService; -import com.yfd.platform.utils.CodeToNameMetadataBo; -import com.yfd.platform.utils.DataSourceRequestUtil; -import com.yfd.platform.utils.DictCodeToNameConverter; -import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -30,7 +29,8 @@ public class SdWqBHServiceImpl extends ServiceImpl impleme @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -68,6 +68,11 @@ public class SdWqBHServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdWqBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWtBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWtBHServiceImpl.java index c179bc38..65af743a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWtBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWtBHServiceImpl.java @@ -1,18 +1,17 @@ package com.yfd.platform.qgc_base.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.domain.SdWtBH; import com.yfd.platform.qgc_base.mapper.SdWtBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdWtBHService; -import com.yfd.platform.utils.CodeToNameMetadataBo; -import com.yfd.platform.utils.DataSourceRequestUtil; -import com.yfd.platform.utils.DictCodeToNameConverter; -import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,7 +31,8 @@ public class SdWtBHServiceImpl extends ServiceImpl impleme @Resource private DictCodeToNameConverter dictCodeToNameConverter; - + @Resource + private StcdUniqueValidator stcdUniqueValidator; /** * 代码转名称元数据配置列表(静态初始化) *

@@ -70,6 +70,11 @@ public class SdWtBHServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) public boolean add(SdWtBH entity, String source) { + if (entity == null || StrUtil.isBlank(entity.getStcd())) { + throw new BizException("站点编码不能为空"); + } + // 检查 STCD 在 V_MS_STBPRP_T 视图中是否已存在 + stcdUniqueValidator.throwIfExists(entity.getStcd()); boolean result = this.save(entity); if (result) { dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); diff --git a/backend/src/main/java/com/yfd/platform/utils/StcdUniqueValidator.java b/backend/src/main/java/com/yfd/platform/utils/StcdUniqueValidator.java new file mode 100644 index 00000000..203736f4 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/utils/StcdUniqueValidator.java @@ -0,0 +1,56 @@ +package com.yfd.platform.utils; + +import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.common.exception.BizException; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * STCD 唯一性校验组件,通过 V_MS_STBPRP_T 视图跨所有站点类型校验 + *

+ * 使用方式:注入即可 + *

+ * {@code @Resource private StcdUniqueValidator stcdUniqueValidator;}
+ * {@code stcdUniqueValidator.throwIfExists(stcd);}
+ * 
+ */ +@Component +public class StcdUniqueValidator { + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + /** + * 校验 STCD 是否已在 V_MS_STBPRP_T 视图中存在,存在则抛异常 + * + * @param stcd 站点编码 + * @throws BizException 站点编码已存在时抛出 + */ + public void throwIfExists(String stcd) { + if (exists(stcd)) { + throw new BizException("当前站点编码已存在"); + } + } + + /** + * 检查 STCD 是否已在 V_MS_STBPRP_T 视图中存在 + * + * @param stcd 站点编码 + * @return true=已存在 + */ + public boolean exists(String stcd) { + String sql = "SELECT COUNT(1) AS cnt FROM V_MS_STBPRP_T WHERE STCD = #{map.stcd}"; + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + List> result = microservicDynamicSQLMapper.getAllList(sql, paramMap); + if (result != null && !result.isEmpty()) { + Object cntObj = result.get(0).get("CNT"); + return cntObj != null && Long.parseLong(cntObj.toString()) > 0; + } + return false; + } +} From d9cf63e993f4a053f87b484ac06144f05244aeeb Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 10:33:04 +0800 Subject: [PATCH 12/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SdEngInfoBHServiceImpl.java | 106 ++++++++---------- .../service/impl/SdWtMonitorServiceImpl.java | 4 +- 2 files changed, 47 insertions(+), 63 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 597827e0..425fa4bd 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -141,9 +141,6 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl queryPageList(Page page, String ennm, String rvcd, String baseId, String hycd) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -4095,18 +4092,31 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl sttpCodes = extractSttpCodesFromRequest(dataSourceRequest); - DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); - String sttpCode = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "sttpCode"); - if(StrUtil.isBlank(sttpCode)){ - result.setData(new ArrayList<>()); - result.setTotal(0L); - return result; + // 使用 buildFilterCondition 动态构建查询条件 + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapVmsFilterColumn + ); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT STCD AS stcd, STNM AS stnm, ") + .append("STTP_CODE AS sttpCode, STTP_NAME AS sttpName, ") + .append("MWAY AS mway, RSTCD AS rstcd, ENNM AS ennm, ") + .append("BASE_ID AS baseId, BASE_NAME AS baseName, ") + .append("NVL(RSTCDSTEPSORT, 999999) AS rstcdStepSort, ") + .append("NVL(ORDER_INDEX, 999999) AS orderIndex, ") + .append("LGTD AS lgtd, LTTD AS lttd ") + .append("FROM V_MS_STBPRP_T ") + .append("WHERE NVL(IS_DELETED, 0) = 0"); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql); } - // 查询 V_MS_STBPRP_T 视图 - List allItems = - vMsStbprpTMapper.selectBySttpCodes(List.of(sttpCode)); + sql.append(" ORDER BY NVL(RSTCDSTEPSORT, 999999), NVL(ORDER_INDEX, 999999)"); + + List allItems = microservicDynamicSQLMapper + .getAllListWithResultType(sql.toString(), paramMap, StcdItemVo.class); if (CollUtil.isEmpty(allItems)) { result.setData(new ArrayList<>()); @@ -4174,53 +4184,27 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl extractSttpCodesFromRequest(DataSourceRequest request) { - if (request == null || request.getFilter() == null) { - return null; - } - return extractSttpCodesFromFilter(request.getFilter()); - } - - private List extractSttpCodesFromFilter(DataSourceRequest.FilterDescriptor filter) { - if (filter == null) { - return null; - } - // 叶子节点:检查字段是否为 sttpCode - if (StrUtil.isNotBlank(filter.getField())) { - if ("sttpCode".equals(filter.getField()) || "sttp_code".equalsIgnoreCase(filter.getField())) { - if ("in".equalsIgnoreCase(filter.getOperator())) { - Object val = filter.getValue(); - if (val instanceof List list) { - return list.stream() - .filter(Objects::nonNull) - .map(Object::toString) - .filter(StrUtil::isNotBlank) - .map(String::trim) - .collect(Collectors.toList()); - } - if (val instanceof Object[] arr) { - return Arrays.stream(arr) - .filter(Objects::nonNull) - .map(Object::toString) - .filter(StrUtil::isNotBlank) - .map(String::trim) - .collect(Collectors.toList()); - } - } - } - return null; - } - // 递归子节点 - if (CollUtil.isNotEmpty(filter.getFilters())) { - for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { - List codes = extractSttpCodesFromFilter(child); - if (codes != null) { - return codes; - } - } - } - return null; + private String mapVmsFilterColumn(String field) { + if (field == null) return null; + return switch (field) { + case "stcd" -> "STCD"; + case "stnm" -> "STNM"; + case "sttpCode", "sttp_code" -> "STTP_CODE"; + case "sttpName", "sttp_name" -> "STTP_NAME"; + case "mway" -> "MWAY"; + case "rstcd" -> "RSTCD"; + case "ennm" -> "ENNM"; + case "baseId", "base_id" -> "BASE_ID"; + case "baseName", "base_name" -> "BASE_NAME"; + case "fhstcd" -> "FHSTCD"; + case "lgtd" -> "LGTD"; + case "lttd" -> "LTTD"; + case "orderIndex", "order_index" -> "ORDER_INDEX"; + case "rstcdStepSort", "rstcdstepsort" -> "RSTCDSTEPSORT"; + case "isDeleted", "is_deleted" -> "IS_DELETED"; + default -> null; + }; } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java index c4f98b49..687b983b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java @@ -3375,7 +3375,7 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { // 前端排序 List sort = dataSourceRequest.getSort(); if (sort != null && !sort.isEmpty()) { - sql.append(") ORDER BY "); + sql.append(") WHERE ROWNUM = 1 ORDER BY "); for (int i = 0; i < sort.size(); i++) { sql.append(sort.get(i).getField()).append(" ").append(sort.get(i).getDir()); if (i < sort.size() - 1) { @@ -3385,7 +3385,7 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { } else { sql.append(")"); } - sql.append(" WHERE ROWNUM = 1"); + List dataList = microservicDynamicSQLMapper .pageAllListWithResultType(null, sql.toString(), null, WtrvDefaultStcdVo.class); From 8e70007bd3e746b04daa3fc121795023f28c9a88 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 11:55:57 +0800 Subject: [PATCH 13/44] =?UTF-8?q?fix:=E8=BF=87=E9=B1=BC=E6=95=B0=E9=87=8F?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=9C=89=E6=95=B0=E6=8D=AE=E7=9A=84=E6=B5=8B?= =?UTF-8?q?=E7=AB=99=E6=A0=91=E5=BD=A2=E4=B8=8B=E6=8B=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdEngMonitorController.java | 7 ++ .../fp/controller/FishPassageController.java | 6 ++ .../fp/entity/vo/FpTreeStcdGroupVo.java | 24 ++++++ .../qgc_env/fp/entity/vo/FpTreeStcdVo.java | 36 +++++++++ .../qgc_env/fp/service/FpRunService.java | 3 + .../fp/service/impl/FpRunServiceImpl.java | 81 +++++++++++++++++++ .../mapLayer/mapper/MsMapmoduleBMapper.java | 2 +- 7 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTreeStcdGroupVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTreeStcdVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java index 501965bb..82432c41 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java @@ -84,4 +84,11 @@ public class SdEngMonitorController { DataSourceResult result = engInfoBHService.getEngTreeByAlong(dataSourceRequest); return ResponseResult.successData(result); } + + @PostMapping("/vmsstbprpt/engTree/GetKendoList") + @Operation(summary = "沿程对象视图 树形结构数据信息 电站沿程排序") + public ResponseResult getVmsstbprptEngTreeKendoList(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = engInfoBHService.getEngTreeByAlong(dataSourceRequest); + return ResponseResult.successData(result); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java index dd46b13d..e5f1f215 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java @@ -130,4 +130,10 @@ public class FishPassageController { public ResponseResult getYearFpStatic(@RequestParam("year") String year,@RequestParam(value = "stcd",required = false) String stcd) { return ResponseResult.successData(fpRunService.getYearFpStatic(year,stcd)); } + + @PostMapping("/query/getTreeStcdList") + @Operation(summary = "过鱼数量获取有数据的测站树形下拉") + public ResponseResult getTreeStcdList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fpRunService.getTreeStcdList(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTreeStcdGroupVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTreeStcdGroupVo.java new file mode 100644 index 00000000..35e8712c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTreeStcdGroupVo.java @@ -0,0 +1,24 @@ +package com.yfd.platform.qgc_env.fp.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * 过鱼设施测站树形分组 VO(按 RSTCD 分组) + */ +@Data +@Schema(description = "过鱼设施测站树形分组") +public class FpTreeStcdGroupVo { + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "测站列表") + private List items = new ArrayList<>(); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTreeStcdVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTreeStcdVo.java new file mode 100644 index 00000000..d61719ec --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTreeStcdVo.java @@ -0,0 +1,36 @@ +package com.yfd.platform.qgc_env.fp.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 过鱼设施测站条目 VO + */ +@Data +@Schema(description = "过鱼设施测站条目") +public class FpTreeStcdVo { + + @Schema(description = "测站编码") + private String stcd; + + @Schema(description = "测站名称") + private String stnm; + + @Schema(description = "监测方式:1=人工 2=自动") + private Integer mway; + + @Schema(description = "经度") + private String lgtd; + + @Schema(description = "纬度") + private String lttd; + + @Schema(description = "所属基地编码") + private String baseId; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String ennm; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java index 77a40565..14e24b26 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java @@ -8,6 +8,7 @@ import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQueryVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunAnalysisTableVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpSdfpssrVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpTableVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpTreeStcdGroupVo; import com.yfd.platform.qgc_env.fp.entity.vo.YearFpStatisticsVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunPlanVo; @@ -32,4 +33,6 @@ public interface FpRunService { DataSourceResult getFishSelect(DataSourceRequest dataSourceRequest); List getYearFpStatic(String year,String stcd); + + DataSourceResult getTreeStcdList(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index f0e2b67f..b4abe1df 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -23,6 +23,8 @@ import com.yfd.platform.qgc_env.fp.entity.vo.FpRunAnalysisVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunPlanVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpSdfpssrVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpTableVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpTreeStcdGroupVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpTreeStcdVo; import com.yfd.platform.qgc_env.fp.entity.vo.YearFpStatisticsVo; import com.yfd.platform.qgc_env.fp.service.FpRunService; import com.yfd.platform.utils.QgcQueryWrapperUtil; @@ -2734,4 +2736,83 @@ public class FpRunServiceImpl implements FpRunService { } return StrUtil.blankToDefault(StrUtil.trim(fallbackFishText), null); } + + @Override + public DataSourceResult getTreeStcdList(DataSourceRequest dataSourceRequest) { + // 查询 SD_FPSSRL_R(自动, MWAY=2)和 SD_FPSS_R(人工, MWAY=1)中有过鱼数据的测站 + // 关联 V_MS_STBPRP_T 视图获取测站基础信息(含 ENNM 电站名称) + String sql = "SELECT STCD, STNM, MWAY, LGTD, LTTD, BASE_ID, RSTCD, ENNM " + + "FROM (" + + " SELECT DISTINCT t2.STCD, t2.STNM, t2.BASE_ID, t2.RSTCD, t2.LGTD, t2.LTTD, t2.MWAY, t2.ENNM " + + " FROM SD_FPSSRL_R t1 " + + " INNER JOIN V_MS_STBPRP_T t2 ON t1.STCD = t2.STCD " + + " WHERE NVL(t2.IS_DELETED, 0) = 0 AND t2.MWAY = 2 AND t1.FTP IS NOT NULL " + + " UNION " + + " SELECT DISTINCT t4.STCD, t4.STNM, t4.BASE_ID, t4.RSTCD, t4.LGTD, t4.LTTD, t4.MWAY, t4.ENNM " + + " FROM SD_FPSS_R t3 " + + " INNER JOIN V_MS_STBPRP_T t4 ON t3.STCD = t4.STCD " + + " WHERE NVL(t4.IS_DELETED, 0) = 0 AND t4.MWAY = 1 AND t3.FTP IS NOT NULL " + + " AND NVL(t3.IS_DELETED, 0) = 0" + + ")"; + + Map paramMap = new HashMap<>(); + List allItems = microservicDynamicSQLMapper + .getAllListWithResultType(sql, paramMap, FpTreeStcdVo.class); + + if (CollUtil.isEmpty(allItems)) { + DataSourceResult emptyResult = new DataSourceResult<>(); + emptyResult.setData(new ArrayList<>()); + emptyResult.setTotal(0L); + emptyResult.setAggregates(new HashMap<>()); + return emptyResult; + } + + // 按 RSTCD 分组,构建树形结构 + Map groupedMap = new LinkedHashMap<>(); + for (FpTreeStcdVo item : allItems) { + String rstcd = StrUtil.blankToDefault(item.getRstcd(), ""); + if (rstcd.contains(",")) { + // 处理逗号分隔的多个 RSTCD + for (String singleRstcd : rstcd.split(",")) { + String r = singleRstcd.trim(); + if (StrUtil.isNotBlank(r)) { + groupedMap.computeIfAbsent(r, k -> { + FpTreeStcdGroupVo group = new FpTreeStcdGroupVo(); + group.setRstcd(r); + group.setEnnm(item.getEnnm()); + return group; + }).getItems().add(item); + } + } + } else if (StrUtil.isNotBlank(rstcd)) { + groupedMap.computeIfAbsent(rstcd, k -> { + FpTreeStcdGroupVo group = new FpTreeStcdGroupVo(); + group.setRstcd(rstcd); + group.setEnnm(item.getEnnm()); + return group; + }).getItems().add(item); + } else { + groupedMap.computeIfAbsent("other", k -> { + FpTreeStcdGroupVo group = new FpTreeStcdGroupVo(); + group.setRstcd("other"); + group.setEnnm("其它"); + return group; + }).getItems().add(item); + } + } + + List resultList = new ArrayList<>(groupedMap.values()); + // 按 RSTCD 排序,other 排最后 + resultList.sort((a, b) -> { + if ("other".equals(a.getRstcd())) return 1; + if ("other".equals(b.getRstcd())) return -1; + return a.getRstcd().compareTo(b.getRstcd()); + }); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(resultList); + result.setTotal(resultList.size()); + result.setAggregates(new HashMap<>()); + return result; + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_sys/mapLayer/mapper/MsMapmoduleBMapper.java b/backend/src/main/java/com/yfd/platform/qgc_sys/mapLayer/mapper/MsMapmoduleBMapper.java index 96a9e23c..b257ef1e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_sys/mapLayer/mapper/MsMapmoduleBMapper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_sys/mapLayer/mapper/MsMapmoduleBMapper.java @@ -28,7 +28,7 @@ public interface MsMapmoduleBMapper extends BaseMapper { + "BML.PARAMJSON AS paramJson, BML.URL, BML.URL_THD AS urlThd, BML.OPACITY, BML.SYSTEM_ID AS systemId, " + "BML.OPTIONS, BMM.MULTI_SELECT AS multiSelect, BMM.CAN_BE_CHECKED AS canBeChecked, " + "CASE WHEN BMM.CHECKED IS NULL THEN 0 ELSE BMM.CHECKED END AS checked, BML.ORDER_INDEX " - + "FROM MS_MAPLAYER_B BML LEFT JOIN MS_MAPMODULE_B BMM ON BML.ID = BMM.RES_ID " + + "FROM MS_MAPLAYER_B BML LEFT JOIN MS_MAPMODULE_B BMM ON BML.ID = BMM.RES_ID AND BMM.IS_DELETED = 0" + " AND BMM.MODULE_ID = #{moduleId}" + " AND BMM.SYSTEM_ID = #{sid}" + "" From a3618ba68889e1e241901853fe67c13a9fa9362f Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 13:34:57 +0800 Subject: [PATCH 14/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E7=94=9F?= =?UTF-8?q?=E6=80=81=E6=B5=81=E9=87=8F=E6=9F=A5=E8=AF=A2=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=85=A8=E5=A4=A7=E5=86=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SdEngInfoBHServiceImpl.java | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 425fa4bd..5f909236 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -822,7 +822,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl> rows = microservicDynamicSQLMapper.pageAllList(page, sql, paramMap); List list = new ArrayList<>(); for (Map row : rows) { - list.add(new EngStbprpDataVo(row)); + list.add(new EngStbprpDataVo(convertKeysToCamelCase(row))); } result.setData(list); result.setTotal(page == null ? list.size() : page.getTotal()); @@ -832,15 +832,44 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl> rows = microservicDynamicSQLMapper.pageAllList(null, groupSql, paramMap); + List> camelRows = new ArrayList<>(); + for (Map row : rows) { + camelRows.add(convertKeysToCamelCase(row)); + } if (Boolean.TRUE.equals(request.getGroupResultFlat())) { - result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + result.setData((List) (List) new GroupHelper().faltGroup(camelRows, Arrays.asList(groupInfos))); } else { - result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + result.setData((List) (List) new GroupHelper().group(camelRows, Arrays.asList(groupInfos))); } result.setTotal((long) rows.size()); return result; } + /** + * 将 Map 的 key 从 ORACLE 大写/下划线格式转为 camelCase + */ + private Map convertKeysToCamelCase(Map row) { + if (CollUtil.isEmpty(row)) { + return row; + } + Map result = new LinkedHashMap<>(row.size()); + for (Map.Entry entry : row.entrySet()) { + String key = entry.getKey(); + if (key == null) { + result.put(null, entry.getValue()); + continue; + } + // 如果已经是小写开头,说明已经是 camelCase,跳过转换 + if (Character.isLowerCase(key.charAt(0))) { + result.put(key, entry.getValue()); + continue; + } + String camelKey = StrUtil.toCamelCase(key.toLowerCase()); + result.put(camelKey, entry.getValue()); + } + return result; + } + private DataSourceResult queryOperatSummaryList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); From 7cc2ff67980784cf69fc39baf9b2f82a9704e08b Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 15:05:47 +0800 Subject: [PATCH 15/44] =?UTF-8?q?fix:=20=E6=A0=B9=E6=8D=AE=E7=AB=99?= =?UTF-8?q?=E7=A0=81=E4=BF=AE=E6=94=B9=E4=BF=AE=E6=94=B9=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdAiboxBHController.java | 5 +- .../controller/SdAimonitorBHController.java | 6 +- .../controller/SdArtsgBHController.java | 5 +- .../qgc_base/controller/SdDwBHController.java | 5 +- .../qgc_base/controller/SdEqBHController.java | 5 +- .../controller/SdFbrdBHController.java | 5 +- .../controller/SdFhbtBHController.java | 5 +- .../controller/SdFpssBHController.java | 5 +- .../controller/SdOpinfoBHController.java | 5 +- .../controller/SdOtteBHController.java | 5 +- .../controller/SdOtweBHController.java | 5 +- .../controller/SdSonarBHController.java | 5 +- .../qgc_base/controller/SdTeBHController.java | 5 +- .../qgc_base/controller/SdVaBHController.java | 5 +- .../controller/SdVdinfoBController.java | 5 +- .../qgc_base/controller/SdVpBHController.java | 5 +- .../qgc_base/controller/SdWeBHController.java | 5 +- .../qgc_base/controller/SdWqBHController.java | 5 +- .../qgc_base/controller/SdWtBHController.java | 5 +- .../qgc_base/service/ISdAiboxBHService.java | 2 + .../service/ISdAimonitorBHService.java | 2 + .../qgc_base/service/ISdArtsgBHService.java | 2 + .../qgc_base/service/ISdDwBHService.java | 2 + .../qgc_base/service/ISdEqBHService.java | 2 + .../qgc_base/service/ISdFbrdBHService.java | 2 + .../qgc_base/service/ISdFhbtBHService.java | 2 + .../qgc_base/service/ISdFpssBHService.java | 2 + .../qgc_base/service/ISdOpinfoBHService.java | 2 + .../qgc_base/service/ISdOtteBHService.java | 2 + .../qgc_base/service/ISdOtweBHService.java | 2 + .../qgc_base/service/ISdSonarBHService.java | 2 + .../qgc_base/service/ISdTeBHService.java | 2 + .../qgc_base/service/ISdVaBHService.java | 2 + .../qgc_base/service/ISdVdinfoBService.java | 2 + .../qgc_base/service/ISdVpBHService.java | 2 + .../qgc_base/service/ISdWeBHService.java | 2 + .../qgc_base/service/ISdWqBHService.java | 2 + .../service/impl/PatchUpdateHelper.java | 121 ++++++++++++++++++ .../service/impl/SdAiboxBHServiceImpl.java | 18 ++- .../impl/SdAimonitorBHServiceImpl.java | 19 ++- .../service/impl/SdArtsgBHServiceImpl.java | 18 ++- .../service/impl/SdDwBHServiceImpl.java | 19 ++- .../service/impl/SdEngInfoBHServiceImpl.java | 32 ++--- .../service/impl/SdEqBHServiceImpl.java | 19 ++- .../service/impl/SdFbrdBHServiceImpl.java | 18 ++- .../service/impl/SdFhbtBHServiceImpl.java | 19 ++- .../service/impl/SdFpssBHServiceImpl.java | 16 +++ .../service/impl/SdOpinfoBHServiceImpl.java | 19 ++- .../service/impl/SdOtteBHServiceImpl.java | 18 ++- .../service/impl/SdOtweBHServiceImpl.java | 18 ++- .../service/impl/SdSonarBHServiceImpl.java | 19 ++- .../service/impl/SdTeBHServiceImpl.java | 18 ++- .../service/impl/SdVaBHServiceImpl.java | 19 ++- .../service/impl/SdVdinfoBServiceImpl.java | 19 ++- .../service/impl/SdVpBHServiceImpl.java | 20 ++- .../service/impl/SdWeBHServiceImpl.java | 18 ++- .../service/impl/SdWqBHServiceImpl.java | 21 ++- .../service/impl/SdWtBHServiceImpl.java | 20 ++- 58 files changed, 511 insertions(+), 129 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/service/impl/PatchUpdateHelper.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAiboxBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAiboxBHController.java index dee34d42..60f49177 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAiboxBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAiboxBHController.java @@ -40,9 +40,8 @@ public class SdAiboxBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdAiboxBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdAiboxBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAimonitorBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAimonitorBHController.java index 6b243a40..313ad157 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAimonitorBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAimonitorBHController.java @@ -44,10 +44,8 @@ public class SdAimonitorBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdAimonitorBH entity = request == null || request.getEngInfo() == null ? null - : objectMapper.convertValue(request.getEngInfo(), SdAimonitorBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdArtsgBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdArtsgBHController.java index a467ed80..66bf3459 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdArtsgBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdArtsgBHController.java @@ -40,9 +40,8 @@ public class SdArtsgBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdArtsgBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdArtsgBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdDwBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdDwBHController.java index ab2f4f9e..190b5103 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdDwBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdDwBHController.java @@ -40,9 +40,8 @@ public class SdDwBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdDwBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdDwBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEqBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEqBHController.java index c303cab1..0a2ba725 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEqBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEqBHController.java @@ -40,9 +40,8 @@ public class SdEqBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdEqBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdEqBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFbrdBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFbrdBHController.java index 6bd460f5..89a4119e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFbrdBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFbrdBHController.java @@ -40,9 +40,8 @@ public class SdFbrdBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdFbrdBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdFbrdBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFhbtBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFhbtBHController.java index b5b12836..735d7106 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFhbtBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFhbtBHController.java @@ -40,9 +40,8 @@ public class SdFhbtBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdFhbtBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdFhbtBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssBHController.java index 9089ba20..037b0da3 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssBHController.java @@ -89,9 +89,8 @@ public class SdFpssBHController { @Log(module = "过鱼设施管理", value = "修改过鱼设施") @PostMapping("/update") @Operation(summary = "修改过鱼设施") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdFpssBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdFpssBH.class); - boolean result = sdFpssBHService.updateById(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = sdFpssBHService.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOpinfoBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOpinfoBHController.java index 4a0f2cd1..a47d3826 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOpinfoBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOpinfoBHController.java @@ -40,9 +40,8 @@ public class SdOpinfoBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdOpinfoBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdOpinfoBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOtteBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOtteBHController.java index c425bca7..9e12585a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOtteBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOtteBHController.java @@ -40,9 +40,8 @@ public class SdOtteBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdOtteBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdOtteBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOtweBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOtweBHController.java index 5311661f..f5ff3740 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOtweBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdOtweBHController.java @@ -40,9 +40,8 @@ public class SdOtweBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdOtweBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdOtweBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdSonarBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdSonarBHController.java index 4c325387..71189278 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdSonarBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdSonarBHController.java @@ -40,9 +40,8 @@ public class SdSonarBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdSonarBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdSonarBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdTeBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdTeBHController.java index ac1c4f52..c6cdb59a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdTeBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdTeBHController.java @@ -40,9 +40,8 @@ public class SdTeBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdTeBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdTeBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVaBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVaBHController.java index d9b79767..6c98dbbc 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVaBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVaBHController.java @@ -40,9 +40,8 @@ public class SdVaBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdVaBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdVaBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVdinfoBController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVdinfoBController.java index c6063d42..40451528 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVdinfoBController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVdinfoBController.java @@ -40,9 +40,8 @@ public class SdVdinfoBController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdVdinfoB entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdVdinfoB.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVpBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVpBHController.java index 879820a8..bc82d44f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVpBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdVpBHController.java @@ -40,9 +40,8 @@ public class SdVpBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdVpBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdVpBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWeBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWeBHController.java index 84d45831..1c3c3c21 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWeBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWeBHController.java @@ -40,9 +40,8 @@ public class SdWeBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdWeBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdWeBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWqBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWqBHController.java index c185b9ef..3dedefc1 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWqBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWqBHController.java @@ -40,9 +40,8 @@ public class SdWqBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdWqBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdWqBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWtBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWtBHController.java index 996cab76..2eb6d5c9 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWtBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdWtBHController.java @@ -40,9 +40,8 @@ public class SdWtBHController { @PostMapping("/update") @Operation(summary = "修改") - public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { - SdWtBH entity = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdWtBH.class); - boolean result = service.update(entity, request == null ? null : request.getSource()); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = service.update(request == null ? null : request.getEngInfo(), request == null ? null : request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAiboxBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAiboxBHService.java index 0999c581..87ae1d20 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAiboxBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAiboxBHService.java @@ -6,6 +6,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdAiboxBH; import java.util.List; +import java.util.Map; /** *

@@ -28,6 +29,7 @@ public interface ISdAiboxBHService extends IService { * 修改 */ boolean update(SdAiboxBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; /** * 删除 diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAimonitorBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAimonitorBHService.java index 8450be92..f07acedf 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAimonitorBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAimonitorBHService.java @@ -6,6 +6,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdAimonitorBH; import java.util.List; +import java.util.Map; /** * AI智能监测装置 Service 接口 @@ -14,5 +15,6 @@ public interface ISdAimonitorBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdAimonitorBH entity, String source); boolean update(SdAimonitorBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdArtsgBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdArtsgBHService.java index 11a57f77..ccaafc63 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdArtsgBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdArtsgBHService.java @@ -6,6 +6,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdArtsgBH; import java.util.List; +import java.util.Map; /** *

@@ -28,6 +29,7 @@ public interface ISdArtsgBHService extends IService { * 修改 */ boolean update(SdArtsgBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; /** * 删除 diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdDwBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdDwBHService.java index 9a793cc2..019aff3a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdDwBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdDwBHService.java @@ -6,6 +6,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdDwBH; import java.util.List; +import java.util.Map; /** *

@@ -28,6 +29,7 @@ public interface ISdDwBHService extends IService { * 修改 */ boolean update(SdDwBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; /** * 删除 diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEqBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEqBHService.java index 8d7f5cc5..dfac906a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEqBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEqBHService.java @@ -6,6 +6,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdEqBH; import java.util.List; +import java.util.Map; /** *

@@ -28,6 +29,7 @@ public interface ISdEqBHService extends IService { * 修改 */ boolean update(SdEqBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; /** * 删除 diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFbrdBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFbrdBHService.java index 70b074f4..a9e7b9da 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFbrdBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFbrdBHService.java @@ -6,6 +6,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdFbrdBH; import java.util.List; +import java.util.Map; /** *

@@ -28,6 +29,7 @@ public interface ISdFbrdBHService extends IService { * 修改 */ boolean update(SdFbrdBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; /** * 删除 diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFhbtBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFhbtBHService.java index 118de1c9..31797de7 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFhbtBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFhbtBHService.java @@ -6,6 +6,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdFhbtBH; import java.util.List; +import java.util.Map; /** *

@@ -28,6 +29,7 @@ public interface ISdFhbtBHService extends IService { * 修改 */ boolean update(SdFhbtBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; /** * 删除 diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssBHService.java index d3009d7f..db38f6ff 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssBHService.java @@ -7,6 +7,7 @@ import com.yfd.platform.qgc_base.domain.SdFhbtBH; import com.yfd.platform.qgc_base.domain.SdFpssBH; import java.util.List; +import java.util.Map; import java.util.Set; public interface ISdFpssBHService extends IService { @@ -25,6 +26,7 @@ public interface ISdFpssBHService extends IService { boolean add(SdFpssBH sdFpssBH, String source); boolean updateById(SdFpssBH sdFpssBH, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean deleteById(String stcd, String sttp); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOpinfoBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOpinfoBHService.java index cbd0ead2..b545cb3a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOpinfoBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOpinfoBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdOpinfoBH; import java.util.List; +import java.util.Map; public interface ISdOpinfoBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdOpinfoBH entity, String source); boolean update(SdOpinfoBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOtteBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOtteBHService.java index 09e162aa..92a9259e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOtteBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOtteBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdOtteBH; import java.util.List; +import java.util.Map; public interface ISdOtteBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdOtteBH entity, String source); boolean update(SdOtteBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOtweBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOtweBHService.java index 6009911c..ab865bec 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOtweBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdOtweBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdOtweBH; import java.util.List; +import java.util.Map; public interface ISdOtweBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdOtweBH entity, String source); boolean update(SdOtweBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdSonarBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdSonarBHService.java index 4ebbe192..3344cec9 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdSonarBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdSonarBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdSonarBH; import java.util.List; +import java.util.Map; public interface ISdSonarBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdSonarBH entity, String source); boolean update(SdSonarBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdTeBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdTeBHService.java index 32beac3c..a1db16c8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdTeBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdTeBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdTeBH; import java.util.List; +import java.util.Map; public interface ISdTeBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdTeBH entity, String source); boolean update(SdTeBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVaBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVaBHService.java index 334768f5..b7fd5773 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVaBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVaBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdVaBH; import java.util.List; +import java.util.Map; public interface ISdVaBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdVaBH entity, String source); boolean update(SdVaBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVdinfoBService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVdinfoBService.java index 10513b62..6d26b55c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVdinfoBService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVdinfoBService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdVdinfoB; import java.util.List; +import java.util.Map; public interface ISdVdinfoBService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdVdinfoB entity, String source); boolean update(SdVdinfoB entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVpBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVpBHService.java index b0f81587..4a459aad 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVpBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdVpBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdVpBH; import java.util.List; +import java.util.Map; public interface ISdVpBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdVpBH entity, String source); boolean update(SdVpBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWeBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWeBHService.java index 252776cd..350c1ee4 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWeBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWeBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdWeBH; import java.util.List; +import java.util.Map; public interface ISdWeBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdWeBH entity, String source); boolean update(SdWeBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWqBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWqBHService.java index 4576c188..13fe3feb 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWqBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWqBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdWqBH; import java.util.List; +import java.util.Map; public interface ISdWqBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdWqBH entity, String source); boolean update(SdWqBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/PatchUpdateHelper.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/PatchUpdateHelper.java new file mode 100644 index 00000000..e4352b45 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/PatchUpdateHelper.java @@ -0,0 +1,121 @@ +package com.yfd.platform.qgc_base.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yfd.platform.common.exception.BizException; +import com.yfd.platform.qgc_base.service.IMsOperationLogService; +import com.yfd.platform.utils.CodeToNameMetadataBo; +import com.yfd.platform.utils.DictCodeToNameConverter; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 公共 Patch 更新辅助工具,按前端 Map patch 显式更新实体字段(含 null 值置空)。 + *

+ * MyBatis-Plus 的 updateById 默认忽略 null 字段,前端传 "baseId": null 表示要将该字段置空, + * 通过本工具 engInfoPatch.containsKey(fieldName) 判断前端显式传入的字段, + * 对 null 值使用 SET column = NULL 实现置空。 + *

+ * + *
+ * 使用示例:
+ * @Resource
+ * private PatchUpdateHelper patchUpdateHelper;
+ *
+ * public boolean update(Map<String, Object> engInfoPatch, String source) throws Exception {
+ *     return patchUpdateHelper.execute(
+ *             this, engInfoPatch, source, TABLE_NAME, SdWtBH.class,
+ *             TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST);
+ * }
+ * 
+ */ +@Component +public class PatchUpdateHelper { + + @Resource + private ObjectMapper objectMapper; + + @Resource + private IMsOperationLogService msOperationLogService; + + @Resource + private DictCodeToNameConverter dictCodeToNameConverter; + + /** + * 执行 patch 更新:仅更新前端显式传入的字段(包括 null 值),未传入的字段保持原值。 + * + * @param service 对应实体的 IService(用于 getById 和 update) + * @param engInfoPatch 前端传入的字段 Map(key=字段名, value=字段值, 显式包含 null) + * @param source 操作来源(用于日志) + * @param tableName 数据库表名(用于日志) + * @param entityClass 实体类 + * @param transientFields 需跳过的瞬态字段集合(如 @TableField(exist=false)、serialVersionUID) + * @param codeToNameMetaList 字典代码转名称配置(用于操作日志) + * @param 实体类型 + * @return true=更新成功 + * @throws Exception Jackson 类型转换异常等 + */ + public boolean execute( + IService service, + Map engInfoPatch, + String source, + String tableName, + Class entityClass, + Set transientFields, + List codeToNameMetaList) throws Exception { + + String stcd = engInfoPatch == null ? null : (String) engInfoPatch.get("stcd"); + if (StrUtil.isBlank(stcd)) { + throw new BizException("站点编码不能为空"); + } + T before = service.getById(stcd); + if (before == null) { + throw new BizException("测站不存在: " + stcd); + } + + T after = entityClass.getDeclaredConstructor().newInstance(); + BeanUtil.copyProperties(before, after); + objectMapper.updateValue(after, engInfoPatch); + + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("STCD", stcd); + boolean hasUpdate = false; + for (Field field : entityClass.getDeclaredFields()) { + String fieldName = field.getName(); + if (transientFields.contains(fieldName) || "stcd".equals(fieldName)) { + continue; + } + if (!engInfoPatch.containsKey(fieldName)) { + continue; + } + String column = StrUtil.toUnderlineCase(fieldName).toUpperCase(); + field.setAccessible(true); + Object value = field.get(after); + if (value == null) { + updateWrapper.setSql(column + " = NULL"); + } else { + updateWrapper.set(column, value); + } + hasUpdate = true; + } + if (!hasUpdate) { + return true; + } + + boolean result = service.update(updateWrapper); + if (result) { + dictCodeToNameConverter.convertCodeToName(before, codeToNameMetaList); + dictCodeToNameConverter.convertCodeToName(after, codeToNameMetaList); + msOperationLogService.recordModifyDetailLog(stcd, tableName, before, after, source, codeToNameMetaList); + } + return result; + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAiboxBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAiboxBHServiceImpl.java index e44b24d4..c88f570f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAiboxBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAiboxBHServiceImpl.java @@ -10,6 +10,7 @@ import com.yfd.platform.qgc_base.domain.SdAiboxBH; import com.yfd.platform.qgc_base.mapper.SdAiboxBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdAiboxBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; @@ -19,9 +20,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdAiboxBHServiceImpl extends ServiceImpl implements ISdAiboxBHService { @@ -37,6 +36,11 @@ public class SdAiboxBHServiceImpl extends ServiceImpl TRANSIENT_FIELDS = Set.of("sttpName", "bldsttCodeName", "usflName", "dtinName", "mwayName", "ennm", "baseName", "rvnm", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -103,6 +107,14 @@ public class SdAiboxBHServiceImpl extends ServiceImpl engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdAiboxBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAimonitorBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAimonitorBHServiceImpl.java index 2f89d347..bd2e71de 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAimonitorBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAimonitorBHServiceImpl.java @@ -10,14 +10,13 @@ import com.yfd.platform.qgc_base.domain.SdAimonitorBH; import com.yfd.platform.qgc_base.mapper.SdAimonitorBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdAimonitorBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; /** * AI智能监测装置 Service 实现类 @@ -34,6 +33,12 @@ public class SdAimonitorBHServiceImpl extends ServiceImpl TRANSIENT_FIELDS = Set.of("sttpName", "bldsttCodeName", "dtinName", "mwayName", "ennm", "baseName", "rvnm", "serialVersionUID"); + private static final List CODE_TO_NAME_META_LIST = new ArrayList<>(); static { @@ -83,6 +88,14 @@ public class SdAimonitorBHServiceImpl extends ServiceImpl engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdAimonitorBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdArtsgBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdArtsgBHServiceImpl.java index b94d15f5..e73401c8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdArtsgBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdArtsgBHServiceImpl.java @@ -9,6 +9,7 @@ import com.yfd.platform.qgc_base.domain.SdArtsgBH; import com.yfd.platform.qgc_base.mapper.SdArtsgBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdArtsgBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; @@ -17,8 +18,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; +import java.util.*; @Service public class SdArtsgBHServiceImpl extends ServiceImpl implements ISdArtsgBHService { @@ -29,6 +29,12 @@ public class SdArtsgBHServiceImpl extends ServiceImpl TRANSIENT_FIELDS = Set.of("sttpName", "dtinName", "ennm", "baseName", "rvnm", "bldsttCodeName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -94,6 +100,14 @@ public class SdArtsgBHServiceImpl extends ServiceImpl engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdArtsgBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdDwBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdDwBHServiceImpl.java index 7045f2f8..12b53e3f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdDwBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdDwBHServiceImpl.java @@ -10,14 +10,13 @@ import com.yfd.platform.qgc_base.domain.SdDwBH; import com.yfd.platform.qgc_base.mapper.SdDwBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdDwBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdDwBHServiceImpl extends ServiceImpl implements ISdDwBHService { @@ -31,6 +30,12 @@ public class SdDwBHServiceImpl extends ServiceImpl impleme private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("sttpName", "dtinName", "baseName", "ennm", "bldsttCodeName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -92,6 +97,14 @@ public class SdDwBHServiceImpl extends ServiceImpl impleme return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdDwBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 5f909236..8276fc3d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -138,6 +138,11 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl TRANSIENT_FIELDS = Set.of("usflName", "sttpName", "bldsttCodeName", "engtpName", "scrscName", "prgrName", "fnName", "adjustEngName", "ishvrgrgName", "rgcpName", "dmatName", "dmtpName", "dvtpName", "cntpName", "blsysName", "impdstrzName", "chngrdName", "chiefbasinengName", "dtinEnvName", "runStateName", "warnStateName", "coenvwStateName", "serialVersionUID"); + @Resource private IAdminAuthService adminAuthService; @@ -333,29 +338,10 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl engInfoPatch, String source) throws JsonMappingException { - Map filteredPatch = filterEngInfoPatchFields(engInfoPatch); - if (filteredPatch.isEmpty()) { - return false; - } - String stcd = toTextValue(filteredPatch.get("stcd")); - if (!StringUtils.hasText(stcd)) { - return false; - } - SdEngInfoBH before = this.getById(stcd); - if (before == null) { - return false; - } - SdEngInfoBH after = BeanUtil.copyProperties(before, SdEngInfoBH.class); - objectMapper.updateValue(after, filteredPatch); - fillRelatedNameFields(after); - boolean result = updateEngInfoByPatch(stcd, after, filteredPatch); - if (result) { - dictCodeToNameConverter.convertCodeToName(after, CODE_TO_NAME_META_LIST); - dictCodeToNameConverter.convertCodeToName(before, CODE_TO_NAME_META_LIST); - msOperationLogService.recordModifyDetailLog(before.getStcd(),TABLE_NAME,before, after, source, CODE_TO_NAME_META_LIST); - } - return result; + public boolean updateEngInfo(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdEngInfoBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); } private boolean updateEngInfoByPatch(String stcd, SdEngInfoBH after, Map engInfoPatch) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEqBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEqBHServiceImpl.java index 86f09915..00b4eacc 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEqBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEqBHServiceImpl.java @@ -10,14 +10,13 @@ import com.yfd.platform.qgc_base.domain.SdEqBH; import com.yfd.platform.qgc_base.mapper.SdEqBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdEqBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdEqBHServiceImpl extends ServiceImpl implements ISdEqBHService { @@ -31,6 +30,12 @@ public class SdEqBHServiceImpl extends ServiceImpl impleme private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("sttpName", "dtinName", "ennm", "baseName", "bldsttCodeName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -92,6 +97,14 @@ public class SdEqBHServiceImpl extends ServiceImpl impleme return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdEqBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFbrdBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFbrdBHServiceImpl.java index 0e78c200..04b91361 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFbrdBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFbrdBHServiceImpl.java @@ -9,6 +9,7 @@ import com.yfd.platform.qgc_base.domain.SdFbrdBH; import com.yfd.platform.qgc_base.mapper.SdFbrdBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdFbrdBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; @@ -17,8 +18,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; +import java.util.*; @Service public class SdFbrdBHServiceImpl extends ServiceImpl implements ISdFbrdBHService { @@ -32,6 +32,12 @@ public class SdFbrdBHServiceImpl extends ServiceImpl i private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("sttpName", "dtinName", "ennm", "baseName", "bldsttCodeName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -93,6 +99,14 @@ public class SdFbrdBHServiceImpl extends ServiceImpl i return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdFbrdBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFhbtBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFhbtBHServiceImpl.java index c6d4f7c9..2b16f0a8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFhbtBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFhbtBHServiceImpl.java @@ -10,14 +10,13 @@ import com.yfd.platform.qgc_base.domain.SdFhbtBH; import com.yfd.platform.qgc_base.mapper.SdFhbtBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdFhbtBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdFhbtBHServiceImpl extends ServiceImpl implements ISdFhbtBHService { @@ -31,6 +30,12 @@ public class SdFhbtBHServiceImpl extends ServiceImpl i private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("sttpName", "dtinName", "ennm", "baseName", "bldsttCodeName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -93,6 +98,14 @@ public class SdFhbtBHServiceImpl extends ServiceImpl i return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdFhbtBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java index a0ac0133..74c7a0f4 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java @@ -16,9 +16,11 @@ import com.yfd.platform.qgc_base.service.ISdFpssBHService; import com.yfd.platform.qgc_data.domain.SysUserDataScope; import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper; import com.yfd.platform.system.service.IAdminAuthService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.*; @@ -43,6 +45,12 @@ public class SdFpssBHServiceImpl extends ServiceImpl i private IMsOperationLogService msOperationLogService; @Resource private StcdUniqueValidator stcdUniqueValidator; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("sttpName", "baseName", "dtinName", "ennm", "bldsttCodeName", "isUpName", "isDownName", "mwayName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -239,6 +247,14 @@ public class SdFpssBHServiceImpl extends ServiceImpl i return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdFpssBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override public boolean deleteById(String stcd, String sttp) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOpinfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOpinfoBHServiceImpl.java index 8fc5ade3..da8fdfe3 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOpinfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOpinfoBHServiceImpl.java @@ -10,14 +10,13 @@ import com.yfd.platform.qgc_base.domain.SdOpinfoBH; import com.yfd.platform.qgc_base.mapper.SdOpinfoBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdOpinfoBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdOpinfoBHServiceImpl extends ServiceImpl implements ISdOpinfoBHService { @@ -31,6 +30,12 @@ public class SdOpinfoBHServiceImpl extends ServiceImpl TRANSIENT_FIELDS = Set.of("dtinName", "ennm", "baseName", "rvnm", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -93,6 +98,14 @@ public class SdOpinfoBHServiceImpl extends ServiceImpl engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdOpinfoBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtteBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtteBHServiceImpl.java index 3307907b..2d278f9b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtteBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtteBHServiceImpl.java @@ -9,6 +9,7 @@ import com.yfd.platform.qgc_base.domain.SdOtteBH; import com.yfd.platform.qgc_base.mapper.SdOtteBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdOtteBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; @@ -17,8 +18,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; +import java.util.*; @Service public class SdOtteBHServiceImpl extends ServiceImpl implements ISdOtteBHService { @@ -32,6 +32,12 @@ public class SdOtteBHServiceImpl extends ServiceImpl i private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("sttpName", "bldsttCodeName", "usflName", "dtinName", "mwayName", "ennm", "baseName", "rvnm", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -96,6 +102,14 @@ public class SdOtteBHServiceImpl extends ServiceImpl i return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdOtteBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtweBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtweBHServiceImpl.java index f7cadf09..4543e6fb 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtweBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdOtweBHServiceImpl.java @@ -9,6 +9,7 @@ import com.yfd.platform.qgc_base.domain.SdOtweBH; import com.yfd.platform.qgc_base.mapper.SdOtweBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdOtweBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; @@ -17,8 +18,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; +import java.util.*; @Service public class SdOtweBHServiceImpl extends ServiceImpl implements ISdOtweBHService { @@ -31,6 +31,12 @@ public class SdOtweBHServiceImpl extends ServiceImpl i private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("sttpName", "usflName", "dtinName", "ennm", "baseName", "rvnm", "bldsttCodeName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -94,6 +100,14 @@ public class SdOtweBHServiceImpl extends ServiceImpl i return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdOtweBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdSonarBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdSonarBHServiceImpl.java index b1a5c16c..0e9d549b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdSonarBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdSonarBHServiceImpl.java @@ -10,14 +10,13 @@ import com.yfd.platform.qgc_base.domain.SdSonarBH; import com.yfd.platform.qgc_base.mapper.SdSonarBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdSonarBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdSonarBHServiceImpl extends ServiceImpl implements ISdSonarBHService { @@ -30,6 +29,12 @@ public class SdSonarBHServiceImpl extends ServiceImpl TRANSIENT_FIELDS = Set.of("sttpName", "bldsttCodeName", "usflName", "dtinName", "mwayName", "ennm", "baseName", "rvnm", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -95,6 +100,14 @@ public class SdSonarBHServiceImpl extends ServiceImpl engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdSonarBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdTeBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdTeBHServiceImpl.java index be1f9bf8..3fb5dcde 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdTeBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdTeBHServiceImpl.java @@ -9,6 +9,7 @@ import com.yfd.platform.qgc_base.domain.SdTeBH; import com.yfd.platform.qgc_base.mapper.SdTeBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdTeBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; @@ -17,8 +18,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; +import java.util.*; @Service public class SdTeBHServiceImpl extends ServiceImpl implements ISdTeBHService { @@ -31,6 +31,12 @@ public class SdTeBHServiceImpl extends ServiceImpl impleme private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("sttpName", "dtinName", "ennm", "baseName", "rvnm", "bldsttCodeName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -94,6 +100,14 @@ public class SdTeBHServiceImpl extends ServiceImpl impleme return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdTeBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVaBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVaBHServiceImpl.java index 74c4c63a..d752bbe6 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVaBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVaBHServiceImpl.java @@ -10,14 +10,13 @@ import com.yfd.platform.qgc_base.domain.SdVaBH; import com.yfd.platform.qgc_base.mapper.SdVaBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdVaBHService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdVaBHServiceImpl extends ServiceImpl implements ISdVaBHService { @@ -30,6 +29,12 @@ public class SdVaBHServiceImpl extends ServiceImpl impleme private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("sttpName", "usflName", "dtinName", "ennm", "baseName", "bldsttCodeName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -91,6 +96,14 @@ public class SdVaBHServiceImpl extends ServiceImpl impleme return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdVaBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVdinfoBServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVdinfoBServiceImpl.java index 0f43ff9b..00a72cbb 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVdinfoBServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVdinfoBServiceImpl.java @@ -9,17 +9,16 @@ import com.yfd.platform.qgc_base.domain.SdVdinfoB; import com.yfd.platform.qgc_base.mapper.SdVdinfoBMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdVdinfoBService; +import com.baomidou.mybatisplus.annotation.TableField; import com.yfd.platform.utils.CodeToNameMetadataBo; import com.yfd.platform.utils.DataSourceRequestUtil; import com.yfd.platform.utils.DictCodeToNameConverter; import com.yfd.platform.utils.StcdUniqueValidator; import jakarta.annotation.Resource; -import org.checkerframework.checker.units.qual.C; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; +import java.util.*; @Service public class SdVdinfoBServiceImpl extends ServiceImpl implements ISdVdinfoBService { @@ -32,6 +31,12 @@ public class SdVdinfoBServiceImpl extends ServiceImpl TRANSIENT_FIELDS = Set.of("sttpName", "ennm", "rvnm", "addvcdName", "baseName", "bldsttCodeName", "dtinName", "serialVersionUID"); + /** * 代码转名称元数据配置列表(静态初始化) *

@@ -99,6 +104,14 @@ public class SdVdinfoBServiceImpl extends ServiceImpl engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdVdinfoB.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVpBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVpBHServiceImpl.java index 86551cc2..ccf84432 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVpBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdVpBHServiceImpl.java @@ -1,6 +1,7 @@ package com.yfd.platform.qgc_base.service.impl; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -15,9 +16,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdVpBHServiceImpl extends ServiceImpl implements ISdVpBHService { @@ -30,6 +29,13 @@ public class SdVpBHServiceImpl extends ServiceImpl impleme private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + @Resource + private PatchUpdateHelper patchUpdateHelper; + + /** SdVpBH 中 @TableField(exist = false) 的字段名 + serialVersionUID */ + private static final Set TRANSIENT_FIELDS = Set.of( + "sttpName", "dtinName", "ennm", "baseName", "bldsttCodeName", "serialVersionUID" + ); /** * 代码转名称元数据配置列表(静态初始化) *

@@ -90,6 +96,14 @@ public class SdVpBHServiceImpl extends ServiceImpl impleme return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdVpBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWeBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWeBHServiceImpl.java index a95bcbe2..b5c46966 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWeBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWeBHServiceImpl.java @@ -17,8 +17,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; +import java.util.*; @Service public class SdWeBHServiceImpl extends ServiceImpl implements ISdWeBHService { @@ -32,6 +31,13 @@ public class SdWeBHServiceImpl extends ServiceImpl impleme private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + @Resource + private PatchUpdateHelper patchUpdateHelper; + + /** SdWeBH 中 @TableField(exist = false) 的字段名 + serialVersionUID */ + private static final Set TRANSIENT_FIELDS = Set.of( + "sttpName", "dtinName", "ennm", "baseName", "rvnm", "bldsttCodeName", "serialVersionUID" + ); /** * 代码转名称元数据配置列表(静态初始化) *

@@ -96,6 +102,14 @@ public class SdWeBHServiceImpl extends ServiceImpl impleme return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdWeBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWqBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWqBHServiceImpl.java index 846dfc2a..eb95b699 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWqBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWqBHServiceImpl.java @@ -1,6 +1,7 @@ package com.yfd.platform.qgc_base.service.impl; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -15,9 +16,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdWqBHServiceImpl extends ServiceImpl implements ISdWqBHService { @@ -31,6 +30,14 @@ public class SdWqBHServiceImpl extends ServiceImpl impleme private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + @Resource + private PatchUpdateHelper patchUpdateHelper; + + /** SdWqBH 中 @TableField(exist = false) 的字段名 + serialVersionUID */ + private static final Set TRANSIENT_FIELDS = Set.of( + "sttpName", "wwqtgName", "bldsttCodeName", "dtinName", + "dtinTypeName", "mwayName", "ennm", "baseName", "serialVersionUID" + ); /** * 代码转名称元数据配置列表(静态初始化) *

@@ -93,6 +100,14 @@ public class SdWqBHServiceImpl extends ServiceImpl impleme return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdWqBH.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWtBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWtBHServiceImpl.java index 65af743a..fd918038 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWtBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdWtBHServiceImpl.java @@ -16,9 +16,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class SdWtBHServiceImpl extends ServiceImpl implements ISdWtBHService { @@ -33,6 +31,14 @@ public class SdWtBHServiceImpl extends ServiceImpl impleme private DictCodeToNameConverter dictCodeToNameConverter; @Resource private StcdUniqueValidator stcdUniqueValidator; + @Resource + private PatchUpdateHelper patchUpdateHelper; + + /** SdWtBH 中 @TableField(exist = false) 的字段名 + serialVersionUID */ + private static final Set WT_TRANSIENT_FIELDS = Set.of( + "sttpName", "bldsttCodeName", "dtinName", "dtinTypeName", + "mwayName", "ennm", "baseName", "serialVersionUID" + ); /** * 代码转名称元数据配置列表(静态初始化) *

@@ -96,6 +102,14 @@ public class SdWtBHServiceImpl extends ServiceImpl impleme return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute( + this, engInfoPatch, source, TABLE_NAME, SdWtBH.class, + WT_TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List stcds, String source) { From 57403df9800712870f62aeb02efaa41e2edb6cc1 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 15:05:59 +0800 Subject: [PATCH 16/44] =?UTF-8?q?fix:=20=E6=A0=B9=E6=8D=AE=E7=AB=99?= =?UTF-8?q?=E7=A0=81=E4=BF=AE=E6=94=B9=E4=BF=AE=E6=94=B9=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yfd/platform/qgc_base/service/ISdWtBHService.java | 2 ++ .../qgc_base/service/impl/MsOperationLogServiceImpl.java | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWtBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWtBHService.java index 6d4fe773..d09ce970 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWtBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdWtBHService.java @@ -6,10 +6,12 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdWtBH; import java.util.List; +import java.util.Map; public interface ISdWtBHService extends IService { Page queryPageList(DataSourceRequest request); boolean add(SdWtBH entity, String source); boolean update(SdWtBH entity, String source); + boolean update(Map engInfoPatch, String source) throws Exception; boolean delete(List stcds, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java index f60f4a7b..fc9bcdba 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -605,9 +605,9 @@ public class MsOperationLogServiceImpl extends ServiceImpl Date: Tue, 11 Aug 2026 15:48:23 +0800 Subject: [PATCH 17/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=B1=BC?= =?UTF-8?q?=E5=AD=97=E5=85=B8=E6=96=B0=E5=A2=9E=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdFishDictoryBController.java | 38 ++++++++++------ .../qgc_base/domain/SdFishDictoryB.java | 5 ++- .../service/ISdFishDictoryBService.java | 12 ++++++ .../service/impl/PatchUpdateHelper.java | 43 +++++++++++++++---- .../impl/SdFishDictoryBServiceImpl.java | 40 +++++++++++++++++ 5 files changed, 116 insertions(+), 22 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFishDictoryBController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFishDictoryBController.java index 981752a2..b78b83a4 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFishDictoryBController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFishDictoryBController.java @@ -20,10 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -88,9 +85,14 @@ public class SdFishDictoryBController { if (entity == null) { return ResponseResult.error("数据不能为空"); } - entity.setId(IdUtil.simpleUUID()); + entity.setId(IdUtil.fastUUID()); entity.setCode(entity.getId()); + // 名称重名校验 + if (sdFishDictoryBService.existsByName(entity.getName())) { + return ResponseResult.error("该鱼类名称已存在"); + } + // 上传文件并设置附件ID到实体 applyUploadedFiles(entity, files); @@ -109,23 +111,35 @@ public class SdFishDictoryBController { @RequestParam(value = "files", required = false) List files) { try { SdEngInfoBHOperateRequest request = objectMapper.readValue(dataStr, SdEngInfoBHOperateRequest.class); - SdFishDictoryB entity = request == null || request.getEngInfo() == null ? null - : objectMapper.convertValue(request.getEngInfo(), SdFishDictoryB.class); - if (entity == null || entity.getId() == null) { + Map engInfo = request == null ? null : request.getEngInfo(); + if (engInfo == null || engInfo.get("id") == null) { return ResponseResult.error("数据或ID不能为空"); } + // 名称重名校验(仅当本次修改了名称时校验) + Object newName = engInfo.get("name"); + if (newName != null && StrUtil.isNotBlank(newName.toString())) { + String name = newName.toString(); + if (sdFishDictoryBService.existsByNameExcludeId(name, (String) engInfo.get("id"))) { + return ResponseResult.error("该鱼类名称已存在"); + } + } + // 获取修改前的实体,用于后续清理旧文件 - SdFishDictoryB before = sdFishDictoryBService.getById(entity.getId()); + SdFishDictoryB before = sdFishDictoryBService.getById((String) engInfo.get("id")); List oldAttachmentIds = before != null ? collectAttachmentIds(before) : Collections.emptyList(); // 上传新文件并设置附件ID - applyUploadedFiles(entity, files); + SdFishDictoryB tempEntity = objectMapper.convertValue(engInfo, SdFishDictoryB.class); + applyUploadedFiles(tempEntity, files); + // 将文件处理后 inffile 合并回 patch map + engInfo.put("inffile", tempEntity.getInffile()); - boolean result = sdFishDictoryBService.update(entity, request.getSource()); + boolean result = sdFishDictoryBService.update(engInfo, request.getSource()); if (result) { // 清理被替换的旧文件 - deleteReplacedFiles(oldAttachmentIds, collectAttachmentIds(entity)); + SdFishDictoryB after = sdFishDictoryBService.getById((String) engInfo.get("id")); + deleteReplacedFiles(oldAttachmentIds, collectAttachmentIds(after)); } return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } catch (Exception e) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFishDictoryB.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFishDictoryB.java index f4a18c95..2f62b2cc 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFishDictoryB.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFishDictoryB.java @@ -21,7 +21,7 @@ public class SdFishDictoryB implements Serializable { private static final long serialVersionUID = 1L; /** 主键 */ - @TableId(type = IdType.ASSIGN_UUID) + @TableId(type = IdType.INPUT) @FieldChinese("主键") private String id; @@ -105,6 +105,9 @@ public class SdFishDictoryB implements Serializable { @FieldChinese("所属流域") private String rvcd; + @TableField(exist = false) + private String rvcdName; + /** 洄游习性 */ @FieldChinese("洄游习性") private String habitMigrat; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFishDictoryBService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFishDictoryBService.java index c687cc28..da9d7224 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFishDictoryBService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFishDictoryBService.java @@ -6,6 +6,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.qgc_base.domain.SdFishDictoryB; import java.util.List; +import java.util.Map; public interface ISdFishDictoryBService extends IService { @@ -16,10 +17,21 @@ public interface ISdFishDictoryBService extends IService { boolean add(SdFishDictoryB entity, String source); boolean update(SdFishDictoryB entity, String source); + boolean update(Map patchMap, String source) throws Exception; boolean delete(List ids, String source); SdFishDictoryB getById(String id); + /** + * 检查名称是否已存在(不过滤IS_DELETED,因为唯一约束不区分软删除) + */ + boolean existsByName(String name); + + /** + * 检查名称是否已被其他记录占用(排除指定ID) + */ + boolean existsByNameExcludeId(String name, String excludeId); + List findSimilarFish(String name, Integer limit); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/PatchUpdateHelper.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/PatchUpdateHelper.java index e4352b45..85f72a98 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/PatchUpdateHelper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/PatchUpdateHelper.java @@ -49,6 +49,22 @@ public class PatchUpdateHelper { @Resource private DictCodeToNameConverter dictCodeToNameConverter; + /** + * 执行 patch 更新(默认主键字段为 "stcd")。 + * + * @see #execute(IService, Map, String, String, Class, Set, List, String) + */ + public boolean execute( + IService service, + Map engInfoPatch, + String source, + String tableName, + Class entityClass, + Set transientFields, + List codeToNameMetaList) throws Exception { + return execute(service, engInfoPatch, source, tableName, entityClass, transientFields, codeToNameMetaList, "stcd"); + } + /** * 执行 patch 更新:仅更新前端显式传入的字段(包括 null 值),未传入的字段保持原值。 * @@ -59,6 +75,7 @@ public class PatchUpdateHelper { * @param entityClass 实体类 * @param transientFields 需跳过的瞬态字段集合(如 @TableField(exist=false)、serialVersionUID) * @param codeToNameMetaList 字典代码转名称配置(用于操作日志) + * @param pkFieldName 主键 Java 字段名(如 "stcd"、"id") * @param 实体类型 * @return true=更新成功 * @throws Exception Jackson 类型转换异常等 @@ -70,27 +87,29 @@ public class PatchUpdateHelper { String tableName, Class entityClass, Set transientFields, - List codeToNameMetaList) throws Exception { + List codeToNameMetaList, + String pkFieldName) throws Exception { - String stcd = engInfoPatch == null ? null : (String) engInfoPatch.get("stcd"); - if (StrUtil.isBlank(stcd)) { - throw new BizException("站点编码不能为空"); + Object pkValue = engInfoPatch == null ? null : engInfoPatch.get(pkFieldName); + if (isEmptyPk(pkValue)) { + throw new BizException("主键不能为空"); } - T before = service.getById(stcd); + T before = service.getById((String) pkValue); if (before == null) { - throw new BizException("测站不存在: " + stcd); + throw new BizException("记录不存在: " + pkValue); } T after = entityClass.getDeclaredConstructor().newInstance(); BeanUtil.copyProperties(before, after); objectMapper.updateValue(after, engInfoPatch); + String pkColumn = StrUtil.toUnderlineCase(pkFieldName).toUpperCase(); UpdateWrapper updateWrapper = new UpdateWrapper<>(); - updateWrapper.eq("STCD", stcd); + updateWrapper.eq(pkColumn, pkValue); boolean hasUpdate = false; for (Field field : entityClass.getDeclaredFields()) { String fieldName = field.getName(); - if (transientFields.contains(fieldName) || "stcd".equals(fieldName)) { + if (transientFields.contains(fieldName) || pkFieldName.equals(fieldName)) { continue; } if (!engInfoPatch.containsKey(fieldName)) { @@ -114,8 +133,14 @@ public class PatchUpdateHelper { if (result) { dictCodeToNameConverter.convertCodeToName(before, codeToNameMetaList); dictCodeToNameConverter.convertCodeToName(after, codeToNameMetaList); - msOperationLogService.recordModifyDetailLog(stcd, tableName, before, after, source, codeToNameMetaList); + msOperationLogService.recordModifyDetailLog(String.valueOf(pkValue), tableName, before, after, source, codeToNameMetaList); } return result; } + + private boolean isEmptyPk(Object value) { + if (value == null) return true; + if (value instanceof String) return StrUtil.isBlank((String) value); + return false; + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFishDictoryBServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFishDictoryBServiceImpl.java index ffe6a682..270aaa7a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFishDictoryBServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFishDictoryBServiceImpl.java @@ -1,6 +1,7 @@ package com.yfd.platform.qgc_base.service.impl; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -36,6 +37,14 @@ public class SdFishDictoryBServiceImpl extends ServiceImpl TRANSIENT_FIELDS = Set.of( + "typeName", "rareName", "specOriginName", "ptypeName", + "habitatName", "situationName", "resourceTypeName", "serialVersionUID" + ); /** * 代码转名称元数据配置列表(静态初始化) @@ -95,6 +104,14 @@ public class SdFishDictoryBServiceImpl extends ServiceImpl patchMap, String source) throws Exception { + return patchUpdateHelper.execute( + this, patchMap, source, TABLE_NAME, SdFishDictoryB.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST, "id"); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean delete(List ids, String source) { @@ -116,6 +133,29 @@ public class SdFishDictoryBServiceImpl extends ServiceImpl 0; } + @Override + public boolean existsByName(String name) { + if (!StringUtils.hasText(name)) { + return false; + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SdFishDictoryB::getName, name); + return count(wrapper) > 0; + } + + @Override + public boolean existsByNameExcludeId(String name, String excludeId) { + if (!StringUtils.hasText(name)) { + return false; + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SdFishDictoryB::getName, name); + if (StringUtils.hasText(excludeId)) { + wrapper.ne(SdFishDictoryB::getId, excludeId); + } + return count(wrapper) > 0; + } + @Override public SdFishDictoryB getById(String id) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); From bcf8279d3d81486ff37260b207c73dac0dac2d4b Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 16:22:16 +0800 Subject: [PATCH 18/44] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E5=AF=86=E7=A0=81=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yfd/platform/config/SecurityConfig.java | 1 + .../SysAcctPasswordPolicyController.java | 139 +++++++++++++ .../system/domain/SysAcctPasswordPolicy.java | 189 ++++++++++++++++++ .../mapper/SysAcctPasswordPolicyMapper.java | 14 ++ .../ISysAcctPasswordPolicyService.java | 26 +++ .../SysAcctPasswordPolicyServiceImpl.java | 95 +++++++++ 6 files changed, 464 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/system/controller/SysAcctPasswordPolicyController.java create mode 100644 backend/src/main/java/com/yfd/platform/system/domain/SysAcctPasswordPolicy.java create mode 100644 backend/src/main/java/com/yfd/platform/system/mapper/SysAcctPasswordPolicyMapper.java create mode 100644 backend/src/main/java/com/yfd/platform/system/service/ISysAcctPasswordPolicyService.java create mode 100644 backend/src/main/java/com/yfd/platform/system/service/impl/SysAcctPasswordPolicyServiceImpl.java diff --git a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java index 3883e656..38674041 100644 --- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -77,6 +77,7 @@ public class SecurityConfig { // .requestMatchers("/threedroamb/**").permitAll() // .requestMatchers("/overview/**").permitAll() .requestMatchers("/wt/**").permitAll() + .requestMatchers("/system/acctPasswordPolicy/**").permitAll() .requestMatchers("/fb/**").permitAll() // .requestMatchers("/base/**").permitAll() // .requestMatchers("/zq/**").permitAll() diff --git a/backend/src/main/java/com/yfd/platform/system/controller/SysAcctPasswordPolicyController.java b/backend/src/main/java/com/yfd/platform/system/controller/SysAcctPasswordPolicyController.java new file mode 100644 index 00000000..4c7bc27f --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/controller/SysAcctPasswordPolicyController.java @@ -0,0 +1,139 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysAcctPasswordPolicy; +import com.yfd.platform.system.service.ISysAcctPasswordPolicyService; +import com.yfd.platform.system.service.IUserService; +import com.yfd.platform.utils.DataSourceRequestUtil; +import com.yfd.platform.utils.SecurityUtils; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + *

+ * 账号密码策略 前端控制器 + *

+ */ +@Slf4j +@RestController +@RequestMapping("/system/acctPasswordPolicy") +@Tag(name = "账号密码策略管理") +public class SysAcctPasswordPolicyController { + + @Resource + private ISysAcctPasswordPolicyService policyService; + + @Resource + private IUserService userService; + + @GetMapping("/current") + @Operation(summary = "获取当前生效的密码策略") + public ResponseResult current() { + SysAcctPasswordPolicy policy = policyService.getCurrentPolicy(); + return policy == null + ? ResponseResult.error("未配置密码策略") + : ResponseResult.successData(policy); + } + + @GetMapping("/getById") + @Operation(summary = "根据ID查询密码策略") + public ResponseResult getById(@RequestParam String id) { + SysAcctPasswordPolicy policy = policyService.getById(id); + return policy == null + ? ResponseResult.error("策略不存在") + : ResponseResult.successData(policy); + } + + @PostMapping("/queryPageList") + @Operation(summary = "分页查询密码策略列表") + public ResponseResult queryPageList(@RequestBody DataSourceRequest request) { + Page page = DataSourceRequestUtil.executeQuery(request, SysAcctPasswordPolicy.class, policyService); + return ResponseResult.successData(page); + } + + @PostMapping("/list") + @Operation(summary = "查询密码策略列表(不分页)") + public ResponseResult list(@RequestBody DataSourceRequest request) { + List list = DataSourceRequestUtil.executeList(request, SysAcctPasswordPolicy.class, policyService); + return ResponseResult.successData(list); + } + + @PostMapping("/add") + @Operation(summary = "新增密码策略") + public ResponseResult add(@RequestBody SysAcctPasswordPolicy policy) { + if (StrUtil.isBlank(policy.getName())) { + return ResponseResult.error("策略名称不能为空"); + } + policy.setId(IdUtil.fastSimpleUUID()); +// policy.setRecordUser(SecurityUtils.getUserId()); + policy.setRecordUser("admin"); + policy.setRecordTime(new Date()); + policy.setIsDeleted(0); + + boolean ok = policyService.save(policy); + return ok ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); + } + + @PostMapping("/update") + @Operation(summary = "修改密码策略") + public ResponseResult update(@RequestBody SysAcctPasswordPolicy policy) { + if (StrUtil.isBlank(policy.getId())) { + return ResponseResult.error("ID不能为空"); + } + SysAcctPasswordPolicy exist = policyService.getById(policy.getId()); + if (exist == null) { + return ResponseResult.error("策略不存在"); + } + policy.setModifyUser(userService.getUsername()); + policy.setModifyTime(new Date()); + + boolean ok = policyService.updateById(policy); + return ok ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); + } + + @PostMapping("/delete") + @Operation(summary = "删除密码策略(软删除)") + public ResponseResult delete(@RequestBody List ids) { + if (ids == null || ids.isEmpty()) { + return ResponseResult.error("ID不能为空"); + } + Date now = new Date(); + String username = userService.getUsername(); + for (String id : ids) { + SysAcctPasswordPolicy policy = policyService.getById(id); + if (policy != null) { + policy.setIsDeleted(1); + policy.setDeleteUser(username); + policy.setDeleteTime(now); + policyService.updateById(policy); + } + } + return ResponseResult.success("删除成功"); + } + + @PostMapping("/validatePassword") + @Operation(summary = "根据当前策略校验密码复杂度") + public ResponseResult validatePassword(@RequestParam String password, + @RequestParam(required = false) String username) { + SysAcctPasswordPolicy policy = policyService.getCurrentPolicy(); + if (policy == null) { + return ResponseResult.error("未配置密码策略"); + } + String errMsg = policyService.validatePassword(policy, password, username); + if (errMsg != null) { + return ResponseResult.error(errMsg); + } + return ResponseResult.success("密码校验通过"); + } +} diff --git a/backend/src/main/java/com/yfd/platform/system/domain/SysAcctPasswordPolicy.java b/backend/src/main/java/com/yfd/platform/system/domain/SysAcctPasswordPolicy.java new file mode 100644 index 00000000..86c838e0 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/domain/SysAcctPasswordPolicy.java @@ -0,0 +1,189 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 账号密码策略表 + *

+ */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("SYS_ACCT_PASSWORD_POLICY") +public class SysAcctPasswordPolicy implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 主键ID */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 密码策略标识 */ + private String code; + + /** 策略名称 */ + private String name; + + /** 用户名敏感性校验 */ + private Integer usernameSensitiveValid; + + /** 密码敏感性校验 */ + private Integer passwordSensitiveValid; + + /** 启用短信重置密码 */ + private Integer enableSmsResetPwd; + + /** 启用邮箱重置密码 */ + private Integer enableEmailResetPwd; + + /** 启用输入密码 */ + private Integer enableInputPassword; + + /** 启用默认密码 */ + private Integer enableDefaultPassword; + + /** 默认密码 */ + private String defaultPassword; + + /** 密码最小长度 */ + private Integer minLength; + + /** 密码最大长度 */ + private Integer maxLength; + + /** 最大密码错误次数 */ + private Integer maxErrorNumber; + + /** 密码必须包含字符类型 */ + private String passwordCharsRequire; + + /** 密码数字数量要求 */ + private Integer digitsCount; + + /** 密码小写字母数量要求 */ + private Integer lowercaseCount; + + /** 密码大写字母数量要求 */ + private Integer uppercaseCount; + + /** 特殊字符数量要求 */ + private Integer specialCharCount; + + /** 密码不可与用户名相同 */ + private Integer notUsername; + + /** 密码正则表达式 */ + private String regularExpression; + + /** 不可使用最近N次密码 */ + private Integer notRecentCount; + + /** 启用密码策略 */ + private Integer enablePasswordPolicy; + + /** 启用安全策略 */ + private Integer enableSecurityPolicy; + + /** 启用账户锁定 */ + private Integer enableLock; + + /** 锁定时长(秒) */ + private Integer lockedExpireTime; + + /** 启用验证码 */ + private Integer enableCaptcha; + + /** 验证码类型 */ + private String captureType; + + /** 触发验证码的错误次数 */ + private Integer maxCheckCaptcha; + + /** Web端多端登录 */ + private Integer enableWebMultipleLogin; + + /** 移动端多端登录 */ + private Integer enableAppMultipleLogin; + + /** 密码更新频率(天) */ + private Integer passwordUpdateRate; + + /** 规则变更时强制修改密码 */ + private Integer forceModifyPwdRuleModify; + + /** 密码修改提醒周期(天) */ + private Integer passwordReminderPeriod; + + /** 首次登录强制修改密码 */ + private Integer forceModifyPassword; + + /** 允许账号登录 */ + private Integer enableAccountLogin; + + /** 修改密码后需重新登录 */ + private Integer loginAgain; + + /** 允许短信登录 */ + private Integer enableSmsLogin; + + /** 启用随机密码 */ + private Integer enableRandomPassword; + + /** 启用数据加密 */ + private Integer enableDataSecurity; + + /** 是否全局策略 */ + private Integer isBelongGlobal; + + /** 是否双重验证 */ + private Integer isTwoFactorAuth; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String recordUser; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + private Date recordTime; + + /** 修改人 */ + @TableField(fill = FieldFill.UPDATE) + private String modifyUser; + + /** 修改时间 */ + @TableField(fill = FieldFill.UPDATE) + private Date modifyTime; + + /** 是否已删除 0=未删除 1=已删除 */ + @TableLogic + private Integer isDeleted; + + /** 删除人 */ + private String deleteUser; + + /** 删除时间 */ + private Date deleteTime; + + /** 过滤内容 */ + private String filterContent; + + /** 排序 */ + private Integer orderIndex; + + /** 启用验证码类型 */ + private String enableCaptchaType; + + /** 启用企业微信登录 */ + private Integer enableEnterpriseWechatLogin; + + /** 启用钉钉登录 */ + private Integer enableDingdingLogin; + + /** 启用微信登录 */ + private Integer enableWechatLogin; +} diff --git a/backend/src/main/java/com/yfd/platform/system/mapper/SysAcctPasswordPolicyMapper.java b/backend/src/main/java/com/yfd/platform/system/mapper/SysAcctPasswordPolicyMapper.java new file mode 100644 index 00000000..b89fb6e7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/mapper/SysAcctPasswordPolicyMapper.java @@ -0,0 +1,14 @@ +package com.yfd.platform.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.system.domain.SysAcctPasswordPolicy; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 账号密码策略表 Mapper 接口 + *

+ */ +@Mapper +public interface SysAcctPasswordPolicyMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/yfd/platform/system/service/ISysAcctPasswordPolicyService.java b/backend/src/main/java/com/yfd/platform/system/service/ISysAcctPasswordPolicyService.java new file mode 100644 index 00000000..eaa81b98 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/service/ISysAcctPasswordPolicyService.java @@ -0,0 +1,26 @@ +package com.yfd.platform.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.system.domain.SysAcctPasswordPolicy; + +/** + *

+ * 账号密码策略表 服务类 + *

+ */ +public interface ISysAcctPasswordPolicyService extends IService { + + /** + * 获取当前生效的策略(取排序最小且未删除的那条) + */ + SysAcctPasswordPolicy getCurrentPolicy(); + + /** + * 根据策略校验密码复杂度 + * + * @param password 待校验的密码 + * @param username 关联的用户名(用于NOT_USERNAME校验) + * @return null=校验通过,否则返回错误提示 + */ + String validatePassword(SysAcctPasswordPolicy policy, String password, String username); +} diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/SysAcctPasswordPolicyServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/SysAcctPasswordPolicyServiceImpl.java new file mode 100644 index 00000000..2c4f569b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/service/impl/SysAcctPasswordPolicyServiceImpl.java @@ -0,0 +1,95 @@ +package com.yfd.platform.system.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.system.domain.SysAcctPasswordPolicy; +import com.yfd.platform.system.mapper.SysAcctPasswordPolicyMapper; +import com.yfd.platform.system.service.ISysAcctPasswordPolicyService; +import org.springframework.stereotype.Service; + +import java.util.regex.Pattern; + +/** + *

+ * 账号密码策略表 服务实现类 + *

+ */ +@Service +public class SysAcctPasswordPolicyServiceImpl extends ServiceImpl + implements ISysAcctPasswordPolicyService { + + @Override + public SysAcctPasswordPolicy getCurrentPolicy() { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysAcctPasswordPolicy::getIsDeleted, 0) + .eq(SysAcctPasswordPolicy::getEnablePasswordPolicy, 1) + .orderByAsc(SysAcctPasswordPolicy::getOrderIndex) + .last("LIMIT 1"); + return getOne(wrapper); + } + + @Override + public String validatePassword(SysAcctPasswordPolicy policy, String password, String username) { + if (policy == null || StrUtil.isBlank(password)) { + return "密码不能为空"; + } + + // 1. 密码长度校验 + if (policy.getMinLength() != null && password.length() < policy.getMinLength()) { + return "密码长度不能少于" + policy.getMinLength() + "位"; + } + if (policy.getMaxLength() != null && password.length() > policy.getMaxLength()) { + return "密码长度不能超过" + policy.getMaxLength() + "位"; + } + + // 2. 密码与用户名不可相同 + if (isEnabled(policy.getNotUsername()) && StrUtil.isNotBlank(username) && username.equals(password)) { + return "密码不能与用户名相同"; + } + + // 3. 字符类型数量校验 + int digits = 0, lowercase = 0, uppercase = 0, special = 0; + for (char c : password.toCharArray()) { + if (Character.isDigit(c)) { + digits++; + } else if (Character.isLowerCase(c)) { + lowercase++; + } else if (Character.isUpperCase(c)) { + uppercase++; + } else { + special++; + } + } + + if (policy.getDigitsCount() != null && digits < policy.getDigitsCount()) { + return "密码至少包含" + policy.getDigitsCount() + "个数字"; + } + if (policy.getLowercaseCount() != null && lowercase < policy.getLowercaseCount()) { + return "密码至少包含" + policy.getLowercaseCount() + "个小写字母"; + } + if (policy.getUppercaseCount() != null && uppercase < policy.getUppercaseCount()) { + return "密码至少包含" + policy.getUppercaseCount() + "个大写字母"; + } + if (policy.getSpecialCharCount() != null && special < policy.getSpecialCharCount()) { + return "密码至少包含" + policy.getSpecialCharCount() + "个特殊字符"; + } + + // 4. 正则表达式校验 + if (StrUtil.isNotBlank(policy.getRegularExpression())) { + try { + if (!Pattern.matches(policy.getRegularExpression(), password)) { + return "密码格式不符合要求"; + } + } catch (Exception e) { + // 正则不合法则跳过 + } + } + + return null; + } + + private boolean isEnabled(Integer value) { + return value != null && value == 1; + } +} From 42ea915d6c6cc3e8366d7d53ff5984b93091e063 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 11 Aug 2026 16:55:22 +0800 Subject: [PATCH 19/44] =?UTF-8?q?fix:=20=E5=A2=9E=E5=8A=A0=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E7=BB=9F=E4=B8=80=E7=99=BB=E5=BD=95=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E7=9F=AD=E4=BF=A1=E5=92=8C=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E7=99=BB=E5=BD=95=EF=BC=8C=E5=B9=B6=E4=B8=94=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9Aweb=E9=99=90=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/LoginController.java | 273 +++++++++++++++++- .../system/domain/UnifiedLoginRequest.java | 56 ++++ 2 files changed, 322 insertions(+), 7 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/system/domain/UnifiedLoginRequest.java diff --git a/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java b/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java index 689fa3c8..47f1c8fa 100644 --- a/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java +++ b/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java @@ -14,9 +14,12 @@ import com.yfd.platform.config.WebConfig; import com.yfd.platform.config.bean.LoginCodeEnum; import com.yfd.platform.config.bean.LoginProperties; import com.yfd.platform.constant.Constant; -import com.yfd.platform.system.domain.LoginUser; -import com.yfd.platform.system.domain.SysLog; -import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.domain.*; +import com.yfd.platform.system.mapper.SysMenuMapper; +import com.yfd.platform.system.mapper.SysUserMapper; +import com.yfd.platform.system.mapper.SysUserTenantMapper; +import com.yfd.platform.system.service.ISmsVerifyCodeService; +import com.yfd.platform.system.service.ISysAcctPasswordPolicyService; import com.yfd.platform.system.service.ISysLogService; import com.yfd.platform.system.service.IUserService; import com.yfd.platform.utils.RequestHolder; @@ -35,6 +38,7 @@ import org.springframework.web.bind.annotation.*; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; + import java.sql.Timestamp; import java.util.HashMap; import java.util.List; @@ -66,10 +70,27 @@ public class LoginController { @Resource private LoginProperties loginProperties; + @Resource + private ISysAcctPasswordPolicyService policyService; + + @Resource + private SysUserTenantMapper sysUserTenantMapper; + + @Resource + private SysMenuMapper sysMenuMapper; + + @Resource + private SysUserMapper sysUserMapper; + + @Resource + private ISmsVerifyCodeService smsVerifyCodeService; + @PostMapping("/login") @Operation(summary = "登录用户") @ResponseBody - public ResponseResult login(SysUser user, @RequestHeader(value = "Tenant_id", required = false) String tenantId) throws Exception { + public ResponseResult login(SysUser user, + @RequestHeader(value = "Tenant_id", required = false) String tenantId, + @RequestParam(value = "clientType", required = false, defaultValue = "web") String clientType) throws Exception { // 密码解密 String password = RsaUtils.decryptByPrivateKey(privateKey, user.getPassword()); @@ -105,15 +126,15 @@ public class LoginController { if (!loginUser.isSuperAdmin() && StrUtil.isNotBlank(tenantId)) { List accessibleIds = loginUser.getAccessibleTenantIds(); if (accessibleIds == null || !accessibleIds.contains(tenantId)) { - return ResponseResult.error("账号不存在或密码错误"); + return ResponseResult.error("用户无权限访问该平台"); } } - if (StrUtil.isNotBlank(regStatus)&&"REJECTED".equals(regStatus)) { + if (StrUtil.isNotBlank(regStatus) && "REJECTED".equals(regStatus)) { return ResponseResult.error("账号审核未通过"); } - if (StrUtil.isNotBlank(regStatus)&&"PENDING".equals(regStatus)) { + if (StrUtil.isNotBlank(regStatus) && "PENDING".equals(regStatus)) { return ResponseResult.error("账号待审核,请联系管理员"); } @@ -121,6 +142,24 @@ public class LoginController { return ResponseResult.error("账号已停用"); } + // 多端登录控制:检查密码策略是否允许当前客户端类型多端登录 +// SysAcctPasswordPolicy policy = policyService.getCurrentPolicy(); +// if (policy != null) { +// boolean multiLoginEnabled; +// if ("app".equals(clientType)) { +// multiLoginEnabled = policy.getEnableAppMultipleLogin() != null && policy.getEnableAppMultipleLogin() == 1; +// } else { +// multiLoginEnabled = policy.getEnableWebMultipleLogin() != null && policy.getEnableWebMultipleLogin() == 1; +// } +// if (!multiLoginEnabled) { +// // 多端登录未开启,检查该用户是否已有同类型的活跃会话 +// String existingClientType = +// webConfig.loginuserCache().get("login:clientType:" + loginUser.getUsername()); +// if (StrUtil.isNotBlank(existingClientType) && existingClientType.equals(clientType)) { +// return ResponseResult.error("该账号已在其他设备登录,不允许同时登录"); +// } +// } +// } HttpServletRequest request = RequestHolder.getHttpServletRequest(); @@ -162,6 +201,8 @@ public class LoginController { String jsonStr = JSONUtil.toJsonStr(loginUser); webConfig.loginuserCache().put("login:" + userId, jsonStr); webConfig.loginuserCache().put("expire_time:" + userId, map.get("expire_time").toString()); + // 记录当前会话的客户端类型,用于多端登录控制 +// webConfig.loginuserCache().put("login:clientType:" + loginUser.getUsername(), clientType); return ResponseResult.successData(map); } @@ -201,6 +242,8 @@ public class LoginController { String userId = loginuser.getUser().getId(); //删除redis中的登陆用户信息 webConfig.loginuserCache().remove("login:" + userId); + // 清除客户端类型记录 +// webConfig.loginuserCache().remove("login:clientType:" + loginuser.getUsername()); //记录退出日志 HttpServletRequest request = RequestHolder.getHttpServletRequest(); SysLog sysLog = new SysLog(); @@ -266,4 +309,220 @@ public class LoginController { } + // ==================== 统一登录 ==================== + + /** + * 统一登录入口,支持两种方式: + *
    + *
  • 密码登录(loginType=password):用户名 + 密码 + 图形验证码
  • + *
  • 短信登录(loginType=sms):手机号 + 短信验证码
  • + *
+ *

均受密码策略中的多端登录控制(enableWebMultipleLogin / enableAppMultipleLogin)

+ */ + @PostMapping("/unifiedLogin") + @Operation(summary = "统一登录(支持密码/短信验证码)") + @ResponseBody + public ResponseResult unifiedLogin(@RequestHeader(value = "Tenant_id", required = false) String tenantId, + @RequestBody UnifiedLoginRequest req) throws Exception { + String clientType = StrUtil.isBlank(req.getClientType()) ? "web" : req.getClientType(); + LoginUser loginUser; + String loginDesc; + + // ========== 1. 密码登录 ========== + if ("password".equals(req.getLoginType())) { + if (StrUtil.isBlank(req.getUsername()) || StrUtil.isBlank(req.getPassword())) { + return ResponseResult.error("用户名和密码不能为空"); + } + + // 1.1 图形验证码校验 + if (StrUtil.isBlank(req.getCaptchaUuid()) || StrUtil.isBlank(req.getCaptchaCode())) { + return ResponseResult.error("验证码不能为空"); + } + String cachedCode = webConfig.loginuserCache().get(req.getCaptchaUuid()); + webConfig.loginuserCache().remove(req.getCaptchaUuid()); + if (StrUtil.isBlank(cachedCode)) { + return ResponseResult.error("验证码不存在或已过期"); + } + if (!req.getCaptchaCode().equalsIgnoreCase(cachedCode)) { + return ResponseResult.error("验证码错误"); + } + + // 1.2 密码解密 + Spring Security 认证 + String password = RsaUtils.decryptByPrivateKey(privateKey, req.getPassword()); + UsernamePasswordAuthenticationToken authToken = + new UsernamePasswordAuthenticationToken(req.getUsername(), password); + Authentication authenticate = authenticationManager.authenticate(authToken); + if (ObjectUtil.isNull(authenticate)) { + return ResponseResult.unlogin(); + } + loginUser = (LoginUser) authenticate.getPrincipal(); + loginDesc = loginUser.getUser().getNickname() + "登录系统!"; + } else if ("sms".equals(req.getLoginType())) { + // ========== 2. 短信验证码登录 ========== + if (StrUtil.isBlank(req.getPhone()) || StrUtil.isBlank(req.getSmsCode())) { + return ResponseResult.error("手机号和验证码不能为空"); + } + + // 2.1 验证短信验证码 + boolean verified = smsVerifyCodeService.verifyCode(req.getPhone(), req.getSmsCode(), SmsVerifyCode.TYPE_LOGIN, tenantId); + if (!verified) { + return ResponseResult.error("验证码错误或已过期"); + } + + // 2.2 通过手机号查找用户 + SysUser user = userService.getUserByPhone(req.getPhone(), null); + if (user == null) { + return ResponseResult.error("该手机号未注册"); + } + + // 2.3 状态校验 + String statusError = checkUserStatus(user); + if (statusError != null) { + return ResponseResult.error(statusError); + } + + // 2.4 判断超级管理员 + boolean isSuperAdmin = (checkIsSuperAdmin(user.getId()) || user.getUsertype() == 0); + + // 2.5 多门户权限校验 + List accessibleTenantIds = sysUserTenantMapper.getTenantIdsByUserId(user.getId()); + if (!isSuperAdmin) { + if (StrUtil.isBlank(tenantId)) { + return ResponseResult.error("用户无权限访问该平台"); + } + if (accessibleTenantIds == null || !accessibleTenantIds.contains(tenantId)) { + return ResponseResult.error("用户无权限访问该平台"); + } + } + + // 2.6 加载权限 + List permissions; + if (isSuperAdmin) { + permissions = sysMenuMapper.selectPermsByUserId(user.getId(), null); + } else { + permissions = sysMenuMapper.selectPermsByUserId(user.getId(), tenantId); + } + + loginUser = new LoginUser(user, permissions, tenantId, accessibleTenantIds, isSuperAdmin); + loginDesc = user.getNickname() + "使用短信验证码登录系统!"; + + // 短信登录:手动设置 SecurityContext + SecurityContextHolder.getContext().setAuthentication( + new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities())); + } else { + return ResponseResult.error("登录类型错误,仅支持 password / sms"); + } + + // ========== 3. 密码登录的额外状态校验 ========== + if ("password".equals(req.getLoginType())) { + String statusError = checkUserStatus(loginUser.getUser()); + if (statusError != null) { + return ResponseResult.error(statusError); + } + // 多门户校验 + if (!loginUser.isSuperAdmin() && StrUtil.isNotBlank(tenantId)) { + List accessibleIds = loginUser.getAccessibleTenantIds(); + if (accessibleIds == null || !accessibleIds.contains(tenantId)) { + return ResponseResult.error("用户无权限访问该平台"); + } + } + } + + // ========== 4. 多端登录控制 ========== + String multiLoginError = checkMultiLogin(loginUser.getUsername(), clientType); + if (multiLoginError != null) { + return ResponseResult.error(multiLoginError); + } + + // ========== 5. 生成 Token + 缓存会话 ========== + return buildLoginResult(loginUser, tenantId, clientType, loginDesc); + } + + + /** + * 校验用户状态,返回错误信息,null 表示通过 + */ + private String checkUserStatus(SysUser user) { + if (user.getStatus() != null && user.getStatus() == 0) { + return "账号已停用"; + } + if (user.getRegStatus() != null && "PENDING".equals(user.getRegStatus())) { + return "账号待审核,请联系管理员"; + } + if (user.getRegStatus() != null && "REJECTED".equals(user.getRegStatus())) { + return "账号审核未通过"; + } + return null; + } + + /** + * 多端登录控制检查 + */ + private String checkMultiLogin(String username, String clientType) { + SysAcctPasswordPolicy policy = policyService.getCurrentPolicy(); + if (policy == null) { + return null; + } + boolean multiLoginEnabled = "app".equals(clientType) + ? (policy.getEnableAppMultipleLogin() != null && policy.getEnableAppMultipleLogin() == 1) + : (policy.getEnableWebMultipleLogin() != null && policy.getEnableWebMultipleLogin() == 1); + if (!multiLoginEnabled) { + String existingClientType = webConfig.loginuserCache().get("login:clientType:" + username); + if (StrUtil.isNotBlank(existingClientType) && existingClientType.equals(clientType)) { + return "该账号已在其他设备登录,不允许同时登录"; + } + } + return null; + } + + /** + * 判断是否为超级管理员 + */ + private boolean checkIsSuperAdmin(String userId) { + String maxLevel = sysUserMapper.getMaxLevel(userId); + return "1".equals(maxLevel); + } + + /** + * 生成 JWT Token、记录日志、缓存会话信息 + */ + private ResponseResult buildLoginResult(LoginUser loginUser, String tenantId, + String clientType, String loginDesc) { + // 记录登录日志 + HttpServletRequest request = RequestHolder.getHttpServletRequest(); + SysLog sysLog = new SysLog(); + sysLog.setUsercode(loginUser.getUsername()); + sysLog.setUsername(loginUser.getUser().getNickname()); + sysLog.setRequestip(StringUtils.getIp(request)); + sysLog.setBrowser(StringUtils.getBrowser(request)); + sysLog.setOpttype("登录(login)"); + sysLog.setModule("统一登录"); + sysLog.setMethod(this.getClass().getName() + ".unifiedLogin()"); + sysLog.setDescription(loginDesc); + sysLog.setLogtime(new Timestamp(System.currentTimeMillis())); + sysLogService.save(sysLog); + + // 生成 JWT Token + String userId = loginUser.getUser().getId(); + Map map = new HashMap<>(10) {{ + put("userid", userId); + put("username", loginUser.getUsername()); + long expireTime = System.currentTimeMillis() + (30L * 24L * 60L * 60L * 1000L); + put("expire_time", expireTime); + }}; + String token = JWTUtil.createToken(map, "12345678".getBytes()); + map.put("token", token); + map.put("accessibleTenantIds", loginUser.getAccessibleTenantIds()); + map.put("superAdmin", loginUser.isSuperAdmin()); + map.put("currentTenantId", tenantId); + + // 缓存登录会话 + String jsonStr = JSONUtil.toJsonStr(loginUser); + webConfig.loginuserCache().put("login:" + userId, jsonStr); + webConfig.loginuserCache().put("expire_time:" + userId, map.get("expire_time").toString()); + webConfig.loginuserCache().put("login:clientType:" + loginUser.getUsername(), clientType); + + return ResponseResult.successData(map); + } + } diff --git a/backend/src/main/java/com/yfd/platform/system/domain/UnifiedLoginRequest.java b/backend/src/main/java/com/yfd/platform/system/domain/UnifiedLoginRequest.java new file mode 100644 index 00000000..ba220e92 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/domain/UnifiedLoginRequest.java @@ -0,0 +1,56 @@ +package com.yfd.platform.system.domain; + +import lombok.Data; + +/** + *

+ * 统一登录请求体,支持密码登录和短信验证码登录 + *

+ * + *
+ * 密码登录示例:
+ * {
+ *     "loginType": "password",
+ *     "username": "admin",
+ *     "password": "rsa_encrypted_password",
+ *     "captchaUuid": "code_xxx",
+ *     "captchaCode": "abcd",
+ *     "clientType": "web"
+ * }
+ *
+ * 短信登录示例:
+ * {
+ *     "loginType": "sms",
+ *     "phone": "13800138000",
+ *     "smsCode": "123456",
+ *     "clientType": "app"
+ * }
+ * 
+ */ +@Data +public class UnifiedLoginRequest { + + /** 登录类型: "password"(用户名密码) / "sms"(短信验证码) */ + private String loginType; + + /** 用户名(密码登录必填) */ + private String username; + + /** 密码(密码登录必填,RSA公钥加密) */ + private String password; + + /** 手机号(短信登录必填) */ + private String phone; + + /** 短信验证码(短信登录必填) */ + private String smsCode; + + /** 图形验证码UUID(密码登录时用于从缓存中比对验证码) */ + private String captchaUuid; + + /** 图形验证码(密码登录时用户输入的验证码) */ + private String captchaCode; + + /** 客户端类型: "web"(浏览器)/ "app"(移动端),默认 "web" */ + private String clientType; +} From bd8472db2ef66ccd4db240fa5b4a26b038d35a06 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 12 Aug 2026 09:40:18 +0800 Subject: [PATCH 20/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_base/service/impl/MsOperationLogServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java index fc9bcdba..10b0858b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -1067,8 +1067,8 @@ public class MsOperationLogServiceImpl extends ServiceImpl wrapper = new LambdaQueryWrapper<>(); wrapper.eq(MsOperationLogDetail::getMainId, mainId) .notIn(MsOperationLogDetail::getFieldCode, - "recordUser", "recordTime", "modifyUser", "modifyTime", - "isDeleted", "deleteUser", "deleteTime"); + "RECORD_USER", "RECORD_TIME", "MODIFY_USER", "MODIFY_TIME", + "IS_DELETED", "DELETE_USER", "DELETE_TIME"); return msOperationLogDetailMapper.selectList(wrapper); } From 7695bc0c126ef1a3fbd5306e07109f1322193ad5 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 12 Aug 2026 10:36:23 +0800 Subject: [PATCH 21/44] =?UTF-8?q?fix:=20=E7=94=B5=E7=AB=99=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E7=BB=93=E6=9E=9C=E6=95=B0=E6=8D=AE=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eq/controller/EngEqDataController.java | 6 + .../qgc_eng/eq/service/EngEqDataService.java | 27 +- .../eq/service/impl/EngEqDataServiceImpl.java | 334 ++++++++++++++++++ .../fp/service/impl/FpRunServiceImpl.java | 52 ++- 4 files changed, 385 insertions(+), 34 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java index 1773f5d0..ea68c002 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java @@ -187,4 +187,10 @@ public class EngEqDataController { public ResponseResult getEqdsKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(engEqDataService.getEqdsKendoListCust(dataSourceRequest)); } + + @PostMapping("/GetKendoListCust") + @Operation(summary = "电站业务结果数据查询(MS_ENG_T + V_MS_STBPRP_T)") + public ResponseResult getMsEngKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(engEqDataService.getMsEngKendoList(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java index 6dbcc43f..54caab7b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java @@ -2,26 +2,7 @@ package com.yfd.platform.qgc_eng.eq.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseVmsstbprptVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayDataVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayIntervalVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqdsVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqHourIntervalVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitQueryVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqMsstbprptVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRuleVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngQecAlongVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRateCountVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqVmsstbprptVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.QgcQecStaticVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.SdEqMonitorCountVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.StBaseInfo; -import com.yfd.platform.qgc_eng.eq.entity.vo.StcdInfoVo; -import com.yfd.platform.qgc_eng.eq.entity.vo.WbsbVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.*; import java.util.List; import java.util.Map; @@ -89,4 +70,10 @@ public interface EngEqDataService { StcdInfoVo getStInfoByStcd(String stcd); DataSourceResult getEqdsKendoListCust(DataSourceRequest dataSourceRequest); + + /** + * 查询 MS_ENG_T 电站业务结果数据(支持动态过滤、排序、分组) + *

对应旧系统 EngEqController.getKendoListCust

+ */ + DataSourceResult getMsEngKendoList(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index 6f7d0543..b7676e03 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -6337,4 +6337,338 @@ public class EngEqDataServiceImpl implements EngEqDataService { .append(String.join(", ", placeholders)) .append(") "); } + + // ==================== MS_ENG_T 电站业务结果查询 ==================== + + @Override + public DataSourceResult getMsEngKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryMsEngDetailList(dataSourceRequest, loadOptions); + } + return queryMsEngGroupList(dataSourceRequest, loadOptions); + } + + private DataSourceResult queryMsEngDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildMsEngDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" ") + .append(buildMsEngViewSql()) + .append(" WHERE NVL(MET.IS_DELETED, 0) = 0 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildMsEngFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildMsEngDetailOrderBySql(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, EngEqDataVo.class); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryMsEngGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapMsEngColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapMsEngColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildMsEngAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("MET.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(String.join(", ", selectItems)) + .append(" ") + .append(buildMsEngViewSql()) + .append(" WHERE NVL(MET.IS_DELETED, 0) = 0 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildMsEngFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapMsEngColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildMsEngGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (dataSourceRequest.getGroupResultFlat() != null && dataSourceRequest.getGroupResultFlat()) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + /** + * MS_ENG_T + V_MS_STBPRP_T 联合查询的 FROM 子句 + */ + private String buildMsEngViewSql() { + return "FROM MS_ENG_T MET " + + "LEFT JOIN MS_ENG_T MET1 ON MET1.STCD = MET.STCD " + + " AND MET1.TYPE = MET.TYPE " + + " AND ADD_MONTHS(MET1.TM, 12) = MET.TM " + + " AND NVL(MET1.IS_DELETED, 0) = 0 " + + "INNER JOIN V_MS_STBPRP_T MSB ON MSB.STCD = MET.STCD " + + " AND MSB.STTP_CODE = 'ENG' " + + " AND MSB.BLDSTT_CODE = 2 "; + } + + private Map msEngFieldColumns() { + Map columns = new LinkedHashMap<>(); + columns.put("id", "MET.ID AS id"); + columns.put("stcd", "MET.STCD AS stcd"); + columns.put("stnm", "MSB.STNM AS stnm"); + columns.put("ennm", "MSB.ENNM AS ennm"); + columns.put("tm", "MET.TM AS tm"); + columns.put("qi", "MET.QI AS qi"); + columns.put("qo", "MET.QO AS qo"); + columns.put("qecLimit", "MET.QEC_LIMIT AS qecLimit"); + columns.put("qec", "MET.QEC AS qec"); + columns.put("mwrLimit", "MET.MWR_LIMIT AS mwrLimit"); + columns.put("avqLimit", "MET.AVQ_LIMIT AS avqLimit"); + columns.put("qecC", "MET.QEC_C AS qecC"); + columns.put("mwrC", "MET.MWR_C AS mwrC"); + columns.put("avqC", "MET.AVQ_C AS avqC"); + columns.put("sfdb", "MET.QEC_SFDB AS sfdb"); + columns.put("sfdbName", "CASE NVL(MET.QEC_SFDB, -1) WHEN 0 THEN '不达标' WHEN 1 THEN '达标' WHEN 2 THEN '无生态流量数据' WHEN 3 THEN '无生态流量限值要求' ELSE NULL END AS sfdbName"); + columns.put("mwrSfdb", "MET.MWR_SFDB AS mwrSfdb"); + columns.put("mwrSfdbName", "CASE NVL(MET.MWR_SFDB, -1) WHEN 0 THEN '不达标' WHEN 1 THEN '达标' WHEN 2 THEN '无生态流量数据' WHEN 3 THEN '无生态流量限值要求' ELSE NULL END AS mwrSfdbName"); + columns.put("avqSfdb", "MET.AVQ_SFDB AS avqSfdb"); + columns.put("avqSfdbName", "CASE NVL(MET.AVQ_SFDB, -1) WHEN 0 THEN '不达标' WHEN 1 THEN '达标' WHEN 2 THEN '无生态流量数据' WHEN 3 THEN '无生态流量限值要求' ELSE NULL END AS avqSfdbName"); + columns.put("rz", "MET.RZ AS rz"); + columns.put("dz", "MET.DDZ AS dz"); + columns.put("baseName", "MSB.BASE_NAME AS baseName"); + columns.put("rvcdName", "MSB.RVCD_NAME AS rvcdName"); + columns.put("hbrvcdName", "MSB.HBRVCD_NAME AS hbrvcdName"); + columns.put("addvcdName", "MSB.ADDVNM AS addvcdName"); + columns.put("baseId", "MSB.BASE_ID AS baseId"); + columns.put("hbrvcd", "MSB.HBRVCD AS hbrvcd"); + columns.put("hycd", "MSB.HYCD AS hycd"); + columns.put("rvcd", "MSB.RVCD AS rvcd"); + columns.put("bldsttCcode", "MSB.BLDSTT_CODE AS bldsttCcode"); + columns.put("beforeQec", "MET1.QEC AS beforeQec"); + columns.put("baseStepSort", "NVL(MSB.BASESTEPSORT, 999999) AS baseStepSort"); + columns.put("rvcdStepSort", "NVL(MSB.RVCDSTEPSORT, 999999) AS rvcdStepSort"); + columns.put("rstcdStepSort", "NVL(MSB.RSTCDSTEPSORT, 999999) AS rstcdStepSort"); + columns.put("siteStepSort", "NVL(MSB.SITESTEPSORT, 999999) AS siteStepSort"); + return columns; + } + + private String buildMsEngDetailSelectSql(List selectFields) { + Map columns = msEngFieldColumns(); + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private String buildMsEngFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildMsEngLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildMsEngFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildMsEngLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapMsEngColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildGenericCondition(column, filter, paramMap, indexHolder, isMsEngDateField(filter.getField())); + } + + private String buildMsEngDetailOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY baseStepSort ASC, rvcdStepSort ASC, rstcdStepSort ASC, siteStepSort ASC, MET.TM DESC"; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapMsEngOrderColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + if (orders.isEmpty()) { + return " ORDER BY baseStepSort ASC, rvcdStepSort ASC, rstcdStepSort ASC, siteStepSort ASC, MET.TM DESC"; + } + return " ORDER BY " + String.join(", ", orders); + } + + private String buildMsEngGroupOrderBySql(List groups) { + if (CollUtil.isEmpty(groups)) { + return ""; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapMsEngColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(descriptor.getDir()) || "des".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders); + } + + private String buildMsEngAggregateSql(String aggregate, String column, String field) { + if (StrUtil.isBlank(aggregate) || StrUtil.isBlank(column)) { + return null; + } + return switch (aggregate.toLowerCase()) { + case "sum" -> "SUM(" + column + ") AS SUM_" + field.toUpperCase(); + case "avg" -> "AVG(" + column + ") AS AVG_" + field.toUpperCase(); + case "min" -> "MIN(" + column + ") AS MIN_" + field.toUpperCase(); + case "max" -> "MAX(" + column + ") AS MAX_" + field.toUpperCase(); + default -> null; + }; + } + + private String mapMsEngColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "MET.ID"; + case "stcd" -> "MSB.STCD"; + case "stnm" -> "MSB.STNM"; + case "ennm" -> "MSB.ENNM"; + case "tm" -> "MET.TM"; + case "qi" -> "MET.QI"; + case "qo" -> "MET.QO"; + case "qecLimit" -> "MET.QEC_LIMIT"; + case "qec" -> "MET.QEC"; + case "mwrLimit" -> "MET.MWR_LIMIT"; + case "avqLimit" -> "MET.AVQ_LIMIT"; + case "qecC" -> "MET.QEC_C"; + case "mwrC" -> "MET.MWR_C"; + case "avqC" -> "MET.AVQ_C"; + case "sfdb", "qecSfdb" -> "MET.QEC_SFDB"; + case "mwrSfdb" -> "MET.MWR_SFDB"; + case "avqSfdb" -> "MET.AVQ_SFDB"; + case "rz" -> "MET.RZ"; + case "dz" -> "MET.DDZ"; + case "baseName" -> "MSB.BASE_NAME"; + case "rvcdName" -> "MSB.RVCD_NAME"; + case "hbrvcdName" -> "MSB.HBRVCD_NAME"; + case "addvcdName" -> "MSB.ADDVNM"; + case "baseId" -> "MSB.BASE_ID"; + case "hbrvcd" -> "MSB.HBRVCD"; + case "hycd" -> "MSB.HYCD"; + case "rvcd" -> "MSB.RVCD"; + case "bldsttCcode" -> "MSB.BLDSTT_CODE"; + case "baseStepSort" -> "MSB.BASESTEPSORT"; + case "rvcdStepSort" -> "MSB.RVCDSTEPSORT"; + case "rstcdStepSort" -> "MSB.RSTCDSTEPSORT"; + case "siteStepSort" -> "MSB.SITESTEPSORT"; + default -> null; + }; + } + + private String mapMsEngOrderColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id", "baseId", "hbrvcd", "hycd", "rvcd", "bldsttCcode", + "sfdbName", "mwrSfdb", "mwrSfdbName", "avqSfdb", "avqSfdbName", + "qecC", "mwrC", "avqC", "beforeQec", + "baseStepSort", "rvcdStepSort", "rstcdStepSort", "siteStepSort", + "stcd", "stnm", "ennm", "qi", "qo", "qec", "sfdb", + "rz", "dz", "qecLimit", "mwrLimit", "avqLimit", "baseName", + "rvcdName", "hbrvcdName", "addvcdName" -> field; + case "tm" -> "MET.TM"; + default -> null; + }; + } + + private boolean isMsEngDateField(String field) { + return "tm".equalsIgnoreCase(field); + } + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index b4abe1df..8baf1fd0 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -2741,23 +2741,33 @@ public class FpRunServiceImpl implements FpRunService { public DataSourceResult getTreeStcdList(DataSourceRequest dataSourceRequest) { // 查询 SD_FPSSRL_R(自动, MWAY=2)和 SD_FPSS_R(人工, MWAY=1)中有过鱼数据的测站 // 关联 V_MS_STBPRP_T 视图获取测站基础信息(含 ENNM 电站名称) - String sql = "SELECT STCD, STNM, MWAY, LGTD, LTTD, BASE_ID, RSTCD, ENNM " - + "FROM (" - + " SELECT DISTINCT t2.STCD, t2.STNM, t2.BASE_ID, t2.RSTCD, t2.LGTD, t2.LTTD, t2.MWAY, t2.ENNM " - + " FROM SD_FPSSRL_R t1 " - + " INNER JOIN V_MS_STBPRP_T t2 ON t1.STCD = t2.STCD " - + " WHERE NVL(t2.IS_DELETED, 0) = 0 AND t2.MWAY = 2 AND t1.FTP IS NOT NULL " - + " UNION " - + " SELECT DISTINCT t4.STCD, t4.STNM, t4.BASE_ID, t4.RSTCD, t4.LGTD, t4.LTTD, t4.MWAY, t4.ENNM " - + " FROM SD_FPSS_R t3 " - + " INNER JOIN V_MS_STBPRP_T t4 ON t3.STCD = t4.STCD " - + " WHERE NVL(t4.IS_DELETED, 0) = 0 AND t4.MWAY = 1 AND t3.FTP IS NOT NULL " - + " AND NVL(t3.IS_DELETED, 0) = 0" - + ")"; + StringBuilder sql = new StringBuilder(); + sql.append("SELECT STCD, STNM, MWAY, LGTD, LTTD, BASE_ID, RSTCD, ENNM ") + .append("FROM (") + .append(" SELECT DISTINCT t2.STCD, t2.STNM, t2.BASE_ID, t2.RSTCD, t2.LGTD, t2.LTTD, t2.MWAY, t2.ENNM ") + .append(" FROM SD_FPSSRL_R t1 ") + .append(" INNER JOIN V_MS_STBPRP_T t2 ON t1.STCD = t2.STCD ") + .append(" WHERE NVL(t2.IS_DELETED, 0) = 0 AND t2.MWAY = 2 AND t1.FTP IS NOT NULL ") + .append(" UNION ") + .append(" SELECT DISTINCT t4.STCD, t4.STNM, t4.BASE_ID, t4.RSTCD, t4.LGTD, t4.LTTD, t4.MWAY, t4.ENNM ") + .append(" FROM SD_FPSS_R t3 ") + .append(" INNER JOIN V_MS_STBPRP_T t4 ON t3.STCD = t4.STCD ") + .append(" WHERE NVL(t4.IS_DELETED, 0) = 0 AND t4.MWAY = 1 AND t3.FTP IS NOT NULL ") + .append(" AND NVL(t3.IS_DELETED, 0) = 0") + .append(") t WHERE 1=1 "); Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::FpTree + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } List allItems = microservicDynamicSQLMapper - .getAllListWithResultType(sql, paramMap, FpTreeStcdVo.class); + .getAllListWithResultType(sql.toString(), paramMap, FpTreeStcdVo.class); if (CollUtil.isEmpty(allItems)) { DataSourceResult emptyResult = new DataSourceResult<>(); @@ -2815,4 +2825,18 @@ public class FpRunServiceImpl implements FpRunService { result.setAggregates(new HashMap<>()); return result; } + + private String FpTree(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field.toLowerCase()) { + case "rstcd" -> "t.RSTCD"; + case "lgtd" -> "fp.LGTD"; + case "lttd" -> "fp.LTTD"; + default -> null; + }; + } + + } From 3f1c01461754156fedcdbff2452d1a9b7d6b42cf Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 12 Aug 2026 17:25:17 +0800 Subject: [PATCH 22/44] =?UTF-8?q?feat:=20=E7=8E=AF=E4=BF=9D=E9=83=A8-?= =?UTF-8?q?=E8=BF=87=E9=B1=BC=E6=80=BB=E9=87=8F-=E4=BA=8C=E7=BA=A7?= =?UTF-8?q?=E5=BC=B9=E7=AA=97=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fp/controller/FishPassageController.java | 6 + .../fp/entity/vo/FpOverfishTotalVo.java | 84 ++++++ .../qgc_env/fp/service/FpRunService.java | 3 + .../fp/service/impl/FpRunServiceImpl.java | 253 ++++++++++++++++++ 4 files changed, 346 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpOverfishTotalVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java index e5f1f215..aeaeca8d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java @@ -136,4 +136,10 @@ public class FishPassageController { public ResponseResult getTreeStcdList(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fpRunService.getTreeStcdList(dataSourceRequest)); } + + @PostMapping("/query/qgc/getOverfishTotal") + @Operation(summary = "环保部-过鱼总量-二级弹窗列表(SD_FPSSRL_R + SD_FPSS_R 合并)") + public ResponseResult getQgcOverfishTotal(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fpRunService.processQgcOverfishTotalKendoList(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpOverfishTotalVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpOverfishTotalVo.java new file mode 100644 index 00000000..49d32290 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpOverfishTotalVo.java @@ -0,0 +1,84 @@ +package com.yfd.platform.qgc_env.fp.entity.vo; + +import lombok.Data; + +import java.util.Date; + +/** + *

+ * 环保部-过鱼总量-二级弹窗列表 VO + *

+ *

对应旧系统 FpssrlRQueryVo.getQgcOverfishTotal,查询 SD_FPSSRL_R + SD_FPSS_R 合并数据

+ */ +@Data +public class FpOverfishTotalVo { + + /** 过鱼设施编码 */ + private String stcd; + + /** 设施名称 */ + private String stnm; + + /** 基地编码 */ + private String baseId; + + /** 基地名称 */ + private String baseName; + + /** 电站编码 */ + private String rstcd; + + /** 电站名称 */ + private String ennm; + + /** 时间 */ + private Date tm; + + /** 过鱼年份 */ + private String yr; + + /** 鱼类名称 */ + private String ftp; + + /** 鱼类编码 */ + private String fishId; + + /** 大小 */ + private String fsz; + + /** 鱼宽度 */ + private String width; + + /** 鱼速度 */ + private String fishspeed; + + /** 游向:0=上行 1=下行 */ + private String direction; + + /** 水温 */ + private String temperature; + + /** 流速 */ + private String speed; + + /** 过鱼通道 */ + private String channelno; + + /** 数量 */ + private String fcnt; + + /** 图片URL */ + private String firstimgurl; + + /** 视频URL */ + private String videourl; + + /** 监测方式:1=人工 2=自动 */ + private Integer mway; + + /** 人工过鱼 开始日期 */ + private Date strdt; + + /** 人工过鱼 结束日期 */ + private Date enddt; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java index 14e24b26..c6eea469 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java @@ -10,6 +10,7 @@ import com.yfd.platform.qgc_env.fp.entity.vo.FpSdfpssrVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpTableVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpTreeStcdGroupVo; import com.yfd.platform.qgc_env.fp.entity.vo.YearFpStatisticsVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpOverfishTotalVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunPlanVo; import java.util.List; @@ -35,4 +36,6 @@ public interface FpRunService { List getYearFpStatic(String year,String stcd); DataSourceResult getTreeStcdList(DataSourceRequest dataSourceRequest); + + DataSourceResult processQgcOverfishTotalKendoList(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index 8baf1fd0..9c753d0a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -17,6 +17,7 @@ import com.yfd.platform.qgc_env.fp.entity.vo.FbFishRunVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFishSelectVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQueryVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFtpStatisticsVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpOverfishTotalVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunAnalysisHeadColumnVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunAnalysisTableVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunAnalysisVo; @@ -2838,5 +2839,257 @@ public class FpRunServiceImpl implements FpRunService { }; } + // ==================== 环保部-过鱼总量-二级弹窗列表 ==================== + + @Override + public DataSourceResult processQgcOverfishTotalKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryOverfishTotalDetailList(dataSourceRequest, loadOptions); + } + return queryOverfishTotalGroupList(dataSourceRequest, loadOptions); + } + + private DataSourceResult queryOverfishTotalDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildOverfishTotalSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildOverfishTotalCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapOverfishTotalColumn + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildOverfishTotalOrderBySql(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, FpOverfishTotalVo.class + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryOverfishTotalGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapOverfishTotalColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapOverfishTotalColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder("SELECT "); + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildOverfishTotalCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapOverfishTotalColumn + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapOverfishTotalColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (dataSourceRequest.getGroupResultFlat() != null && dataSourceRequest.getGroupResultFlat()) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + /** + * 过鱼总量核心 SQL:SD_FPSSRL_R(自动)UNION ALL SD_FPSS_R(人工) + *

使用 V_MS_STBPRP_T 替代旧系统 MS_STBPRP_T,V_SD_FISHDICTORY_B 替代旧版鱼类字典

+ */ + private String buildOverfishTotalCoreSql() { + return "SELECT t.STCD, t.STNM, t.BASE_ID, t.BASE_NAME, " + + "t.RSTCD, t.ENNM, t.TM, t.YR, t.FTP, t.FISHID, t.FSZ, " + + "t.WIDTH, t.FISHSPEED, t.DIRECTION, t.TEMPERATURE, t.SPEED, " + + "t.CHANNELNO, t.FCNT, t.FIRSTIMGURL, t.VIDEOURL, " + + "t.MWAY, t.STRDT, t.ENDDT " + + "FROM ( " + + // ---- 自动监测 SD_FPSSRL_R ---- + " SELECT a.STCD, msb.STNM, msb.BASE_ID, msb.BASE_NAME, msb.RSTCD, msb.ENNM, " + + " a.TM, TO_CHAR(a.TM, 'YYYY') AS YR, dict.NAME AS FTP, a.FTP AS FISHID, a.FSZ, " + + " TO_CHAR(a.WIDTH) AS WIDTH, TO_CHAR(a.FISHSPEED) AS FISHSPEED, " + + " TO_CHAR(a.DIRECTION) AS DIRECTION, TO_CHAR(a.TEMPERATURE) AS TEMPERATURE, " + + " TO_CHAR(a.SPEED) AS SPEED, a.CHANNELNO, TO_CHAR(a.FCNT) AS FCNT, " + + " a.FIRSTIMGURL, a.VIDEOURL, msb.MWAY, NULL AS STRDT, NULL AS ENDDT " + + " FROM SD_FPSSRL_R a " + + " INNER JOIN V_MS_STBPRP_T msb ON a.STCD = msb.STCD AND msb.DATA_SOURCE = 'SD_FPSS_B_H' " + + " INNER JOIN V_SD_FISHDICTORY_B dict ON a.FTP = dict.FISH_ID " + + " AND (msb.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') " + + " WHERE NVL(a.IS_DELETED, 0) = 0 " + + " UNION ALL " + + // ---- 人工监测 SD_FPSS_R ---- + " SELECT a.STCD, msb.STNM, msb.BASE_ID, msb.BASE_NAME, msb.RSTCD, msb.ENNM, " + + " a.STRDT AS TM, TO_CHAR(a.STRDT, 'YYYY') AS YR, dict.NAME AS FTP, a.FTP AS FISHID, " + + " MIN(a.FSZ) AS FSZ, NULL AS WIDTH, NULL AS FISHSPEED, " + + " TO_CHAR(MIN(a.DIRECTION)) AS DIRECTION, NULL AS TEMPERATURE, NULL AS SPEED, " + + " NULL AS CHANNELNO, TO_CHAR(SUM(a.FCNT)) AS FCNT, " + + " NULL AS FIRSTIMGURL, NULL AS VIDEOURL, 1 AS MWAY, a.STRDT, a.ENDDT " + + " FROM SD_FPSS_R a " + + " INNER JOIN V_MS_STBPRP_T msb ON a.STCD = msb.STCD AND msb.DATA_SOURCE = 'SD_FPSS_B_H' " + + " INNER JOIN V_SD_FISHDICTORY_B dict ON a.FTP = dict.FISH_ID " + + " AND (msb.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') " + + " WHERE 1=1 " + + " AND NVL(a.IS_DELETED, 0) = 0 " + + " GROUP BY a.STCD, msb.STNM, msb.BASE_ID, msb.BASE_NAME, msb.RSTCD, msb.ENNM, " + + " a.STRDT, a.ENDDT, TO_CHAR(a.STRDT, 'YYYY'), dict.NAME, a.FTP " + + ") t WHERE 1 = 1 "; + } + + private String buildOverfishTotalSelectSql(List selectFields) { + Map columns = new LinkedHashMap<>(); + columns.put("stcd", "t.STCD AS stcd"); + columns.put("stnm", "t.STNM AS stnm"); + columns.put("baseId", "t.BASE_ID AS baseId"); + columns.put("baseName", "t.BASE_NAME AS baseName"); + columns.put("rstcd", "t.RSTCD AS rstcd"); + columns.put("ennm", "t.ENNM AS ennm"); + columns.put("tm", "t.TM AS tm"); + columns.put("yr", "t.YR AS yr"); + columns.put("ftp", "t.FTP AS ftp"); + columns.put("fishId", "t.FISHID AS fishId"); + columns.put("fsz", "t.FSZ AS fsz"); + columns.put("width", "t.WIDTH AS width"); + columns.put("fishspeed", "t.FISHSPEED AS fishspeed"); + columns.put("direction", "t.DIRECTION AS direction"); + columns.put("temperature", "t.TEMPERATURE AS temperature"); + columns.put("speed", "t.SPEED AS speed"); + columns.put("channelno", "t.CHANNELNO AS channelno"); + columns.put("fcnt", "t.FCNT AS fcnt"); + columns.put("firstimgurl", "t.FIRSTIMGURL AS firstimgurl"); + columns.put("videourl", "t.VIDEOURL AS videourl"); + columns.put("mway", "t.MWAY AS mway"); + columns.put("strdt", "t.STRDT AS strdt"); + columns.put("enddt", "t.ENDDT AS enddt"); + + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private String mapOverfishTotalColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field.toLowerCase()) { + case "stcd" -> "t.STCD"; + case "stnm" -> "t.STNM"; + case "baseid" -> "t.BASE_ID"; + case "basename" -> "t.BASE_NAME"; + case "rstcd" -> "t.RSTCD"; + case "ennm" -> "t.ENNM"; + case "tm" -> "t.TM"; + case "yr" -> "t.YR"; + case "ftp" -> "t.FTP"; + case "fishid" -> "t.FISHID"; + case "fsz" -> "t.FSZ"; + case "width" -> "t.WIDTH"; + case "fishspeed" -> "t.FISHSPEED"; + case "direction" -> "t.DIRECTION"; + case "temperature" -> "t.TEMPERATURE"; + case "speed" -> "t.SPEED"; + case "channelno" -> "t.CHANNELNO"; + case "fcnt" -> "t.FCNT"; + case "mway" -> "t.MWAY"; + case "strdt" -> "t.STRDT"; + case "enddt" -> "t.ENDDT"; + case "firstimgurl" -> "t.FIRSTIMGURL"; + case "videourl" -> "t.VIDEOURL"; + default -> null; + }; + } + + private String buildOverfishTotalOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.TM DESC"; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapOverfishTotalColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + return orders.isEmpty() ? " ORDER BY t.TM DESC" : " ORDER BY " + String.join(", ", orders); + } } From 2e2c91f6796f8da999af5eb2fa401bebd3f2d71c Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 13 Aug 2026 08:14:32 +0800 Subject: [PATCH 23/44] =?UTF-8?q?feat:=20=E8=BF=87=E9=B1=BC=E8=AE=BE?= =?UTF-8?q?=E6=96=BD=E8=87=AA=E5=8A=A8=E6=95=B0=E6=8D=AE=E6=97=A5=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fp/controller/FishPassageController.java | 6 + .../qgc_env/fp/entity/vo/FpFpssrlQdaySVo.java | 83 +++++++ .../qgc_env/fp/service/FpRunService.java | 3 + .../fp/service/impl/FpRunServiceImpl.java | 220 ++++++++++++++++++ 4 files changed, 312 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQdaySVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java index aeaeca8d..763a2697 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java @@ -142,4 +142,10 @@ public class FishPassageController { public ResponseResult getQgcOverfishTotal(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fpRunService.processQgcOverfishTotalKendoList(dataSourceRequest)); } + + @PostMapping("/fpssrlQdays/GetKendoListCust") + @Operation(summary = "过鱼设施自动数据日统计表(SD_FPSSRLDAY_S)") + public ResponseResult getQgcFpssrlQdaySKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fpRunService.processQgcFpssrlQdaySKendoList(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQdaySVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQdaySVo.java new file mode 100644 index 00000000..176d7281 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQdaySVo.java @@ -0,0 +1,83 @@ +package com.yfd.platform.qgc_env.fp.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 过鱼设施自动数据(带水温,流速)日统计表 VO + *

+ *

对应新表 SD_FPSSRLDAY_S(旧系统 SD_FPSSRLQDAY_S)

+ */ +@Data +@Schema(description = "过鱼设施自动数据日统计表") +public class FpFpssrlQdaySVo { + + @Schema(description = "主键ID") + private String id; + + @Schema(description = "过鱼设施编码") + private String stcd; + + @Schema(description = "日期。精确到天") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date dt; + + @Schema(description = "鱼类") + private String ftp; + + @Schema(description = "自动过鱼设施过鱼数量") + private BigDecimal fcnt; + + @Schema(description = "水温,单位:℃") + private BigDecimal temperature; + + @Schema(description = "水位,单位:m") + private BigDecimal waterlevel; + + @Schema(description = "流速,单位:m/s") + private BigDecimal speed; + + @Schema(description = "流量,单位:m3/s") + private BigDecimal q; + + @Schema(description = "溶氧,单位:mg/L") + private BigDecimal dox; + + @Schema(description = "浊度,单位:NTU") + private BigDecimal tu; + + @Schema(description = "鱼尺寸") + private String fsz; + + @Schema(description = "鱼长度") + private BigDecimal length; + + @Schema(description = "鱼宽度") + private BigDecimal width; + + @Schema(description = "鱼速度") + private String fishspeed; + + @Schema(description = "游向:0=上行 1=下行") + private BigDecimal direction; + + @Schema(description = "鱼位置") + private BigDecimal fishposition; + + @Schema(description = "鱼截图主图片url") + private String firstimgurl; + + @Schema(description = "鱼截图副图片url") + private String secondimgurl; + + @Schema(description = "视频url") + private String videourl; + + @Schema(description = "过鱼通道") + private String channelno; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java index c6eea469..833178df 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java @@ -11,6 +11,7 @@ import com.yfd.platform.qgc_env.fp.entity.vo.FpTableVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpTreeStcdGroupVo; import com.yfd.platform.qgc_env.fp.entity.vo.YearFpStatisticsVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpOverfishTotalVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQdaySVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunPlanVo; import java.util.List; @@ -38,4 +39,6 @@ public interface FpRunService { DataSourceResult getTreeStcdList(DataSourceRequest dataSourceRequest); DataSourceResult processQgcOverfishTotalKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult processQgcFpssrlQdaySKendoList(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index 9c753d0a..2991a0a9 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -16,6 +16,7 @@ import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_env.fp.entity.vo.FbFishRunVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFishSelectVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQueryVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQdaySVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFtpStatisticsVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpOverfishTotalVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunAnalysisHeadColumnVo; @@ -3092,4 +3093,223 @@ public class FpRunServiceImpl implements FpRunService { return orders.isEmpty() ? " ORDER BY t.TM DESC" : " ORDER BY " + String.join(", ", orders); } + // ==================== 过鱼设施自动数据日统计表 ==================== + + @Override + public DataSourceResult processQgcFpssrlQdaySKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryFpssrlQdaySDetailList(dataSourceRequest, loadOptions); + } + return queryFpssrlQdaySGroupList(dataSourceRequest, loadOptions); + } + + private DataSourceResult queryFpssrlQdaySDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildFpssrlQdaySSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildFpssrlQdaySCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapFpssrlQdaySColumn + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildFpssrlQdaySOrderBySql(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, FpFpssrlQdaySVo.class + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryFpssrlQdaySGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapFpssrlQdaySColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapFpssrlQdaySColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder("SELECT "); + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildFpssrlQdaySCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapFpssrlQdaySColumn + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapFpssrlQdaySColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildFpssrlQdaySOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (dataSourceRequest.getGroupResultFlat() != null && dataSourceRequest.getGroupResultFlat()) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + /** + * 过鱼设施自动数据日统计表核心 SQL:单表 SD_FPSSRLDAY_S + */ + private String buildFpssrlQdaySCoreSql() { + return "SELECT t.ID, t.STCD, t.DT, t.FTP, t.FCNT, t.TEMPERATURE, t.WATERLEVEL, t.SPEED, " + + "t.Q, t.DOX, t.TU, t.FSZ, t.LENGTH, t.WIDTH, t.FISHSPEED, t.DIRECTION, " + + "t.FISHPOSITION, t.FIRSTIMGURL, t.SECONDIMGURL, t.VIDEOURL, t.CHANNELNO " + + "FROM SD_FPSSRLDAY_S t " + + "WHERE NVL(t.IS_DELETED, 0) = 0 "; + } + + private String buildFpssrlQdaySSelectSql(List selectFields) { + Map columns = new LinkedHashMap<>(); + columns.put("id", "t.ID AS id"); + columns.put("stcd", "t.STCD AS stcd"); + columns.put("dt", "t.DT AS dt"); + columns.put("ftp", "t.FTP AS ftp"); + columns.put("fcnt", "t.FCNT AS fcnt"); + columns.put("temperature", "t.TEMPERATURE AS temperature"); + columns.put("waterlevel", "t.WATERLEVEL AS waterlevel"); + columns.put("speed", "t.SPEED AS speed"); + columns.put("q", "t.Q AS q"); + columns.put("dox", "t.DOX AS dox"); + columns.put("tu", "t.TU AS tu"); + columns.put("fsz", "t.FSZ AS fsz"); + columns.put("length", "t.LENGTH AS length"); + columns.put("width", "t.WIDTH AS width"); + columns.put("fishspeed", "t.FISHSPEED AS fishspeed"); + columns.put("direction", "t.DIRECTION AS direction"); + columns.put("fishposition", "t.FISHPOSITION AS fishposition"); + columns.put("firstimgurl", "t.FIRSTIMGURL AS firstimgurl"); + columns.put("secondimgurl", "t.SECONDIMGURL AS secondimgurl"); + columns.put("videourl", "t.VIDEOURL AS videourl"); + columns.put("channelno", "t.CHANNELNO AS channelno"); + + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private String mapFpssrlQdaySColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field.toLowerCase()) { + case "id" -> "t.ID"; + case "stcd" -> "t.STCD"; + case "dt" -> "t.DT"; + case "ftp" -> "t.FTP"; + case "fcnt" -> "t.FCNT"; + case "temperature" -> "t.TEMPERATURE"; + case "waterlevel" -> "t.WATERLEVEL"; + case "speed" -> "t.SPEED"; + case "q" -> "t.Q"; + case "dox" -> "t.DOX"; + case "tu" -> "t.TU"; + case "fsz" -> "t.FSZ"; + case "length" -> "t.LENGTH"; + case "width" -> "t.WIDTH"; + case "fishspeed" -> "t.FISHSPEED"; + case "direction" -> "t.DIRECTION"; + case "fishposition" -> "t.FISHPOSITION"; + case "firstimgurl" -> "t.FIRSTIMGURL"; + case "secondimgurl" -> "t.SECONDIMGURL"; + case "videourl" -> "t.VIDEOURL"; + case "channelno" -> "t.CHANNELNO"; + default -> null; + }; + } + + private String buildFpssrlQdaySOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.DT DESC"; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapFpssrlQdaySColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + return orders.isEmpty() ? " ORDER BY t.DT DESC" : " ORDER BY " + String.join(", ", orders); + } + } From 8ce31d9c8045f0149495f99baf917e77b510b818 Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 13 Aug 2026 10:59:40 +0800 Subject: [PATCH 24/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E6=B8=B8?= =?UTF-8?q?=E5=90=91=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/FishDraftDataController.java | 5 +- .../qgc_data/service/IFishImportService.java | 2 +- .../service/impl/FishImportServiceImpl.java | 97 +++++++++++++++++-- .../service/impl/AdminAuthServiceImpl.java | 4 +- 4 files changed, 97 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java b/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java index 186e6971..c59aa0a2 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java @@ -1227,8 +1227,9 @@ public class FishDraftDataController { if (data.getDirection() == null || data.getDirection().isEmpty()) { addWarning(warnings, "direction"); } else { - String direction = fishImportService.resolveDirection(data.getDirection().trim(), importRow); - if (direction == null) { + String direction = fishImportService.resolveDirection(data.getStnm(),data.getDirection().trim(), importRow); + if (direction == null||importRow.getWarnings().contains("direction")) { + data.setDirection(direction); addWarning(warnings, "direction"); } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishImportService.java b/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishImportService.java index 44bfdb8d..a78c0c63 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishImportService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishImportService.java @@ -42,7 +42,7 @@ public interface IFishImportService { String resolveBaseCode(String code,String baseName); String resolveRiverCode(String code,String riverName); String resolveHbrvcdCode(String code,String riverName); - String resolveDirection(String direction, FishImportResult.FishImportRow importRow); + String resolveDirection(String stnm,String direction, FishImportResult.FishImportRow importRow); String resolveIsfs(String value, FishImportResult.FishImportRow importRow); diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishImportServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishImportServiceImpl.java index 23f1728b..68e67d3b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishImportServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishImportServiceImpl.java @@ -342,12 +342,16 @@ public class FishImportServiceImpl implements IFishImportService { FishImportResult.FishImportRow importRow = new FishImportResult.FishImportRow(rowIndex); FishDraftData data = new FishDraftData(); data.setId(UUID.randomUUID().toString()); - + String stnm=null; for (Map.Entry entry : columnIndexMap.entrySet()) { Integer columnIndex = entry.getKey(); String fieldName = entry.getValue(); Cell cell = row.getCell(columnIndex); String cellValue = getCellStringValue(cell); + + if("stnm".equals(fieldName)){ + stnm=cellValue; + } try { switch (fieldName) { case "stationName": @@ -509,7 +513,7 @@ public class FishImportServiceImpl implements IFishImportService { importRow.getWarnings().add(fieldName); data.setDirection(cellValue.trim()); } else { - String direction = resolveDirection(cellValue.trim(), importRow); + String direction = resolveDirection(stnm,cellValue.trim(), importRow); data.setDirection(direction); } break; @@ -1372,25 +1376,104 @@ public class FishImportServiceImpl implements IFishImportService { return facilityName; } - public String resolveDirection(String direction, FishImportResult.FishImportRow importRow) { + + public String resolveDirection(String stnm, String direction, FishImportResult.FishImportRow importRow) { if (direction == null) { return null; } String lowerName = direction.toLowerCase().trim(); - if (lowerName.contains("上行") && lowerName.contains("折返")) { + // 独立判断四种方向类型(按优先级从高到低) + boolean isUpReturn = lowerName.contains("上行") && lowerName.contains("折返"); + boolean isDownReturn = lowerName.contains("下行") && lowerName.contains("折返"); + boolean isUp = lowerName.contains("上行") && !isUpReturn; // 排除上行折返 + boolean isDown = lowerName.contains("下行") && !isDownReturn; // 排除下行折返 + + // 判断 direction 是否为字典编码 + boolean isDictCode = "0".equals(direction) || "1".equals(direction) || + "2".equals(direction) || "3".equals(direction); + + // 如果 direction 本身是字典编码(0/1/2/3),直接识别 + if ("0".equals(direction)) { + isUp = true; + isUpReturn = false; + } else if ("1".equals(direction)) { + isDown = true; + isDownReturn = false; + } else if ("2".equals(direction)) { + isUpReturn = true; + isUp = false; + } else if ("3".equals(direction)) { + isDownReturn = true; + isDown = false; + } + + // 根据设施名称校验方向(仅当 stnm 不为 null 时) + if (StrUtil.isNotBlank(stnm)) { + String facilityName = stnm.toLowerCase().trim(); + // 设施名称包含"上行"时,只允许上行或上行折返 + if (facilityName.contains("上行") && !isUp && !isUpReturn) { + importRow.getWarnings().add("direction"); + // 如果是字典编码,返回对应的中文;否则返回原始数据 + return isDictCode ? getDirectionChinese(direction) : direction; + } + // 设施名称包含"下行"时,只允许下行或下行折返 + if (facilityName.contains("下行") && !isDown && !isDownReturn) { + importRow.getWarnings().add("direction"); + // 如果是字典编码,返回对应的中文;否则返回原始数据 + return isDictCode ? getDirectionChinese(direction) : direction; + } + } + + // 返回对应的字典编码 + if (isUpReturn) { return "2"; - } else if (lowerName.contains("下行") && lowerName.contains("折返")) { + } else if (isDownReturn) { return "3"; - } else if (lowerName.contains("上行")) { + } else if (isUp) { return "0"; - } else if (lowerName.contains("下行")) { + } else if (isDown) { return "1"; } + + // 未匹配任何方向 importRow.getWarnings().add("direction"); return direction; } + /** + * 根据字典编码返回对应的中文描述 + */ + private String getDirectionChinese(String dictCode) { + if ("0".equals(dictCode)) { + return "上行"; + } else if ("1".equals(dictCode)) { + return "下行"; + } else if ("2".equals(dictCode)) { + return "上行折返"; + } else if ("3".equals(dictCode)) { + return "下行折返"; + } + return dictCode; + } +// public String resolveDirection(String stnm,String direction, FishImportResult.FishImportRow importRow) { +// if (direction == null) { +// return null; +// } +// String lowerName = direction.toLowerCase().trim(); +// if (lowerName.contains("上行") && lowerName.contains("折返")) { +// return "2"; +// } else if (lowerName.contains("下行") && lowerName.contains("折返")) { +// return "3"; +// } else if (lowerName.contains("上行")) { +// return "0"; +// } else if (lowerName.contains("下行")) { +// return "1"; +// } +// importRow.getWarnings().add("direction"); +// return direction; +// } + public String resolveIsfs(String value, FishImportResult.FishImportRow importRow) { if (value == null) { return null; diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/AdminAuthServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/AdminAuthServiceImpl.java index 4f75a0aa..0afe0e2c 100644 --- a/backend/src/main/java/com/yfd/platform/system/service/impl/AdminAuthServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/system/service/impl/AdminAuthServiceImpl.java @@ -74,8 +74,10 @@ public class AdminAuthServiceImpl implements IAdminAuthService { @Override public boolean isCurrentManagedAdmin() { +// SysUser sysUser = userMapper.selectById(SecurityUtils.getUserId()); String maxLevel = userMapper.getMaxLevel(SecurityUtils.getUserId()); boolean adminRole = "1".equals(maxLevel); - return adminRole||isManagedAdminUsername(SecurityUtils.getCurrentUsername()); + String currentUsername = SecurityUtils.getCurrentUsername(); + return adminRole||isManagedAdminUsername(currentUsername); } } From 24515bf559e2942ca8f00607effbc6e0422c289a Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 13 Aug 2026 14:48:11 +0800 Subject: [PATCH 25/44] =?UTF-8?q?feat:=20=E8=BF=87=E9=B1=BC=E8=AE=BE?= =?UTF-8?q?=E6=96=BD=E8=87=AA=E5=8A=A8=E6=95=B0=E6=8D=AE=E5=91=A8=E6=97=AC?= =?UTF-8?q?=E6=9C=88=E5=B9=B4=E7=BB=9F=E8=AE=A1=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/FishImportServiceImpl.java | 7 +- .../fp/controller/FishPassageController.java | 6 + .../fp/entity/vo/FpFpssrlQdrtpSVo.java | 65 ++++++ .../qgc_env/fp/service/FpRunService.java | 3 + .../fp/service/impl/FpRunServiceImpl.java | 207 ++++++++++++++++++ 5 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQdrtpSVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishImportServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishImportServiceImpl.java index 68e67d3b..b22e2219 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishImportServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishImportServiceImpl.java @@ -1389,10 +1389,15 @@ public class FishImportServiceImpl implements IFishImportService { boolean isUp = lowerName.contains("上行") && !isUpReturn; // 排除上行折返 boolean isDown = lowerName.contains("下行") && !isDownReturn; // 排除下行折返 + // 判断 direction 是否为字典编码 boolean isDictCode = "0".equals(direction) || "1".equals(direction) || "2".equals(direction) || "3".equals(direction); - + if (importRow.getWarnings().contains("stcd")) { + importRow.getWarnings().add("direction"); + // 如果是字典编码,返回对应的中文;否则返回原始数据 + return isDictCode ? getDirectionChinese(direction) : direction; + } // 如果 direction 本身是字典编码(0/1/2/3),直接识别 if ("0".equals(direction)) { isUp = true; diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java index 763a2697..7a6e245f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java @@ -148,4 +148,10 @@ public class FishPassageController { public ResponseResult getQgcFpssrlQdaySKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fpRunService.processQgcFpssrlQdaySKendoList(dataSourceRequest)); } + + @PostMapping("/fpssrlQdrtps/GetKendoListCust") + @Operation(summary = "过鱼设施自动数据周旬月年统计表(SD_FPSSRLDRTP_S)") + public ResponseResult getQgcFpssrlQdrtpSKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fpRunService.processQgcFpssrlQdrtpSKendoList(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQdrtpSVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQdrtpSVo.java new file mode 100644 index 00000000..5e8ea9e7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQdrtpSVo.java @@ -0,0 +1,65 @@ +package com.yfd.platform.qgc_env.fp.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 过鱼设施自动数据(带水温,流速)周旬月年统计表 VO + *

+ *

对应新表 SD_FPSSRLDRTP_S(旧系统 SD_FPSSRLQDRTP_S)

+ */ +@Data +@Schema(description = "过鱼设施自动数据周旬月年统计表") +public class FpFpssrlQdrtpSVo { + + @Schema(description = "主键ID") + private String id; + + @Schema(description = "过鱼设施编码") + private String stcd; + + @Schema(description = "数据时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date tm; + + @Schema(description = "维度类型:WEEK=周 TEN=旬 MON=月 QUA=季 YEAR=年") + private String drtp; + + @Schema(description = "年:YYYY") + private Long year; + + @Schema(description = "月") + private Long month; + + @Schema(description = "时段类型") + private Long dr; + + @Schema(description = "鱼类") + private String ftp; + + @Schema(description = "自动过鱼设施过鱼数量") + private Long fcnt; + + @Schema(description = "水温,单位:℃") + private BigDecimal temperature; + + @Schema(description = "水位,单位:m") + private BigDecimal waterlevel; + + @Schema(description = "流速,单位:m/s") + private BigDecimal speed; + + @Schema(description = "流量,单位:m3/s") + private BigDecimal q; + + @Schema(description = "溶氧,单位:mg/L") + private BigDecimal dox; + + @Schema(description = "浊度,单位:NTU") + private BigDecimal tu; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java index 833178df..2e5fe4ef 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java @@ -12,6 +12,7 @@ import com.yfd.platform.qgc_env.fp.entity.vo.FpTreeStcdGroupVo; import com.yfd.platform.qgc_env.fp.entity.vo.YearFpStatisticsVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpOverfishTotalVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQdaySVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQdrtpSVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunPlanVo; import java.util.List; @@ -41,4 +42,6 @@ public interface FpRunService { DataSourceResult processQgcOverfishTotalKendoList(DataSourceRequest dataSourceRequest); DataSourceResult processQgcFpssrlQdaySKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult processQgcFpssrlQdrtpSKendoList(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index 2991a0a9..ac2c73dc 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -17,6 +17,7 @@ import com.yfd.platform.qgc_env.fp.entity.vo.FbFishRunVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFishSelectVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQueryVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQdaySVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpFpssrlQdrtpSVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpFtpStatisticsVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpOverfishTotalVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunAnalysisHeadColumnVo; @@ -3312,4 +3313,210 @@ public class FpRunServiceImpl implements FpRunService { return orders.isEmpty() ? " ORDER BY t.DT DESC" : " ORDER BY " + String.join(", ", orders); } + // ==================== 过鱼设施自动数据周旬月年统计表 ==================== + + @Override + public DataSourceResult processQgcFpssrlQdrtpSKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryFpssrlQdrtpSDetailList(dataSourceRequest, loadOptions); + } + return queryFpssrlQdrtpSGroupList(dataSourceRequest, loadOptions); + } + + private DataSourceResult queryFpssrlQdrtpSDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildFpssrlQdrtpSSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildFpssrlQdrtpSCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapFpssrlQdrtpSColumn + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildFpssrlQdrtpSOrderBySql(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, FpFpssrlQdrtpSVo.class + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryFpssrlQdrtpSGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapFpssrlQdrtpSColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapFpssrlQdrtpSColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder("SELECT "); + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildFpssrlQdrtpSCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapFpssrlQdrtpSColumn + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapFpssrlQdrtpSColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildFpssrlQdrtpSOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (dataSourceRequest.getGroupResultFlat() != null && dataSourceRequest.getGroupResultFlat()) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + /** + * 过鱼设施自动数据周旬月年统计表核心 SQL:单表 SD_FPSSRLDRTP_S + */ + private String buildFpssrlQdrtpSCoreSql() { + return "SELECT t.ID, t.STCD, t.TM, t.DRTP, t.YEAR, t.MONTH, t.DR, t.FTP, t.FCNT, " + + "t.TEMPERATURE, t.WATERLEVEL, t.SPEED, t.Q, t.DOX, t.TU " + + "FROM SD_FPSSRLDRTP_S t " + + "WHERE NVL(t.IS_DELETED, 0) = 0 "; + } + + private String buildFpssrlQdrtpSSelectSql(List selectFields) { + Map columns = new LinkedHashMap<>(); + columns.put("id", "t.ID AS id"); + columns.put("stcd", "t.STCD AS stcd"); + columns.put("tm", "t.TM AS tm"); + columns.put("drtp", "t.DRTP AS drtp"); + columns.put("year", "t.YEAR AS year"); + columns.put("month", "t.MONTH AS month"); + columns.put("dr", "t.DR AS dr"); + columns.put("ftp", "t.FTP AS ftp"); + columns.put("fcnt", "t.FCNT AS fcnt"); + columns.put("temperature", "t.TEMPERATURE AS temperature"); + columns.put("waterlevel", "t.WATERLEVEL AS waterlevel"); + columns.put("speed", "t.SPEED AS speed"); + columns.put("q", "t.Q AS q"); + columns.put("dox", "t.DOX AS dox"); + columns.put("tu", "t.TU AS tu"); + + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private String mapFpssrlQdrtpSColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field.toLowerCase()) { + case "id" -> "t.ID"; + case "stcd" -> "t.STCD"; + case "tm" -> "t.TM"; + case "drtp" -> "t.DRTP"; + case "year" -> "t.YEAR"; + case "month" -> "t.MONTH"; + case "dr" -> "t.DR"; + case "ftp" -> "t.FTP"; + case "fcnt" -> "t.FCNT"; + case "temperature" -> "t.TEMPERATURE"; + case "waterlevel" -> "t.WATERLEVEL"; + case "speed" -> "t.SPEED"; + case "q" -> "t.Q"; + case "dox" -> "t.DOX"; + case "tu" -> "t.TU"; + default -> null; + }; + } + + private String buildFpssrlQdrtpSOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.YEAR DESC, t.MONTH DESC, t.DR DESC"; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapFpssrlQdrtpSColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + return orders.isEmpty() ? " ORDER BY t.YEAR DESC, t.MONTH DESC, t.DR DESC" : " ORDER BY " + String.join(", ", orders); + } + } From be328e3107a6f840637f78bad31d942d42d33e78 Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 13 Aug 2026 16:13:43 +0800 Subject: [PATCH 26/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yfd/platform/config/SecurityConfig.java | 1 + .../datasource/DynamicDataSource.java | 8 +- .../fp/service/impl/FpRunServiceImpl.java | 4 +- .../system/controller/DataSyncController.java | 93 +++ .../system/domain/DataSyncRequest.java | 49 ++ .../com/yfd/platform/utils/DataSyncUtil.java | 637 ++++++++++++++++++ 6 files changed, 789 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/system/controller/DataSyncController.java create mode 100644 backend/src/main/java/com/yfd/platform/system/domain/DataSyncRequest.java create mode 100644 backend/src/main/java/com/yfd/platform/utils/DataSyncUtil.java diff --git a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java index 38674041..04ab7190 100644 --- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -71,6 +71,7 @@ public class SecurityConfig { // .requestMatchers("/system/**").permitAll() // .requestMatchers("/qgcExport/**").permitAll() .requestMatchers("/eng/**").permitAll() + .requestMatchers("/system/**").permitAll() // .requestMatchers("/eq/**").permitAll() // .requestMatchers("/env/**").permitAll() // .requestMatchers("/warn/**").permitAll() diff --git a/backend/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java b/backend/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java index 8b525217..79dc807c 100644 --- a/backend/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java +++ b/backend/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java @@ -36,5 +36,11 @@ public class DynamicDataSource extends AbstractRoutingDataSource { contextHolder.remove(); } - + /** + * 根据数据源 key 获取目标数据源实例(如 dm-master / oracle-master) + */ + public DataSource getDataSourceByKey(String key) { + Map resolved = getResolvedDataSources(); + return resolved == null ? null : resolved.get(key); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index ac2c73dc..aba8ad7f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -2592,7 +2592,7 @@ public class FpRunServiceImpl implements FpRunService { " t2.pycnt AS pycnt, " + " NULL AS pyRate, " + " t.STTP AS sttpCode, " + - " t1.planFtp AS planFtp, " + + " t.ZYGYDXMS AS planFtp, " + " t.ZYGYDX AS fallbackFishJson, " + " NVL(t.ZYGYDXMS, t.JGGYDXMS) AS fallbackFishText " + "FROM SD_FPSS_B_H t " + @@ -3502,7 +3502,7 @@ public class FpRunServiceImpl implements FpRunService { private String buildFpssrlQdrtpSOrderBySql(List sortList) { if (CollUtil.isEmpty(sortList)) { - return " ORDER BY t.YEAR DESC, t.MONTH DESC, t.DR DESC"; + return " ORDER BY t.YEAR DESC, t.MONTH DESC"; } List orders = new ArrayList<>(); for (DataSourceRequest.SortDescriptor sort : sortList) { diff --git a/backend/src/main/java/com/yfd/platform/system/controller/DataSyncController.java b/backend/src/main/java/com/yfd/platform/system/controller/DataSyncController.java new file mode 100644 index 00000000..fb35cc5c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/controller/DataSyncController.java @@ -0,0 +1,93 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.DataSyncRequest; +import com.yfd.platform.utils.DataSyncUtil; +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; + +/** + * 数据同步控制器:支持 DM / Oracle 之间数据同步(MERGE INTO 方式) + */ +@RestController +@RequestMapping("/system/dataSync") +@Tag(name = "数据同步") +@Validated +public class DataSyncController { + + @Resource + private DataSyncUtil dataSyncUtil; + + /** + * DM 数据同步到 Oracle(使用调用方提供的连接信息) + *

+ * 请求示例(把 DM 库 SD_FPSS_R 同步到 Oracle 库 SD_FPSS_R): + *

+     * {
+     *   "sourceTable": "SD_FPSS_R",
+     *   "targetTable": "SD_FPSS_R",
+     *   "keyColumns": ["ID"],
+     *   "clearTarget": true,
+     *   "batchSize": 500,
+     *   "sourceConn": {
+     *     "url": "jdbc:dm://172.16.21.143:5236/QGC_REFA_TEST",
+     *     "username": "QGC_REFA_TEST",
+     *     "password": "xxxx"
+     *   },
+     *   "targetConn": {
+     *     "url": "jdbc:oracle:thin:@172.16.31.172:1521/SDLYZ",
+     *     "username": "SDLY_QX",
+     *     "password": "xxxx"
+     *   }
+     * }
+     * 
+ */ + @PostMapping("/dmToOracle") + @Operation(summary = "DM 数据同步到 Oracle(自定义连接,MERGE INTO)") + public ResponseResult dmToOracle(@RequestBody DataSyncRequest request) { + DataSyncUtil.DataSyncResult result = dataSyncUtil.syncWithConnections(buildConfig(request), + request.getSourceConn(), request.getTargetConn()); + return ResponseResult.successData(result); + } + + /** + * 通用数据同步(自定义连接,可指定任意方向) + */ + @PostMapping("/sync") + @Operation(summary = "通用数据同步(自定义连接,MERGE INTO)") + public ResponseResult sync(@RequestBody DataSyncRequest request) { + DataSyncUtil.DataSyncResult result = dataSyncUtil.syncWithConnections(buildConfig(request), + request.getSourceConn(), request.getTargetConn()); + return ResponseResult.successData(result); + } + + private DataSyncUtil.DataSyncConfig buildConfig(DataSyncRequest request) { + if (request == null) { + throw new IllegalArgumentException("请求参数不能为空"); + } + if (StrUtil.isBlank(request.getSourceTable())) { + throw new IllegalArgumentException("源表(sourceTable)不能为空"); + } + if (StrUtil.isBlank(request.getTargetTable())) { + throw new IllegalArgumentException("目标表(targetTable)不能为空"); + } + DataSyncUtil.DataSyncConfig config = new DataSyncUtil.DataSyncConfig(); + config.setSourceTable(request.getSourceTable()); + config.setTargetTable(request.getTargetTable()); + config.setColumns(request.getColumns()); + config.setColumnMapping(request.getColumnMapping()); + config.setKeyColumns(request.getKeyColumns()); + config.setConditionSql(request.getConditionSql()); + config.setOrderColumn(request.getOrderColumn()); + config.setBatchSize(request.getBatchSize()); + config.setClearTarget(request.getClearTarget()); + return config; + } +} diff --git a/backend/src/main/java/com/yfd/platform/system/domain/DataSyncRequest.java b/backend/src/main/java/com/yfd/platform/system/domain/DataSyncRequest.java new file mode 100644 index 00000000..eebf4765 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/domain/DataSyncRequest.java @@ -0,0 +1,49 @@ +package com.yfd.platform.system.domain; + +import com.yfd.platform.utils.DataSyncUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + * 数据同步请求 + */ +@Data +@Schema(description = "数据同步请求") +public class DataSyncRequest { + + @Schema(description = "源表名(DM/Oracle)") + private String sourceTable; + + @Schema(description = "目标表名(可与源表名不同)") + private String targetTable; + + @Schema(description = "源表同步列(不指定则自动读取源表全列)") + private List columns; + + @Schema(description = "字段映射:源列名 -> 目标列名") + private Map columnMapping; + + @Schema(description = "MERGE 匹配主键列(目标表列名,必填)") + private List keyColumns; + + @Schema(description = "增量同步条件 SQL 片段(基于源表列)") + private String conditionSql; + + @Schema(description = "分页排序列(源表列,不指定则取第一列)") + private String orderColumn; + + @Schema(description = "每批同步条数,默认 500") + private Integer batchSize; + + @Schema(description = "同步前是否清空目标表(全量覆盖)") + private Boolean clearTarget; + + @Schema(description = "源库连接信息(driverClassName 不填时按 URL 自动识别)") + private DataSyncUtil.DbConnectionInfo sourceConn; + + @Schema(description = "目标库连接信息(driverClassName 不填时按 URL 自动识别)") + private DataSyncUtil.DbConnectionInfo targetConn; +} diff --git a/backend/src/main/java/com/yfd/platform/utils/DataSyncUtil.java b/backend/src/main/java/com/yfd/platform/utils/DataSyncUtil.java new file mode 100644 index 00000000..b7417640 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/utils/DataSyncUtil.java @@ -0,0 +1,637 @@ +package com.yfd.platform.utils; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.druid.pool.DruidDataSource; +import com.yfd.platform.datasource.DataSourceKeys; +import com.yfd.platform.datasource.DynamicDataSource; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; + +import javax.sql.DataSource; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 数据同步控制类:支持 Oracle 与达梦(DM) 之间双向同步,使用 MERGE INTO 方式合并数据。 + *

+ * 支持两种数据源来源: + *

    + *
  • 项目配置的数据源:{@link #syncTable(String, String, DataSyncConfig)}(dm-master / oracle-master 等 key)
  • + *
  • 调用方自定义连接:{@link #syncWithConnections(DataSyncConfig, DbConnectionInfo, DbConnectionInfo)}(URL/账号/密码)
  • + *
+ *

+ *

+ * 支持:源表名与目标表名不同、源字段与目标字段不同(通过 {@link DataSyncConfig#setColumnMapping} 配置映射)。 + *

+ */ +@Component +public class DataSyncUtil { + + private static final Logger log = LoggerFactory.getLogger(DataSyncUtil.class); + + @Resource + private DynamicDataSource dynamicDataSource; + + // ==================== 项目数据源入口 ==================== + + /** + * 达梦(DM) → Oracle 数据同步(使用项目配置的 dm-master / oracle-master 数据源) + */ + public DataSyncResult syncDmToOracle(DataSyncConfig config) { + return syncTable(DataSourceKeys.DM_MASTER, DataSourceKeys.ORACLE_MASTER, config); + } + + /** + * Oracle → 达梦(DM) 数据同步(使用项目配置的 oracle-master / dm-master 数据源) + */ + public DataSyncResult syncOracleToDm(DataSyncConfig config) { + return syncTable(DataSourceKeys.ORACLE_MASTER, DataSourceKeys.DM_MASTER, config); + } + + /** + * 通用数据同步:从源数据源读取,MERGE INTO 写入目标数据源(使用项目配置的数据源 key) + * + * @param sourceDsKey 源数据源 key(如 dm-master / oracle-master) + * @param targetDsKey 目标数据源 key + * @param config 同步配置 + */ + public DataSyncResult syncTable(String sourceDsKey, String targetDsKey, DataSyncConfig config) { + DataSource sourceDataSource = dynamicDataSource.getDataSourceByKey(sourceDsKey); + DataSource targetDataSource = dynamicDataSource.getDataSourceByKey(targetDsKey); + if (sourceDataSource == null) { + throw new IllegalArgumentException("未找到数据源: " + sourceDsKey); + } + if (targetDataSource == null) { + throw new IllegalArgumentException("未找到数据源: " + targetDsKey); + } + return doSync(new JdbcTemplate(sourceDataSource), new JdbcTemplate(targetDataSource), config); + } + + // ==================== 自定义连接入口 ==================== + + /** + * 使用调用方提供的连接信息同步数据(DM → Oracle / Oracle → DM 均适用) + *

+ * 典型场景:把 DM 库 {@code SD_FPSS_R} 同步到 Oracle 库 {@code SD_FPSS_R}, + * 连接信息由调用方在请求中提供。 + *

+ * + * @param config 同步配置 + * @param sourceConn 源库连接信息(driverClassName 不填时按 URL 自动识别) + * @param targetConn 目标库连接信息 + */ + public DataSyncResult syncWithConnections(DataSyncConfig config, DbConnectionInfo sourceConn, DbConnectionInfo targetConn) { + if (sourceConn == null || StrUtil.isBlank(sourceConn.getUrl())) { + throw new IllegalArgumentException("源库连接信息(url)不能为空"); + } + if (targetConn == null || StrUtil.isBlank(targetConn.getUrl())) { + throw new IllegalArgumentException("目标库连接信息(url)不能为空"); + } + DruidDataSource sourceDataSource = buildDataSource(sourceConn); + DruidDataSource targetDataSource = buildDataSource(targetConn); + try { + return doSync(new JdbcTemplate(sourceDataSource), new JdbcTemplate(targetDataSource), config); + } finally { + sourceDataSource.close(); + targetDataSource.close(); + } + } + + // ==================== 核心同步逻辑 ==================== + + /** + * 核心同步:从源 JdbcTemplate 分页读取,MERGE INTO 写入目标 JdbcTemplate + */ + private DataSyncResult doSync(JdbcTemplate sourceJdbc, JdbcTemplate targetJdbc, DataSyncConfig config) { + long startTime = System.currentTimeMillis(); + DataSyncResult result = new DataSyncResult(); + result.setStartTime(startTime); + try { + validateConfig(config); + + // 1. 源表列(未指定时自动读取源表结构) + List sourceColumns = normalizeColumns(config.getColumns()); + if (CollUtil.isEmpty(sourceColumns)) { + sourceColumns = loadTableColumns(sourceJdbc, config.getSourceTable()); + if (CollUtil.isEmpty(sourceColumns)) { + throw new IllegalArgumentException("未从源表 [" + config.getSourceTable() + "] 获取到任何列"); + } + } + + // 2. 目标表列:按 columnMapping 映射,未配置映射的列名保持一致 + Map columnMapping = normalizeMapping(config.getColumnMapping()); + List targetColumns = new ArrayList<>(sourceColumns.size()); + for (String sourceColumn : sourceColumns) { + targetColumns.add(columnMapping.getOrDefault(sourceColumn, sourceColumn)); + } + + // 3. 主键列:keyColumns 配置为目标表列名,反查对应的源表列名用于取值 + List keyColumns = normalizeColumns(config.getKeyColumns()); + Map reverseMapping = new HashMap<>(); + for (Map.Entry entry : columnMapping.entrySet()) { + reverseMapping.put(entry.getValue(), entry.getKey()); + } + List keySourceColumns = new ArrayList<>(keyColumns.size()); + for (String keyColumn : keyColumns) { + keySourceColumns.add(reverseMapping.getOrDefault(keyColumn, keyColumn)); + } + + // 4. 可选:同步前清空目标表(全量覆盖) + if (Boolean.TRUE.equals(config.getClearTarget())) { + clearTargetTable(targetJdbc, config.getTargetTable()); + } + + // 5. 分页读取源数据 → 批量 MERGE 写入目标库 + int batchSize = config.getBatchSize() != null && config.getBatchSize() > 0 + ? config.getBatchSize() : 500; + long totalRead = 0; + long totalProcessed = 0; + int offset = 0; + + while (true) { + List> rows = readPage(sourceJdbc, config, sourceColumns, offset, batchSize); + if (CollUtil.isEmpty(rows)) { + break; + } + int[] effects = mergeInto(targetJdbc, config, sourceColumns, targetColumns, + keyColumns, keySourceColumns, rows); + for (int effect : effects) { + totalProcessed += effect; + } + totalRead += rows.size(); + offset += rows.size(); + if (rows.size() < batchSize) { + break; + } + } + + result.setSuccess(true); + result.setTotalRead(totalRead); + result.setTotalProcessed(totalProcessed); + result.setEndTime(System.currentTimeMillis()); + result.setElapsedMillis(result.getEndTime() - startTime); + result.setMessage("同步完成:读取 " + totalRead + " 条,MERGE 处理 " + totalProcessed + " 条"); + log.info("数据同步完成 sourceTable={} targetTable={} {}", config.getSourceTable(), + config.getTargetTable(), result.getMessage()); + } catch (Exception e) { + result.setSuccess(false); + result.setEndTime(System.currentTimeMillis()); + result.setElapsedMillis(result.getEndTime() - startTime); + result.setMessage("数据同步失败:" + e.getMessage()); + log.error("数据同步失败 sourceTable={} targetTable={}", + config == null ? "" : config.getSourceTable(), + config == null ? "" : config.getTargetTable(), e); + } + return result; + } + + // ==================== 内部实现 ==================== + + private void validateConfig(DataSyncConfig config) { + if (config == null) { + throw new IllegalArgumentException("同步配置(config)不能为空"); + } + if (StrUtil.isBlank(config.getSourceTable())) { + throw new IllegalArgumentException("源表(sourceTable)不能为空"); + } + if (StrUtil.isBlank(config.getTargetTable())) { + throw new IllegalArgumentException("目标表(targetTable)不能为空"); + } + if (CollUtil.isEmpty(config.getKeyColumns())) { + throw new IllegalArgumentException("必须配置主键列(keyColumns)用于 MERGE 匹配"); + } + } + + private List normalizeColumns(List columns) { + if (CollUtil.isEmpty(columns)) { + return new ArrayList<>(); + } + return columns.stream() + .filter(StrUtil::isNotBlank) + .map(String::trim) + .map(String::toUpperCase) + .distinct() + .collect(Collectors.toList()); + } + + private Map normalizeMapping(Map mapping) { + Map normalized = new HashMap<>(); + if (mapping == null || mapping.isEmpty()) { + return normalized; + } + for (Map.Entry entry : mapping.entrySet()) { + if (StrUtil.isNotBlank(entry.getKey()) && StrUtil.isNotBlank(entry.getValue())) { + normalized.put(entry.getKey().trim().toUpperCase(), entry.getValue().trim().toUpperCase()); + } + } + return normalized; + } + + /** + * 根据连接信息构建 Druid 数据源,driverClassName 未填时按 URL 自动识别 + */ + private DruidDataSource buildDataSource(DbConnectionInfo conn) { + DruidDataSource dataSource = new DruidDataSource(); + dataSource.setDriverClassName(resolveDriverClassName(conn)); + dataSource.setUrl(conn.getUrl()); + dataSource.setUsername(conn.getUsername()); + dataSource.setPassword(conn.getPassword()); + dataSource.setInitialSize(1); + dataSource.setMinIdle(1); + dataSource.setMaxActive(5); + dataSource.setMaxWait(30000); + dataSource.setValidationQuery("SELECT 1 FROM DUAL"); + dataSource.setTestWhileIdle(true); + dataSource.setBreakAfterAcquireFailure(true); + dataSource.setConnectionErrorRetryAttempts(0); + try { + dataSource.init(); + } catch (SQLException e) { + dataSource.close(); + throw new IllegalStateException("初始化源数据源失败: " + conn.getUrl(), e); + } + return dataSource; + } + + private String resolveDriverClassName(DbConnectionInfo conn) { + if (StrUtil.isNotBlank(conn.getDriverClassName())) { + return conn.getDriverClassName(); + } + String url = conn.getUrl() == null ? "" : conn.getUrl().toLowerCase(); + if (url.startsWith("jdbc:dm")) { + return "dm.jdbc.driver.DmDriver"; + } + if (url.startsWith("jdbc:oracle")) { + return "oracle.jdbc.OracleDriver"; + } + throw new IllegalArgumentException("无法根据 URL 识别驱动类型,请显式传入 driverClassName: " + conn.getUrl()); + } + + /** + * 读取源表全部列名(大写) + */ + private List loadTableColumns(JdbcTemplate sourceJdbc, String table) { + List columns = new ArrayList<>(); + sourceJdbc.query("SELECT * FROM " + table + " WHERE 1 = 0", rs -> { + ResultSetMetaData metaData = rs.getMetaData(); + for (int i = 1; i <= metaData.getColumnCount(); i++) { + columns.add(metaData.getColumnName(i).toUpperCase()); + } + }); + return columns; + } + + /** + * 分页读取源数据(Oracle/DM 均支持 ROWNUM 分页) + */ + private List> readPage(JdbcTemplate sourceJdbc, DataSyncConfig config, + List sourceColumns, int offset, int batchSize) { + String columnList = String.join(", ", sourceColumns); + String orderBy = StrUtil.isBlank(config.getOrderColumn()) + ? sourceColumns.get(0) : config.getOrderColumn().trim().toUpperCase(); + String where = StrUtil.isBlank(config.getConditionSql()) + ? "" : " AND " + config.getConditionSql(); + String sql = "SELECT * FROM (SELECT t.*, ROWNUM rn FROM (" + + "SELECT " + columnList + " FROM " + config.getSourceTable() + + " WHERE 1 = 1" + where + + " ORDER BY " + orderBy + + ") t WHERE ROWNUM <= " + (offset + batchSize) + + ") WHERE rn > " + offset; + return sourceJdbc.queryForList(sql); + } + + /** + * 批量 MERGE INTO 写入目标库 + * + * @param sourceColumns 源表列(USING 子句占位别名) + * @param targetColumns 目标表列(与 sourceColumns 一一对应) + * @param keyColumns 目标表主键列(ON 匹配 t 侧) + * @param keySourceColumns 源表主键列(ON 匹配 s 侧,与 keyColumns 一一对应) + */ + private int[] mergeInto(JdbcTemplate targetJdbc, DataSyncConfig config, + List sourceColumns, List targetColumns, + List keyColumns, List keySourceColumns, + List> rows) { + String targetTable = config.getTargetTable(); + + // USING 子句:SELECT ? AS SRC_COL1, ? AS SRC_COL2 FROM DUAL + String usingSelect = sourceColumns.stream() + .map(c -> "? AS " + c) + .collect(Collectors.joining(", ")); + + // ON 匹配条件:t.KEY_TARGET = s.KEY_SOURCE + List onItems = new ArrayList<>(keyColumns.size()); + for (int i = 0; i < keyColumns.size(); i++) { + onItems.add("t." + keyColumns.get(i) + " = s." + keySourceColumns.get(i)); + } + String onCondition = String.join(" AND ", onItems); + + // 更新列(排除主键列):t.TARGET_COL = s.SOURCE_COL + List updateSetItems = new ArrayList<>(); + for (int i = 0; i < sourceColumns.size(); i++) { + String targetColumn = targetColumns.get(i); + if (keyColumns.contains(targetColumn)) { + continue; + } + updateSetItems.add("t." + targetColumn + " = s." + sourceColumns.get(i)); + } + if (updateSetItems.isEmpty()) { + throw new IllegalArgumentException("目标表除主键列外没有可更新的列,无法构造 MERGE 的 WHEN MATCHED 分支"); + } + String updateSet = String.join(", ", updateSetItems); + + // 插入列:INSERT (TARGET_COL1, TARGET_COL2) VALUES (s.SRC_COL1, s.SRC_COL2) + String insertColumns = String.join(", ", targetColumns); + String insertValues = sourceColumns.stream() + .map(c -> "s." + c) + .collect(Collectors.joining(", ")); + + String sql = "MERGE INTO " + targetTable + " t " + + "USING (SELECT " + usingSelect + " FROM DUAL) s " + + "ON (" + onCondition + ") " + + "WHEN MATCHED THEN UPDATE SET " + updateSet + " " + + "WHEN NOT MATCHED THEN INSERT (" + insertColumns + ") VALUES (" + insertValues + ")"; + + List batchArgs = new ArrayList<>(rows.size()); + for (Map row : rows) { + Object[] args = new Object[sourceColumns.size()]; + for (int i = 0; i < sourceColumns.size(); i++) { + args[i] = row.get(sourceColumns.get(i)); + } + batchArgs.add(args); + } + return targetJdbc.batchUpdate(sql, batchArgs); + } + + /** + * 清空目标表(TRUNCATE,DDL 自动提交) + */ + private void clearTargetTable(JdbcTemplate targetJdbc, String targetTable) { + targetJdbc.execute("TRUNCATE TABLE " + targetTable); + log.info("已清空目标表 {}", targetTable); + } + + // ==================== 配置与结果 ==================== + + /** + * 数据库连接信息(调用方自定义连接时使用) + */ + public static class DbConnectionInfo { + + /** JDBC URL,如 jdbc:dm://127.0.0.1:5236/DMDB 或 jdbc:oracle:thin:@127.0.0.1:1521/ORCL */ + private String url; + + /** 用户名 */ + private String username; + + /** 密码 */ + private String password; + + /** 驱动类名,不填时按 URL 自动识别(dm.jdbc.driver.DmDriver / oracle.jdbc.OracleDriver) */ + private String driverClassName; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getDriverClassName() { + return driverClassName; + } + + public void setDriverClassName(String driverClassName) { + this.driverClassName = driverClassName; + } + } + + /** + * 数据同步配置 + */ + public static class DataSyncConfig { + + /** 源表名(DM/Oracle) */ + private String sourceTable; + + /** 目标表名(可与源表名不同) */ + private String targetTable; + + /** 源表同步列(不指定则自动读取源表全列) */ + private List columns; + + /** + * 字段映射:源列名 -> 目标列名。 + * 未在映射中的列默认目标列名与源列名一致; + * 若两边字段名完全相同,可不配置。 + */ + private Map columnMapping; + + /** MERGE 匹配主键列(目标表列名,必填) */ + private List keyColumns; + + /** 增量同步条件 SQL 片段(基于源表列),如 MODIFY_TIME >= TO_DATE('2025-01-01','YYYY-MM-DD') */ + private String conditionSql; + + /** 分页排序列(源表列,不指定则取第一列) */ + private String orderColumn; + + /** 每批同步条数,默认 500 */ + private Integer batchSize; + + /** 同步前是否清空目标表(全量覆盖) */ + private Boolean clearTarget; + + public String getSourceTable() { + return sourceTable; + } + + public void setSourceTable(String sourceTable) { + this.sourceTable = sourceTable; + } + + public String getTargetTable() { + return targetTable; + } + + public void setTargetTable(String targetTable) { + this.targetTable = targetTable; + } + + public List getColumns() { + return columns; + } + + public void setColumns(List columns) { + this.columns = columns; + } + + public Map getColumnMapping() { + return columnMapping; + } + + public void setColumnMapping(Map columnMapping) { + this.columnMapping = columnMapping; + } + + public List getKeyColumns() { + return keyColumns; + } + + public void setKeyColumns(List keyColumns) { + this.keyColumns = keyColumns; + } + + public String getConditionSql() { + return conditionSql; + } + + public void setConditionSql(String conditionSql) { + this.conditionSql = conditionSql; + } + + public String getOrderColumn() { + return orderColumn; + } + + public void setOrderColumn(String orderColumn) { + this.orderColumn = orderColumn; + } + + public Integer getBatchSize() { + return batchSize; + } + + public void setBatchSize(Integer batchSize) { + this.batchSize = batchSize; + } + + public Boolean getClearTarget() { + return clearTarget; + } + + public void setClearTarget(Boolean clearTarget) { + this.clearTarget = clearTarget; + } + } + + /** + * 数据同步结果 + */ + public static class DataSyncResult { + + /** 是否成功 */ + private boolean success; + + /** 读取记录数 */ + private long totalRead; + + /** MERGE 处理记录数(含新增+更新) */ + private long totalProcessed; + + /** 开始时间 */ + private long startTime; + + /** 结束时间 */ + private long endTime; + + /** 耗时(毫秒) */ + private long elapsedMillis; + + /** 结果描述 */ + private String message; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public long getTotalRead() { + return totalRead; + } + + public void setTotalRead(long totalRead) { + this.totalRead = totalRead; + } + + public long getTotalProcessed() { + return totalProcessed; + } + + public void setTotalProcessed(long totalProcessed) { + this.totalProcessed = totalProcessed; + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public long getElapsedMillis() { + return elapsedMillis; + } + + public void setElapsedMillis(long elapsedMillis) { + this.elapsedMillis = elapsedMillis; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return "DataSyncResult{" + + "success=" + success + + ", totalRead=" + totalRead + + ", totalProcessed=" + totalProcessed + + ", elapsedMillis=" + elapsedMillis + + ", message='" + message + '\'' + + '}'; + } + } +} From fc0f84dc8d7f2455e508e25671870ebb7edd510e Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 13 Aug 2026 17:50:53 +0800 Subject: [PATCH 27/44] =?UTF-8?q?fix:=20=E6=B5=81=E5=9F=9F-=E7=8F=8D?= =?UTF-8?q?=E7=A8=80=E6=A4=8D=E7=89=A9=E5=9B=AD=E8=BF=90=E8=A1=8C=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VapConstructionController.java | 6 + .../qgc_env/vap/entity/vo/VpBasinVplntVo.java | 70 ++++++ .../vap/service/VpConstructionService.java | 3 + .../impl/VpConstructionServiceImpl.java | 228 ++++++++++++++++++ 4 files changed, 307 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpBasinVplntVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VapConstructionController.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VapConstructionController.java index d6900110..126f32dd 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VapConstructionController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VapConstructionController.java @@ -47,6 +47,12 @@ public class VapConstructionController { return ResponseResult.successData(vpConstructionService.basinVpIntDetail(dataSourceRequest)); } + @PostMapping("/basin/GetKendoListCust") + @Operation(summary = "流域-珍稀植物园运行数据(SD_VP_R + V_MS_STBPRP_T)") + public ResponseResult getBasinVplntKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vpConstructionService.processBasinVplntKendoList(dataSourceRequest)); + } + @PostMapping("/wva/GetKendoListCust") @Operation(summary = "野生动物监测情况") public ResponseResult getWvaKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpBasinVplntVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpBasinVplntVo.java new file mode 100644 index 00000000..2ca72f76 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpBasinVplntVo.java @@ -0,0 +1,70 @@ +package com.yfd.platform.qgc_env.vap.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 流域-珍稀植物园运行数据 VO(对应旧系统 BasinVplnt) + */ +@Data +@Schema(description = "流域-珍稀植物园运行数据") +public class VpBasinVplntVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "年份") + private String year; + + @Schema(description = "植物园编码") + private String stcd; + + @Schema(description = "植物园名称") + private String stnm; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "展示名称") + private String name; + + @Schema(description = "建设状态") + private Integer bldstt; + + @Schema(description = "简介") + private String introduce; + + @Schema(description = "规划设计日期") + private String ststdt; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "介绍弹窗图片") + private String inffile; + + @Schema(description = "站类名称") + private String sttpName; + + @Schema(description = "LOGO图片") + private String logo; + + @Schema(description = "建成日期") + private String jcdt; + + @Schema(description = "数据是否接入") + private Integer dtin; + + @Schema(description = "电站排序") + private Integer rstcdstepsort; + + @Schema(description = "排序") + private Integer orderIndex; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java index 634224a5..5a368a86 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java @@ -5,6 +5,7 @@ import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.qgc_env.vap.entity.vo.FhvapBuiltPointVo; import com.yfd.platform.qgc_env.vap.entity.vo.WvaPointVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinIntDetailVo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinVplntVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpVarVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpStInfoResultVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpVacVo; @@ -20,6 +21,8 @@ public interface VpConstructionService { DataSourceResult basinVpIntDetail(DataSourceRequest dataSourceRequest); + DataSourceResult processBasinVplntKendoList(DataSourceRequest dataSourceRequest); + DataSourceResult processWvaKendoList(DataSourceRequest dataSourceRequest); DataSourceResult processVacKendoList(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java index 9a0ea040..2126f855 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java @@ -12,6 +12,7 @@ import com.yfd.platform.common.PageInfo; import com.yfd.platform.qgc_env.vap.entity.vo.FhvapBuiltPointVo; import com.yfd.platform.qgc_env.vap.entity.vo.WvaPointVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinIntDetailVo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinVplntVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpConstructionSituationVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpVarVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpVacVo; @@ -29,6 +30,7 @@ import org.springframework.util.CollectionUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -174,6 +176,232 @@ public class VpConstructionServiceImpl implements VpConstructionService { return result; } + @Override + public DataSourceResult processBasinVplntKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollectionUtils.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryBasinVplntDetailList(dataSourceRequest, loadOptions); + } + return queryBasinVplntGroupList(dataSourceRequest, loadOptions); + } + + private DataSourceResult queryBasinVplntDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildBasinVplntSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildBasinVplntCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapBasinVplntColumn + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildBasinVplntOrderBySql(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, VpBasinVplntVo.class + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryBasinVplntGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBasinVplntColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollectionUtils.isEmpty(descriptor.getAggregates())) { + continue; + } + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapBasinVplntColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder("SELECT "); + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildBasinVplntCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = QgcQueryWrapperUtil.buildFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0}, + this::mapBasinVplntColumn + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBasinVplntColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildBasinVplntOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (dataSourceRequest.getGroupResultFlat() != null && dataSourceRequest.getGroupResultFlat()) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + /** + * 流域-珍稀植物园运行数据核心 SQL: + * SD_VP_R 按年份+站点分组,关联 V_MS_STBPRP_T(植物园 DATA_SOURCE='SD_VP_B_H')取基础信息 + */ + private String buildBasinVplntCoreSql() { + return "SELECT t.year AS year, t.STCD AS STCD, t0.STNM AS STNM, t0.RSTCD AS RSTCD, t0.ENNM AS ENNM, " + + "t0.BLDSTT_CODE AS BLDSTT, t0.INTRODUCE AS INTRODUCE, TO_CHAR(t0.STDSDT, 'YYYY-MM-DD') AS STSTDT, " + + "t0.BASE_ID AS BASE_ID, t0.BASE_NAME AS BASE_NAME, t0.INFFILE AS INFFILE, " + + "t0.STTP_NAME AS STTP_NAME, t0.LOGO AS LOGO, TO_CHAR(t0.JCDT, 'YYYY-MM-DD') AS JCDT, t0.DTIN AS DTIN, " + + "t0.ORDER_INDEX AS RSTCDSTEPSORT, t0.ORDER_INDEX AS ORDER_INDEX " + + "FROM (SELECT TO_CHAR(r.TM, 'YYYY') AS year, r.STCD FROM SD_VP_R r " + + "WHERE NVL(r.IS_DELETED, 0) = 0 GROUP BY TO_CHAR(r.TM, 'YYYY'), r.STCD) t " + + "INNER JOIN V_MS_STBPRP_T t0 ON t.STCD = t0.STCD AND t0.DATA_SOURCE = 'SD_VP_B_H' " + + "WHERE NVL(t0.IS_DELETED, 0) = 0 "; + } + + private String buildBasinVplntSelectSql(List selectFields) { + Map columns = new LinkedHashMap<>(); + columns.put("year", "t.year AS year"); + columns.put("stcd", "t.STCD AS stcd"); + columns.put("stnm", "t.STNM AS stnm"); + columns.put("rstcd", "t.RSTCD AS rstcd"); + columns.put("ennm", "t.ENNM AS ennm"); + columns.put("name", "t.ENNM AS name"); + columns.put("bldstt", "t.BLDSTT AS bldstt"); + columns.put("introduce", "t.INTRODUCE AS introduce"); + columns.put("ststdt", "t.STSTDT AS ststdt"); + columns.put("baseId", "t.BASE_ID AS baseId"); + columns.put("baseName", "t.BASE_NAME AS baseName"); + columns.put("inffile", "t.INFFILE AS inffile"); + columns.put("sttpName", "t.STTP_NAME AS sttpName"); + columns.put("logo", "t.LOGO AS logo"); + columns.put("jcdt", "t.JCDT AS jcdt"); + columns.put("dtin", "t.DTIN AS dtin"); + columns.put("rstcdstepsort", "t.RSTCDSTEPSORT AS rstcdstepsort"); + columns.put("orderIndex", "t.ORDER_INDEX AS orderIndex"); + + List selected = new ArrayList<>(); + if (CollectionUtils.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private String mapBasinVplntColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field.toLowerCase()) { + case "year" -> "t.year"; + case "stcd" -> "t.STCD"; + case "stnm" -> "t.STNM"; + case "rstcd" -> "t.RSTCD"; + case "ennm", "name" -> "t.ENNM"; + case "bldstt" -> "t.BLDSTT"; + case "introduce" -> "t.INTRODUCE"; + case "ststdt" -> "t.STSTDT"; + case "baseid" -> "t.BASE_ID"; + case "basename" -> "t.BASE_NAME"; + case "inffile" -> "t.INFFILE"; + case "sttpname" -> "t.STTP_NAME"; + case "logo" -> "t.LOGO"; + case "jcdt" -> "t.JCDT"; + case "dtin" -> "t.DTIN"; + case "rstcdstepsort" -> "t.RSTCDSTEPSORT"; + case "orderindex" -> "t.ORDER_INDEX"; + default -> null; + }; + } + + private String buildAggregateSql(String aggregate, String column, String field) { + String normalized = aggregate == null ? "" : aggregate.toLowerCase(); + return switch (normalized) { + case "sum", "min", "max", "avg", "count" -> + normalized.toUpperCase() + "(" + column + ") AS " + normalized + "_" + field; + default -> ""; + }; + } + + private String buildBasinVplntOrderBySql(List sorts) { + if (sorts == null || sorts.isEmpty()) { + return ""; +// return " ORDER BY t.RSTCDSTEPSORT ASC, t.STCD ASC"; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapBasinVplntColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + return orders.isEmpty() ? " ORDER BY t.RSTCDSTEPSORT ASC, t.STCD ASC" : " ORDER BY " + String.join(", ", orders); + } + @Override public DataSourceResult processWvaKendoList(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); From b2ce8cbcc986379a852ac8bbecdb73b6e97d0ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=85=B4=E5=87=AF?= <2448379534@qq.com> Date: Fri, 14 Aug 2026 08:52:59 +0800 Subject: [PATCH 28/44] =?UTF-8?q?=E7=94=B5=E7=AB=99=E4=B8=93=E9=A2=98?= =?UTF-8?q?=E5=AE=8C=E5=96=84=EF=BC=8C=E6=95=B0=E6=8D=AE=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=AD=90=E7=B3=BB=E7=BB=9F=E6=B7=BB=E5=8A=A0=E6=9F=A5=E7=9C=8B?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/DataQueryMenuModule/index.ts | 16 + frontend-sjgl/src/api/select/index.ts | 26 + .../components/OperationLogModal/index.vue | 298 +++++++ .../BasicData/BasicDataSearch.vue | 5 + .../BasicData/EditPowerModal.vue | 51 ++ .../BasicData/index.vue | 12 + .../FishResource/FishResourceSearch.vue | 6 + .../FishResource/index.vue | 9 + .../aiBox/AiBoxSearch.vue | 6 + .../conventionalHydropower/aiBox/index.vue | 9 + .../aquaEco/OtweSearch.vue | 6 + .../conventionalHydropower/aquaEco/index.vue | 9 + .../fishSurvey/FishSearch.vue | 6 + .../fishSurvey/index.vue | 9 + .../guoYuSheShi/FpSearch.vue | 4 +- .../guoYuSheShi/index.vue | 7 +- .../luShengShengTaiDiaoCha/TeSearch.vue | 6 + .../luShengShengTaiDiaoCha/index.vue | 9 + .../qiXiDi/FhSearch.vue | 6 + .../conventionalHydropower/qiXiDi/index.vue | 6 + .../rescueStation/VaSearch.vue | 6 + .../rescueStation/index.vue | 7 +- .../shengTaiLiuLiang/EqSearch.vue | 4 +- .../shengTaiLiuLiang/index.vue | 7 +- .../shiPinJianKong/VdSearch.vue | 4 +- .../shiPinJianKong/index.vue | 7 +- .../shuiShengShengTaiDiaoCha/WeSearch.vue | 6 + .../shuiShengShengTaiDiaoCha/index.vue | 9 + .../shuiWenJianCe/WtSearch.vue | 6 + .../shuiWenJianCe/index.vue | 14 + .../shuiZhiJianCe/WqSearch.vue | 6 + .../shuiZhiJianCe/index.vue | 13 + .../sonarCam/SonarSearch.vue | 6 + .../conventionalHydropower/sonarCam/index.vue | 9 + .../tempMit/DwSearch.vue | 6 + .../conventionalHydropower/tempMit/index.vue | 9 + .../terrEco/OtteSearch.vue | 6 + .../conventionalHydropower/terrEco/index.vue | 9 + .../zengZhiFangLiu/FbSearch.vue | 3 + .../zengZhiFangLiu/index.vue | 7 +- .../zhenXIZhiWuYuan/VpSearch.vue | 4 +- .../zhenXIZhiWuYuan/index.vue | 7 +- .../src/views/monitorData/Export/index.vue | 415 +++++++--- .../monitorData/FishData/FishDataAuto.vue | 404 +++++++++ .../monitorData/FishData/FishDataManual.vue | 369 +++++++++ .../monitorData/FishData/FishDataSearch.vue | 19 +- .../src/views/monitorData/FishData/index.vue | 576 +------------ .../guoYuSheShiShuJuTianBaoTable.vue | 9 +- frontend/src/api/ZXZWYYunXingShuJu/index.ts | 4 +- frontend/src/api/dianzhanzhuantiMode/index.ts | 207 +++++ frontend/src/api/select/index.ts | 28 +- .../src/components/SidePanelItem/index.vue | 35 +- .../components/developStatusChart/index.vue | 1 + frontend/src/modules/GYZLLB/index.vue | 44 +- .../DZChuiXiangShuiWenBianHua/index.vue | 457 +++++++++++ .../DZSheHuiTouZiFP/index.vue | 169 ++++ .../DZShuiDianZhanSPJK/index.vue | 498 +++++++++++ .../DZShuiZhiDaBiaoLv/index.vue | 551 +++++++++++++ .../DZShuiZhiJianCeQuShiTu/index.vue | 761 +++++++++++++++++ .../JianCeDianShuiWenBianHua/index.vue | 772 ++++++++++++++++++ .../ShuiDianZhanJieShao/index.vue | 332 ++++++++ .../ZXZWYYunXingShuJu/arrowUpLg.svg | 32 + .../ZXZWYYunXingShuJu/index.vue | 480 +++++++++++ .../ZenZhiZhanYunXingDetailModal.vue | 292 +++++++ .../ZenZhiZhanYunXingPG/index.vue | 622 ++++++++++++++ .../ecologicalDataMod/index.vue | 351 ++++++++ .../guoyuzongliang/ModelAutoStation.vue | 505 ++++++++++++ .../guoyuzongliang/ModelManualStation.vue | 162 ++++ .../guoyuzongliang/index.vue | 446 ++++++++++ .../PowerStationReleasetaStisticsDetail.vue | 381 +++++++++ .../powerStationReleasetaStistics/index.vue | 449 ++++++++++ .../modules/qixidishuiwenbianhua/index.vue | 64 +- frontend/src/styles/index.scss | 5 + .../components/monitorData/Export/index.vue | 425 +++++++--- .../monitorData/FishData/FishDataAuto.vue | 404 +++++++++ .../monitorData/FishData/FishDataManual.vue | 369 +++++++++ .../monitorData/FishData/FishDataSearch.vue | 19 +- .../components/monitorData/FishData/index.vue | 577 +------------ .../components/ShuiDianZhanJieShao.vue | 2 +- .../views/dianZhanZhuanTi/dianZhanZhuanTi.vue | 50 +- 80 files changed, 10555 insertions(+), 1392 deletions(-) create mode 100644 frontend-sjgl/src/components/OperationLogModal/index.vue create mode 100644 frontend-sjgl/src/views/monitorData/FishData/FishDataAuto.vue create mode 100644 frontend-sjgl/src/views/monitorData/FishData/FishDataManual.vue create mode 100644 frontend/src/api/dianzhanzhuantiMode/index.ts create mode 100644 frontend/src/modules/dianzhanzhuantiMod/DZChuiXiangShuiWenBianHua/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/DZSheHuiTouZiFP/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/DZShuiDianZhanSPJK/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/DZShuiZhiDaBiaoLv/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/DZShuiZhiJianCeQuShiTu/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/JianCeDianShuiWenBianHua/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/ShuiDianZhanJieShao/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/arrowUpLg.svg create mode 100644 frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/ZenZhiZhanYunXingDetailModal.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/ecologicalDataMod/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/ModelAutoStation.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/ModelManualStation.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/index.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/PowerStationReleasetaStisticsDetail.vue create mode 100644 frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/index.vue create mode 100644 frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataAuto.vue create mode 100644 frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataManual.vue diff --git a/frontend-sjgl/src/api/DataQueryMenuModule/index.ts b/frontend-sjgl/src/api/DataQueryMenuModule/index.ts index 65f14399..4de54418 100644 --- a/frontend-sjgl/src/api/DataQueryMenuModule/index.ts +++ b/frontend-sjgl/src/api/DataQueryMenuModule/index.ts @@ -1080,6 +1080,22 @@ export function updateFishDictoryInfo(data) { }); } +// 操作日志 +export function getOperationLogList(data) { + return request({ + url: '/base/operationLog/GetKendoListCust', + method: 'post', + data + }); +} +export function getDetailByMainId(data) { + return request({ + url: '/base/operationLog/getDetailByMainId', + method: 'get', + params:data + }); +} + // 鱼类字典 - 删除 export function deleteFishDictoryInfo(data) { return request({ diff --git a/frontend-sjgl/src/api/select/index.ts b/frontend-sjgl/src/api/select/index.ts index 8fb1b45d..8e240e12 100644 --- a/frontend-sjgl/src/api/select/index.ts +++ b/frontend-sjgl/src/api/select/index.ts @@ -138,3 +138,29 @@ export function noAuthGetKendoPage(data: any = {}) { data }); } +//综合导出 +//taskId +export function qgcExportCreate (data: any = {}) { + return request({ + url: '/qgcExport/create', + method: 'post', + params:data + }); +} +//查看没有没准备完成 +export function qgcExportstatus (data: any = {}) { + return request({ + url: '/qgcExport/status', + method: 'get', + params:data + }); +} +// 下载zip文件 +export function qgcExportdownload (data: any = {}) { + return request({ + url: '/qgcExport/download', + method: 'post', + params:data, + responseType: 'blob' + }); +} \ No newline at end of file diff --git a/frontend-sjgl/src/components/OperationLogModal/index.vue b/frontend-sjgl/src/components/OperationLogModal/index.vue new file mode 100644 index 00000000..9e7f704a --- /dev/null +++ b/frontend-sjgl/src/components/OperationLogModal/index.vue @@ -0,0 +1,298 @@ + + + + diff --git a/frontend-sjgl/src/views/conventionalHydropower/BasicData/BasicDataSearch.vue b/frontend-sjgl/src/views/conventionalHydropower/BasicData/BasicDataSearch.vue index 9d9654ce..c0781865 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/BasicData/BasicDataSearch.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/BasicData/BasicDataSearch.vue @@ -75,6 +75,7 @@ diff --git a/frontend-sjgl/src/views/monitorData/FishData/FishDataManual.vue b/frontend-sjgl/src/views/monitorData/FishData/FishDataManual.vue new file mode 100644 index 00000000..04af01cc --- /dev/null +++ b/frontend-sjgl/src/views/monitorData/FishData/FishDataManual.vue @@ -0,0 +1,369 @@ + + + + diff --git a/frontend-sjgl/src/views/monitorData/FishData/FishDataSearch.vue b/frontend-sjgl/src/views/monitorData/FishData/FishDataSearch.vue index 4234ca89..21ac0880 100644 --- a/frontend-sjgl/src/views/monitorData/FishData/FishDataSearch.vue +++ b/frontend-sjgl/src/views/monitorData/FishData/FishDataSearch.vue @@ -82,12 +82,13 @@ const btnLoading = ref(false); const props = defineProps<{ exportLoading?: boolean; + mway: string; }>(); const initSearchData = { rvcd: 'all', rstcd: null, stcd: '0086601020VP000006', - mway: '1' + mway: props.mway }; const searchData = ref({ ...initSearchData }); @@ -135,22 +136,6 @@ const searchList: any = computed(() => [ value: item.stcd })) }, - { - type: 'Radio', - name: 'mway', - label: '数据类型', - width: 140, - options: [ - { - label: '人工', - value: '1' - }, - { - label: '自动', - value: '2' - } - ] - }, { type: 'custom', name: 'jcdt', diff --git a/frontend-sjgl/src/views/monitorData/FishData/index.vue b/frontend-sjgl/src/views/monitorData/FishData/index.vue index 18f6b8a3..34aae4f5 100644 --- a/frontend-sjgl/src/views/monitorData/FishData/index.vue +++ b/frontend-sjgl/src/views/monitorData/FishData/index.vue @@ -1,551 +1,22 @@ + +} + +.fish-tabs { + height: 100%; + display: flex; + flex-direction: column; + + :deep(.ant-tabs-content-holder) { + flex: 1; + min-height: 0; + } + + :deep(.ant-tabs-content), + :deep(.ant-tabs-tabpane) { + height: 100%; + } +} + diff --git a/frontend-sjtb/src/views/shuJuTianBao/guoYuSheShiShuJuTianBao/guoYuSheShiShuJuTianBaoTable.vue b/frontend-sjtb/src/views/shuJuTianBao/guoYuSheShiShuJuTianBao/guoYuSheShiShuJuTianBaoTable.vue index 120caff7..39725c3f 100644 --- a/frontend-sjtb/src/views/shuJuTianBao/guoYuSheShiShuJuTianBao/guoYuSheShiShuJuTianBaoTable.vue +++ b/frontend-sjtb/src/views/shuJuTianBao/guoYuSheShiShuJuTianBao/guoYuSheShiShuJuTianBaoTable.vue @@ -150,6 +150,11 @@ style="width: 100%" :disabled="!editingData.rstcd" @change="val => handleFpssChange(val, index)" + :dropdown-style="{ + maxHeight: '400px', + overflow: 'auto', + minWidth: '200px' + }" > -
+
@@ -258,7 +259,9 @@ const props = defineProps({ default: () => ({ show: false, value: undefined, - options: [] + options: [], + width: '', + minWidth: '' }) }, datetimePicker: { @@ -281,7 +284,8 @@ const props = defineProps({ show: false, value: undefined, format: null, //YYYY-MM-DD HH - picker: 'month' //date | week | month | quarter | year + picker: 'month', //date | week | month | quarter | year + width: '' }) }, tabs: { @@ -290,6 +294,10 @@ const props = defineProps({ show: false, value: 'one' }) + }, + bodyMarginBottom: { + type: String, + default: '16px' } }); const emit = defineEmits(['tab-change', 'update-values']); @@ -971,6 +979,7 @@ onUnmounted(() => { diff --git a/frontend/src/modules/dianzhanzhuantiMod/DZSheHuiTouZiFP/index.vue b/frontend/src/modules/dianzhanzhuantiMod/DZSheHuiTouZiFP/index.vue new file mode 100644 index 00000000..6474efbf --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/DZSheHuiTouZiFP/index.vue @@ -0,0 +1,169 @@ + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/DZShuiDianZhanSPJK/index.vue b/frontend/src/modules/dianzhanzhuantiMod/DZShuiDianZhanSPJK/index.vue new file mode 100644 index 00000000..365c7fd0 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/DZShuiDianZhanSPJK/index.vue @@ -0,0 +1,498 @@ + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/DZShuiZhiDaBiaoLv/index.vue b/frontend/src/modules/dianzhanzhuantiMod/DZShuiZhiDaBiaoLv/index.vue new file mode 100644 index 00000000..d41b1d96 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/DZShuiZhiDaBiaoLv/index.vue @@ -0,0 +1,551 @@ + + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/DZShuiZhiJianCeQuShiTu/index.vue b/frontend/src/modules/dianzhanzhuantiMod/DZShuiZhiJianCeQuShiTu/index.vue new file mode 100644 index 00000000..8e1d92d3 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/DZShuiZhiJianCeQuShiTu/index.vue @@ -0,0 +1,761 @@ + + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/JianCeDianShuiWenBianHua/index.vue b/frontend/src/modules/dianzhanzhuantiMod/JianCeDianShuiWenBianHua/index.vue new file mode 100644 index 00000000..64e23d36 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/JianCeDianShuiWenBianHua/index.vue @@ -0,0 +1,772 @@ + + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/ShuiDianZhanJieShao/index.vue b/frontend/src/modules/dianzhanzhuantiMod/ShuiDianZhanJieShao/index.vue new file mode 100644 index 00000000..574164b6 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/ShuiDianZhanJieShao/index.vue @@ -0,0 +1,332 @@ + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/arrowUpLg.svg b/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/arrowUpLg.svg new file mode 100644 index 00000000..8ce71c6b --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/arrowUpLg.svg @@ -0,0 +1,32 @@ + + + arrowUpLg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/index.vue b/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/index.vue new file mode 100644 index 00000000..1e8fcc87 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/index.vue @@ -0,0 +1,480 @@ + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/ZenZhiZhanYunXingDetailModal.vue b/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/ZenZhiZhanYunXingDetailModal.vue new file mode 100644 index 00000000..094139f3 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/ZenZhiZhanYunXingDetailModal.vue @@ -0,0 +1,292 @@ + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/index.vue b/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/index.vue new file mode 100644 index 00000000..5e3ca177 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/index.vue @@ -0,0 +1,622 @@ + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/ecologicalDataMod/index.vue b/frontend/src/modules/dianzhanzhuantiMod/ecologicalDataMod/index.vue new file mode 100644 index 00000000..dfaa913e --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/ecologicalDataMod/index.vue @@ -0,0 +1,351 @@ + + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/ModelAutoStation.vue b/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/ModelAutoStation.vue new file mode 100644 index 00000000..88d798f9 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/ModelAutoStation.vue @@ -0,0 +1,505 @@ + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/ModelManualStation.vue b/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/ModelManualStation.vue new file mode 100644 index 00000000..84de9349 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/ModelManualStation.vue @@ -0,0 +1,162 @@ + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/index.vue b/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/index.vue new file mode 100644 index 00000000..a6274e2a --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/index.vue @@ -0,0 +1,446 @@ + + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/PowerStationReleasetaStisticsDetail.vue b/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/PowerStationReleasetaStisticsDetail.vue new file mode 100644 index 00000000..3270d813 --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/PowerStationReleasetaStisticsDetail.vue @@ -0,0 +1,381 @@ + + + + + diff --git a/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/index.vue b/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/index.vue new file mode 100644 index 00000000..c1d9292b --- /dev/null +++ b/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/index.vue @@ -0,0 +1,449 @@ + + + + + diff --git a/frontend/src/modules/qixidishuiwenbianhua/index.vue b/frontend/src/modules/qixidishuiwenbianhua/index.vue index f54c0bb8..91c62529 100644 --- a/frontend/src/modules/qixidishuiwenbianhua/index.vue +++ b/frontend/src/modules/qixidishuiwenbianhua/index.vue @@ -20,7 +20,7 @@ diff --git a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataAuto.vue b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataAuto.vue new file mode 100644 index 00000000..c2779cdf --- /dev/null +++ b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataAuto.vue @@ -0,0 +1,404 @@ + + + + diff --git a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataManual.vue b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataManual.vue new file mode 100644 index 00000000..b69f5574 --- /dev/null +++ b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataManual.vue @@ -0,0 +1,369 @@ + + + + diff --git a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataSearch.vue b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataSearch.vue index b33493e8..de348c95 100644 --- a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataSearch.vue +++ b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataSearch.vue @@ -80,12 +80,13 @@ const btnLoading = ref(false); const props = defineProps<{ exportLoading?: boolean; + mway: string; }>(); const initSearchData = { rvcd: 'all', rstcd: null, stcd: '0086601020VP000006', - mway: '1' + mway: props.mway }; const searchData = ref({ ...initSearchData }); @@ -133,22 +134,6 @@ const searchList: any = computed(() => [ value: item.stcd })) }, - { - type: 'Radio', - name: 'mway', - label: '数据类型', - width: 140, - options: [ - { - label: '人工', - value: '1' - }, - { - label: '自动', - value: '2' - } - ] - }, { type: 'custom', name: 'jcdt', diff --git a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/index.vue b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/index.vue index 421d1faa..42facee3 100644 --- a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/index.vue +++ b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/index.vue @@ -1,551 +1,42 @@ + - + diff --git a/frontend/src/views/dianZhanZhuanTi/components/ShuiDianZhanJieShao.vue b/frontend/src/views/dianZhanZhuanTi/components/ShuiDianZhanJieShao.vue index a1890eb3..9f12e6f5 100644 --- a/frontend/src/views/dianZhanZhuanTi/components/ShuiDianZhanJieShao.vue +++ b/frontend/src/views/dianZhanZhuanTi/components/ShuiDianZhanJieShao.vue @@ -202,7 +202,7 @@ onUnmounted(() => { diff --git a/frontend-sjgl/src/views/conventionalHydropower/BasicData/EditPowerModal.vue b/frontend-sjgl/src/views/conventionalHydropower/BasicData/EditPowerModal.vue index 32c576f0..fbf42cb6 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/BasicData/EditPowerModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/BasicData/EditPowerModal.vue @@ -19,7 +19,7 @@
概述
- + - + - + - + - + - + - + - + - + - + - + - +
水文
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
水库
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
下泄流量及相应下游水位
- + - + - + - + - + - + - + - +
工程效益指标
- + - + - + - + - + - + - +
大坝
- + - + - + - +
其他
- + - + - + - + { stcd: formData.value.stcd }; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); appendSelectLabels(engInfo, changeOrder.value.map(c => c.field)); res = await updatePowerInfo({ diff --git a/frontend-sjgl/src/views/conventionalHydropower/FishResource/EditFishDictoryModal.vue b/frontend-sjgl/src/views/conventionalHydropower/FishResource/EditFishDictoryModal.vue index 39dd8f59..4947a052 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/FishResource/EditFishDictoryModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/FishResource/EditFishDictoryModal.vue @@ -718,7 +718,12 @@ const handleConfirmSubmit = async (source: string) => { // 编辑时只传修改过的字段 engInfo.id = formData.value.id; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); // 保留剩余的已有图片 inffile const existingIds = fileList.value diff --git a/frontend-sjgl/src/views/conventionalHydropower/aiBox/EditAiBoxModal.vue b/frontend-sjgl/src/views/conventionalHydropower/aiBox/EditAiBoxModal.vue index 454ff8da..e25979bd 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/aiBox/EditAiBoxModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/aiBox/EditAiBoxModal.vue @@ -539,7 +539,12 @@ const handleConfirmSubmit = async (source: string) => { } else { engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateAiboxInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/aquaEco/EditOtweModal.vue b/frontend-sjgl/src/views/conventionalHydropower/aquaEco/EditOtweModal.vue index 74a7a98a..b976e590 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/aquaEco/EditOtweModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/aquaEco/EditOtweModal.vue @@ -527,7 +527,12 @@ const handleConfirmSubmit = async (source: string) => { } else { engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateOtweInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/fishSurvey/EditFishModal.vue b/frontend-sjgl/src/views/conventionalHydropower/fishSurvey/EditFishModal.vue index 13c59770..cd70230c 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/fishSurvey/EditFishModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/fishSurvey/EditFishModal.vue @@ -572,7 +572,12 @@ const handleConfirmSubmit = async (source: string) => { } else { engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateAiInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/guoYuSheShi/EditFpModal.vue b/frontend-sjgl/src/views/conventionalHydropower/guoYuSheShi/EditFpModal.vue index 496c8247..326d08af 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/guoYuSheShi/EditFpModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/guoYuSheShi/EditFpModal.vue @@ -403,7 +403,14 @@ const handleConfirmSubmit = async (source: string) => { res = await addFpInfo({ engInfo, source: source.trim() || '新增' }); } else { engInfo.stcd = formData.value.stcd; - changeOrder.value.forEach(item => { engInfo[item.field] = formData.value[item.field]; }); + changeOrder.value.forEach(item => { + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; + }); // fpssmn 多选:数组 → 逗号分隔字符串 if (Array.isArray(engInfo.fpssmn)) engInfo.fpssmn = engInfo.fpssmn.join(','); res = await updateFpInfo({ engInfo, source: source.trim() || '编辑' }); diff --git a/frontend-sjgl/src/views/conventionalHydropower/luShengShengTaiDiaoCha/EditTeModal.vue b/frontend-sjgl/src/views/conventionalHydropower/luShengShengTaiDiaoCha/EditTeModal.vue index 70425fc7..ce39127c 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/luShengShengTaiDiaoCha/EditTeModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/luShengShengTaiDiaoCha/EditTeModal.vue @@ -450,7 +450,12 @@ const handleConfirmSubmit = async (source: string) => { // 编辑时只传 stcd + 修改过的字段 engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateTeInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/qiXiDi/EditFhModal.vue b/frontend-sjgl/src/views/conventionalHydropower/qiXiDi/EditFhModal.vue index a399cceb..d41afe50 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/qiXiDi/EditFhModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/qiXiDi/EditFhModal.vue @@ -44,6 +44,15 @@ /> + + + + + = { stcd: '栖息地站码', stnm: '栖息地名称', stlc: '站址', + layerCode: '图层编码', baseId: '水电基地', rstcd: '所属电站', bhdx: '保护对象', @@ -518,7 +528,12 @@ const handleConfirmSubmit = async (source: string) => { } else { engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); // bhdx 多选:数组 → 逗号分隔字符串 if (Array.isArray(engInfo.bhdx)) engInfo.bhdx = engInfo.bhdx.join(','); diff --git a/frontend-sjgl/src/views/conventionalHydropower/qiXiDi/index.vue b/frontend-sjgl/src/views/conventionalHydropower/qiXiDi/index.vue index 47d20df4..46154722 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/qiXiDi/index.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/qiXiDi/index.vue @@ -64,7 +64,7 @@ const operationLogVisible = ref(false); const columns = ref([ { key: 'stnm', title: '栖息地名称', dataIndex: 'stnm', visible: true, width: 260, ellipsis: true }, - { key: 'stcd', title: '栖息地站码', dataIndex: 'stcd', visible: true, width: 320, fixed: 'left', ellipsis: true }, + { key: 'stcd', title: '栖息地站码', dataIndex: 'stcd', visible: true, width: 320, ellipsis: true }, { key: 'baseName', title: '水电基地', dataIndex: 'baseName', visible: true, width: 120, ellipsis: true }, { key: 'ennm', title: '所属电站', dataIndex: 'ennm', visible: true, width: 150, ellipsis: true }, { key: 'bhdxName', title: '保护对象', dataIndex: 'bhdxName', visible: true, width: 240, ellipsis: true }, @@ -77,6 +77,7 @@ const columns = ref([ { key: 'bhfs', title: '保护方式', dataIndex: 'bhfs', visible: true, width: 120, ellipsis: true }, { key: 'inv', title: '投资(亿元)', dataIndex: 'inv', visible: true, width: 120 }, { key: 'stlc', title: '站址', dataIndex: 'stlc', visible: true, ellipsis: true,width: 220 }, + { key: 'layerCode', title: '图层编码', dataIndex: 'layerCode', visible: true, ellipsis: true, width: 160 }, { key: 'action', title: '操作', dataIndex: 'action', fixed: 'right', width: 120 }, ]); diff --git a/frontend-sjgl/src/views/conventionalHydropower/rescueStation/EditVaModal.vue b/frontend-sjgl/src/views/conventionalHydropower/rescueStation/EditVaModal.vue index 858819ab..dc270da7 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/rescueStation/EditVaModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/rescueStation/EditVaModal.vue @@ -486,7 +486,14 @@ const handleConfirmSubmit = async (source: string) => { res = await addVaInfo({ engInfo, source: source.trim() || '新增' }); } else { engInfo.stcd = formData.value.stcd; - changeOrder.value.forEach(item => { engInfo[item.field] = formData.value[item.field]; }); + changeOrder.value.forEach(item => { + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; + }); res = await updateVaInfo({ engInfo, source: source.trim() || '编辑' }); } if (res?.code == 0 || res?.success) { diff --git a/frontend-sjgl/src/views/conventionalHydropower/shengTaiLiuLiang/EditEqModal.vue b/frontend-sjgl/src/views/conventionalHydropower/shengTaiLiuLiang/EditEqModal.vue index 2b96d1ce..2ad26852 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/shengTaiLiuLiang/EditEqModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/shengTaiLiuLiang/EditEqModal.vue @@ -344,7 +344,14 @@ const handleConfirmSubmit = async (source: string) => { res = await addEqInfo({ engInfo, source: source.trim() || '新增' }); } else { engInfo.stcd = formData.value.stcd; - changeOrder.value.forEach(item => { engInfo[item.field] = formData.value[item.field]; }); + changeOrder.value.forEach(item => { + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; + }); res = await updateEqInfo({ engInfo, source: source.trim() || '编辑' }); } if (res?.code == 0 || res?.success) { diff --git a/frontend-sjgl/src/views/conventionalHydropower/shiPinJianKong/EditVdModal.vue b/frontend-sjgl/src/views/conventionalHydropower/shiPinJianKong/EditVdModal.vue index fd55471d..924a0726 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/shiPinJianKong/EditVdModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/shiPinJianKong/EditVdModal.vue @@ -265,7 +265,14 @@ const handleConfirmSubmit = async (source: string) => { res = await addVdInfo({ engInfo, source: source.trim() || '新增' }); } else { engInfo.stcd = formData.value.stcd; - changeOrder.value.forEach(item => { engInfo[item.field] = formData.value[item.field]; }); + changeOrder.value.forEach(item => { + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; + }); res = await updateVdInfo({ engInfo, source: source.trim() || '编辑' }); } if (res?.code == 0 || res?.success) { diff --git a/frontend-sjgl/src/views/conventionalHydropower/shuiShengShengTaiDiaoCha/EditWeModal.vue b/frontend-sjgl/src/views/conventionalHydropower/shuiShengShengTaiDiaoCha/EditWeModal.vue index fd9f8e8e..16f8f739 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/shuiShengShengTaiDiaoCha/EditWeModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/shuiShengShengTaiDiaoCha/EditWeModal.vue @@ -461,7 +461,12 @@ const handleConfirmSubmit = async (source: string) => { // 编辑时只传 stcd + 修改过的字段 engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateWeInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/shuiWenJianCe/EditWtModal.vue b/frontend-sjgl/src/views/conventionalHydropower/shuiWenJianCe/EditWtModal.vue index e921494c..9be54299 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/shuiWenJianCe/EditWtModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/shuiWenJianCe/EditWtModal.vue @@ -454,7 +454,12 @@ const handleConfirmSubmit = async (source: string) => { // 编辑时只传 stcd + 修改过的字段 engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateWtInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/shuiZhiJianCe/EditWqModal.vue b/frontend-sjgl/src/views/conventionalHydropower/shuiZhiJianCe/EditWqModal.vue index 17706e90..1134facb 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/shuiZhiJianCe/EditWqModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/shuiZhiJianCe/EditWqModal.vue @@ -502,7 +502,12 @@ const handleConfirmSubmit = async (source: string) => { } else { engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateWqInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/sonarCam/EditSonarModal.vue b/frontend-sjgl/src/views/conventionalHydropower/sonarCam/EditSonarModal.vue index 2fcdbca0..44b92d78 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/sonarCam/EditSonarModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/sonarCam/EditSonarModal.vue @@ -513,7 +513,12 @@ const handleConfirmSubmit = async (source: string) => { } else { engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateSonarInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/tempMit/EditDwModal.vue b/frontend-sjgl/src/views/conventionalHydropower/tempMit/EditDwModal.vue index 6407c4d8..1671f1d2 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/tempMit/EditDwModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/tempMit/EditDwModal.vue @@ -525,7 +525,12 @@ const handleConfirmSubmit = async (source: string) => { } else { engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateDwInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/terrEco/EditOtteModal.vue b/frontend-sjgl/src/views/conventionalHydropower/terrEco/EditOtteModal.vue index 8fabb9b0..9d2d0083 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/terrEco/EditOtteModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/terrEco/EditOtteModal.vue @@ -534,7 +534,12 @@ const handleConfirmSubmit = async (source: string) => { } else { engInfo.stcd = formData.value.stcd; changeOrder.value.forEach(item => { - engInfo[item.field] = formData.value[item.field]; + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; }); res = await updateOtteInfo({ engInfo, diff --git a/frontend-sjgl/src/views/conventionalHydropower/zengZhiFangLiu/EditFbModal.vue b/frontend-sjgl/src/views/conventionalHydropower/zengZhiFangLiu/EditFbModal.vue index 327c1249..9a6d23fa 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/zengZhiFangLiu/EditFbModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/zengZhiFangLiu/EditFbModal.vue @@ -350,7 +350,14 @@ const handleConfirmSubmit = async (source: string) => { res = await addFbInfo({ engInfo, source: source.trim() || '新增' }); } else { engInfo.stcd = formData.value.stcd; - changeOrder.value.forEach(item => { engInfo[item.field] = formData.value[item.field]; }); + changeOrder.value.forEach(item => { + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; + }); res = await updateFbInfo({ engInfo, source: source.trim() || '编辑' }); } if (res?.code == 0 || res?.success) { diff --git a/frontend-sjgl/src/views/conventionalHydropower/zhenXIZhiWuYuan/EditVpModal.vue b/frontend-sjgl/src/views/conventionalHydropower/zhenXIZhiWuYuan/EditVpModal.vue index 3d216ea9..557ce21a 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/zhenXIZhiWuYuan/EditVpModal.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/zhenXIZhiWuYuan/EditVpModal.vue @@ -305,7 +305,14 @@ const handleConfirmSubmit = async (source: string) => { res = await addVpInfo({ engInfo, source: source.trim() || '新增' }); } else { engInfo.stcd = formData.value.stcd; - changeOrder.value.forEach(item => { engInfo[item.field] = formData.value[item.field]; }); + changeOrder.value.forEach(item => { + // select 清空后值为 undefined/null,统一转为空字符串,避免序列化时字段被省略 + let val = formData.value[item.field]; + if (val === null || val === undefined) { + val = ''; + } + engInfo[item.field] = val; + }); res = await updateVpInfo({ engInfo, source: source.trim() || '编辑' }); } if (res?.code == 0 || res?.success) { diff --git a/frontend-sjgl/src/views/monitorData/FishData/EditFishDataAutoModal.vue b/frontend-sjgl/src/views/monitorData/FishData/EditFishDataAutoModal.vue new file mode 100644 index 00000000..7e1219bf --- /dev/null +++ b/frontend-sjgl/src/views/monitorData/FishData/EditFishDataAutoModal.vue @@ -0,0 +1,841 @@ + + + diff --git a/frontend-sjgl/src/views/monitorData/FishData/EditFishDataManualModal.vue b/frontend-sjgl/src/views/monitorData/FishData/EditFishDataManualModal.vue new file mode 100644 index 00000000..138355df --- /dev/null +++ b/frontend-sjgl/src/views/monitorData/FishData/EditFishDataManualModal.vue @@ -0,0 +1,823 @@ + + + diff --git a/frontend-sjgl/src/views/monitorData/FishData/FishDataAuto.vue b/frontend-sjgl/src/views/monitorData/FishData/FishDataAuto.vue index 4915db3e..32ff0de2 100644 --- a/frontend-sjgl/src/views/monitorData/FishData/FishDataAuto.vue +++ b/frontend-sjgl/src/views/monitorData/FishData/FishDataAuto.vue @@ -7,6 +7,7 @@ @export-btn="exportBtn" @search-finish="onSearchFinish" @reset="onReset" + @seeEdit="handleSeeEdit" ref="searchRef" /> @@ -20,6 +21,18 @@ sort: sort }" > + @@ -49,6 +62,24 @@ > + + + + + + + + From ab4f40ed564404c677dd56dae4f8c8484df0979b Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 17 Aug 2026 09:43:22 +0800 Subject: [PATCH 33/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E8=BF=87?= =?UTF-8?q?=E9=B1=BC=E8=AE=BE=E6=96=BD=E5=80=92=E6=95=B0=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_data/controller/FishDraftDataController.java | 5 +++-- .../yfd/platform/qgc_data/mapper/FishStatisticsMapper.java | 4 +++- .../platform/qgc_data/service/IFishStatisticsService.java | 2 +- .../qgc_data/service/impl/FishStatisticsServiceImpl.java | 6 +++--- .../src/main/resources/mapper/data/FishStatisticsMapper.xml | 3 +++ 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java b/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java index c59aa0a2..0b799660 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java @@ -112,8 +112,9 @@ public class FishDraftDataController { @PostMapping("/statistics") @Operation(summary = "过鱼到数统计(按用户月度汇总,支持流域/电站多选过滤)") - public ResponseResult statistics(@RequestBody DataSourceRequest dataSourceRequest) { - Page result = fishStatisticsService.queryPage(dataSourceRequest); + public ResponseResult statistics(@RequestBody DataSourceRequest dataSourceRequest, + @RequestHeader(value = "Tenant_id", required = false) String tenantId) { + Page result = fishStatisticsService.queryPage(dataSourceRequest, tenantId); return ResponseResult.successData(result); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishStatisticsMapper.java b/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishStatisticsMapper.java index 8bb8fdd8..75974838 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishStatisticsMapper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishStatisticsMapper.java @@ -10,10 +10,12 @@ public interface FishStatisticsMapper { List queryStatistics(@Param("basinCode") String basinCode, @Param("stationCode") String stationCode, @Param("reportMonth") String reportMonth, + @Param("tenantId") String tenantId, @Param("startRow") int startRow, @Param("endRow") int endRow); int countStatistics(@Param("basinCode") String basinCode, @Param("stationCode") String stationCode, - @Param("reportMonth") String reportMonth); + @Param("reportMonth") String reportMonth, + @Param("tenantId") String tenantId); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishStatisticsService.java b/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishStatisticsService.java index 4a08e371..51091c04 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishStatisticsService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishStatisticsService.java @@ -6,5 +6,5 @@ import com.yfd.platform.qgc_data.domain.vo.FishStatisticsVO; public interface IFishStatisticsService { - Page queryPage(DataSourceRequest dataSourceRequest); + Page queryPage(DataSourceRequest dataSourceRequest, String tenantId); } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishStatisticsServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishStatisticsServiceImpl.java index e9a688da..985bdfbe 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishStatisticsServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishStatisticsServiceImpl.java @@ -26,7 +26,7 @@ public class FishStatisticsServiceImpl implements IFishStatisticsService { private FishStatisticsMapper fishStatisticsMapper; @Override - public Page queryPage(DataSourceRequest dataSourceRequest) { + public Page queryPage(DataSourceRequest dataSourceRequest, String tenantId) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); String basinNamesStr = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "basinCode"); @@ -53,9 +53,9 @@ public class FishStatisticsServiceImpl implements IFishStatisticsService { int endRow = startRow + pageSize; List records = fishStatisticsMapper.queryStatistics( - basinNamesStr, stationNamesStr, reportMonth, startRow, endRow); + basinNamesStr, stationNamesStr, reportMonth, tenantId, startRow, endRow); - int total = fishStatisticsMapper.countStatistics(basinNamesStr, stationNamesStr, reportMonth); + int total = fishStatisticsMapper.countStatistics(basinNamesStr, stationNamesStr, reportMonth, tenantId); Page page = new Page<>(); page.setRecords(records); diff --git a/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml b/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml index 6099458b..486542da 100644 --- a/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml +++ b/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml @@ -115,6 +115,9 @@ AND STATION_CODE = #{stationCode} + + AND USER_ID IN (SELECT USER_ID FROM SYS_USER_TENANT WHERE TENANT_ID = #{tenantId}) + ), From 3093d6bdecff9abe8fb8f9452c1c02e28fe5089a Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 17 Aug 2026 12:40:47 +0800 Subject: [PATCH 34/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/java/com/yfd/platform/config/WebConfig.java | 2 +- backend/src/main/java/com/yfd/platform/constant/Constant.java | 2 +- .../platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/config/WebConfig.java b/backend/src/main/java/com/yfd/platform/config/WebConfig.java index 1539d29b..36b76916 100644 --- a/backend/src/main/java/com/yfd/platform/config/WebConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/WebConfig.java @@ -29,7 +29,7 @@ public class WebConfig implements WebMvcConfigurer { @Bean public Cache loginuserCache() { - return CacheUtil.newLRUCache(200); + return CacheUtil.newLRUCache(500); } public void putLoginCache(String key, String value, long timeoutSeconds) { diff --git a/backend/src/main/java/com/yfd/platform/constant/Constant.java b/backend/src/main/java/com/yfd/platform/constant/Constant.java index 32eab6e9..f9487e59 100644 --- a/backend/src/main/java/com/yfd/platform/constant/Constant.java +++ b/backend/src/main/java/com/yfd/platform/constant/Constant.java @@ -13,7 +13,7 @@ public class Constant { public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; public static final String CODE_KEY = "code-key-"; - public static final long CODE_EXPIRATION_TIME = 1000 * 60 * 2; + public static final long CODE_EXPIRATION_TIME = 1000 * 60 * 5; /** * 用于IP定位转换 */ diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 8276fc3d..b0a27793 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -1284,7 +1284,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl Date: Wed, 19 Aug 2026 12:30:30 +0800 Subject: [PATCH 35/44] =?UTF-8?q?fix:=20=E8=BF=87=E9=B1=BC=E8=AE=BE?= =?UTF-8?q?=E6=96=BDAI=E8=87=AA=E5=8A=A8=E6=95=B0=E6=8D=AE=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdFpssrlAiRController.java | 314 ++++++++++++++++++ .../platform/qgc_base/domain/SdFpssrlAiR.java | 4 + .../qgc_base/service/ISdFpssrlAiRService.java | 48 +++ .../service/impl/SdFpssrlAiRServiceImpl.java | 153 +++++++++ .../fp/service/impl/FpRunServiceImpl.java | 293 ++++++++++++---- 5 files changed, 751 insertions(+), 61 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlAiRController.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssrlAiRService.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlAiRServiceImpl.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlAiRController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlAiRController.java new file mode 100644 index 00000000..951a9772 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlAiRController.java @@ -0,0 +1,314 @@ +package com.yfd.platform.qgc_base.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_base.domain.SdEngInfoBHOperateRequest; +import com.yfd.platform.qgc_base.domain.SdFishDictoryB; +import com.yfd.platform.qgc_base.domain.SdFpssrlAiR; +import com.yfd.platform.qgc_base.domain.SdFpssrlRAiRequest; +import com.yfd.platform.qgc_base.service.ISdFishDictoryBService; +import com.yfd.platform.qgc_base.service.ISdFpssrlAiRService; +import com.yfd.platform.qgc_data.service.AttachmentUploadService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 过鱼设施AI盒子自动数据表 前端控制器 + *

+ */ +@Slf4j +@RestController +@RequestMapping("/base/fpssrlAiR") +@Tag(name = "过鱼设施AI自动数据管理") +public class SdFpssrlAiRController { + + @Resource + private ISdFpssrlAiRService sdFpssrlAiRService; + + @Resource + private ObjectMapper objectMapper; + + @Resource + private AttachmentUploadService attachmentUploadService; + + @Resource + private ISdFishDictoryBService sdFishDictoryBService; + + // ==================== CRUD 方法 ==================== + + @PostMapping("/queryPageList") + @Operation(summary = "分页查询过鱼AI自动数据列表(支持动态过滤和排序)") + public ResponseResult queryPageList(@RequestBody DataSourceRequest request) { + Page page = sdFpssrlAiRService.queryPageList(request); + return ResponseResult.successData(page); + } + + @GetMapping("/getById") + @Operation(summary = "根据ID查询过鱼AI自动数据") + public ResponseResult getById(@RequestParam String id) { + return ResponseResult.successData(sdFpssrlAiRService.getById(id)); + } + + @Log(module = "过鱼设施AI自动数据管理", value = "新增过鱼AI自动数据") + @PostMapping("/add") + @Operation(summary = "新增过鱼AI自动数据") + public ResponseResult add(@RequestParam("data") String dataStr, + @RequestParam(value = "picFiles", required = false) List picFiles, + @RequestParam(value = "vdFiles", required = false) List vdFiles) { + try { + SdEngInfoBHOperateRequest request = objectMapper.readValue(dataStr, SdEngInfoBHOperateRequest.class); + SdFpssrlAiR entity = request == null || request.getEngInfo() == null ? null + : objectMapper.convertValue(request.getEngInfo(), SdFpssrlAiR.class); + if (entity == null) { + return ResponseResult.error("数据不能为空"); + } + + // 上传附件并设置到实体(图片→firstImgUrl,视频→videoUrl) + applyUploadedFiles(entity, picFiles, vdFiles); + + boolean result = sdFpssrlAiRService.add(entity, request.getSource()); + return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); + } catch (Exception e) { + log.error("新增过鱼AI自动数据失败", e); + return ResponseResult.error("新增失败: " + e.getMessage()); + } + } + + @Log(module = "过鱼设施AI自动数据管理", value = "修改过鱼AI自动数据") + @PostMapping("/update") + @Operation(summary = "修改过鱼AI自动数据") + public ResponseResult update(@RequestParam("data") String dataStr, + @RequestParam(value = "picFiles", required = false) List picFiles, + @RequestParam(value = "vdFiles", required = false) List vdFiles) { + try { + SdEngInfoBHOperateRequest request = objectMapper.readValue(dataStr, SdEngInfoBHOperateRequest.class); + Map engInfo = request == null ? null : request.getEngInfo(); + if (engInfo == null || engInfo.get("id") == null) { + return ResponseResult.error("数据或ID不能为空"); + } + + // 获取修改前的实体,用于后续清理被替换的旧附件 + SdFpssrlAiR before = sdFpssrlAiRService.getById((String) engInfo.get("id")); + List oldAttachmentIds = before != null ? collectAttachmentIds(before) : Collections.emptyList(); + + // 上传新附件并合并回 patch map(仅当本次有文件上传时才覆盖对应字段) + SdFpssrlAiR tempEntity = objectMapper.convertValue(engInfo, SdFpssrlAiR.class); + applyUploadedFiles(tempEntity, picFiles, vdFiles); + if (picFiles != null && !picFiles.isEmpty()) { + engInfo.put("firstimgurl", tempEntity.getFirstImgUrl()); + } + if (vdFiles != null && !vdFiles.isEmpty()) { + engInfo.put("videourl", tempEntity.getVideoUrl()); + } + + boolean result = sdFpssrlAiRService.update(engInfo, request.getSource()); + if (result) { + // 清理被替换的旧附件 + SdFpssrlAiR after = sdFpssrlAiRService.getById((String) engInfo.get("id")); + deleteReplacedFiles(oldAttachmentIds, collectAttachmentIds(after)); + } + return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); + } catch (Exception e) { + log.error("修改过鱼AI自动数据失败", e); + return ResponseResult.error("修改失败: " + e.getMessage()); + } + } + + @Log(module = "过鱼设施AI自动数据管理", value = "删除过鱼AI自动数据") + @PostMapping("/delete") + @Operation(summary = "删除过鱼AI自动数据") + public ResponseResult delete(@RequestBody SdEngInfoBHOperateRequest request) { + List ids = request == null ? null : request.getIds(); + if (ids == null || ids.isEmpty()) { + return ResponseResult.error("ID不能为空"); + } + + // 删除前先收集所有需要清理的附件ID + List allAttachmentIds = new ArrayList<>(); + for (String id : ids) { + SdFpssrlAiR entity = sdFpssrlAiRService.getById(id); + if (entity != null) { + allAttachmentIds.addAll(collectAttachmentIds(entity)); + } + } + + boolean result = sdFpssrlAiRService.delete(ids, request.getSource()); + if (result) { + // 删除关联的附件 + deleteAttachments(allAttachmentIds); + } + return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败"); + } + + // ==================== AI 设备识别数据上报接口 ==================== + + /** + * AI设备图片/视频上传接口 + * 步骤1:先上传图片获取附件URL,再将URL填入数据上报接口 + */ + @PostMapping("/ai/uploadImage") + @Operation(summary = "AI设备图片上传") + public ResponseResult aiUploadImage(@RequestParam("file") MultipartFile file) { + if (file == null || file.isEmpty()) { + return ResponseResult.error("文件不能为空"); + } + try { + List files = new ArrayList<>(); + files.add(file); + List attachmentIds = attachmentUploadService.uploadMultipartFiles(files); + if (attachmentIds != null && !attachmentIds.isEmpty()) { + return ResponseResult.successData(attachmentIds); + } else { + return ResponseResult.error("图片上传失败"); + } + } catch (Exception e) { + log.error("AI图片上传失败", e); + return ResponseResult.error("图片上传失败: " + e.getMessage()); + } + } + + /** + * AI设备识别数据上报接口(支持单条和批量) + * 步骤2:上传完图片后,将附件ID填入JSON数组调用此接口 + */ + @PostMapping("/ai/report") + @Operation(summary = "AI设备识别数据上报(支持批量)") + public ResponseResult aiReport(@RequestBody List requests) { + if (requests == null || requests.isEmpty()) { + return ResponseResult.error("请求数据不能为空"); + } + List list = sdFishDictoryBService.list(new LambdaQueryWrapper().eq(SdFishDictoryB::getIsDeleted, "0").select(SdFishDictoryB::getId, SdFishDictoryB::getName)); + Map idNameMap = list.stream() + .filter(item -> item.getId() != null && item.getName() != null) + .collect(Collectors.toMap( + SdFishDictoryB::getName, + SdFishDictoryB::getId, + (oldValue, newValue) -> oldValue // 如果有重复 key 保留旧值(实际不会重复) + )); + // 逐条校验 + for (int i = 0; i < requests.size(); i++) { + SdFpssrlRAiRequest req = requests.get(i); + if (req == null) { + return ResponseResult.error("第" + (i + 1) + "条数据为空"); + } + if (req.getStcd() == null || req.getStcd().isEmpty()) { + return ResponseResult.error("第" + (i + 1) + "条过鱼设施编码(stcd)不能为空"); + } + if (req.getFwdx() == null || req.getFwdx().isEmpty()) { + return ResponseResult.error("第" + (i + 1) + "条服务对象(fwdx)不能为空"); + } + if (req.getTm() == null) { + return ResponseResult.error("第" + (i + 1) + "条识别时间(tm)不能为空"); + } + if (req.getFtp() == null || req.getFtp().isEmpty()) { + return ResponseResult.error("第" + (i + 1) + "条鱼种类(ftp)不能为空"); + } + if (StrUtil.isNotBlank(req.getFtp())) { + req.setFtp(idNameMap.getOrDefault(req.getFtp(), req.getFtp())); + } + } + + try { + List result = sdFpssrlAiRService.processAiReportBatch(requests); + log.info("AI批量上报成功,共{}条", result.size()); + return ResponseResult.success(); + } catch (Exception e) { + log.error("AI识别数据批量上报失败", e); + return ResponseResult.error("上报失败: " + e.getMessage()); + } + } + + // ==================== 附件处理辅助方法 ==================== + + /** + * 上传图片/视频附件并追加附件ID到 firstImgUrl/videoUrl 字段(与已有ID以逗号拼接) + */ + private void applyUploadedFiles(SdFpssrlAiR entity, List picFiles, List vdFiles) { + if (picFiles != null && !picFiles.isEmpty()) { + List ids = attachmentUploadService.uploadMultipartFiles(picFiles); + if (!ids.isEmpty()) { + entity.setFirstImgUrl(mergeIds(entity.getFirstImgUrl(), ids)); + } + } + if (vdFiles != null && !vdFiles.isEmpty()) { + List ids = attachmentUploadService.uploadMultipartFiles(vdFiles); + if (!ids.isEmpty()) { + entity.setVideoUrl(mergeIds(entity.getVideoUrl(), ids)); + } + } + } + + /** + * 将新上传的附件ID列表追加到已有ID字符串后面(逗号分隔) + */ + private String mergeIds(String existing, List ids) { + String newIds = ids.stream() + .filter(StrUtil::isNotBlank) + .collect(Collectors.joining(",")); + if (StrUtil.isBlank(newIds)) { + return existing; + } + return StrUtil.isBlank(existing) ? newIds : existing + "," + newIds; + } + + /** + * 收集实体中 firstImgUrl/videoUrl 字段的附件ID + */ + private List collectAttachmentIds(SdFpssrlAiR entity) { + List ids = new ArrayList<>(); + if (entity == null) { + return ids; + } + if (StrUtil.isNotBlank(entity.getFirstImgUrl())) { + Arrays.stream(entity.getFirstImgUrl().split(",")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .forEach(ids::add); + } + if (StrUtil.isNotBlank(entity.getVideoUrl())) { + Arrays.stream(entity.getVideoUrl().split(",")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .forEach(ids::add); + } + return ids; + } + + /** + * 删除被替换的旧附件(old中有但new中没有的) + */ + private void deleteReplacedFiles(List oldIds, List newIds) { + for (String oldId : oldIds) { + if (StrUtil.isBlank(oldId)) { + continue; + } + if (!newIds.contains(oldId)) { + attachmentUploadService.deleteFile(oldId); + } + } + } + + /** + * 批量删除附件 + */ + private void deleteAttachments(List attachmentIds) { + for (String id : attachmentIds) { + if (StrUtil.isNotBlank(id)) { + attachmentUploadService.deleteFile(id); + } + } + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java index 2a85652d..8fcd28b5 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java @@ -115,6 +115,10 @@ public class SdFpssrlAiR implements Serializable { /** 备注 */ private String remark; + /** 鱼种类名称(非表字段,用于列表展示) */ + @TableField(exist = false) + private String ftpName; + /** 过鱼设施名称(非表字段,用于列表展示) */ @TableField(exist = false) private String stnm; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssrlAiRService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssrlAiRService.java new file mode 100644 index 00000000..4b61c399 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssrlAiRService.java @@ -0,0 +1,48 @@ +package com.yfd.platform.qgc_base.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.qgc_base.domain.SdFpssrlAiR; +import com.yfd.platform.qgc_base.domain.SdFpssrlRAiRequest; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 过鱼设施AI盒子自动数据表 服务接口 + *

+ */ +public interface ISdFpssrlAiRService extends IService { + + /** + * 分页查询(Kendo Grid) + */ + Page queryPageList(DataSourceRequest request); + + /** + * 新增 + */ + boolean add(SdFpssrlAiR entity, String source); + + /** + * 修改(按前端 patch 显式更新字段,含 null 置空) + */ + boolean update(Map engInfoPatch, String source) throws Exception; + + /** + * 删除(逻辑删除) + */ + boolean delete(List ids, String source); + + /** + * 根据ID查询(排除已删除的) + */ + SdFpssrlAiR getById(String id); + + /** + * 批量处理AI设备上报的识别数据 + */ + List processAiReportBatch(List requests); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlAiRServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlAiRServiceImpl.java new file mode 100644 index 00000000..b77f6b17 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlAiRServiceImpl.java @@ -0,0 +1,153 @@ +package com.yfd.platform.qgc_base.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.qgc_base.domain.SdFpssrlAiR; +import com.yfd.platform.qgc_base.domain.SdFpssrlRAiRequest; +import com.yfd.platform.qgc_base.mapper.SdFpssrlAiRMapper; +import com.yfd.platform.qgc_base.service.IMsOperationLogService; +import com.yfd.platform.qgc_base.service.ISdFpssrlAiRService; +import com.yfd.platform.utils.CodeToNameMetadataBo; +import com.yfd.platform.utils.DataSourceRequestUtil; +import com.yfd.platform.utils.DictCodeToNameConverter; +import com.yfd.platform.utils.SecurityUtils; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 过鱼设施AI盒子自动数据表 服务实现类 + *

+ */ +@Slf4j +@Service +public class SdFpssrlAiRServiceImpl extends ServiceImpl implements ISdFpssrlAiRService { + + private static final String TABLE_NAME = "SD_FPSSRL_AI_R"; + + @Resource + private IMsOperationLogService msOperationLogService; + + @Resource + private DictCodeToNameConverter dictCodeToNameConverter; + + @Resource + private PatchUpdateHelper patchUpdateHelper; + + private static final Set TRANSIENT_FIELDS = Set.of("stnm", "ftpName", "serialVersionUID"); + + /** + * 代码转名称元数据配置列表 + */ + private static final List CODE_TO_NAME_META_LIST = new ArrayList<>(); + + static { + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("ftp").modifyProperty("ftpName") + .dictType("DYNAMIC").dictSource("SD_FISHDICTORY_B").codeColumn("ID").nameColumn("NAME") + .filter("NVL(IS_DELETED, 0) = 0 AND NVL(ENABLE, 1) = 1").build()); + } + + @Override + public Page queryPageList(DataSourceRequest request) { + return DataSourceRequestUtil.executeQuery(request, SdFpssrlAiR.class, this); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean add(SdFpssrlAiR entity, String source) { + boolean result = this.save(entity); + if (result) { + dictCodeToNameConverter.convertCodeToName(entity, CODE_TO_NAME_META_LIST); + msOperationLogService.recordAddDetailLog(entity.getId(), TABLE_NAME, entity, source, CODE_TO_NAME_META_LIST); + } + return result; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(Map engInfoPatch, String source) throws Exception { + return patchUpdateHelper.execute(this, engInfoPatch, source, TABLE_NAME, SdFpssrlAiR.class, + TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST, "id"); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean delete(List ids, String source) { + if (ids == null || ids.isEmpty()) return false; + int count = 0; + for (String id : ids) { + SdFpssrlAiR entity = getById(id); + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.eq(SdFpssrlAiR::getId, id); + wrapper.set(SdFpssrlAiR::getIsDeleted, 1); + wrapper.set(SdFpssrlAiR::getDeleteUser, SecurityUtils.getCurrentUsername()); + wrapper.set(SdFpssrlAiR::getDeleteTime, new Date()); + if (this.update(wrapper)) { + msOperationLogService.recordDeleteDetailLog(id, TABLE_NAME, entity, source); + count++; + } + } + return count > 0; + } + + @Override + public SdFpssrlAiR getById(String id) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SdFpssrlAiR::getId, id) + .eq(SdFpssrlAiR::getIsDeleted, 0); + return getOne(wrapper); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public List processAiReportBatch(List requests) { + List entities = new ArrayList<>(); + Date now = new Date(); + for (SdFpssrlRAiRequest req : requests) { + SdFpssrlAiR entity = new SdFpssrlAiR(); + entity.setStcd(req.getFwdx()); + entity.setAiBoxCode(req.getStcd()); + entity.setTm(req.getTm()); + entity.setFtp(req.getFtp()); + entity.setFcnt(req.getFcnt() != null ? req.getFcnt() : 1); + entity.setFsz(req.getFsz()); + entity.setLength(req.getLength()); + entity.setWidth(req.getWidth()); + entity.setFishspeed(req.getFishspeed()); + entity.setDirection(req.getDirection()); + entity.setFishposition(req.getFishposition()); + entity.setFirstImgUrl(req.getFirstImgUrl()); + entity.setSecondImgUrl(req.getSecondImgUrl()); + entity.setVideoUrl(req.getVideoUrl()); + entity.setTemperature(req.getTemperature()); + entity.setWaterlevel(req.getWaterlevel()); + entity.setSpeed(req.getSpeed()); + entity.setQ(req.getQ()); + entity.setDox(req.getDox()); + entity.setTu(req.getTu()); + entity.setChannelno(StrUtil.isNotBlank(req.getChannelno()) ? req.getChannelno() : "主通道"); + entity.setFid(req.getFid()); + entity.setRemark(req.getRemark()); + entity.setRecordUser("AI_SYSTEM"); + entity.setRecordTime(now); + entity.setModifyUser("AI_SYSTEM"); + entity.setModifyTime(now); + entity.setIsDeleted(0); + entities.add(entity); + } + this.baseMapper.mergeFishRecords(entities); + return entities; + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index e04595d3..dcdc553d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -1232,7 +1232,7 @@ public class FpRunServiceImpl implements FpRunService { DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); sql.append("SELECT ") - .append(buildQgcFpssrlDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(buildQgcFpssrlDetailAISelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) .append(" FROM (") .append(buildQgcFpssrlAiRCoreSql()) .append(") t WHERE 1 = 1 "); @@ -1704,12 +1704,12 @@ public class FpRunServiceImpl implements FpRunService { ") src"; } - private String buildQgcFpssrlAiRCoreSql() { return "SELECT " + "src.ID AS id, " + "src.STCD AS stcd, " + "src.STNM AS stnm, " + + "src.ISFS AS isfs, " + "src.BASEID AS baseId, " + "src.BASENAME AS baseName, " + "src.RSTCD AS rstcd, " + @@ -1729,6 +1729,12 @@ public class FpRunServiceImpl implements FpRunService { "src.FISHSPEED AS fishspeed, " + "src.DIRECTION AS direction, " + "src.TEMPERATURE AS temperature, " + + "src.WATERLEVEL AS waterlevel, " + + "src.FISHPOSITION AS fishposition, " + + "src.REMARK AS remark, " + + "src.DOX AS dox, " + + "src.Q AS q, " + + "src.TU AS tu, " + "src.SPEED AS speed, " + "src.CHANNELNO AS channelno, " + "src.FCNT AS fcnt, " + @@ -1757,11 +1763,18 @@ public class FpRunServiceImpl implements FpRunService { " COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, fishDirect.NAME, t.FTP) AS FTP, " + " t.FTP AS FISHID, " + " t.FSZ AS FSZ, " + + " null AS ISFS, " + " TO_CHAR(t.LENGTH) AS LENGTH, " + " TO_CHAR(t.WIDTH) AS WIDTH, " + " TO_CHAR(t.FISHSPEED) AS FISHSPEED, " + " TO_CHAR(t.DIRECTION) AS DIRECTION, " + " TO_CHAR(t.TEMPERATURE) AS TEMPERATURE, " + + " TO_CHAR(t.WATERLEVEL) AS WATERLEVEL, " + + " TO_CHAR(t.FISHPOSITION) AS FISHPOSITION, " + + " TO_CHAR(t.REMARK) AS REMARK, " + + " TO_CHAR(t.DOX) AS DOX, " + + " TO_CHAR(t.Q) AS Q, " + + " TO_CHAR(t.TU) AS TU, " + " TO_CHAR(t.SPEED) AS SPEED, " + " t.CHANNELNO AS CHANNELNO, " + " TO_CHAR(t.FCNT) AS FCNT, " + @@ -1773,64 +1786,6 @@ public class FpRunServiceImpl implements FpRunService { " fp.STTP AS STCODE, " + " sttp.STTP_NAME AS STNAME " + " FROM SD_FPSSRL_AI_R t " + - " INNER JOIN V_MS_STBPRP_T fp ON fp.STCD = t.STCD " + - " LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = fp.STTP AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + - " LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + - " LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + - " LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD " + - " AND hbrv.BASEID = eng.BASE_ID " + - " AND NVL(hbrv.IS_DELETED, 0) = 0 " + - " AND NVL(hbrv.ENABLED, 1) = 1 " + - " LEFT JOIN SD_FISHDICTORY_RLTN_B relRv ON relRv.FISH_ID = t.FTP " + - " AND relRv.RVCD = eng.HBRVCD " + - " AND NVL(relRv.IS_DELETED, 0) = 0 " + - " LEFT JOIN SD_FISHDICTORY_B fishRv ON fishRv.ID = relRv.ZY_FISH_ID " + - " AND NVL(fishRv.IS_DELETED, 0) = 0 " + - " AND NVL(fishRv.ENABLE, 1) = 1 " + - " LEFT JOIN SD_FISHDICTORY_RLTN_B relZy ON relZy.FISH_ID = t.FTP " + - " AND relZy.RVCD = 'ZY' " + - " AND NVL(relZy.IS_DELETED, 0) = 0 " + - " LEFT JOIN SD_FISHDICTORY_B fishZy ON fishZy.ID = relZy.ZY_FISH_ID " + - " AND NVL(fishZy.IS_DELETED, 0) = 0 " + - " AND NVL(fishZy.ENABLE, 1) = 1 " + - " LEFT JOIN SD_FISHDICTORY_B fishDirect ON fishDirect.ID = t.FTP " + - " AND NVL(fishDirect.IS_DELETED, 0) = 0 " + - " AND NVL(fishDirect.ENABLE, 1) = 1 " + - " WHERE NVL(t.IS_DELETED, 0) = 0 " + - " UNION ALL " + - " SELECT t.ID AS ID, " + - " t.STCD AS STCD, " + - " fp.STNM AS STNM, " + - " eng.BASE_ID AS BASEID, " + - " hb.BASENAME AS BASENAME, " + - " fp.RSTCD AS RSTCD, " + - " eng.ENNM AS ENNM, " + - " eng.HBRVCD AS HBRVCD, " + - " NVL(hb.ORDER_INDEX, 999999) AS BASESTEPSORT, " + - " NVL(hbrv.ORDER_INDEX, 999999) AS RVCDSTEPSORT, " + - " NVL(fp.ORDER_INDEX, 999999) AS SITESTEPSORT, " + - " NVL(eng.ORDER_INDEX, 999999) AS RSTCDSTEPSORT, " + - " t.STRDT AS TM, " + - " TO_CHAR(t.STRDT, 'YYYY') AS YR, " + - " COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, fishDirect.NAME, t.FTP) AS FTP, " + - " t.FTP AS FISHID, " + - " t.FSZ AS FSZ, " + - " CAST(NULL AS VARCHAR2(50)) AS LENGTH, " + - " CAST(NULL AS VARCHAR2(50)) AS WIDTH, " + - " CAST(NULL AS VARCHAR2(50)) AS FISHSPEED, " + - " TO_CHAR(t.DIRECTION) AS DIRECTION, " + - " CAST(NULL AS VARCHAR2(50)) AS TEMPERATURE, " + - " CAST(NULL AS VARCHAR2(50)) AS SPEED, " + - " CAST(NULL AS VARCHAR2(100)) AS CHANNELNO, " + - " TO_CHAR(t.FCNT) AS FCNT, " + - " t.PICPTH AS FIRSTIMGURL, " + - " t.VDPTH AS VIDEOURL, " + - " 1 AS MWAY, " + - " t.STRDT AS STRDT, " + - " t.ENDDT AS ENDDT, " + - " fp.STTP AS STCODE, " + - " sttp.STTP_NAME AS STNAME " + - " FROM SD_FPSS_R t " + " INNER JOIN SD_FPSS_B_H fp ON fp.STCD = t.STCD " + " LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = fp.STTP AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + " LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + @@ -1855,10 +1810,164 @@ public class FpRunServiceImpl implements FpRunService { " AND NVL(fishDirect.IS_DELETED, 0) = 0 " + " AND NVL(fishDirect.ENABLE, 1) = 1 " + " WHERE NVL(t.IS_DELETED, 0) = 0 " + -// " AND (t.TASK_STATUS = 'Approved' OR t.TASK_STATUS IS NULL) " + ") src"; } + +// private String buildQgcFpssrlAiRCoreSql() { +// return "SELECT " + +// "src.ID AS id, " + +// "src.STCD AS stcd, " + +// "src.STNM AS stnm, " + +// "src.BASEID AS baseId, " + +// "src.BASENAME AS baseName, " + +// "src.RSTCD AS rstcd, " + +// "src.ENNM AS ennm, " + +// "src.HBRVCD AS hbrvcd, " + +// "src.BASESTEPSORT AS baseStepSort, " + +// "src.RVCDSTEPSORT AS rvcdStepSort, " + +// "src.SITESTEPSORT AS siteStepSort, " + +// "src.RSTCDSTEPSORT AS rstcdStepSort, " + +// "src.TM AS tm, " + +// "src.YR AS yr, " + +// "src.FTP AS ftp, " + +// "src.FISHID AS fishId, " + +// "src.FSZ AS fsz, " + +// "src.LENGTH AS length, " + +// "src.WIDTH AS width, " + +// "src.FISHSPEED AS fishspeed, " + +// "src.DIRECTION AS direction, " + +// "src.TEMPERATURE AS temperature, " + +// "src.SPEED AS speed, " + +// "src.CHANNELNO AS channelno, " + +// "src.FCNT AS fcnt, " + +// "src.FIRSTIMGURL AS firstimgurl, " + +// "src.VIDEOURL AS videourl, " + +// "src.MWAY AS mway, " + +// "src.STRDT AS strdt, " + +// "src.ENDDT AS enddt, " + +// "src.STCODE AS stCode, " + +// "src.STNAME AS stName " + +// "FROM ( " + +// " SELECT t.ID AS ID, " + +// " t.STCD AS STCD, " + +// " fp.STNM AS STNM, " + +// " eng.BASE_ID AS BASEID, " + +// " hb.BASENAME AS BASENAME, " + +// " fp.RSTCD AS RSTCD, " + +// " eng.ENNM AS ENNM, " + +// " eng.HBRVCD AS HBRVCD, " + +// " NVL(hb.ORDER_INDEX, 999999) AS BASESTEPSORT, " + +// " NVL(hbrv.ORDER_INDEX, 999999) AS RVCDSTEPSORT, " + +// " NVL(fp.ORDER_INDEX, 999999) AS SITESTEPSORT, " + +// " NVL(eng.ORDER_INDEX, 999999) AS RSTCDSTEPSORT, " + +// " t.TM AS TM, " + +// " TO_CHAR(t.TM, 'YYYY') AS YR, " + +// " COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, fishDirect.NAME, t.FTP) AS FTP, " + +// " t.FTP AS FISHID, " + +// " t.FSZ AS FSZ, " + +// " TO_CHAR(t.LENGTH) AS LENGTH, " + +// " TO_CHAR(t.WIDTH) AS WIDTH, " + +// " TO_CHAR(t.FISHSPEED) AS FISHSPEED, " + +// " TO_CHAR(t.DIRECTION) AS DIRECTION, " + +// " TO_CHAR(t.TEMPERATURE) AS TEMPERATURE, " + +// " TO_CHAR(t.SPEED) AS SPEED, " + +// " t.CHANNELNO AS CHANNELNO, " + +// " TO_CHAR(t.FCNT) AS FCNT, " + +// " t.FIRSTIMGURL AS FIRSTIMGURL, " + +// " t.VIDEOURL AS VIDEOURL, " + +// " 2 AS MWAY, " + +// " CAST(NULL AS DATE) AS STRDT, " + +// " CAST(NULL AS DATE) AS ENDDT, " + +// " fp.STTP AS STCODE, " + +// " sttp.STTP_NAME AS STNAME " + +// " FROM SD_FPSSRL_AI_R t " + +// " INNER JOIN V_MS_STBPRP_T fp ON fp.STCD = t.STCD " + +// " LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = fp.STTP AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + +// " LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + +// " LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + +// " LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD " + +// " AND hbrv.BASEID = eng.BASE_ID " + +// " AND NVL(hbrv.IS_DELETED, 0) = 0 " + +// " AND NVL(hbrv.ENABLED, 1) = 1 " + +// " LEFT JOIN SD_FISHDICTORY_RLTN_B relRv ON relRv.FISH_ID = t.FTP " + +// " AND relRv.RVCD = eng.HBRVCD " + +// " AND NVL(relRv.IS_DELETED, 0) = 0 " + +// " LEFT JOIN SD_FISHDICTORY_B fishRv ON fishRv.ID = relRv.ZY_FISH_ID " + +// " AND NVL(fishRv.IS_DELETED, 0) = 0 " + +// " AND NVL(fishRv.ENABLE, 1) = 1 " + +// " LEFT JOIN SD_FISHDICTORY_RLTN_B relZy ON relZy.FISH_ID = t.FTP " + +// " AND relZy.RVCD = 'ZY' " + +// " AND NVL(relZy.IS_DELETED, 0) = 0 " + +// " LEFT JOIN SD_FISHDICTORY_B fishZy ON fishZy.ID = relZy.ZY_FISH_ID " + +// " AND NVL(fishZy.IS_DELETED, 0) = 0 " + +// " AND NVL(fishZy.ENABLE, 1) = 1 " + +// " LEFT JOIN SD_FISHDICTORY_B fishDirect ON fishDirect.ID = t.FTP " + +// " AND NVL(fishDirect.IS_DELETED, 0) = 0 " + +// " AND NVL(fishDirect.ENABLE, 1) = 1 " + +// " WHERE NVL(t.IS_DELETED, 0) = 0 " + +//// " UNION ALL " + +//// " SELECT t.ID AS ID, " + +//// " t.STCD AS STCD, " + +//// " fp.STNM AS STNM, " + +//// " eng.BASE_ID AS BASEID, " + +//// " hb.BASENAME AS BASENAME, " + +//// " fp.RSTCD AS RSTCD, " + +//// " eng.ENNM AS ENNM, " + +//// " eng.HBRVCD AS HBRVCD, " + +//// " NVL(hb.ORDER_INDEX, 999999) AS BASESTEPSORT, " + +//// " NVL(hbrv.ORDER_INDEX, 999999) AS RVCDSTEPSORT, " + +//// " NVL(fp.ORDER_INDEX, 999999) AS SITESTEPSORT, " + +//// " NVL(eng.ORDER_INDEX, 999999) AS RSTCDSTEPSORT, " + +//// " t.STRDT AS TM, " + +//// " TO_CHAR(t.STRDT, 'YYYY') AS YR, " + +//// " COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, fishDirect.NAME, t.FTP) AS FTP, " + +//// " t.FTP AS FISHID, " + +//// " t.FSZ AS FSZ, " + +//// " CAST(NULL AS VARCHAR2(50)) AS LENGTH, " + +//// " CAST(NULL AS VARCHAR2(50)) AS WIDTH, " + +//// " CAST(NULL AS VARCHAR2(50)) AS FISHSPEED, " + +//// " TO_CHAR(t.DIRECTION) AS DIRECTION, " + +//// " CAST(NULL AS VARCHAR2(50)) AS TEMPERATURE, " + +//// " CAST(NULL AS VARCHAR2(50)) AS SPEED, " + +//// " CAST(NULL AS VARCHAR2(100)) AS CHANNELNO, " + +//// " TO_CHAR(t.FCNT) AS FCNT, " + +//// " t.PICPTH AS FIRSTIMGURL, " + +//// " t.VDPTH AS VIDEOURL, " + +//// " 1 AS MWAY, " + +//// " t.STRDT AS STRDT, " + +//// " t.ENDDT AS ENDDT, " + +//// " fp.STTP AS STCODE, " + +//// " sttp.STTP_NAME AS STNAME " + +//// " FROM SD_FPSS_R t " + +//// " INNER JOIN SD_FPSS_B_H fp ON fp.STCD = t.STCD " + +//// " LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = fp.STTP AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + +//// " LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + +//// " LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + +//// " LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD " + +//// " AND hbrv.BASEID = eng.BASE_ID " + +//// " AND NVL(hbrv.IS_DELETED, 0) = 0 " + +//// " AND NVL(hbrv.ENABLED, 1) = 1 " + +//// " LEFT JOIN SD_FISHDICTORY_RLTN_B relRv ON relRv.FISH_ID = t.FTP " + +//// " AND relRv.RVCD = eng.HBRVCD " + +//// " AND NVL(relRv.IS_DELETED, 0) = 0 " + +//// " LEFT JOIN SD_FISHDICTORY_B fishRv ON fishRv.ID = relRv.ZY_FISH_ID " + +//// " AND NVL(fishRv.IS_DELETED, 0) = 0 " + +//// " AND NVL(fishRv.ENABLE, 1) = 1 " + +//// " LEFT JOIN SD_FISHDICTORY_RLTN_B relZy ON relZy.FISH_ID = t.FTP " + +//// " AND relZy.RVCD = 'ZY' " + +//// " AND NVL(relZy.IS_DELETED, 0) = 0 " + +//// " LEFT JOIN SD_FISHDICTORY_B fishZy ON fishZy.ID = relZy.ZY_FISH_ID " + +//// " AND NVL(fishZy.IS_DELETED, 0) = 0 " + +//// " AND NVL(fishZy.ENABLE, 1) = 1 " + +//// " LEFT JOIN SD_FISHDICTORY_B fishDirect ON fishDirect.ID = t.FTP " + +//// " AND NVL(fishDirect.IS_DELETED, 0) = 0 " + +//// " AND NVL(fishDirect.ENABLE, 1) = 1 " + +//// " WHERE NVL(t.IS_DELETED, 0) = 0 " + +//// " AND (t.TASK_STATUS = 'Approved' OR t.TASK_STATUS IS NULL) " + +// ") src"; +// } + private String buildQgcSdfpssrDetailSelectSql(List selectFields) { Map selectMap = new LinkedHashMap<>(); selectMap.put("stcd", "t.stcd AS stcd"); @@ -1966,6 +2075,68 @@ public class FpRunServiceImpl implements FpRunService { return String.join(", ", actualColumns); } + + private String buildQgcFpssrlDetailAISelectSql(List selectFields) { + Map selectMap = new LinkedHashMap<>(); + selectMap.put("id", "t.id AS id"); + selectMap.put("yr", "t.yr AS yr"); + selectMap.put("stcd", "t.stcd AS stcd"); + selectMap.put("stnm", "CASE WHEN t.stName IS NULL THEN t.stnm ELSE t.stName || t.stnm END AS stnm"); + selectMap.put("baseId", "t.baseId AS baseId"); + selectMap.put("baseName", "t.baseName AS baseName"); + selectMap.put("rstcd", "t.rstcd AS rstcd"); + selectMap.put("ennm", "t.ennm AS ennm"); + selectMap.put("isfs", "t.isfs AS isfs"); + selectMap.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + selectMap.put("baseStepSort", "t.baseStepSort AS baseStepSort"); + selectMap.put("rvcdStepSort", "t.rvcdStepSort AS rvcdStepSort"); + selectMap.put("siteStepSort", "t.siteStepSort AS siteStepSort"); + selectMap.put("rstcdStepSort", "t.rstcdStepSort AS rstcdStepSort"); + selectMap.put("tm", "t.tm AS tm"); + selectMap.put("ftp", "t.ftp AS ftp"); + selectMap.put("fishId", "t.fishId AS fishId"); + selectMap.put("fsz", "t.fsz AS fsz"); + selectMap.put("length", "t.length AS length"); + selectMap.put("width", "t.width AS width"); + selectMap.put("fishspeed", "t.fishspeed AS fishspeed"); + + selectMap.put("waterlevel", "t.waterlevel AS waterlevel"); + selectMap.put("fishposition", "t.fishposition AS fishposition"); + selectMap.put("dox", "t.dox AS dox"); + selectMap.put("q", "t.q AS q"); + selectMap.put("tu", "t.tu AS tu"); + selectMap.put("remark", "t.remark AS remark"); + + selectMap.put("direction", "t.direction AS direction"); + selectMap.put("directionName", "CASE t.direction WHEN '0' THEN '上行' WHEN '1' THEN '下行' WHEN '2' THEN '上行折返' WHEN '3' THEN '下行折返' END AS directionName"); + selectMap.put("temperature", "t.temperature AS temperature"); + selectMap.put("speed", "t.speed AS speed"); + selectMap.put("channelno", "t.channelno AS channelno"); + selectMap.put("fcnt", "t.fcnt AS fcnt"); + selectMap.put("firstimgurl", "t.firstimgurl AS firstimgurl"); + selectMap.put("videourl", "t.videourl AS videourl"); + selectMap.put("mway", "t.mway AS mway"); + selectMap.put("strdt", "t.strdt AS strdt"); + selectMap.put("enddt", "t.enddt AS enddt"); + selectMap.put("stCode", "t.stCode AS stCode"); + selectMap.put("stName", "t.stName AS stName"); + + if (CollUtil.isEmpty(selectFields)) { + return String.join(", ", selectMap.values()); + } + List actualColumns = new ArrayList<>(); + for (String field : selectFields) { + String column = selectMap.get(field); + if (StrUtil.isNotBlank(column)) { + actualColumns.add(column); + } + } + if (actualColumns.isEmpty()) { + actualColumns.addAll(selectMap.values()); + } + return String.join(", ", actualColumns); + } + private String buildQgcSdfpssrFilterCondition(DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { From 2e7b6d6650d1cf77563cfebf06e8f6a26ce791f9 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 19 Aug 2026 14:20:31 +0800 Subject: [PATCH 36/44] =?UTF-8?q?fix:=20=E8=BF=87=E9=B1=BC=E8=AE=BE?= =?UTF-8?q?=E6=96=BDAI=E8=87=AA=E5=8A=A8=E6=95=B0=E6=8D=AE=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdFpssrlAiRController.java | 16 +++---- .../platform/qgc_base/domain/SdFpssrlAiR.java | 43 +++++++++++++++++-- .../platform/qgc_base/domain/SdFpssrlR.java | 37 +++++++++++++++- .../service/impl/SdFpssrlAiRServiceImpl.java | 6 +-- .../service/impl/SdFpssrlRServiceImpl.java | 6 +-- 5 files changed, 90 insertions(+), 18 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlAiRController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlAiRController.java index 951a9772..a6389905 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlAiRController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlAiRController.java @@ -108,10 +108,10 @@ public class SdFpssrlAiRController { SdFpssrlAiR tempEntity = objectMapper.convertValue(engInfo, SdFpssrlAiR.class); applyUploadedFiles(tempEntity, picFiles, vdFiles); if (picFiles != null && !picFiles.isEmpty()) { - engInfo.put("firstimgurl", tempEntity.getFirstImgUrl()); + engInfo.put("firstimgurl", tempEntity.getFirstimgurl()); } if (vdFiles != null && !vdFiles.isEmpty()) { - engInfo.put("videourl", tempEntity.getVideoUrl()); + engInfo.put("videourl", tempEntity.getVideourl()); } boolean result = sdFpssrlAiRService.update(engInfo, request.getSource()); @@ -240,13 +240,13 @@ public class SdFpssrlAiRController { if (picFiles != null && !picFiles.isEmpty()) { List ids = attachmentUploadService.uploadMultipartFiles(picFiles); if (!ids.isEmpty()) { - entity.setFirstImgUrl(mergeIds(entity.getFirstImgUrl(), ids)); + entity.setFirstimgurl(mergeIds(entity.getFirstimgurl(), ids)); } } if (vdFiles != null && !vdFiles.isEmpty()) { List ids = attachmentUploadService.uploadMultipartFiles(vdFiles); if (!ids.isEmpty()) { - entity.setVideoUrl(mergeIds(entity.getVideoUrl(), ids)); + entity.setVideourl(mergeIds(entity.getVideourl(), ids)); } } } @@ -272,14 +272,14 @@ public class SdFpssrlAiRController { if (entity == null) { return ids; } - if (StrUtil.isNotBlank(entity.getFirstImgUrl())) { - Arrays.stream(entity.getFirstImgUrl().split(",")) + if (StrUtil.isNotBlank(entity.getFirstimgurl())) { + Arrays.stream(entity.getFirstimgurl().split(",")) .map(String::trim) .filter(StrUtil::isNotBlank) .forEach(ids::add); } - if (StrUtil.isNotBlank(entity.getVideoUrl())) { - Arrays.stream(entity.getVideoUrl().split(",")) + if (StrUtil.isNotBlank(entity.getVideourl())) { + Arrays.stream(entity.getVideourl().split(",")) .map(String::trim) .filter(StrUtil::isNotBlank) .forEach(ids::add); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java index 8fcd28b5..01fbf38a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java @@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.yfd.platform.annotation.FieldChinese; import lombok.Data; import java.io.Serializable; @@ -23,96 +25,131 @@ public class SdFpssrlAiR implements Serializable { /** 主键ID */ @TableId(type = IdType.ASSIGN_UUID) + @FieldChinese("主键ID") private String id; /** 过鱼设施编码 */ + @FieldChinese("过鱼设施编码") private String stcd; /** 时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @FieldChinese("时间") private Date tm; /** 鱼种类 */ + @FieldChinese("鱼种类") private String ftp; /** 过鱼数量 */ + @FieldChinese("过鱼数量") private Integer fcnt; /** 鱼尺寸:大/中/小 */ + @FieldChinese("鱼尺寸") private String fsz; /** 鱼长度 */ + @FieldChinese("鱼长度") private BigDecimal length; /** 鱼宽度 */ + @FieldChinese("鱼宽度") private BigDecimal width; /** 鱼速度 */ + @FieldChinese("鱼速度") private String fishspeed; /** 游向:0=上行 1=下行 */ + @FieldChinese("游向") private Integer direction; /** 鱼位置 */ + @FieldChinese("鱼位置") private Long fishposition; /** 鱼截图主图片url */ - private String firstImgUrl; + @FieldChinese("鱼截图主图片url") + private String firstimgurl; /** 鱼截图副图片url */ - private String secondImgUrl; + @FieldChinese("鱼截图副图片url") + private String secondimgurl; /** 视频url */ - private String videoUrl; + @FieldChinese("视频url") + private String videourl; /** 水温:单位:℃ */ + @FieldChinese("水温") private BigDecimal temperature; /** 水位:单位:m */ + @FieldChinese("水位") private BigDecimal waterlevel; /** 流速:单位:m/s */ + @FieldChinese("流速") private BigDecimal speed; /** 流量:单位:m3/s */ + @FieldChinese("流量") private BigDecimal q; /** 溶氧:单位:mg/L */ + @FieldChinese("溶氧") private BigDecimal dox; /** 浊度:单位:NTU */ + @FieldChinese("浊度") private Integer tu; /** 过鱼通道 */ + @FieldChinese("过鱼通道") private String channelno; /** AI盒子编码 */ + @FieldChinese("AI盒子编码") private String aiBoxCode; /** 创建人 */ + @FieldChinese("创建人") private String recordUser; /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @FieldChinese("创建时间") private Date recordTime; /** 更新人 */ + @FieldChinese("更新人") private String modifyUser; /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @FieldChinese("更新时间") private Date modifyTime; /** 是否已删除:0=未删除 1=已删除 */ + @FieldChinese("是否已删除") private Integer isDeleted; /** 删除人 */ + @FieldChinese("删除人") private String deleteUser; /** 删除时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @FieldChinese("删除时间") private Date deleteTime; /** 附件ID */ + @FieldChinese("附件ID") private String fid; /** 备注 */ + @FieldChinese("备注") private String remark; /** 鱼种类名称(非表字段,用于列表展示) */ diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlR.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlR.java index 23846a2a..27c1394c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlR.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlR.java @@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.yfd.platform.annotation.FieldChinese; import lombok.Data; import java.io.Serializable; @@ -25,155 +27,188 @@ public class SdFpssrlR implements Serializable { * 主键ID */ @TableId(type = IdType.ASSIGN_UUID) + @FieldChinese("主键ID") private String id; /** * 过鱼设施编码 */ + @FieldChinese("过鱼设施编码") private String stcd; /** * 时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @FieldChinese("时间") private Date tm; /** * 鱼种类 */ + @FieldChinese("鱼种类") private String ftp; /** * 过鱼数量 */ + @FieldChinese("过鱼数量") private Integer fcnt; /** * 鱼尺寸:大/中/小 */ + @FieldChinese("鱼尺寸") private String fsz; /** * 鱼长度 */ + @FieldChinese("鱼长度") private BigDecimal length; /** * 鱼宽度 */ + @FieldChinese("鱼宽度") private BigDecimal width; /** * 鱼速度 */ + @FieldChinese("鱼速度") private String fishspeed; /** * 游向:0=上行 1=下行 */ + @FieldChinese("游向") private Integer direction; /** * 鱼位置 */ + @FieldChinese("鱼位置") private Long fishposition; /** * 鱼截图主图片url */ @TableField("FIRSTIMGURL") + @FieldChinese("鱼截图主图片url") private String firstimgurl; - /** * 鱼截图副图片url */ @TableField("SECONDIMGURL") + @FieldChinese("鱼截图副图片url") private String secondimgurl; /** * 视频url */ @TableField("VIDEOURL") + @FieldChinese("视频url") private String videourl; /** * 水温:单位:℃ */ + @FieldChinese("水温") private BigDecimal temperature; /** * 水位:单位:m */ + @FieldChinese("水位") private BigDecimal waterlevel; /** * 流速:单位:m/s */ + @FieldChinese("流速") private BigDecimal speed; /** * 流量:单位:m3/s */ + @FieldChinese("流量") private BigDecimal q; /** * 溶氧:单位:mg/L */ + @FieldChinese("溶氧") private BigDecimal dox; /** * 浊度:单位:NTU */ + @FieldChinese("浊度") private Integer tu; /** * 过鱼通道 */ + @FieldChinese("过鱼通道") private String channelno; /** * 创建人:关联SYS_USER.ID */ + @FieldChinese("创建人") private String recordUser; /** * 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @FieldChinese("创建时间") private Date recordTime; /** * 更新人:关联SYS_USER.ID */ + @FieldChinese("更新人") private String modifyUser; /** * 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @FieldChinese("更新时间") private Date modifyTime; /** * 是否已删除:0=未删除 1=已删除 */ + @FieldChinese("是否已删除") private Integer isDeleted; /** * 删除人:关联SYS_USER.ID */ + @FieldChinese("删除人") private String deleteUser; /** * 删除时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @FieldChinese("删除时间") private Date deleteTime; /** * 附件ID */ + @FieldChinese("附件ID") private String fid; /** * 备注 */ + @FieldChinese("备注") private String remark; /** diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlAiRServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlAiRServiceImpl.java index b77f6b17..5ba4e514 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlAiRServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlAiRServiceImpl.java @@ -128,9 +128,9 @@ public class SdFpssrlAiRServiceImpl extends ServiceImpl Date: Wed, 19 Aug 2026 16:36:18 +0800 Subject: [PATCH 37/44] =?UTF-8?q?fix:=20=E6=B5=81=E9=87=8F=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eq/controller/EngEqDataController.java | 10 + .../qgc_eng/eq/service/EngEqDataService.java | 9 + .../eq/service/impl/EngEqDataServiceImpl.java | 570 ++++++++++++++++++ 3 files changed, 589 insertions(+) diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java index ea68c002..85651c10 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java @@ -1,9 +1,11 @@ package com.yfd.platform.qgc_eng.eq.controller; +import com.yfd.platform.annotation.Log; import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseVmsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; @@ -193,4 +195,12 @@ public class EngEqDataController { public ResponseResult getMsEngKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(engEqDataService.getMsEngKendoList(dataSourceRequest)); } + + @Log(module = "生态流量监测数据管理", value = "删除生态流量小时/日/月数据") + @PostMapping("/data/removeKendoByIds") + @Operation(summary = "删除生态流量小时/日/月数据") + public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) { + engEqDataService.removeKendoByIds(batchDeleteAo); + return ResponseResult.success(); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java index 54caab7b..16cd71d5 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java @@ -2,6 +2,7 @@ package com.yfd.platform.qgc_eng.eq.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_eng.eq.entity.vo.*; import java.util.List; @@ -76,4 +77,12 @@ public interface EngEqDataService { *

对应旧系统 EngEqController.getKendoListCust

*/ DataSourceResult getMsEngKendoList(DataSourceRequest dataSourceRequest); + + /** + * 批量删除生态流量小时/日/月数据 + *

删除小时数据后会按受影响站点重新聚合日表(SD_QECDAY_S)和月表(SD_QECDRTP_S)

+ * + * @param batchDeleteAo dataType: TIME=小时 DATE=日 MON=月;dataList: 删除数据列表 + */ + boolean removeKendoByIds(BatchDeleteAo batchDeleteAo); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index b7676e03..c75d6542 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -1,6 +1,7 @@ package com.yfd.platform.qgc_eng.eq.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.platform.common.DataSourceLoadOptionsBase; @@ -37,15 +38,26 @@ import com.yfd.platform.qgc_eng.eq.entity.vo.WbsbVo; import com.yfd.platform.qgc_eng.eq.entity.vo.StBaseInfo; import com.yfd.platform.qgc_eng.eq.entity.vo.StcdInfoVo; import com.yfd.platform.qgc_eng.eq.service.EngEqDataService; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; +import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; +import com.yfd.platform.qgc_base.entity.vo.DataParam; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; import com.yfd.platform.qgc_env.wq.entity.vo.MsWarnRuleDetailBVo; import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils; import com.yfd.platform.utils.QgcQueryWrapperUtil; +import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -67,6 +79,39 @@ public class EngEqDataServiceImpl implements EngEqDataService { @Resource private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + @Resource + private JdbcTemplate jdbcTemplate; + + private static final String QEC_HOUR_TABLE_NAME = "SD_QEC_R"; + private static final String QEC_DAY_TABLE_NAME = "SD_QECDAY_S"; + private static final String QEC_DRTP_TABLE_NAME = "SD_QECDRTP_S"; + + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + + private static final LinkedHashMap QEC_FIELD_MEANING_MAP = new LinkedHashMap<>(); + + static { + QEC_FIELD_MEANING_MAP.put("QEC", "生态流量"); + QEC_FIELD_MEANING_MAP.put("WATERFLOW", "AI识别生态流量值"); + QEC_FIELD_MEANING_MAP.put("TPQEC", "生态流量泄放方式"); + QEC_FIELD_MEANING_MAP.put("SFDB", "生态流量是否达标"); + QEC_FIELD_MEANING_MAP.put("MWR_SFDB", "生态流量是否达标(水利部)"); + QEC_FIELD_MEANING_MAP.put("AVQ_SFDB", "生态流量是否达标(多年平均)"); + QEC_FIELD_MEANING_MAP.put("QEC_LIMIT", "生态流量限值(环保部)"); + QEC_FIELD_MEANING_MAP.put("MWR_LIMIT", "生态流量限值(水利部)"); + QEC_FIELD_MEANING_MAP.put("AVQ_LIMIT", "生态流量限值(多年平均)"); + QEC_FIELD_MEANING_MAP.put("QEC_C", "生态流量限值系数(环保部)"); + QEC_FIELD_MEANING_MAP.put("MWR_C", "生态流量限值系数(水利部)"); + QEC_FIELD_MEANING_MAP.put("AVQ_C", "生态流量系数(多年平均)"); + QEC_FIELD_MEANING_MAP.put("QEC_RULE_DID", "环保部生态流量告警规则详情ID"); + QEC_FIELD_MEANING_MAP.put("QEC_MWRRULE_DID", "水利部生态流量告警规则详情ID"); + QEC_FIELD_MEANING_MAP.put("SHOW_FLAG", "数据显示类型"); + } + @Override public DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -6671,4 +6716,529 @@ public class EngEqDataServiceImpl implements EngEqDataService { return "tm".equalsIgnoreCase(field); } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeKendoByIds(BatchDeleteAo batchDeleteAo) { + List dataList = batchDeleteAo == null ? null : batchDeleteAo.getDataList(); + if (CollUtil.isEmpty(dataList)) { + return true; + } + String dataType = StrUtil.blankToDefault(batchDeleteAo.getDataType(), "").toUpperCase(); + String source = batchDeleteAo == null ? null : batchDeleteAo.getSource(); + int batchSize = 500; + for (int i = 0; i < dataList.size(); i += batchSize) { + List subList = dataList.subList(i, Math.min(i + batchSize, dataList.size())); + if ("MON".equals(dataType)) { + List> beforeRows = queryQecMonthRows(subList); + softDeleteQecDrtpData(subList); + recordQecDeleteLog(beforeRows, QEC_DRTP_TABLE_NAME, "删除生态流量月数据", source); + } + if ("DATE".equals(dataType)) { + List> beforeRows = queryQecDayRows(subList); + softDeleteQecDayData(subList); + recordQecDeleteLog(beforeRows, QEC_DAY_TABLE_NAME, "删除生态流量日数据", source); + } + if ("TIME".equals(dataType)) { + List> beforeRows = queryQecHourRows(subList); + deleteQecHourData(subList); + recordQecDeleteLog(beforeRows, QEC_HOUR_TABLE_NAME, "删除生态流量小时数据", source); + + Map dateRangeMap = new HashMap<>(); + Map monthRangeMap = new HashMap<>(); + for (DataParam param : subList) { + String stcd = param == null ? null : param.getId(); + String tm = param == null ? null : param.getTm(); + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm) || tm.length() < 10) { + continue; + } + String dateStr = tm.substring(0, 10); + dateRangeMap.compute(stcd, (key, range) -> { + if (range == null) { + return new String[]{dateStr, dateStr}; + } + if (dateStr.compareTo(range[0]) < 0) { + range[0] = dateStr; + } + if (dateStr.compareTo(range[1]) > 0) { + range[1] = dateStr; + } + return range; + }); + + String[] ym = tm.substring(0, 7).split("-"); + if (ym.length == 2) { + Integer year = Integer.parseInt(ym[0]); + Integer month = Integer.parseInt(ym[1]); + String monthStart = year + "-" + String.format("%02d", month) + "-01"; + String monthEnd = getMonthEndDate(year, month); + monthRangeMap.putIfAbsent(stcd + "_" + year + "_" + month, + new String[]{stcd, monthStart, monthEnd}); + } + } + + for (Map.Entry entry : dateRangeMap.entrySet()) { + statisticsQecDayDataFromHour(entry.getKey(), entry.getValue()[0], entry.getValue()[1]); + } + Set processedMonths = new HashSet<>(); + for (String[] values : monthRangeMap.values()) { + String monthKey = values[0] + "_" + values[1]; + if (processedMonths.add(monthKey)) { + statisticsQecMonthDataFromDay(values[0], values[1], values[2]); + } + } + } + } + return true; + } + + private void softDeleteQecDrtpData(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return; + } + StringBuilder sql = new StringBuilder("MERGE INTO SD_QECDRTP_S target USING ("); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" UNION ALL "); + } + sql.append("SELECT ? AS STCD, ? AS DRTP, ? AS YEAR, ? AS MONTH FROM DUAL"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDrtp()); + params.add(item == null ? null : item.getYear()); + params.add(item == null ? null : item.getMonth()); + } + sql.append(") source ON (target.STCD = source.STCD AND target.DRTP = source.DRTP ") + .append("AND target.YEAR = source.YEAR AND target.MONTH = source.MONTH) ") + .append("WHEN MATCHED THEN UPDATE SET target.IS_DELETED = 1, target.DELETE_TIME = SYSDATE"); + jdbcTemplate.update(sql.toString(), params.toArray()); + } + + private void softDeleteQecDayData(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return; + } + StringBuilder sql = new StringBuilder("MERGE INTO SD_QECDAY_S target USING ("); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" UNION ALL "); + } + sql.append("SELECT ? AS STCD, TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS') AS DT FROM DUAL"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDt()); + } + sql.append(") source ON (target.STCD = source.STCD AND target.DT = source.DT) ") + .append("WHEN MATCHED THEN UPDATE SET target.IS_DELETED = 1, target.DELETE_TIME = SYSDATE"); + jdbcTemplate.update(sql.toString(), params.toArray()); + } + + private void deleteQecHourData(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return; + } + StringBuilder sql = new StringBuilder("DELETE FROM SD_QEC_R WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getTm()); + } + jdbcTemplate.update(sql.toString(), params.toArray()); + } + + private void appendHourRowConditions(StringBuilder sql, List params, List dataParamList) { + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getTm()); + } + } + + private String buildQecHourLogSelectColumns() { + return "ID,STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, " + + "QEC, WATERFLOW, TPQEC, SFDB, MWR_SFDB, AVQ_SFDB, " + + "QEC_LIMIT, MWR_LIMIT, AVQ_LIMIT, QEC_C, MWR_C, AVQ_C, " + + "QEC_RULE_DID, QEC_MWRRULE_DID, SHOW_FLAG"; + } + + private String buildQecDayLogSelectColumns() { + return "ID,STCD, TO_CHAR(DT, 'YYYY-MM-DD HH24:MI:SS') AS DT, " + + "QEC, WATERFLOW, TPQEC, SFDB, MWR_SFDB, AVQ_SFDB, " + + "QEC_LIMIT, MWR_LIMIT, AVQ_LIMIT, QEC_C, MWR_C, AVQ_C, " + + "QEC_RULE_DID, QEC_MWRRULE_DID, SHOW_FLAG, IS_DELETED"; + } + + private String buildQecMonthLogSelectColumns() { + return "ID,STCD, DRTP, YEAR, MONTH, " + + "QEC, WATERFLOW, TPQEC, SFDB, MWR_SFDB, AVQ_SFDB, " + + "QEC_LIMIT, MWR_LIMIT, AVQ_LIMIT, QEC_C, MWR_C, AVQ_C, " + + "QEC_RULE_DID, QEC_MWRRULE_DID, SHOW_FLAG, IS_DELETED"; + } + + private List> queryQecHourRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildQecHourLogSelectColumns()) + .append(" FROM SD_QEC_R WHERE "); + List params = new ArrayList<>(); + appendHourRowConditions(sql, params, dataParamList); + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> queryQecDayRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildQecDayLogSelectColumns()) + .append(" FROM SD_QECDAY_S WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND DT = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDt()); + } + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> queryQecMonthRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildQecMonthLogSelectColumns()) + .append(" FROM SD_QECDRTP_S WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND DRTP = ? AND YEAR = ? AND MONTH = ?)"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDrtp()); + params.add(item == null ? null : item.getYear()); + params.add(item == null ? null : item.getMonth()); + } + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> normalizeLogRows(List> rows) { + List> result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + for (Map row : rows) { + result.add(normalizeLogRow(row)); + } + return result; + } + + private Map normalizeLogRow(Map row) { + Map normalized = new LinkedHashMap<>(); + if (row == null || row.isEmpty()) { + return normalized; + } + for (Map.Entry entry : row.entrySet()) { + normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue()); + } + return normalized; + } + + private void recordQecDeleteLog(List> rows, String tableName, String remark, String source) { + if (CollUtil.isEmpty(rows)) { + return; + } + List details = new ArrayList<>(); + for (Map row : rows) { + String stcd = asString(row.get("STCD")); + String recordId = asString(row.get("ID")); + MsOperationLog mainLog = buildQecMainLog(recordId, remark, source,"03"); + msOperationLogMapper.insert(mainLog); + for (Map.Entry entry : row.entrySet()) { + String fieldCode = entry.getKey(); + if (StrUtil.isBlank(fieldCode)) { + continue; + } + Object oldValue = entry.getValue(); + if (oldValue == null) { + continue; + } + details.add(buildQecDetail(mainLog.getId(), tableName, stcd, fieldCode, + oldValue, resolveQecDisplayValue(fieldCode, oldValue), + null, null, "删除字段值")); + } + } + batchInsertQecLogDetails(details); + } + + private MsOperationLog buildQecMainLog(String recordId, String remark, String source,String operationType) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveLogOperator()); + log.setOperationType(operationType); + log.setRecordId(recordId); + log.setOperateTime(new Date()); + log.setTableName(QEC_HOUR_TABLE_NAME); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildQecDetail(String mainId, + String tableName, + String stationCode, + String fieldCode, + Object oldValueCode, + Object oldValueName, + Object newValueCode, + Object newValueName, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(tableName); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(QEC_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatLogValue(oldValueCode)); + detail.setOldValueName(formatLogValue(oldValueName)); + detail.setNewValueCode(formatLogValue(newValueCode)); + detail.setNewValueName(formatLogValue(newValueName)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertQecLogDetails(List details) { + if (CollUtil.isEmpty(details)) { + return; + } + for (MsOperationLogDetail detail : details) { + if (detail == null) { + continue; + } + msOperationLogDetailMapper.insert(detail); + } + } + + private Object resolveQecDisplayValue(String fieldCode, Object rawValue) { + String text = formatLogValue(rawValue); + if (StrUtil.isBlank(text)) { + return rawValue; + } + return switch (fieldCode) { + case "SFDB", "MWR_SFDB", "AVQ_SFDB" -> { + Integer val = parseInteger(text); + yield val == null ? text : getQecSfdbName(val); + } + case "SHOW_FLAG" -> { + Integer val = parseInteger(text); + yield val == null ? text : getShowFlagName(val); + } + default -> text; + }; + } + + private String resolveLogOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String formatLogValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + + private Integer parseInteger(Object value) { + if (value == null) { + return null; + } + try { + return Integer.parseInt(String.valueOf(value)); + } catch (NumberFormatException e) { + return null; + } + } + + private String getQecSfdbName(Integer sfdb) { + if (sfdb == null) { + return null; + } + return switch (sfdb) { + case 0 -> "不达标"; + case 1 -> "达标"; + case 2 -> "无生态流量数据"; + case 3 -> "无生态流量限值要求"; + default -> null; + }; + } + + private String getShowFlagName(Integer showFlag) { + if (showFlag == null) { + return null; + } + return switch (showFlag) { + case 1 -> "环保部"; + case 2 -> "水利部"; + case 3 -> "多年平均"; + case 4 -> "无"; + default -> null; + }; + } + + private String getMonthEndDate(Integer year, Integer month) { + Calendar calendar = Calendar.getInstance(); + calendar.set(year, month - 1, 1); + int lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); + return year + "-" + String.format("%02d", month) + "-" + String.format("%02d", lastDay); + } + + /** + * 按站点+日期范围,用小时表(SD_QEC_R)重新聚合日表(SD_QECDAY_S) + *

当天小时数据已删空时,对应日表行被清除;否则按平均值重新聚合。

+ */ + private void statisticsQecDayDataFromHour(String stcd, String startDate, String endDate) { + String deleteSql = "DELETE FROM SD_QECDAY_S T " + + "WHERE T.STCD = ? " + + "AND T.DT BETWEEN TO_DATE(?, 'YYYY-MM-DD') " + + "AND TO_DATE(?, 'YYYY-MM-DD') " + + "AND NOT EXISTS ( " + + "SELECT 1 FROM SD_QEC_R S " + + "WHERE S.STCD = T.STCD " + + "AND TRUNC(S.TM) = T.DT " + + "AND S.TM >= TO_DATE(? || ' 00:00:00', 'YYYY-MM-DD HH24:MI:SS') " + + "AND S.TM <= TO_DATE(? || ' 23:59:59', 'YYYY-MM-DD HH24:MI:SS') " + + "AND S.IS_DELETED = 0)"; + jdbcTemplate.update(deleteSql, stcd, startDate, endDate, startDate, endDate); + + String mergeSql = "MERGE INTO SD_QECDAY_S T " + + "USING ( " + + " SELECT " + + " STCD, " + + " TRUNC(TM) AS DT, " + + " AVG(QEC) AS QEC, " + + " AVG(WATERFLOW) AS WATERFLOW, " + + " MIN(SFDB) AS SFDB, " + + " MIN(MWR_SFDB) AS MWR_SFDB, " + + " MIN(AVQ_SFDB) AS AVQ_SFDB " + + " FROM SD_QEC_R " + + " WHERE STCD = ? " + + " AND TM >= TO_DATE(? || ' 00:00:00', 'YYYY-MM-DD HH24:MI:SS') " + + " AND TM <= TO_DATE(? || ' 23:59:59', 'YYYY-MM-DD HH24:MI:SS') " + + " AND IS_DELETED = 0 " + + " GROUP BY STCD, TRUNC(TM) " + + ") S " + + "ON (T.STCD = S.STCD AND T.DT = S.DT) " + + "WHEN MATCHED THEN UPDATE SET " + + " T.QEC = S.QEC, " + + " T.WATERFLOW = S.WATERFLOW, " + + " T.SFDB = S.SFDB, " + + " T.MWR_SFDB = S.MWR_SFDB, " + + " T.AVQ_SFDB = S.AVQ_SFDB, " + + " T.IS_DELETED = 0, " + + " T.DELETE_USER = NULL, " + + " T.DELETE_TIME = NULL, " + + " T.MODIFY_USER = NULL, " + + " T.MODIFY_TIME = SYSDATE " + + "WHEN NOT MATCHED THEN INSERT ( " + + " ID, STCD, DT, QEC, WATERFLOW, SFDB, MWR_SFDB, AVQ_SFDB, " + + " RECORD_TIME, IS_DELETED " + + ") VALUES ( " + + " SYS_GUID(), S.STCD, S.DT, S.QEC, S.WATERFLOW, S.SFDB, S.MWR_SFDB, S.AVQ_SFDB, " + + " SYSDATE, 0 " + + ")"; + jdbcTemplate.update(mergeSql, stcd, startDate, endDate); + } + + /** + * 按站点+月份范围,用日表(SD_QECDAY_S)重新聚合循表月数据(SD_QECDRTP_S, DRTP='MON') + *

当月日数据已删空时,对应月数据行被清除;否则按平均值重新聚合。

+ */ + private void statisticsQecMonthDataFromDay(String stcd, String startDate, String endDate) { + Integer startYearInt = Integer.parseInt(startDate.substring(0, 4)); + Integer startMonthInt = Integer.parseInt(startDate.substring(5, 7)); + Integer endMonthInt = Integer.parseInt(endDate.substring(5, 7)); + + String deleteSql = "DELETE FROM SD_QECDRTP_S T " + + "WHERE T.DRTP = 'MON' " + + "AND T.STCD = ? " + + "AND T.YEAR = ? " + + "AND T.MONTH BETWEEN ? AND ? " + + "AND NOT EXISTS ( " + + " SELECT 1 FROM SD_QECDAY_S D " + + " WHERE D.STCD = T.STCD " + + " AND D.IS_DELETED = 0 " + + " AND EXTRACT(YEAR FROM D.DT) = T.YEAR " + + " AND EXTRACT(MONTH FROM D.DT) = T.MONTH " + + " AND D.DT >= TO_DATE(?, 'YYYY-MM-DD') " + + " AND D.DT < TO_DATE(?, 'YYYY-MM-DD') + 1)"; + jdbcTemplate.update(deleteSql, stcd, startYearInt, startMonthInt, endMonthInt, startDate, endDate); + + String mergeSql = "MERGE INTO SD_QECDRTP_S T " + + "USING ( " + + " SELECT " + + " STCD, " + + " EXTRACT(YEAR FROM DT) AS YEAR, " + + " EXTRACT(MONTH FROM DT) AS MONTH, " + + " 'MON' AS DRTP, " + + " AVG(QEC) AS QEC, " + + " AVG(WATERFLOW) AS WATERFLOW, " + + " MIN(SFDB) AS SFDB, " + + " MIN(MWR_SFDB) AS MWR_SFDB, " + + " MIN(AVQ_SFDB) AS AVQ_SFDB " + + " FROM SD_QECDAY_S " + + " WHERE STCD = ? " + + " AND DT >= TO_DATE(?, 'YYYY-MM-DD') " + + " AND DT < TO_DATE(?, 'YYYY-MM-DD') + 1 " + + " AND IS_DELETED = 0 " + + " GROUP BY STCD, EXTRACT(YEAR FROM DT), EXTRACT(MONTH FROM DT) " + + ") S " + + "ON (T.STCD = S.STCD AND T.DRTP = 'MON' AND T.YEAR = S.YEAR AND T.MONTH = S.MONTH) " + + "WHEN MATCHED THEN UPDATE SET " + + " T.QEC = S.QEC, " + + " T.WATERFLOW = S.WATERFLOW, " + + " T.SFDB = S.SFDB, " + + " T.MWR_SFDB = S.MWR_SFDB, " + + " T.AVQ_SFDB = S.AVQ_SFDB, " + + " T.IS_DELETED = 0, " + + " T.DELETE_TIME = NULL, " + + " T.MODIFY_TIME = SYSDATE " + + "WHEN NOT MATCHED THEN INSERT ( " + + " ID, STCD, DRTP, YEAR, MONTH, TM, QEC, WATERFLOW, SFDB, MWR_SFDB, AVQ_SFDB, " + + " RECORD_TIME, IS_DELETED " + + ") VALUES ( " + + " SYS_GUID(), S.STCD, 'MON', S.YEAR, S.MONTH, " + + " TO_DATE(S.YEAR || '-' || S.MONTH || '-01', 'YYYY-MM-DD'), " + + " S.QEC, S.WATERFLOW, S.SFDB, S.MWR_SFDB, S.AVQ_SFDB, " + + " SYSDATE, 0 " + + ")"; + jdbcTemplate.update(mergeSql, stcd, startDate, endDate); + } + } From 6cba0db4298f83b6861b9b96cf341d9b6aa99729 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 19 Aug 2026 17:04:40 +0800 Subject: [PATCH 38/44] =?UTF-8?q?fix:=20=E5=88=A0=E9=99=A4=E5=85=A8?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E9=B1=BC=E7=B1=BB=E6=94=BE=E9=B1=BC=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fb/controller/FbStationController.java | 10 + .../fb/entity/vo/FbFishRunQgcDeleteParam.java | 25 +++ .../qgc_env/fb/service/FbStationService.java | 7 + .../fb/service/impl/FbStationServiceImpl.java | 192 ++++++++++++++---- 4 files changed, 194 insertions(+), 40 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcDeleteParam.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java index 71aeb46f..35fab7a8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java @@ -1,9 +1,11 @@ package com.yfd.platform.qgc_env.fb.controller; +import com.yfd.platform.annotation.Log; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_env.fb.entity.vo.BreedStageVO; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishRunQgcDeleteParam; import com.yfd.platform.qgc_env.fb.service.FbStationService; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; @@ -212,6 +214,14 @@ public class FbStationController { return ResponseResult.successData(fbStationService.getFishRunQgcKendoListCust(dataSourceRequest)); } + @Log(module = "鱼类增殖站模块", value = "删除全过程鱼类放鱼数据") + @PostMapping("/fishrun/qgc/removeFishRunQgcData") + @Operation(summary = "删除全过程鱼类放鱼数据(按站点+年份+鱼种)") + public ResponseResult removeFishRunQgcData(@RequestBody List params) { + fbStationService.removeFishRunQgcData(params); + return ResponseResult.success(); + } + @PostMapping("/fishType/GetKendoListCust") @Operation(summary = "增殖站鱼种完成情况统计") public ResponseResult getFishTypeKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcDeleteParam.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcDeleteParam.java new file mode 100644 index 00000000..9c8a6058 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcDeleteParam.java @@ -0,0 +1,25 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 全过程鱼类放鱼数据删除参数(按 站点+年份+鱼种 维度删除) + */ +@Data +@Schema(description = "全过程鱼类放鱼数据删除参数") +public class FbFishRunQgcDeleteParam implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "电站站码") + private String stcd; + + @Schema(description = "放流年份 yyyy") + private String flyr; + + @Schema(description = "鱼种类:关联SD_FISHDICTORY_B.ID") + private String ftp; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index da2ef0e6..a4b5bc41 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -21,6 +21,13 @@ public interface FbStationService { DataSourceResult getFishRunQgcKendoListCust(DataSourceRequest dataSourceRequest); + /** + * 批量删除全过程鱼类放鱼数据(按 站点+年份+鱼种 维度逻辑删除 SD_RPIMNFISH_R 明细) + * + * @param params 删除参数列表(stcd + flyr + ftp) + */ + boolean removeFishRunQgcData(List params); + DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getFishTypeStcdList(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index 80f8b9b0..e49e5681 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -11,51 +11,19 @@ import com.yfd.platform.common.Group; import com.yfd.platform.common.GroupHelper; import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; -import com.yfd.platform.qgc_env.fb.entity.vo.BreedStageVO; -import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbBsdeathRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbBsctmoBVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFbbwtRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFbcwqRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbBsrfiRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbOutfishRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFishartinlRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFishhatchrecRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFishhatchproRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbScwemRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFishbreedRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFishdpacRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishHeadColumnVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishSummaryVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFishRunQgcVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeStcdVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFtpStatisticsVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbEngFishVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbMsfbrdmQgcVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbReleaseDirectionVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbResearchVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbStBaseInfoVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbStInfoResultVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbStationOverviewSecondVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbStationStaticsDataVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbStationStaticsRawVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FbTracingPointVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FishbreedRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.FishhatchrecRVo; -import com.yfd.platform.qgc_env.fb.entity.vo.HeadColunmsVo; -import com.yfd.platform.qgc_env.fb.entity.vo.TableVo; -import com.yfd.platform.qgc_env.fb.entity.vo.YearRpStatisticsVo; +import com.yfd.platform.qgc_env.fb.entity.vo.*; import com.yfd.platform.qgc_env.fb.service.FbStationService; import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; import com.yfd.platform.utils.QgcQueryWrapperUtil; +import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.math.BigDecimal; @@ -68,6 +36,33 @@ public class FbStationServiceImpl implements FbStationService { @Resource private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + @Resource + private JdbcTemplate jdbcTemplate; + + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + + private static final String FISH_RUN_DETAIL_TABLE_NAME = "SD_RPIMNFISH_R"; + + private static final Map FISH_RUN_FIELD_MEANING_MAP = new HashMap<>(); + + static { + FISH_RUN_FIELD_MEANING_MAP.put("FTP", "鱼种类"); + FISH_RUN_FIELD_MEANING_MAP.put("FSZ", "平均长度"); + FISH_RUN_FIELD_MEANING_MAP.put("FWET", "平均体重"); + FISH_RUN_FIELD_MEANING_MAP.put("FCNT", "计划放殖鱼数量"); + FISH_RUN_FIELD_MEANING_MAP.put("TAGTE", "标记类型"); + FISH_RUN_FIELD_MEANING_MAP.put("TAGCNT", "标记数量"); + FISH_RUN_FIELD_MEANING_MAP.put("FAGE", "鱼龄"); + FISH_RUN_FIELD_MEANING_MAP.put("FID", "鱼类档案ID"); + FISH_RUN_FIELD_MEANING_MAP.put("PROTECTLVL", "保护等级"); + FISH_RUN_FIELD_MEANING_MAP.put("FA", "亲本来源"); + FISH_RUN_FIELD_MEANING_MAP.put("REMARK", "备注"); + } + @Override public List getYearRpStatistics(String year) { Map paramMap = new HashMap<>(); @@ -200,6 +195,123 @@ public class FbStationServiceImpl implements FbStationService { return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeFishRunQgcData(List params) { + if (CollUtil.isEmpty(params)) { + return true; + } + Set processed = new HashSet<>(); + for (FbFishRunQgcDeleteParam param : params) { + if (param == null || StrUtil.isBlank(param.getStcd()) + || StrUtil.isBlank(param.getFlyr()) || StrUtil.isBlank(param.getFtp())) { + continue; + } + String key = param.getStcd() + "|" + param.getFlyr() + "|" + param.getFtp(); + if (!processed.add(key)) { + continue; + } + List> beforeRows = queryFishRunDetailRows(param); + int deleteCount = jdbcTemplate.update( + "UPDATE SD_RPIMNFISH_R det " + + "SET det.IS_DELETED = 1, det.DELETE_USER = ?, det.DELETE_TIME = SYSDATE " + + "WHERE NVL(det.IS_DELETED, 0) = 0 " + + " AND det.FTP = ? " + + " AND det.RPIMN_ID IN ( " + + " SELECT run.ID FROM SD_ENGFR_R run " + + " WHERE NVL(run.IS_DELETED, 0) = 0 " + + " AND run.STCD = ? " + + " AND TO_CHAR(run.TM, 'YYYY') = ? )", + resolveLogOperator(), param.getFtp(), param.getStcd(), param.getFlyr() + ); + recordFishRunDeleteLog(beforeRows, param, deleteCount); + } + return true; + } + + private List> queryFishRunDetailRows(FbFishRunQgcDeleteParam param) { + String sql = "SELECT det.ID, det.RPIMN_ID, det.FTP, det.FSZ, det.FWET, det.FCNT, " + + "det.TAGTE, det.TAGCNT, det.FAGE, det.FID, det.PROTECTLVL, det.FA, det.REMARK " + + "FROM SD_RPIMNFISH_R det " + + "INNER JOIN SD_ENGFR_R run ON det.RPIMN_ID = run.ID AND NVL(run.IS_DELETED, 0) = 0 " + + "WHERE NVL(det.IS_DELETED, 0) = 0 " + + " AND det.FTP = ? AND run.STCD = ? AND TO_CHAR(run.TM, 'YYYY') = ?"; + List> rows = jdbcTemplate.queryForList(sql, param.getFtp(), param.getStcd(), param.getFlyr()); + List> normalized = new ArrayList<>(); + for (Map row : rows) { + normalized.add(normalizeFishRunLogRow(row)); + } + return normalized; + } + + private Map normalizeFishRunLogRow(Map row) { + Map normalized = new LinkedHashMap<>(); + if (row == null || row.isEmpty()) { + return normalized; + } + for (Map.Entry entry : row.entrySet()) { + normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue()); + } + return normalized; + } + + private void recordFishRunDeleteLog(List> rows, FbFishRunQgcDeleteParam param, int deleteCount) { + if (CollUtil.isEmpty(rows)) { + return; + } + List details = new ArrayList<>(); + for (Map row : rows) { + MsOperationLog mainLog = new MsOperationLog(); + mainLog.setOperator(resolveLogOperator()); + mainLog.setRecordId(String.valueOf(row.get("ID"))); + mainLog.setOperateTime(new Date()); + mainLog.setTableName(FISH_RUN_DETAIL_TABLE_NAME); + mainLog.setRemark("删除全过程鱼类放鱼数据(站点:" + param.getStcd() + + ",年份:" + param.getFlyr() + ",删除条数:" + deleteCount + ")"); + msOperationLogMapper.insert(mainLog); + for (Map.Entry entry : row.entrySet()) { + if (StrUtil.isBlank(entry.getKey()) || entry.getValue() == null) { + continue; + } + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainLog.getId()); + detail.setTableName(FISH_RUN_DETAIL_TABLE_NAME); + detail.setStationCode(param.getStcd()); + detail.setFieldCode(entry.getKey()); + detail.setFieldMeaning(FISH_RUN_FIELD_MEANING_MAP.getOrDefault(entry.getKey(), entry.getKey())); + detail.setOldValueCode(formatFishRunLogValue(entry.getValue())); + detail.setOldValueName(formatFishRunLogValue(entry.getValue())); + detail.setRemark("删除字段值"); + details.add(detail); + } + } + for (MsOperationLogDetail detail : details) { + msOperationLogDetailMapper.insert(detail); + } + } + + private String resolveLogOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String formatFishRunLogValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + @Override public DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); From 40ceffcfd61675045e0e299ac04201c3dac4cf70 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 19 Aug 2026 18:27:04 +0800 Subject: [PATCH 39/44] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=94=9F?= =?UTF-8?q?=E6=80=81=E6=B5=81=E9=87=8F=E5=B0=8F=E6=97=B6=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eq/controller/EngEqDataController.java | 12 ++ .../eq/entity/vo/EqOperateRequest.java | 24 ++++ .../qgc_eng/eq/service/EngEqDataService.java | 9 ++ .../eq/service/impl/EngEqDataServiceImpl.java | 118 ++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EqOperateRequest.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java index 85651c10..99c4a929 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java @@ -16,6 +16,7 @@ import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqMsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRuleVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqVmsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRateCountVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EqOperateRequest; import com.yfd.platform.qgc_eng.eq.service.EngEqDataService; import com.yfd.platform.qgc_eng.eq.entity.vo.QgcQecStaticVo; import com.yfd.platform.qgc_eng.eq.entity.vo.StcdInfoVo; @@ -203,4 +204,15 @@ public class EngEqDataController { engEqDataService.removeKendoByIds(batchDeleteAo); return ResponseResult.success(); } + + @Log(module = "生态流量监测数据管理", value = "修改生态流量小时数据") + @PostMapping("/data/updateEqRsData") + @Operation(summary = "修改生态流量小时数据") + public ResponseResult updateEqRsData(@RequestBody EqOperateRequest eqOperateRequest) { + engEqDataService.updateQecRsData( + eqOperateRequest == null ? null : eqOperateRequest.getUpdateData(), + eqOperateRequest == null ? null : eqOperateRequest.getSource() + ); + return ResponseResult.success(); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EqOperateRequest.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EqOperateRequest.java new file mode 100644 index 00000000..7214d776 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EqOperateRequest.java @@ -0,0 +1,24 @@ +package com.yfd.platform.qgc_eng.eq.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Map; + +/** + * 生态流量数据操作请求 + *

updateData: 修改数据,其中 stcd/tm 为定位条件,其余 key 对应小时表可修改字段

+ */ +@Data +@Schema(description = "生态流量数据操作请求") +public class EqOperateRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "数据来源") + private String source; + + @Schema(description = "修改数据") + private Map updateData; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java index 16cd71d5..958e85e5 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java @@ -85,4 +85,13 @@ public interface EngEqDataService { * @param batchDeleteAo dataType: TIME=小时 DATE=日 MON=月;dataList: 删除数据列表 */ boolean removeKendoByIds(BatchDeleteAo batchDeleteAo); + + /** + * 修改生态流量小时数据 + *

修改后会按受影响站点重新聚合日表(SD_QECDAY_S)和月表(SD_QECDRTP_S)

+ * + * @param updateData 修改数据,stcd/tm 为定位条件,其余 key 对应小时表可修改字段 + * @param source 数据来源 + */ + boolean updateQecRsData(Map updateData, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index c75d6542..3a1b174b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -3,6 +3,7 @@ package com.yfd.platform.qgc_eng.eq.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; +import com.yfd.platform.common.exception.BizException; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; @@ -112,6 +113,26 @@ public class EngEqDataServiceImpl implements EngEqDataService { QEC_FIELD_MEANING_MAP.put("SHOW_FLAG", "数据显示类型"); } + private static final LinkedHashMap QEC_UPDATE_COLUMN_MAP = new LinkedHashMap<>(); + + static { + QEC_UPDATE_COLUMN_MAP.put("qec", "QEC"); + QEC_UPDATE_COLUMN_MAP.put("waterflow", "WATERFLOW"); + QEC_UPDATE_COLUMN_MAP.put("tpqec", "TPQEC"); + QEC_UPDATE_COLUMN_MAP.put("sfdb", "SFDB"); + QEC_UPDATE_COLUMN_MAP.put("mwrSfdb", "MWR_SFDB"); + QEC_UPDATE_COLUMN_MAP.put("avqSfdb", "AVQ_SFDB"); + QEC_UPDATE_COLUMN_MAP.put("qecLimit", "QEC_LIMIT"); + QEC_UPDATE_COLUMN_MAP.put("mwrLimit", "MWR_LIMIT"); + QEC_UPDATE_COLUMN_MAP.put("avqLimit", "AVQ_LIMIT"); + QEC_UPDATE_COLUMN_MAP.put("qecC", "QEC_C"); + QEC_UPDATE_COLUMN_MAP.put("mwrC", "MWR_C"); + QEC_UPDATE_COLUMN_MAP.put("avqC", "AVQ_C"); + QEC_UPDATE_COLUMN_MAP.put("qecRuleDid", "QEC_RULE_DID"); + QEC_UPDATE_COLUMN_MAP.put("qecMwrruleDid", "QEC_MWRRULE_DID"); + QEC_UPDATE_COLUMN_MAP.put("showFlag", "SHOW_FLAG"); + } + @Override public DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -6716,6 +6737,103 @@ public class EngEqDataServiceImpl implements EngEqDataService { return "tm".equalsIgnoreCase(field); } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateQecRsData(Map updateData, String source) { + if (updateData == null || updateData.isEmpty()) { + return true; + } + String stcd = asString(updateData.get("stcd")); + String tm = asString(updateData.get("tm")); + Map beforeHour = queryQecHourRow(stcd, tm); + updateQecHourData(updateData); + recordQecUpdateLog(beforeHour, updateData, source); + + if (StrUtil.isNotBlank(stcd) && StrUtil.isNotBlank(tm) && tm.length() >= 10) { + String dateStr = tm.substring(0, 10); + statisticsQecDayDataFromHour(stcd, dateStr, dateStr); + + String[] ym = dateStr.substring(0, 7).split("-"); + if (ym.length == 2) { + Integer year = Integer.parseInt(ym[0]); + Integer month = Integer.parseInt(ym[1]); + String startDate = year + "-" + String.format("%02d", month) + "-01"; + String endDate = getMonthEndDate(year, month); + statisticsQecMonthDataFromDay(stcd, startDate, endDate); + } + } + return true; + } + + private void updateQecHourData(Map updateData) { + List setClauses = new ArrayList<>(); + List params = new ArrayList<>(); + for (Map.Entry entry : QEC_UPDATE_COLUMN_MAP.entrySet()) { + if (updateData.containsKey(entry.getKey())) { + setClauses.add(entry.getValue() + " = ?"); + params.add(updateData.get(entry.getKey())); + } + } + if (setClauses.isEmpty()) { + return; + } + String stcd = asString(updateData.get("stcd")); + String tm = asString(updateData.get("tm")); + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm)) { + throw new BizException("站点编码和时间不能为空"); + } + String sql = "UPDATE SD_QEC_R SET " + String.join(", ", setClauses) + + " WHERE STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS')"; + params.add(stcd); + params.add(tm); + jdbcTemplate.update(sql, params.toArray()); + } + + private Map queryQecHourRow(String stcd, String tm) { + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm)) { + return new HashMap<>(); + } + String sql = "SELECT " + buildQecHourLogSelectColumns() + + " FROM SD_QEC_R WHERE STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS')"; + List> rows = jdbcTemplate.queryForList(sql, stcd, tm); + return rows.isEmpty() ? new HashMap<>() : normalizeLogRow(rows.get(0)); + } + + private void recordQecUpdateLog(Map beforeHour, + Map updateData, + String source) { + if (updateData == null || updateData.isEmpty()) { + return; + } + String stcd = asString(updateData.get("stcd")); + List details = new ArrayList<>(); + for (Map.Entry entry : QEC_UPDATE_COLUMN_MAP.entrySet()) { + if (!updateData.containsKey(entry.getKey())) { + continue; + } + String column = entry.getValue(); + Object oldValue = beforeHour == null ? null : beforeHour.get(column); + Object newValue = updateData.get(entry.getKey()); + if (StrUtil.equals(formatLogValue(oldValue), formatLogValue(newValue))) { + continue; + } + details.add(buildQecDetail(null, QEC_HOUR_TABLE_NAME, stcd, column, + oldValue, resolveQecDisplayValue(column, oldValue), + newValue, resolveQecDisplayValue(column, newValue), "修改字段值")); + } + if (details.isEmpty()) { + return; + } + String recordId = beforeHour != null && !beforeHour.isEmpty() + && beforeHour.get("ID") != null ? beforeHour.get("ID").toString() : null; + MsOperationLog mainLog = buildQecMainLog(recordId, "修改生态流量小时数据", source,"02"); + msOperationLogMapper.insert(mainLog); + for (MsOperationLogDetail detail : details) { + detail.setMainId(mainLog.getId()); + } + batchInsertQecLogDetails(details); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean removeKendoByIds(BatchDeleteAo batchDeleteAo) { From 5188d526ec4da19892bfdeedf45758f7c8ec0e51 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 19 Aug 2026 19:11:25 +0800 Subject: [PATCH 40/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/MsOperationLogServiceImpl.java | 1 + .../eq/service/impl/EngEqDataServiceImpl.java | 57 +++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java index 10b0858b..3f19b30e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -54,6 +54,7 @@ public class MsOperationLogServiceImpl extends ServiceImpl ENG_FIELD_MEANING_MAP = new LinkedHashMap<>(); diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index 3a1b174b..4df52a05 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -6796,7 +6796,36 @@ public class EngEqDataServiceImpl implements EngEqDataService { String sql = "SELECT " + buildQecHourLogSelectColumns() + " FROM SD_QEC_R WHERE STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS')"; List> rows = jdbcTemplate.queryForList(sql, stcd, tm); - return rows.isEmpty() ? new HashMap<>() : normalizeLogRow(rows.get(0)); + if (rows.isEmpty()) { + return new HashMap<>(); + } + // 数据库返回的列名默认全大写,转成驼峰 key 与前端参数保持一致 + return convertKeysToCamel(rows.get(0)); + } + + private Map convertKeysToCamel(Map row) { + Map camel = new LinkedHashMap<>(); + if (row == null || row.isEmpty()) { + return camel; + } + for (Map.Entry entry : row.entrySet()) { + camel.put(toCamelCase(entry.getKey()), entry.getValue()); + } + return camel; + } + + private String toCamelCase(String columnName) { + if (StrUtil.isBlank(columnName)) { + return columnName; + } + String[] parts = columnName.toLowerCase().split("_"); + StringBuilder sb = new StringBuilder(parts[0]); + for (int i = 1; i < parts.length; i++) { + if (!parts[i].isEmpty()) { + sb.append(Character.toUpperCase(parts[i].charAt(0))).append(parts[i].substring(1)); + } + } + return sb.toString(); } private void recordQecUpdateLog(Map beforeHour, @@ -6812,9 +6841,11 @@ public class EngEqDataServiceImpl implements EngEqDataService { continue; } String column = entry.getValue(); - Object oldValue = beforeHour == null ? null : beforeHour.get(column); + // beforeHour 已转为驼峰 key,与前端参数统一按驼峰取旧值 + Object oldValue = beforeHour == null ? null : beforeHour.get(entry.getKey()); Object newValue = updateData.get(entry.getKey()); - if (StrUtil.equals(formatLogValue(oldValue), formatLogValue(newValue))) { + // 数值类型按数值大小比较,忽略精度差异(133.0000 == 133.00) + if (sameLogValue(oldValue, newValue)) { continue; } details.add(buildQecDetail(null, QEC_HOUR_TABLE_NAME, stcd, column, @@ -6825,7 +6856,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { return; } String recordId = beforeHour != null && !beforeHour.isEmpty() - && beforeHour.get("ID") != null ? beforeHour.get("ID").toString() : null; + && beforeHour.get("id") != null ? beforeHour.get("id").toString() : null; MsOperationLog mainLog = buildQecMainLog(recordId, "修改生态流量小时数据", source,"02"); msOperationLogMapper.insert(mainLog); for (MsOperationLogDetail detail : details) { @@ -6834,6 +6865,24 @@ public class EngEqDataServiceImpl implements EngEqDataService { batchInsertQecLogDetails(details); } + private boolean sameLogValue(Object oldValue, Object newValue) { + if (oldValue == null && newValue == null) { + return true; + } + if (oldValue == null || newValue == null) { + return false; + } + // BigDecimal/Double 等数值类型按数值大小比较,忽略精度差异(133.0000 == 133.00) + if (oldValue instanceof Number && newValue instanceof Number) { + try { + return new BigDecimal(oldValue.toString()).compareTo(new BigDecimal(newValue.toString())) == 0; + } catch (NumberFormatException e) { + return false; + } + } + return StrUtil.equals(formatLogValue(oldValue), formatLogValue(newValue)); + } + @Override @Transactional(rollbackFor = Exception.class) public boolean removeKendoByIds(BatchDeleteAo batchDeleteAo) { From 50f23abbb916a9f1f85bac9ea87f45a7a746d028 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 19 Aug 2026 19:18:26 +0800 Subject: [PATCH 41/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/MsOperationLogServiceImpl.java | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java index 3f19b30e..ffc6a31f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -44,17 +44,41 @@ public class MsOperationLogServiceImpl extends ServiceImpl + * 若名称列不在本表,而在关联表中(如 SD_QEC_R 本身无站名,需通过 STCD + * 关联 SD_ENGINFO_B_H 查出 ENNM),使用 {@link #join} 配置关联表信息。 */ - private record TableNameConfig(String pkColumn, String nameColumn) {} + private record TableNameConfig(String pkColumn, String nameColumn, + String joinColumn, String joinTableName, String joinTableNameColumn) { + /** + * 名称列在本表中:直接配置主键列和名称列 + */ + static TableNameConfig self(String pkColumn, String nameColumn) { + return new TableNameConfig(pkColumn, nameColumn, null, null, null); + } + + /** + * 名称列在关联表中:本表 joinColumn 关联到关联表同名主键列,取关联表名称列 + * + * @param pkColumn 本表主键列(IN 查询条件) + * @param joinColumn 本表关联列(也是关联表主键列,如 STCD) + * @param joinTableName 关联表名(如 SD_ENGINFO_B_H) + * @param joinTableNameColumn 关联表名称列(如 ENNM) + */ + static TableNameConfig join(String pkColumn, String joinColumn, String joinTableName, String joinTableNameColumn) { + return new TableNameConfig(pkColumn, null, joinColumn, joinTableName, joinTableNameColumn); + } + } private static final Map TABLE_NAME_CONFIG_MAP = new HashMap<>(); static { // Engine Info: 名称列是 ENNM 而非 STNM - TABLE_NAME_CONFIG_MAP.put("SD_ENGINFO_B_H", new TableNameConfig("STCD", "ENNM")); + TABLE_NAME_CONFIG_MAP.put("SD_ENGINFO_B_H", TableNameConfig.self("STCD", "ENNM")); // Hydro Base: 主键列是 BASEID,名称列是 BASENAME - TABLE_NAME_CONFIG_MAP.put("SD_HYDROBASE", new TableNameConfig("BASEID", "BASENAME")); + TABLE_NAME_CONFIG_MAP.put("SD_HYDROBASE", TableNameConfig.self("BASEID", "BASENAME")); // Fish Dictionary: 需确认结构后配置 - TABLE_NAME_CONFIG_MAP.put("SD_FISHDICTORY_B", new TableNameConfig("ID", "NAME")); - TABLE_NAME_CONFIG_MAP.put("SD_QEC_R", new TableNameConfig("ID", "STCD")); + TABLE_NAME_CONFIG_MAP.put("SD_FISHDICTORY_B", TableNameConfig.self("ID", "NAME")); + // 生态流量小时表本身无站名,通过 STCD 关联 SD_ENGINFO_B_H 查询 ENNM + TABLE_NAME_CONFIG_MAP.put("SD_QEC_R", TableNameConfig.join("ID", "STCD", "V_MS_STBPRP_T", "ENNM")); } private static final Map ENG_FIELD_MEANING_MAP = new LinkedHashMap<>(); @@ -1010,10 +1034,22 @@ public class MsOperationLogServiceImpl extends ServiceImpl> results = microservicDynamicSQLMapper.getAllList(sql, paramMap); // 构建 pkVal → nameVal 映射 From f6a4172d1cf6549c36b4663cb7355ef32d6c2b26 Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 20 Aug 2026 08:29:14 +0800 Subject: [PATCH 42/44] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=86=99=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_base/service/impl/MsOperationLogServiceImpl.java | 9 +++++++++ .../qgc_env/wt/service/impl/SdWtvtRServiceImpl.java | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java index ffc6a31f..20ead32a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -79,6 +79,15 @@ public class MsOperationLogServiceImpl extends ServiceImpl ENG_FIELD_MEANING_MAP = new LinkedHashMap<>(); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtvtRServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtvtRServiceImpl.java index 7190ea51..810fdda9 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtvtRServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtvtRServiceImpl.java @@ -251,7 +251,7 @@ public class SdWtvtRServiceImpl extends ServiceImpl } batchUpdateWtvtRData(dataList); if (CollUtil.isNotEmpty(logDetails)) { - MsOperationLog mainLog = buildWtvtMainLog(null,"修改垂向水温数据", source); + MsOperationLog mainLog = buildWtvtMainLog( stcd,"修改垂向水温数据", source); msOperationLogMapper.insert(mainLog); for (MsOperationLogDetail detail : logDetails) { detail.setMainId(mainLog.getId()); @@ -511,7 +511,7 @@ public class SdWtvtRServiceImpl extends ServiceImpl log.setOperator(resolveWtvtLogOperator()); log.setOperateTime(new Date()); log.setTableName(WT_CX_TABLE_NAME); - log.setRecordId(remark); + log.setRecordId(recordId); log.setSource(StringUtils.trimToNull(source)); log.setRemark(remark); return log; From 0f98959722c4074fbd4c8986455b7707cac5c219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=85=B4=E5=87=AF?= <2448379534@qq.com> Date: Thu, 20 Aug 2026 09:03:31 +0800 Subject: [PATCH 43/44] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=AD=90=E7=B3=BB=E7=BB=9F-=E7=9B=91=E6=B5=8B=E6=95=B0?= =?UTF-8?q?=E6=8D=AE-=E9=99=A4=E4=BA=86=E9=B1=BC=E7=B1=BB=E6=94=BE?= =?UTF-8?q?=E9=B1=BC=E6=95=B0=E6=8D=AE=E7=9A=84=E9=A1=B5=E9=9D=A2=EF=BC=8C?= =?UTF-8?q?=E5=88=AB=E7=9A=84=E6=B7=BB=E5=8A=A0=E4=BA=86=E5=88=A0=E6=94=B9?= =?UTF-8?q?=EF=BC=8C=E6=89=B9=E9=87=8F=E5=88=A0=EF=BC=8C=E6=9F=A5=E7=9C=8B?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/DataQueryMenuModule/index.ts | 48 + .../src/components/BasicTable/index.vue | 17 +- .../FishData/EditFishDataAutoModal.vue | 4 +- .../monitorData/FishData/FishDataManual.vue | 456 ---------- .../monitorData/FishData/FishDataSearch.vue | 57 +- .../src/views/monitorData/FishData/index.vue | 722 ++++++++++++++- .../FishRelease/EditFishReleaseModal.vue | 28 + .../FishRelease/FishReleaseDetailModal.vue | 420 +++++++++ .../FishRelease/FishReleaseSearch.vue | 5 + .../views/monitorData/FishRelease/index.vue | 49 + .../FlowData/EditFlowDataModal.vue | 400 +++++++++ .../monitorData/FlowData/FlowDataSearch.vue | 29 +- .../src/views/monitorData/FlowData/index.vue | 157 +++- .../FlowStation/FlowStationSearch.vue | 29 +- .../views/monitorData/FlowStation/index.vue | 83 +- .../SurfaceTemp/SurfaceTempSearch.vue | 29 +- .../views/monitorData/SurfaceTemp/index.vue | 83 +- .../VerticalTemp/VerticalTempSearch.vue | 13 + .../views/monitorData/VerticalTemp/index.vue | 61 +- .../monitorData/WaterData/WaterDataSearch.vue | 29 +- .../src/views/monitorData/WaterData/index.vue | 85 +- .../EditFishSurveyDataModal.vue | 841 ++++++++++++++++++ .../fishSurveyData/fishSurveyDataSearch.vue | 300 +++++++ .../index.vue} | 118 ++- frontend-sjgl/src/views/system/user/index.vue | 33 +- frontend-sjtb/src/views/system/user/index.vue | 34 +- .../MapModal/components/BasicInfo.vue | 101 +-- frontend/src/components/MapModal/index.vue | 11 +- frontend/src/modules/Ysdwjc/index.vue | 1 - .../chuixiangshuiwenChangeMod/index.vue | 1 - ...eixingzuchengjijieruqingkuangTwoLayers.vue | 5 +- .../qixidiheduanjianceqingkuangEJ/index.vue | 1 - .../shuiwenjiancegongzuoEJ.vue | 1 - frontend/src/modules/waterQuality/index.vue | 368 ++------ .../monitorData/FishData/FishDataAuto.vue | 404 --------- .../monitorData/FishData/FishDataManual.vue | 369 -------- .../monitorData/FishData/FishDataSearch.vue | 19 +- .../components/monitorData/FishData/index.vue | 577 +++++++++++- frontend/src/views/system/user/index.vue | 28 +- 39 files changed, 4190 insertions(+), 1826 deletions(-) delete mode 100644 frontend-sjgl/src/views/monitorData/FishData/FishDataManual.vue create mode 100644 frontend-sjgl/src/views/monitorData/FishRelease/EditFishReleaseModal.vue create mode 100644 frontend-sjgl/src/views/monitorData/FishRelease/FishReleaseDetailModal.vue create mode 100644 frontend-sjgl/src/views/monitorData/FlowData/EditFlowDataModal.vue create mode 100644 frontend-sjgl/src/views/monitorData/fishSurveyData/EditFishSurveyDataModal.vue create mode 100644 frontend-sjgl/src/views/monitorData/fishSurveyData/fishSurveyDataSearch.vue rename frontend-sjgl/src/views/monitorData/{FishData/FishDataAuto.vue => fishSurveyData/index.vue} (80%) delete mode 100644 frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataAuto.vue delete mode 100644 frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataManual.vue diff --git a/frontend-sjgl/src/api/DataQueryMenuModule/index.ts b/frontend-sjgl/src/api/DataQueryMenuModule/index.ts index 63501e8d..cb4498e5 100644 --- a/frontend-sjgl/src/api/DataQueryMenuModule/index.ts +++ b/frontend-sjgl/src/api/DataQueryMenuModule/index.ts @@ -114,6 +114,24 @@ export function getFlowDataMonthList(data) { data }); } + +// 生态流量运行数据 - 删除 +export function deleteFlowDataInfo(data) { + return request({ + url: '/eq/data/removeKendoByIds', + method: 'post', + data + }); +} + +// 生态流量运行数据 - 修改 +export function updateEqRsData(data) { + return request({ + url: '/eq/data/updateEqRsData', + method: 'post', + data + }); +} // 水质监测数据 - 断面 export function getWaterDataSectionList(data) { return request({ @@ -331,6 +349,36 @@ export function deleteFpssrlRInfo(data) { }); } +// 过鱼设施AI自动数据 - 分页查询 +export function getFpssrlAiRPageList(data) { + return request({ + url: '/fp/query/qgc/GetKendoListCustAI', + method: 'post', + data + }); +} + +// 过鱼设施AI自动数据 - 编辑 +export function updateFpssrlAiRInfo(data) { + return request({ + url: '/base/fpssrlAiR/update', + method: 'post', + headers: { + 'Content-Type': 'multipart/form-data' + }, + data + }); +} + +// 过鱼设施AI自动数据 - 删除 +export function deleteFpssrlAiRInfo(data) { + return request({ + url: '/base/fpssrlAiR/delete', + method: 'post', + data + }); +} + // 鱼类 放鱼 export function getFishReleaseList(data) { return request({ diff --git a/frontend-sjgl/src/components/BasicTable/index.vue b/frontend-sjgl/src/components/BasicTable/index.vue index 716cc092..88ab0ae9 100644 --- a/frontend-sjgl/src/components/BasicTable/index.vue +++ b/frontend-sjgl/src/components/BasicTable/index.vue @@ -54,7 +54,7 @@ interface Props { data?: any[]; enableRowSelection?: boolean; enableRowHighlight?: boolean; // 是否启用行点击高亮 - rowKey?: string; + rowKey?: string | ((record: any) => string | number); searchParams?: Record; defaultPageSize?: number; isPage?: boolean; @@ -663,7 +663,20 @@ const enhancedColumns = computed(() => { title: String(text) }, { - default: () => String(text) + default: () => + h( + 'span', + { + style: { + display: 'inline-block', + maxWidth: '100%', + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap' + } + }, + String(text) + ) } ) ); diff --git a/frontend-sjgl/src/views/monitorData/FishData/EditFishDataAutoModal.vue b/frontend-sjgl/src/views/monitorData/FishData/EditFishDataAutoModal.vue index 7e1219bf..1b9bdd03 100644 --- a/frontend-sjgl/src/views/monitorData/FishData/EditFishDataAutoModal.vue +++ b/frontend-sjgl/src/views/monitorData/FishData/EditFishDataAutoModal.vue @@ -210,7 +210,7 @@ - + - + -
- - - - - - - - - -
- -
-
- - - -
- -
-
- - - - - - - - -
- - - - diff --git a/frontend-sjgl/src/views/monitorData/FishData/FishDataSearch.vue b/frontend-sjgl/src/views/monitorData/FishData/FishDataSearch.vue index f1312a13..c5de8cbd 100644 --- a/frontend-sjgl/src/views/monitorData/FishData/FishDataSearch.vue +++ b/frontend-sjgl/src/views/monitorData/FishData/FishDataSearch.vue @@ -57,8 +57,10 @@ @@ -77,8 +79,8 @@ const emit = defineEmits<{ (e: 'export-btn'): void; (e: 'reset', values: any): void; (e: 'search-finish', values: any): void; - (e: 'add'): void; (e: 'seeEdit'): void; + (e: 'batch-delete'): void; }>(); const basicSearchRef = ref(); @@ -86,13 +88,13 @@ const btnLoading = ref(false); const props = defineProps<{ exportLoading?: boolean; - mway: string; + selectedCount?: number; }>(); const initSearchData = { rvcd: 'all', rstcd: null, stcd: '0086601020VP000006', - mway: props.mway + mway: '1' }; const searchData = ref({ ...initSearchData }); @@ -140,6 +142,22 @@ const searchList: any = computed(() => [ value: item.stcd })) }, + { + type: 'Radio', + name: 'mway', + label: '数据类型', + width: 140, + options: [ + { + label: '人工', + value: '1' + }, + { + label: '自动', + value: '2' + } + ] + }, { type: 'custom', name: 'jcdt', @@ -157,15 +175,13 @@ const onSearchFinish = (values: any) => { const exportBtn = () => { emit('export-btn'); }; - -const handleAdd = () => { - emit('add'); -}; - const seeEdit = () => { emit('seeEdit'); }; -const initCrossSectionList = (params, setDefault = false) => { +const batchDelete = () => { + emit('batch-delete'); +}; +const initCrossSectionList = params => { const filters = []; if (params) { if (params.rvcd != '' && params.rvcd != 'all') { @@ -185,13 +201,6 @@ const initCrossSectionList = (params, setDefault = false) => { }); } } - // 根据人工/自动站过滤过鱼设施 - filters.push({ - field: 'mway', - operator: 'eq', - dataType: 'string', - value: props.mway - }); crossSectionListLoading.value = true; getFishReleaseMonitorSectionList({ filter: { @@ -202,15 +211,6 @@ const initCrossSectionList = (params, setDefault = false) => { }).then(res => { if (res.data?.data) { crossSectionList.value = res.data?.data; - // 首次加载时默认选中第一条过鱼设施 - if (setDefault && crossSectionList.value.length > 0) { - const firstStcd = crossSectionList.value[0].stcd; - initSearchData.stcd = firstStcd; - if (basicSearchRef.value?.formData) { - basicSearchRef.value.formData.stcd = firstStcd; - } - handleSearchFinish({ ...initSearchData, stcd: firstStcd }); - } } crossSectionListLoading.value = false; }); @@ -261,8 +261,9 @@ onMounted(() => { min: `${now.subtract(5, 'year').format('YYYY-MM-DD')} 00:00:00`, max: `${now.format('YYYY-MM-DD')} 23:59:59` }; - // 首次加载:请求设施列表后默认选中第一条并触发搜索 - initCrossSectionList(undefined, true); + initCrossSectionList(); + // 使用 handleSearchFinish 确保包含 jcdt 等完整参数 + handleSearchFinish({ ...initSearchData }); }); diff --git a/frontend-sjgl/src/views/monitorData/FishData/index.vue b/frontend-sjgl/src/views/monitorData/FishData/index.vue index 34aae4f5..4473c69a 100644 --- a/frontend-sjgl/src/views/monitorData/FishData/index.vue +++ b/frontend-sjgl/src/views/monitorData/FishData/index.vue @@ -1,22 +1,697 @@ - +} diff --git a/frontend-sjgl/src/views/monitorData/FishRelease/EditFishReleaseModal.vue b/frontend-sjgl/src/views/monitorData/FishRelease/EditFishReleaseModal.vue new file mode 100644 index 00000000..70a57045 --- /dev/null +++ b/frontend-sjgl/src/views/monitorData/FishRelease/EditFishReleaseModal.vue @@ -0,0 +1,28 @@ + + + diff --git a/frontend-sjgl/src/views/monitorData/FishRelease/FishReleaseDetailModal.vue b/frontend-sjgl/src/views/monitorData/FishRelease/FishReleaseDetailModal.vue new file mode 100644 index 00000000..e847e317 --- /dev/null +++ b/frontend-sjgl/src/views/monitorData/FishRelease/FishReleaseDetailModal.vue @@ -0,0 +1,420 @@ + + + diff --git a/frontend-sjgl/src/views/monitorData/FishRelease/FishReleaseSearch.vue b/frontend-sjgl/src/views/monitorData/FishRelease/FishReleaseSearch.vue index 53684e85..971248f4 100644 --- a/frontend-sjgl/src/views/monitorData/FishRelease/FishReleaseSearch.vue +++ b/frontend-sjgl/src/views/monitorData/FishRelease/FishReleaseSearch.vue @@ -59,6 +59,7 @@ @@ -97,6 +98,7 @@ const emit = defineEmits<{ (e: 'export-btn'): void; (e: 'reset', values: any): void; (e: 'search-finish', values: any): void; + (e: 'seeEdit'): void; }>(); const basicSearchRef = ref(); @@ -157,6 +159,9 @@ const onSearchFinish = (values: any) => { const exportBtn = () => { emit('export-btn'); }; +const seeEdit = () => { + emit('seeEdit'); +}; const onValuesChange = (changedValues: any, allValues: any) => { handleValuesChange(changedValues, allValues); diff --git a/frontend-sjgl/src/views/monitorData/FishRelease/index.vue b/frontend-sjgl/src/views/monitorData/FishRelease/index.vue index ff145756..f09d6eff 100644 --- a/frontend-sjgl/src/views/monitorData/FishRelease/index.vue +++ b/frontend-sjgl/src/views/monitorData/FishRelease/index.vue @@ -5,6 +5,7 @@ @export-btn="exportBtn" @search-finish="onSearchFinish" @reset="onReset" + @seeEdit="handleSeeEdit" :exportLoading="exportLoading" ref="searchRef" /> @@ -19,13 +20,36 @@ sort: sort }" > + + + + + + + diff --git a/frontend-sjgl/src/views/monitorData/FlowData/FlowDataSearch.vue b/frontend-sjgl/src/views/monitorData/FlowData/FlowDataSearch.vue index 01440908..56097142 100644 --- a/frontend-sjgl/src/views/monitorData/FlowData/FlowDataSearch.vue +++ b/frontend-sjgl/src/views/monitorData/FlowData/FlowDataSearch.vue @@ -63,6 +63,14 @@ @@ -78,13 +86,22 @@ const emit = defineEmits<{ (e: 'export-btn'): void; (e: 'reset', values: any): void; (e: 'search-finish', values: any): void; + (e: 'seeEdit'): void; + (e: 'batch-delete'): void; }>(); const basicSearchRef = ref(); const btnLoading = ref(false); -const props = defineProps<{ - exportLoading?: boolean; -}>(); +const props = withDefaults( + defineProps<{ + exportLoading?: boolean; + selectedCount?: number; + showBatchDelete?: boolean; + }>(), + { + showBatchDelete: true + } +); const initSearchData = { rvcd: 'all', @@ -185,6 +202,12 @@ const onSearchFinish = (values: any) => { const exportBtn = () => { emit('export-btn'); }; +const seeEdit = () => { + emit('seeEdit'); +}; +const batchDelete = () => { + emit('batch-delete'); +}; const onValuesChange = (changedValues: any, allValues: any) => { handleValuesChange(changedValues, allValues); diff --git a/frontend-sjgl/src/views/monitorData/FlowData/index.vue b/frontend-sjgl/src/views/monitorData/FlowData/index.vue index 0b30103f..be0c05cf 100644 --- a/frontend-sjgl/src/views/monitorData/FlowData/index.vue +++ b/frontend-sjgl/src/views/monitorData/FlowData/index.vue @@ -5,6 +5,10 @@ @export-btn="exportBtn" @search-finish="onSearchFinish" @reset="onReset" + @seeEdit="handleSeeEdit" + @batch-delete="handleBatchDelete" + :show-batch-delete="currentSearchParams.timeScale === 'tm'" + :selected-count="selectedRowKeys.length" :exportLoading="exportLoading" ref="searchRef" /> @@ -12,6 +16,7 @@ + + + + + + + + + + diff --git a/frontend-sjgl/src/views/monitorData/fishSurveyData/fishSurveyDataSearch.vue b/frontend-sjgl/src/views/monitorData/fishSurveyData/fishSurveyDataSearch.vue new file mode 100644 index 00000000..c09002b2 --- /dev/null +++ b/frontend-sjgl/src/views/monitorData/fishSurveyData/fishSurveyDataSearch.vue @@ -0,0 +1,300 @@ + + + + + diff --git a/frontend-sjgl/src/views/monitorData/FishData/FishDataAuto.vue b/frontend-sjgl/src/views/monitorData/fishSurveyData/index.vue similarity index 80% rename from frontend-sjgl/src/views/monitorData/FishData/FishDataAuto.vue rename to frontend-sjgl/src/views/monitorData/fishSurveyData/index.vue index 32ff0de2..3c91c891 100644 --- a/frontend-sjgl/src/views/monitorData/FishData/FishDataAuto.vue +++ b/frontend-sjgl/src/views/monitorData/fishSurveyData/index.vue @@ -1,25 +1,28 @@ diff --git a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataManual.vue b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataManual.vue deleted file mode 100644 index b69f5574..00000000 --- a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataManual.vue +++ /dev/null @@ -1,369 +0,0 @@ - - - - diff --git a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataSearch.vue b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataSearch.vue index de348c95..b33493e8 100644 --- a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataSearch.vue +++ b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/FishDataSearch.vue @@ -80,13 +80,12 @@ const btnLoading = ref(false); const props = defineProps<{ exportLoading?: boolean; - mway: string; }>(); const initSearchData = { rvcd: 'all', rstcd: null, stcd: '0086601020VP000006', - mway: props.mway + mway: '1' }; const searchData = ref({ ...initSearchData }); @@ -134,6 +133,22 @@ const searchList: any = computed(() => [ value: item.stcd })) }, + { + type: 'Radio', + name: 'mway', + label: '数据类型', + width: 140, + options: [ + { + label: '人工', + value: '1' + }, + { + label: '自动', + value: '2' + } + ] + }, { type: 'custom', name: 'jcdt', diff --git a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/index.vue b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/index.vue index 42facee3..421d1faa 100644 --- a/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/index.vue +++ b/frontend/src/views/DataQueryMenuModule/components/monitorData/FishData/index.vue @@ -1,42 +1,551 @@ - - + diff --git a/frontend/src/views/system/user/index.vue b/frontend/src/views/system/user/index.vue index 1dc3931d..10a2c004 100644 --- a/frontend/src/views/system/user/index.vue +++ b/frontend/src/views/system/user/index.vue @@ -47,6 +47,12 @@ const dialog = ref(false); const treeRef = ref(); const fishTreeRef = ref(); const infoForm = ref(); +//所属组织树型下拉框字段映射 +const treeSelectProps = { + value: 'id', + label: 'orgname', + children: 'childList' +}; //获取企业树形信息 const treeloading = ref(true); function getTree() { @@ -99,7 +105,8 @@ function addClick() { nickname: '', email: '', phone: '', - roleinfo: [] + roleinfo: [], + orgid: '' }; getrole(); } @@ -178,7 +185,8 @@ const info = ref({ nickname: '', email: '', phone: '', - roleinfo: [] as any[] + roleinfo: [] as any[], + orgid: '' }); //修改-用户 function editdepartment(row: any) { @@ -188,6 +196,8 @@ function editdepartment(row: any) { }); info.value = JSON.parse(JSON.stringify(row)); info.value.roleinfo = selectID; + // 回显所属组织 + info.value.orgid = row.orgid; rolesdata.value = row.roles; title.value = '修改用户'; dialogVisible.value = true; @@ -207,7 +217,8 @@ function confirmClick(formEl: any) { nickname: info.value.nickname, email: info.value.email, phone: info.value.phone, - orgid: orgId.value + // 修改时根据所属组织树型下拉框传递 + orgid: info.value.orgid }; const roleids = String(info.value.roleinfo); updataUser(params, roleids).then(() => { @@ -1274,6 +1285,17 @@ function handleClearSelection() { + + + + Date: Thu, 20 Aug 2026 09:23:32 +0800 Subject: [PATCH 44/44] =?UTF-8?q?=E9=A1=B5=E9=9D=A2debugger=E5=8E=BB?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MapModal/components/BasicInfo.vue | 2 - .../src/components/MapModal/index.vue | 1 - .../src/store/modules/shuJuTianBao.ts | 1 - .../shuiWenJianCe/index.vue | 1 - .../src/views/monitorData/Export/index.vue | 1 - .../src/views/monitorData/FlowData/index.vue | 1 - .../views/system/ConfigManagement/index.vue | 2 - .../system/TiltPhotoManagement/index.vue | 1 - .../components/RulesManagement/index.vue | 1 - frontend-sjgl/src/views/system/user/index.vue | 1 - .../src/components/BasicSearch/index.vue | 1 - frontend-sjtb/src/views/system/user/index.vue | 1 - .../MapModal/components/BasicInfo.vue | 1 - frontend/src/components/MapModal/index.vue | 3 +- .../src/components/SidePanelItem/index.vue | 1 - .../components/developStatusChart/index.vue | 484 +++++++++--------- frontend/src/modules/Ysdwjc/index.vue | 1 - .../alongFishMod/TwoLayers/Yanchengyulei.vue | 1 - .../DZChuiXiangShuiWenBianHua/index.vue | 1 - .../DZShuiDianZhanSPJK/index.vue | 4 +- .../ZXZWYYunXingShuJu/index.vue | 1 - .../ZenZhiZhanYunXingDetailModal.vue | 1 - .../ecologicalDataMod/index.vue | 1 - .../guoyuzongliang/index.vue | 4 +- .../powerStationReleasetaStistics/index.vue | 2 - ...eixingzuchengjijieruqingkuangTwoLayers.vue | 8 - .../SurveyQingKuang/DeviceTableModal.vue | 1 - .../TwoLayers/HuanbaoModTwoLayers.vue | 1 - .../shuizhijianceshuju.vue | 1 - .../modules/lushengshengtaijiance/index.vue | 1 - .../TwoLayer/STLLXFFS.vue | 1 - .../modules/shengtaidabiaoTwoMod/index.vue | 2 - .../TwoLayer/STLLXFFS.vue | 2 +- .../modules/shengtaidabiaoTwoModJJ/index.vue | 4 +- .../shuiShengShengTaiDiaoCha/index.vue | 3 +- .../TwoLayer/ShuiDianKaiFQKTwoLayer.vue | 2 +- .../shuishengshengtaijiance/SsstdcgkTk.vue | 1 - .../yunXingGaoJIng/Aisbdbyx/AISBTK.vue | 1 - .../ZengZhiZhanQingKuangTwoLayers.vue | 1 - .../zengZhiJiHuaWanChengQingKuang/index.vue | 3 - .../index.vue | 2 - frontend/src/store/modules/shuJuTianBao.ts | 1 - .../components/monitorData/Export/index.vue | 1 - .../components/DZShuiDianZhanSPJK.vue | 3 - .../ZenZhiZhanYunXingDetailModal.vue | 1 - .../powerStationReleasetaStistics.vue | 2 - .../shuiShengShengTaiDiaoCha/SSSTDCDB.vue | 1 - .../views/system/ConfigManagement/index.vue | 2 - .../system/TiltPhotoManagement/index.vue | 1 - .../ConfigManagement/ConfigManagementForm.vue | 6 +- .../RulesManagement/LayerManagementForm.vue | 1 - frontend/src/views/system/user/index.vue | 1 - 52 files changed, 259 insertions(+), 314 deletions(-) diff --git a/frontend-sjgl/src/components/MapModal/components/BasicInfo.vue b/frontend-sjgl/src/components/MapModal/components/BasicInfo.vue index b1ffe928..c0e14df1 100644 --- a/frontend-sjgl/src/components/MapModal/components/BasicInfo.vue +++ b/frontend-sjgl/src/components/MapModal/components/BasicInfo.vue @@ -359,7 +359,6 @@ const getData = async () => { try { if (props.url && modelStore.params.stcd) { let res: any = await getStcdDetail(props.url, modelStore.params.stcd); - // debugger if (res && res.code) { let data = res.data; data2.value = data; @@ -372,7 +371,6 @@ const getData = async () => { ? modelStore.params.sttp : modelStore.params.sttp) ).columns; - // debugger columns.forEach(item => { if (item.visible) { diff --git a/frontend-sjgl/src/components/MapModal/index.vue b/frontend-sjgl/src/components/MapModal/index.vue index 8773b3c1..8a450a22 100644 --- a/frontend-sjgl/src/components/MapModal/index.vue +++ b/frontend-sjgl/src/components/MapModal/index.vue @@ -529,7 +529,6 @@ const setQGCTabList = async (_tabs: any, stcd: string) => { // 2. 垂向水温 & AI 识别检查(对所有类型执行,与 React 一致) const res4 = await getStInfoByStcd({ stcd }); let newTabs = [...tabs]; - // debugger if (res4 && res4.data && res4.data.relList) { const relList = res4.data.relList; const jianCei = relList.find((item: any) => item.sttpCode === 'WTVT'); diff --git a/frontend-sjgl/src/store/modules/shuJuTianBao.ts b/frontend-sjgl/src/store/modules/shuJuTianBao.ts index b1cec9a7..d8f967eb 100644 --- a/frontend-sjgl/src/store/modules/shuJuTianBao.ts +++ b/frontend-sjgl/src/store/modules/shuJuTianBao.ts @@ -27,7 +27,6 @@ export const useShuJuTianBaoStore = defineStore('shuJuTianBao', () => { try { baseLoading.value = true; const res = await getBaseDropdown({}); - // debugger if (res.data && Array.isArray(res.data)) { const list = [...res.data]; // 直接赋值给 ref,触发响应式更新 diff --git a/frontend-sjgl/src/views/conventionalHydropower/shuiWenJianCe/index.vue b/frontend-sjgl/src/views/conventionalHydropower/shuiWenJianCe/index.vue index ff42f88d..038364e9 100644 --- a/frontend-sjgl/src/views/conventionalHydropower/shuiWenJianCe/index.vue +++ b/frontend-sjgl/src/views/conventionalHydropower/shuiWenJianCe/index.vue @@ -173,7 +173,6 @@ const tableScrollX = computed(() => ); const buildSearchParams = (values: any) => { - // debugger return { logic: 'and', filters: [ diff --git a/frontend-sjgl/src/views/monitorData/Export/index.vue b/frontend-sjgl/src/views/monitorData/Export/index.vue index d6801f4f..1af4598b 100644 --- a/frontend-sjgl/src/views/monitorData/Export/index.vue +++ b/frontend-sjgl/src/views/monitorData/Export/index.vue @@ -482,7 +482,6 @@ const getDict = async () => { let res = await getDictItemsByCode({ dictCode: 'dataField' }); dataFieldOption.value = res.data; formData.monitorElements = dataFieldOption.value.map(item => item.itemCode); - // debugger }; onMounted(() => { getDict(); diff --git a/frontend-sjgl/src/views/monitorData/FlowData/index.vue b/frontend-sjgl/src/views/monitorData/FlowData/index.vue index be0c05cf..ae13b7cf 100644 --- a/frontend-sjgl/src/views/monitorData/FlowData/index.vue +++ b/frontend-sjgl/src/views/monitorData/FlowData/index.vue @@ -441,7 +441,6 @@ const displayColumns = computed(() => { }); const onSearchFinish = async (values: any) => { - // debugger currentSearchParams.value = values; // 切换查询条件时清空选中 selectedRowKeys.value = []; diff --git a/frontend-sjgl/src/views/system/ConfigManagement/index.vue b/frontend-sjgl/src/views/system/ConfigManagement/index.vue index 72994059..c379c4e4 100644 --- a/frontend-sjgl/src/views/system/ConfigManagement/index.vue +++ b/frontend-sjgl/src/views/system/ConfigManagement/index.vue @@ -185,7 +185,6 @@ const handleEdit = async (record: any) => { const firstLevelNodes = data.filter((item: any) => !item.rstcd); const secondLevelNodes = data.filter((item: any) => item.rstcd); - // debugger const configNodes = firstLevelNodes.map((node: any, index: number) => { const children = secondLevelNodes.filter( (child: any) => child.rstcd === node.stcd @@ -216,7 +215,6 @@ const handleEdit = async (record: any) => { }); currentRecord.value.configNodes = configNodes; - // debugger } editModalVisible.value = true; }; diff --git a/frontend-sjgl/src/views/system/TiltPhotoManagement/index.vue b/frontend-sjgl/src/views/system/TiltPhotoManagement/index.vue index 98aa474e..f9f4b8f5 100644 --- a/frontend-sjgl/src/views/system/TiltPhotoManagement/index.vue +++ b/frontend-sjgl/src/views/system/TiltPhotoManagement/index.vue @@ -211,7 +211,6 @@ const editModalCancel = () => { // 表单提交 const handleEditSubmit = async (values: any) => { - // debugger try { let res = await saveTiltPhoto({ ...currentRecord.value, diff --git a/frontend-sjgl/src/views/system/alertRules/components/RulesManagement/index.vue b/frontend-sjgl/src/views/system/alertRules/components/RulesManagement/index.vue index 7d18ad1a..b85b3256 100644 --- a/frontend-sjgl/src/views/system/alertRules/components/RulesManagement/index.vue +++ b/frontend-sjgl/src/views/system/alertRules/components/RulesManagement/index.vue @@ -197,7 +197,6 @@ const editModalCancel = () => { // 表单提交 const handleEditSubmit = async (values: any) => { - // debugger try { // let res = await saveTiltPhoto({ // ...currentRecord.value, diff --git a/frontend-sjgl/src/views/system/user/index.vue b/frontend-sjgl/src/views/system/user/index.vue index 10a2c004..ad50a0a0 100644 --- a/frontend-sjgl/src/views/system/user/index.vue +++ b/frontend-sjgl/src/views/system/user/index.vue @@ -798,7 +798,6 @@ function getrole() { rolename: '' }; listGroupedByTenant(params).then(res => { - // debugger rolesdata.value = res; }); } diff --git a/frontend-sjtb/src/components/BasicSearch/index.vue b/frontend-sjtb/src/components/BasicSearch/index.vue index a28b9668..45e0780a 100644 --- a/frontend-sjtb/src/components/BasicSearch/index.vue +++ b/frontend-sjtb/src/components/BasicSearch/index.vue @@ -366,7 +366,6 @@ const lyChange = (value: any) => { formData.reachcd = value; formData.rstcd = ""; shuJuTianBaoStore.getEngOption(formData.reachcd); - // debugger // 【关键修改】手动触发 valuesChange,因为 a-form-item-rest 阻断了自动监听 triggerManualValuesChange("reachcd", formData.reachcd); }; diff --git a/frontend-sjtb/src/views/system/user/index.vue b/frontend-sjtb/src/views/system/user/index.vue index 10a2c004..ad50a0a0 100644 --- a/frontend-sjtb/src/views/system/user/index.vue +++ b/frontend-sjtb/src/views/system/user/index.vue @@ -798,7 +798,6 @@ function getrole() { rolename: '' }; listGroupedByTenant(params).then(res => { - // debugger rolesdata.value = res; }); } diff --git a/frontend/src/components/MapModal/components/BasicInfo.vue b/frontend/src/components/MapModal/components/BasicInfo.vue index 8a7bc5b7..9e2b5b5e 100644 --- a/frontend/src/components/MapModal/components/BasicInfo.vue +++ b/frontend/src/components/MapModal/components/BasicInfo.vue @@ -284,7 +284,6 @@ const getData = async () => { ? modelStore.params.sttp : modelStore.params.sttp) ).columns; - // debugger columns.forEach(item => { if (item.visible) { diff --git a/frontend/src/components/MapModal/index.vue b/frontend/src/components/MapModal/index.vue index 866ee90b..bcae9c12 100644 --- a/frontend/src/components/MapModal/index.vue +++ b/frontend/src/components/MapModal/index.vue @@ -348,7 +348,7 @@ const checkPowerStationTopicData = async (stcd: string) => { ] } }); - // debugger + hasPowerStatData.value = res?.data && res?.data?.length > 0; } catch (error) { console.error('查询电站专题配置失败:', error); @@ -518,7 +518,6 @@ const setQGCTabList = async (_tabs: any, stcd: string) => { // 2. 垂向水温 & AI 识别检查(对所有类型执行,与 React 一致) const res4 = await getStInfoByStcd({ stcd }); let newTabs = [...tabs]; - // debugger if (res4 && res4.data && res4.data.relList) { const relList = res4.data.relList; const jianCei = relList.find((item: any) => item.sttpCode === 'WTVT'); diff --git a/frontend/src/components/SidePanelItem/index.vue b/frontend/src/components/SidePanelItem/index.vue index 306bb6ae..6401f2fe 100644 --- a/frontend/src/components/SidePanelItem/index.vue +++ b/frontend/src/components/SidePanelItem/index.vue @@ -681,7 +681,6 @@ const handleTreeSelect = (selectedKeys: string | string[], info: any) => { } }; const handleTreeSelect1 = (selectedKeys: string | string[], info: any) => { - // debugger // 保存选中节点的额外属性(如 lgtd、lttd 等) if (info && typeof info === 'object') { selectedNodeExtra.value = { diff --git a/frontend/src/components/developStatusChart/index.vue b/frontend/src/components/developStatusChart/index.vue index 04767fc7..7b84beaa 100644 --- a/frontend/src/components/developStatusChart/index.vue +++ b/frontend/src/components/developStatusChart/index.vue @@ -1,25 +1,25 @@ diff --git a/frontend/src/modules/Ysdwjc/index.vue b/frontend/src/modules/Ysdwjc/index.vue index 6429dc1b..a5957ea5 100644 --- a/frontend/src/modules/Ysdwjc/index.vue +++ b/frontend/src/modules/Ysdwjc/index.vue @@ -251,7 +251,6 @@ const getStationList = async () => { ] }); const list = res?.data?.data ?? []; - // debugger if (list.length) { select.value.options = list.map((item: any) => ({ label: item.stnm, diff --git a/frontend/src/modules/alongFishMod/TwoLayers/Yanchengyulei.vue b/frontend/src/modules/alongFishMod/TwoLayers/Yanchengyulei.vue index 6b43cfe6..a5d6ba4e 100644 --- a/frontend/src/modules/alongFishMod/TwoLayers/Yanchengyulei.vue +++ b/frontend/src/modules/alongFishMod/TwoLayers/Yanchengyulei.vue @@ -486,7 +486,6 @@ const getTabNumData = async () => { const res = await getTabNum(params); // getTabNum 返回格式:res.data 直接是数组 [{ty, num}, ...] const data = res?.data?.data || []; - // debugger const list = TAB_CONFIG.map(item => ({ ...item, labelWithTooltip: renderTabLabel(item.label, item.prompt) diff --git a/frontend/src/modules/dianzhanzhuantiMod/DZChuiXiangShuiWenBianHua/index.vue b/frontend/src/modules/dianzhanzhuantiMod/DZChuiXiangShuiWenBianHua/index.vue index a32c026e..2bede8c7 100644 --- a/frontend/src/modules/dianzhanzhuantiMod/DZChuiXiangShuiWenBianHua/index.vue +++ b/frontend/src/modules/dianzhanzhuantiMod/DZChuiXiangShuiWenBianHua/index.vue @@ -369,7 +369,6 @@ const onUpdateValues = (payload: any) => { return; } // 年份选择 - // debugger if (payload?.datetime) { yearValue.value = dayjs(payload.datetime); } diff --git a/frontend/src/modules/dianzhanzhuantiMod/DZShuiDianZhanSPJK/index.vue b/frontend/src/modules/dianzhanzhuantiMod/DZShuiDianZhanSPJK/index.vue index 365c7fd0..ed4a9d2c 100644 --- a/frontend/src/modules/dianzhanzhuantiMod/DZShuiDianZhanSPJK/index.vue +++ b/frontend/src/modules/dianzhanzhuantiMod/DZShuiDianZhanSPJK/index.vue @@ -204,7 +204,7 @@ const handleSelectMedia = (item: any) => { type: 'video', src: item.flpth || item.src || '' }; - // debugger + }; // 打开更多视频弹窗 @@ -305,7 +305,6 @@ const fetchVideoData = async (stcd: string) => { }; const videoRes = await realTimeVideo(params1); const videoData = videoRes?.data?.data || videoRes?.data || []; - // debugger const videoItems: VideoItem[] = ( Array.isArray(videoData) ? videoData : [] ).map((item: any) => ({ @@ -323,7 +322,6 @@ const fetchVideoData = async (stcd: string) => { })); videoList.value = videoItems; - // debugger currentSlide.value = 0; scrollOffset.value = 0; } catch (error) { diff --git a/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/index.vue b/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/index.vue index 1e8fcc87..c36c55f7 100644 --- a/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/index.vue +++ b/frontend/src/modules/dianzhanzhuantiMod/ZXZWYYunXingShuJu/index.vue @@ -219,7 +219,6 @@ const fetchGardenList = async () => { const res = await getBotanicalGardenList(params); const list = res?.data?.data || []; - // debugger if (list.length === 0) return; const gardenMap = new Map(); diff --git a/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/ZenZhiZhanYunXingDetailModal.vue b/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/ZenZhiZhanYunXingDetailModal.vue index 094139f3..ff561583 100644 --- a/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/ZenZhiZhanYunXingDetailModal.vue +++ b/frontend/src/modules/dianzhanzhuantiMod/ZenZhiZhanYunXingPG/ZenZhiZhanYunXingDetailModal.vue @@ -232,7 +232,6 @@ const fetchFishDic = async () => { filter: { logic: 'and', filters: [] }, select: ['id', 'name'] }); - // debugger const data = res?.data?.data || []; fishDic.value = data.map((item: any) => ({ value: item.id, diff --git a/frontend/src/modules/dianzhanzhuantiMod/ecologicalDataMod/index.vue b/frontend/src/modules/dianzhanzhuantiMod/ecologicalDataMod/index.vue index dfaa913e..732eda9a 100644 --- a/frontend/src/modules/dianzhanzhuantiMod/ecologicalDataMod/index.vue +++ b/frontend/src/modules/dianzhanzhuantiMod/ecologicalDataMod/index.vue @@ -270,7 +270,6 @@ const fetchChartData = async () => { /** SidePanelItem @update-values */ const onUpdateValues = (payload: any) => { - // debugger if (payload?.datetime) { monthValue.value = dayjs(payload.datetime); } diff --git a/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/index.vue b/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/index.vue index a6274e2a..ebf1e915 100644 --- a/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/index.vue +++ b/frontend/src/modules/dianzhanzhuantiMod/guoyuzongliang/index.vue @@ -245,7 +245,7 @@ const fetchFacilityTree = async () => { const res = await getGuoYuZongLiangFacilityTree(params); const list = res?.data?.data ?? []; - // debugger + // 转换为 moreSelect 需要的 { title, value, children } 格式 const treeData = list.map((group: any) => ({ @@ -258,7 +258,7 @@ const fetchFacilityTree = async () => { })) })); facilityTree.value = treeData; - // debugger + if (list.length > 0) { // 取第一个有 stcdVo 的组的第一个子设施作为默认 const firstGroup = list.find((g: any) => g?.items?.some((v: any) => v?.stcd)); diff --git a/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/index.vue b/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/index.vue index c1d9292b..cae99740 100644 --- a/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/index.vue +++ b/frontend/src/modules/dianzhanzhuantiMod/powerStationReleasetaStistics/index.vue @@ -285,9 +285,7 @@ const fetchYear = () => { }; getPowerStationReleaseYear(params) .then((res: any) => { - // debugger const list = res?.data?.data?.[0] ?? []; - // debugger if (list.length > 0) { searchDate.value = dayjs(list[0].plansd); } else { diff --git a/frontend/src/modules/diwenshuijianhuansheshileixingzuchengjijieruqingkuang/TwoLayers/diwenshuijianhuansheshileixingzuchengjijieruqingkuangTwoLayers.vue b/frontend/src/modules/diwenshuijianhuansheshileixingzuchengjijieruqingkuang/TwoLayers/diwenshuijianhuansheshileixingzuchengjijieruqingkuangTwoLayers.vue index 00f1f1a0..ea85cfac 100644 --- a/frontend/src/modules/diwenshuijianhuansheshileixingzuchengjijieruqingkuang/TwoLayers/diwenshuijianhuansheshileixingzuchengjijieruqingkuangTwoLayers.vue +++ b/frontend/src/modules/diwenshuijianhuansheshileixingzuchengjijieruqingkuang/TwoLayers/diwenshuijianhuansheshileixingzuchengjijieruqingkuangTwoLayers.vue @@ -334,14 +334,6 @@ const fetchBuildStateList = async () => { value: item.itemCode })) buildStateList.value.unshift({ label: '全部', value: '' }) - // debugger - // 临时模拟数据(实际使用时删除) - // buildStateList.value = [ - // { label: '全部', value: '' }, - // { label: '未建', value: '0' }, - // { label: '在建', value: '1' }, - // { label: '已建', value: '2' } - // ] } catch (error) { console.error('获取建设状态列表失败:', error) } finally { diff --git a/frontend/src/modules/fishSurvey/SurveyQingKuang/DeviceTableModal.vue b/frontend/src/modules/fishSurvey/SurveyQingKuang/DeviceTableModal.vue index b9fb5571..bf977f43 100644 --- a/frontend/src/modules/fishSurvey/SurveyQingKuang/DeviceTableModal.vue +++ b/frontend/src/modules/fishSurvey/SurveyQingKuang/DeviceTableModal.vue @@ -115,7 +115,6 @@ const fishTypeOptions = ref([]); const fetchFishTypeList = async () => { try { const res = await sdFprdRgetFishInfo(); - // debugger if (res && res?.data) { fishTypeOptions.value = res.data.map((item: any) => ({ label: item, diff --git a/frontend/src/modules/huanbaoMod/TwoLayers/HuanbaoModTwoLayers.vue b/frontend/src/modules/huanbaoMod/TwoLayers/HuanbaoModTwoLayers.vue index d47071bc..76e11004 100644 --- a/frontend/src/modules/huanbaoMod/TwoLayers/HuanbaoModTwoLayers.vue +++ b/frontend/src/modules/huanbaoMod/TwoLayers/HuanbaoModTwoLayers.vue @@ -346,7 +346,6 @@ const handleViewDetail = (record: any, type: any) => { modelStore.modalVisible = true; modelStore.params = record; modelStore.params.sttp = record.sttpCode; - // debugger modelStore.title = record.stnm; modelStore.params.stcd = record.stcd; } diff --git a/frontend/src/modules/liuyu/yichangyujing/shuizhijiancegaojing/shuizhijianceshuju.vue b/frontend/src/modules/liuyu/yichangyujing/shuizhijiancegaojing/shuizhijianceshuju.vue index 75027bcd..df9aa56e 100644 --- a/frontend/src/modules/liuyu/yichangyujing/shuizhijiancegaojing/shuizhijianceshuju.vue +++ b/frontend/src/modules/liuyu/yichangyujing/shuizhijiancegaojing/shuizhijianceshuju.vue @@ -195,7 +195,6 @@ const getCardData = async () => { const res = await getShuizhiGaojingList(params); const list = res?.data?.data || []; - // debugger const result = { normal: 0, abnormal: 0, diff --git a/frontend/src/modules/lushengshengtaijiance/index.vue b/frontend/src/modules/lushengshengtaijiance/index.vue index 5ceffbf9..19780717 100644 --- a/frontend/src/modules/lushengshengtaijiance/index.vue +++ b/frontend/src/modules/lushengshengtaijiance/index.vue @@ -135,7 +135,6 @@ const handlePanelChange = (data: any) => { const handleCardClick = (facility: any) => { console.log('卡片被点击,准备打开弹框'); - // debugger currentOrderIndex.value = facility.orderInx; modalVisible.value = true; }; diff --git a/frontend/src/modules/shengtaidabiaoTwoMod/TwoLayer/STLLXFFS.vue b/frontend/src/modules/shengtaidabiaoTwoMod/TwoLayer/STLLXFFS.vue index 7b3acca6..7694f324 100644 --- a/frontend/src/modules/shengtaidabiaoTwoMod/TwoLayer/STLLXFFS.vue +++ b/frontend/src/modules/shengtaidabiaoTwoMod/TwoLayer/STLLXFFS.vue @@ -443,7 +443,6 @@ const fetchPieData = async () => { // TODO: 调用实际 API - 待补充接口 const res = await vmsstbprptGetKendoList1(obj); - // debugger if (res?.data?.data) { const dataSource = res.data.data.map((el: any) => ({ id: isAllBase ? el.baseId : el.hbrvcd, diff --git a/frontend/src/modules/shengtaidabiaoTwoMod/index.vue b/frontend/src/modules/shengtaidabiaoTwoMod/index.vue index cdf54d8b..fc8f2229 100644 --- a/frontend/src/modules/shengtaidabiaoTwoMod/index.vue +++ b/frontend/src/modules/shengtaidabiaoTwoMod/index.vue @@ -368,7 +368,6 @@ const getdate = (offsetYears = 0) => { // 提取日期部分(去除时间) startDate1 = formatDate(start); endDate1 = formatDate(end); - // debugger } else { // 否则使用默认的"一个月前到现在" const now = new Date(); @@ -595,7 +594,6 @@ watch( (newVal, oldVal) => { console.log('时间范围变化:', oldVal, '->', newVal); dateArr.value = newVal - // debugger loadData(); // 处理你的逻辑 }, diff --git a/frontend/src/modules/shengtaidabiaoTwoModJJ/TwoLayer/STLLXFFS.vue b/frontend/src/modules/shengtaidabiaoTwoModJJ/TwoLayer/STLLXFFS.vue index 053e8edb..6733d45a 100644 --- a/frontend/src/modules/shengtaidabiaoTwoModJJ/TwoLayer/STLLXFFS.vue +++ b/frontend/src/modules/shengtaidabiaoTwoModJJ/TwoLayer/STLLXFFS.vue @@ -443,7 +443,7 @@ const fetchPieData = async () => { // TODO: 调用实际 API - 待补充接口 const res = await vmsstbprptGetKendoList1(obj); - // debugger + if (res?.data?.data) { const dataSource = res.data.data.map((el: any) => ({ id: isAllBase ? el.baseId : el.hbrvcd, diff --git a/frontend/src/modules/shengtaidabiaoTwoModJJ/index.vue b/frontend/src/modules/shengtaidabiaoTwoModJJ/index.vue index bb397101..24814efe 100644 --- a/frontend/src/modules/shengtaidabiaoTwoModJJ/index.vue +++ b/frontend/src/modules/shengtaidabiaoTwoModJJ/index.vue @@ -370,7 +370,7 @@ const getdate = (offsetYears = 0) => { // 提取日期部分(去除时间) startDate1 = formatDate(start); endDate1 = formatDate(end); - // debugger + } else { // 否则使用默认的"一个月前到现在" const now = new Date(); @@ -597,7 +597,7 @@ watch( (newVal, oldVal) => { console.log('时间范围变化:', oldVal, '->', newVal); dateArr.value = newVal - // debugger + loadData(); // 处理你的逻辑 }, diff --git a/frontend/src/modules/shuiShengShengTaiDiaoCha/index.vue b/frontend/src/modules/shuiShengShengTaiDiaoCha/index.vue index 5d340902..8bdba26d 100644 --- a/frontend/src/modules/shuiShengShengTaiDiaoCha/index.vue +++ b/frontend/src/modules/shuiShengShengTaiDiaoCha/index.vue @@ -183,7 +183,7 @@ const getYearData = async () => { }; const res = await getDftYear(params); - // debugger + const data = res?.data?.data?.[0] || {}; if (Object.keys(data).length > 0) { @@ -260,7 +260,6 @@ const getChartData = async () => { }; const res = await getFishListStat(params); - // debugger chartData.value = res?.data?.data || []; nextTick(() => { updateChart(); diff --git a/frontend/src/modules/shuidianhuangjingjieruMod/TwoLayer/ShuiDianKaiFQKTwoLayer.vue b/frontend/src/modules/shuidianhuangjingjieruMod/TwoLayer/ShuiDianKaiFQKTwoLayer.vue index 27e605a1..b019e568 100644 --- a/frontend/src/modules/shuidianhuangjingjieruMod/TwoLayer/ShuiDianKaiFQKTwoLayer.vue +++ b/frontend/src/modules/shuidianhuangjingjieruMod/TwoLayer/ShuiDianKaiFQKTwoLayer.vue @@ -742,7 +742,7 @@ watch( const result = await fetchTabData(params); tabList.value = result; - // debugger + if (result.length > 0) { if (props.defaultTab) { diff --git a/frontend/src/modules/shuishengshengtaijiance/SsstdcgkTk.vue b/frontend/src/modules/shuishengshengtaijiance/SsstdcgkTk.vue index 0dda5882..549573d3 100644 --- a/frontend/src/modules/shuishengshengtaijiance/SsstdcgkTk.vue +++ b/frontend/src/modules/shuishengshengtaijiance/SsstdcgkTk.vue @@ -264,7 +264,6 @@ const getDcpcOptions = async () => { ]; const res = await getWeStaticsSecond( { filter: params, group }); - // debugger if (res?.data?.data?.length) { const options = res.data.data.map((item: any) => ({ diff --git a/frontend/src/modules/yunXingGaoJIng/Aisbdbyx/AISBTK.vue b/frontend/src/modules/yunXingGaoJIng/Aisbdbyx/AISBTK.vue index 86dac576..07e56470 100644 --- a/frontend/src/modules/yunXingGaoJIng/Aisbdbyx/AISBTK.vue +++ b/frontend/src/modules/yunXingGaoJIng/Aisbdbyx/AISBTK.vue @@ -1311,7 +1311,6 @@ const fetchVideoList = async () => { item => item.flpth !== '' || item.imgPath !== '' ); videoList.value = listMap; - // debugger // 默认选中第一条 if (listMap.length > 0 && !activeFid.value) { handleSelectMedia(listMap[0]); diff --git a/frontend/src/modules/zengZhiJiHuaWanChengQingKuang/TwoLayers/ZengZhiZhanQingKuangTwoLayers.vue b/frontend/src/modules/zengZhiJiHuaWanChengQingKuang/TwoLayers/ZengZhiZhanQingKuangTwoLayers.vue index cb8f0849..e2390d37 100644 --- a/frontend/src/modules/zengZhiJiHuaWanChengQingKuang/TwoLayers/ZengZhiZhanQingKuangTwoLayers.vue +++ b/frontend/src/modules/zengZhiJiHuaWanChengQingKuang/TwoLayers/ZengZhiZhanQingKuangTwoLayers.vue @@ -497,7 +497,6 @@ const handleViewDetail = (record: any, type: any) => { modelStore.params.sttp = 'FB'; modelStore.filter.year = years.value; } else { - // debugger modelStore.modalVisible = true; modelStore.params.sttp = 'ENG'; modelStore.title = record.name; diff --git a/frontend/src/modules/zengZhiJiHuaWanChengQingKuang/index.vue b/frontend/src/modules/zengZhiJiHuaWanChengQingKuang/index.vue index 221a2c68..94570dfc 100644 --- a/frontend/src/modules/zengZhiJiHuaWanChengQingKuang/index.vue +++ b/frontend/src/modules/zengZhiJiHuaWanChengQingKuang/index.vue @@ -445,7 +445,6 @@ const getSelectData = async () => { select.value.value = select.value.options[0].value; // 获取完站点列表后,立即获取图表数据 getEcharts(); - // debugger; }; const getEcharts = async () => { loading.value = true; @@ -524,7 +523,6 @@ const getEcharts = async () => { // 判断是否有数据 noData.value = wangCheng.value.length === 0 && zhongLei.value.length === 0; console.log('图表数据:', noData.value); - // debugger; // 只有有数据时才渲染图表 if (!noData.value) { updateChart(); @@ -560,7 +558,6 @@ onUnmounted(() => { //监听子组件的数据变化 const handlePanelChange1 = async data => { console.log('当前所有控件状态:', data); - // debugger; // 当选择器或日期变化时,重新加载图表数据 if (data.datetime && data.select) { await (datetimePicker.value.value = data.datetime); diff --git a/frontend/src/modules/zengzhizhanjiansheyunxing/WholeValuedStationOverviewDetail/index.vue b/frontend/src/modules/zengzhizhanjiansheyunxing/WholeValuedStationOverviewDetail/index.vue index 4fb71fe7..af611e40 100644 --- a/frontend/src/modules/zengzhizhanjiansheyunxing/WholeValuedStationOverviewDetail/index.vue +++ b/frontend/src/modules/zengzhizhanjiansheyunxing/WholeValuedStationOverviewDetail/index.vue @@ -199,7 +199,6 @@ const customTransform = (res: any) => { // ==================== 搜索与重置 ==================== const handleSearch = () => { - // debugger; const filter = getFilter(); tableRef.value?.getList(filter); }; @@ -212,7 +211,6 @@ const handleReset = () => { // 查看详情 const handleViewDetail = (record: any) => { -// debugger; modelStore.modalVisible = true; modelStore.params = record; modelStore.title = record.stnm; diff --git a/frontend/src/store/modules/shuJuTianBao.ts b/frontend/src/store/modules/shuJuTianBao.ts index b1cec9a7..d8f967eb 100644 --- a/frontend/src/store/modules/shuJuTianBao.ts +++ b/frontend/src/store/modules/shuJuTianBao.ts @@ -27,7 +27,6 @@ export const useShuJuTianBaoStore = defineStore('shuJuTianBao', () => { try { baseLoading.value = true; const res = await getBaseDropdown({}); - // debugger if (res.data && Array.isArray(res.data)) { const list = [...res.data]; // 直接赋值给 ref,触发响应式更新 diff --git a/frontend/src/views/DataQueryMenuModule/components/monitorData/Export/index.vue b/frontend/src/views/DataQueryMenuModule/components/monitorData/Export/index.vue index f68890f2..9cf4ad31 100644 --- a/frontend/src/views/DataQueryMenuModule/components/monitorData/Export/index.vue +++ b/frontend/src/views/DataQueryMenuModule/components/monitorData/Export/index.vue @@ -482,7 +482,6 @@ const getDict = async () => { let res = await getDictItemsByCode({ dictCode: 'dataField' }); dataFieldOption.value = res.data; formData.monitorElements = dataFieldOption.value.map(item => item.itemCode); - // debugger }; onMounted(() => { getDict(); diff --git a/frontend/src/views/dianZhanZhuanTi/components/DZShuiDianZhanSPJK.vue b/frontend/src/views/dianZhanZhuanTi/components/DZShuiDianZhanSPJK.vue index 365c7fd0..2e968c0e 100644 --- a/frontend/src/views/dianZhanZhuanTi/components/DZShuiDianZhanSPJK.vue +++ b/frontend/src/views/dianZhanZhuanTi/components/DZShuiDianZhanSPJK.vue @@ -204,7 +204,6 @@ const handleSelectMedia = (item: any) => { type: 'video', src: item.flpth || item.src || '' }; - // debugger }; // 打开更多视频弹窗 @@ -305,7 +304,6 @@ const fetchVideoData = async (stcd: string) => { }; const videoRes = await realTimeVideo(params1); const videoData = videoRes?.data?.data || videoRes?.data || []; - // debugger const videoItems: VideoItem[] = ( Array.isArray(videoData) ? videoData : [] ).map((item: any) => ({ @@ -323,7 +321,6 @@ const fetchVideoData = async (stcd: string) => { })); videoList.value = videoItems; - // debugger currentSlide.value = 0; scrollOffset.value = 0; } catch (error) { diff --git a/frontend/src/views/dianZhanZhuanTi/components/ZenZhiZhanYunXingDetailModal.vue b/frontend/src/views/dianZhanZhuanTi/components/ZenZhiZhanYunXingDetailModal.vue index 094139f3..ff561583 100644 --- a/frontend/src/views/dianZhanZhuanTi/components/ZenZhiZhanYunXingDetailModal.vue +++ b/frontend/src/views/dianZhanZhuanTi/components/ZenZhiZhanYunXingDetailModal.vue @@ -232,7 +232,6 @@ const fetchFishDic = async () => { filter: { logic: 'and', filters: [] }, select: ['id', 'name'] }); - // debugger const data = res?.data?.data || []; fishDic.value = data.map((item: any) => ({ value: item.id, diff --git a/frontend/src/views/dianZhanZhuanTi/components/powerStationReleasetaStistics.vue b/frontend/src/views/dianZhanZhuanTi/components/powerStationReleasetaStistics.vue index ca80441b..32afa9c9 100644 --- a/frontend/src/views/dianZhanZhuanTi/components/powerStationReleasetaStistics.vue +++ b/frontend/src/views/dianZhanZhuanTi/components/powerStationReleasetaStistics.vue @@ -285,9 +285,7 @@ const fetchYear = () => { }; getPowerStationReleaseYear(params) .then((res: any) => { - // debugger const list = res?.data?.data?.[0] ?? []; - // debugger if (list.length > 0) { searchDate.value = dayjs(list[0].plansd); } else { diff --git a/frontend/src/views/shengTaiDiaoCha/shuiShengShengTaiDiaoCha/SSSTDCDB.vue b/frontend/src/views/shengTaiDiaoCha/shuiShengShengTaiDiaoCha/SSSTDCDB.vue index 85d16a9a..abd2603c 100644 --- a/frontend/src/views/shengTaiDiaoCha/shuiShengShengTaiDiaoCha/SSSTDCDB.vue +++ b/frontend/src/views/shengTaiDiaoCha/shuiShengShengTaiDiaoCha/SSSTDCDB.vue @@ -190,7 +190,6 @@ const fetchChartData = async () => { } }; const res: any = await getCompareBar(params); - // debugger if (res?.data?.data?.[0]?.dataSource) { chartList.value = res.data.data[0].dataSource; } else { diff --git a/frontend/src/views/system/ConfigManagement/index.vue b/frontend/src/views/system/ConfigManagement/index.vue index 72994059..c379c4e4 100644 --- a/frontend/src/views/system/ConfigManagement/index.vue +++ b/frontend/src/views/system/ConfigManagement/index.vue @@ -185,7 +185,6 @@ const handleEdit = async (record: any) => { const firstLevelNodes = data.filter((item: any) => !item.rstcd); const secondLevelNodes = data.filter((item: any) => item.rstcd); - // debugger const configNodes = firstLevelNodes.map((node: any, index: number) => { const children = secondLevelNodes.filter( (child: any) => child.rstcd === node.stcd @@ -216,7 +215,6 @@ const handleEdit = async (record: any) => { }); currentRecord.value.configNodes = configNodes; - // debugger } editModalVisible.value = true; }; diff --git a/frontend/src/views/system/TiltPhotoManagement/index.vue b/frontend/src/views/system/TiltPhotoManagement/index.vue index d16c9d08..f86b8280 100644 --- a/frontend/src/views/system/TiltPhotoManagement/index.vue +++ b/frontend/src/views/system/TiltPhotoManagement/index.vue @@ -211,7 +211,6 @@ const editModalCancel = () => { // 表单提交 const handleEditSubmit = async (values: any) => { - // debugger try { let res = await saveTiltPhoto({ ...currentRecord.value, diff --git a/frontend/src/views/system/alertRules/components/ConfigManagement/ConfigManagementForm.vue b/frontend/src/views/system/alertRules/components/ConfigManagement/ConfigManagementForm.vue index a194ffde..df68fc2a 100644 --- a/frontend/src/views/system/alertRules/components/ConfigManagement/ConfigManagementForm.vue +++ b/frontend/src/views/system/alertRules/components/ConfigManagement/ConfigManagementForm.vue @@ -367,7 +367,6 @@ const fetchFacilityOptions = async (stationCode: string) => { } else if (formData.ruleType === 'WQ_RULE') { params.filter.filters[1].value = ['WQ']; const res: any = await getMonitorDataWq(params); - // debugger const list = res?.data?.data || []; facilityOptions.value = list.map((item: any) => ({ value: item.stcd , label: item.stnm, stcd: item.stcd })); } else { @@ -514,10 +513,9 @@ const filterOption = (inputValue: string, option: any) => { }; const ennmOptions = ref([]); const handleRiverSelect = async (value: any) => { - // debugger - // + let res: any = await getDictItemsByCode({ dictCode: 'WWQTG' }); - // + if (res?.data?.length > 0) { res.data.forEach((item: any) => { item.value = item.itemCode; diff --git a/frontend/src/views/system/alertRules/components/RulesManagement/LayerManagementForm.vue b/frontend/src/views/system/alertRules/components/RulesManagement/LayerManagementForm.vue index b7a15c91..804f5c43 100644 --- a/frontend/src/views/system/alertRules/components/RulesManagement/LayerManagementForm.vue +++ b/frontend/src/views/system/alertRules/components/RulesManagement/LayerManagementForm.vue @@ -239,7 +239,6 @@ const ennmOptions = ref([]); const handleRiverSelect = async (value: any) => { // let res: any = await getDictItemsByCode({ dictCode: 'WWQTG' }); - // debugger if (res?.data?.length > 0) { res.data.forEach((item: any) => { item.value = item.itemCode; diff --git a/frontend/src/views/system/user/index.vue b/frontend/src/views/system/user/index.vue index 10a2c004..ad50a0a0 100644 --- a/frontend/src/views/system/user/index.vue +++ b/frontend/src/views/system/user/index.vue @@ -798,7 +798,6 @@ function getrole() { rolename: '' }; listGroupedByTenant(params).then(res => { - // debugger rolesdata.value = res; }); }