feat:overview 新增chart & overview其他细节调整

1.把overview作为登录后首页
2.asset total 及表格alert列显示调整
3.新增alert trend图表
4.topN头部下拉选调整
5.其他样式调整
This commit is contained in:
wangwenrui
2020-03-23 18:20:19 +08:00
parent 0c33b82ec7
commit 42b1e6a71f
8 changed files with 250 additions and 37 deletions

View File

@@ -185,10 +185,11 @@ const en = {
asset:{ asset:{
title:'Asset', title:'Asset',
assetType:'Asset Type', assetType:'Asset Type',
modelStat:'Model Stat', modelStat:'Model',
dcStat:'DataCenter Stat', dcStat:'DataCenter',
num:'Num', num:'Num',
alert:'Alert', alert:'Alert',
alertTotal:'Total',
alertLow:'Low', alertLow:'Low',
alertMedium:'Medium', alertMedium:'Medium',
alertHigh:'High', alertHigh:'High',
@@ -221,8 +222,11 @@ const en = {
alertNum:'Alert Num', alertNum:'Alert Num',
alertRuleTopN:'According to Alert Rule', alertRuleTopN:'According to Alert Rule',
assetTopN:'According to Asset', assetTopN:'According to Asset',
top:'Top' top:'Top',
chart:{
chartTitle:'Alert Trend'
} }
},
} }
}, },
validate: { //校验规则 validate: { //校验规则

View File

@@ -57,7 +57,7 @@ export default {
this.$i18n.locale = this.lang; this.$i18n.locale = this.lang;
bus.$emit('login'); bus.$emit('login');
this.$router.push({ this.$router.push({
path: "/panel", path: "/overview",
query: { query: {
t: +new Date() t: +new Date()
} }

View File

@@ -1,16 +1,12 @@
<template> <template>
<div class="chart-room"> <div class="chart-room">
<loading :ref="localLoading"></loading> <loading ref="loading"></loading>
<div class="chart-header"></div> <div class="chart-header">{{chartTitle}}</div>
<div class="chart-body" ref="chartBody" :id="chartId" style="height: 95%"></div>
<div class="chart-body" ref="chartBody" id="chartBody"></div>
<div class="chart-foot">
<el-scrollbar>
<div class="chart-legend"></div>
</el-scrollbar>
</div>
</div> </div>
</template> </template>
@@ -18,26 +14,129 @@
import echarts from 'echarts'; import echarts from 'echarts';
import chartDataFormat from "../../../charts/chartDataFormat"; import chartDataFormat from "../../../charts/chartDataFormat";
import loading from "../../../common/loading"; import loading from "../../../common/loading";
import uuidv1 from "uuid/v1";
import chartConfig from './chartConfig' import chartConfig from './chartConfig'
export default { export default {
name: "chart", name: "chart",
props:[], components:{
'loading':loading,
},
props:{
chartTitle:{type:String}
},
data(){ data(){
return { return {
option:chartConfig.getCommonOption chart:null,
option:{},
chartId:new uuidv1()+'-'+new Date().getTime(),
} }
}, },
created() { created() {
chartConfig.setSeries(this.series);
chartConfig.setTooltipFormatter(this.tooltipFormatter);
chartConfig.setTooltipPostion(this.tooltipPosition);
chartConfig.setYAxisLabelFormatter(this.yAxisFormatter);
this.option=chartConfig.getCommonOption();
}, },
methods:{ methods:{
tooltipPosition:function(point,params,dom,rect,size){
dom.style.transform = "translateZ(0)";
//提示框位置
var x=0;
var y=0;
//当前鼠标位置
var pointX = point[0];
var pointY = point[1];
//外层div大小
var viewWidth = size.viewSize[0];
var viewHeight = size.viewSize[1];
//提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
let chartDom = document.getElementById(this.chartId);
if(chartDom){
let parTop = chartDom.offsetTop;
let parLeft = chartDom.offsetLeft;
let parent = chartDom.parentElement;
let parClientHeight = parent.clientHeight;//可视高度
let parClientWidth = parent.clientWidth;//可视宽度
let parScrollTop = parent.scrollTop;
if((parClientWidth-pointX-parLeft-20)>=boxWidth){//说明鼠标在左边放不下提示框
x=pointX+10;
}else{
x = pointX - boxWidth;
}
if((parClientHeight-pointY-(parTop-parScrollTop)-20)>=boxHeight){//说明鼠标上面放不下提示框
y = pointY+10;
}else {
y = pointY-boxHeight;
}
return [x,y];
}else {
x = pointX - boxWidth;
y = pointY+10;
return [x,y];
}
},
tooltipFormatter:function(params){
let str = `<div>`;
params.forEach((item, i) => {
if(i===0){
let t_date = new Date(item.data[0]);
str += [t_date.getFullYear(), t_date.getMonth() + 1, t_date.getDate()].join('-') + " "
+ [t_date.getHours(), t_date.getMinutes(),t_date.getSeconds()].join(':');
str +=`<br/>`;
}
let val = Number(item.data[1]);
str += `<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">`;
str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${item.color};}'></span>${item.seriesName}: </div>`;
str += `<div style="padding-left: 10px;">`;
str += chartDataFormat.getUnit(5).compute(val,null,2);
str += `</div>`;
str += `</div>`;
});
str +=`</div>`;
return str;
},
yAxisFormatter:function(value,index){
let unit=chartDataFormat.getUnit(5);
return unit.compute(value,index);
},
setSeries:function(series){
this.option.series=series;
if(!this.chart){
this.chart=echarts.init(document.getElementById(this.chartId));
}
this.chart.clear();
this.chart.setOption(this.option)
},
startLoading:function(){
this.$refs.loading.startLoading();
},
endLoading:function(){
this.$refs.loading.endLoading();
}
},
mounted() {
this.chart=echarts.init(document.getElementById(this.chartId));
this.chart.setOption(this.option);
}, },
watch:{ watch:{
},
destroyed() {
if(this.chart){
this.chart.clear();
}
} }
} }
</script> </script>
<style scoped> <style scoped>
.chart-room{
width: 95%;
height: 100%;
position: relative;
}
</style> </style>

View File

@@ -5,6 +5,9 @@
show:false, show:false,
}, },
color: this.bgColorList, color: this.bgColorList,
legend:{
show:false,
},
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
confine:false, confine:false,

View File

@@ -1,7 +1,6 @@
.overview{ .overview{
height: 100%; height: 100%;
} }
.overview-content-header{ .overview-content-header{
display: flex; display: flex;
padding-top: 10px; padding-top: 10px;
@@ -51,6 +50,14 @@
.operation .nz-icon-maxview{ .operation .nz-icon-maxview{
font-size: 1.875rem !important; font-size: 1.875rem !important;
} }
.overview-right{
//margin: 0;
//padding: 0;
//position: absolute;
//width: 100%;
//height: 100%;
//left:0; right:0; top:0; bottom:0;
}
.overview-content{ .overview-content{
height: calc(100% - 45px); height: calc(100% - 45px);
width: 100%; width: 100%;
@@ -79,8 +86,8 @@
.box-height-250{ .box-height-250{
height: 250px; height: 250px;
} }
.box-height-300{ .box-height-290{
height: 300px; height: 290px;
} }
.box-height-350{ .box-height-350{
height: 350px; height: 350px;
@@ -112,3 +119,7 @@
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
} }
.sub-title{
display: inline-block;
padding: 5px;
}

View File

@@ -10,7 +10,7 @@
</div> </div>
</div> </div>
<!--右侧内容--> <!--右侧内容-->
<div class="overview-right content-right"> <div class="overview-right content-right" id="mainDisplay">
<!--标题--> <!--标题-->
<div class="overview-content-header"> <div class="overview-content-header">
<div class="header-title">{{$t('dashboard.overview.contentTitle')}}</div> <div class="header-title">{{$t('dashboard.overview.contentTitle')}}</div>
@@ -21,7 +21,7 @@
<div class="week">{{sysWeek}}</div> <div class="week">{{sysWeek}}</div>
<div class="sys-date">{{sysDate}}</div> <div class="sys-date">{{sysDate}}</div>
</div> </div>
<div class="operation"><span ><i class="nz-icon nz-icon-maxview"></i></span></div> <div class="operation" @click="godView"><span ><i class="nz-icon nz-icon-maxview"></i></span></div>
</div> </div>
</div> </div>
</div> </div>
@@ -51,19 +51,34 @@
</div> </div>
</div> </div>
<div class="content-row-box"> <div class="content-row-box">
<div class="content-col-box box-height-300 "style="flex: 3"> <div class="content-col-box box-height-290 "style="flex: 3">
<div class="avg-children-space"> <div class="sub-title">
<el-select v-model="topNFilter.default" placeholder="" size="mini" style="display: inline-block;width: 200px" @change="topNChange"> <!--<el-select v-model="topNFilter.default" placeholder="" size="mini" style="display: inline-block;width: 200px" @change="topNChange">
<el-option v-for="(item,index) in topNFilter.options" :label="item.label" :value="item.value" :key="item.value+index"></el-option> <el-option v-for="(item,index) in topNFilter.options" :label="item.label" :value="item.value" :key="item.value+index"></el-option>
</el-select> </el-select>
<el-select v-model="topNFilter.defaultTop" placeholder="" size="mini" style="display: inline-block;width: 100px" @change="topNChange"> <el-select v-model="topNFilter.defaultTop" placeholder="" size="mini" style="display: inline-block;width: 100px" @change="topNChange">
<el-option v-for="(item,index) in topNFilter.tops" :label="item.label" :value="item.value" :key="item.value+index"></el-option> <el-option v-for="(item,index) in topNFilter.tops" :label="item.label" :value="item.value" :key="item.value+index"></el-option>
</el-select> </el-select>-->
<el-dropdown trigger="click">
<span>{{topNFilter.options.find((item)=>{return item.value==topNFilter.default})['label']}}<i class="el-icon-arrow-down el-icon--right"></i></span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(item,index) in topNFilter.options" :key="item.value+index" @click.native="()=>{topNFilter.default=item.value;topNChange();}">{{item.label}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-divider direction="vertical"></el-divider>
<el-dropdown trigger="click">
<span>{{topNFilter.tops.find((item)=>{return item.value==topNFilter.defaultTop})['label']}}<i class="el-icon-arrow-down el-icon--right"></i></span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(item,index) in topNFilter.tops" :key="item.value+index" @click.native="()=>{topNFilter.defaultTop=item.value;topNChange();}">{{item.label}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div> </div>
<table-box :pop-data="topNStatData" ref="topNTab" style="height: 90%;"></table-box> <table-box :pop-data="topNStatData" ref="topNTab" style="height: 90%;"></table-box>
</div> </div>
<div class="content-col-box box-height-300 "style="flex: 8;"></div> <div class="content-col-box box-height-290 "style="flex: 8;" id="alertTrendBox">
<div class="content-col-box box-height-300 "style="flex: 2;"> <chart-box ref="chartbox" :chart-title="$t('dashboard.overview.alert.chart.chartTitle')"></chart-box>
</div>
<div class="content-col-box box-height-290 "style="flex: 2;">
<table-box :pop-data="alertRuleStatData" ref="alertRuleTab" ></table-box> <table-box :pop-data="alertRuleStatData" ref="alertRuleTab" ></table-box>
</div> </div>
</div> </div>
@@ -75,11 +90,13 @@
<script> <script>
import tableBox from "./tableBox"; import tableBox from "./tableBox";
import chart from "./chart";
import axios from 'axios'; import axios from 'axios';
export default { export default {
name: "overview", name: "overview",
components:{ components:{
'table-box':tableBox 'table-box':tableBox,
'chart-box':chart,
}, },
props:[], props:[],
data(){ data(){
@@ -103,7 +120,9 @@
{label:this.$t('dashboard.overview.alert.top')+'50',value:50}, {label:this.$t('dashboard.overview.alert.top')+'50',value:50},
] ]
}, },
chartSeries:[],
alertRuleStatData:{}, alertRuleStatData:{},
isGodView:false,
sysTime:'', sysTime:'',
sysDate:'', sysDate:'',
sysWeek:'', sysWeek:'',
@@ -120,6 +139,7 @@
this.queryDataCenterData(); this.queryDataCenterData();
this.topNChange(); this.topNChange();
this.queryAlertRuleStatData(); this.queryAlertRuleStatData();
this.queryAlertTrendData();
}, },
queryAssetData:function(){ queryAssetData:function(){
this.$refs.assetTab.startLoading(); this.$refs.assetTab.startLoading();
@@ -136,6 +156,10 @@
}, },
formatAssetData:function(data,totalData){ formatAssetData:function(data,totalData){
if(data && totalData){ if(data && totalData){
data=data.map((item)=>{
item.alertInfo=`<span style="color: #FE6565;">${item.alertHigh}</span>/<span style="color: orange;">${item.alertMedium}</span>/<span style="color: #90ee90">${item.alertLow}</span>`;
return item;
})
let assetStatData={ let assetStatData={
screen:{ //左侧概览信息 screen:{ //左侧概览信息
show:true, show:true,
@@ -143,7 +167,7 @@
total:{ //左侧上方大图标及total信息 total:{ //左侧上方大图标及total信息
show:true, show:true,
direction:'row', direction:'row',
num:totalData.total, num:`<span style="font-size:1.875rem;"><span style="color: #1166bb">${totalData.total}</span>/<span style="color:#90EE90;">${totalData.inStock}</span>/<span style="color:orange">${totalData.outStock}</span></span>`,
title:this.$t('dashboard.overview.asset.title'), title:this.$t('dashboard.overview.asset.title'),
showPopover:true, showPopover:true,
icon:'nz-icon nz-icon-asset', icon:'nz-icon nz-icon-asset',
@@ -212,10 +236,14 @@
}, },
{ {
label:this.$t('dashboard.overview.asset.alert'), label:this.$t('dashboard.overview.asset.alert'),
prop:'alertTotal', prop:'alertInfo',
show:true, show:true,
showPopover:true, showPopover:true,
popover:[ popover:[
{
label:this.$t('dashboard.overview.asset.alertTotal'),
prop:'alertTotal'
},
{ {
label:this.$t('dashboard.overview.asset.alertLow'), label:this.$t('dashboard.overview.asset.alertLow'),
prop:'alertLow' prop:'alertLow'
@@ -669,6 +697,41 @@
return {} return {}
} }
}, },
queryAlertTrendData:function(){
this.$refs.chartbox.startLoading();
let cur=this.dateFormat('yyyy-mm-dd HH:MM:SS',new Date());
let beforeDate=new Date();
beforeDate.setHours(new Date().getHours()-1);
let before=this.dateFormat('yyyy-mm-dd HH:MM:SS',beforeDate);
let params={
query:'sum(nz_alert_nums)',
start:before,
end:cur,
step:'15s'
}
this.$get('/prom/api/v1/query_range',params).then(response=>{
if(response.status == 'success'){
if(response.data.result){
let series={
name: 'nz_alert_nums',
symbol:'none', //去掉点
smooth:true, //曲线变平滑
data: [],
type:'line',
areaStyle:{}
}
series.data=response.data.result[0].values.map((item)=>{
return [item[0]*1000,item[1]];
})
this.chartSeries=[series];
this.$refs.chartbox.setSeries(this.chartSeries);
this.$refs.chartbox.endLoading();
}
}else{
console.error(response)
}
})
},
/*加载数据 end*/ /*加载数据 end*/
getAssetTabTitle:function(){ getAssetTabTitle:function(){
switch (this.typeFilter) { switch (this.typeFilter) {
@@ -734,12 +797,18 @@
this.typeFilter=type; this.typeFilter=type;
this.queryAssetData(); this.queryAssetData();
}, },
topNChange:function(){ topNChange:function(item){
if(this.topNFilter.default == 'alertRule'){ if(this.topNFilter.default == 'alertRule'){
this.queryAlertTopNData(); this.queryAlertTopNData();
}else if(this.topNFilter.default == 'asset'){ }else if(this.topNFilter.default == 'asset'){
this.queryAssetTopNData(); this.queryAssetTopNData();
} }
},
godView:function(el){
},
exitGodView:function(el){
}, },
/*header 时间处理 start*/ /*header 时间处理 start*/
initDate:function(){ initDate:function(){
@@ -784,6 +853,25 @@
return enWeeks[day]; return enWeeks[day];
} }
}, },
dateFormat:function(fmt, date) {
let ret;
const opt = {
"y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"H+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"S+": date.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
},
/*header 时间处理end*/ /*header 时间处理end*/
jumpTo(data, id) { jumpTo(data, id) {
//this.$store.state.assetData.moduleData = data //this.$store.state.assetData.moduleData = data
@@ -813,4 +901,7 @@
.overview .el-scrollbar__wrap{ .overview .el-scrollbar__wrap{
margin-bottom: 0px !important; margin-bottom: 0px !important;
} }
.overview-table .el-table__body{
width: 100% !important;
}
</style> </style>

View File

@@ -10,6 +10,9 @@
.table-box .table-box-left{ .table-box .table-box-left{
flex: 1; flex: 1;
} }
.table-box .table-box-left-half{
flex:0.5;
}
.table-box .table-box-right{ .table-box .table-box-right{
flex:2; flex:2;
} }

View File

@@ -2,7 +2,7 @@
<div class="table-box" :class="{'table-column-box':showData&&showData.screen&&showData.screen.direction=='column'}"> <div class="table-box" :class="{'table-column-box':showData&&showData.screen&&showData.screen.direction=='column'}">
<loading ref="loading"></loading> <loading ref="loading"></loading>
<template v-if="showData&&showData.screen"> <template v-if="showData&&showData.screen">
<div class="table-box-left" v-show="showData.screen.show"> <div class="table-box-left" :class="{'table-box-left-half':showData.screen.total.direction == 'column'}" v-show="showData.screen.show">
<div class="table-screen" :class="{'fill-flex-cavity':!showData.screen.stat.show&&showData.screen.total.direction != 'column'}"> <div class="table-screen" :class="{'fill-flex-cavity':!showData.screen.stat.show&&showData.screen.total.direction != 'column'}">
<div class="screen-top" v-show="showData.screen.total.show" > <div class="screen-top" v-show="showData.screen.total.show" >
<div :class="{'screen-row':showData.screen.total.direction == 'row','screen-column':showData.screen.total.direction == 'column'}"> <div :class="{'screen-row':showData.screen.total.direction == 'row','screen-column':showData.screen.total.direction == 'column'}">
@@ -18,7 +18,8 @@
</div> </div>
</div> </div>
<template slot="reference"> <template slot="reference">
<div class="super-font">{{showData.screen.total.num}}</div> <!-- <div class="super-font">{{showData.screen.total.num}}</div>-->
<div class="super-font" v-html="showData.screen.total.num"></div>
</template> </template>
</el-popover> </el-popover>
</template> </template>
@@ -50,6 +51,7 @@
v-for="(item, index) in showData.table.tableLabel" v-for="(item, index) in showData.table.tableLabel"
v-if="item.show" v-if="item.show"
:key="`col-${index}`" :key="`col-${index}`"
:width="item.width"
:label="item.label" :label="item.label"
:render-header="item.renderHeader" :render-header="item.renderHeader"
show-overflow-tooltip show-overflow-tooltip
@@ -65,12 +67,12 @@
</div> </div>
</div> </div>
<template slot="reference"> <template slot="reference">
<span>{{scope.row[item.prop]}}</span> <span v-html="scope.row[item.prop]"></span>
</template> </template>
</el-popover> </el-popover>
</template> </template>
<template v-else> <template v-else>
{{scope.row[item.prop]}} <span v-html="scope.row[item.prop]"></span>
</template> </template>
</template> </template>
</el-table-column> </el-table-column>