Commit 7d1116c8928770cd7703c83955d77f1e6a430ce3

Authored by mk1990
Committed by GitHub
2 parents 22e1d92a 3501046e

Merge branch '648540858:wvp-28181-2.0' into wvp-28181-2.0

Showing 49 changed files with 3070 additions and 2665 deletions
README.md
... ... @@ -134,10 +134,10 @@ QQ遘∽ソ。荳闊ャ荳榊屓, 邊セ蜉帶怏髯.谺「霑主、ァ螳カ蝨ィ鄒、驥瑚ョィ隶コ.隗牙セ鈴。ケ逶ョ蟇ケ菴
134 134 諢溯ー「菴懆dexter langhuihui](https://github.com/langhuihui) 蠑貅占ソ吩ケ亥・ス逕ィ逧ЦEB謦ュ謾セ蝎ィ縲
135 135 諢溯ー「菴懆Kyle](https://gitee.com/kkkkk5G) 蠑貅蝉コ・ス逕ィ逧燕遶ッ鬘オ髱「
136 136 諢溯ー「蜷ス榊、ァ菴ャ逧オ槫勧莉・蜿雁ッケ鬘ケ逶ョ逧欠豁」荳主クョ蜉ゥ縲ょ桁諡ャ菴ク埼剞莠惹サ」遐∬エ。迪ョ縲琉鬚伜渚鬥医∬オ謐占オ遲牙推遘肴婿蠑冗噪謾ッ謖シ∽サ・荳区賜蜷堺ク榊蜈亥錘
137   -[lawrencehj](https://github.com/lawrencehj) @髯クー-蛻帛・ァ第橿 [swwhaha](https://github.com/swwheihei)
  137 +[lawrencehj](https://github.com/lawrencehj) [Smallwhitepig](https://github.com/Smallwhitepig) [swwhaha](https://github.com/swwheihei)
138 138 [hotcoffie](https://github.com/hotcoffie) [xiaomu](https://github.com/nikmu) [TristingChen](https://github.com/TristingChen)
139 139 [chenparty](https://github.com/chenparty) [Hotleave](https://github.com/hotleave) [ydwxb](https://github.com/ydwxb)
140   -[ydpd](https://github.com/ydpd) [szy833](https://github.com/szy833) [ydwxb](https://github.com/ydwxb)
  140 +[ydpd](https://github.com/ydpd) [szy833](https://github.com/szy833) [ydwxb](https://github.com/ydwxb) [Albertzhu666](https://github.com/Albertzhu666)
141 141  
142 142 ps: 蛻壼「槫刈莠ソ吩クェ蜷榊黒瑚け螳夐@貍丈コク莠帛、ァ菴ャ梧ャ「霑主、ァ菴ャ閨皮ウサ謌第キサ蜉縲
143 143  
... ...
... ... @@ -11,7 +11,7 @@
11 11  
12 12 <groupId>com.genersoft</groupId>
13 13 <artifactId>wvp-pro</artifactId>
14   - <version>2.0.2</version>
  14 + <version>2.1.1</version>
15 15 <name>web video platform</name>
16 16 <description>国标28181视频平台</description>
17 17  
... ...
sql/clean.sql 0 → 100644
  1 +delete from device;
  2 +delete from device_alarm;
  3 +delete from device_channel;
  4 +delete from device_mobile_position;
  5 +delete from gb_stream;
  6 +delete from log;
  7 +delete from media_server;
  8 +delete from parent_platform;
  9 +delete from platform_catalog;
  10 +delete from platform_gb_channel;
  11 +delete from platform_gb_stream;
  12 +delete from stream_proxy;
  13 +delete from stream_push;
0 14 \ No newline at end of file
... ...
sql/mysql.sql
1   --- MySQL dump 10.13 Distrib 8.0.28, for Linux (x86_64)
  1 +-- MariaDB dump 10.19 Distrib 10.7.3-MariaDB, for Linux (x86_64)
2 2 --
3   --- Host: 127.0.0.1 Database: wvp
  3 +-- Host: 127.0.0.1 Database: wvp3
4 4 -- ------------------------------------------------------
5   --- Server version 8.0.28-0ubuntu0.20.04.3
  5 +-- Server version 8.0.0-dmr
6 6  
7 7 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
8 8 /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
9 9 /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
10   -/*!50503 SET NAMES utf8mb4 */;
  10 +/*!40101 SET NAMES utf8mb4 */;
11 11 /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
12 12 /*!40103 SET TIME_ZONE='+00:00' */;
13 13 /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
... ... @@ -21,33 +21,34 @@
21 21  
22 22 DROP TABLE IF EXISTS `device`;
23 23 /*!40101 SET @saved_cs_client = @@character_set_client */;
24   -/*!50503 SET character_set_client = utf8mb4 */;
  24 +/*!40101 SET character_set_client = utf8 */;
25 25 CREATE TABLE `device` (
26   - `id` int NOT NULL AUTO_INCREMENT,
27   - `deviceId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
28   - `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
29   - `manufacturer` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
30   - `model` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
31   - `firmware` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
32   - `transport` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
33   - `streamMode` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
34   - `online` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
35   - `registerTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
36   - `keepaliveTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
37   - `ip` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
38   - `createTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
39   - `updateTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
40   - `port` int NOT NULL,
41   - `expires` int NOT NULL,
42   - `subscribeCycleForCatalog` int NOT NULL,
43   - `subscribeCycleForMobilePosition` int NOT NULL,
44   - `mobilePositionSubmissionInterval` int DEFAULT 5 NOT NULL,
45   - `subscribeCycleForAlarm` int NOT NULL,
46   - `hostAddress` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
47   - `charset` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  26 + `id` int(11) NOT NULL AUTO_INCREMENT,
  27 + `deviceId` varchar(50) NOT NULL,
  28 + `name` varchar(255) DEFAULT NULL,
  29 + `manufacturer` varchar(255) DEFAULT NULL,
  30 + `model` varchar(255) DEFAULT NULL,
  31 + `firmware` varchar(255) DEFAULT NULL,
  32 + `transport` varchar(50) DEFAULT NULL,
  33 + `streamMode` varchar(50) DEFAULT NULL,
  34 + `online` varchar(50) DEFAULT NULL,
  35 + `registerTime` varchar(50) DEFAULT NULL,
  36 + `keepaliveTime` varchar(50) DEFAULT NULL,
  37 + `ip` varchar(50) NOT NULL,
  38 + `createTime` varchar(50) NOT NULL,
  39 + `updateTime` varchar(50) NOT NULL,
  40 + `port` int(11) NOT NULL,
  41 + `expires` int(11) NOT NULL,
  42 + `subscribeCycleForCatalog` int(11) NOT NULL,
  43 + `subscribeCycleForMobilePosition` int(11) NOT NULL,
  44 + `mobilePositionSubmissionInterval` int(11) NOT NULL DEFAULT '5',
  45 + `subscribeCycleForAlarm` int(11) NOT NULL,
  46 + `hostAddress` varchar(50) NOT NULL,
  47 + `charset` varchar(50) NOT NULL,
  48 + `ssrcCheck` int(11) DEFAULT '0',
48 49 PRIMARY KEY (`id`),
49 50 UNIQUE KEY `device_deviceId_uindex` (`deviceId`)
50   -) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  51 +) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8mb4;
51 52 /*!40101 SET character_set_client = @saved_cs_client */;
52 53  
53 54 --
... ... @@ -65,20 +66,20 @@ UNLOCK TABLES;
65 66  
66 67 DROP TABLE IF EXISTS `device_alarm`;
67 68 /*!40101 SET @saved_cs_client = @@character_set_client */;
68   -/*!50503 SET character_set_client = utf8mb4 */;
  69 +/*!40101 SET character_set_client = utf8 */;
69 70 CREATE TABLE `device_alarm` (
70   - `id` int NOT NULL AUTO_INCREMENT,
71   - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
72   - `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
73   - `alarmPriority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
74   - `alarmMethod` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
75   - `alarmTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
76   - `alarmDescription` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  71 + `id` int(11) NOT NULL AUTO_INCREMENT,
  72 + `deviceId` varchar(50) NOT NULL,
  73 + `channelId` varchar(50) NOT NULL,
  74 + `alarmPriority` varchar(50) NOT NULL,
  75 + `alarmMethod` varchar(50) DEFAULT NULL,
  76 + `alarmTime` varchar(50) NOT NULL,
  77 + `alarmDescription` varchar(255) DEFAULT NULL,
77 78 `longitude` double DEFAULT NULL,
78 79 `latitude` double DEFAULT NULL,
79   - `alarmType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  80 + `alarmType` varchar(50) DEFAULT NULL,
80 81 PRIMARY KEY (`id`) USING BTREE
81   -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  82 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
82 83 /*!40101 SET character_set_client = @saved_cs_client */;
83 84  
84 85 --
... ... @@ -96,43 +97,43 @@ UNLOCK TABLES;
96 97  
97 98 DROP TABLE IF EXISTS `device_channel`;
98 99 /*!40101 SET @saved_cs_client = @@character_set_client */;
99   -/*!50503 SET character_set_client = utf8mb4 */;
  100 +/*!40101 SET character_set_client = utf8 */;
100 101 CREATE TABLE `device_channel` (
101   - `id` int NOT NULL AUTO_INCREMENT,
102   - `channelId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
103   - `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
104   - `manufacture` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
105   - `model` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
106   - `owner` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
107   - `civilCode` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
108   - `block` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
109   - `address` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
110   - `parentId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
111   - `safetyWay` int DEFAULT NULL,
112   - `registerWay` int DEFAULT NULL,
113   - `certNum` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
114   - `certifiable` int DEFAULT NULL,
115   - `errCode` int DEFAULT NULL,
116   - `endTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
117   - `secrecy` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
118   - `ipAddress` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
119   - `port` int DEFAULT NULL,
120   - `password` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
121   - `PTZType` int DEFAULT NULL,
122   - `status` int DEFAULT NULL,
  102 + `id` int(11) NOT NULL AUTO_INCREMENT,
  103 + `channelId` varchar(50) NOT NULL,
  104 + `name` varchar(255) DEFAULT NULL,
  105 + `manufacture` varchar(50) DEFAULT NULL,
  106 + `model` varchar(50) DEFAULT NULL,
  107 + `owner` varchar(50) DEFAULT NULL,
  108 + `civilCode` varchar(50) DEFAULT NULL,
  109 + `block` varchar(50) DEFAULT NULL,
  110 + `address` varchar(50) DEFAULT NULL,
  111 + `parentId` varchar(50) DEFAULT NULL,
  112 + `safetyWay` int(11) DEFAULT NULL,
  113 + `registerWay` int(11) DEFAULT NULL,
  114 + `certNum` varchar(50) DEFAULT NULL,
  115 + `certifiable` int(11) DEFAULT NULL,
  116 + `errCode` int(11) DEFAULT NULL,
  117 + `endTime` varchar(50) DEFAULT NULL,
  118 + `secrecy` varchar(50) DEFAULT NULL,
  119 + `ipAddress` varchar(50) DEFAULT NULL,
  120 + `port` int(11) DEFAULT NULL,
  121 + `password` varchar(255) DEFAULT NULL,
  122 + `PTZType` int(11) DEFAULT NULL,
  123 + `status` int(11) DEFAULT NULL,
123 124 `longitude` double DEFAULT NULL,
124 125 `latitude` double DEFAULT NULL,
125   - `streamId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
126   - `deviceId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
127   - `parental` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  126 + `streamId` varchar(50) DEFAULT NULL,
  127 + `deviceId` varchar(50) NOT NULL,
  128 + `parental` varchar(50) DEFAULT NULL,
128 129 `hasAudio` bit(1) DEFAULT NULL,
129   - `createTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
130   - `updateTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
131   - `subCount` int DEFAULT '0',
  130 + `createTime` varchar(50) NOT NULL,
  131 + `updateTime` varchar(50) NOT NULL,
  132 + `subCount` int(11) DEFAULT '0',
132 133 PRIMARY KEY (`id`),
133 134 UNIQUE KEY `device_channel_id_uindex` (`id`),
134 135 UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`)
135   -) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  136 +) ENGINE=InnoDB AUTO_INCREMENT=81657 DEFAULT CHARSET=utf8mb4;
136 137 /*!40101 SET character_set_client = @saved_cs_client */;
137 138  
138 139 --
... ... @@ -150,24 +151,24 @@ UNLOCK TABLES;
150 151  
151 152 DROP TABLE IF EXISTS `device_mobile_position`;
152 153 /*!40101 SET @saved_cs_client = @@character_set_client */;
153   -/*!50503 SET character_set_client = utf8mb4 */;
  154 +/*!40101 SET character_set_client = utf8 */;
154 155 CREATE TABLE `device_mobile_position` (
155   - `id` int NOT NULL AUTO_INCREMENT,
156   - `deviceId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
157   - `channelId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
158   - `deviceName` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
159   - `time` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  156 + `id` int(11) NOT NULL AUTO_INCREMENT,
  157 + `deviceId` varchar(50) NOT NULL,
  158 + `channelId` varchar(50) NOT NULL,
  159 + `deviceName` varchar(255) DEFAULT NULL,
  160 + `time` varchar(50) NOT NULL,
160 161 `longitude` double NOT NULL,
161 162 `latitude` double NOT NULL,
162 163 `altitude` double DEFAULT NULL,
163 164 `speed` double DEFAULT NULL,
164 165 `direction` double DEFAULT NULL,
165   - `reportSource` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
166   - `geodeticSystem` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
167   - `cnLng` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
168   - `cnLat` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  166 + `reportSource` varchar(50) DEFAULT NULL,
  167 + `geodeticSystem` varchar(50) DEFAULT NULL,
  168 + `cnLng` varchar(50) DEFAULT NULL,
  169 + `cnLat` varchar(50) DEFAULT NULL,
169 170 PRIMARY KEY (`id`)
170   -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  171 +) ENGINE=InnoDB AUTO_INCREMENT=6108 DEFAULT CHARSET=utf8mb4;
171 172 /*!40101 SET character_set_client = @saved_cs_client */;
172 173  
173 174 --
... ... @@ -185,23 +186,23 @@ UNLOCK TABLES;
185 186  
186 187 DROP TABLE IF EXISTS `gb_stream`;
187 188 /*!40101 SET @saved_cs_client = @@character_set_client */;
188   -/*!50503 SET character_set_client = utf8mb4 */;
  189 +/*!40101 SET character_set_client = utf8 */;
189 190 CREATE TABLE `gb_stream` (
190   - `gbStreamId` int NOT NULL AUTO_INCREMENT,
191   - `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
192   - `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
193   - `gbId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
194   - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  191 + `gbStreamId` int(11) NOT NULL AUTO_INCREMENT,
  192 + `app` varchar(255) NOT NULL,
  193 + `stream` varchar(255) NOT NULL,
  194 + `gbId` varchar(50) NOT NULL,
  195 + `name` varchar(255) DEFAULT NULL,
195 196 `longitude` double DEFAULT NULL,
196 197 `latitude` double DEFAULT NULL,
197   - `streamType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
198   - `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
199   - `status` int DEFAULT NULL,
200   - `createStamp` bigint DEFAULT NULL,
  198 + `streamType` varchar(50) DEFAULT NULL,
  199 + `mediaServerId` varchar(50) DEFAULT NULL,
  200 + `status` int(11) DEFAULT NULL,
  201 + `createStamp` bigint(20) DEFAULT NULL,
201 202 PRIMARY KEY (`gbStreamId`) USING BTREE,
202 203 UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
203 204 UNIQUE KEY `gbId` (`gbId`) USING BTREE
204   -) ENGINE=InnoDB AUTO_INCREMENT=300766 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  205 +) ENGINE=InnoDB AUTO_INCREMENT=300769 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
205 206 /*!40101 SET character_set_client = @saved_cs_client */;
206 207  
207 208 --
... ... @@ -219,19 +220,19 @@ UNLOCK TABLES;
219 220  
220 221 DROP TABLE IF EXISTS `log`;
221 222 /*!40101 SET @saved_cs_client = @@character_set_client */;
222   -/*!50503 SET character_set_client = utf8mb4 */;
  223 +/*!40101 SET character_set_client = utf8 */;
223 224 CREATE TABLE `log` (
224   - `id` int NOT NULL AUTO_INCREMENT,
225   - `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
226   - `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
227   - `uri` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
228   - `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
229   - `result` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
230   - `timing` bigint NOT NULL,
231   - `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
232   - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  225 + `id` int(11) NOT NULL AUTO_INCREMENT,
  226 + `name` varchar(50) NOT NULL,
  227 + `type` varchar(50) NOT NULL,
  228 + `uri` varchar(200) NOT NULL,
  229 + `address` varchar(50) NOT NULL,
  230 + `result` varchar(50) NOT NULL,
  231 + `timing` bigint(20) NOT NULL,
  232 + `username` varchar(50) NOT NULL,
  233 + `createTime` varchar(50) NOT NULL,
233 234 PRIMARY KEY (`id`) USING BTREE
234   -) ENGINE=InnoDB AUTO_INCREMENT=962 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  235 +) ENGINE=InnoDB AUTO_INCREMENT=1552 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
235 236 /*!40101 SET character_set_client = @saved_cs_client */;
236 237  
237 238 --
... ... @@ -249,34 +250,34 @@ UNLOCK TABLES;
249 250  
250 251 DROP TABLE IF EXISTS `media_server`;
251 252 /*!40101 SET @saved_cs_client = @@character_set_client */;
252   -/*!50503 SET character_set_client = utf8mb4 */;
  253 +/*!40101 SET character_set_client = utf8 */;
253 254 CREATE TABLE `media_server` (
254   - `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
255   - `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
256   - `hookIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
257   - `sdpIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
258   - `streamIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
259   - `httpPort` int NOT NULL,
260   - `httpSSlPort` int NOT NULL,
261   - `rtmpPort` int NOT NULL,
262   - `rtmpSSlPort` int NOT NULL,
263   - `rtpProxyPort` int NOT NULL,
264   - `rtspPort` int NOT NULL,
265   - `rtspSSLPort` int NOT NULL,
266   - `autoConfig` int NOT NULL,
267   - `secret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
268   - `streamNoneReaderDelayMS` int NOT NULL,
269   - `rtpEnable` int NOT NULL,
270   - `rtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
271   - `sendRtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
272   - `recordAssistPort` int NOT NULL,
273   - `defaultServer` int NOT NULL,
274   - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
275   - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
276   - `hookAliveInterval` int NOT NULL,
  255 + `id` varchar(255) NOT NULL,
  256 + `ip` varchar(50) NOT NULL,
  257 + `hookIp` varchar(50) NOT NULL,
  258 + `sdpIp` varchar(50) NOT NULL,
  259 + `streamIp` varchar(50) NOT NULL,
  260 + `httpPort` int(11) NOT NULL,
  261 + `httpSSlPort` int(11) NOT NULL,
  262 + `rtmpPort` int(11) NOT NULL,
  263 + `rtmpSSlPort` int(11) NOT NULL,
  264 + `rtpProxyPort` int(11) NOT NULL,
  265 + `rtspPort` int(11) NOT NULL,
  266 + `rtspSSLPort` int(11) NOT NULL,
  267 + `autoConfig` int(11) NOT NULL,
  268 + `secret` varchar(50) NOT NULL,
  269 + `streamNoneReaderDelayMS` int(11) NOT NULL,
  270 + `rtpEnable` int(11) NOT NULL,
  271 + `rtpPortRange` varchar(50) NOT NULL,
  272 + `sendRtpPortRange` varchar(50) NOT NULL,
  273 + `recordAssistPort` int(11) NOT NULL,
  274 + `defaultServer` int(11) NOT NULL,
  275 + `createTime` varchar(50) NOT NULL,
  276 + `updateTime` varchar(50) NOT NULL,
  277 + `hookAliveInterval` int(11) NOT NULL,
277 278 PRIMARY KEY (`id`) USING BTREE,
278 279 UNIQUE KEY `media_server_i` (`ip`,`httpPort`) USING BTREE
279   -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  280 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
280 281 /*!40101 SET character_set_client = @saved_cs_client */;
281 282  
282 283 --
... ... @@ -294,33 +295,36 @@ UNLOCK TABLES;
294 295  
295 296 DROP TABLE IF EXISTS `parent_platform`;
296 297 /*!40101 SET @saved_cs_client = @@character_set_client */;
297   -/*!50503 SET character_set_client = utf8mb4 */;
  298 +/*!40101 SET character_set_client = utf8 */;
298 299 CREATE TABLE `parent_platform` (
299   - `id` int NOT NULL AUTO_INCREMENT,
300   - `enable` int DEFAULT NULL,
301   - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
302   - `serverGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
303   - `serverGBDomain` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
304   - `serverIP` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
305   - `serverPort` int DEFAULT NULL,
306   - `deviceGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
307   - `deviceIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
308   - `devicePort` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
309   - `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
310   - `password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
311   - `expires` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
312   - `keepTimeout` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
313   - `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
314   - `characterSet` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
315   - `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
316   - `ptz` int DEFAULT NULL,
317   - `rtcp` int DEFAULT NULL,
  300 + `id` int(11) NOT NULL AUTO_INCREMENT,
  301 + `enable` int(11) DEFAULT NULL,
  302 + `name` varchar(255) DEFAULT NULL,
  303 + `serverGBId` varchar(50) NOT NULL,
  304 + `serverGBDomain` varchar(50) DEFAULT NULL,
  305 + `serverIP` varchar(50) DEFAULT NULL,
  306 + `serverPort` int(11) DEFAULT NULL,
  307 + `deviceGBId` varchar(50) NOT NULL,
  308 + `deviceIp` varchar(50) DEFAULT NULL,
  309 + `devicePort` varchar(50) DEFAULT NULL,
  310 + `username` varchar(255) DEFAULT NULL,
  311 + `password` varchar(50) DEFAULT NULL,
  312 + `expires` varchar(50) DEFAULT NULL,
  313 + `keepTimeout` varchar(50) DEFAULT NULL,
  314 + `transport` varchar(50) DEFAULT NULL,
  315 + `characterSet` varchar(50) DEFAULT NULL,
  316 + `catalogId` varchar(50) NOT NULL,
  317 + `ptz` int(11) DEFAULT NULL,
  318 + `rtcp` int(11) DEFAULT NULL,
318 319 `status` bit(1) DEFAULT NULL,
319   - `shareAllLiveStream` int DEFAULT NULL,
  320 + `shareAllLiveStream` int(11) DEFAULT NULL,
  321 + `startOfflinePush` int(11) DEFAULT '0',
  322 + `administrativeDivision` varchar(50) NOT NULL,
  323 + `catalogGroup` int(11) DEFAULT '1',
320 324 PRIMARY KEY (`id`),
321 325 UNIQUE KEY `parent_platform_id_uindex` (`id`),
322 326 UNIQUE KEY `parent_platform_pk` (`serverGBId`)
323   -) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  327 +) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
324 328 /*!40101 SET character_set_client = @saved_cs_client */;
325 329  
326 330 --
... ... @@ -338,14 +342,14 @@ UNLOCK TABLES;
338 342  
339 343 DROP TABLE IF EXISTS `platform_catalog`;
340 344 /*!40101 SET @saved_cs_client = @@character_set_client */;
341   -/*!50503 SET character_set_client = utf8mb4 */;
  345 +/*!40101 SET character_set_client = utf8 */;
342 346 CREATE TABLE `platform_catalog` (
343   - `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
344   - `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
345   - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
346   - `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  347 + `id` varchar(50) NOT NULL,
  348 + `platformId` varchar(50) NOT NULL,
  349 + `name` varchar(255) NOT NULL,
  350 + `parentId` varchar(50) DEFAULT NULL,
347 351 PRIMARY KEY (`id`) USING BTREE
348   -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  352 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
349 353 /*!40101 SET character_set_client = @saved_cs_client */;
350 354  
351 355 --
... ... @@ -363,14 +367,14 @@ UNLOCK TABLES;
363 367  
364 368 DROP TABLE IF EXISTS `platform_gb_channel`;
365 369 /*!40101 SET @saved_cs_client = @@character_set_client */;
366   -/*!50503 SET character_set_client = utf8mb4 */;
  370 +/*!40101 SET character_set_client = utf8 */;
367 371 CREATE TABLE `platform_gb_channel` (
368   - `id` int NOT NULL AUTO_INCREMENT,
369   - `platformId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
370   - `catalogId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
371   - `deviceChannelId` int NOT NULL,
  372 + `id` int(11) NOT NULL AUTO_INCREMENT,
  373 + `platformId` varchar(50) NOT NULL,
  374 + `catalogId` varchar(50) NOT NULL,
  375 + `deviceChannelId` int(11) NOT NULL,
372 376 PRIMARY KEY (`id`)
373   -) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  377 +) ENGINE=InnoDB AUTO_INCREMENT=250 DEFAULT CHARSET=utf8mb4;
374 378 /*!40101 SET character_set_client = @saved_cs_client */;
375 379  
376 380 --
... ... @@ -388,15 +392,15 @@ UNLOCK TABLES;
388 392  
389 393 DROP TABLE IF EXISTS `platform_gb_stream`;
390 394 /*!40101 SET @saved_cs_client = @@character_set_client */;
391   -/*!50503 SET character_set_client = utf8mb4 */;
  395 +/*!40101 SET character_set_client = utf8 */;
392 396 CREATE TABLE `platform_gb_stream` (
393   - `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
394   - `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
395   - `gbStreamId` int NOT NULL,
396   - `id` int NOT NULL AUTO_INCREMENT,
  397 + `platformId` varchar(50) NOT NULL,
  398 + `catalogId` varchar(50) NOT NULL,
  399 + `gbStreamId` int(11) NOT NULL,
  400 + `id` int(11) NOT NULL AUTO_INCREMENT,
397 401 PRIMARY KEY (`id`),
398 402 UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`)
399   -) ENGINE=InnoDB AUTO_INCREMENT=301207 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  403 +) ENGINE=InnoDB AUTO_INCREMENT=301210 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
400 404 /*!40101 SET character_set_client = @saved_cs_client */;
401 405  
402 406 --
... ... @@ -414,29 +418,29 @@ UNLOCK TABLES;
414 418  
415 419 DROP TABLE IF EXISTS `stream_proxy`;
416 420 /*!40101 SET @saved_cs_client = @@character_set_client */;
417   -/*!50503 SET character_set_client = utf8mb4 */;
  421 +/*!40101 SET character_set_client = utf8 */;
418 422 CREATE TABLE `stream_proxy` (
419   - `id` int NOT NULL AUTO_INCREMENT,
420   - `type` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
421   - `app` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
422   - `stream` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
423   - `url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
424   - `src_url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
425   - `dst_url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
426   - `timeout_ms` int DEFAULT NULL,
427   - `ffmpeg_cmd_key` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
428   - `rtp_type` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
429   - `mediaServerId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  423 + `id` int(11) NOT NULL AUTO_INCREMENT,
  424 + `type` varchar(50) NOT NULL,
  425 + `app` varchar(255) NOT NULL,
  426 + `stream` varchar(255) NOT NULL,
  427 + `url` varchar(255) DEFAULT NULL,
  428 + `src_url` varchar(255) DEFAULT NULL,
  429 + `dst_url` varchar(255) DEFAULT NULL,
  430 + `timeout_ms` int(11) DEFAULT NULL,
  431 + `ffmpeg_cmd_key` varchar(255) DEFAULT NULL,
  432 + `rtp_type` varchar(50) DEFAULT NULL,
  433 + `mediaServerId` varchar(50) DEFAULT NULL,
430 434 `enable_hls` bit(1) DEFAULT NULL,
431 435 `enable_mp4` bit(1) DEFAULT NULL,
432 436 `enable` bit(1) NOT NULL,
433 437 `status` bit(1) NOT NULL,
434 438 `enable_remove_none_reader` bit(1) NOT NULL,
435   - `createTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
436   - `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  439 + `createTime` varchar(50) NOT NULL,
  440 + `name` varchar(255) DEFAULT NULL,
437 441 PRIMARY KEY (`id`),
438 442 UNIQUE KEY `stream_proxy_pk` (`app`,`stream`)
439   -) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  443 +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
440 444 /*!40101 SET character_set_client = @saved_cs_client */;
441 445  
442 446 --
... ... @@ -454,20 +458,20 @@ UNLOCK TABLES;
454 458  
455 459 DROP TABLE IF EXISTS `stream_push`;
456 460 /*!40101 SET @saved_cs_client = @@character_set_client */;
457   -/*!50503 SET character_set_client = utf8mb4 */;
  461 +/*!40101 SET character_set_client = utf8 */;
458 462 CREATE TABLE `stream_push` (
459   - `id` int NOT NULL AUTO_INCREMENT,
460   - `app` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
461   - `stream` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
462   - `totalReaderCount` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
463   - `originType` int DEFAULT NULL,
464   - `originTypeStr` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
465   - `createStamp` bigint DEFAULT NULL,
466   - `aliveSecond` int DEFAULT NULL,
467   - `mediaServerId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  463 + `id` int(11) NOT NULL AUTO_INCREMENT,
  464 + `app` varchar(255) NOT NULL,
  465 + `stream` varchar(255) NOT NULL,
  466 + `totalReaderCount` varchar(50) DEFAULT NULL,
  467 + `originType` int(11) DEFAULT NULL,
  468 + `originTypeStr` varchar(50) DEFAULT NULL,
  469 + `createStamp` bigint(20) DEFAULT NULL,
  470 + `aliveSecond` int(11) DEFAULT NULL,
  471 + `mediaServerId` varchar(50) DEFAULT NULL,
468 472 PRIMARY KEY (`id`),
469 473 UNIQUE KEY `stream_push_pk` (`app`,`stream`)
470   -) ENGINE=InnoDB AUTO_INCREMENT=300799 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  474 +) ENGINE=InnoDB AUTO_INCREMENT=300838 DEFAULT CHARSET=utf8mb4;
471 475 /*!40101 SET character_set_client = @saved_cs_client */;
472 476  
473 477 --
... ... @@ -485,17 +489,17 @@ UNLOCK TABLES;
485 489  
486 490 DROP TABLE IF EXISTS `user`;
487 491 /*!40101 SET @saved_cs_client = @@character_set_client */;
488   -/*!50503 SET character_set_client = utf8mb4 */;
  492 +/*!40101 SET character_set_client = utf8 */;
489 493 CREATE TABLE `user` (
490   - `id` int NOT NULL AUTO_INCREMENT,
491   - `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
492   - `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
493   - `roleId` int NOT NULL,
494   - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
495   - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  494 + `id` int(11) NOT NULL AUTO_INCREMENT,
  495 + `username` varchar(255) NOT NULL,
  496 + `password` varchar(255) NOT NULL,
  497 + `roleId` int(11) NOT NULL,
  498 + `createTime` varchar(50) NOT NULL,
  499 + `updateTime` varchar(50) NOT NULL,
496 500 PRIMARY KEY (`id`) USING BTREE,
497 501 UNIQUE KEY `user_username_uindex` (`username`) USING BTREE
498   -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  502 +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
499 503 /*!40101 SET character_set_client = @saved_cs_client */;
500 504  
501 505 --
... ... @@ -504,7 +508,8 @@ CREATE TABLE `user` (
504 508  
505 509 LOCK TABLES `user` WRITE;
506 510 /*!40000 ALTER TABLE `user` DISABLE KEYS */;
507   -INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57');
  511 +INSERT INTO `user` VALUES
  512 + (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57');
508 513 /*!40000 ALTER TABLE `user` ENABLE KEYS */;
509 514 UNLOCK TABLES;
510 515  
... ... @@ -514,15 +519,15 @@ UNLOCK TABLES;
514 519  
515 520 DROP TABLE IF EXISTS `user_role`;
516 521 /*!40101 SET @saved_cs_client = @@character_set_client */;
517   -/*!50503 SET character_set_client = utf8mb4 */;
  522 +/*!40101 SET character_set_client = utf8 */;
518 523 CREATE TABLE `user_role` (
519   - `id` int NOT NULL AUTO_INCREMENT,
520   - `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
521   - `authority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
522   - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
523   - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  524 + `id` int(11) NOT NULL AUTO_INCREMENT,
  525 + `name` varchar(50) NOT NULL,
  526 + `authority` varchar(50) NOT NULL,
  527 + `createTime` varchar(50) NOT NULL,
  528 + `updateTime` varchar(50) NOT NULL,
524 529 PRIMARY KEY (`id`) USING BTREE
525   -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  530 +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
526 531 /*!40101 SET character_set_client = @saved_cs_client */;
527 532  
528 533 --
... ... @@ -531,7 +536,8 @@ CREATE TABLE `user_role` (
531 536  
532 537 LOCK TABLES `user_role` WRITE;
533 538 /*!40000 ALTER TABLE `user_role` DISABLE KEYS */;
534   -INSERT INTO `user_role` VALUES (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
  539 +INSERT INTO `user_role` VALUES
  540 + (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
535 541 /*!40000 ALTER TABLE `user_role` ENABLE KEYS */;
536 542 UNLOCK TABLES;
537 543 /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
... ... @@ -544,4 +550,4 @@ UNLOCK TABLES;
544 550 /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
545 551 /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
546 552  
547   --- Dump completed on 2022-03-07 8:26:30
  553 +-- Dump completed on 2022-04-18 10:50:27
... ...
sql/update.sql
1   -alter table device
2   - add subscribeCycleForMobilePosition int null;
  1 +alter table parent_platform
  2 + add startOfflinePush int default 0 null;
3 3  
4   -alter table device
5   - add mobilePositionSubmissionInterval int default 5 null;
  4 +alter table parent_platform
  5 + add administrativeDivision varchar(50) not null;
  6 +
  7 +alter table parent_platform
  8 + add catalogGroup int default 1 null;
6 9  
7 10 alter table device
8   - add subscribeCycleForAlarm int null;
9 11 \ No newline at end of file
  12 + add ssrcCheck int default 0 null;
  13 +
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
... ... @@ -129,6 +129,11 @@ public class Device {
129 129 */
130 130 private int subscribeCycleForAlarm;
131 131  
  132 + /**
  133 + * 是否开启ssrc校验,默认关闭,开启可以防止串流
  134 + */
  135 + private boolean ssrcCheck;
  136 +
132 137  
133 138 public String getDeviceId() {
134 139 return deviceId;
... ... @@ -321,4 +326,12 @@ public class Device {
321 326 public void setSubscribeCycleForAlarm(int subscribeCycleForAlarm) {
322 327 this.subscribeCycleForAlarm = subscribeCycleForAlarm;
323 328 }
  329 +
  330 + public boolean isSsrcCheck() {
  331 + return ssrcCheck;
  332 + }
  333 +
  334 + public void setSsrcCheck(boolean ssrcCheck) {
  335 + this.ssrcCheck = ssrcCheck;
  336 + }
324 337 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
... ... @@ -169,6 +169,11 @@ public class DeviceChannel {
169 169 */
170 170 private boolean hasAudio;
171 171  
  172 + /**
  173 + * 标记通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
  174 + */
  175 + private int channelType;
  176 +
172 177 public int getId() {
173 178 return id;
174 179 }
... ... @@ -441,4 +446,12 @@ public class DeviceChannel {
441 446 public void setUpdateTime(String updateTime) {
442 447 this.updateTime = updateTime;
443 448 }
  449 +
  450 + public int getChannelType() {
  451 + return channelType;
  452 + }
  453 +
  454 + public void setChannelType(int channelType) {
  455 + this.channelType = channelType;
  456 + }
444 457 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
... ... @@ -129,6 +129,21 @@ public class ParentPlatform {
129 129 */
130 130 private boolean mobilePositionSubscribe;
131 131  
  132 + /**
  133 + * 点播未推流的设备时是否使用redis通知拉起
  134 + */
  135 + private boolean startOfflinePush;
  136 +
  137 + /**
  138 + * 目录分组-每次向上级发送通道信息时单个包携带的通道数量,取值1,2,4,8
  139 + */
  140 + private int catalogGroup;
  141 +
  142 + /**
  143 + * 行政区划
  144 + */
  145 + private String administrativeDivision;
  146 +
132 147 public Integer getId() {
133 148 return id;
134 149 }
... ... @@ -329,4 +344,28 @@ public class ParentPlatform {
329 344 public void setMobilePositionSubscribe(boolean mobilePositionSubscribe) {
330 345 this.mobilePositionSubscribe = mobilePositionSubscribe;
331 346 }
  347 +
  348 + public boolean isStartOfflinePush() {
  349 + return startOfflinePush;
  350 + }
  351 +
  352 + public void setStartOfflinePush(boolean startOfflinePush) {
  353 + this.startOfflinePush = startOfflinePush;
  354 + }
  355 +
  356 + public int getCatalogGroup() {
  357 + return catalogGroup;
  358 + }
  359 +
  360 + public void setCatalogGroup(int catalogGroup) {
  361 + this.catalogGroup = catalogGroup;
  362 + }
  363 +
  364 + public String getAdministrativeDivision() {
  365 + return administrativeDivision;
  366 + }
  367 +
  368 + public void setAdministrativeDivision(String administrativeDivision) {
  369 + this.administrativeDivision = administrativeDivision;
  370 + }
332 371 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
... ... @@ -85,6 +85,12 @@ public class CatalogDataCatch {
85 85 return syncStatus;
86 86 }
87 87  
  88 + public boolean isSyncRunning(String deviceId) {
  89 + CatalogData catalogData = data.get(deviceId);
  90 + if (catalogData == null) return false;
  91 + return !catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end);
  92 + }
  93 +
88 94 @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时
89 95 private void timerTask(){
90 96 Set<String> keys = data.keySet();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
... ... @@ -10,6 +10,8 @@ import org.springframework.scheduling.annotation.Async;
10 10 import javax.sip.Dialog;
11 11 import javax.sip.DialogState;
12 12 import javax.sip.ResponseEvent;
  13 +import java.util.Timer;
  14 +import java.util.TimerTask;
13 15  
14 16 /**
15 17 * 目录订阅任务
... ... @@ -20,6 +22,8 @@ public class CatalogSubscribeTask implements ISubscribeTask {
20 22 private final ISIPCommander sipCommander;
21 23 private Dialog dialog;
22 24  
  25 + private Timer timer ;
  26 +
23 27 public CatalogSubscribeTask(Device device, ISIPCommander sipCommander) {
24 28 this.device = device;
25 29 this.sipCommander = sipCommander;
... ... @@ -27,6 +31,10 @@ public class CatalogSubscribeTask implements ISubscribeTask {
27 31  
28 32 @Override
29 33 public void run() {
  34 + if (timer != null ) {
  35 + timer.cancel();
  36 + timer = null;
  37 + }
30 38 sipCommander.catalogSubscribe(device, dialog, eventResult -> {
31 39 if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
32 40 dialog = eventResult.dialog;
... ... @@ -43,6 +51,13 @@ public class CatalogSubscribeTask implements ISubscribeTask {
43 51 dialog = null;
44 52 // 失败
45 53 logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  54 + timer = new Timer();
  55 + timer.schedule(new TimerTask() {
  56 + @Override
  57 + public void run() {
  58 + CatalogSubscribeTask.this.run();
  59 + }
  60 + }, 2000);
46 61 });
47 62 }
48 63  
... ... @@ -56,9 +71,13 @@ public class CatalogSubscribeTask implements ISubscribeTask {
56 71 * TERMINATED-> Terminated Dialog状态-终止
57 72 */
58 73 logger.info("取消目录订阅时dialog状态为{}", DialogState.CONFIRMED);
  74 + if (timer != null ) {
  75 + timer.cancel();
  76 + timer = null;
  77 + }
59 78 if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
60 79 device.setSubscribeCycleForCatalog(0);
61   - sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
  80 + sipCommander.catalogSubscribe(device, dialog, eventResult -> {
62 81 ResponseEvent event = (ResponseEvent) eventResult.event;
63 82 if (event.getResponse().getRawContent() != null) {
64 83 // 成功
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
... ... @@ -29,7 +29,6 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
29 29 private String key;
30 30  
31 31 public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorage storager, String platformId, String sn, String key, SubscribeHolder subscribeInfo) {
32   - System.out.println("MobilePositionSubscribeHandlerTask 初始化");
33 32 this.redisCatchStorage = redisCatchStorage;
34 33 this.storager = storager;
35 34 this.platform = storager.queryParentPlatByServerGBId(platformId);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
... ... @@ -32,6 +32,7 @@ import javax.sip.header.*;
32 32 import javax.sip.message.Request;
33 33 import java.lang.reflect.Field;
34 34 import java.text.ParseException;
  35 +import java.util.ArrayList;
35 36 import java.util.HashSet;
36 37 import java.util.List;
37 38 import java.util.UUID;
... ... @@ -215,7 +216,11 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
215 216 return false;
216 217 }
217 218 try {
218   - String catalogXml = getCatalogXml(channel, sn, parentPlatform, size);
  219 + List<DeviceChannel> channels = new ArrayList<>();
  220 + if (channel != null) {
  221 + channels.add(channel);
  222 + }
  223 + String catalogXml = getCatalogXml(channels, sn, parentPlatform, size);
219 224  
220 225 // callid
221 226 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
... ... @@ -239,7 +244,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
239 244 sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
240 245 return true;
241 246 }
242   - private String getCatalogXml(DeviceChannel channel, String sn, ParentPlatform parentPlatform, int size) {
  247 + private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) {
243 248 String characterSet = parentPlatform.getCharacterSet();
244 249 StringBuffer catalogXml = new StringBuffer(600);
245 250 catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet +"\"?>\r\n");
... ... @@ -248,34 +253,38 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
248 253 catalogXml.append("<SN>" +sn + "</SN>\r\n");
249 254 catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
250 255 catalogXml.append("<SumNum>" + size + "</SumNum>\r\n");
251   - catalogXml.append("<DeviceList Num=\"1\">\r\n");
252   - catalogXml.append("<Item>\r\n");
253   - if (channel != null) {
254   - catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
255   - catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
256   - catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
257   - catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
258   - catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
259   - catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
260   - catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
261   - catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
262   - if (channel.getParentId() != null) {
263   - catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  256 + catalogXml.append("<DeviceList Num=\"" + channels.size() +"\">\r\n");
  257 + if (channels.size() > 0) {
  258 + for (DeviceChannel channel : channels) {
  259 + catalogXml.append("<Item>\r\n");
  260 + catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
  261 + catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
  262 + catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
  263 + catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
  264 + if (channel.getParentId() != null) {
  265 + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  266 + }
  267 + catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
  268 + catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
  269 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
  270 + if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下字段
  271 + catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
  272 + catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
  273 + catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
  274 + catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
  275 + catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");
  276 + catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n");
  277 + catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
  278 + catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
  279 + catalogXml.append("<Info>\r\n");
  280 + catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
  281 + catalogXml.append("</Info>\r\n");
  282 + }
  283 +
  284 + catalogXml.append("</Item>\r\n");
264 285 }
265   - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
266   - catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
267   - catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
268   - catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");
269   - catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n");
270   - catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
271   - catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
272   - catalogXml.append("<Info>\r\n");
273   - catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
274   - catalogXml.append("</Info>\r\n");
275 286 }
276 287  
277   -
278   - catalogXml.append("</Item>\r\n");
279 288 catalogXml.append("</DeviceList>\r\n");
280 289 catalogXml.append("</Response>\r\n");
281 290 return catalogXml.toString();
... ... @@ -286,15 +295,20 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
286 295 return;
287 296 }
288 297 try {
289   - DeviceChannel deviceChannel = channels.get(index);
290   - String catalogXml = getCatalogXml(deviceChannel, sn, parentPlatform, channels.size());
  298 + List<DeviceChannel> deviceChannels;
  299 + if (index + parentPlatform.getCatalogGroup() < channels.size()) {
  300 + deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());
  301 + }else {
  302 + deviceChannels = channels.subList(index, channels.size());
  303 + }
  304 + String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());
291 305 // callid
292 306 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
293 307 : udpSipProvider.getNewCallId();
294 308  
295 309 Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, callIdHeader);
296 310 transmitRequest(parentPlatform, request, null, eventResult -> {
297   - int indexNext = index + 1;
  311 + int indexNext = index + parentPlatform.getCatalogGroup();
298 312 sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
299 313 });
300 314 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -432,13 +446,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
432 446 if (index >= deviceChannels.size()) {
433 447 return true;
434 448 }
  449 + List<DeviceChannel> channels;
  450 + if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
  451 + channels = deviceChannels.subList(index, index + parentPlatform.getCatalogGroup());
  452 + }else {
  453 + channels = deviceChannels.subList(index, deviceChannels.size());
  454 + }
435 455 try {
436 456 Integer finalIndex = index;
437   - String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, deviceChannels.get(index ), deviceChannels.size(), type, subscribeInfo);
  457 + String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
  458 + deviceChannels.size(), type, subscribeInfo);
438 459 sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
439 460 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
440 461 }, (eventResult -> {
441   - sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex + 1);
  462 + sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo,
  463 + finalIndex + parentPlatform.getCatalogGroup());
442 464 }));
443 465 } catch (SipException | ParseException e) {
444 466 e.printStackTrace();
... ... @@ -500,11 +522,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
500 522  
501 523 }
502 524  
503   - private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type, SubscribeInfo subscribeInfo) {
  525 + private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
504 526 StringBuffer catalogXml = new StringBuffer(600);
505   - if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
506   - channel.setParentId(parentPlatform.getDeviceGBId());
507   - }
  527 +
508 528 String characterSet = parentPlatform.getCharacterSet();
509 529 catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
510 530 catalogXml.append("<Notify>\r\n");
... ... @@ -512,26 +532,35 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
512 532 catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
513 533 catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
514 534 catalogXml.append("<SumNum>1</SumNum>\r\n");
515   - catalogXml.append("<DeviceList Num=\"1\">\r\n");
516   - catalogXml.append("<Item>\r\n");
517   - catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
518   - catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
519   - catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
520   - catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
521   - catalogXml.append("<Owner>0</Owner>\r\n");
522   - catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n");
523   - catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
524   - catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
525   - if (channel.getParentId() != null) {
526   - catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
527   - }
528   - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
529   - catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
530   - catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
531   - if (!"presence".equals(subscribeInfo.getEventType())) {
532   - catalogXml.append("<Event>" + type + "</Event>\r\n");
533   - }
534   - catalogXml.append("</Item>\r\n");
  535 + catalogXml.append("<DeviceList Num=\"" + channels.size() + "\">\r\n");
  536 + if (channels.size() > 0) {
  537 + for (DeviceChannel channel : channels) {
  538 + if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
  539 + channel.setParentId(parentPlatform.getDeviceGBId());
  540 + }
  541 + catalogXml.append("<Item>\r\n");
  542 + catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
  543 + catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
  544 + catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
  545 + catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
  546 + if (channel.getParentId() != null) {
  547 + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  548 + }
  549 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
  550 + catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
  551 + catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
  552 + if (channel.getChannelType() == 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
  553 + catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
  554 + catalogXml.append("<Owner>0</Owner>\r\n");
  555 + catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n");
  556 + catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
  557 + }
  558 + if (!"presence".equals(subscribeInfo.getEventType())) {
  559 + catalogXml.append("<Event>" + type + "</Event>\r\n");
  560 + }
  561 + catalogXml.append("</Item>\r\n");
  562 + }
  563 + }
535 564 catalogXml.append("</DeviceList>\r\n");
536 565 catalogXml.append("</Notify>\r\n");
537 566 return catalogXml.toString();
... ... @@ -553,13 +582,20 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
553 582 if (index >= deviceChannels.size()) {
554 583 return true;
555 584 }
  585 + List<DeviceChannel> channels;
  586 + if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
  587 + channels = deviceChannels.subList(index, index + parentPlatform.getCatalogGroup());
  588 + }else {
  589 + channels = deviceChannels.subList(index, deviceChannels.size());
  590 + }
556 591 try {
557 592 Integer finalIndex = index;
558   - String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, deviceChannels.get(index), type);
  593 + String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
559 594 sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
560 595 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
561 596 }, (eventResult -> {
562   - sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex + 1);
  597 + sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo,
  598 + finalIndex + parentPlatform.getCatalogGroup());
563 599 }));
564 600 } catch (SipException e) {
565 601 e.printStackTrace();
... ... @@ -574,10 +610,8 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
574 610 return true;
575 611 }
576 612  
577   - private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, DeviceChannel channel, String type) {
578   - if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
579   - channel.setParentId(parentPlatform.getDeviceGBId());
580   - }
  613 + private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) {
  614 +
581 615 String characterSet = parentPlatform.getCharacterSet();
582 616 StringBuffer catalogXml = new StringBuffer(600);
583 617 catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
... ... @@ -586,11 +620,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
586 620 catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
587 621 catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
588 622 catalogXml.append("<SumNum>1</SumNum>\r\n");
589   - catalogXml.append("<DeviceList Num=\"1\">\r\n");
590   - catalogXml.append("<Item>\r\n");
591   - catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
592   - catalogXml.append("<Event>" + type + "</Event>\r\n");
593   - catalogXml.append("</Item>\r\n");
  623 + catalogXml.append("<DeviceList Num=\" " + channels.size() + " \">\r\n");
  624 + if (channels.size() > 0) {
  625 + for (DeviceChannel channel : channels) {
  626 + if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
  627 + channel.setParentId(parentPlatform.getDeviceGBId());
  628 + }
  629 + catalogXml.append("<Item>\r\n");
  630 + catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
  631 + catalogXml.append("<Event>" + type + "</Event>\r\n");
  632 + catalogXml.append("</Item>\r\n");
  633 + }
  634 + }
594 635 catalogXml.append("</DeviceList>\r\n");
595 636 catalogXml.append("</Notify>\r\n");
596 637 return catalogXml.toString();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
... ... @@ -397,6 +397,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
397 397 logger.info("[ app={}, stream={} ]通道离线,启用流后开始推流",gbStream.getApp(), gbStream.getStream());
398 398 responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
399 399 }else if ("push".equals(gbStream.getStreamType())) {
  400 + if (!platform.isStartOfflinePush()) {
  401 + responseAck(evt, Response.TEMPORARILY_UNAVAILABLE, "channel unavailable");
  402 + return;
  403 + }
400 404 // 发送redis消息以使设备上线
401 405 logger.info("[ app={}, stream={} ]通道离线,发送redis信息控制设备开始推流",gbStream.getApp(), gbStream.getStream());
402 406 MessageForPushChannel messageForPushChannel = new MessageForPushChannel();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
... ... @@ -3,7 +3,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
3 3 import com.genersoft.iot.vmp.common.VideoManagerConstants;
4 4 import com.genersoft.iot.vmp.conf.SipConfig;
5 5 import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper;
6   -import com.genersoft.iot.vmp.gb28181.auth.RegisterLogicHandler;
7 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
8 7 import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate;
9 8 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
... ... @@ -42,166 +41,157 @@ import java.util.Locale;
42 41 @Component
43 42 public class RegisterRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
44 43  
45   - private Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class);
46   -
47   - public String method = "REGISTER";
48   -
49   - @Autowired
50   - private SipConfig sipConfig;
51   -
52   - @Autowired
53   - private RegisterLogicHandler handler;
54   -
55   - @Autowired
56   - private IRedisCatchStorage redisCatchStorage;
57   -
58   - @Autowired
59   - private IVideoManagerStorage storager;
60   -
61   - @Autowired
62   - private EventPublisher publisher;
63   -
64   - @Autowired
65   - private SIPProcessorObserver sipProcessorObserver;
66   -
67   - @Override
68   - public void afterPropertiesSet() throws Exception {
69   - // 添加消息处理的订阅
70   - sipProcessorObserver.addRequestProcessor(method, this);
71   - }
72   -
73   - /**
74   - * 收到注册请求 处理
75   - * @param evt
76   - */
77   - @Override
78   - public void process(RequestEvent evt) {
79   - try {
80   - RequestEventExt evtExt = (RequestEventExt)evt;
81   - String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort();
82   - logger.info("[{}] 收到注册请求,开始处理", requestAddress);
83   - Request request = evt.getRequest();
84   - ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME);
85   - Response response = null;
86   - boolean passwordCorrect = false;
87   - // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功
88   - int registerFlag = 0;
89   - FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
90   - AddressImpl address = (AddressImpl) fromHeader.getAddress();
91   - SipUri uri = (SipUri) address.getURI();
92   - String deviceId = uri.getUser();
93   - Device deviceInRedis = redisCatchStorage.getDevice(deviceId);
94   - Device device = storager.queryVideoDevice(deviceId);
95   - if (deviceInRedis != null && device == null) {
96   - // redis 存在脏数据
97   - redisCatchStorage.clearCatchByDeviceId(deviceId);
98   - }
99   - AuthorizationHeader authorhead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
100   - // 校验密码是否正确
101   - if (authorhead != null) {
102   - passwordCorrect = new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request,
103   - sipConfig.getPassword());
104   - }
105   - if (StringUtils.isEmpty(sipConfig.getPassword())){
106   - passwordCorrect = true;
107   - }
108   -
109   - // 未携带授权头或者密码错误 回复401
110   - if (authorhead == null ) {
111   -
112   - logger.info("[{}] 未携带授权头 回复401", requestAddress);
113   - response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
114   - new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
115   - }else {
116   - if (!passwordCorrect){
117   - // 注册失败
118   - response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
119   - response.setReasonPhrase("wrong password");
120   - logger.info("[{}] 密码/SIP服务器ID错误, 回复403", requestAddress);
121   - }else {
122   - // 携带授权头并且密码正确
123   - response = getMessageFactory().createResponse(Response.OK, request);
124   - // 添加date头
125   - SIPDateHeader dateHeader = new SIPDateHeader();
126   - // 使用自己修改的
127   - WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis());
128   - dateHeader.setDate(wvpSipDate);
129   - response.addHeader(dateHeader);
130   -
131   -
132   - if (expiresHeader == null) {
133   - response = getMessageFactory().createResponse(Response.BAD_REQUEST, request);
134   - ServerTransaction serverTransaction = getServerTransaction(evt);
135   - serverTransaction.sendResponse(response);
136   - if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
137   - return;
138   - }
139   - // 添加Contact头
140   - response.addHeader(request.getHeader(ContactHeader.NAME));
141   - // 添加Expires头
142   - response.addHeader(request.getExpires());
143   -
144   - // 获取到通信地址等信息
145   - ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
146   - String received = viaHeader.getReceived();
147   - int rPort = viaHeader.getRPort();
148   - // 解析本地地址替代
149   - if (StringUtils.isEmpty(received) || rPort == -1) {
150   - received = viaHeader.getHost();
151   - rPort = viaHeader.getPort();
152   - }
153   - //
154   -
155   - if (device == null) {
156   - device = new Device();
157   - device.setStreamMode("UDP");
158   - device.setCharset("GB2312");
159   - device.setDeviceId(deviceId);
160   - device.setFirsRegister(true);
161   - }else {
162   - if (device.getOnline() == 0) {
163   - device.setFirsRegister(true);
164   - }
165   - }
166   - device.setIp(received);
167   - device.setPort(rPort);
168   - device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
169   - // 注销成功
170   - if (expiresHeader.getExpires() == 0) {
171   - registerFlag = 2;
172   - }
173   - // 注册成功
174   - else {
175   - device.setExpires(expiresHeader.getExpires());
176   - registerFlag = 1;
177   - // 判断TCP还是UDP
178   - boolean isTcp = false;
179   - ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
180   - String transport = reqViaHeader.getTransport();
181   - if (transport.equals("TCP")) {
182   - isTcp = true;
183   - }
184   - device.setTransport(isTcp ? "TCP" : "UDP");
185   - }
186   - }
187   - }
188   -
189   - ServerTransaction serverTransaction = getServerTransaction(evt);
190   - serverTransaction.sendResponse(response);
191   - if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
192   - // 注册成功
193   - // 保存到redis
194   - if (registerFlag == 1 ) {
195   - logger.info("[{}] 注册成功! deviceId:" + device.getDeviceId(), requestAddress);
196   - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER, expiresHeader.getExpires());
197   - } else if (registerFlag == 2) {
198   - logger.info("[{}] 注销成功! deviceId:" + device.getDeviceId(), requestAddress);
199   - publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER);
200   - }
201   - } catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) {
202   - e.printStackTrace();
203   - }
204   -
205   - }
  44 + private final Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class);
  45 +
  46 + public String method = "REGISTER";
  47 +
  48 + @Autowired
  49 + private SipConfig sipConfig;
  50 +
  51 + @Autowired
  52 + private IRedisCatchStorage redisCatchStorage;
  53 +
  54 + @Autowired
  55 + private IVideoManagerStorage storager;
  56 +
  57 + @Autowired
  58 + private EventPublisher publisher;
  59 +
  60 + @Autowired
  61 + private SIPProcessorObserver sipProcessorObserver;
  62 +
  63 + @Override
  64 + public void afterPropertiesSet() throws Exception {
  65 + // 添加消息处理的订阅
  66 + sipProcessorObserver.addRequestProcessor(method, this);
  67 + }
  68 +
  69 + /**
  70 + * 收到注册请求 处理
  71 + *
  72 + * @param evt
  73 + */
  74 + @Override
  75 + public void process(RequestEvent evt) {
  76 + try {
  77 + RequestEventExt evtExt = (RequestEventExt) evt;
  78 + String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort();
  79 + logger.info("[{}] 收到注册请求,开始处理", requestAddress);
  80 + Request request = evt.getRequest();
  81 + ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME);
  82 + Response response = null;
  83 + boolean passwordCorrect = false;
  84 + // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功
  85 + int registerFlag = 0;
  86 + FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
  87 + AddressImpl address = (AddressImpl) fromHeader.getAddress();
  88 + SipUri uri = (SipUri) address.getURI();
  89 + String deviceId = uri.getUser();
  90 +
  91 + AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
  92 + if (authHead == null) {
  93 + logger.info("[{}] 未携带授权头 回复401", requestAddress);
  94 + response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
  95 + new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
  96 + sendResponse(evt, response);
  97 + return;
  98 + }
  99 +
  100 + // 校验密码是否正确
  101 + passwordCorrect = StringUtils.isEmpty(sipConfig.getPassword()) ||
  102 + new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, sipConfig.getPassword());
  103 + // 未携带授权头或者密码错误 回复401
  104 +
  105 + if (!passwordCorrect) {
  106 + // 注册失败
  107 + response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
  108 + response.setReasonPhrase("wrong password");
  109 + logger.info("[{}] 密码/SIP服务器ID错误, 回复403", requestAddress);
  110 + sendResponse(evt, response);
  111 + return;
  112 + }
  113 +
  114 + Device deviceInRedis = redisCatchStorage.getDevice(deviceId);
  115 + Device device = storager.queryVideoDevice(deviceId);
  116 + if (deviceInRedis != null && device == null) {
  117 + // redis 存在脏数据
  118 + redisCatchStorage.clearCatchByDeviceId(deviceId);
  119 + }
  120 + // 携带授权头并且密码正确
  121 + response = getMessageFactory().createResponse(Response.OK, request);
  122 + // 添加date头
  123 + SIPDateHeader dateHeader = new SIPDateHeader();
  124 + // 使用自己修改的
  125 + WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis());
  126 + dateHeader.setDate(wvpSipDate);
  127 + response.addHeader(dateHeader);
  128 +
  129 + if (expiresHeader == null) {
  130 + response = getMessageFactory().createResponse(Response.BAD_REQUEST, request);
  131 + ServerTransaction serverTransaction = getServerTransaction(evt);
  132 + serverTransaction.sendResponse(response);
  133 + if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
  134 + return;
  135 + }
  136 + // 添加Contact头
  137 + response.addHeader(request.getHeader(ContactHeader.NAME));
  138 + // 添加Expires头
  139 + response.addHeader(request.getExpires());
  140 +
  141 + // 获取到通信地址等信息
  142 + ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
  143 + String received = viaHeader.getReceived();
  144 + int rPort = viaHeader.getRPort();
  145 + // 解析本地地址替代
  146 + if (StringUtils.isEmpty(received) || rPort == -1) {
  147 + received = viaHeader.getHost();
  148 + rPort = viaHeader.getPort();
  149 + }
  150 + if (device == null) {
  151 + device = new Device();
  152 + device.setStreamMode("UDP");
  153 + device.setCharset("GB2312");
  154 + device.setDeviceId(deviceId);
  155 + device.setFirsRegister(true);
  156 + } else {
  157 + device.setFirsRegister(device.getOnline() == 0);
  158 + }
  159 + device.setIp(received);
  160 + device.setPort(rPort);
  161 + device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
  162 + if (expiresHeader.getExpires() == 0) {
  163 + // 注销成功
  164 + registerFlag = 2;
  165 + } else {
  166 + // 注册成功
  167 + device.setExpires(expiresHeader.getExpires());
  168 + registerFlag = 1;
  169 + // 判断TCP还是UDP
  170 + ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
  171 + String transport = reqViaHeader.getTransport();
  172 + device.setTransport("TCP".equals(transport) ? "TCP" : "UDP");
  173 + }
  174 +
  175 + sendResponse(evt, response);
  176 + // 注册成功
  177 + // 保存到redis
  178 + if (registerFlag == 1) {
  179 + logger.info("[{}] 注册成功! deviceId:" + deviceId, requestAddress);
  180 + publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER, expiresHeader.getExpires());
  181 + } else if (registerFlag == 2) {
  182 + logger.info("[{}] 注销成功! deviceId:" + deviceId, requestAddress);
  183 + publisher.outlineEventPublish(deviceId, VideoManagerConstants.EVENT_OUTLINE_UNREGISTER);
  184 + }
  185 + } catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) {
  186 + e.printStackTrace();
  187 + }
  188 +
  189 + }
  190 +
  191 + private void sendResponse(RequestEvent evt, Response response) throws InvalidArgumentException, SipException {
  192 + ServerTransaction serverTransaction = getServerTransaction(evt);
  193 + serverTransaction.sendResponse(response);
  194 + if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
  195 + }
