From f5fcc79a2c7e6379a73b14ba4e366ad1654e9475 Mon Sep 17 00:00:00 2001
From: 648540858 <648540858@qq.com>
Date: 星期日, 03 七月 2022 07:40:54 +0800
Subject: [PATCH] 优化国标树型展示

---
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java                                          |   13 
 web_src/src/components/service/DeviceService.js                                                       |   43 +
 web_src/src/components/common/DeviceTree.vue                                                          |  141 ++-
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java                          |   96 +++
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/ChannelIdType.java                                   |   23 
 src/main/java/com/genersoft/iot/vmp/vmanager/bean/BaseTree.java                                       |   87 ++
 src/main/resources/logback-spring-local.xml                                                           |    5 
 web_src/package-lock.json                                                                             |   78 ++
 web_src/src/components/common/DeviceTreeForZtree.vue                                                  |  112 +++
 src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java                                    |    3 
 web_src/src/components/dialog/deviceEdit.vue                                                          |    6 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java                                   |   13 
 sql/mysql.sql                                                                                         |  527 ++++++++--------
 web_src/src/components/DeviceList.vue                                                                 |    6 
 src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java                               |  185 +++++
 src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java                                        |   35 
 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java                                 |    3 
 web_src/src/components/live.vue                                                                       |   20 
 web_src/static/css/iconfont.css                                                                       |   28 
 web_src/package.json                                                                                  |    4 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java |    1 
 web_src/src/components/map.vue                                                                        |   72 +-
 src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java                                       |   19 
 web_src/static/css/iconfont.woff2                                                                     |    0 
 web_src/src/components/channelList.vue                                                                |  301 +++++---
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java            |    5 
 web_src/src/router/index.js                                                                           |    2 
 sql/update.sql                                                                                        |    5 
 src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java                             |   45 +
 29 files changed, 1,341 insertions(+), 537 deletions(-)

diff --git a/sql/mysql.sql b/sql/mysql.sql
index e23f055..f28e398 100644
--- a/sql/mysql.sql
+++ b/sql/mysql.sql
@@ -1,13 +1,13 @@
--- MariaDB dump 10.19  Distrib 10.7.3-MariaDB, for Linux (x86_64)
+-- MySQL dump 10.13  Distrib 8.0.29, for Linux (x86_64)
 --
 -- Host: 127.0.0.1    Database: wvp3
 -- ------------------------------------------------------
--- Server version	8.0.0-dmr
+-- Server version	8.0.29-0ubuntu0.22.04.2
 
 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
 /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
 /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-/*!40101 SET NAMES utf8mb4 */;
+/*!50503 SET NAMES utf8mb4 */;
 /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
 /*!40103 SET TIME_ZONE='+00:00' */;
 /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
