You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

561 lines
16 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="app-container app-box">
<div class="app-left">
<div class="dept-tree">
<div class="dtree-head">按设备组查看</div>
<el-tree
ref="dept-tree"
:props="defaultProps"
:data="deviceGroupList"
class="filter-tree"
:expand-on-click-node="false"
highlight-current
default-expand-all
@node-click="groupNodeClick"
>
<span slot-scope="{ node, data }" class="custom-tree-node">
<i v-if="data.children.length<=0 && node.expanded" class="el-icon-tickets" />
<i v-else-if="data.children && node.expanded" class="el-icon-folder-opened" />
<i v-else class="el-icon-folder" />
<span class="fontSize14" :title="node.label || &quot;-&quot;">{{ node.label }}</span>
</span>
</el-tree>
<div class="dtree-head" style="margin-top:30px;cursor:pointer">按传感器类型查看</div>
<ul class="sensorlist">
<li v-for="(item) in sensorData" :key="item.id" @click="sensorNodeClick(item.id)">
<svg-icon :icon-class="item.icon" class-name="shuiwei" style="font-size:18px" />{{ item.name }}
</li>
</ul>
</div>
</div>
<div class="app-right">
<div class="table-top">
<el-button size="mini" type="info" plain @click="tableExpend">{{ expendName }}</el-button>
<el-button size="mini" type="warning" plain @click="dispAllDev">显示所有设备</el-button>
<el-button size="mini" type="success" plain @click="tableExpend">显示所有在线设备</el-button>
<el-button size="mini" type="danger" plain @click="tableExpend">显示所有离线设备</el-button>
<div class="devmsg">共 {{ totalNum }} 个智慧杆设备,离线 {{ offlineNum }} 个,在线 {{ onlineNum }} 个,预警 {{ yujinNum }} 个</div>
</div>
<div class="app-r-table">
<el-table
v-if="refreshtable"
ref="userLevel"
:data="tableData"
style="margin-bottom: 20px;width: 100%;"
height="calc(100vh - 220px)"
row-key="id"
:row-style="{height: '0'}"
:header-cell-style="{ background: '#f8f8f8', color: '#333', padding: '8px' }"
:header-row-style="{padding:'0px'}"
:cell-style="{ padding: '8px' }"
:show-header="false"
:default-expand-all="expendAll"
:tree-props="{children: 'sensors', hasChildren: 'hasChildren'}"
:row-class-name="tableRowClassName"
class="tableClass"
>
<el-table-column prop="devname" label="设备名">
<template slot-scope="scope">
<svg-icon
v-if="!scope.row.sensors"
:icon-class="reIcoValue(scope.row.type)"
class-name="shuiwei"
:style="connectStyle(scope.row.linkStatus,scope.row.redWarning,scope.row.yellowWarning,scope.row.orangeWarning)"
/>
<span v-if="!scope.row.sensors" class="devicename" :style="connectStyle(scope.row.linkStatus,scope.row.redWarning,scope.row.yellowWarning,scope.row.orangeWarning)">{{
scope.row.name }}</span>
<span v-if="scope.row.sensors" class="devicename">{{ scope.row.name }}<span style="color:cornflowerblue">{{ scope.row.linkStatus == 1 ? '' : '(离线)' }}</span></span>
<!-- <span v-if="scope.row.imei" class="devicename">IMEI:{{ scope.row.imei }}</span> -->
<!-- <span v-if="scope.row.address" class="devicename" style="font-weight:normal;font-size: 14px;">,地址:{{ scope.row.address }}</span> -->
</template>
</el-table-column>
<el-table-column prop="status" label="设备状态">
<template slot-scope="scope">
<span v-if="scope.row.imei" class="devicename">IMEI:{{ scope.row.imei }}</span>
<span v-if="!scope.row.sensors" :style="connectStyle(scope.row.linkStatus,scope.row.redWarning,scope.row.yellowWarning,scope.row.orangeWarning)">
{{ scope.row.linkStatus == 1 ? '已连接' : '未连接' }}
<span class="sport">,端口{{ scope.row.devPort }}</span>
<div class="updatetime">更新:{{ scope.row.lastUpdateTime }}</div>
</span>
</template>
</el-table-column>
<el-table-column prop="currentValue" label="设备值">
<template slot-scope="scope">
<span class="valuestyle" :style="connectStyle(scope.row.linkStatus,scope.row.redWarning,scope.row.yellowWarning,scope.row.orangeWarning)">{{ scope.row.currentValue }} {{
scope.row.unitName }}
<span v-if="scope.row.type ==3">{{ reFengxiang(scope.row.currentValue ) }}</span>
<span v-if="!scope.row.sensors" class="warnstyle" title="已达到预警值,请及时处理">
<svg-icon
icon-class="jinggao"
class-name="jinggao"
:style="reWarn(scope.row.linkStatus,scope.row.redWarning,scope.row.yellowWarning,scope.row.orangeWarning)"
/></span>
</span>
</template>
</el-table-column>
<el-table-column label="操作项">
<template slot-scope="scope">
<span
v-if="!scope.row.sensors"
class="historydata"
:style="connectStyle(scope.row.linkStatus)"
@click="showlog(scope.row.id,scope.row.name)"
><i class="el-icon-s-data" /> 历史数据</span>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total > 0"
:total="total"
:page-size.sync="listQuery.PageSize"
:page-no.sync="listQuery.PageNo"
@pagination="getList"
/>
</div>
<el-dialog
v-el-drag-dialog
:title="dialogFromTitle"
:visible.sync="showLogDailog"
:close-on-click-modal="false"
width="80%"
>
<linechart :chart-data="lineChartData" />
</el-dialog>
</div>
</template>
<script>
import { getDeviceList, getDevReport } from '@/api/device'
import { getDeviceGroupList } from '@/api/devgroup'
import { getSensorLog, getSensorTypeMyList } from '@/api/sensor'
import elDragDialog from '@/directive/el-drag-dialog'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
import linechart from './components/LineChart'
const lineChartData = {
newVisitis: {
expectedData: [],
titleData: [],
actualData: []
}
}
export default {
name: 'Monitor',
components: { Pagination, linechart },
directives: { elDragDialog },
data() {
return {
refreshtable: true,
expendAll: true,
lineChartData: lineChartData.newVisitis,
activeNames: ['1'],
deviceGroupList: [],
defaultProps: { label: 'name', children: 'children' },
dialogFromTitle: '',
tableData: [],
listLoading: true,
listQuery: {
PageNo: 1,
PageSize: 10,
name: '',
GroupCode: -1,
type: ''
},
total: 0,
timer: null, // 定时器名称
logData: [],
showLogDailog: false,
timerLogSensor: {
id: '',
name: ''
},
sensorList: [],
sensorData: [],
currenSensorId: -1,
expendName: '收起列表',
onlineNum: '',
offlineNum: '',
totalNum: '',
yujinNum: ''
}
},
mounted() {
this.getDevReportInfo()
this.getList()
this.getSensorList()
this.get_DeviceGroupList()
this.timer = setInterval(() => {
if (this.showLogDailog === true && this.timerLogSensor.id !== '') {
setTimeout(this.showlog(this.timerLogSensor.id, this.timerLogSensor.name), 0)
}
if (this.currenSensorId !== -1) {
setTimeout(this.getSensorDataList, 0)
} else {
setTimeout(this.getList, 0)
}
}, 1000 * 10)
},
beforeDestroy() {
clearInterval(this.timer)
this.timer = null
},
methods: {
dispAllDev() {
this.listQuery.GroupCode = -1
this.listQuery.type = ''
this.currenSensorId = -1
this.getSensorList()
this.get_DeviceGroupList()
this.getList()
},
tableExpend() {
this.refreshtable = false
this.expendAll = !this.expendAll
if (this.expendAll === false) {
this.expendName = '展开列表'
} else {
this.expendName = '收起列表'
}
this.$nextTick(() => {
this.refreshtable = true
})
},
sensorNodeClick(sensorId) {
this.currenSensorId = sensorId
this.getSensorDataList(sensorId)
},
async getDevReportInfo() {
await getDevReport().then(response => {
this.totalNum = response['data']['数量']
this.onlineNum = response['data']['在线数量']
this.offlineNum = response['data']['离线数量']
this.yujinNum = response['data']['预警数量']
})
},
async getSensorDataList() {
const { PageNo, PageSize } = this.listQuery
await getDeviceList({ PageNo, PageSize, SensorType: this.currenSensorId }).then(response => {
this.total = response.data.total
this.tableData = response.data.items
this.listLoading = false
}).catch(() => {
this.listLoading = false
})
},
async groupNodeClick(obj, node, self) {
this.currenSensorId = -1
this.listQuery.GroupCode = obj.id === '0' || obj.id === 0 ? -1 : obj.id
this.listLoading = true
const { PageNo, PageSize, GroupCode } = this.listQuery
await getDeviceList({ PageNo, PageSize, GroupCode }).then(response => {
this.total = response.data.total
this.tableData = response.data.items
this.listLoading = false
}).catch(() => {
this.listLoading = false
})
},
async get_DeviceGroupList() {
this.listLoading = true
await getDeviceGroupList({ PageNo: 1, PageSize: 10000 }).then(response => {
const list1 = []
const list2 = []
const rData = response.data.items
console.log('rData', rData.length)
for (let index = 0; index < rData.length; index++) {
const childrens = rData[index].children
for (let n = 0; n < childrens.length; n++) {
childrens[n].name = childrens[n].name + '(' + childrens[n].count + ')'
}
list2[index] = { id: rData[index].id, name: rData[index].name + '(' + rData[index].count + ')', children: childrens }
}
list1[0] = { id: '0', name: '所有分组', children: list2 }
this.deviceGroupList = list1
}).catch(() => {
this.listLoading = false
})
},
refresh() {
this.timer = setTimeout(async() => {
await this.getList()
}, 5000) // 设置五秒后刷新
},
getList() {
this.listLoading = true
getDeviceList(this.listQuery).then(response => {
this.tableData = response.data.items
this.total = response.data.total
this.listLoading = false
})
},
tableRowClassName(row, rowIndex) {
if (row.row.sensors) {
return 'warning-row'
}
},
handleChange(val) {
console.log(val)
},
reWarn(cn, red = false, yellow = false, orange = false) {
if (cn !== 1) return { display: 'none' }
if (red === true && cn === 1) {
return {
color: 'red',
fontWeight: 'bold'
}
}
if (yellow === true && cn === 1) {
return {
color: 'yellow',
fontWeight: 'bold'
}
}
if (orange === true && cn === 1) {
return {
color: 'orange',
fontWeight: 'bold'
}
}
return { display: 'none' }
},
connectStyle(cn, red = false, yellow = false, orange = false) {
if (cn !== 1) {
return {
color: 'rgb(187 186 186)',
fontWeight: 'bold'
}
} else {
if (red === true) {
return {
color: 'red',
fontWeight: 'bold'
}
} else if (yellow === true) {
return {
color: 'yellow',
fontWeight: 'bold'
}
} else if (orange === true) {
return {
color: 'orange',
fontWeight: 'bold'
}
} else {
return ''
}
}
},
showlog(id, name) {
const logQuery = { id: id }
this.timerLogSensor.id = id
this.timerLogSensor.name = name
getSensorLog(logQuery).then(response => {
this.logData = response.data.items
const rData = response.data.items
const tData = []
const vData = []
for (let index = 0; index < rData.length; index++) {
const cIndex = rData.length - 1 - index
tData[index] = rData[cIndex]['recTime']
vData[index] = rData[cIndex]['currentValue']
}
this.lineChartData.titleData = tData
this.lineChartData.expectedData = vData
this.dialogFromTitle = name + '的历史数据'
this.showLogDailog = true
})
},
getSensorList() {
getSensorTypeMyList().then(response => {
const rData = response.data
this.sensorData = rData
const tempData = {}
rData.forEach(element => {
tempData[element['id']] = element.icon
})
this.sensorList = tempData
})
},
reIcoValue(itype) {
const icon = this.sensorList[itype]
return icon || ''
},
reFengxiang(du) {
const aDu = parseInt(du)
let x = ''
switch (true) {
case aDu >= 0 && aDu <= 22:
x = '北风'
break
case aDu >= 338 && aDu <= 360:
x = '北风'
break
case aDu >= 23 && aDu <= 67:
x = '东北风'
break
case aDu >= 68 && aDu <= 111:
x = '东风'
break
case aDu >= 112 && aDu <= 157:
x = '东南风'
break
case aDu >= 158 && aDu <= 201:
x = '南风'
break
case aDu >= 202 && aDu <= 247:
x = '西南风'
break
case aDu >= 248 && aDu <= 290:
x = '西风'
break
case aDu >= 291 && aDu <= 337:
x = '西北风'
break
default:
x = ''
}
return x
}
}
}
</script>
<style lang="scss" >
.warnstyle{
font-size: 18px;
color:#666;
font-weight: normal;
margin-left: 5px;
}
.app-box {
display: flex;
}
.app-left {
width: 300px;
padding: 10px;
background: #fff;
height: calc(100vh - 100px);
}
.app-right {
width: calc(100vw - 415px);
margin-left: 15px;
padding: 15px;
background: #fff;
height: calc(100vh - 100px);
}
.dept-tree {
width: 100%;
}
.valuestyle {
font-size: 20px;
color: rgb(12, 184, 12);
font-weight: bold;
}
.el-table .warning-row {
background: rgb(246, 249, 252) !important;
font-weight: bold;
}
.dtree-head {
background: #409EFF;
color: #fff;
font-size: 14px;
padding: 8px 0px 8px 0px;
text-align: center;
margin-bottom: 12px;
cursor: pointer;
}
.dtree-head:hover {
background: #0881fa
}
.shuiwei {
color: #8e7eff;
font-size: 22px;
margin-right: 10px;
}
.devicename {
font-weight: bold;
}
.valuemaxstyle {
color: red;
}
.queryhistory {
cursor: pointer;
color: #087df3
}
.noconnect {
color: #ccc
}
.historydata {
color: #b10606;
cursor: pointer;
}
.sensorlist,
.sensorlist li {
list-style: none;
padding: 0px;
margin: 0px;
}
.sensorlist {
width: 90%;
padding-left: 10%
}
.sensorlist li {
padding: 8px 0px 0px 0px;
cursor: pointer;
color: #606266;
font-size: 14px;
}
.sensorlist li:hover {
color: #087df3;
}
.sensorlist li svg-icon {
font-size: 12px;
}
.fontSize14 {
font-size: 14px;
}
.sport {
font-size: 12px;
font-weight: normal;
}
.updatetime {
font-size: 12px;
font-weight: normal;
}
.table-top{padding: 0px 0px 5px 0px; width: 100%; display: flex;}
.devmsg{line-height: 30px;margin-left:20px;color:#076ace;font-size:14px}
</style>>