Commit 3ffe2050827482ba83a1c15afbf346275be86187

Authored by 648540858
1 parent 95d36770

首页改造,完成cpu,内存,网络图

src/main/java/com/genersoft/iot/vmp/common/SystemAllInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.common;
  2 +
  3 +import java.util.List;
  4 +
  5 +public class SystemAllInfo {
  6 +
  7 + private List<Object> cpu;
  8 + private List<Object> mem;
  9 + private List<Object> net;
  10 +
  11 + public List<Object> getCpu() {
  12 + return cpu;
  13 + }
  14 +
  15 + public void setCpu(List<Object> cpu) {
  16 + this.cpu = cpu;
  17 + }
  18 +
  19 + public List<Object> getMem() {
  20 + return mem;
  21 + }
  22 +
  23 + public void setMem(List<Object> mem) {
  24 + this.mem = mem;
  25 + }
  26 +
  27 + public List<Object> getNet() {
  28 + return net;
  29 + }
  30 +
  31 + public void setNet(List<Object> net) {
  32 + this.net = net;
  33 + }
  34 +}
... ...
src/main/java/com/genersoft/iot/vmp/conf/SystemInfoTimerTask.java
... ... @@ -22,14 +22,14 @@ public class SystemInfoTimerTask {
22 22 @Autowired
23 23 private IRedisCatchStorage redisCatchStorage;
24 24  
25   - @Scheduled(fixedRate = 1000) //每1秒执行一次
  25 + @Scheduled(fixedRate = 2000) //每1秒执行一次
26 26 public void execute(){
27 27 try {
28 28 double cpuInfo = SystemInfoUtils.getCpuInfo();
29 29 redisCatchStorage.addCpuInfo(cpuInfo);
30 30 double memInfo = SystemInfoUtils.getMemInfo();
31 31 redisCatchStorage.addMemInfo(memInfo);
32   - Map<String, String> networkInterfaces = SystemInfoUtils.getNetworkInterfaces();
  32 + Map<String, Double> networkInterfaces = SystemInfoUtils.getNetworkInterfaces();
33 33 redisCatchStorage.addNetInfo(networkInterfaces);
34 34 } catch (InterruptedException e) {
35 35 logger.error("[获取系统信息失败] {}", e.getMessage());
... ...
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
... ... @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.storager;
2 2  
3 3 import com.alibaba.fastjson.JSONObject;
4 4 import com.genersoft.iot.vmp.common.StreamInfo;
  5 +import com.genersoft.iot.vmp.common.SystemAllInfo;
5 6 import com.genersoft.iot.vmp.gb28181.bean.*;
6 7 import com.genersoft.iot.vmp.media.zlm.dto.*;
7 8 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
... ... @@ -196,7 +197,7 @@ public interface IRedisCatchStorage {
196 197  
197 198 void addMemInfo(double memInfo);
198 199  
199   - void addNetInfo(Map<String, String> networkInterfaces);
  200 + void addNetInfo(Map<String, Double> networkInterfaces);
200 201  
201 202 void sendMobilePositionMsg(JSONObject jsonObject);
202 203  
... ... @@ -240,4 +241,7 @@ public interface IRedisCatchStorage {
240 241 List<SendRtpItem> querySendRTPServerByChnnelId(String channelId);
241 242  
242 243 List<SendRtpItem> querySendRTPServerByStream(String stream);
  244 +
  245 + SystemAllInfo getSystemInfo();
  246 +
243 247 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.storager.impl;
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONObject;
5 5 import com.genersoft.iot.vmp.common.StreamInfo;
  6 +import com.genersoft.iot.vmp.common.SystemAllInfo;
6 7 import com.genersoft.iot.vmp.common.SystemInfoDto;
7 8 import com.genersoft.iot.vmp.common.VideoManagerConstants;
8 9 import com.genersoft.iot.vmp.conf.UserSetting;
... ... @@ -694,12 +695,12 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
694 695 @Override
695 696 public void addCpuInfo(double cpuInfo) {
696 697 String key = VideoManagerConstants.SYSTEM_INFO_CPU_PREFIX + userSetting.getServerId();
697   - SystemInfoDto<Double> systemInfoDto = new SystemInfoDto<>();
698   - systemInfoDto.setTime(DateUtil.getNow());
699   - systemInfoDto.setData(cpuInfo);
700   - RedisUtil.lSet(key, systemInfoDto);
  698 + Map<String, String> infoMap = new HashMap<>();
  699 + infoMap.put("time", DateUtil.getNow());
  700 + infoMap.put("data", cpuInfo + "");
  701 + RedisUtil.lSet(key, infoMap);
701 702 // 每秒一个,最多只存30个
702   - if (RedisUtil.lGetListSize(key) > 30) {
  703 + if (RedisUtil.lGetListSize(key) >= 30) {
703 704 for (int i = 0; i < RedisUtil.lGetListSize(key) - 30; i++) {
704 705 RedisUtil.lLeftPop(key);
705 706 }
... ... @@ -709,12 +710,12 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
709 710 @Override
710 711 public void addMemInfo(double memInfo) {
711 712 String key = VideoManagerConstants.SYSTEM_INFO_MEM_PREFIX + userSetting.getServerId();
712   - SystemInfoDto<Double> systemInfoDto = new SystemInfoDto<>();
713   - systemInfoDto.setTime(DateUtil.getNow());
714   - systemInfoDto.setData(memInfo);
715   - RedisUtil.lSet(key, systemInfoDto);
  713 + Map<String, String> infoMap = new HashMap<>();
  714 + infoMap.put("time", DateUtil.getNow());
  715 + infoMap.put("data", memInfo + "");
  716 + RedisUtil.lSet(key, infoMap);
716 717 // 每秒一个,最多只存30个
717   - if (RedisUtil.lGetListSize(key) > 30) {
  718 + if (RedisUtil.lGetListSize(key) >= 30) {
718 719 for (int i = 0; i < RedisUtil.lGetListSize(key) - 30; i++) {
719 720 RedisUtil.lLeftPop(key);
720 721 }
... ... @@ -722,14 +723,16 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
722 723 }
723 724  
724 725 @Override
725   - public void addNetInfo(Map<String, String> networkInterfaces) {
  726 + public void addNetInfo(Map<String, Double> networkInterfaces) {
726 727 String key = VideoManagerConstants.SYSTEM_INFO_NET_PREFIX + userSetting.getServerId();
727   - SystemInfoDto<Map<String, String>> systemInfoDto = new SystemInfoDto<>();
728   - systemInfoDto.setTime(DateUtil.getNow());
729   - systemInfoDto.setData(networkInterfaces);
730   - RedisUtil.lSet(key, systemInfoDto);
  728 + Map<String, Object> infoMap = new HashMap<>();
  729 + infoMap.put("time", DateUtil.getNow());
  730 + for (String netKey : networkInterfaces.keySet()) {
  731 + infoMap.put(netKey, networkInterfaces.get(netKey));
  732 + }
  733 + RedisUtil.lSet(key, infoMap);
731 734 // 每秒一个,最多只存30个
732   - if (RedisUtil.lGetListSize(key) > 30) {
  735 + if (RedisUtil.lGetListSize(key) >= 30) {
733 736 for (int i = 0; i < RedisUtil.lGetListSize(key) - 30; i++) {
734 737 RedisUtil.lLeftPop(key);
735 738 }
... ... @@ -737,6 +740,18 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
737 740 }
738 741  
739 742 @Override
  743 + public SystemAllInfo getSystemInfo() {
  744 + String cpuKey = VideoManagerConstants.SYSTEM_INFO_CPU_PREFIX + userSetting.getServerId();
  745 + String memKey = VideoManagerConstants.SYSTEM_INFO_MEM_PREFIX + userSetting.getServerId();
  746 + String netKey = VideoManagerConstants.SYSTEM_INFO_NET_PREFIX + userSetting.getServerId();
  747 + SystemAllInfo systemAllInfo = new SystemAllInfo();
  748 + systemAllInfo.setCpu(RedisUtil.lGet(cpuKey, 0, -1));
  749 + systemAllInfo.setMem(RedisUtil.lGet(memKey, 0, -1));
  750 + systemAllInfo.setNet(RedisUtil.lGet(netKey, 0, -1));
  751 + return systemAllInfo;
  752 + }
  753 +
  754 + @Override
740 755 public void sendMobilePositionMsg(JSONObject jsonObject) {
741 756 String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION;
742 757 logger.info("[redis发送通知] 移动位置 {}: {}", key, jsonObject.toString());
... ...
src/main/java/com/genersoft/iot/vmp/utils/SystemInfoUtils.java
... ... @@ -8,6 +8,7 @@ import oshi.hardware.NetworkIF;
8 8 import oshi.software.os.OperatingSystem;
9 9 import oshi.util.FormatUtil;
10 10  
  11 +import java.text.DecimalFormat;
11 12 import java.util.HashMap;
12 13 import java.util.List;
13 14 import java.util.Map;
... ... @@ -62,21 +63,32 @@ public class SystemInfoUtils {
62 63 * 获取网络上传和下载
63 64 * @return
64 65 */
65   - public static Map<String,String> getNetworkInterfaces() {
  66 + public static Map<String,Double> getNetworkInterfaces() {
66 67 SystemInfo si = new SystemInfo();
67 68 HardwareAbstractionLayer hal = si.getHardware();
68   - List<NetworkIF> networkIFs = hal.getNetworkIFs();
69   - int i= networkIFs.size() -1;
70   - NetworkIF net= networkIFs.get(i);
  69 + List<NetworkIF> beforeRecvNetworkIFs = hal.getNetworkIFs();
  70 + NetworkIF beforeBet= beforeRecvNetworkIFs.get(beforeRecvNetworkIFs.size() - 1);
  71 + long beforeRecv = beforeBet.getBytesRecv();
  72 + long beforeSend = beforeBet.getBytesSent();
  73 + try {
  74 + Thread.sleep(1000);
  75 + } catch (InterruptedException e) {
  76 + throw new RuntimeException(e);
  77 + }
  78 + List<NetworkIF> afterNetworkIFs = hal.getNetworkIFs();
  79 + NetworkIF afterNet = afterNetworkIFs.get(afterNetworkIFs.size() - 1);
71 80  
72   - String in = FormatUtil.formatBytes(net.getBytesRecv());
73   - String out = FormatUtil.formatBytes(net.getBytesSent());
74   - HashMap<String, String> map = new HashMap<>();
75   - map.put("in",in);
76   - map.put("out",out);
  81 + HashMap<String, Double> map = new HashMap<>();
  82 + // 速度单位: Mbps
  83 + map.put("in",formatUnits(afterNet.getBytesRecv()-beforeRecv, 1048576L));
  84 + map.put("out",formatUnits(afterNet.getBytesSent()-beforeSend, 1048576L));
77 85 return map;
78 86 }
79 87  
  88 + public static double formatUnits(long value, long prefix) {
  89 + return (double)value / (double)prefix;
  90 + }
  91 +
80 92 /**
81 93 * 获取进程数
82 94 * @return
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
... ... @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.server;
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONObject;
5 5 import com.genersoft.iot.vmp.VManageBootstrap;
  6 +import com.genersoft.iot.vmp.common.SystemAllInfo;
6 7 import com.genersoft.iot.vmp.common.VersionPo;
7 8 import com.genersoft.iot.vmp.conf.SipConfig;
8 9 import com.genersoft.iot.vmp.conf.UserSetting;
... ... @@ -12,6 +13,7 @@ import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
12 13 import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
13 14 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
14 15 import com.genersoft.iot.vmp.service.IMediaServerService;
  16 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
15 17 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
16 18 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
17 19 import gov.nist.javax.sip.SipStackImpl;
... ... @@ -60,6 +62,9 @@ public class ServerController {
60 62 @Autowired
61 63 private ThreadPoolTaskExecutor taskExecutor;
62 64  
  65 + @Autowired
  66 + private IRedisCatchStorage redisCatchStorage;
  67 +
63 68  
64 69 @GetMapping(value = "/media_server/list")
65 70 @ResponseBody
... ... @@ -202,4 +207,12 @@ public class ServerController {
202 207 public List<IHookSubscribe> getHooks() {
203 208 return zlmHttpHookSubscribe.getAll();
204 209 }
  210 +
  211 + @GetMapping(value = "/system/info")
  212 + @ResponseBody
  213 + @Operation(summary = "获取系统信息")
  214 + public SystemAllInfo getSystemInfo() {
  215 + SystemAllInfo systemAllInfo = redisCatchStorage.getSystemInfo();
  216 + return systemAllInfo;
  217 + }
205 218 }
... ...
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java
... ... @@ -40,7 +40,7 @@ public class ApiDeviceController {
40 40 // private DeviceOffLineDetector offLineDetector;
41 41  
42 42 /**
43   - * 分页获取设备列表 TODO 现在直接返回,尚未实现分页
  43 + * 分页获取设备列表 现在直接返回,尚未实现分页
44 44 * @param start
45 45 * @param limit
46 46 * @param q
... ... @@ -130,11 +130,11 @@ public class ApiDeviceController {
130 130 deviceJOSNChannel.put("DeviceID", device.getDeviceId());
131 131 deviceJOSNChannel.put("DeviceName", device.getName());
132 132 deviceJOSNChannel.put("DeviceOnline", device.getOnline() == 1);
133   - deviceJOSNChannel.put("Channel", 0); // TODO 自定义序号
  133 + deviceJOSNChannel.put("Channel", 0); // 自定义序号
134 134 deviceJOSNChannel.put("Name", deviceChannel.getName());
135 135 deviceJOSNChannel.put("Custom", false);
136 136 deviceJOSNChannel.put("CustomName", "");
137   - deviceJOSNChannel.put("SubCount", deviceChannel.getSubCount()); // TODO ? 子节点数, SubCount > 0 表示该通道为子目录
  137 + deviceJOSNChannel.put("SubCount", deviceChannel.getSubCount()); // 子节点数, SubCount > 0 表示该通道为子目录
138 138 deviceJOSNChannel.put("SnapURL", "");
139 139 deviceJOSNChannel.put("Manufacturer ", deviceChannel.getManufacture());
140 140 deviceJOSNChannel.put("Model", deviceChannel.getModel());
... ...
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
... ... @@ -57,12 +57,12 @@ public class ApiStreamController {
57 57 * @param serial 设备编号
58 58 * @param channel 通道序号 默认值: 1
59 59 * @param code 通道编号,通过 /api/v1/device/channellist 获取的 ChannelList.ID, 该参数和 channel 二选一传递即可
60   - * @param cdn TODO 转推 CDN 地址, 形如: [rtmp|rtsp]://xxx, encodeURIComponent
61   - * @param audio TODO 是否开启音频, 默认 开启
  60 + * @param cdn 转推 CDN 地址, 形如: [rtmp|rtsp]://xxx, encodeURIComponent
  61 + * @param audio 是否开启音频, 默认 开启
62 62 * @param transport 流传输模式, 默认 UDP
63   - * @param checkchannelstatus TODO 是否检查通道状态, 默认 false, 表示 拉流前不检查通道状态是否在线
64   - * @param transportmode TODO 当 transport=TCP 时有效, 指示流传输主被动模式, 默认被动
65   - * @param timeout TODO 拉流超时(秒),
  63 + * @param checkchannelstatus 是否检查通道状态, 默认 false, 表示 拉流前不检查通道状态是否在线
  64 + * @param transportmode 当 transport=TCP 时有效, 指示流传输主被动模式, 默认被动
  65 + * @param timeout 拉流超时(秒),
66 66 * @return
67 67 */
68 68 @RequestMapping(value = "/start")
... ...
web_src/package-lock.json
... ... @@ -18,6 +18,7 @@
18 18 "ol": "^6.14.1",
19 19 "postcss-pxtorem": "^5.1.1",
20 20 "uuid": "^8.3.2",
  21 + "v-charts": "^1.19.0",
21 22 "vue": "^2.6.11",
22 23 "vue-clipboard2": "^0.3.1",
23 24 "vue-clipboards": "^1.3.0",
... ... @@ -3938,12 +3939,31 @@
3938 3939 },
3939 3940 "node_modules/echarts": {
3940 3941 "version": "4.9.0",
3941   - "resolved": "https://registry.nlark.com/echarts/download/echarts-4.9.0.tgz?cache=0&sync_timestamp=1619495447964&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fecharts%2Fdownload%2Fecharts-4.9.0.tgz",
3942   - "integrity": "sha1-qbm6oD8Doqcx5jQMVb77V6nhNH0=",
  3942 + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-4.9.0.tgz",
  3943 + "integrity": "sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==",
3943 3944 "dependencies": {
3944 3945 "zrender": "4.3.2"
3945 3946 }
3946 3947 },
  3948 + "node_modules/echarts-amap": {
  3949 + "version": "1.0.0-rc.6",
  3950 + "resolved": "https://registry.npmmirror.com/echarts-amap/-/echarts-amap-1.0.0-rc.6.tgz",
  3951 + "integrity": "sha512-cYJCKoQdnkZXrGweYrveU1HruZd1c0KmsF1U8o3FtsvgR2jVL5ZUpGFjMmFtpolHOUFqxizk+s+QBLkYuOWL6Q=="
  3952 + },
  3953 + "node_modules/echarts-liquidfill": {
  3954 + "version": "2.0.6",
  3955 + "resolved": "https://registry.npmmirror.com/echarts-liquidfill/-/echarts-liquidfill-2.0.6.tgz",
  3956 + "integrity": "sha512-p+AH0O9/BtwXMQQyhjJbMZo+GwRAgWG/DCyK5r27PQzpS0UWrgXu57MyEFc0A8Ub3sRuqEu08BuxwHICBkSWSQ==",
  3957 + "peerDependencies": {
  3958 + "echarts": "^4.8.0",
  3959 + "zrender": "^4.3.1"
  3960 + }
  3961 + },
  3962 + "node_modules/echarts-wordcloud": {
  3963 + "version": "1.1.3",
  3964 + "resolved": "https://registry.npmmirror.com/echarts-wordcloud/-/echarts-wordcloud-1.1.3.tgz",
  3965 + "integrity": "sha512-Et8D5xEAoYkidmHun+hEH+2lF9dhCt6D0JJ390vlr2r/1zwhhZAbcL01CEvG93QcMcJpSvSPK8vRiGkTbMHRxg=="
  3966 + },
3947 3967 "node_modules/ee-first": {
3948 3968 "version": "1.1.1",
3949 3969 "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz",
... ... @@ -7160,6 +7180,11 @@
7160 7180 "node": ">=0.10.0"
7161 7181 }
7162 7182 },
  7183 + "node_modules/numerify": {
  7184 + "version": "1.2.9",
  7185 + "resolved": "https://registry.npmmirror.com/numerify/-/numerify-1.2.9.tgz",
  7186 + "integrity": "sha512-X4QzQiytV5ZN3TVLhzbtFzjTarUNnaa1pgNDFqt7u7Nqhxe7FvY2eYrGt4WYHlYXDqgtfC/n/a5nJ2y0LijV8w=="
  7187 + },
7163 7188 "node_modules/object-assign": {
7164 7189 "version": "4.1.1",
7165 7190 "resolved": "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz",
... ... @@ -13004,6 +13029,11 @@
13004 13029 "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
13005 13030 "dev": true
13006 13031 },
  13032 + "node_modules/utils-lite": {
  13033 + "version": "0.1.10",
  13034 + "resolved": "https://registry.npmmirror.com/utils-lite/-/utils-lite-0.1.10.tgz",
  13035 + "integrity": "sha512-jlHvdtI8MyWURF/3u+ufIjf1Cs5WjN6WZl9qO8dEkZsVjaI7X5YMUhaCFzkvB69ljt6fo4Dd7V/Oj2NJOFDFOQ=="
  13036 + },
13007 13037 "node_modules/utils-merge": {
13008 13038 "version": "1.0.1",
13009 13039 "resolved": "https://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz",
... ... @@ -13021,6 +13051,22 @@
13021 13051 "uuid": "dist/bin/uuid"
13022 13052 }
13023 13053 },
  13054 + "node_modules/v-charts": {
  13055 + "version": "1.19.0",
  13056 + "resolved": "https://registry.npmmirror.com/v-charts/-/v-charts-1.19.0.tgz",
  13057 + "integrity": "sha512-vm2HBUmxAsXK0ivwce9LytcpqrItDA5JSPLYVxZXtiuoyhcn80XX1/3dPJd/1GqG1OYv3jfBo1s9ra4q8GowqA==",
  13058 + "dependencies": {
  13059 + "echarts-amap": "1.0.0-rc.6",
  13060 + "echarts-liquidfill": "^2.0.2",
  13061 + "echarts-wordcloud": "^1.1.3",
  13062 + "numerify": "1.2.9",
  13063 + "utils-lite": "0.1.10"
  13064 + },
  13065 + "peerDependencies": {
  13066 + "echarts": ">3.0.0",
  13067 + "vue": ">2.0.0"
  13068 + }
  13069 + },
13024 13070 "node_modules/validate-npm-package-license": {
13025 13071 "version": "3.0.4",
13026 13072 "resolved": "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz",
... ... @@ -17796,12 +17842,28 @@
17796 17842 },
17797 17843 "echarts": {
17798 17844 "version": "4.9.0",
17799   - "resolved": "https://registry.nlark.com/echarts/download/echarts-4.9.0.tgz?cache=0&sync_timestamp=1619495447964&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fecharts%2Fdownload%2Fecharts-4.9.0.tgz",
17800   - "integrity": "sha1-qbm6oD8Doqcx5jQMVb77V6nhNH0=",
  17845 + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-4.9.0.tgz",
  17846 + "integrity": "sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==",
17801 17847 "requires": {
17802 17848 "zrender": "4.3.2"
17803 17849 }
17804 17850 },
  17851 + "echarts-amap": {
  17852 + "version": "1.0.0-rc.6",
  17853 + "resolved": "https://registry.npmmirror.com/echarts-amap/-/echarts-amap-1.0.0-rc.6.tgz",
  17854 + "integrity": "sha512-cYJCKoQdnkZXrGweYrveU1HruZd1c0KmsF1U8o3FtsvgR2jVL5ZUpGFjMmFtpolHOUFqxizk+s+QBLkYuOWL6Q=="
  17855 + },
  17856 + "echarts-liquidfill": {
  17857 + "version": "2.0.6",
  17858 + "resolved": "https://registry.npmmirror.com/echarts-liquidfill/-/echarts-liquidfill-2.0.6.tgz",
  17859 + "integrity": "sha512-p+AH0O9/BtwXMQQyhjJbMZo+GwRAgWG/DCyK5r27PQzpS0UWrgXu57MyEFc0A8Ub3sRuqEu08BuxwHICBkSWSQ==",
  17860 + "requires": {}
  17861 + },
  17862 + "echarts-wordcloud": {
  17863 + "version": "1.1.3",
  17864 + "resolved": "https://registry.npmmirror.com/echarts-wordcloud/-/echarts-wordcloud-1.1.3.tgz",
  17865 + "integrity": "sha512-Et8D5xEAoYkidmHun+hEH+2lF9dhCt6D0JJ390vlr2r/1zwhhZAbcL01CEvG93QcMcJpSvSPK8vRiGkTbMHRxg=="
  17866 + },
17805 17867 "ee-first": {
17806 17868 "version": "1.1.1",
17807 17869 "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz",
... ... @@ -20470,6 +20532,11 @@
20470 20532 "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
20471 20533 "dev": true
20472 20534 },
  20535 + "numerify": {
  20536 + "version": "1.2.9",
  20537 + "resolved": "https://registry.npmmirror.com/numerify/-/numerify-1.2.9.tgz",
  20538 + "integrity": "sha512-X4QzQiytV5ZN3TVLhzbtFzjTarUNnaa1pgNDFqt7u7Nqhxe7FvY2eYrGt4WYHlYXDqgtfC/n/a5nJ2y0LijV8w=="
  20539 + },
20473 20540 "object-assign": {
20474 20541 "version": "4.1.1",
20475 20542 "resolved": "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz",
... ... @@ -25327,6 +25394,11 @@
25327 25394 "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
25328 25395 "dev": true
25329 25396 },
  25397 + "utils-lite": {
  25398 + "version": "0.1.10",
  25399 + "resolved": "https://registry.npmmirror.com/utils-lite/-/utils-lite-0.1.10.tgz",
  25400 + "integrity": "sha512-jlHvdtI8MyWURF/3u+ufIjf1Cs5WjN6WZl9qO8dEkZsVjaI7X5YMUhaCFzkvB69ljt6fo4Dd7V/Oj2NJOFDFOQ=="
  25401 + },
25330 25402 "utils-merge": {
25331 25403 "version": "1.0.1",
25332 25404 "resolved": "https://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz",
... ... @@ -25338,6 +25410,18 @@
25338 25410 "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
25339 25411 "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
25340 25412 },
  25413 + "v-charts": {
  25414 + "version": "1.19.0",
  25415 + "resolved": "https://registry.npmmirror.com/v-charts/-/v-charts-1.19.0.tgz",
  25416 + "integrity": "sha512-vm2HBUmxAsXK0ivwce9LytcpqrItDA5JSPLYVxZXtiuoyhcn80XX1/3dPJd/1GqG1OYv3jfBo1s9ra4q8GowqA==",
  25417 + "requires": {
  25418 + "echarts-amap": "1.0.0-rc.6",
  25419 + "echarts-liquidfill": "^2.0.2",
  25420 + "echarts-wordcloud": "^1.1.3",
  25421 + "numerify": "1.2.9",
  25422 + "utils-lite": "0.1.10"
  25423 + }
  25424 + },
25341 25425 "validate-npm-package-license": {
25342 25426 "version": "3.0.4",
25343 25427 "resolved": "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz",
... ...
web_src/package.json
... ... @@ -20,6 +20,7 @@
20 20 "ol": "^6.14.1",
21 21 "postcss-pxtorem": "^5.1.1",
22 22 "uuid": "^8.3.2",
  23 + "v-charts": "^1.19.0",
23 24 "vue": "^2.6.11",
24 25 "vue-clipboard2": "^0.3.1",
25 26 "vue-clipboards": "^1.3.0",
... ...
web_src/src/components/console.vue 0 → 100644
  1 +<template>
  2 + <div id="app" style="width: 100%">
  3 + <div class="page-header">
  4 + <div class="page-title">控制台</div>
  5 + </div>
  6 + <el-row style="width: 100%">
  7 + <el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
  8 + <div class="control-cell" id="ThreadsLoad" >
  9 + <div style="width:100%; height:100%; ">
  10 + <consoleCPU ref="consoleCPU"></consoleCPU>
  11 + </div>
  12 + </div>
  13 + </el-col>
  14 + <el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
  15 + <div class="control-cell" id="WorkThreadsLoad" >
  16 + <div style="width:100%; height:100%; ">
  17 + <consoleMem ref="consoleMem"></consoleMem>
  18 + </div>
  19 + </div>
  20 + </el-col>
  21 + <el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
  22 + <div class="control-cell" id="WorkThreadsLoad" >
  23 + <div style="width:100%; height:100%; ">
  24 + <consoleNet ref="consoleNet"></consoleNet>
  25 + </div>
  26 + </div>
  27 + </el-col>
  28 + <el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
  29 + <div class="control-cell" id="WorkThreadsLoad" >
  30 + <div style="width:100%; height:100%; ">
  31 + <consoleCPU></consoleCPU>
  32 + </div>
  33 + </div>
  34 + </el-col>
  35 + <el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
  36 + <div class="control-cell" id="WorkThreadsLoad" >
  37 + <div style="width:100%; height:100%; ">
  38 + <consoleCPU></consoleCPU>
  39 + </div>
  40 + </div>
  41 + </el-col>
  42 + <el-col :xl="{ span: 8 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
  43 + <div class="control-cell" id="WorkThreadsLoad" >
  44 + <div style="width:100%; height:100%; ">
  45 + <consoleCPU></consoleCPU>
  46 + </div>
  47 + </div>
  48 + </el-col>
  49 +
  50 +
  51 + </el-row>
  52 + </div>
  53 +</template>
  54 +
  55 +<script>
  56 +import uiHeader from '../layout/UiHeader.vue'
  57 +import consoleCPU from './console/ConsoleCPU.vue'
  58 +import consoleMem from './console/ConsoleMEM.vue'
  59 +import consoleNet from './console/ConsoleNet.vue'
  60 +
  61 +import echarts from 'echarts';
  62 +
  63 +export default {
  64 + name: 'app',
  65 + components: {
  66 + echarts,
  67 + uiHeader,
  68 + consoleCPU,
  69 + consoleMem,
  70 + consoleNet
  71 + },
  72 + data() {
  73 + return {
  74 + timer: null
  75 + };
  76 + },
  77 + created() {
  78 + this.getSystemInfo();
  79 + this.loopForSystemInfo();
  80 + },
  81 + destroyed() {
  82 + },
  83 + methods: {
  84 + loopForSystemInfo: function (){
  85 + if (this.timer != null) {
  86 + window.clearTimeout(this.timer);
  87 + }
  88 + this.timer = setTimeout(()=>{
  89 + this.getSystemInfo();
  90 + this.timer = null;
  91 + this.loopForSystemInfo()
  92 + }, 2000)
  93 + },
  94 + getSystemInfo: function (){
  95 + this.$axios({
  96 + method: 'get',
  97 + url: `/api/server/system/info`,
  98 + }).then( (res)=> {
  99 + if (res.data.code === 0) {
  100 + this.$refs.consoleCPU.setData(res.data.data.cpu)
  101 + this.$refs.consoleMem.setData(res.data.data.mem)
  102 + this.$refs.consoleNet.setData(res.data.data.net)
  103 + }
  104 + }).catch( (error)=> {
  105 + });
  106 + }
  107 + }
  108 +};
  109 +</script>
  110 +
  111 +<style>
  112 +#app {
  113 + height: 100%;
  114 +}
  115 +.control-cell {
  116 + padding-top: 10px;
  117 + padding-left: 5px;
  118 + padding-right: 10px;
  119 + height: 360px;
  120 +}
  121 +</style>
... ...
web_src/src/components/console/ConsoleCPU.vue 0 → 100644
  1 +<template>
  2 + <div id="consoleCPU" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
  3 + <ve-line :data="chartData" :extend="extend" width="100%" height="100%" :legend-visible="false"></ve-line>
  4 + </div>
  5 +</template>
  6 +
  7 +<script>
  8 +
  9 +
  10 +import moment from "moment/moment";
  11 +
  12 +export default {
  13 + name: 'consoleCPU',
  14 + data() {
  15 + return {
  16 + chartData: {
  17 + columns: ['time', 'data'],
  18 + rows: []
  19 + },
  20 +
  21 + extend: {
  22 + title: {
  23 + show: true,
  24 + text: "CPU",
  25 + left: "center",
  26 + top: 20,
  27 +
  28 + },
  29 + grid: {
  30 + show: true,
  31 + right: "30px",
  32 + containLabel: true,
  33 + },
  34 + xAxis: {
  35 + time: "time",
  36 + max: 'dataMax',
  37 + boundaryGap: ['20%', '20%'],
  38 + axisLabel: {
  39 + formatter:(v)=>{
  40 + return moment(v).format("HH:mm:ss");
  41 + },
  42 + showMaxLabel: true,
  43 + }
  44 + },
  45 + yAxis: {
  46 + type: 'value',
  47 + min: 0,
  48 + max: 1,
  49 + splitNumber: 6,
  50 + position: "left",
  51 + silent: true,
  52 + axisLabel: {
  53 + formatter: (v)=>{
  54 + return v*100 + "%";
  55 + },
  56 + }
  57 + },
  58 + tooltip: {
  59 + trigger: 'axis',
  60 + formatter: (data)=>{
  61 + console.log(data)
  62 + return moment(data[0].data[0]).format("HH:mm:ss") + "</br> 使用:" + (data[0].data[1]*100).toFixed(2) + "%";
  63 + }
  64 + },
  65 + series: {
  66 + itemStyle: {
  67 + color: "#409EFF"
  68 + },
  69 + areaStyle: {
  70 + color: {
  71 + type: 'linear',
  72 + x: 0,
  73 + y: 0,
  74 + x2: 0,
  75 + y2: 1,
  76 + colorStops: [{
  77 + offset: 0, color: '#50a3f8' // 0% 处的颜色
  78 + }, {
  79 + offset: 1, color: '#69b0fa' // 100% 处的颜色
  80 + }],
  81 + global: false // 缺省为 false
  82 + }
  83 + }
  84 + }
  85 + }
  86 + };
  87 + },
  88 + mounted() {
  89 + // setInterval(()=>{
  90 + // // console.log(111111)
  91 + // for (let i = 0; i < this.chartData.rows.length; i++) {
  92 + // this.chartData.rows[i].销售额 += 1000;
  93 + // }
  94 + // },1000)
  95 + },
  96 + destroyed() {
  97 + },
  98 + methods: {
  99 + setData: function(data) {
  100 + this.chartData .rows = data;
  101 + }
  102 +
  103 + }
  104 +};
  105 +</script>
... ...
web_src/src/components/console/ConsoleMEM.vue 0 → 100644
  1 +<template>
  2 + <div id="ConsoleMEM" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
  3 + <ve-line :data="chartData" :extend="extend" width="100%" height="100%" :legend-visible="false"></ve-line>
  4 + </div>
  5 +</template>
  6 +
  7 +<script>
  8 +
  9 +
  10 +import moment from "moment/moment";
  11 +
  12 +export default {
  13 + name: 'ConsoleMEM',
  14 + data() {
  15 + return {
  16 + chartData: {
  17 + columns: ['time', 'data'],
  18 + rows: []
  19 + },
  20 +
  21 + extend: {
  22 + title: {
  23 + show: true,
  24 + text: "内存",
  25 + left: "center",
  26 + top: 20,
  27 +
  28 + },
  29 + grid: {
  30 + show: true,
  31 + right: "30px",
  32 + containLabel: true,
  33 + },
  34 + xAxis: {
  35 + time: "time",
  36 + max: 'dataMax',
  37 + boundaryGap: ['20%', '20%'],
  38 + axisLabel: {
  39 + formatter:(v)=>{
  40 + return moment(v).format("HH:mm:ss");
  41 + },
  42 + showMaxLabel: true,
  43 + }
  44 + },
  45 + yAxis: {
  46 + type: 'value',
  47 + min: 0,
  48 + max: 1,
  49 + splitNumber: 6,
  50 + position: "left",
  51 + silent: true,
  52 + axisLabel: {
  53 + formatter: (v)=>{
  54 + return v*100 + "%";
  55 + },
  56 + }
  57 + },
  58 + tooltip: {
  59 + trigger: 'axis',
  60 + formatter: (data)=>{
  61 + console.log(data)
  62 + return moment(data[0].data[0]).format("HH:mm:ss") + "</br> 使用:" + (data[0].data[1]*100).toFixed(2) + "%";
  63 + }
  64 + },
  65 + series: {
  66 + itemStyle: {
  67 + color: "#409EFF"
  68 + },
  69 + areaStyle: {
  70 + color: {
  71 + type: 'linear',
  72 + x: 0,
  73 + y: 0,
  74 + x2: 0,
  75 + y2: 1,
  76 + colorStops: [{
  77 + offset: 0, color: '#50a3f8' // 0% 处的颜色
  78 + }, {
  79 + offset: 1, color: '#69b0fa' // 100% 处的颜色
  80 + }],
  81 + global: false // 缺省为 false
  82 + }
  83 + }
  84 + }
  85 + }
  86 + };
  87 + },
  88 + mounted() {
  89 + // setInterval(()=>{
  90 + // // console.log(111111)
  91 + // for (let i = 0; i < this.chartData.rows.length; i++) {
  92 + // this.chartData.rows[i].销售额 += 1000;
  93 + // }
  94 + // },1000)
  95 + },
  96 + destroyed() {
  97 + },
  98 + methods: {
  99 + setData: function(data) {
  100 + this.chartData .rows = data;
  101 + }
  102 +
  103 + }
  104 +};
  105 +</script>
... ...
web_src/src/components/console/ConsoleMediaServer.vue 0 → 100644
  1 +<template>
  2 + <div id="ConsoleMediaServer" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
  3 + <ve-histogram :data="chartData" :extend="extend" :settings="chartSettings" width="100%" height="100%" ></ve-histogram>
  4 + </div>
  5 +</template>
  6 +
  7 +<script>
  8 +
  9 +
  10 +import moment from "moment/moment";
  11 +
  12 +export default {
  13 + name: 'ConsoleMediaServer',
  14 + data() {
  15 + return {
  16 + chartData: {
  17 + columns: ['time', 'in', 'out'],
  18 + rows: [
  19 + ]
  20 + },
  21 + chartSettings: {
  22 + area: true,
  23 + labelMap: {
  24 + 'in': '下载',
  25 + 'out': '上传'
  26 + },
  27 + },
  28 + extend: {
  29 + title: {
  30 + show: true,
  31 + text: "网络",
  32 + left: "center",
  33 + top: 20,
  34 +
  35 + },
  36 + grid: {
  37 + show: true,
  38 + right: "30px",
  39 + containLabel: true,
  40 + },
  41 + xAxis: {
  42 + time: "time",
  43 + max: 'dataMax',
  44 + boundaryGap: ['20%', '20%'],
  45 + axisLabel: {
  46 + formatter:(v)=>{
  47 + return moment(v).format("HH:mm:ss");
  48 + },
  49 + showMaxLabel: true,
  50 + },
  51 + },
  52 + tooltip: {
  53 + trigger: 'axis',
  54 + formatter: (data)=>{
  55 + console.log(parseFloat(data[0].data[1]).toFixed(2))
  56 + console.log(parseFloat(data[1].data[1]).toFixed(2))
  57 + console.log("############")
  58 + return "下载:" + parseFloat(data[0].data[1]).toFixed(2) + "Mbps" + "</br> 上传:" + parseFloat(data[1].data[1]).toFixed(2) + "Mbps";
  59 + }
  60 + },
  61 + legend: {
  62 + left: "center",
  63 + bottom: "15px",
  64 + }
  65 + }
  66 + };
  67 + },
  68 + mounted() {
  69 + // setInterval(()=>{
  70 + // // console.log(111111)
  71 + // for (let i = 0; i < this.chartData.rows.length; i++) {
  72 + // this.chartData.rows[i].销售额 += 1000;
  73 + // }
  74 + // },1000)
  75 + },
  76 + destroyed() {
  77 + },
  78 + methods: {
  79 + setData: function(data) {
  80 + console.log(data)
  81 + this.chartData .rows = data;
  82 + }
  83 +
  84 + }
  85 +};
  86 +</script>
... ...
web_src/src/components/console/ConsoleNet.vue 0 → 100644
  1 +<template>
  2 + <div id="ConsoleNet" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
  3 + <ve-line :data="chartData" :extend="extend" :settings="chartSettings" width="100%" height="100%" ></ve-line>
  4 + </div>
  5 +</template>
  6 +
  7 +<script>
  8 +
  9 +
  10 +import moment from "moment/moment";
  11 +
  12 +export default {
  13 + name: 'ConsoleNet',
  14 + data() {
  15 + return {
  16 + chartData: {
  17 + columns: ['time', 'in', 'out'],
  18 + rows: []
  19 + },
  20 + chartSettings: {
  21 + area: true,
  22 + labelMap: {
  23 + 'in': '下载',
  24 + 'out': '上传'
  25 + },
  26 + },
  27 + extend: {
  28 + title: {
  29 + show: true,
  30 + text: "网络",
  31 + left: "center",
  32 + top: 20,
  33 +
  34 + },
  35 + grid: {
  36 + show: true,
  37 + right: "30px",
  38 + containLabel: true,
  39 + },
  40 + xAxis: {
  41 + time: "time",
  42 + max: 'dataMax',
  43 + boundaryGap: ['20%', '20%'],
  44 + axisLabel: {
  45 + formatter:(v)=>{
  46 + return moment(v).format("HH:mm:ss");
  47 + },
  48 + showMaxLabel: true,
  49 + },
  50 + },
  51 + tooltip: {
  52 + trigger: 'axis',
  53 + formatter: (data)=>{
  54 + console.log(parseFloat(data[0].data[1]).toFixed(2))
  55 + console.log(parseFloat(data[1].data[1]).toFixed(2))
  56 + console.log("############")
  57 + return "下载:" + parseFloat(data[0].data[1]).toFixed(2) + "Mbps" + "</br> 上传:" + parseFloat(data[1].data[1]).toFixed(2) + "Mbps";
  58 + }
  59 + },
  60 + legend: {
  61 + left: "center",
  62 + bottom: "15px",
  63 + }
  64 + }
  65 + };
  66 + },
  67 + mounted() {
  68 + // setInterval(()=>{
  69 + // // console.log(111111)
  70 + // for (let i = 0; i < this.chartData.rows.length; i++) {
  71 + // this.chartData.rows[i].销售额 += 1000;
  72 + // }
  73 + // },1000)
  74 + },
  75 + destroyed() {
  76 + },
  77 + methods: {
  78 + setData: function(data) {
  79 + console.log(data)
  80 + this.chartData .rows = data;
  81 + }
  82 +
  83 + }
  84 +};
  85 +</script>
... ...
web_src/src/components/control.vue deleted 100644 → 0
1   -<template>
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   -
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>
65   - <span class="el-dropdown-link">
66   - 查看<i class="el-icon-arrow-down el-icon--right"></i>
67   - </span>
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>
87   -
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>
105   -
106   -
107   - </div>
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>-->
198   -
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>-->
216   -
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 v-slot:default="scope">
239   - <el-button size="mini" icon="el-icon-refresh-right" circle @click="getAllSession()"></el-button>
240   - <el-button @click.native.prevent="deleteRow(scope.$index, allSessionData)" type="text" size="small">移除
241   - </el-button>
242   - </template>
243   - </el-table-column>
244   - </el-table>
245   - </div>
246   -</template>
247   -
248   -<script>
249   -import uiHeader from '../layout/UiHeader.vue'
250   -import MediaServer from './service/MediaServer'
251   -
252   -import echarts from 'echarts';
253   -
254   -export default {
255   - name: 'app',
256   - components: {
257   - echarts,
258   - uiHeader
259   - },
260   - data() {
261   - return {
262   - tableOption: {
263   - // legend: {},
264   - xAxis: {},
265   - yAxis: {},
266   - label: {},
267   - tooltip: {},
268   - dataZoom: [],
269   - series: []
270   - },
271   - table1Option: {
272   - // legend: {},
273   - xAxis: {},
274   - yAxis: {},
275   - label: {},
276   - tooltip: {},
277   - series: []
278   - },
279   - mChart: null,
280   - mChart1: null,
281   - charZoomStart: 0,
282   - charZoomEnd: 100,
283   - chartInterval: 0, //更新图表统计图定时任务标识
284   - allSessionData: [],
285   - visible: false,
286   - wvpVisible: false,
287   - serverConfig: {},
288   - wvpServerConfig: {},
289   - wvpServerVersion: {},
290   - mediaServer: new MediaServer(),
291   - mediaServerChoose: null,
292   - loadCount: 0,
293   - mediaServerList: []
294   - };
295   - },
296   - mounted() {
297   - this.initTable()
298   - this.chartInterval = setInterval(this.updateData, 3000);
299   - this.mediaServer.getOnlineMediaServerList((data) => {
300   - this.mediaServerList = data.data;
301   - if (this.mediaServerList && this.mediaServerList.length > 0) {
302   - this.mediaServerChoose = this.mediaServerList[0].id
303   - this.loadCount = this.mediaServerList[0].count;
304   - this.updateData();
305   - }
306   - })
307   - },
308   - destroyed() {
309   - clearInterval(this.chartInterval); //释放定时任务
310   - },
311   - methods: {
312   - chooseMediaChange: function (val) {
313   - this.loadCount = 0
314   - this.initTable()
315   - this.updateData();
316   - },
317   - updateData: function () {
318   - this.getThreadsLoad();
319   - this.getLoadCount();
320   - this.getAllSession();
321   - },
322   - /**
323   - * 获取线程状态
324   - */
325   - getThreadsLoad: function () {
326   - let that = this;
327   - if (!!that.mediaServerChoose) {
328   - this.$axios({
329   - method: 'get',
330   - url: '/zlm/' + that.mediaServerChoose + '/index/api/getThreadsLoad'
331   - }).then(function (res) {
332   - if (res.data.code === 0) {
333   - that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
334   - hour12: false
335   - }));
336   - that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
337   - hour12: false
338   - }));
339   -
340   - for (var i = 0; i < res.data.data.length; i++) {
341   - if (that.tableOption.series[i] === undefined) {
342   - let data = {
343   - data: [],
344   - type: 'line'
345   - };
346   - let data1 = {
347   - data: [],
348   - type: 'line'
349   - };
350   - data.data.push(res.data.data[i].delay);
351   - data1.data.push(res.data.data[i].load);
352   - that.tableOption.series.push(data);
353   - that.table1Option.series.push(data1);
354   - } else {
355   - that.tableOption.series[i].data.push(res.data.data[i].delay);
356   - that.table1Option.series[i].data.push(res.data.data[i].load);
357   - }
358   - }
359   - that.tableOption.dataZoom[0].start = that.charZoomStart;
360   - that.tableOption.dataZoom[0].end = that.charZoomEnd;
361   - that.table1Option.dataZoom[0].start = that.charZoomStart;
362   - that.table1Option.dataZoom[0].end = that.charZoomEnd;
363   - //that.myChart = echarts.init(document.getElementById('ThreadsLoad'));
364   - that.myChart.setOption(that.tableOption, true);
365   - // that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
366   - that.myChart1.setOption(that.table1Option, true);
367   - that.$nextTick(() => {
368   - that.myChart.resize()
369   - that.myChart1.resize()
370   - })
371   - }
372   - });
373   - }
374   -
375   - },
376   - getLoadCount: function () {
377   - let that = this;
378   - if (!!that.mediaServerChoose) {
379   - that.mediaServer.getMediaServer(that.mediaServerChoose, (data) => {
380   - if (data.code == 0) {
381   - that.loadCount = data.data.count
382   - }
383   - })
384   - }
385   - },
386   - initTable: function () {
387   - let that = this;
388   - this.tableOption.xAxis = {
389   - type: 'category',
390   - data: [], // x轴数据
391   - name: '时间', // x轴名称
392   - // x轴名称样式
393   - nameTextStyle: {
394   - fontWeight: 300,
395   - fontSize: 15
396   - }
397   - };
398   - this.tableOption.yAxis = {
399   - type: 'value',
400   - name: '延迟率', // y轴名称
401   - boundaryGap: [0, '100%'],
402   - max: 100,
403   - axisLabel: {
404   - show: true,
405   - interval: 'auto',
406   - formatter: '{value} %'
407   - },
408   - // y轴名称样式
409   - nameTextStyle: {
410   - fontWeight: 300,
411   - fontSize: 15
412   - }
413   - };
414   - this.tableOption.dataZoom = [{
415   - show: true,
416   - start: this.charZoomStart,
417   - end: this.charZoomEnd
418   - }];
419   - this.myChart = echarts.init(document.getElementById('ThreadsLoad'));
420   - this.myChart.setOption(this.tableOption);
421   - this.myChart.on('dataZoom', function (event) {
422   - if (event.batch) {
423   - that.charZoomStart = event.batch[0].start;
424   - that.charZoomEnd = event.batch[0].end;
425   - } else {
426   - that.charZoomStart = event.start;
427   - that.charZoomEnd = event.end;
428   - }
429   - });
430   -
431   - this.table1Option.xAxis = {
432   - type: 'category',
433   - data: [], // x轴数据
434   - name: '时间', // x轴名称
435   - // x轴名称样式
436   - nameTextStyle: {
437   - fontWeight: 300,
438   - fontSize: 15
439   - }
440   - };
441   - this.table1Option.yAxis = {
442   - type: 'value',
443   - name: '负载率', // y轴名称
444   - boundaryGap: [0, '100%'],
445   - max: 100,
446   - axisLabel: {
447   - show: true,
448   - interval: 'auto',
449   - formatter: '{value} %'
450   - },
451   - // y轴名称样式
452   - nameTextStyle: {
453   - fontWeight: 300,
454   - fontSize: 15
455   - }
456   - };
457   - this.table1Option.dataZoom = [{
458   - show: true,
459   - start: this.charZoomStart,
460   - end: this.charZoomEnd
461   - }];
462   - this.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
463   - this.myChart1.setOption(this.table1Option);
464   - this.myChart1.on('dataZoom', function (event) {
465   - if (event.batch) {
466   - that.charZoomStart = event.batch[0].start;
467   - that.charZoomEnd = event.batch[0].end;
468   - } else {
469   - that.charZoomStart = event.start;
470   - that.charZoomEnd = event.end;
471   - }
472   - });
473   - },
474   -
475   - getAllSession: function () {
476   - this.allSessionData = [];
477   - if (!!this.mediaServerChoose) {
478   - this.$axios({
479   - method: 'get',
480   - url: '/zlm/' + this.mediaServerChoose + '/index/api/getAllSession'
481   - }).then((res)=> {
482   - res.data.data.forEach(item => {
483   - let data = {
484   - peer_ip: item.peer_ip,
485   - local_ip: item.local_ip,
486   - typeid: item.typeid,
487   - id: item.id
488   - };
489   - this.allSessionData.push(data);
490   - });
491   - });
492   - }
493   -
494   - },
495   - getServerConfig: function () {
496   - if (!!this.mediaServerChoose) {
497   - this.$axios({
498   - method: 'get',
499   - url: '/zlm/' + this.mediaServerChoose + '/index/api/getServerConfig'
500   - }).then((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   - }
510   -
511   - this.serverConfig = serverInfo;
512   - this.visible = true;
513   - });
514   - }
515   -
516   - },
517   - getWVPServerConfig: function () {
518   - let that = this;
519   - this.$axios({
520   - method: 'get',
521   - url: '/api/server/config'
522   - }).then(function (res) {
523   - console.log(res)
524   - that.wvpServerConfig = res.data.data;
525   - that.wvpVisible = true;
526   - });
527   - this.$axios({
528   - method: 'get',
529   - url: '/api/server/version'
530   - }).then(function (res) {
531   - console.log(res)
532   - that.wvpServerVersion = res.data.data;
533   - that.wvpVisible = true;
534   - });
535   - },
536   - reStartServer: function () {
537   - let that = this;
538   - if (!!!this.mediaServerChoose) {
539   - this.$message({
540   - type: 'info',
541   - message: '未选择节点'
542   - });
543   - return;
544   - }
545   -
546   - this.$confirm('此操作将重启媒体服务器, 是否继续?', '提示', {
547   - confirmButtonText: '确定',
548   - cancelButtonText: '取消',
549   - type: 'warning'
550   - }).then(() => {
551   - let that = this;
552   - this.$axios({
553   - method: 'get',
554   - url: '/zlm/' + that.mediaServerChoose + '/index/api/restartServer'
555   - }).then(function (res) {
556   - that.getAllSession();
557   - if (res.data.code === 0) {
558   - that.$message({
559   - type: 'success',
560   - message: '操作完成'
561   - });
562   - }
563   - });
564   - });
565   - },
566   - deleteRow: function (index, tabledata) {
567   - let that = this;
568   - this.$confirm('此操作将断开该通信链路, 是否继续?', '提示', {
569   - confirmButtonText: '确定',
570   - cancelButtonText: '取消',
571   - type: 'warning'
572   - })
573   - .then(() => {
574   - that.deleteSession(tabledata[index].id);
575   - })
576   - .catch(() => {
577   - console.log('id:' + JSON.stringify(tabledata[index]));
578   - this.$message({
579   - type: 'info',
580   - message: '已取消删除'
581   - });
582   - });
583   - console.log(JSON.stringify(tabledata[index]));
584   - },
585   - deleteSession: function (id) {
586   - if (!!this.mediaServerChoose) {
587   - this.$axios({
588   - method: 'get',
589   - url: '/zlm/' + this.mediaServerChoose + '/index/api/kick_session?id=' + id
590   - }).then((res)=>{
591   - this.getAllSession();
592   - this.$message({
593   - type: 'success',
594   - message: '删除成功!'
595   - });
596   - });
597   - }
598   -
599   - },
600   - getNameFromKey: function (key) {
601   - let nameData = {
602   - "waitTrack": "等待编码信息",
603   - "interfaceAuthenticationExcludes": "不进行鉴权的接口",
604   - "playTimeout": "点播超时时间",
605   - "autoApplyPlay": "自动点播",
606   - "recordPushLive": "推流录像",
607   - "redisConfig": "自动配置redis",
608   - "thirdPartyGBIdReg": "stream信息正则",
609   - "savePositionHistory": "保存轨迹信息",
610   - "interfaceAuthentication": "接口鉴权",
611   - "serverId": "服务ID",
612   - "logInDatebase": "日志存储进数据库",
613   - "seniorSdp": "扩展SDP",
614   - "password": "密码",
615   - "port": "端口号",
616   - "keepaliveTimeOut": "心跳超时",
617   - "domain": "国标域",
618   - "ip": "IP地址",
619   - "monitorIp": "监听IP",
620   - "alarm": "存储报警信息",
621   - "ptzSpeed": "云台控制速度",
622   - "id": "国标ID",
623   - "registerTimeInterval": "注册间隔",
624   - "artifactId": "模块名称",
625   - "version": "版本",
626   - "project": "工程",
627   - "git_Revision": "GIT修订版本",
628   - "git_BRANCH": "GIT分支",
629   - "git_URL": "GIT地址",
630   - "build_DATE": "构建时间",
631   - "create_By": "作者",
632   - "git_Revision_SHORT": "GIT修订版本(短)",
633   - "build_Jdk": "构建用JDK",
634   - };
635   - console.log(key + ": " + nameData[key])
636   -
637   - if (nameData[key]) {
638   - return nameData[key]
639   - } else {
640   - return key;
641   - }
642   - },
643   - getMediaKeyNameFromKey: function (key) {
644   - let nameData = {
645   - "waitTrack": "等待编码信息",
646   - "interfaceAuthenticationExcludes": "不进行鉴权的接口",
647   - "playTimeout": "点播超时时间",
648   - "autoApplyPlay": "自动点播",
649   - "recordPushLive": "推流录像",
650   - "redisConfig": "自动配置redis",
651   - "thirdPartyGBIdReg": "stream信息正则",
652   - "savePositionHistory": "保存轨迹信息",
653   - "interfaceAuthentication": "接口鉴权",
654   - "serverId": "服务ID",
655   - "logInDatebase": "日志存储进数据库",
656   - "seniorSdp": "扩展SDP",
657   - "password": "密码",
658   - "port": "端口号",
659   - "keepaliveTimeOut": "心跳超时",
660   - "domain": "国标域",
661   - "ip": "IP地址",
662   - "monitorIp": "监听IP",
663   - "alarm": "存储报警信息",
664   - "ptzSpeed": "云台控制速度",
665   - "id": "国标ID",
666   - "registerTimeInterval": "注册间隔",
667   - "artifactId": "模块名称",
668   - "version": "版本",
669   - "project": "工程",
670   - "git_Revision": "GIT修订版本",
671   - "git_BRANCH": "GIT分支",
672   - "git_URL": "GIT地址",
673   - "build_DATE": "构建时间",
674   - "create_By": "作者",
675   - "git_Revision_SHORT": "GIT修订版本(短)",
676   - "build_Jdk": "构建用JDK",
677   - };
678   - console.log(key + ": " + nameData[key])
679   -
680   - if (nameData[key]) {
681   - return nameData[key]
682   - } else {
683   - return key;
684   - }
685   - }
686   - }
687   -};
688   -</script>
689   -
690   -<style>
691   -#app {
692   - height: 100%;
693   -}
694   -
695   -.control-table {
696   - background-color: #ffffff;
697   - height: 25rem;
698   -}
699   -
700   -.table-c {
701   - border-right: 1px solid #dcdcdc;
702   - border-bottom: 1px solid #dcdcdc;
703   -}
704   -
705   -.table-c td {
706   - border-left: 1px solid #dcdcdc;
707   - border-top: 1px solid #dcdcdc;
708   - padding: 0.2rem;
709   -}
710   -
711   -.el-table {
712   - width: 99.9% !important;
713   -}
714   -</style>
web_src/src/main.js
... ... @@ -7,6 +7,7 @@ import router from &#39;./router/index.js&#39;;
7 7 import axios from 'axios';
8 8 import VueCookies from 'vue-cookies';
9 9 import echarts from 'echarts';
  10 +import VCharts from 'v-charts';
10 11  
11 12 import VueClipboard from 'vue-clipboard2';
12 13 import { Notification } from 'element-ui';
... ... @@ -39,6 +40,7 @@ Vue.use(VueClipboards);
39 40 Vue.prototype.$axios = axios;
40 41 Vue.prototype.$notify = Notification;
41 42 Vue.use(Contextmenu);
  43 +Vue.use(VCharts);
42 44  
43 45 axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : "";
44 46  
... ...
web_src/src/router/index.js
... ... @@ -2,7 +2,7 @@ import Vue from &#39;vue&#39;
2 2 import VueRouter from 'vue-router'
3 3 import Layout from "../layout/index.vue"
4 4  
5   -import control from '../components/control.vue'
  5 +import console from '../components/console.vue'
6 6 import deviceList from '../components/DeviceList.vue'
7 7 import channelList from '../components/channelList.vue'
8 8 import pushVideoList from '../components/PushVideoList.vue'
... ... @@ -37,11 +37,11 @@ export default new VueRouter({
37 37 path: '/',
38 38 name: 'home',
39 39 component: Layout,
40   - redirect: '/control',
  40 + redirect: '/console',
41 41 children: [
42 42 {
43   - path: '/control',
44   - component: control,
  43 + path: '/console',
  44 + component: console,
45 45 },
46 46 {
47 47 path: '/live',
... ...