@@ -21,34 +21,36 @@
 
 DROP TABLE IF EXISTS `device`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `device` (
-                          `id` int(11) NOT NULL AUTO_INCREMENT,
-                          `deviceId` varchar(50) NOT NULL,
-                          `name` varchar(255) DEFAULT NULL,
-                          `manufacturer` varchar(255) DEFAULT NULL,
-                          `model` varchar(255) DEFAULT NULL,
-                          `firmware` varchar(255) DEFAULT NULL,
-                          `transport` varchar(50) DEFAULT NULL,
-                          `streamMode` varchar(50) DEFAULT NULL,
-                          `online` varchar(50) DEFAULT NULL,
-                          `registerTime` varchar(50) DEFAULT NULL,
-                          `keepaliveTime` varchar(50) DEFAULT NULL,
-                          `ip` varchar(50) NOT NULL,
-                          `createTime` varchar(50) NOT NULL,
-                          `updateTime` varchar(50) NOT NULL,
-                          `port` int(11) NOT NULL,
-                          `expires` int(11) NOT NULL,
-                          `subscribeCycleForCatalog` int(11) NOT NULL,
-                          `subscribeCycleForMobilePosition` int(11) NOT NULL,
-                          `mobilePositionSubmissionInterval` int(11) NOT NULL DEFAULT '5',
-                          `subscribeCycleForAlarm` int(11) NOT NULL,
-                          `hostAddress` varchar(50) NOT NULL,
-                          `charset` varchar(50) NOT NULL,
-                          `ssrcCheck` int(11) DEFAULT '0',
-                          PRIMARY KEY (`id`),
-                          UNIQUE KEY `device_deviceId_uindex` (`deviceId`)
-) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8mb4;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `manufacturer` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `model` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `firmware` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `streamMode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `online` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `registerTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `keepaliveTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `port` int NOT NULL,
+  `expires` int NOT NULL,
+  `subscribeCycleForCatalog` int NOT NULL,
+  `hostAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `charset` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `subscribeCycleForMobilePosition` int DEFAULT NULL,
+  `mobilePositionSubmissionInterval` int DEFAULT '5',
+  `subscribeCycleForAlarm` int DEFAULT NULL,
+  `ssrcCheck` int DEFAULT '0',
+  `geoCoordSys` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `device_deviceId_uindex` (`deviceId`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -66,20 +68,20 @@
 
 DROP TABLE IF EXISTS `device_alarm`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `device_alarm` (
-                                `id` int(11) NOT NULL AUTO_INCREMENT,
-                                `deviceId` varchar(50) NOT NULL,
-                                `channelId` varchar(50) NOT NULL,
-                                `alarmPriority` varchar(50) NOT NULL,
-                                `alarmMethod` varchar(50) DEFAULT NULL,
-                                `alarmTime` varchar(50) NOT NULL,
-                                `alarmDescription` varchar(255) DEFAULT NULL,
-                                `longitude` double DEFAULT NULL,
-                                `latitude` double DEFAULT NULL,
-                                `alarmType` varchar(50) DEFAULT NULL,
-                                PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `alarmPriority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `alarmMethod` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `alarmTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `alarmDescription` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `longitude` double DEFAULT NULL,
+  `latitude` double DEFAULT NULL,
+  `alarmType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -97,43 +99,48 @@
 
 DROP TABLE IF EXISTS `device_channel`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `device_channel` (
-                                  `id` int(11) NOT NULL AUTO_INCREMENT,
-                                  `channelId` varchar(50) NOT NULL,
-                                  `name` varchar(255) DEFAULT NULL,
-                                  `manufacture` varchar(50) DEFAULT NULL,
-                                  `model` varchar(50) DEFAULT NULL,
-                                  `owner` varchar(50) DEFAULT NULL,
-                                  `civilCode` varchar(50) DEFAULT NULL,
-                                  `block` varchar(50) DEFAULT NULL,
-                                  `address` varchar(50) DEFAULT NULL,
-                                  `parentId` varchar(50) DEFAULT NULL,
-                                  `safetyWay` int(11) DEFAULT NULL,
-                                  `registerWay` int(11) DEFAULT NULL,
-                                  `certNum` varchar(50) DEFAULT NULL,
-                                  `certifiable` int(11) DEFAULT NULL,
-                                  `errCode` int(11) DEFAULT NULL,
-                                  `endTime` varchar(50) DEFAULT NULL,
-                                  `secrecy` varchar(50) DEFAULT NULL,
-                                  `ipAddress` varchar(50) DEFAULT NULL,
-                                  `port` int(11) DEFAULT NULL,
-                                  `password` varchar(255) DEFAULT NULL,
-                                  `PTZType` int(11) DEFAULT NULL,
-                                  `status` int(11) DEFAULT NULL,
-                                  `longitude` double DEFAULT NULL,
-                                  `latitude` double DEFAULT NULL,
-                                  `streamId` varchar(50) DEFAULT NULL,
-                                  `deviceId` varchar(50) NOT NULL,
-                                  `parental` varchar(50) DEFAULT NULL,
-                                  `hasAudio` bit(1) DEFAULT NULL,
-                                  `createTime` varchar(50) NOT NULL,
-                                  `updateTime` varchar(50) NOT NULL,
-                                  `subCount` int(11) DEFAULT '0',
-                                  PRIMARY KEY (`id`),
-                                  UNIQUE KEY `device_channel_id_uindex` (`id`),
-                                  UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`)
-) ENGINE=InnoDB AUTO_INCREMENT=81657 DEFAULT CHARSET=utf8mb4;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `manufacture` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `owner` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `civilCode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `block` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `safetyWay` int DEFAULT NULL,
+  `registerWay` int DEFAULT NULL,
+  `certNum` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `certifiable` int DEFAULT NULL,
+  `errCode` int DEFAULT NULL,
+  `endTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `secrecy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `ipAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `port` int DEFAULT NULL,
+  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `PTZType` int DEFAULT NULL,
+  `status` int DEFAULT NULL,
+  `longitude` double DEFAULT NULL,
+  `latitude` double DEFAULT NULL,
+  `streamId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `parental` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `hasAudio` bit(1) DEFAULT NULL,
+  `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `subCount` int DEFAULT '0',
+  `longitudeGcj02` double DEFAULT NULL,
+  `latitudeGcj02` double DEFAULT NULL,
+  `longitudeWgs84` double DEFAULT NULL,
+  `latitudeWgs84` double DEFAULT NULL,
+  `businessGroupId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `device_channel_id_uindex` (`id`) USING BTREE,
+  UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=19314 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -151,24 +158,24 @@
 
 DROP TABLE IF EXISTS `device_mobile_position`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `device_mobile_position` (
-                                          `id` int(11) NOT NULL AUTO_INCREMENT,
-                                          `deviceId` varchar(50) NOT NULL,
-                                          `channelId` varchar(50) NOT NULL,
-                                          `deviceName` varchar(255) DEFAULT NULL,
-                                          `time` varchar(50) NOT NULL,
-                                          `longitude` double NOT NULL,
-                                          `latitude` double NOT NULL,
-                                          `altitude` double DEFAULT NULL,
-                                          `speed` double DEFAULT NULL,
-                                          `direction` double DEFAULT NULL,
-                                          `reportSource` varchar(50) DEFAULT NULL,
-                                          `geodeticSystem` varchar(50) DEFAULT NULL,
-                                          `cnLng` varchar(50) DEFAULT NULL,
-                                          `cnLat` varchar(50) DEFAULT NULL,
-                                          PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=6108 DEFAULT CHARSET=utf8mb4;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `deviceName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `longitude` double NOT NULL,
+  `latitude` double NOT NULL,
+  `altitude` double DEFAULT NULL,
+  `speed` double DEFAULT NULL,
+  `direction` double DEFAULT NULL,
+  `reportSource` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `geodeticSystem` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `cnLng` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `cnLat` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -186,23 +193,23 @@
 
 DROP TABLE IF EXISTS `gb_stream`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `gb_stream` (
-                             `gbStreamId` int(11) NOT NULL AUTO_INCREMENT,
-                             `app` varchar(255) NOT NULL,
-                             `stream` varchar(255) NOT NULL,
-                             `gbId` varchar(50) NOT NULL,
-                             `name` varchar(255) DEFAULT NULL,
-                             `longitude` double DEFAULT NULL,
-                             `latitude` double DEFAULT NULL,
-                             `streamType` varchar(50) DEFAULT NULL,
-                             `mediaServerId` varchar(50) DEFAULT NULL,
-                             `status` int(11) DEFAULT NULL,
-                             `createStamp` bigint(20) DEFAULT NULL,
-                             PRIMARY KEY (`gbStreamId`) USING BTREE,
-                             UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
-                             UNIQUE KEY `gbId` (`gbId`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=300769 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
+  `gbStreamId` int NOT NULL AUTO_INCREMENT,
+  `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `gbId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `longitude` double DEFAULT NULL,
+  `latitude` double DEFAULT NULL,
+  `streamType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `status` int DEFAULT NULL,
+  `createStamp` bigint DEFAULT NULL,
+  PRIMARY KEY (`gbStreamId`) USING BTREE,
+  UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
+  UNIQUE KEY `gbId` (`gbId`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=301679 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -220,19 +227,19 @@
 
 DROP TABLE IF EXISTS `log`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `log` (
-                       `id` int(11) NOT NULL AUTO_INCREMENT,
-                       `name` varchar(50) NOT NULL,
-                       `type` varchar(50) NOT NULL,
-                       `uri` varchar(200) NOT NULL,
-                       `address` varchar(50) NOT NULL,
-                       `result` varchar(50) NOT NULL,
-                       `timing` bigint(20) NOT NULL,
-                       `username` varchar(50) NOT NULL,
-                       `createTime` varchar(50) NOT NULL,
-                       PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=1552 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `uri` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `result` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `timing` bigint NOT NULL,
+  `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=21611 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -250,34 +257,34 @@
 
 DROP TABLE IF EXISTS `media_server`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `media_server` (
-                                `id` varchar(255) NOT NULL,
-                                `ip` varchar(50) NOT NULL,
-                                `hookIp` varchar(50) NOT NULL,
-                                `sdpIp` varchar(50) NOT NULL,
-                                `streamIp` varchar(50) NOT NULL,
-                                `httpPort` int(11) NOT NULL,
-                                `httpSSlPort` int(11) NOT NULL,
-                                `rtmpPort` int(11) NOT NULL,
-                                `rtmpSSlPort` int(11) NOT NULL,
-                                `rtpProxyPort` int(11) NOT NULL,
-                                `rtspPort` int(11) NOT NULL,
-                                `rtspSSLPort` int(11) NOT NULL,
-                                `autoConfig` int(11) NOT NULL,
-                                `secret` varchar(50) NOT NULL,
-                                `streamNoneReaderDelayMS` int(11) NOT NULL,
-                                `rtpEnable` int(11) NOT NULL,
-                                `rtpPortRange` varchar(50) NOT NULL,
-                                `sendRtpPortRange` varchar(50) NOT NULL,
-                                `recordAssistPort` int(11) NOT NULL,
-                                `defaultServer` int(11) NOT NULL,
-                                `createTime` varchar(50) NOT NULL,
-                                `updateTime` varchar(50) NOT NULL,
-                                `hookAliveInterval` int(11) NOT NULL,
-                                PRIMARY KEY (`id`) USING BTREE,
-                                UNIQUE KEY `media_server_i` (`ip`,`httpPort`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
+  `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `hookIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `sdpIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `streamIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `httpPort` int NOT NULL,
+  `httpSSlPort` int NOT NULL,
+  `rtmpPort` int NOT NULL,
+  `rtmpSSlPort` int NOT NULL,
+  `rtpProxyPort` int NOT NULL,
+  `rtspPort` int NOT NULL,
+  `rtspSSLPort` int NOT NULL,
+  `autoConfig` int NOT NULL,
+  `secret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `streamNoneReaderDelayMS` int NOT NULL,
+  `rtpEnable` int NOT NULL,
+  `rtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `sendRtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `recordAssistPort` int NOT NULL,
+  `defaultServer` int NOT NULL,
+  `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `hookAliveInterval` int NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `media_server_i` (`ip`,`httpPort`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -295,36 +302,36 @@
 
 DROP TABLE IF EXISTS `parent_platform`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `parent_platform` (
-                                   `id` int(11) NOT NULL AUTO_INCREMENT,
-                                   `enable` int(11) DEFAULT NULL,
-                                   `name` varchar(255) DEFAULT NULL,
-                                   `serverGBId` varchar(50) NOT NULL,
-                                   `serverGBDomain` varchar(50) DEFAULT NULL,
-                                   `serverIP` varchar(50) DEFAULT NULL,
-                                   `serverPort` int(11) DEFAULT NULL,
-                                   `deviceGBId` varchar(50) NOT NULL,
-                                   `deviceIp` varchar(50) DEFAULT NULL,
-                                   `devicePort` varchar(50) DEFAULT NULL,
-                                   `username` varchar(255) DEFAULT NULL,
-                                   `password` varchar(50) DEFAULT NULL,
-                                   `expires` varchar(50) DEFAULT NULL,
-                                   `keepTimeout` varchar(50) DEFAULT NULL,
-                                   `transport` varchar(50) DEFAULT NULL,
-                                   `characterSet` varchar(50) DEFAULT NULL,
-                                   `catalogId` varchar(50) NOT NULL,
-                                   `ptz` int(11) DEFAULT NULL,
-                                   `rtcp` int(11) DEFAULT NULL,
-                                   `status` bit(1) DEFAULT NULL,
-                                   `shareAllLiveStream` int(11) DEFAULT NULL,
-                                   `startOfflinePush` int(11) DEFAULT '0',
-                                   `administrativeDivision` varchar(50) NOT NULL,
-                                   `catalogGroup` int(11) DEFAULT '1',
-                                   PRIMARY KEY (`id`),
-                                   UNIQUE KEY `parent_platform_id_uindex` (`id`),
-                                   UNIQUE KEY `parent_platform_pk` (`serverGBId`)
-) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `enable` int DEFAULT NULL,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `serverGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `serverGBDomain` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `serverIP` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `serverPort` int DEFAULT NULL,
+  `deviceGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `deviceIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `devicePort` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `expires` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `keepTimeout` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `characterSet` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `ptz` int DEFAULT NULL,
+  `rtcp` int DEFAULT NULL,
+  `status` bit(1) DEFAULT NULL,
+  `shareAllLiveStream` int DEFAULT NULL,
+  `startOfflinePush` int DEFAULT '0',
+  `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `catalogGroup` int DEFAULT '1',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `parent_platform_id_uindex` (`id`) USING BTREE,
+  UNIQUE KEY `parent_platform_pk` (`serverGBId`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -342,14 +349,14 @@
 
 DROP TABLE IF EXISTS `platform_catalog`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `platform_catalog` (
-                                    `id` varchar(50) NOT NULL,
-                                    `platformId` varchar(50) NOT NULL,
-                                    `name` varchar(255) NOT NULL,
-                                    `parentId` varchar(50) DEFAULT NULL,
-                                    PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
+  `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -367,14 +374,14 @@
 
 DROP TABLE IF EXISTS `platform_gb_channel`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `platform_gb_channel` (
-                                       `id` int(11) NOT NULL AUTO_INCREMENT,
-                                       `platformId` varchar(50) NOT NULL,
-                                       `catalogId` varchar(50) NOT NULL,
-                                       `deviceChannelId` int(11) NOT NULL,
-                                       PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=250 DEFAULT CHARSET=utf8mb4;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `deviceChannelId` int NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=4889 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -392,15 +399,15 @@
 
 DROP TABLE IF EXISTS `platform_gb_stream`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `platform_gb_stream` (
-                                      `platformId` varchar(50) NOT NULL,
-                                      `catalogId` varchar(50) NOT NULL,
-                                      `gbStreamId` int(11) NOT NULL,
-                                      `id` int(11) NOT NULL AUTO_INCREMENT,
-                                      PRIMARY KEY (`id`),
-                                      UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`)
-) ENGINE=InnoDB AUTO_INCREMENT=301210 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
+  `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `gbStreamId` int NOT NULL,
+  `id` int NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=302077 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -418,29 +425,29 @@
 
 DROP TABLE IF EXISTS `stream_proxy`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `stream_proxy` (
-                                `id` int(11) NOT NULL AUTO_INCREMENT,
-                                `type` varchar(50) NOT NULL,
-                                `app` varchar(255) NOT NULL,
-                                `stream` varchar(255) NOT NULL,
-                                `url` varchar(255) DEFAULT NULL,
-                                `src_url` varchar(255) DEFAULT NULL,
-                                `dst_url` varchar(255) DEFAULT NULL,
-                                `timeout_ms` int(11) DEFAULT NULL,
-                                `ffmpeg_cmd_key` varchar(255) DEFAULT NULL,
-                                `rtp_type` varchar(50) DEFAULT NULL,
-                                `mediaServerId` varchar(50) DEFAULT NULL,
-                                `enable_hls` bit(1) DEFAULT NULL,
-                                `enable_mp4` bit(1) DEFAULT NULL,
-                                `enable` bit(1) NOT NULL,
-                                `status` bit(1) NOT NULL,
-                                `enable_remove_none_reader` bit(1) NOT NULL,
-                                `createTime` varchar(50) NOT NULL,
-                                `name` varchar(255) DEFAULT NULL,
-                                PRIMARY KEY (`id`),
-                                UNIQUE KEY `stream_proxy_pk` (`app`,`stream`)
-) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `src_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `dst_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `timeout_ms` int DEFAULT NULL,
+  `ffmpeg_cmd_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `rtp_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `enable_hls` bit(1) DEFAULT NULL,
+  `enable_mp4` bit(1) DEFAULT NULL,
+  `enable` bit(1) NOT NULL,
+  `status` bit(1) NOT NULL,
+  `enable_remove_none_reader` bit(1) NOT NULL,
+  `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `stream_proxy_pk` (`app`,`stream`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -458,21 +465,21 @@
 
 DROP TABLE IF EXISTS `stream_push`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `stream_push` (
-                               `id` int(11) NOT NULL AUTO_INCREMENT,
-                               `app` varchar(255) NOT NULL,
-                               `stream` varchar(255) NOT NULL,
-                               `totalReaderCount` varchar(50) DEFAULT NULL,
-                               `originType` int(11) DEFAULT NULL,
-                               `originTypeStr` varchar(50) DEFAULT NULL,
-                               `createStamp` bigint(20) DEFAULT NULL,
-                               `aliveSecond` int(11) DEFAULT NULL,
-                               `mediaServerId` varchar(50) DEFAULT NULL,
-                               `serverId` varchar(50) not NULL,
-                               PRIMARY KEY (`id`),
-                               UNIQUE KEY `stream_push_pk` (`app`,`stream`)
-) ENGINE=InnoDB AUTO_INCREMENT=300838 DEFAULT CHARSET=utf8mb4;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `totalReaderCount` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `originType` int DEFAULT NULL,
+  `originTypeStr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `createStamp` bigint DEFAULT NULL,
+  `aliveSecond` int DEFAULT NULL,
+  `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `serverId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `stream_push_pk` (`app`,`stream`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=305291 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -490,17 +497,17 @@
 
 DROP TABLE IF EXISTS `user`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `user` (
-                        `id` int(11) NOT NULL AUTO_INCREMENT,
-                        `username` varchar(255) NOT NULL,
-                        `password` varchar(255) NOT NULL,
-                        `roleId` int(11) NOT NULL,
-                        `createTime` varchar(50) NOT NULL,
-                        `updateTime` varchar(50) NOT NULL,
-                        PRIMARY KEY (`id`) USING BTREE,
-                        UNIQUE KEY `user_username_uindex` (`username`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `roleId` int NOT NULL,
+  `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `user_username_uindex` (`username`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -509,8 +516,7 @@
 
 LOCK TABLES `user` WRITE;
 /*!40000 ALTER TABLE `user` DISABLE KEYS */;
-INSERT INTO `user` VALUES
-    (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57');
+INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57');
 /*!40000 ALTER TABLE `user` ENABLE KEYS */;
 UNLOCK TABLES;
 
@@ -520,15 +526,15 @@
 
 DROP TABLE IF EXISTS `user_role`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
+/*!50503 SET character_set_client = utf8mb4 */;
 CREATE TABLE `user_role` (
-                             `id` int(11) NOT NULL AUTO_INCREMENT,
-                             `name` varchar(50) NOT NULL,
-                             `authority` varchar(50) NOT NULL,
-                             `createTime` varchar(50) NOT NULL,
-                             `updateTime` varchar(50) NOT NULL,
-                             PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
+  `id` int NOT NULL AUTO_INCREMENT,
+  `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `authority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -537,8 +543,7 @@
 
 LOCK TABLES `user_role` WRITE;
 /*!40000 ALTER TABLE `user_role` DISABLE KEYS */;
-INSERT INTO `user_role` VALUES
-    (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
+INSERT INTO `user_role` VALUES (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
 /*!40000 ALTER TABLE `user_role` ENABLE KEYS */;
 UNLOCK TABLES;
 /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
@@ -551,4 +556,4 @@
 /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
 /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
 
--- Dump completed on 2022-04-18 10:50:27
+-- Dump completed on 2022-06-26 17:33:30
diff --git a/sql/update.sql b/sql/update.sql
index f78744d..0ab8d29 100644
--- a/sql/update.sql
+++ b/sql/update.sql
@@ -2,7 +2,10 @@
     add serverId varchar(50) not null;
 alter table device
     add geoCoordSys varchar(50) not null;
+alter table device
+    add treeType varchar(50) not null;
 update device set device.geoCoordSys='WGS84';
+update device set device.treeType='CivilCode';
 alter table device_channel
     add longitudeGcj02 double default null;
 alter table device_channel
@@ -11,6 +14,8 @@
     add longitudeWgs84 double default null;
 alter table device_channel
     add latitudeWgs84 double default null;
+alter table device_channel
+    add businessGroupId varchar(50) default null;
 
 
 
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ChannelIdType.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ChannelIdType.java
new file mode 100644
index 0000000..320bbdd
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ChannelIdType.java
@@ -0,0 +1,23 @@
+package com.genersoft.iot.vmp.gb28181.bean;
+
+/**
+ * 鍥芥爣绫诲瀷缂栫爜,鍥芥爣缂栫爜涓�11-13浣嶄负绫诲瀷缂栫爜
+ * 璇﹁ 闄� 褰� D  缂栫爜瑙勫垯 A
+ * @author lin
+ */
+public class ChannelIdType {
+    /**
+     * 涓績淇′护鎺у埗鏈嶅姟鍣ㄧ紪鐮�
+     */
+    public final static String CENTRAL_SIGNALING_CONTROL_SERVER = "200";
+
+    /**
+     * 涓氬姟鍒嗙粍缂栫爜
+     */
+    public final static String BUSINESS_GROUP = "215";
+
+    /**
+     * 铏氭嫙缁勭粐缂栫爜
+     */
+    public final static String VIRTUAL_ORGANIZATION = "216";
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
index 253520b..880117f 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
@@ -138,6 +138,11 @@
 	 */
 	private String geoCoordSys;
 
+	/**
+	 * 鏍戠被鍨� 鍥芥爣瑙勫畾浜嗕袱绉嶆爲鐨勫睍鐜版柟寮� 琛屾斂鍖哄垝锛欳ivilCode 鍜屼笟鍔″垎缁�:BusinessGroup
+	 */
+	private String treeType;
+
 
 	public String getDeviceId() {
 		return deviceId;
@@ -338,4 +343,12 @@
 	public void setGeoCoordSys(String geoCoordSys) {
 		this.geoCoordSys = geoCoordSys;
 	}
+
+	public String getTreeType() {
+		return treeType;
+	}
+
+	public void setTreeType(String treeType) {
+		this.treeType = treeType;
+	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
index 6345277..16ead73 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
@@ -194,6 +194,11 @@
 	 */
 	private int channelType;
 
+	/**
+	 * 涓氬姟鍒嗙粍
+	 */
+	private String businessGroupId;
+
 	public int getId() {
 		return id;
 	}
@@ -506,4 +511,12 @@
 	public void setChannelType(int channelType) {
 		this.channelType = channelType;
 	}
+
+	public String getBusinessGroupId() {
+		return businessGroupId;
+	}
+
+	public void setBusinessGroupId(String businessGroupId) {
+		this.businessGroupId = businessGroupId;
+	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
index 2e70ea7..73f9c4f 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -406,7 +406,10 @@
         if (parentPlatform == null) {
             return false;
         }
-        logger.info("[鍙戦�� 绉诲姩浣嶇疆璁㈤槄] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
+        if (logger.isDebugEnabled()) {
+            logger.debug("[鍙戦�� 绉诲姩浣嶇疆璁㈤槄] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
+        }
+
         try {
             String characterSet = parentPlatform.getCharacterSet();
             StringBuffer deviceStatusXml = new StringBuffer(600);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index c2226a1..622cf07 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -141,6 +141,7 @@
                 device.setStreamMode("UDP");
                 device.setCharset("GB2312");
                 device.setGeoCoordSys("WGS84");
+                device.setTreeType("CivilCode");
                 device.setDeviceId(deviceId);
             }
             device.setIp(received);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
index 5ada1e4..0d34c00 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
@@ -249,23 +249,26 @@
             }else {
                 deviceChannel.setParentId(parentId);
             }
-        }else {
-            if (deviceChannel.getChannelId().length() <= 10) { // 姝ゆ椂涓鸿鏀垮尯鍒�, 涓婁笅绾ц鏀垮尯鍒掍娇鐢―eviceId鍏宠仈
-                deviceChannel.setParentId(deviceChannel.getChannelId().substring(0, deviceChannel.getChannelId().length() - 2));
-            }else if (deviceChannel.getChannelId().length() == 20) {
-                if (Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 216) { // 铏氭嫙缁勭粐
-                    deviceChannel.setParentId(businessGroupID);
-                }else if (Integer.parseInt(device.getDeviceId().substring(10, 13) )== 118) {//NVR 濡傛灉涓婄骇璁惧缂栧彿鏄疦VR鍒欑洿鎺ュ皢NVR鐨勭紪鍙疯缃粰閫氶亾鐨勪笂绾х紪鍙�
-                    deviceChannel.setParentId(device.getDeviceId());
-                }else if (deviceChannel.getCivilCode() != null) {
-                    // 璁惧锛� 鏃爌arentId鐨�20浣嶆槸浣跨敤CivilCode琛ㄧず涓婄骇鐨勮澶囷紝
-                    // 娉細215 涓氬姟鍒嗙粍鏄渶瑕佹湁parentId鐨�
-                    deviceChannel.setParentId(deviceChannel.getCivilCode());
-                }
-            }else {
-                deviceChannel.setParentId(deviceChannel.getDeviceId());
-            }
         }
+        deviceChannel.setBusinessGroupId(businessGroupID);
+
+//        else {
+//            if (deviceChannel.getChannelId().length() <= 10) { // 姝ゆ椂涓鸿鏀垮尯鍒�, 涓婁笅绾ц鏀垮尯鍒掍娇鐢―eviceId鍏宠仈
+//                deviceChannel.setParentId(deviceChannel.getChannelId().substring(0, deviceChannel.getChannelId().length() - 2));
+//            }else if (deviceChannel.getChannelId().length() == 20) {
+//                if (Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 216) { // 铏氭嫙缁勭粐
+//                    deviceChannel.setBusinessGroupId(businessGroupID);
+//                }else if (Integer.parseInt(device.getDeviceId().substring(10, 13) )== 118) {//NVR 濡傛灉涓婄骇璁惧缂栧彿鏄疦VR鍒欑洿鎺ュ皢NVR鐨勭紪鍙疯缃粰閫氶亾鐨勪笂绾х紪鍙�
+//                    deviceChannel.setParentId(device.getDeviceId());
+//                }else if (deviceChannel.getCivilCode() != null) {
+//                    // 璁惧锛� 鏃爌arentId鐨�20浣嶆槸浣跨敤CivilCode琛ㄧず涓婄骇鐨勮澶囷紝
+//                    // 娉細215 涓氬姟鍒嗙粍鏄渶瑕佹湁parentId鐨�
+//                    deviceChannel.setParentId(deviceChannel.getCivilCode());
+//                }
+//            }else {
+//                deviceChannel.setParentId(deviceChannel.getDeviceId());
+//            }
+//        }
 
         if (XmlUtil.getText(itemDevice, "SafetyWay") == null
                 || XmlUtil.getText(itemDevice, "SafetyWay") == "") {
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java b/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
index 72af803..5b43496 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
@@ -1,7 +1,9 @@
 package com.genersoft.iot.vmp.service;
 
 import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
+import com.genersoft.iot.vmp.vmanager.bean.BaseTree;
 
 import java.util.List;
 
@@ -110,4 +112,21 @@
      * @param device 璁惧淇℃伅
      */
     void updateDevice(Device device);
+
+    /**
+     * 鏍戝舰鏌ヨ鎺ュ彛
+     * @param deviceId 璁惧ID
+     * @param parentId 鐖禝D
+     * @param onlyCatalog 鍙幏鍙栫洰褰�
+     * @return
+     */
+    List<BaseTree<DeviceChannel>> queryVideoDeviceTree(String deviceId, String parentId, boolean onlyCatalog);
+
+    /**
+     * 鏌ヨ鏍戣妭鐐逛笅鐨勯�氶亾
+     * @param deviceId 璁惧ID
+     * @param parentId 鐖禝D
+     * @return
+     */
+    List<DeviceChannel> queryVideoDeviceInTreeNode(String deviceId, String parentId);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
index ec30cd4..9d376fb 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -1,9 +1,7 @@
 package com.genersoft.iot.vmp.service.impl;
 
 import com.genersoft.iot.vmp.conf.DynamicTask;
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
-import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
+import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
@@ -12,20 +10,23 @@
 import com.genersoft.iot.vmp.service.IDeviceService;
 import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
-import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
 import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
 import com.genersoft.iot.vmp.utils.DateUtil;
+import com.genersoft.iot.vmp.vmanager.bean.BaseTree;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.support.incrementer.AbstractIdentityColumnMaxValueIncrementer;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 
 import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
@@ -341,4 +342,180 @@
        }
         storage.updateChannels(device.getDeviceId(), deviceChannels);
     }
+
+
+    @Override
+    public List<BaseTree<DeviceChannel>> queryVideoDeviceTree(String deviceId, String parentId, boolean onlyCatalog) {
+        Device device = deviceMapper.getDeviceByDeviceId(deviceId);
+        if (device == null) {
+            return null;
+        }
+        if (parentId == null || parentId.equals(deviceId)) {
+            // 瀛楁牴鑺傜偣寮�濮嬫煡璇�
+            List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), true, !onlyCatalog);
+            return transportChannelsToTree(rootNodes, "");
+        }
+
+        if ("CivilCode".equals(device.getTreeType())) {
+            if (parentId.length()%2 != 0) {
+                return null;
+            }
+            // 浣跨敤琛屾斂鍖哄垝灞曠ず鏍�
+            if (parentId.length() > 10) {
+                // TODO 鍙兘鏄鏀垮尯鍒掍笌涓氬姟鍒嗙粍娣锋潅鐨勬儏褰�
+                return null;
+            }
+
+            if (parentId.length() == 10 ) {
+                if (onlyCatalog) {
+                    return null;
+                }
+                // parentId涓鸿涓氱紪鐮侊紝 鍏朵笅涓嶄細鍐嶆湁琛屾斂鍖哄垝
+                List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
+                List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(channels, parentId);
+                return trees;
+            }
+            // 鏌ヨ鍏朵笅鐨勮鏀垮尯鍒掑拰鎽勫儚鏈�
+            List<DeviceChannel> channelsForCivilCode = deviceChannelMapper.getChannelsWithCivilCodeAndLength(deviceId, parentId, parentId.length() + 2);
+            if (!onlyCatalog) {
+                List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
+                channelsForCivilCode.addAll(channels);
+            }
+            List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(channelsForCivilCode, parentId);
+            return trees;
+
+        }
+        // 浣跨敤涓氬姟鍒嗙粍灞曠ず鏍�
+        if ("BusinessGroup".equals(device.getTreeType())) {
+            if (parentId.length() < 14 ) {
+                return null;
+            }
+            List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null);
+            List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(deviceChannels, parentId);
+            return trees;
+        }
+
+        return null;
+    }
+
+    @Override
+    public List<DeviceChannel> queryVideoDeviceInTreeNode(String deviceId, String parentId) {
+        Device device = deviceMapper.getDeviceByDeviceId(deviceId);
+        if (device == null) {
+            return null;
+        }
+        if (parentId == null || parentId.equals(deviceId)) {
+            // 瀛楁牴鑺傜偣寮�濮嬫煡璇�
+            List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), false, true);
+            return rootNodes;
+        }
+
+        if ("CivilCode".equals(device.getTreeType())) {
+            if (parentId.length()%2 != 0) {
+                return null;
+            }
+            // 浣跨敤琛屾斂鍖哄垝灞曠ず鏍�
+            if (parentId.length() > 10) {
+                // TODO 鍙兘鏄鏀垮尯鍒掍笌涓氬姟鍒嗙粍娣锋潅鐨勬儏褰�
+                return null;
+            }
+
+            if (parentId.length() == 10 ) {
+                // parentId涓鸿涓氱紪鐮侊紝 鍏朵笅涓嶄細鍐嶆湁琛屾斂鍖哄垝
+                List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
+                return channels;
+            }
+            // 鏌ヨ鍏朵笅鐨勮鏀垮尯鍒掑拰鎽勫儚鏈�
+            List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
+            return channels;
+
+        }
+        // 浣跨敤涓氬姟鍒嗙粍灞曠ず鏍�
+        if ("BusinessGroup".equals(device.getTreeType())) {
+            if (parentId.length() < 14 ) {
+                return null;
+            }
+            List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null);
+            return deviceChannels;
+        }
+
+        return null;
+    }
+
+    private List<BaseTree<DeviceChannel>> transportChannelsToTree(List<DeviceChannel> channels, String parentId) {
+        if (channels == null) {
+            return null;
+        }
+        List<BaseTree<DeviceChannel>> treeNotes = new ArrayList<>();
+        if (channels.size() == 0) {
+            return treeNotes;
+        }
+        for (DeviceChannel channel : channels) {
+
+            BaseTree<DeviceChannel> node = new BaseTree<>();
+            node.setId(channel.getChannelId());
+            node.setDeviceId(channel.getDeviceId());
+            node.setName(channel.getName());
+            node.setPid(parentId);
+            node.setBasicData(channel);
+            node.setParent(false);
+            if (channel.getChannelId().length() > 8) {
+                String gbCodeType = channel.getChannelId().substring(10, 13);
+                node.setParent(gbCodeType.equals(ChannelIdType.BUSINESS_GROUP) || gbCodeType.equals(ChannelIdType.VIRTUAL_ORGANIZATION) );
+            }else {
+                node.setParent(true);
+            }
+            treeNotes.add(node);
+        }
+        Collections.sort(treeNotes);
+        return treeNotes;
+    }
+
+    private List<DeviceChannel> getRootNodes(String deviceId, boolean isCivilCode, boolean haveCatalog, boolean haveChannel) {
+        if (!haveCatalog && !haveChannel) {
+            return null;
+        }
+        List<DeviceChannel> result = new ArrayList<>();
+        if (isCivilCode) {
+            // 浣跨敤琛屾斂鍖哄垝
+            Integer length= deviceChannelMapper.getChannelMinLength(deviceId);
+            if (length == null) {
+                return null;
+            }
+            if (length <= 10) {
+                if (haveCatalog) {
+                    List<DeviceChannel> provinceNode = deviceChannelMapper.getChannelsWithCivilCodeAndLength(deviceId, null, length);
+                    if (provinceNode != null && provinceNode.size() > 0) {
+                        result.addAll(provinceNode);
+                    }
+                }
+
+                if (haveChannel) {
+                    // 鏌ヨ閭d簺civilCode涓嶅湪閫氶亾涓殑涓嶈鑼冮�氶亾锛屾斁缃湪鏍圭洰褰�
+                    List<DeviceChannel> nonstandardNode = deviceChannelMapper.getChannelWithoutCiviCode(deviceId);
+                    if (nonstandardNode != null && nonstandardNode.size() > 0) {
+                        result.addAll(nonstandardNode);
+                    }
+                }
+            }else {
+                if (haveChannel) {
+                    List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, null, null, null, null);
+                    if (deviceChannels != null && deviceChannels.size() > 0) {
+                        result.addAll(deviceChannels);
+                    }
+                }
+            }
+
+        }else {
+            // 浣跨敤涓氬姟鍒嗙粍+铏氭嫙缁勭粐
+
+            // 鍙幏鍙栦笟鍔″垎缁�
+            List<DeviceChannel> deviceChannels = deviceChannelMapper.getBusinessGroups(deviceId, ChannelIdType.BUSINESS_GROUP);
+            if (deviceChannels != null && deviceChannels.size() > 0) {
+                result.addAll(deviceChannels);
+            }
+        }
+        return result;
+    }
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 41eca5d..041fdf0 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -123,7 +123,7 @@
         result.onCompletion(()->{
             // 鐐规挱缁撴潫鏃惰皟鐢ㄦ埅鍥炬帴鍙�
             // TODO 搴旇鍦ㄤ笂娴佹椂璋冪敤鏇村ソ锛岀粨鏉熶篃鍙兘鏄敊璇粨鏉�
-            String path =  "static/static/snap/";
+            String path =  "snap";
             String fileName =  deviceId + "_" + channelId + ".jpg";
             ResponseEntity responseEntity =  (ResponseEntity)result.getResult();
             if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
@@ -177,7 +177,6 @@
                 streamInfo = null;
 
             }
-
 
         }
         if (streamInfo == null) {
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
index 5c46fb9..69ce4a7 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -1,5 +1,6 @@
 package com.genersoft.iot.vmp.storager.dao;
 
+import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform;
 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
@@ -17,10 +18,12 @@
 
     @Insert("INSERT INTO device_channel (channelId, deviceId, name, manufacture, model, owner, civilCode, block, " +
             "address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " +
-            "ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, longitudeWgs84, latitudeWgs84, createTime, updateTime) " +
+            "ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " +
+            "longitudeWgs84, latitudeWgs84, createTime, updateTime, businessGroupId) " +
             "VALUES ('${channelId}', '${deviceId}', '${name}', '${manufacture}', '${model}', '${owner}', '${civilCode}', '${block}'," +
             "'${address}', ${parental}, '${parentId}', ${safetyWay}, ${registerWay}, '${certNum}', ${certifiable}, ${errCode}, '${secrecy}', " +
-            "'${ipAddress}', ${port}, '${password}', ${PTZType}, ${status}, '${streamId}', ${longitude}, ${latitude}, ${longitudeGcj02}, ${latitudeGcj02}, ${longitudeWgs84}, ${latitudeWgs84},'${createTime}', '${updateTime}')")
+            "'${ipAddress}', ${port}, '${password}', ${PTZType}, ${status}, '${streamId}', ${longitude}, ${latitude}, ${longitudeGcj02}, " +
+            "${latitudeGcj02}, ${longitudeWgs84}, ${latitudeWgs84},'${createTime}', '${updateTime}', '${businessGroupId}')")
     int add(DeviceChannel channel);
 
     @Update(value = {" <script>" +
@@ -54,6 +57,7 @@
             "<if test='latitudeGcj02 != null'>, latitudeGcj02=${latitudeGcj02}</if>" +
             "<if test='longitudeWgs84 != null'>, longitudeWgs84=${longitudeWgs84}</if>" +
             "<if test='latitudeWgs84 != null'>, latitudeWgs84=${latitudeWgs84}</if>" +
+            "<if test='businessGroupId != null'>, businessGroupId=#{businessGroupId}</if>" +
             "WHERE deviceId='${deviceId}' AND channelId='${channelId}'"+
             " </script>"})
     int update(DeviceChannel channel);
@@ -143,7 +147,7 @@
             "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " +
             "  address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " +
             "  ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " +
-            "  longitudeWgs84, latitudeWgs84, createTime, updateTime) " +
+            "  longitudeWgs84, latitudeWgs84, createTime, updateTime, businessGroupId) " +
             "values " +
             "<foreach collection='addChannels' index='index' item='item' separator=','> " +
             "('${item.channelId}', '${item.deviceId}', '${item.name}', '${item.manufacture}', '${item.model}', " +
@@ -152,7 +156,7 @@
             "'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " +
             "'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " +
             "'${item.streamId}', ${item.longitude}, ${item.latitude},${item.longitudeGcj02}, " +
-            "${item.latitudeGcj02},${item.longitudeWgs84}, ${item.latitudeWgs84},'${item.createTime}', '${item.updateTime}')" +
+            "${item.latitudeGcj02},${item.longitudeWgs84}, ${item.latitudeWgs84},'${item.createTime}', '${item.updateTime}, '${item.businessGroupId}')" +
             "</foreach> " +
             "ON DUPLICATE KEY UPDATE " +
             "updateTime=VALUES(updateTime), " +
@@ -183,7 +187,8 @@
             "longitudeGcj02=VALUES(longitudeGcj02), " +
             "latitudeGcj02=VALUES(latitudeGcj02), " +
             "longitudeWgs84=VALUES(longitudeWgs84), " +
-            "latitudeWgs84=VALUES(latitudeWgs84) " +
+            "latitudeWgs84=VALUES(latitudeWgs84), " +
+            "businessGroupId=VALUES(businessGroupId) " +
             "</script>")
     int batchAdd(List<DeviceChannel> addChannels);
 
@@ -221,6 +226,7 @@
             "<if test='item.latitudeGcj02 != null'>, latitudeGcj02=${item.latitudeGcj02}</if>" +
             "<if test='item.longitudeWgs84 != null'>, longitudeWgs84=${item.longitudeWgs84}</if>" +
             "<if test='item.latitudeWgs84 != null'>, latitudeWgs84=${item.latitudeWgs84}</if>" +
+            "<if test='item.businessGroupId != null'>, businessGroupId=${item.businessGroupId}</if>" +
             "WHERE deviceId='${item.deviceId}' AND channelId='${item.channelId}'"+
             "</foreach>" +
             "</script>"})
@@ -277,4 +283,33 @@
 
     @Select("select * from device_channel where longitude*latitude > 0 and deviceId = #{deviceId}")
     List<DeviceChannel> getAllChannelWithCoordinate(String deviceId);
+
+
+    @Select(value = {" <script>" +
+            "select * " +
+            "from device_channel " +
+            "where deviceId=#{deviceId}" +
+            " <if test='parentId != null' > and left(channelId, ${parentId.length()}) = #{parentId}</if>" +
+            " <if test='length != null' > and length(channelId)=${length}</if>" +
+            " </script>"})
+    List<DeviceChannel> getChannelsWithCivilCodeAndLength(String deviceId, String parentId, Integer length);
+
+    @Select(value = {" <script>" +
+            "select * " +
+            "from device_channel " +
+            "where deviceId=#{deviceId} and length(channelId)>14 and civilCode=#{parentId}" +
+            " </script>"})
+    List<DeviceChannel> getChannelsByCivilCode(String deviceId, String parentId);
+
+    @Select("select min(length(channelId)) as minLength " +
+            "from device_channel " +
+            "where deviceId=#{deviceId}")
+    Integer getChannelMinLength(String deviceId);
+
+    @Select("select * from device_channel where deviceId=#{deviceId} and civilCode not in " +
+            "(select civilCode from device_channel where deviceId=#{deviceId} group by civilCode)")
+    List<DeviceChannel> getChannelWithoutCiviCode(String deviceId);
+
+    @Select("select * from device_channel where deviceId=#{deviceId} and SUBSTRING(channelId, 11, 3)=#{typeCode}")
+    List<DeviceChannel> getBusinessGroups(String deviceId, String typeCode);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
index 3e15b73..7e8dd3c 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
@@ -39,6 +39,7 @@
                 "subscribeCycleForAlarm," +
                 "ssrcCheck," +
                 "geoCoordSys," +
+                "treeType," +
                 "online" +
             ") VALUES (" +
                 "#{deviceId}," +
@@ -63,6 +64,7 @@
                 "#{subscribeCycleForAlarm}," +
                 "#{ssrcCheck}," +
                 "#{geoCoordSys}," +
+                "#{treeType}," +
                 "#{online}" +
             ")")
     int add(Device device);
@@ -90,6 +92,7 @@
                 "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=${subscribeCycleForAlarm}</if>" +
                 "<if test=\"ssrcCheck != null\">, ssrcCheck=${ssrcCheck}</if>" +
                 "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" +
+                "<if test=\"treeType != null\">, treeType=#{treeType}</if>" +
                 "WHERE deviceId='${deviceId}'"+
             " </script>"})
     int update(Device device);
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/BaseTree.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/BaseTree.java
new file mode 100644
index 0000000..23690e5
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/BaseTree.java
@@ -0,0 +1,87 @@
+package com.genersoft.iot.vmp.vmanager.bean;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.text.Collator;
+import java.util.Comparator;
+
+/**
+ * @author lin
+ */
+public class BaseTree<T> implements Comparable<BaseTree>{
+    private String id;
+
+    private String deviceId;
+    private String pid;
+    private String name;
+    private boolean parent;
+
+    private T basicData;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(String deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    public String getPid() {
+        return pid;
+    }
+
+    public void setPid(String pid) {
+        this.pid = pid;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public T getBasicData() {
+        return basicData;
+    }
+
+    public void setBasicData(T basicData) {
+        this.basicData = basicData;
+    }
+
+    public boolean isParent() {
+        return parent;
+    }
+
+    public void setParent(boolean parent) {
+        this.parent = parent;
+    }
+
+    @Override
+    public int compareTo(@NotNull BaseTree treeNode) {
+        if (this.parent || treeNode.isParent()) {
+            if (!this.parent && !treeNode.isParent()) {
+                Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);
+                return cmp.compare(treeNode.getName(), this.getName());
+            }else {
+                if (this.isParent()) {
+                    return 1;
+                }else {
+                    return -1;
+                }
+            }
+        }else{
+            Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);
+            return cmp.compare(treeNode.getName(), this.getName());
+        }
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
index 5e1e40b..767e9c4 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -15,6 +15,7 @@
 import com.genersoft.iot.vmp.service.IDeviceService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
+import com.genersoft.iot.vmp.vmanager.bean.BaseTree;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
@@ -479,4 +480,99 @@
 			resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
 		}
 	}
+
+	/**
+	 * 鏌ヨ鍥芥爣鏍�
+	 * @param deviceId 璁惧ID
+	 * @param parentId 鐖禝D
+	 * @param page 褰撳墠椤�
+	 * @param count 姣忛〉鏉℃暟
+	 * @return 鍥芥爣璁惧
+	 */
+	@ApiOperation("鏌ヨ鍥芥爣鏍�")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "deviceId", value = "璁惧ID", required = true, dataTypeClass = String.class),
+			@ApiImplicitParam(name = "parentId", value = "鐖禝D", required = false, dataTypeClass = String.class),
+			@ApiImplicitParam(name = "onlyCatalog", value = "鍙幏鍙栫洰褰�", required = false, dataTypeClass = Boolean.class),
+			@ApiImplicitParam(name="page", value = "褰撳墠椤�", required = true, dataTypeClass = Integer.class),
+			@ApiImplicitParam(name="count", value = "姣忛〉鏉℃暟", required = true, dataTypeClass = Integer.class),
+	})
+	@GetMapping("/tree/{deviceId}")
+	public ResponseEntity<PageInfo> getTree(@PathVariable String deviceId, @RequestParam(required = false) String parentId, @RequestParam(required = false) Boolean onlyCatalog, int page, int count){
+
+
+		if (page <= 0) {
+			page = 1;
+		}
+		if (onlyCatalog == null) {
+			onlyCatalog = false;
+		}
+
+		List<BaseTree<DeviceChannel>> treeData = deviceService.queryVideoDeviceTree(deviceId, parentId, onlyCatalog);
+		if (treeData == null || (page - 1) * count > treeData.size()) {
+			PageInfo<BaseTree<DeviceChannel>> pageInfo = new PageInfo<>();
+			pageInfo.setPageNum(page);
+			pageInfo.setTotal(treeData == null? 0 : treeData.size());
+			pageInfo.setSize(0);
+			pageInfo.setList(new ArrayList<>());
+			return new ResponseEntity<>(pageInfo,HttpStatus.OK);
+		}
+
+		int toIndex = Math.min(page * count, treeData.size());
+		// 澶勭悊鍒嗛〉
+		List<BaseTree<DeviceChannel>> trees = treeData.subList((page - 1) * count, toIndex);
+		PageInfo<BaseTree<DeviceChannel>> pageInfo = new PageInfo<>();
+		pageInfo.setPageNum(page);
+		pageInfo.setTotal(treeData.size());
+		pageInfo.setSize(trees.size());
+		pageInfo.setList(trees);
+
+		return new ResponseEntity<>(pageInfo,HttpStatus.OK);
+	}
+
+
+	/**
+	 * 鏌ヨ鍥芥爣鏍戜笅鐨勯�氶亾
+	 * @param deviceId 璁惧ID
+	 * @param parentId 鐖禝D
+	 * @param page 褰撳墠椤�
+	 * @param count 姣忛〉鏉℃暟
+	 * @return 鍥芥爣璁惧
+	 */
+	@ApiOperation("鏌ヨ鍥芥爣鏍戜笅鐨勯�氶亾")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "deviceId", value = "璁惧ID", required = true, dataTypeClass = String.class),
+			@ApiImplicitParam(name = "parentId", value = "鐖禝D", required = false, dataTypeClass = String.class),
+			@ApiImplicitParam(name="page", value = "褰撳墠椤�", required = true, dataTypeClass = Integer.class),
+			@ApiImplicitParam(name="count", value = "姣忛〉鏉℃暟", required = true, dataTypeClass = Integer.class),
+	})
+	@GetMapping("/tree/channel/{deviceId}")
+	public ResponseEntity<PageInfo> getChannelInTreeNode(@PathVariable String deviceId, @RequestParam(required = false) String parentId, int page, int count){
+
+
+		if (page <= 0) {
+			page = 1;
+		}
+
+		List<DeviceChannel> treeData = deviceService.queryVideoDeviceInTreeNode(deviceId, parentId);
+		if (treeData == null || (page - 1) * count > treeData.size()) {
+			PageInfo<BaseTree<DeviceChannel>> pageInfo = new PageInfo<>();
+			pageInfo.setPageNum(page);
+			pageInfo.setTotal(treeData == null? 0 : treeData.size());
+			pageInfo.setSize(0);
+			pageInfo.setList(new ArrayList<>());
+			return new ResponseEntity<>(pageInfo,HttpStatus.OK);
+		}
+
+		int toIndex = Math.min(page * count, treeData.size());
+		// 澶勭悊鍒嗛〉
+		List<DeviceChannel> trees = treeData.subList((page - 1) * count, toIndex);
+		PageInfo<DeviceChannel> pageInfo = new PageInfo<>();
+		pageInfo.setPageNum(page);
+		pageInfo.setTotal(treeData.size());
+		pageInfo.setSize(trees.size());
+		pageInfo.setList(trees);
+
+		return new ResponseEntity<>(pageInfo,HttpStatus.OK);
+	}
 }
