EventSource 实时传输数据

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 
  4 <head>
  5   <meta charset="UTF-8">
  6   <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7   <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8   <title>Dashboard</title>
  9   <style>
 10     *{margin:0;padding:0;}
 11       /* TV Start */
 12     .RealTimeListTV {
 13         width: 100%;
 14         height: 100%;
 15         overflow: scroll;
 16         background: #030129 url('./image/tvBg.jpg') no-repeat;
 17         background-size: 100% auto;
 18         padding: 136px 0 0 0;
 19         text-align: center;
 20         position: relative;
 21         box-sizing: border-box;
 22     }
 23     .RealTimeListTV .title {
 24         font-size: 76px;
 25         color: #fff;
 26         letter-spacing: 6px;
 27     }
 28     .RealTimeListTV .totalValue {
 29         font-size: 150px;
 30         color: #fff;
 31         letter-spacing: 6px;
 32     }
 33     .RealTimeListTV .totalValue .decoration {
 34         width: 524px;
 35         height: 136px;
 36         display: block;
 37         margin: 0 auto;
 38         background: url('./image/lineH.png') no-repeat;
 39     }
 40     .RealTimeListTV .BusinessUnitList {
 41         display: flex;
 42         justify-content: space-between;
 43         overflow: hidden;
 44         line-height: 50px;
 45         padding: 0 200px;
 46         list-style: none;
 47     }
 48     .BusinessUnitList li {
 49         float: left;
 50         color: #fff;
 51         position: relative;
 52         letter-spacing: 6px;
 53     }
 54     .BusinessUnitList li .name {
 55         font-size: 30px;
 56     }
 57     .BusinessUnitList li .value {
 58         font-size: 36px;
 59     }
 60     .BusinessUnitList li .line {
 61         width: 47px;
 62         height: 48px;
 63         background: url('./image/line.png') no-repeat;
 64         position: absolute;
 65         left: -70px;
 66         top: 0;
 67     }
 68     .main{
 69         margin: 50px auto 0;
 70     }
 71     /* TV End */
 72 
 73 
 74     /* WEB Start */
 75     .RealTimeListWEB{
 76         width: 1280px;
 77         background: #030129 url('./image/webBg.png') no-repeat;
 78         background-size: 100% auto;
 79         padding: 40px 0 0 0;
 80         text-align: center;
 81         position: relative;
 82         box-sizing: border-box;
 83         margin:0 auto;
 84     }
 85 
 86     .RealTimeListWEB .title{
 87         font-size: 46px;
 88         color: #fff;
 89         letter-spacing: 6px;
 90     }
 91     .RealTimeListWEB .totalValue {
 92         font-size: 80px;
 93         color: #fff;
 94         letter-spacing: 6px;
 95     }
 96     .RealTimeListWEB .BusinessUnitList{
 97         list-style: none;
 98         margin-top:110px;
 99     }
