feat:新增功能

1.panel图表的创建
2.panel图表的展示
3.create+增加了创建panel菜单
This commit is contained in:
hanyuxia
2020-01-03 17:17:09 +08:00
parent ffdb21531b
commit 0530d0c9cf
16 changed files with 2862 additions and 243 deletions

View File

@@ -529,3 +529,7 @@ html {
color: #F98D9A;
}
/* end--自定义可编辑的el-select下拉框样式*/
.right-box-add-chart {
width: 520px;
height: calc(100% - 100px);
}

View File

@@ -0,0 +1,328 @@
<style scoped>
.chartBox {
box-sizing: border-box;
padding-bottom: 10px;
float:left;
}
.noData{
text-align: center
}
</style>
<template>
<div>
<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"
ref="editChart"
@on-refresh-data=""
@on-remove-chart-block="removeChart"
@on-edit-chart-block=""
:panel-id="filter.panelId"
:editChartId="'editChartId' + item.id"></line-chart-block>
<!--
<chart-table v-if="item.type === 'table'" ref="editChart" :key="'inner' + item.id"
@on-refresh-data="refreshChart"
@on-remove-chart-block="removeChart"
@on-edit-chart-block="editData"
:panel-id="filter.panelId"
:editChartId="'editChartId' + item.id"></chart-table>
-->
</div>
<el-row v-if="dataList.length === 0" class="noData"></el-row>
</div>
</template>
<script>
import axios from 'axios';
//import bus from '../../libs/bus';
import lineChartBlock from './line-chart-block';
//import chartTable from './chart-table';
export default {
name: 'chartList',
props: {
},
components: {
lineChartBlock,
//chartTable,
},
data() {
return {
filter: {},
dataList: [], // 看板中所有图表信息
time: {
start: '',
end: '',
},
panelId: '',
timer: null,
};
},
computed: {},
watch: {},
methods: {
initData(filter) {
this.dataList = [];
// 内含 panelId,开始时间,结束时间
this.filter = filter;
this.getData(this.filter);
},
// 获取panel详情数据,获取panel下所有chart列表
getData(params) {
if (this.dataList.length > 0) {
this.$refs.editChart.forEach((item) => {
//item.showLoad();//之后要实现
});
}
//param 目前没有用
const param = {
panelId: params.panelId,
query: params.query,
};
if (!param.query) delete param.query;
//根据panelId获得panel下的所有图表
this.$get('panel/'+ params.panelId+'/charts').then(response => {
if (response.code === 200) {
if(response.data.list){
this.dataList = response.data.list;
}else {
this.dataList = response.data;
}
this.dataSetFirst(this.dataList);
}
});
},
// arr: 该panel下图表list,生成该看板下所有图表
dataSetFirst(arr) {
if (arr.length) {
arr.forEach((item, index) => {
this.getChartData(item, index);
});
}
},
// 获取一个图表具体数据,图表信息图表位置index
getChartData(chartInfo, pos, filterType) {
const chartItem = chartInfo;
const index = pos; // 指标
const len = chartItem.elements.length;
//this.setSize(chartItem.span, index); // 设置该图表宽度
this.setSize(chartItem.span,chartItem.height, index); // 设置该图表宽度,高度
// 没有数据的设置提示信息暂无数据-针对每一个图
if (len === 0) {
this.$nextTick(() => {
this.$refs.editChart[index].setData(chartItem, [], this.filter.panelId, this.filter);//????怎么设置的无数据??
});
} else {
let startTime = '';
let endTime = '';
if (filterType === 'refresh') {//刷新:需要根据刷新周期来???
const now = new Date();
const origin = new Date(this.filter.end_time);
const numInterval = now.getTime() - origin.getTime();
if (numInterval >= 6000) {
startTime = this.getNewTime(this.filter.start_time, numInterval);
endTime = bus.timeFormate(now, 'yyyy/MM/dd-hh:mm:ss');
} else {
startTime = this.filter.start_time;
endTime = this.filter.end_time;
}
} else {
startTime = this.filter.start_time;
endTime = this.filter.end_time;
}
//测试数据----之后会要去掉
startTime='2020-01-02T10:10:30.781Z';
endTime = '2020-01-02T20:10:30.781Z';
this.$nextTick(() => {
const axiosArr = chartItem.elements.map((ele) => {
const filterItem = ele;
return this.$get('http://192.168.40.247:9090/api/v1/query_range?query='+filterItem.expression+"&start="+startTime+"&end="+endTime+'&step=3600s');
});
// 一个图表的所有element单独获取数据
axios.all(axiosArr).then((res) => {
if (res.length > 0) {
const series = [];
const legend = [];
const tableData = [];
const sumData = {
name: 'sum',
data: [],
visible: true,
threshold: null,
};
res.forEach((response, innerPos) => {
if (response.status === 'success') {
if (response.data.result) {
// 循环处理每个elements下获取的数据列
response.data.result.forEach((queryItem) => {
const seriesItem = {
theData: {
name: '',
data: [],
type:chartInfo.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 += i === 0 ? `${tag}=${queryItem.metric[tag]}` : ` ${tag}=${queryItem.metric[tag]},`;
}
});
if(host.endsWith(',')){host = host.substr(0,host.length-1);}
legend.push(host);
// 图表中每条线的名字,去掉最后的逗号与空格:metric名称, 标签1=a,标签2=c
seriesItem.theData.name = host;
seriesItem.metric_name = seriesItem.theData.name;
// 将秒改为毫秒
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]];
});
tableData.push({//表格数据
name: host.slice(host.indexOf(', ') + 1),
metric: queryItem.metric.__name__,
time: (dpsArr[dpsArr.length - 1][0]) * 1000,
value: dpsArr[dpsArr.length - 1][1],
});
series.push(seriesItem.theData);
} else if (chartItem.elements && chartItem.elements[innerPos]) {
// 无数据提示
/*
const currentInfo = chartItem.elements[innerPos];
const errorMsg = `图表 ${chartItem.title} 中 ${currentInfo.metric},${currentInfo.tags} 无数据`;
this.$message.warning({
duration: 15,
content: errorMsg,
closable: true,
});
*/
}
});
}
}
});
// chartData, seriesItem, panelsId, filter
if (chartItem.type === 'table') {//表格
this.$refs.editChart[index].setData(chartItem, tableData,
this.filter.panelId, this.filter);
} else if (chartItem.type === 'line' || chartItem.type === 'bar' || chartItem.type === 4) {
if (series.length && chartItem.type === 4) {//曲线汇总
series.push(sumData);
}
this.$refs.editChart[index].setData(chartItem, series,
this.filter.panelId, this.filter,legend);
}
} else {
const type = chartItem.type;
if (type === 'table') {
this.$refs.editChart[index].setData(chartItem, [], this.filter.panelId,
this.filter);
} else if (type === 'line' || type === 'bar' || chartItem.type === 4) {
this.$refs.editChart[index].setData(chartItem, [], this.filter.panelId,
this.filter);
}
}
}).catch((error) => {
if (error) {
this.$message.warning({
content: this.$t("tip.refreshLater"),//'Please refesh later',//请稍后刷新
duration: 3,
});
}
});
});
}
},
// 设置图表的宽度
setSize(size,height, index) {
this.$nextTick(() => {
const chartBox = document.getElementsByClassName('chartBox');
chartBox[index].style.width = `${(size / 12) * 100}%`;
chartBox[index].style.height = height;
});
},
getNewTime(time, num) {
const date = new Date(time);
const newDate = new Date(parseInt(date.getTime(), 10) + num);
return bus.timeFormate(newDate, 'yyyy/MM/dd-hh:mm:ss');
},
// 删除图表
removeChart(chartId) {
/*
const chart = this.dataList.find(item => item.id === chartId);
if (chart) {
this.$confirm(this.$t("tip.confirmDelete"), {
confirmButtonText: this.$t("tip.yes"),
cancelButtonText: this.$t("tip.no"),
type: 'warning'
}).then(() => {
this.$delete("panel?ids=" + u.id).then(response => {
if (response.code === 200) {
this.$message({duration: 1000, type: 'success', message: this.$t("tip.deleteSuccess")});
if(this.showPanel.id===u.id){
this.showPanel.id ='';
}
this.getTableData();
this.rightBox.show = false;
} else {
this.$message.error(response.msg);
}
})
});
//this.$emit('on-remove-chart', chart);
}*/
},
/*
// 刷新列表中的一个图表
refreshChart(chartId) {
this.dataList.forEach((item, index) => {
if (item.id === chartId) {
this.getChartData(item, index, 'refresh');
}
});
},
// 刷新数据
refreshData() {
this.getData(this.filter);
},
// 编辑图表
editData(chartId) {
// 获取该id下chart的相关信息
const chart = this.dataList.find(item => item.id === chartId);
if (chart) {
this.$emit('on-edit-chart', chart);
}
},
*/
},
mounted() {
},
beforeDestroy() {
},
};
</script>

View File

@@ -0,0 +1,63 @@
/* ---------edit-chart-move--------- */
.chart-table {
width: 100%;
height: 100%;
// min-height: 500px;
position: relative;
background: #FFF;
border: 1px solid #d8dce1;
padding: 10px;
margin-bottom: 10px;
.table-title {
font-family: "Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif;
font-size: 14px;
}
.edit {
// position: absolute;
// right: 40px;
// top: 5px;
// z-index: 10;
padding-right: 40px;
.set-icon {
display: inline-block;
cursor: pointer;
font-size: 14px;
margin-left: 15px;
color: #5aacff;
border: 0 none;
background: transparent;
}
.list-icon {
float: left;
margin-right: 10px;
}
.show-icon {
cursor: pointer;
float: right;
font-size: 14px;
}
}
.chart-select {
position: absolute;
left: 40px;
top: 25px;
z-index: 10;
font-size: 14px;
.chart-select-btn {
margin-right: 10px;
cursor: pointer;
&.active {
color: #5aacff;
}
}
}
/*没有数据显示*/
.null {
position: absolute;
top: 50%;
width: 100%;
text-align: center;
font-size: 24px;
font-weight: 600;
}
}

