perf:panel页面后台报错问题修复 & chart组件调整
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
<div class="clearfix chartTitle" :class="{'dragTitle':dragTitleShow}" :id="'chartTitle'+chartIndex">
|
||||
|
||||
<el-dropdown trigger="click" v-show="firstShow" class="nz-chart-top" :key="'chartDropdown'+chartIndex" v-clickoutside="clickos">
|
||||
<el-dropdown-menu style="display: none"></el-dropdown-menu>
|
||||
<span class="el-dropdown-link chart-title" @click="dropdownMenuShow=!dropdownMenuShow">
|
||||
<span class="chart-title-text">{{data.title}}</span>
|
||||
<span class="chart-title-icon"><i class="el-icon-caret-bottom el-icon--right" :class="{'visible':caretShow,'hidden':!caretShow}"></i></span>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<div class="clearfix chartTitle" :class="{'dragTitle':dragTitleShow}" :id="'chartTitle'+chartIndex">
|
||||
|
||||
<el-dropdown trigger="click" v-show="firstShow" class="nz-chart-top" :key="'chartDropdown'+chartIndex" v-clickoutside="clickos">
|
||||
<el-dropdown-menu style="display: none"></el-dropdown-menu>
|
||||
<span class="el-dropdown-link chart-title" @click="dropdownMenuShow=!dropdownMenuShow">
|
||||
<span class="chart-title-text">{{data.title}}</span>
|
||||
<span class="chart-title-icon"><i class="el-icon-caret-bottom el-icon--right" :class="{'visible':caretShow,'hidden':!caretShow}"></i></span>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<div class="clearfix chartTitle" :id="'chartTitle'+chartIndex" >
|
||||
|
||||
<el-dropdown trigger="click" v-show="firstShow" class="nz-chart-top" :key="'chartDropdown'+chartIndex" v-clickoutside="clickos">
|
||||
<el-dropdown-menu style="display: none"></el-dropdown-menu>
|
||||
<span class="el-dropdown-link chart-title" @click="dropdownMenuShow=!dropdownMenuShow">
|
||||
<span class="chart-title-text">{{data.title}}</span>
|
||||
<span class="chart-title-icon"><i class="el-icon-caret-bottom el-icon--right" :class="{'visible':caretShow,'hidden':!caretShow}"></i></span>
|
||||
|
||||
106
nezha-fronted/src/components/common/js/divResize.js
Normal file
106
nezha-fronted/src/components/common/js/divResize.js
Normal file
@@ -0,0 +1,106 @@
|
||||
var EleResize = {
|
||||
_handleResize: function (e) {
|
||||
var ele = e.target || e.srcElement;
|
||||
var trigger = ele.__resizeTrigger__;
|
||||
if (trigger) {
|
||||
var handlers = trigger.__z_resizeListeners;
|
||||
if (handlers) {
|
||||
var size = handlers.length;
|
||||
for (var i = 0; i < size; i++) {
|
||||
var h = handlers[i];
|
||||
var handler = h.handler;
|
||||
var context = h.context;
|
||||
handler.apply(context, [e]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_removeHandler: function (ele, handler, context) {
|
||||
var handlers = ele.__z_resizeListeners;
|
||||
if (handlers) {
|
||||
var size = handlers.length;
|
||||
for (var i = 0; i < size; i++) {
|
||||
var h = handlers[i];
|
||||
if (h.handler === handler && h.context === context) {
|
||||
handlers.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_createResizeTrigger: function (ele) {
|
||||
var obj = document.createElement('object');
|
||||
obj.setAttribute('style',
|
||||
'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -1;');
|
||||
obj.onload = EleResize._handleObjectLoad;
|
||||
obj.type = 'text/html';
|
||||
ele.appendChild(obj);
|
||||
obj.data = 'about:blank';
|
||||
return obj;
|
||||
},
|
||||
_handleObjectLoad: function (evt) {
|
||||
this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
|
||||
this.contentDocument.defaultView.addEventListener('resize', EleResize._handleResize);
|
||||
}
|
||||
};
|
||||
if (document.attachEvent) {//ie9-10
|
||||
EleResize.on = function (ele, handler, context) {
|
||||
var handlers = ele.__z_resizeListeners;
|
||||
if (!handlers) {
|
||||
handlers = [];
|
||||
ele.__z_resizeListeners = handlers;
|
||||
ele.__resizeTrigger__ = ele;
|
||||
ele.attachEvent('onresize', EleResize._handleResize);
|
||||
}
|
||||
handlers.push({
|
||||
handler: handler,
|
||||
context: context
|
||||
});
|
||||
};
|
||||
EleResize.off = function (ele, handler, context) {
|
||||
var handlers = ele.__z_resizeListeners;
|
||||
if (handlers) {
|
||||
EleResize._removeHandler(ele, handler, context);
|
||||
if (handlers.length === 0) {
|
||||
ele.detachEvent('onresize', EleResize._handleResize);
|
||||
delete ele.__z_resizeListeners;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
EleResize.on = function (ele, handler, context) {
|
||||
var handlers = ele.__z_resizeListeners;
|
||||
if (!handlers) {
|
||||
handlers = [];
|
||||
ele.__z_resizeListeners = handlers;
|
||||
|
||||
if (getComputedStyle(ele, null).position === 'static') {
|
||||
ele.style.position = 'relative';
|
||||
}
|
||||
var obj = EleResize._createResizeTrigger(ele);
|
||||
ele.__resizeTrigger__ = obj;
|
||||
obj.__resizeElement__ = ele;
|
||||
}
|
||||
handlers.push({
|
||||
handler: handler,
|
||||
context: context
|
||||
});
|
||||
};
|
||||
EleResize.off = function (ele, handler, context) {
|
||||
var handlers = ele.__z_resizeListeners;
|
||||
if (handlers) {
|
||||
EleResize._removeHandler(ele, handler, context);
|
||||
if (handlers.length === 0) {
|
||||
var trigger = ele.__resizeTrigger__;
|
||||
if (trigger) {
|
||||
trigger.contentDocument.defaultView.removeEventListener('resize', EleResize._handleResize);
|
||||
ele.removeChild(trigger);
|
||||
delete ele.__resizeTrigger__;
|
||||
}
|
||||
delete ele.__z_resizeListeners;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default EleResize;
|
||||
@@ -58,7 +58,7 @@ export default {
|
||||
localStorage.setItem('nz-sys-timezone',res.data.timezone);
|
||||
localStorage.setItem('nz-sys-default-cabinet-usize',res.data.defaultCabinetUsize);
|
||||
localStorage.setItem('nz-sys-max-terminal-num',res.data.maxTerminalNum);
|
||||
localStorage.setItem('nz-sys-asset-ping-switch',res.data.assetPingSwith);
|
||||
localStorage.setItem('nz-sys-asset-ping-switch',res.data.assetPingSwitch);
|
||||
this.$i18n.locale = this.lang;
|
||||
bus.$emit('login');
|
||||
this.$router.push({
|
||||
|
||||
296
nezha-fronted/src/components/page/dashboard/explore/explore.vue
Normal file
296
nezha-fronted/src/components/page/dashboard/explore/explore.vue
Normal file
@@ -0,0 +1,296 @@
|
||||
<template>
|
||||
<div class="explore">
|
||||
<left-menu >
|
||||
<div slot="content-left" class="slot-content">
|
||||
<div class="sidebar-title">{{$t('dashboard.title')}}</div>
|
||||
<div class="sidebar-info">
|
||||
<div class="sidebar-info-item " @click="jumpTo('overview')">{{$t('dashboard.overview.title')}}</div>
|
||||
<div class="sidebar-info-item" @click="jumpTo('panel')">{{$t('dashboard.panel.title')}}</div>
|
||||
<div class="sidebar-info-item" @click="jumpTo('metricPreview')">{{$t('dashboard.metricPreview.title')}}</div>
|
||||
<div class="sidebar-info-item sidebar-info-item-active" >{{$t('dashboard.metricPreview.title')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="content-right" class="slot-content">
|
||||
<div class="main-list main-and-sub-transition" >
|
||||
<!-- 顶部工具栏 -->
|
||||
<div class="top-tools" >
|
||||
<div class="nz-btn-group nz-btn-group-size-normal nz-btn-group-light margin-r-20">
|
||||
<button style="border-right: 1px solid rgba(162,162,162,0.50);" type="button"
|
||||
class="nz-btn nz-btn-size-normal nz-btn-style-light" @click="Refresh()">
|
||||
<i style="font-size: 12px" class="global-active-color nz-icon nz-icon-refresh"></i>
|
||||
</button><el-popover
|
||||
v-model="visible" placement="bottom-start" width="200" trigger="click">
|
||||
<ul class="popover_ul">
|
||||
<li v-for="i in intervalList" :style="{color:interval==i.value?'#31749C':''}" :key="i.value+i.name"
|
||||
@click="selectInterval(i.value)">
|
||||
{{i.name}}
|
||||
</li>
|
||||
</ul>
|
||||
<button type="button" style="border-radius: 0 4px 4px 0" class="nz-btn nz-btn-size-normal nz-btn-style-light" slot="reference">
|
||||
<i style="font-size: 12px" class="nz-icon nz-icon-arrow-down"></i>
|
||||
</button>
|
||||
</el-popover>
|
||||
</div>
|
||||
<el-date-picker size="mini" ref="calendar"
|
||||
format="yyyy/MM/dd HH:mm"
|
||||
@change="dateChange"
|
||||
v-model="searchTime"
|
||||
type="datetimerange"
|
||||
:picker-options="pickerOptions"
|
||||
:range-separator="$t('dashboard.panel.to')"
|
||||
:start-placeholder="$t('dashboard.panel.startTime')"
|
||||
:end-placeholder="$t('dashboard.panel.endTime')"
|
||||
style="margin-right: 20px"
|
||||
align="right">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<div class="expression-room">
|
||||
<promql-input
|
||||
v-for="index of promqlCount"
|
||||
:key="expressions[index]"
|
||||
:expression-list="expressions"
|
||||
:index="index"
|
||||
@change="expressionChange"
|
||||
@addExpression="addExpression"
|
||||
@removeExpression="removeExpression"
|
||||
></promql-input>
|
||||
</div>
|
||||
<div class="chart-room" style="width: 100%;height: 500px">
|
||||
<chart ref="exploreChart"></chart>
|
||||
</div>
|
||||
<div class="table-room">table</div>
|
||||
</div>
|
||||
</div>
|
||||
</left-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import bus from "../../../../libs/bus";
|
||||
import promqlInput from "./promqlInput";
|
||||
import chart from "../overview/chart";
|
||||
import axios from 'axios'
|
||||
import chartDataFormat from "../../../charts/chartDataFormat";
|
||||
export default {
|
||||
name: "explore",
|
||||
components:{
|
||||
'promql-input':promqlInput,
|
||||
'chart':chart,
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
promqlCount:1,
|
||||
expressions:[''],
|
||||
searchTime:[new Date().setHours(new Date().getHours() -1),new Date()],
|
||||
filterTime:{},
|
||||
visible:false,
|
||||
intervalList: [{
|
||||
value: 0,
|
||||
name: this.$t("dashboard.panel.refreshInterval.never"),
|
||||
}, {
|
||||
value: 60,
|
||||
name: this.$t("dashboard.panel.refreshInterval.oneMinute"),
|
||||
}, {
|
||||
value: 180,
|
||||
name: this.$t("dashboard.panel.refreshInterval.threeMinutes"),
|
||||
}, {
|
||||
value: 300,
|
||||
name: this.$t("dashboard.panel.refreshInterval.fiveMinutes"),
|
||||
}, {
|
||||
value: 600,
|
||||
name: this.$t("dashboard.panel.refreshInterval.tenMinutes"),
|
||||
}],
|
||||
interval: 0,
|
||||
pickerOptions: {
|
||||
shortcuts: [
|
||||
{
|
||||
text: this.$t("dashboard.panel.recOne"),
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setHours(start.getHours() - 1);
|
||||
picker.$emit('pick', [start, end]);
|
||||
}
|
||||
},{
|
||||
text: this.$t("dashboard.panel.recFour"),
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setHours(start.getHours() - 4);
|
||||
picker.$emit('pick', [start, end]);
|
||||
}
|
||||
}, {
|
||||
text: this.$t("dashboard.panel.recOneDay"),
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setDate(start.getDate() - 1);
|
||||
picker.$emit('pick', [start, end]);
|
||||
}
|
||||
}, {
|
||||
text: this.$t("dashboard.panel.yesterday"),
|
||||
onClick(picker) {
|
||||
const start = new Date();
|
||||
const end = new Date();
|
||||
start.setDate(start.getDate() - 1);
|
||||
start.setHours(0);
|
||||
start.setMinutes(0);
|
||||
start.setSeconds(0);
|
||||
end.setDate(end.getDate() - 1);
|
||||
end.setHours(23);
|
||||
end.setMinutes(59);
|
||||
end.setSeconds(59);
|
||||
picker.$emit('pick', [start, end]);
|
||||
}
|
||||
},{
|
||||
text: this.$t("dashboard.panel.recSevenDay"),
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setDate(start.getDate() - 7);
|
||||
picker.$emit('pick', [start, end]);
|
||||
}
|
||||
}, {
|
||||
text: this.$t("dashboard.panel.recOneMonth"),
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setDate(start.getDate() - 30);
|
||||
picker.$emit('pick', [start, end]);
|
||||
}
|
||||
}, {
|
||||
text: this.$t("dashboard.panel.curMonth"),
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setDate(1);
|
||||
start.setHours(0);
|
||||
start.setMinutes(0);
|
||||
picker.$emit('pick', [start, end]);
|
||||
}
|
||||
},{
|
||||
text: this.$t("dashboard.panel.lastMonth"),
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setDate(1);
|
||||
start.setMonth(start.getMonth() - 1);
|
||||
end.setDate(0);
|
||||
start.setStart();
|
||||
end.setEnd();
|
||||
picker.$emit('pick', [start, end]);
|
||||
}
|
||||
}],
|
||||
},
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.filterTime.startTime=bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss');
|
||||
this.filterTime.endTime=bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss');
|
||||
},
|
||||
methods:{
|
||||
queryChartData:function(){
|
||||
setTimeout(()=>{
|
||||
if(this.expressions.length>0){
|
||||
let requestArr=[];
|
||||
this.expressions.forEach((item,index)=>{
|
||||
if(item != ''){
|
||||
requestArr.push(axios.get('/prom/api/v1/query_range?query='+item+'&start='+this.filterTime.startTime+'&end='+this.filterTime.endTime+'&step=15'))
|
||||
}
|
||||
})
|
||||
axios.all(requestArr).then(res=>{
|
||||
if(res.length>0){
|
||||
let series=[];
|
||||
let legend=[];
|
||||
res.forEach((response,index)=>{
|
||||
if(response.data.status == 'success'){
|
||||
let data=response.data.data.result;
|
||||
data.forEach((result,index)=>{
|
||||
let seriesItem={
|
||||
name: '',
|
||||
symbol:'none', //去掉点
|
||||
smooth:true, //曲线变平滑
|
||||
data: [],
|
||||
type:'line',
|
||||
}
|
||||
seriesItem.data=result.values.map((item)=>{
|
||||
return [item[0]*1000,item[1]];
|
||||
})
|
||||
console.log(seriesItem);
|
||||
let metric=Object.assign({},result.metric);
|
||||
seriesItem.name+=metric.__name__+'{';
|
||||
delete metric.__name__;
|
||||
for (let key in metric){
|
||||
seriesItem.name+=key+"="+'"'+metric[key]+'",';
|
||||
}
|
||||
seriesItem.name=seriesItem.name.substr(0,seriesItem.name.length-1);
|
||||
seriesItem.name+="}";
|
||||
series.push(seriesItem);
|
||||
legend.push({name:seriesItem.name,alias:null,isGray:false});
|
||||
})
|
||||
}
|
||||
})
|
||||
this.$refs.exploreChart.setLegend(legend);
|
||||
this.$refs.exploreChart.setSeries(series)
|
||||
}
|
||||
})
|
||||
}
|
||||
},200)
|
||||
},
|
||||
queryTableData:function(){
|
||||
setTimeout(()=>{
|
||||
if(this.expressions.length>0){
|
||||
let requestArr=[];
|
||||
this.expressions.forEach((item,index)=>{
|
||||
if(item != ''){
|
||||
requestArr.push(axios.get('/prom/api/v1/query?query='+item))
|
||||
}
|
||||
})
|
||||
|
||||
axios.all(requestArr).then(res=>{
|
||||
res.forEach((response,index)=>{
|
||||
// console.log(response);
|
||||
})
|
||||
})
|
||||
}
|
||||
},200)
|
||||
},
|
||||
expressionChange:function(){
|
||||
this.queryTableData();
|
||||
this.queryChartData()
|
||||
},
|
||||
addExpression:function(index){
|
||||
this.expressions.splice(index+1,0,'');
|
||||
this.promqlCount++;
|
||||
},
|
||||
removeExpression:function(index){
|
||||
this.expressions.splice(index,1);
|
||||
this.promqlCount--;
|
||||
},
|
||||
dateChange(time) {
|
||||
this.filterTime.startTime=bus.timeFormate(time[0], 'yyyy-MM-dd hh:mm:ss');
|
||||
this.filterTime.endTime=bus.timeFormate(time[1], 'yyyy-MM-dd hh:mm:ss');
|
||||
},
|
||||
jumpTo(data, id) {
|
||||
bus.$emit("menu-change", data);
|
||||
this.$router.push({
|
||||
path: "/" + data,
|
||||
query: {
|
||||
t: +new Date()
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
watch:{
|
||||
promqlCount:function(n,o){
|
||||
this.expressionChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.explore{
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<div class="promqlInput">
|
||||
<div class="query-row">
|
||||
<div class="query-input">
|
||||
<div class="metricBtn">
|
||||
<el-dropdown class="metric-selector">
|
||||
<el-dropdown-menu style="display: none"></el-dropdown-menu>
|
||||
<el-button class="metric-btn" @click="toggleDropdown">Metric <i class="el-icon-arrow-down"></i></el-button>
|
||||
<el-cascader-panel v-show="dropDownVisible" v-model="cascaderValue" slot="dropdown" ref="metricSelector" :props="{emitPath:false}" :options="metricOptions" @change="metricChange"></el-cascader-panel>
|
||||
</el-dropdown>
|
||||
|
||||
</div>
|
||||
<div class="inputBox">
|
||||
<el-autocomplete :fetch-suggestions="filterInput" :trigger-on-focus="false" v-model="expressionList[index]" @blur="expressionChange" style="width: 100%"></el-autocomplete>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="query-options">
|
||||
<div class="option" @click="clearExpression"><i class="el-icon-close"></i></div>
|
||||
<div class="option" @click="addExpression"><i class="el-icon-plus"></i></div>
|
||||
<div class="option" @click="removeExpression"><i class="el-icon-minus"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "promqlInput",
|
||||
props:{
|
||||
index:{type:Number},
|
||||
expressionList:{}
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
dropDownVisible:false,
|
||||
metricStore:[],
|
||||
metricOptions:[],
|
||||
cascaderValue:'',
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.queryMetrics();
|
||||
|
||||
},
|
||||
methods:{
|
||||
clearExpression:function(){
|
||||
this.expressionList[this.index]='';
|
||||
},
|
||||
addExpression:function(){
|
||||
this.$emit('addExpression',this.index);
|
||||
},
|
||||
removeExpression:function(){
|
||||
this.$emit('removeExpression',this.index);
|
||||
},
|
||||
toggleDropdown:function(){
|
||||
this.dropDownVisible=!this.dropDownVisible;
|
||||
if(this.dropDownVisible == true){
|
||||
let $temp=this;
|
||||
document.addEventListener('click',function(e){
|
||||
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
|
||||
$temp.dropDownVisible=false;
|
||||
},false)
|
||||
this.$el.addEventListener('click',function(e){
|
||||
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
|
||||
},false)
|
||||
}
|
||||
},
|
||||
queryMetrics:function(){
|
||||
this.metricOptions=[];
|
||||
this.$get('prom/api/v1/label/__name__/values').then(response=>{
|
||||
if(response.status == 'success'){
|
||||
let metrics=response.data.sort();
|
||||
let metricMap=new Map();
|
||||
metrics.forEach((item)=>{
|
||||
let key='';
|
||||
if(/^[a-zA-Z]+?_[a-zA-Z]*/.test(item)){
|
||||
key=item.split('_')[0];
|
||||
}else if(/^_\w*/.test(item)){
|
||||
key=' ';
|
||||
}else{
|
||||
key=item;
|
||||
}
|
||||
if(metricMap.get(key)){
|
||||
let values=metricMap.get(key);
|
||||
values.push({label:item,value:item});
|
||||
}else{
|
||||
let values=[{label:item,value:item}];
|
||||
metricMap.set(key,values);
|
||||
}
|
||||
this.metricStore.push({label:item,value:item})
|
||||
})
|
||||
for(let key of metricMap.keys()){
|
||||
let option={
|
||||
label:key,
|
||||
value:key,
|
||||
}
|
||||
if(metricMap.get(key) && metricMap.get(key).length>1){
|
||||
option.children=metricMap.get(key);
|
||||
}
|
||||
this.metricOptions.push(option);
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
filterInput:function(queryString, cb){
|
||||
let metrics=Object.assign([],this.metricStore);
|
||||
let result=queryString?metrics.filter((item)=>{
|
||||
return item.value.toLowerCase().indexOf(queryString.toLowerCase()) != -1;
|
||||
}):metrics;
|
||||
cb(result)
|
||||
},
|
||||
metricChange:function(value){
|
||||
this.expressionList[this.index]=value;
|
||||
this.dropDownVisible=false;
|
||||
this.$emit('change')
|
||||
},
|
||||
expressionChange:function(){
|
||||
this.$emit('change')
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
dropDownVisible:function(n,o){
|
||||
if(this.$refs.metricSelector){
|
||||
this.$refs.metricSelector.dropDownVisible=n;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.promqlInput{
|
||||
position: relative;
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.promqlInput .query-row{
|
||||
width: 100%;
|
||||
}
|
||||
.query-row .query-input{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.promqlInput .query-options{
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
width: 126px;
|
||||
}
|
||||
.query-options .option{
|
||||
border-right: 1px solid #dde4ed;
|
||||
border-radius: 3px;
|
||||
background-color: #dde4ed;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.query-options .option:focus,.query-options .option:hover{
|
||||
background-color: #CCD7E4;
|
||||
}
|
||||
.query-input .metricBtn{
|
||||
width: 100px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.query-input .inputBox{
|
||||
width: 100%;
|
||||
}
|
||||
.metric-btn{
|
||||
background-color: #dde4ed;
|
||||
}
|
||||
.metric-btn:hover ,.metric-btn:focus {
|
||||
background-color: #CCD7E4;
|
||||
color:#606266;
|
||||
}
|
||||
.metric-selector .el-cascader-panel{
|
||||
height: 300px;
|
||||
position: absolute;
|
||||
z-index: 2100;
|
||||
background-color: #FFF;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.metric-selector-pop{
|
||||
position:relative;
|
||||
z-index: 2100;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -4,8 +4,14 @@
|
||||
|
||||
<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="chartId" ></div>
|
||||
|
||||
<div class="legend-container" id="legendArea" ref="legendArea" v-show="legend.length>0" v-scrollBar:legend>
|
||||
<div v-for="(item, index) in legend" :title="item.alias?item.alias:item.name" @click="clickLegend(item.name,index)" class="legend-item" :class="{'ft-gr':item.isGray}" :key="'legend_' + item.name+'_'+index">
|
||||
<span class="legend-shape" :style="{background:(item.isGray?'#D3D3D3':getBgColor(index))}"></span>{{item.alias?item.alias:item.name}}
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@@ -16,6 +22,8 @@
|
||||
import loading from "../../../common/loading";
|
||||
import uuidv1 from "uuid/v1";
|
||||
import chartConfig from './chartConfig'
|
||||
import bus from "../../../../libs/bus";
|
||||
import EleResize from "../../../common/js/divResize";
|
||||
export default {
|
||||
name: "chart",
|
||||
components:{
|
||||
@@ -24,6 +32,8 @@
|
||||
props:{
|
||||
chartTitle:{type:String},
|
||||
chartType:{type:String,default:'line'},
|
||||
tooltipFormatter:Function,
|
||||
yAxisFormatter:Function,
|
||||
map:{}
|
||||
},
|
||||
data(){
|
||||
@@ -31,19 +41,23 @@
|
||||
chart:null,
|
||||
option:{},
|
||||
chartId:new uuidv1()+'-'+new Date().getTime(),
|
||||
legend:[],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods:{
|
||||
|
||||
modifyOption:function(target,name,obj){
|
||||
if(this.option){
|
||||
this.option=chartConfig.getOption(this.chartType);
|
||||
}
|
||||
this.$set(this.option[target],name,obj)
|
||||
},
|
||||
setLegend:function(legend){
|
||||
this.legend=legend;
|
||||
this.resize();
|
||||
},
|
||||
setSeries:function(series){
|
||||
if(!this.chart){
|
||||
this.chart=echarts.init(document.getElementById(this.chartId));
|
||||
@@ -61,21 +75,153 @@
|
||||
if(this.option){
|
||||
this.option=chartConfig.getOption(this.chartType);
|
||||
}
|
||||
|
||||
this.modifyOption('tooltip','position',this.defaultTooltipPosition)
|
||||
|
||||
if (this.tooltipFormatter) {
|
||||
this.modifyOption('tooltip', 'formatter', this.tooltipFormatter)
|
||||
} else {
|
||||
this.modifyOption('tooltip', 'formatter', this.defaultTooltipFormatter)
|
||||
}
|
||||
|
||||
if(this.chartType == 'line'){
|
||||
if(this.yAxisFormatter){
|
||||
this.modifyOption('yAxis','formatter',this.yAxisFormatter)
|
||||
}else{
|
||||
this.modifyOption('yAxis','formatter',this.defaultYAxisFormatter)
|
||||
}
|
||||
}
|
||||
|
||||
this.$set(this.option,'series',this.series);
|
||||
/*if(this.chartType == 'line'){
|
||||
this.$set(this.option.tooltip,'formatter',this.tooltipFormatter);
|
||||
this.$set(this.option.tooltip,'position',this.tooltipPosition);
|
||||
this.$set(this.option.yAxis,'formatter',this.yAxisFormatter);
|
||||
}*/
|
||||
|
||||
this.chart.clear();
|
||||
this.chart.setOption(this.option)
|
||||
this.resize();
|
||||
},
|
||||
resizeChart:function(width,height){
|
||||
if(this.chart){
|
||||
this.chart.resize({width:width,height:height});
|
||||
}
|
||||
},
|
||||
resize:function(){
|
||||
if(this.chart){
|
||||
let height=this.$el.clientHeight ;
|
||||
let width=this.$el.clientWidth;
|
||||
if(this.chartTitle){
|
||||
height = height - 20;
|
||||
}
|
||||
if(this.legend && this.legend.length>0){
|
||||
height = height - 80;
|
||||
}
|
||||
this.chart.resize({width:width,height:height});
|
||||
}
|
||||
},
|
||||
getBgColor:function(index){
|
||||
let color=chartConfig.getBgColorList()[index];
|
||||
return color;
|
||||
},
|
||||
clickLegend(legendName,index){
|
||||
let curIsGrey=this.legend[index].isGray;
|
||||
if(this.chart){
|
||||
this.legend.forEach((item,i)=>{
|
||||
let isGrey = item.isGray;
|
||||
if(index != i){ //不是当前点击的
|
||||
if(!curIsGrey && !isGrey){
|
||||
this.chart.dispatchAction({
|
||||
type: 'legendUnSelect',
|
||||
name: item.name
|
||||
});
|
||||
item.isGray=true;
|
||||
}else if(!curIsGrey && isGrey){
|
||||
this.chart.dispatchAction({
|
||||
type: 'legendSelect',
|
||||
name: item.name
|
||||
});
|
||||
item.isGray=false;
|
||||
}else{
|
||||
this.chart.dispatchAction({
|
||||
type: 'legendUnSelect',
|
||||
name: item.name
|
||||
});
|
||||
item.isGray=true
|
||||
}
|
||||
}else {//当前点击的
|
||||
this.chart.dispatchAction({
|
||||
type: 'legendSelect',
|
||||
name: item.name
|
||||
});
|
||||
if(item.isGray === true){
|
||||
item.isGray = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
defaultTooltipPosition: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];
|
||||
}
|
||||
},
|
||||
defaultTooltipFormatter:function(params){
|
||||
let str = `<div>`;
|
||||
params.forEach((item, i) => {
|
||||
if(i===0){
|
||||
let value=bus.computeTimezone(item.data[0])
|
||||
let t_date = new Date(value);
|
||||
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;
|
||||
},
|
||||
defaultYAxisFormatter:function(value,index){
|
||||
let unit=chartDataFormat.getUnit(5);
|
||||
return unit.compute(value,index);
|
||||
},
|
||||
startLoading:function(){
|
||||
this.$refs.loading.startLoading();
|
||||
},
|
||||
@@ -85,6 +231,7 @@
|
||||
},
|
||||
mounted() {
|
||||
this.chart=echarts.init(document.getElementById(this.chartId));
|
||||
EleResize.on(this.$el,this.resize);
|
||||
},
|
||||
watch:{
|
||||
|
||||
@@ -98,9 +245,41 @@
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-room{
|
||||
.chart-room{
|
||||
width: 95%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
.chart-room .legend-container{
|
||||
width: calc(100% - 30px);
|
||||
/*max-height:80px;*/
|
||||
/*min-height:40px;*/
|
||||
height: 80px;
|
||||
font-size:12px;
|
||||
text-align:left;
|
||||
margin:0 auto;
|
||||
line-height: 18px;
|
||||
position: relative;
|
||||
}
|
||||
.chart-room .legend-container .legend-item{
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap;
|
||||
width:100%;
|
||||
overflow-x:hidden;
|
||||
cursor:pointer;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
line-height: 20px;
|
||||
}
|
||||
.chart-room .ft-gr{
|
||||
color:lightgray;
|
||||
}
|
||||
.chart-room .legend-shape{
|
||||
display:inline-block;
|
||||
margin-right:5px;
|
||||
border-radius:10px;
|
||||
width:15px;
|
||||
height:5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
<script>
|
||||
import chartDataFormat from "../../../charts/chartDataFormat";
|
||||
import bus from '../../../../libs/bus';
|
||||
let bgColorList=['#7bbfea', '#b3424a', '#f05b72', '#596032', '#bd6758',
|
||||
'#cd9a5b', '#918597', '#70a19f', '#005344', '#FF00FF',
|
||||
'#f7acbc', '#5f5d46', '#66ffff', '#ccFF66', '#f47920',
|
||||
'#769149', '#1d953f', '#abc88b', '#7f7522', '#9b95c9',
|
||||
'#f3715c', '#ea66a6', '#d1c7b7', '#9d9087', '#77787b',
|
||||
'#f58220', '#c37e00', '#00ae9d', '#f26522', '#76becc',
|
||||
'#76624c', '#d71345', '#2468a2', '#ca8687', '#1b315e',
|
||||
]
|
||||
const commonOption={
|
||||
title:{
|
||||
show:false,
|
||||
},
|
||||
color: this.bgColorList,
|
||||
color: bgColorList,
|
||||
legend:{
|
||||
show:false,
|
||||
},
|
||||
@@ -25,7 +33,7 @@
|
||||
},
|
||||
dataZoom: [{
|
||||
type: 'slider',
|
||||
show:true,
|
||||
show:false,
|
||||
xAxisIndex: [0],
|
||||
start: 0,
|
||||
end: 100,
|
||||
@@ -119,6 +127,9 @@
|
||||
},
|
||||
setMap:function(map){
|
||||
mapOptions.geo.map=map
|
||||
},
|
||||
getBgColorList:function(){
|
||||
return Object.assign([],bgColorList)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<div class="sidebar-info-item sidebar-info-item-active" >{{$t('dashboard.overview.title')}}</div>
|
||||
<div class="sidebar-info-item sidebar-info-top " @click="jumpTo('panel')">{{$t('dashboard.panel.title')}}</div>
|
||||
<div class="sidebar-info-item" @click="jumpTo('metricPreview')">{{$t('dashboard.metricPreview.title')}}</div>
|
||||
<div class="sidebar-info-item" @click="jumpTo('explore')">{{$t('dashboard.metricPreview.title')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--右侧内容-->
|
||||
@@ -48,7 +49,7 @@
|
||||
<table-box :pop-data="dataCenterStatData" ref="dataCenterTab" ></table-box>
|
||||
</div>
|
||||
<div style="flex: 3;">
|
||||
<chart-box chart-title="" chart-type="map" :map="map" ref="dataCenterMap"></chart-box>
|
||||
<chart-box chart-title="" chart-type="map" :tooltip-formatter="mapTooltipFormatter" :map="map" ref="dataCenterMap"></chart-box>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -940,71 +941,6 @@
|
||||
|
||||
return tooltip;
|
||||
},
|
||||
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 value=bus.computeTimezone(item.data[0])
|
||||
let t_date = new Date(value);
|
||||
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);
|
||||
},
|
||||
getAssetTabTitle:function(){
|
||||
switch (this.typeFilter) {
|
||||
case "typeStat":
|
||||
|
||||
Reference in New Issue
Block a user