仿海康网页版做一个在线的实时监控网站(1)-- 侧边栏站点选择
目前的渔政网页版的开发已经接近尾声,目前要做的是一个网页版的在线视频实时监控的功能,仿照海康的网页版示例,整个页面做下来有点心得体会,所以写一篇博文记录下,方便自己以后翻阅,也希望可以给别人提供帮助
首先搭建页面,用css+div布局生成页面,如何用js生成div在我前面的博客中有提过
这篇博客我准备写两篇,第一篇讲侧边栏的生成过程,第二遍讲海康视频插件的添加和云台的操作
因为获取数据的原因,侧边栏的生成比我预计的多花了好几天的时间,当然了这么几天我也学到了很多新的知识,这更主要的是对于数组有了一个更深刻的理论
首先获取到所有的设备,里面的数据包括所有的设备和设备编号,相当于所有数据的总框,我需要根据这个总框编写一个字典函数,根据其其他接口获取到得设备,得到设备名称显示在节点中,关于字典函数的编写和数据的层级关系在上一篇博客里。
然后根据接口,获取所有的IRST设备,将从接口获取的LIST格式的数据整理成LIst{IRST,LIST{}}的格式,获取完毕之后拼接字符串,在写的时候出现了两处错误,一处是遍历数组添加数据的时候,后面的数据替换了之前的存储数据,二是之前写的字典函数没有应用上去,该显示站点名称的地方写的是未定义
我们依次解决这些问题
第一个问题,首先看一段代码

1 //设置站点设备的索引 2 var nationindex = 0; 3 var irstindex = 0; 4 var index = 0; 5 //获取第一个站点名称 6 var IRSTnation = nodelist[0].szDeviceID; 7 8 //数组用来存储所有的IRST设备信息 9 var IRSTlist = new Array(IRST); 10 11 //数组用来存储站点名称以及对应的IRST设备信息 12 var list = new Array(IRSTnation, IRSTlist); 13 14 15 for (var i = 0; i < nodelength; i++) { 16 if (nodelist[i].szDeviceID === IRSTnation) { 17 //数组用来存储单个的IRST设备信息 18 var IRST = new Array(); 19 IRST[irstindex] = new Array(); 20 IRST[irstindex] = [nodelist[i].szName, nodelist[i].szIP, nodelist[i].NPort, nodelist[i].szUser, nodelist[i].szPassword, nodelist[i].NChannel, nodelist[i].szName, nodelist[i].szStation, nodelist[i].NDeviceType]; 21 IRSTlist[nationindex] = new Array(); 22 IRSTlist[nationindex].push(IRST); 23 list[index] = new Array(); 24 var copyIRSTlist = IRSTlist; 25 list[index].push(IRSTnation, copyIRSTlist[nationindex]); 26 irstindex++; 27 } 28 if (nodelist[i].szDeviceID !== IRSTnation) { 29 index++; 30 nationindex++; 31 irstindex = 0; 32 IRSTnation = nodelist[i].szDeviceID; 33 //数组用来存储单个的IRST设备信息 34 var IRST = new Array(); 35 IRST[irstindex] = new Array(); 36 IRST[irstindex] = [nodelist[i].szName, nodelist[i].szIP, nodelist[i].NPort, nodelist[i].szUser, nodelist[i].szPassword, nodelist[i].NChannel, nodelist[i].szName, nodelist[i].szStation, nodelist[i].NDeviceType]; 37 IRSTlist[nationindex] = new Array(); 38 IRSTlist[nationindex].push(IRST); 39 list[index] = new Array(); 40 var copyIRSTlist = IRSTlist; 41 list[index].push(IRSTnation, copyIRSTlist[nationindex]); 42 irstindex++; 43 } 44 }
这段代码看起来比较复杂,其实逻辑比较好理解,IRST存储每个摄像头的信息,IRSTList存储IRST数据,list存储站点和对应的摄像头数据,我在第一个循环执行完之后,切换站点,重置IRSTList的索引为0时,后面生成的数据就把前面的数据覆盖了,我试了很久没找到一个好的解决方法,后来在网上找到一个别人用js写的Map方法,达成了我想要的数据格式
从thrift获取数据,用map函数变成我想要的数据格式,然后拼接字符串,代码如下:

