This commit is contained in:
扈兆增 2026-06-26 18:00:36 +08:00
commit 264a10931b
66 changed files with 8728 additions and 798 deletions

View File

@ -45,7 +45,8 @@ public interface MicroservicDynamicSQLMapper<T> {
default <R> List<R> getAllListWithResultType(String sql, default <R> List<R> getAllListWithResultType(String sql,
Map<String, Object> map, Map<String, Object> map,
Class<R> resultType) { Class<R> resultType) {
return convertList(getAllList(sql, map), resultType); List<Map<String, Object>> allList = getAllList(sql, map);
return convertList(allList, resultType);
} }
@Select({"select count(1) count from ${sql} and ${ew.sqlSegment}"}) @Select({"select count(1) count from ${sql} and ${ew.sqlSegment}"})

View File

@ -61,19 +61,21 @@ public class SecurityConfig {
.requestMatchers("/tempFile/**").permitAll() .requestMatchers("/tempFile/**").permitAll()
.requestMatchers("/system/user/auditUser").permitAll() .requestMatchers("/system/user/auditUser").permitAll()
.requestMatchers("/register/accessToken").permitAll() .requestMatchers("/register/accessToken").permitAll()
// .requestMatchers("/eng/**").permitAll() .requestMatchers("/eng/**").permitAll()
// .requestMatchers("/eq/**").permitAll() .requestMatchers("/eq/**").permitAll()
// .requestMatchers("/env/**").permitAll() .requestMatchers("/env/**").permitAll()
// .requestMatchers("/warn/**").permitAll() .requestMatchers("/warn/**").permitAll()
// .requestMatchers("/wt/**").permitAll() .requestMatchers("/wt/**").permitAll()
// .requestMatchers("/fb/**").permitAll() .requestMatchers("/fb/**").permitAll()
// .requestMatchers("/zq/**").permitAll() .requestMatchers("/zq/**").permitAll()
// .requestMatchers("/wq/**").permitAll() .requestMatchers("/wq/**").permitAll()
// .requestMatchers("/vd/**").permitAll() .requestMatchers("/wte/**").permitAll()
// .requestMatchers("/fp/**").permitAll() .requestMatchers("/vd/**").permitAll()
// .requestMatchers("/fpr/**").permitAll() .requestMatchers("/vap/**").permitAll()
// .requestMatchers("/fh/**").permitAll() .requestMatchers("/fp/**").permitAll()
// .requestMatchers("/data/**").permitAll() .requestMatchers("/fpr/**").permitAll()
.requestMatchers("/fh/**").permitAll()
.requestMatchers("/data/**").permitAll()
.requestMatchers("/sms/**").permitAll() .requestMatchers("/sms/**").permitAll()
.requestMatchers(HttpMethod.GET, "/").permitAll() .requestMatchers(HttpMethod.GET, "/").permitAll()
.requestMatchers(HttpMethod.GET, .requestMatchers(HttpMethod.GET,

View File

@ -143,6 +143,14 @@ public class SwaggerConfig {
.build(); .build();
} }
@Bean
public GroupedOpenApi groupEnvWteApi() {
return GroupedOpenApi.builder()
.group("3.9 全过程-生态环保数据服务-生态调查(wte)")
.packagesToScan("com.yfd.platform.qgc_env.wte.controller")
.build();
}

View File

@ -13,7 +13,7 @@ public class Constant {
public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String CODE_KEY = "code-key-"; public static final String CODE_KEY = "code-key-";
public static final long CODE_EXPIRATION_TIME = 1000 * 60; public static final long CODE_EXPIRATION_TIME = 1000 * 60 * 2;
/** /**
* 用于IP定位转换 * 用于IP定位转换
*/ */

View File

@ -0,0 +1,27 @@
package com.yfd.platform.qgc_base.controller;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.qgc_base.domain.SdAddvcdDicDropdownRequest;
import com.yfd.platform.qgc_base.service.ISdAddvcdDicService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/env/addvcd")
@Tag(name = "行政区管理")
public class SdAddvcdDicController {
@Resource
private ISdAddvcdDicService addvcdDicService;
@PostMapping("/selectForDropdown")
@Operation(summary = "根据级别和父级行政区编码查询行政区下拉")
public ResponseResult selectForDropdown(@RequestBody SdAddvcdDicDropdownRequest request) {
return ResponseResult.successData(addvcdDicService.selectForDropdown(request.getGrd(), request.getPaddvcd()));
}
}

View File

@ -1,6 +1,7 @@
package com.yfd.platform.qgc_base.controller; package com.yfd.platform.qgc_base.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yfd.platform.annotation.Log; import com.yfd.platform.annotation.Log;
import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.config.ResponseResult; import com.yfd.platform.config.ResponseResult;
@ -24,6 +25,9 @@ import jakarta.annotation.Resource;
@Tag(name = "电站管理") @Tag(name = "电站管理")
public class SdEngInfoBHController { public class SdEngInfoBHController {
@Resource
private ObjectMapper objectMapper;
@Resource @Resource
private ISdEngInfoBHService engInfoBHService; private ISdEngInfoBHService engInfoBHService;
@ -93,14 +97,15 @@ public class SdEngInfoBHController {
@PostMapping("/add") @PostMapping("/add")
@Operation(summary = "新增电站") @Operation(summary = "新增电站")
public ResponseResult add(@RequestBody SdEngInfoBHOperateRequest request) { public ResponseResult add(@RequestBody SdEngInfoBHOperateRequest request) {
boolean result = engInfoBHService.addEngInfo(request.getEngInfo(), request.getSource()); SdEngInfoBH engInfo = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdEngInfoBH.class);
boolean result = engInfoBHService.addEngInfo(engInfo, request.getSource());
return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败");
} }
@Log(module = "电站管理", value = "修改电站") @Log(module = "电站管理", value = "修改电站")
@PostMapping("/update") @PostMapping("/update")
@Operation(summary = "修改电站") @Operation(summary = "修改电站")
public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception {
boolean result = engInfoBHService.updateEngInfo(request.getEngInfo(), request.getSource()); boolean result = engInfoBHService.updateEngInfo(request.getEngInfo(), request.getSource());
return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败");
} }
@ -108,8 +113,9 @@ public class SdEngInfoBHController {
@Log(module = "电站管理", value = "删除电站") @Log(module = "电站管理", value = "删除电站")
@PostMapping("/delete") @PostMapping("/delete")
@Operation(summary = "删除电站") @Operation(summary = "删除电站")
public ResponseResult delete(@RequestParam String stcd) { public ResponseResult delete(@RequestBody SdEngInfoBHOperateRequest request) {
boolean result = engInfoBHService.deleteEngInfo(stcd); boolean result = engInfoBHService.deleteEngInfo(request == null ? null : request.getIds(),
request == null ? null : request.getSource());
return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败"); return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
} }

View File

@ -38,4 +38,10 @@ public class SdEngMonitorController {
public ResponseResult getEiaapprovalKendoList(@RequestBody DataSourceRequest dataSourceRequest) { public ResponseResult getEiaapprovalKendoList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(engInfoBHService.getEiaapprovalKendoList(dataSourceRequest)); return ResponseResult.successData(engInfoBHService.getEiaapprovalKendoList(dataSourceRequest));
} }
@PostMapping("/operat/GetKendoListCust")
@Operation(summary = "首页-环保设施运行状况")
public ResponseResult getOperatKendoList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(engInfoBHService.getOperatKendoList(dataSourceRequest));
}
} }

View File

@ -0,0 +1,93 @@
package com.yfd.platform.qgc_base.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* <p>
* 行政区字典表
* </p>
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("SD_ADDVCD_DIC")
public class SdAddvcdDic implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 行政区编码
*/
@TableId(type = IdType.INPUT)
private String addvcd;
/**
* 行政区划名称
*/
private String addvnm;
/**
* 所属行政编码根节点为空
*/
private String paddvcd;
/**
* 树级别从1开始 1= 2= 3=
*/
private Integer grd;
/**
* 树全路径
*/
private String path;
/**
* 排序
*/
private Integer orderIndex;
/**
* 中心经度
*/
private Double lgtd;
/**
* 中心纬度
*/
private Double lttd;
/**
* 面积
*/
private Double area;
/**
* 周长
*/
private Double perimeter;
/**
* 所属国家
*/
private String country;
/**
* 简介
*/
private String introduce;
/**
* 介绍图片
*/
private String inffile;
/**
* 简称
*/
private String shortname;
}

View File

@ -0,0 +1,17 @@
package com.yfd.platform.qgc_base.domain;
import lombok.Data;
@Data
public class SdAddvcdDicDropdownRequest {
/**
* 树级别从1开始 1= 2= 3=
*/
private Integer grd;
/**
* 所属行政编码根节点为空
*/
private String paddvcd;
}

View File

@ -2,10 +2,15 @@ package com.yfd.platform.qgc_base.domain;
import lombok.Data; import lombok.Data;
import java.util.List;
import java.util.Map;
@Data @Data
public class SdEngInfoBHOperateRequest { public class SdEngInfoBHOperateRequest {
private SdEngInfoBH engInfo; private Map<String, Object> engInfo;
private List<String> ids;
private String source; private String source;
} }

View File

@ -228,7 +228,7 @@ public class SdFpssBH implements Serializable {
/** /**
* 鱼道或仿自然通道-流速单位m/s * 鱼道或仿自然通道-流速单位m/s
*/ */
private String v; private String flow;
/** /**
* 仿自然通道断面形状 * 仿自然通道断面形状
@ -308,7 +308,7 @@ public class SdFpssBH implements Serializable {
/** /**
* 设计过鱼规模单位 * 设计过鱼规模单位
*/ */
private Long sjgycnt; private String sjgycnt;
/** /**
* 主要过鱼对象{[code:鱼编码1,name:鱼名称1数量],[code:鱼编码2,name:鱼名称2]...} * 主要过鱼对象{[code:鱼编码1,name:鱼名称1数量],[code:鱼编码2,name:鱼名称2]...}

View File

@ -0,0 +1,32 @@
package com.yfd.platform.qgc_base.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Data
@Schema(description = "环保设施运行状况")
public class EngOperatVo implements Serializable {
private static final long serialVersionUID = 1L;
private String repCode;
private String sttpCode;
private String pcode;
private String pname;
private String stcd;
private String ennm;
private String stnm;
private String addvcdName;
private String rvcdName;
private String sttpName;
private String baseId;
private Integer dtin;
private Integer runState;
private Integer stdState;
private Integer runSstate;
private Integer bldsttCcode;
private Integer yr;
private Integer count;
}

View File

@ -21,6 +21,7 @@ public class EngVmsstbprptVo implements Serializable {
private String baseId; private String baseId;
private String baseName; private String baseName;
private String reachcdName; private String reachcdName;
private String reachcd;
private String hbrvcd; private String hbrvcd;
private String hbrvcdName; private String hbrvcdName;
private String rvcd; private String rvcd;
@ -28,7 +29,11 @@ public class EngVmsstbprptVo implements Serializable {
private String addvcdName; private String addvcdName;
private String hynm; private String hynm;
private String topHynm; private String topHynm;
private String hycd;
private String topHycd;
private String stlc; private String stlc;
private Double lgtd;
private Double lttd;
private Date jcdt; private Date jcdt;
private Date piodt; private Date piodt;
private Date aiodt; private Date aiodt;

View File

@ -0,0 +1,12 @@
package com.yfd.platform.qgc_base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yfd.platform.qgc_base.domain.SdAddvcdDic;
/**
* <p>
* 行政区字典表 Mapper 接口
* </p>
*/
public interface SdAddvcdDicMapper extends BaseMapper<SdAddvcdDic> {
}

View File

@ -7,4 +7,6 @@ public interface IMsOperationLogService {
void recordEngAddLog(SdEngInfoBH engInfo, String source); void recordEngAddLog(SdEngInfoBH engInfo, String source);
void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH changeSet, String source); void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH changeSet, String source);
void recordEngDeleteLog(SdEngInfoBH engInfo, String source);
} }

View File

@ -0,0 +1,19 @@
package com.yfd.platform.qgc_base.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yfd.platform.qgc_base.domain.SdAddvcdDic;
import java.util.List;
/**
* <p>
* 行政区字典表 服务类
* </p>
*/
public interface ISdAddvcdDicService extends IService<SdAddvcdDic> {
/**
* 根据级别和父级行政区编码查询下拉数据
*/
List<SdAddvcdDic> selectForDropdown(Integer grd, String paddvcd);
}

View File

@ -8,10 +8,12 @@ import com.yfd.platform.qgc_base.domain.SdEngInfoBH;
import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest;
import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo; 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.EngEiaapprovalVo;
import com.yfd.platform.qgc_base.domain.vo.EngOperatVo;
import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo; 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.EngVmsstbprptVo;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@ -62,11 +64,15 @@ public interface ISdEngInfoBHService extends IService<SdEngInfoBH> {
boolean updateEngInfo(SdEngInfoBH engInfo, String source); boolean updateEngInfo(SdEngInfoBH engInfo, String source);
boolean updateEngInfo(Map<String, Object> engInfoPatch, String source) throws Exception;
/** /**
* 删除电站 * 删除电站
*/ */
boolean deleteEngInfo(String stcd); boolean deleteEngInfo(String stcd);
boolean deleteEngInfo(List<String> ids, String source);
List<SdEngInfoBH> selectRegDropdown(SdEngInfoBHRequest sdEngInfoBHRequest); List<SdEngInfoBH> selectRegDropdown(SdEngInfoBHRequest sdEngInfoBHRequest);
EngBaseInfoVo getStInfoByStcd(String stcd); EngBaseInfoVo getStInfoByStcd(String stcd);
@ -76,4 +82,6 @@ public interface ISdEngInfoBHService extends IService<SdEngInfoBH> {
DataSourceResult<EngEiaapprovalVo> getEiaapprovalKendoList(DataSourceRequest dataSourceRequest); DataSourceResult<EngEiaapprovalVo> getEiaapprovalKendoList(DataSourceRequest dataSourceRequest);
DataSourceResult<EngVmsstbprptVo> getVmsstbprptKendoList(DataSourceRequest dataSourceRequest); DataSourceResult<EngVmsstbprptVo> getVmsstbprptKendoList(DataSourceRequest dataSourceRequest);
DataSourceResult<EngOperatVo> getOperatKendoList(DataSourceRequest dataSourceRequest);
} }

View File

@ -1,7 +1,5 @@
package com.yfd.platform.qgc_base.service.impl; package com.yfd.platform.qgc_base.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
@ -20,9 +18,11 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
@Service @Service
public class MsOperationLogServiceImpl implements IMsOperationLogService { public class MsOperationLogServiceImpl implements IMsOperationLogService {
@ -33,22 +33,235 @@ public class MsOperationLogServiceImpl implements IMsOperationLogService {
static { static {
ENG_FIELD_MEANING_MAP.put("STCD", "电站编码"); ENG_FIELD_MEANING_MAP.put("STCD", "电站编码");
ENG_FIELD_MEANING_MAP.put("TM", "数据时间");
ENG_FIELD_MEANING_MAP.put("ENNM", "电站名称"); ENG_FIELD_MEANING_MAP.put("ENNM", "电站名称");
ENG_FIELD_MEANING_MAP.put("BASE_ID", "所属基地编码"); ENG_FIELD_MEANING_MAP.put("BASE_ID", "所属基地编码");
// ENG_FIELD_MEANING_MAP.put("BASE_NAME", "所属基地名称");
ENG_FIELD_MEANING_MAP.put("HBRVCD", "所属基地流域编码"); ENG_FIELD_MEANING_MAP.put("HBRVCD", "所属基地流域编码");
// ENG_FIELD_MEANING_MAP.put("HBRVCD_NAME", "所属基地流域名称");
ENG_FIELD_MEANING_MAP.put("RVCD", "所属流域编码"); ENG_FIELD_MEANING_MAP.put("RVCD", "所属流域编码");
// ENG_FIELD_MEANING_MAP.put("RVCD_NAME", "所属流域名称");
ENG_FIELD_MEANING_MAP.put("ADDVCD", "所属行政区编码"); ENG_FIELD_MEANING_MAP.put("ADDVCD", "所属行政区编码");
// ENG_FIELD_MEANING_MAP.put("ADDVCD_NAME", "所属行政区名称");
ENG_FIELD_MEANING_MAP.put("COUNTRY", "所属国家编码");
// ENG_FIELD_MEANING_MAP.put("COUNTRY_NAME", "所属国家名称");
ENG_FIELD_MEANING_MAP.put("REACHCD", "所属河段编码");
// ENG_FIELD_MEANING_MAP.put("REACHCD_NAME", "所属河段名称");
ENG_FIELD_MEANING_MAP.put("HYCD", "所属公司编码"); ENG_FIELD_MEANING_MAP.put("HYCD", "所属公司编码");
// ENG_FIELD_MEANING_MAP.put("HYNM", "所属公司名称");
ENG_FIELD_MEANING_MAP.put("TOP_HYCD", "所属集团编码");
// ENG_FIELD_MEANING_MAP.put("TOP_HYNM", "所属集团名称");
ENG_FIELD_MEANING_MAP.put("BLPRD", "所属建设阶段"); ENG_FIELD_MEANING_MAP.put("BLPRD", "所属建设阶段");
ENG_FIELD_MEANING_MAP.put("BLDSTT", "建设状态"); ENG_FIELD_MEANING_MAP.put("BLDSTT", "建设状态");
ENG_FIELD_MEANING_MAP.put("BLDSTT_CODE", "建设状态分类"); ENG_FIELD_MEANING_MAP.put("BLDSTT_CODE", "建设状态分类");
ENG_FIELD_MEANING_MAP.put("ENGTP", "工程类别");
ENG_FIELD_MEANING_MAP.put("PRSC", "工程规模");
ENG_FIELD_MEANING_MAP.put("SCRSC", "工程规模(水库库容)");
ENG_FIELD_MEANING_MAP.put("PRGR", "工程等别");
ENG_FIELD_MEANING_MAP.put("FN", "主要功能");
ENG_FIELD_MEANING_MAP.put("BSSSIN", "地震基本烈度");
ENG_FIELD_MEANING_MAP.put("FRSSIN", "设防地震烈度");
ENG_FIELD_MEANING_MAP.put("ADJUST_ENG", "是否调节水库");
ENG_FIELD_MEANING_MAP.put("ISHVBRRG", "有无拦河坝");
ENG_FIELD_MEANING_MAP.put("DVTP", "开发方式"); ENG_FIELD_MEANING_MAP.put("DVTP", "开发方式");
ENG_FIELD_MEANING_MAP.put("CNTP", "建设类型");
ENG_FIELD_MEANING_MAP.put("DTIN", "数据是否接入"); ENG_FIELD_MEANING_MAP.put("DTIN", "数据是否接入");
ENG_FIELD_MEANING_MAP.put("DTIN_TM", "数据接入时间");
ENG_FIELD_MEANING_MAP.put("USFL", "是否启用");
ENG_FIELD_MEANING_MAP.put("MONTH_REPORT", "是否发布月报");
ENG_FIELD_MEANING_MAP.put("TB_WAY", "填报方式");
ENG_FIELD_MEANING_MAP.put("TB_FREQUENCY", "填报频率");
ENG_FIELD_MEANING_MAP.put("RGCP", "调节性能"); ENG_FIELD_MEANING_MAP.put("RGCP", "调节性能");
ENG_FIELD_MEANING_MAP.put("LGTD", "经度"); ENG_FIELD_MEANING_MAP.put("LGTD", "经度");
ENG_FIELD_MEANING_MAP.put("LTTD", "纬度"); ENG_FIELD_MEANING_MAP.put("LTTD", "纬度");
ENG_FIELD_MEANING_MAP.put("ELEV", "高程");
ENG_FIELD_MEANING_MAP.put("STLC", "站址"); ENG_FIELD_MEANING_MAP.put("STLC", "站址");
ENG_FIELD_MEANING_MAP.put("ORDER_INDEX", "排序"); ENG_FIELD_MEANING_MAP.put("ORDER_INDEX", "排序");
ENG_FIELD_MEANING_MAP.put("STDSDT", "规划设计日期");
ENG_FIELD_MEANING_MAP.put("PSTSTDT", "计划开工日期");
ENG_FIELD_MEANING_MAP.put("PESSTDT", "计划完工日期");
ENG_FIELD_MEANING_MAP.put("SWDT", "开工日期");
ENG_FIELD_MEANING_MAP.put("JCDT", "建成日期");
ENG_FIELD_MEANING_MAP.put("WDDT", "退役/拆除日期");
ENG_FIELD_MEANING_MAP.put("JLDT", "截流日期");
ENG_FIELD_MEANING_MAP.put("INTRODUCE", "电站简介");
ENG_FIELD_MEANING_MAP.put("LOGO", "电站LOGO");
ENG_FIELD_MEANING_MAP.put("INFFILE", "介绍弹窗图片");
ENG_FIELD_MEANING_MAP.put("DMAT", "坝体材质");
ENG_FIELD_MEANING_MAP.put("DMTP", "坝体类型");
ENG_FIELD_MEANING_MAP.put("MNUN", "管理单位");
ENG_FIELD_MEANING_MAP.put("CMUN", "主管单位");
ENG_FIELD_MEANING_MAP.put("BLSYS", "归属部门");
ENG_FIELD_MEANING_MAP.put("ROLL", "绕经度方向旋转矩阵值");
ENG_FIELD_MEANING_MAP.put("PITCH", "绕纬度方向旋转矩阵值");
ENG_FIELD_MEANING_MAP.put("HEADING", "绕高程方向旋转矩阵值");
ENG_FIELD_MEANING_MAP.put("SCALE", "模型缩放比例");
ENG_FIELD_MEANING_MAP.put("IMPDSTRZ", "是否受下游顶托");
ENG_FIELD_MEANING_MAP.put("PROV", "工程概况");
ENG_FIELD_MEANING_MAP.put("ESTRYDIS", "河口距离");
ENG_FIELD_MEANING_MAP.put("THRSMDAYS", "三同时评价允许误差天数");
ENG_FIELD_MEANING_MAP.put("ZJXYDZ", "直接下游电站");
ENG_FIELD_MEANING_MAP.put("EDTUN", "编制单位");
ENG_FIELD_MEANING_MAP.put("EDTTM", "编制时间");
ENG_FIELD_MEANING_MAP.put("DSNSTT", "勘测设计情况");
ENG_FIELD_MEANING_MAP.put("YSDLEN", "引水道长");
ENG_FIELD_MEANING_MAP.put("DMRKTP", "坝基岩性");
ENG_FIELD_MEANING_MAP.put("HNTJZL", "混凝土浇筑量");
ENG_FIELD_MEANING_MAP.put("GNTP", "容量构成");
ENG_FIELD_MEANING_MAP.put("CNTRAR", "控制流域面积");
ENG_FIELD_MEANING_MAP.put("CNTRSC", "控制面积占全流域比例");
ENG_FIELD_MEANING_MAP.put("AVYRP", "多年平均降水量");
ENG_FIELD_MEANING_MAP.put("AVQ", "多年平均流量");
ENG_FIELD_MEANING_MAP.put("DSAVQ", "电站未建枯水期平均流量");
ENG_FIELD_MEANING_MAP.put("DSMXQ", "设计洪峰流量");
ENG_FIELD_MEANING_MAP.put("CHMXQ", "校核洪峰流量");
ENG_FIELD_MEANING_MAP.put("RVLEN", "河道长度");
ENG_FIELD_MEANING_MAP.put("RVGR", "河道比降");
ENG_FIELD_MEANING_MAP.put("AVW", "多年平均径流量");
ENG_FIELD_MEANING_MAP.put("AVYRQ", "多年平均年径流量");
ENG_FIELD_MEANING_MAP.put("AVSD", "多年平均输沙量");
ENG_FIELD_MEANING_MAP.put("AVS", "多年平均含沙量");
ENG_FIELD_MEANING_MAP.put("MYAVMNAT", "多年平均最低气温");
ENG_FIELD_MEANING_MAP.put("DSW1", "设计一日洪量");
ENG_FIELD_MEANING_MAP.put("DSW3", "设计三日洪量");
ENG_FIELD_MEANING_MAP.put("CHFLDR", "校核洪水历时");
ENG_FIELD_MEANING_MAP.put("CHFLW", "校核洪水总量");
ENG_FIELD_MEANING_MAP.put("CPSC", "库容系数");
ENG_FIELD_MEANING_MAP.put("NRZAR", "正常蓄水位时水库面积");
ENG_FIELD_MEANING_MAP.put("BCKLEN", "水库回水长度");
ENG_FIELD_MEANING_MAP.put("NRAVWT", "天然河流平均水温");
ENG_FIELD_MEANING_MAP.put("NRMXAVWT", "天然河流最高温月份多年平均水温");
ENG_FIELD_MEANING_MAP.put("NRMNAVWT", "天然河流最低温月份多年平均水温");
ENG_FIELD_MEANING_MAP.put("DNAVWT", "建成后坝下平均水温");
ENG_FIELD_MEANING_MAP.put("DNMXAVWT", "建成后坝下最高温月份多年平均水温");
ENG_FIELD_MEANING_MAP.put("DNMNAVWT", "建成后坝下最低温月份多年平均水温");
ENG_FIELD_MEANING_MAP.put("NRUPAR", "坝址以上流域面积");
ENG_FIELD_MEANING_MAP.put("NRAVZ", "坝址天然河流平均水位");
ENG_FIELD_MEANING_MAP.put("NRAVH", "坝址天然河流平均水深");
ENG_FIELD_MEANING_MAP.put("DSNFQFRQ", "设计入库洪水流量");
ENG_FIELD_MEANING_MAP.put("CKFQFQR", "校核入库洪水流量");
ENG_FIELD_MEANING_MAP.put("OBMXW3", "实测最大洪量(三天)");
ENG_FIELD_MEANING_MAP.put("FDCZ", "水库淹没城镇");
ENG_FIELD_MEANING_MAP.put("FDQT", "淹没其它设施");
ENG_FIELD_MEANING_MAP.put("DSTCRVR", "距河源距离");
ENG_FIELD_MEANING_MAP.put("CKW3", "校核洪量(三天)");
ENG_FIELD_MEANING_MAP.put("FSLTDZ", "防洪限制水位");
ENG_FIELD_MEANING_MAP.put("RSTP", "资源类别");
ENG_FIELD_MEANING_MAP.put("ADJCPS", "调节库容单独");
ENG_FIELD_MEANING_MAP.put("ADJCPM", "调节库容联合");
ENG_FIELD_MEANING_MAP.put("YRGEB", "已正建规模装机容量");
ENG_FIELD_MEANING_MAP.put("TTPWRB", "已正建规模年发电量");
ENG_FIELD_MEANING_MAP.put("DMCREL", "坝顶高程");
ENG_FIELD_MEANING_MAP.put("WSC", "水量利用系数");
ENG_FIELD_MEANING_MAP.put("MXDMHG", "最大坝高");
ENG_FIELD_MEANING_MAP.put("MXDMHGL", "最大坝高(左)");
ENG_FIELD_MEANING_MAP.put("MXDMHGR", "最大坝高(右)");
ENG_FIELD_MEANING_MAP.put("WVTPEL", "防浪墙顶高程");
}
private static final Map<String, String> ENG_CODE_NAME_FIELD_MAP = new LinkedHashMap<>();
private static final Set<String> ENG_NAME_COLUMNS = new HashSet<>();
private static final Map<String, Map<String, String>> ENG_DICT_VALUE_NAME_MAP = new LinkedHashMap<>();
static {
ENG_CODE_NAME_FIELD_MAP.put("BASE_ID", "BASE_NAME");
ENG_CODE_NAME_FIELD_MAP.put("HBRVCD", "HBRVCD_NAME");
ENG_CODE_NAME_FIELD_MAP.put("RVCD", "RVCD_NAME");
ENG_CODE_NAME_FIELD_MAP.put("ADDVCD", "ADDVCD_NAME");
ENG_CODE_NAME_FIELD_MAP.put("COUNTRY", "COUNTRY_NAME");
ENG_CODE_NAME_FIELD_MAP.put("HYCD", "HYNM");
ENG_CODE_NAME_FIELD_MAP.put("TOP_HYCD", "TOP_HYNM");
ENG_CODE_NAME_FIELD_MAP.put("REACHCD", "REACHCD_NAME");
ENG_NAME_COLUMNS.addAll(ENG_CODE_NAME_FIELD_MAP.values());
ENG_DICT_VALUE_NAME_MAP.put("USFL", buildValueNameMap("0", "禁用", "1", "启用"));
ENG_DICT_VALUE_NAME_MAP.put("DTIN", buildValueNameMap("0", "", "1", ""));
ENG_DICT_VALUE_NAME_MAP.put("MONTH_REPORT", buildValueNameMap("0", "", "1", ""));
ENG_DICT_VALUE_NAME_MAP.put("BLPRD", buildValueNameMap(
"1001000", "规划",
"1002000", "预可研",
"1003000", "环评",
"1004000", "可研",
"1005000", "在建",
"1006000", "招标设计",
"1007000", "施工详图",
"1009000", "建设",
"1010000", "蓄水阶段环保验收",
"1011000", "竣工",
"1012000", "竣工环保验收",
"1013000", "环境影响后评价"
));
ENG_DICT_VALUE_NAME_MAP.put("BLDSTT", buildValueNameMap(
"1", "已建成未验收",
"2", "在建",
"3", "可研",
"4", "规划",
"5", "预可研",
"6", "已核准",
"7", "招标设计",
"8", "施工详图",
"9", "其他",
"10", "已建成已验收",
"11", "已开展后评价",
"31", "项目建议书",
"32", "可研",
"33", "已审批",
"34", "初步设计",
"35", "技施设计",
"36", "在建",
"37", "已建成未验收",
"38", "已建成已验收",
"39", "已开展后评价",
"40", "其他",
"61", "规划",
"62", "项目建议书",
"63", "预可研",
"64", "可研",
"65", "已核准",
"66", "初步设计",
"67", "招标设计",
"68", "技施设计",
"69", "施工详图",
"70", "在建",
"71", "已建成未验收",
"72", "已建成已验收",
"73", "已开展后评价",
"74", "其他",
"91", "拆除"
));
ENG_DICT_VALUE_NAME_MAP.put("BLDSTT_CODE", buildValueNameMap(
"0", "未建/规划",
"1", "在建",
"2", "已建"
));
ENG_DICT_VALUE_NAME_MAP.put("ENGTP", buildValueNameMap("1", "水电站", "2", "水利工程", "3", "航电枢纽"));
ENG_DICT_VALUE_NAME_MAP.put("PRSC", buildValueNameMap("1", "大型1", "2", "大型2", "3", "中型", "4", "小型"));
ENG_DICT_VALUE_NAME_MAP.put("SCRSC", buildValueNameMap("1", "大型1", "2", "大型2", "3", "中型", "4", "小型1", "5", "小型2"));
ENG_DICT_VALUE_NAME_MAP.put("PRGR", buildValueNameMap("1", "", "2", "", "3", "", "4", "", "5", ""));
ENG_DICT_VALUE_NAME_MAP.put("FN", buildValueNameMap(
"1", "发电", "2", "防洪", "3", "灌溉", "4", "供水", "5", "航运",
"6", "旅游", "7", "环境", "8", "养殖", "9", "其他"
));
ENG_DICT_VALUE_NAME_MAP.put("BSSSIN", buildValueNameMap("5", "<Ⅵ", "6", "", "7", "", "8", "", "9", "≥Ⅸ"));
ENG_DICT_VALUE_NAME_MAP.put("FRSSIN", buildValueNameMap("0", "未设防", "6", "", "7", "", "8", "", "9", "≥Ⅸ"));
ENG_DICT_VALUE_NAME_MAP.put("ADJUST_ENG", buildValueNameMap("0", "", "1", ""));
ENG_DICT_VALUE_NAME_MAP.put("ISHVBRRG", buildValueNameMap("0", "", "1", ""));
ENG_DICT_VALUE_NAME_MAP.put("RGCP", buildValueNameMap(
"1", "多年调节", "2", "年调节", "3", "不完全年调节", "4", "径流式(无调节)",
"5", "季调节", "6", "月调节", "7", "周调节", "8", "日调节", "9", "其他"
));
ENG_DICT_VALUE_NAME_MAP.put("DMAT", buildValueNameMap("0", "混凝土坝", "1", "土坝"));
ENG_DICT_VALUE_NAME_MAP.put("DMTP", buildValueNameMap(
"0", "混合型", "1", "重力坝", "2", "拱坝", "3", "土石坝", "4", "支墩坝",
"5", "混凝土闸坝", "6", "混凝土面板堆石坝", "7", "预应力坝",
"8", "复合土工膜面板堆石坝", "9", "碾压混凝土重力坝", "10", "混凝土重力坝"
));
ENG_DICT_VALUE_NAME_MAP.put("DVTP", buildValueNameMap("1", "堤坝式", "2", "引水式", "3", "混合式"));
ENG_DICT_VALUE_NAME_MAP.put("CNTP", buildValueNameMap("1", "新建", "2", "改建", "3", "扩建", "4", "加固"));
ENG_DICT_VALUE_NAME_MAP.put("BLSYS", buildValueNameMap("1", "水利", "2", "能源", "3", "交通", "4", "农业", "5", "建设", "9", "其他"));
ENG_DICT_VALUE_NAME_MAP.put("IMPDSTRZ", buildValueNameMap("0", "", "1", ""));
} }
@Resource @Resource
@ -66,45 +279,101 @@ public class MsOperationLogServiceImpl implements IMsOperationLogService {
msOperationLogMapper.insert(mainLog); msOperationLogMapper.insert(mainLog);
List<MsOperationLogDetail> details = new ArrayList<>(); List<MsOperationLogDetail> details = new ArrayList<>();
Set<String> processedColumns = new HashSet<>();
for (Field field : SdEngInfoBH.class.getDeclaredFields()) { for (Field field : SdEngInfoBH.class.getDeclaredFields()) {
if (shouldSkipField(field)) { if (shouldSkipField(field)) {
continue; continue;
} }
field.setAccessible(true); field.setAccessible(true);
String columnName = resolveColumnName(field);
if (ENG_NAME_COLUMNS.contains(columnName) || processedColumns.contains(columnName)) {
continue;
}
Object newValue = getFieldValue(field, engInfo); Object newValue = getFieldValue(field, engInfo);
if (newValue == null) { if (newValue == null) {
continue; continue;
} }
details.add(buildDetail(mainLog.getId(), engInfo.getStcd(), resolveColumnName(field), String nameColumn = ENG_CODE_NAME_FIELD_MAP.get(columnName);
null, newValue, "新增字段值")); Object newNameValue = StrUtil.isBlank(nameColumn) ? newValue : getColumnValue(engInfo, nameColumn);
details.add(buildDetail(mainLog.getId(), engInfo.getStcd(), columnName,
null, null, newValue, newNameValue, "新增字段值"));
processedColumns.add(columnName);
if (StrUtil.isNotBlank(nameColumn)) {
processedColumns.add(nameColumn);
}
} }
batchInsertDetails(details); batchInsertDetails(details);
} }
@Override @Override
public void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH changeSet, String source) { public void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH after, String source) {
if (before == null || changeSet == null) { if (before == null || after == null) {
return; return;
} }
SdEngInfoBH after = BeanUtil.copyProperties(before, SdEngInfoBH.class);
BeanUtil.copyProperties(changeSet, after, CopyOptions.create().ignoreNullValue());
MsOperationLog mainLog = buildMainLog("修改电站", source); MsOperationLog mainLog = buildMainLog("修改电站", source);
msOperationLogMapper.insert(mainLog); msOperationLogMapper.insert(mainLog);
List<MsOperationLogDetail> details = new ArrayList<>(); List<MsOperationLogDetail> details = new ArrayList<>();
Set<String> processedColumns = new HashSet<>();
for (Field field : SdEngInfoBH.class.getDeclaredFields()) { for (Field field : SdEngInfoBH.class.getDeclaredFields()) {
if (shouldSkipField(field)) { if (shouldSkipField(field)) {
continue; continue;
} }
field.setAccessible(true); field.setAccessible(true);
Object oldValue = getFieldValue(field, before); String columnName = resolveColumnName(field);
Object newValue = getFieldValue(field, after); if (ENG_NAME_COLUMNS.contains(columnName) || processedColumns.contains(columnName)) {
if (equalsValue(oldValue, newValue)) {
continue; continue;
} }
details.add(buildDetail(mainLog.getId(), after.getStcd(), resolveColumnName(field), Object oldValue = getFieldValue(field, before);
oldValue, newValue, "修改字段值")); Object newValue = getFieldValue(field, after);
String nameColumn = ENG_CODE_NAME_FIELD_MAP.get(columnName);
Object oldNameValue = resolveNameValue(columnName, nameColumn, oldValue, before);
Object newNameValue = resolveNameValue(columnName, nameColumn, newValue, after);
if (equalsValue(oldValue, newValue) && equalsValue(oldNameValue, newNameValue)) {
continue;
}
details.add(buildDetail(mainLog.getId(), after.getStcd(), columnName,
oldValue, oldNameValue, newValue, newNameValue, "修改字段值"));
processedColumns.add(columnName);
if (StrUtil.isNotBlank(nameColumn)) {
processedColumns.add(nameColumn);
}
}
batchInsertDetails(details);
}
@Override
public void recordEngDeleteLog(SdEngInfoBH engInfo, String source) {
if (engInfo == null) {
return;
}
MsOperationLog mainLog = buildMainLog("删除电站", source);
msOperationLogMapper.insert(mainLog);
List<MsOperationLogDetail> details = new ArrayList<>();
Set<String> processedColumns = new HashSet<>();
for (Field field : SdEngInfoBH.class.getDeclaredFields()) {
if (shouldSkipField(field)) {
continue;
}
field.setAccessible(true);
String columnName = resolveColumnName(field);
if (ENG_NAME_COLUMNS.contains(columnName) || processedColumns.contains(columnName)) {
continue;
}
Object oldValue = getFieldValue(field, engInfo);
if (oldValue == null) {
continue;
}
String nameColumn = ENG_CODE_NAME_FIELD_MAP.get(columnName);
Object oldNameValue = resolveNameValue(columnName, nameColumn, oldValue, engInfo);
details.add(buildDetail(mainLog.getId(), engInfo.getStcd(), columnName,
oldValue, oldNameValue, null, null, "删除字段值"));
processedColumns.add(columnName);
if (StrUtil.isNotBlank(nameColumn)) {
processedColumns.add(nameColumn);
}
} }
batchInsertDetails(details); batchInsertDetails(details);
} }
@ -121,8 +390,10 @@ public class MsOperationLogServiceImpl implements IMsOperationLogService {
private MsOperationLogDetail buildDetail(String mainId, private MsOperationLogDetail buildDetail(String mainId,
String stationCode, String stationCode,
String fieldCode, String fieldCode,
Object oldValue, Object oldValueCode,
Object newValue, Object oldValueName,
Object newValueCode,
Object newValueName,
String remark) { String remark) {
MsOperationLogDetail detail = new MsOperationLogDetail(); MsOperationLogDetail detail = new MsOperationLogDetail();
detail.setMainId(mainId); detail.setMainId(mainId);
@ -130,10 +401,10 @@ public class MsOperationLogServiceImpl implements IMsOperationLogService {
detail.setStationCode(stationCode); detail.setStationCode(stationCode);
detail.setFieldCode(fieldCode); detail.setFieldCode(fieldCode);
detail.setFieldMeaning(ENG_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); detail.setFieldMeaning(ENG_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode));
detail.setOldValueCode(formatValue(oldValue)); detail.setOldValueCode(formatValue(oldValueCode));
detail.setOldValueName(formatValue(oldValue)); detail.setOldValueName(formatValue(oldValueName));
detail.setNewValueCode(formatValue(newValue)); detail.setNewValueCode(formatValue(newValueCode));
detail.setNewValueName(formatValue(newValue)); detail.setNewValueName(formatValue(newValueName));
detail.setRemark(remark); detail.setRemark(remark);
return detail; return detail;
} }
@ -173,6 +444,64 @@ public class MsOperationLogServiceImpl implements IMsOperationLogService {
} }
} }
private Object getColumnValue(Object target, String columnName) {
if (target == null || StrUtil.isBlank(columnName)) {
return null;
}
for (Field field : SdEngInfoBH.class.getDeclaredFields()) {
if (shouldSkipField(field)) {
continue;
}
field.setAccessible(true);
if (StrUtil.equals(resolveColumnName(field), columnName)) {
return getFieldValue(field, target);
}
}
return null;
}
private Object resolveNameValue(String fieldCode, String nameColumn, Object rawValue, SdEngInfoBH target) {
if (StrUtil.isNotBlank(nameColumn)) {
return getColumnValue(target, nameColumn);
}
return resolveDictName(fieldCode, rawValue);
}
private Object resolveDictName(String fieldCode, Object rawValue) {
String text = formatValue(rawValue);
if (StrUtil.isBlank(text)) {
return rawValue;
}
Map<String, String> dictMap = ENG_DICT_VALUE_NAME_MAP.get(fieldCode);
if (dictMap == null || dictMap.isEmpty()) {
return rawValue;
}
if (!text.contains(",") && !text.contains(";")) {
return dictMap.getOrDefault(text, rawValue == null ? null : text);
}
String[] parts = text.split("[,;]");
List<String> names = new ArrayList<>();
for (String part : parts) {
String code = StrUtil.trim(part);
if (StrUtil.isBlank(code)) {
continue;
}
names.add(dictMap.getOrDefault(code, code));
}
return names.isEmpty() ? rawValue : String.join(",", names);
}
private static Map<String, String> buildValueNameMap(String... keyValues) {
Map<String, String> valueMap = new LinkedHashMap<>();
if (keyValues == null) {
return valueMap;
}
for (int i = 0; i + 1 < keyValues.length; i += 2) {
valueMap.put(keyValues[i], keyValues[i + 1]);
}
return valueMap;
}
private boolean equalsValue(Object oldValue, Object newValue) { private boolean equalsValue(Object oldValue, Object newValue) {
return StrUtil.equals(formatValue(oldValue), formatValue(newValue)); return StrUtil.equals(formatValue(oldValue), formatValue(newValue));
} }

