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.

1470 lines
43 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="container">
<div class="centerImg" v-if="!isMap"
:style="`background-image: url(${picUrl ? picUrl : containerPic})`"></div>
<div class="title">监控单元统计</div>
<Chart ref="chart1" class="chart1"></Chart>
<div class="chart1Right">
<p v-for="(i,k) in chart1Data.slice(0,4)" :key="k" :style="'margin:0.6vw;color:'+ chart1Color[k]">{{ i.name }}</p>
</div>
<div class="chart1Table">
<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>
<vue-seamless-scroll
:class-option="chart1TableOption"
:data="chart1Data"
class="case-item"
style="height: 84%;overflow: hidden;"
>
<div
v-for="(item, index) in chart1Data"
:key="index"
>
<div :style='"background-color:" + ((index % 2 === 0)? "#053460":"#032d57") '>
<div
class="scrollTable">
{{ item.name }}
</div>
<div
class="scrollTable">
{{ item.value }}
</div>
<div
class="scrollTable">
{{ item.value2 }}
</div>
</div>
</div>
</vue-seamless-scroll>
</div>
<Chart ref="chart2" class="chart2"></Chart>
<div class="chart2Table">
<div style="background-color: #094170">
<div class="scrollTable" style="font-weight: bold;width: 50%">
名称
</div>
<div class="scrollTable" style="font-weight: bold;width: 50%">
数量
</div>
</div>
<vue-seamless-scroll
:class-option="chart1TableOption"
:data="chart2Data"
class="case-item"
style="height: 84%;overflow: hidden;"
>
<div
v-for="(item, index) in chart2Data"
:key="index"
>
<div :style='"background-color:" + ((index % 2 === 0)? "#053460":"#032d57") '>
<div class="scrollTable" style="width: 50%">
{{ item.name }}
</div>
<div class="scrollTable" style="width: 50%">
{{ item.value }}
</div>
</div>
</div>
</vue-seamless-scroll>
</div>
<div>
<div class="centerInfo">传感器数量</div>
<div class="centerInfo" style="font-weight:bold;top:19.3%;left: 42.5%;font-size: 2vw;">{{
centerNum.sum
}}
</div>
<div class="centerInfo" style="left: 56%">监控单元数量</div>
<div class="centerInfo" style="font-weight:bold;top:19.3%;left: 66%;font-size: 2vw;">{{ centerNum.subSum }}</div>
</div>
<div class="inTransit">在运: <span style="color: #00f6ff">{{ inTransitNum }}</span></div>
<Chart ref="chart3" class="chart3"></Chart>
<div class="table1">
<div style="background-color: #094170">
<div class="scrollTable" style="font-weight: bold;width: 25%">
告警编号
</div>
<div class="scrollTable" style="font-weight: bold;width: 25%">
告警类型
</div>
<div class="scrollTable" style="font-weight: bold;width: 25%">
告警位置
</div>
<div class="scrollTable" style="font-weight: bold;width: 25%">
操作
</div>
</div>
<vue-seamless-scroll
:class-option="{...chart1TableOption,limitMoveNum:10}"
:data="table1Data"
class="case-item"
style="height: calc(100% - 33px);overflow: hidden;"
>
<div
v-for="(item, index) in table1Data"
:key="index"
>
<div :style='"background-color:" + ((index % 2 === 0)? "#053460":"#032d57") '>
<div class="scrollTable" style="width: 25%">
{{ item.no }}
</div>
<div class="scrollTable" style="width: 25%">
{{ item.alarmInfoType === '1' ? '设备报警' : '' }}
{{ item.alarmInfoType === '2' ? '监控单元报警' : '' }}
{{ item.alarmInfoType === '3' ? '离线报警' : '' }}
{{ item.alarmInfoType === '4' ? '电子围栏' : '' }}
</div>
<div class="scrollTable" style="width: 25%">
{{ item.location }}
</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 class="exTable">
<el-date-picker
style="width: calc(100% - 114px)"
size="mini"
v-model="exTableTime"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
<el-button size="mini" type="primary" @click="exTable" style="margin-left: 8px">导出告警信息</el-button>
</div>
<div v-if="isMap">
<Chart ref="mapChart" class="mapChart"></Chart>
<div type="primary" class="backButton" @click="goBack">
<svg t="1719391363434" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="2674" width="200" height="200">
<path
d="M927.2 610.5c0 143-116.3 259.4-259.3 259.4H196.1c-12.9 0-23.4-10.4-23.4-23.4 0-12.9 10.4-23.4 23.4-23.4h471.7c117.2 0 212.6-95.4 212.6-212.6S785 397.8 667.8 397.8h-458l199.6 199.6c9.1 9.1 9.1 23.9 0 33-4.6 4.6-10.5 6.8-16.5 6.8s-11.9-2.3-16.5-6.8L137 391.1c-9.1-9.1-9.1-23.9 0-33l239.6-239.5c9.1-9.1 23.9-9.1 33 0s9.1 23.9 0 33L210 351.2h457.9c143 0 259.3 116.3 259.3 259.3z"
p-id="2675" fill="#ffffff"></path>
</svg>
<span>返回</span>
</div>
<div type="primary" class="realMapButton" @click="toRealMap">
<svg t="1719391119148" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="1489" width="200" height="200">
<path
d="M512 800.182857a18.651429 18.651429 0 0 1-12.8-5.485714c-10.971429-10.971429-261.485714-265.508571-261.485714-428.982857A271.725714 271.725714 0 0 1 512 91.428571a271.725714 271.725714 0 0 1 274.285714 274.285715c0 163.474286-250.514286 418.011429-261.485714 428.982857a18.651429 18.651429 0 0 1-12.8 5.485714zM512 128A235.154286 235.154286 0 0 0 274.285714 365.714286c0 128.731429 186.148571 334.994286 237.714286 389.485714 51.565714-54.491429 237.714286-260.754286 237.714286-389.485714A235.154286 235.154286 0 0 0 512 128z"
fill="#ffffff" p-id="1490"></path>
<path
d="M512 457.142857a91.428571 91.428571 0 1 1 91.428571-91.428571 91.428571 91.428571 0 0 1-91.428571 91.428571z m0-146.285714a54.857143 54.857143 0 1 0 54.857143 54.857143A54.857143 54.857143 0 0 0 512 310.857143zM512 932.571429c-208.822857 0-420.571429-43.885714-420.571429-128 0-65.097143 123.977143-96.914286 197.851429-109.714286a18.651429 18.651429 0 0 1 21.211429 14.994286 18.285714 18.285714 0 0 1-14.628572 21.211428c-123.245714 21.942857-167.862857 55.954286-167.862857 73.142857 0 36.571429 149.577143 91.428571 384 91.428572S896 841.142857 896 804.571429c0-17.92-44.617143-51.931429-167.862857-73.142858a18.285714 18.285714 0 0 1-14.628572-21.211428 18.651429 18.651429 0 0 1 21.211429-14.994286c73.142857 13.165714 197.851429 44.982857 197.851429 109.714286 0 83.748571-211.748571 127.634286-420.571429 127.634286z"
fill="#ffffff" p-id="1491"></path>
</svg>
<span>打开地图</span>
</div>
<!-- <el-button type="primary" style="position:absolute;bottom: 4%;left: 49%;transform: translateX(-100%)"-->
<!-- @click="goBack">返回-->
<!-- </el-button>-->
<!-- <el-button type="primary" style="position:absolute;bottom: 4%;left: 51%;transform: translateX(0%)"-->
<!-- @click="toRealMap">打开地图-->
<!-- </el-button>-->
</div>
<el-dialog :visible.sync="realMap" width="80%" @close="monitorUnitId = null;options=[];value=[]">
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="搜索">
<el-select
v-model="value"
multiple
filterable
remote
reserve-keyword
placeholder="请输入关键词"
@change="setMarker2"
:remote-method="searchMap1"
:loading="loading">
<el-option
v-for="item in options"
:key="item.value.deviceId"
:label="item.label"
:value="item.value.deviceId">
</el-option>
</el-select>
<!-- <el-input v-model="formInline.name" placeholder="名称"></el-input>-->
</el-form-item>
<!-- <el-form-item>-->
<!-- <el-button type="primary" @click="searchMap">查询</el-button>-->
<!-- </el-form-item>-->
</el-form>
<el-switch
v-model="isRail"
@change="RailChange"
active-text="显示点位"
inactive-text="隐藏点位">
</el-switch>
<div id="map" class="map"></div>
</el-dialog>
<el-dialog
:visible.sync="isDispose"
width="30%">
<el-descriptions class="margin-top" :column="2" border>
<el-descriptions-item>
<template slot="label">
设备id
</template>
{{ warInfo.deviceId }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
监控单元名称
</template>
{{ warInfo.monitorUnitName }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
监控单元类型
</template>
{{ warInfo.monitorUnitTypeName }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
告警编号
</template>
{{ warInfo.alarmInfoId }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
告警类型
</template>
{{ warInfo.alarmInfoType === '1' ? '设备报警' : '' }}
{{ warInfo.alarmInfoType === '2' ? '监控单元报警' : '' }}
{{ warInfo.alarmInfoType === '3' ? '离线报警' : '' }}
{{ warInfo.alarmInfoType === '4' ? '电子围栏' : '' }}
<!-- {{ warInfo.alarmTypeName }}-->
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
告警位置
</template>
{{ warInfo.monitorUnitName }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
告警信息
</template>
{{ warInfo.alarmLevelName }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
告警时间
</template>
{{ warInfo.createTime }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
告警区域
</template>
{{ warInfo.areaName }}
</el-descriptions-item>
</el-descriptions>
<span>备注</span>
<el-input
style="margin-top: 12px;margin-bottom:12px"
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model="textarea">
</el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="isDispose = false">取 消</el-button>
<el-button type="primary" @click="disposeThis">处理当前</el-button>
<el-button type="primary" @click="disposeAll">处理所有</el-button>
</span>
</el-dialog>
<el-dialog title="设备信息" :visible.sync="equipmentInfoDialog">
<el-table
:data="equipmentInfo"
style="width: 100%">
<el-table-column
prop="deviceCode"
label="编号"
width="180">
</el-table-column>
<el-table-column
prop="deviceName"
label="名称"
width="180">
</el-table-column>
<el-table-column
prop="monitorUnitName"
label="监控单元">
</el-table-column>
<el-table-column
prop="longitude"
label="经度">
</el-table-column>
<el-table-column
prop="latitude"
label="纬度">
</el-table-column>
</el-table>
<!-- <el-descriptions class="margin-top" :column="3" border v-for="i in equipmentInfo" style="margin-top: 8px">-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- 编号-->
<!-- </template>-->
<!-- {{ i.deviceCode }}-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- 名称-->
<!-- </template>-->
<!-- {{ i.deviceName }}-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- 监控单元-->
<!-- </template>-->
<!-- {{ i.monitorUnitName }}-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- 经度-->
<!-- </template>-->
<!-- {{ i.longitude }}-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- 纬度-->
<!-- </template>-->
<!-- {{ i.latitude }}-->
<!-- </el-descriptions-item>-->
<!-- </el-descriptions>-->
<div slot="footer" class="dialog-footer">
<el-button @click="equipmentInfoDialog = false">关 闭</el-button>
<el-button type="primary" @click="getDeviceInfo" :disabled="!monitorUnitId">设备信息</el-button>
<!-- <el-button type="primary" @click="equipmentInfoDialog = true">打开内层 Dialog</el-button>-->
</div>
</el-dialog>
</div>
</template>
<script>
// import gif from '@/assets/board/index/gif.gif'
import gif from '@/assets/board/index/dot.png'
import containerPic from "@/assets/board/index/container.png";
import Chart from "@/components/Charts/Chart";
import vueSeamlessScroll from "vue-seamless-scroll";
import * as echarts from 'echarts';
import {
monitorUnitPercentage,
monitorPercentage,
allNums,
getAlarmInfos,
getDeviceOperations,
handleAlarmInfo,
getDeviceByAreaId,
getTenantData,
selectMonitorElectronic,
selectDeviceByName,
exTableData,
getMapData
} from '@/api/board/index'
import ChinaMapData from '@/utils/ChinaMapData.json'
import gsByMap from '@/utils/map/gs_by.json'
import axios from "axios";
let map = null
let markers = []
let markerIds = []
let polygons = []
let circles = []
const vw = (document.documentElement.clientWidth || document.body.clientWidth) / 100
let time1 = null
let time2 = null
const isJSON = (str) => {
try {
JSON.parse(str);
return true;
} catch (e) {
return false;
}
}
export default {
components: {
vueSeamlessScroll,
Chart,
},
data() {
return {
containerPic,
markerData: [],
isTown: false,
value: [],
loading: false,
options: [],
isRail: true,
monitorUnitId: null,
equipmentInfoDialog: false,
exTableTime: [new Date(new Date().getTime() - 1000 * 60 * 60 * 24), new Date()],
equipmentInfo: [],
warInfo: {},
formInline: {},
textarea: '',
disposeNo: null,
isDispose: false,
realMap: false,
centerGeo: [],
picUrl: null,
code: 620000,
cityJson: null,
isMap: true,
centerNum: {},
chart1Option: {
tooltip: {
valueFormatter: (e) => {
return e + '%'
},
},
angleAxis: {
max: 100,
clockwise: true,
show: false,
},
radiusAxis: {
type: "category",
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
polar: {
center: ["30%", "50%"],
radius: "100%", //图形大小
},
},
chart1Color: ['#2ff', '#f22', '#f2f', '#1f1'],
chart1Data: [],
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,
},
chart2Data: [],
chart2Option: {
color: ["#22acfd", "#22fe97", "#f9e728", "#ff922b", "#ed1814"],
legend: {
type: 'scroll',
orient: "vertical",
x: "right",
y: "center",
width: '100px',
textStyle: {
color: '#fff',
fontSize: 0.6 * vw
}
},
tooltip: {
trigger: "item",
formatter: "{b} : ({d}%)",
},
series: [
{
type: "pie",
radius: ["45%", "76%"],
center: ["25%", "50%"],
encode: {
itemName: "group",
value: "占比",
},
labelLine: {
show: false,
},
label: {
show: false,
},
itemStyle: {
opacity: '0.8'
}
},
{
type: "pie",
radius: ["75%", "90%"],
center: ["25%", "50%"],
encode: {
itemName: "group",
value: "占比",
},
labelLine: {
show: false,
},
label: {
show: false,
},
},
],
},
inTransitNum: 0,
chart3Option: {
tooltip: {
trigger: "axis",
},
grid: {
top: "middle",
left: "3%",
right: "4%",
bottom: "3%",
height: "80%",
containLabel: true,
},
yAxis: {
type: "value",
splitLine: {
lineStyle: {
type: "dashed",
color: "#ccc3",
},
},
axisLine: {
show: false,
lineStyle: {
color: "#ccc",
},
},
nameTextStyle: {
color: "#999",
},
splitArea: {
show: false,
},
},
},
table1Data: []
}
},
async mounted() {
await getTenantData(this.$store.getters.tenantId).then(e => {
this.isMap = e.data.tenantField === '2';
this.picUrl = e.data.tenantBoardPic
this.code = parseFloat(e.data.tenantMapCode) || 620000
})
this.setChart1()
this.setChart2()
this.setAllNums()
this.setDeviceOperations()
setInterval(()=>{
this.setTable3()
},5000)
// let data = await axios.get(`https://geo.datav.aliyun.com/areas_v3/bound/${this.code}_full.json`)
// let data = await axios.get(`http://124.223.15.102:3333/componentLib/getMap?id=${this.code}`)
let {msg} = await getMapData({areaCode: this.code})
let data
if (isJSON(msg)) {
data = JSON.parse(msg)
} else {
data = ''
}
let mapData = this.code === 100000 ? ChinaMapData : data
await this.getMap(mapData)
this.chartClick()
},
methods: {
async setChart1() {
const {rows: data} = await monitorPercentage()
let data1 = data.slice(0, 4)
data1.reverse()
let option1 = {
...this.chart1Option,
series: [
{
type: "bar",
data: data1.map((e, i) => {
return {
value: parseFloat(e.percentage),
name: e.sceneName,
itemStyle: {
color: this.chart1Color[i]
}
}
}),
showBackground: true,
coordinateSystem: "polar",
roundCap: true,
barWidth: 8,
},
]
}
this.$refs.chart1.setData(option1)
this.chart1Data = data.map(e => {
return {
value: e.sum || 0,
value2: e.err || 0,
name: e.sceneName || '',
}
})
},
async setChart2() {
const {rows: data} = await monitorUnitPercentage()
let chart2Num = eval(data.map(e => e.sum).join("+"));
let option2 = {
...this.chart2Option,
dataset: {
source: [
["group", "占比"],
...data.slice(0, 7).map(e => [e.deviceModeName, parseFloat(e.percentage)])
],
}
}
this.$refs.chart2.setData(option2)
this.chart2Data = data.map(e => {
return {
value: e.sum,
name: e.deviceModeName,
}
})
},
async setAllNums() {
const data = await allNums()
this.centerNum = data
},
async setTable3() {
const {rows: data} = await getAlarmInfos()
this.table1Data = data.map((e, i) => {
return {
...e,
no: e.alarmInfoId,
type: e.alarmTypeName,
location: e.monitorUnitName,
status: e.handleStatus
}
})
},
async setDeviceOperations() {
let {data: data} = await getDeviceOperations()
let onlineDevicesTrend = data["onlineDevicesTrend"];
let sortArr = Object.keys(onlineDevicesTrend)
sortArr = sortArr.sort((a, b) => {
return new Date(a).getTime() - new Date(b).getTime()
})
let x = sortArr
let y = sortArr.map(e => {
return onlineDevicesTrend[e]
})
// this.inTransitNum = y.reduce((a, b) => {
// return a + b
// }, 0)
this.inTransitNum = data["onlineDevicesCount"];
let option3 = {
...this.chart3Option,
xAxis: {
boundaryGap: false,
type: "category",
data: x,
splitLine: {
show: true,
lineStyle: {
type: "dashed",
color: "#ccc3",
},
},
axisLine: {
lineStyle: {
color: "#999",
},
},
},
series: [
{
name: "",
type: "line",
data: y,
color: "#00dae0",
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: "#00dae033",
},
{
offset: 1,
color: "rgba(0,202,149,0)",
},
],
false
),
shadowColor: "rgba(0,202,149, 0.9)",
shadowBlur: 20,
},
},
},
],
}
this.$refs.chart3.setData(option3)
},
dispose(e) {
this.warInfo = e
this.textarea = ''
this.isDispose = true
this.disposeNo = e.no
},
disposeThis() {
handleAlarmInfo({
alarmInfoId: this.disposeNo,
alarmInfoField: this.textarea,
ifDisposalAll: 0,
}).then(e => {
if (e.code === 200) {
this.$message({
type: 'success',
message: '已处理!'
});
this.setTable3()
} else {
this.$message({
type: 'info',
message: '网络错误'
});
}
this.isDispose = false
})
},
disposeAll() {
handleAlarmInfo({
alarmInfoId: this.disposeNo,
alarmInfoField: this.textarea,
ifDisposalAll: 1,
}).then(e => {
if (e.code === 200) {
this.$message({
type: 'success',
message: '已处理!'
});
this.setTable3()
} else {
this.$message({
type: 'info',
message: '网络错误'
});
}
this.isDispose = false
})
},
async getMap(geoJson) {
this.cityJson = geoJson.features
echarts.registerMap('map', geoJson);
this.centerGeo = geoJson.features[0].properties.center || geoJson.features[0].properties.geo_wkt.split('(')[1].split(')')[0].split(' ').map(e => parseFloat(e))
const random = (val = 1) => {
return Math.ceil(Math.random() * val)
}
let Point = [
{value: [120.3, 36.0], index: random(5), type: random(5), state: random(5)},
{value: [104.065735, 30.659462], index: random(5), type: random(5), state: random(5)},
{value: [123.1238, 42.1216], index: random(5), type: random(5), state: random(5)},
{value: [114.4995, 38.1006], index: random(5), type: random(5), state: random(5)},
{value: [109.1162, 34.2004], index: random(5), type: random(5), state: random(5)},
{value: [106.3586, 38.1775], index: random(5), type: random(5), state: random(5)},
{value: [101.4038, 36.8207], index: random(5), type: random(5), state: random(5)},
{value: [113.0823, 28.2568], index: random(5), type: random(5), state: random(5)},
{value: [102.9199, 25.46639], index: random(5), type: random(5), state: random(5)},
]
Point = []
let option = {
grid: {
top: '0%',
left: '0%',
right: '0%',
bottom: '0%',
},
geo: {
map: "map",
show: false,
aspectScale: 0.75, //长宽比
zoom: 1.1,
label: {
show: true
},
roam: true,
layoutCenter: ["50%", "50%"], // position位置
layoutSize: 25 * vw,
itemStyle: {
normal: {
areaColor: {
type: "radial",
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [
{
offset: 0,
color: "#013B8F", // 0% 处的颜色
},
{
offset: 1,
color: "#013B8F", // 100% 处的颜色
},
],
globalCoord: true, // 缺省为 false
},
shadowColor: "#013B8F",
shadowOffsetX: 0,
shadowOffsetY: 8,
},
emphasis: {
areaColor: "#2AB8FF",
borderWidth: 0,
color: "green",
label: {
show: false,
},
},
},
},
series: [
{
type: "map",
// roam: 'scale',
label: {
normal: {
show: true,
textStyle: {
color: "#1DE9B6",
},
},
},
itemStyle: {
normal: {
borderColor: "rgb(147, 235, 248,0.5)",
borderWidth: 1,
areaColor: {
type: "radial",
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [
{
offset: 0,
color: "#013B8F", // 0% 处的颜色
},
{
offset: 1,
color: "#013B8F", // 100% 处的颜色
},
],
globalCoord: true, // 缺省为 false
},
},
},
zoom: 1.1,
map: 'map', //使用
aspectScale: 0.75, //长宽比
},
{
type: "effectScatter",
coordinateSystem: "geo",
showEffectOn: 'emphasis',
zlevel: 1,
rippleEffect: {
period: 15,
scale: 1,
brushType: "fill",
},
hoverAnimation: true,
itemStyle: {
normal: {
color: "#1DE9B6",
shadowBlur: 10,
shadowColor: "#333",
},
},
symbolSize: [0.5 * vw, 0.5 * vw],
data: Point,
label: {
padding: [-16, 0, 0, 5],
show: true,
position: 'bottom',
formatter: function (val) {
return [`{a|}{b|'点位${val.data.index}}`]
},
rich: {
a: {
width: 0.34 * vw,
height: 0.34 * vw,
borderColor: '#0FF32E',
borderWidth: 0.34 * vw,
borderRadius: 0.17 * vw,
shadowBlur: 20,
shadowColor: "#0FF32E",
},
b: {
padding: [0, 0, 0, 5],
color: '#0FF32E',
height: 40,
fontSize: 0.75 * vw,
},
}
}
},
],
};
this.$refs.mapChart.setData(option);
},
chartClick() {
this.$refs.mapChart.chart.on('click', async (params) => {
this.isTown = (this.cityJson[params.dataIndex].properties.adcode || gsByMap.features[params.dataIndex].properties.unique_id).toString().length === 9
this.code = this.cityJson[params.dataIndex].properties.adcode || this.code || gsByMap.features[params.dataIndex].properties.unique_id
let mapData
if (this.code !== 620400 && this.code.toString().startsWith('6204')) {
mapData = {features: gsByMap.features.filter(e => e.properties.pid === this.code.toString())}
if (this.isTown) {
mapData = {features: mapData.features.filter(v => v.properties.name === params.name)}
}
} else {
// let data = await axios.get(`https://geo.datav.aliyun.com/areas_v3/bound/${this.code}_full.json`)
// let data = await axios.get(`http://124.223.15.102:3333/componentLib/getMap?id=${this.code}`)
let {msg} = await getMapData({areaCode: this.code})
let data
if (isJSON(msg)) {
data = JSON.parse(msg)
} else {
data = ''
}
mapData = this.cityJson[params.dataIndex].properties.adcode === 100000 ? ChinaMapData : data
}
await this.getMap(mapData)
})
this.$refs.mapChart.$el.addEventListener('dblclick', () => {
this.chartDblClick(this.code)
});
},
goBack() {
if (this.isTown) {
this.getMap({features: gsByMap.features.filter(e => e.properties.pid === this.code.toString())})
this.isTown = false
} else {
this.chartDblClick(this.code)
}
},
async chartDblClick(val) {
let a = val.toString().substr(0, 2)
let b = val.toString().substr(2, 2)
let c = val.toString().substr(4, 2)
let d = val.toString().substr(6, 9)
d = null
if (d && d !== '000') {
this.code = Number(a + b + c)
} else if (c !== '00') {
this.code = Number(a + b + '00')
} else if (b !== '00') {
this.code = Number(a + '0000')
} else if (a !== '10') {
this.code = 100000
}
let mapData
if (this.code !== 620400 && this.code.toString().startsWith('6204')) {
mapData = gsByMap
} else {
// let data = await axios.get(`https://geo.datav.aliyun.com/areas_v3/bound/${this.code}_full.json`)
// let data = await axios.get(`http://124.223.15.102:3333/componentLib/getMap?id=${this.code}`)
let {msg} = await getMapData({areaCode: this.code})
let data
if (isJSON(msg)) {
data = JSON.parse(msg)
} else {
data = ''
}
mapData = this.code === 100000 ? ChinaMapData : data
}
this.getMap(mapData)
},
async toRealMap() {
this.realMap = true
markerIds = []
this.$nextTick(async () => {
this.createMap()
const data = await getDeviceByAreaId(this.$store.getters.tenantId)
this.markerData = data.data.map(e => e.devicesList).flat(1)
data.data.map(e => e.devicesList).flat(1).forEach(e => {
this.setMarker(e)
})
})
},
setMarker(e) {
if (!this.isRail) {
return
}
let marker = new AMap.Marker({
position: [e.longitude, e.latitude],
title: `信息\n经度${e.longitude}\n纬度${e.latitude}\n名称${e.deviceName}\n`,
offset: new AMap.Pixel(-15, -30),
content: `<div> <svg t="1718261114618" class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" p-id="4305" style="width: 30px;height: 30px;">
<path fill="${(e.ifAlarm === '1') ? '#3D93FD' : '#ff0000'}" d="M512 64.5c-180.5 0-326.9 146.4-326.9 326.9 0 63.3 18 122.3 49.2 172.4 1.1 2 2.1 4 3.2 5.9 34.9 58.2 113.9 128.8 165.5 194.5 66.3 84.4 93.2 158 93.2 158 1.6 1.4 13.1 35.6 15.1 35.8 2.5 0.2 12.6-34 14.5-35.8 0 0 22-69.2 83.7-146.6 56-70.1 142.8-145.7 177-206 0.9-1.6 1.8-3.3 2.6-5 31.5-50.2 49.7-109.6 49.7-173.3 0.1-180.5-146.3-326.8-326.8-326.8z" p-id="4306">
</path></svg></div>`
});
marker.on('rightclick', async () => {
// if (markerIds.includes(e.deviceId)) {
// return
// } else {
// markerIds.push(e.deviceId)
// }
const {data} = await selectMonitorElectronic(e.deviceId)
data.map(e => e.hwFenceAreaList).flat(1).forEach(e => {
if (e.areaShapeFlag === '1') {
this.setPolygon(e.areaRange.split('_').map(e => e.split(',').map(v => parseFloat(v))))
}
if (e.areaShapeFlag === '2') {
let arr = e.areaRange.split(',')
this.setCircle([arr[0], arr[1]], arr[2])
}
})
})
marker.on('dblclick', () => {
this.equipmentInfoDialog = true
this.equipmentInfo = this.markerData.filter(v => v.monitorUnitId === e.monitorUnitId)
this.monitorUnitId = e.monitorUnitId
// this.$router.push({path: '/board/equipment', query: {monitorUnitId: e.monitorUnitId}})
});
map.add(marker);
markers.push(marker)
},
setMarker1(e) {
let marker = new AMap.Marker({
position: [e.longitude, e.latitude],
title: `信息\n经度${e.longitude}\n纬度${e.latitude}\n名称${e.deviceName}\n`,
offset: new AMap.Pixel(-20, -40),
content: `<div>
<img src="${gif}" alt="" width=" 40px" style="animation:an1 2s ease-in-out infinite;" >
</div>`
});
marker.on('rightclick', async () => {
// if (markerIds.includes(e.deviceId)) {
// return
// } else {
// markerIds.push(e.deviceId)
// }
const {data} = await selectMonitorElectronic(e.deviceId)
data.map(e => e.hwFenceAreaList).flat(1).forEach(e => {
if (e.areaShapeFlag === '1') {
this.setPolygon(e.areaRange.split('_').map(e => e.split(',').map(v => parseFloat(v))))
}
if (e.areaShapeFlag === '2') {
let arr = e.areaRange.split(',')
this.setCircle([arr[0], arr[1]], arr[2])
}
})
})
marker.on('dblclick', () => {
this.equipmentInfoDialog = true
this.equipmentInfo = this.markerData.filter(v => v.monitorUnitId === e.monitorUnitId)
this.monitorUnitId = e.monitorUnitId
// this.$router.push({path: '/board/equipment', query: {monitorUnitId: e.monitorUnitId}})
});
map.add(marker);
markers.push(marker)
},
setMarker2(e, bl) {
if (!bl) {
if (time1) {
clearInterval(time1)
}
time1 = null
time1 = setInterval(() => {
this.setMarker2(e, true)
}, 5000)
}
map.remove(markers)
map.remove(polygons)
map.remove(circles)
markers = []
e.forEach(v => {
console.log(v)
console.log(this.options)
let arr = this.options.filter(r => r.value.deviceId === v) || []
if (arr.length > 0) {
this.setMarker1(arr[0].value)
}
})
if(!bl){
map.setFitView(markers)
}
},
getDeviceInfo() {
this.$router.push({path: '/board/equipment', query: {monitorUnitId: this.monitorUnitId}})
},
setPolygon(e, val) {
// let e = position.map(val => {
// return [val.longitude, val.latitude]
// })
let thisPolygon = new AMap.Polygon({
path: e,
fillColor: '#1791fc',
// fillColor: val > 0 ? '#ff0000' : '#1791fc',
});
map.add(thisPolygon)
map.setFitView(thisPolygon)
polygons.push(thisPolygon)
},
setCircle(center, radius, e) {
let circle = new AMap.Circle({
center,
radius,
borderWeight: 3,
strokeColor: "#FF33FF",
// strokeColor: e ? '#ff0000' : "#FF33FF",
strokeWeight: 6,
strokeOpacity: 0.2,
fillOpacity: 0.4,
strokeDasharray: [10, 10],
fillColor: '#1791fc',
// fillColor: e > 0 ? '#ff0000' : '#1791fc',
})
map.add(circle);
map.setFitView(circle)
circles.push(circle)
},
createMap() {
map = new AMap.Map('map', {
zoom: 11,
center: this.centerGeo,
});
},
async searchMap() {
const {data} = await selectDeviceByName(this.formInline)
map.remove(markers)
map.remove(polygons)
map.remove(circles)
markers = []
this.markerData = data
console.log(data)
data.forEach(e => {
if (e.latitude && e.longitude) {
this.setMarker1(e)
}
})
map.setFitView(markers)
},
async searchMap1(name, e) {
// if(!e){
if (time2) {
clearInterval(time2)
}
time2 = null
if(name.length === 0){
const data = await getDeviceByAreaId(this.$store.getters.tenantId)
this.markerData = data.data.map(e => e.devicesList).flat(1)
data.data.map(e => e.devicesList).flat(1).forEach(e => {
this.setMarker(e)
})
}else{
time2 = setInterval(async () => {
const {data} = await selectDeviceByName({name: name})
this.markerData = data
}, 5000)
// }
const {data} = await selectDeviceByName({name: name})
this.value = []
map.remove(markers)
map.remove(polygons)
map.remove(circles)
markers = []
this.loading = true;
this.loading = false;
let option = []
data.forEach(e => {
if (e.latitude && e.longitude && e.deviceName.includes(name)) {
option.push({
label: e.deviceName,
value: e
})
}
})
this.options = option
}
},
exTable() {
let query = {}
query.startTime = this.parseTime(this.exTableTime?.[0]?.getTime())
query.endTime = this.parseTime(this.exTableTime?.[1]?.getTime())
exTableData(query, '告警信息')
},
async RailChange() {
if (this.isRail) {
const data = await getDeviceByAreaId(this.$store.getters.tenantId)
data.data.map(e => e.devicesList).flat(1).forEach(e => {
this.setMarker(e)
})
} else {
map.remove(markers)
}
}
}
}
;
</script>
<style scoped lang="less">
.title {
position: absolute;
top: 12%;
left: 13.6%;
font-size: 1vw;
color: #00f8ff;
transform: translateX(-50%);
}
.container {
background-image: url("~@/assets/board/index/bg.jpg");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 100%;
height: calc(100vh);
position: relative;
}
.centerImg {
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
width: 45vw;
height: 20vw;
top: 60%;
left: 50%;
transform: translate(-50%, -50%);
}
.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: 33%;
}
.chart1 {
position: absolute;
width: 20%;
height: 21%;
top: 16%;
left: 3%;
}
.chart1Right {
background-image: url("~@/assets/board/common/bg1.png");
background-repeat: no-repeat;
background-size: 100% 100%;
padding: 0 12px;
position: absolute;
top: 17%;
right: 76.3%;
font-size: 0.8vw;
p {
display: block;
max-width: 10vw;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.chart1Table {
position: absolute;
top: 38%;
left: 2.8%;
width: 21%;
height: 14%;
overflow: hidden;
}
.chart2 {
position: absolute;
width: 20%;
height: 21%;
top: 58.5%;
left: 3%;
}
.chart2Table {
position: absolute;
top: 81%;
left: 2.8%;
width: 21%;
height: 15%;
overflow: hidden;
}
.centerInfo {
position: absolute;
width: 7%;
top: 17.5%;
left: 32.7%;
font-size: 1.4vw;
text-align: center;
transform: translateX(-50%);
color: #01c7fd;
letter-spacing: 4px;
}
.inTransit {
position: absolute;
top: 16%;
left: 87%;
transform: translateX(-50%);
font-size: 1.2vw;
color: rgb(30, 158, 223);
}
.chart3 {
position: absolute;
width: 21%;
height: 22%;
top: 21.5%;
left: 76.1%;
}
.table1 {
position: absolute;
width: 21%;
height: 45%;
top: 50.5%;
left: 76.3%;
}
.mapChart {
position: absolute;
width: 50%;
height: 60%;
top: 30%;
left: 25%;
}
.map {
width: 100%;
height: 80vh;
}
.exTable {
position: absolute;
bottom: 50%;
left: 76.3%;
width: 21%;
/*transform: translateX(-50%);*/
}
.backButton {
position: absolute;
bottom: 2%;
left: 32%;
/*transform: translateX(-100%);*/
background-image: url("~@/assets/board/index/leftButtonBg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 18vw;
height: 4.865vw;
line-height: 4.865vw;
text-align: center;
}
.realMapButton {
position: absolute;
bottom: 2%;
left: 53%;
/*transform: translateX(-100%);*/
background-image: url("~@/assets/board/index/rightButtonBg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 18vw;
height: 4.865vw;
line-height: 4.865vw;
text-align: center;
}
.backButton, .realMapButton {
span {
position: absolute;
top: 60%;
left: 45%;
transform: translateY(-50%);
color: #fff;
font-size: 1.1vw;
font-weight: 600;
}
svg {
position: absolute;
top: 60%;
left: 30%;
transform: translateY(-50%);
color: #fff;
width: 1.5vw;
height: 1.5vw;
}
}
</style>
<style>
@keyframes an1 {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>