前言:
而今大家对“jquery自由编辑组态图库”大约比较注意,同学们都想要分析一些“jquery自由编辑组态图库”的相关资讯。那么小编在网摘上搜集了一些对于“jquery自由编辑组态图库””的相关内容,希望小伙伴们能喜欢,各位老铁们快快来学习一下吧!近年来,数据可视化大屏的出现,掀起一番又一番的浪潮,众多企业主纷纷想要打造属于自己的 “酷炫吊炸天” 的霸道总裁大屏驾驶舱。今天为大家分享的是 【物联网平台数据统计】。
话不多说,开始分享干货,欢迎讨论!
首先看动态效果图 :
再看实时分片数据图:
一、 确定需求方案
1、确定产品上线部署的屏幕LED分辨率
1280px*768px,F11全屏后占满整屏且无滚动条;其它分辨率屏幕均可自适应显示。
2、功能模块
平台数据分布在线 离线设备在线情况接入工厂类型监控列表告警信息报警记录数据记录
3、部署方式
基于免安装可执行程序:支持Windows、Linux、Mac等各种主流操作系统;将可执行程序exe复制到服务器上即可,无需其它环境依赖;
观看方式:既可在服务器上直接观看程序界面,也可远程使用浏览器打开播放,支持Chrome浏览器、360浏览器等主流浏览器。
二、整体架构设计
前端基于Echarts开源库设计,使用WebStorm编辑器;后端基于Python Web实现,使用Pycharm编辑器;数据传输格式:JSON;数据源类型:目前已支持PostgreSQL、MySQL、Oracle、Microsoft SQL Server、SQLite、Excel表格等,还可以定制HTTP API接口方式或其它类型数据库。数据更新方式:摒弃了前端页面定时拉取的方式(这种方式带来严重的资源浪费),采用后端数据实时更新,实时推送到前端展示;
三、编码实现 (基于篇幅及可读性考虑,此处展示部分关键代码)
1.前端html代码
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>数据大屏</title> <link rel="stylesheet" href="css/style.css" /> <script type="text/javascript" src="js/jquery-1.8.0.min.js"></script> </head> <body> <header> 物联网平台数据统计案例 <span id=localtime style=" font-size:14px; position: absolute; right: 30px; top:-20px; "></span> </header> <div id="content"> <div class="content_left"> <div class="dtuplc"> <div class="dtu"> <div id="container" style="height: 100%;"></div> </div> <div class="plc"> <div id="container1" style="height: 100%"></div> </div> </div> <!-- DTU和PLC完 --> <div class="online"> <div class="title"><img src="images/icon01.png" /> 设备在线情况</div> <div class="online_con" id="container2"> </div> </div> <div class="industry"> <div class="title"><img src="images/icon02.png" /> 接入工厂类型</div> <div class="industry_con" id="container3"></div> </div> </div> <div class="content_center"> <div class="center_top"> <div class="title"><img src="images/icon03.png" /> 平台数据分布</div> <div class="center_top_con" id="distribution_map"> </div> </div> <div class="center_bot"> <table class="panel-table"bordercolor="#0d48e0" border="1"> <thead bgcolor="#0e4ae0" align="center" > <tr height="40"> <th colspan="6"><img src="images/icon04.png" /> 监控列表</th> </tr> </thead> <tbody> <tr class="aaa" align="center"> <td v-for="item in factoryHeader" style="color: #00fcff; font-size: 18px; padding: 5px 0;">{{ item.categories }}</td> </tr> <tr v-for="y in factory.slice(0,6)" class="aaa" style="font-size: 16px;" align="center" > <td>{{ y.company }}</td> <td>{{ y.dtuCnt }}</td> <td>{{ y.plcCnt }}</td> <td>{{ y.dataCnt }}</td> <td>{{ y.alarm }}</td> <td width="250"> <button class="b1 click_pop">报警记录</button> <button class="b2 click_pop2">历史数据</button> <button class="b3 click_pop3">组态应用</button> </td> </tr> </tbody> </table> </div> </div> <div class="content_right"> <div class="report"> <div class="report1"> <p>告警信息</p> <small>{{alarm.alarm}}条</small> </div> <div class="report2"> <p>故障信息</p> <small>{{alarm.fault}}条</small> </div> </div> <div class="news_report"> <div class="title"><img src="images/icon05.png" /> 报警记录</div> <div class="news_list"> <ul> <li v-for="item in almMsg.slice(0,3)" class="li02"> {{ item.msg }} </li> </ul> </div> </div> <div class="data_box"> <div class="title"><img src="images/icon06.png" /> 数据记录</div> <div class="data_con" id="container4"> </div> </div> </div> </div> <!--遮罩层--> <div class="bgPop"></div> <!--弹出框--> <div class="pop"> <div class="pop-top"> 报警记录 <span class="pop-close">X</span> </div> <div class="pop-content"> <table class="panel-table" bordercolor="#deefff" border="1"> <thead bgcolor="#971212" align="center" > <tr height="38"> <th>字段</th> <th>字段</th> <th>字段</th> <th>字段</th> <th>字段</th> </tr> </thead> <tbody> <tr class="aaa" style="font-size: 16px;" align="center" > <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr class="aaa" style="font-size: 16px;" align="center" > <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr class="aaa" style="font-size: 16px;" align="center" > <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr class="aaa" style="font-size: 16px;" align="center" > <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> </tbody> </table> </div> <div class="pop-foot"> <input type="button" value="确定" class="pop-cancel pop-close"> </div> </div> <script> $(document).ready(function () { $('.pop-close').click(function () { $('.bgPop,.pop').hide(); }); $('.click_pop').click(function () { $('.bgPop,.pop').show(); }); }) </script> <!--遮罩层--> <div class="bgPop2"></div> <!--弹出框--> <div class="pop2"> <div class="pop-top"> 历史记录 <span class="pop-close">X</span> </div> <div class="pop-content"> <table class="panel-table" bordercolor="#deefff" border="1"> <thead bgcolor="#10aaa5" align="center" > <tr height="38"> <th>字段</th> <th>字段</th> <th>字段</th> <th>字段</th> <th>字段</th> </tr> </thead> <tbody> <tr class="aaa" style="font-size: 16px;" align="center" > <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr class="aaa" style="font-size: 16px;" align="center" > <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr class="aaa" style="font-size: 16px;" align="center" > <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr class="aaa" style="font-size: 16px;" align="center" > <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> </tbody> </table> </div> <div class="pop-foot"> <input type="button" value="确定" class="pop-cancel pop-close"> </div> </div> <script> $(document).ready(function () { $('.pop-close').click(function () { $('.bgPop2,.pop2').hide(); }); $('.click_pop2').click(function () { $('.bgPop2,.pop2').show(); }); }) </script> <!--遮罩层--> <div class="bgPop3"></div> <!--弹出框--> <div class="pop3"> <div class="pop-top"> 组态应用 <span class="pop-close">X</span> </div> <div class="pop-content"> 组态应用 </div> <div class="pop-foot"> <input type="button" value="确定" class="pop-cancel pop-close"> </div> </div> <script> $(document).ready(function () { $('.pop-close').click(function () { $('.bgPop3,.pop3').hide(); }); $('.click_pop3').click(function () { $('.bgPop3,.pop3').show(); }); }) </script> <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript" src="js/echarts.min.js"></script> <script type="text/javascript" src="js/china.js"></script> <script type="text/javascript" src="js/vue.min.js"></script> <script type="text/javascript" src="js/map.js"></script> <script type="text/javascript" src="js/times.js"></script> <script type="text/javascript" src="js/DTU.js"></script> <script type="text/javascript" src="js/PLC.js"></script> <script type="text/javascript" src="js/online.js"></script> <script type="text/javascript" src="js/industry.js"></script> <script type="text/javascript" src="js/data.js"></script> <script type="text/javascript" src="js/index.js"></script> <script> function async_data() { async_map_data(); async_chart_1(); async_chart_2(); async_chart_3(); async_chart_4(); async_chart_5(); async_chart_6(); } async_data() ; </script> </body></html>
2.前端JS代码
var scn_data={ alarm:{alarm:10,fault:10}, dtu:{ on:150,off:150}, plc:{on:10,off:10}, industy:{v1:10,v2:11,v3:12,v3:14,v4:15,v5:17,v6:18}, online:{v1:10,v2:11,v3:12,v3:14,v4:15,v5:17,v6:18}, almMsg:[{msg:"2017年5月4日市A区12#机器气压过高报警"}, {msg:"上海市A区12#机器气压过高报警"}, {msg:"江苏省12#机器气压过高报警"}, {msg:"河南省郑州市B区12#机器气压过高报警"}, {msg:"河南省郑州市B区12#机器气压过高报警"}, {msg:"河南省郑州市B区12#机器气压过高报警"}, {msg:"河南省郑州市B区12#机器气压过高报警"} ], msgCnt:[{msg:100,alm:20}, {msg:200,alm:40}, {msg:300,alm:50}, {msg:400,alm:35}, {msg:400,alm:40}, {msg:400,alm:11}, {msg:400,alm:66}, {msg:100,alm:77}, {msg:200,alm:88}, {msg:300,alm:22}, {msg:400,alm:99}, {msg:400,alm:100}, {msg:400,alm:111}, {msg:400,alm:222}, {msg:100,alm:333}, {msg:200,alm:11}, {msg:300,alm:33}, {msg:400,alm:55}, {msg:400,alm:77}, {msg:400,alm:90} ], map:[{area:"山东",cnt:20}, {area:"浙江",cnt:40}, {area:"江苏",cnt:50}, {area:"辽宁",cnt:50} ], factoryHeader:[ {"categories":"单位名"}, {"categories":"网关数"}, {"categories":"设备数"}, {"categories":"数据点"}, {"categories":"报警"}, {"categories":"操作"} ], factory:[ {"company":"宝钢","dtuCnt": 200, "plcCnt": 400,"dataCnt": 5000,"alarm": "无"}, {"company":"造纸厂","dtuCnt": 3000,"plcCnt": 2000,"dataCnt": 1000,"alarm": "无"}, {"company":"锅炉厂","dtuCnt": 1500,"plcCnt": 1000,"dataCnt": 500,"alarm": "无"}, {"company":"锅炉二厂","dtuCnt": 1500,"plcCnt": 300,"dataCnt": 1200,"alarm": "温度上限报警>120"}, {"company":"锅炉三厂","dtuCnt": 1000,"plcCnt": 800,"dataCnt": 200,"alarm": "无"}, {"company":"锅炉三厂","dtuCnt": 1000,"plcCnt": 800,"dataCnt": 200,"alarm": "无"}, {"company":"锅炉三厂","dtuCnt": 1000,"plcCnt": 800,"dataCnt": 200,"alarm": "无"}, {"company":"锅炉三厂","dtuCnt": 1000,"plcCnt": 800,"dataCnt": 200,"alarm": "无"}, {"company":"锅炉三厂","dtuCnt": 1000,"plcCnt": 800,"dataCnt": 200,"alarm": "无"}, {"company":"锅炉三厂","dtuCnt": 1000,"plcCnt": 800,"dataCnt": 200,"alarm": "无"} ] };var vm = new Vue({ el: '#content', data: scn_data, methods: { details: function() { } }})
3.后端python代码
import _threadimport sysfrom PyQt5.QtWidgets import *from PyQt5.QtCore import *from PyQt5.QtWebEngineWidgets import QWebEngineViewfrom pyecharts import Geofrom PyQt5.QtCore import QUrlfrom win32api import GetSystemMetricsfrom PyQt5 import QtGuifrom httpserver import *from asyncJson import * class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.loadfinished = False self.setWindowTitle('大屏展示') self.showMaximized() #全屏显示 self.showFullScreen() self.isFullScreen = True self.webview = WebEngineView() self.webview.load(QUrl(index_url)) self.setCentralWidget(self.webview) QShortcut(QtGui.QKeySequence("Escape"), self, self.Esc) self.webview.loadFinished.connect(self.SetLoadFinished) _thread.start_new_thread(HttpServer, ()) _thread.start_new_thread(self.ChangeData, ()) def SetLoadFinished(self): self.loadfinished = True #模拟刷新数据 def ChangeData(self): while 1: time.sleep(3) #页面加载完毕再开始刷新数据 if self.loadfinished == False : continue change_all_json() # change_chart_map() try: self.webview.page().runJavaScript("async_data()") except Exception as e: print(e) #按ESC全屏或缩小 def Esc(self): if self.isFullScreen == True : self.isFullScreen = False #不加这句的话,标题栏就看不到了 self.showNormal() #设置固定宽高 self.setGeometry(GetSystemMetrics(0)/2, GetSystemMetrics(1)/2, 1280, 768) #再移动到屏幕中央 screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) else: self.showFullScreen() self.isFullScreen = True class WebEngineView(QWebEngineView): windowList = [] # 重写createwindow() def createWindow(self, QWebEnginePage_WebWindowType): new_webview = WebEngineView() new_window = MainWindow() new_window.setCentralWidget(new_webview) #new_window.show() self.windowList.append(new_window) #注:没有这句会崩溃!!! return new_webview if __name__ == "__main__": app = QApplication(sys.argv) w = MainWindow() w.show() sys.exit(app.exec_())
四、上线运行
本次分享结束,欢迎讨论!
感谢:本项目引用了互联网大牛的前端代码,然后定制开发实现了后端服务器,最终实现了可视化大屏的完整方案。