View File

@ -0,0 +1,28 @@
package com.yfd.platform.qgc_base.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.qgc_base.domain.SdAddvcdDic;
import com.yfd.platform.qgc_base.mapper.SdAddvcdDicMapper;
import com.yfd.platform.qgc_base.service.ISdAddvcdDicService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.List;
/**
* <p>
* 行政区字典表 服务实现类
* </p>
*/
@Service
public class SdAddvcdDicServiceImpl extends ServiceImpl<SdAddvcdDicMapper, SdAddvcdDic> implements ISdAddvcdDicService {
@Override
public List<SdAddvcdDic> selectForDropdown(Integer grd, String paddvcd) {
return this.lambdaQuery()
.eq(grd != null, SdAddvcdDic::getGrd, grd)
.eq(StringUtils.hasText(paddvcd), SdAddvcdDic::getPaddvcd, paddvcd)
.orderByAsc(SdAddvcdDic::getOrderIndex)
.list();
}
}

View File

@ -4,9 +4,15 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceLoadOptionsBase;
import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceRequest;
@ -20,6 +26,7 @@ import com.yfd.platform.qgc_base.domain.SdEngInfoBH;
import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest;
import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo; 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.EngEiaapprovalVo;
import com.yfd.platform.qgc_base.domain.vo.EngOperatVo;
import com.yfd.platform.qgc_base.domain.vo.EngStBaseInfoVo; 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.EngStInfoResultVo;
import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo;
@ -33,8 +40,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -51,6 +60,19 @@ import java.util.stream.Collectors;
@Service @Service
public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEngInfoBH> implements ISdEngInfoBHService { public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEngInfoBH> implements ISdEngInfoBHService {
private static final Map<String, String> ENG_CODE_NAME_FIELD_MAP = new LinkedHashMap<>();
static {
ENG_CODE_NAME_FIELD_MAP.put("baseId", "baseName");
ENG_CODE_NAME_FIELD_MAP.put("hbrvcd", "hbrvcdName");
ENG_CODE_NAME_FIELD_MAP.put("rvcd", "rvcdName");
ENG_CODE_NAME_FIELD_MAP.put("addvcd", "addvcdName");
ENG_CODE_NAME_FIELD_MAP.put("country", "countryName");
ENG_CODE_NAME_FIELD_MAP.put("hycd", "hynm");
ENG_CODE_NAME_FIELD_MAP.put("topHycd", "topHynm");
ENG_CODE_NAME_FIELD_MAP.put("reachcd", "reachcdName");
}
@Resource @Resource
private SdEngInfoBHMapper engInfoBHMapper; private SdEngInfoBHMapper engInfoBHMapper;
@ -63,6 +85,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
@Resource @Resource
private IMsOperationLogService msOperationLogService; private IMsOperationLogService msOperationLogService;
@Resource
private ObjectMapper objectMapper;
@Override @Override
public Page<SdEngInfoBH> queryPageList(Page<SdEngInfoBH> page, String ennm, String rvcd, String baseId, String hycd) { public Page<SdEngInfoBH> queryPageList(Page<SdEngInfoBH> page, String ennm, String rvcd, String baseId, String hycd) {
LambdaQueryWrapper<SdEngInfoBH> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SdEngInfoBH> wrapper = new LambdaQueryWrapper<>();
@ -203,6 +228,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public boolean addEngInfo(SdEngInfoBH engInfo, String source) { public boolean addEngInfo(SdEngInfoBH engInfo, String source) {
fillRelatedNameFields(engInfo);
boolean result = this.save(engInfo); boolean result = this.save(engInfo);
if (result) { if (result) {
msOperationLogService.recordEngAddLog(engInfo, source); msOperationLogService.recordEngAddLog(engInfo, source);
@ -219,17 +245,301 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public boolean updateEngInfo(SdEngInfoBH engInfo, String source) { public boolean updateEngInfo(SdEngInfoBH engInfo, String source) {
SdEngInfoBH before = engInfo == null ? null : this.getById(engInfo.getStcd()); SdEngInfoBH before = engInfo == null ? null : this.getById(engInfo.getStcd());
boolean result = this.updateById(engInfo); SdEngInfoBH after = before == null ? engInfo : BeanUtil.copyProperties(before, SdEngInfoBH.class);
if (after != null) {
BeanUtil.copyProperties(engInfo, after, CopyOptions.create().ignoreNullValue());
fillRelatedNameFields(after);
}
boolean result = this.updateById(after);
if (result && before != null) { if (result && before != null) {
msOperationLogService.recordEngUpdateLog(before, engInfo, source); msOperationLogService.recordEngUpdateLog(before, after, source);
} }
return result; return result;
} }
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateEngInfo(Map<String, Object> engInfoPatch, String source) throws JsonMappingException {
Map<String, Object> 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) {
msOperationLogService.recordEngUpdateLog(before, after, source);
}
return result;
}
private boolean updateEngInfoByPatch(String stcd, SdEngInfoBH after, Map<String, Object> engInfoPatch) {
UpdateWrapper<SdEngInfoBH> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("STCD", stcd);
boolean hasUpdateField = false;
for (Field field : SdEngInfoBH.class.getDeclaredFields()) {
field.setAccessible(true);
String fieldName = field.getName();
if ("serialVersionUID".equals(fieldName) || "stcd".equals(fieldName)) {
continue;
}
boolean explicitPatched = engInfoPatch.containsKey(fieldName);
boolean linkedNamePatched = isLinkedNameFieldPatched(fieldName, engInfoPatch);
if (!explicitPatched && !linkedNamePatched) {
continue;
}
String resolveColumnName = resolveColumnName(field);
Object fieldValue = getFieldValue(field, after);
if (fieldValue == null) {
updateWrapper.setSql(resolveColumnName + " = NULL");
} else {
updateWrapper.set(resolveColumnName, fieldValue);
}
hasUpdateField = true;
}
if (!hasUpdateField) {
return true;
}
return this.update(null, updateWrapper);
}
private void fillRelatedNameFields(SdEngInfoBH engInfo) {
if (engInfo == null) {
return;
}
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("baseId", engInfo.getBaseId());
paramMap.put("hbrvcd", engInfo.getHbrvcd());
paramMap.put("rvcd", engInfo.getRvcd());
paramMap.put("addvcd", engInfo.getAddvcd());
paramMap.put("country", engInfo.getCountry());
paramMap.put("hycd", engInfo.getHycd());
paramMap.put("topHycd", engInfo.getTopHycd());
paramMap.put("reachcd", engInfo.getReachcd());
Map<String, Object> row = microservicDynamicSQLMapper.getOneBySql(buildEngRelatedNameSql(paramMap), paramMap);
engInfo.setBaseName(resolveRelatedName(engInfo.getBaseId(), row, "BASENAME"));
engInfo.setHbrvcdName(resolveRelatedName(engInfo.getHbrvcd(), row, "HBRVNM"));
engInfo.setRvcdName(resolveRelatedName(engInfo.getRvcd(), row, "RVNM"));
engInfo.setAddvcdName(resolveRelatedName(engInfo.getAddvcd(), row, "ADDVNM"));
engInfo.setCountryName(resolveRelatedName(engInfo.getCountry(), row, "COUNTRY_NAME"));
engInfo.setHynm(resolveRelatedName(engInfo.getHycd(), row, "HYNM"));
engInfo.setTopHynm(resolveRelatedName(engInfo.getTopHycd(), row, "TOP_HYNM"));
engInfo.setReachcdName(resolveRelatedName(engInfo.getReachcd(), row, "REACHCD_NAME"));
}
private String buildEngRelatedNameSql(Map<String, Object> paramMap) {
StringBuilder sql = new StringBuilder("SELECT ");
sql.append(buildScalarNameSelect(
StringUtils.hasText((String) paramMap.get("baseId")),
"(SELECT hb.BASENAME FROM SD_HYDROBASE hb WHERE hb.BASEID = #{map.baseId} AND NVL(hb.IS_DELETED, 0) = 0 AND ROWNUM = 1)",
"BASENAME"
));
sql.append(", ");
sql.append(buildHbrvNameSelect(paramMap));
sql.append(", ");
sql.append(buildScalarNameSelect(
StringUtils.hasText((String) paramMap.get("rvcd")),
"(SELECT rv.RVNM FROM SD_RVCD_DIC rv WHERE rv.RVCD = #{map.rvcd} AND ROWNUM = 1)",
"RVNM"
));
sql.append(", ");
sql.append(buildScalarNameSelect(
StringUtils.hasText((String) paramMap.get("addvcd")),
"(SELECT addv.ADDVNM FROM SD_ADDVCD_DIC addv WHERE addv.ADDVCD = #{map.addvcd} AND ROWNUM = 1)",
"ADDVNM"
));
sql.append(", ");
sql.append(buildScalarNameSelect(
StringUtils.hasText((String) paramMap.get("country")),
"(SELECT country.COUNTRY_NAME FROM SD_COUNTRY_B country WHERE country.COUNTRY_ID = #{map.country} " +
"AND NVL(country.ENABLED, 1) = 1 AND ROWNUM = 1)",
"COUNTRY_NAME"
));
sql.append(", ");
sql.append(buildScalarNameSelect(
StringUtils.hasText((String) paramMap.get("hycd")),
"(SELECT hy.HYNM FROM SD_HYCD_DIC hy WHERE hy.HYCD = #{map.hycd} " +
"AND NVL(hy.IS_DELETED, 0) = 0 AND NVL(hy.ENABLED, 1) = 1 AND ROWNUM = 1)",
"HYNM"
));
sql.append(", ");
sql.append(buildScalarNameSelect(
StringUtils.hasText((String) paramMap.get("topHycd")),
"(SELECT hy.HYNM FROM SD_HYCD_DIC hy WHERE hy.HYCD = #{map.topHycd} " +
"AND NVL(hy.IS_DELETED, 0) = 0 AND NVL(hy.ENABLED, 1) = 1 AND ROWNUM = 1)",
"TOP_HYNM"
));
sql.append(", ");
sql.append(buildReachcdNameSelect(paramMap));
sql.append(" FROM DUAL");
return sql.toString();
}
private String buildHbrvNameSelect(Map<String, Object> paramMap) {
if (!StringUtils.hasText((String) paramMap.get("hbrvcd"))) {
return "NULL AS HBRVNM";
}
StringBuilder sql = new StringBuilder("(SELECT hbrv.HBRVNM FROM SD_HBRV_DIC hbrv WHERE hbrv.HBRVCD = #{map.hbrvcd} ");
if (StringUtils.hasText((String) paramMap.get("baseId"))) {
sql.append("AND hbrv.BASEID = #{map.baseId} ");
}
sql.append("AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 AND ROWNUM = 1) AS HBRVNM");
return sql.toString();
}
private String buildScalarNameSelect(boolean hasText, String querySql, String alias) {
if (!hasText) {
return "NULL AS " + alias;
}
return querySql + " AS " + alias;
}
private String buildReachcdNameSelect(Map<String, Object> paramMap) {
if (!StringUtils.hasText((String) paramMap.get("reachcd"))) {
return "NULL AS REACHCD_NAME";
}
return "(SELECT LISTAGG(pathNode.RVNM, '-') WITHIN GROUP (ORDER BY pathNode.LVL DESC) " +
"FROM ( " +
" SELECT rv.RVNM, LEVEL AS LVL " +
" FROM SD_RVCD_DIC rv " +
" START WITH rv.RVCD = #{map.reachcd} " +
" CONNECT BY PRIOR rv.PRVCD = rv.RVCD " +
") pathNode) AS REACHCD_NAME";
}
private String resolveRelatedName(String code, Map<String, Object> row, String column) {
if (code == null) {
return null;
}
if (code.isBlank()) {
return "";
}
if (row == null) {
return null;
}
Object value = row.get(column);
if (value == null) {
value = row.get(column.toLowerCase());
}
return value == null ? null : String.valueOf(value);
}
private Map<String, Object> filterEngInfoPatchFields(Map<String, Object> engInfoPatch) {
Map<String, Object> filteredPatch = new LinkedHashMap<>();
if (engInfoPatch == null || engInfoPatch.isEmpty()) {
return filteredPatch;
}
Set<String> validFieldNames = new HashSet<>();
for (Field field : SdEngInfoBH.class.getDeclaredFields()) {
if ("serialVersionUID".equals(field.getName())) {
continue;
}
validFieldNames.add(field.getName());
}
for (Map.Entry<String, Object> entry : engInfoPatch.entrySet()) {
if (validFieldNames.contains(entry.getKey())) {
filteredPatch.put(entry.getKey(), entry.getValue());
}
}
return filteredPatch;
}
private boolean isLinkedNameFieldPatched(String fieldName, Map<String, Object> engInfoPatch) {
for (Map.Entry<String, String> entry : ENG_CODE_NAME_FIELD_MAP.entrySet()) {
if (entry.getValue().equals(fieldName) && engInfoPatch.containsKey(entry.getKey())) {
return true;
}
}
return false;
}
private String resolveColumnName(Field field) {
TableId tableId = field.getAnnotation(TableId.class);
if (tableId != null) {
return camelToUpperUnderline(field.getName());
}
TableField tableField = field.getAnnotation(TableField.class);
if (tableField != null && StrUtil.isNotBlank(tableField.value())) {
return tableField.value();
}
return camelToUpperUnderline(field.getName());
}
private Object getFieldValue(Field field, Object target) {
try {
return field.get(target);
} catch (IllegalAccessException e) {
return null;
}
}
private String toTextValue(Object value) {
if (value == null) {
return null;
}
String text = String.valueOf(value);
return text.isBlank() ? null : text;
}
private String camelToUpperUnderline(String text) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
if (Character.isUpperCase(ch) && i > 0) {
builder.append('_');
}
builder.append(Character.toUpperCase(ch));
}
return builder.toString();
}
@Override @Override
public boolean deleteEngInfo(String stcd) { public boolean deleteEngInfo(String stcd) {
return this.update( new LambdaUpdateWrapper<SdEngInfoBH>().eq(SdEngInfoBH::getStcd, stcd).set(SdEngInfoBH::getIsDeleted, 1)); if (StrUtil.isBlank(stcd)) {
// return this.removeById(stcd); return false;
}
return deleteEngInfo(java.util.Collections.singletonList(stcd), null);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteEngInfo(List<String> ids, String source) {
List<String> stcdList = ids == null ? new ArrayList<>() : ids.stream()
.filter(StrUtil::isNotBlank)
.distinct()
.collect(Collectors.toList());
if (CollUtil.isEmpty(stcdList)) {
return false;
}
List<SdEngInfoBH> beforeList = this.lambdaQuery()
.in(SdEngInfoBH::getStcd, stcdList)
.eq(SdEngInfoBH::getIsDeleted, 0)
.list();
if (CollUtil.isEmpty(beforeList)) {
return false;
}
boolean result = this.update(new LambdaUpdateWrapper<SdEngInfoBH>()
.in(SdEngInfoBH::getStcd, stcdList)
.eq(SdEngInfoBH::getIsDeleted, 0)
.set(SdEngInfoBH::getIsDeleted, 1)
.set(SdEngInfoBH::getDeleteUser, SecurityUtils.getCurrentUsername())
.set(SdEngInfoBH::getDeleteTime, new Date()));
if (result) {
for (SdEngInfoBH before : beforeList) {
msOperationLogService.recordEngDeleteLog(before, source);
}
}
return result;
} }
@Override @Override
@ -382,6 +692,132 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
return result; return result;
} }
@Override
public DataSourceResult<EngOperatVo> getOperatKendoList(DataSourceRequest dataSourceRequest) {
DataSourceResult<EngOperatVo> result = new DataSourceResult<>();
result.setAggregates(new HashMap<>());
if (dataSourceRequest == null) {
result.setData(new ArrayList<>());
result.setTotal(0L);
return result;
}
DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest();
if (CollUtil.isEmpty(dataSourceRequest.getGroup())) {
return queryOperatSummaryList(dataSourceRequest, loadOptions);
}
return queryOperatGroupList(dataSourceRequest, loadOptions);
}
private DataSourceResult<EngOperatVo> queryOperatSummaryList(DataSourceRequest dataSourceRequest,
DataSourceLoadOptionsBase loadOptions) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT ")
.append(buildOperatSummarySelectSql(dataSourceRequest.getSelect()))
.append(" FROM (")
.append(buildOperatCategorySql())
.append(") cat ")
.append("LEFT JOIN (SELECT * FROM (")
.append(buildOperatBaseViewSql())
.append(") t WHERE 1 = 1 ");
Map<String, Object> paramMap = new HashMap<>();
String filterSql = buildOperatBaseFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
if (StringUtils.hasText(filterSql)) {
sql.append(" AND ").append(filterSql);
}
sql.append(") src ON cat.repCode = src.repCode ")
.append("GROUP BY cat.repCode, cat.sttpName, cat.orderIndex ")
.append(buildOperatSummaryOrderBySql(dataSourceRequest.getSort()));
Page<?> page = loadOptions == null ? null
: QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
List<EngOperatVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(
page, sql.toString(), paramMap, EngOperatVo.class);
DataSourceResult<EngOperatVo> result = new DataSourceResult<>();
result.setData(list);
result.setTotal(page == null ? list.size() : page.getTotal());
result.setAggregates(new HashMap<>());
return result;
}
private DataSourceResult<EngOperatVo> queryOperatGroupList(DataSourceRequest dataSourceRequest,
DataSourceLoadOptionsBase loadOptions) {
List<DataSourceRequest.GroupDescriptor> groups = dataSourceRequest.getGroup();
GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup();
List<String> selectItems = new ArrayList<>();
for (DataSourceRequest.GroupDescriptor descriptor : groups) {
if (descriptor == null || !StringUtils.hasText(descriptor.getField())) {
continue;
}
String column = mapOperatGroupColumn(descriptor.getField());
if (!StringUtils.hasText(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 = mapOperatGroupColumn(aggregate.getField());
if (!StringUtils.hasText(aggregateColumn) || !StringUtils.hasText(aggregate.getAggregate())) {
continue;
}
String aggregateSql = buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField());
if (StringUtils.hasText(aggregateSql)) {
selectItems.add(aggregateSql);
}
}
}
}
if (selectItems.isEmpty()) {
selectItems.add("t.STCD AS STCD");
selectItems.add("COUNT(*) AS COUNT_STCD");
}
StringBuilder sql = new StringBuilder();
sql.append("SELECT ")
.append(String.join(", ", selectItems))
.append(" FROM (")
.append(buildOperatStateViewSql())
.append(") t WHERE 1 = 1 ");
Map<String, Object> paramMap = new HashMap<>();
if (!containsOperatYearFilter(dataSourceRequest.getFilter())) {
sql.append(" AND t.yr = ").append(new Date().getYear() + 1900);
}
String filterSql = buildOperatGroupFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
if (StringUtils.hasText(filterSql)) {
sql.append(" AND ").append(filterSql);
}
List<String> groupByColumns = new ArrayList<>();
for (DataSourceRequest.GroupDescriptor descriptor : groups) {
if (descriptor == null || !StringUtils.hasText(descriptor.getField())) {
continue;
}
String column = mapOperatGroupColumn(descriptor.getField());
if (StringUtils.hasText(column)) {
groupByColumns.add(column);
}
}
if (!groupByColumns.isEmpty()) {
sql.append(" GROUP BY ").append(String.join(", ", groupByColumns));
}
sql.append(buildOperatGroupOrderBySql(groups));
List<Map<String, Object>> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap);
DataSourceResult<EngOperatVo> result = new DataSourceResult<>();
if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) {
result.setData((List<EngOperatVo>) (List<?>) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos)));
} else {
result.setData((List<EngOperatVo>) (List<?>) new GroupHelper().group(rows, Arrays.asList(groupInfos)));
}
result.setTotal(0L);
result.setAggregates(new HashMap<>());
return result;
}
@Override @Override
public DataSourceResult<EngEiaapprovalVo> getEiaapprovalKendoList(DataSourceRequest dataSourceRequest) { public DataSourceResult<EngEiaapprovalVo> getEiaapprovalKendoList(DataSourceRequest dataSourceRequest) {
DataSourceResult<EngEiaapprovalVo> result = new DataSourceResult<>(); DataSourceResult<EngEiaapprovalVo> result = new DataSourceResult<>();
@ -531,6 +967,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
"'电站' AS sttpName, " + "'电站' AS sttpName, " +
"eng.STCD AS stcd, " + "eng.STCD AS stcd, " +
"eng.ENNM AS stnm, " + "eng.ENNM AS stnm, " +
"eng.LGTD AS lgtd, " +
"eng.LTTD AS lttd, " +
"eng.REACHCD AS reachcd, " +
"eng.REACHCD_NAME AS reachcdName, " + "eng.REACHCD_NAME AS reachcdName, " +
"eng.ENNM AS ennm, " + "eng.ENNM AS ennm, " +
"eng.BASE_ID AS baseId, " + "eng.BASE_ID AS baseId, " +
@ -542,6 +981,8 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
"addv.ADDVNM AS addvcdName, " + "addv.ADDVNM AS addvcdName, " +
"hy.HYNM AS hynm, " + "hy.HYNM AS hynm, " +
"topHy.HYNM AS topHynm, " + "topHy.HYNM AS topHynm, " +
"hy.HYCD AS hycd, " +
"topHy.HYCD AS topHycd, " +
"eng.STLC AS stlc, " + "eng.STLC AS stlc, " +
"eng.JCDT AS jcdt, " + "eng.JCDT AS jcdt, " +
"eng.PIODT AS piodt, " + "eng.PIODT AS piodt, " +
@ -622,7 +1063,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
"CAST(NULL AS NUMBER) AS gncnt, " + "CAST(NULL AS NUMBER) AS gncnt, " +
"eng.GNTP AS gntp, " + "eng.GNTP AS gntp, " +
"CAST(NULL AS NUMBER) AS grntpwr, " + "CAST(NULL AS NUMBER) AS grntpwr, " +
"eng.TTPWRB AS yrge, " + "pwr.YRGE AS yrge, " +
"CAST(NULL AS NUMBER) AS ushr, " + "CAST(NULL AS NUMBER) AS ushr, " +
"CAST(NULL AS NUMBER) AS k, " + "CAST(NULL AS NUMBER) AS k, " +
"eng.DMTP AS dmtp, " + "eng.DMTP AS dmtp, " +
@ -639,6 +1080,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
" WHEN '3' THEN '混合式' " + " WHEN '3' THEN '混合式' " +
" ELSE NULL END AS dvtpName, " + " ELSE NULL END AS dvtpName, " +
"eng.DTIN AS dtin, " + "eng.DTIN AS dtin, " +
"eng.DTIN_ENV AS dtinEnv, " +
"CASE NVL(eng.DTIN, 0) " + "CASE NVL(eng.DTIN, 0) " +
" WHEN 0 THEN '否' " + " WHEN 0 THEN '否' " +
" WHEN 1 THEN '是' " + " WHEN 1 THEN '是' " +
@ -655,6 +1097,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
"LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " +
"LEFT JOIN SD_HYCD_DIC hy ON hy.HYCD = eng.HYCD AND NVL(hy.IS_DELETED, 0) = 0 AND NVL(hy.ENABLED, 1) = 1 " + "LEFT JOIN SD_HYCD_DIC hy ON hy.HYCD = eng.HYCD AND NVL(hy.IS_DELETED, 0) = 0 AND NVL(hy.ENABLED, 1) = 1 " +
"LEFT JOIN SD_HYCD_DIC topHy ON topHy.HYCD = eng.TOP_HYCD AND NVL(topHy.IS_DELETED, 0) = 0 AND NVL(topHy.ENABLED, 1) = 1 " + "LEFT JOIN SD_HYCD_DIC topHy ON topHy.HYCD = eng.TOP_HYCD AND NVL(topHy.IS_DELETED, 0) = 0 AND NVL(topHy.ENABLED, 1) = 1 " +
"LEFT JOIN SD_PWR_B_H pwr ON pwr.STCD = eng.STCD AND NVL(pwr.IS_DELETED, 0) = 0 " +
"LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " + "LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " +
"LEFT JOIN ( " + "LEFT JOIN ( " +
" SELECT det.SORT, cfg.RVCD, det.STCD " + " SELECT det.SORT, cfg.RVCD, det.STCD " +
@ -699,15 +1142,20 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
columns.put("stnm", "t.stnm AS stnm"); columns.put("stnm", "t.stnm AS stnm");
columns.put("ennm", "t.ennm AS ennm"); columns.put("ennm", "t.ennm AS ennm");
columns.put("baseId", "t.baseId AS baseId"); columns.put("baseId", "t.baseId AS baseId");
columns.put("reachcd", "t.reachcd AS reachcd");
columns.put("reachcdName", "t.reachcdName AS reachcdName"); columns.put("reachcdName", "t.reachcdName AS reachcdName");
columns.put("baseName", "t.baseName AS baseName"); columns.put("baseName", "t.baseName AS baseName");
columns.put("hbrvcd", "t.hbrvcd AS hbrvcd"); columns.put("hbrvcd", "t.hbrvcd AS hbrvcd");
columns.put("hbrvcdName", "t.hbrvcdName AS hbrvcdName"); columns.put("hbrvcdName", "t.hbrvcdName AS hbrvcdName");
columns.put("rvcd", "t.rvcd AS rvcd"); columns.put("rvcd", "t.rvcd AS rvcd");
columns.put("lgtd", "t.lgtd AS lgtd");
columns.put(" lttd", "t. lttd AS lttd");
columns.put("rvcdName", "t.rvcdName AS rvcdName"); columns.put("rvcdName", "t.rvcdName AS rvcdName");
columns.put("addvcdName", "t.addvcdName AS addvcdName"); columns.put("addvcdName", "t.addvcdName AS addvcdName");
columns.put("hynm", "t.hynm AS hynm"); columns.put("hynm", "t.hynm AS hynm");
columns.put("topHynm", "t.topHynm AS topHynm"); columns.put("topHynm", "t.topHynm AS topHynm");
columns.put("hycd", "t.hycd AS hycd");
columns.put("topHycd", "t.topHycd AS topHycd");
columns.put("stlc", "t.stlc AS stlc"); columns.put("stlc", "t.stlc AS stlc");
columns.put("jcdt", "t.jcdt AS jcdt"); columns.put("jcdt", "t.jcdt AS jcdt");
columns.put("piodt", "t.piodt AS piodt"); columns.put("piodt", "t.piodt AS piodt");
@ -969,6 +1417,410 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
return orderItems.isEmpty() ? "" : " ORDER BY " + String.join(", ", orderItems); return orderItems.isEmpty() ? "" : " ORDER BY " + String.join(", ", orderItems);
} }
private String buildOperatCategorySql() {
return "SELECT STTP_CODE AS repCode, STTP_NAME AS sttpName, ORDER_INDEX AS orderIndex " +
"FROM SD_STTP_B WHERE NVL(IS_DELETED, 0) = 0 " +
"AND STTP_CODE IN ('FP', 'DW', 'VP', 'FB', 'VA', 'FH', 'EQ')";
}
private String buildOperatBaseViewSql() {
return buildOperatBaseSelectSql("vp.STCD", "vp.STNM", "vp.STTP", "vp.DTIN", "vp.BLDSTT_CODE",
"NVL(vp.BASE_ID, eng.BASE_ID)", "NVL(vp.HBRVCD, eng.HBRVCD)", "eng.RVCD", "eng.RVCD_NAME",
"eng.ADDVCD_NAME", "vp.RSTCD", "eng.ENNM", "SD_VP_B_H vp",
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = vp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0",
"NVL(vp.IS_DELETED, 0) = 0") +
" UNION ALL " +
buildOperatBaseSelectSql("fb.STCD", "fb.STNM", "fb.STTP", "fb.DTIN", "fb.BLDSTT_CODE",
"NVL(fb.BASE_ID, eng.BASE_ID)", "NVL(fb.HBRVCD, eng.HBRVCD)", "eng.RVCD", "eng.RVCD_NAME",
"eng.ADDVCD_NAME", "fb.RSTCD", "eng.ENNM", "SD_FBRD_B_H fb",
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD AND NVL(eng.IS_DELETED, 0) = 0",
" 1=1 "
// "NVL(fb.IS_DELETED, 0) = 0"
) +
" UNION ALL " +
buildOperatBaseSelectSql("va.STCD", "va.STNM", "va.STTP", "va.DTIN", "va.BLDSTT_CODE",
"NVL(va.BASE_ID, eng.BASE_ID)", "NVL(va.HBRVCD, eng.HBRVCD)", "eng.RVCD", "eng.RVCD_NAME",
"eng.ADDVCD_NAME", "va.RSTCD", "eng.ENNM", "SD_VA_B_H va",
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = va.RSTCD AND NVL(eng.IS_DELETED, 0) = 0",
"NVL(va.IS_DELETED, 0) = 0") +
" UNION ALL " +
buildOperatBaseSelectSql("fh.STCD", "fh.STNM", "'FH'", "fh.DTIN", "NULL",
"NVL(fh.BASE_ID, eng.BASE_ID)", "NVL(fh.HBRVCD, eng.HBRVCD)", "NVL(fh.RVCD, eng.RVCD)",
"NVL(eng.RVCD_NAME, NULL)", "eng.ADDVCD_NAME", "fh.RSTCD", "eng.ENNM", "SD_FHBT_B_H fh",
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fh.RSTCD AND NVL(eng.IS_DELETED, 0) = 0",
"NVL(fh.IS_DELETED, 0) = 0") +
" UNION ALL " +
buildOperatBaseSelectSql("dw.STCD", "dw.STNM", "dw.STTP", "dw.DTIN", "dw.BLDSTT_CODE",
"eng.BASE_ID", "eng.HBRVCD", "eng.RVCD", "eng.RVCD_NAME", "eng.ADDVCD_NAME", "dw.RSTCD",
"eng.ENNM", "SD_DFLTKW_B_H dw",
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = dw.RSTCD AND NVL(eng.IS_DELETED, 0) = 0",
"NVL(dw.IS_DELETED, 0) = 0") +
" UNION ALL " +
buildOperatBaseSelectSql("fp.STCD", "fp.STNM", "fp.STTP", "fp.DTIN", "fp.BLDSTT_CODE",
"eng.BASE_ID", "eng.HBRVCD", "eng.RVCD", "eng.RVCD_NAME", "eng.ADDVCD_NAME", "fp.RSTCD",
"eng.ENNM", "SD_FPSS_B_H fp",
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0",
"1 = 1") +
" UNION ALL " +
buildOperatBaseSelectSql("eq.STCD", "eq.STNM", "eq.STTP", "eq.DTIN", "eq.BLDSTT_CODE",
"NVL(eq.BASE_ID, eng.BASE_ID)", "NVL(eq.HBRVCD, eng.HBRVCD)", "eng.RVCD", "eng.RVCD_NAME",
"eng.ADDVCD_NAME", "eq.RSTCD", "eng.ENNM", "SD_EQ_B_H eq",
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = eq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0",
"NVL(eq.IS_DELETED, 0) = 0");
}
private String buildOperatBaseSelectSql(String stcdExpr,
String stnmExpr,
String sttpExpr,
String dtinExpr,
String bldsttExpr,
String baseIdExpr,
String hbrvcdExpr,
String rvcdExpr,
String rvcdNameExpr,
String addvcdNameExpr,
String rstcdExpr,
String ennmExpr,
String fromSql,
String joinSql,
String whereSql) {
return "SELECT " +
stcdExpr + " AS stcd, " +
stnmExpr + " AS stnm, " +
sttpExpr + " AS sttpCode, " +
"CASE WHEN INSTR(" + sttpExpr + ", '_') > 0 THEN SUBSTR(" + sttpExpr + ", 1, INSTR(" + sttpExpr + ", '_') - 1) ELSE " + sttpExpr + " END AS repCode, " +
dtinExpr + " AS dtin, " +
bldsttExpr + " AS bldsttCcode, " +
baseIdExpr + " AS baseId, " +
hbrvcdExpr + " AS hbrvcd, " +
rvcdExpr + " AS rvcd, " +
rvcdNameExpr + " AS rvcdName, " +
addvcdNameExpr + " AS addvcdName, " +
rstcdExpr + " AS rstcd, " +
ennmExpr + " AS ennm " +
"FROM " + fromSql + " " +
joinSql + " WHERE " + whereSql;
}
private String buildOperatStateViewSql() {
return "SELECT " +
"src.repCode AS repCode, " +
"src.sttpCode AS sttpCode, " +
"src.repCode AS pcode, " +
"parent.STTP_NAME AS pname, " +
"child.STTP_NAME AS sttpName, " +
"src.stcd AS stcd, " +
"src.ennm AS ennm, " +
"src.stnm AS stnm, " +
"src.addvcdName AS addvcdName, " +
"src.rvcdName AS rvcdName, " +
"src.baseId AS baseId, " +
"src.dtin AS dtin, " +
"src.bldsttCcode AS bldsttCcode, " +
"state.RUN_STATE AS runState, " +
"state.STD_STATE AS stdState, " +
"state.STD_SSTATE AS runSstate, " +
"state.YR AS yr " +
"FROM (" + buildOperatBaseViewSql() + ") src " +
"LEFT JOIN SD_STTP_B child ON child.STTP_CODE = src.sttpCode AND NVL(child.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_STTP_B parent ON parent.STTP_CODE = src.repCode AND NVL(parent.IS_DELETED, 0) = 0 " +
"INNER JOIN MS_STSTATE_T state ON state.STCD = src.stcd AND NVL(state.IS_DELETED, 0) = 0";
}
private String buildOperatSummarySelectSql(List<String> selectFields) {
Map<String, String> columnMap = new LinkedHashMap<>();
columnMap.put("repCode", "cat.repCode AS repCode");
columnMap.put("sttpName", "cat.sttpName AS sttpName");
columnMap.put("count", "COUNT(src.repCode) AS count");
List<String> items = new ArrayList<>();
if (CollUtil.isNotEmpty(selectFields)) {
for (String field : selectFields) {
String column = columnMap.get(field);
if (StringUtils.hasText(column)) {
items.add(column);
}
}
}
if (items.isEmpty()) {
items.addAll(columnMap.values());
}
return String.join(", ", items);
}
private String buildOperatSummaryOrderBySql(List<DataSourceRequest.SortDescriptor> sortList) {
if (CollUtil.isEmpty(sortList)) {
return " ORDER BY cat.orderIndex ASC NULLS LAST, cat.repCode ASC";
}
List<String> orderItems = new ArrayList<>();
for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) {
if (sortDescriptor == null || !StringUtils.hasText(sortDescriptor.getField())) {
continue;
}
String column = mapOperatSummaryColumn(sortDescriptor.getField());
if (!StringUtils.hasText(column)) {
continue;
}
String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) || "des".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC";
orderItems.add(column + " " + dir);
}
if (orderItems.isEmpty()) {
return " ORDER BY cat.orderIndex ASC NULLS LAST, cat.repCode ASC";
}
return " ORDER BY " + String.join(", ", orderItems);
}
private String buildOperatBaseFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
if (filter == null) {
return "";
}
if (StringUtils.hasText(filter.getField())) {
String column = mapOperatBaseColumn(filter.getField());
return buildOperatCondition(column, filter, paramMap, indexHolder, false, "operatBase");
}
if (CollUtil.isEmpty(filter.getFilters())) {
return "";
}
List<String> childConditions = new ArrayList<>();
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
String childSql = buildOperatBaseFilterCondition(child, paramMap, indexHolder);
if (StringUtils.hasText(childSql)) {
childConditions.add("(" + childSql + ")");
}
}
if (childConditions.isEmpty()) {
return "";
}
String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND ";
return String.join(logic, childConditions);
}
private String buildOperatGroupFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
if (filter == null) {
return "";
}
if (StringUtils.hasText(filter.getField())) {
String field = filter.getField();
String column = mapOperatGroupColumn(field);
boolean dateField = false;
return buildOperatCondition(column, filter, paramMap, indexHolder, dateField, "operatGroup");
}
if (CollUtil.isEmpty(filter.getFilters())) {
return "";
}
List<String> childConditions = new ArrayList<>();
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
String childSql = buildOperatGroupFilterCondition(child, paramMap, indexHolder);
if (StringUtils.hasText(childSql)) {
childConditions.add("(" + childSql + ")");
}
}
if (childConditions.isEmpty()) {
return "";
}
String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND ";
return String.join(logic, childConditions);
}
private String buildOperatCondition(String column,
DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder,
boolean dateField,
String keyPrefix) {
if (!StringUtils.hasText(column) || filter == null) {
return "";
}
String operator = filter.getOperator() == null ? "eq" : filter.getOperator().toLowerCase();
Object value = filter.getValue();
if ("isnull".equals(operator)) {
return column + " IS NULL";
}
if ("isnotnull".equals(operator)) {
return column + " IS NOT NULL";
}
if ("isempty".equals(operator)) {
return "(" + column + " IS NULL OR " + column + " = '')";
}
if ("isnotempty".equals(operator)) {
return "(" + column + " IS NOT NULL AND " + column + " <> '')";
}
if ("in".equals(operator) || "ni".equals(operator)) {
List<Object> values = normalizeFilterValues(value);
if (values.isEmpty()) {
return "";
}
List<String> placeholders = new ArrayList<>();
for (Object item : values) {
String key = keyPrefix + indexHolder[0]++;
paramMap.put(key, item);
placeholders.add("#{map." + key + "}");
}
return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")";
}
if (value == null) {
return "";
}
String key = keyPrefix + indexHolder[0]++;
String expr = buildOperatValueExpr(key, dateField, value);
return switch (operator) {
case "eq" -> {
paramMap.put(key, value);
yield column + " = " + expr;
}
case "neq" -> {
paramMap.put(key, value);
yield column + " <> " + expr;
}
case "contains" -> {
paramMap.put(key, "%" + value + "%");
yield column + " LIKE #{map." + key + "}";
}
case "doesnotcontain" -> {
paramMap.put(key, "%" + value + "%");
yield column + " NOT LIKE #{map." + key + "}";
}
case "startswith" -> {
paramMap.put(key, value + "%");
yield column + " LIKE #{map." + key + "}";
}
case "endswith" -> {
paramMap.put(key, "%" + value);
yield column + " LIKE #{map." + key + "}";
}
case "gt" -> {
paramMap.put(key, value);
yield column + " > " + expr;
}
case "gte" -> {
paramMap.put(key, value);
yield column + " >= " + expr;
}
case "lt" -> {
paramMap.put(key, value);
yield column + " < " + expr;
}
case "lte" -> {
paramMap.put(key, value);
yield column + " <= " + expr;
}
default -> "";
};
}
private String buildOperatValueExpr(String paramKey, boolean dateField, Object value) {
if (!dateField || value == null) {
return "#{map." + paramKey + "}";
}
String text = String.valueOf(value).trim();
if (text.length() <= 10) {
return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')";
}
return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')";
}
private String mapOperatSummaryColumn(String field) {
if (!StringUtils.hasText(field)) {
return null;
}
return switch (field) {
case "repCode" -> "cat.repCode";
case "sttpName" -> "cat.sttpName";
case "count" -> "COUNT(src.repCode)";
default -> null;
};
}
private String mapOperatBaseColumn(String field) {
if (!StringUtils.hasText(field)) {
return null;
}
return switch (field) {
case "repCode" -> "t.repCode";
case "sttpCode" -> "t.sttpCode";
case "stcd" -> "t.stcd";
case "stnm" -> "t.stnm";
case "rstcd" -> "t.rstcd";
case "ennm" -> "t.ennm";
case "baseId", "baseid" -> "t.baseId";
case "hbrvcd" -> "t.hbrvcd";
case "rvcdName" -> "t.rvcdName";
case "addvcdName" -> "t.addvcdName";
case "dtin" -> "t.dtin";
case "bldsttCcode" -> "t.bldsttCcode";
default -> null;
};
}
private String mapOperatGroupColumn(String field) {
if (!StringUtils.hasText(field)) {
return null;
}
return switch (field) {
case "repCode" -> "t.repCode";
case "sttpCode" -> "t.sttpCode";
case "pcode" -> "t.pcode";
case "pname" -> "t.pname";
case "sttpName" -> "t.sttpName";
case "stcd" -> "t.stcd";
case "ennm" -> "t.ennm";
case "stnm" -> "t.stnm";
case "addvcdName" -> "t.addvcdName";
case "rvcdName" -> "t.rvcdName";
case "baseId", "baseid" -> "t.baseId";
case "dtin" -> "t.dtin";
case "runState" -> "t.runState";
case "stdState" -> "t.stdState";
case "runSstate" -> "t.runSstate";
case "bldsttCcode" -> "t.bldsttCcode";
case "yr" -> "t.yr";
default -> null;
};
}
private String buildOperatGroupOrderBySql(List<DataSourceRequest.GroupDescriptor> groups) {
if (CollUtil.isEmpty(groups)) {
return "";
}
List<String> orderItems = new ArrayList<>();
for (DataSourceRequest.GroupDescriptor descriptor : groups) {
if (descriptor == null || !StringUtils.hasText(descriptor.getField())) {
continue;
}
String column = mapOperatGroupColumn(descriptor.getField());
if (!StringUtils.hasText(column)) {
continue;
}
String dir = "desc".equalsIgnoreCase(descriptor.getDir()) || "des".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC";
orderItems.add(column + " " + dir);
}
if (orderItems.isEmpty()) {
return "";
}
return " ORDER BY " + String.join(", ", orderItems);
}
private boolean containsOperatYearFilter(DataSourceRequest.FilterDescriptor filter) {
if (filter == null) {
return false;
}
if ("yr".equalsIgnoreCase(filter.getField())) {
return true;
}
if (CollUtil.isEmpty(filter.getFilters())) {
return false;
}
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
if (containsOperatYearFilter(child)) {
return true;
}
}
return false;
}
private String buildAggregateSql(String aggregate, String column, String field) { private String buildAggregateSql(String aggregate, String column, String field) {
String upperField = field == null ? "" : field.toUpperCase(); String upperField = field == null ? "" : field.toUpperCase();
return switch (aggregate.toLowerCase()) { return switch (aggregate.toLowerCase()) {
@ -987,10 +1839,12 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
} }
return switch (field) { return switch (field) {
case "id" -> "t.id"; case "id" -> "t.id";
case "sttp" -> "t.sttp";
case "sttpCode" -> "t.sttpCode"; case "sttpCode" -> "t.sttpCode";
case "sttpName" -> "t.sttpName"; case "sttpName" -> "t.sttpName";
case "stcd" -> "t.stcd"; case "stcd" -> "t.stcd";
case "stnm", "ennm" -> "t.stnm"; case "stnm", "ennm" -> "t.stnm";
case "dtinEnv" -> "t.dtinEnv";
case "baseId" -> "t.baseId"; case "baseId" -> "t.baseId";
case "baseName" -> "t.baseName"; case "baseName" -> "t.baseName";
case "hbrvcd" -> "t.hbrvcd"; case "hbrvcd" -> "t.hbrvcd";

View File

@ -72,6 +72,9 @@ public class FpFpssrlQueryVo {
@Schema(description = "游向") @Schema(description = "游向")
private String direction; private String direction;
@Schema(description = "游向中文")
private String directionName;
@Schema(description = "水温") @Schema(description = "水温")
private String temperature; private String temperature;

View File

@ -199,8 +199,11 @@ public class FpVmsstbprptVo implements Serializable {
@Schema(description = "升鱼机集鱼槽水深") @Schema(description = "升鱼机集鱼槽水深")
private String syjwdp; private String syjwdp;
// @Schema(description = "设计过鱼规模")
// private Integer sjgycnt;
@Schema(description = "设计过鱼规模") @Schema(description = "设计过鱼规模")
private Integer sjgycnt; private String sjgycnt;
@Schema(description = "主要过鱼对象描述") @Schema(description = "主要过鱼对象描述")
private String zygydxms; private String zygydxms;

View File

@ -337,7 +337,7 @@ public class FpBuildServiceImpl implements FpBuildService {
.append("fp.YDCSPD AS ydcspd, ") .append("fp.YDCSPD AS ydcspd, ")
.append("fp.YDCSCNT AS ydcscnt, ") .append("fp.YDCSCNT AS ydcscnt, ")
.append("fp.YDXXCCNT AS ydxxccnt, ") .append("fp.YDXXCCNT AS ydxxccnt, ")
.append("fp.V AS v, ") .append("fp.FLOW AS flow, ")
.append("fp.FZRDMXZ AS fzrdmxz, ") .append("fp.FZRDMXZ AS fzrdmxz, ")
.append("fp.FZRTDSZ AS fzrtdsz, ") .append("fp.FZRTDSZ AS fzrtdsz, ")
.append("fp.FZRYXWDP AS fzryxwdp, ") .append("fp.FZRYXWDP AS fzryxwdp, ")
@ -858,7 +858,7 @@ public class FpBuildServiceImpl implements FpBuildService {
columnMap.put("ydcspd", "fp.YDCSPD"); columnMap.put("ydcspd", "fp.YDCSPD");
columnMap.put("ydcscnt", "fp.YDCSCNT"); columnMap.put("ydcscnt", "fp.YDCSCNT");
columnMap.put("ydxxccnt", "fp.YDXXCCNT"); columnMap.put("ydxxccnt", "fp.YDXXCCNT");
columnMap.put("v", "fp.V"); columnMap.put("flow", "fp.flow");
columnMap.put("fzrdmxz", "fp.FZRDMXZ"); columnMap.put("fzrdmxz", "fp.FZRDMXZ");
columnMap.put("fzrtdsz", "fp.FZRTDSZ"); columnMap.put("fzrtdsz", "fp.FZRTDSZ");
columnMap.put("fzryxwdp", "fp.FZRYXWDP"); columnMap.put("fzryxwdp", "fp.FZRYXWDP");

View File

@ -1635,6 +1635,7 @@ public class FpRunServiceImpl implements FpRunService {
selectMap.put("width", "t.width AS width"); selectMap.put("width", "t.width AS width");
selectMap.put("fishspeed", "t.fishspeed AS fishspeed"); selectMap.put("fishspeed", "t.fishspeed AS fishspeed");
selectMap.put("direction", "t.direction AS direction"); 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("temperature", "t.temperature AS temperature");
selectMap.put("speed", "t.speed AS speed"); selectMap.put("speed", "t.speed AS speed");
selectMap.put("channelno", "t.channelno AS channelno"); selectMap.put("channelno", "t.channelno AS channelno");

View File

@ -1738,7 +1738,7 @@ public class VpConstructionServiceImpl implements VpConstructionService {
columnMap.put("runState", "vp.RUN_STATE"); columnMap.put("runState", "vp.RUN_STATE");
columnMap.put("runStateName", "CASE NVL(vp.RUN_STATE, -1) WHEN 1 THEN '运行' WHEN 0 THEN '未运行' ELSE NULL END"); columnMap.put("runStateName", "CASE NVL(vp.RUN_STATE, -1) WHEN 1 THEN '运行' WHEN 0 THEN '未运行' ELSE NULL END");
columnMap.put("baseStepSort", "hb.ORDER_INDEX"); columnMap.put("baseStepSort", "hb.ORDER_INDEX");
columnMap.put("rvcdStepSort", "hbrv.ORDER_INDEX"); // columnMap.put("rvcdStepSort", "hbrv.ORDER_INDEX");
columnMap.put("rstcdStepSort", "eng.ORDER_INDEX"); columnMap.put("rstcdStepSort", "eng.ORDER_INDEX");
columnMap.put("siteStepSort", "vp.ORDER_INDEX"); columnMap.put("siteStepSort", "vp.ORDER_INDEX");
return columnMap.get(field); return columnMap.get(field);

View File

@ -1179,26 +1179,33 @@ public class VdMonitorServiceImpl implements VdMonitorService {
private List<Object> normalizeValues(Object value) { private List<Object> normalizeValues(Object value) {
List<Object> values = new ArrayList<>(); List<Object> values = new ArrayList<>();
appendNormalizedValues(values, value);
return values;
}
private void appendNormalizedValues(List<Object> values, Object value) {
if (value == null) {
return;
}
if (value instanceof List<?> list) { if (value instanceof List<?> list) {
for (Object item : list) { for (Object item : list) {
if (item != null) { appendNormalizedValues(values, item);
values.add(item);
}
} }
return values; return;
} }
if (value instanceof Object[] array) { if (value instanceof Object[] array) {
for (Object item : array) { for (Object item : array) {
if (item != null) { appendNormalizedValues(values, item);
values.add(item);
}
} }
return values; return;
} }
if (value != null) { if (value instanceof String text) {
values.add(value); if (StrUtil.isNotBlank(text)) {
values.add(text);
}
return;
} }
return values; values.add(value);
} }
private String mapVdTreeColumn(String field) { private String mapVdTreeColumn(String field) {

View File

@ -51,9 +51,15 @@ public class StcdWarnStateVo {
@Schema(description = "基础排序") @Schema(description = "基础排序")
private Integer baseStepSort; private Integer baseStepSort;
@Schema(description = "流域排序")
private Integer rvcdStepSort;
@Schema(description = "电站排序") @Schema(description = "电站排序")
private Integer rstcdStepSort; private Integer rstcdStepSort;
@Schema(description = "站点排序")
private Integer siteStepSort;
@Schema(description = "数据接入类型") @Schema(description = "数据接入类型")
private Integer dtinType; private Integer dtinType;
} }

View File

@ -325,7 +325,9 @@ public class WarnDataServiceImpl implements WarnDataService {
.append("r.rvcd AS rvcd, ") .append("r.rvcd AS rvcd, ")
.append("r.warnState AS warnState, ") .append("r.warnState AS warnState, ")
.append("r.baseStepSort AS baseStepSort, ") .append("r.baseStepSort AS baseStepSort, ")
.append("r.rvcdStepSort AS rvcdStepSort, ")
.append("r.rstcdStepSort AS rstcdStepSort, ") .append("r.rstcdStepSort AS rstcdStepSort, ")
.append("r.siteStepSort AS siteStepSort, ")
.append("r.dtinType AS dtinType ") .append("r.dtinType AS dtinType ")
.append("FROM (") .append("FROM (")
.append(buildWarnStcdDetailSql(warnType)) .append(buildWarnStcdDetailSql(warnType))
@ -369,18 +371,16 @@ public class WarnDataServiceImpl implements WarnDataService {
String normalizedWarnStateExpr = "CASE " + String normalizedWarnStateExpr = "CASE " +
"WHEN eng.WARN_STATE = '0' OR eng.WARN_STATE IS NULL OR eng.WARN_STATE = '' THEN '00' " + "WHEN eng.WARN_STATE = '0' OR eng.WARN_STATE IS NULL OR eng.WARN_STATE = '' THEN '00' " +
"ELSE eng.WARN_STATE END"; "ELSE eng.WARN_STATE END";
String nonEngWarnStateExpr = "CASE state.STD_SSTATE " + String wqWarnStateExpr = "TO_NUMBER(NULLIF(wq.WARN_STATE, ''))";
"WHEN 2 THEN 0 " + String wtWarnStateExpr = "TO_NUMBER(NULLIF(wt.WARN_STATE, ''))";
"WHEN 3 THEN 2 " +
"ELSE state.STD_SSTATE END";
List<String> parts = new ArrayList<>(); List<String> parts = new ArrayList<>();
if ("QEC".equalsIgnoreCase(warnType)) { if ("QEC".equalsIgnoreCase(warnType)) {
parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType)); parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType));
} else { } else {
parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType)); parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType));
parts.add(buildWarnStcdWqSql(nonEngWarnStateExpr)); parts.add(buildWarnStcdWqSql(wqWarnStateExpr));
parts.add(buildWarnStcdWtSql(nonEngWarnStateExpr)); parts.add(buildWarnStcdWtSql(wtWarnStateExpr));
} }
return String.join(" UNION ALL ", parts); return String.join(" UNION ALL ", parts);
} }
@ -409,11 +409,14 @@ public class WarnDataServiceImpl implements WarnDataService {
.append("eng.HBRVCD AS rvcd, ") .append("eng.HBRVCD AS rvcd, ")
.append(warnStateExpr).append(" AS warnState, ") .append(warnStateExpr).append(" AS warnState, ")
.append("hb.ORDER_INDEX AS baseStepSort, ") .append("hb.ORDER_INDEX AS baseStepSort, ")
.append("along.ORDER_INDEX AS rvcdStepSort, ")
.append("eng.ORDER_INDEX AS rstcdStepSort, ") .append("eng.ORDER_INDEX AS rstcdStepSort, ")
.append("eng.ORDER_INDEX AS siteStepSort, ")
.append("CAST(NULL AS NUMBER) AS dtinType ") .append("CAST(NULL AS NUMBER) AS dtinType ")
.append("FROM SD_ENGINFO_B_H eng ") .append("FROM SD_ENGINFO_B_H eng ")
.append("LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = 'ENG' AND NVL(sttp.IS_DELETED, 0) = 0 ") .append("LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = 'ENG' AND NVL(sttp.IS_DELETED, 0) = 0 ")
.append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 ") .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 ")
.append("LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 ")
.append("WHERE NVL(eng.IS_DELETED, 0) = 0 "); .append("WHERE NVL(eng.IS_DELETED, 0) = 0 ");
if ("QEC".equalsIgnoreCase(warnType)) { if ("QEC".equalsIgnoreCase(warnType)) {
sql.append("AND NVL(eng.BLDSTT_CODE, -1) = 2 ") sql.append("AND NVL(eng.BLDSTT_CODE, -1) = 2 ")
@ -439,12 +442,15 @@ public class WarnDataServiceImpl implements WarnDataService {
"eng.HBRVCD AS rvcd, " + "eng.HBRVCD AS rvcd, " +
warnStateExpr + " AS warnState, " + warnStateExpr + " AS warnState, " +
"hb.ORDER_INDEX AS baseStepSort, " + "hb.ORDER_INDEX AS baseStepSort, " +
"along.ORDER_INDEX AS rvcdStepSort, " +
"eng.ORDER_INDEX AS rstcdStepSort, " + "eng.ORDER_INDEX AS rstcdStepSort, " +
"siteAlong.SORT AS siteStepSort, " +
"wq.DTIN_TYPE AS dtinType " + "wq.DTIN_TYPE AS dtinType " +
"FROM SD_WQ_B_H wq " + "FROM SD_WQ_B_H wq " +
"LEFT JOIN (" + buildWarnStcdLatestStateSql() + ") state ON state.STCD = wq.STCD AND state.STTP_CODE = wq.STTP " +
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.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_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " +
"LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " +
"LEFT JOIN MS_ALONGDET_B siteAlong ON siteAlong.ALONG_ID = along.ID AND siteAlong.STCD = wq.STCD AND NVL(siteAlong.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wq.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wq.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " +
"WHERE NVL(wq.IS_DELETED, 0) = 0 " + "WHERE NVL(wq.IS_DELETED, 0) = 0 " +
"AND NVL(wq.USFL, 0) = 1 " + "AND NVL(wq.USFL, 0) = 1 " +
@ -465,30 +471,21 @@ public class WarnDataServiceImpl implements WarnDataService {
"eng.HBRVCD AS rvcd, " + "eng.HBRVCD AS rvcd, " +
warnStateExpr + " AS warnState, " + warnStateExpr + " AS warnState, " +
"hb.ORDER_INDEX AS baseStepSort, " + "hb.ORDER_INDEX AS baseStepSort, " +
"along.ORDER_INDEX AS rvcdStepSort, " +
"eng.ORDER_INDEX AS rstcdStepSort, " + "eng.ORDER_INDEX AS rstcdStepSort, " +
"siteAlong.SORT AS siteStepSort, " +
"wt.DTIN_TYPE AS dtinType " + "wt.DTIN_TYPE AS dtinType " +
"FROM SD_WT_B_H wt " + "FROM SD_WT_B_H wt " +
"LEFT JOIN (" + buildWarnStcdLatestStateSql() + ") state ON state.STCD = wt.STCD AND state.STTP_CODE = wt.STTP " +
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.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_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " +
"LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " +
"LEFT JOIN MS_ALONGDET_B siteAlong ON siteAlong.ALONG_ID = along.ID AND siteAlong.STCD = wt.STCD AND NVL(siteAlong.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wt.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wt.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " +
"WHERE NVL(wt.IS_DELETED, 0) = 0 " + "WHERE NVL(wt.IS_DELETED, 0) = 0 " +
"AND NVL(wt.USFL, 0) = 1 " + "AND NVL(wt.USFL, 0) = 1 " +
"AND wt.STTP = 'WTRV' "; "AND wt.STTP = 'WTRV' ";
} }
private String buildWarnStcdLatestStateSql() {
return "SELECT s.STCD, s.STTP_CODE, s.STD_SSTATE " +
"FROM MS_STSTATE_T s " +
"INNER JOIN (" +
"SELECT STCD, MAX(YR) AS MAX_YR " +
"FROM MS_STSTATE_T " +
"WHERE NVL(IS_DELETED, 0) = 0 " +
"GROUP BY STCD" +
") mx ON mx.STCD = s.STCD AND mx.MAX_YR = s.YR " +
"WHERE NVL(s.IS_DELETED, 0) = 0";
}
private String buildWarnStcdFilterCondition(DataSourceRequest.FilterDescriptor filter, private String buildWarnStcdFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap, Map<String, Object> paramMap,
int[] indexHolder) { int[] indexHolder) {
@ -595,6 +592,10 @@ public class WarnDataServiceImpl implements WarnDataService {
case "baseName" -> "r.baseName"; case "baseName" -> "r.baseName";
case "rvcd" -> "r.rvcd"; case "rvcd" -> "r.rvcd";
case "warnState" -> "r.warnState"; case "warnState" -> "r.warnState";
case "baseStepSort" -> "r.baseStepSort";
case "rvcdStepSort" -> "r.rvcdStepSort";
case "rstcdStepSort" -> "r.rstcdStepSort";
case "siteStepSort" -> "r.siteStepSort";
case "dtinType" -> "r.dtinType"; case "dtinType" -> "r.dtinType";
default -> null; default -> null;
}; };

View File

@ -9,6 +9,7 @@ import com.yfd.platform.common.exception.BizException;
import com.yfd.platform.config.ResponseResult; import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo;
import com.yfd.platform.qgc_env.wt.entity.vo.WtrvInfo; import com.yfd.platform.qgc_env.wt.entity.vo.WtrvInfo;
import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendSaveVo;
import com.yfd.platform.qgc_env.wt.service.*; import com.yfd.platform.qgc_env.wt.service.*;
import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.QgcQueryWrapperUtil;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -17,6 +18,7 @@ import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map; import java.util.Map;
@RestController @RestController
@ -197,6 +199,25 @@ public class SdWTMonitorController {
return ResponseResult.successData(sdWtMonitorService.getMsstbprptList(dataSourceRequest)); return ResponseResult.successData(sdWtMonitorService.getMsstbprptList(dataSourceRequest));
} }
@PostMapping("/msstbprpt/eng/GetKendoList")
@Operation(summary = "根据条件查询电站页水温基础站点列表")
public ResponseResult getMsstbprptEngList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(sdWtMonitorService.getMsstbprptEngList(dataSourceRequest));
}
@PostMapping("/wtrvAmend/dayAmend/GetKendoListCust")
@Operation(summary = "水温日数据统计修正结果数据")
public ResponseResult getWtrvAmendDayList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(sdWtMonitorService.getWtrvAmendDayList(dataSourceRequest));
}
@PostMapping("/wtrvAmend/dayAmend/saveAmendData")
@Operation(summary = "保存修正后的河道水温日数据")
public ResponseResult saveWtrvAmendData(@RequestBody List<WtrvAmendSaveVo> amendDataList) {
sdWtMonitorService.saveWtrvAmendData(amendDataList);
return ResponseResult.success();
}
@GetMapping("/msstbprpt/getStcdInfo") @GetMapping("/msstbprpt/getStcdInfo")
@Operation(summary = "根据站码查询单条水温基础数据") @Operation(summary = "根据站码查询单条水温基础数据")
public ResponseResult getStcdInfo(@RequestParam String stcd) { public ResponseResult getStcdInfo(@RequestParam String stcd) {

View File

@ -74,6 +74,15 @@ public class SdWtBaseInfoVO implements Serializable {
@Schema(description = "所属电站编码") @Schema(description = "所属电站编码")
private String rstcd; private String rstcd;
@Schema(description = "设备类型")
private Integer wtDeviceType;
@Schema(description = "接入类型")
private Integer dtinType;
@Schema(description = "监测方式")
private Integer mway;
@Schema(description = "所属测站编码") @Schema(description = "所属测站编码")
private String stCode; private String stCode;

View File

@ -0,0 +1,38 @@
package com.yfd.platform.qgc_env.wt.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;
@Data
@Schema(description = "水温日数据统计修正结果数据")
public class WtrvAmendResultVo {
@Schema(description = "站点编码")
private String stcd;
@Schema(description = "日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date dt;
@Schema(description = "温度")
private BigDecimal wt;
@Schema(description = "站点名称")
private String stnm;
@Schema(description = "电站编码")
private String rstcd;
@Schema(description = "电站名称")
private String ennm;
@Schema(description = "基地编码")
private String baseId;
@Schema(description = "基地名称")
private String baseName;
}

View File

@ -0,0 +1,20 @@
package com.yfd.platform.qgc_env.wt.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "河道水温日修正保存入参")
public class WtrvAmendSaveVo {
@Schema(description = "站点编码")
private String stcd;
@Schema(description = "日期,支持 yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss")
private String dt;
@Schema(description = "修正后水温")
private BigDecimal wt;
}

View File

@ -10,7 +10,9 @@ 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.SttpInfoVo;
import com.yfd.platform.qgc_env.wt.entity.vo.WbsbVo; 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.WtBaseInfoVo;
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.WtrvVo;
import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendResultVo;
import java.util.List; import java.util.List;
@ -22,6 +24,12 @@ public interface SdWtMonitorService {
DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest); DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest);
DataSourceResult getMsstbprptEngList(DataSourceRequest dataSourceRequest);
DataSourceResult<WtrvAmendResultVo> getWtrvAmendDayList(DataSourceRequest dataSourceRequest);
void saveWtrvAmendData(List<WtrvAmendSaveVo> amendDataList);
WtBaseInfoVo getStcdInfo(String stcd); WtBaseInfoVo getStcdInfo(String stcd);
DataSourceResult getCxDetailList(DataSourceRequest dataSourceRequest); DataSourceResult getCxDetailList(DataSourceRequest dataSourceRequest);

View File

@ -1,5 +1,6 @@
package com.yfd.platform.qgc_env.wt.service.impl; package com.yfd.platform.qgc_env.wt.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.common.*; import com.yfd.platform.common.*;
@ -16,13 +17,17 @@ 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.WtBaseInfoVo;
import com.yfd.platform.qgc_env.wt.entity.vo.WtFishVo; 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.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.WtrvVo;
import com.yfd.platform.qgc_env.wt.mapper.SdWtMonitorMapper; import com.yfd.platform.qgc_env.wt.mapper.SdWtMonitorMapper;
import com.yfd.platform.qgc_env.wt.service.SdWtMonitorService; import com.yfd.platform.qgc_env.wt.service.SdWtMonitorService;
import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.QgcQueryWrapperUtil;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.Data; import lombok.Data;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
@ -46,6 +51,9 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
@Resource @Resource
private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; private MicroservicDynamicSQLMapper microservicDynamicSQLMapper;
@Resource
private JdbcTemplate jdbcTemplate;
@Override @Override
public DataSourceResult getEvnmAutoMonitorList(DataSourceRequest dataSourceRequest) { public DataSourceResult getEvnmAutoMonitorList(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
@ -856,14 +864,7 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
StringBuilder sql = new StringBuilder(); StringBuilder sql = new StringBuilder();
sql.append("SELECT ").append(selectSql).append(" ") sql.append("SELECT ").append(selectSql).append(" ")
.append("FROM SD_WT_B_H wt ") .append(buildWtMsstbprptFromSql());
.append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ")
.append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 ")
.append("LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD AND hbrv.BASEID = eng.BASE_ID AND NVL(hbrv.IS_DELETED, 0) = 0 ")
.append("LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wt.STTP AND NVL(sttp.IS_DELETED, 0) = 0 ")
.append("LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTRV_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) rvRecent ON rvRecent.STCD = wt.STCD ")
.append("LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTVT_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) vtRecent ON vtRecent.STCD = wt.STCD ")
.append("WHERE NVL(wt.IS_DELETED, 0) = 0 AND NVL(wt.DTIN_TYPE, 0) = 0 ");
Map<String, Object> paramMap = new HashMap<>(); Map<String, Object> paramMap = new HashMap<>();
appendWtMsstbprptFilters(sql, paramMap, dataSourceRequest == null ? null : dataSourceRequest.getFilter()); appendWtMsstbprptFilters(sql, paramMap, dataSourceRequest == null ? null : dataSourceRequest.getFilter());
@ -880,6 +881,74 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
return result; return result;
} }
@Override
public DataSourceResult getMsstbprptEngList(DataSourceRequest dataSourceRequest) {
List<String> selectFields = dataSourceRequest == null ? null : dataSourceRequest.getSelect();
String selectSql = buildWtMsstbprptEngSelectSql(selectFields);
StringBuilder sql = new StringBuilder();
sql.append("SELECT ").append(selectSql).append(" ")
.append(buildWtMsstbprptFromSql());
Map<String, Object> paramMap = new HashMap<>();
appendWtMsstbprptFilters(sql, paramMap, dataSourceRequest == null ? null : dataSourceRequest.getFilter());
sql.append(buildVmsstbprptOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort()));
DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest();
Page<?> page = QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
List<SdWtBaseInfoVO> list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, SdWtBaseInfoVO.class);
DataSourceResult<SdWtBaseInfoVO> result = new DataSourceResult<>();
result.setData(list);
result.setTotal(page != null ? page.getTotal() : list.size());
result.setAggregates(new HashMap<>());
return result;
}
@Override
public DataSourceResult<WtrvAmendResultVo> getWtrvAmendDayList(DataSourceRequest dataSourceRequest) {
List<String> selectFields = dataSourceRequest == null ? null : dataSourceRequest.getSelect();
String selectSql = buildWtrvAmendSelectSql(selectFields);
StringBuilder sql = new StringBuilder();
sql.append("SELECT ").append(selectSql).append(" FROM (")
.append(buildWtrvAmendMergedSql())
.append(") t WHERE 1 = 1 ");
Map<String, Object> paramMap = new HashMap<>();
String filterSql = buildWtrvAmendFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(),
paramMap, new int[]{0});
if (StrUtil.isNotBlank(filterSql)) {
sql.append(" AND ").append(filterSql);
}
sql.append(buildWtrvAmendOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort()));
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
Page<?> page = loadOptions == null ? null
: QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
List<WtrvAmendResultVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(page,
sql.toString(), paramMap, WtrvAmendResultVo.class);
DataSourceResult<WtrvAmendResultVo> result = new DataSourceResult<>();
result.setData(list);
result.setTotal(page != null ? page.getTotal() : list.size());
result.setAggregates(new HashMap<>());
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveWtrvAmendData(List<WtrvAmendSaveVo> amendDataList) {
if (amendDataList == null || amendDataList.isEmpty()) {
throw new BizException("数据不能为空");
}
int batchSize = 500;
for (int i = 0; i < amendDataList.size(); i += batchSize) {
List<WtrvAmendSaveVo> subList = amendDataList.subList(i, Math.min(i + batchSize, amendDataList.size()));
mergeWtrvAmendDataBatch(subList, i);
}
}
@Override @Override
public DataSourceResult getCxDetailList(DataSourceRequest dataSourceRequest) { public DataSourceResult getCxDetailList(DataSourceRequest dataSourceRequest) {
List<DataSourceRequest.FilterDescriptor> filters = new ArrayList<>(); List<DataSourceRequest.FilterDescriptor> filters = new ArrayList<>();
@ -1802,6 +1871,300 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
return " ORDER BY " + String.join(", ", orderColumns); return " ORDER BY " + String.join(", ", orderColumns);
} }
private String buildWtrvAmendMergedSql() {
return "SELECT " +
"dayData.STCD AS stcd, " +
"dayData.DT AS dt, " +
"NVL(amendData.WT, dayData.WT) AS wt, " +
"wt.STNM AS stnm, " +
"wt.RSTCD AS rstcd, " +
"eng.ENNM AS ennm, " +
"eng.BASE_ID AS baseId, " +
"hb.BASENAME AS baseName " +
"FROM SD_WTRVDAY_S dayData " +
"INNER JOIN SD_WT_B_H wt ON dayData.STCD = wt.STCD " +
" AND wt.STTP = 'WTRV' " +
" AND NVL(wt.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_WTRVAMEND_S amendData ON amendData.STCD = dayData.STCD " +
" AND amendData.DT = dayData.DT " +
" AND NVL(amendData.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.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 " +
"WHERE NVL(dayData.IS_DELETED, 0) = 0 " +
"UNION ALL " +
"SELECT " +
"amendData.STCD AS stcd, " +
"amendData.DT AS dt, " +
"amendData.WT AS wt, " +
"wt.STNM AS stnm, " +
"wt.RSTCD AS rstcd, " +
"eng.ENNM AS ennm, " +
"eng.BASE_ID AS baseId, " +
"hb.BASENAME AS baseName " +
"FROM SD_WTRVAMEND_S amendData " +
"INNER JOIN SD_WT_B_H wt ON amendData.STCD = wt.STCD " +
" AND wt.STTP = 'WTRV' " +
" AND NVL(wt.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.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 " +
"WHERE NVL(amendData.IS_DELETED, 0) = 0 " +
"AND NOT EXISTS ( " +
" SELECT 1 FROM SD_WTRVDAY_S dayData " +
" WHERE dayData.STCD = amendData.STCD " +
" AND dayData.DT = amendData.DT " +
" AND NVL(dayData.IS_DELETED, 0) = 0 " +
")";
}
private String buildWtrvAmendSelectSql(List<String> selectFields) {
Map<String, String> columnMap = buildWtrvAmendColumnMap();
List<String> actualColumns = new ArrayList<>();
if (selectFields != null && !selectFields.isEmpty()) {
for (String field : selectFields) {
String column = columnMap.get(field);
if (StrUtil.isNotBlank(column)) {
actualColumns.add(column);
}
}
}
if (actualColumns.isEmpty()) {
actualColumns.addAll(columnMap.values());
}
return String.join(", ", actualColumns);
}
private Map<String, String> buildWtrvAmendColumnMap() {
Map<String, String> columnMap = new LinkedHashMap<>();
columnMap.put("stcd", "t.stcd AS stcd");
columnMap.put("dt", "t.dt AS dt");
columnMap.put("wt", "t.wt AS wt");
columnMap.put("stnm", "t.stnm AS stnm");
columnMap.put("rstcd", "t.rstcd AS rstcd");
columnMap.put("ennm", "t.ennm AS ennm");
columnMap.put("baseId", "t.baseId AS baseId");
columnMap.put("baseName", "t.baseName AS baseName");
return columnMap;
}
private String buildWtrvAmendFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
if (filter == null) {
return "";
}
if (filter.getFilters() != null && !filter.getFilters().isEmpty()) {
List<String> conditions = new ArrayList<>();
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
String condition = buildWtrvAmendFilterCondition(child, paramMap, indexHolder);
if (StrUtil.isNotBlank(condition)) {
conditions.add("(" + condition + ")");
}
}
if (conditions.isEmpty()) {
return "";
}
String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND ";
return String.join(logic, conditions);
}
return buildWtrvAmendLeafCondition(filter, paramMap, indexHolder);
}
private String buildWtrvAmendLeafCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
String column = mapWtrvAmendColumn(filter == null ? null : filter.getField());
if (StrUtil.isBlank(column) || StrUtil.isBlank(filter.getOperator())) {
return "";
}
String operator = filter.getOperator().toLowerCase();
Object rawValue = filter.getValue();
if ("isnull".equals(operator)) {
return column + " IS NULL";
}
if ("isnotnull".equals(operator)) {
return column + " IS NOT NULL";
}
if ("isempty".equals(operator)) {
return "(" + column + " IS NULL OR " + column + " = '')";
}
if ("isnotempty".equals(operator)) {
return "(" + column + " IS NOT NULL AND " + column + " <> '')";
}
if (rawValue == null) {
return "";
}
String paramKey = "wtrvAmendP" + indexHolder[0]++;
boolean dateField = isWtrvAmendDateField(filter);
if ("in".equals(operator) || "ni".equals(operator)) {
List<?> values = normalizeToList(rawValue);
if (values.isEmpty()) {
return "";
}
List<String> placeholders = new ArrayList<>();
int itemIndex = 0;
for (Object value : values) {
String itemKey = paramKey + "_" + itemIndex++;
paramMap.put(itemKey, String.valueOf(value).trim());
placeholders.add(buildWtrvAmendValueExpr(itemKey, dateField, value));
}
return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")";
}
String text = String.valueOf(rawValue).trim();
paramMap.put(paramKey, text);
String valueExpr = buildWtrvAmendValueExpr(paramKey, dateField, rawValue);
return switch (operator) {
case "eq" -> column + " = " + valueExpr;
case "neq" -> column + " <> " + valueExpr;
case "gt" -> column + " > " + valueExpr;
case "gte" -> column + " >= " + valueExpr;
case "lt" -> column + " < " + valueExpr;
case "lte" -> column + " <= " + valueExpr;
case "contains" -> {
paramMap.put(paramKey, "%" + text + "%");
yield column + " LIKE #{map." + paramKey + "}";
}
case "doesnotcontain" -> {
paramMap.put(paramKey, "%" + text + "%");
yield column + " NOT LIKE #{map." + paramKey + "}";
}
case "startswith" -> {
paramMap.put(paramKey, text + "%");
yield column + " LIKE #{map." + paramKey + "}";
}
case "endswith" -> {
paramMap.put(paramKey, "%" + text);
yield column + " LIKE #{map." + paramKey + "}";
}
default -> "";
};
}
private String mapWtrvAmendColumn(String field) {
if (StrUtil.isBlank(field)) {
return null;
}
return switch (field) {
case "stcd" -> "t.stcd";
case "dt" -> "t.dt";
case "wt" -> "t.wt";
case "stnm" -> "t.stnm";
case "rstcd" -> "t.rstcd";
case "ennm" -> "t.ennm";
case "baseId" -> "t.baseId";
case "baseName" -> "t.baseName";
default -> null;
};
}
private String buildWtrvAmendOrderBySql(List<DataSourceRequest.SortDescriptor> sortList) {
List<String> orderColumns = new ArrayList<>();
if (sortList != null) {
for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) {
String column = mapWtrvAmendColumn(sortDescriptor.getField());
if (StrUtil.isBlank(column)) {
continue;
}
String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) || "des".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC";
orderColumns.add(column + " " + dir + ("t.dt".equals(column) || "t.wt".equals(column) ? " NULLS LAST" : ""));
}
}
if (orderColumns.isEmpty()) {
return " ORDER BY t.dt DESC, t.stcd ASC";
}
return " ORDER BY " + String.join(", ", orderColumns);
}
private boolean isWtrvAmendDateField(DataSourceRequest.FilterDescriptor filter) {
if (filter == null || StrUtil.isBlank(filter.getField())) {
return false;
}
if ("dt".equalsIgnoreCase(filter.getField())) {
return true;
}
return "date".equalsIgnoreCase(filter.getDataType());
}
private String buildWtrvAmendValueExpr(String paramKey, boolean dateField, Object value) {
if (!dateField || value == null) {
return "#{map." + paramKey + "}";
}
String text = String.valueOf(value).trim();
if (text.length() <= 10) {
return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')";
}
return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')";
}
private List<?> normalizeToList(Object value) {
if (value == null) {
return Collections.emptyList();
}
if (value instanceof List<?> list) {
return list.stream().filter(Objects::nonNull).collect(Collectors.toList());
}
return Collections.singletonList(value);
}
private void mergeWtrvAmendDataBatch(List<WtrvAmendSaveVo> amendDataList, int startIndex) {
StringBuilder sql = new StringBuilder("MERGE INTO SD_WTRVAMEND_S target USING (");
List<Object> params = new ArrayList<>();
for (int i = 0; i < amendDataList.size(); i++) {
WtrvAmendSaveVo item = amendDataList.get(i);
int rowNo = startIndex + i + 1;
String stcd = item == null ? null : StrUtil.trimToNull(item.getStcd());
if (StrUtil.isBlank(stcd)) {
throw new BizException("" + rowNo + "条数据站点编码不能为空");
}
String dt = normalizeWtrvAmendDate(item.getDt());
if (StrUtil.isBlank(dt)) {
throw new BizException("" + rowNo + "条数据日期格式不正确");
}
if (i > 0) {
sql.append(" UNION ALL ");
}
sql.append("SELECT ? AS STCD, TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS') AS DT, ? AS WT FROM DUAL");
params.add(stcd);
params.add(dt);
params.add(item.getWt());
}
sql.append(") source ON (target.STCD = source.STCD AND target.DT = source.DT) ")
.append("WHEN MATCHED THEN UPDATE SET ")
.append("target.WT = source.WT, ")
.append("target.IS_DELETED = 0, ")
.append("target.DELETE_USER = NULL, ")
.append("target.DELETE_TIME = NULL, ")
.append("target.MODIFY_TIME = SYSDATE ")
.append("WHEN NOT MATCHED THEN INSERT (ID, STCD, DT, WT, RECORD_TIME, IS_DELETED) ")
.append("VALUES (SYS_GUID(), source.STCD, source.DT, source.WT, SYSDATE, 0)");
jdbcTemplate.update(sql.toString(), params.toArray());
}
private String normalizeWtrvAmendDate(String value) {
if (StrUtil.isBlank(value)) {
return null;
}
String text = value.trim().replace('T', ' ');
try {
if (text.length() <= 10) {
return DateUtil.formatDateTime(DateUtil.parse(text.substring(0, 10), "yyyy-MM-dd").toJdkDate());
}
if (text.length() >= 19) {
return DateUtil.formatDateTime(DateUtil.parse(text.substring(0, 19), "yyyy-MM-dd HH:mm:ss").toJdkDate());
}
return DateUtil.formatDateTime(DateUtil.parse(text, "yyyy-MM-dd HH:mm").toJdkDate());
} catch (Exception ex) {
try {
return DateUtil.formatDateTime(DateUtil.parse(value.trim()).toJdkDate());
} catch (Exception ignore) {
return null;
}
}
}
private String buildSttpInfoFilterCondition(DataSourceRequest.FilterDescriptor filter, private String buildSttpInfoFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap, Map<String, Object> paramMap,
int[] indexHolder) { int[] indexHolder) {
@ -1980,6 +2343,16 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
orderColumns.add("NVL(dtin, -1) " + dir + " NULLS LAST"); orderColumns.add("NVL(dtin, -1) " + dir + " NULLS LAST");
} else if ("dtinName".equals(field)) { } else if ("dtinName".equals(field)) {
orderColumns.add("CASE WHEN NVL(dtin, 0) = 1 THEN '已接入' ELSE '未接入' END " + dir + " NULLS LAST"); orderColumns.add("CASE WHEN NVL(dtin, 0) = 1 THEN '已接入' ELSE '未接入' END " + dir + " NULLS LAST");
} else if ("wtDeviceType".equals(field)) {
orderColumns.add("NVL(wtDeviceType, -1) " + dir + " NULLS LAST");
} else if ("dtinType".equals(field)) {
orderColumns.add("NVL(dtinType, -1) " + dir + " NULLS LAST");
} else if ("mway".equals(field)) {
orderColumns.add("NVL(mway, -1) " + dir + " NULLS LAST");
} else if ("lgtd".equals(field)) {
orderColumns.add("lgtd " + dir + " NULLS LAST");
} else if ("lttd".equals(field)) {
orderColumns.add("lttd " + dir + " NULLS LAST");
} }
} }
} }
@ -1991,6 +2364,54 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
} }
private String buildWtMsstbprptSelectSql(List<String> selectFields) { private String buildWtMsstbprptSelectSql(List<String> selectFields) {
Map<String, String> columnMap = buildWtMsstbprptColumnMap();
List<String> actualColumns = new ArrayList<>();
if (selectFields != null && !selectFields.isEmpty()) {
for (String field : selectFields) {
String column = columnMap.get(field);
if (StrUtil.isNotBlank(column)) {
actualColumns.add(column);
}
}
}
if (actualColumns.isEmpty()) {
actualColumns.addAll(columnMap.values());
}
return String.join(", ", actualColumns);
}
private String buildWtMsstbprptEngSelectSql(List<String> selectFields) {
Map<String, String> columnMap = buildWtMsstbprptColumnMap();
List<String> actualColumns = new ArrayList<>();
if (selectFields == null || selectFields.isEmpty()) {
actualColumns.add(columnMap.get("stcd"));
actualColumns.add(columnMap.get("stnm"));
actualColumns.add(columnMap.get("wtDeviceType"));
actualColumns.add(columnMap.get("dtinType"));
actualColumns.add(columnMap.get("mway"));
actualColumns.add(columnMap.get("lgtd"));
actualColumns.add(columnMap.get("lttd"));
actualColumns.add(columnMap.get("baseId"));
actualColumns.add(columnMap.get("baseName"));
} else {
for (String field : selectFields) {
String column = columnMap.get(field);
if (StrUtil.isNotBlank(column)) {
actualColumns.add(column);
}
}
}
ensureWtMsstbprptColumn(actualColumns, columnMap, "stcd");
ensureWtMsstbprptColumn(actualColumns, columnMap, "stnm");
ensureWtMsstbprptColumn(actualColumns, columnMap, "lgtd");
ensureWtMsstbprptColumn(actualColumns, columnMap, "lttd");
ensureWtMsstbprptColumn(actualColumns, columnMap, "baseId");
ensureWtMsstbprptColumn(actualColumns, columnMap, "baseName");
return String.join(", ", actualColumns);
}
private Map<String, String> buildWtMsstbprptColumnMap() {
Map<String, String> columnMap = new LinkedHashMap<>(); Map<String, String> columnMap = new LinkedHashMap<>();
columnMap.put("baseName", "hb.BASENAME AS baseName"); columnMap.put("baseName", "hb.BASENAME AS baseName");
columnMap.put("baseId", "hb.BASEID AS baseId"); columnMap.put("baseId", "hb.BASEID AS baseId");
@ -2009,31 +2430,43 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
columnMap.put("stcd", "wt.STCD AS stcd"); columnMap.put("stcd", "wt.STCD AS stcd");
columnMap.put("fhstcd", "wt.FHSTCD AS fhstcd"); columnMap.put("fhstcd", "wt.FHSTCD AS fhstcd");
columnMap.put("rstcd", "wt.RSTCD AS rstcd"); columnMap.put("rstcd", "wt.RSTCD AS rstcd");
// columnMap.put("bldsttCcodeName", "CASE WHEN wt.BLDSTT_CODE IN ('1', '10', '11') THEN '已建' WHEN wt.BLDSTT_CODE IN ('2', '7', '8') THEN '在建' ELSE '未建/规划' END AS bldsttCcodeName");
columnMap.put("bldsttCcodeName", columnMap.put("bldsttCcodeName",
"CASE WHEN wt.BLDSTT_CODE = 0 THEN '未建/规划' " + "CASE WHEN wt.BLDSTT_CODE = 0 THEN '未建/规划' " +
"WHEN wt.BLDSTT_CODE = 1 THEN '在建' " + "WHEN wt.BLDSTT_CODE = 1 THEN '在建' " +
"WHEN wt.BLDSTT_CODE = 2 THEN '已建' " + "WHEN wt.BLDSTT_CODE = 2 THEN '已建' " +
"ELSE '未知' END"); "ELSE '未知' END AS bldsttCcodeName");
columnMap.put("bldsttCcode", "wt.BLDSTT_CODE AS bldsttCcode"); columnMap.put("bldsttCcode", "wt.BLDSTT_CODE AS bldsttCcode");
columnMap.put("stCode", "NULL AS stCode"); columnMap.put("stCode", "NULL AS stCode");
columnMap.put("stName", "NULL AS stName"); columnMap.put("stName", "NULL AS stName");
columnMap.put("dvtp", "eng.DVTP AS dvtp"); columnMap.put("dvtp", "eng.DVTP AS dvtp");
columnMap.put("hbrvcd", "eng.HBRVCD AS hbrvcd"); columnMap.put("hbrvcd", "eng.HBRVCD AS hbrvcd");
columnMap.put("lgtd", "wt.LGTD AS lgtd");
columnMap.put("lttd", "wt.LTTD AS lttd");
columnMap.put("wtDeviceType", "wt.WT_DEVICE_TYPE AS wtDeviceType");
columnMap.put("dtinType", "wt.DTIN_TYPE AS dtinType");
columnMap.put("mway", "wt.MWAY AS mway");
return columnMap;
}
List<String> actualColumns = new ArrayList<>(); private void ensureWtMsstbprptColumn(List<String> actualColumns, Map<String, String> columnMap, String field) {
if (selectFields != null && !selectFields.isEmpty()) { String column = columnMap.get(field);
for (String field : selectFields) { if (StrUtil.isBlank(column)) {
String column = columnMap.get(field); return;
if (StrUtil.isNotBlank(column)) {
actualColumns.add(column);
}
}
} }
if (actualColumns.isEmpty()) { if (!actualColumns.contains(column)) {
actualColumns.addAll(columnMap.values()); actualColumns.add(column);
} }
return String.join(", ", actualColumns); }
private String buildWtMsstbprptFromSql() {
return "FROM SD_WT_B_H wt " +
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.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 " +
"LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wt.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " +
"LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTRV_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) rvRecent ON rvRecent.STCD = wt.STCD " +
"LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTVT_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) vtRecent ON vtRecent.STCD = wt.STCD " +
"WHERE NVL(wt.IS_DELETED, 0) = 0 AND NVL(wt.DTIN_TYPE, 0) = 0 ";
} }
private void appendWtMsstbprptFilters(StringBuilder sql, private void appendWtMsstbprptFilters(StringBuilder sql,
@ -2061,6 +2494,8 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
appendWtMsstbprptLeaf(sql, paramMap, paramKey, "wt.RSTCD", operator, value); appendWtMsstbprptLeaf(sql, paramMap, paramKey, "wt.RSTCD", operator, value);
} else if ("baseId".equals(field)) { } else if ("baseId".equals(field)) {
appendWtMsstbprptLeaf(sql, paramMap, paramKey, "eng.BASE_ID", operator, value); appendWtMsstbprptLeaf(sql, paramMap, paramKey, "eng.BASE_ID", operator, value);
} else if ("sttpFullPath".equals(field)) {
appendWtMsstbprptLeaf(sql, paramMap, paramKey, "sttp.FULL_PATH", operator, value);
} else if ("mway".equals(field)) { } else if ("mway".equals(field)) {
appendWtMsstbprptLeaf(sql, paramMap, paramKey, "wt.MWAY", operator, value); appendWtMsstbprptLeaf(sql, paramMap, paramKey, "wt.MWAY", operator, value);
} else if ("dtin".equals(field)) { } else if ("dtin".equals(field)) {

View File

@ -0,0 +1,95 @@
package com.yfd.platform.qgc_env.wte.controller;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.qgc_env.wte.service.WeFishService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/wte")
@Tag(name = "生态调查模块")
@Validated
public class WeFishController {
@Resource
private WeFishService weFishService;
@PostMapping("/we/fisht/qgc/GetKendoListCust")
@Operation(summary = "全过程沿程鱼类变化情况")
public ResponseResult getQgcWeFishTKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeFishTKendoListCust(dataSourceRequest));
}
@PostMapping("/we/fishList/GetKendoListCust")
@Operation(summary = "环保部-水生生态调查-水生生态一级页面列表")
public ResponseResult getQgcWeFishList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeFishList(dataSourceRequest));
}
@PostMapping("/msstbprpt/GetKendoList")
@Operation(summary = "水生生态AI监测装置基础信息查询")
public ResponseResult getMsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getMsstbprptList(dataSourceRequest));
}
@PostMapping("/vmsstbprpt/GetKendoList")
@Operation(summary = "水生生态站点基础统计查询")
public ResponseResult getVmsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getVmsstbprptList(dataSourceRequest));
}
@PostMapping("/wva/year/GetKendoListCust")
@Operation(summary = "野生动物监测默认有数据的年份和月份")
public ResponseResult getWvaDefaultYearList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getWvaDefaultYearList(dataSourceRequest));
}
@PostMapping("/wva/GetKendoListCust")
@Operation(summary = "野生动物监测情况")
public ResponseResult getWvaList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getWvaList(dataSourceRequest));
}
@PostMapping("/we/fisht/year/qgc/GetKendoListCust")
@Operation(summary = "全过程沿程鱼类变化情况有数据的流域和年份")
public ResponseResult getQgcFishStaticsYearList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcFishStaticsYearList(dataSourceRequest));
}
@PostMapping("/we/fisht/statics/GetKendoListCust")
@Operation(summary = "水生生态调查概况")
public ResponseResult getQgcWeFishStatics(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeFishStatics(dataSourceRequest));
}
@PostMapping("/we/fisht/stat/qgc/GetKendoListCust")
@Operation(summary = "环保部-沿程鱼类变化情况柱状图")
public ResponseResult getQgcWeFishStatList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeFishStatList(dataSourceRequest));
}
@PostMapping("/we/fishList/stat/qgc/GetKendoListCust")
@Operation(summary = "环保部-水生生态调查-水生生态面板")
public ResponseResult getQgcFishListStat(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcFishListStat(dataSourceRequest));
}
@PostMapping("/we/fishPoint/qgc/GetKendoListCust")
@Operation(summary = "环保部-水生生态调查-鱼类分布锚点")
public ResponseResult getQgcWeFishPoint(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeFishPoint(dataSourceRequest));
}
@PostMapping("/te/tet/spec/GetKendoListCust")
@Operation(summary = "重点陆生动物二级页面")
public ResponseResult getTeSpecialAnimalList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getTeSpecialAnimalList(dataSourceRequest));
}
}

