feat: 视频站树级结构查询

This commit is contained in:
tangwei 2026-06-22 17:12:03 +08:00
parent b0ef0ada66
commit 9409efa0c3
5 changed files with 446 additions and 2 deletions

View File

@ -47,6 +47,12 @@ public class VdMonitorController {
return ResponseResult.successData(vdMonitorService.getKendoListCust(dataSourceRequest));
}
@PostMapping("/tree/GetKendoListCust")
@Operation(summary = "视频站树级结构查询")
public ResponseResult getVdTreeKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(vdMonitorService.getVdTreeKendoListCust(dataSourceRequest));
}
@PostMapping("/vdpoint/GetKendoListCust")
@Operation(summary = "视频站锚点接口")
public ResponseResult getVdPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {

View File

@ -0,0 +1,71 @@
package com.yfd.platform.qgc_env.vd.entity.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@Data
@Schema(description = "视频站树节点")
public class VdTreeNodeVo implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "节点ID")
private String id;
@Schema(description = "节点名称")
private String name;
@Schema(description = "节点类型")
private String type;
@Schema(description = "节点类型名称")
private String typeName;
@Schema(description = "排序值")
private Integer sort;
@Schema(description = "父节点ID")
private String parentId;
@Schema(description = "父节点名称")
private String parentName;
@Schema(description = "是否有子节点")
private Integer hasChildren;
@Schema(description = "播放地址")
private String url;
@Schema(description = "播放方式")
private String playWay;
@Schema(description = "设备序列号")
private String deviceSerial;
@Schema(description = "接入方式")
private String accessWay;
@Schema(description = "流协议")
private String protocol;
@Schema(description = "清晰度")
private String quality;
@Schema(description = "控制方式")
private String controlMode;
@Schema(description = "设备状态")
private Integer status;
@Schema(description = "状态时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date statusTm;
@Schema(description = "子节点")
private List<VdTreeNodeVo> children;
}

View File

@ -0,0 +1,39 @@
package com.yfd.platform.qgc_env.vd.entity.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class VdTreeRowVo implements Serializable {
private static final long serialVersionUID = 1L;
private String stcd;
private String stCode;
private String stName;
private String stnm;
private String sttpCode;
private String sttpName;
private String sttpFullPath;
private String rstcd;
private String ennm;
private String baseId;
private String baseName;
private String url;
private String playWay;
private Integer baseSort;
private Integer rstcdStepSort;
private Integer siteStepSort;
private String deviceSerial;
private String accessWay;
private String protocol;
private String quality;
private String controlMode;
private Integer status;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date statusTm;
}

View File