206 196  
207 197 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
... ... @@ -79,7 +79,7 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
79 79 deviceChannel.setParental(1);
80 80 deviceChannel.setParentId(catalog.getParentId());
81 81 deviceChannel.setRegisterWay(1);
82   - deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6));
  82 + deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
83 83 deviceChannel.setModel("live");
84 84 deviceChannel.setOwner("wvp-pro");
85 85 deviceChannel.setSecrecy("0");
... ... @@ -116,7 +116,7 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
116 116 deviceChannel.setStatus(1);
117 117 deviceChannel.setParentId(gbStream.getCatalogId());
118 118 deviceChannel.setRegisterWay(1);
119   - deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6));
  119 + deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
120 120 deviceChannel.setModel("live");
121 121 deviceChannel.setOwner("wvp-pro");
122 122 deviceChannel.setParental(0);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
... ... @@ -83,20 +83,17 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
83 83 catalog.setParentId(parentPlatform.getDeviceGBId());
84 84 }
85 85 DeviceChannel deviceChannel = new DeviceChannel();
  86 + // 通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
  87 + deviceChannel.setChannelType(2);
86 88 deviceChannel.setChannelId(catalog.getId());
87 89 deviceChannel.setName(catalog.getName());
88   - deviceChannel.setLongitude(0.0);
89   - deviceChannel.setLatitude(0.0);
90 90 deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
91 91 deviceChannel.setManufacture("wvp-pro");
92 92 deviceChannel.setStatus(1);
93 93 deviceChannel.setParental(1);
94 94 deviceChannel.setParentId(catalog.getParentId());
95 95 deviceChannel.setRegisterWay(1);
96   - deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6));
97   - deviceChannel.setModel("live");
98   - deviceChannel.setOwner("wvp-pro");
99   - deviceChannel.setSecrecy("0");
  96 + deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
100 97 allChannels.add(deviceChannel);
101 98 }
102 99 }
... ... @@ -107,6 +104,8 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
107 104 channel.setCatalogId(parentPlatform.getDeviceGBId());
108 105 }
109 106 DeviceChannel deviceChannel = storage.queryChannel(channel.getDeviceId(), channel.getChannelId());
  107 + // 通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
  108 + deviceChannel.setChannelType(0);
110 109 deviceChannel.setParental(0);
111 110 deviceChannel.setParentId(channel.getCatalogId());
112 111 deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0, 6));
... ... @@ -120,6 +119,8 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
120 119 gbStream.setCatalogId(null);
121 120 }
122 121 DeviceChannel deviceChannel = new DeviceChannel();
  122 + // 通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
  123 + deviceChannel.setChannelType(1);
123 124 deviceChannel.setChannelId(gbStream.getGbId());
124 125 deviceChannel.setName(gbStream.getName());
125 126 deviceChannel.setLongitude(gbStream.getLongitude());
... ... @@ -130,7 +131,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
130 131 deviceChannel.setStatus(1);
131 132 deviceChannel.setParentId(gbStream.getCatalogId());
132 133 deviceChannel.setRegisterWay(1);
133   - deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0,6));
  134 + deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
134 135 deviceChannel.setModel("live");
135 136 deviceChannel.setOwner("wvp-pro");
136 137 deviceChannel.setParental(0);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
... ... @@ -118,8 +118,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
118 118 channelList.add(deviceChannel);
119 119 }
120 120 int sn = Integer.parseInt(snElement.getText());
121   - logger.info("收到来自设备【{}】的通道: {}个,{}/{}", device.getDeviceId(), channelList.size(), catalogDataCatch.get(key) == null ? 0 :catalogDataCatch.get(key).size(), sumNum);
122 121 catalogDataCatch.put(device.getDeviceId(), sn, sumNum, device, channelList);
  122 + logger.info("收到来自设备【{}】的通道: {}个,{}/{}", device.getDeviceId(), channelList.size(), catalogDataCatch.get(device.getDeviceId()) == null ? 0 :catalogDataCatch.get(device.getDeviceId()).size(), sumNum);