View File

@ -0,0 +1,50 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(description = "环保部-水生生态调查-水生生态一级页面列表")
public class WeFishListQgcVo {
@Schema(description = "鱼类编码")
private String id;
@Schema(description = "鱼类名称")
private String name;
@Schema(description = "基地编码")
private String baseId;
@Schema(description = "基地名称")
private String baseName;
@Schema(description = "河流编码")
private String rvcd;
@Schema(description = "河流名称")
private String rvcdName;
@Schema(description = "流域编码")
private String hbrvcd;
@Schema(description = "流域名称")
private String hbrvcdName;
@Schema(description = "电站编码")
private String rstcd;
@Schema(description = "电站名称")
private String ennm;
@Schema(description = "时间")
private String tm;
@Schema(description = "年份")
private Integer yr;
@Schema(description = "鱼类数量")
private Long fcnt;
}

View File

@ -0,0 +1,52 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@Data
@Accessors(chain = true)
@Schema(description = "环保部-水生生态调查-水生生态面板")
public class WeFishListStatQgcVo {
@Schema(description = "鱼类编码")
private String id;
@Schema(description = "鱼类名称")
private String name;
@Schema(description = "基地编码")
private String baseId;
@Schema(description = "基地名称")
private String baseName;
@Schema(description = "河流编码")
private String rvcd;
@Schema(description = "河流名称")
private String rvcdName;
@Schema(description = "流域编码")
private String hbrvcd;
@Schema(description = "流域名称")
private String hbrvcdName;
@Schema(description = "电站编码")
private String rstcd;
@Schema(description = "电站名称")
private String ennm;
@Schema(description = "时间")
private Date tm;
@Schema(description = "年份")
private Integer yr;
@Schema(description = "鱼类数量")
private Long fcnt;
}