View File

@@ -0,0 +1,187 @@
<style lang="scss">
@import './chart-table.scss';
</style>
<template>
<div class="chart-table">
<div class="clearfix">
<div class="float-left table-title">
{{data.title}}
</div>
<div class="float-right">
<div class="edit">
<!-- v-if="firstShow" -->
<div class="list-icon">
<span @click="refreshChart" title="刷新" class="set-icon" v-if="showSetting">
<Icon type="refresh"></Icon>
</span>
<span @click="editChart" title="编辑" class="set-icon" v-if="showSetting">
<Icon type="compose"></Icon>
</span>
<span @click="removeChart" title="删除" class="set-icon" v-if="showSetting">
<Icon type="trash-a"></Icon>
</span>
<span @click="showAllScreen" title="全屏" class="set-icon">
<Icon type="arrow-expand"></Icon>
</span>
</div>
</div>
</div>
</div>
<div class="mt-10">
<Table border size="small" :height="350" :data="seriesItem" :columns="columns" :loading="tableLoading"></Table>
</div>
<Modal title="查看" v-model="screenModal" width="96%">
<div class="clearfix">
<div class="float-left table-title">
{{data.title}}
</div>
<div class="float-right">
<Icon style="cursor:pointer;" type="refresh" size="16" color="#5aacff" @click.native="refreshChart"></Icon>
</div>
</div>
<div class="mt-10">
<Table border size="small" :height="350" :data="seriesItem" :columns="columns" :loading="tableLoading"></Table>
</div>
</Modal>
</div>
</template>
<script>
// import axios from 'axios';
import bus from '../../libs/bus';
// import { getQueryChart } from '../../models/service';
export default {
name: 'chartTable',
components: {
},
props: {
// 看板id
panelId: {
type: Number,
default: 0,
},
// 展示设置内容
showSetting: {
type: Boolean,
default: true,
},
},
data() {
return {
data: {}, // 该图表信息,chartItem
seriesItem: [], // 保存信息
images: '',
toolbox: false,
items: {
metric_name: [], // 每条数据列名称
xAxis: [],
theData: [], // series数据组
},
panelIdInner: '', // 看板id=panelId,原写作chart,由set_data获取
firstLoad: false, // 是否第一次加载
chartType: 'table', // 图表类型
screenModal: false,
// 查询数据使用
filter: {
start_time: '',
end_time: '',
},
stableFilter: {}, // 保存数据使用,初始化起止时间,单图or多图等
firstShow: false, // 默认不显示操作按钮,
tableLoading: false,
columns: [{
title: 'metric',
key: 'metric',
width: 200,
sortable: true,
}, {
title: 'tag',
key: 'name',
minWidth: 200,
sortable: true,
}, {
title: '采集时间',
key: 'time',
width: 160,
render: (h, params) => h('span', bus.timeFormate(params.row.time, 'yyyy-MM-dd hh:mm:ss')),
}, {
title: '数值',
key: 'value',
width: 160,
sortable: true,
render: (h, params) => h('span', this.getNumStr(params.row.value)),
}],
};
},
computed: {
},
watch: {},
methods: {
showLoad() {},
// 展示图表编辑区
showTool() {
this.toolbox = !this.toolbox;
},
// 重新请求数据 刷新操作
refreshChart() {
this.tableLoading = true;
this.$emit('on-refresh-data', this.data.id);
},
// 编辑图表
editChart() {
this.$emit('on-edit-chart-block', this.data.id);
},
// 删除该图表
removeChart() {
this.$emit('on-remove-chart-block', this.data.id);
},
// 全屏查看
showAllScreen() {
this.screenModal = true;
},
// 设置数据, filter区分
setData(chartItem, seriesItem, panelId, filter) {
this.firstShow = true; // 展示操作按键
this.tableLoading = false;
if (filter) { // 保存数据,用于同步时间
this.stableFilter = filter;
}
this.panelIdInner = panelId;
this.data = chartItem;
this.seriesItem = seriesItem;
},
// 获取格式
getNumStr(num) {
if (num) {
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 `${gbNum.toFixed(2)}GB`;
}
return `${mbNum.toFixed(2)}MB`;
}
return `${kbNum.toFixed(2)}KB`;
}
return num.toFixed(2);
}
return num;
},
},
mounted() {
this.firstLoad = false;
},
beforeDestroy() {},
};
</script>

View File

@@ -0,0 +1,86 @@
/* ---------edit-chart-move--------- */
.line-chart-block {
width: 100%;
height: 100%;
// min-height: 500px;
position: relative;
background: #FFF;
border: 1px solid #d8dce1;
margin-bottom: 10px;
padding-bottom: 3px;
.line-area {
box-sizing: border-box;
background: #FFF;
min-height: 400px;
span.highcharts-title {
display: block !important;
width: 50%;
font-size: 14px !important;
overflow: hidden;
word-wrap: break-word !important;
white-space: pre-wrap !important;
}
}
.edit {
position: absolute;
right: 40px;
top: 15px;
z-index: 10;
.set-icon {
display: inline-block;
cursor: pointer;
font-size: 14px;
margin-left: 15px;
color: #5aacff;
border: 0 none;
background: transparent;
}
.list-icon {
float: left;
margin-right: 10px;
}
.show-icon {
cursor: pointer;
float: right;
font-size: 14px;
}
}
.chart-select {
position: absolute;
left: 40px;
top: 25px;
z-index: 10;
font-size: 14px;
.chart-select-btn {
margin-right: 10px;
cursor: pointer;
&.active {
color: #5aacff;
}
}
}
/*没有数据显示*/
.null {
position: absolute;
top: 50%;
width: 100%;
text-align: center;
font-size: 24px;
font-weight: 600;
}
}
.line-chart-block-modal {
.line-area {
box-sizing: border-box;
background: #FFF;
min-height: 400px;
span.highcharts-title {/*针对highcharts设置的样式echarts需要修改*/
display: block !important;
width: 50%;
font-size: 14px !important;
overflow: hidden;
word-wrap: break-word !important;
white-space: pre-wrap !important;
}
}
}

View File