diff --git a/src/main/resources/logback-spring-local.xml b/src/main/resources/logback-spring-local.xml
index ec80d2d..9e58355 100644
--- a/src/main/resources/logback-spring-local.xml
+++ b/src/main/resources/logback-spring-local.xml
@@ -11,6 +11,11 @@
 			<!--鏍煎紡鍖栬緭鍑猴細%d琛ㄧず鏃ユ湡锛�%thread琛ㄧず绾跨▼鍚嶏紝%-5level锛氱骇鍒粠宸︽樉绀�5涓瓧绗﹀搴�%msg锛氭棩蹇楁秷鎭紝%n鏄崲琛岀 -->
 			<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
 		</encoder>
+		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+			<!--涓嶵hresholdFilter鐨勫尯鍒�,鍏佽onmatch-->
+			<!--璁剧疆鏃ュ織绾у埆 鎺ユ敹info绾у埆鐨勬棩蹇�-->
+			<level>DEBUG</level>
+		</filter>
 	</appender>
 
 	<!-- 鎸夌収姣忓ぉ鐢熸垚鏃ュ織鏂囦欢 DEBUG浠ヤ笂绾у埆鐨勬棩蹇�,浠呯敤浜庢祴璇曠幆澧�,姝e紡鐜涓篿nfo绾у埆浠ヤ笂鐨勬棩蹇�-->
