物联网平台 +Web 组态
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

875 lines
37 KiB

2 years ago
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="./css/index.css">
<link rel="stylesheet" href="../../lib/iview/dist/styles/iview.css">
<script src="../common/util.js"></script>
<script src="../../lib/bigscreen/lib/jquery/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="../../lib/layer/layer.js"></script>
<script src="../../lib/bigscreen/js/vue.min.js"></script>
<script src="../../lib/iview/dist/iview.js"></script>
<script src="../../lib/echarts/echarts.min.js"></script>
<script src="http://api.map.baidu.com/api?v=3.0&ak=q5uqiBY29eEu0wNIAPoCXwq1HvUmDzqP"></script>
<script type="text/javascript" src="../../lib/mqtt/mqtt.min.js"></script>
<script>
function fun_date(num) {
var date1 = new Date();
//今天时间
var time1 = date1.getFullYear() + "-" + (date1.getMonth() + 1) + "-" + date1.getDate()
var date2 = new Date(date1);
date2.setDate(date1.getDate() + num);
//num是正数表示之后的时间,num负数表示之前的时间,0表示今天
var time2 = date2.getFullYear() + "-" + (date2.getMonth() + 1) + "-" + date2.getDate();
return time2;
}
function FormatTime (time) {
var fmt = "yyyy/MM/dd hh:mm:ss";
var datetime = new Date();
datetime.setTime(time);
var o = {
"M+": datetime.getMonth() + 1,
"d+": datetime.getDate(),
"h+": datetime.getHours(),
"m+": datetime.getMinutes(),
"s+": datetime.getSeconds(),
"q+": Math.floor((datetime.getMonth() + 3) / 3),
"S": datetime.getMilliseconds()
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (datetime.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
};
</script>
<title>设备详情页</title>
</head>
<body>
<div id="app" v-cloak>
<!-- <div class="d-head-title"> -->
<!-- <span class="small">设备运行监测</span> -->
<!-- </div> -->
<Row :gutter="16">
<i-col span="12">
<Card class="box-Card">
<div slot="title" class="clearfix">
<span class="d-common-title">设备信息</span>
</div>
<div>
<Row>
<i-col span="13" style="height:126px;padding-left:20px;">
<div style="margin-top: 15px;">
<span class="d-font-bold">所属项目</span>
<span v-cloak>: {{scene_name}}</span>
</div>
<div>
<span class="d-font-bold">设备名称</span>
<span v-cloak>: {{device_name}}</span>
</div>
<div>
<span class="d-font-bold">设备SN号</span>
<span v-cloak>: {{device_code}}</span>
</div>
</i-col>
<i-col span="11">
<div style="margin-top: 15px;">
<span class="d-font-bold">在线状态</span>
<span>: </span>
<Tag size="mini" :color="nowtype" v-cloak>{{state}}</Tag>
</div>
<div>
<span class="d-font-bold">通讯协议</span>
<span v-cloak>: {{iot_node_type}}</span>
</div>
<div>
<span class="d-font-bold">经纬度</span>
<span v-cloak>: {{lonLat}}</span>
</div>
</i-col>
</Row>
</div>
</Card>
</i-col>
<i-col span="12">
<Card class="box-Card">
<div slot="title" class="clearfix">
<span class="d-common-title">设备地图</span>
</div>
<div id="dmap">
</div>
</Card>
</i-col>
</Row>
<Card class="d-bottom-card">
<div slot="title">
<Row>
<i-col span="20">
<span class="d-common-title">运行监测</span>
<span> - </span>
<span>设备实时数据</span>
</i-col>
</Row>
</div>
<Row v-for="(item,i) in dotList">
<i-col span="8" v-for="innerItem in item" >
<!-- @click="chart(innerItem)" -->
<div>
<div v-if="innerItem.name" style="width:100%;">
<Row class="img-set" align="middle">
<i-col span="4">
<img :src="innerItem.picUrl" class="sensor-img">
</i-col>
<i-col span="11">
<div v-cloak class="name-wrap">
{{innerItem.name}}
</div>
<div v-cloak class="time-wrap">
{{innerItem.mtime}}
</div>
</i-col>
<i-col style="overflow: hidden;text-overflow:ellipsis;white-space: nowrap;" span="9" class="data-wrap">
<span v-cloak v-if="innerItem.iot_sensor_type!=27">
{{innerItem.showSensorTtype}}
</span>
<i-switch
:loading="isload"
@on-change="onChange(innerItem)"
v-if="innerItem.iot_sensor_type==27"
v-model="innerItem.ison">
</i-switch>
<img @click="downparam(innerItem.id)" v-if="innerItem.readType == 1" class="editicon" src="../../image/wechat/iot/edit.png">
</i-col>
</Row>
</div>
</div>
</i-col>
</Row>
</Card>
<Card style="margin-top:10px" >
<div slot="title">
<Row>
<i-col span="20">
<span class="d-common-title">参数配置</span>
<span> - </span>
<span>设备配置信息</span>
</i-col>
</Row>
</div>
<Row :gutter="16">
<i-col :key="index" v-for="(item,index) in paramsdata" span="12" style="margin-bottom:10px;" >
<Card :key="index">
<p slot="title" v-cloak>
{{item.name}}
</p>
<div slot="extra">
<span v-cloak style="margin-right:20px;">更新时间:{{FormatTime(item.mtime)}}</span>
<i-button size="small" style="margin-top:-5px;" @click="downparam(item.id)" type="primary">参数下发</i-button>
<!-- <i-button size="small" style="margin-top:-5px;" @click="getparams(item)" type="success">读取参数</i-button> set(item) -->
</div>
<Row style="margin:8px 0;">
<i-col v-cloak style="margin-top:6px;" span="12">
{{item.sdata}} <span style="color:#999;margin-left: 30px;">{{item.param_config}}</span>
</i-col>
</Row>
<div>
<span>备注:</span>
<span v-cloak>设置{{item.param_names}}</span>
</div>
</Card>
</i-col>
</Row>
</Card>
<Card style="margin-top:10px" >
<div slot="title">
<Row>
<i-col span="20">
<span class="d-common-title">规则配置</span>
<span> - </span>
<span>触发器信息</span>
</i-col>
</Row>
</div>
<i-table border :columns="columns1" :data="tableData"></i-table>
</Card>
</div>
<script>
var map=null;
var id = getQueryString('id') ;
new Vue({
el: '#app',
data: function() {
return {
tableData: [],
columns1: [
{
title: '序号',
width: 70,
key: 'index'
},
{
title: '触发器名称',
key: 'name'
},
{
title: '关联传感器',
key: 'from_sensor_name'
},
{
title: '触发条件',
key: 'tiaojian'
},
{
title: '触发条件参数',
key: 'condition_params'
},
{
title: '报警开关',
key: 'kaiguan'
}, {
title: '触发器状态',
key: 'zhuangtai',
render:(h,params)=>{
return h('span',{
style:{
color:params.row.zhuangtai=='暂停'?'red':'#3499da'
}
},params.row.zhuangtai)
}
}
, {
title: '触发循环时间',
key: 'trigger_inteval_time',
width:140
},
{
title: '操作',
key: 'action',
width: 150,
render: (h, params) => {
return h('div', [
h('Tooltip', {
props: {
content:params.row.iot_trigger_status==43?'暂停':'开启',
placement: "top"
},
},[
h('span', {
class:params.row.iot_trigger_status==43?'self-icon icon-pause':'self-icon icon-play',
on: {
click: () => {
this.pause(params)
}
}
}, '')
], '')
]);
}
}
],
chartList:[],
paramsdata:[],
isload:false,
dotList:[],
nowtype:'success',
device_name:'',
lonLat:'',
scene_name:'',
device_code:'',
state:'',
iot_node_type:'',
deviceID:'',
productOptions:[],
deviceDotOptions:[],
deviceOptions:[],
client: null ,
idsArr:[],
lastTime: new Date().getTime() ,
iotNodeStatus: null ,
search: {
deviceDot: [],
timeDistance:'',
device: '',
product:''
}
}
},
methods:{
pause(val){
var that=this
this.$Modal.confirm({
title: val.row.iot_trigger_status==43?'是否暂停':'是否开启',
width:'300px',
className:'vertical-center-modal',
style:{top:'220px'},
content:'',
onOk: () => {
$.ajax({
type:'PUT',
url:baseurl+'/service/trigger.json',
contentType: 'application/json',
dataType: "json",
data:JSON.stringify({
id:val.row.id,
iot_trigger_status:val.row.iot_trigger_status==43?44:43
}),
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.status==2){
that.getTableData()
that.$Message.success('操作成功!');
}else{
that.$Message.error(e.statusMsg)
}
},
error: function (e) {
console.log(e)
}
});
}
})
},
downparam(id){
var that = this ;
layer.prompt({title: '数据下发', formType: 3}, function(val, index){
commonAjax('PUT',baseurl+'/service/sensor/param/down.json', {sdata : val ,id:id },function(data){
if(data.status == 2){
that.$Message.success("写指令下发成功!");
}else{
that.$Message.error(data.statusMsg);
}
});
layer.close(index);
});
},
remove(val){
var that=this
this.$Modal.confirm({
title: '是否删除?',
width:'300px',
className:'vertical-center-modal',
style:{top:'220px'},
content: '',
onOk: () => {
$.ajax({
type:'delete',
url:baseurl+'/service/trigger.json?id='+val.row.id,
contentType: 'application/json',
dataType: "json",
data:JSON.stringify({
}),
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.status==2){
that.getTableData()
that.$Message.success('操作成功!');
}else{
that.$Message.error(e.statusMsg);
}
},
error: function (e) {
console.log(e)
}
});
}
})
},
getTableData(){
var that=this
$.ajax({
type:'post',
url:baseurl+'/service/page/trigger?paged=1',
contentType: 'application/json',
dataType: "json",
data:JSON.stringify({
"node_id": id
}),
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.status==2){
that.tableData=e.data.data.map((item,index)=>{
item.index=index+1
item.tiaojian=item.data.iot_trigger_condition_type
item.kaiguan=item.data.iot_trigger_alarm_flag
item.zhuangtai=item.data.iot_trigger_status
return item
})
}else{
that.tableData=[]
}
},
error: function (e) {
console.log(e)
}
});
},
chart(item){
},
mqttInit(){
var that = this ;
// 连接选项
var client = this.client ;
const options = {
connectTimeout: 4000, // 超时时间
// 认证信息
clientId: 'brower_' + parseInt(Math.random()/31.1*10000000000),
username: mqttUserName ,
password: mqttPassword ,
}
client = mqtt.connect('ws://'+document.domain+':8083/mqtt', options) ;
client.on('reconnect', function(error) {
console.log("reconnect");
})
client.on('error', function(error) {
console.log('连接失败:', error)
})
client.on('message', function(topic, message,s) {
if( message.toString() == '1' ){
if( that.lastTime + 3*1000 < new Date().getTime() ){
that.getDevData()
that.getSet()
that.getDevDots();
that.lastTime = new Date().getTime() ;
}
}
})
client.subscribe("/node/update/"+ id );
client.publish('/sys/update/node' , id );
},
getDsv(value ,status ){
if( status != 16 ){
return "-" ;
}else{
return value ;
}
},
getSwitch(value, status){
if( status != 16 ){
return 0 ;
}else{
return value ;
}
},
setChart(data,id){
let dataArr=data.data
var myChart = echarts.init(document.getElementById(id));
let ydata=[];
var xdata=[]
for(var i=0;i<dataArr.length;i++){
xdata.push(FormatTime(dataArr[i].atime))
ydata.push(dataArr[i].sdata)
}
option = {
title: {
text: ''
},
tooltip: {
trigger: 'axis',
axisPointer: {
animation: false,
type: 'cross'
}
},
dataZoom: [
{
show: true,
realtime: true,
start: 65,
end: 85
},
{
type: 'inside',
realtime: true,
start: 65,
end: 85
}
],
xAxis: {
type: 'category',
data:xdata.reverse(),
boundaryGap: false,
axisLabel:{
formatter: function (value, index) {
return value.replace(' ', '\n');
}
},
splitLine: {
            show: false
        }
},
yAxis: {
type: 'value',
name: data.name,
nameTextStyle:{
color:"#2a53cd",
fontSize:16,
padding:10
}
},
series:[
{
type: 'line',
data: ydata.reverse(),
smooth: true,
lineStyle: {
opacity: 0.5
}
},
]
}
myChart.setOption(option, true);
},
getChart(item){
var that=this
this.isload=true
$.ajax({
type:'post',
url:baseurl+'/service/page/sensor/history.json?paged=1&pageSize=400',
contentType: 'application/json',
dataType: "json",
data:JSON.stringify({
"sensor_id":item.id ,
start_time:fun_date(-6)+' 00:00:00',
end_time: fun_date(0)+" 23:59:59"
}),
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.status==2){
e.data.name=item.name
that.chartList.push(e.data)
that.$nextTick(() => {
for(var i=0;i<that.chartList.length;i++){
that.setChart(that.chartList[i],'chart'+i)
}
})
}else{
that.chartList.push({
data:[],
name:item.name
})
that.$nextTick(() => {
for(var i=0;i<that.chartList.length;i++){
that.setChart(that.chartList[i],'chart'+i)
}
})
}
},
error: function (e) {
}
});
},
onChange(val){
var that=this ;
if( that.iotNodeStatus != 16 ){
that.$Message.error('设备已离线');
that.getDevDots();
return ;
}
this.isload=true ;
$.ajax({
type:'PUT',
url:baseurl+'/service/sensor/control/realtime/update',
contentType: 'application/json',
dataType: "json",
data:JSON.stringify({
id: val.id,
request_sdata: val.ison?1:0
}),
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.status==2){
that.$Message.success('操作成功');
}else{
that.$Message.error(e.statusMsg);
}
setTimeout(() => {
that.isload=false ;
}, 800);
that.lastTime = that.lastTime - 3*1000 ;
},
error: function (e) {
}
});
},
getparams(val){
var that=this
$.ajax({
type:'PUT',
url:baseurl+'/service/sensor/param/read.json',
contentType: 'application/json',
dataType: "json",
data:JSON.stringify({
id:val.id
}),
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.status==2){
that.$Message.success('操作成功');
that.getSet()
}else{
that.$Message.error(e.statusMsg);
}
},
error: function (e) {
}
});
},
set(val){
var that=this
$.ajax({
type:'PUT',
url:baseurl+'/service/sensor/param/down.json',
contentType: 'application/json',
dataType: "json",
data:JSON.stringify({
sdata:Number(val.sdata),
id:val.id
}),
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.status==2){
that.$Message.success('操作成功');
setTimeout(function(){
that.getSet()
},3000)
}else{
that.$Message.error(e.statusMsg);
}
},
error: function (e) {
}
});
},
getSet(){
var that=this
$.ajax({
type:'POSt',
url:baseurl+'/service/page/sensor?paged=1',
contentType: 'application/json',
dataType: "json",
data:JSON.stringify({
data_type:1,
node_id:id
}),
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.data){
that.paramsdata=e.data.data
}
},
error: function (e) {
}
});
},
getDevDots(){
var that=this
$.ajax({
type:'POSt',
url:baseurl+'/service/page/sensor?paged=1&pageSize=100',
contentType: 'application/json',
dataType: "json",
data:JSON.stringify({
data_type:0,
node_id: id
}),
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.data==null){
return
}
var allDotData=e.data.data ;
var listData=[] ;
for(var i=0;i<allDotData.length;i++){
var obj={
id: allDotData[i].id,
name:allDotData[i].name,
mtime:FormatTime(allDotData[i].mtime),
str_sdata:allDotData[i].str_sdata,
sdata:allDotData[i].sdata,
iot_sensor_type:allDotData[i].iot_sensor_type,
data:allDotData[i].data,
readType: JSON.parse(gdv(allDotData[i].infos,'{}')).readType ,
picUrl:baseurl+'/image/oss/iot/'+allDotData[i].measure_unit_type+'.png'
}
listData.push(obj)
}
var lenData = 3 - listData.length % 3 ;
for(var i=0;i<lenData;i++){
listData.push({})
}
// 设置没有数值时,不显示数据
setTimeout( function() {
that.dotList=[] ;
for(var i=0;i<listData.length;i++){
var showSensorTtype=''
switch(listData[i].iot_sensor_type){
case 25:
showSensorTtype= that.getDsv(listData[i].sdata, that.iotNodeStatus )+ " "+ listData[i].data.measure_unit_type
break;
case 26:
showSensorTtype= that.getDsv(listData[i].data.measure_unit_type,that.iotNodeStatus )
break;
case 27:
showSensorTtype= that.getDsv(listData[i].data.measure_unit_type ,that.iotNodeStatus )
break;
case 90:
showSensorTtype= that.getDsv( listData[i].str_sdata,that.iotNodeStatus )
break;
}
listData[i].showSensorTtype=showSensorTtype
if( that.iotNodeStatus == 16 ){
listData[i].ison=showSensorTtype=='关闭'?false:true ;
}else{
listData[i].ison=showSensorTtype = false ;
}
}
for(var j=0;j<listData.length;j++){
that.dotList.push( listData.slice(j,j+3) ) ;
j=j+2
}
}, 400);
},
error: function (e) {
}
});
},
getDevData(){
var that=this
$.ajax({
type:'GET',
url:baseurl+'/service/node?id='+id,
contentType: 'application/json',
dataType: "json",
headers : {'USER-KEY':ucode},
success: function (e) {
if(e.status==2){
if(!e.data.lonLat){
e.data.lonLat='118.7812,32.0712'
}
var lonLat=e.data.lonLat.split(',')
that.lonLat=e.data.lonLat;
var str_name = 'location2.png' ;
if(e.data.iot_node_status != 16){
str_name = 'location2_red.png' ;
}
var myIcon = new BMap.Icon(baseurl+"/image/oss/iot/"+str_name, new BMap.Size(30,37));
var point = new BMap.Point(lonLat[0], lonLat[1]);
that.state=e.data.data.iot_node_status
switch(that.state){
case '故障':
that.nowtype='error'
break;
case '未连接':
that.nowtype='warning'
break;
case '设备已离线':
that.nowtype='error'
break;
case '在线':
that.nowtype='success'
break;
}
that.iot_node_type=e.data.data.iot_node_type
that.scene_name=e.data.scene_name
that.device_code=e.data.device_code
that.device_name=e.data.name
that.deviceID=e.data.id
that.iotNodeStatus = e.data.iot_node_status ;
var marker = new BMap.Marker(point,{icon:myIcon}); // 创建标注
map.addOverlay(marker);
map.centerAndZoom(point, 13); // 将标注添加到地图中
}
},
error: function (e) {
}
});
}
},
created(){
let that=this
this.getTableData()
this.getDevDots()
that.getDevData()
this.getSet()
this.mqttInit();
},
mounted(){
map = new BMap.Map("dmap");
map.enableScrollWheelZoom(true);
map.setMapStyle({
styleJson: [{
"featureType": "road",//道路
"elementType": "all",
"stylers": {
"color": "#ffffff",
"visibility": "off"
}
},
{
"featureType": "building",
"elementType": "all",
"stylers": {
"visibility": "off"
}
},
{
"featureType": "poilabel",//景点
"elementType": "all",
"stylers": {
"visibility": "off"
}
},
{
"featureType": "manmade",//学院
"elementType": "all",
"stylers": {
"visibility": "off"
}
}
]
})
}
})
</script>
</body>
</html>