Commit 1e2d207aea24b5956d5ece95ed4a9db0f59f34d7
1 parent
190fc62b
添加优化后的地图页面,完全一处百度地图相关的api
Showing
40 changed files
with
732 additions
and
1041 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java
| @@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | @@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | ||
| 5 | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; | 5 | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| 6 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | 6 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 7 | import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; | 7 | import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; |
| 8 | -import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree; | ||
| 9 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; | 8 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
| 10 | import com.github.pagehelper.PageInfo; | 9 | import com.github.pagehelper.PageInfo; |
| 11 | 10 | ||
| @@ -94,12 +93,6 @@ public interface IVideoManagerStorage { | @@ -94,12 +93,6 @@ public interface IVideoManagerStorage { | ||
| 94 | 93 | ||
| 95 | public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit); | 94 | public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit); |
| 96 | 95 | ||
| 97 | - /** | ||
| 98 | - * 获取某个设备的通道树 | ||
| 99 | - * @param deviceId 设备ID | ||
| 100 | - * @return | ||
| 101 | - */ | ||
| 102 | - List<DeviceChannelTree> tree(String deviceId); | ||
| 103 | 96 | ||
| 104 | /** | 97 | /** |
| 105 | * 获取某个设备的通道列表 | 98 | * 获取某个设备的通道列表 |
| @@ -285,7 +278,7 @@ public interface IVideoManagerStorage { | @@ -285,7 +278,7 @@ public interface IVideoManagerStorage { | ||
| 285 | * @param startTime | 278 | * @param startTime |
| 286 | * @param endTime | 279 | * @param endTime |
| 287 | */ | 280 | */ |
| 288 | - public List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime); | 281 | + public List<MobilePosition> queryMobilePositions(String deviceId, String channelId, String startTime, String endTime); |
| 289 | 282 | ||
| 290 | /** | 283 | /** |
| 291 | * 查询最新移动位置 | 284 | * 查询最新移动位置 |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
| @@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.storager.dao; | @@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.storager.dao; | ||
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | 3 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| 4 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform; | 4 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform; |
| 5 | -import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree; | ||
| 6 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; | 5 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
| 7 | import org.apache.ibatis.annotations.*; | 6 | import org.apache.ibatis.annotations.*; |
| 8 | import org.springframework.stereotype.Repository; | 7 | import org.springframework.stereotype.Repository; |
| @@ -236,23 +235,6 @@ public interface DeviceChannelMapper { | @@ -236,23 +235,6 @@ public interface DeviceChannelMapper { | ||
| 236 | @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1") | 235 | @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1") |
| 237 | List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId); | 236 | List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId); |
| 238 | 237 | ||
| 239 | - @Select(" SELECT\n" + | ||
| 240 | - " id,\n" + | ||
| 241 | - " channelId,\n" + | ||
| 242 | - " deviceId,\n" + | ||
| 243 | - " parentId,\n" + | ||
| 244 | - " status,\n" + | ||
| 245 | - " name as title,\n" + | ||
| 246 | - " channelId as \"value\",\n" + | ||
| 247 | - " channelId as \"key\",\n" + | ||
| 248 | - " longitude,\n" + | ||
| 249 | - " latitude,\n" + | ||
| 250 | - " PTZType,\n" + | ||
| 251 | - " subCount\n" + | ||
| 252 | - " from device_channel\n" + | ||
| 253 | - " where deviceId = #{deviceId}") | ||
| 254 | - List<DeviceChannelTree> tree(String deviceId); | ||
| 255 | - | ||
| 256 | @Delete(value = {" <script>" + | 238 | @Delete(value = {" <script>" + |
| 257 | "DELETE " + | 239 | "DELETE " + |
| 258 | "from " + | 240 | "from " + |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java
| @@ -16,12 +16,12 @@ public interface DeviceMobilePositionMapper { | @@ -16,12 +16,12 @@ public interface DeviceMobilePositionMapper { | ||
| 16 | 16 | ||
| 17 | @Select(value = {" <script>" + | 17 | @Select(value = {" <script>" + |
| 18 | "SELECT * FROM device_mobile_position" + | 18 | "SELECT * FROM device_mobile_position" + |
| 19 | - " WHERE deviceId = #{deviceId} " + | 19 | + " WHERE deviceId = #{deviceId} and channelId = #{channelId} " + |
| 20 | "<if test=\"startTime != null\"> AND time>=#{startTime}</if>" + | 20 | "<if test=\"startTime != null\"> AND time>=#{startTime}</if>" + |
| 21 | "<if test=\"endTime != null\"> AND time<=#{endTime}</if>" + | 21 | "<if test=\"endTime != null\"> AND time<=#{endTime}</if>" + |
| 22 | " ORDER BY time ASC" + | 22 | " ORDER BY time ASC" + |
| 23 | " </script>"}) | 23 | " </script>"}) |
| 24 | - List<MobilePosition> queryPositionByDeviceIdAndTime(String deviceId, String startTime, String endTime); | 24 | + List<MobilePosition> queryPositionByDeviceIdAndTime(String deviceId, String channelId, String startTime, String endTime); |
| 25 | 25 | ||
| 26 | @Select("SELECT * FROM device_mobile_position WHERE deviceId = #{deviceId}" + | 26 | @Select("SELECT * FROM device_mobile_position WHERE deviceId = #{deviceId}" + |
| 27 | " ORDER BY time DESC LIMIT 1") | 27 | " ORDER BY time DESC LIMIT 1") |
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
| @@ -13,8 +13,6 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | @@ -13,8 +13,6 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | ||
| 13 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 13 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 14 | import com.genersoft.iot.vmp.storager.dao.*; | 14 | import com.genersoft.iot.vmp.storager.dao.*; |
| 15 | import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; | 15 | import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; |
| 16 | -import com.genersoft.iot.vmp.utils.node.ForestNodeMerger; | ||
| 17 | -import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree; | ||
| 18 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; | 16 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
| 19 | import com.github.pagehelper.PageHelper; | 17 | import com.github.pagehelper.PageHelper; |
| 20 | import com.github.pagehelper.PageInfo; | 18 | import com.github.pagehelper.PageInfo; |
| @@ -354,10 +352,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -354,10 +352,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 354 | return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, null, query, hasSubChannel, online, start, limit); | 352 | return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, null, query, hasSubChannel, online, start, limit); |
| 355 | } | 353 | } |
| 356 | 354 | ||
| 357 | - @Override | ||
| 358 | - public List<DeviceChannelTree> tree(String deviceId) { | ||
| 359 | - return ForestNodeMerger.merge(deviceChannelMapper.tree(deviceId)); | ||
| 360 | - } | ||
| 361 | 355 | ||
| 362 | @Override | 356 | @Override |
| 363 | public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) { | 357 | public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) { |
| @@ -504,8 +498,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -504,8 +498,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 504 | * @param endTime | 498 | * @param endTime |
| 505 | */ | 499 | */ |
| 506 | @Override | 500 | @Override |
| 507 | - public synchronized List<MobilePosition> queryMobilePositions(String deviceId, String startTime, String endTime) { | ||
| 508 | - return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, startTime, endTime); | 501 | + public synchronized List<MobilePosition> queryMobilePositions(String deviceId, String channelId, String startTime, String endTime) { |
| 502 | + return deviceMobilePositionMapper.queryPositionByDeviceIdAndTime(deviceId, channelId, startTime, endTime); | ||
| 509 | } | 503 | } |
| 510 | 504 | ||
| 511 | @Override | 505 | @Override |
src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.utils.node; | ||
| 2 | - | ||
| 3 | -import com.fasterxml.jackson.annotation.JsonInclude; | ||
| 4 | - | ||
| 5 | -import java.util.ArrayList; | ||
| 6 | -import java.util.List; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * 节点基类 | ||
| 10 | - * | ||
| 11 | - */ | ||
| 12 | -public class BaseNode<T> implements INode<T> { | ||
| 13 | - | ||
| 14 | - private static final long serialVersionUID = 1L; | ||
| 15 | - | ||
| 16 | - /** | ||
| 17 | - * 主键ID | ||
| 18 | - */ | ||
| 19 | - protected String channelId; | ||
| 20 | - | ||
| 21 | - /** | ||
| 22 | - * 父节点ID | ||
| 23 | - */ | ||
| 24 | - protected String parentId; | ||
| 25 | - | ||
| 26 | - /** | ||
| 27 | - * 子孙节点 | ||
| 28 | - */ | ||
| 29 | - @JsonInclude(JsonInclude.Include.NON_EMPTY) | ||
| 30 | - protected List<T> children = new ArrayList<T>(); | ||
| 31 | - | ||
| 32 | - /** | ||
| 33 | - * 是否有子孙节点 | ||
| 34 | - */ | ||
| 35 | - @JsonInclude(JsonInclude.Include.NON_EMPTY) | ||
| 36 | - private Boolean hasChildren; | ||
| 37 | - | ||
| 38 | - /** | ||
| 39 | - * 是否有子孙节点 | ||
| 40 | - * | ||
| 41 | - * @return Boolean | ||
| 42 | - */ | ||
| 43 | - @Override | ||
| 44 | - public Boolean getHasChildren() { | ||
| 45 | - if (children.size() > 0) { | ||
| 46 | - return true; | ||
| 47 | - } else { | ||
| 48 | - return this.hasChildren; | ||
| 49 | - } | ||
| 50 | - } | ||
| 51 | - | ||
| 52 | - @Override | ||
| 53 | - public String getChannelId() { | ||
| 54 | - return channelId; | ||
| 55 | - } | ||
| 56 | - | ||
| 57 | - @Override | ||
| 58 | - public String getParentId() { | ||
| 59 | - return parentId; | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - @Override | ||
| 63 | - public List<T> getChildren() { | ||
| 64 | - return children; | ||
| 65 | - } | ||
| 66 | - | ||
| 67 | - public void setChildren(List<T> children) { | ||
| 68 | - this.children = children; | ||
| 69 | - } | ||
| 70 | - | ||
| 71 | - public void setHasChildren(Boolean hasChildren) { | ||
| 72 | - this.hasChildren = hasChildren; | ||
| 73 | - } | ||
| 74 | -} |
src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.utils.node; | ||
| 2 | - | ||
| 3 | - | ||
| 4 | - | ||
| 5 | -/** | ||
| 6 | - * 森林节点类 | ||
| 7 | - * | ||
| 8 | - */ | ||
| 9 | -public class ForestNode extends BaseNode<ForestNode> { | ||
| 10 | - | ||
| 11 | - private static final long serialVersionUID = 1L; | ||
| 12 | - | ||
| 13 | - /** | ||
| 14 | - * 节点内容 | ||
| 15 | - */ | ||
| 16 | - private Object content; | ||
| 17 | - | ||
| 18 | - public ForestNode(String id, String parentId, Object content) { | ||
| 19 | - this.channelId = id; | ||
| 20 | - this.parentId = parentId; | ||
| 21 | - this.content = content; | ||
| 22 | - } | ||
| 23 | - | ||
| 24 | - public Object getContent() { | ||
| 25 | - return content; | ||
| 26 | - } | ||
| 27 | - | ||
| 28 | - public void setContent(Object content) { | ||
| 29 | - this.content = content; | ||
| 30 | - } | ||
| 31 | -} |
src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.utils.node; | ||
| 2 | - | ||
| 3 | -import com.google.common.collect.ImmutableMap; | ||
| 4 | -import com.google.common.collect.Maps; | ||
| 5 | - | ||
| 6 | -import java.util.ArrayList; | ||
| 7 | -import java.util.List; | ||
| 8 | -import java.util.Map; | ||
| 9 | - | ||
| 10 | -/** | ||
| 11 | - * 森林管理类 | ||
| 12 | - * | ||
| 13 | - * @author smallchill | ||
| 14 | - */ | ||
| 15 | -public class ForestNodeManager<T extends INode<T>> { | ||
| 16 | - | ||
| 17 | - /** | ||
| 18 | - * 森林的所有节点 | ||
| 19 | - */ | ||
| 20 | - private final ImmutableMap<String, T> nodeMap; | ||
| 21 | - | ||
| 22 | - /** | ||
| 23 | - * 森林的父节点ID | ||
| 24 | - */ | ||
| 25 | - private final Map<String, Object> parentIdMap = Maps.newHashMap(); | ||
| 26 | - | ||
| 27 | - public ForestNodeManager(List<T> nodes) { | ||
| 28 | - nodeMap = Maps.uniqueIndex(nodes, INode::getChannelId); | ||
| 29 | - } | ||
| 30 | - | ||
| 31 | - /** | ||
| 32 | - * 根据节点ID获取一个节点 | ||
| 33 | - * | ||
| 34 | - * @param id 节点ID | ||
| 35 | - * @return 对应的节点对象 | ||
| 36 | - */ | ||
| 37 | - public INode<T> getTreeNodeAt(String id) { | ||
| 38 | - if (nodeMap.containsKey(id)) { | ||
| 39 | - return nodeMap.get(id); | ||
| 40 | - } | ||
| 41 | - return null; | ||
| 42 | - } | ||
| 43 | - | ||
| 44 | - /** | ||
| 45 | - * 增加父节点ID | ||
| 46 | - * | ||
| 47 | - * @param parentId 父节点ID | ||
| 48 | - */ | ||
| 49 | - public void addParentId(String parentId) { | ||
| 50 | - parentIdMap.put(parentId, ""); | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - /** | ||
| 54 | - * 获取树的根节点(一个森林对应多颗树) | ||
| 55 | - * | ||
| 56 | - * @return 树的根节点集合 | ||
| 57 | - */ | ||
| 58 | - public List<T> getRoot() { | ||
| 59 | - List<T> roots = new ArrayList<>(); | ||
| 60 | - nodeMap.forEach((key, node) -> { | ||
| 61 | - if (node.getParentId() == null || parentIdMap.containsKey(node.getChannelId())) { | ||
| 62 | - roots.add(node); | ||
| 63 | - } | ||
| 64 | - }); | ||
| 65 | - return roots; | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | -} |
src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeMerger.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.utils.node; | ||
| 2 | - | ||
| 3 | -import com.genersoft.iot.vmp.utils.CollectionUtil; | ||
| 4 | - | ||
| 5 | -import java.util.List; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * 森林节点归并类 | ||
| 9 | - * | ||
| 10 | - */ | ||
| 11 | -public class ForestNodeMerger { | ||
| 12 | - | ||
| 13 | - /** | ||
| 14 | - * 将节点数组归并为一个森林(多棵树)(填充节点的children域) | ||
| 15 | - * 时间复杂度为O(n^2) | ||
| 16 | - * | ||
| 17 | - * @param items 节点域 | ||
| 18 | - * @return 多棵树的根节点集合 | ||
| 19 | - */ | ||
| 20 | - public static <T extends INode<T>> List<T> merge(List<T> items) { | ||
| 21 | - ForestNodeManager<T> forestNodeManager = new ForestNodeManager<>(items); | ||
| 22 | - items.forEach(forestNode -> { | ||
| 23 | - if (forestNode.getParentId() != null) { | ||
| 24 | - INode<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId()); | ||
| 25 | - if (node != null) { | ||
| 26 | - node.getChildren().add(forestNode); | ||
| 27 | - } else { | ||
| 28 | - forestNodeManager.addParentId(forestNode.getChannelId()); | ||
| 29 | - } | ||
| 30 | - } | ||
| 31 | - }); | ||
| 32 | - return forestNodeManager.getRoot(); | ||
| 33 | - } | ||
| 34 | - | ||
| 35 | - public static <T extends INode<T>> List<T> merge(List<T> items, String[] parentIds) { | ||
| 36 | - ForestNodeManager<T> forestNodeManager = new ForestNodeManager<>(items); | ||
| 37 | - items.forEach(forestNode -> { | ||
| 38 | - if (forestNode.getParentId() != null) { | ||
| 39 | - INode<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId()); | ||
| 40 | - if (CollectionUtil.contains(parentIds, forestNode.getChannelId())){ | ||
| 41 | - forestNodeManager.addParentId(forestNode.getChannelId()); | ||
| 42 | - } else { | ||
| 43 | - if (node != null){ | ||
| 44 | - node.getChildren().add(forestNode); | ||
| 45 | - } | ||
| 46 | - } | ||
| 47 | - } | ||
| 48 | - }); | ||
| 49 | - return forestNodeManager.getRoot(); | ||
| 50 | - } | ||
| 51 | -} |
src/main/java/com/genersoft/iot/vmp/utils/node/INode.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.utils.node; | ||
| 2 | - | ||
| 3 | -import java.io.Serializable; | ||
| 4 | -import java.util.List; | ||
| 5 | - | ||
| 6 | -/** | ||
| 7 | - * | ||
| 8 | - * 节点 | ||
| 9 | - */ | ||
| 10 | -public interface INode<T> extends Serializable { | ||
| 11 | - | ||
| 12 | - /** | ||
| 13 | - * 主键 | ||
| 14 | - * | ||
| 15 | - * @return String | ||
| 16 | - */ | ||
| 17 | - String getChannelId(); | ||
| 18 | - | ||
| 19 | - /** | ||
| 20 | - * 父主键 | ||
| 21 | - * | ||
| 22 | - * @return String | ||
| 23 | - */ | ||
| 24 | - String getParentId(); | ||
| 25 | - | ||
| 26 | - /** | ||
| 27 | - * 子孙节点 | ||
| 28 | - * | ||
| 29 | - * @return List<T> | ||
| 30 | - */ | ||
| 31 | - List<T> getChildren(); | ||
| 32 | - | ||
| 33 | - /** | ||
| 34 | - * 是否有子孙节点 | ||
| 35 | - * | ||
| 36 | - * @return Boolean | ||
| 37 | - */ | ||
| 38 | - default Boolean getHasChildren() { | ||
| 39 | - return false; | ||
| 40 | - } | ||
| 41 | - | ||
| 42 | -} |
src/main/java/com/genersoft/iot/vmp/utils/node/TreeNode.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.utils.node; | ||
| 2 | - | ||
| 3 | - | ||
| 4 | - | ||
| 5 | -/** | ||
| 6 | - * 树型节点类 | ||
| 7 | - * | ||
| 8 | - */ | ||
| 9 | -public class TreeNode extends BaseNode<TreeNode> { | ||
| 10 | - | ||
| 11 | - private static final long serialVersionUID = 1L; | ||
| 12 | - | ||
| 13 | - private String title; | ||
| 14 | - | ||
| 15 | - private String key; | ||
| 16 | - | ||
| 17 | - private String value; | ||
| 18 | - | ||
| 19 | - public String getTitle() { | ||
| 20 | - return title; | ||
| 21 | - } | ||
| 22 | - | ||
| 23 | - public void setTitle(String title) { | ||
| 24 | - this.title = title; | ||
| 25 | - } | ||
| 26 | - | ||
| 27 | - public String getKey() { | ||
| 28 | - return key; | ||
| 29 | - } | ||
| 30 | - | ||
| 31 | - public void setKey(String key) { | ||
| 32 | - this.key = key; | ||
| 33 | - } | ||
| 34 | - | ||
| 35 | - public String getValue() { | ||
| 36 | - return value; | ||
| 37 | - } | ||
| 38 | - | ||
| 39 | - public void setValue(String value) { | ||
| 40 | - this.value = value; | ||
| 41 | - } | ||
| 42 | -} |
src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTree.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.vmanager.bean; | ||
| 2 | - | ||
| 3 | -import com.fasterxml.jackson.annotation.JsonInclude; | ||
| 4 | -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | ||
| 5 | -import com.genersoft.iot.vmp.utils.node.INode; | ||
| 6 | -import io.swagger.annotations.ApiModel; | ||
| 7 | - | ||
| 8 | -import java.util.ArrayList; | ||
| 9 | -import java.util.List; | ||
| 10 | - | ||
| 11 | -@ApiModel(value = "DeviceChannelTree对象", description = "DeviceChannelTree对象") | ||
| 12 | -public class DeviceChannelTree extends DeviceChannel implements INode<DeviceChannelTree> { | ||
| 13 | - private static final long serialVersionUID = 1L; | ||
| 14 | - | ||
| 15 | - /** | ||
| 16 | - * 主键ID | ||
| 17 | - */ | ||
| 18 | - private int id; | ||
| 19 | - | ||
| 20 | - /** | ||
| 21 | - * 父节点ID | ||
| 22 | - */ | ||
| 23 | - private String parentId; | ||
| 24 | - | ||
| 25 | - private String parentName; | ||
| 26 | - | ||
| 27 | - private String title; | ||
| 28 | - | ||
| 29 | - private String key; | ||
| 30 | - | ||
| 31 | - private String value; | ||
| 32 | - | ||
| 33 | - /** | ||
| 34 | - * 子孙节点 | ||
| 35 | - */ | ||
| 36 | - @JsonInclude(JsonInclude.Include.NON_EMPTY) | ||
| 37 | - private List<DeviceChannelTree> children; | ||
| 38 | - | ||
| 39 | - /** | ||
| 40 | - * 是否有子孙节点 | ||
| 41 | - */ | ||
| 42 | - @JsonInclude(JsonInclude.Include.NON_EMPTY) | ||
| 43 | - private Boolean hasChildren; | ||
| 44 | - | ||
| 45 | - @Override | ||
| 46 | - public List<DeviceChannelTree> getChildren() { | ||
| 47 | - if (this.children == null) { | ||
| 48 | - this.children = new ArrayList<>(); | ||
| 49 | - } | ||
| 50 | - return this.children; | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - @Override | ||
| 54 | - public Boolean getHasChildren() { | ||
| 55 | - if (children.size() > 0) { | ||
| 56 | - return true; | ||
| 57 | - } else { | ||
| 58 | - return this.hasChildren; | ||
| 59 | - } | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - @Override | ||
| 63 | - public int getId() { | ||
| 64 | - return id; | ||
| 65 | - } | ||
| 66 | - | ||
| 67 | - @Override | ||
| 68 | - public void setId(int id) { | ||
| 69 | - this.id = id; | ||
| 70 | - } | ||
| 71 | - | ||
| 72 | - @Override | ||
| 73 | - public String getParentId() { | ||
| 74 | - return parentId; | ||
| 75 | - } | ||
| 76 | - | ||
| 77 | - @Override | ||
| 78 | - public void setParentId(String parentId) { | ||
| 79 | - this.parentId = parentId; | ||
| 80 | - } | ||
| 81 | - | ||
| 82 | - public String getParentName() { | ||
| 83 | - return parentName; | ||
| 84 | - } | ||
| 85 | - | ||
| 86 | - public void setParentName(String parentName) { | ||
| 87 | - this.parentName = parentName; | ||
| 88 | - } | ||
| 89 | - | ||
| 90 | - public String getTitle() { | ||
| 91 | - return title; | ||
| 92 | - } | ||
| 93 | - | ||
| 94 | - public void setTitle(String title) { | ||
| 95 | - this.title = title; | ||
| 96 | - } | ||
| 97 | - | ||
| 98 | - public String getKey() { | ||
| 99 | - return key; | ||
| 100 | - } | ||
| 101 | - | ||
| 102 | - public void setKey(String key) { | ||
| 103 | - this.key = key; | ||
| 104 | - } | ||
| 105 | - | ||
| 106 | - public String getValue() { | ||
| 107 | - return value; | ||
| 108 | - } | ||
| 109 | - | ||
| 110 | - public void setValue(String value) { | ||
| 111 | - this.value = value; | ||
| 112 | - } | ||
| 113 | - | ||
| 114 | - public void setChildren(List<DeviceChannelTree> children) { | ||
| 115 | - this.children = children; | ||
| 116 | - } | ||
| 117 | - | ||
| 118 | - public void setHasChildren(Boolean hasChildren) { | ||
| 119 | - this.hasChildren = hasChildren; | ||
| 120 | - } | ||
| 121 | -} |
src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTreeNode.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.vmanager.bean; | ||
| 2 | - | ||
| 3 | -import com.genersoft.iot.vmp.utils.node.TreeNode; | ||
| 4 | - | ||
| 5 | -public class DeviceChannelTreeNode extends TreeNode { | ||
| 6 | - | ||
| 7 | - private Integer status; | ||
| 8 | - | ||
| 9 | - private String deviceId; | ||
| 10 | - | ||
| 11 | - private String channelId; | ||
| 12 | - | ||
| 13 | - private Double lng; | ||
| 14 | - | ||
| 15 | - private Double lat; | ||
| 16 | - | ||
| 17 | - public Integer getStatus() { | ||
| 18 | - return status; | ||
| 19 | - } | ||
| 20 | - | ||
| 21 | - public void setStatus(Integer status) { | ||
| 22 | - this.status = status; | ||
| 23 | - } | ||
| 24 | - | ||
| 25 | - public String getDeviceId() { | ||
| 26 | - return deviceId; | ||
| 27 | - } | ||
| 28 | - | ||
| 29 | - public void setDeviceId(String deviceId) { | ||
| 30 | - this.deviceId = deviceId; | ||
| 31 | - } | ||
| 32 | - | ||
| 33 | - public String getChannelId() { | ||
| 34 | - return channelId; | ||
| 35 | - } | ||
| 36 | - | ||
| 37 | - public void setChannelId(String channelId) { | ||
| 38 | - this.channelId = channelId; | ||
| 39 | - } | ||
| 40 | - | ||
| 41 | - public Double getLng() { | ||
| 42 | - return lng; | ||
| 43 | - } | ||
| 44 | - | ||
| 45 | - public void setLng(Double lng) { | ||
| 46 | - this.lng = lng; | ||
| 47 | - } | ||
| 48 | - | ||
| 49 | - public Double getLat() { | ||
| 50 | - return lat; | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - public void setLat(Double lat) { | ||
| 54 | - this.lat = lat; | ||
| 55 | - } | ||
| 56 | -} |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
| @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | ||
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 10 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 11 | import com.genersoft.iot.vmp.service.IDeviceService; | 11 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 12 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 12 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 13 | +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | ||
| 13 | import com.github.pagehelper.util.StringUtil; | 14 | import com.github.pagehelper.util.StringUtil; |
| 14 | 15 | ||
| 15 | import io.swagger.annotations.Api; | 16 | import io.swagger.annotations.Api; |
| @@ -65,10 +66,11 @@ public class MobilePositionController { | @@ -65,10 +66,11 @@ public class MobilePositionController { | ||
| 65 | @ApiImplicitParam(name = "start", value = "开始时间", required = true, dataTypeClass = String.class), | 66 | @ApiImplicitParam(name = "start", value = "开始时间", required = true, dataTypeClass = String.class), |
| 66 | @ApiImplicitParam(name = "end", value = "结束时间", required = true, dataTypeClass = String.class), | 67 | @ApiImplicitParam(name = "end", value = "结束时间", required = true, dataTypeClass = String.class), |
| 67 | }) | 68 | }) |
| 68 | - @GetMapping("/history/{deviceId}") | ||
| 69 | - public ResponseEntity<List<MobilePosition>> positions(@PathVariable String deviceId, | ||
| 70 | - @RequestParam(required = false) String start, | ||
| 71 | - @RequestParam(required = false) String end) { | 69 | + @GetMapping("/history/{deviceId}/{channelId}") |
| 70 | + public ResponseEntity<WVPResult<List<MobilePosition>>> positions(@PathVariable String deviceId, | ||
| 71 | + @PathVariable String channelId, | ||
| 72 | + @RequestParam(required = false) String start, | ||
| 73 | + @RequestParam(required = false) String end) { | ||
| 72 | // if (logger.isDebugEnabled()) { | 74 | // if (logger.isDebugEnabled()) { |
| 73 | // logger.debug("查询设备" + deviceId + "的历史轨迹"); | 75 | // logger.debug("查询设备" + deviceId + "的历史轨迹"); |
| 74 | // } | 76 | // } |
| @@ -79,9 +81,11 @@ public class MobilePositionController { | @@ -79,9 +81,11 @@ public class MobilePositionController { | ||
| 79 | if (StringUtil.isEmpty(end)) { | 81 | if (StringUtil.isEmpty(end)) { |
| 80 | end = null; | 82 | end = null; |
| 81 | } | 83 | } |
| 82 | - | ||
| 83 | - List<MobilePosition> result = storager.queryMobilePositions(deviceId, start, end); | ||
| 84 | - return new ResponseEntity<>(result, HttpStatus.OK); | 84 | + WVPResult<List<MobilePosition>> wvpResult = new WVPResult<>(); |
| 85 | + wvpResult.setCode(0); | ||
| 86 | + List<MobilePosition> result = storager.queryMobilePositions(deviceId, channelId, start, end); | ||
| 87 | + wvpResult.setData(result); | ||
| 88 | + return new ResponseEntity<>(wvpResult, HttpStatus.OK); | ||
| 85 | } | 89 | } |
| 86 | 90 | ||
| 87 | /** | 91 | /** |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
| @@ -9,7 +9,6 @@ import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; | @@ -9,7 +9,6 @@ import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; | ||
| 9 | import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; | 9 | import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector; |
| 10 | import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; | 10 | import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; |
| 11 | import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; | 11 | import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; |
| 12 | -import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask; | ||
| 13 | import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; | 12 | import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; |
| 14 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 15 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 14 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| @@ -17,14 +16,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | @@ -17,14 +16,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 17 | import com.genersoft.iot.vmp.service.IDeviceService; | 16 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 18 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 17 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 19 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 18 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 20 | -import com.genersoft.iot.vmp.vmanager.bean.DeviceChannelTree; | ||
| 21 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | 19 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| 22 | import com.github.pagehelper.PageInfo; | 20 | import com.github.pagehelper.PageInfo; |
| 23 | import io.swagger.annotations.Api; | 21 | import io.swagger.annotations.Api; |
| 24 | import io.swagger.annotations.ApiImplicitParam; | 22 | import io.swagger.annotations.ApiImplicitParam; |
| 25 | import io.swagger.annotations.ApiImplicitParams; | 23 | import io.swagger.annotations.ApiImplicitParams; |
| 26 | import io.swagger.annotations.ApiOperation; | 24 | import io.swagger.annotations.ApiOperation; |
| 27 | -import org.kxml2.wap.wv.WV; | ||
| 28 | import org.slf4j.Logger; | 25 | import org.slf4j.Logger; |
| 29 | import org.slf4j.LoggerFactory; | 26 | import org.slf4j.LoggerFactory; |
| 30 | import org.springframework.beans.factory.annotation.Autowired; | 27 | import org.springframework.beans.factory.annotation.Autowired; |
| @@ -450,11 +447,6 @@ public class DeviceQuery { | @@ -450,11 +447,6 @@ public class DeviceQuery { | ||
| 450 | return result; | 447 | return result; |
| 451 | } | 448 | } |
| 452 | 449 | ||
| 453 | - @GetMapping("/{deviceId}/tree") | ||
| 454 | - @ApiOperation(value = "通道树形结构", notes = "通道树形结构") | ||
| 455 | - public WVPResult<List<DeviceChannelTree>> tree(@PathVariable String deviceId) { | ||
| 456 | - return WVPResult.Data(storager.tree(deviceId)); | ||
| 457 | - } | ||
| 458 | 450 | ||
| 459 | @GetMapping("/{deviceId}/sync_status") | 451 | @GetMapping("/{deviceId}/sync_status") |
| 460 | @ApiOperation(value = "获取通道同步进度", notes = "获取通道同步进度") | 452 | @ApiOperation(value = "获取通道同步进度", notes = "获取通道同步进度") |
web_src/index.html
web_src/package-lock.json
| @@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
| 16 | "moment": "^2.29.1", | 16 | "moment": "^2.29.1", |
| 17 | "ol": "^6.14.1", | 17 | "ol": "^6.14.1", |
| 18 | "postcss-pxtorem": "^5.1.1", | 18 | "postcss-pxtorem": "^5.1.1", |
| 19 | + "uuid": "^8.3.2", | ||
| 19 | "vue": "^2.6.11", | 20 | "vue": "^2.6.11", |
| 20 | "vue-clipboard2": "^0.3.1", | 21 | "vue-clipboard2": "^0.3.1", |
| 21 | "vue-clipboards": "^1.3.0", | 22 | "vue-clipboards": "^1.3.0", |
| @@ -11880,6 +11881,16 @@ | @@ -11880,6 +11881,16 @@ | ||
| 11880 | "node": ">=0.8.0" | 11881 | "node": ">=0.8.0" |
| 11881 | } | 11882 | } |
| 11882 | }, | 11883 | }, |
| 11884 | + "node_modules/sockjs/node_modules/uuid": { | ||
| 11885 | + "version": "3.4.0", | ||
| 11886 | + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz", | ||
| 11887 | + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", | ||
| 11888 | + "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.", | ||
| 11889 | + "dev": true, | ||
| 11890 | + "bin": { | ||
| 11891 | + "uuid": "bin/uuid" | ||
| 11892 | + } | ||
| 11893 | + }, | ||
| 11883 | "node_modules/sort-asc": { | 11894 | "node_modules/sort-asc": { |
| 11884 | "version": "0.1.0", | 11895 | "version": "0.1.0", |
| 11885 | "resolved": "https://registry.npmmirror.com/sort-asc/-/sort-asc-0.1.0.tgz", | 11896 | "resolved": "https://registry.npmmirror.com/sort-asc/-/sort-asc-0.1.0.tgz", |
| @@ -12978,13 +12989,11 @@ | @@ -12978,13 +12989,11 @@ | ||
| 12978 | } | 12989 | } |
| 12979 | }, | 12990 | }, |
| 12980 | "node_modules/uuid": { | 12991 | "node_modules/uuid": { |
| 12981 | - "version": "3.4.0", | ||
| 12982 | - "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", | ||
| 12983 | - "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=", | ||
| 12984 | - "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.", | ||
| 12985 | - "dev": true, | 12992 | + "version": "8.3.2", |
| 12993 | + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", | ||
| 12994 | + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", | ||
| 12986 | "bin": { | 12995 | "bin": { |
| 12987 | - "uuid": "bin/uuid" | 12996 | + "uuid": "dist/bin/uuid" |
| 12988 | } | 12997 | } |
| 12989 | }, | 12998 | }, |
| 12990 | "node_modules/validate-npm-package-license": { | 12999 | "node_modules/validate-npm-package-license": { |
| @@ -24308,6 +24317,14 @@ | @@ -24308,6 +24317,14 @@ | ||
| 24308 | "requires": { | 24317 | "requires": { |
| 24309 | "faye-websocket": "^0.10.0", | 24318 | "faye-websocket": "^0.10.0", |
| 24310 | "uuid": "^3.0.1" | 24319 | "uuid": "^3.0.1" |
| 24320 | + }, | ||
| 24321 | + "dependencies": { | ||
| 24322 | + "uuid": { | ||
| 24323 | + "version": "3.4.0", | ||
| 24324 | + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz", | ||
| 24325 | + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", | ||
| 24326 | + "dev": true | ||
| 24327 | + } | ||
| 24311 | } | 24328 | } |
| 24312 | }, | 24329 | }, |
| 24313 | "sockjs-client": { | 24330 | "sockjs-client": { |
| @@ -25260,10 +25277,9 @@ | @@ -25260,10 +25277,9 @@ | ||
| 25260 | "dev": true | 25277 | "dev": true |
| 25261 | }, | 25278 | }, |
| 25262 | "uuid": { | 25279 | "uuid": { |
| 25263 | - "version": "3.4.0", | ||
| 25264 | - "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", | ||
| 25265 | - "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=", | ||
| 25266 | - "dev": true | 25280 | + "version": "8.3.2", |
| 25281 | + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", | ||
| 25282 | + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" | ||
| 25267 | }, | 25283 | }, |
| 25268 | "validate-npm-package-license": { | 25284 | "validate-npm-package-license": { |
| 25269 | "version": "3.0.4", | 25285 | "version": "3.0.4", |
web_src/package.json
| @@ -18,6 +18,7 @@ | @@ -18,6 +18,7 @@ | ||
| 18 | "moment": "^2.29.1", | 18 | "moment": "^2.29.1", |
| 19 | "ol": "^6.14.1", | 19 | "ol": "^6.14.1", |
| 20 | "postcss-pxtorem": "^5.1.1", | 20 | "postcss-pxtorem": "^5.1.1", |
| 21 | + "uuid": "^8.3.2", | ||
| 21 | "vue": "^2.6.11", | 22 | "vue": "^2.6.11", |
| 22 | "vue-clipboard2": "^0.3.1", | 23 | "vue-clipboard2": "^0.3.1", |
| 23 | "vue-clipboards": "^1.3.0", | 24 | "vue-clipboards": "^1.3.0", |
web_src/src/api/deviceApi.js deleted
100644 → 0
| 1 | -import axios from 'axios'; | ||
| 2 | - | ||
| 3 | -export const tree = (deviceId) => { | ||
| 4 | - return axios({ | ||
| 5 | - url: `/api/device/query/${deviceId}/tree`, | ||
| 6 | - method: 'get' | ||
| 7 | - }) | ||
| 8 | -} | ||
| 9 | - | ||
| 10 | -export const deviceList = (page, count) => { | ||
| 11 | - return axios({ | ||
| 12 | - method: 'get', | ||
| 13 | - url:`/api/device/query/devices`, | ||
| 14 | - params: { | ||
| 15 | - page, | ||
| 16 | - count | ||
| 17 | - } | ||
| 18 | - }) | ||
| 19 | -} | ||
| 20 | \ No newline at end of file | 0 | \ No newline at end of file |
web_src/src/components/DeviceList.vue
| @@ -194,7 +194,7 @@ export default { | @@ -194,7 +194,7 @@ export default { | ||
| 194 | this.$router.push(`/channelList/${row.deviceId}/0/15/1`); | 194 | this.$router.push(`/channelList/${row.deviceId}/0/15/1`); |
| 195 | }, | 195 | }, |
| 196 | showDevicePosition: function (row) { | 196 | showDevicePosition: function (row) { |
| 197 | - this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); | 197 | + this.$router.push(`/map?deviceId=${row.deviceId}`); |
| 198 | }, | 198 | }, |
| 199 | 199 | ||
| 200 | //gb28181平台对接 | 200 | //gb28181平台对接 |
web_src/src/components/channelTree.vue deleted
100644 → 0
| 1 | -<template> | ||
| 2 | - <div> | ||
| 3 | - <el-tree :data="channelList" :props="props" @node-click="sendDevicePush"> | ||
| 4 | - <span slot-scope="{ node }"> | ||
| 5 | - <span v-if="node.isLeaf"> | ||
| 6 | - <i class="el-icon-video-camera" :style="{color:node.disabled==1?'#67C23A':'#F56C6C'}"></i> | ||
| 7 | - </span> | ||
| 8 | - <span v-else> | ||
| 9 | - <i class="el-icon-folder"></i> | ||
| 10 | - </span> | ||
| 11 | - <span> | ||
| 12 | - {{ node.label }} | ||
| 13 | - </span> | ||
| 14 | - </span> | ||
| 15 | - </el-tree> | ||
| 16 | - </div> | ||
| 17 | -</template> | ||
| 18 | -<script> | ||
| 19 | -import ChannelTreeItem from "@/components/channelTreeItem" | ||
| 20 | -import {tree} from '@/api/deviceApi' | ||
| 21 | - | ||
| 22 | -export default { | ||
| 23 | - components: { | ||
| 24 | - ChannelTreeItem, | ||
| 25 | - }, | ||
| 26 | - props:{ | ||
| 27 | - device: { | ||
| 28 | - type: Object, | ||
| 29 | - required: true | ||
| 30 | - } | ||
| 31 | - }, | ||
| 32 | - data() { | ||
| 33 | - return { | ||
| 34 | - loading: false, | ||
| 35 | - channelList: [], | ||
| 36 | - props: { | ||
| 37 | - label: 'title', | ||
| 38 | - children: 'children', | ||
| 39 | - isLeaf: 'hasChildren', | ||
| 40 | - disabled: 'status' | ||
| 41 | - }, | ||
| 42 | - } | ||
| 43 | - }, | ||
| 44 | - computed: { | ||
| 45 | - | ||
| 46 | - }, | ||
| 47 | - mounted() { | ||
| 48 | - this.leafs = [] | ||
| 49 | - this.getTree() | ||
| 50 | - }, | ||
| 51 | - methods: { | ||
| 52 | - getTree() { | ||
| 53 | - this.loading = true | ||
| 54 | - var that = this | ||
| 55 | - tree(this.device.deviceId).then(function (res) { | ||
| 56 | - console.log(res.data.data); | ||
| 57 | - that.channelList = res.data.data; | ||
| 58 | - that.loading = false; | ||
| 59 | - }).catch(function (error) { | ||
| 60 | - console.log(error); | ||
| 61 | - that.loading = false; | ||
| 62 | - }); | ||
| 63 | - }, | ||
| 64 | - sendDevicePush(c) { | ||
| 65 | - if(c.hasChildren) return | ||
| 66 | - this.$emit('sendDevicePush',c) | ||
| 67 | - } | ||
| 68 | - } | ||
| 69 | -} | ||
| 70 | -</script> | ||
| 71 | \ No newline at end of file | 0 | \ No newline at end of file |
web_src/src/components/channelTreeItem.vue deleted
100644 → 0
| 1 | -<template> | ||
| 2 | - <div> | ||
| 3 | - <!-- <div :index="item.key" v-for="(item,i) in list" :key="i+'-'"> | ||
| 4 | - <el-submenu v-if="item.hasChildren"> | ||
| 5 | - <template slot="title"> | ||
| 6 | - <i class="el-icon-video-camera"></i> | ||
| 7 | - <span slot="title">{{item.title || item.deviceId}}</span> | ||
| 8 | - </template> | ||
| 9 | - <channel-list :list="item.children" @sendDevicePush="sendDevicePush"></channel-list> | ||
| 10 | - </el-submenu> | ||
| 11 | - <el-menu-item v-else :index="item.key" @click="sendDevicePush(item)"> | ||
| 12 | - <template slot="title" > | ||
| 13 | - <i class="el-icon-switch-button" :style="{color:item.status==1?'#67C23A':'#F56C6C'}"></i> | ||
| 14 | - <span slot="title">{{item.title}}</span> | ||
| 15 | - </template> | ||
| 16 | - </el-menu-item> | ||
| 17 | - </div> --> | ||
| 18 | - <div > | ||
| 19 | - <template v-if="!item.hasChildren"> | ||
| 20 | - <el-menu-item :index="item.key" @click="sendDevicePush(item)"> | ||
| 21 | - <i class="el-icon-video-camera" :style="{color:item.status==1?'#67C23A':'#F56C6C'}"></i> | ||
| 22 | - {{item.title}} | ||
| 23 | - </el-menu-item> | ||
| 24 | - </template> | ||
| 25 | - | ||
| 26 | - <el-submenu v-else :index="item.key"> | ||
| 27 | - <template slot="title" > | ||
| 28 | - <i class="el-icon-location-outline"></i> | ||
| 29 | - {{item.title}} | ||
| 30 | - </template> | ||
| 31 | - | ||
| 32 | - <template v-for="child in item.children"> | ||
| 33 | - <channel-item | ||
| 34 | - v-if="child.hasChildren" | ||
| 35 | - :item="child" | ||
| 36 | - :key="child.key" | ||
| 37 | - @sendDevicePush="sendDevicePush"/> | ||
| 38 | - <el-menu-item v-else :key="child.key" :index="child.key" @click="sendDevicePush(child)"> | ||
| 39 | - <i class="el-icon-video-camera" :style="{color:child.status==1?'#67C23A':'#F56C6C'}"></i> | ||
| 40 | - {{child.title}} | ||
| 41 | - </el-menu-item> | ||
| 42 | - </template> | ||
| 43 | - </el-submenu> | ||
| 44 | - </div> | ||
| 45 | - </div> | ||
| 46 | -</template> | ||
| 47 | -<script> | ||
| 48 | -export default { | ||
| 49 | - name:'ChannelItem', | ||
| 50 | - props:{ | ||
| 51 | - list:Array, | ||
| 52 | - channelId: String, | ||
| 53 | - item: { | ||
| 54 | - type: Object, | ||
| 55 | - required: true | ||
| 56 | - } | ||
| 57 | - }, | ||
| 58 | - data () { | ||
| 59 | - return { | ||
| 60 | - | ||
| 61 | - } | ||
| 62 | - }, | ||
| 63 | - watch: { | ||
| 64 | - channelId(val) { | ||
| 65 | - console.log(val); | ||
| 66 | - } | ||
| 67 | - }, | ||
| 68 | - methods: { | ||
| 69 | - sendDevicePush(c) { | ||
| 70 | - this.$emit('sendDevicePush',c) | ||
| 71 | - } | ||
| 72 | - } | ||
| 73 | -} | ||
| 74 | -</script> |
web_src/src/components/common/DeviceTree.vue
| 1 | <template> | 1 | <template> |
| 2 | - <div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF"> | 2 | + <div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF; overflow: auto"> |
| 3 | <el-container> | 3 | <el-container> |
| 4 | <el-header>设备列表</el-header> | 4 | <el-header>设备列表</el-header> |
| 5 | <el-main style="background-color: #ffffff;"> | 5 | <el-main style="background-color: #ffffff;"> |
| 6 | <div class="device-tree-main-box"> | 6 | <div class="device-tree-main-box"> |
| 7 | - <el-tree :props="defaultProps" :load="loadNode" lazy @node-click="handleNodeClick"@node-contextmenu="handleContextMenu"> | 7 | + <el-tree :props="defaultProps" :load="loadNode" lazy @node-click="handleNodeClick"@node-contextmenu="handleContextMenu" style="min-width: 100%; display:inline-block !important;"> |
| 8 | <span class="custom-tree-node" slot-scope="{ node, data }" style="width: 100%"> | 8 | <span class="custom-tree-node" slot-scope="{ node, data }" style="width: 100%"> |
| 9 | <span v-if="node.data.type === 0 && node.data.online" title="在线设备" class="device-online iconfont icon-jiedianleizhukongzhongxin2"></span> | 9 | <span v-if="node.data.type === 0 && node.data.online" title="在线设备" class="device-online iconfont icon-jiedianleizhukongzhongxin2"></span> |
| 10 | <span v-if="node.data.type === 0 && !node.data.online " title="离线设备" class="device-offline iconfont icon-jiedianleizhukongzhongxin2"></span> | 10 | <span v-if="node.data.type === 0 && !node.data.online " title="离线设备" class="device-offline iconfont icon-jiedianleizhukongzhongxin2"></span> |
| @@ -49,16 +49,17 @@ export default { | @@ -49,16 +49,17 @@ export default { | ||
| 49 | }, | 49 | }, |
| 50 | props: ['clickEvent', 'contextMenuEvent'], | 50 | props: ['clickEvent', 'contextMenuEvent'], |
| 51 | methods: { | 51 | methods: { |
| 52 | - handleNodeClick(data) { | 52 | + handleNodeClick(data,node,element) { |
| 53 | console.log("点击事件") | 53 | console.log("点击事件") |
| 54 | + console.log(data) | ||
| 54 | if(typeof (this.clickEvent) == "function") { | 55 | if(typeof (this.clickEvent) == "function") { |
| 55 | this.clickEvent(data.userData) | 56 | this.clickEvent(data.userData) |
| 56 | } | 57 | } |
| 57 | }, | 58 | }, |
| 58 | - handleContextMenu(data) { | 59 | + handleContextMenu(event,data,node,element) { |
| 59 | console.log("右键点击事件") | 60 | console.log("右键点击事件") |
| 60 | if(typeof (this.contextMenuEvent) == "function") { | 61 | if(typeof (this.contextMenuEvent) == "function") { |
| 61 | - this.contextMenuEvent(data.userData) | 62 | + this.contextMenuEvent(event, data.userData) |
| 62 | } | 63 | } |
| 63 | }, | 64 | }, |
| 64 | loadNode: function(node, resolve){ | 65 | loadNode: function(node, resolve){ |
web_src/src/components/common/MapComponent.vue
| 1 | <template> | 1 | <template> |
| 2 | - <div id="mapContainer" style="width: 100%;height: 100%;"></div> | 2 | + <div id="mapContainer" ref="mapContainer" style="width: 100%;height: 100%;"></div> |
| 3 | </template> | 3 | </template> |
| 4 | 4 | ||
| 5 | <script> | 5 | <script> |
| @@ -7,10 +7,20 @@ import 'ol/ol.css'; | @@ -7,10 +7,20 @@ import 'ol/ol.css'; | ||
| 7 | import Map from 'ol/Map'; | 7 | import Map from 'ol/Map'; |
| 8 | import OSM from 'ol/source/OSM'; | 8 | import OSM from 'ol/source/OSM'; |
| 9 | import XYZ from 'ol/source/XYZ'; | 9 | import XYZ from 'ol/source/XYZ'; |
| 10 | -import TileLayer from 'ol/layer/Tile'; | 10 | +import VectorSource from 'ol/source/Vector'; |
| 11 | +import Tile from 'ol/layer/Tile'; | ||
| 12 | +import VectorLayer from 'ol/layer/Vector'; | ||
| 13 | +import Style from 'ol/style/Style'; | ||
| 14 | +import Icon from 'ol/style/Icon'; | ||
| 11 | import View from 'ol/View'; | 15 | import View from 'ol/View'; |
| 16 | +import Feature from 'ol/Feature'; | ||
| 17 | +import Overlay from 'ol/Overlay'; | ||
| 18 | +import {Point, LineString} from 'ol/geom'; | ||
| 12 | import {get as getProj, fromLonLat} from 'ol/proj'; | 19 | import {get as getProj, fromLonLat} from 'ol/proj'; |
| 13 | import {ZoomSlider, Zoom} from 'ol/control'; | 20 | import {ZoomSlider, Zoom} from 'ol/control'; |
| 21 | +import {containsCoordinate} from 'ol/extent'; | ||
| 22 | + | ||
| 23 | +import {v4} from 'uuid' | ||
| 14 | 24 | ||
| 15 | let olMap = null; | 25 | let olMap = null; |
| 16 | 26 | ||
| @@ -24,7 +34,9 @@ export default { | @@ -24,7 +34,9 @@ export default { | ||
| 24 | }, | 34 | }, |
| 25 | created(){ | 35 | created(){ |
| 26 | this.$nextTick(() => { | 36 | this.$nextTick(() => { |
| 27 | - this.init(); | 37 | + setTimeout(()=>{ |
| 38 | + this.init() | ||
| 39 | + }, 100) | ||
| 28 | }) | 40 | }) |
| 29 | 41 | ||
| 30 | }, | 42 | }, |
| @@ -48,7 +60,7 @@ export default { | @@ -48,7 +60,7 @@ export default { | ||
| 48 | }); | 60 | }); |
| 49 | let tileLayer = null; | 61 | let tileLayer = null; |
| 50 | if (mapParam.tilesUrl) { | 62 | if (mapParam.tilesUrl) { |
| 51 | - tileLayer = new TileLayer({ | 63 | + tileLayer = new Tile({ |
| 52 | source: new XYZ({ | 64 | source: new XYZ({ |
| 53 | projection: getProj("EPSG:3857"), | 65 | projection: getProj("EPSG:3857"), |
| 54 | wrapX: false, | 66 | wrapX: false, |
| @@ -57,13 +69,13 @@ export default { | @@ -57,13 +69,13 @@ export default { | ||
| 57 | }) | 69 | }) |
| 58 | }) | 70 | }) |
| 59 | }else { | 71 | }else { |
| 60 | - tileLayer = new TileLayer({ | 72 | + tileLayer = new Tile({ |
| 61 | preload: 4, | 73 | preload: 4, |
| 62 | source: new OSM(), | 74 | source: new OSM(), |
| 63 | }) | 75 | }) |
| 64 | } | 76 | } |
| 65 | olMap = new Map({ | 77 | olMap = new Map({ |
| 66 | - target: "mapContainer", // 容器ID | 78 | + target: this.$refs.mapContainer, // 容器ID |
| 67 | layers: [tileLayer], // 默认图层 | 79 | layers: [tileLayer], // 默认图层 |
| 68 | view: view, // 视图 | 80 | view: view, // 视图 |
| 69 | controls:[ // 控件 | 81 | controls:[ // 控件 |
| @@ -71,6 +83,7 @@ export default { | @@ -71,6 +83,7 @@ export default { | ||
| 71 | new Zoom(), | 83 | new Zoom(), |
| 72 | ] , | 84 | ] , |
| 73 | }) | 85 | }) |
| 86 | + console.log(3222) | ||
| 74 | }, | 87 | }, |
| 75 | setCenter(point){ | 88 | setCenter(point){ |
| 76 | 89 | ||
| @@ -82,26 +95,151 @@ export default { | @@ -82,26 +95,151 @@ export default { | ||
| 82 | 95 | ||
| 83 | }, | 96 | }, |
| 84 | centerAndZoom(point,zoom,callback){ | 97 | centerAndZoom(point,zoom,callback){ |
| 85 | - | 98 | + var zoom_ = olMap.getView().getZoom(); |
| 99 | + zoom = zoom|| zoom_; | ||
| 100 | + var duration = 600; | ||
| 101 | + olMap.getView().setCenter(fromLonLat(point)) | ||
| 102 | + olMap.getView().animate({ | ||
| 103 | + zoom: zoom , | ||
| 104 | + duration: duration | ||
| 105 | + }); | ||
| 86 | }, | 106 | }, |
| 87 | - panTo(point){ | 107 | + panTo(point, zoom){ |
| 108 | + let duration = 800; | ||
| 88 | 109 | ||
| 89 | - }, | ||
| 90 | - openInfoBox(){ | 110 | + olMap.getView().cancelAnimations() |
| 111 | + olMap.getView().animate({ | ||
| 112 | + center: fromLonLat(point), | ||
| 113 | + duration: duration | ||
| 114 | + }); | ||
| 115 | + if (!containsCoordinate(olMap.getView().calculateExtent(), fromLonLat(point))) { | ||
| 116 | + olMap.getView().animate({ | ||
| 117 | + zoom: olMap.getView().getZoom() - 1, | ||
| 118 | + duration: duration / 2 | ||
| 119 | + }, { | ||
| 120 | + zoom: zoom || olMap.getView().getZoom(), | ||
| 121 | + duration: duration / 2 | ||
| 122 | + }); | ||
| 123 | + } | ||
| 91 | 124 | ||
| 92 | }, | 125 | }, |
| 93 | - closeInfoBox(){ | 126 | + fit(layer){ |
| 127 | + let extent = layer.getSource().getExtent(); | ||
| 128 | + if (extent) { | ||
| 129 | + olMap.getView().fit(extent,{ | ||
| 130 | + duration : 600, | ||
| 131 | + padding: [100, 100, 100, 100] | ||
| 132 | + }); | ||
| 133 | + } | ||
| 94 | 134 | ||
| 95 | - }, | ||
| 96 | - addLayer(){ | ||
| 97 | 135 | ||
| 98 | }, | 136 | }, |
| 99 | - removeLayer(){ | 137 | + openInfoBox(position, content, offset){ |
| 138 | + let id = v4() | ||
| 139 | + // let infoBox = document.createElement("div"); | ||
| 140 | + // infoBox.innerHTML = content ; | ||
| 141 | + // infoBox.setAttribute("infoBoxId", id) | ||
| 142 | + let overlay = new Overlay({ | ||
| 143 | + id:id, | ||
| 144 | + autoPan:true, | ||
| 145 | + autoPanAnimation:{ | ||
| 146 | + duration: 250 | ||
| 147 | + }, | ||
| 148 | + element: content, | ||
| 149 | + positioning:"bottom-center", | ||
| 150 | + offset:offset, | ||
| 151 | + // className:overlayStyle.className | ||
| 152 | + }); | ||
| 153 | + olMap.addOverlay(overlay); | ||
| 154 | + overlay.setPosition(fromLonLat(position)); | ||
| 155 | + return id; | ||
| 156 | + }, | ||
| 157 | + closeInfoBox(id){ | ||
| 158 | + olMap.getOverlayById(id).setPosition(undefined) | ||
| 159 | + // olMap.removeOverlay(olMap.getOverlayById(id)) | ||
| 160 | + }, | ||
| 161 | + /** | ||
| 162 | + * 添加图层 | ||
| 163 | + * @param data | ||
| 164 | + * [ | ||
| 165 | + * { | ||
| 166 | + * | ||
| 167 | + * position: [119.1212,45,122], | ||
| 168 | + * image: { | ||
| 169 | + * src:"/images/123.png", | ||
| 170 | + * anchor: [0.5, 0.5] | ||
| 171 | + * | ||
| 172 | + * } | ||
| 173 | + * } | ||
| 174 | + * | ||
| 175 | + * ] | ||
| 176 | + */ | ||
| 177 | + addLayer(data, clickEvent){ | ||
| 178 | + let style = new Style(); | ||
| 179 | + if (data.length > 0) { | ||
| 180 | + let features = []; | ||
| 181 | + for (let i = 0; i < data.length; i++) { | ||
| 182 | + let feature = new Feature(new Point(fromLonLat(data[i].position))); | ||
| 183 | + feature.customData = data[i].data; | ||
| 184 | + let cloneStyle = style.clone() | ||
| 185 | + cloneStyle.setImage(new Icon({ | ||
| 186 | + anchor: data[i].image.anchor, | ||
| 187 | + crossOrigin: 'Anonymous', | ||
| 188 | + src: data[i].image.src, | ||
| 189 | + })) | ||
| 190 | + feature.setStyle(cloneStyle) | ||
| 191 | + features.push(feature); | ||
| 192 | + } | ||
| 193 | + let source = new VectorSource(); | ||
| 194 | + source.addFeatures(features); | ||
| 195 | + let vectorLayer = new VectorLayer({ | ||
| 196 | + source:source, | ||
| 197 | + style:style, | ||
| 198 | + renderMode:"image", | ||
| 199 | + declutter: false | ||
| 200 | + }) | ||
| 201 | + olMap.addLayer(vectorLayer) | ||
| 202 | + if (typeof clickEvent == "function") { | ||
| 203 | + olMap.on("click", (event)=>{ | ||
| 204 | + vectorLayer.getFeatures(event.pixel).then((features)=>{ | ||
| 205 | + if (features.length > 0) { | ||
| 206 | + let items = [] | ||
| 207 | + for (let i = 0; i < features.length; i++) { | ||
| 208 | + items.push(features[i].customData) | ||
| 209 | + } | ||
| 210 | + clickEvent(items) | ||
| 211 | + } | ||
| 212 | + }) | ||
| 100 | 213 | ||
| 101 | - } | ||
| 102 | 214 | ||
| 215 | + }) | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + return vectorLayer; | ||
| 219 | + } | ||
| 220 | + }, | ||
| 221 | + removeLayer(layer){ | ||
| 222 | + olMap.removeLayer(layer) | ||
| 223 | + }, | ||
| 103 | 224 | ||
| 225 | + addLineLayer(positions) { | ||
| 226 | + if (positions.length > 0) { | ||
| 227 | + let points = []; | ||
| 228 | + for (let i = 0; i < positions.length; i++) { | ||
| 229 | + points.push(fromLonLat(positions[i])); | ||
| 230 | + } | ||
| 231 | + let line = new LineString(points) | ||
| 232 | + let lineFeature = new Feature(line); | ||
| 104 | 233 | ||
| 234 | + let source = new VectorSource(); | ||
| 235 | + source.addFeature(lineFeature); | ||
| 236 | + let vectorLayer = new VectorLayer({ | ||
| 237 | + source: source, | ||
| 238 | + }) | ||
| 239 | + olMap.addLayer(vectorLayer) | ||
| 240 | + return vectorLayer; | ||
| 241 | + } | ||
| 242 | + } | ||
| 105 | }, | 243 | }, |
| 106 | destroyed() { | 244 | destroyed() { |
| 107 | // if (this.jessibuca) { | 245 | // if (this.jessibuca) { |
web_src/src/components/devicePosition.vue
| 1 | <template> | 1 | <template> |
| 2 | - <div id="devicePosition" style="height: 100%"> | ||
| 3 | - <el-container style="height: 100%"> | ||
| 4 | - <el-header> | ||
| 5 | - <uiHeader></uiHeader> | ||
| 6 | - </el-header> | ||
| 7 | - <el-container> | ||
| 8 | - <el-aside width="250px" height="100%" style="background-color: #FFFFFF; margin: 0 0 20px 20px;"> | ||
| 9 | - <div style=" padding-top: 10px"> | ||
| 10 | - <el-tree class="el-scrollbar" | ||
| 11 | - ref="tree" | ||
| 12 | - id="deviceTree" | ||
| 13 | - empty-text="未知节点" | ||
| 14 | - node-key="id" | ||
| 15 | - :highlight-current="false" | ||
| 16 | - :expand-on-click-node="false" | ||
| 17 | - :props="props" | ||
| 18 | - :load="loadNode" | ||
| 19 | - @node-contextmenu="contextmenuEventHandler" | ||
| 20 | - @node-click="nodeClickHandler" | ||
| 21 | - lazy> | ||
| 22 | - </el-tree> | ||
| 23 | - </div> | ||
| 24 | - | ||
| 25 | - </el-aside> | ||
| 26 | - <el-main> | ||
| 27 | - <MapComponent></MapComponent> | ||
| 28 | - </el-main> | ||
| 29 | - </el-container> | ||
| 30 | - </el-container> | 2 | + <div id="devicePosition" style="width: 100vw; height: 91vh;"> |
| 3 | + <el-container style="height: 91vh;" v-loading="isLoging"> | ||
| 4 | + <el-aside width="auto" style="background-color: #ffffff"> | ||
| 5 | + <DeviceTree ref="deviceTree" :clickEvent="clickEvent" :contextMenuEvent="contextmenuEventHandler" ></DeviceTree> | ||
| 6 | + </el-aside> | ||
| 7 | + <el-main style="height: 91vh; padding: 0"> | ||
| 8 | + <MapComponent ref="map"></MapComponent> | ||
| 9 | + </el-main> | ||
| 10 | + </el-container> | ||
| 11 | + <div ref="infobox" v-if="channel != null " > | ||
| 12 | + <div v-if="channel != null" class="infobox-content"> | ||
| 13 | + <el-descriptions class="margin-top" :title="channel.name" :column="1" :colon="true" size="mini" :labelStyle="labelStyle" > | ||
| 14 | + <el-descriptions-item label="生产厂商">{{channel.manufacture}}</el-descriptions-item> | ||
| 15 | + <el-descriptions-item label="型号">{{channel.model}}</el-descriptions-item> | ||
| 16 | + <el-descriptions-item label="设备归属" >{{channel.owner}}</el-descriptions-item> | ||
| 17 | + <el-descriptions-item label="行政区域" >{{channel.civilCode}}</el-descriptions-item> | ||
| 18 | + <el-descriptions-item label="安装地址" >{{channel.address == null?'未知': channel.address}}</el-descriptions-item> | ||
| 19 | + <el-descriptions-item label="云台类型" >{{channel.ptztypeText}}</el-descriptions-item> | ||
| 20 | + <el-descriptions-item label="经纬度" >{{channel.longitude}},{{channel.latitude}}</el-descriptions-item> | ||
| 21 | + <el-descriptions-item label="状态"> | ||
| 22 | + <el-tag size="small" v-if="channel.status === 1">在线</el-tag> | ||
| 23 | + <el-tag size="small" type="info" v-if="channel.status === 0">离线</el-tag> | ||
| 24 | + </el-descriptions-item> | ||
| 25 | + </el-descriptions> | ||
| 26 | + <div style="padding-top: 10px"> | ||
| 27 | + <el-button type="primary" size="small" title="播放" icon="el-icon-video-play" @click="play(channel)"></el-button> | ||
| 28 | + <el-button type="primary" size="small" title="编辑位置" icon="el-icon-edit" @click="edit(channel)"></el-button> | ||
| 29 | + <el-button type="primary" size="small" title="轨迹查询" icon="el-icon-map-location" @click="getTrace(channel)"></el-button> | ||
| 30 | + </div> | ||
| 31 | + <span class="infobox-close el-icon-close" @click="closeInfoBox()"></span> | ||
| 32 | + </div> | ||
| 33 | + </div> | ||
| 34 | + <devicePlayer ref="devicePlayer" ></devicePlayer> | ||
| 35 | + <queryTrace ref="queryTrace" ></queryTrace> | ||
| 31 | </div> | 36 | </div> |
| 32 | </template> | 37 | </template> |
| 33 | 38 | ||
| 34 | <script> | 39 | <script> |
| 35 | -import uiHeader from "./UiHeader.vue"; | ||
| 36 | import MapComponent from "./common/MapComponent.vue"; | 40 | import MapComponent from "./common/MapComponent.vue"; |
| 37 | import DeviceService from "./service/DeviceService"; | 41 | import DeviceService from "./service/DeviceService"; |
| 42 | +import DeviceTree from "./common/DeviceTree"; | ||
| 43 | +import channelMapInfobox from "./dialog/channelMapInfobox"; | ||
| 44 | +import devicePlayer from './dialog/devicePlayer.vue' | ||
| 45 | +import queryTrace from './dialog/queryTrace.vue' | ||
| 46 | + | ||
| 38 | export default { | 47 | export default { |
| 39 | - name: "devicePosition", | ||
| 40 | - components: { | ||
| 41 | - MapComponent, | ||
| 42 | - uiHeader, | ||
| 43 | - }, | ||
| 44 | - data() { | ||
| 45 | - return { | ||
| 46 | - deviceService: new DeviceService(), | ||
| 47 | - props: { | ||
| 48 | - label: 'name', | ||
| 49 | - children: 'children', | ||
| 50 | - isLeaf: 'leaf' | ||
| 51 | - }, | ||
| 52 | - }; | ||
| 53 | - }, | ||
| 54 | - created() { | ||
| 55 | - this.init(); | ||
| 56 | - }, | ||
| 57 | - destroyed() { | 48 | + name: "devicePosition", |
| 49 | + components: { | ||
| 50 | + MapComponent, | ||
| 51 | + DeviceTree, | ||
| 52 | + channelMapInfobox, | ||
| 53 | + devicePlayer, | ||
| 54 | + queryTrace, | ||
| 55 | + }, | ||
| 56 | + data() { | ||
| 57 | + return { | ||
| 58 | + deviceService: new DeviceService(), | ||
| 59 | + layer: null, | ||
| 60 | + lineLayer: null, | ||
| 61 | + channel: null, | ||
| 62 | + infoBoxId: null, | ||
| 63 | + labelStyle: { | ||
| 64 | + width: "56px" | ||
| 65 | + }, | ||
| 66 | + isLoging: false, | ||
| 67 | + }; | ||
| 68 | + }, | ||
| 69 | + created() { | ||
| 70 | + if (this.$route.query.deviceId) { | ||
| 71 | + console.log(this.$route.query.deviceId) | ||
| 72 | + // this.$refs.deviceTree.openByDeivceId(this.$route.query.deivceId) | ||
| 73 | + setTimeout(()=>{ // 延迟以等待地图加载完成 TODO 后续修改为通过是实际这;状态加回调完成 | ||
| 74 | + this.deviceService.getAllChannel(false, this.$route.query.deviceId, this.channelsHandler) | ||
| 75 | + }, 1000) | ||
| 58 | 76 | ||
| 59 | - }, | ||
| 60 | - methods: { | ||
| 61 | - init(){ | 77 | + } |
| 78 | + }, | ||
| 79 | + destroyed() { | ||
| 62 | 80 | ||
| 63 | - }, | ||
| 64 | - loadNode: function(node, resolve){ | ||
| 65 | - if (node.level === 0) { | ||
| 66 | - this.deviceService.getAllDeviceList((data)=>{ | ||
| 67 | - console.log("all deivce") | ||
| 68 | - console.log(data) | ||
| 69 | - if (data.length > 0) { | ||
| 70 | - let nodeList = [] | ||
| 71 | - for (let i = 0; i < data.length; i++) { | ||
| 72 | - let node = { | ||
| 73 | - name: data[i].name || data[i].deviceId, | ||
| 74 | - id: data[i].deviceId, | ||
| 75 | - online: data[i].online, | ||
| 76 | - deviceId: data[i].deviceId, | ||
| 77 | - } | ||
| 78 | - nodeList.push(node); | 81 | + }, |
| 82 | + methods: { | ||
| 83 | + clickEvent: function (data) { | ||
| 84 | + if (data.channelId && data.subCount == 0) { | ||
| 85 | + // 点击通道 | ||
| 86 | + if (data.longitude * data.latitude === 0) { | ||
| 87 | + this.$message.error('未获取到位置信息'); | ||
| 88 | + } else { | ||
| 89 | + if (this.layer != null) { | ||
| 90 | + this.$refs.map.removeLayer(this.layer); | ||
| 91 | + } | ||
| 92 | + this.closeInfoBox() | ||
| 93 | + this.layer = this.$refs.map.addLayer([{ | ||
| 94 | + position: [data.longitude, data.latitude], | ||
| 95 | + image: { | ||
| 96 | + src: this.getImageByChannel(data), | ||
| 97 | + anchor: [0.5, 1] | ||
| 98 | + }, | ||
| 99 | + data: data | ||
| 100 | + }], this.featureClickEvent) | ||
| 101 | + this.$refs.map.panTo([data.longitude, data.latitude], mapParam.maxZoom) | ||
| 102 | + } | ||
| 103 | + } | ||
| 104 | + }, | ||
| 105 | + contextmenuEventHandler: function (event, data) { | ||
| 106 | + if (data.channelId && data.subCount == 0) { | ||
| 107 | + // 点击通道 | ||
| 108 | + this.$contextmenu({ | ||
| 109 | + items: [ | ||
| 110 | + { | ||
| 111 | + label: "播放", | ||
| 112 | + icon: "el-icon-video-play", | ||
| 113 | + disabled: false, | ||
| 114 | + onClick: () => { | ||
| 115 | + this.play(data); | ||
| 116 | + } | ||
| 117 | + }, | ||
| 118 | + { | ||
| 119 | + label: "编辑位置", | ||
| 120 | + icon: "el-icon-edit", | ||
| 121 | + disabled: false, | ||
| 122 | + onClick: () => { | ||
| 123 | + this.edit(data) | ||
| 124 | + } | ||
| 125 | + }, | ||
| 126 | + { | ||
| 127 | + label: "轨迹查询", | ||
| 128 | + icon: "el-icon-map-location", | ||
| 129 | + disabled: false, | ||
| 130 | + onClick: () => { | ||
| 131 | + this.getTrace(data) | ||
| 79 | } | 132 | } |
| 80 | - resolve(nodeList) | ||
| 81 | - }else { | ||
| 82 | - resolve([]) | ||
| 83 | } | 133 | } |
| 84 | - }, (error)=>{ | 134 | + ], |
| 135 | + event, // 鼠标事件信息 | ||
| 136 | + customClass: "custom-class", // 自定义菜单 class | ||
| 137 | + zIndex: 3000, // 菜单样式 z-index | ||
| 138 | + }); | ||
| 139 | + } else { | ||
| 140 | + this.deviceOrSubChannelMenu(event, data) | ||
| 141 | + } | ||
| 85 | 142 | ||
| 86 | - }) | ||
| 87 | - } | ||
| 88 | - if (node.level === 1){ | ||
| 89 | - console.log(node) | ||
| 90 | - this.deviceService.getAllCatalog(node.data.deviceId, (data)=>{ | ||
| 91 | - console.log("all Catalog") | ||
| 92 | - console.log(data) | ||
| 93 | - if (data.length > 0) { | ||
| 94 | - let nodeList = [] | ||
| 95 | - for (let i = 0; i < data.length; i++) { | ||
| 96 | - let node = { | ||
| 97 | - name: data[i].name || data[i].channelId, | ||
| 98 | - id: data[i].channelId, | ||
| 99 | - online: data[i].status === 1, | ||
| 100 | - deviceId: data[i].deviceId, | ||
| 101 | - channelId: data[i].channelId, | ||
| 102 | - } | ||
| 103 | - nodeList.push(node); | 143 | + }, |
| 144 | + deviceOrSubChannelMenu: function (event, data) { | ||
| 145 | + // 点击设备 | ||
| 146 | + this.$contextmenu({ | ||
| 147 | + items: [ | ||
| 148 | + { | ||
| 149 | + label: "定位", | ||
| 150 | + icon: "el-icon-s-promotion", | ||
| 151 | + disabled: false, | ||
| 152 | + onClick: () => { | ||
| 153 | + if (!data.channelId) { | ||
| 154 | + this.deviceService.getAllChannel(false, data.deviceId, this.channelsHandler) | ||
| 155 | + } | ||
| 156 | + if (data.channelId && data.subCount > 0) { | ||
| 157 | + // 点击子目录 | ||
| 158 | + this.deviceService.getAllSubChannel(false, data.deviceId, data.channelId, this.channelsHandler) | ||
| 104 | } | 159 | } |
| 105 | - resolve(nodeList) | ||
| 106 | - }else { | ||
| 107 | - resolve([]) | ||
| 108 | } | 160 | } |
| 109 | - }, (error)=>{ | 161 | + } |
| 162 | + ], | ||
| 163 | + event, // 鼠标事件信息 | ||
| 164 | + customClass: "custom-class", // 自定义菜单 class | ||
| 165 | + zIndex: 3000, // 菜单样式 z-index | ||
| 166 | + }); | ||
| 110 | 167 | ||
| 111 | - }) | 168 | + }, |
| 169 | + channelsHandler: function (channels) { | ||
| 170 | + console.log(2) | ||
| 171 | + if (channels.length > 0) { | ||
| 172 | + this.clean() | ||
| 173 | + this.closeInfoBox() | ||
| 174 | + let params = []; | ||
| 175 | + for (let i = 0; i < channels.length; i++) { | ||
| 176 | + if (channels[i].longitude * channels[i].latitude === 0) { | ||
| 177 | + continue; | ||
| 178 | + } | ||
| 179 | + let item = { | ||
| 180 | + position: [channels[i].longitude, channels[i].latitude], | ||
| 181 | + image: { | ||
| 182 | + src: this.getImageByChannel(channels[i]), | ||
| 183 | + anchor: [0.5, 1] | ||
| 184 | + }, | ||
| 185 | + data: channels[i] | ||
| 186 | + } | ||
| 187 | + params.push(item); | ||
| 112 | } | 188 | } |
| 189 | + console.log(3) | ||
| 113 | 190 | ||
| 114 | - if (node.level > 1) { | ||
| 115 | - console.log(node.data.channelId) | ||
| 116 | - this.deviceService.getAllSubCatalog(node.data.deviceId, node.data.channelId, (data)=>{ | ||
| 117 | - console.log("all Catalog") | ||
| 118 | - console.log(data) | ||
| 119 | - if (data.length > 0) { | ||
| 120 | - let nodeList = [] | ||
| 121 | - for (let i = 0; i < data.length; i++) { | ||
| 122 | - let node = { | ||
| 123 | - name: data[i].name || data[i].channelId, | ||
| 124 | - id: data[i].channelId, | ||
| 125 | - online: data[i].status === 1, | ||
| 126 | - deviceId: data[i].deviceId, | ||
| 127 | - channelId: data[i].channelId, | ||
| 128 | - } | ||
| 129 | - nodeList.push(node); | ||
| 130 | - } | ||
| 131 | - resolve(nodeList) | ||
| 132 | - }else { | ||
| 133 | - resolve([]) | ||
| 134 | - } | ||
| 135 | - }, (error)=>{ | ||
| 136 | - | ||
| 137 | - }) | 191 | + this.layer = this.$refs.map.addLayer(params, this.featureClickEvent) |
| 192 | + console.log(4) | ||
| 193 | + if (params.length === 1) { | ||
| 194 | + this.$refs.map.panTo([channels[0].longitude, channels[0].latitude], mapParam.maxZoom) | ||
| 195 | + } else if (params.length > 1) { | ||
| 196 | + this.$refs.map.fit(this.layer) | ||
| 197 | + } else { | ||
| 198 | + this.$message.error('未获取到位置信息'); | ||
| 138 | } | 199 | } |
| 139 | - }, | ||
| 140 | - contextmenuEventHandler: function (event,data,node,element){ | ||
| 141 | - if (node.data.type !== 0) { | ||
| 142 | - data.parentId = node.parent.data.id; | ||
| 143 | - this.$contextmenu({ | ||
| 144 | - items: [ | ||
| 145 | - { | ||
| 146 | - label: "移除通道", | ||
| 147 | - icon: "el-icon-delete", | ||
| 148 | - disabled: false, | ||
| 149 | - onClick: () => { | ||
| 150 | - this.$axios({ | ||
| 151 | - method:"delete", | ||
| 152 | - url:"/api/platform/catalog/relation/del", | ||
| 153 | - data: data | ||
| 154 | - }).then((res)=>{ | ||
| 155 | - console.log("移除成功") | ||
| 156 | - node.parent.loaded = false | ||
| 157 | - node.parent.expand(); | ||
| 158 | - }).catch(function (error) { | ||
| 159 | - console.log(error); | ||
| 160 | - }); | ||
| 161 | - } | ||
| 162 | - } | ||
| 163 | - ], | ||
| 164 | - event, // 鼠标事件信息 | ||
| 165 | - customClass: "custom-class", // 自定义菜单 class | ||
| 166 | - zIndex: 3000, // 菜单样式 z-index | ||
| 167 | - }); | ||
| 168 | - }else { | ||
| 169 | - this.$contextmenu({ | ||
| 170 | - items: [ | ||
| 171 | - { | ||
| 172 | - label: "刷新节点", | ||
| 173 | - icon: "el-icon-refresh", | ||
| 174 | - disabled: false, | ||
| 175 | - onClick: () => { | ||
| 176 | - this.refreshCatalog(node); | ||
| 177 | - } | ||
| 178 | - }, | ||
| 179 | - { | ||
| 180 | - label: "新建节点", | ||
| 181 | - icon: "el-icon-plus", | ||
| 182 | - disabled: false, | ||
| 183 | - onClick: () => { | ||
| 184 | - this.addCatalog(data.id, node); | ||
| 185 | - } | ||
| 186 | - }, | ||
| 187 | - { | ||
| 188 | - label: "修改节点", | ||
| 189 | - icon: "el-icon-edit", | ||
| 190 | - disabled: node.level === 1, | ||
| 191 | - onClick: () => { | ||
| 192 | - this.editCatalog(data, node); | ||
| 193 | - } | ||
| 194 | - }, | ||
| 195 | - { | ||
| 196 | - label: "删除节点", | ||
| 197 | - icon: "el-icon-delete", | ||
| 198 | - disabled: node.level === 1, | ||
| 199 | - divided: true, | ||
| 200 | - onClick: () => { | ||
| 201 | - this.$confirm('确定删除?', '提示', { | ||
| 202 | - confirmButtonText: '确定', | ||
| 203 | - cancelButtonText: '取消', | ||
| 204 | - type: 'warning' | ||
| 205 | - }).then(() => { | ||
| 206 | - this.removeCatalog(data.id, node) | ||
| 207 | - }).catch(() => { | 200 | + } else { |
| 201 | + this.$message.error('未获取到位置信息'); | ||
| 202 | + } | ||
| 203 | + }, | ||
| 204 | + getImageByChannel: function (channel) { | ||
| 205 | + let src = "static/images/gis/camera.png" | ||
| 206 | + switch (channel.ptztype) { | ||
| 207 | + case 1: | ||
| 208 | + if (channel.status === 1) { | ||
| 209 | + src = "static/images/gis/camera1.png" | ||
| 210 | + } else { | ||
| 211 | + src = "static/images/gis/camera1-offline.png" | ||
| 212 | + } | ||
| 213 | + break; | ||
| 214 | + case 2: | ||
| 215 | + if (channel.status === 1) { | ||
| 216 | + src = "static/images/gis/camera2.png" | ||
| 217 | + } else { | ||
| 218 | + src = "static/images/gis/camera2-offline.png" | ||
| 219 | + } | ||
| 220 | + break; | ||
| 221 | + case 3: | ||
| 222 | + if (channel.status === 1) { | ||
| 223 | + src = "static/images/gis/camera3.png" | ||
| 224 | + } else { | ||
| 225 | + src = "static/images/gis/camera3-offline.png" | ||
| 226 | + } | ||
| 227 | + break; | ||
| 228 | + default: | ||
| 229 | + if (channel.status === 1) { | ||
| 230 | + src = "static/images/gis/camera.png" | ||
| 231 | + } else { | ||
| 232 | + src = "static/images/gis/camera-offline.png" | ||
| 233 | + } | ||
| 234 | + } | ||
| 235 | + return src; | ||
| 236 | + }, | ||
| 237 | + featureClickEvent: function (channels) { | ||
| 238 | + this.closeInfoBox() | ||
| 239 | + if (channels.length > 0) { | ||
| 240 | + this.channel = channels[0] | ||
| 241 | + } | ||
| 242 | + this.$nextTick(() => { | ||
| 243 | + this.infoBoxId = this.$refs.map.openInfoBox([this.channel.longitude, this.channel.latitude], this.$refs.infobox, [0, -50]) | ||
| 244 | + }) | ||
| 245 | + }, | ||
| 246 | + closeInfoBox: function () { | ||
| 247 | + if (this.infoBoxId != null) { | ||
| 248 | + this.$refs.map.closeInfoBox(this.infoBoxId) | ||
| 249 | + } | ||
| 250 | + }, | ||
| 251 | + play: function (channel) { | ||
| 208 | 252 | ||
| 209 | - }); | ||
| 210 | - } | ||
| 211 | - }, | ||
| 212 | - { | ||
| 213 | - label: "设为默认", | ||
| 214 | - icon: "el-icon-folder-checked", | ||
| 215 | - disabled: node.data.id === this.defaultCatalogIdSign, | ||
| 216 | - onClick: () => { | ||
| 217 | - this.setDefaultCatalog(data.id) | ||
| 218 | - }, | ||
| 219 | - }, | ||
| 220 | - // { | ||
| 221 | - // label: "导出", | ||
| 222 | - // icon: "el-icon-download", | ||
| 223 | - // disabled: false, | ||
| 224 | - // children: [ | ||
| 225 | - // { | ||
| 226 | - // label: "导出到文件", | ||
| 227 | - // onClick: () => { | ||
| 228 | - // | ||
| 229 | - // }, | ||
| 230 | - // }, | ||
| 231 | - // { | ||
| 232 | - // label: "导出到其他平台", | ||
| 233 | - // onClick: () => { | ||
| 234 | - // | ||
| 235 | - // }, | ||
| 236 | - // } | ||
| 237 | - // ] | ||
| 238 | - // }, | 253 | + let deviceId = channel.deviceId; |
| 254 | + this.isLoging = true; | ||
| 255 | + let channelId = channel.channelId; | ||
| 256 | + console.log("通知设备推流1:" + deviceId + " : " + channelId); | ||
| 257 | + let that = this; | ||
| 258 | + this.$axios({ | ||
| 259 | + method: 'get', | ||
| 260 | + url: '/api/play/start/' + deviceId + '/' + channelId | ||
| 261 | + }).then(function (res) { | ||
| 262 | + that.isLoging = false; | ||
| 263 | + if (res.data.code === 0) { | ||
| 239 | 264 | ||
| 240 | - ], | ||
| 241 | - event, // 鼠标事件信息 | ||
| 242 | - customClass: "custom-class", // 自定义菜单 class | ||
| 243 | - zIndex: 3000, // 菜单样式 z-index | 265 | + that.$refs.devicePlayer.openDialog("media", deviceId, channelId, { |
| 266 | + streamInfo: res.data.data, | ||
| 267 | + hasAudio: channel.hasAudio | ||
| 244 | }); | 268 | }); |
| 269 | + | ||
| 270 | + } else { | ||
| 271 | + that.$message.error(res.data.msg); | ||
| 245 | } | 272 | } |
| 273 | + }).catch(function (e) { | ||
| 274 | + }); | ||
| 275 | + }, | ||
| 276 | + edit: function (data) { | ||
| 277 | + this.$message.warning('暂不支持'); | ||
| 278 | + }, | ||
| 279 | + getTrace: function (data) { | ||
| 280 | + // this.$message.warning('暂不支持'); | ||
| 281 | + this.clean() | ||
| 282 | + this.$refs.queryTrace.openDialog(data, (channelPositions) => { | ||
| 283 | + console.log("getTrace") | ||
| 284 | + console.log(channelPositions) | ||
| 285 | + if (channelPositions.length === 0) { | ||
| 286 | + this.$message.success('未查询到轨迹信息'); | ||
| 287 | + } else { | ||
| 288 | + let positions = []; | ||
| 289 | + for (let i = 0; i < channelPositions.length; i++) { | ||
| 290 | + if (channelPositions[i].cnLng * channelPositions[i].cnLat > 0) { | ||
| 291 | + positions.push([channelPositions[i].cnLng, channelPositions[i].cnLat]) | ||
| 292 | + } | ||
| 246 | 293 | ||
| 247 | - return false; | ||
| 248 | - }, | ||
| 249 | - nodeClickHandler: function (data, node, tree){ | ||
| 250 | - this.chooseId = data.id; | ||
| 251 | - this.chooseName = data.name; | ||
| 252 | - if (this.catalogIdChange)this.catalogIdChange(this.chooseId, this.chooseName); | ||
| 253 | - } | 294 | + } |
| 295 | + if (positions.length === 0) { | ||
| 296 | + this.$message.success('未查询到轨迹信息'); | ||
| 297 | + return; | ||
| 298 | + } | ||
| 299 | + this.lineLayer = this.$refs.map.addLineLayer(positions) | ||
| 300 | + this.$refs.map.fit(this.lineLayer) | ||
| 301 | + } | ||
| 302 | + }) | ||
| 254 | }, | 303 | }, |
| 304 | + clean: function (){ | ||
| 305 | + if (this.lineLayer != null) { | ||
| 306 | + this.$refs.map.removeLayer(this.lineLayer) | ||
| 307 | + } | ||
| 308 | + if (this.infoBoxId != null) { | ||
| 309 | + this.$refs.map.closeInfoBox(this.infoBoxId) | ||
| 310 | + } | ||
| 311 | + if (this.layer != null) { | ||
| 312 | + this.$refs.map.removeLayer(this.layer) | ||
| 313 | + } | ||
| 314 | + } | ||
| 315 | + }, | ||
| 316 | + | ||
| 255 | }; | 317 | }; |
| 256 | </script> | 318 | </script> |
| 257 | 319 | ||
| 258 | <style> | 320 | <style> |
| 321 | +.infobox-content{ | ||
| 322 | + width: 260px; | ||
| 323 | + background-color: #FFFFFF; | ||
| 324 | + padding: 10px; | ||
| 325 | + border-radius: 10px; | ||
| 326 | + border: 1px solid #e2e2e2; | ||
| 327 | +} | ||
| 259 | 328 | ||
| 329 | +.infobox-content::after { | ||
| 330 | + position: absolute; | ||
| 331 | + bottom: -11px; | ||
| 332 | + left: 130px; | ||
| 333 | + display: block; | ||
| 334 | + content: ""; | ||
| 335 | + width: 16px; | ||
| 336 | + height: 16px; | ||
| 337 | + background: url('~@static/images/arrow.png') no-repeat center; | ||
| 338 | +} | ||
| 339 | +.infobox-close { | ||
| 340 | + position: absolute; | ||
| 341 | + right: 1rem; | ||
| 342 | + top: 1rem; | ||
| 343 | + color: #000000; | ||
| 344 | + cursor:pointer | ||
| 345 | +} | ||
| 346 | +.el-descriptions__title { | ||
| 347 | + font-size: 1rem; | ||
| 348 | + font-weight: 700; | ||
| 349 | + padding: 20px 20px 0px 23px; | ||
| 350 | + text-align: center; | ||
| 351 | + width: 100%; | ||
| 352 | +} | ||
| 260 | </style> | 353 | </style> |
web_src/src/components/dialog/channelMapInfobox.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div id="channelMapInfobox" style="display: none"> | ||
| 3 | + <div > | ||
| 4 | + <el-descriptions class="margin-top" title="channel.name" :column="4" direction="vertical"> | ||
| 5 | + <el-descriptions-item label="生产厂商">{{channel.manufacture}}</el-descriptions-item> | ||
| 6 | + <el-descriptions-item label="型号">{{channel.model}}</el-descriptions-item> | ||
| 7 | + <el-descriptions-item label="设备归属" >{{channel.owner}}</el-descriptions-item> | ||
| 8 | + <el-descriptions-item label="行政区域" >{{channel.civilCode}}</el-descriptions-item> | ||
| 9 | + <el-descriptions-item label="安装地址" >{{channel.address}}</el-descriptions-item> | ||
| 10 | + <el-descriptions-item label="云台类型" >{{channel.ptztypeText}}</el-descriptions-item> | ||
| 11 | + <el-descriptions-item label="经纬度" >{{channel.longitude}},{{channel.latitude}}</el-descriptions-item> | ||
| 12 | + <el-descriptions-item label="状态"> | ||
| 13 | + <el-tag size="small" v-if="channel.status === 1">在线</el-tag> | ||
| 14 | + <el-tag size="small" v-if="channel.status === 0">离线</el-tag> | ||
| 15 | + </el-descriptions-item> | ||
| 16 | + </el-descriptions> | ||
| 17 | + </div> | ||
| 18 | + | ||
| 19 | + <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer> | ||
| 20 | + </div> | ||
| 21 | +</template> | ||
| 22 | + | ||
| 23 | +<script> | ||
| 24 | +import devicePlayer from '../dialog/devicePlayer.vue' | ||
| 25 | + | ||
| 26 | +export default { | ||
| 27 | + name: "channelMapInfobox", | ||
| 28 | + props: ['channel'], | ||
| 29 | + computed: {devicePlayer}, | ||
| 30 | + created() {}, | ||
| 31 | + data() { | ||
| 32 | + return { | ||
| 33 | + showDialog: false, | ||
| 34 | + isLoging: false | ||
| 35 | + }; | ||
| 36 | + }, | ||
| 37 | + methods: { | ||
| 38 | + | ||
| 39 | + play: function (){ | ||
| 40 | + let deviceId = this.channel.deviceId; | ||
| 41 | + this.isLoging = true; | ||
| 42 | + let channelId = this.channel.channelId; | ||
| 43 | + console.log("通知设备推流1:" + deviceId + " : " + channelId); | ||
| 44 | + let that = this; | ||
| 45 | + this.$axios({ | ||
| 46 | + method: 'get', | ||
| 47 | + url: '/api/play/start/' + deviceId + '/' + channelId | ||
| 48 | + }).then(function (res) { | ||
| 49 | + that.isLoging = false; | ||
| 50 | + if (res.data.code === 0) { | ||
| 51 | + that.$refs.devicePlayer.openDialog("media", deviceId, channelId, { | ||
| 52 | + streamInfo: res.data.data, | ||
| 53 | + hasAudio: this.channel.hasAudio | ||
| 54 | + }); | ||
| 55 | + } else { | ||
| 56 | + that.$message.error(res.data.msg); | ||
| 57 | + } | ||
| 58 | + }).catch(function (e) { | ||
| 59 | + }); | ||
| 60 | + }, | ||
| 61 | + close: function () { | ||
| 62 | + }, | ||
| 63 | + }, | ||
| 64 | +}; | ||
| 65 | +</script> |
web_src/src/components/dialog/queryTrace.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div id="queryTrace" > | ||
| 3 | + <el-dialog | ||
| 4 | + title="查询轨迹" | ||
| 5 | + width="40%" | ||
| 6 | + top="2rem" | ||
| 7 | + :close-on-click-modal="false" | ||
| 8 | + :visible.sync="showDialog" | ||
| 9 | + :destroy-on-close="true" | ||
| 10 | + @close="close()" | ||
| 11 | + > | ||
| 12 | + <div v-loading="isLoging"> | ||
| 13 | + <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> | ||
| 14 | + <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> | ||
| 15 | + <el-button icon="el-icon-search" size="mini" type="primary" @click="onSubmit">查询</el-button> | ||
| 16 | + </div> | ||
| 17 | + | ||
| 18 | + </el-dialog> | ||
| 19 | + </div> | ||
| 20 | +</template> | ||
| 21 | + | ||
| 22 | +<script> | ||
| 23 | +import DeviceService from '../service/DeviceService' | ||
| 24 | + | ||
| 25 | +export default { | ||
| 26 | + name: "deviceEdit", | ||
| 27 | + props: [], | ||
| 28 | + computed: {}, | ||
| 29 | + created() {}, | ||
| 30 | + data() { | ||
| 31 | + return { | ||
| 32 | + deviceService: new DeviceService(), | ||
| 33 | + pickerOptions: { | ||
| 34 | + shortcuts: [{ | ||
| 35 | + text: '今天', | ||
| 36 | + onClick(picker) { | ||
| 37 | + picker.$emit('pick', new Date()); | ||
| 38 | + } | ||
| 39 | + }, { | ||
| 40 | + text: '昨天', | ||
| 41 | + onClick(picker) { | ||
| 42 | + const date = new Date(); | ||
| 43 | + date.setTime(date.getTime() - 3600 * 1000 * 24); | ||
| 44 | + picker.$emit('pick', date); | ||
| 45 | + } | ||
| 46 | + }, { | ||
| 47 | + text: '一周前', | ||
| 48 | + onClick(picker) { | ||
| 49 | + const date = new Date(); | ||
| 50 | + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); | ||
| 51 | + picker.$emit('pick', date); | ||
| 52 | + } | ||
| 53 | + }] | ||
| 54 | + }, | ||
| 55 | + searchFrom: null, | ||
| 56 | + searchTo: null, | ||
| 57 | + listChangeCallback: null, | ||
| 58 | + showDialog: false, | ||
| 59 | + isLoging: false, | ||
| 60 | + channel: null, | ||
| 61 | + callback: null, | ||
| 62 | + }; | ||
| 63 | + }, | ||
| 64 | + methods: { | ||
| 65 | + openDialog: function (channel, callback) { | ||
| 66 | + console.log(channel) | ||
| 67 | + this.showDialog = true; | ||
| 68 | + this.callback = callback; | ||
| 69 | + this.channel = channel; | ||
| 70 | + }, | ||
| 71 | + | ||
| 72 | + onSubmit: function () { | ||
| 73 | + console.log("onSubmit"); | ||
| 74 | + this.isLoging = true; | ||
| 75 | + this.$axios.get(`/api/position/history/${this.channel.deviceId}/${this.channel.channelId}`, { | ||
| 76 | + }).then((res)=> { | ||
| 77 | + this.isLoging = false; | ||
| 78 | + if (typeof this.callback == "function") { | ||
| 79 | + if (res.data.code == 0) { | ||
| 80 | + this.callback(res.data.data) | ||
| 81 | + this.close() | ||
| 82 | + }else { | ||
| 83 | + this.$message.error(res.data.msg); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + } | ||
| 87 | + }).catch(function (error) { | ||
| 88 | + this.isLoging = false; | ||
| 89 | + console.error(error); | ||
| 90 | + }) | ||
| 91 | + }, | ||
| 92 | + close: function () { | ||
| 93 | + this.showDialog = false; | ||
| 94 | + this.isLoging = false; | ||
| 95 | + this.callback = null; | ||
| 96 | + this.channel = null; | ||
| 97 | + }, | ||
| 98 | + }, | ||
| 99 | +}; | ||
| 100 | +</script> |
web_src/src/components/live.vue
| 1 | <template> | 1 | <template> |
| 2 | - <div id="devicePosition" style="height: 100%"> | ||
| 3 | - <el-container style="height: 100%"> | ||
| 4 | - <el-header> | ||
| 5 | - <uiHeader></uiHeader> | ||
| 6 | - </el-header> | ||
| 7 | - <el-container v-loading="loading" element-loading-text="拼命加载中" style="margin: 0 20px;"> | ||
| 8 | - <el-aside width="300px" style="background-color: #ffffff"> | ||
| 9 | - <div style="text-align: center;padding-top: 20px;">设备列表</div> | ||
| 10 | - <el-menu v-loading="loading"> | ||
| 11 | - <el-submenu v-for="device in deviceList" :key="device.deviceId" :index="device.deviceId" @click="sendDevicePush(item)"> | ||
| 12 | - <template slot="title" > | ||
| 13 | - <i class="el-icon-location-outline"></i> | ||
| 14 | - {{device.name}} | ||
| 15 | - </template> | ||
| 16 | - <ChannelTree :device="device" @sendDevicePush="sendDevicePush"></ChannelTree> | ||
| 17 | - </el-submenu> | ||
| 18 | - </el-menu> | ||
| 19 | - </el-aside> | ||
| 20 | - <el-container> | ||
| 21 | - <!-- <LivePlay></LivePlay> --> | ||
| 22 | - <el-header height="40px" style="text-align: left;font-size: 17px;line-height: 40px;"> | ||
| 23 | - 分屏: | ||
| 24 | - <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/> | ||
| 25 | - <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/> | ||
| 26 | - <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/> | ||
| 27 | - </el-header> | ||
| 28 | - <el-main> | ||
| 29 | - <div style="width: 100%;height: calc( 100vh - 110px );display: flex;flex-wrap: wrap;background-color: #000;"> | ||
| 30 | - <div v-for="i in spilt" :key="i" class="play-box" | ||
| 31 | - :style="liveStyle" :class="{redborder:playerIdx == (i-1)}" | ||
| 32 | - @click="playerIdx = (i-1)" | ||
| 33 | - > | ||
| 34 | - <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div> | ||
| 35 | - <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true" | ||
| 36 | - :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player> | ||
| 37 | - <!-- <player v-else ref="'player'+i" :idx="'player'+i" :visible.sync="showVideoDialog" :videoUrl="videoUrl[i-1]" :height="true" :hasAudio="hasAudio" fluent autoplay live ></player> --> | ||
| 38 | - </div> | ||
| 39 | - </div> | ||
| 40 | - </el-main> | ||
| 41 | - </el-container> | 2 | + <div id="devicePosition" style="width:100vw; height: 91vh"> |
| 3 | + <el-container v-loading="loading" style="height: 91vh;" element-loading-text="拼命加载中" > | ||
| 4 | + <el-aside width="300px" style="background-color: #ffffff"> | ||
| 5 | + <DeviceTree :clickEvent="clickEvent" :contextMenuEvent="contextMenuEvent" ></DeviceTree> | ||
| 6 | + </el-aside> | ||
| 7 | + <el-container> | ||
| 8 | + <el-header height="5vh" style="text-align: left;font-size: 17px;line-height:5vh"> | ||
| 9 | + 分屏: | ||
| 10 | + <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/> | ||
| 11 | + <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/> | ||
| 12 | + <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/> | ||
| 13 | + </el-header> | ||
| 14 | + <el-main style="padding: 0;"> | ||
| 15 | + <div style="width: 99%;height: 85vh;display: flex;flex-wrap: wrap;background-color: #000;"> | ||
| 16 | + <div v-for="i in spilt" :key="i" class="play-box" | ||
| 17 | + :style="liveStyle" :class="{redborder:playerIdx == (i-1)}" | ||
| 18 | + @click="playerIdx = (i-1)" | ||
| 19 | + > | ||
| 20 | + <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div> | ||
| 21 | + <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true" | ||
| 22 | + :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player> | ||
| 23 | + </div> | ||
| 24 | + </div> | ||
| 25 | + </el-main> | ||
| 42 | </el-container> | 26 | </el-container> |
| 43 | </el-container> | 27 | </el-container> |
| 44 | </div> | 28 | </div> |
| @@ -46,13 +30,13 @@ | @@ -46,13 +30,13 @@ | ||
| 46 | 30 | ||
| 47 | <script> | 31 | <script> |
| 48 | import uiHeader from "../layout/UiHeader.vue"; | 32 | import uiHeader from "../layout/UiHeader.vue"; |
| 49 | - import player from './dialog/jessibuca.vue' | ||
| 50 | - import ChannelTree from './channelTree.vue' | 33 | + import player from './common/jessibuca.vue' |
| 34 | + import DeviceTree from './common/DeviceTree.vue' | ||
| 51 | 35 | ||
| 52 | export default { | 36 | export default { |
| 53 | name: "live", | 37 | name: "live", |
| 54 | components: { | 38 | components: { |
| 55 | - uiHeader, player, ChannelTree | 39 | + uiHeader, player, DeviceTree |
| 56 | }, | 40 | }, |
| 57 | data() { | 41 | data() { |
| 58 | return { | 42 | return { |
| @@ -127,33 +111,17 @@ | @@ -127,33 +111,17 @@ | ||
| 127 | clearTimeout(this.updateLooper); | 111 | clearTimeout(this.updateLooper); |
| 128 | }, | 112 | }, |
| 129 | methods: { | 113 | methods: { |
| 130 | - initData: function () { | ||
| 131 | - this.getDeviceList(); | ||
| 132 | - | ||
| 133 | - }, | ||
| 134 | destroy(idx) { | 114 | destroy(idx) { |
| 135 | console.log(idx); | 115 | console.log(idx); |
| 136 | this.clear(idx.substring(idx.length-1)) | 116 | this.clear(idx.substring(idx.length-1)) |
| 137 | }, | 117 | }, |
| 138 | - getDeviceList: function() { | ||
| 139 | - let that = this; | ||
| 140 | - this.$axios({ | ||
| 141 | - method: 'get', | ||
| 142 | - url:`/api/device/query/devices`, | ||
| 143 | - params: { | ||
| 144 | - page: that.currentPage, | ||
| 145 | - count: that.count | ||
| 146 | - } | ||
| 147 | - }).then(function (res) { | ||
| 148 | - console.log(res.data.list); | ||
| 149 | - that.total = res.data.total; | 118 | + clickEvent: function (data) { |
| 119 | + if (data.channelId && data.subCount == 0) { | ||
| 120 | + this.sendDevicePush(data) | ||
| 121 | + } | ||
| 122 | + }, | ||
| 123 | + contextMenuEvent: function (data) { | ||
| 150 | 124 | ||
| 151 | - that.deviceList = res.data.list.map(item=>{return {deviceChannelList:[],...item}}); | ||
| 152 | - that.getDeviceListLoading = false; | ||
| 153 | - }).catch(function (error) { | ||
| 154 | - console.log(error); | ||
| 155 | - that.getDeviceListLoading = false; | ||
| 156 | - }); | ||
| 157 | }, | 125 | }, |
| 158 | //通知设备上传媒体流 | 126 | //通知设备上传媒体流 |
| 159 | sendDevicePush: function (itemData) { | 127 | sendDevicePush: function (itemData) { |
web_src/src/components/service/DeviceService.js
| @@ -32,7 +32,6 @@ class DeviceService{ | @@ -32,7 +32,6 @@ class DeviceService{ | ||
| 32 | 32 | ||
| 33 | getAllDeviceListIteration(deviceList, currentPage, count, callback, errorCallback) { | 33 | getAllDeviceListIteration(deviceList, currentPage, count, callback, errorCallback) { |
| 34 | this.getDeviceList(currentPage, count, (data) => { | 34 | this.getDeviceList(currentPage, count, (data) => { |
| 35 | - console.log(data) | ||
| 36 | if (data.list) { | 35 | if (data.list) { |
| 37 | deviceList = deviceList.concat(data.list); | 36 | deviceList = deviceList.concat(data.list); |
| 38 | if (deviceList.length < data.total) { | 37 | if (deviceList.length < data.total) { |
| @@ -55,14 +54,13 @@ class DeviceService{ | @@ -55,14 +54,13 @@ class DeviceService{ | ||
| 55 | 54 | ||
| 56 | getAllChannelIteration(isCatalog, deviceId, catalogList, currentPage, count, callback, errorCallback) { | 55 | getAllChannelIteration(isCatalog, deviceId, catalogList, currentPage, count, callback, errorCallback) { |
| 57 | this.getChanel(isCatalog, deviceId, currentPage, count, (data) => { | 56 | this.getChanel(isCatalog, deviceId, currentPage, count, (data) => { |
| 58 | - console.log(data) | ||
| 59 | if (data.list) { | 57 | if (data.list) { |
| 60 | catalogList = catalogList.concat(data.list); | 58 | catalogList = catalogList.concat(data.list); |
| 61 | if (catalogList.length < data.total) { | 59 | if (catalogList.length < data.total) { |
| 62 | currentPage ++ | 60 | currentPage ++ |
| 63 | this.getAllChannelIteration(isCatalog, deviceId, catalogList, currentPage, count, callback, errorCallback) | 61 | this.getAllChannelIteration(isCatalog, deviceId, catalogList, currentPage, count, callback, errorCallback) |
| 64 | }else { | 62 | }else { |
| 65 | - console.log(2222) | 63 | + console.log(1) |
| 66 | if (typeof (callback) == "function") callback(catalogList) | 64 | if (typeof (callback) == "function") callback(catalogList) |
| 67 | } | 65 | } |
| 68 | } | 66 | } |
| @@ -94,7 +92,6 @@ class DeviceService{ | @@ -94,7 +92,6 @@ class DeviceService{ | ||
| 94 | 92 | ||
| 95 | getAllSubChannelIteration(isCatalog, deviceId,channelId, catalogList, currentPage, count, callback, errorCallback) { | 93 | getAllSubChannelIteration(isCatalog, deviceId,channelId, catalogList, currentPage, count, callback, errorCallback) { |
| 96 | this.getSubChannel(isCatalog, deviceId, channelId, currentPage, count, (data) => { | 94 | this.getSubChannel(isCatalog, deviceId, channelId, currentPage, count, (data) => { |
| 97 | - console.log(data) | ||
| 98 | if (data.list) { | 95 | if (data.list) { |
| 99 | catalogList = catalogList.concat(data.list); | 96 | catalogList = catalogList.concat(data.list); |
| 100 | if (catalogList.length < data.total) { | 97 | if (catalogList.length < data.total) { |
| @@ -121,16 +118,6 @@ class DeviceService{ | @@ -121,16 +118,6 @@ class DeviceService{ | ||
| 121 | if (typeof (callback) == "function") callback(res.data) | 118 | if (typeof (callback) == "function") callback(res.data) |
| 122 | }).catch(errorCallback); | 119 | }).catch(errorCallback); |
| 123 | } | 120 | } |
| 124 | - getDeviceTree(deviceId, callback, errorCallback){ | ||
| 125 | - this.$axios({ | ||
| 126 | - method: 'get', | ||
| 127 | - url: `/api/device/query/${deviceId}/tree`, | ||
| 128 | - params:{} | ||
| 129 | - }).then((res) =>{ | ||
| 130 | - console.log(res.data) | ||
| 131 | - if (typeof (callback) == "function") callback(res.data.data) | ||
| 132 | - }).catch(errorCallback); | ||
| 133 | - } | ||
| 134 | } | 121 | } |
| 135 | 122 | ||
| 136 | export default DeviceService; | 123 | export default DeviceService; |
web_src/src/layout/UiHeader.vue
| @@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
| 5 | <el-menu-item index="/control">控制台</el-menu-item> | 5 | <el-menu-item index="/control">控制台</el-menu-item> |
| 6 | <el-menu-item index="/live">实时监控</el-menu-item> | 6 | <el-menu-item index="/live">实时监控</el-menu-item> |
| 7 | <el-menu-item index="/deviceList">国标设备</el-menu-item> | 7 | <el-menu-item index="/deviceList">国标设备</el-menu-item> |
| 8 | + <el-menu-item index="/map">电子地图</el-menu-item> | ||
| 8 | <el-menu-item index="/pushVideoList">推流列表</el-menu-item> | 9 | <el-menu-item index="/pushVideoList">推流列表</el-menu-item> |
| 9 | <el-menu-item index="/streamProxyList">拉流代理</el-menu-item> | 10 | <el-menu-item index="/streamProxyList">拉流代理</el-menu-item> |
| 10 | <el-menu-item index="/cloudRecord">云端录像</el-menu-item> | 11 | <el-menu-item index="/cloudRecord">云端录像</el-menu-item> |
| @@ -47,7 +48,6 @@ export default { | @@ -47,7 +48,6 @@ export default { | ||
| 47 | if (this.$route.path.startsWith("/channelList")) { | 48 | if (this.$route.path.startsWith("/channelList")) { |
| 48 | this.activeIndex = "/deviceList" | 49 | this.activeIndex = "/deviceList" |
| 49 | } | 50 | } |
| 50 | - | ||
| 51 | }, | 51 | }, |
| 52 | mounted() { | 52 | mounted() { |
| 53 | window.addEventListener('beforeunload', e => this.beforeunloadHandler(e)) | 53 | window.addEventListener('beforeunload', e => this.beforeunloadHandler(e)) |
web_src/src/router/index.js
| @@ -108,6 +108,11 @@ export default new VueRouter({ | @@ -108,6 +108,11 @@ export default new VueRouter({ | ||
| 108 | name: 'rtcPlayer', | 108 | name: 'rtcPlayer', |
| 109 | component: rtcPlayer, | 109 | component: rtcPlayer, |
| 110 | }, | 110 | }, |
| 111 | + { | ||
| 112 | + path: '/map', | ||
| 113 | + name: 'devicePosition', | ||
| 114 | + component: devicePosition, | ||
| 115 | + }, | ||
| 111 | ] | 116 | ] |
| 112 | }, | 117 | }, |
| 113 | { | 118 | { |
web_src/static/images/arrow.png
0 → 100644
4.93 KB
web_src/static/images/gis/camera-offline.png
0 → 100644
8.68 KB
web_src/static/images/gis/camera.png
0 → 100644
10.1 KB
web_src/static/images/gis/camera1-offline.png
0 → 100644
10.2 KB
web_src/static/images/gis/camera1.png
0 → 100644
12.7 KB
web_src/static/images/gis/camera2-offline.png
0 → 100644
9.83 KB
web_src/static/images/gis/camera2.png
0 → 100644
12.3 KB
web_src/static/images/gis/camera3-offline.png
0 → 100644
10.2 KB
web_src/static/images/gis/camera3.png
0 → 100644
12.7 KB
-
mentioned in commit 44b7f67a