feat: 野生动物监测情况

This commit is contained in:
tangwei 2026-06-11 17:13:39 +08:00
parent ddde939ad7
commit 23f0c51edd
4 changed files with 402 additions and 1 deletions

View File

@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/vap") @RequestMapping("/vap")
@Tag(name = "珍稀植物园建设及接入情况") @Tag(name = "珍稀植物园建设及接入情况")
@Validated @Validated
public class VpConstructionController { public class VapConstructionController {
@Resource @Resource
private VpConstructionService vpConstructionService; private VpConstructionService vpConstructionService;
@ -46,4 +46,10 @@ public class VpConstructionController {
public ResponseResult basinVpIntDetail(@RequestBody DataSourceRequest dataSourceRequest) { public ResponseResult basinVpIntDetail(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(vpConstructionService.basinVpIntDetail(dataSourceRequest)); return ResponseResult.successData(vpConstructionService.basinVpIntDetail(dataSourceRequest));
} }
@PostMapping("/wva/GetKendoListCust")
@Operation(summary = "野生动物监测情况")
public ResponseResult getWvaKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(vpConstructionService.processWvaKendoList(dataSourceRequest));
}
} }

View File

@ -0,0 +1,88 @@
package com.yfd.platform.qgc_env.vap.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 VpWvaRunVo {
@Schema(description = "站点编码")
private String stcd;
@Schema(description = "站点名称")
private String stnm;
@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 = "平台ID")
private String platformId;
@Schema(description = "部门ID")
private String departmentId;
@Schema(description = "是否暂存")
private Long isTempStorage;
@Schema(description = "站类编码")
private String sttpCode;
@Schema(description = "站类名称")
private String sttpName;
@Schema(description = "所属基地编码")
private String baseId;
@Schema(description = "所属基地名称")
private String baseName;
@Schema(description = "所属电站编码")
private String rstcd;
@Schema(description = "所属电站名称")
private String ennm;
@Schema(description = "所属基地流域编码")
private String hbrvcd;
@Schema(description = "所属基地流域名称")
private String hbrvcdName;
@Schema(description = "建设状态编码")
private String bldsttCcode;
@Schema(description = "建设状态名称")
private String bldsttCcodeName;
@Schema(description = "动物类型")
private String tetp;
@Schema(description = "救助数量")
private Integer tecnt;
@Schema(description = "放生地点")
private String stlc;
@Schema(description = "原始照片路径")
private String fpth;
}

View File

