820 lines
23 KiB
HTML
820 lines
23 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8"/>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||
<title>稳态数据</title>
|
||
<link rel="stylesheet" href="./element.css"/>
|
||
<script src="./vue.js"></script>
|
||
<script src="./echarts.min.js"></script>
|
||
<script src="./jquery.min.js"></script>
|
||
</head>
|
||
<body>
|
||
<div>
|
||
|
||
|
||
<button id="buttonHistory">历史趋势</button>
|
||
<button id="buttonPinPu">谐波频谱</button>
|
||
|
||
<label>设备标识:</label>
|
||
<select id="selectId">
|
||
<option value="NJCN230497">NJCN230497</option>
|
||
<option value="NJCN230497">NJCN230447</option>
|
||
<option value="3206010121">3206010121</option>
|
||
</select>
|
||
|
||
|
||
<button style="margin-left: 100px" id="export">导出历史数据</button>
|
||
|
||
<span style="float: right" id="stationId">xxxxxxxxxxxxxx</span>
|
||
|
||
<span style="float: right;margin-right: 15px" id="timeId">yyyy-MM-dd HH:mm:ss</span>
|
||
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
|
||
<div id="history">
|
||
<div id="mainOne" style="width: 100%;height: 800px"></div>
|
||
<div id="mainTwo" style="width: 100%;height: 800px"></div>
|
||
</div>
|
||
|
||
<div id="pinPu" style="display: none">
|
||
|
||
<div id="pinPuChar" style="width: 100%;height: 800px"></div>
|
||
</div>
|
||
</div>
|
||
<script type="text/javascript">
|
||
|
||
var devId;
|
||
$(function () {
|
||
$('#mainOne').css('height', window.innerHeight / 2 - 20)
|
||
$('#mainTwo').css('height', window.innerHeight / 2 - 20)
|
||
|
||
devId = $('#selectId').find('option:selected').val()
|
||
|
||
var webSocket = getWebSocket();
|
||
initVEchart()
|
||
})
|
||
|
||
|
||
var vEchar;
|
||
var vTime = []
|
||
var vA = []
|
||
var vB = []
|
||
var vC = []
|
||
|
||
var iEchar;
|
||
|
||
var iA = []
|
||
var iB = []
|
||
var iC = []
|
||
|
||
$('#buttonHistory').click(function () {
|
||
$('#pinPu').hide()
|
||
$('#history').show()
|
||
initVEchart()
|
||
})
|
||
|
||
$('#export').click(function () {
|
||
let str = ``;
|
||
if(historyMessage.length > 0){
|
||
|
||
for(let i in historyMessage[0]){
|
||
str+=i+',';
|
||
}
|
||
str = str.substring(0,str.lastIndexOf(','))+'\n'
|
||
|
||
}else {
|
||
alert("当前无历史数据")
|
||
return false
|
||
}
|
||
|
||
|
||
download(str, historyMessage)
|
||
})
|
||
const download = (str, data) => {
|
||
// 增加\t为了不让表格显示科学计数法或者其他格式
|
||
for (let i = 0; i < data.length; i++) {
|
||
for (const key in data[i]) {
|
||
str += `${data[i][key] + '\t'},`;
|
||
}
|
||
str += '\n';
|
||
}
|
||
// encodeURIComponent解决中文乱码
|
||
const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str);
|
||
// 通过创建a标签实现
|
||
const link = document.createElement("a");
|
||
link.href = uri;
|
||
// 对下载的文件命名
|
||
link.download = "下载数据.csv";
|
||
link.click();
|
||
}
|
||
|
||
|
||
function initVEchart() {
|
||
// 基于准备好的dom,初始化echarts实例
|
||
vEchar = echarts.init(document.getElementById('mainOne'));
|
||
vEchar.clear()
|
||
let options = {
|
||
title: {
|
||
left: 'center',
|
||
text: '监测点-相电压有效值',
|
||
textStyle: {
|
||
color: 'black'
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'cross',
|
||
label: {
|
||
backgroundColor: '#283b56'
|
||
}
|
||
}
|
||
},
|
||
legend: {
|
||
left: '80px',
|
||
verticalAlign: 'top',
|
||
enabled: true,
|
||
itemDistance: 5,
|
||
textStyle: {
|
||
rich: {
|
||
a: {
|
||
verticalAlign: 'middle'
|
||
}
|
||
},
|
||
|
||
padding: [0, 0, 0, 0] //[上、右、下、左]
|
||
}
|
||
|
||
},
|
||
xAxis: {
|
||
name: '时间',
|
||
type: 'category',
|
||
value: vTime,
|
||
boundaryGap: true,
|
||
axisLine: {
|
||
show: true,
|
||
onZero: false,
|
||
lineStyle: {
|
||
color: '#000000'
|
||
}
|
||
},
|
||
axisLabel: {
|
||
textStyle: {
|
||
fontFamily: 'dinproRegular',
|
||
color: '#000000'
|
||
}
|
||
}
|
||
},
|
||
yAxis: {
|
||
name: 'V',
|
||
type: 'value',
|
||
axisLabel: {
|
||
interval: 0,
|
||
formatter: function (value, index) {
|
||
return value.toFixed(3)
|
||
},
|
||
left: '20px',
|
||
color: '#000000'
|
||
},
|
||
|
||
axisLine: {
|
||
show: true,
|
||
onZero: false, //-----------重点
|
||
lineStyle: {
|
||
color: '#000000'
|
||
}
|
||
},
|
||
splitLine: {
|
||
lineStyle: {
|
||
// 使用深浅的间隔色
|
||
color: ['#000000'],
|
||
type: 'dashed',
|
||
opacity: 0.5
|
||
}
|
||
}
|
||
},
|
||
series: [
|
||
{
|
||
data: vA,
|
||
type: 'line',
|
||
smooth: true,
|
||
color: '#CC0000',
|
||
name: 'A相',
|
||
symbol: 'none',
|
||
lineStyle: {
|
||
width: 1.5, // 设置折线的宽度为2(单位:像素)
|
||
},
|
||
markPoint: {
|
||
data: [
|
||
{type: 'max', name: '最大值'},
|
||
{type: 'min', name: '最小值'}
|
||
]
|
||
},
|
||
markLine: {
|
||
data: [{type: 'average', name: '平均值'}]
|
||
}
|
||
},
|
||
{
|
||
data: vB,
|
||
name: 'B相',
|
||
type: 'line',
|
||
smooth: true,
|
||
color: '#339900',
|
||
symbol: 'none',
|
||
lineStyle: {
|
||
width: 1.5, // 设置折线的宽度为2(单位:像素)
|
||
},
|
||
markPoint: {
|
||
data: [
|
||
{type: 'max', name: '最大值'},
|
||
{type: 'min', name: '最小值'}
|
||
]
|
||
},
|
||
markLine: {
|
||
data: [{type: 'average', name: '平均值'}]
|
||
}
|
||
},
|
||
{
|
||
data: vC,
|
||
name: 'C相',
|
||
type: 'line',
|
||
color: '#CC9900',
|
||
smooth: true,
|
||
symbol: 'none',
|
||
lineStyle: {
|
||
width: 1.5, // 设置折线的宽度为2(单位:像素)
|
||
},
|
||
markPoint: {
|
||
data: [
|
||
{type: 'max', name: '最大值'},
|
||
{type: 'min', name: '最小值'}
|
||
]
|
||
},
|
||
markLine: {
|
||
data: [{type: 'average', name: '平均值'}]
|
||
}
|
||
}
|
||
]
|
||
}
|
||
vEchar.setOption(options);
|
||
|
||
iEchar = echarts.init(document.getElementById('mainTwo'));
|
||
iEchar.clear()
|
||
let optionsI = {
|
||
title: {
|
||
left: 'center',
|
||
text: '监测点-电流有效值',
|
||
textStyle: {
|
||
color: 'black'
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'cross',
|
||
label: {
|
||
backgroundColor: '#283b56'
|
||
}
|
||
}
|
||
},
|
||
legend: {
|
||
left: '80px',
|
||
verticalAlign: 'top',
|
||
enabled: true,
|
||
itemDistance: 5,
|
||
textStyle: {
|
||
rich: {
|
||
a: {
|
||
verticalAlign: 'middle'
|
||
}
|
||
},
|
||
|
||
padding: [0, 0, 0, 0] //[上、右、下、左]
|
||
}
|
||
|
||
},
|
||
xAxis: {
|
||
name: '时间',
|
||
type: 'category',
|
||
value: vTime,
|
||
boundaryGap: true,
|
||
axisLine: {
|
||
show: true,
|
||
onZero: false,
|
||
lineStyle: {
|
||
color: '#000000'
|
||
}
|
||
},
|
||
axisLabel: {
|
||
textStyle: {
|
||
fontFamily: 'dinproRegular',
|
||
color: '#000000'
|
||
}
|
||
}
|
||
},
|
||
yAxis: {
|
||
name: 'A',
|
||
type: 'value',
|
||
axisLabel: {
|
||
interval: 0,
|
||
formatter: function (value, index) {
|
||
return value.toFixed(3)
|
||
},
|
||
left: '20px',
|
||
color: '#000000'
|
||
},
|
||
|
||
axisLine: {
|
||
show: true,
|
||
onZero: false, //-----------重点
|
||
lineStyle: {
|
||
color: '#000000'
|
||
}
|
||
},
|
||
splitLine: {
|
||
lineStyle: {
|
||
// 使用深浅的间隔色
|
||
color: ['#000000'],
|
||
type: 'dashed',
|
||
opacity: 0.5
|
||
}
|
||
}
|
||
},
|
||
series: [
|
||
{
|
||
data: iA,
|
||
type: 'line',
|
||
smooth: true,
|
||
color: '#CC0000',
|
||
name: 'A相',
|
||
symbol: 'none',
|
||
lineStyle: {
|
||
width: 1.5, // 设置折线的宽度为2(单位:像素)
|
||
},
|
||
markPoint: {
|
||
data: [
|
||
{type: 'max', name: '最大值'},
|
||
{type: 'min', name: '最小值'}
|
||
]
|
||
},
|
||
markLine: {
|
||
data: [{type: 'average', name: '平均值'}]
|
||
}
|
||
},
|
||
{
|
||
data: iB,
|
||
name: 'B相',
|
||
type: 'line',
|
||
smooth: true,
|
||
color: '#339900',
|
||
symbol: 'none',
|
||
lineStyle: {
|
||
width: 1.5, // 设置折线的宽度为2(单位:像素)
|
||
},
|
||
markPoint: {
|
||
data: [
|
||
{type: 'max', name: '最大值'},
|
||
{type: 'min', name: '最小值'}
|
||
]
|
||
},
|
||
markLine: {
|
||
data: [{type: 'average', name: '平均值'}]
|
||
}
|
||
},
|
||
{
|
||
data: iC,
|
||
name: 'C相',
|
||
type: 'line',
|
||
color: '#CC9900',
|
||
smooth: true,
|
||
symbol: 'none',
|
||
lineStyle: {
|
||
width: 1.5, // 设置折线的宽度为2(单位:像素)
|
||
},
|
||
markPoint: {
|
||
data: [
|
||
{type: 'max', name: '最大值'},
|
||
{type: 'min', name: '最小值'}
|
||
]
|
||
},
|
||
markLine: {
|
||
data: [{type: 'average', name: '平均值'}]
|
||
}
|
||
}
|
||
]
|
||
}
|
||
iEchar.setOption(optionsI);
|
||
|
||
}
|
||
|
||
|
||
var historyMessage = []
|
||
|
||
|
||
/**
|
||
* WebSocket客户端
|
||
*
|
||
* 使用说明:
|
||
* 1、WebSocket客户端通过回调函数来接收服务端消息。例如:webSocket.onmessage
|
||
* 2、WebSocket客户端通过send方法来发送消息给服务端。例如:webSocket.send();
|
||
*/
|
||
function getWebSocket() {
|
||
/**
|
||
* 配置 WebSocket
|
||
* WebSocket客户端 PS:URL开头表示WebSocket协议 中间是域名端口 结尾是服务端映射地址
|
||
*/
|
||
var webSocket = new WebSocket('ws://localhost:8790/socket');
|
||
/**
|
||
* 当服务端打开连接
|
||
*/
|
||
webSocket.onopen = function (event) {
|
||
historyMessage = []
|
||
console.log('WebSocket打开连接');
|
||
};
|
||
|
||
/**
|
||
* 当服务端发来消息:1.广播消息 2.更新在线人数
|
||
*/
|
||
webSocket.onmessage = function (event) {
|
||
console.log('WebSocket收到消息:%c' + event.data, 'color:green');
|
||
//获取服务端消息
|
||
var message = JSON.parse(event.data) || {};
|
||
historyMessage.push(message)
|
||
|
||
|
||
devId = $('#selectId').find('option:selected').val()
|
||
if (devId != message.customDevId) {
|
||
return false;
|
||
}
|
||
|
||
$("#timeId").text(message.time.substring(0, 4) + '-' + message.time.substring(4, 6) + '-' + message.time.substring(6, 8) + ' ' + message.time.substring(9, 11) + ':' + message.time.substring(11, 13) + ':' + message.time.substring(13, 15))
|
||
|
||
if (devId == 'NJCN230447') {
|
||
$("#stationId").text("当前位置:保定-满城区-电能质量监测装置-0447")
|
||
|
||
} else if (devId == 'NJCN230497') {
|
||
$("#stationId").text("当前位置:保定-满城区-电能质量监测装置-0497")
|
||
|
||
} else if (devId == '3206010121') {
|
||
$("#stationId").text("当前位置:xx-xx-电能质量监测装置-0121")
|
||
|
||
} else {
|
||
$("#stationId").text("暂无数据")
|
||
}
|
||
if (vTime.length > 50) {
|
||
vTime.shift();
|
||
|
||
vA.shift();
|
||
vB.shift();
|
||
vC.shift();
|
||
iA.shift();
|
||
iB.shift();
|
||
iC.shift();
|
||
}
|
||
|
||
let temDate = message.time
|
||
let aaaDate = temDate.substring(0, 4) + '-' + temDate.substring(4, 6) + '-' + temDate.substring(6, 8) + ' ' + temDate.substring(9, 11) + ':' + temDate.substring(11, 13) + ':' + temDate.substring(13, 15)
|
||
vTime.push(aaaDate)
|
||
vA.push(message.PhV_phsA)
|
||
vB.push(message.PhV_phsB)
|
||
vC.push(message.PhV_phsC)
|
||
|
||
iA.push(message.A_phsA)
|
||
iB.push(message.A_phsB)
|
||
iC.push(message.A_phsC)
|
||
|
||
|
||
vEchar.setOption({
|
||
xAxis: [
|
||
{
|
||
data: vTime
|
||
}
|
||
],
|
||
series: [
|
||
{
|
||
data: vA
|
||
},
|
||
{
|
||
data: vB
|
||
},
|
||
{
|
||
data: vC
|
||
}
|
||
]
|
||
})
|
||
|
||
iEchar.setOption({
|
||
xAxis: [
|
||
{
|
||
data: vTime
|
||
}
|
||
],
|
||
series: [
|
||
{
|
||
data: iA
|
||
},
|
||
{
|
||
data: iB
|
||
},
|
||
{
|
||
data: iC
|
||
}
|
||
]
|
||
})
|
||
|
||
|
||
if (pinPuEcharts) {
|
||
serviseV = []
|
||
for (let i = 2; i < 26; i++) {
|
||
|
||
let temValV = (Number(message['HRPhV_H' + i + '_phsA']) + Number(message['HRPhV_H' + i + '_phsB']) + Number(message['HRPhV_H' + i + '_phsC'])) / 3
|
||
serviseV.push(temValV.toFixed(3))
|
||
}
|
||
|
||
pinPuEcharts.setOption({
|
||
series: [
|
||
{
|
||
data: serviseV
|
||
},
|
||
]
|
||
})
|
||
}
|
||
|
||
|
||
};
|
||
|
||
/**
|
||
* 关闭连接
|
||
*/
|
||
webSocket.onclose = function (event) {
|
||
console.log('WebSocket关闭连接');
|
||
};
|
||
|
||
/**
|
||
* 通信失败
|
||
*/
|
||
webSocket.onerror = function (event) {
|
||
console.log('WebSocket发生异常');
|
||
|
||
};
|
||
return webSocket;
|
||
}
|
||
|
||
|
||
var serviseV = []
|
||
var pinPuEcharts
|
||
$('#buttonPinPu').click(function () {
|
||
$('#pinPu').show()
|
||
$('#history').hide()
|
||
|
||
var pinPuX = []
|
||
for (let i = 2; i < 26; i++) {
|
||
pinPuX.push(i + '次')
|
||
}
|
||
|
||
// 基于准备好的dom,初始化echarts实例
|
||
pinPuEcharts = echarts.init(document.getElementById('pinPuChar'));
|
||
pinPuEcharts.clear()
|
||
|
||
// 指定图表的配置项和数据
|
||
var option = {
|
||
title: {
|
||
left: 'center',
|
||
text: '2~25次谐波电压含有率',
|
||
textStyle: {
|
||
color: 'black'
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'cross',
|
||
label: {
|
||
backgroundColor: '#283b56'
|
||
}
|
||
}
|
||
},
|
||
legend: {
|
||
left: '80px',
|
||
verticalAlign: 'top',
|
||
enabled: true,
|
||
itemDistance: 5,
|
||
textStyle: {
|
||
rich: {
|
||
a: {
|
||
verticalAlign: 'middle'
|
||
}
|
||
},
|
||
|
||
padding: [0, 0, 0, 0] //[上、右、下、左]
|
||
}
|
||
|
||
},
|
||
xAxis: {
|
||
name: '次数',
|
||
data: pinPuX,
|
||
boundaryGap: true,
|
||
axisLine: {
|
||
show: true,
|
||
onZero: false,
|
||
lineStyle: {
|
||
color: '#000000'
|
||
}
|
||
},
|
||
axisLabel: {
|
||
textStyle: {
|
||
fontFamily: 'dinproRegular',
|
||
color: '#000000'
|
||
}
|
||
}
|
||
},
|
||
yAxis: {
|
||
name: '%',
|
||
boundaryGap: true,
|
||
axisLine: {
|
||
show: true,
|
||
onZero: false,
|
||
lineStyle: {
|
||
color: '#000000'
|
||
}
|
||
},
|
||
axisLabel: {
|
||
textStyle: {
|
||
fontFamily: 'dinproRegular',
|
||
color: '#000000'
|
||
}
|
||
}
|
||
},
|
||
series: [
|
||
{
|
||
name: '谐波电压含有率',
|
||
type: 'bar',
|
||
data: serviseV,
|
||
color: '#339966'
|
||
},
|
||
{
|
||
color: '#FF9900',
|
||
name: '限值',
|
||
type: 'bar',
|
||
data: [
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8,
|
||
1.6,
|
||
0.8
|
||
]
|
||
}
|
||
]
|
||
};
|
||
|
||
// 使用刚指定的配置项和数据显示图表。
|
||
pinPuEcharts.setOption(option);
|
||
})
|
||
|
||
|
||
$("#selectId").change(function () {
|
||
vTime = []
|
||
vA = []
|
||
vB = []
|
||
vC = []
|
||
iA = []
|
||
iB = []
|
||
iC = []
|
||
|
||
serviseV = []
|
||
|
||
vEchar.setOption({
|
||
xAxis: [
|
||
{
|
||
data: vTime
|
||
}
|
||
],
|
||
series: [
|
||
{
|
||
data: vA
|
||
},
|
||
{
|
||
data: vB
|
||
},
|
||
{
|
||
data: vC
|
||
}
|
||
]
|
||
})
|
||
|
||
iEchar.setOption({
|
||
xAxis: [
|
||
{
|
||
data: vTime
|
||
}
|
||
],
|
||
series: [
|
||
{
|
||
data: iA
|
||
},
|
||
{
|
||
data: iB
|
||
},
|
||
{
|
||
data: iC
|
||
}
|
||
]
|
||
})
|
||
|
||
pinPuEcharts.setOption({
|
||
series: [
|
||
{
|
||
data: serviseV
|
||
},
|
||
]
|
||
})
|
||
})
|
||
</script>
|
||
|
||
|
||
</body>
|
||
<style>
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
}
|
||
|
||
table caption {
|
||
font-size: 2em;
|
||
font-weight: bold;
|
||
margin: 1em 0;
|
||
}
|
||
|
||
th, td {
|
||
border: 1px solid #999;
|
||
text-align: center;
|
||
padding: 6px 0;
|
||
}
|
||
|
||
table thead tr {
|
||
background-color: #008c8c;
|
||
color: #fff;
|
||
}
|
||
|
||
table tbody tr:nth-child(odd) {
|
||
background-color: #eee;
|
||
}
|
||
|
||
table tbody tr:hover {
|
||
background-color: #ccc;
|
||
}
|
||
|
||
table tbody tr td:first-child {
|
||
color: #3d34fc;
|
||
}
|
||
|
||
table tfoot tr td {
|
||
text-align: right;
|
||
padding-right: 20px;
|
||
}
|
||
</style>
|
||
</html>
|