feat: 环保部-水生生态调查-鱼类分布锚点

This commit is contained in:
tangwei 2026-06-26 09:23:17 +08:00
parent 2e6a1197f5
commit a96b76afcf
4 changed files with 345 additions and 0 deletions

View File

@ -50,4 +50,10 @@ public class WeFishController {
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));
}
}

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

@ -3,6 +3,7 @@ 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.WeFishListStatQgcVo;
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;
@ -21,4 +22,6 @@ public interface WeFishService {
DataSourceResult<WeFishStatQgcVo> getQgcWeFishStatList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishListStatQgcVo> getQgcFishListStat(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishPointQgcVo> getQgcWeFishPoint(DataSourceRequest dataSourceRequest);
}

View File

@ -11,6 +11,7 @@ import com.yfd.platform.common.GroupHelper;
import com.yfd.platform.common.GroupingInfo;
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListStatQgcVo;
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.WeRvcdYearVo;
@ -20,14 +21,17 @@ import com.yfd.platform.utils.QgcQueryWrapperUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Service
public class WeFishServiceImpl implements WeFishService {
@ -230,6 +234,38 @@ public class WeFishServiceImpl implements WeFishService {
return result;
}
@Override
public DataSourceResult<WeFishPointQgcVo> getQgcWeFishPoint(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
String stcd = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "stcd");
String baseId = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "baseId");
String startTime = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "startTime");
String endTime = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "endTime");
List<String> fishList = getWeFishFilterTexts(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), "fishList");
Map<String, Object> paramMap = new HashMap<>();
String sql = buildWeFishPointQgcSql(stcd, baseId, startTime, endTime, fishList, paramMap);
Page<?> page = loadOptions == null ? null
: QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
List<Map<String, Object>> rows = microservicDynamicSQLMapper.pageAllList(page, sql, paramMap);
Map<String, String> fishNameMap = loadWeFishNameMap();
List<WeFishPointQgcVo> list = new ArrayList<>();
for (Map<String, Object> row : rows) {
WeFishPointQgcVo vo = buildWeFishPointQgcVo(row, fishNameMap);
if (vo != null) {
list.add(vo);
}
}
applyWeFishPointMapDistance(list);
DataSourceResult<WeFishPointQgcVo> result = new DataSourceResult<>();
result.setData(list);
result.setTotal(page != null ? page.getTotal() : list.size());
result.setAggregates(new HashMap<>());
return result;
}
private String buildWeFishQgcGroupSql(String baseSql, GroupingInfo[] groupInfos) {
if (groupInfos == null || groupInfos.length == 0) {
return baseSql;
@ -474,6 +510,96 @@ public class WeFishServiceImpl implements WeFishService {
"AND NVL(we.STATUS, 1) = 1 ";
}
private String buildWeFishPointQgcSql(String stcd,
String baseId,
String startTime,
String endTime,
List<String> fishList,
Map<String, Object> paramMap) {
Date start = null;
Date end = null;
if (StrUtil.isNotBlank(startTime) && StrUtil.isNotBlank(endTime)) {
start = parseDateTimeSafely(startTime);
end = parseDateTimeSafely(endTime);
}
StringBuilder sql = new StringBuilder();
sql.append("SELECT agg.ftp AS ftp, section.STCD AS stcd, section.RSTCD AS rstcds, ")
.append("section.STNM AS stnm, eng.ENNM AS ennm, ")
.append("section.LGTD AS lgtd, section.LTTD AS lttd, ")
.append("'ylfb' AS sttp, 'ylfb' AS sttpMap, ")
.append("section.RVCD AS rvcd, section.ADDVCD AS addvcd, section.BASE_ID AS baseId, ")
.append("'WE' AS sttpCode, 'ylfb' AS anchoPointState, '鱼类分布' AS titleName, ")
.append("eng.ELEV AS dtmel ")
.append("FROM (")
.append("SELECT LISTAGG(TO_CHAR(t.ID), ',') WITHIN GROUP (ORDER BY t.ID) AS ftp, t.stcd ")
.append("FROM (")
.append("SELECT dict.ZY_FISH_ID AS ID, we.STCD AS stcd ")
.append("FROM SD_WE_R we ")
.append("INNER JOIN SD_WE_B_H section ON we.STCD = section.STCD ")
.append(" AND NVL(section.USFL, 0) = 1 ")
.append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ")
.append(" AND NVL(fish.IS_DELETED, 0) = 0 ")
.append("INNER JOIN V_SD_FISHDICTORY_B dict ON dict.FISH_ID = fish.FTP ")
.append(" AND (section.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') ")
.append("WHERE NVL(we.IS_DELETED, 0) = 0 ")
.append("AND NVL(we.STATUS, 1) = 1 ");
if (StrUtil.isNotBlank(stcd)) {
paramMap.put("weFishPointStcd", stcd);
sql.append("AND we.STCD = #{map.weFishPointStcd} ");
}
if (start != null && end != null) {
paramMap.put("weFishPointStartTime", start);
paramMap.put("weFishPointEndTime", end);
sql.append("AND we.TM BETWEEN #{map.weFishPointStartTime} AND #{map.weFishPointEndTime} ");
}
if (CollUtil.isNotEmpty(fishList)) {
List<String> placeholders = new ArrayList<>();
int index = 0;
for (String fishId : fishList) {
if (StrUtil.isBlank(fishId)) {
continue;
}
String key = "weFishPointFish" + index++;
paramMap.put(key, fishId);
placeholders.add("#{map." + key + "}");
}
if (CollUtil.isNotEmpty(placeholders)) {
sql.append("AND we.STCD IN (")
.append("SELECT a.STCD ")
.append("FROM SD_WE_R a ")
.append("INNER JOIN SD_WE_B_H section2 ON a.STCD = section2.STCD ")
.append(" AND NVL(section2.USFL, 0) = 1 ")
.append("INNER JOIN SD_WEFISH_R b ON a.ID = b.WER_ID ")
.append(" AND NVL(b.IS_DELETED, 0) = 0 ")
.append("INNER JOIN V_SD_FISHDICTORY_B c ON c.FISH_ID = b.FTP ")
.append(" AND (section2.HBRVCD = c.RVCD OR c.RVCD = 'ZY') ")
.append("WHERE NVL(a.IS_DELETED, 0) = 0 ")
.append("AND NVL(a.STATUS, 1) = 1 ");
if (start != null && end != null) {
sql.append("AND a.TM BETWEEN #{map.weFishPointStartTime} AND #{map.weFishPointEndTime} ");
}
sql.append("AND c.FISH_ID IN (").append(String.join(", ", placeholders)).append(")")
.append(") ");
}
}
sql.append("GROUP BY we.STCD, dict.ZY_FISH_ID")
.append(") t GROUP BY t.stcd")
.append(") agg ")
.append("INNER JOIN SD_WE_B_H section ON agg.stcd = section.STCD ")
.append(" AND NVL(section.USFL, 0) = 1 ")
.append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = section.RSTCD ")
.append(" AND NVL(eng.IS_DELETED, 0) = 0 ")
.append("WHERE 1 = 1 ");
if (StrUtil.isNotBlank(baseId)) {
paramMap.put("weFishPointBaseId", baseId);
sql.append("AND section.BASE_ID = #{map.weFishPointBaseId} ");
}
sql.append("ORDER BY section.STCD ASC");
return sql.toString();
}
private String buildWeFishStaticsSql(String baseId,
String hbrvcd,
String yr,
@ -997,6 +1123,152 @@ public class WeFishServiceImpl implements WeFishService {
.setFcnt(toWeFishLongValue(firstPresentWeFishValue(row, "FCNT", "fcnt")));
}
private WeFishPointQgcVo buildWeFishPointQgcVo(Map<String, Object> row, Map<String, String> fishNameMap) {
if (row == null || row.isEmpty()) {
return null;
}
return new WeFishPointQgcVo()
.setFtp(resolveWeFishNames(firstPresentWeFishValue(row, "FTP", "ftp"), fishNameMap))
.setStcd(safeWeFishString(firstPresentWeFishValue(row, "STCD", "stcd")))
.setRstcds(safeWeFishString(firstPresentWeFishValue(row, "RSTCDS", "rstcds")))
.setStnm(safeWeFishString(firstPresentWeFishValue(row, "STNM", "stnm")))
.setEnnm(safeWeFishString(firstPresentWeFishValue(row, "ENNM", "ennm")))
.setLgtd(toWeFishBigDecimalValue(firstPresentWeFishValue(row, "LGTD", "lgtd")))
.setLttd(toWeFishBigDecimalValue(firstPresentWeFishValue(row, "LTTD", "lttd")))
.setSttp(safeWeFishString(firstPresentWeFishValue(row, "STTP", "sttp")))
.setSttpMap(safeWeFishString(firstPresentWeFishValue(row, "STTPMAP", "sttpMap")))
.setRvcd(safeWeFishString(firstPresentWeFishValue(row, "RVCD", "rvcd")))
.setAddvcd(safeWeFishString(firstPresentWeFishValue(row, "ADDVCD", "addvcd")))
.setBaseId(safeWeFishString(firstPresentWeFishValue(row, "BASEID", "baseId")))
.setSttpCode(safeWeFishString(firstPresentWeFishValue(row, "STTPCODE", "sttpCode")))
.setAnchoPointState(safeWeFishString(firstPresentWeFishValue(row, "ANCHOPOINTSTATE", "anchoPointState")))
.setTitleName(safeWeFishString(firstPresentWeFishValue(row, "TITLENAME", "titleName")))
.setDtmel(toWeFishBigDecimalValue(firstPresentWeFishValue(row, "DTMEL", "dtmel")));
}
private Map<String, String> loadWeFishNameMap() {
List<Map<String, Object>> rows = microservicDynamicSQLMapper.getAllList(
"SELECT ID AS id, NAME AS name FROM SD_FISHDICTORY_B WHERE NVL(IS_DELETED, 0) = 0",
new HashMap<>()
);
Map<String, String> fishNameMap = new LinkedHashMap<>();
for (Map<String, Object> row : rows) {
String id = safeWeFishString(firstPresentWeFishValue(row, "ID", "id"));
String name = safeWeFishString(firstPresentWeFishValue(row, "NAME", "name"));
if (StrUtil.isNotBlank(id) && StrUtil.isNotBlank(name)) {
fishNameMap.put(id, name);
}
}
return fishNameMap;
}
private String resolveWeFishNames(Object ftpValue, Map<String, String> fishNameMap) {
String ftp = safeWeFishString(ftpValue);
if (StrUtil.isBlank(ftp)) {
return "";
}
String[] ids = ftp.split(",");
List<String> names = new ArrayList<>();
for (String id : ids) {
String trimId = StrUtil.trim(id);
if (StrUtil.isBlank(trimId)) {
continue;
}
String name = fishNameMap.get(trimId);
if (StrUtil.isNotBlank(name)) {
names.add(name);
}
}
return names.isEmpty() ? "" : String.join(",", names);
}
private void applyWeFishPointMapDistance(List<WeFishPointQgcVo> points) {
if (CollUtil.isEmpty(points)) {
return;
}
int defaultLevel = 50000000;
int level1 = 1500000;
double level1Distance = 1.2D;
int level2 = 800000;
double level2Distance = 0.8D;
int level3 = 400000;
double level3Distance = 0.4D;
int level4 = 50000;
double level4Distance = 0.1D;
Set<String> marked = new HashSet<>();
for (int i = 0; i < points.size(); i++) {
WeFishPointQgcVo current = points.get(i);
String category = current.getAnchoPointState();
String currentKey = StrUtil.nullToEmpty(current.getStcd()) + StrUtil.nullToEmpty(category);
if (marked.contains(currentKey)) {
continue;
}
current.setDistance(defaultLevel);
BigDecimal x1 = current.getLgtd();
BigDecimal y1 = current.getLttd();
if (x1 == null || y1 == null) {
continue;
}
for (int j = i + 1; j < points.size(); j++) {
WeFishPointQgcVo target = points.get(j);
String targetCategory = target.getAnchoPointState();
String targetKey = StrUtil.nullToEmpty(target.getStcd()) + StrUtil.nullToEmpty(targetCategory);
if (marked.contains(targetKey)) {
continue;
}
BigDecimal x2 = target.getLgtd();
BigDecimal y2 = target.getLttd();
if (x2 == null || y2 == null || currentKey.equals(targetKey)) {
continue;
}
double dx = Math.abs(x1.doubleValue() - x2.doubleValue());
double dy = Math.abs(y1.doubleValue() - y2.doubleValue());
double distance = Math.sqrt(dx * dx + dy * dy);
if (distance < level4Distance) {
target.setDistance(level4);
marked.add(targetKey);
} else if (distance < level3Distance) {
target.setDistance(level3);
marked.add(targetKey);
} else if (distance < level2Distance) {
target.setDistance(level2);
marked.add(targetKey);
} else if (distance < level1Distance) {
target.setDistance(level1);
marked.add(targetKey);
}
}
}
}
private java.math.BigDecimal toWeFishBigDecimalValue(Object value) {
if (value == null) {
return null;
}
if (value instanceof java.math.BigDecimal decimal) {
return decimal;
}
if (value instanceof Number number) {
return java.math.BigDecimal.valueOf(number.doubleValue());
}
try {
return new java.math.BigDecimal(String.valueOf(value).trim());
} catch (Exception ex) {
return null;
}
}
private String resolveWeFishStringFilterValue(DataSourceRequest dataSourceRequest,
DataSourceLoadOptionsBase loadOptions,
String field) {
String value = getFirstWeFishFilterText(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), field);
if (StrUtil.isBlank(value) && loadOptions != null) {
value = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, field);
}
return StrUtil.trim(value);
}
private Date toDateValue(Object value) {
if (value == null) {
return null;