From 1e2d207aea24b5956d5ece95ed4a9db0f59f34d7 Mon Sep 17 00:00:00 2001 From: 648540858 <456panlinlin> Date: 星期五, 22 四月 2022 16:21:05 +0800 Subject: [PATCH] 添加优化后的地图页面,完全一处百度地图相关的api --- web_src/src/components/service/DeviceService.js | 15 web_src/src/components/common/DeviceTree.vue | 11 web_src/static/images/gis/camera3-offline.png | 0 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java | 8 src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java | 4 web_src/package-lock.json | 36 + web_src/index.html | 2 web_src/static/images/gis/camera1.png | 0 web_src/src/components/devicePosition.vue | 575 +++++++++++++++----------- src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java | 10 web_src/src/components/common/MapComponent.vue | 170 +++++++ src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java | 2 web_src/static/images/gis/camera1-offline.png | 0 web_src/static/images/gis/camera2-offline.png | 0 web_src/src/components/DeviceList.vue | 2 web_src/src/components/live.vue | 98 +--- web_src/package.json | 1 web_src/static/images/gis/camera.png | 0 web_src/static/images/gis/camera3.png | 0 /dev/null | 74 --- src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java | 9 web_src/static/images/gis/camera-offline.png | 0 web_src/src/components/dialog/channelMapInfobox.vue | 65 +++ web_src/src/router/index.js | 5 web_src/src/components/dialog/queryTrace.vue | 100 ++++ web_src/src/layout/UiHeader.vue | 2 web_src/static/images/arrow.png | 0 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java | 18 src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java | 18 web_src/static/images/gis/camera2.png | 0 30 files changed, 745 insertions(+), 480 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java index 1e6ef77..95576f3 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java @@ -4,7 +4,7 @@ /** - * 鏁版嵁搴撹嚜璧營D + * 鏁版嵁搴撹嚜澧濱D */ private int id; diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java index d57f812..d3a9ae9 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java @@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; -import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; import com.github.pagehelper.PageInfo; @@ -94,12 +93,6 @@ public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit); - /** - * 鑾峰彇鏌愪釜璁惧鐨勯�氶亾鏍� - * @param deviceId 璁惧ID - * @return - */ - List<DeviceChannelTree> tree(String deviceId); /** * 鑾峰彇鏌愪釜璁惧鐨勯�氶亾鍒楄〃 @@ -285,7 +278,7 @@ * @param startTime * @param endTime */ - public List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime); + public List<MobilePosition> queryMobilePositions(String deviceId, String channelId, String startTime, String endTime); /** * 鏌ヨ鏈�鏂扮Щ鍔ㄤ綅缃� diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java index c1ff7a6..312d3e0 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java @@ -2,7 +2,6 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform; -import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; import org.apache.ibatis.annotations.*; import org.springframework.stereotype.Repository; @@ -235,23 +234,6 @@ @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1") List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId); - - @Select(" SELECT\n" + - " id,\n" + - " channelId,\n" + - " deviceId,\n" + - " parentId,\n" + - " status,\n" + - " name as title,\n" + - " channelId as \"value\",\n" + - " channelId as \"key\",\n" + - " longitude,\n" + - " latitude,\n" + - " PTZType,\n" + - " subCount\n" + - " from device_channel\n" + - " where deviceId = #{deviceId}") - List<DeviceChannelTree> tree(String deviceId); @Delete(value = {" <script>" + "DELETE " + diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java index f3e4261..51da4a8 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java @@ -16,12 +16,12 @@ @Select(value = {" <script>" + "SELECT * FROM device_mobile_position" + - " WHERE deviceId = #{deviceId} " + + " WHERE deviceId = #{deviceId} and channelId = #{channelId} " + "<if test=\"startTime != null\"> AND time>=#{startTime}</if>" + "<if test=\"endTime != null\"> AND time<=#{endTime}</if>" + " ORDER BY time ASC" + " </script>"}) - List<MobilePosition> queryPositionByDeviceIdAndTime(String deviceId, String startTime, String endTime); + List<MobilePosition> queryPositionByDeviceIdAndTime(String deviceId, String channelId, String startTime, String endTime); @Select("SELECT * FROM device_mobile_position WHERE deviceId = #{deviceId}" + " ORDER BY time DESC LIMIT 1") diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java index 5d0031f..661a69b 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java @@ -13,8 +13,6 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.dao.*; import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; -import com.genersoft.iot.vmp.utils.node.ForestNodeMerger; -import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; @@ -354,10 +352,6 @@ return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, null, query, hasSubChannel, online, start, limit); } - @Override - public List<DeviceChannelTree> tree(String deviceId) { - return ForestNodeMerger.merge(deviceChannelMapper.tree(deviceId)); - } @Override public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) { @@ -504,8 +498,8 @@ * @param endTime */ @Override - public synchronized List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime) { - return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, startTime, endTime); + public synchronized List<MobilePosition> queryMobilePositions(String deviceId, String channelId, String startTime, String endTime) { + return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, channelId, startTime, endTime); } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java deleted file mode 100644 index 89e35a5..0000000 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.genersoft.iot.vmp.utils.node; - -import com.fasterxml.jackson.annotation.JsonInclude; - -import java.util.ArrayList; -import java.util.List; - -/** - * 鑺傜偣鍩虹被 - * - */ -public class BaseNode<T> implements INode<T> { - - private static final long serialVersionUID = 1L; - - /** - * 涓婚敭ID - */ - protected String channelId; - - /** - * 鐖惰妭鐐笽D - */ - protected String parentId; - - /** - * 瀛愬瓩鑺傜偣 - */ - @JsonInclude(JsonInclude.Include.NON_EMPTY) - protected List<T> children = new ArrayList<T>(); - - /** - * 鏄惁鏈夊瓙瀛欒妭鐐� - */ - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Boolean hasChildren; - - /** - * 鏄惁鏈夊瓙瀛欒妭鐐� - * - * @return Boolean - */ - @Override - public Boolean getHasChildren() { - if (children.size() > 0) { - return true; - } else { - return this.hasChildren; - } - } - - @Override - public String getChannelId() { - return channelId; - } - - @Override - public String getParentId() { - return parentId; - } - - @Override - public List<T> getChildren() { - return children; - } - - public void setChildren(List<T> children) { - this.children = children; - } - - public void setHasChildren(Boolean hasChildren) { - this.hasChildren = hasChildren; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java deleted file mode 100644 index d983c56..0000000 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.genersoft.iot.vmp.utils.node; - - - -/** - * 妫灄鑺傜偣绫� - * - */ -public class ForestNode extends BaseNode<ForestNode> { - - private static final long serialVersionUID = 1L; - - /** - * 鑺傜偣鍐呭 - */ - private Object content; - - public ForestNode(String id, String parentId, Object content) { - this.channelId = id; - this.parentId = parentId; - this.content = content; - } - - public Object getContent() { - return content; - } - - public void setContent(Object content) { - this.content = content; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java deleted file mode 100644 index affce9d..0000000 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.genersoft.iot.vmp.utils.node; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * 妫灄绠$悊绫� - * - * @author smallchill - */ -public class ForestNodeManager<T extends INode<T>> { - - /** - * 妫灄鐨勬墍鏈夎妭鐐� - */ - private final ImmutableMap<String, T> nodeMap; - - /** - * 妫灄鐨勭埗鑺傜偣ID - */ - private final Map<String, Object> parentIdMap = Maps.newHashMap(); - - public ForestNodeManager(List<T> nodes) { - nodeMap = Maps.uniqueIndex(nodes, INode::getChannelId); - } - - /** - * 鏍规嵁鑺傜偣ID鑾峰彇涓�涓妭鐐� - * - * @param id 鑺傜偣ID - * @return 瀵瑰簲鐨勮妭鐐瑰璞� - */ - public INode<T> getTreeNodeAt(String id) { - if (nodeMap.containsKey(id)) { - return nodeMap.get(id); - } - return null; - } - - /** - * 澧炲姞鐖惰妭鐐笽D - * - * @param parentId 鐖惰妭鐐笽D - */ - public void addParentId(String parentId) { - parentIdMap.put(parentId, ""); - } - - /** - * 鑾峰彇鏍戠殑鏍硅妭鐐�(涓�涓.鏋楀搴斿棰楁爲) - * - * @return 鏍戠殑鏍硅妭鐐归泦鍚� - */ - public List<T> getRoot() { - List<T> roots = new ArrayList<>(); - nodeMap.forEach((key, node) -> { - if (node.getParentId() == null || parentIdMap.containsKey(node.getChannelId())) { - roots.add(node); - } - }); - return roots; - } - -} diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeMerger.java b/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeMerger.java deleted file mode 100644 index 8df6f50..0000000 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeMerger.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.genersoft.iot.vmp.utils.node; - -import com.genersoft.iot.vmp.utils.CollectionUtil; - -import java.util.List; - -/** - * 妫灄鑺傜偣褰掑苟绫� - * - */ -public class ForestNodeMerger { - - /** - * 灏嗚妭鐐规暟缁勫綊骞朵负涓�涓.鏋楋紙澶氭5鏍戯級锛堝~鍏呰妭鐐圭殑children鍩燂級 - * 鏃堕棿澶嶆潅搴︿负O(n^2) - * - * @param items 鑺傜偣鍩� - * @return 澶氭5鏍戠殑鏍硅妭鐐归泦鍚� - */ - public static <T extends INode<T>> List<T> merge(List<T> items) { - ForestNodeManager<T> forestNodeManager = new ForestNodeManager<>(items); - items.forEach(forestNode -> { - if (forestNode.getParentId() != null) { - INode<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId()); - if (node != null) { - node.getChildren().add(forestNode); - } else { - forestNodeManager.addParentId(forestNode.getChannelId()); - } - } - }); - return forestNodeManager.getRoot(); - } - - public static <T extends INode<T>> List<T> merge(List<T> items, String[] parentIds) { - ForestNodeManager<T> forestNodeManager = new ForestNodeManager<>(items); - items.forEach(forestNode -> { - if (forestNode.getParentId() != null) { - INode<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId()); - if (CollectionUtil.contains(parentIds, forestNode.getChannelId())){ - forestNodeManager.addParentId(forestNode.getChannelId()); - } else { - if (node != null){ - node.getChildren().add(forestNode); - } - } - } - }); - return forestNodeManager.getRoot(); - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java deleted file mode 100644 index 2772747..0000000 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/INode.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.genersoft.iot.vmp.utils.node; - -import java.io.Serializable; -import java.util.List; - -/** - * - * 鑺傜偣 - */ -public interface INode<T> extends Serializable { - - /** - * 涓婚敭 - * - * @return String - */ - String getChannelId(); - - /** - * 鐖朵富閿� - * - * @return String - */ - String getParentId(); - - /** - * 瀛愬瓩鑺傜偣 - * - * @return List<T> - */ - List<T> getChildren(); - - /** - * 鏄惁鏈夊瓙瀛欒妭鐐� - * - * @return Boolean - */ - default Boolean getHasChildren() { - return false; - } - -} diff --git a/src/main/java/com/genersoft/iot/vmp/utils/node/TreeNode.java b/src/main/java/com/genersoft/iot/vmp/utils/node/TreeNode.java deleted file mode 100644 index 71f1b2b..0000000 --- a/src/main/java/com/genersoft/iot/vmp/utils/node/TreeNode.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.genersoft.iot.vmp.utils.node; - - - -/** - * 鏍戝瀷鑺傜偣绫� - * - */ -public class TreeNode extends BaseNode<TreeNode> { - - private static final long serialVersionUID = 1L; - - private String title; - - private String key; - - private String value; - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTree.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTree.java deleted file mode 100644 index 73928a4..0000000 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTree.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.genersoft.iot.vmp.vmanager.bean; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.utils.node.INode; -import io.swagger.annotations.ApiModel; - -import java.util.ArrayList; -import java.util.List; - -@ApiModel(value = "DeviceChannelTree瀵硅薄", description = "DeviceChannelTree瀵硅薄") -public class DeviceChannelTree extends DeviceChannel implements INode<DeviceChannelTree> { - private static final long serialVersionUID = 1L; - - /** - * 涓婚敭ID - */ - private int id; - - /** - * 鐖惰妭鐐笽D - */ - private String parentId; - - private String parentName; - - private String title; - - private String key; - - private String value; - - /** - * 瀛愬瓩鑺傜偣 - */ - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List<DeviceChannelTree> children; - - /** - * 鏄惁鏈夊瓙瀛欒妭鐐� - */ - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private Boolean hasChildren; - - @Override - public List<DeviceChannelTree> getChildren() { - if (this.children == null) { - this.children = new ArrayList<>(); - } - return this.children; - } - - @Override - public Boolean getHasChildren() { - if (children.size() > 0) { - return true; - } else { - return this.hasChildren; - } - } - - @Override - public int getId() { - return id; - } - - @Override - public void setId(int id) { - this.id = id; - } - - @Override - public String getParentId() { - return parentId; - } - - @Override - public void setParentId(String parentId) { - this.parentId = parentId; - } - - public String getParentName() { - return parentName; - } - - public void setParentName(String parentName) { - this.parentName = parentName; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public void setChildren(List<DeviceChannelTree> children) { - this.children = children; - } - - public void setHasChildren(Boolean hasChildren) { - this.hasChildren = hasChildren; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTreeNode.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTreeNode.java deleted file mode 100644 index 96577d1..0000000 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTreeNode.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.genersoft.iot.vmp.vmanager.bean; - -import com.genersoft.iot.vmp.utils.node.TreeNode; - -public class DeviceChannelTreeNode extends TreeNode { - - private Integer status; - - private String deviceId; - - private String channelId; - - private Double lng; - - private Double lat; - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public String getChannelId() { - return channelId; - } - - public void setChannelId(String channelId) { - this.channelId = channelId; - } - - public Double getLng() { - return lng; - } - - public void setLng(Double lng) { - this.lng = lng; - } - - public Double getLat() { - return lat; - } - - public void setLat(Double lat) { - this.lat = lat; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java index c360843..7d11b15 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.github.pagehelper.util.StringUtil; import io.swagger.annotations.Api; @@ -65,10 +66,11 @@ @ApiImplicitParam(name = "start", value = "寮�濮嬫椂闂�", required = true, dataTypeClass = String.class), @ApiImplicitParam(name = "end", value = "缁撴潫鏃堕棿", required = true, dataTypeClass = String.class), }) - @GetMapping("/history/{deviceId}") - public ResponseEntity<List<MobilePosition>> positions(@PathVariable String deviceId, - @RequestParam(required = false) String start, - @RequestParam(required = false) String end) { + @GetMapping("/history/{deviceId}/{channelId}") + public ResponseEntity<WVPResult<List<MobilePosition>>> positions(@PathVariable String deviceId, + @PathVariable String channelId, + @RequestParam(required = false) String start, + @RequestParam(required = false) String end) { // if (logger.isDebugEnabled()) { // logger.debug("鏌ヨ璁惧" + deviceId + "鐨勫巻鍙茶建杩�"); // } @@ -79,9 +81,11 @@ if (StringUtil.isEmpty(end)) { end = null; } - - List<MobilePosition> result = storager.queryMobilePositions(deviceId, start, end); - return new ResponseEntity<>(result, HttpStatus.OK); + WVPResult<List<MobilePosition>> wvpResult = new WVPResult<>(); + wvpResult.setCode(0); + List<MobilePosition> result = storager.queryMobilePositions(deviceId, channelId, start, end); + wvpResult.setData(result); + return new ResponseEntity<>(wvpResult, HttpStatus.OK); } /** diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java index 38cbdee..ab153ad 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java @@ -9,7 +9,6 @@ import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; -import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask; import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; @@ -17,14 +16,12 @@ import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.github.pagehelper.PageInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; -import org.kxml2.wap.wv.WV; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -450,11 +447,6 @@ return result; } - @GetMapping("/{deviceId}/tree") - @ApiOperation(value = "閫氶亾鏍戝舰缁撴瀯", notes = "閫氶亾鏍戝舰缁撴瀯") - public WVPResult<List<DeviceChannelTree>> tree(@PathVariable String deviceId) { - return WVPResult.Data(storager.tree(deviceId)); - } @GetMapping("/{deviceId}/sync_status") @ApiOperation(value = "鑾峰彇閫氶亾鍚屾杩涘害", notes = "鑾峰彇閫氶亾鍚屾杩涘害") diff --git a/web_src/index.html b/web_src/index.html index df23a7f..24d5ee2 100644 --- a/web_src/index.html +++ b/web_src/index.html @@ -28,7 +28,7 @@ // 榛樿鍦板浘涓績鐐� center:[116.41020, 39.915119], // 鍦板浘鏈�澶у眰绾� - maxZoom:19, + maxZoom:18, // 鍦板浘鏈�灏忓眰绾� minZoom: 3 } diff --git a/web_src/package-lock.json b/web_src/package-lock.json index f97b032..0d4c886 100644 --- a/web_src/package-lock.json +++ b/web_src/package-lock.json @@ -16,6 +16,7 @@ "moment": "^2.29.1", "ol": "^6.14.1", "postcss-pxtorem": "^5.1.1", + "uuid": "^8.3.2", "vue": "^2.6.11", "vue-clipboard2": "^0.3.1", "vue-clipboards": "^1.3.0", @@ -11880,6 +11881,16 @@ "node": ">=0.8.0" } }, + "node_modules/sockjs/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/sort-asc": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/sort-asc/-/sort-asc-0.1.0.tgz", @@ -12978,13 +12989,11 @@ } }, "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1601826530476&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", - "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, + "version": "8.3.2", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "bin": { - "uuid": "bin/uuid" + "uuid": "dist/bin/uuid" } }, "node_modules/validate-npm-package-license": { @@ -24308,6 +24317,14 @@ "requires": { "faye-websocket": "^0.10.0", "uuid": "^3.0.1" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "sockjs-client": { @@ -25260,10 +25277,9 @@ "dev": true }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1601826530476&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", - "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=", - "dev": true + "version": "8.3.2", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "validate-npm-package-license": { "version": "3.0.4", diff --git a/web_src/package.json b/web_src/package.json index 4fa733e..1e7f043 100644 --- a/web_src/package.json +++ b/web_src/package.json @@ -18,6 +18,7 @@ "moment": "^2.29.1", "ol": "^6.14.1", "postcss-pxtorem": "^5.1.1", + "uuid": "^8.3.2", "vue": "^2.6.11", "vue-clipboard2": "^0.3.1", "vue-clipboards": "^1.3.0", diff --git a/web_src/src/api/deviceApi.js b/web_src/src/api/deviceApi.js deleted file mode 100644 index 830164f..0000000 --- a/web_src/src/api/deviceApi.js +++ /dev/null @@ -1,19 +0,0 @@ -import axios from 'axios'; - -export const tree = (deviceId) => { - return axios({ - url: `/api/device/query/${deviceId}/tree`, - method: 'get' - }) -} - -export const deviceList = (page, count) => { - return axios({ - method: 'get', - url:`/api/device/query/devices`, - params: { - page, - count - } - }) -} \ No newline at end of file diff --git a/web_src/src/components/DeviceList.vue b/web_src/src/components/DeviceList.vue index d934fe6..62cba31 100644 --- a/web_src/src/components/DeviceList.vue +++ b/web_src/src/components/DeviceList.vue @@ -194,7 +194,7 @@ this.$router.push(`/channelList/${row.deviceId}/0/15/1`); }, showDevicePosition: function (row) { - this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); + this.$router.push(`/map?deviceId=${row.deviceId}`); }, //gb28181骞冲彴瀵规帴 diff --git a/web_src/src/components/channelTree.vue b/web_src/src/components/channelTree.vue deleted file mode 100644 index ae9eac7..0000000 --- a/web_src/src/components/channelTree.vue +++ /dev/null @@ -1,70 +0,0 @@ -<template> - <div> - <el-tree :data="channelList" :props="props" @node-click="sendDevicePush"> - <span slot-scope="{ node }"> - <span v-if="node.isLeaf"> - <i class="el-icon-video-camera" :style="{color:node.disabled==1?'#67C23A':'#F56C6C'}"></i> - </span> - <span v-else> - <i class="el-icon-folder"></i> - </span> - <span> - {{ node.label }} - </span> - </span> - </el-tree> - </div> -</template> -<script> -import ChannelTreeItem from "@/components/channelTreeItem" -import {tree} from '@/api/deviceApi' - -export default { - components: { - ChannelTreeItem, - }, - props:{ - device: { - type: Object, - required: true - } - }, - data() { - return { - loading: false, - channelList: [], - props: { - label: 'title', - children: 'children', - isLeaf: 'hasChildren', - disabled: 'status' - }, - } - }, - computed: { - - }, - mounted() { - this.leafs = [] - this.getTree() - }, - methods: { - getTree() { - this.loading = true - var that = this - tree(this.device.deviceId).then(function (res) { - console.log(res.data.data); - that.channelList = res.data.data; - that.loading = false; - }).catch(function (error) { - console.log(error); - that.loading = false; - }); - }, - sendDevicePush(c) { - if(c.hasChildren) return - this.$emit('sendDevicePush',c) - } - } -} -</script> \ No newline at end of file diff --git a/web_src/src/components/channelTreeItem.vue b/web_src/src/components/channelTreeItem.vue deleted file mode 100644 index 7f2a2a5..0000000 --- a/web_src/src/components/channelTreeItem.vue +++ /dev/null @@ -1,74 +0,0 @@ -<template> - <div> - <!-- <div :index="item.key" v-for="(item,i) in list" :key="i+'-'"> - <el-submenu v-if="item.hasChildren"> - <template slot="title"> - <i class="el-icon-video-camera"></i> - <span slot="title">{{item.title || item.deviceId}}</span> - </template> - <channel-list :list="item.children" @sendDevicePush="sendDevicePush"></channel-list> - </el-submenu> - <el-menu-item v-else :index="item.key" @click="sendDevicePush(item)"> - <template slot="title" > - <i class="el-icon-switch-button" :style="{color:item.status==1?'#67C23A':'#F56C6C'}"></i> - <span slot="title">{{item.title}}</span> - </template> - </el-menu-item> - </div> --> - <div > - <template v-if="!item.hasChildren"> - <el-menu-item :index="item.key" @click="sendDevicePush(item)"> - <i class="el-icon-video-camera" :style="{color:item.status==1?'#67C23A':'#F56C6C'}"></i> - {{item.title}} - </el-menu-item> - </template> - - <el-submenu v-else :index="item.key"> - <template slot="title" > - <i class="el-icon-location-outline"></i> - {{item.title}} - </template> - - <template v-for="child in item.children"> - <channel-item - v-if="child.hasChildren" - :item="child" - :key="child.key" - @sendDevicePush="sendDevicePush"/> - <el-menu-item v-else :key="child.key" :index="child.key" @click="sendDevicePush(child)"> - <i class="el-icon-video-camera" :style="{color:child.status==1?'#67C23A':'#F56C6C'}"></i> - {{child.title}} - </el-menu-item> - </template> - </el-submenu> - </div> - </div> -</template> -<script> -export default { - name:'ChannelItem', - props:{ - list:Array, - channelId: String, - item: { - type: Object, - required: true - } - }, - data () { - return { - - } - }, - watch: { - channelId(val) { - console.log(val); - } - }, - methods: { - sendDevicePush(c) { - this.$emit('sendDevicePush',c) - } - } -} -</script> diff --git a/web_src/src/components/common/DeviceTree.vue b/web_src/src/components/common/DeviceTree.vue index 43a797b..fab895f 100644 --- a/web_src/src/components/common/DeviceTree.vue +++ b/web_src/src/components/common/DeviceTree.vue @@ -1,10 +1,10 @@ <template> - <div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF"> + <div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF; overflow: auto"> <el-container> <el-header>璁惧鍒楄〃</el-header> <el-main style="background-color: #ffffff;"> <div class="device-tree-main-box"> - <el-tree :props="defaultProps" :load="loadNode" lazy @node-click="handleNodeClick"@node-contextmenu="handleContextMenu"> + <el-tree :props="defaultProps" :load="loadNode" lazy @node-click="handleNodeClick"@node-contextmenu="handleContextMenu" style="min-width: 100%; display:inline-block !important;"> <span class="custom-tree-node" slot-scope="{ node, data }" style="width: 100%"> <span v-if="node.data.type === 0 && node.data.online" title="鍦ㄧ嚎璁惧" class="device-online iconfont icon-jiedianleizhukongzhongxin2"></span> <span v-if="node.data.type === 0 && !node.data.online " title="绂荤嚎璁惧" class="device-offline iconfont icon-jiedianleizhukongzhongxin2"></span> @@ -49,16 +49,17 @@ }, props: ['clickEvent', 'contextMenuEvent'], methods: { - handleNodeClick(data) { + handleNodeClick(data,node,element) { console.log("鐐瑰嚮浜嬩欢") + console.log(data) if(typeof (this.clickEvent) == "function") { this.clickEvent(data.userData) } }, - handleContextMenu(data) { + handleContextMenu(event,data,node,element) { console.log("鍙抽敭鐐瑰嚮浜嬩欢") if(typeof (this.contextMenuEvent) == "function") { - this.contextMenuEvent(data.userData) + this.contextMenuEvent(event, data.userData) } }, loadNode: function(node, resolve){ diff --git a/web_src/src/components/common/MapComponent.vue b/web_src/src/components/common/MapComponent.vue index b9317d7..2d8600d 100644 --- a/web_src/src/components/common/MapComponent.vue +++ b/web_src/src/components/common/MapComponent.vue @@ -1,5 +1,5 @@ <template> - <div id="mapContainer" style="width: 100%;height: 100%;"></div> + <div id="mapContainer" ref="mapContainer" style="width: 100%;height: 100%;"></div> </template> <script> @@ -7,10 +7,20 @@ import Map from 'ol/Map'; import OSM from 'ol/source/OSM'; import XYZ from 'ol/source/XYZ'; -import TileLayer from 'ol/layer/Tile'; +import VectorSource from 'ol/source/Vector'; +import Tile from 'ol/layer/Tile'; +import VectorLayer from 'ol/layer/Vector'; +import Style from 'ol/style/Style'; +import Icon from 'ol/style/Icon'; import View from 'ol/View'; +import Feature from 'ol/Feature'; +import Overlay from 'ol/Overlay'; +import {Point, LineString} from 'ol/geom'; import {get as getProj, fromLonLat} from 'ol/proj'; import {ZoomSlider, Zoom} from 'ol/control'; +import {containsCoordinate} from 'ol/extent'; + +import {v4} from 'uuid' let olMap = null; @@ -24,7 +34,9 @@ }, created(){ this.$nextTick(() => { - this.init(); + setTimeout(()=>{ + this.init() + }, 100) }) }, @@ -48,7 +60,7 @@ }); let tileLayer = null; if (mapParam.tilesUrl) { - tileLayer = new TileLayer({ + tileLayer = new Tile({ source: new XYZ({ projection: getProj("EPSG:3857"), wrapX: false, @@ -57,13 +69,13 @@ }) }) }else { - tileLayer = new TileLayer({ + tileLayer = new Tile({ preload: 4, source: new OSM(), }) } olMap = new Map({ - target: "mapContainer", // 瀹瑰櫒ID + target: this.$refs.mapContainer, // 瀹瑰櫒ID layers: [tileLayer], // 榛樿鍥惧眰 view: view, // 瑙嗗浘 controls:[ // 鎺т欢 @@ -71,6 +83,7 @@ new Zoom(), ] , }) + console.log(3222) }, setCenter(point){ @@ -82,26 +95,151 @@ }, centerAndZoom(point,zoom,callback){ + var zoom_ = olMap.getView().getZoom(); + zoom = zoom|| zoom_; + var duration = 600; + olMap.getView().setCenter(fromLonLat(point)) + olMap.getView().animate({ + zoom: zoom , + duration: duration + }); + }, + panTo(point, zoom){ + let duration = 800; + + olMap.getView().cancelAnimations() + olMap.getView().animate({ + center: fromLonLat(point), + duration: duration + }); + if (!containsCoordinate(olMap.getView().calculateExtent(), fromLonLat(point))) { + olMap.getView().animate({ + zoom: olMap.getView().getZoom() - 1, + duration: duration / 2 + }, { + zoom: zoom || olMap.getView().getZoom(), + duration: duration / 2 + }); + } }, - panTo(point){ + fit(layer){ + let extent = layer.getSource().getExtent(); + if (extent) { + olMap.getView().fit(extent,{ + duration : 600, + padding: [100, 100, 100, 100] + }); + } + }, - openInfoBox(){ - + openInfoBox(position, content, offset){ + let id = v4() + // let infoBox = document.createElement("div"); + // infoBox.innerHTML = content ; + // infoBox.setAttribute("infoBoxId", id) + let overlay = new Overlay({ + id:id, + autoPan:true, + autoPanAnimation:{ + duration: 250 + }, + element: content, + positioning:"bottom-center", + offset:offset, + // className:overlayStyle.className + }); + olMap.addOverlay(overlay); + overlay.setPosition(fromLonLat(position)); + return id; }, - closeInfoBox(){ - + closeInfoBox(id){ + olMap.getOverlayById(id).setPosition(undefined) + // olMap.removeOverlay(olMap.getOverlayById(id)) }, - addLayer(){ + /** + * 娣诲姞鍥惧眰 + * @param data + * [ + * { + * + * position: [119.1212,45,122], + * image: { + * src:"/images/123.png", + * anchor: [0.5, 0.5] + * + * } + * } + * + * ] + */ + addLayer(data, clickEvent){ + let style = new Style(); + if (data.length > 0) { + let features = []; + for (let i = 0; i < data.length; i++) { + let feature = new Feature(new Point(fromLonLat(data[i].position))); + feature.customData = data[i].data; + let cloneStyle = style.clone() + cloneStyle.setImage(new Icon({ + anchor: data[i].image.anchor, + crossOrigin: 'Anonymous', + src: data[i].image.src, + })) + feature.setStyle(cloneStyle) + features.push(feature); + } + let source = new VectorSource(); + source.addFeatures(features); + let vectorLayer = new VectorLayer({ + source:source, + style:style, + renderMode:"image", + declutter: false + }) + olMap.addLayer(vectorLayer) + if (typeof clickEvent == "function") { + olMap.on("click", (event)=>{ + vectorLayer.getFeatures(event.pixel).then((features)=>{ + if (features.length > 0) { + let items = [] + for (let i = 0; i < features.length; i++) { + items.push(features[i].customData) + } + clickEvent(items) + } + }) + + }) + } + + return vectorLayer; + } }, - removeLayer(){ + removeLayer(layer){ + olMap.removeLayer(layer) + }, + addLineLayer(positions) { + if (positions.length > 0) { + let points = []; + for (let i = 0; i < positions.length; i++) { + points.push(fromLonLat(positions[i])); + } + let line = new LineString(points) + let lineFeature = new Feature(line); + + let source = new VectorSource(); + source.addFeature(lineFeature); + let vectorLayer = new VectorLayer({ + source: source, + }) + olMap.addLayer(vectorLayer) + return vectorLayer; + } } - - - }, destroyed() { // if (this.jessibuca) { diff --git a/web_src/src/components/devicePosition.vue b/web_src/src/components/devicePosition.vue index 2674b0f..cc74dc1 100644 --- a/web_src/src/components/devicePosition.vue +++ b/web_src/src/components/devicePosition.vue @@ -1,260 +1,353 @@ <template> - <div id="devicePosition" style="height: 100%"> - <el-container style="height: 100%"> - <el-header> - <uiHeader></uiHeader> - </el-header> - <el-container> - <el-aside width="250px" height="100%" style="background-color: #FFFFFF; margin: 0 0 20px 20px;"> - <div style=" padding-top: 10px"> - <el-tree class="el-scrollbar" - ref="tree" - id="deviceTree" - empty-text="鏈煡鑺傜偣" - node-key="id" - :highlight-current="false" - :expand-on-click-node="false" - :props="props" - :load="loadNode" - @node-contextmenu="contextmenuEventHandler" - @node-click="nodeClickHandler" - lazy> - </el-tree> - </div> - - </el-aside> - <el-main> - <MapComponent></MapComponent> - </el-main> - </el-container> - </el-container> + <div id="devicePosition" style="width: 100vw; height: 91vh;"> + <el-container style="height: 91vh;" v-loading="isLoging"> + <el-aside width="auto" style="background-color: #ffffff"> + <DeviceTree ref="deviceTree" :clickEvent="clickEvent" :contextMenuEvent="contextmenuEventHandler" ></DeviceTree> + </el-aside> + <el-main style="height: 91vh; padding: 0"> + <MapComponent ref="map"></MapComponent> + </el-main> + </el-container> + <div ref="infobox" v-if="channel != null " > + <div v-if="channel != null" class="infobox-content"> + <el-descriptions class="margin-top" :title="channel.name" :column="1" :colon="true" size="mini" :labelStyle="labelStyle" > + <el-descriptions-item label="鐢熶骇鍘傚晢">{{channel.manufacture}}</el-descriptions-item> + <el-descriptions-item label="鍨嬪彿">{{channel.model}}</el-descriptions-item> + <el-descriptions-item label="璁惧褰掑睘" >{{channel.owner}}</el-descriptions-item> + <el-descriptions-item label="琛屾斂鍖哄煙" >{{channel.civilCode}}</el-descriptions-item> + <el-descriptions-item label="瀹夎鍦板潃" >{{channel.address == null?'鏈煡': channel.address}}</el-descriptions-item> + <el-descriptions-item label="浜戝彴绫诲瀷" >{{channel.ptztypeText}}</el-descriptions-item> + <el-descriptions-item label="缁忕含搴�" >{{channel.longitude}},{{channel.latitude}}</el-descriptions-item> + <el-descriptions-item label="鐘舵��"> + <el-tag size="small" v-if="channel.status === 1">鍦ㄧ嚎</el-tag> + <el-tag size="small" type="info" v-if="channel.status === 0">绂荤嚎</el-tag> + </el-descriptions-item> + </el-descriptions> + <div style="padding-top: 10px"> + <el-button type="primary" size="small" title="鎾斁" icon="el-icon-video-play" @click="play(channel)"></el-button> + <el-button type="primary" size="small" title="缂栬緫浣嶇疆" icon="el-icon-edit" @click="edit(channel)"></el-button> + <el-button type="primary" size="small" title="杞ㄨ抗鏌ヨ" icon="el-icon-map-location" @click="getTrace(channel)"></el-button> + </div> + <span class="infobox-close el-icon-close" @click="closeInfoBox()"></span> + </div> + </div> + <devicePlayer ref="devicePlayer" ></devicePlayer> + <queryTrace ref="queryTrace" ></queryTrace> </div> </template> <script> -import uiHeader from "./UiHeader.vue"; import MapComponent from "./common/MapComponent.vue"; import DeviceService from "./service/DeviceService"; +import DeviceTree from "./common/DeviceTree"; +import channelMapInfobox from "./dialog/channelMapInfobox"; +import devicePlayer from './dialog/devicePlayer.vue' +import queryTrace from './dialog/queryTrace.vue' + export default { - name: "devicePosition", - components: { - MapComponent, - uiHeader, - }, - data() { - return { - deviceService: new DeviceService(), - props: { - label: 'name', - children: 'children', - isLeaf: 'leaf' - }, - }; - }, - created() { - this.init(); - }, - destroyed() { - - }, - methods: { - init(){ - + name: "devicePosition", + components: { + MapComponent, + DeviceTree, + channelMapInfobox, + devicePlayer, + queryTrace, + }, + data() { + return { + deviceService: new DeviceService(), + layer: null, + lineLayer: null, + channel: null, + infoBoxId: null, + labelStyle: { + width: "56px" }, - loadNode: function(node, resolve){ - if (node.level === 0) { - this.deviceService.getAllDeviceList((data)=>{ - console.log("all deivce") - console.log(data) - if (data.length > 0) { - let nodeList = [] - for (let i = 0; i < data.length; i++) { - let node = { - name: data[i].name || data[i].deviceId, - id: data[i].deviceId, - online: data[i].online, - deviceId: data[i].deviceId, - } - nodeList.push(node); - } - resolve(nodeList) - }else { - resolve([]) - } - }, (error)=>{ + isLoging: false, + }; + }, + created() { + if (this.$route.query.deviceId) { + console.log(this.$route.query.deviceId) + // this.$refs.deviceTree.openByDeivceId(this.$route.query.deivceId) + setTimeout(()=>{ // 寤惰繜浠ョ瓑寰呭湴鍥惧姞杞藉畬鎴� TODO 鍚庣画淇敼涓洪�氳繃鏄疄闄呰繖锛涚姸鎬佸姞鍥炶皟瀹屾垚 + this.deviceService.getAllChannel(false, this.$route.query.deviceId, this.channelsHandler) + }, 1000) - }) + } + }, + destroyed() { + + }, + methods: { + clickEvent: function (data) { + if (data.channelId && data.subCount == 0) { + // 鐐瑰嚮閫氶亾 + if (data.longitude * data.latitude === 0) { + this.$message.error('鏈幏鍙栧埌浣嶇疆淇℃伅'); + } else { + if (this.layer != null) { + this.$refs.map.removeLayer(this.layer); + } + this.closeInfoBox() + this.layer = this.$refs.map.addLayer([{ + position: [data.longitude, data.latitude], + image: { + src: this.getImageByChannel(data), + anchor: [0.5, 1] + }, + data: data + }], this.featureClickEvent) + this.$refs.map.panTo([data.longitude, data.latitude], mapParam.maxZoom) } - if (node.level === 1){ - console.log(node) - this.deviceService.getAllCatalog(node.data.deviceId, (data)=>{ - console.log("all Catalog") - console.log(data) - if (data.length > 0) { - let nodeList = [] - for (let i = 0; i < data.length; i++) { - let node = { - name: data[i].name || data[i].channelId, - id: data[i].channelId, - online: data[i].status === 1, - deviceId: data[i].deviceId, - channelId: data[i].channelId, - } - nodeList.push(node); - } - resolve(nodeList) - }else { - resolve([]) - } - }, (error)=>{ - - }) - } - - if (node.level > 1) { - console.log(node.data.channelId) - this.deviceService.getAllSubCatalog(node.data.deviceId, node.data.channelId, (data)=>{ - console.log("all Catalog") - console.log(data) - if (data.length > 0) { - let nodeList = [] - for (let i = 0; i < data.length; i++) { - let node = { - name: data[i].name || data[i].channelId, - id: data[i].channelId, - online: data[i].status === 1, - deviceId: data[i].deviceId, - channelId: data[i].channelId, - } - nodeList.push(node); - } - resolve(nodeList) - }else { - resolve([]) - } - }, (error)=>{ - - }) - } - }, - contextmenuEventHandler: function (event,data,node,element){ - if (node.data.type !== 0) { - data.parentId = node.parent.data.id; - this.$contextmenu({ - items: [ - { - label: "绉婚櫎閫氶亾", - icon: "el-icon-delete", - disabled: false, - onClick: () => { - this.$axios({ - method:"delete", - url:"/api/platform/catalog/relation/del", - data: data - }).then((res)=>{ - console.log("绉婚櫎鎴愬姛") - node.parent.loaded = false - node.parent.expand(); - }).catch(function (error) { - console.log(error); - }); - } - } - ], - event, // 榧犳爣浜嬩欢淇℃伅 - customClass: "custom-class", // 鑷畾涔夎彍鍗� class - zIndex: 3000, // 鑿滃崟鏍峰紡 z-index - }); - }else { - this.$contextmenu({ - items: [ - { - label: "鍒锋柊鑺傜偣", - icon: "el-icon-refresh", - disabled: false, - onClick: () => { - this.refreshCatalog(node); - } - }, - { - label: "鏂板缓鑺傜偣", - icon: "el-icon-plus", - disabled: false, - onClick: () => { - this.addCatalog(data.id, node); - } - }, - { - label: "淇敼鑺傜偣", - icon: "el-icon-edit", - disabled: node.level === 1, - onClick: () => { - this.editCatalog(data, node); - } - }, - { - label: "鍒犻櫎鑺傜偣", - icon: "el-icon-delete", - disabled: node.level === 1, - divided: true, - onClick: () => { - this.$confirm('纭畾鍒犻櫎?', '鎻愮ず', { - confirmButtonText: '纭畾', - cancelButtonText: '鍙栨秷', - type: 'warning' - }).then(() => { - this.removeCatalog(data.id, node) - }).catch(() => { - - }); - } - }, - { - label: "璁句负榛樿", - icon: "el-icon-folder-checked", - disabled: node.data.id === this.defaultCatalogIdSign, - onClick: () => { - this.setDefaultCatalog(data.id) - }, - }, - // { - // label: "瀵煎嚭", - // icon: "el-icon-download", - // disabled: false, - // children: [ - // { - // label: "瀵煎嚭鍒版枃浠�", - // onClick: () => { - // - // }, - // }, - // { - // label: "瀵煎嚭鍒板叾浠栧钩鍙�", - // onClick: () => { - // - // }, - // } - // ] - // }, - - ], - event, // 榧犳爣浜嬩欢淇℃伅 - customClass: "custom-class", // 鑷畾涔夎彍鍗� class - zIndex: 3000, // 鑿滃崟鏍峰紡 z-index - }); - } - - return false; - }, - nodeClickHandler: function (data, node, tree){ - this.chooseId = data.id; - this.chooseName = data.name; - if (this.catalogIdChange)this.catalogIdChange(this.chooseId, this.chooseName); } }, + contextmenuEventHandler: function (event, data) { + if (data.channelId && data.subCount == 0) { + // 鐐瑰嚮閫氶亾 + this.$contextmenu({ + items: [ + { + label: "鎾斁", + icon: "el-icon-video-play", + disabled: false, + onClick: () => { + this.play(data); + } + }, + { + label: "缂栬緫浣嶇疆", + icon: "el-icon-edit", + disabled: false, + onClick: () => { + this.edit(data) + } + }, + { + label: "杞ㄨ抗鏌ヨ", + icon: "el-icon-map-location", + disabled: false, + onClick: () => { + this.getTrace(data) + } + } + ], + event, // 榧犳爣浜嬩欢淇℃伅 + customClass: "custom-class", // 鑷畾涔夎彍鍗� class + zIndex: 3000, // 鑿滃崟鏍峰紡 z-index + }); + } else { + this.deviceOrSubChannelMenu(event, data) + } + + }, + deviceOrSubChannelMenu: function (event, data) { + // 鐐瑰嚮璁惧 + this.$contextmenu({ + items: [ + { + label: "瀹氫綅", + icon: "el-icon-s-promotion", + disabled: false, + onClick: () => { + if (!data.channelId) { + this.deviceService.getAllChannel(false, data.deviceId, this.channelsHandler) + } + if (data.channelId && data.subCount > 0) { + // 鐐瑰嚮瀛愮洰褰� + this.deviceService.getAllSubChannel(false, data.deviceId, data.channelId, this.channelsHandler) + } + } + } + ], + event, // 榧犳爣浜嬩欢淇℃伅 + customClass: "custom-class", // 鑷畾涔夎彍鍗� class + zIndex: 3000, // 鑿滃崟鏍峰紡 z-index + }); + + }, + channelsHandler: function (channels) { + console.log(2) + if (channels.length > 0) { + this.clean() + this.closeInfoBox() + let params = []; + for (let i = 0; i < channels.length; i++) { + if (channels[i].longitude * channels[i].latitude === 0) { + continue; + } + let item = { + position: [channels[i].longitude, channels[i].latitude], + image: { + src: this.getImageByChannel(channels[i]), + anchor: [0.5, 1] + }, + data: channels[i] + } + params.push(item); + } + console.log(3) + + this.layer = this.$refs.map.addLayer(params, this.featureClickEvent) + console.log(4) + if (params.length === 1) { + this.$refs.map.panTo([channels[0].longitude, channels[0].latitude], mapParam.maxZoom) + } else if (params.length > 1) { + this.$refs.map.fit(this.layer) + } else { + this.$message.error('鏈幏鍙栧埌浣嶇疆淇℃伅'); + } + } else { + this.$message.error('鏈幏鍙栧埌浣嶇疆淇℃伅'); + } + }, + getImageByChannel: function (channel) { + let src = "static/images/gis/camera.png" + switch (channel.ptztype) { + case 1: + if (channel.status === 1) { + src = "static/images/gis/camera1.png" + } else { + src = "static/images/gis/camera1-offline.png" + } + break; + case 2: + if (channel.status === 1) { + src = "static/images/gis/camera2.png" + } else { + src = "static/images/gis/camera2-offline.png" + } + break; + case 3: + if (channel.status === 1) { + src = "static/images/gis/camera3.png" + } else { + src = "static/images/gis/camera3-offline.png" + } + break; + default: + if (channel.status === 1) { + src = "static/images/gis/camera.png" + } else { + src = "static/images/gis/camera-offline.png" + } + } + return src; + }, + featureClickEvent: function (channels) { + this.closeInfoBox() + if (channels.length > 0) { + this.channel = channels[0] + } + this.$nextTick(() => { + this.infoBoxId = this.$refs.map.openInfoBox([this.channel.longitude, this.channel.latitude], this.$refs.infobox, [0, -50]) + }) + }, + closeInfoBox: function () { + if (this.infoBoxId != null) { + this.$refs.map.closeInfoBox(this.infoBoxId) + } + }, + play: function (channel) { + + let deviceId = channel.deviceId; + this.isLoging = true; + let channelId = channel.channelId; + console.log("閫氱煡璁惧鎺ㄦ祦1锛�" + deviceId + " : " + channelId); + let that = this; + this.$axios({ + method: 'get', + url: '/api/play/start/' + deviceId + '/' + channelId + }).then(function (res) { + that.isLoging = false; + if (res.data.code === 0) { + + that.$refs.devicePlayer.openDialog("media", deviceId, channelId, { + streamInfo: res.data.data, + hasAudio: channel.hasAudio + }); + + } else { + that.$message.error(res.data.msg); + } + }).catch(function (e) { + }); + }, + edit: function (data) { + this.$message.warning('鏆備笉鏀寔'); + }, + getTrace: function (data) { + // this.$message.warning('鏆備笉鏀寔'); + this.clean() + this.$refs.queryTrace.openDialog(data, (channelPositions) => { + console.log("getTrace") + console.log(channelPositions) + if (channelPositions.length === 0) { + this.$message.success('鏈煡璇㈠埌杞ㄨ抗淇℃伅'); + } else { + let positions = []; + for (let i = 0; i < channelPositions.length; i++) { + if (channelPositions[i].cnLng * channelPositions[i].cnLat > 0) { + positions.push([channelPositions[i].cnLng, channelPositions[i].cnLat]) + } + + } + if (positions.length === 0) { + this.$message.success('鏈煡璇㈠埌杞ㄨ抗淇℃伅'); + return; + } + this.lineLayer = this.$refs.map.addLineLayer(positions) + this.$refs.map.fit(this.lineLayer) + } + }) + }, + clean: function (){ + if (this.lineLayer != null) { + this.$refs.map.removeLayer(this.lineLayer) + } + if (this.infoBoxId != null) { + this.$refs.map.closeInfoBox(this.infoBoxId) + } + if (this.layer != null) { + this.$refs.map.removeLayer(this.layer) + } + } + }, + }; </script> <style> +.infobox-content{ + width: 260px; + background-color: #FFFFFF; + padding: 10px; + border-radius: 10px; + border: 1px solid #e2e2e2; +} +.infobox-content::after { + position: absolute; + bottom: -11px; + left: 130px; + display: block; + content: ""; + width: 16px; + height: 16px; + background: url('~@static/images/arrow.png') no-repeat center; +} +.infobox-close { + position: absolute; + right: 1rem; + top: 1rem; + color: #000000; + cursor:pointer +} +.el-descriptions__title { + font-size: 1rem; + font-weight: 700; + padding: 20px 20px 0px 23px; + text-align: center; + width: 100%; +} </style> diff --git a/web_src/src/components/dialog/channelMapInfobox.vue b/web_src/src/components/dialog/channelMapInfobox.vue new file mode 100644 index 0000000..2ef0e52 --- /dev/null +++ b/web_src/src/components/dialog/channelMapInfobox.vue @@ -0,0 +1,65 @@ +<template> + <div id="channelMapInfobox" style="display: none"> + <div > + <el-descriptions class="margin-top" title="channel.name" :column="4" direction="vertical"> + <el-descriptions-item label="鐢熶骇鍘傚晢">{{channel.manufacture}}</el-descriptions-item> + <el-descriptions-item label="鍨嬪彿">{{channel.model}}</el-descriptions-item> + <el-descriptions-item label="璁惧褰掑睘" >{{channel.owner}}</el-descriptions-item> + <el-descriptions-item label="琛屾斂鍖哄煙" >{{channel.civilCode}}</el-descriptions-item> + <el-descriptions-item label="瀹夎鍦板潃" >{{channel.address}}</el-descriptions-item> + <el-descriptions-item label="浜戝彴绫诲瀷" >{{channel.ptztypeText}}</el-descriptions-item> + <el-descriptions-item label="缁忕含搴�" >{{channel.longitude}},{{channel.latitude}}</el-descriptions-item> + <el-descriptions-item label="鐘舵��"> + <el-tag size="small" v-if="channel.status === 1">鍦ㄧ嚎</el-tag> + <el-tag size="small" v-if="channel.status === 0">绂荤嚎</el-tag> + </el-descriptions-item> + </el-descriptions> + </div> + + <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer> + </div> +</template> + +<script> +import devicePlayer from '../dialog/devicePlayer.vue' + +export default { + name: "channelMapInfobox", + props: ['channel'], + computed: {devicePlayer}, + created() {}, + data() { + return { + showDialog: false, + isLoging: false + }; + }, + methods: { + + play: function (){ + let deviceId = this.channel.deviceId; + this.isLoging = true; + let channelId = this.channel.channelId; + console.log("閫氱煡璁惧鎺ㄦ祦1锛�" + deviceId + " : " + channelId); + let that = this; + this.$axios({ + method: 'get', + url: '/api/play/start/' + deviceId + '/' + channelId + }).then(function (res) { + that.isLoging = false; + if (res.data.code === 0) { + that.$refs.devicePlayer.openDialog("media", deviceId, channelId, { + streamInfo: res.data.data, + hasAudio: this.channel.hasAudio + }); + } else { + that.$message.error(res.data.msg); + } + }).catch(function (e) { + }); + }, + close: function () { + }, + }, +}; +</script> diff --git a/web_src/src/components/dialog/queryTrace.vue b/web_src/src/components/dialog/queryTrace.vue new file mode 100644 index 0000000..bb12765 --- /dev/null +++ b/web_src/src/components/dialog/queryTrace.vue @@ -0,0 +1,100 @@ +<template> + <div id="queryTrace" > + <el-dialog + title="鏌ヨ杞ㄨ抗" + width="40%" + top="2rem" + :close-on-click-modal="false" + :visible.sync="showDialog" + :destroy-on-close="true" + @close="close()" + > + <div v-loading="isLoging"> + <el-date-picker v-model="searchFrom" type="datetime" placeholder="閫夋嫨寮�濮嬫棩鏈熸椂闂�" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> + <el-date-picker v-model="searchTo" type="datetime" placeholder="閫夋嫨缁撴潫鏃ユ湡鏃堕棿" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> + <el-button icon="el-icon-search" size="mini" type="primary" @click="onSubmit">鏌ヨ</el-button> + </div> + + </el-dialog> + </div> +</template> + +<script> +import DeviceService from '../service/DeviceService' + +export default { + name: "deviceEdit", + props: [], + computed: {}, + created() {}, + data() { + return { + deviceService: new DeviceService(), + pickerOptions: { + shortcuts: [{ + text: '浠婂ぉ', + onClick(picker) { + picker.$emit('pick', new Date()); + } + }, { + text: '鏄ㄥぉ', + onClick(picker) { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24); + picker.$emit('pick', date); + } + }, { + text: '涓�鍛ㄥ墠', + onClick(picker) { + const date = new Date(); + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); + picker.$emit('pick', date); + } + }] + }, + searchFrom: null, + searchTo: null, + listChangeCallback: null, + showDialog: false, + isLoging: false, + channel: null, + callback: null, + }; + }, + methods: { + openDialog: function (channel, callback) { + console.log(channel) + this.showDialog = true; + this.callback = callback; + this.channel = channel; + }, + + onSubmit: function () { + console.log("onSubmit"); + this.isLoging = true; + this.$axios.get(`/api/position/history/${this.channel.deviceId}/${this.channel.channelId}`, { + }).then((res)=> { + this.isLoging = false; + if (typeof this.callback == "function") { + if (res.data.code == 0) { + this.callback(res.data.data) + this.close() + }else { + this.$message.error(res.data.msg); + } + + } + }).catch(function (error) { + this.isLoging = false; + console.error(error); + }) + }, + close: function () { + this.showDialog = false; + this.isLoging = false; + this.callback = null; + this.channel = null; + }, + }, +}; +</script> diff --git a/web_src/src/components/live.vue b/web_src/src/components/live.vue index bcb1389..adf434e 100644 --- a/web_src/src/components/live.vue +++ b/web_src/src/components/live.vue @@ -1,44 +1,28 @@ <template> - <div id="devicePosition" style="height: 100%"> - <el-container style="height: 100%"> - <el-header> - <uiHeader></uiHeader> - </el-header> - <el-container v-loading="loading" element-loading-text="鎷煎懡鍔犺浇涓�" style="margin: 0 20px;"> - <el-aside width="300px" style="background-color: #ffffff"> - <div style="text-align: center;padding-top: 20px;">璁惧鍒楄〃</div> - <el-menu v-loading="loading"> - <el-submenu v-for="device in deviceList" :key="device.deviceId" :index="device.deviceId" @click="sendDevicePush(item)"> - <template slot="title" > - <i class="el-icon-location-outline"></i> - {{device.name}} - </template> - <ChannelTree :device="device" @sendDevicePush="sendDevicePush"></ChannelTree> - </el-submenu> - </el-menu> - </el-aside> - <el-container> - <!-- <LivePlay></LivePlay> --> - <el-header height="40px" style="text-align: left;font-size: 17px;line-height: 40px;"> - 鍒嗗睆: - <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/> - <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/> - <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/> - </el-header> - <el-main> - <div style="width: 100%;height: calc( 100vh - 110px );display: flex;flex-wrap: wrap;background-color: #000;"> - <div v-for="i in spilt" :key="i" class="play-box" - :style="liveStyle" :class="{redborder:playerIdx == (i-1)}" - @click="playerIdx = (i-1)" - > - <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div> - <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true" - :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player> - <!-- <player v-else ref="'player'+i" :idx="'player'+i" :visible.sync="showVideoDialog" :videoUrl="videoUrl[i-1]" :height="true" :hasAudio="hasAudio" fluent autoplay live ></player> --> - </div> - </div> - </el-main> - </el-container> + <div id="devicePosition" style="width:100vw; height: 91vh"> + <el-container v-loading="loading" style="height: 91vh;" element-loading-text="鎷煎懡鍔犺浇涓�" > + <el-aside width="300px" style="background-color: #ffffff"> + <DeviceTree :clickEvent="clickEvent" :contextMenuEvent="contextMenuEvent" ></DeviceTree> + </el-aside> + <el-container> + <el-header height="5vh" style="text-align: left;font-size: 17px;line-height:5vh"> + 鍒嗗睆: + <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/> + <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/> + <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/> + </el-header> + <el-main style="padding: 0;"> + <div style="width: 99%;height: 85vh;display: flex;flex-wrap: wrap;background-color: #000;"> + <div v-for="i in spilt" :key="i" class="play-box" + :style="liveStyle" :class="{redborder:playerIdx == (i-1)}" + @click="playerIdx = (i-1)" + > + <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div> + <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true" + :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player> + </div> + </div> + </el-main> </el-container> </el-container> </div> @@ -46,13 +30,13 @@ <script> import uiHeader from "../layout/UiHeader.vue"; - import player from './dialog/jessibuca.vue' - import ChannelTree from './channelTree.vue' + import player from './common/jessibuca.vue' + import DeviceTree from './common/DeviceTree.vue' export default { name: "live", components: { - uiHeader, player, ChannelTree + uiHeader, player, DeviceTree }, data() { return { @@ -127,33 +111,17 @@ clearTimeout(this.updateLooper); }, methods: { - initData: function () { - this.getDeviceList(); - - }, destroy(idx) { console.log(idx); this.clear(idx.substring(idx.length-1)) }, - getDeviceList: function() { - let that = this; - this.$axios({ - method: 'get', - url:`/api/device/query/devices`, - params: { - page: that.currentPage, - count: that.count - } - }).then(function (res) { - console.log(res.data.list); - that.total = res.data.total; + clickEvent: function (data) { + if (data.channelId && data.subCount == 0) { + this.sendDevicePush(data) + } + }, + contextMenuEvent: function (data) { - that.deviceList = res.data.list.map(item=>{return {deviceChannelList:[],...item}}); - that.getDeviceListLoading = false; - }).catch(function (error) { - console.log(error); - that.getDeviceListLoading = false; - }); }, //閫氱煡璁惧涓婁紶濯掍綋娴� sendDevicePush: function (itemData) { diff --git a/web_src/src/components/service/DeviceService.js b/web_src/src/components/service/DeviceService.js index aae0418..6149579 100644 --- a/web_src/src/components/service/DeviceService.js +++ b/web_src/src/components/service/DeviceService.js @@ -32,7 +32,6 @@ getAllDeviceListIteration(deviceList, currentPage, count, callback, errorCallback) { this.getDeviceList(currentPage, count, (data) => { - console.log(data) if (data.list) { deviceList = deviceList.concat(data.list); if (deviceList.length < data.total) { @@ -55,14 +54,13 @@ getAllChannelIteration(isCatalog, deviceId, catalogList, currentPage, count, callback, errorCallback) { this.getChanel(isCatalog, deviceId, currentPage, count, (data) => { - console.log(data) if (data.list) { catalogList = catalogList.concat(data.list); if (catalogList.length < data.total) { currentPage ++ this.getAllChannelIteration(isCatalog, deviceId, catalogList, currentPage, count, callback, errorCallback) }else { - console.log(2222) + console.log(1) if (typeof (callback) == "function") callback(catalogList) } } @@ -94,7 +92,6 @@ getAllSubChannelIteration(isCatalog, deviceId,channelId, catalogList, currentPage, count, callback, errorCallback) { this.getSubChannel(isCatalog, deviceId, channelId, currentPage, count, (data) => { - console.log(data) if (data.list) { catalogList = catalogList.concat(data.list); if (catalogList.length < data.total) { @@ -119,16 +116,6 @@ } }).then((res) =>{ if (typeof (callback) == "function") callback(res.data) - }).catch(errorCallback); - } - getDeviceTree(deviceId, callback, errorCallback){ - this.$axios({ - method: 'get', - url: `/api/device/query/${deviceId}/tree`, - params:{} - }).then((res) =>{ - console.log(res.data) - if (typeof (callback) == "function") callback(res.data.data) }).catch(errorCallback); } } diff --git a/web_src/src/layout/UiHeader.vue b/web_src/src/layout/UiHeader.vue index 10410bd..a0a252c 100644 --- a/web_src/src/layout/UiHeader.vue +++ b/web_src/src/layout/UiHeader.vue @@ -5,6 +5,7 @@ <el-menu-item index="/control">鎺у埗鍙�</el-menu-item> <el-menu-item index="/live">瀹炴椂鐩戞帶</el-menu-item> <el-menu-item index="/deviceList">鍥芥爣璁惧</el-menu-item> + <el-menu-item index="/map">鐢靛瓙鍦板浘</el-menu-item> <el-menu-item index="/pushVideoList">鎺ㄦ祦鍒楄〃</el-menu-item> <el-menu-item index="/streamProxyList">鎷夋祦浠g悊</el-menu-item> <el-menu-item index="/cloudRecord">浜戠褰曞儚</el-menu-item> @@ -47,7 +48,6 @@ if (this.$route.path.startsWith("/channelList")) { this.activeIndex = "/deviceList" } - }, mounted() { window.addEventListener('beforeunload', e => this.beforeunloadHandler(e)) diff --git a/web_src/src/router/index.js b/web_src/src/router/index.js index 6128d43..5a1d964 100644 --- a/web_src/src/router/index.js +++ b/web_src/src/router/index.js @@ -108,6 +108,11 @@ name: 'rtcPlayer', component: rtcPlayer, }, + { + path: '/map', + name: 'devicePosition', + component: devicePosition, + }, ] }, { diff --git a/web_src/static/images/arrow.png b/web_src/static/images/arrow.png new file mode 100644 index 0000000..4d8df46 --- /dev/null +++ b/web_src/static/images/arrow.png Binary files differ diff --git a/web_src/static/images/gis/camera-offline.png b/web_src/static/images/gis/camera-offline.png new file mode 100644 index 0000000..67eb0fc --- /dev/null +++ b/web_src/static/images/gis/camera-offline.png Binary files differ diff --git a/web_src/static/images/gis/camera.png b/web_src/static/images/gis/camera.png new file mode 100644 index 0000000..a93bd55 --- /dev/null +++ b/web_src/static/images/gis/camera.png Binary files differ diff --git a/web_src/static/images/gis/camera1-offline.png b/web_src/static/images/gis/camera1-offline.png new file mode 100644 index 0000000..597209b --- /dev/null +++ b/web_src/static/images/gis/camera1-offline.png Binary files differ diff --git a/web_src/static/images/gis/camera1.png b/web_src/static/images/gis/camera1.png new file mode 100644 index 0000000..e5f2b5f --- /dev/null +++ b/web_src/static/images/gis/camera1.png Binary files differ diff --git a/web_src/static/images/gis/camera2-offline.png b/web_src/static/images/gis/camera2-offline.png new file mode 100644 index 0000000..4ddae23 --- /dev/null +++ b/web_src/static/images/gis/camera2-offline.png Binary files differ diff --git a/web_src/static/images/gis/camera2.png b/web_src/static/images/gis/camera2.png new file mode 100644 index 0000000..073bceb --- /dev/null +++ b/web_src/static/images/gis/camera2.png Binary files differ diff --git a/web_src/static/images/gis/camera3-offline.png b/web_src/static/images/gis/camera3-offline.png new file mode 100644 index 0000000..f05c2a3 --- /dev/null +++ b/web_src/static/images/gis/camera3-offline.png Binary files differ diff --git a/web_src/static/images/gis/camera3.png b/web_src/static/images/gis/camera3.png new file mode 100644 index 0000000..b40f67b --- /dev/null +++ b/web_src/static/images/gis/camera3.png Binary files differ -- Gitblit v1.8.0