123 123 if (catalogDataCatch.get(device.getDeviceId()).size() == sumNum) {
124 124 // 数据已经完整接收
125 125 boolean resetChannelsResult = storager.resetChannels(device.getDeviceId(), catalogDataCatch.get(device.getDeviceId()));
... ... @@ -223,6 +223,14 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
223 223 }
224 224 }
225 225  
  226 + public boolean isSyncRunning(String deviceId) {
  227 + if (catalogDataCatch.get(deviceId) == null) {
  228 + return false;
  229 + }else {
  230 + return catalogDataCatch.isSyncRunning(deviceId);
  231 + }
  232 + }
  233 +
226 234 public void setChannelSyncReady(Device device, int sn) {
227 235 catalogDataCatch.addReady(device, sn);
228 236 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
... ... @@ -20,8 +20,8 @@ import java.util.*;
20 20  
21 21 /**
22 22 * 基于dom4j的工具包
23   - *
24   - *
  23 + *
  24 + *
25 25 */
26 26 public class XmlUtil {
27 27 /**
... ... @@ -31,9 +31,9 @@ public class XmlUtil {
31 31  
32 32 /**
33 33 * 解析XML为Document对象
34   - *
  34 + *
35 35 * @param xml 被解析的XMl
36   - *
  36 + *
37 37 * @return Document
38 38 */
39 39 public static Element parseXml(String xml) {
... ... @@ -51,7 +51,7 @@ public class XmlUtil {
51 51  
52 52 /**
53 53 * 获取element对象的text的值
54   - *
  54 + *
55 55 * @param em 节点的对象
56 56 * @param tag 节点的tag
57 57 * @return 节点
... ... @@ -62,12 +62,12 @@ public class XmlUtil {
62 62 }
63 63 Element e = em.element(tag);
64 64 //
65   - return null == e ? null : e.getText();
  65 + return null == e ? null : e.getText().trim();
66 66 }
67 67  
68 68 /**
69 69 * 递归解析xml节点,适用于 多节点数据
70   - *
  70 + *
71 71 * @param node node
72 72 * @param nodeName nodeName
73 73 * @return List<Map<String, Object>>
... ... @@ -106,7 +106,7 @@ public class XmlUtil {
106 106  
107 107 /**
108 108 * xml转json
109   - *
  109 + *
110 110 * @param element
111 111 * @param json
112 112 */
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
... ... @@ -81,7 +81,7 @@ public class ZLMRTPServerFactory {
81 81 return result;
82 82 }
83 83  
84   - public int createRTPServer(MediaServerItem mediaServerItem, String streamId) {
  84 + public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc) {
85 85 int result = -1;
86 86 // 查询此rtp server 是否已经存在
87 87 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId);
... ... @@ -94,6 +94,7 @@ public class ZLMRTPServerFactory {
94 94 param.put("enable_tcp", 1);
95 95 param.put("stream_id", streamId);
96 96 param.put("port", 0);
  97 + param.put("ssrc", ssrc);
97 98 JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
98 99  
99 100 if (openRtpServerResultJson != null) {
... ...
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
... ... @@ -44,6 +44,13 @@ public interface IDeviceService {
44 44 SyncStatus getChannelSyncStatus(String deviceId);
45 45  
46 46 /**
  47 + * 查看是否仍在同步
  48 + * @param deviceId 设备ID
  49 + * @return
  50 + */
  51 + Boolean isSyncRunning(String deviceId);
  52 +
  53 + /**
47 54 * 通道同步
48 55 * @param device
49 56 */
... ...
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
... ... @@ -44,9 +44,9 @@ public interface IMediaServerService {
44 44  
45 45 void updateVmServer(List<MediaServerItem> mediaServerItemList);
46 46  
47   - SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId);
  47 + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck);
48 48  
49   - SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback);
  49 + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback);
50 50  
51 51 void closeRTPServer(String deviceId, String channelId, String ssrc);
52 52  
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
... ... @@ -41,10 +41,6 @@ public class DeviceServiceImpl implements IDeviceService {
41 41 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
42 42 return false;
43 43 }
44   - CatalogSubscribeTask task = (CatalogSubscribeTask)dynamicTask.get(device.getDeviceId() + "catalog");
45   - if (task != null && task.getDialogState() != null && task.getDialogState().equals(DialogState.CONFIRMED)) { // 已存在不需要再次添加
46   - return true;
47   - }
48 44 logger.info("[添加目录订阅] 设备{}", device.getDeviceId());
49 45 // 添加目录订阅
50 46 CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander);
... ... @@ -71,10 +67,6 @@ public class DeviceServiceImpl implements IDeviceService {
71 67 return false;
72 68 }
73 69 logger.info("[添加移动位置订阅] 设备{}", device.getDeviceId());
74   - MobilePositionSubscribeTask task = (MobilePositionSubscribeTask)dynamicTask.get(device.getDeviceId() + "mobile_position");
75   - if (task != null && task.getDialogState() != null && task.getDialogState().equals(DialogState.CONFIRMED)) { // 已存在不需要再次添加
76   - return true;
77   - }
78 70 // 添加目录订阅
79 71 MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander);
80 72 // 提前开始刷新订阅
... ... @@ -100,8 +92,13 @@ public class DeviceServiceImpl implements IDeviceService {
100 92 }
101 93  
102 94 @Override
  95 + public Boolean isSyncRunning(String deviceId) {
  96 + return catalogResponseMessageHandler.isSyncRunning(deviceId);
  97 + }
  98 +
  99 + @Override
103 100 public void sync(Device device) {
104   - if (catalogResponseMessageHandler.getChannelSyncProgress(device.getDeviceId()) != null) {
  101 + if (catalogResponseMessageHandler.isSyncRunning(device.getDeviceId())) {
105 102 logger.info("开启同步时发现同步已经存在");
106 103 return;
107 104 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
... ... @@ -117,12 +117,12 @@ public class MediaServerServiceImpl implements IMediaServerService {
117 117 }
118 118  
119 119 @Override
120   - public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId) {
121   - return openRTPServer(mediaServerItem, streamId, false);
  120 + public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck) {
  121 + return openRTPServer(mediaServerItem, streamId, ssrcCheck,false);
122 122 }
123 123  
124 124 @Override
125   - public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback) {
  125 + public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback) {
126 126 if (mediaServerItem == null || mediaServerItem.getId() == null) {
127 127 return null;
128 128 }
... ... @@ -146,7 +146,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
146 146 }
147 147 int rtpServerPort = mediaServerItem.getRtpProxyPort();
148 148 if (mediaServerItem.isRtpEnable()) {
149   - rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
  149 + rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0);
150 150 }
151 151 redisUtil.set(key, mediaServerItem);
152 152 return new SSRCInfo(rtpServerPort, ssrc, streamId);
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -188,7 +188,7 @@ public class PlayServiceImpl implements IPlayService {
188 188 if (mediaServerItem.isRtpEnable()) {
189 189 streamId = String.format("%s_%s", device.getDeviceId(), channelId);
190 190 }
191   - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId);
  191 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck());
192 192 play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response)->{
193 193 if (hookEvent != null) {
194 194 hookEvent.response(mediaServerItem, response);
... ... @@ -232,7 +232,7 @@ public class PlayServiceImpl implements IPlayService {
232 232 streamId = String.format("%s_%s", device.getDeviceId(), channelId);
233 233 }
234 234 if (ssrcInfo == null) {
235   - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId);
  235 + ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck());
236 236 }
237 237  
238 238 // 超时处理
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
... ... @@ -420,9 +420,6 @@ public class StreamPushServiceImpl implements IStreamPushService {
420 420 continue;
421 421 }
422 422 streamPushItemForPlatform.setPlatformId(platFormInfoArray[0]);
423   - if (platFormInfoArray[0].equals("34020000002110000001")) {
424   - System.out.println(111);
425   - }
426 423 List<GbStream> gbStreamList = platformForEvent.get(platFormInfoArray[0]);
427 424 if (gbStreamList == null) {
428 425 gbStreamList = new ArrayList<>();
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
... ... @@ -37,6 +37,7 @@ public interface DeviceMapper {
37 37 "subscribeCycleForMobilePosition," +
38 38 "mobilePositionSubmissionInterval," +
39 39 "subscribeCycleForAlarm," +
  40 + "ssrcCheck," +
40 41 "online" +
41 42 ") VALUES (" +
42 43 "#{deviceId}," +
... ... @@ -59,6 +60,7 @@ public interface DeviceMapper {
59 60 "#{subscribeCycleForMobilePosition}," +
60 61 "#{mobilePositionSubmissionInterval}," +
61 62 "#{subscribeCycleForAlarm}," +
  63 + "#{ssrcCheck}," +
62 64 "#{online}" +
63 65 ")")
64 66 int add(Device device);
... ... @@ -84,6 +86,7 @@ public interface DeviceMapper {
84 86 "<if test=\"subscribeCycleForMobilePosition != null\">, subscribeCycleForMobilePosition=${subscribeCycleForMobilePosition}</if>" +
85 87 "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=${mobilePositionSubmissionInterval}</if>" +
86 88 "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=${subscribeCycleForAlarm}</if>" +
  89 + "<if test=\"ssrcCheck != null\">, ssrcCheck=${ssrcCheck}</if>" +
87 90 "WHERE deviceId='${deviceId}'"+
88 91 " </script>"})
89 92 int update(Device device);
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
... ... @@ -16,10 +16,10 @@ public interface ParentPlatformMapper {
16 16  
17 17 @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " +
18 18 " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " +
19   - " status, shareAllLiveStream, catalogId) " +
  19 + " status, shareAllLiveStream, startOfflinePush, catalogId, administrativeDivision, catalogGroup) " +
20 20 " VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " +
21 21 " '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${ptz}, ${rtcp}, " +
22   - " ${status}, ${shareAllLiveStream}, #{catalogId})")
  22 + " ${status}, ${shareAllLiveStream}, ${startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup})")