diff --git a/web_src/package-lock.json b/web_src/package-lock.json
index 0d4c886..8e0a324 100644
--- a/web_src/package-lock.json
+++ b/web_src/package-lock.json
@@ -22,7 +22,9 @@
         "vue-clipboards": "^1.3.0",
         "vue-contextmenujs": "^1.3.13",
         "vue-cookies": "^1.7.4",
-        "vue-router": "^3.1.6"
+        "vue-giant-tree": "^0.1.5",
+        "vue-router": "^3.1.6",
+        "vue-ztree-2.0": "^1.0.4"
       },
       "devDependencies": {
         "autoprefixer": "^7.1.2",
@@ -50,7 +52,7 @@
         "postcss-url": "^7.2.1",
         "rimraf": "^2.6.0",
         "semver": "^5.3.0",
-        "shelljs": "^0.7.6",
+        "shelljs": "^0.8.5",
         "uglifyjs-webpack-plugin": "^1.1.1",
         "url-loader": "^0.5.8",
         "vue-loader": "^13.3.0",
@@ -115,6 +117,17 @@
       "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
       "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==",
       "dev": true
+    },
+    "node_modules/@ztree/ztree_v3": {
+      "version": "3.5.48",
+      "resolved": "https://registry.npmmirror.com/@ztree/ztree_v3/-/ztree_v3-3.5.48.tgz",
+      "integrity": "sha512-4dSA1g26T3j/O3I89+r/Palg+a+xwMGRS1etZoggnCGBPoOrwW8VGA3zitJCK/Yd7eEMX+LfKTRJjEGiWpoN3w==",
+      "dependencies": {
+        "jquery": ">=1.4.4"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
     },
     "node_modules/accepts": {
       "version": "1.3.7",
@@ -6034,6 +6047,11 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/jquery": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmmirror.com/jquery/-/jquery-3.6.0.tgz",
+      "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
+    },
     "node_modules/js-base64": {
       "version": "2.6.4",
       "resolved": "https://registry.npm.taobao.org/js-base64/download/js-base64-2.6.4.tgz?cache=0&sync_timestamp=1599897619557&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-base64%2Fdownload%2Fjs-base64-2.6.4.tgz",
@@ -11655,9 +11673,9 @@
       }
     },
     "node_modules/shelljs": {
-      "version": "0.7.8",
-      "resolved": "https://registry.npm.taobao.org/shelljs/download/shelljs-0.7.8.tgz",
-      "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=",
+      "version": "0.8.5",
+      "resolved": "https://registry.npmmirror.com/shelljs/-/shelljs-0.8.5.tgz",
+      "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
       "dev": true,
       "dependencies": {
         "glob": "^7.0.0",
@@ -11668,8 +11686,7 @@
         "shjs": "bin/shjs"
       },
       "engines": {
-        "iojs": "*",
-        "node": ">=0.11.0"
+        "node": ">=4"
       }
     },
     "node_modules/shellwords": {
@@ -13068,6 +13085,15 @@
       "resolved": "https://registry.npm.taobao.org/vue-cookies/download/vue-cookies-1.7.4.tgz?cache=0&sync_timestamp=1598941352058&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-cookies%2Fdownload%2Fvue-cookies-1.7.4.tgz",
       "integrity": "sha1-0kHQoEMdoHlYN2UdELTXPnyNPo0="
     },