View File

@ -0,0 +1,64 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Data
@Accessors(chain = true)
@Schema(description = "环保部-水生生态调查-鱼类分布锚点")
public class WeFishPointQgcVo {
@Schema(description = "站点类型")
private String sttp;
@Schema(description = "站点编码")
private String stcd;
@Schema(description = "经度")
private BigDecimal lgtd;
@Schema(description = "纬度")
private BigDecimal lttd;
@Schema(description = "高程")
private BigDecimal dtmel;
@Schema(description = "描点状态")
private String anchoPointState;
@Schema(description = "锚点类型")
private String sttpMap;
@Schema(description = "弹框站点名称")
private String titleName;
@Schema(description = "地图避让")
private Integer distance;
@Schema(description = "流域编码")
private String rvcd;
@Schema(description = "行政编码")
private String addvcd;
@Schema(description = "基地编码")
private String baseId;
@Schema(description = "关联电站编码")
private String rstcds;
@Schema(description = "设施类型")
private String sttpCode;
@Schema(description = "断面名称")
private String stnm;
@Schema(description = "电站名称")
private String ennm;
@Schema(description = "调查鱼类列表")
private String ftp;
}

View File

@ -0,0 +1,26 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Map;
@Data
@Schema(description = "全过程沿程鱼类变化情况柱状图")
public class WeFishStatQgcVo {
@Schema(description = "电站编码")
private String stcd;
@Schema(description = "电站名称")
private String stnm;
@Schema(description = "鱼类类型总数")
private Long total;
@Schema(description = "鱼类类型明细key 为鱼类类型value 为鱼种类数量")
private Map<String, Long> detail;
@Schema(description = "排序")
private Integer sort;
}

