统计数据页面

This commit is contained in:
hh
2020-12-29 17:06:45 +08:00
parent b95a3bc801
commit 3de890cda2
6 changed files with 820 additions and 1 deletions

View File

@ -267,4 +267,14 @@
.scrollbar-wrapper {
overflow-x: hidden !important;
}
}
.column {
display: flex;
flex-direction: column;
.flex {
flex: 1;
display: flex;
}
}

View File

@ -0,0 +1,53 @@
<template>
<section>
<div class="BoxBoardBody">
<div class="BoxBoardTit"><slot name="tit"></slot></div>
<div class="body">
<slot></slot>
</div>
</div>
</section>
</template>
<script>
export default {
name: 'BoxBoardBody',
props: {
tit: {
type: String,
default: "",
},
}
}
</script>
<style scoped>
.BoxBoardBody {
position: relative;
width: 100%;
height: 100%;
padding: 0 0 20px 0;
}
.body {
position: relative;
width: 99%;
height: 100%;
text-align: center;
vertical-align: middle;
line-height: 100%;
background-color: rgba(0, 0, 0, 0.2);
border: 0px solid rgba(70, 233, 255, 1);
border-radius: 3px 3px 3px 3px;
-webkit-box-shadow: #666 0px 0px 10px;
-moz-box-shadow: #666 0px 0px 10px;
/* box-shadow: #666 0px 0px 10px; */
pointer-events: auto;
z-index: 10100;
overflow: hidden;
}
.BoxBoardTit {
position: absolute;
left: 50px;
top: -10px;
}
</style>

View File

@ -0,0 +1,37 @@
<template>
<section>
<div class="boxBoardTit">{{tit}}</div>
</section>
</template>
<script>
export default {
name: 'BoxBoardTit',
props: {
tit: {
type: String,
default: "",
},
}
}
</script>
<style scoped>
.boxBoardTit {
font-size: 12px;
width: 70px;
height: 20px;
line-height: 20px;
background-color: transparent;
color: rgba(70, 233, 255, 1);
font-weight: bold;
border: 0.5px solid rgba(70, 233, 255, 1);
border-radius: 10px 1px 10px 1px;
text-align: center;
vertical-align: middle;
z-index: 10100;
-webkit-box-shadow: #666 0px 0px 10px;
-moz-box-shadow: #666 0px 0px 10px;
box-shadow: #666 0px 0px 10px;
}
</style>

699
src/views/chart/index.vue Normal file
View File