+    "node_modules/vue-giant-tree": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmmirror.com/vue-giant-tree/-/vue-giant-tree-0.1.5.tgz",
+      "integrity": "sha512-P3KEHSZU2NkpWl6frss+sJLO0DLrtarMNLeTV/IGU2/w50rgrlKbKNr/ckK6BBVdWXAJYlYf6HUTNkKvGq5hlg==",
+      "dependencies": {
+        "@ztree/ztree_v3": "^3.5.44",
+        "jquery": "^3.5.1"
+      }
+    },
     "node_modules/vue-hot-reload-api": {
       "version": "2.3.4",
       "resolved": "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz",
@@ -13174,6 +13200,11 @@
       "resolved": "https://registry.npm.taobao.org/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.9.1.tgz",
       "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
       "dev": true
+    },
+    "node_modules/vue-ztree-2.0": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmmirror.com/vue-ztree-2.0/-/vue-ztree-2.0-1.0.4.tgz",
+      "integrity": "sha512-d7KZsquEYpM0jD/k1uwOMFCd08L6++7zwRESaL2sF43OtRFCump8BxcLpjusBIHpFadPvOSMMnK5P41y+ZiTlA=="
     },
     "node_modules/watchpack": {
       "version": "1.7.4",
@@ -14418,6 +14449,14 @@
       "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
       "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==",
       "dev": true
+    },
+    "@ztree/ztree_v3": {
+      "version": "3.5.48",
+      "resolved": "https://registry.npmmirror.com/@ztree/ztree_v3/-/ztree_v3-3.5.48.tgz",
+      "integrity": "sha512-4dSA1g26T3j/O3I89+r/Palg+a+xwMGRS1etZoggnCGBPoOrwW8VGA3zitJCK/Yd7eEMX+LfKTRJjEGiWpoN3w==",
+      "requires": {
+        "jquery": ">=1.4.4"
+      }
     },
     "accepts": {
       "version": "1.3.7",
@@ -19488,6 +19527,11 @@
       "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
       "dev": true
     },
+    "jquery": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmmirror.com/jquery/-/jquery-3.6.0.tgz",
+      "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
+    },
     "js-base64": {
       "version": "2.6.4",
       "resolved": "https://registry.npm.taobao.org/js-base64/download/js-base64-2.6.4.tgz?cache=0&sync_timestamp=1599897619557&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-base64%2Fdownload%2Fjs-base64-2.6.4.tgz",
@@ -24156,9 +24200,9 @@
       "dev": true
     },
     "shelljs": {
-      "version": "0.7.8",
-      "resolved": "https://registry.npm.taobao.org/shelljs/download/shelljs-0.7.8.tgz",
-      "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=",
+      "version": "0.8.5",
+      "resolved": "https://registry.npmmirror.com/shelljs/-/shelljs-0.8.5.tgz",
+      "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
       "dev": true,
       "requires": {
         "glob": "^7.0.0",
@@ -25352,6 +25396,15 @@
       "resolved": "https://registry.npm.taobao.org/vue-cookies/download/vue-cookies-1.7.4.tgz?cache=0&sync_timestamp=1598941352058&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-cookies%2Fdownload%2Fvue-cookies-1.7.4.tgz",
       "integrity": "sha1-0kHQoEMdoHlYN2UdELTXPnyNPo0="
     },
+    "vue-giant-tree": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmmirror.com/vue-giant-tree/-/vue-giant-tree-0.1.5.tgz",
+      "integrity": "sha512-P3KEHSZU2NkpWl6frss+sJLO0DLrtarMNLeTV/IGU2/w50rgrlKbKNr/ckK6BBVdWXAJYlYf6HUTNkKvGq5hlg==",
+      "requires": {
+        "@ztree/ztree_v3": "^3.5.44",
+        "jquery": "^3.5.1"
+      }
+    },
     "vue-hot-reload-api": {
       "version": "2.3.4",
       "resolved": "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz",
@@ -25448,6 +25501,11 @@
       "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
       "dev": true
     },