View File

@ -0,0 +1,134 @@
package com.yfd.platform.qgc_env.wte.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;
@Data
@Schema(description = "全过程沿程鱼类变化情况")
public class WeFishTQgcVo {
@Schema(description = "断面编码")
private String stcd;
@Schema(description = "断面名称")
private String stnm;
@Schema(description = "基地编码")
private String baseId;
@Schema(description = "基地名称")
private String baseName;
@Schema(description = "流域编码")
private String rvcd;
@Schema(description = "流域名称")
private String rvcdName;
@Schema(description = "行政区编码")
private String addvcd;
@Schema(description = "行政区名称")
private String addvcdName;
@Schema(description = "河段编码")
private String hbrvcd;
@Schema(description = "河段名称")
private String hbrvcdName;
@Schema(description = "调查批次")
private String dcpc;
@Schema(description = "调查时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date tm;
@Schema(description = "调查报告")
private String werFid;
@Schema(description = "调查主表ID")
private String werId;
@Schema(description = "渔获物种类编码")
private String ftp;
@Schema(description = "鱼类规格(cm)")
private String fsz;
@Schema(description = "渔获物数量(尾)")
private Long fcnt;
@Schema(description = "渔获物重量(kg)")
private BigDecimal fwgh;
@Schema(description = "性腺发育期")
private String st;
@Schema(description = "早期资源量和种类")
private String ps;
@Schema(description = "平均重量")
private BigDecimal avgFwgt;
@Schema(description = "平均体长")
private BigDecimal avgFsz;
@Schema(description = "附件ID")
private String fid;
@Schema(description = "现场影像ID")
private String fileId;
@Schema(description = "鱼类ID")
private String id;
@Schema(description = "渔获物种类")
private String name;
@Schema(description = "别名")
private String alias;
@Schema(description = "")
private String genus;
@Schema(description = "")
private String family;
@Schema(description = "")
private String species;
@Schema(description = "鱼类分类")
private String type;
@Schema(description = "鱼类分类名称")
private String typeName;
@Schema(description = "稀有程度")
private String rare;
@Schema(description = "鱼类来源")
private String specOrigin;
@Schema(description = "鱼类来源名称")
private String specOriginName;
@Schema(description = "保护类型")
private String ptype;
@Schema(description = "保护类型名称")
private String ptypeName;
@Schema(description = "年份")
private String yr;
@Schema(description = "鱼类类型")
private Integer ty;
@Schema(description = "鱼类类型名称")
private String tyName;
}

View File

@ -0,0 +1,38 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "水生生态AI监测装置基础信息查询")
public class WeMsstbprptVo {
@Schema(description = "主键")
private String id;
@Schema(description = "站点编码")
private String stcd;
@Schema(description = "所属电站编码")
private String rstcd;
@Schema(description = "电站名称")
private String ennm;
@Schema(description = "站点名称")
private String stnm;
@Schema(description = "站类编码")
private String sttpCode;
@Schema(description = "排序")
private Integer orderIndex;
@Schema(description = "经度")
private BigDecimal lgtd;
@Schema(description = "纬度")
private BigDecimal lttd;
}

View File

@ -0,0 +1,15 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "沿程鱼类有数据流域年份")
public class WeRvcdYearVo {
@Schema(description = "河段编码")
private String hbrvcd;
@Schema(description = "年份")
private String yr;
}

View File

@ -0,0 +1,23 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(description = "水生生态调查概况")
public class WeStaticsVo {
@Schema(description = "调查批次数量")
private Long dcpcCount;
@Schema(description = "调查断面数量")
private Long stcdCount;
@Schema(description = "调查鱼类数量")
private Long ftpCount;
@Schema(description = "调查鱼类总数")
private Long fcntSum;
}

View File

@ -0,0 +1,32 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(description = "重点陆生动物二级页面")
public class WeTeSpecialAnimalVo {
@Schema(description = "动物主键")
private String id;
@Schema(description = "动物名称")
private String name;
@Schema(description = "动物英文名称")
private String nameEn;
@Schema(description = "保护级别编码")
private String protectlvl;
@Schema(description = "保护级别名称")
private String protectlvlName;
@Schema(description = "LOGO")
private String logo;
@Schema(description = "介绍")
private String introduce;
}

View File

@ -0,0 +1,47 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "水生生态站点基础统计查询")
public class WeVmsstbprptVo {
@Schema(description = "主键")
private String id;
@Schema(description = "站类编码")
private String sttpCode;
@Schema(description = "站点编码")
private String stcd;
@Schema(description = "站点名称")
private String stnm;
@Schema(description = "所属电站编码")
private String rstcd;
@Schema(description = "所属电站名称")
private String ennm;
@Schema(description = "基地编码")
private String baseId;
@Schema(description = "流域编码")
private String hbrvcd;
@Schema(description = "河流编码")
private String rvcd;
@Schema(description = "排序")
private Integer orderIndex;
@Schema(description = "经度")
private BigDecimal lgtd;
@Schema(description = "纬度")
private BigDecimal lttd;
}

View File

@ -0,0 +1,58 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@Data
@Schema(description = "野生动物监测情况")
public class WeWvaQgcVo {
@Schema(description = "主键")
private String id;
@Schema(description = "野生动物监测站编码")
private String stcd;
@Schema(description = "野生动物监测站名称")
private String stnm;
@Schema(description = "站类编码")
private String sttpCode;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "时间")
private Date tm;
@Schema(description = "显示名称")
private String flnm;
@Schema(description = "图片路径")
private String imgPath;
@Schema(description = "视频路径")
private String flpth;
@Schema(description = "附件ID")
private String fid;
@Schema(description = "备注")
private String description;
@Schema(description = "所属电站编码")
private String rstcd;
@Schema(description = "基地编码")
private String baseId;
@Schema(description = "流域编码")
private String hbrvcd;
@Schema(description = "河流编码")
private String rvcd;
@Schema(description = "排序")
private Integer orderIndex;
}

View File

@ -0,0 +1,12 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "野生动物监测默认有数据的年月")
public class WeWvaYearQgcVo {
@Schema(description = "年月格式yyyy-MM")
private String ym;
}

View File