23 23 int addParentPlatform(ParentPlatform parentPlatform);
24 24  
25 25 @Update("UPDATE parent_platform " +
... ... @@ -42,6 +42,9 @@ public interface ParentPlatformMapper {
42 42 "rtcp=#{rtcp}, " +
43 43 "status=#{status}, " +
44 44 "shareAllLiveStream=#{shareAllLiveStream}, " +
  45 + "startOfflinePush=${startOfflinePush}, " +
  46 + "catalogGroup=#{catalogGroup}, " +
  47 + "administrativeDivision=#{administrativeDivision}, " +
45 48 "catalogId=#{catalogId} " +
46 49 "WHERE id=#{id}")
47 50 int updateParentPlatform(ParentPlatform parentPlatform);
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
... ... @@ -520,6 +520,12 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
520 520 @Override
521 521 public boolean updateParentPlatform(ParentPlatform parentPlatform) {
522 522 int result = 0;
  523 + if (parentPlatform.getCatalogGroup() == 0) {
  524 + parentPlatform.setCatalogGroup(1);
  525 + }
  526 + if (parentPlatform.getAdministrativeDivision() == null) {
  527 + parentPlatform.setAdministrativeDivision(parentPlatform.getAdministrativeDivision());
  528 + }
523 529 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); // .getDeviceGBId());
524 530 if (parentPlatform.getId() == null ) {
525 531 if (parentPlatform.getCatalogId() == null) {
... ... @@ -539,6 +545,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
539 545 parentPlatformCatch.setId(parentPlatform.getServerGBId());
540 546 redisCatchStorage.delPlatformCatchInfo(parentPlatById.getServerGBId());
541 547 }
  548 +
542 549 result = platformMapper.updateParentPlatform(parentPlatform);
543 550 }
544 551 // 更新缓存
... ... @@ -1074,7 +1081,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
1074 1081 deviceChannel.setParentId(catalog.getParentId());
1075 1082 deviceChannel.setRegisterWay(1);
1076 1083 // 行政区划应该是Domain的前八位
1077   - deviceChannel.setCivilCode(parentPlatByServerGBId.getDeviceGBId().substring(0,6));
  1084 + deviceChannel.setCivilCode(parentPlatByServerGBId.getAdministrativeDivision());
1078 1085 deviceChannel.setModel("live");
1079 1086 deviceChannel.setOwner("wvp-pro");
1080 1087 deviceChannel.setSecrecy("0");
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
... ... @@ -164,12 +164,13 @@ public class DeviceQuery {
164 164 logger.debug("设备通道信息同步API调用,deviceId:" + deviceId);
165 165 }
166 166 Device device = storager.queryVideoDevice(deviceId);
167   - SyncStatus syncStatus = deviceService.getChannelSyncStatus(deviceId);
  167 + boolean status = deviceService.isSyncRunning(deviceId);
168 168 // 已存在则返回进度
169   - if (syncStatus != null && syncStatus.getErrorMsg() == null) {
  169 + if (status) {
170 170 WVPResult<SyncStatus> wvpResult = new WVPResult<>();
171 171 wvpResult.setCode(0);
172   - wvpResult.setData(syncStatus);
  172 + SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId);
  173 + wvpResult.setData(channelSyncStatus);
173 174 return wvpResult;
174 175 }
175 176 deviceService.sync(device);
... ...
web_src/src/components/CloudRecord.vue
1 1 <template>
2   - <div id="app">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span v-if="!recordDetail" >云端录像</span>
10   - <el-page-header v-if="recordDetail" @back="backToList" content="云端录像">
11   - </el-page-header>
12   - <div style="position: absolute; right: 5rem; top: 0.3rem;">
13   - 节点选择:
14   - <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" :disabled="recordDetail">
15   - <el-option
16   - v-for="item in mediaServerList"
17   - :key="item.id"
18   - :label="item.id"
19   - :value="item.id">
20   - </el-option>
21   - </el-select>
22   - </div>
23   - <div style="position: absolute; right: 1rem; top: 0.3rem;">
24   - <el-button v-if="!recordDetail" icon="el-icon-refresh-right" circle size="mini" :loading="loading" @click="getRecordList()"></el-button>
25   - </div>
26   - </div>
27   - <div v-if="!recordDetail">
  2 + <div id="app" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">云端录像</div>
  5 + <div class="page-header-btn">
  6 + 节点选择:
  7 + <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" :disabled="recordDetail">
  8 + <el-option
  9 + v-for="item in mediaServerList"
  10 + :key="item.id"
  11 + :label="item.id"
  12 + :value="item.id">
  13 + </el-option>
  14 + </el-select>
  15 + <el-button v-if="!recordDetail" icon="el-icon-refresh-right" circle size="mini" :loading="loading" @click="getRecordList()"></el-button>
  16 + </div>
  17 + </div>
  18 + <div v-if="!recordDetail">
28 19  
29   - <!--设备列表-->
30   - <el-table :data="recordList" border style="width: 100%" :height="winHeight">
31   - <el-table-column prop="app" label="应用名" align="center">
32   - </el-table-column>
33   - <el-table-column prop="stream" label="流ID" align="center">
34   - </el-table-column>
35   - <el-table-column prop="time" label="时间" align="center">
36   - </el-table-column>
37   - <el-table-column label="操作" width="360" align="center" fixed="right">
38   - <template slot-scope="scope">
39   - <el-button-group>
40   - <el-button size="mini" icon="el-icon-video-camera-solid" type="primary" @click="showRecordDetail(scope.row)">查看</el-button>
41   -<!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord(scope.row)">删除</el-button>-->
42   - </el-button-group>
43   - </template>
44   - </el-table-column>
45   - </el-table>
46   - <el-pagination
47   - style="float: right"
48   - @size-change="handleSizeChange"
49   - @current-change="currentChange"
50   - :current-page="currentPage"
51   - :page-size="count"
52   - :page-sizes="[15, 25, 35, 50]"
53   - layout="total, sizes, prev, pager, next"
54   - :total="total">
55   - </el-pagination>
56   - </div>
57   - <cloud-record-detail ref="cloudRecordDetail" v-if="recordDetail" :recordFile="chooseRecord" :mediaServerId="mediaServerId" :mediaServerPath="mediaServerPath" ></cloud-record-detail>
58   - </el-main>
59   - </el-container>
60   - </div>
  20 + <!--设备列表-->
  21 + <el-table :data="recordList" border style="width: 100%" :height="winHeight">
  22 + <el-table-column prop="app" label="应用名" align="center">
  23 + </el-table-column>
  24 + <el-table-column prop="stream" label="流ID" align="center">
  25 + </el-table-column>
  26 + <el-table-column prop="time" label="时间" align="center">
  27 + </el-table-column>
  28 + <el-table-column label="操作" width="360" align="center" fixed="right">
  29 + <template slot-scope="scope">
  30 + <el-button-group>
  31 + <el-button size="mini" icon="el-icon-video-camera-solid" type="primary" @click="showRecordDetail(scope.row)">查看</el-button>
  32 + <!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord(scope.row)">删除</el-button>-->
  33 + </el-button-group>
  34 + </template>
  35 + </el-table-column>
  36 + </el-table>
  37 + <el-pagination
  38 + style="float: right"
  39 + @size-change="handleSizeChange"
  40 + @current-change="currentChange"
  41 + :current-page="currentPage"
  42 + :page-size="count"
  43 + :page-sizes="[15, 25, 35, 50]"
  44 + layout="total, sizes, prev, pager, next"
  45 + :total="total">
  46 + </el-pagination>
  47 + </div>
  48 + <cloud-record-detail ref="cloudRecordDetail" v-if="recordDetail" :recordFile="chooseRecord" :mediaServerId="mediaServerId" :mediaServerPath="mediaServerPath" ></cloud-record-detail>
  49 +
  50 + </div>
61 51 </template>
62 52  
63 53 <script>
64   - import uiHeader from './UiHeader.vue'
  54 + import uiHeader from '../layout/UiHeader.vue'
65 55 import cloudRecordDetail from './CloudRecordDetail.vue'
66 56 import MediaServer from './service/MediaServer'
67 57 export default {
... ...
web_src/src/components/CloudRecordDetail.vue
... ... @@ -104,7 +104,7 @@
104 104  
105 105 <script>
106 106 // TODO 根据查询的时间列表设置滑轨的最大值与最小值,
107   - import uiHeader from './UiHeader.vue'
  107 + import uiHeader from '../layout/UiHeader.vue'
108 108 import player from './dialog/easyPlayer.vue'
109 109 import moment from 'moment'
110 110 export default {
... ...
web_src/src/components/DeviceList.vue
1 1 <template>
2   - <div id="app">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span style="font-size: 1rem; font-weight: bold;">设备列表</span>
10   - <div style="position: absolute; right: 1rem; top: 0.3rem;">
11   - <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button>
12   - </div>
13   - </div>
14   - <!-- <devicePlayer ref="devicePlayer"></devicePlayer> -->
15   - <!--设备列表-->
16   - <el-table :data="deviceList" border style="width: 100%;font-size: 12px;" :height="winHeight">
17   - <el-table-column prop="name" label="名称" align="center">
18   - </el-table-column>
19   - <el-table-column prop="deviceId" label="设备编号" width="180" align="center">
20   - </el-table-column>
21   - <el-table-column label="地址" width="180" align="center">
22   - <template slot-scope="scope">
23   - <div slot="reference" class="name-wrapper">
24   - <el-tag size="medium">{{ scope.row.hostAddress }}</el-tag>
25   - </div>
26   - </template>
27   - </el-table-column>
28   - <el-table-column prop="manufacturer" label="厂家" align="center">
29   - </el-table-column>
30   - <el-table-column label="流传输模式" align="center" width="120">
31   - <template slot-scope="scope">
32   - <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择">
33   - <el-option key="UDP" label="UDP" value="UDP"></el-option>
34   - <el-option key="TCP-ACTIVE" label="TCP主动模式" :disabled="true" value="TCP-ACTIVE"></el-option>
35   - <el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option>
36   - </el-select>
37   - </template>
38   - </el-table-column>
39   - <el-table-column prop="channelCount" label="通道数" align="center">
40   - </el-table-column>
41   - <el-table-column label="状态" width="120" align="center">
42   - <template slot-scope="scope">
43   - <div slot="reference" class="name-wrapper">
44   - <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag>
45   - <el-tag size="medium" type="info" v-if="scope.row.online == 0">离线</el-tag>
46   - </div>
47   - </template>
48   - </el-table-column>
49   - <el-table-column prop="keepaliveTime" label="最近心跳" align="center" width="140">
50   - </el-table-column>
51   - <el-table-column prop="registerTime" label="最近注册" align="center" width="140">
52   - </el-table-column>
53   - <el-table-column prop="updateTime" label="更新时间" align="center" width="140">
54   - </el-table-column>
55   - <el-table-column prop="createTime" label="创建时间" align="center" width="140">
56   - </el-table-column>
  2 + <div id="app" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">设备列表</div>
  5 + <div class="page-header-btn">
  6 + <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading"
  7 + @click="getDeviceList()"></el-button>
  8 + </div>
  9 + </div>
  10 + <!-- <devicePlayer ref="devicePlayer"></devicePlayer> -->
  11 + <!--设备列表-->
  12 + <el-table :data="deviceList" border style="width: 100%;font-size: 12px;" :height="winHeight">
  13 + <el-table-column prop="name" label="名称" align="center">
  14 + </el-table-column>
  15 + <el-table-column prop="deviceId" label="设备编号" width="180" align="center">
  16 + </el-table-column>
  17 + <el-table-column label="地址" width="180" align="center">
  18 + <template slot-scope="scope">
  19 + <div slot="reference" class="name-wrapper">
  20 + <el-tag size="medium">{{ scope.row.hostAddress }}</el-tag>
  21 + </div>
  22 + </template>
  23 + </el-table-column>
  24 + <el-table-column prop="manufacturer" label="厂家" align="center">
  25 + </el-table-column>
  26 + <el-table-column label="流传输模式" align="center" width="120">
  27 + <template slot-scope="scope">
  28 + <el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择">
  29 + <el-option key="UDP" label="UDP" value="UDP"></el-option>
  30 + <el-option key="TCP-ACTIVE" label="TCP主动模式" :disabled="true" value="TCP-ACTIVE"></el-option>
  31 + <el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option>
  32 + </el-select>
  33 + </template>
  34 + </el-table-column>
  35 + <el-table-column prop="channelCount" label="通道数" align="center">
  36 + </el-table-column>
  37 + <el-table-column label="状态" width="120" align="center">
  38 + <template slot-scope="scope">
  39 + <div slot="reference" class="name-wrapper">
  40 + <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag>
  41 + <el-tag size="medium" type="info" v-if="scope.row.online == 0">离线</el-tag>
  42 + </div>
  43 + </template>
  44 + </el-table-column>
  45 + <el-table-column prop="keepaliveTime" label="最近心跳" align="center" width="140">
  46 + </el-table-column>
  47 + <el-table-column prop="registerTime" label="最近注册" align="center" width="140">
  48 + </el-table-column>
  49 + <el-table-column prop="updateTime" label="更新时间" align="center" width="140">
  50 + </el-table-column>
  51 + <el-table-column prop="createTime" label="创建时间" align="center" width="140">
  52 + </el-table-column>
57 53  
58   - <el-table-column label="操作" width="450" align="center" fixed="right">
59   - <template slot-scope="scope">
60   - <el-button size="mini" v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)" @mouseover="getTooltipContent(scope.row.deviceId)">刷新</el-button>
61   - <el-button-group>
62   - <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button>
63   - <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button>
64   - <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button>
65   - <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">删除</el-button>
66   - </el-button-group>
67   - </template>
68   - </el-table-column>
69   - </el-table>
70   - <el-pagination
71   - style="float: right"
72   - @size-change="handleSizeChange"
73   - @current-change="currentChange"
74   - :current-page="currentPage"
75   - :page-size="count"
76   - :page-sizes="[15, 25, 35, 50]"
77   - layout="total, sizes, prev, pager, next"
78   - :total="total">
79   - </el-pagination>
80   - <deviceEdit ref="deviceEdit" ></deviceEdit>
81   - <syncChannelProgress ref="syncChannelProgress" ></syncChannelProgress>
82   - </el-main>
83   - </el-container>
84   - </div>
  54 + <el-table-column label="操作" width="450" align="center" fixed="right">
  55 + <template slot-scope="scope">
  56 + <el-button size="mini" v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)"
  57 + @mouseover="getTooltipContent(scope.row.deviceId)">刷新
  58 + </el-button>
  59 + <el-button-group>
  60 + <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0"
  61 + type="primary" @click="showChannelList(scope.row)">通道
  62 + </el-button>
  63 + <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary"
  64 + @click="showDevicePosition(scope.row)">定位
  65 + </el-button>
  66 + <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button>
  67 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">删除</el-button>
  68 + </el-button-group>
  69 + </template>
  70 + </el-table-column>
  71 + </el-table>
  72 + <el-pagination
  73 + style="float: right"
  74 + @size-change="handleSizeChange"
  75 + @current-change="currentChange"
  76 + :current-page="currentPage"
  77 + :page-size="count"
  78 + :page-sizes="[15, 25, 35, 50]"
  79 + layout="total, sizes, prev, pager, next"
  80 + :total="total">
  81 + </el-pagination>
  82 + <deviceEdit ref="deviceEdit"></deviceEdit>
  83 + <syncChannelProgress ref="syncChannelProgress"></syncChannelProgress>
  84 + </div>
85 85 </template>
86 86  
87 87 <script>
88   - import uiHeader from './UiHeader.vue'
89   - import deviceEdit from './dialog/deviceEdit.vue'
90   - import syncChannelProgress from './dialog/SyncChannelProgress.vue'
91   - export default {
92   - name: 'app',
93   - components: {
94   - uiHeader,
95   - deviceEdit,
96   - syncChannelProgress,
97   - },
98   - data() {
99   - return {
100   - deviceList: [], //设备列表
101   - currentDevice: {}, //当前操作设备对象
  88 +import uiHeader from '../layout/UiHeader.vue'
  89 +import deviceEdit from './dialog/deviceEdit.vue'
  90 +import syncChannelProgress from './dialog/SyncChannelProgress.vue'
102 91  
103   - videoComponentList: [],
104   - updateLooper: 0, //数据刷新轮训标志
105   - currentDeviceChannelsLenth:0,
106   - winHeight: window.innerHeight - 200,
107   - currentPage:1,
108   - count:15,
109   - total:0,
110   - getDeviceListLoading: false,
111   - };
112   - },
113   - computed: {
114   - getcurrentDeviceChannels: function() {
115   - let data = this.currentDevice['channelMap'];
116   - let channels = null;
117   - if (data) {
118   - channels = Object.keys(data).map(key => {
119   - return data[key];
120   - });
121   - this.currentDeviceChannelsLenth = channels.length;
122   - }
123   - return channels;
124   - }
125   - },
126   - mounted() {
127   - this.initData();
128   - this.updateLooper = setInterval(this.initData, 10000);
129   - },
130   - destroyed() {
131   - this.$destroy('videojs');
132   - clearTimeout(this.updateLooper);
133   - },
134   - methods: {
135   - initData: function() {
136   - this.getDeviceList();
137   - },
138   - currentChange: function(val){
139   - this.currentPage = val;
140   - this.getDeviceList();
141   - },
142   - handleSizeChange: function(val){
143   - this.count = val;
144   - this.getDeviceList();
145   - },
146   - getDeviceList: function() {
147   - let that = this;
148   - this.getDeviceListLoading = true;
149   - this.$axios({
150   - method: 'get',
151   - url:`/api/device/query/devices`,
152   - params: {
153   - page: that.currentPage,
154   - count: that.count
155   - }
156   - }).then(function (res) {
157   - that.total = res.data.total;
158   - that.deviceList = res.data.list;
159   - that.getDeviceListLoading = false;
160   - }).catch(function (error) {
161   - console.error(error);
162   - that.getDeviceListLoading = false;
163   - });
  92 +export default {
  93 + name: 'app',
  94 + components: {
  95 + uiHeader,
  96 + deviceEdit,
  97 + syncChannelProgress,
  98 + },
  99 + data() {
  100 + return {
  101 + deviceList: [], //设备列表
  102 + currentDevice: {}, //当前操作设备对象
164 103  
165   - },
166   - deleteDevice: function(row) {
167   - let msg = "确定删除此设备?"
168   - if (row.online !== 0) {
169   - msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>"
  104 + videoComponentList: [],
  105 + updateLooper: 0, //数据刷新轮训标志
  106 + currentDeviceChannelsLenth: 0,
  107 + winHeight: window.innerHeight - 200,
  108 + currentPage: 1,
  109 + count: 15,
  110 + total: 0,
  111 + getDeviceListLoading: false,
  112 + };
  113 + },
  114 + computed: {
  115 + getcurrentDeviceChannels: function () {
  116 + let data = this.currentDevice['channelMap'];
  117 + let channels = null;
  118 + if (data) {
  119 + channels = Object.keys(data).map(key => {
  120 + return data[key];
  121 + });
  122 + this.currentDeviceChannelsLenth = channels.length;
  123 + }
  124 + return channels;
  125 + }
  126 + },
  127 + mounted() {
  128 + this.initData();
  129 + this.updateLooper = setInterval(this.initData, 10000);
  130 + },
  131 + destroyed() {
  132 + this.$destroy('videojs');
  133 + clearTimeout(this.updateLooper);
  134 + },
  135 + methods: {
  136 + initData: function () {
  137 + this.getDeviceList();
  138 + },
  139 + currentChange: function (val) {
  140 + this.currentPage = val;
  141 + this.getDeviceList();
  142 + },
  143 + handleSizeChange: function (val) {
  144 + this.count = val;
  145 + this.getDeviceList();
  146 + },
  147 + getDeviceList: function () {
  148 + let that = this;
  149 + this.getDeviceListLoading = true;
  150 + this.$axios({
  151 + method: 'get',
  152 + url: `/api/device/query/devices`,
  153 + params: {
  154 + page: that.currentPage,
  155 + count: that.count
170 156 }
171   - this.$confirm(msg, '提示', {
172   - dangerouslyUseHTMLString : true,
173   - confirmButtonText: '确定',
174   - cancelButtonText: '取消',
175   - center: true,
176   - type: 'warning'
177   - }).then(() => {
178   - this.$axios({
179   - method: 'delete',
180   - url:`/api/device/query/devices/${row.deviceId}/delete`
181   - }).then((res)=>{
182   - this.getDeviceList();
183   - }).catch((error) =>{
184   - console.error(error);
185   - });
186   - }).catch(() => {
  157 + }).then(function (res) {
  158 + that.total = res.data.total;
  159 + that.deviceList = res.data.list;
  160 + that.getDeviceListLoading = false;
  161 + }).catch(function (error) {
  162 + console.error(error);
  163 + that.getDeviceListLoading = false;
  164 + });
187 165  
  166 + },
  167 + deleteDevice: function (row) {
  168 + let msg = "确定删除此设备?"
  169 + if (row.online !== 0) {
  170 + msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>"
  171 + }
  172 + this.$confirm(msg, '提示', {
  173 + dangerouslyUseHTMLString: true,
  174 + confirmButtonText: '确定',
  175 + cancelButtonText: '取消',
  176 + center: true,
  177 + type: 'warning'
  178 + }).then(() => {
  179 + this.$axios({
  180 + method: 'delete',
  181 + url: `/api/device/query/devices/${row.deviceId}/delete`
  182 + }).then((res) => {
  183 + this.getDeviceList();
  184 + }).catch((error) => {
  185 + console.error(error);
188 186 });
  187 + }).catch(() => {
  188 +
  189 + });
189 190  
190 191  
191   - },
192   - showChannelList: function(row) {
193   - this.$router.push(`/channelList/${row.deviceId}/0/15/1`);
194   - },
195   - showDevicePosition: function(row) {
196   - this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`);
197   - },
  192 + },
  193 + showChannelList: function (row) {
  194 + this.$router.push(`/channelList/${row.deviceId}/0/15/1`);
  195 + },
  196 + showDevicePosition: function (row) {
  197 + this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`);
  198 + },
198 199  
199   - //gb28181平台对接
200   - //刷新设备信息
201   - refDevice: function(itemData) {
202   - console.log("刷新对应设备:" + itemData.deviceId);
203   - let that = this;
204   - this.$axios({
205   - method: 'post',
206   - url: '/api/device/query/devices/' + itemData.deviceId + '/sync'
207   - }).then((res) => {
208   - console.log("刷新设备结果:"+JSON.stringify(res));
209   - if (res.data.code !==0) {
210   - that.$message({
211   - showClose: true,
212   - message: res.data.msg,
213   - type: 'error'
214   - });
215   - }else{
216   - // that.$message({
217   - // showClose: true,
218   - // message: res.data.msg,
219   - // type: 'success'
220   - // });
221   - this.$refs.syncChannelProgress.openDialog(itemData.deviceId)
222   - }
223   - that.initData()
224   - }).catch((e) => {
225   - console.error(e)
  200 + //gb28181平台对接
  201 + //刷新设备信息
  202 + refDevice: function (itemData) {
  203 + console.log("刷新对应设备:" + itemData.deviceId);
  204 + let that = this;
  205 + this.$axios({
  206 + method: 'post',
  207 + url: '/api/device/query/devices/' + itemData.deviceId + '/sync'
  208 + }).then((res) => {
  209 + console.log("刷新设备结果:" + JSON.stringify(res));
  210 + if (res.data.code !== 0) {
226 211 that.$message({
227 212 showClose: true,
228   - message: e,
  213 + message: res.data.msg,
229 214 type: 'error'
230 215 });
231   - });
  216 + } else {
  217 + // that.$message({
  218 + // showClose: true,
  219 + // message: res.data.msg,
  220 + // type: 'success'
  221 + // });
  222 + this.$refs.syncChannelProgress.openDialog(itemData.deviceId)
  223 + }
  224 + that.initData()
  225 + }).catch((e) => {
  226 + console.error(e)
  227 + that.$message({
  228 + showClose: true,
  229 + message: e,
  230 + type: 'error'
  231 + });
  232 + });
232 233  
233   - },
  234 + },
234 235  
235   - getTooltipContent: async function (deviceId){
236   - let result = "";
237   - await this.$axios({
238   - method: 'get',
239   - async: false,
240   - url:`/api/device/query/${deviceId}/sync_status/`,
241   - }).then((res) => {
242   - if (res.data.code == 0) {
243   - if (res.data.data.errorMsg !== null) {
244   - result = res.data.data.errorMsg
245   - } else if (res.data.msg !== null) {
246   - result = res.data.msg
247   - } else {
248   - result = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
249   - }
250   - }
251   - })
252   - return result;
253   - },
254   - //通知设备上传媒体流
255   - sendDevicePush: function(itemData) {
256   - // let deviceId = this.currentDevice.deviceId;
257   - // let channelId = itemData.channelId;
258   - // console.log("通知设备推流1:" + deviceId + " : " + channelId);
259   - // let that = this;
260   - // this.$axios({
261   - // method: 'get',
262   - // url: '/api/play/' + deviceId + '/' + channelId
263   - // }).then(function(res) {
264   - // let ssrc = res.data.ssrc;
265   - // that.$refs.devicePlayer.play(ssrc,deviceId,channelId);
266   - // }).catch(function(e) {
267   - // });
268   - },
269   - transportChange: function (row) {
270   - console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);
271   - let that = this;
272   - this.$axios({
273   - method: 'post',
274   - url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode
275   - }).then(function(res) {
  236 + getTooltipContent: async function (deviceId) {
  237 + let result = "";
  238 + await this.$axios({
  239 + method: 'get',
  240 + async: false,
  241 + url: `/api/device/query/${deviceId}/sync_status/`,
  242 + }).then((res) => {
  243 + if (res.data.code == 0) {
  244 + if (res.data.data.errorMsg !== null) {
  245 + result = res.data.data.errorMsg
  246 + } else if (res.data.msg !== null) {
  247 + result = res.data.msg
  248 + } else {
  249 + result = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
  250 + }
  251 + }
  252 + })
  253 + return result;
  254 + },
  255 + //通知设备上传媒体流
  256 + sendDevicePush: function (itemData) {
  257 + // let deviceId = this.currentDevice.deviceId;
  258 + // let channelId = itemData.channelId;
  259 + // console.log("通知设备推流1:" + deviceId + " : " + channelId);
  260 + // let that = this;
  261 + // this.$axios({
  262 + // method: 'get',
  263 + // url: '/api/play/' + deviceId + '/' + channelId
  264 + // }).then(function(res) {
  265 + // let ssrc = res.data.ssrc;
  266 + // that.$refs.devicePlayer.play(ssrc,deviceId,channelId);
  267 + // }).catch(function(e) {
  268 + // });
  269 + },
  270 + transportChange: function (row) {
  271 + console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);
  272 + let that = this;
  273 + this.$axios({
  274 + method: 'post',
  275 + url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode
  276 + }).then(function (res) {
276 277  
277   - }).catch(function(e) {
  278 + }).catch(function (e) {
  279 + });
  280 + },
  281 + edit: function (row) {
  282 + this.$refs.deviceEdit.openDialog(row, () => {
  283 + this.$refs.deviceEdit.close();
  284 + this.$message({
  285 + showClose: true,
  286 + message: "设备修改成功,通道字符集将在下次更新生效",
  287 + type: "success",
278 288 });
279   - },
280   - edit: function (row) {
281   - this.$refs.deviceEdit.openDialog(row, ()=>{
282   - this.$refs.deviceEdit.close();
283   - this.$message({
284   - showClose: true,
285   - message: "设备修改成功,通道字符集将在下次更新生效",
286   - type: "success",
287   - });
288   - setTimeout(this.getDeviceList, 200)
  289 + setTimeout(this.getDeviceList, 200)
289 290  
290   - })
291   - }
  291 + })
  292 + }
292 293  
293   - }
294   - };
  294 + }
  295 +};
295 296 </script>
296 297  
297 298 <style>
298   - .videoList {
299   - display: flex;
300   - flex-wrap: wrap;
301   - align-content: flex-start;
302   - }
  299 +.videoList {
  300 + display: flex;
  301 + flex-wrap: wrap;
  302 + align-content: flex-start;
  303 +}
303 304  
304   - .video-item {
305   - position: relative;
306   - width: 15rem;
307   - height: 10rem;
308   - margin-right: 1rem;
309   - background-color: #000000;
310   - }
  305 +.video-item {
  306 + position: relative;
  307 + width: 15rem;
  308 + height: 10rem;
  309 + margin-right: 1rem;
  310 + background-color: #000000;
  311 +}
311 312  
312   - .video-item-img {
313   - position: absolute;
314   - top: 0;
315   - bottom: 0;
316   - left: 0;
317   - right: 0;
318   - margin: auto;
319   - width: 100%;
320   - height: 100%;
321   - }
  313 +.video-item-img {
  314 + position: absolute;
  315 + top: 0;
  316 + bottom: 0;
  317 + left: 0;
  318 + right: 0;
  319 + margin: auto;
  320 + width: 100%;
  321 + height: 100%;
  322 +}
322 323  
323   - .video-item-img:after {
324   - content: "";
325   - display: inline-block;
326   - position: absolute;
327   - z-index: 2;
328   - top: 0;
329   - bottom: 0;
330   - left: 0;
331   - right: 0;
332   - margin: auto;
333   - width: 3rem;
334   - height: 3rem;
335   - background-image: url("../assets/loading.png");
336   - background-size: cover;
337   - background-color: #000000;
338   - }
  324 +.video-item-img:after {
  325 + content: "";
  326 + display: inline-block;
  327 + position: absolute;
  328 + z-index: 2;
  329 + top: 0;
  330 + bottom: 0;
  331 + left: 0;
  332 + right: 0;
  333 + margin: auto;
  334 + width: 3rem;
  335 + height: 3rem;
  336 + background-image: url("../assets/loading.png");
  337 + background-size: cover;
  338 + background-color: #000000;
  339 +}
339 340  
340   - .video-item-title {
341   - position: absolute;
342   - bottom: 0;
343   - color: #000000;
344   - background-color: #ffffff;
345   - line-height: 1.5rem;
346   - padding: 0.3rem;
347   - width: 14.4rem;
348   - }
  341 +.video-item-title {
  342 + position: absolute;
  343 + bottom: 0;
  344 + color: #000000;
  345 + background-color: #ffffff;
  346 + line-height: 1.5rem;
  347 + padding: 0.3rem;
  348 + width: 14.4rem;
  349 +}
349 350 </style>
... ...
web_src/src/components/MediaServerManger.vue
1 1 <template>
2   - <div id="mediaServerManger">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main id="msMain">
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span style="font-size: 1rem; font-weight: bold;">节点列表</span>
10   - </div>
11   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
12   - <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加节点</el-button>
13   - </div>
  2 + <div id="mediaServerManger" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">节点列表</div>
  5 + <div class="page-header-btn">
  6 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加节点</el-button>
  7 + </div>
  8 + </div>
14 9  
15   - <el-row :gutter="12">
16   - <el-col :span="num" v-for="item in mediaServerList" :key="item.id">
17   - <el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card">
18   - <div class="card-img-zlm"></div>
19   - <div style="padding: 14px;text-align: left">
20   - <span style="font-size: 16px">{{item.id}}</span>
21   - <el-button v-if="!item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">编辑</el-button>
22   - <el-button v-if="item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">查看</el-button>
23   - <el-button icon="el-icon-delete" style="margin-right: 10px;padding: 0;float: right;" type="text" @click="del(item)">移除</el-button>
24   - <div style="margin-top: 13px; line-height: 12px; ">
25   - <span style="font-size: 14px; color: #999; margin-top: 5px; ">{{item.ip}}</span>
26   - <span style="font-size: 14px; color: #999; margin-top: 5px; float: right;">{{item.createTime}}</span>
27   - </div>
28   - </div>
29   - <i v-if="item.status" class="iconfont icon-online server-card-status-online" title="在线"></i>
30   - <i v-if="!item.status" class="iconfont icon-online server-card-status-offline" title="离线"></i>
31   - <i v-if="item.defaultServer" class="server-card-default" >默认</i>
32   - </el-card>
33   - </el-col>
34   - </el-row>
35   - <mediaServerEdit ref="mediaServerEdit" ></mediaServerEdit>
36   - </el-main>
37   - </el-container>
  10 + <el-row :gutter="12">
  11 + <el-col :span="num" v-for="item in mediaServerList" :key="item.id">
  12 + <el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card">
  13 + <div class="card-img-zlm"></div>
  14 + <div style="padding: 14px;text-align: left">
  15 + <span style="font-size: 16px">{{item.id}}</span>
  16 + <el-button v-if="!item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">编辑</el-button>
  17 + <el-button v-if="item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">查看</el-button>
  18 + <el-button icon="el-icon-delete" style="margin-right: 10px;padding: 0;float: right;" type="text" @click="del(item)">移除</el-button>
  19 + <div style="margin-top: 13px; line-height: 12px; ">
  20 + <span style="font-size: 14px; color: #999; margin-top: 5px; ">{{item.ip}}</span>
  21 + <span style="font-size: 14px; color: #999; margin-top: 5px; float: right;">{{item.createTime}}</span>
  22 + </div>
  23 + </div>
  24 + <i v-if="item.status" class="iconfont icon-online server-card-status-online" title="在线"></i>
  25 + <i v-if="!item.status" class="iconfont icon-online server-card-status-offline" title="离线"></i>
  26 + <i v-if="item.defaultServer" class="server-card-default" >默认</i>
  27 + </el-card>
  28 + </el-col>
  29 + </el-row>
  30 + <mediaServerEdit ref="mediaServerEdit" ></mediaServerEdit>
38 31 </div>
39 32 </template>
40 33  
41 34 <script>
42   - import uiHeader from './UiHeader.vue'
  35 + import uiHeader from '../layout/UiHeader.vue'
43 36 import MediaServer from './service/MediaServer'
44 37 import mediaServerEdit from './dialog/MediaServerEdit'
45 38 export default {
... ...
web_src/src/components/ParentPlatformList.vue
1 1 <template>
2   - <div id="app">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span style="font-size: 1rem; font-weight: bold;">上级平台列表</span>
10   - </div>
11   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
12   - <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addParentPlatform">添加</el-button>
13   - </div>
14   - <!--设备列表-->
15   - <el-table :data="platformList" border style="width: 100%" :height="winHeight">
16   - <el-table-column prop="name" label="名称" align="center"></el-table-column>
17   - <el-table-column prop="serverGBId" label="平台编号" width="180" align="center"></el-table-column>
18   - <el-table-column label="是否启用" width="120" align="center">
19   - <template slot-scope="scope">
20   - <div slot="reference" class="name-wrapper">
21   - <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
22   - <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
23   - </div>
24   - </template>
25   - </el-table-column>
26   - <el-table-column label="状态" width="120" align="center">
27   - <template slot-scope="scope">
28   - <div slot="reference" class="name-wrapper">
29   - <el-tag size="medium" v-if="scope.row.status">在线</el-tag>
30   - <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>
31   - </div>
32   - </template>
33   - </el-table-column>
34   - <el-table-column label="地址" width="180" align="center">
35   - <template slot-scope="scope">
36   - <div slot="reference" class="name-wrapper">
37   - <el-tag size="medium">{{ scope.row.serverIP}}:{{scope.row.serverPort }}</el-tag>
38   - </div>
39   - </template>
40   - </el-table-column>
41   - <el-table-column prop="deviceGBId" label="设备国标编号" width="200" align="center"></el-table-column>
42   - <el-table-column prop="transport" label="信令传输模式" width="120" align="center"></el-table-column>
43   - <el-table-column prop="channelCount" label="通道数" width="120" align="center"></el-table-column>
44   - <el-table-column label="订阅信息" width="240" align="center" fixed="right">
45   - <template slot-scope="scope">
46   - <i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-on " ></i>
47   - <i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-off " ></i>
48   - <i v-if="scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-on" ></i>
49   - <i v-if="!scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-off" ></i>
50   - <i v-if="scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-on" ></i>
51   - <i v-if="!scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-off" ></i>
52   - </template>
53   - </el-table-column>
  2 + <div id="app" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">上级平台列表</div>
  5 + <div class="page-header-btn">
  6 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addParentPlatform">添加</el-button>
  7 + </div>
  8 + </div>
54 9  
55   - <el-table-column label="操作" width="300" align="center" fixed="right">
56   - <template slot-scope="scope">
57   - <el-button size="mini" icon="el-icon-edit" @click="editPlatform(scope.row)">编辑</el-button>
58   - <el-button size="mini" icon="el-icon-share" type="primary" @click="chooseChannel(scope.row)">选择通道</el-button>
59   - <el-button size="mini" icon="el-icon-delete" type="danger" @click="deletePlatform(scope.row)">删除</el-button>
60   - </template>
61   - </el-table-column>
62   - </el-table>
63   - <el-pagination
64   - style="float: right"
65   - @size-change="handleSizeChange"
66   - @current-change="currentChange"
67   - :current-page="currentPage"
68   - :page-size="count"
69   - :page-sizes="[15, 25, 35, 50]"
70   - layout="total, sizes, prev, pager, next"
71   - :total="total">
72   - </el-pagination>
73   - <platformEdit ref="platformEdit" ></platformEdit>
74   - <chooseChannelDialog ref="chooseChannelDialog" ></chooseChannelDialog>
75   - </el-main>
76   - </el-container>
  10 + <!--设备列表-->
  11 + <el-table :data="platformList" border style="width: 100%" :height="winHeight">
  12 + <el-table-column prop="name" label="名称" align="center"></el-table-column>
  13 + <el-table-column prop="serverGBId" label="平台编号" align="center"></el-table-column>
  14 + <el-table-column label="是否启用" width="120" align="center">
  15 + <template slot-scope="scope">
  16 + <div slot="reference" class="name-wrapper">
  17 + <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
  18 + <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
  19 + </div>
  20 + </template>
  21 + </el-table-column>
  22 + <el-table-column label="状态" width="120" align="center">
  23 + <template slot-scope="scope">
  24 + <div slot="reference" class="name-wrapper">
  25 + <el-tag size="medium" v-if="scope.row.status">在线</el-tag>
  26 + <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>
  27 + </div>
  28 + </template>
  29 + </el-table-column>
  30 + <el-table-column label="地址" width="180" align="center">
  31 + <template slot-scope="scope">
  32 + <div slot="reference" class="name-wrapper">
  33 + <el-tag size="medium">{{ scope.row.serverIP}}:{{scope.row.serverPort }}</el-tag>
  34 + </div>
  35 + </template>
  36 + </el-table-column>
  37 + <el-table-column prop="deviceGBId" label="设备国标编号" width="200" align="center"></el-table-column>
  38 + <el-table-column prop="transport" label="信令传输模式" width="120" align="center"></el-table-column>
  39 + <el-table-column prop="channelCount" label="通道数" width="120" align="center"></el-table-column>
  40 + <el-table-column label="订阅信息" width="240" align="center" fixed="right">
  41 + <template slot-scope="scope">
  42 + <i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-on " ></i>
  43 + <i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅" class="iconfont icon-gbaojings subscribe-off " ></i>
  44 + <i v-if="scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-on" ></i>
  45 + <i v-if="!scope.row.catalogSubscribe" title="目录订阅" class="iconfont icon-gjichus subscribe-off" ></i>
  46 + <i v-if="scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-on" ></i>
  47 + <i v-if="!scope.row.mobilePositionSubscribe" title="位置订阅" class="iconfont icon-gxunjians subscribe-off" ></i>
  48 + </template>
  49 + </el-table-column>
  50 +
  51 + <el-table-column label="操作" width="300" align="center" fixed="right">
  52 + <template slot-scope="scope">
  53 + <el-button size="mini" icon="el-icon-edit" @click="editPlatform(scope.row)">编辑</el-button>
  54 + <el-button size="mini" icon="el-icon-share" type="primary" @click="chooseChannel(scope.row)">选择通道</el-button>
  55 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deletePlatform(scope.row)">删除</el-button>
  56 + </template>
  57 + </el-table-column>
  58 + </el-table>
  59 + <el-pagination
  60 + style="float: right"
  61 + @size-change="handleSizeChange"
  62 + @current-change="currentChange"
  63 + :current-page="currentPage"
  64 + :page-size="count"
  65 + :page-sizes="[15, 25, 35, 50]"
  66 + layout="total, sizes, prev, pager, next"
  67 + :total="total">
  68 + </el-pagination>
  69 + <platformEdit ref="platformEdit" ></platformEdit>
  70 + <chooseChannelDialog ref="chooseChannelDialog" ></chooseChannelDialog>
77 71 </div>
78 72 </template>
79 73  
80 74 <script>
81 75 import platformEdit from './dialog/platformEdit.vue'
82   -import uiHeader from './UiHeader.vue'
  76 +import uiHeader from '../layout/UiHeader.vue'
83 77 import chooseChannelDialog from './dialog/chooseChannel.vue'
84 78 export default {
85 79 name: 'app',
... ...
web_src/src/components/PushVideoList.vue
1 1 <template>
2   - <div id="pushVideoList">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span style="font-size: 1rem; font-weight: bold;">推流列表</span>
10   - </div>
11   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
12   -
13   - 搜索: <el-input @input="getPushList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字" prefix-icon="el-icon-search" v-model="searchSrt" clearable> </el-input>
14   -
15   - 流媒体: <el-select size="mini" @change="getPushList" style="margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" default-first-option>
  2 + <div id="pushVideoList" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">推流列表</div>
  5 + <div class="page-header-btn">
  6 + 搜索:
  7 + <el-input @input="getPushList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
  8 + prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
  9 + 流媒体:
  10 + <el-select size="mini" @change="getPushList" style="margin-right: 1rem;" v-model="mediaServerId"
  11 + placeholder="请选择" default-first-option>
16 12 <el-option label="全部" value=""></el-option>
17 13 <el-option
18 14 v-for="item in mediaServerList"
... ... @@ -21,309 +17,327 @@
21 17 :value="item.id">
22 18 </el-option>
23 19 </el-select>
24   - 推流状态: <el-select size="mini" style="margin-right: 1rem;" @change="getPushList" v-model="pushing" placeholder="请选择" default-first-option>
  20 + 推流状态:
  21 + <el-select size="mini" style="margin-right: 1rem;" @change="getPushList" v-model="pushing" placeholder="请选择"
  22 + default-first-option>
25 23 <el-option label="全部" value=""></el-option>
26 24 <el-option label="推流进行中" value="true"></el-option>
27 25 <el-option label="推流未进行" value="false"></el-option>
28 26 </el-select>
29   - <el-button icon="el-icon-upload2" size="mini" style="margin-right: 1rem;" type="primary" @click="importChannel">通道导入</el-button>
30   - <el-button icon="el-icon-download" size="mini" style="margin-right: 1rem;" type="primary" >
31   - <a style="color: #FFFFFF; text-align: center; text-decoration: none" href="/static/file/推流通道导入.zip" download='推流通道导入.zip' >下载模板</a>
32   - </el-button>
33   - <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;" :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">批量移除</el-button>
34   - </div>
35   - <devicePlayer ref="devicePlayer"></devicePlayer>
36   - <addStreamTOGB ref="addStreamTOGB"></addStreamTOGB>
37   - <el-table ref="pushListTable" :data="pushList" border style="width: 100%" :height="winHeight" @selection-change="handleSelectionChange" :row-key="(row)=> row.app + row.stream">
38   - <el-table-column align="center" type="selection" :reserve-selection="true" width="55">
39   - </el-table-column>
40   - <el-table-column prop="name" label="名称" align="center">
41   - </el-table-column>
42   - <el-table-column prop="app" label="APP" align="center">
43   - </el-table-column>
44   - <el-table-column prop="stream" label="流ID" align="center">
45   - </el-table-column>
46   - <el-table-column prop="gbId" label="国标编码" width="200" align="center">
47   - </el-table-column>
48   - <el-table-column prop="mediaServerId" label="流媒体" width="200" align="center">
49   - </el-table-column>
50   - <el-table-column label="开始时间" align="center" width="200">
51   - <template slot-scope="scope">
52   - <el-button-group>
53   - {{dateFormat(parseInt(scope.row.createStamp))}}
54   - </el-button-group>
55   - </template>
56   - </el-table-column>
57   - <el-table-column label="正在推流" align="center" width="100">
58   - <template slot-scope="scope">
59   - {{(scope.row.status == false && scope.row.gbId == null) || scope.row.status ?'是':'否'}}
60   - </template>
61   - </el-table-column>
  27 + <el-button icon="el-icon-upload2" size="mini" style="margin-right: 1rem;" type="primary" @click="importChannel">
  28 + 通道导入
  29 + </el-button>
  30 + <el-button icon="el-icon-download" size="mini" style="margin-right: 1rem;" type="primary">
  31 + <a style="color: #FFFFFF; text-align: center; text-decoration: none" href="/static/file/推流通道导入.zip"
  32 + download='推流通道导入.zip'>下载模板</a>
  33 + </el-button>
  34 + <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;"
  35 + :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">批量移除
  36 + </el-button>
  37 + </div>
  38 + </div>
  39 + <devicePlayer ref="devicePlayer"></devicePlayer>
  40 + <addStreamTOGB ref="addStreamTOGB"></addStreamTOGB>
  41 + <el-table ref="pushListTable" :data="pushList" border style="width: 100%" :height="winHeight"
  42 + @selection-change="handleSelectionChange" :row-key="(row)=> row.app + row.stream">
  43 + <el-table-column align="center" type="selection" :reserve-selection="true" width="55">
  44 + </el-table-column>
  45 + <el-table-column prop="name" label="名称" align="center">
  46 + </el-table-column>
  47 + <el-table-column prop="app" label="APP" align="center">
  48 + </el-table-column>
  49 + <el-table-column prop="stream" label="流ID" align="center">
  50 + </el-table-column>
  51 + <el-table-column prop="gbId" label="国标编码" width="200" align="center">
  52 + </el-table-column>
  53 + <el-table-column prop="mediaServerId" label="流媒体" width="200" align="center">
  54 + </el-table-column>
  55 + <el-table-column label="开始时间" align="center" width="200">
  56 + <template slot-scope="scope">
  57 + <el-button-group>
  58 + {{ dateFormat(parseInt(scope.row.createStamp)) }}
  59 + </el-button-group>
  60 + </template>
  61 + </el-table-column>
  62 + <el-table-column label="正在推流" align="center" width="100">
  63 + <template slot-scope="scope">
  64 + {{ (scope.row.status == false && scope.row.gbId == null) || scope.row.status ? '是' : '否' }}
  65 + </template>
  66 + </el-table-column>
62 67  
63   - <el-table-column label="操作" width="360" align="center" fixed="right">
64   - <template slot-scope="scope">
65   - <el-button-group>
66   - <el-button size="mini" icon="el-icon-video-play" v-if="(scope.row.status == false && scope.row.gbId == null) || scope.row.status" @click="playPush(scope.row)">播放</el-button>
67   - <el-button size="mini" icon="el-icon-delete" type="danger" @click="stopPush(scope.row)">移除</el-button>
68   - <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!!scope.row.gbId" @click="addToGB(scope.row)">加入国标</el-button>
69   - <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!scope.row.gbId" @click="removeFromGB(scope.row)">移出国标</el-button>
70   - </el-button-group>
71   - </template>
72   - </el-table-column>
73   - </el-table>
74   - <el-pagination
75   - style="float: right"
76   - @size-change="handleSizeChange"
77   - @current-change="currentChange"
78   - :current-page="currentPage"
79   - :page-size="count"
80   - :page-sizes="[15, 25, 35, 50]"
81   - layout="total, sizes, prev, pager, next"
82   - :total="total">
83   - </el-pagination>
84   - <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
85   - <importChannel ref="importChannel" ></importChannel>
86   - </el-main>
87   - </el-container>
88   - </div>
  68 + <el-table-column label="操作" width="360" align="center" fixed="right">
  69 + <template slot-scope="scope">
  70 + <el-button-group>
  71 + <el-button size="mini" icon="el-icon-video-play"
  72 + v-if="(scope.row.status == false && scope.row.gbId == null) || scope.row.status"
  73 + @click="playPush(scope.row)">播放
  74 + </el-button>
  75 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="stopPush(scope.row)">移除</el-button>
  76 + <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!!scope.row.gbId"
  77 + @click="addToGB(scope.row)">加入国标
  78 + </el-button>
  79 + <el-button size="mini" icon="el-icon-position" type="primary" v-if="!!scope.row.gbId"
  80 + @click="removeFromGB(scope.row)">移出国标
  81 + </el-button>
  82 + </el-button-group>
  83 + </template>
  84 + </el-table-column>
  85 + </el-table>
  86 + <el-pagination
  87 + style="float: right"
  88 + @size-change="handleSizeChange"
  89 + @current-change="currentChange"
  90 + :current-page="currentPage"
  91 + :page-size="count"
  92 + :page-sizes="[15, 25, 35, 50]"
  93 + layout="total, sizes, prev, pager, next"
  94 + :total="total">
  95 + </el-pagination>
  96 + <streamProxyEdit ref="streamProxyEdit"></streamProxyEdit>
  97 + <importChannel ref="importChannel"></importChannel>
  98 + </div>
89 99 </template>
90 100  
91 101 <script>
92   - import streamProxyEdit from './dialog/StreamProxyEdit.vue'
93   - import devicePlayer from './dialog/devicePlayer.vue'
94   - import addStreamTOGB from './dialog/addStreamTOGB.vue'
95   - import uiHeader from './UiHeader.vue'
96   - import importChannel from './dialog/importChannel.vue'
97   - import MediaServer from './service/MediaServer'
98   - export default {
99   - name: 'pushVideoList',
100   - components: {
101   - devicePlayer,
102   - addStreamTOGB,
103   - streamProxyEdit,
104   - uiHeader,
105   - importChannel,
106   - },
107   - data() {
108   - return {
109   - pushList: [], //设备列表
110   - currentPusher: {}, //当前操作设备对象
111   - updateLooper: 0, //数据刷新轮训标志
112   - currentDeviceChannelsLenth:0,
113   - winHeight: window.innerHeight - 250,
114   - mediaServerObj : new MediaServer(),
115   - currentPage:1,
116   - count:15,
117   - total:0,
118   - searchSrt: "",
119   - pushing: "",
120   - mediaServerId: "",
121   - mediaServerList: [],
122   - multipleSelection: [],
123   - getDeviceListLoading: false
124   - };
125   - },
126   - computed: {
127   - },
128   - mounted() {
129   - this.initData();
130   - this.updateLooper = setInterval(this.getPushList, 2000);
131   - },
132   - destroyed() {
133   - clearTimeout(this.updateLooper);
134   - },
135   - methods: {
136   - initData: function() {
137   - this.mediaServerObj.getOnlineMediaServerList((data)=>{
138   - this.mediaServerList = data.data;
139   - })
140   - this.getPushList();
141   - },
142   - currentChange: function(val){
143   - this.currentPage = val;
144   - this.getPushList();
145   - },
146   - handleSizeChange: function(val){
147   - this.count = val;
148   - this.getPushList();
149   - },
150   - getPushList: function() {
151   - let that = this;
152   - this.getDeviceListLoading = true;
153   - this.$axios({
154   - method: 'get',
155   - url:`/api/push/list`,
156   - params: {
157   - page: that.currentPage,
158   - count: that.count,
159   - query: that.searchSrt,
160   - pushing: that.pushing,
161   - mediaServerId: that.mediaServerId,
162   - }
163   - }).then(function (res) {
164   - that.total = res.data.total;
165   - that.pushList = res.data.list;
166   - that.getDeviceListLoading = false;
167   - }).catch(function (error) {
168   - console.error(error);
169   - that.getDeviceListLoading = false;
170   - });
171   - },
  102 +import streamProxyEdit from './dialog/StreamProxyEdit.vue'
  103 +import devicePlayer from './dialog/devicePlayer.vue'
  104 +import addStreamTOGB from './dialog/addStreamTOGB.vue'
  105 +import uiHeader from '../layout/UiHeader.vue'
  106 +import importChannel from './dialog/importChannel.vue'
  107 +import MediaServer from './service/MediaServer'
  108 +
  109 +export default {
  110 + name: 'pushVideoList',
  111 + components: {
  112 + devicePlayer,
  113 + addStreamTOGB,
  114 + streamProxyEdit,
  115 + uiHeader,
  116 + importChannel,
  117 + },
  118 + data() {
  119 + return {
  120 + pushList: [], //设备列表
  121 + currentPusher: {}, //当前操作设备对象
  122 + updateLooper: 0, //数据刷新轮训标志
  123 + currentDeviceChannelsLenth: 0,
  124 + winHeight: window.innerHeight - 250,
  125 + mediaServerObj: new MediaServer(),
  126 + currentPage: 1,
  127 + count: 15,
  128 + total: 0,
  129 + searchSrt: "",
  130 + pushing: "",
  131 + mediaServerId: "",
  132 + mediaServerList: [],
  133 + multipleSelection: [],
  134 + getDeviceListLoading: false
  135 + };
  136 + },
  137 + computed: {},
  138 + mounted() {
  139 + this.initData();
  140 + this.updateLooper = setInterval(this.getPushList, 2000);
  141 + },
  142 + destroyed() {
  143 + clearTimeout(this.updateLooper);
  144 + },
  145 + methods: {
  146 + initData: function () {
  147 + this.mediaServerObj.getOnlineMediaServerList((data) => {
  148 + this.mediaServerList = data.data;
  149 + })
  150 + this.getPushList();
  151 + },
  152 + currentChange: function (val) {
  153 + this.currentPage = val;
  154 + this.getPushList();
  155 + },
  156 + handleSizeChange: function (val) {
  157 + this.count = val;
  158 + this.getPushList();
  159 + },
  160 + getPushList: function () {
  161 + let that = this;
  162 + this.getDeviceListLoading = true;
  163 + this.$axios({
  164 + method: 'get',
  165 + url: `/api/push/list`,
  166 + params: {
  167 + page: that.currentPage,
  168 + count: that.count,
  169 + query: that.searchSrt,
  170 + pushing: that.pushing,
  171 + mediaServerId: that.mediaServerId,
  172 + }
  173 + }).then(function (res) {
  174 + that.total = res.data.total;
  175 + that.pushList = res.data.list;
  176 + that.getDeviceListLoading = false;
  177 + }).catch(function (error) {
  178 + console.error(error);
  179 + that.getDeviceListLoading = false;
  180 + });
  181 + },
172 182  
173   - playPush: function(row){
174   - let that = this;
175   - this.getListLoading = true;
176   - this.$axios({
177   - method: 'get',
178   - url: '/api/media/stream_info_by_app_and_stream',
179   - params: {
180   - app: row.app,
181   - stream: row.stream,
182   - mediaServerId: row.mediaServerId
183   - }
184   - }).then(function (res) {
185   - that.getListLoading = false;
186   - that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
187   - streamInfo: res.data.data,
188   - hasAudio: true
189   - });
190   - }).catch(function (error) {
191   - console.error(error);
192   - that.getListLoading = false;
193   - });
194   - },
195   - stopPush: function(row){
  183 + playPush: function (row) {
  184 + let that = this;
  185 + this.getListLoading = true;
  186 + this.$axios({
  187 + method: 'get',
  188 + url: '/api/media/stream_info_by_app_and_stream',
  189 + params: {
  190 + app: row.app,
  191 + stream: row.stream,
  192 + mediaServerId: row.mediaServerId
  193 + }
  194 + }).then(function (res) {
  195 + that.getListLoading = false;
  196 + that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
  197 + streamInfo: res.data.data,
  198 + hasAudio: true
  199 + });
  200 + }).catch(function (error) {
  201 + console.error(error);
  202 + that.getListLoading = false;
  203 + });
  204 + },
  205 + stopPush: function (row) {
  206 + let that = this;
  207 + that.$axios({
  208 + method: "post",
  209 + url: "/api/push/stop",
  210 + params: {
  211 + app: row.app,
  212 + streamId: row.stream
  213 + }
  214 + }).then((res) => {
  215 + if (res.data == "success") {
  216 + that.initData()
  217 + }
  218 + }).catch(function (error) {
  219 + console.error(error);
  220 + });
  221 + },
  222 + addToGB: function (row) {
  223 + this.$refs.addStreamTOGB.openDialog({
  224 + app: row.app,
  225 + stream: row.stream,
  226 + mediaServerId: row.mediaServerId
  227 + }, this.initData);
  228 + },
  229 + removeFromGB: function (row) {
  230 + let that = this;
  231 + that.$axios({
  232 + method: "delete",
  233 + url: "/api/push/remove_form_gb",
  234 + data: row
  235 + }).then((res) => {
  236 + if (res.data == "success") {
  237 + that.initData()
  238 + }
  239 + }).catch(function (error) {
  240 + console.error(error);
  241 + });
  242 + },
  243 + dateFormat: function (/** timestamp=0 **/) {
  244 + let ts = arguments[0] || 0;
  245 + let t, y, m, d, h, i, s;
  246 + t = ts ? new Date(ts) : new Date();
  247 + y = t.getFullYear();
  248 + m = t.getMonth() + 1;
  249 + d = t.getDate();
  250 + h = t.getHours();
  251 + i = t.getMinutes();
  252 + s = t.getSeconds();
  253 + // 可根据需要在这里定义时间格式
  254 + return y + '-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d) + ' ' + (h < 10 ? '0' + h : h) + ':' + (i < 10 ? '0' + i : i) + ':' + (s < 10 ? '0' + s : s);
  255 + },
  256 + importChannel: function () {
  257 + this.$refs.importChannel.openDialog(() => {
  258 +
  259 + })
  260 + },
  261 + batchDel: function () {
  262 + this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', {
  263 + confirmButtonText: '确定',
  264 + cancelButtonText: '取消',
  265 + type: 'warning'
  266 + }).then(() => {
196 267 let that = this;
197 268 that.$axios({
198   - method:"post",
199   - url:"/api/push/stop",
200   - params: {
201   - app: row.app,
202   - streamId: row.stream
203   - }
204   - }).then((res)=>{
205   - if (res.data == "success") {
206   - that.initData()
  269 + method: "delete",
  270 + url: "/api/push/batchStop",
  271 + data: {
  272 + gbStreams: this.multipleSelection
207 273 }
  274 + }).then((res) => {
  275 + this.initData();
  276 + this.$refs.pushListTable.clearSelection();
208 277 }).catch(function (error) {
209 278 console.error(error);
210 279 });
211   - },
212   - addToGB: function(row){
213   - this.$refs.addStreamTOGB.openDialog({app: row.app, stream: row.stream, mediaServerId: row.mediaServerId}, this.initData);
214   - },
215   - removeFromGB: function(row){
216   - let that = this;
217   - that.$axios({
218   - method:"delete",
219   - url:"/api/push/remove_form_gb",
220   - data:row
221   - }).then((res)=>{
222   - if (res.data == "success") {
223   - that.initData()
224   - }
225   - }).catch(function (error) {
226   - console.error(error);
227   - });
228   - },
229   - dateFormat: function(/** timestamp=0 **/) {
230   - let ts = arguments[0] || 0;
231   - let t,y,m,d,h,i,s;
232   - t = ts ? new Date(ts) : new Date();
233   - y = t.getFullYear();
234   - m = t.getMonth()+1;
235   - d = t.getDate();
236   - h = t.getHours();
237   - i = t.getMinutes();
238   - s = t.getSeconds();
239   - // 可根据需要在这里定义时间格式
240   - return y+'-'+(m<10?'0'+m:m)+'-'+(d<10?'0'+d:d)+' '+(h<10?'0'+h:h)+':'+(i<10?'0'+i:i)+':'+(s<10?'0'+s:s);
241   - },
242   - importChannel: function () {
243   - this.$refs.importChannel.openDialog(()=>{
  280 + }).catch(() => {
244 281  
245   - })
246   - },
247   - batchDel: function () {
248   - this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', {
249   - confirmButtonText: '确定',
250   - cancelButtonText: '取消',
251   - type: 'warning'
252   - }).then(() => {
253   - let that = this;
254   - that.$axios({
255   - method:"delete",
256   - url:"/api/push/batchStop",
257   - data: {
258   - gbStreams: this.multipleSelection
259   - }
260   - }).then((res)=>{
261   - this.initData();
262   - this.$refs.pushListTable.clearSelection();
263   - }).catch(function (error) {
264   - console.error(error);
265   - });
266   - }).catch(() => {
267   -
268   - });
269   - },
270   - handleSelectionChange: function (val) {
271   - this.multipleSelection = val;
272   - },
273   - }
274   - };
  282 + });
  283 + },
  284 + handleSelectionChange: function (val) {
  285 + this.multipleSelection = val;
  286 + },
  287 + }
  288 +};