1 //获取所有IRST设备 2 $.ajax({ 3 contentType: "application/x-www-form-urlencoded; charset=utf-8", 4 type: "POST", 5 url: "/getit", //servlet路径 6 statusCode: { 7 404: function () { 8 alert('获取IRST设备失败,请刷新'); 9 } 10 }, 11 success: function (data) { 12 nodelist = eval(data); 13 var areas = new Map(); 14 for (var i = 0; i < nodelist.length; i++) { 15 var deviceid = nodelist[i].szDeviceID; 16 //获取站点编号 17 var stationid = deviceid.substring(0, 6); 18 //获取湖区编号 19 var areaid = deviceid.substring(0, 4); 20 21 //添加湖区信息 22 if (!areas.containsKey(areaid)) 23 areas.put(areaid, new Map()); 24 25 //添加站点信息 26 var area =areas.get(areaid); 27 if (!area.containsKey(stationid)) 28 area.put(stationid,new Map()); 29 30 //添加设备信息 31 var station = area.get(stationid); 32 if (!station.containsKey(deviceid)) 33 station.put(deviceid,new Map()); 34 35 station.get(deviceid).put(nodelist[i].szName,nodelist[i]); 36 37 } 38 39 var keys = areas.keys(); 40 41 var i = 0; 42 var ii = 0; 43 var iii = 0; 44 var iiii = 0; 45 var station = ""; 46 var device = ""; 47 var IRST = ""; 48 var str = ""; 49 50 //拼接字符串 51 str = "["; 52 53 for ( i = 0; i < keys.length; i++) { 54 //根据湖区名称找站点名称 55 var allinfo = areas.get(keys); 56 station = allinfo.elements; 57 //如果有站点信息 58 if(station.length > 0){ 59 for (ii = 0; ii < station.length; ii++) { 60 if (ii + 1 === station.length) { 61 str += "{id:'" + station[ii].key + "',text:'" + adddevide.find(station[ii].key) + "'"; 62 alldevice(); 63 break; 64 } 65 else { 66 str += "{id:'" + station[ii].key + "',text:'" + adddevide.find(station[ii].key) + "'"; 67 alldevice(); 68 str += "},"; 69 } 70 } 71 } 72 } 73 74 str += "}];"; 75 76 //获取不同的设备 77 function alldevice() { 78 device = station[ii].value.elements; 79 if(device.length > 0){ 80 for (iii = 0; iii < device.length; iii++) { 81 if (str.charAt(str.length - 1) !== ",") { 82 str += ",nodes:["; 83 } 84 //如果是节点的最后一位 85 if (iii + 1 === device.length) { 86 str += "{id:'" + device[iii].key + "',text:'" + adddevide.find(device[iii].key)+ "'"; 87 IRSTType(); 88 str += "}]"; 89 return 0; 90 } 91 else { 92 str += "{id:'" + device[iii].key + "',text:'" + adddevide.find(device[iii].key)+ "'"; 93 IRSTType(); 94 str += "},"; 95 } 96 } 97 } 98 return 0; 99 } 100 101 //获取设备上不同的摄像头 102 function IRSTType() { 103 var info = new Array(); 104 var index = 0; 105 IRST = device[iii].value.elements; 106 if(IRST.length > 0){ 107 for (iiii = 0; iiii < IRST.length; iiii++) { 108 if (str.charAt(str.length - 1) !== ",") { 109 str += ",nodes:["; 110 } 111 //如果是节点的最后一位 112 if (iiii + 1 === IRST.length) { 113 //定义数组,存储用户登录信息 114 info[index] = new Array(); 115 info[index].push(IRST[iiii].value.szIP,IRST[iiii].value.szUser,IRST[iiii].value.szPassword,IRST[iiii].value.NPort,IRST[iiii].value.NChannel); 116 str += "{id:'" + IRST[iiii].value.szIP + IRST[iiii].value.NChannel + "',tags:['" + info[index] + "'],text:'" + IRST[iiii].key + "'}]"; 117 index++; 118 return 0; 119 } 120 else { 121 info[index] = new Array(); 122 info[index].push(IRST[iiii].value.szIP,IRST[iiii].value.szUser,IRST[iiii].value.szPassword,IRST[iiii].value.NPort,IRST[iiii].value.NChannel); 123 str += "{id:'" + IRST[iiii].value.szIP + IRST[iiii].value.NChannel + "',tags:['" + info[index] + "'],text:'" + IRST[iiii].key + "'},"; 124 index++; 125 } 126 } 127 } 128 return 0; 129 } 130 131 var nodedata = eval(str); 132 133 $("#nationselect").treeview({ 134 //默认只显示第一层级的数据 135 levels: 1, 136 data: nodedata 137 }); 138 139 $('#nationselect').on('nodeSelected', function (event, data) { 140 //数组转字符串 141 var IRSTinfo = data.tags.toString(); 142 //字符串拼接数组 143 var abcArray = IRSTinfo.split(','); 144 //用户登陆IP 145 var IRSTIP = abcArray[0]; 146 //用户登陆名 147 var IRSTUSER = abcArray[1]; 148 //用户登陆密码 149 var IRSTPSW = abcArray[2]; 150 //用户登陆端口号 151 var IRSTPort = abcArray[3]; 152 //摄像头的通道号 153 var IRSTChannel = abcArray[4]; 154 var a = new NationInfo(IRSTIP, IRSTPort, IRSTUSER, IRSTPSW, IRSTChannel); 155 openvideo(a); 156 clickLogin(); 157 }); 158 159 } 160 });
下面就出现了第二个问题,servlet的调用顺序问题,我发现有时候运行的时候,显示的是未定义数据,说明先运行的是获取IRST的servlet,虽然我写的是获取所有设备的servlet的函数在前,于是我将获取所有站点的ajax放在了获取所有IRST的ajax里面的success函数里,完成效果如下:
在node的click时间里添加 clickLogin()函数,点击站点,完成登录
好,获取了站点信息,完成了登陆之后,下面就是安放视频插件个控制按钮,下一篇博客会详细说一下这个流程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构