@@ -0,0 +1,599 @@
<style lang="scss">
@import './line-chart-block.scss';
</style>
<template>
<div class="line-chart-block" >
<div class="edit">
<div class="list-icon" v-if="firstShow">
<span @click="refreshChart" :title="$t('dashboard.refresh')" class="set-icon" v-if="showSetting">
<i class="el-icon-refresh-right"></i>
</span>
<span @click="editChart" :title="$t('dashboard.edit')" class="set-icon" v-if="showSetting">
<i class="el-icon-edit-outline"></i>
</span>
<span @click="removeChart" :title="$t('dashboard.delete')" class="set-icon" v-if="showSetting">
<i class="el-icon-delete"></i>
</span>
<span @click="showAllScreen" :title="$t('dashboard.screen')" class="set-icon">
<i class="el-icon-full-screen"></i>
</span>
</div>
</div>
<div class="line-area" ref="lineChartArea" style=""></div>
<!--
<Modal title="查看" v-model="screenModal" width="96%" class="line-chart-block-modal">-
<el-dialog class="line-chart-block-modal"
title="查看"
:visible.sync="screenModal"
width="90%"
:before-close="handleClose">
<el-row>
<div class="float-right">
全屏日期选择组件
<calendar-select placement="bottom-end" ref="dateSelect" @on-date-change="dateChange"></calendar-select>
</div>
</el-row>>
<div class="line-area" ref="screenShowArea" id="lineChartArea"></div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
-->
<!--</Modal>-->
</div>
</template>
<script>
import axios from 'axios';
//import highstock from 'highcharts/highstock';
import echarts from 'echarts';
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 {
name: 'lineChartBlock',
components: {
//calendarSelect,
},
props: {
editChartId: {
type: String,
default: 'editChartId',
},
// 看板id
panelId: {
type: Number,
default: 0,
},
// 展示设置内容
showSetting: {
type: Boolean,
default: true,
},
},
data() {
return {
data: {}, // 该图表信息,chartItem
seriesItem: [], // 保存信息
images: '',
toolbox: false,
items: {
metric_name: [], // 每条数据列名称
xAxis: [],
theData: [], // series数据组
},
panelIdInner: '', // 看板id=panelId,原写作chart,由set_data获取
chartName: '',
firstLoad: false, // 是否第一次加载
highchartStore: null, // 保存图表数据
echartStore:null,// 保存图表数据
highchartModalStore: null, // 全屏查看时数据
chartType: 'line', // 图表类型
screenModal: false,
// 查询数据使用
filter: {
start_time: '',
end_time: '',
},
stableFilter: {}, // 保存数据使用,初始化起止时间,单图or多图等
firstShow: false, // 默认不显示操作按钮,
};
},
computed: {
/*
typeVisible() {
if (this.data.type === 'line' || this.data.type === 'bar' || this.data.type === 4) {
return true;
}
return false;
},
*/
},
watch: {},
methods: {
// chartSite用于区分是全屏显示还是局部显示
initChart(chartInfo, dataArg, ele, chartSite,legend) {
this.firstShow = true; // 展示操作按键
const self = this;
this.chartType = ''; // 图表类型
if ( chartInfo.type === 4) {//line,bar
this.chartType = 'line';
}
//var myEchart = echarts.init(document.getElementById('lineChartArea'));
this.echartStore = echarts.init(ele);
var option = {
title: {
text: chartInfo.title || null,
textAlign: 'left',
useHTML: true,
textStyle: {
//display: 'inline-block',//无此属性
width: '300px',
}
},
color: ['#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',
],
tooltip: {
trigger: 'axis',
confine:true
},
legend: {
show:true,
formatter:function(name){
if(!name){
return '';
}
if(name.length>5){
return name.slice(0,5)+'...';
}
},
tooltip:{show:true},
data: legend,
//orient:'vertical',
x:'center',
y:'top',
top:'5%',
//bottom:0
},
grid: {
bottom: '10%',
containLabel: true
},
dataZoom: [{
type: 'inside',
start: 0,
end: 100,
height:15
}, {
start: 0,
end: 100,
handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
handleSize: '80%',
handleStyle: {
color: '#fff',
shadowBlur: 3,
shadowColor: 'rgba(0, 0, 0, 0.6)',
shadowOffsetX: 2,
shadowOffsetY: 2
}
}],
xAxis: {
type: 'time',
//boundaryGap: false,//line-false; bar-true;
//data: ['20190101', '20190102', '周三', '周四', '周五', '周六', '周日']
axisLabel: {
intervale: 0,
rotate: 0,
formatter: function (value) {
var t_date = new Date(value);
return [t_date.getFullYear(), t_date.getMonth() + 1, t_date.getDate()].join('-') + "\n"
+ [t_date.getHours(), t_date.getMinutes()].join(':');
}
},
axisPointer: {//y轴上显示指针对应的值
show: true,
},
splitLine:{
show:false
}
},
yAxis: {
type: 'value',
splitLine:{
show:true
}
},
useUTC: false,//使用本地时间
series: dataArg
};
// params.series = dataArg;
if (chartSite === 'local') { // 本地显示
/*
option.series = dataArg.map((item) => {// params.series = dataArg.map((item) => {
const obj = Object.assign(item);
/*
obj.events = {
// eslint-disable-next-line
legendItemClick: function(event) {//点击metric的事件可以用默认的先
event.preventDefault();
let visibleAll = true; // 全部显示
let visibleThis = true; // 点击是否是当前显示的那个条目
self.highchartStore.series.forEach((serie, i) => {
// 最后一个为导航,排除。
if (i !== self.highchartStore.series.length - 1) {
// 查看是否为显示一条状态数据,如果有非显示状态的,表示当前只显示一条数据
if (!serie.visible) {
visibleAll = false;
// 点击前显示单个,判断是否点击为正在显示那个,该种情况表示点击了其他隐藏状态数据
if (event.target.index === i) { // one to another
visibleThis = false;
}
}
}
});
// 根据visibleAll和visibleThis判断是要显示一个还是全显示
// 当visibleAll为true(表示all => one)
// visibleAll为false: visibleThis为false(one => another one)。
// visibleAll为false: visibleThis为true(one => all)。
if (visibleAll || !visibleThis) { // 隐藏显示其中一个
self.highchartStore.series.forEach((serie, i) => {
const operateObj = serie;
// 除显示条目以外,还有一条serie是导航栏
if (i !== self.highchartStore.series.length - 1) {
if (event.target.index === i) {
operateObj.setVisible(true, false);
} else {
operateObj.setVisible(false, false);
}
} else {
operateObj.setVisible(true, false);
}
});
self.highchartStore.redraw();
} else { // 全部显示
self.highchartStore.series.forEach((serie) => {
const operateObj = serie;
operateObj.setVisible(true, false);
});
self.highchartStore.redraw();
}
},
};
return obj;
});
*/
this.echartStore.setOption(option);//创建图表
} else if (chartSite === 'screen') { // 全屏显示
option.series = dataArg.map((item) => {// params.series = dataArg.map((item) => {
const obj = Object.assign(item);
obj.events = {
// eslint-disable-next-line
legendItemClick: function(event) {
event.preventDefault();
let visibleAll = true; // 全部显示
let visibleThis = true; // 点击是否是当前显示的那个条目
self.highchartModalStore.series.forEach((serie, i) => {
if (i !== self.highchartModalStore.series.length - 1) {
if (!serie.visible) {
visibleAll = false;
if (event.target.index === i) {
visibleThis = false;
}
}
}
});
if (visibleAll || !visibleThis) {
self.highchartModalStore.series.forEach((serie, i) => {
const operateObj = serie;
if (i !== self.highchartModalStore.series.length - 1) {
if (event.target.index === i) {
operateObj.setVisible(true, false);
} else {
operateObj.setVisible(false, false);
}
} else {
operateObj.setVisible(true, false);
}
});
self.highchartModalStore.redraw();
} else {
self.highchartModalStore.series.forEach((serie) => {
const operateObj = serie;
operateObj.setVisible(true, false);
});
self.highchartModalStore.redraw();
}
},
};
return obj;
});
// eslint-disable-next-line
this.echartStore.setOption(option);//显示全屏界面
}
},
// 设置数据, filter区分
setData(chartItem, seriesItem, panelId, filter,legend) {
if (filter) { // 保存数据,用于同步时间
this.stableFilter = filter;
}
this.panelIdInner = panelId;
this.data = chartItem;
this.seriesItem = seriesItem;
this.initChart(chartItem, seriesItem, this.$refs.lineChartArea, 'local',legend);
if (chartItem.type === 'line' || chartItem.type === 'bar' || chartItem.type === 4) {
this.initChart(chartItem, seriesItem, this.$refs.lineChartArea, 'local',legend);
}
},
// 删除该图表
removeChart() {
this.$emit('on-remove-chart-block', this.data.id);
}
/*
handleClose(done) {
/*
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},*/
/*
// 展示图表编辑区
showTool() {
this.toolbox = !this.toolbox;
},
// 修改图表类型
changeChart(type) {
this.chartType = type;
this.highchartStore.update({
chart: {
type: this.chartType,
},
});
},
// 重新请求数据 刷新操作-> console, create-board
refreshChart() {
this.highchartStore.showLoading();
this.$emit('on-refresh-data', this.data.id);
},
// 编辑图表
editChart() {
this.$emit('on-edit-chart-block', this.data.id);
},
},
// 全屏查看
showAllScreen() {
// 初始化同步时间
this.filter.start_time = this.stableFilter.start_time;
this.filter.end_time = this.stableFilter.end_time;
this.screenModal = true;
// 全屏绘图
this.initChart(this.data, this.seriesItem, this.$refs.screenShowArea, 'screen');
// 日期组件同步时间
this.$refs.dateSelect.initTime({
start: this.stableFilter.start_time,
end: this.stableFilter.end_time,
});
},
dateChange(time) {
this.filter.start_time = `${time[0]}:00`;
this.filter.end_time = `${time[1]}:59`;
if (this.showSetting) {
this.getQueryChart('list');
} else {
this.getQueryChart('dashboard');
}
},
// 查询数据,修改日期查询全屏数据
getQueryChart(type) {
if (this.highchartModalStore) {
this.highchartModalStore.showLoading();
}
let axiosArr = [];
if (type === 'list') { // 普通模式,主控台使用
axiosArr = this.data.elements.map((ele) => {
const filterItem = ele;
return getQueryChart({
product_id: this.productId,
metric: filterItem.metric,
tags: filterItem.tags,
start: this.filter.start_time,
end: this.filter.end_time,
});
});
} 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 sumData = {
name: 'sum',
data: [],
visible: true,
threshold: null,
};
res.forEach((response) => {
if (response.data.code === 200) {
if (response.data.data) {
// 循环处理每个elements下获取的数据列
response.data.data.forEach((queryItem) => {
const seriesItem = {
theData: {
name: '',
data: [],
visible: true,
threshold: null,
},
metric_name: '',
};
// 图表中每条线的名字,后半部分
let host = `${queryItem.metric}, `;
const tagsArr = Object.keys(queryItem.tags);
// 设置时间-数据格式对
const dpsArr = Object.entries(queryItem.dps);
if (tagsArr.length > 0 && dpsArr.length > 0) {
tagsArr.forEach((tag, i) => {
if (tag !== 'uuid') {
host += i === 0 ? `${tag}=${queryItem.tags[tag]}` : `, ${tag}=${queryItem.tags[tag]}`;
}
});
// 图表中每条线的名字,去掉最后的逗号与空格
seriesItem.theData.name = host;
seriesItem.metric_name = seriesItem.theData.name;
// 将秒改为毫秒
seriesItem.theData.data = dpsArr.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);
}
});
}
}
});
if (series.length && this.data.type === 4) {
series.push(sumData);
}
this.initChart(this.data, series, this.$refs.screenShowArea, 'screen');
}
}).catch((error) => {
if (error) {
this.$Message.warning({
content: '请稍后刷新',
duration: 3,
});
}
});
},
showLoad() {
if (this.highchartStore) {
this.highchartStore.showLoading();
}
},
// 获取格式
getNumStr(num) {
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 `${gbNum.toFixed(2)}GB`;
}
return `${mbNum.toFixed(2)}MB`;
}
return `${kbNum.toFixed(2)}KB`;
}
return num.toFixed(2);
},
// 获取tag数组
proTags(data) {
const dou = data.indexOf(',');
const tmp = [];
if (dou === -1) {
const set = data.split('=');
if (set[1].indexOf('|') > -1) {
const valueArr = set[1].split('|');
valueArr.forEach((keyV) => {
tmp.push(`${set[0]}=${keyV}`);
});
} else {
tmp.push(`${set[0]}=${set[1]}`);
}
} else {
const mid = data.split(','); // ['key=v1','key=v2',....]
mid.forEach((item) => {
const setInner = item.split('=');
if (setInner[1].indexOf('|') > -1) {
const valueArr = setInner[1].split('|');
valueArr.forEach((keyV) => {
tmp.push(`${setInner[0]}=${keyV}`);
});
} else {
tmp.push(`${setInner[0]}=${setInner[1]}`);
}
});
}
return tmp;
},
// 获取交集,取得所需tags进行查询,k1=v1,k2=v2
getCompilation(arr1, arr2) {
const arr = [];
if (arr1.length && arr2.length) {
arr1.forEach((item) => {
if (arr2.indexOf(item) > -1) {
arr.push(item);
}
});
return arr;
}
return [];
},
*/
},
mounted() {
this.firstLoad = false;
},
beforeDestroy() {},
};
</script>