275 289 </script>
276 290  
277 291 <style>
278   - .videoList {
279   - display: flex;
280   - flex-wrap: wrap;
281   - align-content: flex-start;
282   - }
  292 +.videoList {
  293 + display: flex;
  294 + flex-wrap: wrap;
  295 + align-content: flex-start;
  296 +}
283 297  
284   - .video-item {
285   - position: relative;
286   - width: 15rem;
287   - height: 10rem;
288   - margin-right: 1rem;
289   - background-color: #000000;
290   - }
  298 +.video-item {
  299 + position: relative;
  300 + width: 15rem;
  301 + height: 10rem;
  302 + margin-right: 1rem;
  303 + background-color: #000000;
  304 +}
291 305  
292   - .video-item-img {
293   - position: absolute;
294   - top: 0;
295   - bottom: 0;
296   - left: 0;
297   - right: 0;
298   - margin: auto;
299   - width: 100%;
300   - height: 100%;
301   - }
  306 +.video-item-img {
  307 + position: absolute;
  308 + top: 0;
  309 + bottom: 0;
  310 + left: 0;
  311 + right: 0;
  312 + margin: auto;
  313 + width: 100%;
  314 + height: 100%;
  315 +}
302 316  
303   - .video-item-img:after {
304   - content: "";
305   - display: inline-block;
306   - position: absolute;
307   - z-index: 2;
308   - top: 0;
309   - bottom: 0;
310   - left: 0;
311   - right: 0;
312   - margin: auto;
313   - width: 3rem;
314   - height: 3rem;
315   - background-image: url("../assets/loading.png");
316   - background-size: cover;
317   - background-color: #000000;
318   - }
  317 +.video-item-img:after {
  318 + content: "";
  319 + display: inline-block;
  320 + position: absolute;
  321 + z-index: 2;
  322 + top: 0;
  323 + bottom: 0;
  324 + left: 0;
  325 + right: 0;
  326 + margin: auto;
  327 + width: 3rem;
  328 + height: 3rem;
  329 + background-image: url("../assets/loading.png");
  330 + background-size: cover;
  331 + background-color: #000000;
  332 +}
319 333  
320   - .video-item-title {
321   - position: absolute;
322   - bottom: 0;
323   - color: #000000;
324   - background-color: #ffffff;
325   - line-height: 1.5rem;
326   - padding: 0.3rem;
327   - width: 14.4rem;
328   - }
  334 +.video-item-title {
  335 + position: absolute;
  336 + bottom: 0;
  337 + color: #000000;
  338 + background-color: #ffffff;
  339 + line-height: 1.5rem;
  340 + padding: 0.3rem;
  341 + width: 14.4rem;
  342 +}
329 343 </style>
... ...
web_src/src/components/StreamProxyList.vue
1 1 <template>
2   - <div id="streamProxyList">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span style="font-size: 1rem; font-weight: bold;">拉流代理列表</span>
10   - </div>
11   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
12   - <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>
13   - <el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">搜索ONVIF</el-button>
14   - </div>
15   - <devicePlayer ref="devicePlayer"></devicePlayer>
16   - <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight">
17   - <el-table-column prop="name" label="名称" align="center" show-overflow-tooltip/>
18   - <el-table-column prop="app" label="流应用名" align="center" show-overflow-tooltip/>
19   - <el-table-column prop="stream" label="流ID" align="center" show-overflow-tooltip/>
20   - <el-table-column label="流地址" width="400" align="center" show-overflow-tooltip >
21   - <template slot-scope="scope">
22   - <div slot="reference" class="name-wrapper">
  2 + <div id="streamProxyList" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">拉流代理列表</div>
  5 + <div class="page-header-btn">
  6 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>
  7 + <el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">搜索ONVIF</el-button>
  8 + </div>
  9 + </div>
  10 + <devicePlayer ref="devicePlayer"></devicePlayer>
  11 + <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight">
  12 + <el-table-column prop="name" label="名称" align="center" show-overflow-tooltip/>
  13 + <el-table-column prop="app" label="流应用名" align="center" show-overflow-tooltip/>
  14 + <el-table-column prop="stream" label="流ID" align="center" show-overflow-tooltip/>
  15 + <el-table-column label="流地址" width="400" align="center" show-overflow-tooltip >
  16 + <template slot-scope="scope">
  17 + <div slot="reference" class="name-wrapper">
23 18  
24   - <el-tag size="medium" v-if="scope.row.type == 'default'">
25   - <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
26   - {{scope.row.url}}
27   - </el-tag>
28   - <el-tag size="medium" v-if="scope.row.type != 'default'">
29   - <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.src_url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
30   - {{scope.row.src_url}}
31   - </el-tag>
32   - </div>
33   - </template>
34   - </el-table-column>
35   - <el-table-column prop="mediaServerId" label="流媒体" width="150" align="center"></el-table-column>
36   - <el-table-column label="类型" width="100" align="center">
37   - <template slot-scope="scope">
38   - <div slot="reference" class="name-wrapper">
39   - <el-tag size="medium">{{scope.row.type}}</el-tag>
40   - </div>
41   - </template>
42   - </el-table-column>
  19 + <el-tag size="medium" v-if="scope.row.type == 'default'">
  20 + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
  21 + {{scope.row.url}}
  22 + </el-tag>
  23 + <el-tag size="medium" v-if="scope.row.type != 'default'">
  24 + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.src_url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
  25 + {{scope.row.src_url}}
  26 + </el-tag>
  27 + </div>
  28 + </template>
  29 + </el-table-column>
  30 + <el-table-column prop="mediaServerId" label="流媒体" width="150" align="center"></el-table-column>
  31 + <el-table-column label="类型" width="100" align="center">
  32 + <template slot-scope="scope">
  33 + <div slot="reference" class="name-wrapper">
  34 + <el-tag size="medium">{{scope.row.type}}</el-tag>
  35 + </div>
  36 + </template>
  37 + </el-table-column>
43 38  
44   - <el-table-column prop="gbId" label="国标编码" width="180" align="center" show-overflow-tooltip/>
45   - <el-table-column label="状态" width="120" align="center">
46   - <template slot-scope="scope">
47   - <div slot="reference" class="name-wrapper">
48   - <el-tag size="medium" v-if="scope.row.status">在线</el-tag>
49   - <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>
50   - </div>
51   - </template>
52   - </el-table-column>
53   - <el-table-column label="启用" width="120" align="center">
54   - <template slot-scope="scope">
55   - <div slot="reference" class="name-wrapper">
56   - <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
57   - <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
58   - </div>
59   - </template>
60   - </el-table-column>
61   - <el-table-column prop="createTime" label="创建时间" align="center" width="150" show-overflow-tooltip/>
62   - <el-table-column label="转HLS" width="120" align="center">
63   - <template slot-scope="scope">
64   - <div slot="reference" class="name-wrapper">
65   - <el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag>
66   - <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag>
67   - </div>
68   - </template>
69   - </el-table-column>
70   - <el-table-column label="MP4录制" width="120" align="center">
71   - <template slot-scope="scope">
72   - <div slot="reference" class="name-wrapper">
73   - <el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag>
74   - <el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">未启用</el-tag>
75   - </div>
76   - </template>
77   - </el-table-column>
78   - <el-table-column label="无人观看自动删除" width="160" align="center">
79   - <template slot-scope="scope">
80   - <div slot="reference" class="name-wrapper">
81   - <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">已启用</el-tag>
82   - <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader">未启用</el-tag>
83   - </div>
84   - </template>
85   - </el-table-column>
  39 + <el-table-column prop="gbId" label="国标编码" width="180" align="center" show-overflow-tooltip/>
  40 + <el-table-column label="状态" width="120" align="center">
  41 + <template slot-scope="scope">
  42 + <div slot="reference" class="name-wrapper">
  43 + <el-tag size="medium" v-if="scope.row.status">在线</el-tag>
  44 + <el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>
  45 + </div>
  46 + </template>
  47 + </el-table-column>
  48 + <el-table-column label="启用" width="120" align="center">
  49 + <template slot-scope="scope">
  50 + <div slot="reference" class="name-wrapper">
  51 + <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
  52 + <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
  53 + </div>
  54 + </template>
  55 + </el-table-column>
  56 + <el-table-column prop="createTime" label="创建时间" align="center" width="150" show-overflow-tooltip/>
  57 + <el-table-column label="转HLS" width="120" align="center">
  58 + <template slot-scope="scope">
  59 + <div slot="reference" class="name-wrapper">
  60 + <el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag>
  61 + <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag>
  62 + </div>
  63 + </template>
  64 + </el-table-column>
  65 + <el-table-column label="MP4录制" width="120" align="center">
  66 + <template slot-scope="scope">
  67 + <div slot="reference" class="name-wrapper">
  68 + <el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag>
  69 + <el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">未启用</el-tag>
  70 + </div>
  71 + </template>
  72 + </el-table-column>
  73 + <el-table-column label="无人观看自动删除" width="160" align="center">
  74 + <template slot-scope="scope">
  75 + <div slot="reference" class="name-wrapper">
  76 + <el-tag size="medium" v-if="scope.row.enable_remove_none_reader">已启用</el-tag>
  77 + <el-tag size="medium" type="info" v-if="!scope.row.enable_remove_none_reader">未启用</el-tag>
  78 + </div>
  79 + </template>
  80 + </el-table-column>
86 81  
87 82  
88   - <el-table-column label="操作" width="360" align="center" fixed="right">
89   - <template slot-scope="scope">
90   - <el-button-group>
91   - <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">播放</el-button>
92   - <el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">停用</el-button>
93   - <el-button size="mini" icon="el-icon-check" type="primary" :loading="startBtnLaoding" v-if="!scope.row.enable" @click="start(scope.row)">启用</el-button>
94   - <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">删除</el-button>
95   - </el-button-group>
96   - </template>
97   - </el-table-column>
98   - </el-table>
99   - <el-pagination
100   - style="float: right"
101   - @size-change="handleSizeChange"
102   - @current-change="currentChange"
103   - :current-page="currentPage"
104   - :page-size="count"
105   - :page-sizes="[15, 25, 35, 50]"
106   - layout="total, sizes, prev, pager, next"
107   - :total="total">
108   - </el-pagination>
109   - <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
110   - <onvifEdit ref="onvifEdit" ></onvifEdit>
111   - </el-main>
112   - </el-container>
  83 + <el-table-column label="操作" width="360" align="center" fixed="right">
  84 + <template slot-scope="scope">
  85 + <el-button-group>
  86 + <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">播放</el-button>
  87 + <el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">停用</el-button>
  88 + <el-button size="mini" icon="el-icon-check" type="primary" :loading="startBtnLaoding" v-if="!scope.row.enable" @click="start(scope.row)">启用</el-button>
  89 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">删除</el-button>
  90 + </el-button-group>
  91 + </template>
  92 + </el-table-column>
  93 + </el-table>
  94 + <el-pagination
  95 + style="float: right"
  96 + @size-change="handleSizeChange"
  97 + @current-change="currentChange"
  98 + :current-page="currentPage"
  99 + :page-size="count"
  100 + :page-sizes="[15, 25, 35, 50]"
  101 + layout="total, sizes, prev, pager, next"
  102 + :total="total">
  103 + </el-pagination>
  104 + <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
  105 + <onvifEdit ref="onvifEdit" ></onvifEdit>
113 106 </div>
114 107 </template>
115 108  
... ... @@ -117,7 +110,7 @@
117 110 import streamProxyEdit from './dialog/StreamProxyEdit.vue'
118 111 import onvifEdit from './dialog/onvifEdit.vue'
119 112 import devicePlayer from './dialog/devicePlayer.vue'
120   - import uiHeader from './UiHeader.vue'
  113 + import uiHeader from '../layout/UiHeader.vue'
121 114 export default {
122 115 name: 'streamProxyList',
123 116 components: {
... ...
web_src/src/components/channelList.vue
1 1 <template>
2   -<div id="channelList">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;">
9   - <span style="font-size: 1rem; font-weight: 500; ">通道列表({{parentChannelId ==0 ? deviceId:parentChannelId}})</span>
  2 + <div id="channelList" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">
  5 + <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem;" type="primary" @click="showDevice">
  6 + 返回
  7 + </el-button>
  8 + 通道列表({{ parentChannelId == 0 ? deviceId : parentChannelId }})</div>
  9 + <div class="page-header-btn">
  10 + 搜索:
  11 + <el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
  12 + prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
10 13  
11   - </div>
12   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
13   - <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem;" type="primary" @click="showDevice">返回</el-button>
14   - 搜索: <el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字" prefix-icon="el-icon-search" v-model="searchSrt" clearable> </el-input>
  14 + 通道类型:
  15 + <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="请选择"
  16 + default-first-option>
  17 + <el-option label="全部" value=""></el-option>
  18 + <el-option label="设备" value="false"></el-option>
  19 + <el-option label="子目录" value="true"></el-option>
  20 + </el-select>
  21 + 在线状态:
  22 + <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
  23 + default-first-option>
  24 + <el-option label="全部" value=""></el-option>
  25 + <el-option label="在线" value="true"></el-option>
  26 + <el-option label="离线" value="false"></el-option>
  27 + </el-select>
  28 + <el-checkbox size="mini" v-model="autoList" @change="autoListChange">
  29 + 自动刷新
  30 + </el-checkbox>
  31 + </div>
  32 + </div>
  33 + <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
  34 + <!--设备列表-->
  35 + <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%">
  36 + <el-table-column prop="channelId" label="通道编号" width="200">
  37 + </el-table-column>
  38 + <el-table-column prop="name" label="通道名称">
  39 + </el-table-column>
  40 + <el-table-column label="快照" width="80" align="center">
  41 + <template slot-scope="scope">
  42 + <img style="max-height: 3rem;max-width: 4rem;"
  43 + :id="scope.row.deviceId + '_' + scope.row.channelId"
  44 + :src="getSnap(scope.row)"
  45 + @error="getSnapErrorEvent($event.target.id)"
  46 + alt="">
  47 + <!-- <el-image-->
  48 + <!-- :id="'snapImg_' + scope.row.deviceId + '_' + scope.row.channelId"-->
  49 + <!-- :src="getSnap(scope.row)"-->
  50 + <!-- @error="getSnapErrorEvent($event, scope.row)"-->
  51 + <!-- :fit="'contain'">-->
  52 + <!-- <div slot="error" class="image-slot">-->
  53 + <!-- <i class="el-icon-picture-outline"></i>-->
  54 + <!-- </div>-->
  55 + <!-- </el-image>-->
  56 + </template>
  57 + </el-table-column>
  58 + <el-table-column prop="subCount" label="子节点数">
  59 + </el-table-column>
  60 + <el-table-column prop="manufacture" label="厂家">
  61 + </el-table-column>
  62 + <el-table-column label="位置信息" align="center">
  63 + <template slot-scope="scope">
  64 + <span>{{ scope.row.longitude }},{{ scope.row.latitude }}</span>
  65 + </template>
  66 + </el-table-column>
  67 + <el-table-column prop="ptztypeText" label="云台类型"/>
  68 + <el-table-column label="开启音频" align="center">
  69 + <template slot-scope="scope">
  70 + <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
  71 + </el-switch>
  72 + </template>
  73 + </el-table-column>
  74 + <el-table-column label="状态" width="180" align="center">
  75 + <template slot-scope="scope">
  76 + <div slot="reference" class="name-wrapper">
  77 + <el-tag size="medium" v-if="scope.row.status == 1">开启</el-tag>
  78 + <el-tag size="medium" type="info" v-if="scope.row.status == 0">关闭</el-tag>
  79 + </div>
  80 + </template>
  81 + </el-table-column>
15 82  
16   - 通道类型: <el-select size="mini" @change="search" style="margin-right: 1rem;" v-model="channelType" placeholder="请选择" default-first-option>
17   - <el-option label="全部" value=""></el-option>
18   - <el-option label="设备" value="false"></el-option>
19   - <el-option label="子目录" value="true"></el-option>
20   - </el-select>
21   - 在线状态: <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择" default-first-option>
22   - <el-option label="全部" value=""></el-option>
23   - <el-option label="在线" value="true"></el-option>
24   - <el-option label="离线" value="false"></el-option>
25   - </el-select>
26   - <el-checkbox size="mini" style="margin-right: 1rem; float: right;" v-model="autoList" @change="autoListChange">自动刷新</el-checkbox>
27   - </div>
28   - <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
29   - <!--设备列表-->
30   - <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%">
31   - <el-table-column prop="channelId" label="通道编号" width="200">
32   - </el-table-column>
33   - <el-table-column prop="name" label="通道名称">
34   - </el-table-column>
35   - <el-table-column label="快照" width="80" align="center">
36   - <template slot-scope="scope">
37   - <img style="max-height: 3rem;max-width: 4rem;"
38   - :id="scope.row.deviceId + '_' + scope.row.channelId"
39   - :src="getSnap(scope.row)"
40   - @error="getSnapErrorEvent($event.target.id)"
41   - alt="">
42   -<!-- <el-image-->
43   -<!-- :id="'snapImg_' + scope.row.deviceId + '_' + scope.row.channelId"-->
44   -<!-- :src="getSnap(scope.row)"-->
45   -<!-- @error="getSnapErrorEvent($event, scope.row)"-->
46   -<!-- :fit="'contain'">-->
47   -<!-- <div slot="error" class="image-slot">-->
48   -<!-- <i class="el-icon-picture-outline"></i>-->
49   -<!-- </div>-->
50   -<!-- </el-image>-->
51   - </template>
52   - </el-table-column>
53   - <el-table-column prop="subCount" label="子节点数">
54   - </el-table-column>
55   - <el-table-column prop="manufacture" label="厂家">
56   - </el-table-column>
57   - <el-table-column label="位置信息" align="center">
58   - <template slot-scope="scope">
59   - <span>{{scope.row.longitude}},{{scope.row.latitude}}</span>
60   - </template>
61   - </el-table-column>
62   - <el-table-column prop="ptztypeText" label="云台类型"/>
63   - <el-table-column label="开启音频" align="center">
64   - <template slot-scope="scope">
65   - <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
66   - </el-switch>
67   - </template>
68   - </el-table-column>
69   - <el-table-column label="状态" width="180" align="center">
70   - <template slot-scope="scope">
71   - <div slot="reference" class="name-wrapper">
72   - <el-tag size="medium" v-if="scope.row.status == 1">开启</el-tag>
73   - <el-tag size="medium" type="info" v-if="scope.row.status == 0">关闭</el-tag>
74   - </div>
75   - </template>
76   - </el-table-column>
77 83  
78   -
79   - <el-table-column label="操作" width="280" align="center" fixed="right">
80   - <template slot-scope="scope">
81   - <el-button-group>
82   - <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> -->
83   - <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>
84   - <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button>
85   - <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0" @click="changeSubchannel(scope.row)">查看</el-button>
86   - <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象</el-button>
87   - <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> -->
88   - </el-button-group>
89   - </template>
90   - </el-table-column>
91   - </el-table>
92   - <el-pagination style="float: right" @size-change="handleSizeChange" @current-change="currentChange" :current-page="currentPage" :page-size="count" :page-sizes="[15, 20, 30, 50]" layout="total, sizes, prev, pager, next" :total="total">
93   - </el-pagination>
94   -
95   - </el-main>
96   - </el-container>
97   -</div>
  84 + <el-table-column label="操作" width="280" align="center" fixed="right">
  85 + <template slot-scope="scope">
  86 + <el-button-group>
  87 + <!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> -->
  88 + <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>
  89 + <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId"
  90 + @click="stopDevicePush(scope.row)">停止
  91 + </el-button>
  92 + <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0"
  93 + @click="changeSubchannel(scope.row)">查看
  94 + </el-button>
  95 + <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象
  96 + </el-button>
  97 + <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> -->
  98 + </el-button-group>
  99 + </template>
  100 + </el-table-column>
  101 + </el-table>
  102 + <el-pagination style="float: right" @size-change="handleSizeChange" @current-change="currentChange"
  103 + :current-page="currentPage" :page-size="count" :page-sizes="[15, 20, 30, 50]"
  104 + layout="total, sizes, prev, pager, next" :total="total">
  105 + </el-pagination>
  106 + </div>
98 107 </template>
99 108  
100 109 <script>
101 110 import devicePlayer from './dialog/devicePlayer.vue'
102   -import uiHeader from './UiHeader.vue'
  111 +import uiHeader from '../layout/UiHeader.vue'
103 112 import moment from "moment";
  113 +
104 114 export default {
105   - name: 'channelList',
106   - components: {
107   - devicePlayer,
108   - uiHeader
109   - },
110   - data() {
111   - return {
112   - deviceId: this.$route.params.deviceId,
113   - parentChannelId: this.$route.params.parentChannelId,
114   - deviceChannelList: [],
115   - videoComponentList: [],
116   - currentPlayerInfo: {}, //当前播放对象
117   - updateLooper: 0, //数据刷新轮训标志
118   - searchSrt: "",
119   - channelType: "",
120   - online: "",
121   - winHeight: window.innerHeight - 250,
122   - currentPage: parseInt(this.$route.params.page),
123   - count: parseInt(this.$route.params.count),
124   - total: 0,
125   - beforeUrl: "/deviceList",
126   - isLoging: false,
127   - autoList: true,
128   - loadSnap:{}
129   - };
  115 + name: 'channelList',
  116 + components: {
  117 + devicePlayer,
  118 + uiHeader
  119 + },
  120 + data() {
  121 + return {
  122 + deviceId: this.$route.params.deviceId,
  123 + parentChannelId: this.$route.params.parentChannelId,
  124 + deviceChannelList: [],
  125 + videoComponentList: [],
  126 + currentPlayerInfo: {}, //当前播放对象
  127 + updateLooper: 0, //数据刷新轮训标志
  128 + searchSrt: "",
  129 + channelType: "",
  130 + online: "",
  131 + winHeight: window.innerHeight - 250,
  132 + currentPage: parseInt(this.$route.params.page),
  133 + count: parseInt(this.$route.params.count),
  134 + total: 0,
  135 + beforeUrl: "/deviceList",
  136 + isLoging: false,
  137 + autoList: true,
  138 + loadSnap: {}
  139 + };
  140 + },
  141 +
  142 + mounted() {
  143 + this.initData();
  144 + if (this.autoList) {
  145 + this.updateLooper = setInterval(this.initData, 5000);
  146 + }
  147 +
  148 + },
  149 + destroyed() {
  150 + this.$destroy('videojs');
  151 + clearTimeout(this.updateLooper);
  152 + },
  153 + methods: {
  154 + initData: function () {
  155 + if (typeof (this.parentChannelId) == "undefined" || this.parentChannelId == 0) {
  156 + this.getDeviceChannelList();
  157 + } else {
  158 + this.showSubchannels();
  159 + }
130 160 },
  161 + initParam: function () {
  162 + this.deviceId = this.$route.params.deviceId;
  163 + this.parentChannelId = this.$route.params.parentChannelId;
  164 + this.currentPage = parseInt(this.$route.params.page);
  165 + this.count = parseInt(this.$route.params.count);
  166 + if (this.parentChannelId == "" || this.parentChannelId == 0) {
  167 + this.beforeUrl = "/deviceList"
  168 + }
131 169  
132   - mounted() {
  170 + },
  171 + currentChange: function (val) {
  172 + var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}`
  173 + this.$router.push(url).then(() => {
  174 + this.initParam();
133 175 this.initData();
134   - if (this.autoList) {
135   - this.updateLooper = setInterval(this.initData, 5000);
136   - }
  176 + })
  177 + },
  178 + handleSizeChange: function (val) {
  179 + var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1`
  180 + this.$router.push(url).then(() => {
  181 + this.initParam();
  182 + this.initData();
  183 + })
137 184  
138 185 },
139   - destroyed() {
140   - this.$destroy('videojs');
141   - clearTimeout(this.updateLooper);
  186 + getDeviceChannelList: function () {
  187 + let that = this;
  188 + if (typeof (this.$route.params.deviceId) == "undefined") return;
  189 + this.$axios({
  190 + method: 'get',
  191 + url: `/api/device/query/devices/${this.$route.params.deviceId}/channels`,
  192 + params: {
  193 + page: that.currentPage,
  194 + count: that.count,
  195 + query: that.searchSrt,
  196 + online: that.online,
  197 + channelType: that.channelType
  198 + }
  199 + }).then(function (res) {
  200 + that.total = res.data.total;
  201 + that.deviceChannelList = res.data.list;
  202 + // 防止出现表格错位
  203 + that.$nextTick(() => {
  204 + that.$refs.channelListTable.doLayout();
  205 + })
  206 + }).catch(function (error) {
  207 + console.log(error);
  208 + });
142 209 },
143   - methods: {
144   - initData: function () {
145   - if (typeof (this.parentChannelId) == "undefined" || this.parentChannelId == 0) {
146   - this.getDeviceChannelList();
147   - } else {
148   - this.showSubchannels();
149   - }
150   - },
151   - initParam: function () {
152   - this.deviceId = this.$route.params.deviceId;
153   - this.parentChannelId = this.$route.params.parentChannelId;
154   - this.currentPage = parseInt(this.$route.params.page);
155   - this.count = parseInt(this.$route.params.count);
156   - if (this.parentChannelId == "" || this.parentChannelId == 0) {
157   - this.beforeUrl = "/deviceList"
158   - }
159 210  
160   - },
161   - currentChange: function (val) {
162   - var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}`
163   - this.$router.push(url).then(() => {
164   - this.initParam();
165   - this.initData();
166   - })
167   - },
168   - handleSizeChange: function (val) {
169   - var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1`
170   - this.$router.push(url).then(() => {
171   - this.initParam();
172   - this.initData();
173   - })
  211 + //通知设备上传媒体流
  212 + sendDevicePush: function (itemData) {
  213 + let deviceId = this.deviceId;
  214 + this.isLoging = true;
  215 + let channelId = itemData.channelId;
  216 + console.log("通知设备推流1:" + deviceId + " : " + channelId);
  217 + let that = this;
  218 + this.$axios({
  219 + method: 'get',
  220 + url: '/api/play/start/' + deviceId + '/' + channelId
  221 + }).then(function (res) {
  222 + that.isLoging = false;
  223 + if (res.data.code === 0) {
174 224  
175   - },
176   - getDeviceChannelList: function () {
177   - let that = this;
178   - if (typeof (this.$route.params.deviceId) == "undefined") return;
179   - this.$axios({
180   - method: 'get',
181   - url: `/api/device/query/devices/${this.$route.params.deviceId}/channels`,
182   - params:{
183   - page: that.currentPage,
184   - count: that.count,
185   - query: that.searchSrt,
186   - online: that.online,
187   - channelType: that.channelType
188   - }
189   - }).then(function (res) {
190   - that.total = res.data.total;
191   - that.deviceChannelList = res.data.list;
192   - // 防止出现表格错位
193   - that.$nextTick(() => {
194   - that.$refs.channelListTable.doLayout();
195   - })
196   - }).catch(function (error) {
197   - console.log(error);
198   - });
199   - },
  225 + setTimeout(() => {
200 226  
201   - //通知设备上传媒体流
202   - sendDevicePush: function (itemData) {
203   - let deviceId = this.deviceId;
204   - this.isLoging = true;
205   - let channelId = itemData.channelId;
206   - console.log("通知设备推流1:" + deviceId + " : " + channelId );
207   - let that = this;
208   - this.$axios({
209   - method: 'get',
210   - url: '/api/play/start/' + deviceId + '/' + channelId
211   - }).then(function (res) {
212   - that.isLoging = false;
213   - if (res.data.code === 0) {
  227 + let snapId = deviceId + "_" + channelId;
  228 + that.loadSnap[snapId] = 0;
  229 + that.getSnapErrorEvent(snapId)
  230 + }, 5000)
  231 + that.$refs.devicePlayer.openDialog("media", deviceId, channelId, {
  232 + streamInfo: res.data.data,
  233 + hasAudio: itemData.hasAudio
  234 + });
  235 + setTimeout(() => {
  236 + that.initData();
  237 + }, 1000)
214 238  
215   - setTimeout(()=>{
216   -
217   - let snapId = deviceId + "_" + channelId;
218   - that.loadSnap[snapId] = 0;
219   - that.getSnapErrorEvent(snapId)
220   - },5000)
221   - that.$refs.devicePlayer.openDialog("media", deviceId, channelId, {
222   - streamInfo: res.data.data,
223   - hasAudio: itemData.hasAudio
224   - });
225   - setTimeout(()=>{
226   - that.initData();
227   - },1000)
228   -
229   - }else {
230   - that.$message.error(res.data.msg);
231   - }
232   - }).catch(function (e) {});
233   - },
234   - queryRecords: function (itemData) {
235   - var format = moment().format("YYYY-M-D");
236   - let deviceId = this.deviceId;
237   - let channelId = itemData.channelId;
238   - this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format})
239   - },
240   - stopDevicePush: function (itemData) {
241   - var that = this;
242   - this.$axios({
243   - method: 'get',
244   - url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId
245   - }).then(function (res) {
246   - that.initData();
247   - }).catch(function (error) {
248   - if (error.response.status === 402) { // 已经停止过
249   - that.initData();
250   - }else {
251   - console.log(error)
252   - }
253   - });
254   - },
255   - getSnap: function (row){
256   - return '/static/snap/' + row.deviceId + '_' + row.channelId + '.jpg'
257   - },
258   - getSnapErrorEvent: function (id){
  239 + } else {
  240 + that.$message.error(res.data.msg);
  241 + }
  242 + }).catch(function (e) {
  243 + });
  244 + },
  245 + queryRecords: function (itemData) {
  246 + var format = moment().format("YYYY-M-D");
  247 + let deviceId = this.deviceId;
  248 + let channelId = itemData.channelId;
  249 + this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format})
  250 + },
  251 + stopDevicePush: function (itemData) {
  252 + var that = this;
  253 + this.$axios({
  254 + method: 'get',
  255 + url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId
  256 + }).then(function (res) {
  257 + that.initData();
  258 + }).catch(function (error) {
  259 + if (error.response.status === 402) { // 已经停止过
  260 + that.initData();
  261 + } else {
  262 + console.log(error)
  263 + }
  264 + });
  265 + },
  266 + getSnap: function (row) {
  267 + return '/static/snap/' + row.deviceId + '_' + row.channelId + '.jpg'
  268 + },
  269 + getSnapErrorEvent: function (id) {
259 270  
260   - if (typeof (this.loadSnap[id]) != "undefined") {
261   - console.log("下载截图" + this.loadSnap[id])
262   - if (this.loadSnap[id] > 5) {
263   - delete this.loadSnap[id];
264   - return;
265   - }
266   - setTimeout(()=>{
267   - this.loadSnap[id] ++
268   - document.getElementById(id).setAttribute("src", '/static/snap/' + id + '.jpg?' + new Date().getTime())
269   - },1000)
  271 + if (typeof (this.loadSnap[id]) != "undefined") {
  272 + console.log("下载截图" + this.loadSnap[id])
  273 + if (this.loadSnap[id] > 5) {
  274 + delete this.loadSnap[id];
  275 + return;
  276 + }
  277 + setTimeout(() => {
  278 + this.loadSnap[id]++
  279 + document.getElementById(id).setAttribute("src", '/static/snap/' + id + '.jpg?' + new Date().getTime())
  280 + }, 1000)
270 281  
271   - }
272   - },
273   - showDevice: function () {
274   - this.$router.push(this.beforeUrl).then(() => {
275   - this.initParam();
276   - this.initData();
277   - })
278   - },
279   - changeSubchannel(itemData) {
280   - this.beforeUrl = this.$router.currentRoute.path;
  282 + }
  283 + },
  284 + showDevice: function () {
  285 + this.$router.push(this.beforeUrl).then(() => {
  286 + this.initParam();
  287 + this.initData();
  288 + })
  289 + },
  290 + changeSubchannel(itemData) {
  291 + this.beforeUrl = this.$router.currentRoute.path;
281 292  
282   - var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}/${this.$router.currentRoute.params.count}/1`
283   - this.$router.push(url).then(() => {
284   - this.searchSrt = "";
285   - this.channelType = "";
286   - this.online = "";
287   - this.initParam();
288   - this.initData();
289   - })
290   - },
291   - showSubchannels: function (channelId) {
292   - let that = this;
  293 + var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}/${this.$router.currentRoute.params.count}/1`
  294 + this.$router.push(url).then(() => {
  295 + this.searchSrt = "";
  296 + this.channelType = "";
  297 + this.online = "";
  298 + this.initParam();
  299 + this.initData();
  300 + })
  301 + },
  302 + showSubchannels: function (channelId) {
  303 + let that = this;
293 304  
294   - this.$axios({
295   - method: 'get',
296   - url:`/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
297   - params: {
298   - page: that.currentPage,
299   - count: that.count,
300   - query: that.searchSrt,
301   - online: that.online,
302   - channelType: that.channelType
303   - }
304   - }).then(function (res) {
305   - that.total = res.data.total;
306   - that.deviceChannelList = res.data.list;
307   - // 防止出现表格错位
308   - that.$nextTick(() => {
309   - that.$refs.channelListTable.doLayout();
310   - })
311   - }).catch(function (error) {
312   - console.log(error);
313   - });
314   - },
315   - search: function () {
316   - this.currentPage = 1;
317   - this.total = 0;
318   - this.initData();
319   - },
320   - updateChannel: function (row) {
321   - this.$axios({
322   - method: 'post',
323   - url: `/api/device/query/channel/update/${this.deviceId}`,
324   - params: row
325   - }).then(function (res) {
326   - console.log(JSON.stringify(res));
327   - });
328   - },
329   - autoListChange: function () {
330   - if (this.autoList) {
331   - this.updateLooper = setInterval(this.initData, 1500);
332   - }else{
333   - window.clearInterval(this.updateLooper);
334   - }
  305 + this.$axios({
  306 + method: 'get',
  307 + url: `/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
  308 + params: {
  309 + page: that.currentPage,
  310 + count: that.count,
  311 + query: that.searchSrt,
  312 + online: that.online,
  313 + channelType: that.channelType
335 314 }
336   -
  315 + }).then(function (res) {
  316 + that.total = res.data.total;
  317 + that.deviceChannelList = res.data.list;
  318 + // 防止出现表格错位
  319 + that.$nextTick(() => {
  320 + that.$refs.channelListTable.doLayout();
  321 + })
  322 + }).catch(function (error) {
  323 + console.log(error);
  324 + });
  325 + },
  326 + search: function () {
  327 + this.currentPage = 1;
  328 + this.total = 0;
  329 + this.initData();
  330 + },
  331 + updateChannel: function (row) {
  332 + this.$axios({
  333 + method: 'post',
  334 + url: `/api/device/query/channel/update/${this.deviceId}`,
  335 + params: row
  336 + }).then(function (res) {
  337 + console.log(JSON.stringify(res));
  338 + });
  339 + },
  340 + autoListChange: function () {
  341 + if (this.autoList) {
  342 + this.updateLooper = setInterval(this.initData, 1500);
  343 + } else {
  344 + window.clearInterval(this.updateLooper);
  345 + }
337 346 }
  347 +
  348 + }
338 349 };
339 350 </script>
340 351  
341 352 <style>
342 353 .videoList {
343   - display: flex;
344   - flex-wrap: wrap;
345   - align-content: flex-start;
  354 + display: flex;
  355 + flex-wrap: wrap;
  356 + align-content: flex-start;
346 357 }
347 358  
348 359 .video-item {
349   - position: relative;
350   - width: 15rem;
351   - height: 10rem;
352   - margin-right: 1rem;
353   - background-color: #000000;
  360 + position: relative;
  361 + width: 15rem;
  362 + height: 10rem;
  363 + margin-right: 1rem;
  364 + background-color: #000000;
354 365 }
355 366  
356 367 .video-item-img {
357   - position: absolute;
358   - top: 0;
359   - bottom: 0;
360   - left: 0;
361   - right: 0;
362   - margin: auto;
363   - width: 100%;
364   - height: 100%;
  368 + position: absolute;
  369 + top: 0;
  370 + bottom: 0;
  371 + left: 0;
  372 + right: 0;
  373 + margin: auto;
  374 + width: 100%;
  375 + height: 100%;
365 376 }
366 377  
367 378 .video-item-img:after {
368   - content: "";
369   - display: inline-block;
370   - position: absolute;
371   - z-index: 2;
372   - top: 0;
373   - bottom: 0;
374   - left: 0;
375   - right: 0;
376   - margin: auto;
377   - width: 3rem;
378   - height: 3rem;
379   - background-image: url("../assets/loading.png");
380   - background-size: cover;
381   - background-color: #000000;
  379 + content: "";
  380 + display: inline-block;
  381 + position: absolute;
  382 + z-index: 2;
  383 + top: 0;
  384 + bottom: 0;
  385 + left: 0;
  386 + right: 0;
  387 + margin: auto;
  388 + width: 3rem;
  389 + height: 3rem;
  390 + background-image: url("../assets/loading.png");
  391 + background-size: cover;
  392 + background-color: #000000;
382 393 }
383 394  
384 395 .video-item-title {
385   - position: absolute;
386   - bottom: 0;
387   - color: #000000;
388   - background-color: #ffffff;
389   - line-height: 1.5rem;
390   - padding: 0.3rem;
391   - width: 14.4rem;
  396 + position: absolute;
  397 + bottom: 0;
  398 + color: #000000;
  399 + background-color: #ffffff;
  400 + line-height: 1.5rem;
  401 + padding: 0.3rem;
  402 + width: 14.4rem;
392 403 }
393 404 </style>
... ...
web_src/src/components/control.vue
1 1 <template>
2   -<div id="app">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span style="font-size: 1rem; font-weight: bold;">控制台</span>
10   - <div style="position: absolute; right: 17rem; top: 0.3rem;">
11   - 节点选择: <el-select size="mini" @change="chooseMediaChange" style="width: 18rem; margin-right: 8rem;" v-model="mediaServerChoose" placeholder="请选择" default-first-option>
12   - <el-option
13   - v-for="item in mediaServerList"
14   - :key="item.id"
15   - :label="item.id + '( ' + item.streamIp + ' )'"
16   - :value="item.id">
17   - </el-option>
18   - </el-select>
19   - <span >{{loadCount}}</span>
20   - </div>
21   - <div style="position: absolute; right: 1rem; top: 0.3rem;">
22   - <el-popover placement="bottom" width="900" height="300" trigger="click">
23   - <div style="height: 600px; overflow:auto; padding: 20px">
24   - <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border :column="1" style="margin-bottom: 1rem">
25   - <template slot="title">
26   - {{key}}
27   - </template>
28   - <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1">
29   - <template slot="label" >
30   - {{ getMediaKeyNameFromKey(key1) }}
31   - </template>
32   - {{ value1 }}
33   - </el-descriptions-item>
34   - </el-descriptions>
35   - </div>
36   - <el-button type="primary" slot="reference" size="mini" @click="getServerConfig()">媒体服务器配置</el-button>
37   - </el-popover>
38   - <el-popover placement="bottom" width="900" height="300" trigger="click">
39   - <div style="height: 600px;overflow:auto; padding: 20px">
40   - <el-descriptions title="国标配置" border :column="1">
41   - <template slot="extra">
42   - <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerConfig.sip)|| ''" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
43   - </template>
44   - <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip">
45   - <template slot="label">
46   - {{ getNameFromKey(key) }}
47   - </template>
48   - {{ value }}
49   - </el-descriptions-item>
50   - </el-descriptions>
  2 + <div id="app" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">控制台</div>
  5 + <div class="page-header-btn">
  6 + 节点选择:
  7 + <el-select size="mini" @change="chooseMediaChange" style="width: 18rem; margin-right: 8rem;"
  8 + v-model="mediaServerChoose" placeholder="请选择" default-first-option>
  9 + <el-option
  10 + v-for="item in mediaServerList"
  11 + :key="item.id"
  12 + :label="item.id + '( ' + item.streamIp + ' )'"
  13 + :value="item.id">
  14 + </el-option>
  15 + </el-select>
  16 + <span>{{ loadCount }}</span>
  17 + </div>
  18 + <div class="page-header-btn">
  19 + <el-popover placement="bottom" width="900" height="300" trigger="click">
  20 + <div style="height: 600px; overflow:auto; padding: 20px">
  21 + <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border :column="1"
  22 + style="margin-bottom: 1rem">
  23 + <template slot="title">
  24 + {{ key }}
  25 + </template>
  26 + <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1">
  27 + <template slot="label">
  28 + {{ getMediaKeyNameFromKey(key1) }}
  29 + </template>
  30 + {{ value1 }}
  31 + </el-descriptions-item>
  32 + </el-descriptions>
  33 + </div>
  34 + <el-button type="primary" slot="reference" size="mini" @click="getServerConfig()">媒体服务器配置</el-button>
  35 + </el-popover>
  36 + <el-popover placement="bottom" width="900" height="300" trigger="click">
  37 + <div style="height: 600px;overflow:auto; padding: 20px">
  38 + <el-descriptions title="国标配置" border :column="1">
  39 + <template slot="extra">
  40 + <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"
  41 + v-clipboard="JSON.stringify(wvpServerConfig.sip)|| ''"
  42 + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
  43 + </template>
  44 + <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip" :key="key">
  45 + <template slot="label">
  46 + {{ getNameFromKey(key) }}
  47 + </template>
  48 + {{ value }}
  49 + </el-descriptions-item>
  50 + </el-descriptions>
