From 2811ed75687510d89e55fbcdfca5139ae64db66d Mon Sep 17 00:00:00 2001 From: yinhuaiwei Date: Wed, 21 Oct 2026 15:07:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Echannel=E6=A0=91?= =?UTF-8?q?=E7=9A=84deviceSource=E7=AD=9B=E9=80=89;=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AF=B9channel=E8=A1=A8capabilities=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E7=9A=84=E6=B1=87=E8=81=9A;=E6=96=B0=E5=A2=9E=E6=B1=87?= =?UTF-8?q?=E8=81=9Aarea/eqpbook/channel=E8=A1=A8=E7=9A=84order=5Fnum?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E8=87=AA=E5=AE=9A=E4=B9=89=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/GlobalExceptionHandler.java | 2 +- .../agg/entity/AggBasedataEqpbook.java | 2 + .../agg/entity/AggBasedataEqpbookChannel.java | 4 ++ .../agg/service/AggDeviceTreeService.java | 57 +++++++++++++++++++ .../agg/service/ChannelSyncService.java | 1 + .../agg/service/EqpbookTreeService.java | 55 ++++++++++++++++-- .../inspect/agg/web/AggTreeController.java | 3 +- .../mapper/AggBasedataAreaMapper.xml | 1 - .../AggBasedataEqpbookChannelMapper.xml | 9 ++- .../mapper/AggBasedataEqpbookMapper.xml | 3 +- 10 files changed, 126 insertions(+), 11 deletions(-) diff --git a/inspect-common/inspect-common-security/src/main/java/com/inspect/common/security/handler/GlobalExceptionHandler.java b/inspect-common/inspect-common-security/src/main/java/com/inspect/common/security/handler/GlobalExceptionHandler.java index 4066f3f..eb9a16b 100644 --- a/inspect-common/inspect-common-security/src/main/java/com/inspect/common/security/handler/GlobalExceptionHandler.java +++ b/inspect-common/inspect-common-security/src/main/java/com/inspect/common/security/handler/GlobalExceptionHandler.java @@ -50,7 +50,7 @@ public class GlobalExceptionHandler { public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request) { log.error(e.getMessage(), e); Integer code = e.getCode(); - return StringUtils.isNotNull(code) ? AjaxResult.error(code, "服务器异常,请稍后再试", e.getMessage()) : AjaxResult.error("服务器异常,请稍后再试", e.getMessage()); + return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage()); } @ExceptionHandler({RuntimeException.class}) diff --git a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbook.java b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbook.java index 4aa81b6..69b4d75 100644 --- a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbook.java +++ b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbook.java @@ -17,6 +17,8 @@ public class AggBasedataEqpbook { private String stationCode; /** 源台账 id */ private Long eqpbookId; + /** 汇聚自定义显示顺序 */ + private Integer orderNum; private String patrolDeviceCode; private String patrolDeviceName; private String stationName; diff --git a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbookChannel.java b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbookChannel.java index 319cf7d..415a7fa 100644 --- a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbookChannel.java +++ b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/entity/AggBasedataEqpbookChannel.java @@ -18,6 +18,8 @@ public class AggBasedataEqpbookChannel { private String stationName; /** 源通道 id */ private Long channelId; + /** 汇聚自定义显示顺序 */ + private Integer orderNum; private String channelCode; private String channelName; /** vl/ir/ptz/ng */ @@ -34,6 +36,8 @@ public class AggBasedataEqpbookChannel { private String patrolDeviceCode; private String upSystemDeviceCode; private String deviceSource; + /** 通道能力(JSON 字符串,树接口返回时解析为对象) */ + private String capabilities; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime updateTime; private LocalDateTime syncedAt; diff --git a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/AggDeviceTreeService.java b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/AggDeviceTreeService.java index 6b390d9..001e2de 100644 --- a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/AggDeviceTreeService.java +++ b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/AggDeviceTreeService.java @@ -2,6 +2,8 @@ package com.inspect.agg.service; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -10,9 +12,12 @@ import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.inspect.agg.config.AggProperties; +import com.inspect.agg.entity.AggBasedataArea; import com.inspect.agg.entity.AggStation; +import com.inspect.agg.mapper.AggBasedataAreaMapper; import com.inspect.agg.station.StationApiClient; import lombok.RequiredArgsConstructor; @@ -30,6 +35,7 @@ public class AggDeviceTreeService { private final StationRegistry stationRegistry; private final StationApiClient stationApiClient; private final AggProperties props; + private final AggBasedataAreaMapper areaMapper; public List loadRelationTree(String stationCode, Map params) { List stations; @@ -42,6 +48,7 @@ public class AggDeviceTreeService { List result = new ArrayList<>(); int pageSize = props.getSync().getBase().getPageSize(); for (AggStation station : stations) { + Map areaOrder = areaOrderMap(station.getStationCode()); List roots = stationApiClient.fetchAllRows( station, TREE_PATH, pageSize, 20, params, "dataId"); for (JsonNode root : roots) { @@ -49,12 +56,62 @@ public class AggDeviceTreeService { normalizeNode(copy, station.getStationCode(), station.getStationName() != null ? station.getStationName() : station.getStationCode(), aggregate); + sortAreaChildren(copy, areaOrder); result.add(copy); } } return result; } + private Map areaOrderMap(String stationCode) { + Map orderMap = new HashMap<>(); + for (AggBasedataArea area : areaMapper.listForTree(stationCode)) { + if (area.getAreaId() != null) { + orderMap.put(area.getAreaId(), area.getOrderNum() == null ? Integer.MAX_VALUE : area.getOrderNum()); + } + } + return orderMap; + } + + private static void sortAreaChildren(JsonNode node, Map areaOrder) { + if (node == null || !node.isObject()) { + return; + } + JsonNode children = node.get("children"); + if (children == null || !children.isArray()) { + return; + } + List sorted = new ArrayList<>(); + for (JsonNode child : children) { + sorted.add(child); + } + sorted.sort(Comparator + .comparingInt((JsonNode child) -> isAreaNode(child) ? 0 : 1) + .thenComparingInt(child -> isAreaNode(child) ? areaOrderValue(child, areaOrder) : 0)); + ArrayNode array = (ArrayNode) children; + array.removeAll(); + for (JsonNode child : sorted) { + array.add(child); + } + for (JsonNode child : array) { + sortAreaChildren(child, areaOrder); + } + } + + private static boolean isAreaNode(JsonNode node) { + JsonNode flag = node.get("areaFlag"); + return flag != null && "Yes".equals(flag.asText()); + } + + private static int areaOrderValue(JsonNode node, Map areaOrder) { + JsonNode areaId = node.get("areaId"); + if (areaId == null || areaId.isNull()) { + return Integer.MAX_VALUE; + } + Integer order = areaOrder.get(areaId.asLong()); + return order == null ? Integer.MAX_VALUE : order; + } + private static void normalizeNode(ObjectNode node, String stationCode, String stationName, boolean prefixIds) { if (node == null || !node.isObject()) { diff --git a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/ChannelSyncService.java b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/ChannelSyncService.java index 1c536a1..14ae3c0 100644 --- a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/ChannelSyncService.java +++ b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/ChannelSyncService.java @@ -92,6 +92,7 @@ public class ChannelSyncService { c.setPatrolDeviceCode(Rows.text(r, "patroldeviceCode", "patrolDeviceCode")); c.setUpSystemDeviceCode(Rows.text(r, "upSystemDeviceCode")); c.setDeviceSource(Rows.text(r, "deviceSource")); + c.setCapabilities(Rows.jsonText(r, "capabilities")); c.setUpdateTime(Rows.date(r, "updateTime")); c.setSyncedAt(LocalDateTime.now()); c.setIsDeleted(0); diff --git a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/EqpbookTreeService.java b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/EqpbookTreeService.java index 0243f91..15f50e7 100644 --- a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/EqpbookTreeService.java +++ b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/service/EqpbookTreeService.java @@ -11,6 +11,9 @@ import java.util.Set; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.inspect.agg.entity.AggBasedataArea; import com.inspect.agg.entity.AggBasedataEqpbook; import com.inspect.agg.entity.AggBasedataEqpbookChannel; @@ -19,10 +22,12 @@ import com.inspect.agg.mapper.AggBasedataEqpbookChannelMapper; import com.inspect.agg.mapper.AggBasedataEqpbookMapper; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; /** * 使用汇聚区域、台账和通道数据构建通道树。 */ +@Slf4j @Service @RequiredArgsConstructor public class EqpbookTreeService { @@ -30,11 +35,13 @@ public class EqpbookTreeService { private final AggBasedataAreaMapper areaMapper; private final AggBasedataEqpbookMapper eqpbookMapper; private final AggBasedataEqpbookChannelMapper channelMapper; + private final ObjectMapper objectMapper; public List> buildFilterTree(String stationCode, String patrolDeviceName, String onlineStatus, - String patrolDeviceTypeFlag) { + String patrolDeviceTypeFlag, + String deviceSource) { List areas = areaMapper.listForTree(stationCode); List eqpbooks = eqpbookMapper.list(stationCode, 0); List channels = channelMapper.list(stationCode, 0); @@ -46,6 +53,9 @@ public class EqpbookTreeService { Map> channelIndex = new HashMap<>(); for (AggBasedataEqpbookChannel channel : channels) { + if (!matchesDeviceSource(channel, deviceSource)) { + continue; + } channelIndex.computeIfAbsent(eqpbookKey(channel.getStationCode(), channel.getEqpbookId()), key -> new ArrayList<>()).add(channel); } @@ -81,9 +91,9 @@ public class EqpbookTreeService { } Map> areaNodes = new LinkedHashMap<>(); - for (String key : selectedAreaKeys) { - AggBasedataArea area = areaIndex.get(key); - if (area == null) continue; + for (AggBasedataArea area : areas) { + String key = areaKey(area.getStationCode(), area.getAreaId()); + if (!selectedAreaKeys.contains(key)) continue; Map node = new LinkedHashMap<>(); node.put("id", key); String parentKey = area.getParentId() == null ? null : areaKey(area.getStationCode(), area.getParentId()); @@ -147,6 +157,8 @@ public class EqpbookTreeService { channelNode.put("channelName", channel.getChannelName()); channelNode.put("channelFlag", "Yes"); channelNode.put("channelType", channel.getChannelType()); + channelNode.put("deviceSource", channel.getDeviceSource()); + channelNode.put("capabilities", parseCapabilities(channel.getCapabilities())); channelNode.put("host", channel.getHost()); channelNode.put("port", channel.getPort()); channelNode.put("stationCode", channel.getStationCode()); @@ -171,6 +183,28 @@ public class EqpbookTreeService { return roots; } + private Map parseCapabilities(String value) { + if (!StringUtils.hasText(value)) { + return null; + } + try { + JsonNode node = objectMapper.readTree(value); + if (node == null || !node.isObject()) { + log.warn("通道 capabilities 不是 JSON 对象,已忽略: {}", abbrev(value)); + return null; + } + return objectMapper.convertValue(node, new TypeReference>() { + }); + } catch (Exception e) { + log.warn("通道 capabilities 解析失败,已忽略: {}", abbrev(value)); + return null; + } + } + + private static String abbrev(String value) { + return value.length() <= 120 ? value : value.substring(0, 120); + } + @SuppressWarnings("unchecked") private static List> children(Map node) { return (List>) node.get("children"); @@ -196,6 +230,19 @@ public class EqpbookTreeService { && eqpbook.getPatrolDeviceName().contains(value)); } + private static boolean matchesDeviceSource(AggBasedataEqpbookChannel channel, String deviceSource) { + if (!StringUtils.hasText(deviceSource)) { + return true; + } + String expected = deviceSource.trim(); + String value = channel.getDeviceSource(); + String actual = value == null ? "" : value.trim(); + if ("其他".equals(expected)) { + return actual.isEmpty() || "其他".equals(actual); + } + return expected.equals(actual); + } + private static boolean matchesType(AggBasedataEqpbook eqpbook, String flag) { if (!StringUtils.hasText(flag)) return true; String type = eqpbook.getDeviceType(); diff --git a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/web/AggTreeController.java b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/web/AggTreeController.java index fa1987a..02498a1 100644 --- a/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/web/AggTreeController.java +++ b/inspect-main/inspect-main-agg/src/main/java/com/inspect/agg/web/AggTreeController.java @@ -34,9 +34,10 @@ public class AggTreeController { @RequestParam(value = "patroldeviceName", required = false) String patrolDeviceName, @RequestParam(value = "onlineStatus", required = false) String onlineStatus, @RequestParam(value = "patroldeviceTypeFlag", required = false) String patrolDeviceTypeFlag, + @RequestParam(value = "deviceSource", required = false) String deviceSource, @RequestParam(required = false) String stationCode) { List> tree = eqpbookTreeService.buildFilterTree( - stationCode, patrolDeviceName, onlineStatus, patrolDeviceTypeFlag); + stationCode, patrolDeviceName, onlineStatus, patrolDeviceTypeFlag, deviceSource); return AjaxResult.success(tree); } diff --git a/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataAreaMapper.xml b/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataAreaMapper.xml index 34ce574..4512616 100644 --- a/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataAreaMapper.xml +++ b/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataAreaMapper.xml @@ -34,7 +34,6 @@ area_addr = VALUES(area_addr), area_type = VALUES(area_type), device_type_code = VALUES(device_type_code), - order_num = VALUES(order_num), status = VALUES(status), remark = VALUES(remark), update_time = VALUES(update_time), diff --git a/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookChannelMapper.xml b/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookChannelMapper.xml index 6636f66..730771a 100644 --- a/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookChannelMapper.xml +++ b/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookChannelMapper.xml @@ -6,6 +6,7 @@ + @@ -19,6 +20,7 @@ + @@ -27,8 +29,8 @@ - INSERT INTO agg_basedata_eqpbook_channel (station_code, channel_id, channel_code, channel_name, channel_type, online_state, channel_content, host, port, area_id, area_name, eqpbook_id, patrol_device_code, up_system_device_code, device_source, update_time, synced_at, is_deleted) - VALUES (#{stationCode}, #{channelId}, #{channelCode}, #{channelName}, #{channelType}, #{onlineState}, #{channelContent}, #{host}, #{port}, #{areaId}, #{areaName}, #{eqpbookId}, #{patrolDeviceCode}, #{upSystemDeviceCode}, #{deviceSource}, #{updateTime}, #{syncedAt}, #{isDeleted}) + INSERT INTO agg_basedata_eqpbook_channel (station_code, channel_id, channel_code, channel_name, channel_type, online_state, channel_content, host, port, area_id, area_name, eqpbook_id, patrol_device_code, up_system_device_code, device_source, capabilities, update_time, synced_at, is_deleted) + VALUES (#{stationCode}, #{channelId}, #{channelCode}, #{channelName}, #{channelType}, #{onlineState}, #{channelContent}, #{host}, #{port}, #{areaId}, #{areaName}, #{eqpbookId}, #{patrolDeviceCode}, #{upSystemDeviceCode}, #{deviceSource}, #{capabilities}, #{updateTime}, #{syncedAt}, #{isDeleted}) ON DUPLICATE KEY UPDATE channel_code = VALUES(channel_code), channel_name = VALUES(channel_name), @@ -43,6 +45,7 @@ patrol_device_code = VALUES(patrol_device_code), up_system_device_code = VALUES(up_system_device_code), device_source = VALUES(device_source), + capabilities = VALUES(capabilities), update_time = VALUES(update_time), synced_at = VALUES(synced_at), is_deleted = VALUES(is_deleted), @@ -66,7 +69,7 @@ LEFT JOIN agg_station s ON s.station_code = c.station_code WHERE c.is_deleted = 0 AND c.station_code = #{stationCode} - ORDER BY c.eqpbook_id, c.channel_id + ORDER BY c.eqpbook_id, c.order_num, c.channel_id LIMIT #{limit} diff --git a/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookMapper.xml b/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookMapper.xml index 9c572b9..51652ba 100644 --- a/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookMapper.xml +++ b/inspect-main/inspect-main-agg/src/main/resources/mapper/AggBasedataEqpbookMapper.xml @@ -5,6 +5,7 @@ + @@ -69,7 +70,7 @@ LEFT JOIN agg_station s ON s.station_code = e.station_code WHERE e.is_deleted = 0 AND e.station_code = #{stationCode} - ORDER BY e.area_id, e.eqpbook_id + ORDER BY e.area_id, e.order_num, e.eqpbook_id LIMIT #{limit}