feat:dashboard chart unit 配置

1.dashboard chart unit 配置
2.增加stack area 图表类型
This commit is contained in:
wangwenrui
2020-03-10 22:40:45 +08:00
parent c522965257
commit 40db6afd46
8 changed files with 499 additions and 68 deletions

View File

@@ -261,6 +261,11 @@ export default {
},
metric_name: '',
};
if(chartInfo.type === 'stackArea'){
seriesItem.theData.type='line';
seriesItem.theData.stack='stack'
seriesItem.theData.areaStyle={};
}
// 图表中每条线的名字,后半部分
let host = '';//up,
if(queryItem.metric.__name__){
@@ -332,7 +337,7 @@ export default {
}
}
});
if(this.$refs.editChart[index]) {
if(this.$refs.editChart&&this.$refs.editChart[index]) {
if (chartItem.type === 'table') {//表格
if (filterType === 'showFullScreen') {//table的全屏查询
this.$refs.editChart[index].setData(chartItem, tableData,
@@ -341,7 +346,7 @@ export default {
this.$refs.editChart[index].setData(chartItem, tableData,
this.filter.panelId, this.filter);
}
} else if (chartItem.type === 'line' || chartItem.type === 'bar' || chartItem.type === 4) {
} else if (chartItem.type === 'line' || chartItem.type === 'bar' || chartItem.type === 'stackArea' || chartItem.type === 4) {
if (series.length && chartItem.type === 4) {//曲线汇总
//series.push(sumData);//后续需要
}
@@ -365,7 +370,7 @@ export default {
this.$refs.editChart[index].setData(chartItem, [], this.filter.panelId,
this.filter);
}
} else if (type === 'line' || type === 'bar' || chartItem.type === 4) {
} else if (type === 'line' || type === 'bar' || type === 'stackArea' || chartItem.type === 4) {
if (filterType === 'showFullScreen') {//table的全屏查询
this.$refs.editChart[index].setData(chartItem, [], this.filter.panelId,
this.filter, filterType);

View File

@@ -0,0 +1,350 @@
function none(value,index){
return value;
}
function short(value,index){
return asciiCompute(value,1000,['','K','Mil','Bil'],0)
}
function percent01(value,index){
return `${value}%`;
}
function percent02(value,index){
return `${value * 100 }%`;
}
function localFormat(value,index){
let num = (value || 0).toString();
let result = '';
while (num.length > 3) {
result = ',' + num.slice(-3) + result;
num = num.slice(0, num.length - 3);
}
if (num) { result = num + result; }
return result;
}
function bits(value,index){
return asciiCompute(value,1024,['b','B','KB','MB','GB','TB','PB','EB','ZB','YB'],0)
}
function bytes(value,index){
return asciiCompute(value,1024,['B','KB','MB','GB','TB','PB','EB','ZB','YB'],0)
}
function kilobytes(value,index){
return asciiCompute(value,1024,['KB','MB','GB','TB','PB','EB','ZB','YB'],0)
}
function megabytes(value,index){
return asciiCompute(value,1024,['MB','GB','TB','PB','EB','ZB','YB'],0)
}
function gigabytes(value,index){
return asciiCompute(value,1024,['GB','TB','PB','EB','ZB','YB'],0)
}
function terabytes(value,index){
return asciiCompute(value,1024,['TB','PB','EB','ZB','YB'],0)
}
function petabytes(value,index){
return asciiCompute(value,1024,['PB','EB','ZB','YB'],0)
}
function packetsSec(value,index){
return asciiCompute(value,1000,['pps','Kpps','Mpps','Gpps','Tpps','Ppps','Epps','Zpps','Ypps'],1)
}
function bitsSec(value,index){
return asciiCompute(value,1000,['bps','Kbps','Mbps','Gbps','Tbps','Pbps','Epps','Zpps','Ypps'],1)
}
function bytesSec(value,index){
return asciiCompute(value,1000,['Bs','KBs','MBs','GBs','TBs','PBs','EBs','ZBs','YBs'],1)
}
function kilobytesSec(value,index){
return asciiCompute(value,1000,['KBs','MBs','GBs','TBs','PBs','EBs','ZBs','YBs'],1)
}
function kilobitsSec(value,index){
return asciiCompute(value,1000,['Kbps','Mbps','Gbps','Tbps','Pbps','Ebps','Zbps','Ybps'],1)
}
function megabytesSec(value,index){
return asciiCompute(value,1000,['MBs','GBs','TBs','PBs','EBs','ZBs','YBs'],1)
}
function megabitsSec(value,index){
return asciiCompute(value,1000,['Mbps','Gbps','Tbps','Pbps','Ebps','Zbps','Ybps'],1)
}
function gigabytesSec(value,index){
return asciiCompute(value,1000,['GBs','TBs','PBs','EBs','ZBs','YBs'],1)
}
function gigabitsSec(value,index){
return asciiCompute(value,1000,['Gbps','Tbps','Pbps','Ebps','Zbps','Ybps'],1)
}
function terabytesSec(value,index){
return asciiCompute(value,1000,['TBs','PBs','EBs','ZBs','YBs'],1)
}
function terabitsSec(value,index){
return asciiCompute(value,1000,['Tbps','Pbps','Ebps','Zbps','Ybps'],1)
}
function petabytesSec(value,index){
return asciiCompute(value,1000,['PBs','EBs','ZBs','YBs'],1)
}
function petabitsSec(value,index){
return asciiCompute(value,1000,['Pbps','Ebps','Zbps','Ybps'],1)
}
function Hertz(value,index){
return asciiCompute(value,1000,['Hz','KHz','MHz','GHz','THz','PHz','EHz','ZHz','YHz'],1);
}
function nanoseconds(value,index){
}
/*
* 一般数值格式化方法
* num: 需要格式化的值
* ascii:进制比如数据为1024
* units单位列表
* dot保留的小数位
* unitIndex不需要传递用于递归获取units中的单位
* */
function asciiCompute(num,ascii,units,dot=2,unitIndex=0){
num = parseFloat(num)
let quotient=num / ascii;
if(unitIndex <= units.length-1){
if(quotient <1 ){ //不足以进位
let toFixed=parseFloat(num.toFixed(dot));
if(toFixed == 0){
return `${num}${units[unitIndex]}`
}else{
return `${num.toFixed(dot)}${units[unitIndex]}`;
}
}else if(quotient >= 1 && quotient <10){ //可以进位,但是又不足以更进一位
if(unitIndex >= units.length-1){
unitIndex++;
return asciiCompute(num,ascii,units,dot,unitIndex);
}else{
unitIndex++;
return `${quotient.toFixed(dot)}${units[unitIndex]}`;
}
} else{ //可以更进一位
if(unitIndex >= units.length-1){
unitIndex++;
return asciiCompute(num,ascii,units,dot,unitIndex);
}else{
unitIndex++;
num=quotient;
return asciiCompute(num,ascii,units,dot,unitIndex);
}
}
}else{
return `${num.toFixed(2)}${units[units.length-1]}`;
}
}
/*
* 时间格式化方法
* */
//unit转化配置信息
/*
* value:传递给数据库的值
* label下拉选显示的名字
* compute用于格式化计算的方法返回一个string类型的串
* */
let unitOptions=[
{//Misc start
value:'Misc',
label:'Misc',
children:[
{
value:1,
compute:none,
label:'none'
},
{
value:2,
compute:short,
label:'short'
},
{
value:3,
compute:percent01,
label:'percent(0-100)'
},
{
value:4,
compute:percent02,
label:'percent(0.0-0.1)'
},
{
value:5,
compute:localFormat,
label:'local format'
}
]
},//Misc end
{//Data start
value:'Data',
label:'Data',
children: [
{
value:6,
compute:bits,
label:'bits'
},
{
value:7,
compute:bytes,
label:'bytes'
},
{
value:8,
compute:kilobytes,
label:'kilobytes'
},
{
value:9,
compute:megabytes,
label:'megabytes'
},
{
value:10,
compute:gigabytes,
label:'gigabytes'
},
{
value:11,
compute:terabytes,
label:'terabytes'
},
{
value:12,
compute:petabytes,
label:'petabytes'
}
]
},//Data end
{//DataRate start
value:'DataRate',
label:'DataRate',
children: [
{
value:13,
compute:packetsSec,
label:'packets/sec'
},
{
value:14,
compute:bitsSec,
label:'bits/sec'
},
{
value:15,
compute:bytesSec,
label:'bytes/sec'
},
{
value:16,
compute:kilobytesSec,
label:'kilobytes/sec'
},
{
value:17,
compute:kilobitsSec,
label:'kilobits/sec'
},
{
value:18,
compute:megabytesSec,
label:'megabytes/sec'
},
{
value:19,
compute:megabitsSec,
label:'megabits/sec'
},
{
value:20,
compute:gigabytesSec,
label:'gigabytes/sec'
},
{
value:21,
compute:gigabitsSec,
label:'gigabits/sec'
},
{
value:22,
compute:terabytesSec,
label:'terabytes/sec'
},
{
value:23,
compute:terabitsSec,
label:'terabits/sec'
},
{
value:24,
compute:petabytesSec,
label:'petabytes/sec'
},
{
value:25,
compute:petabitsSec,
label:'petabits/sec'
}
]
},//DataRate end
{//Time start
value:'Time',
label: 'Time',
children: [
{
value:26,
compute:Hertz,
label:'Hertz (1/s)'
},
{
value:27,
compute:nanoseconds,
label:'nanoseconds (ns)'
},
{
value:28,
compute:null,
label:'microseconds (us)'
},
{
value:29,
compute:null,
label:'milliseconds (ms)'
},
{
value:30,
compute:null,
label:'seconds (s)'
},
{
value:31,
compute:null,
label:'minutes (m)'
},
{
value:32,
compute:null,
label:'hours (h)'
},
{
value:33,
compute:null,
label:'days (d)'
},
]
}//Time end
]
let units=[];
window.onload=function(){
unitOptions.forEach((item,index)=>{
item.children.forEach((n,i)=>{
units.push(n);
})
})
console.log(units)
}
export default {
unitOptions:function(){
return unitOptions;
},
getUnit:function(index){
return units[index-1];
},
short,
}

View File

@@ -89,6 +89,7 @@
import echarts from 'echarts';
import bus from '../../libs/bus';
import loading from "../common/loading";
import chartDataFormat from './chartDataFormat'
export default {
name: 'lineChartBlock',
@@ -498,8 +499,21 @@
}
},
formatter:function(params){
// let maxWidth=0;
let avgWidth=0;
let sumWidth=0;
params.forEach((item, i) => {
let tip=legend.find((element)=>{
return element.name == item.seriesName;
})
let curLength=(tip.alias?tip.alias:tip.name).length;
// maxWidth=maxWidth>curLength?maxWidth:curLength;
sumWidth+=curLength;
})
avgWidth=sumWidth/params.length;
//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;'>`;
let str = `<div style='width:${avgWidth*11}px;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=legend.find((element)=>{
return element.name == item.seriesName;
@@ -543,9 +557,9 @@
str +=seriesNameTmp+":"+val;
*/
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 +=`</div>`;
// str +=`<div style="display: inline-block;max-width: 10px; min-width: 5px;line-height: 18px;"></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>`;
@@ -670,35 +684,10 @@
show:true
},
axisLabel: {
formatter: function(num,index) {
if (num >= 1000) {
const kbNum = num / 1000;
if (kbNum >= 1000) {
const mbNum = kbNum / 1000;
if (mbNum >= 1000) {
const gbNum = mbNum / 1000;
/*
if (gbNum > 1000) {
const tbNum = gbNum / 1000;
if (tbNum > 1000) {
const pbNum = tbNum / 1000;
return `${pbNum.toFixed(2)}PB`;
}
return `${tbNum.toFixed(2)}TB`;
}*/
return `${parseFloat(gbNum.toFixed(2))}B`;
}
return `${parseFloat(mbNum.toFixed(2))}M`;
}
return `${parseFloat(kbNum.toFixed(2))}K`;
}else {
let rlt = parseFloat(num.toFixed(2));
if(rlt===0){
return num;
}else {
return rlt;
}
}
formatter: function(value,index){
let chartUnit=chartInfo.unit;
let unit=chartDataFormat.getUnit(chartUnit);
return unit.compute(value,index);
},
},
//boundaryGap:[0,0.2]
@@ -1401,7 +1390,11 @@
}, 500)
*/
},
beforeDestroy() {},
beforeDestroy() {
if(this.echartStore){
this.echartStore.clear();
}
},
};
</script>

View File

@@ -88,6 +88,7 @@ const en = {
chartId:"ID",
chartName:"Chart Name",
type:"Type",
unit:"Unit",
legend:'Legend',
legendTip:'Controls the name of the time series, using name or pattern. For example {{hostname}} will be replaced with label value for the label hostname.',
typeVal:{
@@ -99,6 +100,9 @@ const en = {
},
table:{
label:'Table' //"表格"
},
stackArea:{
label:"Stack Area"
}
},
width:'Width', //"宽"
@@ -261,9 +265,11 @@ const en = {
protocol:"Protocol",
sshProtocol:"SSH",
telnetProtocol:"Telnet",
userTip:"UserTip",
passwordTip:"PasswordTip",
reloginPasswordTip:"Relogin",
userTip:"UserTip",//用户名提示
passwordTip:"PasswordTip",//密码提示
reloginPasswordTip:"Relogin",//密码提示
userPwdIntroduce:'Please specify a user name and password so that the telenet login process can automatically log in',
reLoginPwdIntroduce:'Please specify the password prompt so that the login process can run automatically',
account:'User name',//'用户名'
port:'Port',//'端口'
upload:'Upload',//'上传'
@@ -488,7 +494,11 @@ const en = {
value: 'Value',
promExpr: 'Please input expression',
dialogTitle:'View', //endpoint 弹出dialog 标题,
hideSameLabels:'Hide same labels'
hideSameLabels:'Hide same labels',
stateInfo_230009:'promserver available',
stateInfo_230010:'promserver can be used',
stateInfo_230011:'promserver can not beused ',
},
metrics: {
metrics: 'Metrics',//"指标"

View File

@@ -51,12 +51,18 @@
<div class="telnet-option" v-show="isEdit && account.protocol=='TELNET'">
<div class="telnet-option_title clickable" @click="isShowTelnetOption">login option<i style="font-size: 12px;" :class="{'el-icon-arrow-left':!showTelnetOption,'el-icon-arrow-down':showTelnetOption}"></i></div>
<div v-show="isEdit && account.protocol=='TELNET' && showTelnetOption" class="auto-login-tip">
{{$t('asset.createAssetTab.userPwdIntroduce')}}
</div>
<el-form-item :label="$t('asset.createAssetTab.userTip')" v-show="isEdit && account.protocol=='TELNET' && showTelnetOption" >
<el-input type="text" size="small" v-model="account.userTip" />
</el-form-item>
<el-form-item :label="$t('asset.createAssetTab.passwordTip')" v-show="isEdit && account.protocol=='TELNET' && showTelnetOption">
<el-input type="text" size="small" v-model="account.passwordTip" />
</el-form-item>
<div v-show="isEdit && account.protocol=='TELNET' && showTelnetOption" class="auto-login-tip">
{{$t('asset.createAssetTab.reLoginPwdIntroduce')}}
</div>
<el-form-item :label="$t('asset.createAssetTab.reloginPasswordTip')" v-show="isEdit && account.protocol=='TELNET' && showTelnetOption">
<el-input type="text" size="small" v-model="account.reloginPasswordTip" />
</el-form-item>
@@ -210,4 +216,11 @@ export default {
vertical-align: middle;
margin-bottom: 18px;
}
.auto-login-tip{
font-size: 12px;
margin-bottom: 18px;
color: #b4b4b4;
min-height: 18px;
}
</style>

View File

@@ -649,6 +649,7 @@
if (data === 'showAdd') {
//this.addUnitShow = true;
this.editUnitShow = true;
this.$refs['assetEditUnit'].accountSwitch=false;
this.$refs['assetEditUnit'].getAssetData('');
this.$refs['assetEditUnit'].resetAsset();
}

View File

@@ -152,6 +152,22 @@
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="2">
<div class="label-center" >{{$t('dashboard.panel.chartForm.unit')}}</div>
</el-col>
<el-col :span="22">
<el-cascader filterable placeholder="" popper-class="chart-box-dropdown" size="small" style="width: 100%"
:options="unitOptions"
:props="{ expandTrigger: 'hover' }"
:show-all-levels="false"
v-model="chart.unit"
@change="unitSelected"
>
</el-cascader>
</el-col>
</el-row>
<div class="right-box-sub-title">{{$t('dashboard.panel.chartForm.metric')}}</div>
<div class="line-100"></div>
@@ -193,7 +209,7 @@
<script>
import bus from '../../../libs/bus';
import ChartMetric from "./chartMetric";
import chartDataFormat from '../../charts/chartDataFormat';
export default {
name: "chartBox",
props: {
@@ -212,6 +228,7 @@
type:'line',
span:12,
height:'400',
unit:1,
elements:{
id: '',
expression: '',
@@ -237,6 +254,10 @@
{
id:"table",
name:this.$t("dashboard.panel.chartForm.typeVal.table.label")
},
{
id:'stackArea',
name:this.$t("dashboard.panel.chartForm.typeVal.stackArea.label")
}
],
elements: [1], // 指标部分 tarNum
@@ -256,7 +277,8 @@
id: '',
name: ''
},
heightSuggestions:['300','400','500','600']
heightSuggestions:['300','400','500','600'],
unitOptions:chartDataFormat.unitOptions(),
}
},
components:{
@@ -313,7 +335,6 @@
this.rightBox.title = title;
},
save() {
console.log(this.chart);
this.$refs['chartForm'].validate((valid) => {
if (valid) {
if (this.chart.id) {//修改
@@ -491,6 +512,7 @@
span: this.chart.span,
height: this.chart.height,
type: this.chart.type,
unit:this.chart.unit,
};
//生成指标数组
@@ -629,6 +651,7 @@
this.chart.span = data.span;
this.chart.height = data.height+'';
this.chart.type = data.type;
this.chart.unit=data.unit
this.getSuggestMetric();//获得指标列表
// 指标
this.elements = [];
@@ -651,6 +674,7 @@
this.chart.type = 'line';
this.chart.span = 12;
this.chart.height = 400+'';
this.chart.unit=1;
this.elements = [1];
this.elementTarget = [];
bus.chartAddInfo.metricTarget = [];
@@ -681,6 +705,9 @@
},
handleSelect:function(item){
this.chart.height=item;
},
unitSelected:function(value){
this.chart.unit=value[value.length-1];
}
},
created() {

View File

@@ -150,7 +150,7 @@
</div>
<span v-else-if="item.prop == 'lastUpdate'">{{dateFormat(scope.row.lastUpdate)}}</span>
<span v-else-if="item.prop == 'state'" >
<el-popover placement="right" width="50" trigger="hover" :content="(scope.row.state == '1'?'up':'down')+'['+(scope.row.lastUpdate&&scope.row.lastUpdate!=''?(new Date(scope.row.lastUpdate).getHours()+':'+new Date(scope.row.lastUpdate).getMinutes()):'--')+']'">
<el-popover placement="right" width="50" trigger="hover" :content="getStateContent(scope.row)">
<div slot="reference" style="width: 20px">
<div :class="{'active-icon green':scope.row.state == '1','active-icon red':scope.row.state == '0'}"></div>
</div>
@@ -588,8 +588,20 @@
return [x,y];
},
formatter:function(params){
let avgWidth=0;
let sumWidth=0;
params.forEach((item, i) => {
let tip=temp.legend.find((element)=>{
return element.name == item.seriesName;
})
let curLength=(temp.hideSameLabels&&tip.alias?tip.alias:tip.name).length;
// maxWidth=maxWidth>curLength?maxWidth:curLength;
sumWidth+=curLength;
})
avgWidth=sumWidth/params.length;
//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;'>`;
let str = `<div style='width:${avgWidth*10}px;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;
@@ -922,15 +934,15 @@
});
},
getMetricsTableData() {
this.metricSearchLabel.moduleId = this.currentModule.id;
this.$set(this.metricSearchLabel, 'pageNo', this.metricPageObj.pageNo);
this.$set(this.metricSearchLabel, 'pageSize', this.metricPageObj.pageSize);
this.$get('metric', this.metricSearchLabel).then(response => {
if (response.code === 200) {
this.metricsTableData = response.data.list;
this.metricPageObj.total = response.data.total;
}
});
// this.metricSearchLabel.moduleId = this.currentModule.id;
// this.$set(this.metricSearchLabel, 'pageNo', this.metricPageObj.pageNo);
// this.$set(this.metricSearchLabel, 'pageSize', this.metricPageObj.pageSize);
// this.$get('metric', this.metricSearchLabel).then(response => {
// if (response.code === 200) {
// this.metricsTableData = response.data.list;
// this.metricPageObj.total = response.data.total;
// }
// });
},
endpointPageNo(val) {
this.endpointPageObj.pageNo = val;
@@ -1423,20 +1435,6 @@
return 'disabledCheck'
}
},
// 获取metric列表
getSuggestMetric() {
this.$get('metric', {pageNo: 1, pageSize: -1}).then(response => {
if (response.code === 200) {
this.metricList = response.data.list.map((item,index)=>{
item.__label__='metric';
return {key:item.metric,type:'metric'};
});
}else {
this.metricList = [];
}
})
},
getPanelData() { //获取panel数据
this.$get('panel?pageNo=1&pageSize=-1').then(response => {
if (response.code === 200) {
@@ -1558,6 +1556,36 @@
}
}
},
getStateContent:function(row){
if(row){
if(row.state == 1){
return 'up'+'['+this.formatUpdateTime(row.lastUpdate)+']';
}else{
return 'down'+'['+this.getStateErrorMsg(row)+']';
}
}
},
formatUpdateTime:function(date){
let time=new Date(date);
let hours=time.getHours()>9?time.getHours():'0'+time.getHours();
let minutes=time.getMinutes()>9?time.getMinutes():'0'+time.getMinutes();
return hours+':'+minutes;
},
getStateErrorMsg:function(row){
let errCodes=[230009,230010,230011];
if(row){
if(row.state == 0){
if(errCodes.find((item)=>{return row.stateInfo.code == item})){
return this.$t('project.endpoint.stateInfo_'+row.stateInfo.code)
}else{
return row.stateInfo.msg;
this.$message.error('state code error');
}
}
}
}
/*gutterHandler() {
setTimeout(() => {
let gutterCol = document.querySelector(".endpoint-table col[name='gutter']");
@@ -1932,4 +1960,8 @@
.control-icon-checked{
color:#666;
}
.dropdownBtn .el-dropdown__caret-button{
top:0px !important;
left:2px;
}
</style>