100     .RealTimeListWEB .BusinessUnitList::after{
101         content:".";
102         clear:both;
103         display:block;
104         height:0;
105         overflow:hidden;
106         visibility:hidden;
107     }
108 
109 
110     .RealTimeListWEB .BusinessUnitList li{
111         width: 20%;
112         padding-bottom: 30px;
113         letter-spacing: 3px;
114     }
115     .RealTimeListWEB .BusinessUnitList li .line{
116         left: 25px;
117         top: -8px;
118         width: 32px;
119         height: 32px;
120     }
121     .RealTimeListWEB .BusinessUnitList li .name,.RealTimeListWEB .BusinessUnitList li .value{
122         font-size: 20px;
123         padding-bottom: 20px;
124     }
125     .echartsList{
126         margin-top: 200px;
127     }
128     /* WEB End */
129 
130     /* comment */
131     .lageBoxNone,.smallBoxNone{
132             display: none;
133     }
134     @media screen and (min-width:3000px) and (max-width:5000px) {
135         .lageBoxNone{
136             display: block;
137         }
138     }
139     @media only screen and (max-width: 2999px) {
140       .smallBoxNone{
141         display: block;
142       }
143     }
144 
145 
146   </style>
147 </head>
148 
149 <body>
150 
151   <!--  电视尺寸 -->
152   <div class="RealTimeListTV lageBoxNone">
153     <div class="title">总销售额</div>
154     <div class="totalValue">$<span>0.00</span><span class="decoration"></span></div>
155     <ul class="BusinessUnitList">
156       <li> <span class="line"></span> <p class="name">SW事业部</p> <p class="value">$0.00</p></li>
157       <li> <span class="line"></span> <p class="name">SP事业部</p> <p class="value">$0.00</p></li>
158       <li> <span class="line"></span> <p class="name">JFN事业部</p> <p class="value">$0.00</p></li>
159       <li> <span class="line"></span> <p class="name">PJ事业部</p> <p class="value">$0.00</p></li>
160       <li> <span class="line"></span> <p class="name">Pi事业部</p> <p class="value">$0.00</p></li>
161       <li> <span class="line"></span> <p class="name">AG事业部</p> <p class="value">$0.00</p></li>
162       <li> <span class="line"></span> <p class="name">HA事业部</p> <p class="value">$0.00</p></li>
163       <li> <span class="line"></span> <p class="name">Q事业部</p> <p class="value">$0.00</p></li>
164       <li> <span class="line"></span> <p class="name">N事业部</p> <p class="value">$0.00</p></li>
165       <li> <span class="line"></span> <p class="name">GS事业部</p> <p class="value">$0.00</p></li>
166     </ul>
167     <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
168     <div style="padding:0 50px;">
169       <div id="main" class="main" style="width: 100%;height:1500px;"></div>
170     </div>
171 
172   </div>
173 
174   <!-- pc尺寸 -->
175   <div class="RealTimeListWEB smallBoxNone">
176     <div class="title">总销售额</div>
177     <div class="totalValue">$<span>0.00</span></div>
178     <ul class="BusinessUnitList">
179       <li> <span class="line"></span> <p class="name">SW事业部</p> <p class="value">$0.00</p></li>
180       <li> <span class="line"></span> <p class="name">SP事业部</p> <p class="value">$0.00</p></li>
181       <li> <span class="line"></span> <p class="name">JFN事业部</p> <p class="value">$0.00</p></li>
182       <li> <span class="line"></span> <p class="name">PJ事业部</p> <p class="value">$0.00</p></li>
183       <li> <span class="line"></span> <p class="name">Pi事业部</p> <p class="value">$0.00</p></li>
184       <li> <span class="line"></span> <p class="name">AG事业部</p> <p class="value">$0.00</p></li>
185       <li> <span class="line"></span> <p class="name">HA事业部</p> <p class="value">$0.00</p></li>
186       <li> <span class="line"></span> <p class="name">Q事业部</p> <p class="value">$0.00</p></li>
187       <li> <span class="line"></span> <p class="name">N事业部</p> <p class="value">$0.00</p></li>
188       <li> <span class="line"></span> <p class="name">GS事业部</p> <p class="value">$0.00</p></li>
189     </ul>
190     <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
191     <div class="echartsList">
192       <div id="main1" class="main" style="width: 1200px;height:450px;display: none;"></div>
193       <div id="main2" class="main" style="width: 1200px;height:450px;display: none;"></div>
194       <div id="main3" class="main" style="width: 1200px;height:450px;display: none;"></div>
195       <div id="main4" class="main" style="width: 1200px;height:450px;display: none;"></div>
196       <div id="main5" class="main" style="width: 1200px;height:450px;display: none;"></div>
197       <div id="main6" class="main" style="width: 1200px;height:450px;display: none;"></div>
198       <div id="main7" class="main" style="width: 1200px;height:450px;display: none;"></div>
199       <div id="main8" class="main" style="width: 1200px;height:450px;display: none;"></div>
200       <div id="main9" class="main" style="width: 1200px;height:450px;display: none;"></div>
201       <div id="main10" class="main" style="width: 1200px;height:450px;display: none;"></div>
202       <div id="main11" class="main" style="width: 1200px;height:450px;display: none;"></div>
203       <div id="main12" class="main" style="width: 1200px;height:450px;display: none;"></div>
204       <div id="main13" class="main" style="width: 1200px;height:450px;display: none;"></div>
205       <div id="main14" class="main" style="width: 1200px;height:450px;display: none;"></div>
206       <div id="main15" class="main" style="width: 1200px;height:450px;display: none;"></div>
207     </div>
208   </div>
209 
210 </body>
211 <script src='./js/jquery-3.1.0.min.js'></script>
212 <script src="./js/echarts.min.js"></script>
213 <script src="./js/eventsource.min.js"></script>
214 
215 <script type="text/javascript">
216   /*
217       堆叠条形图 公共配置
218     xData: x轴数据 type=category  arr  必填
219     yData: y轴数据 type=value     arr  必填
220     HistogramW:  单个柱状图的宽度   str  如果不传默认是60
221    */
222   // 基于准备好的dom,初始化echarts实例
223   function StackedBarChart(xData, yData, HistogramW) {
224     var yData1 = [],
225       yData2 = [],
226       yData3 = [],
227       yData4 = [],
228       HistogramW = HistogramW ? HistogramW : '60px';
229     for (var i = 0, len = yData.length; i < len; i++) {
230       var cur = yData[i];
231       yData1.push(cur * 0.1 >>> 0);
232       yData2.push(cur * 0.2 >>> 0);
233       yData3.push(cur * 0.3 >>> 0);
234       yData4.push(cur * 0.4 >>> 0);
235     }
236     return {
237       textStyle: {
238         color: '#fff',
239         fontSize: '42px'
240       },
241       tooltip: {
242         trigger: 'axis',
243         axisPointer: { // 坐标轴指示器,坐标轴触发有效
244           type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
245         },
246         show: false
247       },
248       grid: {
249         left: '3%',
250         right: '4%',
251         bottom: '3%',
252         containLabel: true
253       },
254       xAxis: [{
255         type: 'category',
256         axisLine: { // x轴的颜色和宽度
257           lineStyle: {
258             color: '#373750',
259             width: 5 //这里是坐标轴的宽度,可以去掉
260           }
261         },
262         axisLabel: {
263           interval:0,
264           rotate:40
265         },
266         data: xData
267       }],
268       yAxis: [{
269         type: 'value',
270         axisLabel: {
271           show: true,
272           textStyle: {
273             color: '#fff'
274           }
275         },
276         // 控制网格线是否显示
277         splitLine: {
278           show: true,
279           //  改变轴线颜色
280           lineStyle: {
281             // 使用深浅的间隔色
282             color: ['#24243f']
283           }
284         }
285 
286       }],
287       series: [
288 
289         {
290           type: 'bar', //  柱状图
291           stack: '站点总销售额', //  数据堆叠,同个类目轴上系列配置相同的stack值可以堆叠放置
292           itemStyle: {
293             normal: {
294               color: new echarts.graphic.LinearGradient(
295                 0, 0, 0, 1,
296                 [{
297                     offset: 0,
298                     color: '#5fa2bc'
299                   },
300                   {
301                     offset: 0.7,
302                     color: '#9fe595'
303                   }
304                 ]
305               )
306             }
307           },
308 
309           barMaxWidth: HistogramW,
310           data: yData1
311         },
312         {
313           type: 'bar',
314           stack: '站点总销售额',
315           itemStyle: {
316             normal: {
317               color: new echarts.graphic.LinearGradient(
318                 0, 0, 0, 1,
319                 [{
320                     offset: 0,
321                     color: '#fae093'
322                   },
323                   {
324                     offset: 0.7,
325                     color: '#f99c72'
326                   }
327                 ]
328               )
329             }
330           },
331           data: yData2
332         },
333         {
334           type: 'bar',
335           stack: '站点总销售额',
336           itemStyle: {
337             normal: {
338               color: new echarts.graphic.LinearGradient(
339                 0, 0, 0, 1,
340                 [{
341                     offset: 0,
342                     color: '#ff79aa'
343                   },
344                   {
345                     offset: 0.7,
346                     color: '#e9566d'
347                   }
348                 ]
349               )
350             }
351           },
352           data: yData3
353         },
354         {
355           // 只在最后一组数据中显示 label,由于最后一组数据的值来自 total * 0.4,
356           // 由此逆推出总数为 data / 0.4,
357           // >>> 用于去除小数部分
358           label: {
359             show: true,
360             position: 'top',
361             formatter: function (param) {
362               return Math.round(yData[param.dataIndex]);
363             }
364           },
365           type: 'bar',
366           stack: '站点总销售额',
367           itemStyle: {
368             normal: {
369               color: new echarts.graphic.LinearGradient(
370                 0, 0, 0, 1,
371                 [{
372                     offset: 0,
373                     color: '#94c8d3'
374                   },
375                   {
376                     offset: 0.7,
377                     color: '#6a71e4'
378                   }
379                 ]
380               )
381             }
382           },
383           data: yData4
384         },
385 
386       ]
387     };
388   }
389 
390   function SetXYStyle(arr) {
391     return arr.map(function(item) {
392       return {
393         value: item,
394         textStyle: {
395           fontSize: 22
396         }
397       }
398     })
399   }
400   /*  设置电视echarts图表尺寸 */
401   var totalH = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight,
402       titleH = $('.title').outerHeight(true),
403       totalValueH = $('.totalValue').outerHeight(true),
404       businessUnitListH = $('.BusinessUnitList').outerHeight(true),
405       mainH = totalH - titleH - totalValueH - businessUnitListH - 136 - 50 ;
406       $('#main').css('height',mainH+'px');
407 
408 
409 
410   /*---------------- Echarts ---------------- */
411   var is_pc = true,
412       params = 'is_pc=yes',
413       w = window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;
414   if (w > 3000) {
415       is_pc = false;
416       params = 'is_tv=yes'
417   }
418 
419   var source = new EventSource('/rest/dashboard/fetch?' + params, { withCredentials: false, format: 'json' });
420 
421   // open事件 连接一旦建立,就会触发open事件,可以定义相应的回调函数。
422   source.onopen = function (event) {
423       // handle open event
424       console.log('onopen', event)
425   };
426 
427   // error事件  如果发生通信错误(比如连接中断),就会触发error事件。
428   source.onerror = function (event) {
429       // handle error event
430       var data = event.data;
431       if (typeof data == 'string') {
432           data = data.replace(/\n/g,'')
433       }
434       console.log('onerror', data)
435   };
436 
437   // 自定义事件
438   source.addEventListener("whole_total", function (event) {
439       var data = event.data;
440       var origin = event.origin;
441       var lastEventId = event.lastEventId;
442       // handle message
443       if (typeof data == 'string') {
444           data = data.replace(/\n/g,'')
445       }
446 
447       $(".RealTimeListTV .totalValue span").eq(0).text(data)
448       $(".RealTimeListWEB .totalValue span").eq(0).text(data)
449   }, false);
450 
451   // 自定义事件
452   source.addEventListener("depart_total", function (event) {
453       // handle message
454       var data = event.data;
455       // console.log('depart_total', data)
456       if (typeof data == 'string') {
457           data = data.replace(/\n/g,'')
458           data = JSON.parse(data);
459       }
460 
461       var html = '';
462       for (var i=0; i < data.length; i++) {
463         html += '<li>';
464         html += ' <span class="line"></span>';
465         html += ' <p class="name">' + data[i]['name'] + '</p>';
466         html += ' <p class="value">$' + data[i]['data'] + '</p>';
467         html += '</li>';
468       }
469 
470       $('.RealTimeListTV .BusinessUnitList').html(html);
471       $('.RealTimeListWEB .BusinessUnitList').html(html);
472 
473   }, false);
474 
475   // 自定义事件
476   source.addEventListener("site_total", function (event) {
477 
478       var data = event.data;
479 
480       if (typeof data == 'string') {
481           data = data.replace(/\n/g,'')
482           data = JSON.parse(data);
483       }
484       console.log('data.length', data.length)
485 
486       // 循环15个一组, 重新渲染
487       if (is_pc) {
488         /*---------------- WEB Echarts ---------------- */
489         for (var i = 0; i < data.length; i++) {
490           var id = 'main' + (i + 1);
491           $('#' + id).show()
492           var myChart = echarts.init(document.getElementById(id)),
493           xData = data[i].xData,
494           yData = data[i].yData;
495           myChart.setOption(StackedBarChart(xData, yData, '40'));
496         }
497 
498         for (var i=data.length; i<15; i++) {
499             var id = 'main' + (i + 1);
500             $('#' + id).hide()
501         }
502       // 渲染30个一排
503       } else {
504         /* ----------------   TV Echarts ---------------- */
505         var myChart = echarts.init(document.getElementById('main')),
506         xData = data[0].xData
507         yData = data[0].yData;
508         // 使用刚指定的配置项和数据显示图表。
509         myChart.setOption(StackedBarChart(SetXYStyle(xData),yData));
510       }
511 
512   }, false);
513 
514   var last_hart_time = Math.round((new Date()).getTime() / 1000);
515 
516   // 自定义事件
517   source.addEventListener("hart", function (event) {
518       var data = event.data;
519       var origin = event.origin;
520       var lastEventId = event.lastEventId;
521       // handle message
522 
523       if (typeof data == 'string') {
524           data = data.replace(/\n/g,'')
525           data = JSON.parse(data)
526       }
527       var max_delay_seconds = data.max_delay || 5
528       var now_hart_time = Math.round((new Date()).getTime() / 1000);
529       if(now_hart_time - last_hart_time > max_delay_seconds) {
530           $.ajax({
531               url: '/rest/dashboard/hartReply',
532               method: 'POST',
533               data: { uid: data['uid'], token: data['token'] },
534               dataType: 'json',
535               success: function (result) {
536                   last_hart_time = now_hart_time
537                   console.log('reply')
538               }
539           })
540       }
541       console.log('hart')
542   }, false);
543 
544   // 自定义事件
545   source.addEventListener("close", function (event) {
546       var data = event.data;
547       var origin = event.origin;
548       var lastEventId = event.lastEventId;
549       // handle message
550       if (typeof data == 'string') {
551           data = data.replace(/\n/g,'')
552       }
553 
554       // close方法用于关闭连接。
555       source.close();
556       console.log('close', event)
557   }, false);
558 
559 
560 </script>
561 
562 </html>

 

posted @ 2018-11-28 11:35  *小七儿*  阅读(1931)  评论(0编辑  收藏  举报