@ -0,0 +1,45 @@
package com.yfd.platform.qgc_env.wte.service;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListStatQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeMsstbprptVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPointQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishTQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeStaticsVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeTeSpecialAnimalVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeVmsstbprptVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaYearQgcVo;
import java.util.List;
import java.util.Map;
public interface WeFishService {
DataSourceResult<WeFishTQgcVo> getQgcWeFishTKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishListQgcVo> getQgcWeFishList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeMsstbprptVo> getMsstbprptList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeVmsstbprptVo> getVmsstbprptList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeWvaQgcVo> getWvaList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeWvaYearQgcVo> getWvaDefaultYearList(DataSourceRequest dataSourceRequest);
DataSourceResult<Map<String, List<String>>> getQgcFishStaticsYearList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeStaticsVo> getQgcWeFishStatics(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishStatQgcVo> getQgcWeFishStatList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishListStatQgcVo> getQgcFishListStat(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishPointQgcVo> getQgcWeFishPoint(DataSourceRequest dataSourceRequest);
DataSourceResult<WeTeSpecialAnimalVo> getTeSpecialAnimalList(DataSourceRequest dataSourceRequest);
}

View File

@ -68,7 +68,7 @@ public class LoginController {
@PostMapping("/login") @PostMapping("/login")
@Operation(summary = "登录用户") @Operation(summary = "登录用户")
@ResponseBody @ResponseBody
public ResponseResult login(SysUser user) throws Exception { public ResponseResult login(SysUser user, @RequestHeader(value = "Tenant_id", required = false) String tenantId) throws Exception {
// 密码解密 // 密码解密
String password = RsaUtils.decryptByPrivateKey(privateKey, String password = RsaUtils.decryptByPrivateKey(privateKey,
user.getPassword()); user.getPassword());
@ -100,6 +100,10 @@ public class LoginController {
Integer status = loginUser.getUser().getStatus(); Integer status = loginUser.getUser().getStatus();
String regStatus = loginUser.getUser().getRegStatus(); String regStatus = loginUser.getUser().getRegStatus();
if (StrUtil.isNotBlank(tenantId)&&!tenantId.equals(loginUser.getUser().getTenantId())) {
return ResponseResult.error("账号不存在或密码错误");
}
if (StrUtil.isNotBlank(regStatus)&&"REJECTED".equals(regStatus)) { if (StrUtil.isNotBlank(regStatus)&&"REJECTED".equals(regStatus)) {
return ResponseResult.error("账号审核未通过"); return ResponseResult.error("账号审核未通过");
} }

View File

@ -76,7 +76,7 @@
ON sud.ORG_ID = rr.ROOT_RVCD ON sud.ORG_ID = rr.ROOT_RVCD
JOIN SD_ENGINFO_B_H e JOIN SD_ENGINFO_B_H e
ON e.REACHCD = rr.DESC_RVCD ON e.REACHCD = rr.DESC_RVCD
AND e.USFL = 1 -- AND e.USFL = 1
JOIN river_display r JOIN river_display r
ON e.REACHCD = r.RVCD ON e.REACHCD = r.RVCD
WHERE su.STATUS = 1 WHERE su.STATUS = 1
@ -98,7 +98,7 @@
AND sud.ORG_TYPE = 'STATION' AND sud.ORG_TYPE = 'STATION'
JOIN SD_ENGINFO_B_H e JOIN SD_ENGINFO_B_H e
ON sud.ORG_ID = e.STCD ON sud.ORG_ID = e.STCD
AND e.USFL = 1 -- AND e.USFL = 1
JOIN river_display r JOIN river_display r
ON e.REACHCD = r.RVCD ON e.REACHCD = r.RVCD
WHERE su.STATUS = 1 WHERE su.STATUS = 1

View File

@ -1,4 +1,12 @@
import request from '@/utils/request'; import request from '@/utils/request';
//水电基地数据获取
export function wbsbGetKendoList(data: any) {
return request({
url: '/env/hydrobase/wbsb/GetKendoList',
method: 'post',
data
});
}
// 基地下拉列表 // 基地下拉列表
export function getBaseDropdown(data: any) { export function getBaseDropdown(data: any) {

View File

@ -0,0 +1,139 @@
import request from '@/utils/request';
//水生生态调查情况-下拉选择框
export function wbsbGetKendoList(data: any) {
return request({
url: '/api/dec-lygk-base-server/base/wbsb/GetKendoList',
method: 'post',
data
});
}
// 水生生态调查情况-获取默认年份
export function getDftYear(data: any) {
return request({
url: '/api/wmp-env-server/env/we/fisht/year/qgc/GetKendoListCust',
method: 'post',
data
});
}
// 水生生态调查情况-获取统计数据
export function getWeFisht(data: any) {
return request({
url: '/api/wmp-env-server/env/we/fisht/statics/GetKendoListCust',
method: 'post',
data
});
}
// 水生生态调查概况-表格数据接口
export function getWeStaticsSecond(data: any) {
return request({
url: '/api/wmp-env-server/env/we/fisht/statics/getWeStaticsSecond',
method: 'post',
data
});
}
// 沿程鱼类变化-图表数据接口
export function fishChanges2(data: any) {
return request({
url: '/api/wmp-env-server/env/we/fisht/stat/GetKendoListCust',
method: 'post',
data
});
}
// 沿程鱼类变化-详情表格接口
export function fishDetail(data: any) {
return request({
url: '/api/wmp-env-server/env/we/fisht/detail/GetKendoListCust',
method: 'post',
data
});
}
// 沿程鱼类变化-Tab数量统计接口
export function getTabNum(data: any) {
return request({
url: '/api/wmp-env-server/env/we/fisht/statTab/GetKendoListCust',
method: 'post',
data
});
}
// 沿程鱼类变化-获取断面列表
export function getStcdList(data: any) {
return request({
url: '/api/dec-lygk-base-server/base/vmsstbprpt/noWqDtinType0Auth/GetKendoList',
method: 'post',
data: {
filter: data,
orders: JSON.stringify({ siteStepSort: 'asc' })
}
});
}
// 沿程鱼类变化-基地模式详情表格接口
export function fishQgcDetail(data: any) {
return request({
url: '/api/wmp-env-server/env/we/fisht/qgcDetail/GetKendoListCust',
method: 'post',
data
});
}
// 陆生生态监测情况-获取统计数据
export function getEvnmAutoMonitor(data: any) {
return request({
url: '/api/dec-lygk-base-server/base/evnmAutoMonitor/GetKendoListCust',
method: 'post',
data
});
}
// 陆生生态监测-红外相机信息表格
export function getVmsstbprptList(data: any) {
return request({
url: '/api/dec-lygk-base-server/base/vmsstbprpt/GetKendoList',
method: 'post',
data
});
}
// 陆生生态监测-重点陆生动物表格
export function getTetSpecList(data: any) {
return request({
url: '/api/wmp-env-server/te/tet/spec/GetKendoListCust',
method: 'post',
data
});
}
// 野生动物监测-获取运行数据
export function getWvaData(data: any) {
return request({
url: '/api/wmp-env-server/env/wva/GetKendoListCust',
method: 'post',
data
});
}
// 野生动物监测-获取默认数据
export function getWvaDftData(data: any) {
return request({
url: '/api/wmp-env-server/env/wva/default/GetKendoListCust',
method: 'post',
data
});
}
// 野生动物监测-获取默认年份列表
export function getWvaDftTm(data: any) {
return request({
url: '/api/wmp-env-server/env/wva/year/GetKendoListCust',
method: 'post',
data
});
}

View File

@ -596,12 +596,18 @@ const enhancedColumns = computed(() => {
const { slots, ...restCol } = enhancedCol; const { slots, ...restCol } = enhancedCol;
return { return {
...restCol, ...restCol,
customCell: createMergeCellHandler(col),
_slotName: slots.customRender, _slotName: slots.customRender,
...(props.enableEllipsis ? { ellipsis: true } : {}) ...(props.enableEllipsis ? { ellipsis: true } : {})
}; };
} }
return enhancedCol; // slots customCell
return {
...enhancedCol,
customCell: createMergeCellHandler(col),
...(props.enableEllipsis ? { ellipsis: true } : {})
};
} }
// slots.customRender slots // slots.customRender slots

View File

@ -47,26 +47,7 @@
</span> </span>
</div> </div>
<div class="title_right"> <div class="title_right">
<div v-if="select.show">
<a-select
v-model:value="selectValue"
show-search
placeholder="请选择"
:size="'small'"
:style="{ width: select.width || '80px' }"
:dropdown-style="{
maxHeight: '400px',
overflow: 'auto',
minWidth: '200px'
}"
:options="select.options"
:filter-option="filterOption"
@focus="handleFocus"
@blur="handleBlur"
@change="handleChange"
@select="handleTreeSelect1"
></a-select>
</div>
<div v-if="shrink" class="title_shrink" @click="isExpand = !isExpand"> <div v-if="shrink" class="title_shrink" @click="isExpand = !isExpand">
<img v-if="isExpand" src="@/assets/components/arrow-up.png" alt="" /> <img v-if="isExpand" src="@/assets/components/arrow-up.png" alt="" />
<img v-else src="@/assets/components/arrow-down.png" alt="" /> <img v-else src="@/assets/components/arrow-down.png" alt="" />
@ -96,6 +77,26 @@
@expand="handleTreeExpand" @expand="handleTreeExpand"
> >
</a-tree-select> </a-tree-select>
</div>
<div v-if="select.show">
<a-select
v-model:value="selectValue"
show-search
placeholder="请选择"
:size="'small'"
:style="{ width: select.width || '80px' }"
:dropdown-style="{
maxHeight: '400px',
overflow: 'auto',
minWidth: '200px'
}"
:options="select.options"
:filter-option="filterOption"
@focus="handleFocus"
@blur="handleBlur"
@change="handleChange"
@select="handleTreeSelect1"
></a-select>
</div> </div>
<div v-if="datetimePicker.show"> <div v-if="datetimePicker.show">
<!-- 添加 locale 属性来设置语言 --> <!-- 添加 locale 属性来设置语言 -->

View File

@ -46,6 +46,5 @@ app
.use(router) .use(router)
.use(ElementPlus) .use(ElementPlus)
.use(Antd) .use(Antd)
.use(Antd)
.use(i18n) .use(i18n)
.mount('#app'); .mount('#app');

View File

@ -1,320 +1,541 @@
<!-- SidePanelItem.vue --> <!-- 野生动物监测 -->
<template> <template>
<SidePanelItem title="野生动物监测" :select="select" :datetimePicker="datetimePicker" :tabs="tabs" <SidePanelItem
@tab-change="handleTabChange"> title="野生动物监测"
<div v-if="tabsa == 'one'" class="container" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave"> :select="select"
<!-- 跑马灯轨道容器 --> :datetimePicker="datetimePicker"
<div class="carousel-track" :class="{ 'no-transition': isTransitioning }" :tabs="tabs"
:style="{ transform: `translateX(-${currentIndex * 100}%)` }"> @tab-change="handleTabChange"
<!-- 遍历所有媒体项包含克隆项 --> @update-values="handlePanelChange"
<div v-for="(item, index) in renderMediaData" :key="index" class="carousel-item"> >
<!-- 图片 --> <a-spin :spinning="loading" tip="加载中...">
<a-image :src="item.url" /> <div v-if="originalMediaData.length === 0" class="empty-wrapper">
<!-- 说明文字 --> <a-empty description="暂无数据" />
<div class="text">{{ item.text }}</div> </div>
</div> <template v-else>
<div
v-if="tabsa == 'one'"
class="container"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
>
<div
class="carousel-track"
:class="{ 'no-transition': isTransitioning }"
:style="{ transform: `translateX(-${currentIndex * 100}%)` }"
>
<div
v-for="(item, index) in renderMediaData"
:key="index"
class="carousel-item"
@click="handleItemClick(item)"
>
<img :src="item.url" />
<div class="text">{{ item.text }}</div>
</div> </div>
</div>
</div> </div>
<div v-else class="container video-carousel-container" @mouseenter="handleMouseEnter" <div
@mouseleave="handleMouseLeave"> v-else
<!-- 跑马灯轨道容器 --> class="container video-carousel-container"
<div class="carousel-track" :class="{ 'no-transition': isTransitioning }" @mouseenter="handleMouseEnter"
:style="{ transform: `translateX(-${currentIndex * 30}%)` }"> @mouseleave="handleMouseLeave"
<!-- 遍历所有媒体项包含克隆项 --> >
<div v-for="(item, index) in renderMediaData" :key="index" class="carousel-item1"> <div
<!-- 图片 --> class="carousel-track"
<a-image :src="item.url" /> :class="{ 'no-transition': isTransitioning }"
<div class="biaozji"> :style="{ transform: `translateX(-${currentIndex * 30}%)` }"
<span class="icon iconfont icon-play" ></span> >
</div> <div
</div> v-for="(item, index) in renderMediaData"
:key="index"
class="carousel-item1"
@click="handleItemClick(item)"
>
<img :src="item.url" />
<div class="biaozji">
<span class="icon iconfont icon-play"></span>
</div>
</div> </div>
</div>
</div> </div>
</SidePanelItem> </template>
</a-spin>
</SidePanelItem>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, onUnmounted } from 'vue'; import { ref, onMounted, onUnmounted, watch } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import { getVmsstbprptList, getWvaData, getWvaDftTm } from '@/api/stdc';
import { useModelStore } from '@/store/modules/model';
// 便
defineOptions({ defineOptions({
name: 'ZhiWuYuanJianSheJiJieRuQingKuangBar' name: 'ZhiWuYuanJianSheJiJieRuQingKuangBar'
}); });
// ==================== ====================//
const modelStore = useModelStore();
// ==================== ====================
const select = ref({ const select = ref({
show: true, show: true,
value: undefined, value: undefined as string | undefined,
options: [], options: [] as Array<{ label: string; value: string }>,
picker: undefined, picker: undefined,
format: undefined format: undefined
}); });
// // ==================== ====================
const datetimePicker = ref({ const datetimePicker = ref({
show: true, show: true,
value: `2024`, value: '',
format: 'YYYY', format: 'YYYY',
picker: 'year' as const, picker: 'year' as const
options: [] // options: [] as string[]
}); });
// ==================== Tab ====================
const tabs = ref({ const tabs = ref({
show: true, show: true,
value: 'one', value: 'one'
}); });
const tabsa = ref('one');
// ==================== ====================
//
interface MediaItem { interface MediaItem {
type: 'image' | 'video'; type: 'image' | 'video';
url: string; url: string;
text: string; text: string;
stcd: string;
stnm: string;
fid?: string;
flpth?: string;
flnm?: string;
tm?: string;
} }
// 5 const originalMediaData = ref<MediaItem[]>([]);
const originalMediaData = ref<MediaItem[]>([
{
type: 'image',
url: 'https://211.99.26.225:12125/?20250709001636453909987812803850&view=jpg&token=bearer 0a2549fe-9bc6-4bef-b098-1344e569c395',
text: '糯扎渡动物救护站 2025-04-11 15'
},
{
type: 'image',
url: 'https://211.99.26.225:12125/?20250709001636453909987812803850&view=jpg&token=bearer 0a2549fe-9bc6-4bef-b098-1344e569c395',
text: '糯扎渡动物救护站 2025-04-11 15'
},
{
type: 'image',
url: 'https://211.99.26.225:12125/?20250709001636453909987812803850&view=jpg&token=bearer 0a2549fe-9bc6-4bef-b098-1344e569c395',
text: '糯扎渡动物救护站 2025-04-11 15'
},
{
type: 'image',
url: 'https://211.99.26.225:12125/?20250709001636453909987812803850&view=jpg&token=bearer 0a2549fe-9bc6-4bef-b098-1344e569c395',
text: '糯扎渡动物救护站 2025-04-11 15'
},
]);
const tabsa = ref('one')
//
// [, ..., ]
const renderMediaData = ref<MediaItem[]>([]); const renderMediaData = ref<MediaItem[]>([]);
const currentIndex = ref(1);
// renderMediaData
const currentIndex = ref(1); // 1
//
let timer: any = null; let timer: any = null;
//
const isHovering = ref(false); const isHovering = ref(false);
// transition
const isTransitioning = ref(false); const isTransitioning = ref(false);
const loading = ref(false);
// // ==================== ====================
const initRenderData = () => { const initRenderData = () => {
const length = originalMediaData.value.length; const length = originalMediaData.value.length;
if (length === 0) return; if (length === 0) {
renderMediaData.value = [];
currentIndex.value = 0;
return;
}
// > 1
if (length === 1) {
renderMediaData.value = [...originalMediaData.value];
currentIndex.value = 0;
} else {
renderMediaData.value = [ renderMediaData.value = [
originalMediaData.value[length - 1], // originalMediaData.value[length - 1],
...originalMediaData.value, // ...originalMediaData.value,
originalMediaData.value[0] // originalMediaData.value[0]
]; ];
currentIndex.value = 1;
}
}; };
// // ==================== ====================
const startAutoPlay = () => { const startAutoPlay = () => {
if (timer) clearInterval(timer); if (timer) clearInterval(timer);
timer = setInterval(() => { // 1
if (!isHovering.value && !isTransitioning.value) { if (originalMediaData.value.length <= 1) return;
nextSlide(); timer = setInterval(() => {
} if (
}, 2000); !isHovering.value &&
}; !isTransitioning.value &&
originalMediaData.value.length > 1
// ) {
const nextSlide = () => { nextSlide();
currentIndex.value++;
//
setTimeout(() => {
checkSeamlessJump();
}, 500); // transition
};
//
const checkSeamlessJump = () => {
const realLength = originalMediaData.value.length;
// = realLength + 1
if (currentIndex.value >= realLength + 1) {
// 1.
isTransitioning.value = true;
// 2. 1
currentIndex.value = 1;
// 3. DOM
requestAnimationFrame(() => {
requestAnimationFrame(() => {
isTransitioning.value = false;
});
});
} }
}, 3000);
};
const stopAutoPlay = () => {
if (timer) {
clearInterval(timer);
timer = null;
}
};
const nextSlide = () => {
currentIndex.value++;
setTimeout(() => {
checkSeamlessJump();
}, 500);
};
const checkSeamlessJump = () => {
const realLength = originalMediaData.value.length;
if (currentIndex.value >= realLength + 1) {
isTransitioning.value = true;
currentIndex.value = 1;
requestAnimationFrame(() => {
requestAnimationFrame(() => {
isTransitioning.value = false;
});
});
}
}; };
//
const handleMouseEnter = () => { const handleMouseEnter = () => {
isHovering.value = true; isHovering.value = true;
}; };
//
const handleMouseLeave = () => { const handleMouseLeave = () => {
isHovering.value = false; isHovering.value = false;
};
const handleTabChange = (data: { tabValue: string; tabLabel: string }) => {
console.log('当前选中标签:', data.tabValue);
console.log('标签名称:', data.tabLabel);
//
tabsa.value = data.tabValue;
}; };
// const handleTabChange = (data: { tabValue: string; tabLabel: string }) => {
onMounted(() => { tabsa.value = data.tabValue;
// tab
getData();
};
// ==================== ====================
const handlePanelChange = (data: any) => {
if (data.select !== undefined && data.select !== null) {
select.value.value = data.select;
}
if (data.datetime !== undefined && data.datetime !== null) {
datetimePicker.value.value = data.datetime;
}
if (data.tabs !== undefined && data.tabs !== null) {
tabsa.value = data.tabs;
}
//
getData();
};
// ==================== ====================
const handleItemClick = (item: MediaItem) => {
modelStore.modalVisible = true;
modelStore.params.sttp = 'WVA';
modelStore.params.stcd = item.stcd;
modelStore.title = `${item.stnm} 野生动物监测`;
modelStore.isBasicEdit = true;
};
// ==================== ====================
const getStationList = async () => {
try {
const res = await getVmsstbprptList({
filter: {
logic: 'and',
filters: [
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: 'WVA'
}
]
},
select: [
'id',
'stcd',
'rstcd',
'ennm',
'stnm',
'sttpCode',
'orderIndex',
'lgtd',
'lttd'
]
});
const list = res?.data?.data ?? [];
// debugger
if (list.length) {
select.value.options = list.map((item: any) => ({
label: item.stnm,
value: item.stcd
}));
select.value.value = list[0].stcd;
}
} catch (error) {
console.error('获取站点列表失败:', error);
}
};
// ==================== ====================
const getDefaultYear = async () => {
try {
let params = {
filter: {
logic: 'and',
filters: [
tabsa.value === 'one'
? {
field: 'fid',
operator: 'isnotnull',
dataType: 'string'
}
: { field: 'flpth', operator: 'isnotnull', dataType: 'string' }
]
}
};
const res = await getWvaDftTm(params);
const data = res?.data?.data ?? [];
if (data.length) {
const yrList = data
.map((el: any) => el.ym)
.sort((a: any, b: any) => b - a);
// datetimePicker.value.options = yrList;
datetimePicker.value.value = String(yrList[0]);
} else {
datetimePicker.value.value = String(new Date().getFullYear());
}
} catch (error) {
console.error('获取默认年份失败:', error);
datetimePicker.value.value = String(new Date().getFullYear());
}
};
// ==================== ====================
const getFileUrl = (path: string, view = 'jpg') => {
const fsAddress =import.meta.env.VITE_APP_ATTACHMENT_URL ||'';
return `${fsAddress}?${path}&view=${view}`;
};
const getData = async () => {
if (!datetimePicker.value.value) return;
loading.value = true;
try {
// datetimePicker.value.value YYYY-MM
const year = datetimePicker.value.value?.toString().slice(0, 4);
let params = {
filter: {
logic: 'and',
filters: [
{
field: 'tm',
operator: 'gte',
dataType: 'date',
value: `${year}-01-01 00:00:00`
},
{
field: 'tm',
operator: 'lte',
dataType: 'date',
value: `${year}-12-31 23:59:59`
},
{
field: 'stcd',
operator: 'eq',
dataType: 'string',
value: select.value.value
},
tabsa.value === 'one'
? {
field: 'fid',
operator: 'isnotnull',
dataType: 'string'
}
: { field: 'flpth', operator: 'isnotnull' }
]
}
};
const res = await getWvaData(params);
const datas = res?.data?.data ?? [];
if (tabsa.value === 'one') {
const pics = datas.reduce((result: MediaItem[], el: any) => {
const ids = el?.fid?.split(',') ?? [];
ids.forEach((id: string) => {
result.push({
type: 'image',
url: getFileUrl(id),
text: el?.flnm || '',
stcd: el?.stcd,
stnm: el?.stnm,
fid: id,
flnm: el?.flnm,
tm: el?.tm
});
});
return result;
}, []);
originalMediaData.value = pics;
} else {
const videos = datas.map((el: any) => ({
type: 'video' as const,
url: el.imgPath ? getFileUrl(el.imgPath) : '',
text: el?.flnm || '',
stcd: el?.stcd,
stnm: el?.stnm,
flpth: el?.flpth,
flnm: el?.flnm,
tm: el?.tm
}));
originalMediaData.value = videos;
}
initRenderData(); initRenderData();
startAutoPlay(); startAutoPlay();
} catch (error) {
console.error('获取数据失败:', error);
} finally {
loading.value = false;
}
};
// <= 1
watch(
() => originalMediaData.value.length,
(newLen) => {
if (newLen <= 1) {
stopAutoPlay();
}
}
);
// ==================== ====================
onMounted(async () => {
await getStationList();
await getDefaultYear();
//
getData();
}); });
//
onUnmounted(() => { onUnmounted(() => {
if (timer) clearInterval(timer); if (timer) clearInterval(timer);
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.container { .empty-wrapper {
width: 100%; width: 100%;
height: 290px; height: 290px;
border: 1px solid #7fd6ff; display: flex;
border-radius: 5px; align-items: center;
position: relative; justify-content: center;
overflow: hidden; // }
// .container {
.carousel-track { width: 100%;
display: flex; // height: 290px;
border: 1px solid #7fd6ff;
border-radius: 5px;
position: relative;
overflow: hidden;
.carousel-track {
display: flex;
width: 100%;
height: 100%;
transition: transform 0.5s ease-in-out;
&.no-transition {
transition: none;
}
.carousel-item {
width: 100% !important;
height: 100%;
position: relative;
flex-shrink: 0;
cursor: pointer;
img,
video {
width: 100%; width: 100%;
height: 100%; height: 100%;
transition: transform 0.5s ease-in-out; // 0.5 object-fit: cover;
}
// :deep(.ant-image) {
&.no-transition { width: 100%;
transition: none; height: 100%;
img {
width: 100%;
height: 100%;
object-fit: cover;
} }
}
// .text {
.carousel-item { position: absolute;
width: 100% !important; // bottom: 0;
height: 100%; left: 0;
position: relative; width: 100%;
flex-shrink: 0; // height: 40px;
align-items: center;
img, line-height: 40px;
video { background: rgba(0, 0, 0, 0.4);
width: 100%; color: #fff;
height: 100%; padding-left: 10px;
object-fit: cover; // }
}
// Ant Design Vue a-image
:deep(.ant-image) {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.text {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40px;
align-items: center;
line-height: 40px;
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding-left: 10px;
}
}
} }
}
} }
.video-carousel-container { .video-carousel-container {
border: 0px solid #7fd6ff !important; border: 0px solid #7fd6ff !important;
border-radius: 0px !important; border-radius: 0px !important;
.carousel-item1 {
position: relative;
width: 40% !important; //
height: 100%;
position: relative;
flex-shrink: 0; //
// margin-right: 10px;
padding: 6px;
border-top:#f0f0f0 solid 1px;
border-bottom:#f0f0f0 solid 1px;
border-right:#f0f0f0 solid 1px;
img, .carousel-item1 {
video { position: relative;
width: 100%; width: 40% !important;
height: 100%; height: 100%;
object-fit: cover; // flex-shrink: 0;
} padding: 6px;
border-top: #f0f0f0 solid 1px;
border-bottom: #f0f0f0 solid 1px;
border-right: #f0f0f0 solid 1px;
cursor: pointer;
// Ant Design Vue a-image img,
:deep(.ant-image) { video {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.biaozji{
position: absolute;
width:40px;
height:40px;
border-radius:50%;
background:#0c33586c;
z-index: 9999;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
display:flex;
align-items: center;
justify-content: center;
cursor: pointer;
span{
width:16px;
height:16px;
font-size: 16px;
color: #abacad;
display: inline-block;
text-align: center;
line-height: 16px;
}
}
} }
:deep(.ant-image) {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.biaozji {
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
background: #0c33586c;
z-index: 9999;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
span {
width: 16px;
height: 16px;
font-size: 16px;
color: #abacad;
display: inline-block;
text-align: center;
line-height: 16px;
}
}
}
} }
</style> </style>

View File

@ -0,0 +1,615 @@
<!-- 沿程鱼类变化详情组件 -->
<template>
<div class="yancheng-yulei">
<!-- 搜索表单 -->
<a-form layout="inline" class="search-form">
<!-- 基地名称非沿程模式显示 -->
<a-form-item v-if="!props.ly" label="基地名称">
<a-select
v-model:value="formState.baseId"
placeholder="请选择"
style="width: 150px"
:options="baseOptions"
@change="handleBaseChange"
/>
</a-form-item>
<!-- 所在流域 -->
<a-form-item label="所在流域">
<a-select
v-model:value="formState.rvcd"
placeholder="请选择"
style="width: 150px"
:options="lyOptions"
@change="handleRvcdChange"
/>
</a-form-item>
<!-- 断面名称沿程模式显示 -->
<a-form-item v-if="props.ly" label="断面名称">
<a-select
v-model:value="formState.stcd"
placeholder="请选择"
style="width: 150px"
:options="dmOptions"
@change="handleStcdChange"
/>
</a-form-item>
<!-- 年份 -->
<a-form-item label="年份">
<a-date-picker
v-model:value="yearValue"
picker="year"
format="YYYY"
:allow-clear="false"
style="width: 120px"
@change="handleYearChange"
/>
</a-form-item>
<a-form-item>
<a-space>
<a-button type="primary" @click="handleSearch">查询</a-button>
<a-button @click="handleReset">重置</a-button>
</a-space>
</a-form-item>
</a-form>
<!-- Tab 切换 + 表格 -->
<a-tabs v-model:activeKey="tabIndex" class="ylycbh-tabs" @change="handleTabChange">
<a-tab-pane v-for="item in tabList" :key="item.key" :tab="item.labelWithTooltip">
<div class="table-wrapper">
<BasicTable
v-if="tabIndex === item.key"
:ref="el => setTableRef(el, item.key)"
:columns="tableColumns"
:scroll-y="500"
:scroll-x="800"
:list-url="listUrl"
:search-params="searchParams"
:transform-data="customTransform"
>
<!-- 沿程模式断面名称列带电站名称分组 -->
<template v-if="props.ly" #rsctdName="{ record }">
{{ record.rsctdName || '-' }}
</template>
<template v-if="props.ly" #stcdList="{ record }">
<div v-for="st in record.stcdList" :key="st.stcd">
<a @click="handleViewDetail(st.stcd, st.stnm)" class="text-link">
{{ st.stnm }}
</a>
</div>
</template>
<template v-if="props.ly" #fishList="{ record }">
<a-list size="small" :data-source="record.fishList">
<template #renderItem="{ item }">
<a-list-item>{{ item }}</a-list-item>
</template>
</a-list>
</template>
<!-- 基地模式调查断面列 -->
<template v-else #stnm="{ record }">
<a @click="handleViewDetail(record.stcd, record.stnm)" class="text-link">
{{ record.stnm }}
</a>
</template>
<template v-else #name="{ record }">
{{ record.name || '-' }}
</template>
</BasicTable>
</div>
</a-tab-pane>
</a-tabs>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, watch, onMounted, nextTick, h } from 'vue';
import { Tooltip } from 'ant-design-vue';
import BasicTable from '@/components/BasicTable/index.vue';
import {
wbsbGetKendoList,
getStcdList,
getTabNum,
fishDetail,
fishQgcDetail
} from '@/api/stdc';
import dayjs from 'dayjs';
import { useModelStore } from '@/store/modules/model';
const modelStore = useModelStore();
// ==================== Props ====================
const props = defineProps<{
tm: string; // "2024"
dataDimensionVal: string; // ID
hbrvcd: string; //
jdList: any[]; //
stateName: string; // ""
sectionName: string; //
stcd: string; //
ly: boolean; // 沿
}>();
// ==================== Tab ====================
const TAB_CONFIG = [
{ key: '1', label: '外来鱼类', prompt: '通过人为行为引入的本流域原生态没有的鱼类' },
{ key: '2', label: '本土受威胁鱼类', prompt: '流域原生态鱼类中处于近危或者濒危的鱼类' },
{ key: '3', label: '本土无危鱼类', prompt: '分类属于本土且保护类型属于无危的鱼类' }
];
// ==================== ====================
const formState = ref({
baseId: props.dataDimensionVal || 'all',
rvcd: props.hbrvcd || '',
stcd: props.stcd || '',
yr: props.tm || dayjs().format('YYYY')
});
const yearValue = ref(props.tm ? dayjs(props.tm) : dayjs());
// ==================== ====================
/** 基地下拉选项 */
const baseOptions = computed(() =>
props.jdList.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}))
);
/** 流域下拉选项 */
const lyOptions = ref<Array<{ label: string; value: string }>>([]);
/** 断面下拉选项 */
const dmOptions = ref<Array<{ label: string; value: string }>>([
{ label: '全部', value: '' }
]);
// ==================== Tab ====================
/** 根据 props.stateName 确定初始 Tab */
const initTabIndex = (() => {
if (props.stateName === '外来鱼类') return '1';
if (props.stateName === '本土受威胁鱼类') return '2';
return '3';
})();
const tabIndex = ref(initTabIndex);
/** Tab 列表(带 Tooltip 渲染) */
const tabList = ref<any[]>(
TAB_CONFIG.map(item => ({
...item,
labelWithTooltip: renderTabLabel(item.label, item.prompt)
}))
);
/**
* 渲染 Tab 标签 Tooltip 提示
*/
function renderTabLabel(label: string, prompt: string) {
return () =>
h('div', { style: { display: 'flex', alignItems: 'center' } }, [
h('span', label),
h(
Tooltip,
{ placement: 'topLeft', title: prompt },
{
default: () =>
h('span', {
class: 'icon iconfont icon-iconQuestion',
style: { marginLeft: '4px', cursor: 'pointer' }
})
}
)
]);
}
// ==================== ====================
/** 沿程模式表格列 */
const lyColumns = [
{
key: 'rsctdName',
title: '电站名称',
dataIndex: 'rsctdName',
width: 200,
ellipsis: true,
slots: { customRender: 'rsctdName' }
},
{
key: 'stcdList',
title: '调查断面',
dataIndex: 'stcdList',
width: 200,
ellipsis: true,
slots: { customRender: 'stcdList' }
},
{
key: 'fishList',
title: '渔获物种类',
dataIndex: 'fishList',
width: 300,
ellipsis: true,
slots: { customRender: 'fishList' }
}
];
/** 基地模式表格列 */
const baseColumns = [
{
key: 'stnm',
title: '调查断面',
dataIndex: 'stnm',
fixed: 'left' as const,
width: 200,
ellipsis: true,
slots: { customRender: 'stnm' },
merge: true,
mergeDeps: ['stnm']
},
{
key: 'name',
title: '渔获物种类',
dataIndex: 'name',
width: 300,
ellipsis: true,
slots: { customRender: 'name' }
}
];
/** 根据 ly 模式切换表格列 */
const tableColumns = computed(() => (props.ly ? lyColumns : baseColumns));
/** 根据 ly 模式切换表格 API */
const listUrl = computed(() => (props.ly ? fishDetail : fishQgcDetail));
/** 表格搜索参数 */
const searchParams = computed(() => ({
group: [],
select: [],
groupResultFlat: true
}));
/** 表格 ref 映射(每个 Tab 一个 ref */
const tableRefs = ref<Record<string, any>>({});
function setTableRef(el: any, key: string) {
if (el) tableRefs.value[key] = el;
}
/** 数据转换 */
const customTransform = (res: any) => ({
records: res?.data?.data || [],
total: res?.data?.total || 0
});
// ==================== ====================
const fetchLyList = async () => {
try {
const params = {
filter: {
logic: 'and',
filters: [
{ field: 'wbsType', operator: 'eq', value: 'PSB_RVCD' },
{
field: 'fullPath',
operator: 'contains',
dataType: 'string',
value: formState.value.baseId + ','
}
]
},
group: [
{ dir: 'asc', field: 'objId' },
{ dir: 'asc', field: 'orderIndex' },
{ dir: 'des', field: 'wbsCode' },
{ dir: 'des', field: 'wbsName' }
],
groupResultFlat: true
};
const res = await wbsbGetKendoList(params);
const data = res?.data?.data || [];
if (data.length > 0) {
const options = data.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}));
lyOptions.value = options;
// hbrvcd
const matched = options.find(o => o.value === props.hbrvcd);
formState.value.rvcd = matched?.value || options[0]?.value || '';
} else {
lyOptions.value = [];
formState.value.rvcd = '';
}
} catch (error) {
console.error('获取流域列表失败:', error);
lyOptions.value = [];
formState.value.rvcd = '';
}
};
// ==================== ====================
const fetchDmList = async () => {
try {
const params = {
logic: 'and',
filters: [
{ field: 'hbrvcd', operator: 'eq', value: formState.value.rvcd },
{ field: 'sttpCode', operator: 'eq', value: 'ENG' },
{
field: 'bldsttCcode',
operator: 'in',
value: ['1', '2']
}
]
};
const res = await getStcdList(params);
const data = res?.data?.data || [];
if (data.length > 0) {
const options = data.map((item: any) => ({
label: item.stnm,
value: item.stcd
}));
dmOptions.value = [{ label: '全部', value: '' }, ...options];
// sectionName
const matched = options.find(o => o.label === props.sectionName);
formState.value.stcd = matched?.value || options[0]?.value || '';
} else {
dmOptions.value = [{ label: '全部', value: '' }];
formState.value.stcd = '';
}
} catch (error) {
console.error('获取断面列表失败:', error);
dmOptions.value = [{ label: '全部', value: '' }];
formState.value.stcd = '';
}
};
// ==================== Tab ====================
const getTabNumData = async () => {
const params: any = {
baseId: formState.value.baseId,
rvcd: formState.value.rvcd,
yr: dayjs(yearValue.value).format('YYYY'),
ty: tabIndex.value
};
// 沿 stcd
if (props.ly) {
params.stcd = formState.value.stcd;
}
//
if (!params.stcd) delete params.stcd;
if (params.baseId === 'all') delete params.baseId;
try {
const res = await getTabNum(params);
// getTabNum res.data [{ty, num}, ...]
const data = res?.data || [];
const list = TAB_CONFIG.map(item => ({
...item,
labelWithTooltip: renderTabLabel(item.label, item.prompt)
}));
if (data.length > 0) {
data.forEach((el: any) => {
const found = list.find(item => item.key === el?.ty);
if (found) {
found.labelWithTooltip = renderTabLabel(
`${found.label}(${el?.num}种)`,
found.prompt
);
}
});
}
tabList.value = list;
} catch (error) {
console.error('获取 Tab 数量失败:', error);
tabList.value = TAB_CONFIG.map(item => ({
...item,
labelWithTooltip: renderTabLabel(item.label, item.prompt)
}));
}
};
// ==================== ====================
/** 构建表格过滤条件 */
const getFilter = () => {
const filters: any[] = [
{
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: formState.value.baseId
},
{
field: 'rvcd',
operator: 'eq',
dataType: 'string',
value: formState.value.rvcd
},
{
field: 'yr',
operator: 'eq',
dataType: 'string',
value: dayjs(yearValue.value).format('YYYY')
},
{
field: 'ty',
operator: 'eq',
dataType: 'string',
value: tabIndex.value
}
];
// 沿 stcd
if (props.ly && formState.value.stcd) {
filters.push({
field: 'stcd',
operator: 'eq',
dataType: 'string',
value: formState.value.stcd
});
}
return {
logic: 'and',
filters: filters.filter(Boolean)
};
};
/** 查询 */
const handleSearch = () => {
const filter = getFilter();
const currentTable = tableRefs.value[tabIndex.value];
currentTable?.getList(filter);
getTabNumData();
};
/** 重置 */
const handleReset = () => {
formState.value = {
baseId: props.dataDimensionVal || 'all',
rvcd: props.hbrvcd || '',
stcd: props.stcd || '',
yr: props.tm || dayjs().format('YYYY')
};
yearValue.value = props.tm ? dayjs(props.tm) : dayjs();
handleSearch();
};
// ==================== ====================
/** 基地变化 */
const handleBaseChange = () => {
formState.value.rvcd = '';
formState.value.stcd = '';
fetchLyList();
};
/** 流域变化 */
const handleRvcdChange = () => {
formState.value.stcd = '';
if (props.ly) {
fetchDmList();
}
};
/** 断面变化 */
const handleStcdChange = () => {
//
};
/** 年份变化 */
const handleYearChange = () => {
//
};
/** Tab 切换 */
const handleTabChange = () => {
handleSearch();
};
// ==================== ====================
/**
* 点击断面链接弹出详情
* 参考 SsstdcgkTk.vue handleViewDetail
*/
const handleViewDetail = (stcd: string, stnm: string) => {
modelStore.modalVisible = true;
modelStore.params.sttp = 'WE';
modelStore.params.stcd = stcd;
modelStore.params.timeRange = [
dayjs(yearValue.value).startOf('year'),
dayjs(yearValue.value).endOf('year')
];
modelStore.params.ty1 = tabIndex.value;
modelStore.title = stnm;
};
// ==================== Watch ====================
/** 监听 props 变化,同步表单状态 */
watch(
() => [props.tm, props.hbrvcd, props.stcd, props.sectionName],
() => {
formState.value = {
baseId: props.dataDimensionVal || 'all',
rvcd: props.hbrvcd || '',
stcd: props.stcd || '',
yr: props.tm || dayjs().format('YYYY')
};
yearValue.value = props.tm ? dayjs(props.tm) : dayjs();
},
{ immediate: false }
);
// ==================== ====================
onMounted(async () => {
await nextTick();
//
await fetchLyList();
// 沿
if (props.ly) {
await fetchDmList();
}
// Tab
await getTabNumData();
//
handleSearch();
});
</script>
<style lang="scss" scoped>
.yancheng-yulei {
display: flex;
flex-direction: column;
height: 100%;
.search-form {
padding: 16px 0;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 16px;
flex-shrink: 0;
}
.ylycbh-tabs {
flex: 1;
overflow: hidden;
:deep(.ant-tabs-content) {
height: 100%;
}
:deep(.ant-tabs-tabpane) {
height: 100%;
}
}
.table-wrapper {
width: 100%;
}
}
.text-link {
color: #1990ff;
cursor: pointer;
&:hover {
color: #40a9ff;
}
}
</style>

