feat:新增功能

1.panel图表曲线全屏增加时间查询
2.panel图表的定期刷新
3.panel图表数据获取参数step按时间指定不同值
4.panel图表全屏相关文字国际化
fix:修改BUG
1.panel图表查询2次
2.panel图表列表底部显示多余的滚动条
This commit is contained in:
hanyuxia
2020-01-10 17:13:41 +08:00
parent a592576c73
commit 663f8e1b4f
7 changed files with 327 additions and 52 deletions

View File

@@ -7,10 +7,13 @@
.noData{ .noData{
text-align: center text-align: center
} }
.list-width{
width:98%;
}
</style> </style>
<template> <template>
<div> <div class="list-width">
<div class="chartBox" v-for="(item, index) in dataList" :key="item.id"> <div class="chartBox" v-for="(item, index) in dataList" :key="item.id">
<line-chart-block v-if="item.type === 'line' || item.type === 'bar' || item.type === 4" :key="'inner' + item.id" <line-chart-block v-if="item.type === 'line' || item.type === 'bar' || item.type === 4" :key="'inner' + item.id"
@@ -69,11 +72,6 @@ export default {
}, },
// 获取panel详情数据,获取panel下所有chart列表 // 获取panel详情数据,获取panel下所有chart列表
getData(params) { getData(params) {
if (this.dataList.length > 0) {
this.$refs.editChart.forEach((item) => {
//item.showLoad();//之后要实现
});
}
//param 目前没有用 //param 目前没有用
const param = { const param = {
panelId: params.panelId, panelId: params.panelId,
@@ -92,6 +90,11 @@ export default {
}else { }else {
this.dataList = response.data; this.dataList = response.data;
} }
if (this.dataList.length > 0) {
this.$refs.editChart.forEach((item) => {
item.showLoad();//之后要实现
});
}
//alert(JSON.stringify(response)); 查着,返回的内容就没有图表表达式了?? //alert(JSON.stringify(response)); 查着,返回的内容就没有图表表达式了??
this.dataSetFirst(this.dataList); this.dataSetFirst(this.dataList);
} }
@@ -136,10 +139,11 @@ export default {
startTime = this.filter.start_time; startTime = this.filter.start_time;
endTime = this.filter.end_time; endTime = this.filter.end_time;
} }
let step = bus.getStep(startTime,endTime);
this.$nextTick(() => { this.$nextTick(() => {
const axiosArr = chartItem.elements.map((ele) => { const axiosArr = chartItem.elements.map((ele) => {
const filterItem = ele; const filterItem = ele;
return this.$get('/prom/api/v1/query_range?query='+filterItem.expression+"&start="+startTime+"&end="+endTime+'&step=3600s'); return this.$get('/prom/api/v1/query_range?query='+filterItem.expression+"&start="+startTime+"&end="+endTime+'&step='+step);
}); });
// 一个图表的所有element单独获取数据 // 一个图表的所有element单独获取数据
axios.all(axiosArr).then((res) => { axios.all(axiosArr).then((res) => {

View File

@@ -38,7 +38,7 @@
</el-table> </el-table>
</div> </div>
<!--全屏--> <!--全屏-->
<el-dialog title="查看" :visible.sync="screenModal" width="96%" :before-close="handleClose"> <el-dialog :title="$t('dashboard.panel.view')" :visible.sync="screenModal" width="96%" :before-close="handleClose">
<div class="clearfix element-top-border"> <div class="clearfix element-top-border">
<div class="float-left table-title"> <div class="float-left table-title">
{{data.title}} {{data.title}}
@@ -59,8 +59,8 @@
</div> </div>
<div class=" element-bottom-border" ></div> <div class=" element-bottom-border" ></div>
<span slot="footer" class="dialog-footer" > <span slot="footer" class="dialog-footer" >
<el-button @click="screenModal = false"> </el-button> <el-button @click="screenModal = false">{{$t('dashboard.panel.cancel')}}</el-button>
<el-button type="primary" @click="screenModal = false"> </el-button> <el-button type="primary" @click="screenModal = false">{{$t('dashboard.panel.confirm')}}</el-button>
</span> </span>
</el-dialog> </el-dialog>
</div> </div>
@@ -130,7 +130,9 @@ export default {
}, },
watch: {}, watch: {},
methods: { methods: {
showLoad() {}, showLoad() {
this.tableLoading = true;
},
// 展示图表编辑区 // 展示图表编辑区
showTool() { showTool() {
this.toolbox = !this.toolbox; this.toolbox = !this.toolbox;

View File

@@ -25,15 +25,13 @@
<!-- <!--
<Modal title="查看" v-model="screenModal" width="96%" class="line-chart-block-modal">--> <Modal title="查看" v-model="screenModal" width="96%" class="line-chart-block-modal">-->
<el-dialog class="line-chart-block-modal" <el-dialog class="line-chart-block-modal"
title="查看" :title="$t('dashboard.panel.view')"
:visible.sync="screenModal" :visible.sync="screenModal"
width="90%" width="90%"
:before-close="handleClose" :before-close="handleClose"
@opened="initDialog"> @opened="initDialog">
<el-row class="element-top-border" > <el-row class="element-top-border" >
<div class="float-right"> <div class="float-right" style="padding-top:10px;">
<div class="block">
<!--
<el-date-picker size="small" ref="calendar" <el-date-picker size="small" ref="calendar"
format="yyyy/MM/dd HH:mm" format="yyyy/MM/dd HH:mm"
@change="dateChange" @change="dateChange"
@@ -45,15 +43,13 @@
:end-placeholder="$t('dashboard.panel.endTime')" :end-placeholder="$t('dashboard.panel.endTime')"
align="right"> align="right">
</el-date-picker> </el-date-picker>
-->
</div>
</div> </div>
</el-row> </el-row>
<div class="line-area " ref="screenShowArea" ></div> <div class="line-area " ref="screenShowArea" ></div>
<div class=" element-bottom-border" ></div> <div class=" element-bottom-border" ></div>
<span slot="footer" class="dialog-footer" > <span slot="footer" class="dialog-footer" >
<el-button @click="screenModal = false"> </el-button> <el-button @click="screenModal = false">{{$t('dashboard.panel.cancel')}}</el-button>
<el-button type="primary" @click="screenModal = false"> </el-button> <el-button type="primary" @click="screenModal = false">{{$t('dashboard.panel.confirm')}}</el-button>
</span> </span>
</el-dialog> </el-dialog>
@@ -62,13 +58,8 @@
</template> </template>
<script> <script>
import axios from 'axios'; import axios from 'axios';
//import highstock from 'highcharts/highstock';
import echarts from 'echarts'; import echarts from 'echarts';
import bus from '../../libs/bus'; import bus from '../../libs/bus';
//import calendarSelect from '../page/calendar-select';
//import { getQueryChart } from '../../models/service';
//require('highcharts/modules/no-data-to-display')(highstock);
export default { export default {
name: 'lineChartBlock', name: 'lineChartBlock',
@@ -107,7 +98,7 @@ export default {
firstLoad: false, // 是否第一次加载 firstLoad: false, // 是否第一次加载
highchartStore: null, // 保存图表数据 highchartStore: null, // 保存图表数据
echartStore:null,// 保存图表数据 echartStore:null,// 保存图表数据
highchartModalStore: null, // 全屏查看时数据 echartModalStore: null, // 全屏查看时数据
chartType: 'line', // 图表类型 chartType: 'line', // 图表类型
screenModal: false, screenModal: false,
// 查询数据使用 // 查询数据使用
@@ -116,8 +107,90 @@ export default {
end_time: '', end_time: '',
}, },
stableFilter: {}, // 保存数据使用,初始化起止时间,单图or多图等 stableFilter: {}, // 保存数据使用,初始化起止时间,单图or多图等
legend:[] legend:[],
// firstShow: false, // 默认不显示操作按钮, // firstShow: false, // 默认不显示操作按钮,
searchTime:[new Date().setHours(new Date().getHours()-1),new Date()],
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]);
}
}]
},
}; };
}, },
computed: { computed: {
@@ -140,7 +213,11 @@ export default {
if ( chartInfo.type === 4) {//line,bar if ( chartInfo.type === 4) {//line,bar
this.chartType = 'line'; this.chartType = 'line';
} }
this.echartStore = echarts.init(ele); if (chartSite === 'local') {
this.echartStore = echarts.init(ele);
}else if (chartSite === 'screen') {
this.echartModalStore = echarts.init(ele);
}
var chartWidth = ele.clientWidth; var chartWidth = ele.clientWidth;
var option = { var option = {
title: { title: {
@@ -331,6 +408,7 @@ export default {
*/ */
this.echartStore.setOption(option);//创建图表 this.echartStore.setOption(option);//创建图表
this.echartStore.hideLoading(); this.echartStore.hideLoading();
this.echartStore.resize({height:chartInfo.height});//,width:`${ele.clientWidth-100}`}
} else if (chartSite === 'screen') { // 全屏显示 } else if (chartSite === 'screen') { // 全屏显示
/* /*
option.series = dataArg.map((item) => {// params.series = dataArg.map((item) => { option.series = dataArg.map((item) => {// params.series = dataArg.map((item) => {
@@ -378,10 +456,11 @@ export default {
}); });
*/ */
// eslint-disable-next-line // eslint-disable-next-line
this.echartStore.setOption(option);//显示全屏界面 this.echartModalStore.clear();
this.echartStore.hideLoading(); this.echartModalStore.setOption(option);//显示全屏界面
this.echartModalStore.hideLoading();
this.echartModalStore.resize({height:chartInfo.height});//,width:`${ele.clientWidth-100}`}
} }
this.echartStore.resize({height:chartInfo.height});//,width:`${ele.clientWidth-100}`}
}, },
// 设置数据, filter区分 // 设置数据, filter区分
setData(chartItem, seriesItem, panelId, filter,legend) { setData(chartItem, seriesItem, panelId, filter,legend) {
@@ -392,6 +471,8 @@ export default {
this.panelIdInner = panelId; this.panelIdInner = panelId;
this.data = chartItem; this.data = chartItem;
this.seriesItem = seriesItem; this.seriesItem = seriesItem;
this.searchTime[0] = filter.start_time;
this.searchTime[1] = filter.end_time;
this.initChart(chartItem, seriesItem, this.$refs.lineChartArea, 'local',legend); this.initChart(chartItem, seriesItem, this.$refs.lineChartArea, 'local',legend);
/* /*
if (chartItem.type === 'line' || chartItem.type === 'bar' || chartItem.type === 4) { if (chartItem.type === 'line' || chartItem.type === 'bar' || chartItem.type === 4) {
@@ -432,15 +513,161 @@ export default {
this.screenModal = true; this.screenModal = true;
}, },
dateChange(time) { dateChange(time) {
/* this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss');
this.filter.start_time = `${time[0]}:00`; this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss');
this.filter.end_time = `${time[1]}:59`;
if (this.showSetting) { if (this.showSetting) {
this.getQueryChart('list'); this.getQueryChart('list');
} else { } else {
this.getQueryChart('dashboard'); this.getQueryChart('dashboard');
} }
*/ },
// 查询数据,修改日期查询全屏数据
getQueryChart(type) {
if (this.echartModalStore) {
this.echartModalStore.showLoading();
}
let axiosArr = [];
this.$nextTick(() => {
if (type === 'list') { // 普通模式,主控台使用
let startTime = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss');
let endTime = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss');
if(!startTime || !endTime){//如果时间为空则默认取最近1小时
let now = new Date();
startTime = bus.timeFormate(now, 'yyyy-MM-dd hh:mm:ss');
endTime = bus.timeFormate(now.setHours(now.getHours()-1), 'yyyy-MM-dd hh:mm:ss');
this.searchTime[0] = startTime;
this.searchTime[1] = endTime;
}
let step = bus.getStep(startTime,endTime);
axiosArr = this.data.elements.map((ele) => {
const filterItem = ele;
return this.$get('/prom/api/v1/query_range?query='+filterItem.expression+"&start="+startTime+"&end="+endTime+'&step='+step);
});
} else if (type === 'dashboard') { // 概览模式,指标概览中使用
/*
// 概览模式,需要区分单独一个和多个
if (this.stableFilter.chartCount === 'multiple') {
// 所有tag标签
const tagAllArr = this.proTags(this.data.tags);
// 根据title格式化的标签
const titles = this.data.title.split(',');
const titleArr = titles.map(item => item.trim());
// 获取所需标签
const tagArr = this.getCompilation(tagAllArr, titleArr);
axiosArr = [getQueryChart({
product_id: this.productId,
metric: this.data.metric,
tags: tagArr.toString(),
start: this.filter.start_time,
end: this.filter.end_time,
})];
} else {
axiosArr = [getQueryChart({
product_id: this.productId,
metric: this.data.metric,
tags: this.data.tags,
start: this.filter.start_time,
end: this.filter.end_time,
})];
}
*/
}
// 一个图表
axios.all(axiosArr).then((res) => {
if (res.length > 0) {
const series = [];
const legend = [];
const sumData = {
name: 'sum',
data: [],
visible: true,
threshold: null,
};
res.forEach((response) => {
if (response.status === 'success') {
if (response.data.result) {
// 循环处理每个elements下获取的数据列
response.data.result.forEach((queryItem,innerPos) => {
const seriesItem = {
theData: {
name: '',
data: [],
type:this.data.type,
//visible: true,
//threshold: null,
},
metric_name: '',
};
// 图表中每条线的名字,后半部分
let host = `${queryItem.metric.__name__}{`;//up,
const tagsArr = Object.keys(queryItem.metric);//["__name__","asset","idc","instance","job","module","project"]
// 设置时间-数据格式对
const dpsArr = Object.entries(queryItem.values);//[ ["0",[1577959830.781,"0"]], ["1",[1577959845.781,"0"]] ]
// 判断是否有数据
if (dpsArr.length > 0 && tagsArr.length > 0) {
tagsArr.forEach((tag, i) => {
if (tag !== '__name__') {
host += `${tag}="${queryItem.metric[tag]}",`;
}
});
if(host.endsWith(',')){host = host.substr(0,host.length-1);}
host +="}";
legend.push(host);
// 图表中每条线的名字,去掉最后的逗号与空格:metric名称, 标签1=a,标签2=c
seriesItem.theData.name = host;
seriesItem.metric_name = seriesItem.theData.name;
// 将秒改为毫秒
//alert('table=='+JSON.stringify(queryItem))
seriesItem.theData.data = queryItem.values.map((dpsItem, dpsIndex) => {
/*曲线汇总暂不需要
if (sumData.data[dpsIndex]) {
const sumNum = sumData.data[dpsIndex][1] || 0;
sumData.data[dpsIndex][1] = sumNum + dpsItem[1];
} else {
sumData.data[dpsIndex] = [dpsItem[0] * 1000, dpsItem[1]];
}
*/
return [dpsItem[0] * 1000, dpsItem[1]];
});
series.push(seriesItem.theData);
} else if (this.data.elements && this.data.elements[innerPos]) {
// 无数据提示
/*
const currentInfo = chartItem.elements[innerPos];
const errorMsg = `图表 ${chartItem.title} 中 ${currentInfo.metric},${currentInfo.tags} 无数据`;
this.$message.warning({
duration: 15,
content: errorMsg,
closable: true,
});
*/
}
});
}
}
});
/*
if (series.length && this.data.type === 4) {
series.push(sumData);
}
*/
this.initChart(this.data, series, this.$refs.screenShowArea, 'screen',legend);
}
}).catch((error) => {
if (error) {
this.$message.warning({
content: this.$t("tip.refreshLater"),//'Please refesh later',//请稍后刷新
duration: 3,
});
}
});
});
},
showLoad() {
if (this.echartStore) {
this.echartStore.showLoading();
}
}, },
/* /*
handleClose(done) { handleClose(done) {
@@ -589,11 +816,6 @@ export default {
}); });
}, },
showLoad() {
if (this.highchartStore) {
this.highchartStore.showLoading();
}
},
// 获取格式 // 获取格式
getNumStr(num) { getNumStr(num) {
if (num >= 1000) { if (num >= 1000) {

View File

@@ -77,7 +77,10 @@ const cn = {
threeMinutes:'3分钟', threeMinutes:'3分钟',
fiveMinutes:'5分钟', fiveMinutes:'5分钟',
tenMinutes:'10分钟', tenMinutes:'10分钟',
} },
view:'查看',
confirm:'确 定',
cancel:'取 消'
}, },
metric:{ metric:{
name:"指标名称", name:"指标名称",

View File

@@ -30,7 +30,7 @@ const en = {
panel:{ panel:{
title:'Panel', title:'Panel',
searchItem:{ searchItem:{
name:'Title' name:'name'
}, },
//面板-侧滑框 //面板-侧滑框
createPanelTitle: "Create Panel", createPanelTitle: "Create Panel",
@@ -86,7 +86,10 @@ const en = {
threeMinutes:'3 mins', threeMinutes:'3 mins',
fiveMinutes:'5 mins', fiveMinutes:'5 mins',
tenMinutes:'10 mins', tenMinutes:'10 mins',
} },
view:'View',
confirm:'Ok',
cancel:'Cancel'
}, },
metric:{ metric:{
name:"Metric", name:"Metric",

View File

@@ -253,6 +253,7 @@
}] }]
}, },
searchTime: [new Date().setHours(new Date().getHours()-1),new Date()], searchTime: [new Date().setHours(new Date().getHours()-1),new Date()],
intervalTimer: null,
intervalList: [{ intervalList: [{
value: 0, value: 0,
name: this.$t("dashboard.panel.refreshInterval.never"), name: this.$t("dashboard.panel.refreshInterval.never"),
@@ -299,16 +300,15 @@
panelData: [], panelData: [],
searchMsg: { //给搜索框子组件传递的信息 searchMsg: { //给搜索框子组件传递的信息
zheze_none: true, zheze_none: true,
searchLabelList: [ searchLabelList: [/*
/*
{ {
id: 1, id: 1,
name: this.$t("dashboard.panel.searchItem.name"), name: this.$t("dashboard.panel.searchItem.name"),
type: 'input', type: 'input',
label: 'name', label: 'name',
disabled: false disabled: false
} }*/
*/], ],
}, },
searchLabel: {}, //搜索参数 searchLabel: {}, //搜索参数
//---图表相关参数--start //---图表相关参数--start
@@ -334,8 +334,7 @@
methods: { methods: {
//面板相关操作 //面板相关操作
panelChange(){ panelChange(){
//alert(JSON.stringify(this.$refs.searchInput.select_list)); //this.$refs.searchInput.select();
this.$refs.searchInput.select();
this.filter.panelId = this.showPanel.id; this.filter.panelId = this.showPanel.id;
this.getData(this.filter); this.getData(this.filter);
}, },
@@ -443,7 +442,7 @@
/*时间条件查询--start*/ /*时间条件查询--start*/
// 选择日期变化 // 选择日期变化
dateChange() { dateChange() {
this.$refs.searchInput.select(); //this.$refs.searchInput.select();
this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss'); this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss');
this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss'); this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss');
this.filter.panelId = this.showPanel.id; this.filter.panelId = this.showPanel.id;
@@ -482,7 +481,32 @@
} }
} }
}) })
},
//定期刷新
selectInterval(val) {
clearInterval(this.intervalTimer);
if (val) {
const start = new Date(this.searchTime[1]);
const now = new Date();
const interval = Math.floor((now.getTime() - start.getTime()) / 1000);//计算当前结束时间到现在的间隔(秒)
if (interval >= 60) {//如果结束时间到现在超过1分钟
this.getIntervalData(interval);
}
this.intervalTimer = setInterval(() => {
this.getIntervalData(this.interval);
}, val * 1000);
}
},
getIntervalData(interval) {//interval:结束时间到现在的秒数
const start = new Date(this.searchTime[0]);
const end = new Date(this.searchTime[1]);
start.setSeconds(start.getSeconds() + interval);
end.setSeconds(end.getSeconds() + interval);
const startTime = bus.timeFormate(start, 'yyyy-MM-dd hh:mm');
const endTime = bus.timeFormate(end, 'yyyy-MM-dd hh:mm');
this.searchTime = [startTime, endTime];
//刷新数据
this.dateChange();
}, },
pageNo(val) { pageNo(val) {
this.pageObj.pageNo = val; this.pageObj.pageNo = val;

View File

@@ -1,6 +1,4 @@
import Vue from 'vue'; import Vue from 'vue';
//import Cookies from 'js-cookie';
//import md5 from 'md5';
Date.prototype.setStart = function() { Date.prototype.setStart = function() {
this.setHours(0); this.setHours(0);
@@ -120,6 +118,25 @@ export default new Vue({
}); });
return fm; return fm;
}, },
getStep(startTime,endTime){
const start = new Date(startTime);
const end = new Date(endTime);
let step='15s';
const numInterval = end.getTime()-start.getTime();
let oneDay = 86400000;
let sevenDay = 604800000;
let thirtyDay = 2592000000;
if (numInterval < oneDay) {//小于1天step为15s
step='15s';
}else if(numInterval<sevenDay){
step='5m';
}else if(numInterval<thirtyDay){
step='10m';
}else {
step='30m';
}
return step;
},
isEmptyObject(obj) { isEmptyObject(obj) {
if (obj) { if (obj) {
let name = ''; let name = '';