51 51  
52   - <div style="margin-top: 1rem">
53   - <el-descriptions title="基础配置" border :column="1">
54   - <template slot="extra">
55   - <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerConfig.base)|| ''" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
56   - </template>
57   - <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key">
58   - <template slot="label" >
59   - {{ getNameFromKey(key) }}
60   - </template>
61   - <div v-if="key === 'interfaceAuthenticationExcludes'">
62   - <el-dropdown>
  52 + <div style="margin-top: 1rem">
  53 + <el-descriptions title="基础配置" border :column="1">
  54 + <template slot="extra">
  55 + <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"
  56 + v-clipboard="JSON.stringify(wvpServerConfig.base)|| ''"
  57 + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
  58 + </template>
  59 + <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key">
  60 + <template slot="label">
  61 + {{ getNameFromKey(key) }}
  62 + </template>
  63 + <div v-if="key === 'interfaceAuthenticationExcludes'">
  64 + <el-dropdown>
63 65 <span class="el-dropdown-link">
64 66 查看<i class="el-icon-arrow-down el-icon--right"></i>
65 67 </span>
66   - <el-dropdown-menu slot="dropdown">
67   - <el-dropdown-item v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes" :key="key">{{value}}</el-dropdown-item>
68   - </el-dropdown-menu>
69   - </el-dropdown>
70   - </div>
71   - <div v-if="key !== 'interfaceAuthenticationExcludes'">
72   - <div v-if="value === true">
73   - 已启用
74   - </div>
75   - <div v-if="value === false">
76   - 未启用
77   - </div>
78   - <div v-if="value !== true && value !== false">
79   - {{ value }}
80   - </div>
81   - </div>
  68 + <el-dropdown-menu slot="dropdown">
  69 + <el-dropdown-item
  70 + v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes"
  71 + :key="key">{{ value }}
  72 + </el-dropdown-item>
  73 + </el-dropdown-menu>
  74 + </el-dropdown>
  75 + </div>
  76 + <div v-if="key !== 'interfaceAuthenticationExcludes'">
  77 + <div v-if="value === true">
  78 + 已启用
  79 + </div>
  80 + <div v-if="value === false">
  81 + 未启用
  82 + </div>
  83 + <div v-if="value !== true && value !== false">
  84 + {{ value }}
  85 + </div>
  86 + </div>
82 87  
83   - </el-descriptions-item>
84   - </el-descriptions>
85   - </div>
86   - <div style="margin-top: 1rem">
87   - <el-descriptions title="版本信息" border :column="1">
88   - <template slot="extra">
89   - <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerVersion) || ''" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
90   - </template>
91   - <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key">
92   - <template slot="label">
93   - {{ getNameFromKey(key) }}
94   - </template>
95   - {{ value }}
96   - </el-descriptions-item>
97   - </el-descriptions>
  88 + </el-descriptions-item>
  89 + </el-descriptions>
  90 + </div>
  91 + <div style="margin-top: 1rem">
  92 + <el-descriptions title="版本信息" border :column="1">
  93 + <template slot="extra">
  94 + <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"
  95 + v-clipboard="JSON.stringify(wvpServerVersion) || ''"
  96 + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
  97 + </template>
  98 + <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key">
  99 + <template slot="label">
  100 + {{ getNameFromKey(key) }}
  101 + </template>
  102 + {{ value }}
  103 + </el-descriptions-item>
  104 + </el-descriptions>
98 105  
99 106  
100   - </div>
101   - </div>
102   - <el-button type="primary" slot="reference" size="mini" @click="getWVPServerConfig()">信令服务器配置</el-button>
103   - </el-popover>
104   - <el-button style="margin-left: 1rem;" type="danger" size="mini" @click="reStartServer()">重启媒体服务器</el-button>
105   - </div>
106 107 </div>
107   - <el-row :gutter="30">
108   - <el-col :span="12">
109   - <div class="control-table" id="ThreadsLoad">table1</div>
110   - </el-col>
111   - <el-col :span="12">
112   - <div class="control-table" id="WorkThreadsLoad">table2</div>
113   - </el-col>
114   - </el-row>
115   - <el-table :data="allSessionData" style="margin-top: 1rem;">
116   - <el-table-column prop="peer_ip" label="远端"></el-table-column>
117   - <el-table-column prop="local_ip" label="本地"></el-table-column>
118   - <el-table-column prop="typeid" label="类型"></el-table-column>
119   - <el-table-column align="right">
120   - <template slot="header" slot-scope="scope">
121   - <el-button icon="el-icon-refresh-right" circle @click="getAllSession()"></el-button>
122   - </template>
123   - <template slot-scope="scope">
124   - <el-button @click.native.prevent="deleteRow(scope.$index, allSessionData)" type="text" size="small">移除</el-button>
125   - </template>
126   - </el-table-column>
127   - </el-table>
  108 + </div>
  109 + <el-button type="primary" slot="reference" size="mini" @click="getWVPServerConfig()">信令服务器配置</el-button>
  110 + </el-popover>
  111 + <el-button style="margin-left: 1rem;" type="danger" size="mini" @click="reStartServer()">重启媒体服务器</el-button>
  112 + </div>
  113 + </div>
  114 + <!-- <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">-->
  115 + <!-- <span style="font-size: 1rem; font-weight: bold;">控制台</span>-->
  116 + <!-- <div style="position: absolute; right: 17rem; top: 0.3rem;">-->
  117 + <!-- 节点选择:-->
  118 + <!-- <el-select size="mini" @change="chooseMediaChange" style="width: 18rem; margin-right: 8rem;"-->
  119 + <!-- v-model="mediaServerChoose" placeholder="请选择" default-first-option>-->
  120 + <!-- <el-option-->
  121 + <!-- v-for="item in mediaServerList"-->
  122 + <!-- :key="item.id"-->
  123 + <!-- :label="item.id + '( ' + item.streamIp + ' )'"-->
  124 + <!-- :value="item.id">-->
  125 + <!-- </el-option>-->
  126 + <!-- </el-select>-->
  127 + <!-- <span>{{ loadCount }}</span>-->
  128 + <!-- </div>-->
  129 + <!-- <div style="position: absolute; right: 1rem; top: 0.3rem;">-->
  130 + <!-- <el-popover placement="bottom" width="900" height="300" trigger="click">-->
  131 + <!-- <div style="height: 600px; overflow:auto; padding: 20px">-->
  132 + <!-- <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border :column="1"-->
  133 + <!-- style="margin-bottom: 1rem">-->
  134 + <!-- <template slot="title">-->
  135 + <!-- {{ key }}-->
  136 + <!-- </template>-->
  137 + <!-- <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1">-->
  138 + <!-- <template slot="label">-->
  139 + <!-- {{ getMediaKeyNameFromKey(key1) }}-->
  140 + <!-- </template>-->
  141 + <!-- {{ value1 }}-->
  142 + <!-- </el-descriptions-item>-->
  143 + <!-- </el-descriptions>-->
  144 + <!-- </div>-->
  145 + <!-- <el-button type="primary" slot="reference" size="mini" @click="getServerConfig()">媒体服务器配置</el-button>-->
  146 + <!-- </el-popover>-->
  147 + <!-- <el-popover placement="bottom" width="900" height="300" trigger="click">-->
  148 + <!-- <div style="height: 600px;overflow:auto; padding: 20px">-->
  149 + <!-- <el-descriptions title="国标配置" border :column="1">-->
  150 + <!-- <template slot="extra">-->
  151 + <!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"-->
  152 + <!-- v-clipboard="JSON.stringify(wvpServerConfig.sip)|| ''"-->
  153 + <!-- @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>-->
  154 + <!-- </template>-->
  155 + <!-- <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.sip" :key="key">-->
  156 + <!-- <template slot="label">-->
  157 + <!-- {{ getNameFromKey(key) }}-->
  158 + <!-- </template>-->
  159 + <!-- {{ value }}-->
  160 + <!-- </el-descriptions-item>-->
  161 + <!-- </el-descriptions>-->
  162 +
  163 + <!-- <div style="margin-top: 1rem">-->
  164 + <!-- <el-descriptions title="基础配置" border :column="1">-->
  165 + <!-- <template slot="extra">-->
  166 + <!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"-->
  167 + <!-- v-clipboard="JSON.stringify(wvpServerConfig.base)|| ''"-->
  168 + <!-- @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>-->
  169 + <!-- </template>-->
  170 + <!-- <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key">-->
  171 + <!-- <template slot="label">-->
  172 + <!-- {{ getNameFromKey(key) }}-->
  173 + <!-- </template>-->
  174 + <!-- <div v-if="key === 'interfaceAuthenticationExcludes'">-->
  175 + <!-- <el-dropdown>-->
  176 + <!-- <span class="el-dropdown-link">-->
  177 + <!-- 查看<i class="el-icon-arrow-down el-icon&#45;&#45;right"></i>-->
  178 + <!-- </span>-->
  179 + <!-- <el-dropdown-menu slot="dropdown">-->
  180 + <!-- <el-dropdown-item-->
  181 + <!-- v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes"-->
  182 + <!-- :key="key">{{ value }}-->
  183 + <!-- </el-dropdown-item>-->
  184 + <!-- </el-dropdown-menu>-->
  185 + <!-- </el-dropdown>-->
  186 + <!-- </div>-->
  187 + <!-- <div v-if="key !== 'interfaceAuthenticationExcludes'">-->
  188 + <!-- <div v-if="value === true">-->
  189 + <!-- 已启用-->
  190 + <!-- </div>-->
  191 + <!-- <div v-if="value === false">-->
  192 + <!-- 未启用-->
  193 + <!-- </div>-->
  194 + <!-- <div v-if="value !== true && value !== false">-->
  195 + <!-- {{ value }}-->
  196 + <!-- </div>-->
  197 + <!-- </div>-->
128 198  
129   - </el-main>
130   - <!-- <el-footer style="position: absolute; bottom: 0; width: 100%;">ZLMediaKit-VUE_UI v1</el-footer> -->
131   - </el-container>
  199 + <!-- </el-descriptions-item>-->
  200 + <!-- </el-descriptions>-->
  201 + <!-- </div>-->
  202 + <!-- <div style="margin-top: 1rem">-->
  203 + <!-- <el-descriptions title="版本信息" border :column="1">-->
  204 + <!-- <template slot="extra">-->
  205 + <!-- <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝"-->
  206 + <!-- v-clipboard="JSON.stringify(wvpServerVersion) || ''"-->
  207 + <!-- @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>-->
  208 + <!-- </template>-->
  209 + <!-- <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key">-->
  210 + <!-- <template slot="label">-->
  211 + <!-- {{ getNameFromKey(key) }}-->
  212 + <!-- </template>-->
  213 + <!-- {{ value }}-->
  214 + <!-- </el-descriptions-item>-->
  215 + <!-- </el-descriptions>-->
132 216  
133   -</div>
  217 +
  218 + <!-- </div>-->
  219 + <!-- </div>-->
  220 + <!-- <el-button type="primary" slot="reference" size="mini" @click="getWVPServerConfig()">信令服务器配置</el-button>-->
  221 + <!-- </el-popover>-->
  222 + <!-- <el-button style="margin-left: 1rem;" type="danger" size="mini" @click="reStartServer()">重启媒体服务器</el-button>-->
  223 + <!-- </div>-->
  224 + <!-- </div>-->
  225 + <el-row style="width: 100%">
  226 + <el-col :span="12">
  227 + <div class="control-table" id="ThreadsLoad" style="margin-right:10px;">table1</div>
  228 + </el-col>
  229 + <el-col :span="12">
  230 + <div class="control-table" id="WorkThreadsLoad" style="margin-left:10px;">table2</div>
  231 + </el-col>
  232 + </el-row>
  233 + <el-table :data="allSessionData" style="margin-top: 1rem;">
  234 + <el-table-column prop="peer_ip" label="远端"></el-table-column>
  235 + <el-table-column prop="local_ip" label="本地"></el-table-column>
  236 + <el-table-column prop="typeid" label="类型"></el-table-column>
  237 + <el-table-column align="right">
  238 + <template slot="header" slot-scope="scope">
  239 + <el-button icon="el-icon-refresh-right" circle @click="getAllSession()"></el-button>
  240 + </template>
  241 + <template slot-scope="scope">
  242 + <el-button @click.native.prevent="deleteRow(scope.$index, allSessionData)" type="text" size="small">移除
  243 + </el-button>
  244 + </template>
  245 + </el-table-column>
  246 + </el-table>
  247 + </div>
134 248 </template>
135 249  
136 250 <script>
137   -import uiHeader from './UiHeader.vue'
  251 +import uiHeader from '../layout/UiHeader.vue'