@ -0,0 +1,699 @@
<template>
<div style="width: 100%;height:100%;position: relative;">
<div ref="bmap" id="main" style="width: 100%;height:100%;"></div>
<div id="chart">
<div class="center tc">
<div class="tit">{{time}}</div>
<div class="des">锐能在线设备{{devCount}}</div>
</div>
<div class="left column">
<boxBoardBody class="flex">
<boxBoardTit slot="tit" tit="工单总览"></boxBoardTit>
<div ref="ticketAll" style="width: 100%;height:100%;"></div>
</boxBoardBody>
<div style="height:20px"></div>
<boxBoardBody class="flex">
<boxBoardTit slot="tit" tit="告警总览"></boxBoardTit>
<div ref="alarmAll" style="width: 100%;height:100%;"></div>
</boxBoardBody>
</div>
<div class="right column">
<div class="flex"></div>
<div style="height:20px"></div>
<boxBoardBody class="flex">
<boxBoardTit slot="tit" tit="告警趋势"></boxBoardTit>
<div ref="alarmTrend" style="width: 100%;height:100%;"></div>
</boxBoardBody>
</div>
</div>
</div>
</template>
<script>
import request from '@/utils/request';
import echarts from 'echarts';
import loadBMap from './loadBMap';
require('echarts/extension/bmap/bmap');
require('echarts/extension/bmap/bmap');
import resize from '../dashboard/mixins/resize';
import boxBoardTit from './boxBoardTit';
import boxBoardBody from './boxBoardBody';
import { parseTime } from "@/utils/ruoyi";
export default {
name: 'Chart',
mixins: [resize],
components: { boxBoardTit, boxBoardBody },
data () {
return {
bmapChart: null,
ticketAllChart: null,
alarmAllChart: null,
alarmTrendChart: null,
alarmTrendDay: [],
alarmTrendMonth: [],
devCount: 5,
spotList: [],
zoom: 1,
date: new Date(),
workStatusList: {
'1': '待接单',
'2': '待回单',
'3': '已回单',
},
myStyleJson: [
{
"featureType": "water",
"elementType": "all",
"stylers": {
"color": "#021019"
}
},
{
"featureType": "highway",
"elementType": "geometry.fill",
"stylers": {
"color": "#000000"
}
},
{
"featureType": "highway",
"elementType": "geometry.stroke",
"stylers": {
"color": "#147a92"
}
},
{
"featureType": "arterial",
"elementType": "geometry.fill",
"stylers": {
"color": "#000000"
}
},
{
"featureType": "arterial",
"elementType": "geometry.stroke",
"stylers": {
"color": "#0b3d51"
}
},
{
"featureType": "local",
"elementType": "geometry",
"stylers": {
"color": "#000000"
}
},
{
"featureType": "land",
"elementType": "all",
"stylers": {
"color": "#08304b"
}
},
{
"featureType": "railway",
"elementType": "geometry.fill",
"stylers": {
"color": "#000000"
}
},
{
"featureType": "railway",
"elementType": "geometry.stroke",
"stylers": {
"color": "#08304b"
}
},
{
"featureType": "subway",
"elementType": "geometry",
"stylers": {
"lightness": -70
}
},
{
"featureType": "building",
"elementType": "geometry.fill",
"stylers": {
"color": "#000000"
}
},
{
"featureType": "all",
"elementType": "labels.text.fill",
"stylers": {
"color": "#857f7f"
}
},
{
"featureType": "all",
"elementType": "labels.text.stroke",
"stylers": {
"color": "#000000"
}
},
{
"featureType": "building",
"elementType": "geometry",
"stylers": {
"color": "#022338"
}
},
{
"featureType": "green",
"elementType": "geometry",
"stylers": {
"color": "#062032"
}
},
{
"featureType": "boundary",
"elementType": "all",
"stylers": {
"color": "#1e1c1c"
}
},
{
"featureType": "manmade",
"elementType": "geometry",
"stylers": {
"color": "#022338"
}
},
{
"featureType": "poi",
"elementType": "all",
"stylers": {
"visibility": "off"
}
},
{
"featureType": "all",
"elementType": "labels.icon",
"stylers": {
"visibility": "off"
}
},
{
"featureType": "all",
"elementType": "labels.text.fill",
"stylers": {
"color": "#2da0c6",
"visibility": "on"
}
}
]
}
},
computed: {
time() {
return parseTime(this.date,'{h} : {i} : {s}')
}
},
mounted () {
let timer = setInterval(() => {
this.date = new Date()
}, 1000);
this.$once('hook:beforeDestroy', () => {
clearInterval(timer);
timer = null;
})
this.getData().then(({ code, msg, list, work, activity, devCount }) => {
if (200 == code) {
let spotList = [];
list.map(v => {
spotList.push({
id: v.id,
deviceId: v.deviceId,
deviceName: v.deviceName,
value: [parseFloat(v.longitude), parseFloat(v.latitude),]
})
})
this.spotList = spotList;
this.devCount = devCount;
this.$nextTick(() => {
this.initBmpChart()
this.initTicketAllChart(work)
this.initAlarmAllChart(activity)
});
}
})
this.initAlarmTrendChart()
this.getTicketData().then(({ code, msg, day, month }) => {
if (200 == code) {
this.alarmTrendDay = day;
this.alarmTrendMonth = month;
this.$nextTick(() => {
this.alarmTrendChartSetDay()
});
}
})
},
methods: {
getData () {
return request({
url: '/system/device/deviceSignal',
method: 'get',
})
},
getTicketData () {
return request({
url: '/system/warning/warningList',
method: 'get',
})
},
initTicketAllChart (ticketAll) {
if (!this.ticketAllChart) {
this.ticketAllChart = echarts.init(this.$refs.ticketAll)
}
let legends = Object.values(this.workStatusList);
let data = ticketAll.map(v => {
return {
name: this.workStatusList[v.workStatus],
value: v.workCount
}
})
console.log(data, ticketAll)
let option = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
x: 10,
y: 'center',
textStyle: {
color: '#ffffff'
},
data: legends
},
color: ['#ee504f', '#edb14f', '#42cabe', '#407ebb'],
series: [
{
name: '工单总览',
type: 'pie',
radius: ['50%', '70%'],
center: ['70%', '50%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '20',
}
},
labelLine: {
show: false
},
data: data
}
]
};
this.ticketAllChart.setOption(option);
},
initAlarmTrendChart () {
if (!this.alarmTrendChart) {
this.alarmTrendChart = echarts.init(this.$refs.alarmTrend)
}
this.alarmTrendChart.setOption({
visualMap: [{
show: false,
type: 'continuous',
seriesIndex: 0
}],
toolbox: {
show: true,
feature: {
// myHour: {
// show: true,
// title: '每小时',
// name: '时',
// icon: 'path://M113.48438,148.58984H248.25v318.35938h-30.85938v-32.42188h-73.04688v37.10938h-30.85938V148.58984zM217.39062,177.49609h-73.04688v98.82812h73.04688V177.49609zM144.34375,405.62109h73.04688V304.44922h-73.04688V405.62109zM261.14062,197.80859H399.8125v-86.32812h31.25v86.32812h55.46875v28.90625H431.0625v210.15625c0,34.89355-16.66895,52.34375-50,52.34375c-15.10645,0-37.24023-0.39062-66.40625-1.17188c-1.30273-9.375-3.3877-20.3125-6.25-32.8125c27.34375,2.08105,48.69727,3.125,64.0625,3.125c18.22852,0,27.34375-9.24707,27.34375-27.73438V226.71484H261.14062V197.80859zM304.89062,264.21484c20.83105,38.02197,36.58789,68.35938,47.26562,91.01562c-6.77148,3.125-17.1875,8.33398-31.25,15.625c-10.15625-24.7373-24.74023-55.59668-43.75-92.57812L304.89062,264.21484z',
// onclick: function () {
// console.log('每小时')
// }
// },
myDay: {
show: true,
title: '每天',
name: '天',
icon: 'path://M105.46875,450.16797c97.5249-41.53418,154.29688-99.34668,170.3125-173.4375H110.54688v-29.6875h169.33594c1.17188-18.4873,1.75781-50.39062,1.75781-95.70312H132.03125v-29.6875h337.5v29.6875H316.01562c-0.2627,27.21582-0.78125,59.11572-1.5625,95.70312h175v29.6875H319.72656c24.86914,82.55273,83.26758,137.7627,175.19531,165.625c-10.67773,12.75977-19.66211,23.56543-26.95312,32.42188c-84.89648-34.24707-140.75586-90.82031-167.57812-169.72656c-20.5752,73.4375-77.4751,131.70508-170.70312,174.80469C124.21875,472.82422,116.14355,462.92773,105.46875,450.16797z',
onclick: () => {
this.alarmTrendChartSetDay()
}
},
myMonth: {
show: true,
title: '每月',
name: '月',
icon: 'path://M225.19531,349.82422c-5.85938,50.2627-25.45801,95.70312-58.78906,136.32812c-8.33447-8.0752-17.31885-15.8877-26.95312-23.4375c25.25928-27.34375,42.1875-59.89355,50.78125-97.65625c5.9873-27.8623,8.98438-66.40625,8.98438-115.625V114.27734h260.9375v304.6875c0,38.54102-18.35938,57.8125-55.07812,57.8125c-15.36523,0-35.15625-0.2627-59.375-0.78125c-1.30273-9.375-3.25586-20.3125-5.85938-32.8125c23.95605,1.5625,42.83789,2.34375,56.64062,2.34375c21.09375,0,31.64062-10.28711,31.64062-30.85938v-64.84375H225.19531zM228.32031,321.30859H428.125v-75H231.25C231.25,272.35254,230.27344,297.35254,228.32031,321.30859z M231.25,143.57422v74.21875h196.875v-74.21875H231.25z',
onclick: () => {
this.alarmTrendChartSetMonth()
}
},
}
},
title: [{
left: 'center',
text: ''
}],
tooltip: {
trigger: 'axis',
formatter: '{b0}<br />告警数: {c0}'
},
textStyle: {
color: '#ffffff'
},
xAxis: [{
data: [],
axisLabel: { show: false }
}],
yAxis: [{
splitLine: { show: false }
}],
grid: [{
containLabel: true,
left: '5',
right: '5',
top: '20%',
height: '70%'
}],
series: [{
type: 'line',
showSymbol: false,
data: []
}]
});
this.alarmTrendChart.showLoading();
},
alarmTrendChartSetDay () {
let dateX = [];
let dateY = [];
this.alarmTrendDay.forEach(v => {
dateX.push(v.datas)
dateY.push(v.count)
});
this.alarmTrendChartSetData(dateX, dateY)
this.alarmTrendChart.hideLoading();
},
alarmTrendChartSetMonth () {
let dateX = [];
let dateY = [];
this.alarmTrendMonth.forEach(v => {
dateX.push(v.datas)
dateY.push(v.count)
});
this.alarmTrendChartSetData(dateX, dateY)
this.alarmTrendChart.hideLoading();
},
alarmTrendChartSetData (dateX, dateY) {
this.alarmTrendChart.setOption({
visualMap: [{
show: false,
type: 'continuous',
seriesIndex: 0,
min: Math.min.apply(null, dateY),
max: Math.max.apply(null, dateY)
}],
xAxis: [{
data: dateX
}],
series: [{
type: 'line',
showSymbol: false,
data: dateY
}]
})
},
initAlarmAllChart (alarmAll) {
if (!this.alarmAllChart) {
this.alarmAllChart = echarts.init(this.$refs.alarmAll)
}
let snapAlarmAll = []
for (let index = 0; index < 4; index++) {
let snap = alarmAll.find(v => v.signalLevel == index + 1)
if (snap) {
snapAlarmAll.push(snap.warningCount)
} else {
snapAlarmAll.push(0)
}
}
let level4 = '四级告警 ' + snapAlarmAll[3]
let level3 = '三级告警 ' + snapAlarmAll[2]
let level2 = '二级告警 ' + snapAlarmAll[1]
let level1 = '一级告警 ' + snapAlarmAll[0]
let levels = [level1, level2, level3, level4];
let levelsColors = ['#ee504f', '#edb14f', '#42cabe', '#407ebb']
let freeStyle = {
normal: {
color: 'rgba(192,192,192,0.2)',
label: { show: false },
labelLine: { show: false }
},
emphasis: {
color: 'rgba(192,192,192,0.2)'
}
};
let dataStyle = {
normal: {
label: { show: false },
labelLine: { show: false },
barBorderRadius: 0
},
emphasis: {
show: false,
barBorderRadius: 0
}
};
let placeHolderStyle = {
normal: {
color: 'rgba(0,0,0,0)',
label: { show: false },
labelLine: { show: false }
},
emphasis: {
color: 'rgba(0,0,0,0)'
}
};
let maxRadius = this.$refs.alarmAll.offsetHeight / 3;
let sum = eval(snapAlarmAll.join("+"));
let series = [];
for (let index = 0; index < snapAlarmAll.length; index++) {
let snap = {
type: 'pie',
clockWise: false,
hoverAnimation: false,
center: ['70%', '50%'],
radius: [maxRadius * (0.85 - index * 0.2), maxRadius * (1 - index * 0.2)],
itemStyle: dataStyle,
data: [
{
value: snapAlarmAll[index],
name: levels[index],
itemStyle: {
normal: {
color: levelsColors[index],
label: { show: false },
labelLine: { show: false }
},
emphasis: {
color: levelsColors[index]
}
}
},
{
value: sum == 0 ? 1 : (sum - snapAlarmAll[index]),
name: 'invisible',
itemStyle: freeStyle
}
]
}
series.push(snap)
}
this.alarmAllChart.setOption({ //加载数据图表
legend: {
show: true,
orient: 'vertical',
x: maxRadius * 0.1,
y: 'center',
itemWidth: 20,
itemHeight: maxRadius * 0.15,
itemGap: maxRadius * 0.2,
data: levels,
textStyle: {
color: '#ffffff'
}
},
series: series
});
},
initBmpChart () {
if (!this.bmapChart) {
this.bmapChart = echarts.init(this.$refs.bmap)
}
this.setOptions()
},
setOptions () {
let option = {
title: {  //标题
textStyle: {
color: '#fff'
},
left: 'center'  //标题位置,居中
},
tooltip: {
formatter: function (params) {
return (
"设备名: " + params.data.deviceName + "<br>设备sn: " + params.data.deviceId
);
}
},
bmap: {  //百度地图的设置
center: [104.114129, 37.550339],
zoom: 5,
roam: true,
mapStyle: {
styleJson: this.myStyleJson
}
},
series: [
{
name: '设备分布',
type: 'effectScatter',
coordinateSystem: 'bmap',
data: this.spotList,
symbolSize: function (val, params) {
// console.log(val, params)
return 6;
},
label: {
show: false,
position: 'inside',
formatter: '{c}',
color: '#fff'
},
rippleEffect: { brushType: 'stroke' },
hoverAnimation: true,
animation: false,
itemStyle: { normal: { color: 'red', shadowBlur: 10, shadowColor: 'red' } },
zlevel: 1
},
]
};
loadBMap("mKEqGSlYu4puhYjqtRZlsyVOtstkQ9A6")
.then(() => {
// 配置option
this.bmapChart.setOption(option)
let bmap = this.bmapChart.getModel().getComponent('bmap').getBMap();
bmap.enableContinuousZoom(); //启用地图惯性拖拽,默认禁用
bmap.addControl(new BMap.OverviewMapControl()); //添加缩略地图控件
bmap.enableScrollWheelZoom();//启用滚轮放大缩小
// bmap.addControl(new BMap.MapTypeControl());//添加地图类型控件
bmap.disable3DBuilding();
let zoomdrag = (() => {
let bounds = bmap.getBounds()
let sw = bounds.getSouthWest()//获取西南角的经纬度(左下端点)
let ne = bounds.getNorthEast();//获取东北角的经纬度(右上端点)
let wn = new BMap.Point(sw.lng, ne.lat);//获取西北角的经纬度(左上端点)
let es = new BMap.Point(ne.lng, sw.lat);//获取东南角的经纬度(右下端点)
// this.lng = bmap.getCenter().lng//经度
// this.lat = bmap.getCenter().lat//纬度
// this.lngLatZoom = [Number(this.lng.toFixed(2)), Number(this.lat.toFixed(2)), this.zoom]//经度 纬度 放大级别 用于watch监听
this.zoom = bmap.getZoom()//获取缩放级别
console.log('zoom', bmap.getZoom())
})
bmap.addEventListener("zoomend", zoomdrag) //监听地图缩放
bmap.addEventListener("dragend", zoomdrag) //监听地图拖拽平移
this.bmapChart.on('click', function (params) {
if (params.componentType == "series") {
let { id } = params.data;
window.open(`/hardware/device/detail?id=${id}`);
}
})
})
},
}
}
</script>
<style>
.ec-extension-bmap {
background: #23375f !important;
}
.BMap_cpyCtrl,
.anchorBL {
display: none;
}
.BMap_omBtn.BMap_omBtnClosed,
.anchorBR .BMap_omOutFrame,
.BMap_omCtrl {
display: none;
}
</style>
<style lang="scss" scoped>
#chart {
background-color: rgba(0, 0, 0, 0);
padding: 0px;
z-index: 10100;
border: 0px;
color: white;
text-align: center;
vertical-align: middle;
overflow: hidden;
pointer-events: none;
}
.center,
.left,
.right {
position: absolute;
top: 0;
width: 28vw;
height: 100vh;
box-sizing: border-box;
display: flex;
}
.center {
width: 30vw;
right: 35vw;
display: block;
color: white;
.tit {
padding-top: 20px;
font-size: 40px;
text-align: center;
vertical-align: middle;
}
.des {
padding-top: 10px;
}
}
.left {
left: 0;
padding: 35px 0 35px 35px;
}
.right {
right: 0;
padding: 35px 35px 35px 0;
}
</style>

View File

@ -0,0 +1,17 @@
export default function loadBMap(ak) {
return new Promise(function(resolve, reject) {
if (typeof BMap !== 'undefined') {
resolve(BMap)
return true
}
window.onBMapCallback = function() {
resolve(BMap)
}
let script = document.createElement('script')
script.type = 'text/javascript'
script.src =
'http://api.map.baidu.com/api?v=2.0&ak=' + ak + '&callback=onBMapCallback'
script.onerror = reject
document.head.appendChild(script)
})
}

View File

@ -7,6 +7,9 @@
<line-chart :chart-data="lineChartData" />
</el-row>
<el-row v-hasPermi="['/system/device/deviceSignal']"><router-link target="_blank" :to="{path:'/chart'}">查看数据</router-link>
</el-row>
<el-row :gutter="32">
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">