|
|
|
<template>
|
|
|
|
<div class="container">
|
|
|
|
<div class="centerImg"></div>
|
|
|
|
<Chart ref="chart1" class="chart1"></Chart>
|
|
|
|
<div class="table1">
|
|
|
|
<div style="background-color: #094170">
|
|
|
|
<div class="scrollTable" style="font-weight: bold;">
|
|
|
|
告警编号
|
|
|
|
</div>
|
|
|
|
<div class="scrollTable" style="font-weight: bold;">
|
|
|
|
告警类型
|
|
|
|
</div>
|
|
|
|
<div class="scrollTable" style="font-weight: bold;">
|
|
|
|
告警单元
|
|
|
|
</div>
|
|
|
|
<div class="scrollTable" style="font-weight: bold;">
|
|
|
|
操作
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<vue-seamless-scroll
|
|
|
|
:class-option="{...chart1TableOption,limitMoveNum:10}"
|
|
|
|
:data="table1Data"
|
|
|
|
class="case-item"
|
|
|
|
style="height: 84%;overflow: hidden;"
|
|
|
|
>
|
|
|
|
<div
|
|
|
|
v-for="(item, index) in table1Data"
|
|
|
|
:key="index"
|
|
|
|
|
|
|
|
>
|
|
|
|
<div :style='"background-color:" + ((index % 2 === 0)? "#053460":"#032d57") '>
|
|
|
|
<div
|
|
|
|
class="scrollTable">
|
|
|
|
{{ item.value1 }}
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
class="scrollTable">
|
|
|
|
{{ item.value2 }}
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
class="scrollTable">
|
|
|
|
{{ item.value3 }}
|
|
|
|
</div>
|
|
|
|
<div class="scrollTable" style="width: 25%">
|
|
|
|
<el-button v-if="item.status === '0'" size="mini" type="primary" @click="dispose(item)">处理</el-button>
|
|
|
|
<span v-else>已处理</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</vue-seamless-scroll>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div class="title1">监控单元报警统计</div>
|
|
|
|
<div class="title2">告警信息</div>
|
|
|
|
<div class="info1">监控单元数量</div>
|
|
|
|
<div class="info2">设备数量</div>
|
|
|
|
<div class="info3">在线设备数量</div>
|
|
|
|
<div class="num1">{{ num2 }}</div>
|
|
|
|
<div class="num2">{{ num1 }}</div>
|
|
|
|
<div class="num3">{{ num3 }}</div>
|
|
|
|
</div>
|
|
|
|
<div id="map" class="map"></div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import Chart from "@/components/Charts/Chart";
|
|
|
|
import vueSeamlessScroll from "vue-seamless-scroll";
|
|
|
|
import * as echarts from 'echarts';
|
|
|
|
import {
|
|
|
|
alarmStats,
|
|
|
|
subDevice,
|
|
|
|
getAlarmInfos,
|
|
|
|
ElectronicNumVo
|
|
|
|
} from '@/api/board/GPS'
|
|
|
|
import red from '@/assets/board/GPS/red.png'
|
|
|
|
import green from '@/assets/board/GPS/green.png'
|
|
|
|
import {handleAlarmInfo} from "@/api/board/index";
|
|
|
|
|
|
|
|
let map = null
|
|
|
|
let polyEditor = null
|
|
|
|
export default {
|
|
|
|
components: {
|
|
|
|
Chart,
|
|
|
|
vueSeamlessScroll,
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
async $route(to, from) {
|
|
|
|
await this.getData()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
num1: 0,
|
|
|
|
num2: 0,
|
|
|
|
num3: 0,
|
|
|
|
chart1TableOption: {
|
|
|
|
step: 0.5, // 数值越大速度滚动越快
|
|
|
|
limitMoveNum: 3, // 开始无缝滚动的数据量 this.dataList.length
|
|
|
|
hoverStop: true, // 是否开启鼠标悬停stop
|
|
|
|
direction: 1, // 0向下 1向上 2向左 3向右
|
|
|
|
openWatch: true, // 开启数据实时监控刷新dom
|
|
|
|
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
|
|
|
|
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
|
|
|
|
waitTime: 0,
|
|
|
|
},
|
|
|
|
chart1Option: {
|
|
|
|
grid: {
|
|
|
|
left: "0%",
|
|
|
|
right: "5%",
|
|
|
|
top: "0%",
|
|
|
|
bottom: "0%",
|
|
|
|
containLabel: true,
|
|
|
|
},
|
|
|
|
tooltip: {
|
|
|
|
trigger: "axis",
|
|
|
|
axisPointer: {
|
|
|
|
type: "shadow",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
xAxis: {
|
|
|
|
type: "value",
|
|
|
|
axisLine: {
|
|
|
|
show: true,
|
|
|
|
lineStyle: {
|
|
|
|
color: "#fffa",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
splitLine: {
|
|
|
|
show: true,
|
|
|
|
lineStyle: {
|
|
|
|
color: "#fff4",
|
|
|
|
type: 'dashed'
|
|
|
|
},
|
|
|
|
},
|
|
|
|
boundaryGap: [0, 0.01],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
table1Data: [],
|
|
|
|
sceneId: 0,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
async mounted() {
|
|
|
|
await this.getData()
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
async getData() {
|
|
|
|
if (this.$store.getters.sceneId === null) return
|
|
|
|
await this.createMap()
|
|
|
|
await this.getAlarmStats()
|
|
|
|
await this.getAubDevice()
|
|
|
|
await this.setAlarmInfos()
|
|
|
|
await this.setElectronicNumVo()
|
|
|
|
},
|
|
|
|
dispose(e) {
|
|
|
|
this.$confirm('该问题已处理?', '提示', {
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
type: 'warning'
|
|
|
|
}).then(() => {
|
|
|
|
handleAlarmInfo({
|
|
|
|
alarmInfoId: e.no
|
|
|
|
}).then(e => {
|
|
|
|
if (e.code === 200) {
|
|
|
|
this.$message({
|
|
|
|
type: 'success',
|
|
|
|
message: '已处理!'
|
|
|
|
});
|
|
|
|
this.setTable3()
|
|
|
|
} else {
|
|
|
|
this.$message({
|
|
|
|
type: 'info',
|
|
|
|
message: '网络错误'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}).catch(() => {
|
|
|
|
this.$message({
|
|
|
|
type: 'info',
|
|
|
|
message: '已取消'
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
createMap() {
|
|
|
|
map = new AMap.Map('map', {
|
|
|
|
zoom: 11,
|
|
|
|
center: [113.4, 23.35],
|
|
|
|
});
|
|
|
|
},
|
|
|
|
setText(e) {
|
|
|
|
let position = e.areaPoints?.length > 0 ? e.areaPoints : e.centerPoint
|
|
|
|
if (position.length > 0) {
|
|
|
|
let length = position.length
|
|
|
|
let longitudes = e.areaPoints.map(e => e.longitude).reduce((a, b) => a + b)
|
|
|
|
let latitudes = e.areaPoints.map(e => e.latitude).reduce((a, b) => a + b)
|
|
|
|
position = [longitudes / length, latitudes / length]
|
|
|
|
} else {
|
|
|
|
position = [e.centerPoint.longitude, e.centerPoint.latitude]
|
|
|
|
}
|
|
|
|
let text = new AMap.Text({
|
|
|
|
text: '<div style="color:#fff;width: 100%;height: 100%;">' + '总数:' + e.deviceCount + (e.abnormalCount ? ('/异常数量:' + e.abnormalCount) : '') + '</div>',
|
|
|
|
anchor: 'center',
|
|
|
|
draggable: true,
|
|
|
|
cursor: 'pointer',
|
|
|
|
position: position
|
|
|
|
});
|
|
|
|
text.setStyle({
|
|
|
|
'background-color': e.abnormalCount? '#fe0000':'#0055fe',
|
|
|
|
padding:'4px 12px',
|
|
|
|
'font-size':'1vw'
|
|
|
|
})
|
|
|
|
map.add(text)
|
|
|
|
},
|
|
|
|
setPolygon(position, val) {
|
|
|
|
let e = position.map(val => {
|
|
|
|
return [val.longitude, val.latitude]
|
|
|
|
})
|
|
|
|
let thisPolygon = new AMap.Polygon({
|
|
|
|
path: e,
|
|
|
|
fillColor: val > 0 ? '#ff0000' : '#1791fc',
|
|
|
|
});
|
|
|
|
map.add(thisPolygon)
|
|
|
|
map.setFitView()
|
|
|
|
},
|
|
|
|
setCircle(center, radius, e) {
|
|
|
|
let circle = new AMap.Circle({
|
|
|
|
center,
|
|
|
|
radius,
|
|
|
|
borderWeight: 3,
|
|
|
|
strokeColor: e ? '#ff0000' : "#FF33FF",
|
|
|
|
strokeWeight: 6,
|
|
|
|
strokeOpacity: 0.2,
|
|
|
|
fillOpacity: 0.4,
|
|
|
|
strokeDasharray: [10, 10],
|
|
|
|
fillColor: e > 0 ? '#ff0000' : '#1791fc',
|
|
|
|
})
|
|
|
|
map.add(circle);
|
|
|
|
map.setFitView()
|
|
|
|
},
|
|
|
|
async getAlarmStats() {
|
|
|
|
if (this.$store.getters.sceneId === null) return
|
|
|
|
const {data} = await alarmStats(this.$store.getters.sceneId)
|
|
|
|
let option1 = {
|
|
|
|
...this.chart1Option,
|
|
|
|
yAxis: {
|
|
|
|
axisLine: {
|
|
|
|
show: true,
|
|
|
|
lineStyle: {
|
|
|
|
color: "#fffa",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
splitLine: {
|
|
|
|
show: true,
|
|
|
|
lineStyle: {
|
|
|
|
color: "#fff4",
|
|
|
|
type: 'dashed'
|
|
|
|
},
|
|
|
|
},
|
|
|
|
type: "category",
|
|
|
|
data: data.map(e => e.monitorUnitName),
|
|
|
|
},
|
|
|
|
series: [
|
|
|
|
{
|
|
|
|
name: "数量",
|
|
|
|
type: "bar",
|
|
|
|
yAxisIndex: 0,
|
|
|
|
data: data.map(e => e.sum),
|
|
|
|
barWidth: '60%',
|
|
|
|
itemStyle: {
|
|
|
|
normal: {
|
|
|
|
show: true,
|
|
|
|
color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
|
|
|
{
|
|
|
|
offset: 0,
|
|
|
|
color: "#00faff",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
offset: 1,
|
|
|
|
color: "#1eadf1",
|
|
|
|
},
|
|
|
|
]),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
}
|
|
|
|
this.$refs.chart1.setData(option1)
|
|
|
|
},
|
|
|
|
async getAubDevice() {
|
|
|
|
let data = await subDevice(this.$store.getters.sceneId)
|
|
|
|
this.num1 = data.deviceNum
|
|
|
|
this.num2 = data.subSum
|
|
|
|
this.num3 = data.onlineDeviceNum
|
|
|
|
},
|
|
|
|
async setAlarmInfos() {
|
|
|
|
const {rows: data} = await getAlarmInfos({"sceneId": this.$store.getters.sceneId})
|
|
|
|
this.table1Data = data.map((e, i) => {
|
|
|
|
return {
|
|
|
|
value1: e.alarmInfoId,
|
|
|
|
value2: e.alarmTypeName,
|
|
|
|
value3: e.monitorUnitName,
|
|
|
|
status: e.handleStatus
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
async setElectronicNumVo() {
|
|
|
|
const {data} = await ElectronicNumVo(this.$store.getters.sceneId)
|
|
|
|
data.forEach(e => {
|
|
|
|
if (e.areaPoints?.length > 0) {
|
|
|
|
this.setPolygon(e.areaPoints, e.abnormalCount)
|
|
|
|
}
|
|
|
|
if (e.centerPoint) {
|
|
|
|
this.setCircle([e.centerPoint.longitude, e.centerPoint.latitude], e.radius, e.abnormalCount)
|
|
|
|
}
|
|
|
|
this.setText(e)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
<style scoped>
|
|
|
|
.container {
|
|
|
|
background-image: url("~@/assets/board/GPS/bg.jpg");
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
background-size: 100% 100%;
|
|
|
|
width: 100%;
|
|
|
|
height: calc(100vh);
|
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
|
|
|
|
.chart1 {
|
|
|
|
position: absolute;
|
|
|
|
width: 25%;
|
|
|
|
height: 21%;
|
|
|
|
top: 16%;
|
|
|
|
left: 3%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.table1 {
|
|
|
|
position: absolute;
|
|
|
|
top: 48%;
|
|
|
|
left: 2.5%;
|
|
|
|
width: 26%;
|
|
|
|
height: 48%;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
.scrollTable {
|
|
|
|
color: rgb(185, 186, 192);
|
|
|
|
margin: auto 0px;
|
|
|
|
padding: 4px 0;
|
|
|
|
white-space: nowrap;
|
|
|
|
overflow: hidden;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
text-align: center;
|
|
|
|
display: inline-block;
|
|
|
|
width: 25%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title1 {
|
|
|
|
position: absolute;
|
|
|
|
top: 13%;
|
|
|
|
left: 15.5%;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
font-size: 1vw;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title2 {
|
|
|
|
position: absolute;
|
|
|
|
top: 45.4%;
|
|
|
|
left: 15.6%;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
font-size: 1vw;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
|
|
|
|
.info1 {
|
|
|
|
position: absolute;
|
|
|
|
top: 18%;
|
|
|
|
left: 39%;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
font-size: 1vw;
|
|
|
|
color: #179ce1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.info2 {
|
|
|
|
position: absolute;
|
|
|
|
top: 18%;
|
|
|
|
left: 62%;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
font-size: 1vw;
|
|
|
|
color: #179ce1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.info3 {
|
|
|
|
position: absolute;
|
|
|
|
top: 18%;
|
|
|
|
left: 83%;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
font-size: 1vw;
|
|
|
|
color: #179ce1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.num1 {
|
|
|
|
position: absolute;
|
|
|
|
top: 18%;
|
|
|
|
left: 47%;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
font-size: 1.4vw;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
|
|
|
|
.num2 {
|
|
|
|
position: absolute;
|
|
|
|
top: 18%;
|
|
|
|
left: 69%;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
font-size: 1.4vw;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
|
|
|
|
.num3 {
|
|
|
|
position: absolute;
|
|
|
|
top: 18%;
|
|
|
|
left: 91%;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
font-size: 1.4vw;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
|
|
|
|
.map {
|
|
|
|
position: absolute;
|
|
|
|
top: 28%;
|
|
|
|
left: 31%;
|
|
|
|
width: 67%;
|
|
|
|
height: 69%;
|
|
|
|
}
|
|
|
|
</style>
|