138 252 import MediaServer from './service/MediaServer'
139 253  
140 254 import echarts from 'echarts';
141   -export default {
142   - name: 'app',
143   - components: {
144   - echarts,
145   - uiHeader
146   - },
147   - data() {
148   - return {
149   - tableOption: {
150   - // legend: {},
151   - xAxis: {},
152   - yAxis: {},
153   - label: {},
154   - tooltip: {},
155   - dataZoom: [],
156   - series: []
157   - },
158   - table1Option: {
159   - // legend: {},
160   - xAxis: {},
161   - yAxis: {},
162   - label: {},
163   - tooltip: {},
164   - series: []
165   - },
166   - mChart: null,
167   - mChart1: null,
168   - charZoomStart: 0,
169   - charZoomEnd: 100,
170   - chartInterval: 0, //更新图表统计图定时任务标识
171   - allSessionData: [],
172   - visible: false,
173   - wvpVisible: false,
174   - serverConfig: {},
175   - wvpServerConfig: {},
176   - wvpServerVersion: {},
177   - mediaServer : new MediaServer(),
178   - mediaServerChoose : null,
179   - loadCount : 0,
180   - mediaServerList : []
181   - };
182   - },
183   - mounted() {
184 255  
185   - this.initTable();
186   - this.chartInterval = setInterval(this.updateData, 3000);
187   - this.mediaServer.getOnlineMediaServerList((data)=>{
188   - this.mediaServerList = data.data;
189   - if (this.mediaServerList && this.mediaServerList.length > 0) {
190   - this.mediaServerChoose = this.mediaServerList[0].id
191   - this.loadCount = this.mediaServerList[0].count;
192   - this.updateData();
193   - }
194   - })
  256 +export default {
  257 + name: 'app',
  258 + components: {
  259 + echarts,
  260 + uiHeader
  261 + },
  262 + data() {
  263 + return {
  264 + tableOption: {
  265 + // legend: {},
  266 + xAxis: {},
  267 + yAxis: {},
  268 + label: {},
  269 + tooltip: {},
  270 + dataZoom: [],
  271 + series: []
  272 + },
  273 + table1Option: {
  274 + // legend: {},
  275 + xAxis: {},
  276 + yAxis: {},
  277 + label: {},
  278 + tooltip: {},
  279 + series: []
  280 + },
  281 + mChart: null,
  282 + mChart1: null,
  283 + charZoomStart: 0,
  284 + charZoomEnd: 100,
  285 + chartInterval: 0, //更新图表统计图定时任务标识
  286 + allSessionData: [],
  287 + visible: false,
  288 + wvpVisible: false,
  289 + serverConfig: {},
  290 + wvpServerConfig: {},
  291 + wvpServerVersion: {},
  292 + mediaServer: new MediaServer(),
  293 + mediaServerChoose: null,
  294 + loadCount: 0,
  295 + mediaServerList: []
  296 + };
  297 + },
  298 + mounted() {
  299 + this.initTable()
  300 + this.chartInterval = setInterval(this.updateData, 3000);
  301 + this.mediaServer.getOnlineMediaServerList((data) => {
  302 + this.mediaServerList = data.data;
  303 + if (this.mediaServerList && this.mediaServerList.length > 0) {
  304 + this.mediaServerChoose = this.mediaServerList[0].id
  305 + this.loadCount = this.mediaServerList[0].count;
  306 + this.updateData();
  307 + }
  308 + })
  309 + },
  310 + destroyed() {
  311 + clearInterval(this.chartInterval); //释放定时任务
  312 + },
  313 + methods: {
  314 + chooseMediaChange: function (val) {
  315 + this.loadCount = 0
  316 + this.initTable()
  317 + this.updateData();
195 318 },
196   - destroyed() {
197   - clearInterval(this.chartInterval); //释放定时任务
  319 + updateData: function () {
  320 + this.getThreadsLoad();
  321 + this.getLoadCount();
  322 + this.getAllSession();
198 323 },
199   - methods: {
200   - chooseMediaChange: function (val) {
201   - this.loadCount = 0
202   - this.initTable()
203   - this.updateData();
204   - },
205   - updateData: function () {
206   - this.getThreadsLoad();
207   - this.getLoadCount();
208   - this.getAllSession();
209   - },
210   - /**
211   - * 获取线程状态
212   - */
213   - getThreadsLoad: function () {
214   - let that = this;
215   - if (that.mediaServerChoose != null) {
216   - this.$axios({
217   - method: 'get',
218   - url: '/zlm/' + that.mediaServerChoose +'/index/api/getThreadsLoad'
219   - }).then(function (res) {
220   - if (res.data.code == 0) {
221   - that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
222   - hour12: false
223   - }));
224   - that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
225   - hour12: false
226   - }));
  324 + /**
  325 + * 获取线程状态
  326 + */
  327 + getThreadsLoad: function () {
  328 + let that = this;
  329 + if (that.mediaServerChoose != null) {
  330 + this.$axios({
  331 + method: 'get',
  332 + url: '/zlm/' + that.mediaServerChoose + '/index/api/getThreadsLoad'
  333 + }).then(function (res) {
  334 + if (res.data.code == 0) {
  335 + that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
  336 + hour12: false
  337 + }));
  338 + that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
  339 + hour12: false
  340 + }));
227 341  
228   - for (var i = 0; i < res.data.data.length; i++) {
229   - if (that.tableOption.series[i] === undefined) {
230   - let data = {
231   - data: [],
232   - type: 'line'
233   - };
234   - let data1 = {
235   - data: [],
236   - type: 'line'
237   - };
238   - data.data.push(res.data.data[i].delay);
239   - data1.data.push(res.data.data[i].load);
240   - that.tableOption.series.push(data);
241   - that.table1Option.series.push(data1);
242   - } else {
243   - that.tableOption.series[i].data.push(res.data.data[i].delay);
244   - that.table1Option.series[i].data.push(res.data.data[i].load);
245   - }
246   - }
247   - that.tableOption.dataZoom[0].start = that.charZoomStart;
248   - that.tableOption.dataZoom[0].end = that.charZoomEnd;
249   - that.table1Option.dataZoom[0].start = that.charZoomStart;
250   - that.table1Option.dataZoom[0].end = that.charZoomEnd;
251   - //that.myChart = echarts.init(document.getElementById('ThreadsLoad'));
252   - that.myChart.setOption(that.tableOption, true);
253   - // that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
254   - that.myChart1.setOption(that.table1Option, true);
255   - }
256   - });
257   - }
258   -
259   - },
260   - getLoadCount: function (){
261   - let that = this;
262   - if (that.mediaServerChoose != null) {
263   - that.mediaServer.getMediaServer(that.mediaServerChoose, (data)=>{
264   - if (data.code == 0) {
265   - that.loadCount = data.data.count
  342 + for (var i = 0; i < res.data.data.length; i++) {
  343 + if (that.tableOption.series[i] === undefined) {
  344 + let data = {
  345 + data: [],
  346 + type: 'line'
  347 + };
  348 + let data1 = {
  349 + data: [],
  350 + type: 'line'
  351 + };
  352 + data.data.push(res.data.data[i].delay);
  353 + data1.data.push(res.data.data[i].load);
  354 + that.tableOption.series.push(data);
  355 + that.table1Option.series.push(data1);
  356 + } else {
  357 + that.tableOption.series[i].data.push(res.data.data[i].delay);
  358 + that.table1Option.series[i].data.push(res.data.data[i].load);
266 359 }
  360 + }
  361 + that.tableOption.dataZoom[0].start = that.charZoomStart;
  362 + that.tableOption.dataZoom[0].end = that.charZoomEnd;
  363 + that.table1Option.dataZoom[0].start = that.charZoomStart;
  364 + that.table1Option.dataZoom[0].end = that.charZoomEnd;
  365 + //that.myChart = echarts.init(document.getElementById('ThreadsLoad'));
  366 + that.myChart.setOption(that.tableOption, true);
  367 + // that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
  368 + that.myChart1.setOption(that.table1Option, true);
  369 + that.$nextTick(() => {
  370 + that.myChart.resize()
  371 + that.myChart1.resize()
267 372 })
268 373 }
269   - },
270   - initTable: function () {
271   - let that = this;
272   - this.tableOption.xAxis = {
273   - type: 'category',
274   - data: [], // x轴数据
275   - name: '时间', // x轴名称
276   - // x轴名称样式
277   - nameTextStyle: {
278   - fontWeight: 300,
279   - fontSize: 15
280   - }
281   - };
282   - this.tableOption.yAxis = {
283   - type: 'value',
284   - name: '延迟率', // y轴名称
285   - boundaryGap: [0, '100%'],
286   - max: 100,
287   - axisLabel: {
288   - show: true,
289   - interval: 'auto',
290   - formatter: '{value} %'
291   - },
292   - // y轴名称样式
293   - nameTextStyle: {
294   - fontWeight: 300,
295   - fontSize: 15
296   - }
297   - };
298   - this.tableOption.dataZoom = [{
299   - show: true,
300   - start: this.charZoomStart,
301   - end: this.charZoomEnd
302   - }];
303   - this.myChart = echarts.init(document.getElementById('ThreadsLoad'));
304   - this.myChart.setOption(this.tableOption);
305   - this.myChart.on('dataZoom', function (event) {
306   - if (event.batch) {
307   - that.charZoomStart = event.batch[0].start;
308   - that.charZoomEnd = event.batch[0].end;
309   - } else {
310   - that.charZoomStart = event.start;
311   - that.charZoomEnd = event.end;
312   - }
313   - });
  374 + });
  375 + }
314 376  
315   - this.table1Option.xAxis = {
316   - type: 'category',
317   - data: [], // x轴数据
318   - name: '时间', // x轴名称
319   - // x轴名称样式
320   - nameTextStyle: {
321   - fontWeight: 300,
322   - fontSize: 15
323   - }
324   - };
325   - this.table1Option.yAxis = {
326   - type: 'value',
327   - name: '负载率', // y轴名称
328   - boundaryGap: [0, '100%'],
329   - max: 100,
330   - axisLabel: {
331   - show: true,
332   - interval: 'auto',
333   - formatter: '{value} %'
334   - },
335   - // y轴名称样式
336   - nameTextStyle: {
337   - fontWeight: 300,
338   - fontSize: 15
339   - }
340   - };
341   - this.table1Option.dataZoom = [{
342   - show: true,
343   - start: this.charZoomStart,
344   - end: this.charZoomEnd
345   - }];
346   - this.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
347   - this.myChart1.setOption(this.table1Option);
348   - this.myChart1.on('dataZoom', function (event) {
349   - if (event.batch) {
350   - that.charZoomStart = event.batch[0].start;
351   - that.charZoomEnd = event.batch[0].end;
352   - } else {
353   - that.charZoomStart = event.start;
354   - that.charZoomEnd = event.end;
355   - }
356   - });
  377 + },
  378 + getLoadCount: function () {
  379 + let that = this;
  380 + if (that.mediaServerChoose != null) {
  381 + that.mediaServer.getMediaServer(that.mediaServerChoose, (data) => {
  382 + if (data.code == 0) {
  383 + that.loadCount = data.data.count
  384 + }
  385 + })
  386 + }
  387 + },
  388 + initTable: function () {
  389 + let that = this;
  390 + this.tableOption.xAxis = {
  391 + type: 'category',
  392 + data: [], // x轴数据
  393 + name: '时间', // x轴名称
  394 + // x轴名称样式
  395 + nameTextStyle: {
  396 + fontWeight: 300,
  397 + fontSize: 15
  398 + }
  399 + };
  400 + this.tableOption.yAxis = {
  401 + type: 'value',
  402 + name: '延迟率', // y轴名称
  403 + boundaryGap: [0, '100%'],
  404 + max: 100,
  405 + axisLabel: {
  406 + show: true,
  407 + interval: 'auto',
  408 + formatter: '{value} %'
357 409 },
  410 + // y轴名称样式
  411 + nameTextStyle: {
  412 + fontWeight: 300,
  413 + fontSize: 15
  414 + }
  415 + };
  416 + this.tableOption.dataZoom = [{
  417 + show: true,
  418 + start: this.charZoomStart,
  419 + end: this.charZoomEnd
  420 + }];
  421 + this.myChart = echarts.init(document.getElementById('ThreadsLoad'));
  422 + this.myChart.setOption(this.tableOption);
  423 + this.myChart.on('dataZoom', function (event) {
  424 + if (event.batch) {
  425 + that.charZoomStart = event.batch[0].start;
  426 + that.charZoomEnd = event.batch[0].end;
  427 + } else {
  428 + that.charZoomStart = event.start;
  429 + that.charZoomEnd = event.end;
  430 + }
  431 + });
358 432  
359   - getAllSession: function () {
360   - let that = this;
361   - that.allSessionData = [];
362   - this.$axios({
363   - method: 'get',
364   - url: '/zlm/' + that.mediaServerChoose +'/index/api/getAllSession'
365   - }).then(function (res) {
366   - res.data.data.forEach(item => {
367   - let data = {
368   - peer_ip: item.peer_ip,
369   - local_ip: item.local_ip,
370   - typeid: item.typeid,
371   - id: item.id
372   - };
373   - that.allSessionData.push(data);
374   - });
375   - });
  433 + this.table1Option.xAxis = {
  434 + type: 'category',
  435 + data: [], // x轴数据
  436 + name: '时间', // x轴名称
  437 + // x轴名称样式
  438 + nameTextStyle: {
  439 + fontWeight: 300,
  440 + fontSize: 15
  441 + }
  442 + };
  443 + this.table1Option.yAxis = {
  444 + type: 'value',
  445 + name: '负载率', // y轴名称
  446 + boundaryGap: [0, '100%'],
  447 + max: 100,
  448 + axisLabel: {
  449 + show: true,
  450 + interval: 'auto',
  451 + formatter: '{value} %'
376 452 },
377   - getServerConfig: function () {
378   - let that = this;
379   - this.$axios({
380   - method: 'get',
381   - url: '/zlm/' + that.mediaServerChoose +'/index/api/getServerConfig'
382   - }).then(function (res) {
383   - let info = res.data.data[0];
384   - let serverInfo = {}
385   - for (let i = 0; i < Object.keys(info).length; i++) {
386   - let key = Object.keys(info)[i];
387   - let group = key.substring(0, key.indexOf("."))
388   - let itemKey = key.substring(key.indexOf(".") + 1)
389   - if (!serverInfo[group]) serverInfo[group] = {}
390   - serverInfo[group][itemKey] = info[key]
391   - }
  453 + // y轴名称样式
  454 + nameTextStyle: {
  455 + fontWeight: 300,
  456 + fontSize: 15
  457 + }
  458 + };
  459 + this.table1Option.dataZoom = [{
  460 + show: true,
  461 + start: this.charZoomStart,
  462 + end: this.charZoomEnd
  463 + }];
  464 + this.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
  465 + this.myChart1.setOption(this.table1Option);
  466 + this.myChart1.on('dataZoom', function (event) {
  467 + if (event.batch) {
  468 + that.charZoomStart = event.batch[0].start;
  469 + that.charZoomEnd = event.batch[0].end;
  470 + } else {
  471 + that.charZoomStart = event.start;
  472 + that.charZoomEnd = event.end;
  473 + }
  474 + });
  475 + },
392 476  
393   - that.serverConfig = serverInfo;
394   - that.visible = true;
395   - });
396   - },
397   - getWVPServerConfig: function () {
398   - let that = this;
399   - this.$axios({
400   - method: 'get',
401   - url: '/api/server/config'
402   - }).then(function (res) {
403   - console.log(res)
404   - that.wvpServerConfig = res.data.data;
405   - that.wvpVisible = true;
406   - });
407   - this.$axios({
408   - method: 'get',
409   - url: '/api/server/version'
410   - }).then(function (res) {
411   - console.log(res)
412   - that.wvpServerVersion = res.data.data;
413   - that.wvpVisible = true;
414   - });
415   - },
416   - reStartServer: function () {
417   - let that = this;
418   - this.$confirm('此操作将重启媒体服务器, 是否继续?', '提示', {
419   - confirmButtonText: '确定',
420   - cancelButtonText: '取消',
421   - type: 'warning'
422   - }).then(() => {
423   - let that = this;
424   - this.$axios({
425   - method: 'get',
426   - url: '/zlm/' + that.mediaServerChoose +'/index/api/restartServer'
427   - }).then(function (res) {
428   - that.getAllSession();
429   - if (res.data.code == 0) {
430   - that.$message({
431   - type: 'success',
432   - message: '操作完成'
433   - });
434   - }
435   - });
436   - });
437   - },
438   - deleteRow: function (index, tabledata) {
439   - let that = this;
440   - this.$confirm('此操作将断开该通信链路, 是否继续?', '提示', {
441   - confirmButtonText: '确定',
442   - cancelButtonText: '取消',
443   - type: 'warning'
444   - })
445   - .then(() => {
446   - that.deleteSession(tabledata[index].id);
447   - })
448   - .catch(() => {
449   - console.log('id:' + JSON.stringify(tabledata[index]));
450   - this.$message({
451   - type: 'info',
452   - message: '已取消删除'
453   - });
454   - });
455   - console.log(JSON.stringify(tabledata[index]));
456   - },
457   - deleteSession: function (id) {
458   - let that = this;
459   - this.$axios({
460   - method: 'get',
461   - url: '/zlm/' + that.mediaServerChoose +'/index/api/kick_session&id=' + id
462   - }).then(function (res) {
463   - that.getAllSession();
464   - that.$message({
465   - type: 'success',
466   - message: '删除成功!'
467   - });
468   - });
469   - },
470   - getNameFromKey: function(key) {
471   - let nameData = {
472   - "waitTrack": "等待编码信息",
473   - "interfaceAuthenticationExcludes": "不进行鉴权的接口",
474   - "playTimeout": "点播超时时间",
475   - "autoApplyPlay": "自动点播",
476   - "recordPushLive": "推流录像",
477   - "redisConfig": "自动配置redis",
478   - "thirdPartyGBIdReg": "stream信息正则",
479   - "savePositionHistory": "保存轨迹信息",
480   - "interfaceAuthentication": "接口鉴权",
481   - "serverId": "服务ID",
482   - "logInDatebase": "日志存储进数据库",
483   - "seniorSdp": "扩展SDP",
484   - "password": "密码",
485   - "port": "端口号",
486   - "keepaliveTimeOut": "心跳超时",
487   - "domain": "国标域",
488   - "ip": "IP地址",
489   - "monitorIp": "监听IP",
490   - "alarm": "存储报警信息",
491   - "ptzSpeed": "云台控制速度",
492   - "id": "国标ID",
493   - "registerTimeInterval": "注册间隔",
494   - "artifactId": "模块名称",
495   - "version": "版本",
496   - "project": "工程",
497   - "git_Revision": "GIT修订版本",
498   - "git_BRANCH": "GIT分支",
499   - "git_URL": "GIT地址",
500   - "build_DATE": "构建时间",
501   - "create_By": "作者",
502   - "git_Revision_SHORT": "GIT修订版本(短)",
503   - "build_Jdk": "构建用JDK",
  477 + getAllSession: function () {
  478 + let that = this;
  479 + that.allSessionData = [];
  480 + this.$axios({
  481 + method: 'get',
  482 + url: '/zlm/' + that.mediaServerChoose + '/index/api/getAllSession'
  483 + }).then(function (res) {
  484 + res.data.data.forEach(item => {
  485 + let data = {
  486 + peer_ip: item.peer_ip,
  487 + local_ip: item.local_ip,
  488 + typeid: item.typeid,
  489 + id: item.id
504 490 };
505   - console.log(key + ": " + nameData[key])
  491 + that.allSessionData.push(data);
  492 + });
  493 + });
  494 + },
  495 + getServerConfig: function () {
  496 + let that = this;
  497 + this.$axios({
  498 + method: 'get',
  499 + url: '/zlm/' + that.mediaServerChoose + '/index/api/getServerConfig'
  500 + }).then(function (res) {
  501 + let info = res.data.data[0];
  502 + let serverInfo = {}
  503 + for (let i = 0; i < Object.keys(info).length; i++) {
  504 + let key = Object.keys(info)[i];
  505 + let group = key.substring(0, key.indexOf("."))
  506 + let itemKey = key.substring(key.indexOf(".") + 1)
  507 + if (!serverInfo[group]) serverInfo[group] = {}
  508 + serverInfo[group][itemKey] = info[key]
  509 + }
506 510  
507   - if (nameData[key]) {
508   - return nameData[key]
509   - }else {
510   - return key;
  511 + that.serverConfig = serverInfo;
  512 + that.visible = true;
  513 + });
  514 + },
  515 + getWVPServerConfig: function () {
  516 + let that = this;
  517 + this.$axios({
  518 + method: 'get',
  519 + url: '/api/server/config'
  520 + }).then(function (res) {
  521 + console.log(res)
  522 + that.wvpServerConfig = res.data.data;
  523 + that.wvpVisible = true;
  524 + });
  525 + this.$axios({
  526 + method: 'get',
  527 + url: '/api/server/version'
  528 + }).then(function (res) {
  529 + console.log(res)
  530 + that.wvpServerVersion = res.data.data;
  531 + that.wvpVisible = true;
  532 + });
  533 + },
  534 + reStartServer: function () {
  535 + let that = this;
  536 + this.$confirm('此操作将重启媒体服务器, 是否继续?', '提示', {
  537 + confirmButtonText: '确定',
  538 + cancelButtonText: '取消',
  539 + type: 'warning'
  540 + }).then(() => {
  541 + let that = this;
  542 + this.$axios({
  543 + method: 'get',
  544 + url: '/zlm/' + that.mediaServerChoose + '/index/api/restartServer'
  545 + }).then(function (res) {
  546 + that.getAllSession();
  547 + if (res.data.code == 0) {
  548 + that.$message({
  549 + type: 'success',
  550 + message: '操作完成'
  551 + });
511 552 }
512   - },
513   - getMediaKeyNameFromKey: function(key) {
514   - let nameData = {
515   - "waitTrack": "等待编码信息",
516   - "interfaceAuthenticationExcludes": "不进行鉴权的接口",
517   - "playTimeout": "点播超时时间",
518   - "autoApplyPlay": "自动点播",
519   - "recordPushLive": "推流录像",
520   - "redisConfig": "自动配置redis",
521   - "thirdPartyGBIdReg": "stream信息正则",
522   - "savePositionHistory": "保存轨迹信息",
523   - "interfaceAuthentication": "接口鉴权",
524   - "serverId": "服务ID",
525   - "logInDatebase": "日志存储进数据库",
526   - "seniorSdp": "扩展SDP",
527   - "password": "密码",
528   - "port": "端口号",
529   - "keepaliveTimeOut": "心跳超时",
530   - "domain": "国标域",
531   - "ip": "IP地址",
532   - "monitorIp": "监听IP",
533   - "alarm": "存储报警信息",
534   - "ptzSpeed": "云台控制速度",
535   - "id": "国标ID",
536   - "registerTimeInterval": "注册间隔",
537   - "artifactId": "模块名称",
538   - "version": "版本",
539   - "project": "工程",
540   - "git_Revision": "GIT修订版本",
541   - "git_BRANCH": "GIT分支",
542   - "git_URL": "GIT地址",
543   - "build_DATE": "构建时间",
544   - "create_By": "作者",
545   - "git_Revision_SHORT": "GIT修订版本(短)",
546   - "build_Jdk": "构建用JDK",
547   - };
548   - console.log(key + ": " + nameData[key])
  553 + });
  554 + });
  555 + },
  556 + deleteRow: function (index, tabledata) {
  557 + let that = this;
  558 + this.$confirm('此操作将断开该通信链路, 是否继续?', '提示', {
  559 + confirmButtonText: '确定',
  560 + cancelButtonText: '取消',
  561 + type: 'warning'
  562 + })
  563 + .then(() => {
  564 + that.deleteSession(tabledata[index].id);
  565 + })
  566 + .catch(() => {
  567 + console.log('id:' + JSON.stringify(tabledata[index]));
  568 + this.$message({
  569 + type: 'info',
  570 + message: '已取消删除'
  571 + });
  572 + });
  573 + console.log(JSON.stringify(tabledata[index]));
  574 + },
  575 + deleteSession: function (id) {
  576 + let that = this;
  577 + this.$axios({
  578 + method: 'get',
  579 + url: '/zlm/' + that.mediaServerChoose + '/index/api/kick_session&id=' + id
  580 + }).then(function (res) {
  581 + that.getAllSession();
  582 + that.$message({
  583 + type: 'success',
  584 + message: '删除成功!'
  585 + });
  586 + });
  587 + },
  588 + getNameFromKey: function (key) {
  589 + let nameData = {
  590 + "waitTrack": "等待编码信息",
  591 + "interfaceAuthenticationExcludes": "不进行鉴权的接口",
  592 + "playTimeout": "点播超时时间",
  593 + "autoApplyPlay": "自动点播",
  594 + "recordPushLive": "推流录像",
  595 + "redisConfig": "自动配置redis",
  596 + "thirdPartyGBIdReg": "stream信息正则",
  597 + "savePositionHistory": "保存轨迹信息",
  598 + "interfaceAuthentication": "接口鉴权",
  599 + "serverId": "服务ID",
  600 + "logInDatebase": "日志存储进数据库",
  601 + "seniorSdp": "扩展SDP",
  602 + "password": "密码",
  603 + "port": "端口号",
  604 + "keepaliveTimeOut": "心跳超时",
  605 + "domain": "国标域",
  606 + "ip": "IP地址",
  607 + "monitorIp": "监听IP",
  608 + "alarm": "存储报警信息",
  609 + "ptzSpeed": "云台控制速度",
  610 + "id": "国标ID",
  611 + "registerTimeInterval": "注册间隔",
  612 + "artifactId": "模块名称",
  613 + "version": "版本",
  614 + "project": "工程",
  615 + "git_Revision": "GIT修订版本",
  616 + "git_BRANCH": "GIT分支",
  617 + "git_URL": "GIT地址",
  618 + "build_DATE": "构建时间",
  619 + "create_By": "作者",
  620 + "git_Revision_SHORT": "GIT修订版本(短)",
  621 + "build_Jdk": "构建用JDK",
  622 + };
  623 + console.log(key + ": " + nameData[key])
549 624  
550   - if (nameData[key]) {
551   - return nameData[key]
552   - }else {
553   - return key;
554   - }
555   - }
  625 + if (nameData[key]) {
  626 + return nameData[key]
  627 + } else {
  628 + return key;
  629 + }
  630 + },
  631 + getMediaKeyNameFromKey: function (key) {
  632 + let nameData = {
  633 + "waitTrack": "等待编码信息",
  634 + "interfaceAuthenticationExcludes": "不进行鉴权的接口",
  635 + "playTimeout": "点播超时时间",
  636 + "autoApplyPlay": "自动点播",
  637 + "recordPushLive": "推流录像",
  638 + "redisConfig": "自动配置redis",
  639 + "thirdPartyGBIdReg": "stream信息正则",
  640 + "savePositionHistory": "保存轨迹信息",
  641 + "interfaceAuthentication": "接口鉴权",
  642 + "serverId": "服务ID",
  643 + "logInDatebase": "日志存储进数据库",
  644 + "seniorSdp": "扩展SDP",
  645 + "password": "密码",
  646 + "port": "端口号",
  647 + "keepaliveTimeOut": "心跳超时",
  648 + "domain": "国标域",
  649 + "ip": "IP地址",
  650 + "monitorIp": "监听IP",
  651 + "alarm": "存储报警信息",
  652 + "ptzSpeed": "云台控制速度",
  653 + "id": "国标ID",
  654 + "registerTimeInterval": "注册间隔",
  655 + "artifactId": "模块名称",
  656 + "version": "版本",
  657 + "project": "工程",
  658 + "git_Revision": "GIT修订版本",
  659 + "git_BRANCH": "GIT分支",
  660 + "git_URL": "GIT地址",
  661 + "build_DATE": "构建时间",
  662 + "create_By": "作者",
  663 + "git_Revision_SHORT": "GIT修订版本(短)",
  664 + "build_Jdk": "构建用JDK",
  665 + };
  666 + console.log(key + ": " + nameData[key])
  667 +
  668 + if (nameData[key]) {
  669 + return nameData[key]
  670 + } else {
  671 + return key;
  672 + }
556 673 }
  674 + }
557 675 };
558 676 </script>
559 677  
560 678 <style>
561 679 #app {
562   - height: 100%;
  680 + height: 100%;
563 681 }
564 682  
565 683 .control-table {
566   - background-color: #ffffff;
567   - height: 25rem;
  684 + background-color: #ffffff;
  685 + height: 25rem;
568 686 }
569 687  
570 688 .table-c {
571   - border-right: 1px solid #dcdcdc;
572   - border-bottom: 1px solid #dcdcdc;
  689 + border-right: 1px solid #dcdcdc;
  690 + border-bottom: 1px solid #dcdcdc;
573 691 }
574 692  
575 693 .table-c td {
576   - border-left: 1px solid #dcdcdc;
577   - border-top: 1px solid #dcdcdc;
578   - padding: 0.2rem;
  694 + border-left: 1px solid #dcdcdc;
  695 + border-top: 1px solid #dcdcdc;
  696 + padding: 0.2rem;
579 697 }
580 698  
581 699 .el-table {
582   - width: 99.9% !important;
  700 + width: 99.9% !important;
583 701 }
584 702 </style>
... ...
web_src/src/components/devicePosition.vue
1 1 <template>
2 2 <div id="devicePosition" style="height: 100%">
3   - <el-container style="height: 100%">
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;">
9   - <span style="font-size: 1rem; font-weight: 500">设备定位 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span>
10   - </div>
11   - <div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;">
12   - <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">返回</el-button>
13   - <!-- <span class="demonstration">从</span> -->
14   - <el-date-picker v-model="searchFrom" type="datetime" placeholder="选择开始日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
15   - <el-date-picker v-model="searchTo" type="datetime" placeholder="选择结束日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
16   - <el-button-group>
17   - <el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">历史轨迹</el-button>
18   - <el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">最新位置</el-button>
19   - </el-button-group>
20   - <el-tag style="width: 5rem; text-align: center" size="medium">过期时间</el-tag>
21   - <el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number>
22   - <el-tag style="width: 5rem; text-align: center" size="medium">上报周期</el-tag>
23   - <el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number>
24   - <el-button-group>
25   - <el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">位置订阅</el-button>
26   - <el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">取消订阅</el-button>
27   - </el-button-group>
28   - <el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >自动刷新</el-checkbox>
29   - </div>
30   - <div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);">
31   - <div class="baidumap" id="allmap"></div>
32   - </div>
33   - </el-main>
34   - </el-container>
  3 + <div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;">
  4 + <span style="font-size: 1rem; font-weight: 500">设备定位 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span>
  5 + </div>
  6 + <div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;">
  7 + <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">返回</el-button>
  8 + <!-- <span class="demonstration">从</span> -->
  9 + <el-date-picker v-model="searchFrom" type="datetime" placeholder="选择开始日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
  10 + <el-date-picker v-model="searchTo" type="datetime" placeholder="选择结束日期时间" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
  11 + <el-button-group>
  12 + <el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">历史轨迹</el-button>
  13 + <el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">最新位置</el-button>
  14 + </el-button-group>
  15 + <el-tag style="width: 5rem; text-align: center" size="medium">过期时间</el-tag>
  16 + <el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number>
  17 + <el-tag style="width: 5rem; text-align: center" size="medium">上报周期</el-tag>
  18 + <el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number>
  19 + <el-button-group>
  20 + <el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">位置订阅</el-button>
  21 + <el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">取消订阅</el-button>
  22 + </el-button-group>
  23 + <el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >自动刷新</el-checkbox>
  24 + </div>
  25 + <div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);">
  26 + <div class="baidumap" id="allmap"></div>
  27 + </div>
35 28 </div>
36 29 </template>
37 30  
38 31 <script>
39   -import uiHeader from "./UiHeader.vue";
40   -import moment from "moment";
  32 +import uiHeader from "../layout/UiHeader.vue";