+    "vue-ztree-2.0": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmmirror.com/vue-ztree-2.0/-/vue-ztree-2.0-1.0.4.tgz",
+      "integrity": "sha512-d7KZsquEYpM0jD/k1uwOMFCd08L6++7zwRESaL2sF43OtRFCump8BxcLpjusBIHpFadPvOSMMnK5P41y+ZiTlA=="
+    },
     "watchpack": {
       "version": "1.7.4",
       "resolved": "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.4.tgz?cache=0&sync_timestamp=1600385388649&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.4.tgz",
diff --git a/web_src/package.json b/web_src/package.json
index b825f84..d19a58d 100644
--- a/web_src/package.json
+++ b/web_src/package.json
@@ -24,7 +24,9 @@
     "vue-clipboards": "^1.3.0",
     "vue-contextmenujs": "^1.3.13",
     "vue-cookies": "^1.7.4",
-    "vue-router": "^3.1.6"
+    "vue-giant-tree": "^0.1.5",
+    "vue-router": "^3.1.6",
+    "vue-ztree-2.0": "^1.0.4"
   },
   "devDependencies": {
     "autoprefixer": "^7.1.2",
diff --git a/web_src/src/components/DeviceList.vue b/web_src/src/components/DeviceList.vue
index 1911d1d..97fa4f2 100644
--- a/web_src/src/components/DeviceList.vue
+++ b/web_src/src/components/DeviceList.vue
@@ -56,11 +56,11 @@
                      @mouseover="getTooltipContent(scope.row.deviceId)">鍒锋柊
           </el-button>
           <el-divider direction="vertical"></el-divider>
-          <el-button type="text" size="medium" icon="el-icon-video-camera" v-bind:disabled="scope.row.online==0"
+          <el-button type="text" size="medium" icon="el-icon-video-camera"
                      @click="showChannelList(scope.row)">閫氶亾
           </el-button>
           <el-divider direction="vertical"></el-divider>
-          <el-button size="medium" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="text"
+          <el-button size="medium" icon="el-icon-location" type="text"
                      @click="showDevicePosition(scope.row)">瀹氫綅
           </el-button>
           <el-divider direction="vertical"></el-divider>
@@ -192,7 +192,7 @@
 
     },
     showChannelList: function (row) {
-      this.$router.push(`/channelList/${row.deviceId}/0/15/1`);
+      this.$router.push(`/channelList/${row.deviceId}/0`);
     },
     showDevicePosition: function (row) {
       this.$router.push(`/map?deviceId=${row.deviceId}`);
diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue
index d27e62b..2a09c5c 100644
--- a/web_src/src/components/channelList.vue
+++ b/web_src/src/components/channelList.vue
@@ -7,104 +7,116 @@
         閫氶亾鍒楄〃
       </div>
       <div class="page-header-btn">
-      鎼滅储:
-      <el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="鍏抽敭瀛�"
-                prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
+        <div v-if="!showTree" style="display: inline;">
+          鎼滅储:
+          <el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="鍏抽敭瀛�"
+                    prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
 
-      閫氶亾绫诲瀷:
-      <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="璇烽�夋嫨"
-                 default-first-option>
-        <el-option label="鍏ㄩ儴" value=""></el-option>
-        <el-option label="璁惧" value="false"></el-option>
-        <el-option label="瀛愮洰褰�" value="true"></el-option>
-      </el-select>
-      鍦ㄧ嚎鐘舵��:
-      <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="璇烽�夋嫨"
-                 default-first-option>
-        <el-option label="鍏ㄩ儴" value=""></el-option>
-        <el-option label="鍦ㄧ嚎" value="true"></el-option>
-        <el-option label="绂荤嚎" value="false"></el-option>
-      </el-select>
+          閫氶亾绫诲瀷:
+          <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="璇烽�夋嫨"
+                     default-first-option>
+            <el-option label="鍏ㄩ儴" value=""></el-option>
+            <el-option label="璁惧" value="false"></el-option>
+            <el-option label="瀛愮洰褰�" value="true"></el-option>
+          </el-select>
+          鍦ㄧ嚎鐘舵��:
+          <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="璇烽�夋嫨"
+                     default-first-option>
+            <el-option label="鍏ㄩ儴" value=""></el-option>
+            <el-option label="鍦ㄧ嚎" value="true"></el-option>
+            <el-option label="绂荤嚎" value="false"></el-option>
+          </el-select>
+        </div>
       <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
+      <el-button v-if="showTree" icon="iconfont icon-list" circle size="mini" @click="switchList()"></el-button>
+      <el-button v-if="!showTree"  icon="iconfont icon-tree" circle size="mini" @click="switchTree()"></el-button>
     </div>
   </div>
   <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
+  <el-container v-loading="isLoging" style="height: 82vh;">
+    <el-aside width="auto" style="height: 82vh; background-color: #ffffff; overflow: auto" v-if="showTree" >
+      <DeviceTree ref="deviceTree" :device="device" :onlyCatalog="true" :clickEvent="treeNodeClickEvent" ></DeviceTree>
+    </el-aside>
+    <el-main style="padding: 5px;">
+      <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" style="width: 100%" header-row-class-name="table-header">
+        <el-table-column prop="channelId" label="閫氶亾缂栧彿" min-width="200">
+        </el-table-column>
+        <el-table-column prop="deviceId" label="璁惧缂栧彿" min-width="200">
+        </el-table-column>
+        <el-table-column prop="name" label="閫氶亾鍚嶇О" min-width="200">
+        </el-table-column>
+        <el-table-column label="蹇収" min-width="120">
+          <template v-slot:default="scope">
+            <el-image
+              :src="getSnap(scope.row)"
+              :preview-src-list="getBigSnap(scope.row)"
+              @error="getSnapErrorEvent(scope.row.deviceId, scope.row.channelId)"
+              :fit="'contain'"
+              style="width: 60px">
+              <div slot="error" class="image-slot">
+                <i class="el-icon-picture-outline"></i>
+              </div>
+            </el-image>
+          </template>
+        </el-table-column>
+        <el-table-column prop="subCount" label="瀛愯妭鐐规暟" min-width="120">
+        </el-table-column>
+        <el-table-column prop="manufacture" label="鍘傚" min-width="120">
+        </el-table-column>
+        <el-table-column label="浣嶇疆淇℃伅"  min-width="200">
+          <template slot-scope="scope">
+            <span v-if="scope.row.longitude*scope.row.latitude > 0">{{ scope.row.longitude }},<br>{{ scope.row.latitude }}</span>
+            <span v-if="scope.row.longitude*scope.row.latitude === 0">鏃�</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="ptztypeText" label="浜戝彴绫诲瀷" min-width="120"/>
+        <el-table-column label="寮�鍚煶棰�" min-width="120">
+          <template slot-scope="scope">
+            <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
+            </el-switch>
+          </template>
+        </el-table-column>
+        <el-table-column label="鐘舵��" min-width="120">
+          <template slot-scope="scope">
+            <div slot="reference" class="name-wrapper">
+              <el-tag size="medium" v-if="scope.row.status === 1">鍦ㄧ嚎</el-tag>
+              <el-tag size="medium" type="info" v-if="scope.row.status === 0">绂荤嚎</el-tag>
+            </div>
+          </template>
+        </el-table-column>
+
+
+        <el-table-column label="鎿嶄綔" min-width="280" fixed="right">
+          <template slot-scope="scope">
+            <el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play" type="text" @click="sendDevicePush(scope.row)">鎾斁</el-button>
+            <el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-switch-button" type="text"  style="color: #f56c6c" v-if="!!scope.row.streamId"
+                       @click="stopDevicePush(scope.row)">鍋滄
+            </el-button>
+            <el-divider direction="vertical"></el-divider>
+            <el-button size="medium" icon="el-icon-s-open" type="text" v-if="scope.row.subCount > 0 || scope.row.parental === 1"
+                       @click="changeSubchannel(scope.row)">鏌ョ湅
+            </el-button>
+            <el-divider v-if="scope.row.subCount > 0 || scope.row.parental === 1" direction="vertical"></el-divider>
+            <el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-camera" type="text" @click="queryRecords(scope.row)">璁惧褰曞儚
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination
+        style="float: right"
+        @size-change="handleSizeChange"
+        @current-change="currentChange"
+        :current-page="currentPage"
+        :page-size="count"
+        :page-sizes="[15, 25, 35, 50]"
+        layout="total, sizes, prev, pager, next"
+        :total="total">
+      </el-pagination>
+    </el-main>
+  </el-container>
+
   <!--璁惧鍒楄〃-->
-  <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" style="width: 100%" header-row-class-name="table-header">
-    <el-table-column prop="channelId" label="閫氶亾缂栧彿" min-width="200">
-    </el-table-column>
-    <el-table-column prop="deviceId" label="璁惧缂栧彿" min-width="200">
-    </el-table-column>
-    <el-table-column prop="name" label="閫氶亾鍚嶇О" min-width="200">
-    </el-table-column>
-    <el-table-column label="蹇収" min-width="120">
-      <template v-slot:default="scope">
-        <el-image
-          :src="getSnap(scope.row)"
-          :preview-src-list="getBigSnap(scope.row)"
-          @error="getSnapErrorEvent(scope.row.deviceId, scope.row.channelId)"
-          :fit="'contain'"
-          style="width: 60px">
-          <div slot="error" class="image-slot">
-            <i class="el-icon-picture-outline"></i>
-          </div>
-        </el-image>
-      </template>
-    </el-table-column>
-    <el-table-column prop="subCount" label="瀛愯妭鐐规暟" min-width="120">
-    </el-table-column>
-    <el-table-column prop="manufacture" label="鍘傚" min-width="120">
-    </el-table-column>
-    <el-table-column label="浣嶇疆淇℃伅"  min-width="200">
-      <template slot-scope="scope">
-        <span v-if="scope.row.longitude*scope.row.latitude > 0">{{ scope.row.longitude }},<br>{{ scope.row.latitude }}</span>
-        <span v-if="scope.row.longitude*scope.row.latitude === 0">鏃�</span>
-      </template>
-    </el-table-column>
-    <el-table-column prop="ptztypeText" label="浜戝彴绫诲瀷" min-width="120"/>
-    <el-table-column label="寮�鍚煶棰�" min-width="120">
-      <template slot-scope="scope">
-        <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
-        </el-switch>
-      </template>
-    </el-table-column>
-    <el-table-column label="鐘舵��" min-width="120">
-      <template slot-scope="scope">
-        <div slot="reference" class="name-wrapper">
-          <el-tag size="medium" v-if="scope.row.status === 1">鍦ㄧ嚎</el-tag>
-          <el-tag size="medium" type="info" v-if="scope.row.status === 0">绂荤嚎</el-tag>
-        </div>
-      </template>
-    </el-table-column>
 
-
-    <el-table-column label="鎿嶄綔" min-width="280" fixed="right">
-      <template slot-scope="scope">
-        <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">鎾斁</el-button> -->
-        <el-button size="medium" icon="el-icon-video-play" type="text" @click="sendDevicePush(scope.row)">鎾斁</el-button>
-        <el-button size="medium" icon="el-icon-switch-button" type="text"  style="color: #f56c6c" v-if="!!scope.row.streamId"
-                   @click="stopDevicePush(scope.row)">鍋滄
-        </el-button>
-        <el-divider direction="vertical"></el-divider>
-        <el-button size="medium" icon="el-icon-s-open" type="text" v-if="scope.row.subCount > 0 || scope.row.parental === 1"
-                   @click="changeSubchannel(scope.row)">鏌ョ湅
-        </el-button>
-        <el-divider v-if="scope.row.subCount > 0 || scope.row.parental === 1" direction="vertical"></el-divider>
-        <el-button size="medium" icon="el-icon-video-camera" type="text" @click="queryRecords(scope.row)">璁惧褰曞儚
-        </el-button>
-      </template>
-    </el-table-column>
-  </el-table>
-  <el-pagination
-    style="float: right"
-    @size-change="handleSizeChange"
-    @current-change="currentChange"
-    :current-page="currentPage"
-    :page-size="count"
-    :page-sizes="[15, 25, 35, 50]"
-    layout="total, sizes, prev, pager, next"
-    :total="total">
-  </el-pagination>
   </div>
 </template>
 
@@ -114,12 +126,14 @@
 import moment from "moment";
 import DviceService from "./service/DeviceService";
 import DeviceService from "./service/DeviceService";
+import DeviceTree from "./common/DeviceTree";
 
 export default {
   name: 'channelList',
   components: {
     devicePlayer,
-    uiHeader
+    uiHeader,
+    DeviceTree
   },
   data() {
     return {
@@ -134,12 +148,13 @@
       searchSrt: "",
       channelType: "",
       online: "",
-      winHeight: window.innerHeight - 250,
-      currentPage: parseInt(this.$route.params.page),
-      count: parseInt(this.$route.params.count),
+      winHeight: window.innerHeight - 200,
+      currentPage: 1,
+      count: 15,
       total: 0,
       beforeUrl: "/deviceList",
       isLoging: false,
+      showTree: false,
       loadSnap: {}
     };
   },
@@ -172,19 +187,16 @@
     initParam: function () {
       this.deviceId = this.$route.params.deviceId;
       this.parentChannelId = this.$route.params.parentChannelId;
-      this.currentPage = parseInt(this.$route.params.page);
-      this.count = parseInt(this.$route.params.count);
+      this.currentPage = 1;
+      this.count = 15;
       if (this.parentChannelId == "" || this.parentChannelId == 0) {
         this.beforeUrl = "/deviceList"
       }
 
     },
     currentChange: function (val) {
-      var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}`
-      this.$router.push(url).then(() => {
-        this.initParam();
-        this.initData();
-      })
+      this.currentPage = val;
+      this.initData();
     },
     handleSizeChange: function (val) {
       this.count = val;
@@ -316,28 +328,48 @@
       })
     },
     showSubchannels: function (channelId) {
-      let that = this;
+      if (!this.showTree) {
+        this.$axios({
+          method: 'get',
+          url: `/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
+          params: {
+            page: this.currentPage,
+            count: this.count,
+            query: this.searchSrt,
+            online: this.online,
+            channelType: this.channelType
+          }
+        }).then( (res) =>{
+          this.total = res.data.total;
+          this.deviceChannelList = res.data.list;
+          // 闃叉鍑虹幇琛ㄦ牸閿欎綅
+          this.$nextTick(() => {
+            this.$refs.channelListTable.doLayout();
+          })
+        }).catch(function (error) {
+          console.log(error);
+        });
+      }else {
+        this.$axios({
+          method: 'get',
+          url: `/api/device/query/tree/channel/${this.deviceId}`,
+          params: {
+            parentId: this.parentChannelId,
+            page: this.currentPage,
+            count: this.count,
+          }
+        }).then((res)=> {
+          this.total = res.data.total;
+          this.deviceChannelList = res.data.list;
+          // 闃叉鍑虹幇琛ㄦ牸閿欎綅
+          this.$nextTick(() => {
+            this.$refs.channelListTable.doLayout();
+          })
+        }).catch(function (error) {
+          console.log(error);
+        });
+      }
 