View File

@ -1,209 +1,631 @@
<!-- SidePanelItem.vue --> <!-- 沿程鱼类变化情况 -->
<template> <template>
<SidePanelItem title="水生生态调查" :select="select" :datetimePicker="datetimePicker"> <SidePanelItem
<div ref="chartRef" class="chart-container"></div> title="沿程鱼类变化情况"
</SidePanelItem> :moreSelect="moreSelect"
:select="select"
@update-values="handlePanelChange"
>
<a-spin :spinning="dataLoading" tip="加载中...">
<div
v-show="chartData.length > 0 && select.options.length > 0"
ref="chartRef"
class="chart-container"
></div>
<a-empty
v-show="
!dataLoading &&
(chartData.length === 0 || select.options.length === 0)
"
:description="select.options.length === 0 ? '暂无数据' : '暂无数据'"
class="empty-placeholder"
/>
</a-spin>
</SidePanelItem>
<!-- 沿程鱼类变化详情弹框 -->
<a-modal
v-model:open="modalVisible"
title="沿程鱼类变化"
width="1536px"
:footer="null"
@cancel="handleModalClose"
>
<Yanchengyulei
v-if="modalVisible"
:tm="modalYear"
:dataDimensionVal="baseid"
:hbrvcd="modalHbrvcd"
:jdList="JidiSelectEventStore.jidiData"
:stateName="modalStateName"
:sectionName="modalSectionName"
:stcd="modalStcd"
:ly="true"
/>
</a-modal>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'; import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts'; import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import Yanchengyulei from './TwoLayers/Yanchengyulei.vue';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { wbsbGetKendoList, getDftYear, fishChanges2 } from '@/api/stdc';
import moment from 'moment';
//
defineOptions({ defineOptions({
name: 'shuiShengShengTaiDiaoCha' name: 'alongFishMod'
}); });
// ==================== ==================== // ==================== Store ====================
const JidiSelectEventStore = useJidiSelectEventStore();
// ==================== ====================
/** 当前选中的基地ID来自 JidiSelectEventStore.selectedItem */
const baseid = ref('');
/** 图表数据加载状态 */
const dataLoading = ref(false);
/** 初始化标志位:初始化期间不响应控件变化触发数据请求 */
const isInitializing = ref(false);
// ==================== ====================
/** 流域树形选择器配置 */
const moreSelect = ref({
show: true,
value: undefined as string | undefined,
options: [] as any[]
});
/** 年份选择器配置 */
const select = ref({
show: true,
value: undefined as string | undefined,
options: [] as any[],
picker: undefined,
format: undefined,
width: '120px'
});
/**
* 按流域分组的年份数据
* 结构{ "wbsCode1": [{label:'2023', value:'2023'}], "wbsCode2": [...] }
* 用于流域切换时快速更新年份下拉选项
*/
const yearOptions = ref<Record<string, any[]>>({});
// ==================== ====================
const chartRef = ref<HTMLDivElement>(); const chartRef = ref<HTMLDivElement>();
let chartInstance: any = null; let chartInstance: any = null;
/** 图表原始数据,由 API 返回 */
const chartData = ref<any[]>([]);
// // ==================== ====================
const select = ref({ const modalVisible = ref(false);
show: true, const modalYear = ref('');
value: undefined, const modalHbrvcd = ref('');
options: [], const modalStateName = ref('');
picker: undefined, const modalSectionName = ref('');
format: undefined const modalStcd = ref('');
});
// // ==================== ====================
const datetimePicker = ref({
show: true,
value: '2020',
format: 'YYYY',
picker: 'year' as const,
options: []
});
// /**
* 初始化 ECharts 实例
* onMounted 中调用绑定点击事件用于打开详情弹框
*/
const initChart = () => { const initChart = () => {
if (!chartRef.value) return; if (!chartRef.value) return;
// if (chartInstance) {
if (chartInstance) { chartInstance.dispose();
chartInstance.dispose(); }
chartInstance = echarts.init(chartRef.value);
//
chartInstance.on('click', (params: any) => {
if (params.componentType === 'series') {
openDetail(params);
}
});
updateChart();
};
/**
* 根据 chartData 更新图表配置
* API 返回的 detail 对象key: 1=外来鱼类, 2=本土受威胁, 3=本土无危
* 转换为 ECharts 堆叠柱状图数据
*/
const updateChart = () => {
if (!chartInstance) return;
// sort
const sortedData = [...chartData.value].sort(
(a, b) => (a.sort || 0) - (b.sort || 0)
);
const waimaiData: number[] = [];
const bentuThreatData: number[] = [];
const bentuSafeData: number[] = [];
const xAxisData: string[] = [];
sortedData.forEach((item: any) => {
xAxisData.push(item.stnm || '');
waimaiData.push(item.detail?.['1'] || 0);
bentuThreatData.push(item.detail?.['2'] || 0);
bentuSafeData.push(item.detail?.['3'] || 0);
});
const option: EChartsOption = {
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
backgroundColor: 'rgba(0, 0, 0, 0.5)',
borderColor: 'transparent',
textStyle: { color: '#ffffff' }
},
grid: {
top: 30,
left: '2%',
right: '4%',
bottom: 30,
containLabel: true
},
legend: {
bottom: 0,
itemWidth: 10,
itemHeight: 10
},
yAxis: {
type: 'value',
minInterval: 1,
name: '种',
axisLine: { lineStyle: { color: '#e0e0e0' } },
axisLabel: { color: '#666' },
splitLine: { lineStyle: { color: '#e0e0e0', type: 'solid' } }
},
xAxis: {
type: 'category',
axisTick: { show: false },
axisLabel: {
interval: 0,
rotate: 0,
color: '#666',
rich: {
a: { height: 24, align: 'center' },
b: { height: 30, align: 'center' }
}
},
name: '数量(个)',
data: xAxisData
},
series: [
{
name: '外来鱼类',
type: 'bar',
stack: 'stack',
data: waimaiData,
label: { show: false }
},
{
name: '本土受威胁鱼类',
type: 'bar',
stack: 'stack',
data: bentuThreatData,
label: { show: false }
},
{
name: '本土无危鱼类',
type: 'bar',
stack: 'stack',
data: bentuSafeData,
label: { show: false }
}
],
barWidth: 15,
color: ['#4B79AB', '#78C300', '#9556A4']
};
chartInstance.setOption(option);
nextTick(() => {
chartInstance.resize();
});
};
/** 窗口大小变化时自适应 */
const handleResize = () => {
if (chartInstance) {
chartInstance.resize();
}
};
// ==================== ====================
/**
* 获取年份选项数据
* 调用 getDftYear API按基地/流域分组返回可用年份
* 初始化时调用为每个流域缓存其对应的年份列表
*/
const getYearData = async () => {
try {
const filter: any = {};
if (baseid.value && baseid.value !== 'all') {
filter.baseId = baseid.value;
} }
// const params = {
chartInstance = echarts.init(chartRef.value); filter,
group: [{ dir: 'des', field: 'yr' }]
//
const option: EChartsOption = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
backgroundColor: 'rgba(0, 0, 0, 0.5)',
borderColor: 'transparent',
textStyle: {
color: '#ffffff'
}
},
grid: {
top: 30,
left: '2%',
right: '4%',
bottom: 30,
containLabel: true
},
legend: {
bottom: 0,
itemWidth: 10,
itemHeight: 10
},
yAxis: {
type: 'value',
minInterval: 1,
name: '种',
axisLine: {
lineStyle: {
color: '#e0e0e0'
}
},
axisLabel: {
color: '#666'
},
splitLine: {
lineStyle: {
color: '#e0e0e0',
type: 'solid'
}
}
},
xAxis: {
type: 'category',
axisTick: {
show: false
},
axisLabel: {
interval: 0,
rotate: 0,
color: '#666',
rich: {
a: {
height: 24,
align: 'center'
},
b: {
height: 30,
align: 'center'
}
}
},
name: '数量(个)',
data: [
'两河口',
'杨房沟',
'锦屏一级',
'锦屏二级',
'官地',
'二滩',
'桐子林'
]
},
series: [
{
name: '外来鱼类',
type: 'bar',
stack: 'stack',
data: [0, 0, 0, 0, 0, 1, 2],
label: {
show: true,
position: 'top',
color: '#FFF'
}
},
{
name: '本土受威胁鱼类',
type: 'bar',
stack: 'stack',
data: [1, 10, 10, 5, 4, 6, 11],
label: {
show: true,
position: 'top',
color: '#FFF'
}
},
{
name: '本土无危鱼类',
type: 'bar',
stack: 'stack',
data: [1, 10, 6, 5, 2, 13, 23],
label: {
show: true,
position: 'top',
color: '#FFF'
}
}
],
barWidth: 15,
color: ['#4B79AB', '#78C300', '#9556A4']
}; };
// const res = await getDftYear(params);
chartInstance.setOption(option); const data = res?.data?.data?.[0] || {};
if (Object.keys(data).length > 0) {
const objYear: Record<string, any[]> = {};
const allYears: any[] = [];
Object.keys(data).forEach(key => {
objYear[key] = data[key].map((item: any) => ({
label: String(item),
value: String(item)
}));
allYears.push(...data[key]);
});
yearOptions.value = objYear;
//
const uniqueYears = [...new Set(allYears)].sort(
(a: any, b: any) => Number(b) - Number(a)
);
const latestYear = uniqueYears[0];
// baseid all
const firstWbsCode = Object.keys(data)[0];
select.value.options = objYear[firstWbsCode] || [];
select.value.value = latestYear
? String(latestYear)
: moment().format('YYYY');
} else {
yearOptions.value = {};
select.value.options = [];
select.value.value = moment().format('YYYY');
}
} catch (error) {
console.error('获取年份数据失败:', error);
select.value.options = [];
select.value.value = moment().format('YYYY');
}
}; };
// /**
const handleResize = () => { * 根据选中的流域代码更新年份下拉选项
if (chartInstance) { * yearOptions 缓存中查找对应流域的年份列表并更新 select.options
chartInstance.resize(); * @param wbsCode 流域代码
} */
const updateYearOptionsByBase = async (wbsCode: string) => {
const options = yearOptions.value[wbsCode];
if (options) {
select.value.options = options;
await nextTick();
//
select.value.value = options[0]?.value || '';
} else {
select.value.options = [];
await nextTick();
select.value.value = '';
}
}; };
/**
* 获取流域树形选择器数据 + 年份数据 + 图表数据
* 在基地变化时调用是整个模块数据加载的入口
*/
const getMoreSelectData = async () => {
if (!baseid.value) return;
isInitializing.value = true;
try {
const params = {
filter: {
logic: 'and',
filters: [
{
field: 'wbsType',
operator: 'eq',
value: 'PSB_RVCD'
},
baseid.value !== 'all'
? {
field: 'objid',
operator: 'eq',
value: baseid.value
}
: null
].filter(Boolean)
},
group: [
{ dir: 'asc', field: 'orderIndex' },
{ dir: 'asc', field: 'wbsCode' },
{ dir: 'asc', field: 'wbsName' },
{ dir: 'asc', field: 'objid' }
],
groupResultFlat: true
};
const res = await wbsbGetKendoList(params);
const data = res?.data?.data || [];
if (data.length > 0) {
const treeData = buildTreeData(data);
const filteredData = filterSelectOptions(treeData);
//
moreSelect.value.options = filteredData;
moreSelect.value.value = treeData?.[0]?.children?.[0]?.value;
// yearOptions
await getYearData();
if (moreSelect.value.value) {
await updateYearOptionsByBase(moreSelect.value.value);
}
await getChartData();
} else {
moreSelect.value.options = [];
moreSelect.value.value = undefined;
await getYearData();
}
} catch (error) {
console.error('获取树形选择器数据失败:', error);
moreSelect.value.options = [];
moreSelect.value.value = undefined;
} finally {
isInitializing.value = false;
}
};
/**
* 获取图表数据
* 根据当前选中的流域(hbrvcd)年份(yr)基地(baseId)调用 fishChanges2 API
*/
const getChartData = async () => {
if (!select.value.value) return;
dataLoading.value = true;
try {
const params = {
filter: {
logic: 'and',
filters: [
moreSelect.value.value
? {
field: 'hbrvcd',
operator: 'eq',
dataType: 'string',
value: moreSelect.value.value
}
: null,
{
field: 'yr',
operator: 'eq',
dataType: 'string',
value: moment(select.value.value).format('YYYY')
},
baseid.value !== 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: baseid.value
}
: null
].filter(Boolean)
},
group: [
{ dir: 'des', field: 'stnm' },
{ dir: 'des', field: 'stcd' },
{ dir: 'des', field: 'ty' }
],
groupResultFlat: 'true'
};
const res = await fishChanges2(params);
chartData.value = res?.data?.data || [];
nextTick(() => {
updateChart();
});
} catch (error) {
console.error('获取图表数据失败:', error);
chartData.value = [];
nextTick(() => {
updateChart();
});
} finally {
dataLoading.value = false;
}
};
// ==================== ====================
/**
* API 返回的扁平数据转换为树形结构
* objid基地分组每个基地下包含其流域列表
* @param data 扁平的流域数据数组
*/
const buildTreeData = (data: any[]) => {
if (!data || data.length === 0) return [];
//
const jiDiListMap: Record<string, string> = {};
JidiSelectEventStore.jidiData.forEach((item: any) => {
jiDiListMap[item.wbsCode] = item.wbsName;
});
// objid
const dataMapNameMap: Record<string, any[]> = {};
data.forEach(item => {
const objId = item.objid || item.objId;
if (!dataMapNameMap[objId]) {
dataMapNameMap[objId] = [];
}
const exists = dataMapNameMap[objId].some(
existing => existing.wbsCode === item.wbsCode
);
if (!exists) {
dataMapNameMap[objId].push(item);
}
});
const treeData = Object.keys(dataMapNameMap).map(objId => ({
title: jiDiListMap[objId] || '---',
value: objId,
selectable: false,
children: dataMapNameMap[objId].map((item: any) => ({
title: item.wbsName,
value: item.wbsCode
}))
}));
//
treeData.sort((a, b) => {
const numA = Number(a.value);
const numB = Number(b.value);
const aIsNum = !isNaN(numA);
const bIsNum = !isNaN(numB);
if (aIsNum && bIsNum) return numA - numB;
if (aIsNum) return -1;
if (bIsNum) return 1;
return a.value.localeCompare(b.value);
});
return treeData;
};
/**
* 过滤树形选择器数据
* 当只有一个基地且只有一个流域时直接返回流域列表跳过基地层级
*/
const filterSelectOptions = (options: any[]) => {
if (options?.length === 1 && options?.[0]?.children?.length === 1) {
return options[0].children;
}
return options;
};
// ==================== ====================
/**
* 打开详情弹框
* 点击图表柱子时触发传递当前选中的年份流域站点名称等参数
*/
const openDetail = (params: any) => {
// chartData stcd
const found = chartData.value.find((el: any) => el.stnm === params.name);
modalYear.value = select.value.value;
modalHbrvcd.value = moreSelect.value.value || '';
modalStateName.value = params.name || '';
modalSectionName.value = params.name || '';
modalStcd.value = found?.stcd || '';
modalVisible.value = true;
};
/** 关闭详情弹框 */
const handleModalClose = () => {
modalVisible.value = false;
};
// ==================== ====================
/**
* 处理侧边面板控件变化流域或年份选择改变时触发
* SidePanelItem 内部通过 watch 监听用户操作后 emit 此事件
* @param data 包含 { select, moreSelect, ... } 的变更值
*/
const handlePanelChange = async (data: any) => {
//
if (isInitializing.value) return;
// +
if (
data.moreSelect !== undefined &&
data.moreSelect !== moreSelect.value.value
) {
moreSelect.value.value = data.moreSelect;
await updateYearOptionsByBase(data.moreSelect);
await getChartData();
return; //
}
//
if (data.select !== undefined && data.select !== select.value.value) {
select.value.value = data.select;
await getChartData();
}
};
// ==================== Watch ====================
/**
* 监听基地变化
* 当用户在顶部切换基地时重新加载流域列表年份和图表数据
*/
watch(
() => JidiSelectEventStore.selectedItem,
async newVal => {
if (newVal && newVal.wbsCode) {
baseid.value = newVal.wbsCode;
await getMoreSelectData();
}
},
{ deep: true, immediate: true }
);
// ==================== ==================== // ==================== ====================
//
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
setTimeout(() => { setTimeout(() => {
initChart(); initChart();
window.addEventListener('resize', handleResize); window.addEventListener('resize', handleResize);
}, 50); }, 50);
}); });
}); });
//
onUnmounted(() => { onUnmounted(() => {
// window.removeEventListener('resize', handleResize);
window.removeEventListener('resize', handleResize);
if (chartInstance) {
// chartInstance.dispose();
if (chartInstance) { chartInstance = null;
chartInstance.dispose(); }
chartInstance = null;
}
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chart-container { .chart-container {
width: 100%; width: 100%;
height: 231px; height: 231px;
min-height: 231px; min-height: 231px;
} }
</style>
.empty-placeholder {
width: 100%;
min-height: 231px;
display: flex;
background: #fff;
flex-direction: column;
justify-content: center;
align-items: center;
}
:deep(.ant-empty-description) {
text-indent: 0em !important;
}
</style>

View File

@ -14,7 +14,7 @@ onMounted(() => {});
<template> <template>
<div class="jidiSelectorMod"> <div class="jidiSelectorMod">
<a-spin :spinning="loading"> <a-spin :spinning="JidiSelectEventStore.loading">
<div <div
class="qgc-dropdown-select" class="qgc-dropdown-select"
@mouseenter="jidiDataNum = JidiSelectEventStore.jidiData.length" @mouseenter="jidiDataNum = JidiSelectEventStore.jidiData.length"

View File

@ -0,0 +1,234 @@
<template>
<div class="lsstjk-table">
<!-- 表格 -->
<div class="table-wrapper">
<BasicTable
ref="tableRef"
:columns="columns"
:scroll-y="500"
:scroll-x="800"
:list-url="listUrl"
:search-params="searchParams"
:transform-data="customTransform"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, watch, onMounted } from 'vue';
import BasicTable from '@/components/BasicTable/index.vue';
import { getVmsstbprptList, getTetSpecList } from '@/api/stdc';
import dayjs from 'dayjs';
// ==================== Props ====================
const props = defineProps<{
selectDateTime?: any;
orderIndex?: string;
hbrvcd?: string;
}>();
// ==================== ====================
const tableRef = ref();
const yearValue = ref(
props.selectDateTime ? dayjs(props.selectDateTime) : dayjs()
);
// ==================== URL ====================
const listUrl = computed(() => {
return props.orderIndex === '20' ? getTetSpecList : getVmsstbprptList;
});
// ==================== ====================
const columns = computed(() => {
if (props.orderIndex === '20') {
return [
{
key: 'name',
title: '名称',
dataIndex: 'name',
fixed: 'left' as const,
width: 200,
ellipsis: true
},
{
key: 'nameEn',
title: '英文名称',
dataIndex: 'nameEn',
width: 200,
ellipsis: true
},
{
key: 'protectlvlName',
title: '保护级别',
dataIndex: 'protectlvlName',
width: 200,
ellipsis: true
}
];
}else{
// orderIndex === '16'
return [
{
key: 'box',
title: '监测区域',
dataIndex: 'box',
fixed: 'left' as const,
width: 200,
ellipsis: true
},
{
key: 'stnm',
title: '站点名称',
dataIndex: 'stnm',
width: 200,
ellipsis: true
},
{
key: 'baseName',
title: '所属基地',
dataIndex: 'baseName',
width: 200,
ellipsis: true
},
{
key: 'stlc',
title: '所在地址',
dataIndex: 'stlc',
width: 200,
ellipsis: true
}
];
}
});
// ==================== ====================
const searchParams = computed(() => {
const filters: any[] = [];
if (props.hbrvcd) {
filters.push({
field: 'hbrvcd',
operator: 'in',
dataType: 'string',
value: props.hbrvcd
});
}
if (props.orderIndex === '20') {
filters.push({
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: 'TE_ANIMALS'
});
}
const startTime = `${dayjs(yearValue.value).format('YYYY')}-01-01 00:00:00`;
const endTime = `${dayjs(yearValue.value).format('YYYY')}-12-31 23:59:59`;
filters.push({
field: 'startTime',
operator: 'gte',
dataType: 'date',
value: startTime
});
filters.push({
field: 'endTime',
operator: 'lte',
dataType: 'date',
value: endTime
});
return {
filter: {
logic: 'and',
filters
},
sort: [],
group: [],
select: [],
groupResultFlat: false
};
});
// ==================== ====================
const customTransform = (res: any) => {
return {
records: res?.data?.data || [],
total: res?.data?.total || 0
};
};
// ==================== ====================
const handleSearch = () => {
const filter = getFilter();
tableRef.value?.getList(filter);
};
const getFilter = () => {
const filters: any[] = [
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: 'WVA'
}
];
if (props.hbrvcd) {
filters.push({
field: 'hbrvcd',
operator: 'in',
dataType: 'string',
value: props.hbrvcd
});
}
return {
logic: 'and',
filters
};
};
// ==================== selectDateTime ====================
watch(
() => props.selectDateTime,
newVal => {
if (newVal) {
yearValue.value = dayjs(newVal);
handleSearch();
}
},
{ immediate: false }
);
// ==================== orderIndex ====================
watch(
() => props.orderIndex,
() => {
handleSearch();
}
);
// ==================== ====================
onMounted(() => {
handleSearch();
});
</script>
<style lang="scss" scoped>
.lsstjk-table {
width: 100%;
.search-form {
padding: 16px 0;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 16px;
}
.table-wrapper {
width: 100%;
}
}
</style>

View File

@ -1,133 +1,361 @@
<!-- SidePanelItem.vue --> <!-- SidePanelItem.vue -->
<template> <template>
<SidePanelItem title="水生生态调查情况" :select="select" :datetimePicker="datetimePicker"> <SidePanelItem
<div class="facility-grid"> title="陆生生态监测情况"
<div v-for="facility in facilities" :key="facility.name" class="facility-card"> :select="select"
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;"> :datetimePicker="datetimePicker"
<div class="facility-icon"> @update-values="handlePanelChange"
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i> >
</div> <a-spin :spinning="dataLoading" tip="加载中...">
</div> <div class="facility-grid">
<div
<div class="facility-info"> v-for="facility in facilities"
<div class="facility-name">{{ facility.name }}</div> :key="facility.name"
<div style="font-size: 16px;"> <span class="facility-count">{{ facility.count class="facility-card"
}}</span><span></span></div> @click="handleCardClick(facility)"
</div> >
<div
style="
width: 60px;
height: 62px;
display: flex;
align-items: center;
justify-content: center;
"
>
<div class="facility-icon">
<i
style="color: #fff"
:class="facility.icon"
type="icon-shengtailiuliang2"
></i>
</div> </div>
</div>
<div class="facility-info">
<div class="facility-name">{{ facility.name }}</div>
<div style="font-size: 16px">
<span class="facility-count">{{ facility.count }}</span>
<span>{{ facility.unit }}</span>
</div>
</div>
</div> </div>
</SidePanelItem> </div>
</a-spin>
</SidePanelItem>
<!-- 陆生生态调查概况弹框 -->
<a-modal
v-model:open="modalVisible"
:title="currentOrderIndex === '16' ? '红外相机信息' : '重点陆生动物'"
width="1536px"
:footer="null"
@cancel="handleModalClose"
>
<LsstjkTk
v-if="modalVisible"
:selectDateTime="datetimePicker.value"
:orderIndex="currentOrderIndex"
:hbrvcd="select.value"
/>
</a-modal>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'; import { ref, watch } from 'vue';
import * as echarts from 'echarts'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import LsstjkTk from './LsstjkTk.vue';
import { wbsbGetKendoList, getEvnmAutoMonitor } from '@/api/stdc';
import moment from 'moment';
// //
defineOptions({ defineOptions({
name: 'shuishengshengtaijiance' name: 'lushengshengtaijiance'
}); });
// ==================== ====================// const JidiSelectEventStore = useJidiSelectEventStore();
const baseid = ref('');
const dataLoading = ref(false);
// ==================== ====================
const modalVisible = ref(false);
const currentOrderIndex = ref('16');
// ==================== ====================
//
const select = ref({ const select = ref({
show: true, show: true,
value: undefined, value: undefined,
options: [], options: [],
picker: undefined, picker: undefined,
format: undefined format: undefined,
width: '120px'
}); });
// //
const datetimePicker = ref({ const datetimePicker = ref({
show: true, show: true,
value: `${new Date().getFullYear()}`, value: `${new Date().getFullYear()}`,
format: 'YYYY', format: 'YYYY',
picker: 'year' as const, picker: 'year' as const,
options: [] options: []
}); });
const facilities = ref([ const facilities:any = ref([
{ {
name: '红外相机数量', name: '野生动物监测',
count: 31, count: 0,
icon: 'icon iconfont icon-shipinjiankongshebei' unit: '个',
}, icon: 'icon iconfont icon-dongwujiuzhuzhan',
{ orderInx: '16'
name: '重点陆生动物', },
count: 24, {
icon: 'icon iconfont icon-dongwujiuzhuzhan' name: '重点陆生动物',
}, count: 0,
unit: '种',
icon: 'icon iconfont icon-shipinjiankongshebei',
orderInx: '20'
}
]); ]);
// ==================== ====================
// // ==================== ====================
onMounted(() => { const handlePanelChange = (data: any) => {
console.log('当前所有控件状态:', data);
if (data.select) {
select.value.value = data.select;
}
if (data.datetime) {
datetimePicker.value.value = data.datetime;
}
//
getCardData();
};
}); const handleCardClick = (facility: any) => {
console.log('卡片被点击,准备打开弹框');
// debugger
currentOrderIndex.value = facility.orderInx;
modalVisible.value = true;
};
// const handleModalClose = () => {
onUnmounted(() => { modalVisible.value = false;
};
}); // ==================== ====================
const getCardData = async () => {
if (!datetimePicker.value.value) return;
dataLoading.value = true;
try {
const year = moment(datetimePicker.value.value).format('YYYY');
const startTime = `${year}-01-01 00:00:00`;
const endTime = `${year}-12-31 23:59:59`;
const filters: any[] = [
{
field: 'showIds',
operator: 'in',
value: ['16', '20']
},
{
field: 'startTime',
operator: 'gte',
dataType: 'date',
value: startTime
},
{
field: 'endTime',
operator: 'lte',
dataType: 'date',
value: endTime
}
];
if (baseid.value && baseid.value !== 'all') {
filters.unshift({
field: 'hbrvcd',
operator: 'in',
value: [baseid.value]
});
}
const params = {
filter: {
logic: 'and',
filters
}
};
const res = await getEvnmAutoMonitor(params);
const data = res?.data?.data;
if (data && Array.isArray(data)) {
const wildAnimalItem = data.find((item: any) => item.orderInx === 16);
const keyAnimalItem = data.find((item: any) => item.orderInx === 20);
facilities.value = [
{
name: '野生动物监测',
count: wildAnimalItem?.cnt ?? 0,
unit: '个',
icon: 'icon iconfont icon-dongwujiuzhuzhan',
orderInx: '16'
},
{
name: '重点陆生动物',
count: keyAnimalItem?.cnt ?? 0,
unit: '种',
icon: 'icon iconfont icon-shipinjiankongshebei',
orderInx: '20'
}
];
}
} catch (error) {
console.error('获取统计数据失败:', error);
facilities.value = [
{
name: '野生动物监测',
count: 0,
unit: '个',
icon: 'icon iconfont icon-dongwujiuzhuzhan',
orderInx: '16'
},
{
name: '重点陆生动物',
count: 0,
unit: '种',
icon: 'icon iconfont icon-shipinjiankongshebei',
orderInx: '20'
}
];
} finally {
dataLoading.value = false;
}
};
// ==================== ====================
const getSelectData = async () => {
let params = {
filter: {
logic: 'and',
filters: [
{
field: 'wbsType',
operator: 'eq',
value: 'PSB_RVCD'
},
baseid.value != 'all'
? {
field: 'objId',
operator: 'eq',
value: baseid.value
}
: null
].filter(Boolean)
},
group: [
{
dir: 'asc',
field: 'orderIndex'
},
{
dir: 'asc',
field: 'wbsCode'
},
{
dir: 'asc',
field: 'wbsName'
},
{
dir: 'asc',
field: 'objid'
}
],
groupResultFlat: true
};
const res = await wbsbGetKendoList(params);
let data = res?.data?.data;
select.value.options = data.map((item: any) => {
return {
value: item.wbsCode,
label: item.wbsName
};
});
};
// ==================== ====================
watch(
() => JidiSelectEventStore.selectedItem,
async newVal => {
if (newVal && newVal.wbsCode) {
baseid.value = newVal.wbsCode;
getSelectData();
getCardData();
}
},
{ deep: true, immediate: true }
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.facility-grid { .facility-grid {
width: 406px; width: 406px;
flex-flow: wrap; flex-flow: wrap;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji,
Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
} }
.facility-card { .facility-card {
width: 200px; width: 200px;
height: 64px; height: 64px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
margin: 4px 0px; margin: 4px 0px;
background: #fff; background: #fff;
border: 1px solid #e8e8e8; border: 1px solid rgb(229, 236, 245);
border-radius: 2px; border-radius: 2px;
transition: all 0.3s; transition: all 0.3s;
cursor: pointer; cursor: pointer;
box-sizing: border-box; box-sizing: border-box;
} }
.facility-icon { .facility-icon {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 40px; width: 40px;
height: 40px; height: 40px;
// margin-right: 8px; background: #2f6b98;
background: #2f6b98; border-radius: 50%;
border-radius: 50%;
.anticon { .anticon {
font-size: 24px; font-size: 24px;
color: #fff; color: #fff;
} }
} }
.facility-info { .facility-info {
flex: 1; flex: 1;
} }
.facility-name { .facility-name {
font-size: 16px; font-size: 16px;
color: #333; color: #333;
// margin-bottom: 4px;
// font-weight: 500;
} }
.facility-count { .facility-count {
font-size: 18px; font-size: 18px;
color: #2f6b98; color: #2f6b98;
// font-weight: 600;
} }
</style>
:deep(.ant-spin-nested-loading) {
min-height: 72px;
}
</style>

View File

@ -0,0 +1,362 @@
<template>
<div class="ssst-dcgk-table">
<!-- 搜索表单 -->
<a-form layout="inline" class="search-form">
<a-form-item label="年份">
<a-date-picker
v-model:value="yearValue"
picker="year"
format="YYYY"
:allow-clear="false"
:show-time="false"
style="width: 150px"
@change="handleYearChange"
/>
</a-form-item>
<a-form-item label="调查批次">
<a-select
v-model:value="dcpcValue"
placeholder="请选择"
style="width: 150px"
:options="dcpcOptions"
/>
</a-form-item>
<a-form-item label="调查鱼种类">
<a-input
v-model:value="nameValue"
placeholder="请输入鱼种类"
allow-clear
style="width: 200px"
/>
</a-form-item>
<a-form-item>
<a-space>
<a-button type="primary" @click="handleSearch">查询</a-button>
<a-button @click="handleReset">重置</a-button>
</a-space>
</a-form-item>
</a-form>
<!-- 表格 -->
<div class="table-wrapper">
<BasicTable
ref="tableRef"
:columns="columns"
:scroll-y="500"
:scroll-x="800"
:list-url="listUrl"
:search-params="searchParams"
:transform-data="customTransform"
>
<template #stnm="{ record }">
<a @click="handleViewDetail(record)" class="text-link">
{{ record.stnm }}
</a>
</template>
<template #tm="{ record }">
{{ record.tm ? dayjs(record.tm).format('YYYY-MM-DD') : '-' }}
</template>
<template #fid="{ record }">
<a-button
type="link"
style="padding: 4px"
:disabled="record.fid"
@click="handleViewAttachment(record.fid)"
>
查看附件
</a-button>
</template>
</BasicTable>
</div>
<CommonAttachmentModal
v-model:open="attachmentModalVisible"
:fid="currentAttachmentFid"
title="查看附件"
/>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, watch, onMounted } from 'vue';
import BasicTable from '@/components/BasicTable/index.vue';
import { getWeStaticsSecond } from '@/api/stdc';
import dayjs from 'dayjs';
import { useModelStore } from "@/store/modules/model";
const modelStore = useModelStore();
// ==================== Props ====================
const props = defineProps<{
selectDateTime?: any; //
stcd?: string; //
all?: boolean; //
}>();
// ==================== ====================
const tableRef = ref();
const yearValue = ref(props.selectDateTime ? dayjs(props.selectDateTime) : dayjs());
const dcpcValue = ref('');
const nameValue = ref('');
const dcpcOptions = ref<Array<{ label: string; value: string }>>([
{ label: '全部', value: '' }
]);
// ==================== ====================
const attachmentModalVisible = ref(false);
const currentAttachmentFid = ref('');
// ==================== URL ====================
const listUrl = getWeStaticsSecond;
// ==================== ====================
const searchParams = computed(() => ({
sort: [
{
field: 'tm',
dir: 'desc'
}
],
group: [],
select: [],
groupResultFlat: false
}));
// ==================== ====================
const columns = [
{
key: 'stnm',
title: '断面名称',
dataIndex: 'stnm',
fixed: 'left' as const,
width: 200,
ellipsis: true,
slots: { customRender: 'stnm' },
merge: true,
mergeDeps: ['stnm']
},
{
key: 'tm',
title: '调查日期',
dataIndex: 'tm',
fixed: 'left' as const,
width: 200,
ellipsis: true,
slots: { customRender: 'tm' },
merge: true,
mergeDeps: ['stnm']
},
{
key: 'dcpc',
title: '调查批次',
dataIndex: 'dcpc',
width: 200,
ellipsis: true,
merge: true,
mergeDeps: ['stnm']
},
{
key: 'ftpName',
title: '调查鱼种类',
dataIndex: 'ftpName',
width: 200,
ellipsis: true
},
{
key: 'fcnt',
title: '调查鱼总数',
dataIndex: 'fcnt',
width: 200,
ellipsis: true
},
{
key: 'fid',
title: '证明材料',
dataIndex: 'fid',
width: 200,
ellipsis: true,
slots: { customRender: 'fid' }
}
];
// ==================== ====================
const getFilter = () => {
const filters: any[] = [
{
field: 'year',
operator: 'in',
dataType: 'string',
value: [dayjs(yearValue.value).format('YYYY')]
}
];
//
if (!props.all && props.stcd) {
filters.push({
field: 'rstcd',
operator: 'in',
dataType: 'string',
value: props.stcd
});
}
//
if (dcpcValue.value) {
filters.push({
field: 'dcpc',
operator: 'eq',
dataType: 'string',
value: dcpcValue.value
});
}
//
if (nameValue.value) {
filters.push({
field: 'ftpName',
operator: 'contains',
dataType: 'string',
value: nameValue.value
});
}
return {
logic: 'and',
filters: filters.filter((el: any) => el != null)
};
};
// ==================== ====================
const customTransform = (res: any) => {
return {
records: res?.data?.data || [],
total: res?.data?.total || 0
};
};
// ==================== ====================
const getDcpcOptions = async () => {
try {
const params = {
logic: 'and',
filters: [
...(props.all
? []
: [
{
field: 'rstcd',
operator: 'in',
dataType: 'string',
value: props.stcd
}
]),
{
field: 'year',
operator: 'in',
dataType: 'string',
value: [dayjs(yearValue.value).format('YYYY')]
}
]
};
const group = [
{
dir: 'des',
field: 'dcpc'
}
];
const res = await getWeStaticsSecond( { filter: params, group });
if (res?.data?.data?.length) {
const options = res.data.data.map((item: any) => ({
label: item.dcpc,
value: item.dcpc
}));
dcpcOptions.value = [{ label: '全部', value: '' }, ...options];
} else {
dcpcOptions.value = [{ label: '全部', value: '' }];
}
} catch (error) {
console.error('获取调查批次选项失败:', error);
dcpcOptions.value = [{ label: '全部', value: '' }];
}
};
// ==================== ====================
const handleSearch = () => {
const filter = getFilter();
tableRef.value?.getList(filter);
};
const handleReset = () => {
yearValue.value = props.selectDateTime ? dayjs(props.selectDateTime) : dayjs();
dcpcValue.value = '';
nameValue.value = '';
handleSearch();
};
const handleYearChange = () => {
dcpcValue.value = '';
getDcpcOptions();
};
//
const handleViewDetail = (record: any) => {
modelStore.modalVisible = true;
modelStore.params = record;
modelStore.params.sttp = "WE";
modelStore.title = record.stnm;
};
//
const handleViewAttachment = (fid: string) => {
currentAttachmentFid.value = fid;
attachmentModalVisible.value = true;
};
// ==================== selectDateTime ====================
watch(
() => props.selectDateTime,
(newVal) => {
if (newVal) {
yearValue.value = dayjs(newVal);
getDcpcOptions();
handleSearch();
}
},
{ immediate: false }
);
// ==================== ====================
onMounted(() => {
getDcpcOptions();
handleSearch();
});
</script>
<style lang="scss" scoped>
.ssst-dcgk-table {
width: 100%;
.search-form {
padding: 16px 0;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 16px;
}
.table-wrapper {
width: 100%;
}
}
.text-link {
color: #2f6b98;
&:hover {
color: #40a9ff;
}
}
.detail-placeholder,
.attachment-placeholder {
padding: 40px 0;
}
</style>

View File

@ -1,133 +1,400 @@
<!-- SidePanelItem.vue --> <!-- SidePanelItem.vue -->
<template> <template>
<SidePanelItem title="水生生态调查情况" :select="select" :datetimePicker="datetimePicker"> <SidePanelItem
<div class="facility-grid"> title="水生生态调查情况"
<div v-for="facility in facilities" :key="facility.name" class="facility-card"> :select="select"
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;"> :datetimePicker="datetimePicker"
<div class="facility-icon"> @update-values="handlePanelChange"
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i> >
</div> <a-spin :spinning="dataLoading" tip="加载中...">
</div> <div class="facility-grid">
<div
<div class="facility-info"> v-for="facility in facilities"
<div class="facility-name">{{ facility.name }}</div> :key="facility.name"
<div style="font-size: 16px;"> <span class="facility-count">{{ facility.count class="facility-card"
}}</span><span></span></div> @click="handleCardClick"
</div> >
<div
style="
width: 60px;
height: 62px;
display: flex;
align-items: center;
justify-content: center;
"
>
<div class="facility-icon">
<i
style="color: #fff"
:class="facility.icon"
type="icon-shengtailiuliang2"
></i>
</div> </div>
</div>
<div class="facility-info">
<div class="facility-name">{{ facility.name }}</div>
<div style="font-size: 16px">
<span class="facility-count">{{ facility.count }}</span>
<span>{{ facility.unit }}</span>
</div>
</div>
</div> </div>
</SidePanelItem> </div>
</a-spin>
</SidePanelItem>
<!-- 水生生态调查概况弹框 -->
<a-modal
v-model:open="modalVisible"
title="水生生态调查概况"
width="1536px"
:footer="null"
@cancel="handleModalClose"
>
<SsstdcgkTk
v-if="modalVisible"
:selectDateTime="datetimePicker.value"
:all="true"
/>
</a-modal>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'; import { ref, watch } from 'vue';
import * as echarts from 'echarts'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue'; import SidePanelItem from '@/components/SidePanelItem/index.vue';
import SsstdcgkTk from './SsstdcgkTk.vue';
import { wbsbGetKendoList, getDftYear, getWeFisht } from '@/api/stdc';
import moment from 'moment';
import { Label } from 'cesium';
// //
defineOptions({ defineOptions({
name: 'shuishengshengtaijiance' name: 'shuishengshengtaijiance'
}); });
// ==================== ====================// const JidiSelectEventStore = useJidiSelectEventStore();
const baseid = ref('');
const dataLoading = ref(false);
// ==================== ====================
const modalVisible = ref(false);
// ==================== ====================
//
const select = ref({ const select = ref({
show: true, show: true,
value: undefined, value: undefined,
options: [], options: [],
picker: undefined, picker: undefined,
format: undefined format: undefined,
width: '120px'
}); });
// //
const datetimePicker = ref({ const datetimePicker = ref({
show: true, show: true,
value: '2023', value: '',
format: 'YYYY', format: 'YYYY',
picker: 'year' as const, picker: 'year' as const,
options: [] options: []
}); });
const facilities = ref([ const facilities = ref([
{ {
name: '水生态调查断面', name: '水生态调查断面',
count: 145, count: 0,
icon: 'icon iconfont icon-liuliangjiancezhan' unit: '个',
}, icon: 'icon iconfont icon-liuliangjiancezhan'
{ },
name: '调查鱼类统计', {
count: 24, name: '调查鱼类统计',
icon: 'icon iconfont icon-yuleizengzhizhan' count: 0,
}, unit: '种',
icon: 'icon iconfont icon-yuleizengzhizhan'
}
]); ]);
// ==================== ====================
// // ==================== ====================
onMounted(() => { const handlePanelChange = (data: any) => {
console.log('当前所有控件状态:', data);
if (data.select) {
select.value.value = data.select;
}
if (data.datetime) {
datetimePicker.value.value = data.datetime;
}
//
getCardData();
};
}); const handleCardClick = () => {
console.log('卡片被点击,准备打开弹框');
console.log('modalVisible:', datetimePicker.value.value);
modalVisible.value = true;
console.log('modalVisible:', modalVisible.value);
};
// const handleModalClose = () => {
onUnmounted(() => { modalVisible.value = false;
};
}); // ==================== ====================
const getDefaultYear = async () => {
if (!baseid.value) return;
try {
// const params = {
// filter: { baseId: baseid.value },
// group: [{ dir: 'des', field: 'yr' }]
// };
let params = {
filter: {
logic: 'and',
filters: [
baseid.value != 'all'
? {
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: baseid.value
}
: null
].filter(Boolean)
},
group: [
{
dir: 'des',
field: 'yr'
}
]
};
const res = await getDftYear(params);
const data = res?.data?.data?.[0] || {};
const allYears = Object.values(data);
if (allYears?.length) {
const last = (allYears as any[]).flat().sort().pop();
datetimePicker.value.value = last;
} else {
datetimePicker.value.value = moment().format('YYYY');
}
//
getCardData();
} catch (error) {
console.error('获取默认年份失败:', error);
datetimePicker.value.value = moment().format('YYYY');
getCardData();
}
};
// ==================== ====================
const getCardData = async () => {
if (!datetimePicker.value.value) return;
dataLoading.value = true;
try {
const filters: any[] = [
{
field: 'yr',
operator: 'eq',
dataType: 'string',
value: moment(datetimePicker.value.value).format('YYYY')
}
];
if (baseid.value && baseid.value !== 'all') {
filters.push({
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: baseid.value
});
}
if (select.value.value) {
filters.push({
field: 'hbrvcd',
operator: 'eq',
dataType: 'string',
value: select.value.value
});
}
const params = {
filter: {
logic: 'and',
filters
},
group: [],
groupResultFlat: true
};
const res = await getWeFisht(params);
const data = res?.data?.data?.[0];
facilities.value = [
{
name: '水生态调查断面',
count: data?.stcdCount ?? 0,
unit: '个',
icon: 'icon iconfont icon-liuliangjiancezhan'
},
{
name: '调查鱼类统计',
count: data?.ftpCount ?? 0,
unit: '种',
icon: 'icon iconfont icon-yuleizengzhizhan'
}
];
} catch (error) {
console.error('获取统计数据失败:', error);
facilities.value = [
{
name: '水生态调查断面',
count: 0,
unit: '个',
icon: 'icon iconfont icon-liuliangjiancezhan'
},
{
name: '调查鱼类统计',
count: 0,
unit: '种',
icon: 'icon iconfont icon-yuleizengzhizhan'
}
];
} finally {
dataLoading.value = false;
}
};
// ==================== ====================
const getSelectData = async () => {
let params = {
filter: {
logic: 'and',
filters: [
{
field: 'wbsType',
operator: 'eq',
value: 'PSB_RVCD'
},
baseid.value != 'all'
? {
field: 'objId',
operator: 'eq',
value: '水生生态调查情况'
}
: null
].filter(Boolean)
},
group: [
{
dir: 'asc',
field: 'orderIndex'
},
{
dir: 'asc',
field: 'wbsCode'
},
{
dir: 'asc',
field: 'wbsName'
},
{
dir: 'asc',
field: 'objid'
}
],
groupResultFlat: true
};
const res = await wbsbGetKendoList(params);
let data = res?.data?.data;
select.value.options = data.map((item: any) => {
return {
value: item.wbsCode,
label: item.wbsName
};
});
};
// ==================== ====================
watch(
() => JidiSelectEventStore.selectedItem,
async newVal => {
if (newVal && newVal.wbsCode) {
baseid.value = newVal.wbsCode;
getSelectData();
getDefaultYear();
}
},
{ deep: true, immediate: true }
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.facility-grid { .facility-grid {
width: 406px; width: 406px;
flex-flow: wrap; flex-flow: wrap;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji,
Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
} }
.facility-card { .facility-card {
width: 200px; width: 200px;
height: 64px; height: 64px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
margin: 4px 0px; margin: 4px 0px;
background: #fff; background: #fff;
border: 1px solid #e8e8e8; border: 1px solid rgb(229, 236, 245);
border-radius: 2px; border-radius: 2px;
transition: all 0.3s; transition: all 0.3s;
cursor: pointer; cursor: pointer;
box-sizing: border-box; box-sizing: border-box;
} }
.facility-icon { .facility-icon {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 40px; width: 40px;
height: 40px; height: 40px;
// margin-right: 8px; // margin-right: 8px;
background: #2f6b98; background: #2f6b98;
border-radius: 50%; border-radius: 50%;
.anticon { .anticon {
font-size: 24px; font-size: 24px;
color: #fff; color: #fff;
} }
} }
.facility-info { .facility-info {
flex: 1; flex: 1;
} }
.facility-name { .facility-name {
font-size: 16px; font-size: 16px;
color: #333; color: #333;
// margin-bottom: 4px; // margin-bottom: 4px;
// font-weight: 500; // font-weight: 500;
} }
.facility-count { .facility-count {
font-size: 18px; font-size: 18px;
color: #2f6b98; color: #2f6b98;
// font-weight: 600; // font-weight: 600;
} }
</style>
:deep(.ant-spin-nested-loading) {
min-height: 72px;
}
</style>

View File

@ -1,81 +1,15 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { ref } from 'vue'; import { ref, onMounted } from 'vue';
import { wbsbGetKendoList } from '@/api/select';
export const useJidiSelectEventStore = defineStore('jidiSelectEvent', () => { export const useJidiSelectEventStore = defineStore('jidiSelectEvent', () => {
const jidiData: any = ref([ const jidiData: any = ref([
{ {
wbsCode: 'all', wbsCode: 'all',
wbsName: '当前全部', wbsName: '当前全部',
selected: true selected: true
},
{
wbsCode: '01',
wbsName: '金沙江干流',
selected: false
},
{
wbsCode: '02',
wbsName: '雅砻江干流',
selected: false
},
{
wbsCode: '03',
wbsName: '大渡河干流',
selected: false
},
{
wbsCode: '04',
wbsName: '乌江干流',
selected: false
},
{
wbsCode: '05',
wbsName: '长江上游干流',
selected: false
},
{
wbsCode: '10',
wbsName: '湘西',
selected: false
},
{
wbsCode: '08',
wbsName: '黄河上游干流',
selected: false
},
{
wbsCode: '09',
wbsName: '黄河中游干流',
selected: false
},
{
wbsCode: '06',
wbsName: '南盘江-红水河',
selected: false
},
{
wbsCode: '12',
wbsName: '东北',
selected: false
},
{
wbsCode: '07',
wbsName: '澜沧江干流',
selected: false
},
{
wbsCode: '13',
wbsName: '怒江干流'
},
{
wbsCode: '11',
wbsName: '闽浙赣'
},
{
wbsCode: 'other',
wbsName: '其他'
} }
]); ]);
const loading = ref(false);
const selectedItem = ref(jidiData.value[0]); const selectedItem = ref(jidiData.value[0]);
const updataJidiData = (index: any) => { const updataJidiData = (index: any) => {
console.log(index); console.log(index);
@ -85,10 +19,58 @@ export const useJidiSelectEventStore = defineStore('jidiSelectEvent', () => {
}); });
jidiData.value[index].selected = true; jidiData.value[index].selected = true;
}; };
const getJidiData = async () => {
loading.value = true;
let params = {
filter: {
logic: 'and',
filters: [
{
field: 'wbsType',
operator: 'eq',
dataType: 'string',
value: 'PSB'
},
{
field: 'treeLevel',
operator: 'eq',
dataType: 'string',
value: '1'
}
]
},
sort: [
{
field: 'orderIndex',
dir: 'asc'
}
],
select: ['wbsCode', 'wbsName']
};
const res = await wbsbGetKendoList(params);
let data = res?.data?.data || [
{
wbsCode: 'all',
wbsName: '当前全部',
selected: true
}
];
jidiData.value = data.map((item: any) => {
return {
...item,
selected: item.wbsCode == 'all' ? true : false
};
});
loading.value = false;
};
onMounted(() => {
getJidiData();
});
return { return {
jidiData, jidiData,
selectedItem, selectedItem,
updataJidiData updataJidiData,
loading
}; };
}); });

