pref:显示优化性修改

1.dashboard tooltip 宽度自适应
2.导入提示框关闭逻辑特殊化
3.endpoint-query 增加hide same labels 工能
4.endpoint-query图表:
   1).修复第一次点击,图表无法渲染的bug
   2).legend、tooltip 和element列统一
   3).legend 点击逻辑和dashboard统一
This commit is contained in:
wangwenrui
2020-03-06 09:29:53 +08:00
parent ac8dfd95b1
commit ef6166fe19
14 changed files with 208 additions and 645 deletions

View File

@@ -20,6 +20,9 @@ Created by iconfont
/> />
<missing-glyph /> <missing-glyph />
<glyph glyph-name="chart" unicode="&#59266;" d="M105.71 318.35v-232a25 25 0 1 1 50 0v232a25 25 0 0 1-50 0zM352.71 443.86v-357.48a25 25 0 0 1 50 0V443.86a25 25 0 0 1-50 0zM599.71 281v-194.62a25 25 0 0 1 50 0V281a25 25 0 0 1-50 0zM871.71 61.379999999999995a25 25 0 0 1 25 25v362a25 25 0 0 1-50 0v-362a25 25 0 0 1 25-25zM842.2 611.25a25 25 0 0 1 25-24.72h0.28a25 25 0 0 1 24.72 25.28l-1.72 155.07v0.23c0 0.47 0 0.94-0.07 1.4v0.34a25 25 0 0 1-0.53 3.36v0.16a26.32 26.32 0 0 1-1 3.3v0.07a24.75 24.75 0 0 1-1.48 3.12s0 0.08-0.07 0.13c-0.27 0.47-0.56 0.93-0.85 1.38l-0.05 0.07c-0.3 0.45-0.62 0.9-0.95 1.33l-0.19 0.24q-0.42 0.54-0.87 1l-0.2 0.24c-0.35 0.38-0.7 0.75-1.07 1.12l-0.28 0.26q-0.47 0.45-1 0.87l-0.26 0.23c-0.41 0.34-0.82 0.67-1.25 1l-0.22 0.16q-0.62 0.43-1.26 0.84l-0.14 0.09c-0.49 0.31-1 0.6-1.52 0.88a24.52 24.52 0 0 1-5.07 2c-0.57 0.15-1.14 0.28-1.72 0.4h-0.12c-0.49 0.09-1 0.17-1.48 0.23h-0.35c-0.53 0.06-1.06 0.11-1.6 0.13H698a25 25 0 0 1 0-50h102.8L566.38 528.54l-155.94 145.1a25 25 0 0 1-30.95 2.46l-262.7-176.16a25 25 0 1 1 27.84-41.52l246.25 165.12 158.27-147.27a25 25 0 0 1 33.85-0.2l258.09 234.59zM922.72-55a25 25 0 0 1 0 50H98a25 25 0 0 1 0-50z" horiz-adv-x="1024" />
<glyph glyph-name="duoxuan" unicode="&#59085;" d="M128 768v-768h768V768H128z m682.666667-682.666667H213.333333V682.666667h597.333334v-597.333334zM755.498667 496.896l-60.330667 60.373333L469.333333 331.434667 328.832 471.936l-60.330667-60.373333L469.333333 210.73066700000004z" horiz-adv-x="1024" /> <glyph glyph-name="duoxuan" unicode="&#59085;" d="M128 768v-768h768V768H128z m682.666667-682.666667H213.333333V682.666667h597.333334v-597.333334zM755.498667 496.896l-60.330667 60.373333L469.333333 331.434667 328.832 471.936l-60.330667-60.373333L469.333333 210.73066700000004z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

View File