41 33 import geoTools from "./GeoConvertTools.js";
42 34 export default {
43 35 name: "devicePosition",
... ... @@ -173,7 +165,7 @@ export default {
173 165 let self = this;
174 166 this.$axios({
175 167 method: 'get',
176   - url:`/api/position/history/${this.deviceId}`,
  168 + url:`/api/position/history/${this.deviceId}`,
177 169 params: {
178 170 start: self.startTime,
179 171 end: self.endTime,
... ... @@ -259,7 +251,7 @@ export default {
259 251 },
260 252 toGBString: function (dateTime) {
261 253 return (
262   - dateTime.getFullYear() +
  254 + dateTime.getFullYear() +
263 255 "-" + this.twoDigits(dateTime.getMonth() + 1) +
264 256 "-" + this.twoDigits(dateTime.getDate()) +
265 257 "T" + this.twoDigits(dateTime.getHours()) +
... ...
web_src/src/components/dialog/catalogEdit.vue
... ... @@ -13,11 +13,24 @@
13 13 <div id="shared" style="margin-top: 1rem;margin-right: 100px;">
14 14 <el-form ref="form" :rules="rules" :model="form" label-width="140px" >
15 15 <el-form-item label="节点编号" prop="id" >
16   - <el-input v-model="form.id" :disabled="isEdit"></el-input>
  16 + <el-tooltip class="item" effect="dark" content="" placement="top-start">
  17 + <div slot="content">
  18 + 建议的类型:
  19 + <br/>
  20 + &emsp;&emsp;行政区划(可选2位/4位/6位/8位/10位数字,例如:130432,表示河北省邯郸市广平县)
  21 + <br/>
  22 + &emsp;&emsp;业务分组(第11、12、13位215,例如:34020000002150000001)
  23 + <br/>
  24 + &emsp;&emsp;虚拟组织(第11、12、13位216,例如:34020000002160000001)
  25 + </div>
  26 + <el-input v-model="form.id" :disabled="isEdit"></el-input>
  27 + </el-tooltip>
17 28 </el-form-item>
18 29 <el-form-item label="节点名称" prop="name">
19 30 <el-input v-model="form.name" clearable></el-input>
20 31 </el-form-item>
  32 +
  33 +
21 34 <el-form-item>
22 35 <div style="float: right;">
23 36 <el-button type="primary" @click="onSubmit" >确认</el-button>
... ...
web_src/src/components/dialog/deviceEdit.vue
... ... @@ -45,6 +45,9 @@
45 45 <el-form-item v-if="form.subscribeCycleForMobilePosition > 0" label="移动位置报送间隔" prop="subscribeCycleForCatalog" >
46 46 <el-input v-model="form.mobilePositionSubmissionInterval" clearable ></el-input>
47 47 </el-form-item>
  48 + <el-form-item label="其他选项">
  49 + <el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox>
  50 + </el-form-item>
48 51 <el-form-item>
49 52 <div style="float: right;">
50 53 <el-button type="primary" @click="onSubmit" >确认</el-button>
... ...
web_src/src/components/dialog/platformEdit.vue
... ... @@ -44,6 +44,9 @@
44 44 <el-form-item label="SIP认证用户名" prop="username">
45 45 <el-input v-model="platform.username"></el-input>
46 46 </el-form-item>
  47 + <el-form-item label="行政区划" prop="administrativeDivision">
  48 + <el-input v-model="platform.administrativeDivision" clearable></el-input>
  49 + </el-form-item>
47 50 <el-form-item label="SIP认证密码" prop="password">
48 51 <el-input v-model="platform.password" ></el-input>
49 52 </el-form-item>
... ... @@ -63,6 +66,18 @@
63 66 <el-option label="TCP" value="TCP"></el-option>
64 67 </el-select>
65 68 </el-form-item>
  69 + <el-form-item label="目录分组" prop="catalogGroup">
  70 + <el-select
  71 + v-model="platform.catalogGroup"
  72 + style="width: 100%"
  73 + placeholder="请选择目录分组"
  74 + >
  75 + <el-option label="1" value="1"></el-option>
  76 + <el-option label="2" value="2"></el-option>
  77 + <el-option label="4" value="4"></el-option>
  78 + <el-option label="8" value="8"></el-option>
  79 + </el-select>
  80 + </el-form-item>
66 81 <el-form-item label="字符集" prop="characterSet">
67 82 <el-select
68 83 v-model="platform.characterSet"
... ... @@ -77,6 +92,7 @@
77 92 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox>
78 93 <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>
79 94 <el-checkbox label="共享所有直播流" v-model="platform.shareAllLiveStream"></el-checkbox>
  95 + <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox>
80 96 </el-form-item>
81 97 <el-form-item>
82 98 <el-button type="primary" @click="onSubmit">{{
... ... @@ -138,6 +154,9 @@ export default {
138 154 transport: "UDP",
139 155 characterSet: "GB2312",
140 156 shareAllLiveStream: false,
  157 + startOfflinePush: false,
  158 + catalogGroup: 1,
  159 + administrativeDivision: null,
141 160 },
142 161 rules: {
143 162 name: [{ required: true, message: "请输入平台名称", trigger: "blur" }],
... ... @@ -175,6 +194,7 @@ export default {
175 194 that.platform.devicePort = res.data.devicePort;
176 195 that.platform.username = res.data.username;
177 196 that.platform.password = res.data.password;
  197 + that.platform.administrativeDivision = res.data.username.substr(0, 6);
178 198 }).catch(function (error) {
179 199 console.log(error);
180 200 });
... ... @@ -199,6 +219,9 @@ export default {
199 219 this.platform.characterSet = platform.characterSet;
200 220 this.platform.shareAllLiveStream = platform.shareAllLiveStream;
201 221 this.platform.catalogId = platform.catalogId;
  222 + this.platform.startOfflinePush = platform.startOfflinePush;
  223 + this.platform.catalogGroup = platform.catalogGroup;
  224 + this.platform.administrativeDivision = platform.administrativeDivision;
202 225 this.onSubmit_text = "保存";
203 226 this.saveUrl = "/api/platform/save";
204 227 }
... ... @@ -213,6 +236,10 @@ export default {
213 236 deviceGBIdChange: function () {
214 237  
215 238 this.platform.username = this.platform.deviceGBId ;
  239 + if (this.platform.administrativeDivision == null) {
  240 + this.platform.administrativeDivision = this.platform.deviceGBId.substr(0, 6);
  241 + }
  242 +
216 243 },
217 244 onSubmit: function () {
218 245 var that = this;
... ... @@ -253,6 +280,7 @@ export default {
253 280 rtcp: false,
254 281 name: null,
255 282 serverGBId: null,
  283 + administrativeDivision: null,
256 284 serverGBDomain: null,
257 285 serverIP: null,
258 286 serverPort: null,
... ... @@ -266,6 +294,8 @@ export default {
266 294 transport: "UDP",
267 295 characterSet: "GB2312",
268 296 shareAllLiveStream: false,
  297 + startOfflinePush: false,
  298 + catalogGroup: 1,
269 299 }
270 300 },
271 301 deviceGBIdExit: async function (deviceGbId) {
... ...
web_src/src/components/live.vue
1 1 <template>
2   - <div id="devicePosition" style="height: 100%">
3   - <el-container style="height: 100%">
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-container v-loading="loading" element-loading-text="拼命加载中">
8   - <el-aside width="300px" style="background-color: #ffffff">
9   - <div style="text-align: center;padding-top: 20px;">设备列表</div>
10   - <el-menu v-loading="loading">
11   - <el-submenu v-for="device in deviceList" :key="device.deviceId" :index="device.deviceId" @click="sendDevicePush(item)">
12   - <template slot="title" >
13   - <i class="el-icon-location-outline"></i>
14   - {{device.name}}
15   - </template>
16   - <ChannelTree :device="device" @sendDevicePush="sendDevicePush"></ChannelTree>
17   - </el-submenu>
18   - </el-menu>
19   - </el-aside>
20   - <el-container>
21   - <!-- <LivePlay></LivePlay> -->
22   - <el-header height="40px" style="text-align: left;font-size: 17px;line-height: 40px;">
23   - 分屏:
24   - <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/>
25   - <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/>
26   - <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/>
27   - </el-header>
28   - <el-main>
29   - <div style="width: 100%;height: calc( 100vh - 110px );display: flex;flex-wrap: wrap;background-color: #000;">
30   - <div v-for="i in spilt" :key="i" class="play-box"
31   - :style="liveStyle" :class="{redborder:playerIdx == (i-1)}"
32   - @click="playerIdx = (i-1)"
33   - >
34   - <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div>
35   - <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true"
36   - :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player>
37   - <!-- <player v-else ref="'player'+i" :idx="'player'+i" :visible.sync="showVideoDialog" :videoUrl="videoUrl[i-1]" :height="true" :hasAudio="hasAudio" fluent autoplay live ></player> -->
38   - </div>
39   - </div>
40   - </el-main>
41   - </el-container>
  2 + <div id="devicePosition" style="height: 100%;width: 100%">
  3 + <el-container v-loading="loading" element-loading-text="拼命加载中">
  4 + <el-aside width="300px" style="background-color: #ffffff">
  5 + <div style="text-align: center;padding-top: 20px;">设备列表</div>
  6 + <el-menu v-loading="loading">
  7 + <el-submenu v-for="device in deviceList" :key="device.deviceId" :index="device.deviceId" @click="sendDevicePush(item)">
  8 + <template slot="title" >
  9 + <i class="el-icon-location-outline"></i>
  10 + {{device.name}}
  11 + </template>
  12 + <ChannelTree :device="device" @sendDevicePush="sendDevicePush"></ChannelTree>
  13 + </el-submenu>
  14 + </el-menu>
  15 + </el-aside>
  16 + <el-container>
  17 + <!-- <LivePlay></LivePlay> -->
  18 + <el-header height="40px" style="text-align: left;font-size: 17px;line-height: 40px;">
  19 + 分屏:
  20 + <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/>
  21 + <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/>
  22 + <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/>
  23 + </el-header>
  24 + <el-main>
  25 + <div style="width: 100%;height: calc( 100vh - 150px );display: flex;flex-wrap: wrap;background-color: #000;">
  26 + <div v-for="i in spilt" :key="i" class="play-box"
  27 + :style="liveStyle" :class="{redborder:playerIdx == (i-1)}"
  28 + @click="playerIdx = (i-1)"
  29 + >
  30 + <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div>
  31 + <player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true"
  32 + :containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player>
  33 + <!-- <player v-else ref="'player'+i" :idx="'player'+i" :visible.sync="showVideoDialog" :videoUrl="videoUrl[i-1]" :height="true" :hasAudio="hasAudio" fluent autoplay live ></player> -->
  34 + </div>
  35 + </div>
  36 + </el-main>
42 37 </el-container>
43 38 </el-container>
44 39 </div>
45 40 </template>
46 41  
47 42 <script>
48   - import uiHeader from "./UiHeader.vue";
  43 + import uiHeader from "../layout/UiHeader.vue";
49 44 import player from './dialog/jessibuca.vue'
50 45 import ChannelTree from './channelTree.vue'
51 46  
... ...
web_src/src/components/setting/Media.vue
1 1 <template>
2   - <div id="SettingForMedia">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span style="font-size: 1rem; font-weight: bold;">媒体服务</span>
10   - </div>
11   - <div style="width: 60%; margin:0 auto; background-color: #FFFFFF; position: relative; padding: 5rem 6.5rem; text-align: left;font-size: 14px; max-width: 400px">
12   - <el-form ref="form" :rules="rules" :model="form" label-width="140px">
13   - <el-form-item label="IP" prop="IP">
14   - <el-input v-model="form.IP" clearable></el-input>
15   - </el-form-item>
16   - <el-form-item label="公网IP" prop="wanIp">
17   - <el-input v-model="form.wanIp" clearable></el-input>
18   - </el-form-item>
19   - <el-form-item label="HOOK IP" prop="hookIp">
20   - <el-input v-model="form.hookIp" clearable></el-input>
21   - </el-form-item>
22   - <el-form-item label="HTTP端口" >
23   - <el-input v-model.number="form.httpPort" clearable></el-input>
24   - </el-form-item>
25   - <el-form-item label="HTTP SSL端口" >
26   - <el-input v-model.number="form.httpSSlPort" clearable></el-input>
27   - </el-form-item>
28   - <el-form-item label="RTMP端口" >
29   - <el-input v-model.number="form.rtmpPort" clearable></el-input>
30   - </el-form-item>
31   - <el-form-item label="RTMP SSL端口" >
32   - <el-input v-model.number="form.rtmpSSlPort" clearable></el-input>
33   - </el-form-item>
34   - <el-form-item label="RTSP端口" >
35   - <el-input v-model.number="form.rtspPort" clearable></el-input>
36   - </el-form-item>
37   - <el-form-item label="RTSP SSL端口" >
38   - <el-input v-model.number="form.rtspSSLPort" clearable></el-input>
39   - </el-form-item>
40   - <el-form-item label="RTP端口" >
41   - <el-input v-model.number="form.rtpProxyPort" clearable></el-input>
42   - </el-form-item>
43   - <el-form-item label="自动点播" >
44   - <el-switch v-model="form.autoApplyPlay"></el-switch>
45   - </el-form-item>
46   - <el-form-item label="接口密钥" prop="secret">
47   - <el-input v-model="form.secret" clearable></el-input>
48   - </el-form-item>
49   - <el-form-item label="无人观看触发时长" >
50   - <el-input v-model.number="form.streamNoneReaderDelayMS" clearable></el-input>
51   - </el-form-item>
52   - <el-form-item label="自动配置" >
53   - <el-switch v-model="form.autoConfig"></el-switch>
54   - </el-form-item>
55   - <el-form-item label="使用多端口" >
56   - <el-switch v-model="form.rtp.enable"></el-switch>
57   - </el-form-item>
58   - <el-form-item label="端口范围" >
59   - <el-input v-model.number="form.rtp.portRange" clearable></el-input>
60   - </el-form-item>
61   - <el-form-item label="DOCKER智能识别">
62   - <el-input type="textarea" v-model="dockerStr"></el-input>
63   - </el-form-item>
  2 + <div id="SettingForMedia" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">媒体服务</div>
  5 + </div>
  6 + <div
  7 + style="width: 60%; margin:0 auto; background-color: #FFFFFF; position: relative; padding: 5rem 6.5rem; text-align: left;font-size: 14px; max-width: 400px">
  8 + <el-form ref="form" :rules="rules" :model="form" label-width="140px">
  9 + <el-form-item label="IP" prop="IP">
  10 + <el-input v-model="form.IP" clearable></el-input>
  11 + </el-form-item>
  12 + <el-form-item label="公网IP" prop="wanIp">
  13 + <el-input v-model="form.wanIp" clearable></el-input>
  14 + </el-form-item>
  15 + <el-form-item label="HOOK IP" prop="hookIp">
  16 + <el-input v-model="form.hookIp" clearable></el-input>
  17 + </el-form-item>
  18 + <el-form-item label="HTTP端口">
  19 + <el-input v-model.number="form.httpPort" clearable></el-input>
  20 + </el-form-item>
  21 + <el-form-item label="HTTP SSL端口">
  22 + <el-input v-model.number="form.httpSSlPort" clearable></el-input>
  23 + </el-form-item>
  24 + <el-form-item label="RTMP端口">
  25 + <el-input v-model.number="form.rtmpPort" clearable></el-input>
  26 + </el-form-item>
  27 + <el-form-item label="RTMP SSL端口">
  28 + <el-input v-model.number="form.rtmpSSlPort" clearable></el-input>
  29 + </el-form-item>
  30 + <el-form-item label="RTSP端口">
  31 + <el-input v-model.number="form.rtspPort" clearable></el-input>
  32 + </el-form-item>
  33 + <el-form-item label="RTSP SSL端口">
  34 + <el-input v-model.number="form.rtspSSLPort" clearable></el-input>
  35 + </el-form-item>
  36 + <el-form-item label="RTP端口">
  37 + <el-input v-model.number="form.rtpProxyPort" clearable></el-input>
  38 + </el-form-item>
  39 + <el-form-item label="自动点播">
  40 + <el-switch v-model="form.autoApplyPlay"></el-switch>
  41 + </el-form-item>
  42 + <el-form-item label="接口密钥" prop="secret">
  43 + <el-input v-model="form.secret" clearable></el-input>
  44 + </el-form-item>
  45 + <el-form-item label="无人观看触发时长">
  46 + <el-input v-model.number="form.streamNoneReaderDelayMS" clearable></el-input>
  47 + </el-form-item>
  48 + <el-form-item label="自动配置">
  49 + <el-switch v-model="form.autoConfig"></el-switch>
  50 + </el-form-item>
  51 + <el-form-item label="使用多端口">
  52 + <el-switch v-model="form.rtp.enable"></el-switch>
  53 + </el-form-item>
  54 + <el-form-item label="端口范围">
  55 + <el-input v-model.number="form.rtp.portRange" clearable></el-input>
  56 + </el-form-item>
  57 + <el-form-item label="DOCKER智能识别">
  58 + <el-input type="textarea" v-model="dockerStr"></el-input>
  59 + </el-form-item>
64 60  
65   - <el-form-item>
66   - <div style="float: right;">
67   - <el-button type="primary" @click="onSubmit">保存</el-button>
68   -<!-- <el-button @click="close">取消</el-button>-->
69   - </div>
  61 + <el-form-item>
  62 + <div style="float: right;">
  63 + <el-button type="primary" @click="onSubmit">保存</el-button>
  64 + <!-- <el-button @click="close">取消</el-button>-->
  65 + </div>
70 66  
71   - </el-form-item>
72   - </el-form>
73   - </div>
74   -
75   -
76   - </el-main>
77   - </el-container>
  67 + </el-form-item>
  68 + </el-form>
  69 + </div>
78 70 </div>
79 71 </template>
80 72  
81 73 <script>
82   -import uiHeader from '../UiHeader.vue'
  74 +import uiHeader from '../../layout/UiHeader.vue'
  75 +
83 76 export default {
84 77 name: "SettingForMedia",
85 78 components: {
... ... @@ -107,9 +100,9 @@ export default {
107 100 },
108 101  
109 102 rules: {
110   - IP: [{ required: true, message: "请输入名称", trigger: "blur" }],
111   - wanIp: [{ required: false, message: "请输入应用名", trigger: "blur" }],
112   - hookIp: [{ required: false, message: "请输入流ID", trigger: "blur" }],
  103 + IP: [{required: true, message: "请输入名称", trigger: "blur"}],
  104 + wanIp: [{required: false, message: "请输入应用名", trigger: "blur"}],
  105 + hookIp: [{required: false, message: "请输入流ID", trigger: "blur"}],
113 106 },
114 107 }
115 108 }
... ...
web_src/src/components/setting/Sip.vue
1 1 <template>
2   - <div id="SettingForSip">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span style="font-size: 1rem; font-weight: bold;">国标服务</span>
10   - </div>
11   - <div style="width: 60%; margin:0 auto; background-color: #FFFFFF; position: relative; padding: 5rem 6.5rem; text-align: left;font-size: 14px; max-width: 400px">
12   - <el-form ref="form" :rules="rules" :model="form" label-width="140px">
13   - <el-form-item label="ip" prop="ip">
14   - <el-input v-model="form.ip" clearable></el-input>
15   - </el-form-item>
16   - <el-form-item label="端口" prop="port">
17   - <el-input v-model.number="form.port" clearable></el-input>
18   - </el-form-item>
19   - <el-form-item label="域" prop="domain">
20   - <el-input v-model="form.domain" clearable></el-input>
21   - </el-form-item>
22   - <el-form-item label="id" prop="id">
23   - <el-input v-model="form.id" clearable></el-input>
24   - </el-form-item>
25   - <el-form-item label="密码" prop="password">
26   - <el-input v-model="form.password" clearable></el-input>
27   - </el-form-item>
  2 + <div id="SettingForSip" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">国标服务</div>
  5 + </div>
  6 + <div
  7 + style="width: 60%; margin:0 auto; background-color: #FFFFFF; position: relative; padding: 5rem 6.5rem; text-align: left;font-size: 14px; max-width: 400px">
  8 + <el-form ref="form" :rules="rules" :model="form" label-width="140px">
  9 + <el-form-item label="ip" prop="ip">
  10 + <el-input v-model="form.ip" clearable></el-input>
  11 + </el-form-item>
  12 + <el-form-item label="端口" prop="port">
  13 + <el-input v-model.number="form.port" clearable></el-input>
  14 + </el-form-item>
  15 + <el-form-item label="域" prop="domain">
  16 + <el-input v-model="form.domain" clearable></el-input>
  17 + </el-form-item>
  18 + <el-form-item label="id" prop="id">
  19 + <el-input v-model="form.id" clearable></el-input>
  20 + </el-form-item>
  21 + <el-form-item label="密码" prop="password">
  22 + <el-input v-model="form.password" clearable></el-input>
  23 + </el-form-item>
28 24  
29 25  
30   - <el-form-item>
31   - <div style="float: right;">
32   - <el-button type="primary" @click="onSubmit">保存</el-button>
33   -<!-- <el-button @click="close">取消</el-button>-->
34   - </div>
  26 + <el-form-item>
  27 + <div style="float: right;">
  28 + <el-button type="primary" @click="onSubmit">保存</el-button>
  29 + <!-- <el-button @click="close">取消</el-button>-->
  30 + </div>
35 31  
36   - </el-form-item>
37   - </el-form>
38   - </div>
39   -
40   -
41   - </el-main>
42   - </el-container>
  32 + </el-form-item>
  33 + </el-form>
  34 + </div>
43 35 </div>
44 36 </template>
45 37  
46 38 <script>
47   -import uiHeader from '../UiHeader.vue'
  39 +import uiHeader from '../../layout/UiHeader.vue'
  40 +
48 41 export default {
49 42 name: "SettingForSip",
50 43 components: {
... ... @@ -61,11 +54,11 @@ export default {
61 54 },
62 55  
63 56 rules: {
64   - ip: [{ required: true, message: "请输入名称", trigger: "blur" }],
65   - port: [{ required: true, message: "请输入应用名", trigger: "blur" }],
66   - domain: [{ required: true, message: "请输入流ID", trigger: "blur" }],
67   - id: [{ required: true, message: "请输入国标编码", trigger: "blur" }],
68   - password: [{ required: true, message: "请输入国标编码", trigger: "blur" }],
  57 + ip: [{required: true, message: "请输入名称", trigger: "blur"}],
  58 + port: [{required: true, message: "请输入应用名", trigger: "blur"}],
  59 + domain: [{required: true, message: "请输入流ID", trigger: "blur"}],
  60 + id: [{required: true, message: "请输入国标编码", trigger: "blur"}],
  61 + password: [{required: true, message: "请输入国标编码", trigger: "blur"}],
69 62 },
70 63 }
71 64 }
... ...
web_src/src/components/setting/Web.vue
1 1 <template>
2   - <div id="SettingForWeb">
3   - <el-container>
4   - <el-header>
5   - <uiHeader></uiHeader>
6   - </el-header>
7   - <el-main>
8   - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9   - <span style="font-size: 1rem; font-weight: bold;">WEB服务</span>
  2 + <div id="SettingForWeb" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">WEB服务</div>
10 5 </div>
11 6 <div style="width: 60%; margin:0 auto; background-color: #FFFFFF; position: relative; padding: 5rem 6.5rem; text-align: left;font-size: 14px; max-width: 400px">
12 7 <el-form ref="form" :rules="rules" :model="form" label-width="140px">
... ... @@ -41,15 +36,11 @@
41 36 </el-form-item>
42 37 </el-form>
43 38 </div>
44   -
45   -
46   - </el-main>
47   - </el-container>
48 39 </div>
49 40 </template>
50 41  
51 42 <script>
52   -import uiHeader from '../UiHeader.vue'
  43 +import uiHeader from '../../layout/UiHeader.vue'
53 44 export default {
54 45 name: "SettingForWeb",
55 46 components: {
... ...
web_src/src/components/UiHeader.vue renamed to web_src/src/layout/UiHeader.vue
1 1 <template>
2   - <div id="UiHeader">
3   - <el-menu router :default-active="activeIndex" menu-trigger="click" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" mode="horizontal">
4   - <el-menu-item index="/">控制台</el-menu-item>
5   - <el-menu-item index="/live">实时监控</el-menu-item>
6   - <el-menu-item index="/deviceList">国标设备</el-menu-item>
7   - <el-menu-item index="/pushVideoList">推流列表</el-menu-item>
8   - <el-menu-item index="/streamProxyList">拉流代理</el-menu-item>
9   - <el-menu-item index="/cloudRecord">云端录像</el-menu-item>
10   - <el-menu-item index="/mediaServerManger">节点管理</el-menu-item>
11   - <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
12   - <el-menu-item @click="openDoc">在线文档</el-menu-item>
13   -<!-- <el-submenu index="/setting">-->
14   -<!-- <template slot="title">系统设置</template>-->
15   -<!-- <el-menu-item index="/setting/web">WEB服务</el-menu-item>-->
16   -<!-- <el-menu-item index="/setting/sip">国标服务</el-menu-item>-->
17   -<!-- <el-menu-item index="/setting/media">媒体服务</el-menu-item>-->
18   -<!-- </el-submenu>-->
19   - <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="alarmNotifyChannge"></el-switch>
20   -<!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>-->
21   - <el-submenu index="" style="float: right;" >
22   - <template slot="title">欢迎,{{this.$cookies.get("session").username}}</template>
23   - <el-menu-item @click="changePassword">修改密码</el-menu-item>
24   - <el-menu-item @click="loginout">注销</el-menu-item>
25   - </el-submenu>
26   - </el-menu>
  2 + <div id="UiHeader">
  3 + <el-menu router :default-active="activeIndex" menu-trigger="click" background-color="#545c64" text-color="#fff"
  4 + active-text-color="#ffd04b" mode="horizontal">
  5 + <el-menu-item index="/control">控制台</el-menu-item>
  6 + <el-menu-item index="/live">实时监控</el-menu-item>
  7 + <el-menu-item index="/deviceList">国标设备</el-menu-item>
  8 + <el-menu-item index="/pushVideoList">推流列表</el-menu-item>
  9 + <el-menu-item index="/streamProxyList">拉流代理</el-menu-item>
  10 + <el-menu-item index="/cloudRecord">云端录像</el-menu-item>
  11 + <el-menu-item index="/mediaServerManger">节点管理</el-menu-item>
  12 + <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
  13 + <el-menu-item @click="openDoc">在线文档</el-menu-item>
  14 + <!-- <el-submenu index="/setting">-->
  15 + <!-- <template slot="title">系统设置</template>-->
  16 + <!-- <el-menu-item index="/setting/web">WEB服务</el-menu-item>-->
  17 + <!-- <el-menu-item index="/setting/sip">国标服务</el-menu-item>-->
  18 + <!-- <el-menu-item index="/setting/media">媒体服务</el-menu-item>-->
  19 + <!-- </el-submenu>-->
  20 + <el-switch v-model="alarmNotify" active-text="报警信息推送" @change="alarmNotifyChannge"></el-switch>
  21 + <!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>-->
  22 + <el-submenu index="" style="float: right;">
  23 + <template slot="title">欢迎,{{ this.$cookies.get("session").username }}</template>
  24 + <el-menu-item @click="changePassword">修改密码</el-menu-item>
  25 + <el-menu-item @click="loginout">注销</el-menu-item>
  26 + </el-submenu>
  27 + </el-menu>
27 28 <changePasswordDialog ref="changePasswordDialog"></changePasswordDialog>
28   - </div>
  29 + </div>
29 30 </template>
30 31  
31 32 <script>
32 33  
33   -import changePasswordDialog from './dialog/changePassword.vue'
  34 +import changePasswordDialog from '../components/dialog/changePassword.vue'
  35 +
34 36 export default {
35   - name: "UiHeader",
36   - components: { Notification, changePasswordDialog },
37   - data() {
38   - return {
39   - alarmNotify: false,
40   - sseSource: null,
41   - activeIndex: this.$route.path,
42   - };
43   - },
44   - created(){
45   - if (this.$route.path.startsWith("/channelList")){
46   - this.activeIndex = "/deviceList"
47   - }
  37 + name: "UiHeader",
  38 + components: {Notification, changePasswordDialog},
  39 + data() {
  40 + return {
  41 + alarmNotify: false,
  42 + sseSource: null,
  43 + activeIndex: this.$route.path,
  44 + };
  45 + },
  46 + created() {
  47 + if (this.$route.path.startsWith("/channelList")) {
  48 + this.activeIndex = "/deviceList"
  49 + }
48 50  
  51 + },
  52 + mounted() {
  53 + window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
  54 + // window.addEventListener('unload', e => this.unloadHandler(e))
  55 + this.alarmNotify = this.getAlarmSwitchStatus() === "true";
  56 + this.sseControl();
  57 + },
  58 + methods: {
  59 + loginout() {
  60 + this.$axios({
  61 + method: 'get',
  62 + url: "/api/user/logout"
  63 + }).then((res) => {
  64 + // 删除cookie,回到登录页面
  65 + this.$cookies.remove("session");
  66 + this.$router.push('/login');
  67 + this.sseSource.close();
  68 + }).catch((error) => {
  69 + console.error("登出失败")
  70 + console.error(error)
  71 + });
  72 + },
  73 + changePassword() {
  74 + this.$refs.changePasswordDialog.openDialog()
49 75 },
50   - mounted() {
51   - window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
52   - // window.addEventListener('unload', e => this.unloadHandler(e))
53   - this.alarmNotify = this.getAlarmSwitchStatus() === "true";
54   - this.sseControl();
  76 + openDoc() {
  77 + console.log(process.env.BASE_API)
  78 + window.open(!!process.env.BASE_API ? process.env.BASE_API + "/doc.html" : "/doc.html")
55 79 },
56   - methods:{
57   - loginout(){
58   - this.$axios({
59   - method: 'get',
60   - url:"/api/user/logout"
61   - }).then((res)=> {
62   - // 删除cookie,回到登录页面
63   - this.$cookies.remove("session");
64   - this.$router.push('/login');
65   - this.sseSource.close();
66   - }).catch((error)=> {
67   - console.error("登出失败")
68   - console.error(error)
  80 + beforeunloadHandler() {
  81 + this.sseSource.close();
  82 + },
  83 + alarmNotifyChannge() {
  84 + this.setAlarmSwitchStatus()
  85 + this.sseControl()
  86 + },
  87 + sseControl() {
  88 + let that = this;
  89 + if (this.alarmNotify) {
  90 + console.log("申请SSE推送API调用,浏览器ID: " + this.$browserId);
  91 + this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId);
  92 + this.sseSource.addEventListener('message', function (evt) {
  93 + that.$notify({
  94 + title: '收到报警信息',
  95 + dangerouslyUseHTMLString: true,
  96 + message: evt.data,
  97 + type: 'warning'
69 98 });
70   - },
71   - changePassword(){
72   - this.$refs.changePasswordDialog.openDialog()
73   - },
74   - openDoc(){
75   - console.log(process.env.BASE_API)
76   - window.open( !!process.env.BASE_API? process.env.BASE_API + "/doc.html": "/doc.html")
77   - },
78   - beforeunloadHandler() {
79   - this.sseSource.close();
80   - },
81   - alarmNotifyChannge(){
82   - this.setAlarmSwitchStatus()
83   - this.sseControl()
84   - },
85   - sseControl() {
86   - let that = this;
87   - if (this.alarmNotify) {
88   - console.log("申请SSE推送API调用,浏览器ID: " + this.$browserId);
89   - this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId);
90   - this.sseSource.addEventListener('message', function(evt) {
91   - that.$notify({
92   - title: '收到报警信息',
93   - dangerouslyUseHTMLString: true,
94   - message: evt.data,
95   - type: 'warning'
96   - });
97   - console.log("收到信息:" + evt.data);
98   - });
99   - this.sseSource.addEventListener('open', function(e) {
100   - console.log("SSE连接打开.");
101   - }, false);
102   - this.sseSource.addEventListener('error', function(e) {
103   - if (e.target.readyState == EventSource.CLOSED) {
104   - console.log("SSE连接关闭");
105   - } else {
106   - console.log(e.target.readyState);
107   - }
108   - }, false);
109   - } else {
110   - if (this.sseSource != null) {
111   - this.sseSource.removeEventListener('open', null);
112   - this.sseSource.removeEventListener('message', null);
113   - this.sseSource.removeEventListener('error', null);
114   - this.sseSource.close();
115   - }
116   -
117   - }
118   - },
119   - getAlarmSwitchStatus(){
120   - if (localStorage.getItem("alarmSwitchStatus") == null) {
121   - localStorage.setItem("alarmSwitchStatus", false);
  99 + console.log("收到信息:" + evt.data);
  100 + });
  101 + this.sseSource.addEventListener('open', function (e) {
  102 + console.log("SSE连接打开.");
  103 + }, false);
  104 + this.sseSource.addEventListener('error', function (e) {
  105 + if (e.target.readyState == EventSource.CLOSED) {
  106 + console.log("SSE连接关闭");
  107 + } else {
  108 + console.log(e.target.readyState);
122 109 }
123   - return localStorage.getItem("alarmSwitchStatus");
124   - },
125   - setAlarmSwitchStatus(){
126   - localStorage.setItem("alarmSwitchStatus", this.alarmNotify);
127   - }
128   - },
129   - destroyed() {
130   - window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
  110 + }, false);
  111 + } else {
131 112 if (this.sseSource != null) {
132 113 this.sseSource.removeEventListener('open', null);
133 114 this.sseSource.removeEventListener('message', null);
134 115 this.sseSource.removeEventListener('error', null);
135 116 this.sseSource.close();
136 117 }
  118 +
  119 + }
  120 + },
  121 + getAlarmSwitchStatus() {
  122 + if (localStorage.getItem("alarmSwitchStatus") == null) {
  123 + localStorage.setItem("alarmSwitchStatus", false);
  124 + }
  125 + return localStorage.getItem("alarmSwitchStatus");
137 126 },
  127 + setAlarmSwitchStatus() {
  128 + localStorage.setItem("alarmSwitchStatus", this.alarmNotify);
  129 + }
  130 + },
  131 + destroyed() {
  132 + window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
  133 + if (this.sseSource != null) {
  134 + this.sseSource.removeEventListener('open', null);
  135 + this.sseSource.removeEventListener('message', null);
  136 + this.sseSource.removeEventListener('error', null);
  137 + this.sseSource.close();
  138 + }
  139 + },
138 140  
139   - }
  141 +}
140 142  
141 143 </script>
  144 +<style>
  145 +#UiHeader .el-switch__label {
  146 + color: white;
  147 +}
  148 +#UiHeader .el-switch__label.is-active{
  149 + color: #409EFF;
  150 +}
  151 +</style>
... ...
web_src/src/layout/index.vue 0 → 100644
  1 +<template>
  2 + <el-container style="height: 100%">
  3 + <el-header>
  4 + <ui-header/>
  5 + </el-header>
  6 + <el-main>
  7 + <el-container>
  8 + <transition name="fade">
  9 + <router-view></router-view>
  10 + </transition>
  11 + </el-container>
  12 + </el-main>
  13 + </el-container>
  14 +</template>
  15 +
  16 +<script>
  17 +import uiHeader from "./UiHeader.vue";
  18 +
  19 +export default {
  20 + name: "index",
  21 + components: {
  22 + uiHeader
  23 + },
  24 +}
  25 +</script>
  26 +<style>
  27 +/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
  28 +::-webkit-scrollbar {
  29 + width: 8px;
  30 + height: 8px;
  31 +}
  32 +
  33 +/*定义滚动条轨道 内阴影+圆角*/
  34 +::-webkit-scrollbar-track {
  35 + border-radius: 4px;
  36 + background-color: #F5F5F5;
  37 +}
  38 +
  39 +/*定义滑块 内阴影+圆角*/
  40 +::-webkit-scrollbar-thumb {
  41 + border-radius: 4px;
  42 + background-color: #c8c8c8;
  43 + box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
  44 + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
  45 +}
  46 +
  47 +/*定义标题栏*/
  48 +.page-header {
  49 + background-color: #FFFFFF;
  50 + margin-bottom: 1rem;
  51 + padding: 0.5rem;
  52 + display: flex;
  53 + justify-content: space-between;
  54 + align-items: center;
  55 +}
  56 +
  57 +.page-title {
  58 + font-weight: bold;
  59 + text-align: left;
  60 +}
  61 +
  62 +.page-header-btn {
  63 + text-align: right;
  64 +}
  65 +</style>
  66 +<style scoped>
  67 +.el-main {
  68 + margin: 0;
  69 +}
  70 +
  71 +.fade-enter {
  72 + visibility: hidden;
  73 + opacity: 0;
  74 +}
  75 +
  76 +.fade-leave-to {
  77 + display: none;
  78 +}
  79 +
  80 +.fade-enter-active,
  81 +.fade-leave-active {
  82 + transition: opacity .5s ease;
  83 +}
  84 +
  85 +.fade-enter-to,
  86 +.fade-leave {
  87 + visibility: visible;
  88 + opacity: 1;
  89 +}
  90 +</style>
... ...
web_src/src/router/index.js
1 1 import Vue from 'vue'
2 2 import VueRouter from 'vue-router'
  3 +import Layout from "../layout/index.vue"
3 4  
4 5 import control from '../components/control.vue'
5 6 import deviceList from '../components/DeviceList.vue'
... ... @@ -32,78 +33,86 @@ export default new VueRouter({
32 33 routes: [
33 34 {
34 35 path: '/',
35   - component: control,
36   - },
37   - {
38   - path: '/live',
39   - component: live,
40   - },
41   - {
42   - path: '/deviceList',
43   - component: deviceList,
44   - },
45   - {
46   - path: '/pushVideoList',
47   - component: pushVideoList,
48   - },
49   - {
50   - path: '/streamProxyList',
51   - component: streamProxyList,
  36 + name: 'home',
  37 + component: Layout,
  38 + redirect: '/control',
  39 + children: [
  40 + {
  41 + path: '/control',
  42 + component: control,
  43 + },
  44 + {
  45 + path: '/live',
  46 + component: live,
  47 + },
  48 + {
  49 + path: '/deviceList',
  50 + component: deviceList,
  51 + },
  52 + {
  53 + path: '/pushVideoList',
  54 + component: pushVideoList,
  55 + },
  56 + {
  57 + path: '/streamProxyList',
  58 + component: streamProxyList,
  59 + },
  60 + {
  61 + path: '/channelList/:deviceId/:parentChannelId/:count/:page',
  62 + name: 'channelList',
  63 + component: channelList,
  64 + },
  65 + {
  66 + path: '/parentPlatformList/:count/:page',
  67 + name: 'parentPlatformList',
  68 + component: parentPlatformList,
  69 + },
  70 + {
  71 + path: '/devicePosition/:deviceId/:parentChannelId/:count/:page',
  72 + name: 'devicePosition',
  73 + component: devicePosition,
  74 + },
  75 + {
  76 + path: '/cloudRecord',
  77 + name: 'cloudRecord',
  78 + component: cloudRecord,
  79 + },
  80 + {
  81 + path: '/mediaServerManger',
  82 + name: 'mediaServerManger',
  83 + component: mediaServerManger,
  84 + },
  85 + {
  86 + path: '/setting/web',
  87 + name: 'web',
  88 + component: web,
  89 + },
  90 + {
  91 + path: '/setting/sip',
  92 + name: 'sip',
  93 + component: sip,
  94 + },
  95 + {
  96 + path: '/setting/media',
  97 + name: 'media',
  98 + component: media,
  99 + },
  100 + {
  101 + path: '/play/wasm/:url',
  102 + name: 'wasmPlayer',
  103 + component: wasmPlayer,
  104 + },
  105 + {
  106 + path: '/play/rtc/:url',
  107 + name: 'rtcPlayer',
  108 + component: rtcPlayer,
  109 + },
  110 + ]
52 111 },
53 112 {
54 113 path: '/login',
55 114 name: '登录',
56 115 component: login,
57 116 },
58   - {
59   - path: '/channelList/:deviceId/:parentChannelId/:count/:page',
60   - name: 'channelList',
61   - component: channelList,
62   - },
63   - {
64   - path: '/parentPlatformList/:count/:page',
65   - name: 'parentPlatformList',
66   - component: parentPlatformList,
67   - },
68   - {
69   - path: '/devicePosition/:deviceId/:parentChannelId/:count/:page',
70   - name: 'devicePosition',
71   - component: devicePosition,
72   - },
73   - {
74   - path: '/cloudRecord',
75   - name: 'cloudRecord',
76   - component: cloudRecord,
77   - },
78   - {
79   - path: '/mediaServerManger',
80   - name: 'mediaServerManger',
81   - component: mediaServerManger,
82   - },
83   - {
84   - path: '/setting/web',
85   - name: 'web',
86   - component: web,
87   - },
88   - {
89   - path: '/setting/sip',
90   - name: 'sip',
91   - component: sip,
92   - },
93   - {
94   - path: '/setting/media',
95   - name: 'media',
96   - component: media,
97   - },
98   - {
99   - path: '/play/wasm/:url',
100   - name: 'wasmPlayer',
101   - component: wasmPlayer,
102   - },
103   - {
104   - path: '/play/rtc/:url',
105   - name: 'rtcPlayer',
106   - component: rtcPlayer,
107   - },
108 117 ]
109 118 })
... ...