View File

@ -154,7 +154,7 @@ const showMapModal17 = () => {
<!-- <a-button @click="showMapModal7">打开动物救助站弹窗</a-button> --> <!-- <a-button @click="showMapModal7">打开动物救助站弹窗</a-button> -->
<!-- <a-button @click="showMapModal8">打开珍稀植物园弹窗</a-button> --> <!-- <a-button @click="showMapModal8">打开珍稀植物园弹窗</a-button> -->
<!-- <a-button @click="showMapModal9">打开水生生态调查断面弹窗</a-button> --> <!-- <a-button @click="showMapModal9">打开水生生态调查断面弹窗</a-button> -->
<!-- <a-button @click="showMapModal10">打开野生动物监测弹窗</a-button> --> <a-button @click="showMapModal10">打开野生动物监测弹窗</a-button>
<!-- <a-button @click="showMapModal11">打开AI视频监控站弹窗</a-button> --> <!-- <a-button @click="showMapModal11">打开AI视频监控站弹窗</a-button> -->
<!-- <a-button @click="showMapModal12">打开水电站告警情况弹窗</a-button> --> <!-- <a-button @click="showMapModal12">打开水电站告警情况弹窗</a-button> -->
<!-- <a-button @click="showMapModal13">打开鱼类调查装置弹窗</a-button> --> <!-- <a-button @click="showMapModal13">打开鱼类调查装置弹窗</a-button> -->