View File

@@ -204,7 +204,7 @@
</el-popover>
</div>-->
</div>
<panel-box :panel="editPanel" @reload="panelListReload" @reloadForDel="" ref="panelBox"></panel-box>
<project-box :project="editProject" ref="projectBox"></project-box>
<module-box :currentProject="currentProject" :module="editModule" @reload="" ref="moduleBox"></module-box>
<add-endpoint-box :currentProject="currentProject" :currentModule="currentModule" @reload=""
@@ -221,6 +221,10 @@
username: sessionStorage.getItem("nz-username"),
language: localStorage.getItem("nz-language"),
assetData: [],
editPanel:{//新增or编辑的panel
id:'',
name: ''
},
projectData: [], //顶部菜单project列表中的数据
editProject: {id: '', name: '', remark: ''}, //新增/编辑的project
currentProject: {id: '', name: '', remark: ''}, //module/endpoint弹框用来回显project
@@ -252,6 +256,11 @@
receiver: '',
},
createMenu: [ //新增按钮内容
{
label: this.$t('dashboard.panel.createPanelTitle'),
url: 'panel',
type: 0
},
{
label: this.$t('project.project.createProject'),
url: 'project',
@@ -300,7 +309,10 @@
},
createBox(item) {
if (item.type == 1) {
if (item.type == 0) {
this.$refs.panelBox.show(true);
this.editPanel = {id: '', name: ''};
}else if (item.type == 1) {
this.$refs.projectBox.show(true);
this.editProject = {id: '', name: '', remark: ''};
} else if (item.type == 2) {
@@ -428,6 +440,11 @@
this.$refs.projectBox.show(true);
this.editProject = Object.assign({}, p);
},
panelListReload(){
if(this.$route.path==='/panel'){
this.$store.commit('panelListChange',true);//新增panel之后,且当前页面为panel页面则更新panel列表
}
},
logout() {
this.$get('logout');
this.jumpTo('login');

View File

@@ -20,18 +20,53 @@ const cn = {
title:'仪表盘',
panel:{
title:'看板',
//侧滑框
//面板-侧滑框
createPanelTitle: "创建面板",
createPanelTitleSec:"创建新面板",
editPanelTitle: "编辑面板",
panelForm:{
panelName:"面板名称" ,
panelId:"ID"
} ,
//图表-侧滑框
createChartTitle: "Create Chart",
editChartTitle: "Edit Chart",
chartForm:{
chartId:"ID",
chartName:"图表名称",
type:"类型",
typeVal:{
line:{
label:"曲线"
},
bar:{
label:"柱状图"
},
table:{
label:"表格",
}
},
width:"宽度",
high:"高度",
metric:"指标",
addMetric:"添加指标",
},
},
metric:{
name:"指标名称",
normal:"Normal",
expert:"Expert",
label:"指标标签",
addMetric:"添加指标",
expertTip:"请输入表达式"
},
metricPreview:{
title:'指标预览',
}
},
refresh:'刷新',
edit:'编辑',
delete:'删除',
screen:'全屏'
},
asset: {
tableTitle: {

View File

@@ -25,24 +25,57 @@ const en = {
title:'Dashboard',
panel:{
title:'Panel',
//侧滑框
//面板-侧滑框
createPanelTitle: "Create Panel",
createPanelTitleSec:"Create New Panel",
editPanelTitle: "Panel",
panelForm:{
panelName:"Panel Name",
panelId:"ID"
},
//图表-侧滑框
createChartTitle: "Create Chart",
editChartTitle: "Edit Chart",
chartForm:{
chartId:"ID",
chartName:"Chart Name",
type:"Type",
typeVal:{
line:{
label:"Line"
},
bar:{
label:"Bar"
},
table:{
label:"Table"
}
},
width:"Width",
high:"High",
metric:"Metric",
addMetric:"Add Metric",
},
},
metric:{
name:"Metric",
normal:"Normal",
expert:"Expert",
label:"MetricLabel",
addMetric:"Create Metric",
expertTip:"Please enter an expression"
},
metricPreview:{
title:'MetricPreview',
}
},
refresh:'refresh',
edit:'edit',
delete:'delete',
screen:'fullScreen'
},
validate: { //校验规则
required: 'Required',
number: 'Must be a number',
email:'E-mail is invalide',
tel:'Phone number is invalide',
config: {
account: {
@@ -60,7 +93,8 @@ const en = {
no: "No",
deleteSuccess: "Successfully Deleted",
saveSuccess: "Successfully Saved",
coverSuccess: 'Successfully Covered'
coverSuccess: 'Successfully Covered',
refreshLater:'Please refresh later'
},
asset:{
asset: 'Asset',

View File

@@ -0,0 +1,145 @@
<template key="panelBox">
<transition name="right-box">
<div class="right-box right-box-panel" v-if="rightBox.show">
<!-- begin--顶部按钮-->
<div class="right-box-top-btns">
<button type="button" v-if="panel.id != ''" @click="del(panel)" class="nz-btn nz-btn-size-normal nz-btn-style-light">
<span class="top-tool-btn-txt">{{$t('overall.delete')}}</span>
</button>
<button type="button" @click="save" class="nz-btn nz-btn-size-normal nz-btn-style-normal">
<span class="top-tool-btn-txt">{{$t('overall.save')}}</span>
</button>
<button type="button" @click="esc" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-style-square">
<span class="top-tool-btn-txt"><i class="el-icon-close"></i></span>
</button>
<!--
<div class="right-box-top-btn right-box-top-btn-full" @click="esc">
<div class="right-box-btn-icon">
<i class="el-icon-close"></i>
</div>
<span>{{$t('overall.esc')}}</span>
</div>
<div class="right-box-top-btn right-box-top-btn-full" @click="save">
<div class="right-box-btn-icon">
<i class="el-icon-edit-outline"></i>
</div>
<span >{{$t('overall.save')}}</span>
</div>
<div @click="del(panel)" class="right-box-top-btn" v-if="panel.id != ''">
<div class="right-box-btn-icon">
<i class="el-icon-delete"></i>
</div>
<span>{{$t('overall.delete')}}</span>
</div>
-->
</div>
<!-- end--顶部按钮-->
<!-- begin--标题-->
<div class="right-box-title">{{rightBox.title}}</div>
<!-- end--标题-->
<!-- begin--表单-->
<div class="right-box-form">
<div class="right-box-form-row">
<div class="right-box-form-label">{{$t('dashboard.panel.panelForm.panelName')}}</div>
<div class="right-box-form-content">
<el-input placeholder="" maxlength="64" show-word-limit v-model="panel.name" size="small"></el-input>
</div>
</div>
</div>
<!-- end--表单-->
<!-- begin--底部按钮-->
<!--
<div class="right-box-bottom-btns">
<div @click="esc()" :class="{'right-box-bottom-btn-50': true}" class="right-box-bottom-btn right-box-bottom-btn-cancel">{{$t('overall.cancel')}}</div><div @click="save()" class="right-box-bottom-btn right-box-bottom-btn-50">{{panel.id == '' ? $t('overall.create') : $t('overall.save')}}</div>
</div>
-->
<!-- end--底部按钮-->
</div>
</transition>
</template>
<script>
export default {
name: "panelBox",
props: {
panel: Object
},
data() {
return {
rightBox: { //面板弹出框相关
show: false,
title: this.$t('dashboard.panel.createPanelTitle')
},
}
},
methods: {
show(show) {
this.rightBox.show = show;
},
setTitle(title) {
this.rightBox.title = title;
},
//面板相关方法
del: function(u) {
this.$confirm(this.$t("tip.confirmDelete"), {
confirmButtonText: this.$t("tip.yes"),
cancelButtonText: this.$t("tip.no"),
type: 'warning'
}).then(() => {
this.$delete("panel?ids=" + u.id).then(response => {
if (response.code === 200) {
this.esc();
this.$message({duration: 1000, type: 'success', message: this.$t("tip.deleteSuccess")});
this.$emit("reloadForDel");
} else {
this.$message.error(response.msg);
}
})
});
},
save: function() {
if (this.panel.id) {
this.$put('panel', this.panel).then(response => {
if (response.code === 200) {
this.esc();
this.$message({duration: 1000, type: 'success', message: this.$t("tip.saveSuccess")});
this.$emit("reload");
} else {
this.$message.error(response.msg);
}
});
} else {
this.$post('panel', this.panel).then(response => {
if (response.code === 200) {
this.esc();
this.$message({duration: 1000, type: 'success', message: this.$t("tip.saveSuccess")});
this.$emit("reload");
} else {
this.$message.error(response.msg);
}
});
}
},
esc: function() {
this.rightBox.show = false;
},
},
created() {
},
mounted: function() {
},
watch: {
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,496 @@
<style scoped>
.el-row {
margin-bottom: 20px;
}
.el-row:last-child {
margin-bottom: 0;
}
.el-col {
border-radius: 4px;
}
.bg-purple {
background: white;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.common-float-left {
float: left;
display:inline-block;
}
.el-inner {
width: 200px;
border-top-width: 0px;
border-left-width: 0px;
border-right-width: 0px;
border-bottom-width: 10px;
border-color:red;
/*outline: medium;*/
}
.element-bottom-border {
padding-bottom: 5px;
border-bottom: 1px solid #dfe7f2;
margin-top:-25px;
}
/*metric样式--begin*/
.element-item {
padding-bottom: 20px;
border-bottom: 1px dashed #dfe7f2;
}
/*metric样式--end*/
.label-center{
margin-top:6px;
}
</style>
<template key="chartBox">
<transition name="right-box">
<div class="right-box right-box-add-chart" v-if="rightBox.show" >
<!-- begin--顶部按钮-->
<div class="right-box-top-btns">
<button type="button" v-if="chart.id != ''" @click="del(chart)" class="nz-btn nz-btn-size-normal nz-btn-style-light">
<span class="top-tool-btn-txt">{{$t('overall.delete')}}</span>
</button>
<button type="button" @click="confirmAdd" class="nz-btn nz-btn-size-normal nz-btn-style-normal">
<span class="top-tool-btn-txt">{{$t('overall.save')}}</span>
</button>
<button type="button" @click="esc" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-style-square">
<span class="top-tool-btn-txt"><i class="el-icon-close"></i></span>
</button>
</div>
<!-- end--顶部按钮-->
<!-- begin--标题-->
<div class="right-box-title">{{rightBox.title}}</div>
<!-- end--标题-->
<!-- begin--表单-->
<el-scrollbar class="right-box-form-box">
<el-form class="right-box-form" :model="chart" label-position="top" :rules="rules" ref="chartForm">
<el-form-item :label='$t("dashboard.panel.chartForm.chartName")' prop="title">
<el-input size="mini" maxlength="64" show-word-limit v-model="chart.title"></el-input>
</el-form-item>
<el-row :gutter="10">
<el-col :span="2" >
<div class="label-center" >{{$t('dashboard.panel.chartForm.type')}}</div>
</el-col>
<el-col :span="4">
<div class="grid-content ">
<el-form-item prop="type">
<el-select class="right-box-row-with-btn" value-key="chartType" popper-class="" v-model="chart.type" placeholder="" size="small">
<el-option v-for="item in chartTypeList" :key="item.id" :label="item.name" :value="item.id">
<span class="panel-dropdown-label-txt" >{{item.name}}</span>
</el-option>
</el-select>
</el-form-item>
</div>
</el-col>
<el-col :span="2.1">
<div class="label-center" >{{$t('dashboard.panel.chartForm.width')}}</div>
</el-col>
<el-col :span="5">
<div class="grid-content ">
<el-form-item prop="span">
<el-select class="right-box-row-with-btn" value-key="chartSpan" popper-class="" v-model="chart.span" placeholder="" size="small">
<el-option v-for="item in spanList" :key="item" :label="'span-' + item" :value="item">
<span class="panel-dropdown-label-txt" > span-{{item}}</span>
</el-option>
</el-select>
</el-form-item>
</div>
</el-col>
<el-col :span="2">
<div class="label-center" >{{$t('dashboard.panel.chartForm.high')}}</div>
</el-col>
<el-col :span="8">
<div class="grid-content ">
<el-form-item prop="heigh">
<el-input-number :min="10" label="" v-model="chart.height" placeholder="" size="small"></el-input-number>px
</el-form-item>
</div>
</el-col>
</el-row>
<el-row class="element-bottom-border" >
<div >{{$t('dashboard.panel.chartForm.metric')}}</div>
</el-row>
<el-row class="element-item" v-for="(elem, index) in elements" :key="'ele' + index">
<chart-metric ref="chartTag"
:product-id="productId"
:pointer="index"
:metric-list="metricList"
:count-total="elements.length"
@on-delete-target="deleteTarget"
@sub-save-ok="subOk"
@on-add-target-success="getTarget"
></chart-metric>
</el-row>
<el-row :gutter="20">
<el-col :span="20">
<button type="button" @click="addTarget" class="nz-btn nz-btn-size-normal nz-btn-style-normal">
<span class="top-tool-btn-txt">{{$t('dashboard.panel.chartForm.addMetric')}}</span>
</button>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="20">
&nbsp;
</el-col>
</el-row>
</el-form>
</el-scrollbar>
<!--
<div class="right-box-form">
<div class="right-box-form-row">
<div class="right-box-form-label">{{$t('dashboard.panel.chartForm.chartName')}}</div>
<div class="right-box-form-content">
<el-input placeholder="" maxlength="64" show-word-limit v-model="chart.title" size="small"></el-input>
</div>
</div>
<div class="right-box-form-row">
<el-row :gutter="20">
<el-col :span="8"><div class="grid-content bg-purple">1</div></el-col>
<el-col :span="8"><div class="grid-content bg-purple">2</div></el-col>
<el-col :span="8"><div class="grid-content bg-purple">3</div></el-col>
</el-row>
</div>
</div>
-->
<!-- end--表单-->
<!-- begin--底部按钮-->
<!--
<div class="right-box-bottom-btns">
<div @click="esc" class="right-box-bottom-btn right-box-bottom-btn-cancel right-box-bottom-btn-50">{{$t('overall.cancel')}}</div><div @click="save" class="right-box-bottom-btn right-box-bottom-btn-50">{{$t('overall.create')}}</div>
</div>
-->
<!-- end--底部按钮-->
</div>
</transition>
</template>
<script>
import bus from '../../../libs/bus';
import ChartMetric from "./chartMetric";
export default {
name: "chartBox",
props: {
},
data() {
return {
rightBox: {
show: false,
title: this.$t('dashboard.panel.createChartTitle'),
},
chart: {
id:'',
title: '',
type:'line',
span:12,
height:400,
elements:{
id: '',
expression: '',
type: ''
}
},
rules: {
title: [
{required: true, trigger: 'blur'}
],
/*
heigh: [
{required: true, message: this.$t('validate.required'), trigger: 'blur'}
]
*/
},
chartTypeList: [
{
id:"line",
name:this.$t("dashboard.panel.chartForm.typeVal.line.label")
},
{
id:"bar",
name:this.$t("dashboard.panel.chartForm.typeVal.bar.label")
},
{
id:"table",
name:this.$t("dashboard.panel.chartForm.typeVal.table.label")
}
],
elements: [1], // 指标部分 tarNum
elementTarget: [], // 本地保存数据
spanList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
// 是否为编辑已有信息
isedit: false,
productId: 0,//不需要这个参数,可以删除
panelId: 0,
metricList: [], // metric列表
deleteIndex: '', // 要删除的指标模块
subCount: 0, // subSave保存data到bus计数器
}
},
components:{
'chart-metric':ChartMetric
},
methods: {
show(show) {
this.rightBox.show = show;
},
save() {
this.$refs['chartForm'].validate((valid) => {
if (valid) {
if (this.chart.id) {//修改
this.$put('panel/'+this.chart.id+'/charts', this.project).then(response => {
if (response.code === 200) {
this.esc();
this.$message({duration: 1000, type: 'success', message: this.$t("tip.saveSuccess")});
} else {
this.$message.error(response.msg);
}
});
} else {//新增
this.$post('panel/charts', this.chart).then(response => {
if (response.code === 200) {
this.esc();
this.$message({duration: 1000, type: 'success', message: this.$t("tip.saveSuccess")});
} else {
this.$message.error(response.msg);
}
});
}
} else {
console.log('error submit!!');
return false;
}
});
},
del: function(u) {
this.$confirm(this.$t("tip.confirmDelete"), {
confirmButtonText: this.$t("tip.yes"),
cancelButtonText: this.$t("tip.no"),
type: 'warning'
}).then(() => {
this.$delete("panel/"+u.id+"/charts").then(response => {
if (response.code === 200) {
this.esc();
this.$message({duration: 1000, type: 'success', message: this.$t("tip.deleteSuccess")});
} else {
this.$message.error(response.msg);
}
})
});
},
//----------------------------------
/*关闭弹框*/
esc() {
this.rightBox.show = false;
//this.editParamBox.show = false;
},
/*metric部分相关方法--begin*/
// 增加指标,tarNum
addTarget() {
this.elements.push(1);
},
// 删除指标,第一步, 新方法
deleteTarget(index) {
this.deleteIndex = index;
this.$refs.chartTag.forEach((item) => {
// 子组件保存内容到bus
item.subSave();
});
},
// subSave保存成功后回调,第二步
subOk() {
// 每个模块均有返回,当全部模块返回完成时,将sub计数器重置
this.subCount += 1;
if (this.subCount === this.elements.length) {
this.subCount = 0;
// 保存完成,进行删除操作
this.elements.splice(this.deleteIndex, 1);
this.elementTarget.splice(this.deleteIndex, 1);
bus.chartAddInfo.metricTarget.splice(this.deleteIndex, 1);
this.$nextTick(() => {
this.$refs.chartTag.forEach((item, index) => {
item.setSubdata(index); // 将数据从bus重新赋值
});
});
}
},
// 格式化tag为字符串表达式
tagsToString(metric,arr) {
let str = metric;
arr.forEach((item, index) => {
if (index === 0) {
str +="{"
if(item.value.length===1){
str += `${item.name}='${item.value.join('|')}'`;
}else if(item.value.length>1){
str += `${item.name}=~'${item.value.join('|')}'`;
}
} else {
if(item.value.length===1){
str += `,${item.name}='${item.value.join('|')}'`;
}else if(item.value.length>1){
str += `,${item.name}=~'${item.value.join('|')}'`;
}
}
});
str +="}";
return str;
},
// 新建图表
addCharts(params) {
this.$post('panel/'+this.panelId+'/charts', params).then(response => {
if (response.code === 200) {
this.esc();
this.$message({duration: 1000, type: 'success', message: this.$t("tip.saveSuccess")});
this.$refs.chartForm.resetFields();//清空表单
this.$emit('on-create-success', 'create', response.data,params);
} else {
this.$message.error(response.msg);
}
});
},
// 更新图表
updateCharts(params) {
/*
const obj = params;
obj.id = this.chartId;
updateCharts(obj).then((res) => {
if (res.status === 200) {
this.chartModal = false;
this.initInfo();
this.$refs.chartInfo.resetFields();
this.$emit('on-create-success', 'update', res.data);
}
});
*/
},
// 获取每个tag组件内部校验后数据,点击生成图表时触发
getTarget(target) {
this.elementTarget.push(target);
if (this.elementTarget.length === this.elements.length) {
this.$refs.chartForm.validate((valid) => {
const params = {
// productId: this.productId,
//panelId: this.panelId,
title: this.chart.title,//this.chart
span: this.chart.span,
height: this.chart.height,
type: this.chart.type,
};
//生成指标数组
const elements = [];
this.elementTarget.forEach((elem,index) => {
if(elem.type==='normal'){
const metricStr = this.tagsToString(elem.metric,elem.selectedTagList);
elements.push({
//id:index+1,
//metric: elem.metric,//指标名称
expression: metricStr,//指标对应Label及Value组成的表达式字符串
type:elem.type,//指标类型
});
}else if(elem.type==='expert'){
elements.push({
//id:index+1,
//metric: elem.metric,//指标名称
expression: elem.expression,//指标对应Label及Value组成的表达式字符串
type:elem.type,//指标类型
});
}
});
params.elements = elements;
if (valid) {
if (this.isedit) {
params.id = this.chartId;
this.updateCharts(params);
} else {
this.addCharts(params);
}
}
});
}
},
// 生成图表
confirmAdd() {
this.elementTarget = []; // 初始化清空参数
this.$refs.chartTag.forEach((item, index) => {//循环指标列表
// 触发每个tag组件内部进行校验
item.saveTarget(index);
});
this.$refs.chartForm.validate();
},
// 获取metric列表
getSuggestMetric() {
this.$get('metric', {pageNo: 1, pageSize: 9999}).then(response => {
if (response.code === 200) {
this.metricList = response.data.list;
}else {
this.metricList = [];
}
})
},
// 创建打开
createData(panelId) {
this.panelId = panelId;
this.isedit = false;
this.initInfo(); // 初始化图表信息
//this.chartModal = true;//????控制弹出框显示和隐藏的,不需要了
this.initOpen(); // 获取metric, productId数据
},
// 初始化信息
initInfo() {
this.chart.title = '';
this.chart.type = 'line';
this.chart.span = 12;
this.chart.height = 400;
this.elements = [1];
this.elementTarget = [];
bus.chartAddInfo.metricTarget = [];
},
// 创建时打开,用于清空chart-tag数据
initOpen() {
bus.$emit('clear_history');
/* 项目不需要produce
if (this.$route.params.productId) {
this.productId = parseInt(this.$route.params.productId, 10);
}
*/
this.getSuggestMetric();//this.getSuggestMetric(this.productId);
},
/*metric部分相关方法--end*/
},
created() {
},
watch: {
}
}
</script>

View File

@@ -0,0 +1,418 @@
<style scoped>
.without-bottom {
margin-bottom: 0;
}
.ivu-select-dropdown {
max-height: 100px;
}
.error-info-text {
position: absolute;
top: 100%;
left: 0;
line-height: 1;
padding-top: 6px;
color: #ed3f14;
white-space: nowrap;
word-wrap: normal;
}
.error-text {
color: #ed3f14;
line-height: 1.5;
}
.nz-btn-style-higher{
line-height: 22px;
}
.li-list-part {
width: 90%;
height: 130px;
border: 1px solid #cfcfcf;
overflow-y: auto;
}
.li-list-part-label-val-list {
width: 100%;
height: 165px;
border: 1px solid #cfcfcf;
overflow-y: auto;
margin-top: -10px;/*21*/
border: 0px;
}
.no-list-style{
list-style: none;
}
.li-cursor{
cursor: pointer;
}
.activeColor {
background-color: #409EFF;
}
.metric-title-label{
margin-bottom:8px;
}
.metric-title-position{
margin-bottom:-5px;
}
.metric-title-row-position{
margin-top:-10px;
}
</style>
<template>
<el-form :model="elementInfo" ref="elementInfo">
<el-row>
<el-col span="16">
{{$t('dashboard.panel.chartForm.metric')}}
</el-col>
<el-col span="8">
<div class="nz-btn-group float-left" v-show="tableShow == 2">
<button @click="clickTabelShow(1,'normal')" class="nz-btn nz-btn-size-small nz-btn-style-light float-left">
<span>{{$t('dashboard.metric.normal')}}</span>
</button>
<button @click="" class="nz-btn nz-btn-size-small nz-btn-disabled nz-btn-style-normal float-left">
<span>{{$t('dashboard.metric.expert')}}</span>
</button>
</div>
<div class="nz-btn-group float-left" v-show="tableShow == 1">
<button @click="" class="nz-btn nz-btn-size-small nz-btn-disabled nz-btn-style-normal float-left">
<span>{{$t('dashboard.metric.normal')}}</span>
</button>
<button @click="clickTabelShow(2,'expert')" class="nz-btn nz-btn-size-small nz-btn-style-light float-left">
<span>{{$t('dashboard.metric.expert')}}</span>
</button>
</div>
</el-col>
</el-row>
<el-row v-show="tableShow == 2">
<el-col span="22">
<el-form-item prop="expression" ><!--expression和metric的验证只能有一个不能同时存在:rules="{ required: true, type: 'string', message: '', trigger: 'change' }"-->
<el-input size="mini" type="textarea" maxlength="1024" show-word-limit v-model="elementInfo.expression" :placeholder="this.$t('dashboard.metric.expertTip')" ></el-input>
</el-form-item>
</el-col>
<el-col span="2">
&nbsp;&nbsp;<button type="button" v-if="countTotal > 1" @click="deleteTarget" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-style-square nz-btn-style-higher"><span class="top-tool-btn-txt"><i class="el-icon-close"></i></span></button>
</el-col>
</el-row>
<el-row v-show="tableShow == 1">
<el-col span="22">
<el-form-item :label-width="80" prop="metric" ><!--:rules="{ required: true, type: 'string', message: '', trigger: 'change' }"-->
<el-select ref="metricSelect" placeholder="" popper-class="" size="small" v-model="elementInfo.metric" @change="selectMetric">
<el-option v-for="(item, index) in metricShowList.arr" :key="item.metric + index"
:value="item.metric">{{item.metric}}</el-option>
</el-select>
<span v-if="metricShowList.text" class="error-info-text">{{metricShowList.text}}</span>
</el-form-item>
</el-col>
<el-col span="2">
&nbsp;&nbsp;<button type="button" v-if="countTotal > 1" @click="deleteTarget" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-style-square nz-btn-style-higher"><span class="top-tool-btn-txt"><i class="el-icon-close"></i></span></button>
</el-col>
</el-row>
<el-row v-if="elementInfo.metric" v-show="tableShow == 1"><!--v-if="elementInfo.tagList.length > 0"-->
<el-col span="12">
<div class="metric-title-label">{{elementInfo.metric}}</div>
<div class="li-list-part">
<ul class="no-list-style">
<li class="li-cursor" v-if="!item.isSelect"
v-for="(item,index) in elementInfo.tagList"
@click="getLidata(index,item)"
:key="index">
<div>
<span >{{ item.name }}</span>
</div>
</li>
</ul>
</div>
</el-col>
<el-col span="12">
<div class="li-list-part-label-val-list" >
<el-form-item class="metric-title-position" v-for="(item, index) in elementInfo.selectedTagList" :key="index" :label="item.name" :label-width="100" :ref="'tagItem' + index" :prop="'tagList.' + index + '.value'" >
<el-row class="metric-title-row-position" >
<!--多选列表 -->
<el-col span="20" >
<el-select v-model="item.value" ref="tagSelect" size="small"
placeholder=""
collapse-tags
multiple>
<el-option v-for="(op, j) in elementInfo.selectedTagList[index].list" :key="op + j" :value="op">{{op}}</el-option>
</el-select>
</el-col>
<el-col span="4" >
&nbsp;&nbsp;<button type="button" @click="deleteMetricLabel(item,index)" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-style-square nz-btn-style-higher"><span class="top-tool-btn-txt"><i class="el-icon-close"></i></span></button>
</el-col>
</el-row>
</el-form-item>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
import bus from '../../../libs/bus';
export default {
name: 'chartTag',
props: {
// 序号
pointer: {
type: Number,
default: 0,
},
// metric列表
metricList: {
type: Array,
default: () => [],
},
countTotal: {
type: Number,
default: 1,
},
},
components: {
//multipleSelect
},
data() {
return {
tableShow: 1, // 1.normal; 2.expert
// 指标信息
elementInfo: {
metric: '',//当前选中的metric名称
type:'normal',
// name: '',
tagList: [], // 标签列表
selectedTagList:[],//已选中的标签列表
expression:''
},
metricLoading: false,
keydataList: [], // tag标签键列表
target: null, // 获取到的数据
tagSet: null, // 根据你metric获取的tags信息
setDataFlag: false, // true时为获取数据,编辑状态
vendorCount: '',
};
},
watch: {},
beforeDestroy() {},
methods: {
// 删除该选项,第一步,传递要删除的参数
deleteTarget() {
this.$emit('on-delete-target', this.pointer);
},
// 第二步,on-delete-target回调保存数据
subSave() {
bus.chartAddInfo.metricTarget[this.pointer] = this.elementInfo;
this.$emit('sub-save-ok');
},
// 第三步,将数据重新赋值,sub-save-ok回调
setSubdata(index) {
if (index === this.pointer) {
this.elementInfo.metric = bus.chartAddInfo.metricTarget[this.pointer].metric;
// 当该项metric为空时重置一下
if (!this.elementInfo.metric && this.$refs.metricSelect) {
this.$refs.metricSelect.reset();
}
this.elementInfo.tagList = bus.chartAddInfo.metricTarget[this.pointer].tagList;
}
},
// (最后整体保存添加的图标的时候执行)保存, chartdata点击确认后保存本身数据并返回给chartdata
saveTarget(pointer) {
if (this.pointer === pointer) {
this.$refs.elementInfo.validate((valid) => {
if (valid) {//根据设置的rules进行验证验证通过则返回继续进行保存每个el-form-item都需要验证
this.$emit('on-add-target-success', this.elementInfo, pointer);
}
});
}
},
// 选择metric
selectMetric() {
if (this.elementInfo.metric) {//选择了metric则设置tagList否则设置为空
this.getSuggestTags(this.elementInfo.metric);
} else {
this.elementInfo.tagList = [];
}
},
// 选择主机
/*
selectHost(arr, index) {
this.elementInfo.tagList[index].value = arr;
if (this.$refs.elementInfo && this.$refs[`tagItem${index}`]) {
this.$refs.elementInfo.validateField(`tagList.${index}.value`);
}
},
*/
/*
selectTag(index) {//多选列表改变时的操作:为了* 的操作,此处不需要
const arr = this.elementInfo.tagList[index].value;
if (arr.length > 0 && arr.indexOf('*') > -1) {
this.elementInfo.tagList[index].value = ['*'];
}
},
*/
// 获取tags列表
getSuggestTags(metric) {
this.$get('metric/labelName?metric='+metric).then(response => {
this.elementInfo.selectedTagList = [];
this.elementInfo.tagList = [];
if (response.code === 200) {
if(response.data.list){
//this.elementInfo.tagList = response.data.list;
response.data.list.forEach((item) => {
const tagObj = {
name: item.name,
isSelect:false//当前元素是否被选中,默认都未选中
};
this.elementInfo.tagList.push(tagObj);
});
}else{
response.data.forEach((item) => {
const tagObj = {
name: item.name,
isSelect:false //当前元素是否被选中,默认都未选中
};
this.elementInfo.tagList.push(tagObj);
});
}
//this.elementInfo.tagList = response.data.list;
}else {
this.elementInfo.tagList = [];
}
});
},
getStyles(width) {
return `width: ${width}px;`;
},
filterMethod(value, option) {
return option.toUpperCase().indexOf(value.toUpperCase()) !== -1;
},
// 编辑已有图表状态时,先填充数据
setMdata(data) {
this.setDataFlag = true;
this.target = Object.assign({}, data);
this.elementInfo.metric = data.metric;
this.selectMetric(); // 获取tag
// this.proTags(data.tags);
},
clearHistory() {
this.elementInfo.metric = '';
this.setDataFlag = false;
if (this.$refs.elementInfo) {
this.$refs.elementInfo.resetFields();//???
}
if (this.$refs.metricSelect) {
this.$refs.metricSelect.reset();
}
this.elementInfo.tagList = [];
},
// 获取文本宽度
getWidth(str) {
const sensor = document.createElement('pre');
sensor.innerHTML = str;
sensor.style.display = 'inline-block';
sensor.style.width = 'auto';
sensor.style.visibility = 'hidden';
sensor.style.height = 0;
sensor.style.position = 'relative';
sensor.style['z-index'] = -10;
document.body.appendChild(sensor);
const width = sensor.offsetWidth;
document.body.removeChild(sensor);
const widthL = width > 180 ? width : 180;
return widthL;
},
// 将tag添加到相应框内
proTags(data) {
const dou = data.indexOf(',');
// 只有一组tag
if (dou === -1) {
const set = data.split('=');
const tagValueArr = set[1].indexOf('|') > -1 ? set[1].split('|') : [set[1]];
const tagIndex = this.elementInfo.tagList.findIndex(t => t.name === set[0]);
if (tagIndex > -1) {
this.elementInfo.tagList[tagIndex].value = tagValueArr;
}
} else { // 多组tag
const mid = data.split(','); // ['key=v1','key=v2|v3',....]
mid.forEach((item) => {
const setInner = item.split('=');
const innerValueArr = setInner[1].indexOf('|') > -1 ?
setInner[1].split('|') : [setInner[1]];
const tagIndex = this.elementInfo.tagList.findIndex(t => t.name === setInner[0]);
if (tagIndex > -1) {
this.elementInfo.tagList[tagIndex].value = innerValueArr;
}
});
}
},
//metricLabelName单击事件
getLidata(index, item) {
if(!item.isSelect){
this.vendorCount = index;
//查询metricLabel名称对应的LabelValue
this.$get('metric/labelVal?metric='+this.elementInfo.metric+"&name="+item.name).then(response => {
const tagObj = {
name: item.name,//选中的metricLabel名称
list:[],//metricLabel名称对应的LabelValue
value:[]//最终选择的值
};
//this.elementInfo.selectedTagList = [];
if (response.code === 200) {
if(response.data.list){
response.data.list.forEach((item) => {
tagObj.list.push(item.value)
});
this.elementInfo.selectedTagList.push(tagObj);
}else{
response.data.forEach((item) => {
tagObj.list.push(item.value)
});
this.elementInfo.selectedTagList.push(tagObj);
}
}else {
this.elementInfo.selectedTagList.push(tagObj);
}
});
item.isSelect = true;
}
},
//删除MetricLabel时需要将tagList中的isSelect设置为false并删除elementInfo.selectedTagList里对应的元素
deleteMetricLabel(item,index) {
this.elementInfo.tagList.forEach((tagItem) => {
if(tagItem.name===item.name){
tagItem.isSelect = false;
}
});
this.elementInfo.selectedTagList.splice(index,1);
//this.$emit('on-delete-target', this.pointer);
},
clickTabelShow(val,type){
this.tableShow = val;
this.elementInfo.type = type;
if(val===2){
this.elementInfo.metric='';
}
if(val===1){
this.elementInfo.expression='';
}
}
},
computed: {
metricShowList() {
const obj = {
arr: [...this.metricList],
text: '',
};
return obj;
},
},
mounted() {
bus.$on('clear_history', () => {
this.clearHistory();
});
},
};
</script>

View File

@@ -22,11 +22,15 @@
.content-right-option .el-icon-view:hover {
color: #409EFF;
}
/* begin-chart list*/
.table-list {
margin-top: 100px;
}
margin-top: 10px;
}
.box-content {
position: relative;
}
/* end-chart list*/
/* begin--Panel-自定义可编辑的el-select下拉框样式*/
.panel-dropdown-btn {
display: inline-block;
@@ -74,11 +78,11 @@
</div>
<div class="content-right">
<div class="top-tools">
<button @click="toAdd" class="nz-btn nz-btn-size-normal nz-btn-style-normal float-right">
<button @click="toAddChart" class="nz-btn nz-btn-size-normal nz-btn-style-normal float-right">
<span class="top-tool-btn-txt">{{$t('overall.add')}}</span>
</button>
<div class="top-tool-search float-right"><search-input :searchMsg="searchMsg" @search="search"></search-input></div>
<el-select class="right-box-row-with-btn" popper-class="" v-model="showPanel.id" placeholder="" size="small">
<el-select class="right-box-row-with-btn" popper-class="" v-model="showPanel.id" placeholder="" size="small" @change="panelChange">
<el-option >
<span class="panel-dropdown-btn-create" @click.stop="toAdd" >{{$t('dashboard.panel.createPanelTitleSec')}}</span>
</el-option>
@@ -96,73 +100,29 @@
</el-option>
</el-select>
</div>
<div class="table-list">
<!--<div class="box-content">
<div class="table-list" style="overflow-y:auto;height: 100%;">
<div class="box-content">
<chart-list
@on-edit-chart="editData"
@on-remove-chart="removeData" ref="chartList"></chart-list>
</div>
-->
</div>
</div>
<transition name="right-box">
<div class="right-box right-box-panel" v-if="rightBox.show">
<!-- begin--顶部按钮-->
<div class="right-box-top-btns">
<div class="right-box-top-btn right-box-top-btn-full" @click="esc">
<div class="right-box-btn-icon">
<i class="el-icon-close"></i>
</div>
<span>{{$t('overall.esc')}}</span>
</div>
<div class="right-box-top-btn right-box-top-btn-full" @click="save">
<div class="right-box-btn-icon">
<i class="el-icon-edit-outline"></i>
</div>
<span >{{$t('overall.save')}}</span>
</div>
<div @click="del(panel)" class="right-box-top-btn" v-if="panel.id != ''">
<div class="right-box-btn-icon">
<i class="el-icon-delete"></i>
</div>
<span>{{$t('overall.delete')}}</span>
</div>
</div>
<!-- end--顶部按钮-->
<!-- begin--标题-->
<div class="right-box-title">{{rightBox.title}}</div>
<!-- end--标题-->
<!-- begin--表单-->
<div class="right-box-form">
<div class="right-box-form-row">
<div class="right-box-form-label">{{$t('dashboard.panel.panelForm.panelName')}}</div>
<div class="right-box-form-content">
<el-input placeholder="" maxlength="64" show-word-limit v-model="panel.name" size="small"></el-input>
</div>
</div>
</div>
<!-- end--表单-->
<!-- begin--底部按钮-->
<div class="right-box-bottom-btns">
<div @click="esc()" :class="{'right-box-bottom-btn-50': true}" class="right-box-bottom-btn right-box-bottom-btn-cancel">{{$t('overall.cancel')}}</div><div @click="save()" class="right-box-bottom-btn right-box-bottom-btn-50">{{panel.id == '' ? $t('overall.create') : $t('overall.save')}}</div>
</div>
<!-- end--底部按钮-->
</div>
</transition>
<panel-box :panel="panel" @reload="panelReload" @reloadForDel="panelReloadForDel" ref="panelBox"></panel-box>
<chart-box ref="addChartModal" @on-create-success="createSuccess"></chart-box>
</div>
</template>
<script>
export default {
import ChartBox from "./chartBox";
import ChartList from '../../charts/chart-list';
export default {
name: "panel",
data() {
return {
rightBox: { //弹出框相关
rightBox: { //面板弹出框相关
show: false,
title: this.$t('dashboard.panel.createPanelTitle')
},
@@ -174,6 +134,18 @@ export default {
id:'',
name: ''
},
chart: {
id:'',
title: '',
type:'line',
span:12,
height:400,
elements:{
id: '',
expression: '',
type: ''
}
},
pageObj: {
pageNo: 1,
pageSize: 9999,//此处获取所有数据,所以设置一个较大的值
@@ -198,9 +170,32 @@ export default {
}],
},
searchLabel: {}, //搜索参数
//---图表相关参数--start
dataList: [], // 数据列表
searchName: '', // 搜索名称
filter: { // 过滤条件
//productId: 0,
panelId: 0,
start_time: '',
end_time: '',
},
panelId: 0,
removeModal: false, // 删除弹出
deleteObj: {}, // 删除对象
//---图表相关参数--end
}
},
components:{
'chart-box':ChartBox,
'chart-list':ChartList
},
methods: {
//面板相关操作
panelChange(){
this.filter.panelId = this.showPanel.id;
this.getData(this.filter);
},
del: function(u) {
this.$confirm(this.$t("tip.confirmDelete"), {
confirmButtonText: this.$t("tip.yes"),
@@ -223,40 +218,61 @@ export default {
},
toEdit: function(u) {
this.panel = Object.assign({}, u);
this.rightBox.title = this.$t("dashboard.panel.editPanelTitle") ;
this.rightBox.show = true;
this.$refs.panelBox.setTitle(this.$t("dashboard.panel.editPanelTitle"));
this.$refs.panelBox.show(true);
},
toAdd: function() {
this.cleanPanel();
this.rightBox.title = this.$t("dashboard.panel.createPanelTitle");
this.rightBox.show = true;
this.$refs.panelBox.show(true);
this.panel = {id: '', name: ''};
this.$refs.panelBox.setTitle(this.$t("dashboard.panel.createPanelTitle"));
},
save: function() {
if (this.panel.id) {
this.$put('panel', this.panel).then(response => {
if (response.code === 200) {
this.$message({duration: 1000, type: 'success', message: this.$t("tip.saveSuccess")});
panelReload(){
this.getTableData();
this.esc();
} else {
this.$message.error(response.msg);
},
panelReloadForDel:function(){
if(this.showPanel.id===this.panel.id){
this.showPanel.id ='';
}
});
} else {
this.$post('panel', this.panel).then(response => {
if (response.code === 200) {
this.$message({duration: 1000, type: 'success', message: this.$t("tip.saveSuccess")});
this.getTableData();
this.esc();
},
/*图表相关操作--start*/
toAddChart:function(){
this.$refs.addChartModal.show(true);
this.$refs.addChartModal.createData(this.showPanel.id);//初始化创建图表需要的初始数据
},
// 编辑图表信息,打开编辑弹窗
editData(data) {
this.$refs.addChartModal.editData(data, this.panelId, this.filter.productId);
},
// 移除图表
removeData(data) {
this.deleteObj = data;
this.removeModal = true;
},
// 图表创建成功回调panel页面进行图表的刷新
createSuccess(msg, data,params) {
/*
if (data && data.code === 200) {
if (msg === 'create') {
//this.$message.success('添加成功');
} else {
this.$message.error(response.msg);
//this.$message.success('编辑成功');
}
});
}
*/
this.filter.panelId = this.showPanel.id;
this.getData(this.filter);
},
esc: function() {
this.rightBox.show = false;
// 获取数据,用在子页面
getData(params) {
this.$refs.chartList.initData(params);
},
/*图表相关操作--end*/
//公用操作
jumpTo(data,id) {
this.$store.state.assetData.moduleData = data
this.$store.state.assetData.selectedData = id
@@ -273,18 +289,19 @@ export default {
this.$get('panel', this.searchLabel).then(response => {
if (response.code === 200) {
this.panelData = response.data.list;
if(this.panelData.length>0 ){
this.filter.panelId = this.panelData[0].id;
}
if( response.data.list.length>0 && this.showPanel.id===''){
this.showPanel.id = response.data.list[0].id;
this.filter.panelId = this.showPanel.id;
}
this.pageObj.total = response.data.total
this.getData(this.filter);
}
})
},
cleanPanel: function() {
this.panel = {
id: '',
name: ''
}
},
pageNo(val) {
this.pageObj.pageNo = val;
@@ -309,10 +326,19 @@ export default {
this.getTableData();
},
mounted: function() {
},
computed: {
refreshPanel() {
return this.$store.state.panelListReload;
}
},
watch: {
refreshPanel(n, o) {
if (n) {
this.getTableData();
this.$store.commit('panelListChange', false);
}
}
}
}
}
</script>

View File

@@ -0,0 +1,175 @@
import Vue from 'vue';
//import Cookies from 'js-cookie';
//import md5 from 'md5';
Date.prototype.setStart = function() {
this.setHours(0);
this.setMinutes(0);
this.setSeconds(0);
};
// eslint-disable-next-line
Date.prototype.setEnd = function() {
this.setHours(23);
this.setMinutes(59);
this.setSeconds(59);
};
export default new Vue({
data() {
return {
selectDate: [], // 选中的时间段
emailReg: /^[a-zA-Z0-9]{1,10}@[a-zA-Z0-9]{1,5}\.[a-zA-Z0-9]{1,5}$/,
// 创建策略信息
buildRuleInfo: {
triggers: [],
actions: [],
},
backtoRulelist: '', // 返回策略列表页信息
//role: md5(1),
role:1,
// 创建图表信息
chartAddInfo: {
metricTarget: [],
},
};
},
methods: {
// 获取初始化时间,默认最近一周
getDefaultDate() {
let start = this.getDays(-7);
let end = this.getDays(0);
start.setStart();
end.setEnd();
// let start = this.getHoursTime(-1);
// let end = this.getHoursTime(0);
start = this.timeFormate(start, 'yyyy-MM-dd hh:mm:ss');
end = this.timeFormate(end, 'yyyy-MM-dd hh:mm:ss');
this.selectDate = [start, end];
},
getHoursTime(hours) {
const today = new Date().getTime();
const date = new Date(today + (hours * 60 * 60 * 1000));
return date;
},
// 初始化日期
getDays(days) {
const today = new Date().getTime();
const date = new Date(today + (days * 24 * 60 * 60 * 1000));
return date;
},
formatDate(date, type) {
const yy = date.getFullYear();
const dateM = date.getMonth() + 1;
const mm = dateM > 9 ? dateM : `0${dateM}`;
const dateD = date.getDate();
const dd = dateD > 9 ? dateD : `0${dateD}`;
if (type) {
return `${yy}${type}${mm}${type}${dd}`;
}
return `${yy}${mm}${dd}`;
},
timeFormate(date, fmt) {
const time = new Date(date);
let fm = fmt;
// fmt 自定义格式,如yy-MM-dd
let week = '';
switch (time.getDay()) {
case 0:
week = '周日';
break;
case 1:
week = '周一';
break;
case 2:
week = '周二';
break;
case 3:
week = '周三';
break;
case 4:
week = '周四';
break;
case 5:
week = '周五';
break;
case 6:
week = '周六';
break;
default:
week = '';
break;
}
const o = {
'M+': time.getMonth() + 1, // 月份
'd+': time.getDate(), // 日
'h+': time.getHours(), // 小时
'm+': time.getMinutes(), // 分
's+': time.getSeconds(), // 秒
'q+': Math.floor((time.getMonth() + 3) / 3), // 季度
S: time.getMilliseconds(), // 毫秒
w: week,
};
if (/(y+)/.test(fm)) {
fm = fm.replace(RegExp.$1, (time.getFullYear().toString()).substr(4 - RegExp.$1.length));
}
Object.keys(o).forEach((k) => {
if (new RegExp(`(${k})`).test(fm)) {
fm = fm.replace(RegExp.$1, (RegExp.$1.length === 1) ?
(o[k]) : ((`00${o[k]}`).substr((`${o[k]}`).length)));
}
});
return fm;
},
isEmptyObject(obj) {
if (obj) {
let name = '';
// eslint-disable-next-line
for (name in obj) { return false; }
return true;
}
return true;
},
validateEmail(rule, value, callback) {
if (value === '') {
callback(new Error('请输入邮箱'));
} else if (!this.emailReg.test(value)) {
callback(new Error('邮箱格式不正确'));
} else {
callback();
}
},
getNumStr(num) {
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 `${gbNum.toFixed(2)}GB`;
}
return `${mbNum.toFixed(2)}MB`;
}
return `${kbNum.toFixed(2)}KB`;
}
return num.toFixed(2);
},
},
created() {
this.getDefaultDate();
},
computed: {
/*
isAdmin() {
return this.role === Cookies.get('owl_role');
},
*/
},
});

View File

@@ -25,6 +25,7 @@ import assetAddUnit from "./components/page/asset/assetAddUnit"; //资产添加
import assetEditUnit from "./components/page/asset/assetEditUnit"; //资产添加组件
import alertConfigBox from "./components/common/rightBox/alertConfigBox"; //告警规则弹框组件
import dcConfigBox from "./components/common/dcConfig"; //idc配置弹框组件
import panelBox from "./components/common/rightBox/panelBox"; //面板弹框组件
Vue.component("Pagination", Pagination);
Vue.component("searchInput", searchInput);
@@ -36,6 +37,7 @@ Vue.component("assetAddUnit", assetAddUnit);
Vue.component("assetEditUnit", assetEditUnit);
Vue.component("alert-config-box", alertConfigBox);
Vue.component("idc-config-box", dcConfigBox);
Vue.component("panel-box", panelBox);
Vue.prototype.$axios = axios;
Vue.prototype.$post = post;

View File

@@ -17,6 +17,7 @@ const store = new Vuex.Store({
projectListChange: 0,
moduleListChange: 0,
flushDataSign: false,
panelListReload:false
},
getters: {
},
@@ -32,6 +33,9 @@ const store = new Vuex.Store({
},
moduleListChange(state) {
state.moduleListChange = state.moduleListChange + 1;
},
panelListChange(state,status){
state.panelListReload = status;
}
},
actions: {