@ -2,6 +2,7 @@ package com.yfd.platform.qgc_env.vd.service;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeNodeVo;
import com.yfd.platform.qgc_env.vd.entity.vo.VdRunDataVo;
import com.yfd.platform.qgc_env.vd.entity.vo.VdVmsstbprptVo;
@ -13,6 +14,8 @@ public interface VdMonitorService {
DataSourceResult<VdRunDataVo> getKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<VdTreeNodeVo> getVdTreeKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<?> getVdPointKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<VdRunDataVo> getRunDataKendoListCust(DataSourceRequest dataSourceRequest);

View File

@ -11,6 +11,8 @@ import com.yfd.platform.common.GroupingInfo;
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
import com.yfd.platform.qgc_env.vd.entity.vo.VdPointVo;
import com.yfd.platform.qgc_env.vd.entity.vo.VdRunDataVo;
import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeNodeVo;
import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeRowVo;
import com.yfd.platform.qgc_env.vd.entity.vo.VdVmsstbprptVo;
import com.yfd.platform.qgc_env.vd.service.VdMonitorService;
import com.yfd.platform.utils.QgcQueryWrapperUtil;
@ -19,6 +21,7 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@ -119,6 +122,55 @@ public class VdMonitorServiceImpl implements VdMonitorService {
return queryLatestRunDataGroupList(dataSourceRequest, loadOptions);
}
@Override
public DataSourceResult<VdTreeNodeVo> getVdTreeKendoListCust(DataSourceRequest dataSourceRequest) {
Map<String, Object> paramMap = new HashMap<>();
String filterSql = buildVdTreeFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0});
StringBuilder sql = new StringBuilder();
sql.append("SELECT ")
.append("t.stcd AS stcd, ")
.append("t.stCode AS stCode, ")
.append("t.stName AS stName, ")
.append("t.stnm AS stnm, ")
.append("t.sttpCode AS sttpCode, ")
.append("t.sttpName AS sttpName, ")
.append("t.sttpFullPath AS sttpFullPath, ")
.append("t.rstcd AS rstcd, ")
.append("t.ennm AS ennm, ")
.append("t.baseId AS baseId, ")
.append("t.baseName AS baseName, ")
.append("t.url AS url, ")
.append("t.playWay AS playWay, ")
.append("t.baseSort AS baseSort, ")
.append("t.rstcdStepSort AS rstcdStepSort, ")
.append("t.siteStepSort AS siteStepSort, ")
.append("t.deviceSerial AS deviceSerial, ")
.append("t.accessWay AS accessWay, ")
.append("t.protocol AS protocol, ")
.append("t.quality AS quality, ")
.append("t.controlMode AS controlMode, ")
.append("t.status AS status, ")
.append("t.statusTm AS statusTm ")
.append("FROM (")
.append(buildVdTreeCoreSql())
.append(") t WHERE 1 = 1 ");
if (StrUtil.isNotBlank(filterSql)) {
sql.append(" AND ").append(filterSql).append(" ");
}
sql.append(" ORDER BY t.baseSort ASC NULLS LAST, t.rstcdStepSort ASC NULLS LAST, t.siteStepSort ASC NULLS LAST, t.stcd ASC");
List<VdTreeRowVo> rows = microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, VdTreeRowVo.class);
boolean baseScoped = containsNonBlankFilterValue(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), "baseId");
DataSourceResult<VdTreeNodeVo> result = new DataSourceResult<>();
List<VdTreeNodeVo> treeData = buildVdTreeNodes(rows, baseScoped);
result.setData(treeData);
result.setTotal((long) treeData.size());
result.setAggregates(new HashMap<>());
return result;
}
@Override
public DataSourceResult<?> getVdPointKendoListCust(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
@ -491,12 +543,57 @@ public class VdMonitorServiceImpl implements VdMonitorService {
" AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 ";
}
private String buildVdTreeCoreSql() {
return "SELECT " +
"base.STCD AS stcd, " +
"base.STNM AS stnm, " +
"base.CSTCD AS stCode, " +
"cst.STNM AS stName, " +
"base.STTP AS sttpCode, " +
"sttp.STTP_NAME AS sttpName, " +
"sttp.FULL_PATH AS sttpFullPath, " +
"base.RSTCD AS rstcd, " +
"eng.ENNM AS ennm, " +
"NVL(eng.BASE_ID, base.BASE_ID) AS baseId, " +
"hb.BASENAME AS baseName, " +
"base.URL AS url, " +
"CASE WHEN base.URL IS NULL THEN NULL WHEN INSTR(base.URL, 'm3u8') > 0 THEN '1' ELSE '0' END AS playWay, " +
"NVL(hb.ORDER_INDEX, 999999) AS baseSort, " +
"NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " +
"NVL(base.ORDER_INDEX, 999999) AS siteStepSort, " +
"base.DEVICE_SERIAL AS deviceSerial, " +
"base.ACCESS_WAY AS accessWay, " +
"base.PROTOCOL AS protocol, " +
"base.QUALITY AS quality, " +
"base.CONTROL_MODE AS controlMode, " +
"status.STATUS AS status, " +
"status.TM AS statusTm " +
"FROM (" + buildVdDeviceBaseSql() + ") base " +
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = base.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " +
"LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(eng.BASE_ID, base.BASE_ID) " +
" AND NVL(hb.IS_DELETED, 0) = 0 AND NVL(hb.ENABLED, 1) = 1 " +
"LEFT JOIN (" + buildStationBaseSql() + ") cst ON cst.STCD = base.CSTCD " +
"LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = base.STTP " +
" AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " +
"LEFT JOIN ( " +
"SELECT detail.STCD, detail.TM, detail.STATUS " +
"FROM MS_SBGZSTAT_B detail " +
"INNER JOIN ( " +
"SELECT STCD, MAX(TM) AS MAX_TM FROM MS_SBGZSTAT_B " +
"WHERE NVL(IS_DELETED, 0) = 0 GROUP BY STCD " +
") latest ON detail.STCD = latest.STCD AND detail.TM = latest.MAX_TM " +
"WHERE NVL(detail.IS_DELETED, 0) = 0 " +
") status ON status.STCD = base.STCD " +
"WHERE base.STTP LIKE 'VD_%' ";
}
private String buildVdDeviceBaseSql() {
return "SELECT vd.STCD, vd.STNM, vd.MNTP, vd.STTP, vd.LGTD, vd.LTTD, vd.ELEV, vd.STLC, " +
" vd.JCDT, vd.WDDT, vd.BLDSTT_CODE, vd.USFL, vd.DTIN, vd.STINDX, vd.RSTCD, vd.BASE_ID, " +
" vd.HBRVCD, vd.RVCD, vd.ADDVCD, vd.CSTCD, vd.FHSTCD, CAST(NULL AS VARCHAR2(3000)) AS INTRODUCE, " +
" CAST(NULL AS VARCHAR2(255)) AS LOGO, CAST(NULL AS VARCHAR2(1000)) AS INFFILE, " +
" vd.DTFRQCY, vd.REMARK, vd.VLSR, vd.VLSR_TM, vd.URL AS URL, CAST(NULL AS NUMBER(8,0)) AS ORDER_INDEX, " +
" vd.DTFRQCY, vd.REMARK, vd.VLSR, vd.VLSR_TM, vd.URL AS URL, vd.DEVICE_SERIAL, vd.ACCESS_WAY, " +
" vd.PROTOCOL, vd.QUALITY, vd.CONTROL_MODE, CAST(NULL AS NUMBER(8,0)) AS ORDER_INDEX, " +
" 'SD_VDINFO_B' AS SOURCE_TABLE " +
"FROM SD_VDINFO_B vd WHERE 1=1 " +
// " AND vd.STTP = 'VD_FP' "+
@ -504,7 +601,9 @@ public class VdMonitorServiceImpl implements VdMonitorService {
"SELECT sonar.STCD, sonar.STNM, sonar.MNTP, sonar.STTP, sonar.LGTD, sonar.LTTD, sonar.ELEV, sonar.STLC, " +
" sonar.JCDT, sonar.WDDT, sonar.BLDSTT_CODE, sonar.USFL, sonar.DTIN, sonar.STINDX, sonar.RSTCD, sonar.BASE_ID, " +
" sonar.HBRVCD, sonar.RVCD, sonar.ADDVCD, CAST(NULL AS VARCHAR2(36)) AS CSTCD, CAST(NULL AS VARCHAR2(36)) AS FHSTCD, " +
" sonar.INTRODUCE, sonar.LOGO, sonar.INFFILE, sonar.DTFRQCY, sonar.REMARK, sonar.VLSR, sonar.VLSR_TM, CAST(NULL AS VARCHAR2(512)) AS URL, sonar.ORDER_INDEX, " +
" sonar.INTRODUCE, sonar.LOGO, sonar.INFFILE, sonar.DTFRQCY, sonar.REMARK, sonar.VLSR, sonar.VLSR_TM, CAST(NULL AS VARCHAR2(512)) AS URL, " +
" CAST(NULL AS VARCHAR2(255)) AS DEVICE_SERIAL, CAST(NULL AS VARCHAR2(10)) AS ACCESS_WAY, " +
" CAST(NULL AS VARCHAR2(50)) AS PROTOCOL, CAST(NULL AS VARCHAR2(50)) AS QUALITY, CAST(NULL AS VARCHAR2(2048)) AS CONTROL_MODE, sonar.ORDER_INDEX, " +
" 'SD_SONAR_B_H' AS SOURCE_TABLE " +
"FROM SD_SONAR_B_H sonar WHERE NVL(sonar.IS_DELETED, 0) = 0 AND sonar.STTP IN ('VD_WVD', 'VD_SN') ";
}
@ -809,6 +908,42 @@ public class VdMonitorServiceImpl implements VdMonitorService {
};
}
private String buildVdTreeFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
if (filter == null) {
return "";
}
if (StrUtil.isNotBlank(filter.getField())) {
return buildVdTreeLeafCondition(filter, paramMap, indexHolder);
}
if (CollUtil.isEmpty(filter.getFilters())) {
return "";
}
List<String> conditions = new ArrayList<>();
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
String childSql = buildVdTreeFilterCondition(child, paramMap, indexHolder);
if (StrUtil.isNotBlank(childSql)) {
conditions.add("(" + childSql + ")");
}
}
if (conditions.isEmpty()) {
return "";
}
String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND ";
return String.join(logic, conditions);
}
private String buildVdTreeLeafCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
String column = mapVdTreeColumn(filter.getField());
if (StrUtil.isBlank(column)) {
return "";
}
return buildSimpleCondition(column, "vdTreeParam", filter, paramMap, indexHolder, isVdTreeDateField(filter));
}
private String buildFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
@ -972,6 +1107,16 @@ public class VdMonitorServiceImpl implements VdMonitorService {
return "date".equalsIgnoreCase(filter.getDataType());
}
private boolean isVdTreeDateField(DataSourceRequest.FilterDescriptor filter) {
if (filter == null || StrUtil.isBlank(filter.getField())) {
return false;
}
if ("statusTm".equalsIgnoreCase(filter.getField())) {
return true;
}
return "date".equalsIgnoreCase(filter.getDataType());
}
private String buildValueExpr(String paramKey, boolean dateField, Object value) {
if (!dateField || value == null) {
return "#{map." + paramKey + "}";
@ -1007,6 +1152,35 @@ public class VdMonitorServiceImpl implements VdMonitorService {
return values;
}
private String mapVdTreeColumn(String field) {
if (StrUtil.isBlank(field)) {
return null;
}
return switch (field) {
case "stcd" -> "t.stcd";
case "stCode" -> "t.stCode";
case "stName" -> "t.stName";
case "stnm" -> "t.stnm";
case "sttpCode" -> "t.sttpCode";
case "sttpName" -> "t.sttpName";
case "sttpFullPath" -> "t.sttpFullPath";
case "rstcd" -> "t.rstcd";
case "ennm" -> "t.ennm";
case "baseId" -> "t.baseId";
case "baseName" -> "t.baseName";
case "url" -> "t.url";
case "playWay" -> "t.playWay";
case "deviceSerial" -> "t.deviceSerial";
case "accessWay" -> "t.accessWay";
case "protocol" -> "t.protocol";
case "quality" -> "t.quality";
case "controlMode" -> "t.controlMode";
case "status" -> "NVL(t.status, 0)";
case "statusTm" -> "t.statusTm";
default -> null;
};
}
private String mapColumn(String field) {
if (StrUtil.isBlank(field)) {
return null;
@ -1144,4 +1318,155 @@ public class VdMonitorServiceImpl implements VdMonitorService {
}
return " ORDER BY " + String.join(", ", orderItems);
}
private boolean containsNonBlankFilterValue(DataSourceRequest.FilterDescriptor filter, String fieldName) {
if (filter == null || StrUtil.isBlank(fieldName)) {
return false;
}
if (fieldName.equalsIgnoreCase(filter.getField())) {
if (filter.getValue() instanceof List<?> list) {
return CollUtil.isNotEmpty(list);
}
return StrUtil.isNotBlank(filter.getValue() == null ? null : String.valueOf(filter.getValue()));
}
if (CollUtil.isEmpty(filter.getFilters())) {
return false;
}
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
if (containsNonBlankFilterValue(child, fieldName)) {
return true;
}
}
return false;
}
private List<VdTreeNodeVo> buildVdTreeNodes(List<VdTreeRowVo> rows, boolean baseScoped) {
List<VdTreeNodeVo> stationNodes = buildStationTreeNodes(rows, baseScoped);
if (baseScoped) {
return sortTreeNodes(stationNodes);
}
LinkedHashMap<String, VdTreeNodeVo> baseNodeMap = new LinkedHashMap<>();
List<VdTreeNodeVo> topLevelWithoutBase = new ArrayList<>();
for (VdTreeRowVo row : rows) {
if (row == null) {
continue;
}
if (StrUtil.isBlank(row.getBaseId())) {
continue;
}
baseNodeMap.computeIfAbsent(row.getBaseId(), key -> {
VdTreeNodeVo node = new VdTreeNodeVo();
node.setId(key);
node.setName(StrUtil.blankToDefault(row.getBaseName(), key));
node.setType("PSB");
node.setTypeName("基地");
node.setSort(defaultSort(row.getBaseSort()));
node.setHasChildren(1);
node.setParentId(null);
node.setParentName(null);
return node;
});
}
Map<String, List<VdTreeNodeVo>> stationByBase = new LinkedHashMap<>();
for (VdTreeNodeVo stationNode : stationNodes) {
if (StrUtil.isBlank(stationNode.getParentId())) {
topLevelWithoutBase.add(stationNode);
continue;
}
stationByBase.computeIfAbsent(stationNode.getParentId(), key -> new ArrayList<>()).add(stationNode);
}
List<VdTreeNodeVo> result = new ArrayList<>();
for (Map.Entry<String, VdTreeNodeVo> entry : baseNodeMap.entrySet()) {
VdTreeNodeVo baseNode = entry.getValue();
baseNode.setChildren(sortTreeNodes(stationByBase.get(entry.getKey())));
result.add(baseNode);
}
result.addAll(topLevelWithoutBase);
return sortTreeNodes(result);
}
private List<VdTreeNodeVo> buildStationTreeNodes(List<VdTreeRowVo> rows, boolean baseScoped) {
LinkedHashMap<String, List<VdTreeRowVo>> stationRowMap = new LinkedHashMap<>();
for (VdTreeRowVo row : rows) {
if (row == null || StrUtil.isBlank(row.getRstcd())) {
continue;
}
stationRowMap.computeIfAbsent(row.getRstcd(), key -> new ArrayList<>()).add(row);
}
List<VdTreeNodeVo> stationNodes = new ArrayList<>();
for (Map.Entry<String, List<VdTreeRowVo>> entry : stationRowMap.entrySet()) {
List<VdTreeRowVo> stationRows = entry.getValue();
if (CollUtil.isEmpty(stationRows)) {
continue;
}
VdTreeRowVo sample = stationRows.get(0);
VdTreeNodeVo stationNode = new VdTreeNodeVo();
stationNode.setId(entry.getKey());
stationNode.setName(StrUtil.blankToDefault(sample.getEnnm(), entry.getKey()));
stationNode.setType("ENG");
stationNode.setTypeName("电站");
stationNode.setSort(defaultSort(sample.getRstcdStepSort()));
stationNode.setHasChildren(1);
if (baseScoped) {
stationNode.setParentId(null);
stationNode.setParentName(null);
} else {
stationNode.setParentId(sample.getBaseId());
stationNode.setParentName(sample.getBaseName());
}
stationNode.setChildren(buildSiteTreeNodes(stationRows));
stationNodes.add(stationNode);
}
return sortTreeNodes(stationNodes);
}
private List<VdTreeNodeVo> buildSiteTreeNodes(List<VdTreeRowVo> rows) {
LinkedHashMap<String, VdTreeNodeVo> siteNodeMap = new LinkedHashMap<>();
for (VdTreeRowVo row : rows) {
if (row == null || StrUtil.isBlank(row.getStcd()) || siteNodeMap.containsKey(row.getStcd())) {
continue;
}
VdTreeNodeVo node = new VdTreeNodeVo();
node.setId(row.getStcd());
node.setName(StrUtil.blankToDefault(row.getStnm(), row.getStcd()));
node.setType(row.getSttpCode());
node.setTypeName(row.getSttpName());
node.setSort(defaultSort(row.getSiteStepSort()));
node.setHasChildren(0);
node.setParentId(row.getRstcd());
node.setParentName(row.getEnnm());
node.setUrl(row.getUrl());
node.setPlayWay(row.getPlayWay());
node.setDeviceSerial(row.getDeviceSerial());
node.setAccessWay(row.getAccessWay());
node.setProtocol(row.getProtocol());
node.setQuality(row.getQuality());
node.setControlMode(row.getControlMode());
node.setStatus(row.getStatus());
node.setStatusTm(row.getStatusTm());
siteNodeMap.put(row.getStcd(), node);
}
return sortTreeNodes(new ArrayList<>(siteNodeMap.values()));
}
private List<VdTreeNodeVo> sortTreeNodes(List<VdTreeNodeVo> nodes) {
if (CollUtil.isEmpty(nodes)) {
return new ArrayList<>();
}
nodes.sort(Comparator.comparing(VdMonitorServiceImpl::sortValue)
.thenComparing(node -> StrUtil.blankToDefault(node.getId(), "")));
return nodes;
}
private static Integer sortValue(VdTreeNodeVo node) {
return node == null ? 999999 : defaultSort(node.getSort());
}
private static Integer defaultSort(Integer sort) {
return sort == null ? 999999 : sort;
}
}