@@ -495,7 +495,7 @@
}, },
formatter:function(params){ formatter:function(params){
//display:inline-block;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis; //display:inline-block;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;
let str = `<div style='width:600px;display:inline-block;line-height: 18px;font-size:12px;font-family: Roboto,Helvetica Neue,Arial,sans-serif;'>`; let str = `<div style='max-width:600px;display:inline-block;line-height: 18px;font-size:12px;font-family: Roboto,Helvetica Neue,Arial,sans-serif;'>`;
params.forEach((item, i) => { params.forEach((item, i) => {
let tip=legend.find((element)=>{ let tip=legend.find((element)=>{
return element.name == item.seriesName; return element.name == item.seriesName;
@@ -540,7 +540,7 @@
*/ */
str += `<div style='max-width:510px;display:inline-block;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;line-height: 18px;font-size:12px;font-family: Roboto,Helvetica Neue,Arial,sans-serif;'>`; str += `<div style='max-width:510px;display:inline-block;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;line-height: 18px;font-size:12px;font-family: Roboto,Helvetica Neue,Arial,sans-serif;'>`;
str +=`<span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${item.color};}'></span>${tip.alias?tip.alias:tip.name}: `; str +=`<span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${item.color};}'></span>${tip.alias?tip.alias:tip.name}: `;
str +=`</div>`; str +=`</div>`;
str += `<div style='max-width:90px;min-width:20px;float:right;text-align:right;display:inline-block;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;line-height: 18px;font-size:12px;font-family: Roboto,Helvetica Neue,Arial,sans-serif;'>`; str += `<div style='max-width:90px;min-width:20px;float:right;text-align:right;display:inline-block;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;line-height: 18px;font-size:12px;font-family: Roboto,Helvetica Neue,Arial,sans-serif;'>`;
str +=val; str +=val;

View File

@@ -10,7 +10,7 @@
</el-dropdown> </el-dropdown>
</div> </div>
<div> <div>
<el-dialog :visible.sync="importBox.show" :title="importBox.title" :modal-append-to-body='false' :show-close="true" :width="importBox.width" @close="closeDialog" class="nz-dialog"> <el-dialog :visible.sync="importBox.show" :title="importBox.title" :modal-append-to-body='false' :show-close="true" :width="importBox.width" @close="closeDialog" class="nz-dialog" :close-on-click-modal="importBox.type!=3">
<div v-if="importBox.type==1"> <div v-if="importBox.type==1">
<div class="upload-body"> <div class="upload-body">
<el-upload class="upload-demo" ref="uploadExcel" action="" :file-list="importFileList" :on-change="importChange" :auto-upload="false" accept=".xlsx,.xls"> <el-upload class="upload-demo" ref="uploadExcel" action="" :file-list="importFileList" :on-change="importChange" :auto-upload="false" accept=".xlsx,.xls">
@@ -60,11 +60,13 @@
</div> </div>
<div> <div>
<div class="result-title">{{$t('overall.result.failedDetail')}}:</div> <div class="result-title">{{$t('overall.result.failedDetail')}}:</div>
<div class="result-detail" v-if="importResult&&importResult.failDetail"> <el-scrollbar style="height: 100%">
<ul> <div class="result-detail" v-if="importResult&&importResult.failDetail">
<li v-for="(item,index) in importResult.failDetail"><span>{{item.lineNo}}</span>:<span>{{item.errorMsg}}</span> </li> <ul>
</ul> <li v-for="(item,index) in importResult.failDetail"><span>{{item.lineNo}}</span>:<span>{{item.errorMsg}}</span> </li>
</div> </ul>
</div>
</el-scrollbar>
</div> </div>
</div> </div>
<div slot="footer" class="footer"> <div slot="footer" class="footer">
@@ -311,7 +313,7 @@
} }
.result-detail{ .result-detail{
height: 100px; height: 100px;
overflow-y: auto; /*overflow-y: auto;*/
margin-bottom: 20px; margin-bottom: 20px;
} }
.result-body{ .result-body{

View File

@@ -481,7 +481,8 @@ const en = {
element: 'Element', element: 'Element',
value: 'Value', value: 'Value',
promExpr: 'Please input expression', promExpr: 'Please input expression',
dialogTitle:'View', //endpoint 弹出dialog 标题 dialogTitle:'View', //endpoint 弹出dialog 标题,
hideSameLabels:'Hide same labels'
}, },
metrics: { metrics: {
metrics: 'Metrics',//"指标" metrics: 'Metrics',//"指标"

View File

@@ -133,14 +133,14 @@
</el-col> </el-col>
<el-col :span="6" style="margin-left: 0px;"> <el-col :span="6" style="margin-left: 0px;">
<div class="grid-content" > <div class="grid-content" >
<el-form-item prop="heigh"> <el-form-item prop="height">
<!-- <el-input label="" v-model="chart.height" placeholder="" size="mini"></el-input>--> <!-- <el-input label="" v-model="chart.height" placeholder="" size="mini"></el-input>-->
<el-autocomplete <el-autocomplete
v-model="chart.height" v-model="chart.height"
:fetch-suggestions="querySearch" :fetch-suggestions="querySearch"
placeholder="" placeholder=""
size="mini" size="mini"
popper-class="popper-z-index" popper-class="popper-z-index no-style-class"
@select="handleSelect"> @select="handleSelect">
<template slot-scope="{ item }"> <template slot-scope="{ item }">
<div class="name">{{ item }}</div> <div class="name">{{ item }}</div>
@@ -224,11 +224,6 @@
title: [ title: [
{required: true, message: this.$t('validate.required'), trigger: 'blur'} {required: true, message: this.$t('validate.required'), trigger: 'blur'}
] ]
/*
heigh: [
{required: true, message: this.$t('validate.required'), trigger: 'blur'}
]
*/
}, },
chartTypeList: [ chartTypeList: [
{ {
@@ -347,12 +342,13 @@
}); });
}, },
del: function(u) { del: function(u) {
let cloneChart=JSON.parse(JSON.stringify(u))
this.$confirm(this.$t("tip.confirmDelete"), { this.$confirm(this.$t("tip.confirmDelete"), {
confirmButtonText: this.$t("tip.yes"), confirmButtonText: this.$t("tip.yes"),
cancelButtonText: this.$t("tip.no"), cancelButtonText: this.$t("tip.no"),
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
this.$delete("panel/"+this.panelId+"/charts?ids="+u.id).then(response => { this.$delete("panel/"+this.panelId+"/charts?ids="+cloneChart.id).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.esc(); this.esc();
this.$message({duration: 1000, type: 'success', message: this.$t("tip.deleteSuccess")}); this.$message({duration: 1000, type: 'success', message: this.$t("tip.deleteSuccess")});
@@ -629,7 +625,7 @@
this.chart.id = data.id; this.chart.id = data.id;
this.chart.title = data.title; this.chart.title = data.title;
this.chart.span = data.span; this.chart.span = data.span;
this.chart.height = data.height; this.chart.height = data.height+'';
this.chart.type = data.type; this.chart.type = data.type;
this.getSuggestMetric();//获得指标列表 this.getSuggestMetric();//获得指标列表
// 指标 // 指标

View File

@@ -33,7 +33,7 @@
<div class="top-tool-right"> <div class="top-tool-right">
<div class="top-tool-search relative-position" > <div class="top-tool-search relative-position" >
<el-input ref="queryPanel" @clear="clearInput" id="queryPanel" @focus="focusInput" @blur="blurInput" v-model="filter.searchName" class="query-input-inactive" size="mini" clearable > <el-input ref="queryPanel" @clear="clearInput" id="queryPanel" @focus="focusInput" @blur="blurInput" v-model="filter.searchName" class="query-input-inactive" size="mini" clearable >
<i slot="suffix" class="el-input__icon el-icon-search" @click="focusInput"></i> <i slot="suffix" class="el-input__icon el-icon-search" @click="focusInput" style="float: right"></i>
</el-input> </el-input>
</div> </div>

View File

@@ -1,577 +0,0 @@
<template>
<div class="new-search" >
<div class="search-input-all input-position" @click="">
<!-- 历史记录-->
<div class="search-history">
<el-popover placement="bottom"
v-model="historyShow"
>
<div>
<div class="history-title">
<span >{{$t('search.recentSearch')}}</span>
</div>
<ul>
<li v-for="(item,index) in queryHistory" class="history-li" @click="pickHistory(item)">{{item}}</li>
</ul>
</div>
<div slot="reference" @click.prevent.stop="" class="search-input-history" ><i class="el-icon-time" id="search-view-history"></i></div>
</el-popover>
</div>
<!-- 搜索框-->
<div class="input-center-box" id="input-center-box">
<el-autocomplete
id="query-expression"
class="inline-input"
v-model="queryExpression"
size="mini"
:fetch-suggestions="querySearch"
:placeholder="$t('project.endpoint.promExpr')"
@select="handleSelect"
ref="queryExpression"
>
<template slot-scope="{ item }">
<el-popover
trigger="hover"
placement="left"
>
<span><span class="tip-line-font">[{{item.type}}]&nbsp;</span>{{ item.key }}</span>
<span slot="reference">{{ item.key }}<!--:{{item.type}}--></span>
</el-popover>
</template>
</el-autocomplete>
</div>
<!-- 清空内容-->
<div class="clear-search" @click="clearInput">
<i class="el-icon-close"></i>
</div>
</div>
<button @click="filterTabelData" type="button" class="nz-btn nz-btn-size-normal nz-btn-style-light float-right" id="search-input-search"><i class="el-icon-search"></i></button>
</div>
<!--<div class="metric-search-box margin-r-20" :class="componetStyle">
<el-popover placement="bottom"
width="200"
v-model="historyShow"
>
<ul>
<li v-for="(item,index) in queryHistory" class="history-li" @click="pickHistory(item)">{{item}}</li>
</ul>
<div slot="reference" @click.prevent.stop="" class="search-input-history" ><i class="el-icon-time"/></div>
</el-popover>
<div class="search-input">
<el-autocomplete
id="query-expression"
class="inline-input"
v-model="queryExpression"
size="mini"
width="300"
:fetch-suggestions="querySearch"
:placeholder="$t('project.endpoint.promExpr')"
@select="handleSelect"
ref="queryExpression"
>
<template slot-scope="{ item }">
<span>{{ item.key }}&lt;!&ndash;:{{item.type}}&ndash;&gt;</span>
</template>
</el-autocomplete><button class="nz-btn nz-btn-size-normal nz-btn-style-light" @click="filterTabelData"><i class="el-icon-search"></i></button>
</div>
</div>-->
</template>
<script>
import en from "../../common/language/en";
export default {
name: "metricSearch",
props:{
metrics:{type:Array},
labels:{type:Array},
componetStyle:{type:String}
},
created() {
},
data:function(){
return {
queryExpression:'',//输入框显示的表达式
saveExpression:'',
filter:null, //filter
metricSet:false,//是否设置了metric
labelSet:false,//是否设置了label
suggestionArray:[], //提示下拉选的数组
inputElment:null,//输入框的html元素,
caretIndex:-1, //选中后光标的位置
localStorageHistoryKey:'endpoint_query_history',
queryHistory:[],
historyShow:false,
}
},
methods:{
querySearch(queryString, cb) {
// 调用 callback 返回建议列表的数据
let results=queryString?this.suggestionArray.filter(this.filter(queryString)):this.suggestionArray;
cb(results)
},
handleSelect(item) {
let temp=this;
console.log(temp.queryExpression)
if(item.type==='metric'){
temp.queryExpression=item.key+'{}';
temp.saveExpression=temp.queryExpression;
temp.filter=this.labelFilter;
temp.metricSet=true;
temp.suggestionArray=temp.labels;
this.foucsAndMoveCaret();
}else if(item.type==='label' && this.metricSet){
temp.queryExpression=temp.saveExpression.substr(0,temp.caretIndex)+item.key+'='+temp.saveExpression.substr(temp.caretIndex,temp.saveExpression.length);
temp.saveExpression=temp.queryExpression;
temp.suggestionArray=[];
temp.foucsAndMoveCaret();
}else if(item.type==='label' && !this.metricSet && !temp.labelSet){
temp.queryExpression="{"+item.key+"=}";
temp.saveExpression=temp.queryExpression;
temp.suggestionArray=[];
temp.labelSet=true;
temp.foucsAndMoveCaret();
}else if(item.type=='label'&& !this.metricSet && temp.labelSet){
temp.queryExpression=temp.saveExpression.substr(0,temp.caretIndex)+item.key+'='+temp.saveExpression.substr(temp.caretIndex,temp.saveExpression.length);
temp.saveExpression=temp.queryExpression;
temp.suggestionArray=[];
temp.foucsAndMoveCaret();
}
},
initFilter(queryString) {
return (suggestion) => {
return (suggestion.key.toLowerCase().indexOf(queryString.toLowerCase()) != -1);
};
},
labelFilter(queryString){
let caretPos = this.inputElment.selectionEnd;
queryString=queryString.substr(this.caretIndex,caretPos-this.caretIndex);
return (suggestion) => {
return (suggestion.key.toLowerCase().indexOf(queryString.toLowerCase()) != -1);
};
},
foucsAndMoveCaret(){
let temp=this;
temp.$refs.queryExpression.focus();
setTimeout(function(){
temp.caretIndex=temp.queryExpression.length-1
temp.inputElment.setSelectionRange(temp.caretIndex,temp.caretIndex);
},100);
},
filterTabelData:function(){
this.$emit('expression-change',this.queryExpression);
this.queryHistory.unshift(this.queryExpression);
if(this.queryHistory.length>10){
this.queryHistory.splice(10,this.queryHistory.length-10);
}
localStorage.setItem(this.localStorageHistoryKey,JSON.stringify(this.queryHistory));
},
pickHistory:function(expression){
this.queryExpression=expression;
this.filterTabelData();
this.historyShow=false;
},
clearInput:function(){
this.queryExpression=this.saveExpression='';
}
},
mounted() {
this.filter=this.initFilter;
this.suggestionArray=this.labels.concat(this.metrics);
this.inputElment=document.getElementById('query-expression');
this.queryHistory=JSON.parse(localStorage.getItem(this.localStorageHistoryKey))?JSON.parse(localStorage.getItem(this.localStorageHistoryKey)):[];
},
watch:{
queryExpression:function(n,o){
if(o.length<n.length){
if(n&&/\w*\{.*\}.*/i.test(n)){
let caretPos=this.inputElment.selectionEnd;
console.log('caretPos:'+caretPos+" lastOf:"+n.lastIndexOf('}'))
if(caretPos <= n.lastIndexOf('}')&&n.substr(caretPos-1,1)==','){
this.suggestionArray=this.labels;
this.saveExpression=n;
this.filter=this.labelFilter;
this.foucsAndMoveCaret();
}
}
}else{
this.saveExpression=n;
this.caretIndex=this.inputElment.selectionEnd;
if(n.length==0){
this.filter=this.initFilter;
this.suggestionArray=this.labels.concat(this.metrics);
this.metricSet=false;
this.labelSet=false;
}
if(n.length>0 && n.indexOf('{')==-1){
this.filter=this.initFilter;
this.suggestionArray=this.metrics;
}
}
}
}
}
</script>
<style scoped lang="scss">
@import '../../../assets/stylus/index';
/* .search-input-history{
display: inline-block;
border:1px solid #e5e5e5;
border-radius: 10%;
}
.search-input{
display: inline-block;
}
.metric-search-box {
display: inline-block;
}*/
.history-title{
width: 100%;
height: 40px;
line-height: 40px;
line-height: 40px;
text-align: center;
position: relative;
border-bottom: 1px solid #dfdfdf;
color: #2e2e2e;
}
.history-li{
padding: 5px 10px;
line-height: 20px;
}
.history-li:hover{
background: #f0f0f0;
cursor:pointer;
}
.tip-line-font{
color:$header-text-color;
}
.new-search{
display: flex;
position: relative;
line-height: 25px;
border-radius: 4px;
border: 1px solid #D8D8D8;
/*box-shadow: inset 0 0 5px 0 rgba(184,184,184,0.80);*/
}
.new-search .nz-btn {
box-shadow: 0 0 1px 1px #d8d8d8;
border-radius: 0 4px 4px 0;
}
.new-search .search-input-all{
width: 240px;
background-color: $content-right-background-color;
color: rgba(0,0,0,.55);
height: 24px;
line-height: 24px;
border-bottom-left-radius: 5px;
border-top-left-radius: 5px;
display: flex;
position: relative;
}
input {
background-color: $content-right-background-color;
}
.search-input-all .btn-retract{
padding: 0px 4px;
text-align: center;
}
.search-input-all .search-history{
padding: 0px 7px;
height: 16px;
line-height: 16px;
text-align: center;
border-right: 1px solid #e5e5e5;
margin-top: 4px;
position: relative;
}
.search-input-all .input-center-box{
flex: 1;
height: 100%;
overflow-x: auto;
overflow-y: hidden;
}
.input-center-box::-webkit-scrollbar {/*滚动条整体样式*/
width: 4px; /*高宽分别对应横竖滚动条的尺寸*/
height: 6px;
}
.input-center-box::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
border-radius: 3px;
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
background: rgba(0,0,0,0.2);
}
.input-center-box::-webkit-scrollbar-track {/*滚动条里面轨道*/
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
border-radius: 0;
background: rgba(0,0,0,0.1);
}
.search-input-all .clear-search{
padding: 0 5px;
text-align: center;
font-size: 12px;
}
.dataBackG{
background: #f0f0f0;
}
.none{
display: none !important;
}
.new-search-btn {
padding: 0 4px;
cursor: pointer;
}
.search-text{
display: inline-block;
margin-right: 20px;
}
.sreach_box{
position: relative;
width: 80%;
height: 25px;
padding: 20px;
background: #fff;
margin: 200px auto;
}
.keyring_sreach_right_btn{
width: 18%;
height: 25px;
float: right;
line-height: 25px;
text-align: center;
border: 1px solid #dfdfdf;
}
.keyring_sreach_right_btn .right-btn-group{
float: left;
width: 80%;
border-right: 1px solid #dfdfdf;
box-sizing: border-box;
}
.keyring_sreach_right_btn .right-btn-icon{
float: left;
width: 19%;
}
.sreach_box .close_zhezhao{
position: absolute;
right: 0;
top: -50px;
width: 24px;
height: 25px;
border-radius: 50%;
background: #fff;
text-align: center;
line-height: 28px;
font-size: 12px;
}
.localStorage_list_box{
position: absolute;
left: 10px;
top: 36px;
width: auto;
min-width:250px;
max-width: 350px;
height: auto;
border: 1px solid #dfdfdf;
background: #fff;
color: #2e2e2e;
text-align: left;
border-radius: 3px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
z-index: 9999;
font-size: 12px;
}
.localStorage_list_box .list_box_title{
width: 100%;
height: 40px;
line-height: 40px;
line-height: 40px;
text-align: center;
position: relative;
border-bottom: 1px solid #dfdfdf;
color: #2e2e2e;
}
.localStorage_list_box .list_box_title i{
position: absolute;
right: 10px;
}
.localStorage_list_box .list_box_content{
text-align: left;
padding: 5px 0;
box-sizing: border-box;
border-bottom: 1px solid #dfdfdf;
}
.localStorage_list_box ul li{
padding: 5px 10px;
line-height: 20px;
}
.localStorage_list_box ul li:hover{
background: #f0f0f0;
cursor:pointer;
}
.localStorage_list_box ul li span{
color: #2e2e2e;
}
.localStorage_list_box ul li .value{
font-weight: 600;
}
.localStorage_list_box .list_box_clear{
padding-left: 10px;
line-height: 40px;
}
.localStorage_list_box .list_box_clear:hover{
background: #f0f0f0;
cursor:pointer;
}
.input-center-box .sreach_fixe_left{
width: auto;
display: flex;
height: 100%;
min-width: 100%;
}
.sreach_list{
display: flex;
justify-content:flex-start;
height: 100%;
padding-left: 10px;
}
.sreach_fixe_left .selectinfo_box{
display: flex;
flex-shrink: 0;
width: auto;
height: auto;
margin: 3px 2px;
font-size: 12px;
}
.selectinfo_box .select_condition{
float:left;
height: 13px;
padding: 3px;
background:#f8f8f8;
line-height: 13px;
color: rgba(0,0,0,.55);
}
.selectinfo_box .select_content{
float: left;
line-height: 13px;
height: 13px;
padding: 3px;
background: #f0f0f0;
color: rgba(0,0,0,0.85);
display: flex;
}
.select_input{
height: 100%;
flex: 1;
float: left;
min-width: 100px;
}
.select_input input{
width: 100%;
height: 100%;
border: none;
float: left;
padding-left: 5px !important;
box-sizing: border-box;
}
.select_input input:focus {
border:none;
box-shadow:none;
}
.select_input .select_info_list{
position: absolute;
left: 100px;
top: 36px;
height: auto;
width: auto;
max-height: 240px;
padding: 5px 0;
background: #fff;
border: 1px solid #e5e5e5;
border-radius: 3px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
overflow-y: auto;
z-index: 9999;
}
.select_info_list ul li{
padding: 5px 10px;
line-height: 20px;
}
.select_info_list ul li:hover{
background: #f0f0f0;
cursor: pointer;
}
.sreach_input .input{
flex: 1;
height: 100%;
padding-left: 10px !important;
box-sizing: border-box;
position: relative;
}
.sreach_input .input input{
width: 100%;
height: 100%;
border: none;
padding: 0 !important;
float: left;
}
.sreach_box input:focus {
outline: none;
border-color: transparent;
box-shadow: none;
}
.sreach_input input::placeholder{
color: rgba(0,0,0,0.55)
}
.input_list{
position: absolute;
left: 47px;
top: 36px;
width: auto;
max-width: 400px;
max-height: 240px;
min-width: 300px;
background: #fff;
border-radius: 3px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
z-index: 9;
overflow-y: auto;
font-size: 12px;
}
.input_list ul{
padding: 4px 0;
}
.input_list ul li{
padding: 4px 10px;
line-height: 16px;
height: 20px;
}
.input_list ul li:hover{
background: #f0f0f0;
cursor:pointer;
}
.search-style-ind{
background: #f0f0f0;
cursor:pointer;
}
.sreach_fixe>i{
margin-right: 15px;
}
.is-disabled{
color: #C0C4CC;
cursor: not-allowed !important;
background: #fff !important;
}
li {
list-style: none;
}
</style>

View File

@@ -182,9 +182,8 @@
<!--时间选择器--> <!--时间选择器-->
<div class="top-tool-right"> <div class="top-tool-right">
<div class="top-tool-search relative-position" > <div class="top-tool-search relative-position" >
<!-- <metric-search :metrics="metricList" :labels="labelList" v-if="tableShow == 3" @expression-change="tableFilter"></metric-search>-->
<el-input ref="elementQuery" @clear="clearInput" id="elementQuery" @focus="focusInput" @blur="blurInput" v-model="queryExpression" class="query-input-inactive" size="mini" clearable :placeholder="$t('project.endpoint.promExpr')" > <el-input ref="elementQuery" @clear="clearInput" id="elementQuery" @focus="focusInput" @blur="blurInput" v-model="queryExpression" class="query-input-inactive" size="mini" clearable :placeholder="$t('project.endpoint.promExpr')" >
<i slot="suffix" class="el-input__icon el-icon-search" @click="focusInput"></i> <i slot="suffix" class="el-input__icon el-icon-search" style="float:right" @click="focusInput"></i>
</el-input> </el-input>
</div> </div>
<div class="margin-r-20 date-pick-group"> <div class="margin-r-20 date-pick-group">
@@ -203,10 +202,23 @@
</el-date-picker> </el-date-picker>
<button @click="changeTime(10)" class="nz-btn nz-btn-size-normal nz-btn-style-light change-time-height"><i class="el-icon-d-arrow-right"></i></button> <button @click="changeTime(10)" class="nz-btn nz-btn-size-normal nz-btn-style-light change-time-height"><i class="el-icon-d-arrow-right"></i></button>
</div> </div>
<el-dropdown split-button type="primary" size="mini" class="dropdownBtn">
<i class="nz-icon nz-icon-chart" @click="viewGraph" ></i>
<el-dropdown-menu slot="dropdown" style="padding:10px 4px 10px 10px;">
<el-row>
<el-col :span="16" style="padding-top: 4px;padding-left: 1px"><span style="padding-top: 2px">{{$t('project.endpoint.hideSameLabels')}}</span></el-col>
<el-col :span="8">
<el-dropdown-item class="dropdown-content" >
<el-switch v-model="hideSameLabels" active-color="#ee9d3f" size="small"></el-switch>
</el-dropdown-item>
</el-col>
</el-row>
<button @click="viewGraph" slot="reference" class="nz-btn nz-btn-size-normal nz-btn-style-normal nz-btn-min-width-120" :class="{'nz-btn-disabled':selectedEndpoints.length<1}"> </el-dropdown-menu>
<span class='top-tool-btn-txt'>{{$t('project.endpoint.addGraph')}}</span> </el-dropdown>
</button> <!-- <button @click="viewGraph" slot="reference" class="nz-btn nz-btn-size-normal nz-btn-style-normal nz-btn-min-width-120" :class="{'nz-btn-disabled':selectedEndpoints.length<1}">-->
<!-- <span class='top-tool-btn-txt'>{{$t('project.endpoint.addGraph')}}</span>-->
<!-- </button>-->
</div> </div>
</div> </div>
<div class="table-header-inner" @click="clearSelectedMetrics"><span><i class="nz-icon nz-icon-duoxuan " :class="{'control-icon-unchecked':selectedEndpoints.length<1,'control-icon-checked':selectedEndpoints.length>0}"></i></span></div> <div class="table-header-inner" @click="clearSelectedMetrics"><span><i class="nz-icon nz-icon-duoxuan " :class="{'control-icon-unchecked':selectedEndpoints.length<1,'control-icon-checked':selectedEndpoints.length>0}"></i></span></div>
@@ -244,7 +256,7 @@
</div> </div>
<span slot="reference"><i class="nz-icon nz-icon-info-normal metric-tip-icon"></i></span> <span slot="reference"><i class="nz-icon nz-icon-info-normal metric-tip-icon"></i></span>
</el-popover> </el-popover>
<span>{{scope.row.element}}</span> <span>{{hideSameLabels?scope.row.simpleElement: scope.row.element}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@@ -290,8 +302,8 @@
</div> </div>
<div class="line-area " style="height: 300px" ref="viewGraphChart" id="viewGraphChart"></div> <div class="line-area " style="height: 300px" ref="viewGraphChart" id="viewGraphChart"></div>
<div class="legend-container" id="legendArea" ref="legendArea"> <div class="legend-container" id="legendArea" ref="legendArea">
<div v-for="(item, index) in legend" :title="item.name" @click="clickLegend(item.name,index)" class="legend-item" :class="{'ft-gr':isGrey[index]}" :key="'legend_' + item.name+'_'+index"> <div v-for="(item, index) in legend" :title="hideSameLabels&&item.alias?item.alias:item.name" @click="clickLegend(item.name,index)" class="legend-item" :class="{'ft-gr':isGrey[index]}" :key="'legend_' + item.name+'_'+index">
<span class="legend-shape" :style="{background:(isGrey[index]?'#D3D3D3':bgColorList[index])}"></span>{{item.name}} <span class="legend-shape" :style="{background:(isGrey[index]?'#D3D3D3':bgColorList[index])}"></span>{{hideSameLabels&&item.alias?item.alias:item.name}}
<br/> <br/>
</div> </div>
</div> </div>
@@ -313,14 +325,12 @@
import echarts from 'echarts'; import echarts from 'echarts';
import chartBox from "../dashboard/chartBox"; import chartBox from "../dashboard/chartBox";
import bus from "../../../libs/bus"; import bus from "../../../libs/bus";
import metricSearch from "./metricSearch";
import axios from 'axios'; import axios from 'axios';
import exportXLSX from "../../common/exportXLSX"; import exportXLSX from "../../common/exportXLSX";
export default { export default {
name: "project2", name: "project2",
components: { components: {
'chart-box': chartBox, 'chart-box': chartBox,
'metric-search':metricSearch,
'export-excel':exportXLSX 'export-excel':exportXLSX
}, },
data() { data() {
@@ -443,8 +453,6 @@
queryExpression:'', queryExpression:'',
metricList: [], // metric列表 metricList: [], // metric列表
elementMetricDatas:[],//element 列提示信息列表 elementMetricDatas:[],//element 列提示信息列表
labelSet:new Set(),
labelList:[],
formatTime:'',//查询endpoint的时间 formatTime:'',//查询endpoint的时间
selectedEndpoints:[],//选中的metric{label='value'} selectedEndpoints:[],//选中的metric{label='value'}
chartDatas:[],//从query_range查询到的数据 chartDatas:[],//从query_range查询到的数据
@@ -535,12 +543,69 @@
}] }]
}, },
chartOptions:{ chartOptions:{
color: this.bgColorList, color: temp.bgColorList,
title: { title: {
text: "" text: ""
}, },
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
confine:false,
extraCssText:'z-index:1000;',
/*enterable:true, 导致tooltip不消失显示多个tooltip*/
position: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];
if(pointX<(viewWidth/2)){//说明鼠标在左边放不下提示框
x=pointX+10;
}else{
x = pointX - boxWidth;
}
if(pointY<(viewHeight/2)){//说明鼠标上面放不下提示框
y = pointY+10;
}else {
y = pointY-boxHeight;
}
return [x,y];
},
formatter:function(params){
//display:inline-block;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;
let str = `<div style='max-width:600px;display:inline-block;line-height: 18px;font-size:12px;font-family: Roboto,Helvetica Neue,Arial,sans-serif;'>`;
params.forEach((item, i) => {
let tip=temp.legend.find((element)=>{
return element.name == item.seriesName;
})
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 = parseFloat(Number(item.data[1]).toFixed(2));
if(val===0){
val = Number(item.data[1]);
}
str += `<div style='max-width:510px;display:inline-block;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;line-height: 18px;font-size:12px;font-family: Roboto,Helvetica Neue,Arial,sans-serif;'>`;
str +=`<span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${item.color};}'></span>${temp.hideSameLabels&& tip.alias?tip.alias:tip.name}: `;
str +=`</div>`;
str += `<div style='max-width:90px;min-width:20px;float:right;text-align:right;display:inline-block;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;line-height: 18px;font-size:12px;font-family: Roboto,Helvetica Neue,Arial,sans-serif;'>`;
str +=val;
str +=`</div>`;
});
str +=`</div>`;
return str;
},
}, },
legend: { legend: {
show:false, show:false,
@@ -675,18 +740,57 @@
'#f58220', '#c37e00', '#00ae9d', '#f26522', '#76becc', '#f58220', '#c37e00', '#00ae9d', '#f26522', '#76becc',
'#76624c', '#d71345', '#2468a2', '#ca8687', '#1b315e', '#76624c', '#d71345', '#2468a2', '#ca8687', '#1b315e',
], ],
panelData: [], //chart-box的panel下拉框数据 panelData: [], //chart-box的panel下拉框数据,
hideSameLabels:true,
sameLabels:['instance','module','project','asset','job','dc'],
} }
}, },
methods: { methods: {
clickLegend(legendName,index){ clickLegend(legendName,index){
if (this.graphChart) { //点击图表某一个legend图表只显示当前点击的曲线或柱状图其它隐藏再次点击已选中的legend ,显示全部
this.graphChart.dispatchAction({ let curIsGrey=this.isGrey[index];
type: 'legendToggleSelect', if(this.graphChart){
name: legendName this.legend.forEach((item,i)=>{
}); let isGrey = this.isGrey[i];
let isGreyTmp = this.isGrey[index]; if(index != i){
this.$set(this.isGrey, index, !isGreyTmp); if(!curIsGrey && !isGrey){
this.graphChart.dispatchAction({
type: 'legendUnSelect',
name: item.name
});
}else if(!curIsGrey && isGrey){
this.graphChart.dispatchAction({
type: 'legendSelect',
name: item.name
});
}else{
this.graphChart.dispatchAction({
type: 'legendUnSelect',
name: item.name
});
}
}else {
this.graphChart.dispatchAction({
type: 'legendSelect',
name: item.name
});
}
})
this.isGrey.forEach((item,i)=>{
if(index != i){
if(!curIsGrey && !item){
this.$set(this.isGrey, i, true);
}else if(!curIsGrey && item){
this.$set(this.isGrey, i, false);
}else{
this.$set(this.isGrey, i, true);
}
}else{
if(item === true){
this.$set(this.isGrey, i, false);
}
}
})
} }
}, },
formatLegend(name,chartWidth){ formatLegend(name,chartWidth){
@@ -1028,6 +1132,7 @@
for (let result of results){ for (let result of results){
// {"metric":{"instance":"192.168.40.126:9100","__name__":"scrape_duration_seconds","module":"node_exporter","project":"kafka","asset":"192.168.40.126","job":"ed_1","dc":"dc5"},"value":[1580782176.522,"0.000560761"]} // {"metric":{"instance":"192.168.40.126:9100","__name__":"scrape_duration_seconds","module":"node_exporter","project":"kafka","asset":"192.168.40.126","job":"ed_1","dc":"dc5"},"value":[1580782176.522,"0.000560761"]}
let temp=result.metric.__name__; let temp=result.metric.__name__;
let simpleTemp=result.metric.__name__;//显示简略信息隐藏same labels后的结果
let metricTip={}; let metricTip={};
let queryInfos=(this.elementMetricDatas.filter((item)=>{ let queryInfos=(this.elementMetricDatas.filter((item)=>{
return item.metric===temp; return item.metric===temp;
@@ -1039,17 +1144,22 @@
} }
delete result.metric.__name__; delete result.metric.__name__;
temp+="{"; temp+="{";
simpleTemp+="{";
for (let key in result.metric){ for (let key in result.metric){
temp+=key +"='"+result.metric[key]+"',"; temp+=key +"='"+result.metric[key]+"',";
this.labelSet.add(key); if(!this.sameLabels.some((i)=>{return i == key})){
simpleTemp+=key +"='"+result.metric[key]+"',";
}
} }
temp=temp.charAt(temp.length-1) == ","?temp.substr(0,temp.length-1):temp; temp=temp.charAt(temp.length-1) == ","?temp.substr(0,temp.length-1):temp;
simpleTemp=simpleTemp.charAt(simpleTemp.length-1) == ","?simpleTemp.substr(0,simpleTemp.length-1):simpleTemp;
temp+="}"; temp+="}";
let edpQueryData={element:temp,value:result.value[1],type:(result.metric.type?result.metric.type:'2'),metricTip:metricTip}; simpleTemp+="}";
if(!/.+\{.+\}/.test(simpleTemp)){
simpleTemp=simpleTemp.substr(0,simpleTemp.length-2);
}
let edpQueryData={element:temp,simpleElement:simpleTemp,value:result.value[1],type:(result.metric.type?result.metric.type:'2'),metricTip:metricTip};
this.showTableData.push(edpQueryData); this.showTableData.push(edpQueryData);
this.labelList=Array.from(this.labelSet).map((item,index)=>{
return {key:item,type:'label'}
})
} }
this.showTableDataCopy=JSON.stringify(this.showTableData); this.showTableDataCopy=JSON.stringify(this.showTableData);
this.tableShow=3; this.tableShow=3;
@@ -1178,10 +1288,16 @@
}else{ }else{
step='30m'; step='30m';
} }
let axiosArr=[];
for(let endpoint of this.selectedEndpoints){ for(let endpoint of this.selectedEndpoints){
this.$get("/prom/api/v1/query_range?query="+endpoint.element+"&start="+start+"&end="+end+"&step="+step).then(response=> { axiosArr.push(axios.get("/prom/api/v1/query_range?query="+endpoint.element+"&start="+start+"&end="+end+"&step="+step));
if (response.status === "success") { }
let queryData=response.data.result[0]; this.legend=[];
this.isGrey=[];
axios.all(axiosArr).then(res =>{
res.forEach((response,promIndex)=>{
if (response.status == 200) {
let queryData=response.data.data.result[0];
if(queryData){ if(queryData){
let chartData={ let chartData={
type:"line", type:"line",
@@ -1189,22 +1305,32 @@
smooth:true, //曲线变平滑 smooth:true, //曲线变平滑
}; };
chartData.name=queryData.metric.__name__; chartData.name=queryData.metric.__name__;
let alias=queryData.metric.__name__;
delete queryData.metric.__name__; delete queryData.metric.__name__;
chartData.name+="{"; chartData.name+="{";
alias+="{";
Object.keys(queryData.metric).forEach((item,index)=>{ Object.keys(queryData.metric).forEach((item,index)=>{
let label=item; let label=item;
let value=queryData.metric[label]; let value=queryData.metric[label];
chartData.name+=label +"='"+value+"',"; chartData.name+=label +"='"+value+"',";
if(!this.sameLabels.some((i)=>{return i == label})){
alias+=label +"='"+value+"',";
}
}) })
chartData.name=chartData.name.charAt(chartData.name.length-1) == ","?chartData.name.substr(0,chartData.name.length-1):chartData.name; chartData.name=chartData.name.charAt(chartData.name.length-1) == ","?chartData.name.substr(0,chartData.name.length-1):chartData.name;
alias=alias.charAt(alias.length-1) == ","?alias.substr(0,alias.length-1):alias;
chartData.name+="}"; chartData.name+="}";
alias+="}";
if(!/.+\{.+\}/.test(alias)){
alias=alias.substr(0,alias.length-2);
}
let legend={ let legend={
name:chartData.name, name:chartData.name,
alias:alias,
showText:this.formatLegend(chartData.name) showText:this.formatLegend(chartData.name)
} }
this.legend.push(legend); this.legend.push(legend);
this.screenLegendList.push(legend); this.isGrey.push(false);
this.isGreyScreen.push(false);
chartData.data=queryData.values.map((dpsItem, dpsIndex) => { chartData.data=queryData.values.map((dpsItem, dpsIndex) => {
return [dpsItem[0] * 1000, Number(dpsItem[1])]; return [dpsItem[0] * 1000, Number(dpsItem[1])];
}); });
@@ -1212,21 +1338,28 @@
} }
} }
}) })
} }, this.$nextTick(()=>{
this.graphChart.clear();
this.chartOptions.color=this.bgColorList;
this.chartOptions.series=this.chartDatas;
this.graphChart.setOption(this.chartOptions);//创建图表
});
})
},
dateChange:function(){ dateChange:function(){
if(this.graphChart){ if(this.graphChart){
this.graphChart.clear(); this.graphChart.clear();
this.queryChartDate();
} }
this.queryChartDate();
// this.chartOptions.legend.data=this.legend;
this.chartOptions.series=this.chartDatas;
this.graphChart.setOption(this.chartOptions);//创建图表
}, },
initDialog:function(){ initDialog:function(){
this.graphChart = echarts.init(document.getElementById('viewGraphChart')); this.graphChart = echarts.init(document.getElementById('viewGraphChart'));
// this.queryChartDate();
// this.chartOptions.legend.data=this.legend; // this.chartOptions.legend.data=this.legend;
this.chartOptions.series=this.chartDatas; // this.chartOptions.series=this.chartDatas;
this.graphChart.setOption(this.chartOptions);//创建图表 // this.graphChart.setOption(this.chartOptions);//创建图表
// console.log(this.chartOptions)
// let legendHeight = this.$refs.legendArea.offsetHeight; // let legendHeight = this.$refs.legendArea.offsetHeight;
// let dialogDom=document.getElementById('viewGraphDialog'); // let dialogDom=document.getElementById('viewGraphDialog');
// let dialogWidth=dialogDom.offsetWidth // let dialogWidth=dialogDom.offsetWidth
@@ -1264,10 +1397,10 @@
}); });
}, },
tableFilter:function(){ tableFilter:function(){
let temp=this;
let tableDatas=JSON.parse(this.showTableDataCopy); let tableDatas=JSON.parse(this.showTableDataCopy);
this.showTableData=tableDatas.filter((item)=>{ this.showTableData=tableDatas.filter((item)=>{
let element=item.element; let element=temp.hideSameLabels?item.simpleElement: item.element;
return element.indexOf(this.queryExpression) != -1; return element.indexOf(this.queryExpression) != -1;
}) })
}, },
@@ -1358,7 +1491,8 @@
} }
}, },
clearInput:function(){ clearInput:function(){
this.$refs.elementQuery.foucs();
this.$refs.elementQuery.focus();
}, },
queryElementTips:async function(){ queryElementTips:async function(){
this.elementMetricDatas=[]; this.elementMetricDatas=[];

View File

@@ -150,7 +150,7 @@ Vue.directive("scrollBar", {
}, },
}); });
const exceptClassName = ["config-dropdown", "nz-pop", "el-picker", "chart-box-dropdown", 'metric-dropdown', 'el-cascader__dropdown', "asset-dropdown"]; //clickoutside排除的class(白名单) const exceptClassName = ["config-dropdown", "nz-pop", "el-picker", "chart-box-dropdown", 'metric-dropdown', 'el-cascader__dropdown', "asset-dropdown","no-style-class"]; //clickoutside排除的class(白名单) no-style-class没有任何样式的class
const clickoutside = { const clickoutside = {
// 初始化指令 // 初始化指令
bind(el, binding, vnode) { bind(el, binding, vnode) {