@ -4,6 +4,7 @@ import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinIntDetailVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinIntDetailVo;
import com.yfd.platform.qgc_env.vap.entity.vo.VpStInfoResultVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpStInfoResultVo;
import com.yfd.platform.qgc_env.vap.entity.vo.VpWvaRunVo;
public interface VpConstructionService { public interface VpConstructionService {
@ -14,4 +15,6 @@ public interface VpConstructionService {
VpStInfoResultVo getStInfoByStcd(String stcd); VpStInfoResultVo getStInfoByStcd(String stcd);
DataSourceResult<VpBasinIntDetailVo> basinVpIntDetail(DataSourceRequest dataSourceRequest); DataSourceResult<VpBasinIntDetailVo> basinVpIntDetail(DataSourceRequest dataSourceRequest);
DataSourceResult<VpWvaRunVo> processWvaKendoList(DataSourceRequest dataSourceRequest);
} }

View File

@ -14,6 +14,7 @@ import com.yfd.platform.qgc_env.vap.entity.vo.VpConstructionSituationVo;
import com.yfd.platform.qgc_env.vap.entity.vo.VpStBaseInfoVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpStBaseInfoVo;
import com.yfd.platform.qgc_env.vap.entity.vo.VpStInfoResultVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpStInfoResultVo;
import com.yfd.platform.qgc_env.vap.entity.vo.VpVmsstbprptVo; import com.yfd.platform.qgc_env.vap.entity.vo.VpVmsstbprptVo;
import com.yfd.platform.qgc_env.vap.entity.vo.VpWvaRunVo;
import com.yfd.platform.qgc_env.vap.service.VpConstructionService; import com.yfd.platform.qgc_env.vap.service.VpConstructionService;
import com.yfd.platform.utils.KendoUtil; import com.yfd.platform.utils.KendoUtil;
import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.QgcQueryWrapperUtil;
@ -171,6 +172,309 @@ public class VpConstructionServiceImpl implements VpConstructionService {
return result; return result;
} }
@Override
public DataSourceResult<VpWvaRunVo> processWvaKendoList(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
PageInfo pageInfo = loadOptions == null ? new PageInfo() : QgcQueryWrapperUtil.getPageInfo(loadOptions);
Page<?> page = pageInfo.getHasPageInfo() ? pageInfo.getPage() : null;
Map<String, Object> paramMap = new HashMap<>();
StringBuilder sql = new StringBuilder(buildWvaBaseSql());
String filterSql = buildWvaFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(),
paramMap, new int[]{0});
if (StrUtil.isNotBlank(filterSql)) {
sql.append(" AND ").append(filterSql);
}
String groupBy = dataSourceRequest == null ? null : KendoUtil.getGroupBy(dataSourceRequest);
GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup();
if (StrUtil.isNotBlank(groupBy) && groupInfos != null && groupInfos.length > 0) {
String groupedSql = buildWvaGroupSql(sql.toString(), groupInfos);
List<Map<String, Object>> rows = microservicDynamicSQLMapper.pageAllList(null, groupedSql, paramMap);
DataSourceResult result = new DataSourceResult();
if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) {
result.setData(new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos)));
} else {
result.setData(new GroupHelper().group(rows, Arrays.asList(groupInfos)));
}
result.setTotal(0L);
result.setAggregates(new HashMap<>());
return result;
}
sql.append(buildWvaOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort()));
List<VpWvaRunVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(
page, sql.toString(), paramMap, VpWvaRunVo.class
);
DataSourceResult<VpWvaRunVo> result = new DataSourceResult<>();
result.setData(list);
result.setTotal(page != null ? page.getTotal() : list.size());
result.setAggregates(new HashMap<>());
return result;
}
private String buildWvaBaseSql() {
return "SELECT " +
"va.STCD AS stcd, " +
"vb.STNM AS stnm, " +
"va.TM AS tm, " +
"vb.STNM || ' ' || TO_CHAR(va.TM, 'yyyy-MM-dd HH24') AS flnm, " +
"va.FPTH AS imgPath, " +
"va.FPTH AS flpth, " +
"va.FID AS fid, " +
"va.DESCRIPTION AS description, " +
"CAST(NULL AS VARCHAR2(36)) AS platformId, " +
"CAST(NULL AS VARCHAR2(36)) AS departmentId, " +
"CAST(NULL AS NUMBER(1,0)) AS isTempStorage, " +
"vb.STTP AS sttpCode, " +
"sttp.STTP_NAME AS sttpName, " +
"vb.BASE_ID AS baseId, " +
"hb.BASENAME AS baseName, " +
"vb.RSTCD AS rstcd, " +
"eng.ENNM AS ennm, " +
"vb.HBRVCD AS hbrvcd, " +
"hbrv.HBRVNM AS hbrvcdName, " +
"TO_CHAR(vb.BLDSTT_CODE) AS bldsttCcode, " +
"CASE WHEN vb.BLDSTT_CODE IN (1, 10, 11) THEN '已建' " +
"WHEN vb.BLDSTT_CODE IN (2, 7, 8) THEN '在建' ELSE '未建/规划' END AS bldsttCcodeName, " +
"va.TETP AS tetp, " +
"va.TECNT AS tecnt, " +
"va.STLC AS stlc, " +
"va.FPTH AS fpth, " +
"NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " +
"NVL(hbrv.ORDER_INDEX, 999999) AS rvcdStepSort, " +
"NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " +
"NVL(vb.ORDER_INDEX, 999999) AS siteStepSort " +
"FROM SD_VA_R va " +
"INNER JOIN SD_VA_B_H vb ON vb.STCD = va.STCD AND NVL(vb.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = vb.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = vb.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = vb.HBRVCD " +
"AND (hbrv.BASEID = vb.BASE_ID OR vb.BASE_ID IS NULL) " +
"AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " +
"LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = vb.STTP " +
"AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " +
"WHERE NVL(va.IS_DELETED, 0) = 0 ";
}
private String buildWvaFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
if (filter == null) {
return "";
}
if (StrUtil.isNotBlank(filter.getField())) {
return buildWvaLeafCondition(filter, paramMap, indexHolder);
}
if (CollectionUtils.isEmpty(filter.getFilters())) {
return "";
}
List<String> conditions = new ArrayList<>();
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
String childSql = buildWvaFilterCondition(child, paramMap, indexHolder);
if (StrUtil.isNotBlank(childSql)) {
conditions.add("(" + childSql + ")");
}
}
if (conditions.isEmpty()) {
return "";
}
return String.join("or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND ", conditions);
}
private String buildWvaLeafCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
String field = filter.getField();
Object value = filter.getValue();
String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase();
if ("keyword".equals(field)) {
if (value == null || StrUtil.isBlank(String.valueOf(value))) {
return "";
}
String paramKey = "wvaParam" + indexHolder[0]++;
paramMap.put(paramKey, "%" + value + "%");
return "(vb.STNM LIKE #{map." + paramKey + "} OR hb.BASENAME LIKE #{map." + paramKey + "} " +
"OR eng.ENNM LIKE #{map." + paramKey + "} OR va.TETP LIKE #{map." + paramKey + "} " +
"OR va.DESCRIPTION LIKE #{map." + paramKey + "})";
}
String column = mapWvaColumn(field);
if (StrUtil.isBlank(column)) {
return "";
}
if ("isnull".equals(operator)) {
return column + " IS NULL";
}
if ("isnotnull".equals(operator)) {
return column + " IS NOT NULL";
}
if ("in".equals(operator)) {
List<Object> values = normalizeValues(value);
if (values.isEmpty()) {
return "";
}
List<String> placeholders = new ArrayList<>();
for (Object item : values) {
String paramKey = "wvaParam" + indexHolder[0]++;
paramMap.put(paramKey, item);
placeholders.add("#{map." + paramKey + "}");
}
return column + " IN (" + String.join(", ", placeholders) + ")";
}
if (value == null) {
return "";
}
String paramKey = "wvaParam" + indexHolder[0]++;
switch (operator) {
case "eq":
paramMap.put(paramKey, value);
return column + " = #{map." + paramKey + "}";
case "neq":
paramMap.put(paramKey, value);
return column + " <> #{map." + paramKey + "}";
case "contains":
paramMap.put(paramKey, "%" + value + "%");
return column + " LIKE #{map." + paramKey + "}";
case "startswith":
paramMap.put(paramKey, value + "%");
return column + " LIKE #{map." + paramKey + "}";
case "endswith":
paramMap.put(paramKey, "%" + value);
return column + " LIKE #{map." + paramKey + "}";
case "gt":
paramMap.put(paramKey, value);
return column + " > #{map." + paramKey + "}";
case "gte":
paramMap.put(paramKey, value);
return column + " >= #{map." + paramKey + "}";
case "lt":
paramMap.put(paramKey, value);
return column + " < #{map." + paramKey + "}";
case "lte":
paramMap.put(paramKey, value);
return column + " <= #{map." + paramKey + "}";
default:
return "";
}
}
private String buildWvaGroupSql(String detailSql, GroupingInfo[] groupInfos) {
List<String> groupFields = new ArrayList<>();
List<String> orderItems = new ArrayList<>();
StringBuilder sql = new StringBuilder("SELECT ");
boolean first = true;
for (GroupingInfo item : groupInfos) {
if (item == null || StrUtil.isBlank(item.getSelector())) {
continue;
}
String selector = item.getSelector();
if (!isWvaGroupSupported(selector)) {
continue;
}
if (!first) {
sql.append(", ");
}
sql.append("t.").append(selector).append(" AS ").append(selector)
.append(", COUNT(*) AS count_").append(selector);
groupFields.add("t." + selector);
orderItems.add("t." + selector + (item.getDesc() ? " DESC" : " ASC"));
first = false;
}
if (groupFields.isEmpty()) {
return "SELECT * FROM (" + detailSql + ") t WHERE 1 = 0";
}
sql.append(" FROM (").append(detailSql).append(") t GROUP BY ")
.append(String.join(", ", groupFields));
if (!orderItems.isEmpty()) {
sql.append(" ORDER BY ").append(String.join(", ", orderItems));
}
return sql.toString();
}
private boolean isWvaGroupSupported(String selector) {
return "stcd".equals(selector)
|| "stnm".equals(selector)
|| "sttpCode".equals(selector)
|| "sttpName".equals(selector)
|| "baseId".equals(selector)
|| "baseName".equals(selector)
|| "rstcd".equals(selector)
|| "ennm".equals(selector)
|| "hbrvcd".equals(selector)
|| "hbrvcdName".equals(selector)
|| "bldsttCcode".equals(selector)
|| "bldsttCcodeName".equals(selector)
|| "tetp".equals(selector)
|| "stlc".equals(selector);
}
private String mapWvaColumn(String field) {
if (StrUtil.isBlank(field)) {
return null;
}
Map<String, String> columnMap = new HashMap<>();
columnMap.put("stcd", "va.STCD");
columnMap.put("stnm", "vb.STNM");
columnMap.put("tm", "va.TM");
columnMap.put("flnm", "vb.STNM || ' ' || TO_CHAR(va.TM, 'yyyy-MM-dd HH24')");
columnMap.put("imgPath", "va.FPTH");
columnMap.put("flpth", "va.FPTH");
columnMap.put("fid", "va.FID");
columnMap.put("description", "va.DESCRIPTION");
columnMap.put("sttpCode", "vb.STTP");
columnMap.put("sttpName", "sttp.STTP_NAME");
columnMap.put("baseId", "vb.BASE_ID");
columnMap.put("baseName", "hb.BASENAME");
columnMap.put("rstcd", "vb.RSTCD");
columnMap.put("ennm", "eng.ENNM");
columnMap.put("hbrvcd", "vb.HBRVCD");
columnMap.put("hbrvcdName", "hbrv.HBRVNM");
columnMap.put("bldsttCcode", "vb.BLDSTT_CODE");
columnMap.put("bldsttCcodeName",
"CASE WHEN vb.BLDSTT_CODE IN (1, 10, 11) THEN '已建' WHEN vb.BLDSTT_CODE IN (2, 7, 8) THEN '在建' ELSE '未建/规划' END");
columnMap.put("tetp", "va.TETP");
columnMap.put("tecnt", "va.TECNT");
columnMap.put("stlc", "va.STLC");
columnMap.put("fpth", "va.FPTH");
return columnMap.get(field);
}
private String buildWvaOrderBySql(List<DataSourceRequest.SortDescriptor> sorts) {
if (sorts == null || sorts.isEmpty()) {
return " ORDER BY NVL(hb.ORDER_INDEX, 999999) ASC, NVL(hbrv.ORDER_INDEX, 999999) ASC, "
+ "NVL(eng.ORDER_INDEX, 999999) ASC, NVL(vb.ORDER_INDEX, 999999) ASC, va.TM ASC, va.STCD ASC";
}
List<String> orderItems = new ArrayList<>();
for (DataSourceRequest.SortDescriptor sort : sorts) {
if (sort == null || StrUtil.isBlank(sort.getField())) {
continue;
}
String column = mapWvaColumn(sort.getField());
if (StrUtil.isBlank(column)) {
column = switch (sort.getField()) {
case "baseStepSort" -> "hb.ORDER_INDEX";
case "rvcdStepSort" -> "hbrv.ORDER_INDEX";
case "rstcdStepSort" -> "eng.ORDER_INDEX";
case "siteStepSort" -> "vb.ORDER_INDEX";
default -> null;
};
}
if (StrUtil.isBlank(column)) {
continue;
}
String direction = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC";
orderItems.add(column + " " + direction + " NULLS LAST");
}
if (orderItems.isEmpty()) {
return " ORDER BY NVL(hb.ORDER_INDEX, 999999) ASC, NVL(hbrv.ORDER_INDEX, 999999) ASC, "
+ "NVL(eng.ORDER_INDEX, 999999) ASC, NVL(vb.ORDER_INDEX, 999999) ASC, va.TM DESC, va.STCD ASC";
}
return " ORDER BY " + String.join(", ", orderItems);
}
private String buildBaseSql(boolean botanicalGarden, boolean nationwide) { private String buildBaseSql(boolean botanicalGarden, boolean nationwide) {
String baseIdExpr = botanicalGarden String baseIdExpr = botanicalGarden
? "CASE WHEN vp.BASE_ID IS NULL THEN 'null' ELSE vp.BASE_ID END" ? "CASE WHEN vp.BASE_ID IS NULL THEN 'null' ELSE vp.BASE_ID END"