-      this.$axios({
-        method: 'get',
-        url: `/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
-        params: {
-          page: that.currentPage,
-          count: that.count,
-          query: that.searchSrt,
-          online: that.online,
-          channelType: that.channelType
-        }
-      }).then(function (res) {
-        that.total = res.data.total;
-        that.deviceChannelList = res.data.list;
-        // 闃叉鍑虹幇琛ㄦ牸閿欎綅
-        that.$nextTick(() => {
-          that.$refs.channelListTable.doLayout();
-        })
-      }).catch(function (error) {
-        console.log(error);
-      });
     },
     search: function () {
       this.currentPage = 1;
@@ -355,6 +387,29 @@
     },
     refresh: function () {
       this.initData();
+    },
+    switchTree: function (){
+      this.showTree = true;
+      this.deviceChannelList = [];
+      this.parentChannelId = 0;
+      this.currentPage = 1;
+
+    },
+    switchList: function (){
+      this.showTree = false;
+      this.deviceChannelList = [];
+      this.parentChannelId = 0;
+      this.currentPage = 1;
+      this.initData();
+    },
+    treeNodeClickEvent: function (device, data, isCatalog) {
+      console.log(device)
+      if (!!!data.channelId) {
+        this.parentChannelId = device.deviceId;
+      }else {
+        this.parentChannelId = data.channelId;
+      }
+      this.initData();
     }
 
   }
diff --git a/web_src/src/components/common/DeviceTree.vue b/web_src/src/components/common/DeviceTree.vue
index 73618cc..c701bf0 100644
--- a/web_src/src/components/common/DeviceTree.vue
+++ b/web_src/src/components/common/DeviceTree.vue
@@ -4,7 +4,7 @@
       <el-header>璁惧鍒楄〃</el-header>
       <el-main style="background-color: #ffffff;">
         <div class="device-tree-main-box">
-          <el-tree :props="defaultProps" :load="loadNode" lazy @node-click="handleNodeClick"@node-contextmenu="handleContextMenu" style="min-width: 100%; display:inline-block !important;">
+          <el-tree ref="gdTree" :props="defaultProps" :load="loadNode" lazy @node-click="handleNodeClick"@node-contextmenu="handleContextMenu" node-key="id" style="min-width: 100%; display:inline-block !important;">
             <span class="custom-tree-node" slot-scope="{ node, data }" style="width: 100%">
               <span v-if="node.data.type === 0 && node.data.online" title="鍦ㄧ嚎璁惧" class="device-online iconfont icon-jiedianleizhukongzhongxin2"></span>
               <span v-if="node.data.type === 0 && !node.data.online " title="绂荤嚎璁惧" class="device-offline iconfont icon-jiedianleizhukongzhongxin2"></span>
@@ -47,98 +47,112 @@
           }
         };
     },
-    props: ['clickEvent', 'contextMenuEvent'],
+    props: ['device', 'onlyCatalog', 'clickEvent', 'contextMenuEvent'],
     methods: {
       handleNodeClick(data,node,element) {
-        console.log("鐐瑰嚮浜嬩欢")
-        console.log(data)
+        let deviceNode = this.$refs.gdTree.getNode(data.userData.deviceId)
         if(typeof (this.clickEvent) == "function") {
-          this.clickEvent(data.userData)
+          this.clickEvent(deviceNode.data.userData, data.userData, data.type === 2)
         }
       },
       handleContextMenu(event,data,node,element) {
         console.log("鍙抽敭鐐瑰嚮浜嬩欢")
+        let deviceNode = this.$refs.gdTree.getNode(data.userData.deviceId)
         if(typeof (this.contextMenuEvent) == "function") {
-          this.contextMenuEvent(event, data.userData)
+          this.contextMenuEvent(deviceNode.data.userData, event, data.userData, data.type === 2)
         }
       },
       loadNode: function(node, resolve){
+        console.log(this.device)
         if (node.level === 0) {
-          this.deviceService.getAllDeviceList((data)=>{
-            console.log(data)
-            if (data.length > 0) {
-              let nodeList = []
-              for (let i = 0; i < data.length; i++) {
-                console.log(data[i].name)
-                let node = {
-                  name: data[i].name || data[i].deviceId,
-                  isLeaf: false,
-                  id: data[i].deviceId,
-                  type: data[i].online,
-                  online: data[i].online === 1,
-                  userData: data[i]
-                }
-                nodeList.push(node);
-              }
-              resolve(nodeList)
-            }else {
-              resolve([])
+          if (this.device) {
+            let node = {
+              name: this.device.name || this.device.deviceId,
+              isLeaf: false,
+              id: this.device.deviceId,
+              type: this.device.online,
+              online: this.device.online === 1,
+              userData: this.device
             }
-          }, (list)=>{
+            resolve([node])
+          }else {
+            this.deviceService.getAllDeviceList((data)=>{
+              console.log(data)
+              if (data.length > 0) {
+                let nodeList = []
+                for (let i = 0; i < data.length; i++) {
+                  console.log(data[i].name)
+                  let node = {
+                    name: data[i].name || data[i].deviceId,
+                    isLeaf: false,
+                    id: data[i].deviceId,
+                    type: data[i].online,
+                    online: data[i].online === 1,
+                    userData: data[i]
+                  }
+                  nodeList.push(node);
+                }
+                resolve(nodeList)
+              }else {
+                resolve([])
+              }
+            }, (list)=>{
               console.log("璁惧鍔犺浇瀹屾垚")
-          }, (error)=>{
+            }, (error)=>{
 
-          })
-        }
-        if (node.level === 1) {
+            })
+          }
+        }else {
           let channelArray = []
-          this.deviceService.getAllChannel(true, true, node.data.id, catalogData =>{
+
+          this.deviceService.getTree(node.data.userData.deviceId, node.data.id, this.onlyCatalog, catalogData =>{
+            console.log(catalogData)
             channelArray = channelArray.concat(catalogData)
             this.channelDataHandler(channelArray, resolve)
           },(endCatalogData) => {
-            this.deviceService.getAllChannel(false, true, node.data.id, channelData => {
-              channelArray = channelArray.concat(channelData)
-              this.channelDataHandler(channelArray, resolve)
-            }, endChannelList => {
 
-            })
-          })
-        }else if (node.level > 1){
-          let channelArray = []
-          this.deviceService.getAllSubChannel(true, node.data.deviceId, node.data.id, (catalogData)=>{
-            channelArray = channelArray.concat(catalogData)
-            this.channelDataHandler(channelArray, resolve)
-          }, (endCatalogData)=>{
-            this.deviceService.getAllSubChannel(false, node.data.deviceId, node.data.id, (channelData)=>{
-              channelArray = channelArray.concat(channelData)
-              this.channelDataHandler(channelArray, resolve)
-            })
           })
         }
+
       },
       channelDataHandler: function (data, resolve) {
         if (data.length > 0) {
           let nodeList = []
-          for (let i = 0; i < data.length; i++) {
+          for (let i = 0; i <data.length; i++) {
+            let item = data[i];
             let type = 3;
-            if (data[i].subCount > 0 || data[i].parental === 1) {
+            if (item.id.length <= 10) {
               type = 2;
-            }else if (data[i].ptztype === 1 ) { // 1-鐞冩満;2-鍗婄悆;3-鍥哄畾鏋満;4-閬ユ帶鏋満
-              type = 4;
-            }else if (data[i].ptztype === 2) {
-              type = 5;
-            }else if (data[i].ptztype === 3 || data[i].ptztype === 4) {
-              type = 6;
+            }else {
+              if (item.id.length > 14) {
+                let channelType = item.id.substring(10, 13)
+                console.log("channelType: " + channelType)
+                if (channelType === '215' || channelType === '216') {
+                  type = 2;
+                }
+                console.log(type)
+                if (item.basicData.ptztype === 1 ) { // 1-鐞冩満;2-鍗婄悆;3-鍥哄畾鏋満;4-閬ユ帶鏋満
+                  type = 4;
+                }else if (item.basicData.ptztype === 2) {
+                  type = 5;
+                }else if (item.basicData.ptztype === 3 || item.basicData.ptztype === 4) {
+                  type = 6;
+                }
+              }else {
+                if (item.basicData.subCount > 0 || item.basicData.parental === 1) {
+                  type = 2;
+                }
+              }
             }
             let node = {
-              name: data[i].name || data[i].channelId,
-              isLeaf: data[i].subCount === 0,
-              id: data[i].channelId,
-              deviceId: data[i].deviceId,
+              name: item.name || item.basicData.channelId,
+              isLeaf: type !== 2,
+              id: item.id,
+              deviceId: item.deviceId,
               type: type,
-              online: data[i].status === 1,
-              hasGPS: data[i].longitude*data[i].latitude !== 0,
-              userData: data[i]
+              online: item.basicData.status === 1,
+              hasGPS: item.basicData.longitude*item.basicData.latitude !== 0,
+              userData: item.basicData
             }
             nodeList.push(node);
           }
@@ -146,6 +160,9 @@
         }else {
           resolve([])
         }
+      },
+      reset: function (){
+        this.$forceUpdate();
       }
     },
     destroyed() {
diff --git a/web_src/src/components/common/DeviceTreeForZtree.vue b/web_src/src/components/common/DeviceTreeForZtree.vue
new file mode 100644
index 0000000..6c02bcc
--- /dev/null
+++ b/web_src/src/components/common/DeviceTreeForZtree.vue
@@ -0,0 +1,112 @@
+<template>
+  <div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF; overflow: auto">
+    <el-container>
+      <el-header>璁惧鍒楄〃</el-header>
+      <el-main style="background-color: #ffffff;">
+        <div class="device-tree-main-box">
+          <tree
+            :nodes="nodes"
+            @onClick="onClick"
+            @onCheck="onCheck"
+            @onExpand="onExpand"
+            @onCreated="handleCreated"
+          />
+        </div>
+      </el-main>
+    </el-container>
+  </div>
+</template>
+
+<script>
+import DeviceService from "../service/DeviceService.js";
+import tree from "vue-giant-tree";
+
+export default {
+    name: 'DeviceTreeForZtree',
+    components: {
+      tree
+    },
+    data() {
+        return {
+          deviceService: new DeviceService(),
+          device: null,
+          nodes:[],
+          setting: {
+            callback: {
+              beforeExpand: this.beforeExpand
+            },
+            // async: {
+            //   enable: true,
+            //   type: "get",
+            //   url: `/api/device/query/tree`,
+            //   contentType: "application/json",
+            //   // autoParam: ["pid=parentId"],
+            // },
+            check: {
+              enable: false,
+            },
+            edit: {
+              enable: false,
+            }
+          },
+          defaultProps: {
+            children: 'children',
+            label: 'name',
+            isLeaf: 'isLeaf'
+          }
+        };
+    },
+    props: ['clickEvent', 'contextMenuEvent'],
+    mounted() {
+      this.deviceService.getAllDeviceList((data)=>{
+        console.log(data)
+        for (let i = 0; i < data.length; i++) {
+          console.log(data[i].name)
+          let node = {
+            name: data[i].name || data[i].deviceId,
+            id: data[i].deviceId,
+            isParent: true,
+          }
+          this.nodes.push(node)
+        }
+      }, (list)=>{
+        console.log("璁惧鍔犺浇瀹屾垚")
+      })
+    },
+    methods: {
+      onClick(evt, treeId, treeNode) {
+        console.log(evt)
+        console.log(treeId)
+        console.log(treeNode)
+      },
+      onCheck(evt, treeId, treeNode) {
+        console.log(evt)
+      },
+      beforeExpand(treeId, treeNode) {
+        console.log(treeId)
+        console.log(treeNode)
+        return true;
+      },
+      onExpand(evt, treeId, treeNode) {
+        // console.log(evt)
+        // console.log(treeId)
+        // console.log(treeNodes)
+      },
+      handleCreated(ztreeObj) {
+        console.log(ztreeObj)
+      }
+    }
+}
+</script>
+
+<style>
+.device-tree-main-box{
+  text-align: left;
+}
+.device-online{
+  color: #252525;
+}
+.device-offline{
+  color: #727272;
+}
+</style>
diff --git a/web_src/src/components/dialog/deviceEdit.vue b/web_src/src/components/dialog/deviceEdit.vue
index ed17d17..773e7c9 100644
--- a/web_src/src/components/dialog/deviceEdit.vue
+++ b/web_src/src/components/dialog/deviceEdit.vue
@@ -42,6 +42,12 @@
               <el-option key="GCJ02" label="GCJ02" value="GCJ02"></el-option>
             </el-select>
           </el-form-item>
+          <el-form-item label="鐩綍缁撴瀯" prop="treeType" >
+            <el-select v-model="form.treeType" style="float: left; width: 100%" >
+              <el-option key="WGS84" label="琛屾斂鍖哄垝" value="CivilCode"></el-option>
+              <el-option key="GCJ02" label="涓氬姟鍒嗙粍" value="BusinessGroup"></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item label="鐩綍璁㈤槄" title="0涓哄彇娑堣闃�" prop="subscribeCycleForCatalog" >
             <el-input v-model="form.subscribeCycleForCatalog" clearable ></el-input>
           </el-form-item>
diff --git a/web_src/src/components/live.vue b/web_src/src/components/live.vue
index 797be84..1f2d6ca 100644
--- a/web_src/src/components/live.vue
+++ b/web_src/src/components/live.vue
@@ -107,20 +107,24 @@
       console.log(idx);
       this.clear(idx.substring(idx.length - 1))
     },
-    clickEvent: function (data) {
-      if (data.channelId && data.subCount == 0) {
-        this.sendDevicePush(data)
+    clickEvent: function (device, data, isCatalog) {
+      if (data.channelId && !isCatalog) {
+        if (device.online === 0) {
+          this.$message.error('璁惧绂荤嚎!涓嶅厑璁哥偣鎾�');
+        }else {
+          this.sendDevicePush(data)
+        }
       }
     },
-    contextMenuEvent: function (data) {
+    contextMenuEvent: function (device, event, data, isCatalog) {
 
     },
     //閫氱煡璁惧涓婁紶濯掍綋娴�
     sendDevicePush: function (itemData) {
-      if (itemData.status === 0) {
-        this.$message.error('璁惧绂荤嚎!');
-        return
-      }
+      // if (itemData.status === 0) {
+      //   this.$message.error('璁惧绂荤嚎!');
+      //   return
+      // }
       this.save(itemData)
       let deviceId = itemData.deviceId;
       // this.isLoging = true;
diff --git a/web_src/src/components/map.vue b/web_src/src/components/map.vue
index e9e8628..d4a36cf 100644
--- a/web_src/src/components/map.vue
+++ b/web_src/src/components/map.vue
@@ -16,7 +16,8 @@
           <el-descriptions class="margin-top" :title="channel.name" :column="1" :colon="true" size="mini" :labelStyle="labelStyle" >
             <el-descriptions-item label="缂栧彿" >{{channel.channelId}}</el-descriptions-item>
             <el-descriptions-item label="鍨嬪彿">{{channel.model}}</el-descriptions-item>
-            <el-descriptions-item label="缁忕含搴�" >{{channel.longitude}},{{channel.latitude}}</el-descriptions-item>
+            <el-descriptions-item label="缁忓害" >{{channel[longitudeStr]}}</el-descriptions-item>
+            <el-descriptions-item label="绾害" >{{channel[latitudeStr]}}</el-descriptions-item>
             <el-descriptions-item label="鐢熶骇鍘傚晢">{{channel.manufacture}}</el-descriptions-item>
             <el-descriptions-item label="琛屾斂鍖哄煙" >{{channel.civilCode}}</el-descriptions-item>
             <el-descriptions-item label="璁惧褰掑睘" >{{channel.owner}}</el-descriptions-item>
@@ -28,7 +29,7 @@
             </el-descriptions-item>
           </el-descriptions>
           <div style="padding-top: 10px">
-            <el-button type="primary" size="small" title="鎾斁" icon="el-icon-video-play" @click="play(channel)"></el-button>
+            <el-button v-bind:disabled="device == null || device.online === 0" type="primary" size="small" title="鎾斁" icon="el-icon-video-play" @click="play(channel)"></el-button>
             <el-button type="primary" size="small" title="缂栬緫浣嶇疆" icon="el-icon-edit" @click="edit(channel)"></el-button>
             <el-button type="primary" size="small" title="杞ㄨ抗鏌ヨ" icon="el-icon-map-location" @click="getTrace(channel)"></el-button>
           </div>
@@ -64,11 +65,14 @@
       layer: null,
       lineLayer: null,
       channel: null,
+      device: null,
       infoBoxId: null,
       labelStyle: {
         width: "56px"
       },
       isLoging: false,
+      longitudeStr: "longitude",
+      latitudeStr: "latitude",
     };
   },
   created() {
@@ -78,17 +82,27 @@
       setTimeout(()=>{ // 寤惰繜浠ョ瓑寰呭湴鍥惧姞杞藉畬鎴� TODO 鍚庣画淇敼涓洪�氳繃鏄疄闄呰繖锛涚姸鎬佸姞鍥炶皟瀹屾垚
         this.deviceService.getAllChannel(false, false, this.$route.query.deviceId, this.channelsHandler)
       }, 1000)
-
+    }
+    if (window.mapParam.coordinateSystem == "GCJ-02") {
+      this.longitudeStr = "longitudeGcj02";
+      this.latitudeStr = "latitudeGcj02";
+    }else if (window.mapParam.coordinateSystem == "WGS84") {
+      this.longitudeStr = "longitudeWgs84";
+      this.latitudeStr = "latitudeWgs84";
+    }else {
+      this.longitudeStr = "longitude";
+      this.latitudeStr = "latitude";
     }
   },
   destroyed() {
 
   },
   methods: {
-    clickEvent: function (data) {
-      if (data.channelId && data.subCount == 0) {
+    clickEvent: function (device, data, isCatalog) {
+      this.device = device;
+      if (data.channelId && !isCatalog) {
         // 鐐瑰嚮閫氶亾
-        if (data.longitude * data.latitude === 0) {
+        if (data[this.longitudeStr] * data[this.latitudeStr] === 0) {
           this.$message.error('鏈幏鍙栧埌浣嶇疆淇℃伅');
         } else {
           if (this.layer != null) {
@@ -96,26 +110,29 @@
           }
           this.closeInfoBox()
           this.layer = this.$refs.map.addLayer([{
-            position: [data.longitude, data.latitude],
+            position: [data[this.longitudeStr], data[this.latitudeStr]],
             image: {
               src: this.getImageByChannel(data),
               anchor: [0.5, 1]
             },
             data: data
           }], this.featureClickEvent)
-          this.$refs.map.panTo([data.longitude, data.latitude], mapParam.maxZoom)
+          this.$refs.map.panTo([data[this.longitudeStr], data[this.latitudeStr]], mapParam.maxZoom)
         }
       }
     },
-    contextmenuEventHandler: function (event, data) {
-      if (data.channelId && data.subCount == 0) {
+    contextmenuEventHandler: function (device, event, data, isCatalog) {
+      console.log(device)
+      console.log(device.online)
+      this.device = device;
+      if (data.channelId && !isCatalog) {
         // 鐐瑰嚮閫氶亾
         this.$contextmenu({
           items: [
             {
               label: "鎾斁",
               icon: "el-icon-video-play",
-              disabled: false,
+              disabled: device.online === 0,
               onClick: () => {
                 this.play(data);
               }
@@ -183,22 +200,11 @@
         this.clean()
         this.closeInfoBox()
         let params = [];
-        let longitudeStr;
-        let latitudeStr;
-        if (window.mapParam.coordinateSystem == "GCJ-02") {
-          longitudeStr = "longitudeGcj02";
-          latitudeStr = "latitudeGcj02";
-        }else if (window.mapParam.coordinateSystem == "WGS84") {
-          longitudeStr = "longitudeWgs84";
-          latitudeStr = "latitudeWgs84";
-        }else {
-          longitudeStr = "longitude";
-          latitudeStr = "latitude";
-        }
+
 
         for (let i = 0; i < channels.length; i++) {
-          let longitude = channels[i][longitudeStr];
-          let latitude = channels[i][latitudeStr];
+          let longitude = channels[i][this.longitudeStr];
+          let latitude = channels[i][this.latitudeStr];
           if (longitude * latitude === 0) {
             continue;
           }
@@ -217,7 +223,7 @@
         this.layer = this.$refs.map.addLayer(params, this.featureClickEvent)
         console.log(4)
         if (params.length === 1) {
-          this.$refs.map.panTo([channels[0][longitudeStr], channels[0][latitudeStr]], mapParam.maxZoom)
+          this.$refs.map.panTo([channels[0][this.longitudeStr], channels[0][this.latitudeStr]], mapParam.maxZoom)
         } else if (params.length > 1) {
           this.$refs.map.fit(this.layer)
         } else {
@@ -266,19 +272,7 @@
         this.channel = channels[0]
       }
       this.$nextTick(() => {
-        let longitudeStr;
-        let latitudeStr;
-        if (window.mapParam.coordinateSystem == "GCJ-02") {
-          longitudeStr = "longitudeGcj02";
-          latitudeStr = "latitudeGcj02";
-        }else if (window.mapParam.coordinateSystem == "WGS84") {
-          longitudeStr = "longitudeWgs84";
-          latitudeStr = "latitudeWgs84";
-        }else {
-          longitudeStr = "longitude";
-          latitudeStr = "latitude";
-        }
-        let position = [this.channel[longitudeStr], this.channel[latitudeStr]];
+        let position = [this.channel[this.longitudeStr], this.channel[this.latitudeStr]];
         this.infoBoxId = this.$refs.map.openInfoBox(position, this.$refs.infobox, [0, -50])
       })
     },
diff --git a/web_src/src/components/service/DeviceService.js b/web_src/src/components/service/DeviceService.js
index fb66374..45d4ac2 100644
--- a/web_src/src/components/service/DeviceService.js
+++ b/web_src/src/components/service/DeviceService.js
@@ -133,6 +133,49 @@
       if (typeof (callback) == "function") callback(res.data)
     }).catch(errorCallback);
   }
+
+  getTree(deviceId, id, param3, param4) {
+
+  }
+
+  getTree(deviceId, parentId, onlyCatalog, callback, endCallback, errorCallback) {
+    let currentPage = 1;
+    let count = 100;
+    let catalogList = []
+    this.getTreeIteration(deviceId, parentId, onlyCatalog, catalogList, currentPage, count, callback, endCallback, errorCallback)
+  }
+
+  getTreeIteration(deviceId, parentId, onlyCatalog, catalogList, currentPage, count, callback, endCallback, errorCallback) {
+    this.getTreeInfo(deviceId, parentId, onlyCatalog, currentPage, count, (data) => {
+      if (data.list) {
+        if (typeof (callback) == "function") callback(data.list)
+        catalogList = catalogList.concat(data.list);
+        if (catalogList.length < data.total) {
+          currentPage ++
+          this.getTreeIteration(deviceId, parentId, onlyCatalog, catalogList, currentPage, count, callback, endCallback, errorCallback)
+        }else {
+          if (typeof (endCallback) == "function") endCallback(catalogList)
+        }
+      }
+    }, errorCallback)
+  }
+  getTreeInfo(deviceId, parentId, onlyCatalog, currentPage, count, callback, errorCallback) {
+    if (onlyCatalog == null || typeof onlyCatalog === "undefined") {
+      onlyCatalog = false;
+    }
+    this.$axios({
+      method: 'get',
+      url: `/api/device/query/tree/${deviceId}`,
+      params:{
+        page: currentPage,
+        count: count,
+        parentId: parentId,
+        onlyCatalog: onlyCatalog
+      }
+    }).then((res) =>{
+      if (typeof (callback) == "function") callback(res.data)
+    }).catch(errorCallback);
+  }
 }
 
 export default DeviceService;
diff --git a/web_src/src/router/index.js b/web_src/src/router/index.js
index 2f44fd8..2c9c6f3 100644
--- a/web_src/src/router/index.js
+++ b/web_src/src/router/index.js
@@ -59,7 +59,7 @@
           component: streamProxyList,
         },
         {
-          path: '/channelList/:deviceId/:parentChannelId/:count/:page',
+          path: '/channelList/:deviceId/:parentChannelId/',
           name: 'channelList',
           component: channelList,
         },
diff --git a/web_src/static/css/iconfont.css b/web_src/static/css/iconfont.css
index 2a08b07..a09b98e 100644
--- a/web_src/static/css/iconfont.css
+++ b/web_src/static/css/iconfont.css
@@ -1,6 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 1291092 */
-  src: url('iconfont.woff2?t=1650436696596') format('woff2');
+  src: url('iconfont.woff2?t=1655453611360') format('woff2'),
+       url('iconfont.woff?t=1655453611360') format('woff'),
+       url('iconfont.ttf?t=1655453611360') format('truetype');
 }
 
 .iconfont {
@@ -11,6 +13,30 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-list:before {
+  content: "\e7de";
+}
+
+.icon-tree:before {
+  content: "\e7df";
+}
+
+.icon-shipin:before {
+  content: "\e7db";
+}
+
+.icon-shipin1:before {
+  content: "\e7dc";
+}
+
+.icon-shipin2:before {
+  content: "\e7dd";
+}
+
+.icon-LC_icon_gps_fill:before {
+  content: "\e7da";
+}
+
 .icon-jiedianleizhukongzhongxin1:before {
   content: "\e9d0";
 }
diff --git a/web_src/static/css/iconfont.woff2 b/web_src/static/css/iconfont.woff2
index 7204137..c2fdf69 100644
--- a/web_src/static/css/iconfont.woff2
+++ b/web_src/static/css/iconfont.woff2
Binary files differ

--
Gitblit v1.8.0