Merge branch 'dev-3.3' of git.mesalab.cn:nezha/nezha-fronted into dev-3.3
This commit is contained in:
@@ -12,10 +12,14 @@ npm install
|
||||
npm run dev
|
||||
|
||||
# build for production with minification
|
||||
npm run build
|
||||
npm run build -- dev
|
||||
|
||||
# build for production and view the bundle analyzer report
|
||||
npm run build --report
|
||||
```
|
||||
|
||||
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
|
||||
|
||||
使用
|
||||
|
||||
需要配置 config.json 为 {"baseUrl":"http://192.168.40.42:8080/", "version": "21.04"}
|
||||
|
||||
@@ -63,6 +63,12 @@
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
.no-position-alert-label {
|
||||
.alert-label.alert-label__border{
|
||||
border: none !important;
|
||||
position: unset;
|
||||
}
|
||||
}
|
||||
//.alert-label::after, .alert-labelUp::after {
|
||||
// content: '';
|
||||
// display: block;
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
.chart-fullscreen.nz-dialog .panel-chart--fullscreen{
|
||||
.alert-message-info-header{
|
||||
border-bottom: 1px solid rgba(0,0,0,0.09);;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.alert-message-info-box{
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
.info-box-left{
|
||||
width: 66%;
|
||||
min-width: 500px;
|
||||
min-height: 600px;
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.nz-chart {
|
||||
height: 36%;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid $--border-color-light;
|
||||
flex: none;
|
||||
}
|
||||
.alert-message-info-tab{
|
||||
height: 63%;
|
||||
flex: 1;
|
||||
.el-tabs.el-tabs--card {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.el-tabs__header{
|
||||
margin: 0;
|
||||
.el-tabs__item{
|
||||
border: 1px solid $--border-color-light;
|
||||
border-radius: 2px;
|
||||
//border-bottom: none;
|
||||
margin-right: 6px;
|
||||
background: $--background-color-base;
|
||||
color: $--color-text-regular;
|
||||
}
|
||||
.el-tabs__item:hover{
|
||||
color: $--color-warning;
|
||||
background: $--background-color-empty;
|
||||
border-bottom-color: $--background-color-empty;
|
||||
}
|
||||
.el-tabs__item.is-active{
|
||||
color: $--color-warning;
|
||||
background: $--background-color-empty;
|
||||
border-bottom-color: $--background-color-empty;
|
||||
}
|
||||
}
|
||||
.el-tabs__content{
|
||||
padding: 20px;
|
||||
flex: 1;
|
||||
border: 1px solid $--border-color-light;
|
||||
border-top: none;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.info-box-right{
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
border: 1px solid #E7EAED;
|
||||
border-radius: 2px;
|
||||
box-sizing: border-box;
|
||||
padding: 0px 20px 20px 0;
|
||||
.table-no-data {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
.time-line-header{
|
||||
padding: 20px;
|
||||
font-size: 16px;
|
||||
color: $--color-text-primary;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.scope-icon-box {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: right;
|
||||
}
|
||||
.scope-box {
|
||||
cursor: pointer;
|
||||
color: $--background-color-disabled;
|
||||
.nz-icon {
|
||||
margin-right: 5px;
|
||||
color: $--background-color-disabled ;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
.scope-box.is-select{
|
||||
color: $--color-monitor;
|
||||
.nz-icon {
|
||||
color: $--color-monitor;
|
||||
}
|
||||
}
|
||||
#time-line-scope{
|
||||
//float: right;
|
||||
}
|
||||
}
|
||||
.el-timeline{
|
||||
height: calc(100% - 80px);
|
||||
overflow-y: auto;
|
||||
padding-top: 14px;
|
||||
padding-left: 40px;
|
||||
box-sizing: border-box;
|
||||
.el-timeline-item{
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
.has-time{
|
||||
padding-top: 36px;
|
||||
.el-timeline-item__tail{
|
||||
height: calc(100% + 14px);
|
||||
top: -14px;
|
||||
}
|
||||
}
|
||||
.el-timeline-item.last .el-timeline-item__tail{
|
||||
display: block;
|
||||
top: -100%;
|
||||
}
|
||||
.el-timeline-item:last-child .el-timeline-item__tail.only{
|
||||
display: block;
|
||||
top: -100%;
|
||||
}
|
||||
.el-timeline-item__timestamp.is-top{
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
left: -20px;
|
||||
font-size: 14px;
|
||||
color: $--color-text-regular;
|
||||
font-weight: 600;
|
||||
background: $--background-color-empty;
|
||||
margin: 0;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.el-timeline-item__node {
|
||||
z-index: 1;
|
||||
}
|
||||
.time-line-item-header{
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
.load-more-box{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.table-no-data {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.el-tabs__nav{
|
||||
border: none;
|
||||
}
|
||||
.info-box-header{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.info-box-title{
|
||||
font-size: 16px;
|
||||
color: $--color-text-primary;
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.info-box-content{
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
font-weight: 400;
|
||||
width: 100%;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,5 +104,5 @@
|
||||
.alert-message-state{
|
||||
padding: 3px 5px;
|
||||
border-radius: 4px;
|
||||
color: $--color-text-primary;
|
||||
color: $--color-text-label;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
@import './common/alert/alertLabel.scss';
|
||||
@import './common/alert/alertRuleInfo.scss';
|
||||
@import './common/alert/selectAlertSilence.scss';
|
||||
@import './common/alert/alertMessageInfo.scss';
|
||||
@import './common/alert/alertDaysInfo.scss';
|
||||
@import './common/bottomBox/bottomBox.scss';
|
||||
@import './common/bottomBox/panelTabNew.scss';
|
||||
|
||||
@@ -41,6 +41,8 @@ $--color-text-secondary: #999998;
|
||||
$--color-text-link: #3C92F1;
|
||||
// 禁用字色
|
||||
$--color-text-disabled: #505050;
|
||||
// 标签内白色
|
||||
$--color-text-label: #505050;
|
||||
|
||||
/* 4.边框色 */
|
||||
// 普通边框色
|
||||
|
||||
@@ -41,6 +41,8 @@ $--color-text-secondary: #999998;
|
||||
$--color-text-link: #3C92F1;
|
||||
// 禁用字色
|
||||
$--color-text-disabled: #FFFFFF;
|
||||
// 标签内白色
|
||||
$--color-text-label: #FFFFFF;
|
||||
|
||||
/* 4.边框色 */
|
||||
// 普通边框色(覆盖element-ui内置变量)
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
</span>
|
||||
</el-popover>
|
||||
</span>
|
||||
<div class="chart-header__title" :title="chartInfo.name">{{chartInfo.name}}</div>
|
||||
<div class="chart-header__title" :title="chartInfo.name">
|
||||
<slot name="title-icon"></slot>
|
||||
{{chartInfo.name}}
|
||||
</div>
|
||||
<div class="chart-header__tools">
|
||||
<span v-if="chartInfo.remark" class="chart-header__tool top-tool-btn-group">
|
||||
<el-tooltip :content="chartInfo.remark" effect="light" placement="top">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div :style="showHeader&&chartInfo.param.showHeader ? '' : 'padding-top: 15px;'" class="nz-chart" :class="showHeader&&chartInfo.param.showHeader ? '' : 'no-header'" >
|
||||
<loading :loading="loading"></loading>
|
||||
<chart-no-data v-if="isNoData || isError || chartChildrenData"></chart-no-data>
|
||||
<chart-no-data v-if="isNoData || isError || chartChildrenData"></chart-no-data>
|
||||
<template v-else>
|
||||
<chart-time-series
|
||||
v-if="isTimeSeries(chartInfo.type)"
|
||||
|
||||
@@ -16,6 +16,11 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resize () {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,11 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resize () {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,9 +214,11 @@ export default {
|
||||
})
|
||||
},
|
||||
resize () {
|
||||
this.getLayout().then(layout => {
|
||||
this.renderGauge(layout).then(() => {
|
||||
this.gaugeChartResize()
|
||||
setTimeout(() => {
|
||||
this.getLayout().then(layout => {
|
||||
this.renderGauge(layout).then(() => {
|
||||
this.gaugeChartResize()
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
@@ -54,9 +54,8 @@ export default {
|
||||
setTimeout(() => {
|
||||
this.dataList = this.dataList.map(item => {
|
||||
return {
|
||||
...item,
|
||||
...item
|
||||
// hide: item.name.indexOf(this.filter.searchName) === -1, // 搜索条件
|
||||
loaded: false
|
||||
}
|
||||
})
|
||||
}, 100)
|
||||
@@ -70,9 +69,9 @@ export default {
|
||||
const arr = JSON.parse(JSON.stringify(n))
|
||||
this.dataList = arr.map(item => {
|
||||
return {
|
||||
...item,
|
||||
...item
|
||||
// hide: item.name.indexOf(this.filter.searchName) === -1, // 搜索条件
|
||||
loaded: false
|
||||
// loaded: false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'chartNoData'
|
||||
name: 'chartNoData',
|
||||
methods: {
|
||||
resize () {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -21,6 +21,9 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resize () {
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
chartInfo: {
|
||||
|
||||
@@ -72,6 +72,15 @@ export default {
|
||||
methods: {
|
||||
initChart (chartOptions = this.chartOption) {
|
||||
const chartOption = lodash.cloneDeep(chartOptions)
|
||||
if (this.chartInfo.isAlertMessage) {
|
||||
chartOption.title = {
|
||||
show: true,
|
||||
text: this.$t('project.endpoint.dialogTitle'),
|
||||
top: 20
|
||||
}
|
||||
chartOption.grid.top = 70
|
||||
chartOption.toolbox.top = 20
|
||||
}
|
||||
this.legends = []
|
||||
this.series = chartOption.series = this.handleTimeSeries(this.chartInfo, chartOption.series[0], this.chartData) // 生成series和legends
|
||||
if (!this.series.length) {
|
||||
@@ -89,6 +98,9 @@ export default {
|
||||
chartOption.yAxis.axisLabel.formatter = this.yAxisLabelFormatter(minValue, maxValue, copies, unit, decimals)
|
||||
chartOption.yAxis.minInterval = chartDataFormat.Interval(maxValue, copies, unit.type, 'min')
|
||||
chartOption.yAxis.maxInterval = chartDataFormat.Interval(maxValue, copies, unit.type, 'max') * Math.ceil(chartOption.series.length / 5)
|
||||
if (this.chartInfo.param.stack) {
|
||||
chartOption.yAxis.maxInterval = chartOption.yAxis.maxInterval * (Math.ceil(chartOption.series.length / 5) + 1)
|
||||
}
|
||||
if (unit.type === 'Time') {
|
||||
delete chartOption.yAxis.minInterval
|
||||
delete chartOption.yAxis.maxInterval
|
||||
@@ -127,10 +139,12 @@ export default {
|
||||
})
|
||||
})
|
||||
const timeSorted = datas.sort((a, b) => {
|
||||
return a[0] - b[0]
|
||||
return Number(a[0]) - Number(b[0])
|
||||
})
|
||||
const valueSorted = datas.sort((a, b) => {
|
||||
return a[1] - b[1]
|
||||
const a1 = isNaN(a[1]) && !a[1] ? 0 : Number(a[1])
|
||||
const b1 = isNaN(b[1]) && !b[1] ? 0 : Number(b[1])
|
||||
return a1 - b1
|
||||
})
|
||||
minTime = timeSorted.length ? timeSorted[0][0] : ''
|
||||
maxTime = timeSorted.length ? timeSorted[timeSorted.length - 1][0] : ''
|
||||
@@ -160,7 +174,6 @@ export default {
|
||||
maxValue = Math.floor(oldValue) / Math.pow(10, dot)
|
||||
dot++
|
||||
}
|
||||
console.log(oldValue)
|
||||
const copies = chartDataFormat.copies(Number(oldValue), unit.type)
|
||||
return { minTime, maxTime, minValue, maxValue, copies, unit, dot }
|
||||
},
|
||||
@@ -201,7 +214,11 @@ export default {
|
||||
let sum = 0
|
||||
let flag = true
|
||||
params.forEach((item, i) => {
|
||||
const seriesName = item.seriesName.split('-')[0]
|
||||
const nameArr = item.seriesName.split('-')
|
||||
if (nameArr.length > 1) {
|
||||
nameArr.splice(nameArr.length - 1, 1)
|
||||
}
|
||||
const seriesName = nameArr.join('-')
|
||||
if (i === 0 && item.seriesName.indexOf('Previous') === -1) {
|
||||
const value = bus.computeTimezone(item.data[0] * 1000)
|
||||
const tData = new Date(value)
|
||||
@@ -283,7 +300,7 @@ export default {
|
||||
yAxisLabelFormatter (minValue, maxValue, copies, unit, dot) {
|
||||
const self = this
|
||||
return function (val, index) {
|
||||
const value = formatScientificNotation(val, 2)
|
||||
const value = formatScientificNotation(val, 6)
|
||||
// let chartUnit = self.chartInfo.unit
|
||||
// chartUnit = chartUnit || 2
|
||||
// const unit = chartDataFormat.getUnit(chartUnit)
|
||||
@@ -317,11 +334,18 @@ export default {
|
||||
self.isStack = !self.isStack
|
||||
// 改变tooltip
|
||||
option.tooltip[0].formatter = self.tooltipFormatter(self.isStack)
|
||||
if (!self.chartInfo.param.stack) {
|
||||
option.yAxis.maxInterval = option.yAxis.maxInterval / (Math.ceil(option.series.length / 5) + 1)
|
||||
} else {
|
||||
option.yAxis.maxInterval = option.yAxis.maxInterval * (Math.ceil(option.series.length / 5) + 1)
|
||||
}
|
||||
myChart.setOption(option)
|
||||
}
|
||||
},
|
||||
resize () {
|
||||
getChart(this.chartId).resize()
|
||||
setTimeout(() => {
|
||||
getChart(this.chartId) && getChart(this.chartId).resize()
|
||||
}, 100)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
<div class="legend--table">
|
||||
<div class="legend--table-row table-header">
|
||||
<div class="legend--table-cell"></div>
|
||||
<div v-for="statistics in chartInfo.param.legend.values" :key="statistics" class="legend--table-cell">{{statistics}}</div>
|
||||
<div v-for="statistics in chartInfo.param.legend.values" :key="statistics" class="legend--table-cell">
|
||||
<span v-if="statisticsList.find(key=>key.value === statistics)">{{$t(statisticsList.find(key=>key.value === statistics).label)}}</span>
|
||||
<span v-else>--</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-for="(item, index) in legends"
|
||||
:key="index"
|
||||
@@ -40,6 +43,7 @@
|
||||
import lodash from 'lodash'
|
||||
import { getChart } from '@/components/common/js/common'
|
||||
import chartDataFormat from '@/components/charts/chartDataFormat'
|
||||
import { statisticsList } from '@/components/common/js/constants'
|
||||
export default {
|
||||
name: 'chartLegend',
|
||||
props: {
|
||||
@@ -51,6 +55,7 @@ export default {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
statisticsList,
|
||||
isGrey: [],
|
||||
legendDefaultCount: 20, // 初始显示的legend条数
|
||||
showLegends: [], // 要显示的legend;若legend数量过多,初始时这个数据里只有前20条legend
|
||||
@@ -200,16 +205,6 @@ export default {
|
||||
if (isNaN(result)) {
|
||||
return '--'
|
||||
}
|
||||
// result = Math.round(num * 100) / 100
|
||||
// let decimal = result.toString()
|
||||
// let posDecimal = decimal.indexOf('.')
|
||||
// if (posDecimal < 0) {
|
||||
// posDecimal = decimal.length
|
||||
// decimal += '.'
|
||||
// }
|
||||
// while (decimal.length <= posDecimal + 2) {
|
||||
// decimal += '0'
|
||||
// }
|
||||
result = chartDataFormat.getUnit(this.chartInfo.unit ? this.chartInfo.unit : 2).compute(result, null, -1, 2)
|
||||
return result
|
||||
},
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
<div class="basic-info-table-value" v-if="chartDetail">
|
||||
<i :class="chartDetail.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{chartDetail.alertNum}}</div>
|
||||
@@ -118,7 +118,7 @@
|
||||
<div class="basic-info-table-value" v-if="chartDetail">
|
||||
<i :class="chartDetail.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{chartDetail.alertNum}}</div>
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
:chart-info="item"
|
||||
:from="from"
|
||||
:time-range="timeRange"
|
||||
@groupShow="groupShow"
|
||||
:chart-detail-info="chartDetailInfo"
|
||||
@refreshPanel="refreshPanel"
|
||||
@showFullscreen="showFullscreen"
|
||||
@@ -209,6 +210,8 @@ export default {
|
||||
if (!this.isGroup) {
|
||||
this.moveChart()
|
||||
this.onScroll(this.scrollTop)
|
||||
} else {
|
||||
bus.$emit('groupChildMove')
|
||||
}
|
||||
},
|
||||
containerResizedEvent (i, newH, newW, newHPx, newWPx) {
|
||||
@@ -232,7 +235,7 @@ export default {
|
||||
this.copyDataList = [...this.copyDataList]
|
||||
// this.$refs.layout.layoutUpdate()
|
||||
}
|
||||
this.moveChart()
|
||||
this.onScroll(this.scrollTop)
|
||||
},
|
||||
cleanData () {
|
||||
|
||||
@@ -243,51 +246,46 @@ export default {
|
||||
this.onScroll(this.scrollTop)
|
||||
},
|
||||
moveChart () {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
this.timer = setTimeout(() => {
|
||||
const arr = this.copyDataList.filter(item => !item.staic)
|
||||
const charts = []
|
||||
let weight = 0
|
||||
arr.forEach(item => {
|
||||
charts.push({
|
||||
id: item.id,
|
||||
x: item.x,
|
||||
y: item.y,
|
||||
span: item.span,
|
||||
height: item.height,
|
||||
groupId: item.groupId,
|
||||
weight: weight
|
||||
})
|
||||
weight++
|
||||
if (item.type === 'group') {
|
||||
item.children && item.children.forEach(children => {
|
||||
charts.push({
|
||||
id: children.id,
|
||||
x: children.x,
|
||||
y: children.y,
|
||||
span: children.span,
|
||||
height: children.height,
|
||||
groupId: children.groupId,
|
||||
weight: weight
|
||||
})
|
||||
weight++
|
||||
})
|
||||
}
|
||||
this.onScroll(this.scrollTop)
|
||||
const arr = this.copyDataList.filter(item => !item.staic)
|
||||
const charts = []
|
||||
let weight = 0
|
||||
arr.forEach(item => {
|
||||
charts.push({
|
||||
id: item.id,
|
||||
x: item.x,
|
||||
y: item.y,
|
||||
span: item.span,
|
||||
height: item.height,
|
||||
groupId: item.groupId,
|
||||
weight: weight
|
||||
})
|
||||
const params = {
|
||||
panelId: this.panelId,
|
||||
charts: charts
|
||||
}
|
||||
if (charts && charts.length) {
|
||||
this.$put('/visual/panel/chart/weights', params).then(() => {
|
||||
const position = getLayoutPosition(this.copyDataList)
|
||||
this.$store.commit('setChartLastPosition', position)
|
||||
weight++
|
||||
if (item.type === 'group') {
|
||||
item.children && item.children.forEach(children => {
|
||||
charts.push({
|
||||
id: children.id,
|
||||
x: children.x,
|
||||
y: children.y,
|
||||
span: children.span,
|
||||
height: children.height,
|
||||
groupId: children.groupId,
|
||||
weight: weight
|
||||
})
|
||||
weight++
|
||||
})
|
||||
}
|
||||
}, 1000)
|
||||
})
|
||||
const params = {
|
||||
panelId: this.panelId,
|
||||
charts: charts
|
||||
}
|
||||
if (charts && charts.length) {
|
||||
this.$put('/visual/panel/chart/weights', params).then(() => {
|
||||
const position = getLayoutPosition(this.copyDataList)
|
||||
this.$store.commit('setChartLastPosition', position)
|
||||
})
|
||||
}
|
||||
},
|
||||
onScroll (scrollTop = 0, groupTop = 0) {
|
||||
const self = this
|
||||
@@ -304,8 +302,13 @@ export default {
|
||||
if (dom) {
|
||||
let top = dom.style.top
|
||||
top = Number(top.substring(0, top.length - 2)) + groupTop
|
||||
if (item.type === 'group') {
|
||||
if (item.type === 'group' && item.loaded) {
|
||||
this.$refs['chart' + item.id][0] && this.$refs['chart' + item.id][0].$refs.chart && this.$refs['chart' + item.id][0].$refs.chart.$refs['chart' + item.id] && this.$refs['chart' + item.id][0].$refs.chart.$refs['chart' + item.id].$refs.chartList.onScroll(scrollTop, top)
|
||||
return
|
||||
}
|
||||
if (item.type === 'group' && !item.loaded) {
|
||||
item.loaded = true
|
||||
this.$refs['chart' + item.id][0].getChartData()
|
||||
}
|
||||
if (item.loaded) {
|
||||
return
|
||||
@@ -333,8 +336,77 @@ export default {
|
||||
})
|
||||
}, 200)
|
||||
},
|
||||
resize () {
|
||||
this.init()
|
||||
this.copyDataList.forEach(item => {
|
||||
if (item.type === 'group') {
|
||||
this.$refs['chart' + item.id][0] && this.$refs['chart' + item.id][0].groupShow(item.param.collapse)
|
||||
this.$refs['chart' + item.id][0] && this.$refs['chart' + item.id][0].$refs.chart && this.$refs['chart' + item.id][0].$refs.chart.$refs['chart' + item.id] && this.$refs['chart' + item.id][0].$refs.chart.$refs['chart' + item.id].$refs.chartList.resize()
|
||||
}
|
||||
this.$refs['chart' + item.id][0] && this.$refs['chart' + item.id][0].resize()
|
||||
})
|
||||
},
|
||||
refreshPanel () {
|
||||
bus.$emit('refreshPanel')
|
||||
},
|
||||
createChartSuccess (params) {
|
||||
const arr = this.copyDataList.filter(item => !item.staic)
|
||||
const charts = []
|
||||
let weight = 0
|
||||
arr.forEach(item => {
|
||||
const chart = {
|
||||
id: item.id,
|
||||
x: item.x,
|
||||
y: item.y,
|
||||
span: item.span,
|
||||
height: item.height,
|
||||
groupId: item.groupId,
|
||||
weight: weight
|
||||
}
|
||||
if (!params.groupId && chart.y >= params.y) {
|
||||
chart.y = chart.y + 1
|
||||
}
|
||||
if (params.id == item.id) {
|
||||
chart.y = params.y
|
||||
chart.x = params.x
|
||||
}
|
||||
charts.push(chart)
|
||||
|
||||
weight++
|
||||
if (item.type === 'group') {
|
||||
item.children && item.children.forEach(children => {
|
||||
const childrenChart = {
|
||||
id: children.id,
|
||||
x: children.x,
|
||||
y: children.y,
|
||||
span: children.span,
|
||||
height: children.height,
|
||||
groupId: children.groupId,
|
||||
weight: weight
|
||||
}
|
||||
if (item.id === params.groupId && children.y >= params.y) {
|
||||
childrenChart.y = childrenChart.y + 1
|
||||
}
|
||||
if (params.id == childrenChart.id) {
|
||||
childrenChart.y = params.y
|
||||
childrenChart.x = params.x
|
||||
}
|
||||
charts.push(childrenChart)
|
||||
weight++
|
||||
})
|
||||
}
|
||||
})
|
||||
const chartParams = {
|
||||
panelId: this.panelId,
|
||||
charts: charts
|
||||
}
|
||||
if (charts && charts.length) {
|
||||
this.$put('/visual/panel/chart/weights', chartParams).then(() => {
|
||||
if (params.cb) {
|
||||
params.cb()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
@@ -344,9 +416,15 @@ export default {
|
||||
this.init()
|
||||
if (!this.isGroup) {
|
||||
bus.$on('groupMove', this.changeGroupHeight)
|
||||
bus.$on('creat-chart-success', this.createChartSuccess)
|
||||
bus.$on('groupChildMove', this.moveChart)
|
||||
this.$store.commit('setChartListId', `chartList${this.timestamp}`)
|
||||
window.addEventListener('resize', this.resize)
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('resize', this.resize)
|
||||
},
|
||||
watch: {
|
||||
dataList: {
|
||||
deep: true,
|
||||
@@ -371,6 +449,19 @@ export default {
|
||||
// }
|
||||
height = (item.type === 'group' && item.param.collapse) ? this.headerH : item.height
|
||||
param.showHeader = true
|
||||
if (param.valueMapping) {
|
||||
param.valueMapping.forEach(valueMapping => {
|
||||
if (!valueMapping.show) {
|
||||
valueMapping.show = false
|
||||
}
|
||||
if (valueMapping.text && !valueMapping.display) {
|
||||
valueMapping.display = valueMapping.text
|
||||
}
|
||||
if (valueMapping.columns && !valueMapping.column) {
|
||||
valueMapping.column = valueMapping.columns
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
@@ -397,7 +488,9 @@ export default {
|
||||
this.copyDataList = JSON.parse(JSON.stringify(tempList))
|
||||
setTimeout(() => {
|
||||
this.gridLayoutShow = true
|
||||
this.onScroll()
|
||||
if (!this.isGroup) {
|
||||
this.onScroll()
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.firstInit = false
|
||||
|
||||
@@ -110,16 +110,17 @@ export default {
|
||||
if (data.metric.__name__) {
|
||||
legend += '}'
|
||||
}
|
||||
if (!legend && chartInfo.elements) {
|
||||
legend = chartInfo.elements[expressionIndex].expression
|
||||
}
|
||||
// if (!legend && chartInfo.elements) {
|
||||
// // legend = chartInfo.elements[expressionIndex].expression
|
||||
// legend = ''
|
||||
// }
|
||||
// 处理legend别名
|
||||
alias = alias + this.handleLegendAlias(legend, chartInfo.elements[expressionIndex].legend)
|
||||
if (!alias) {
|
||||
alias = legend
|
||||
alias = chartInfo.elements[expressionIndex].expression
|
||||
}
|
||||
if (alias == 'Previous ') {
|
||||
alias += legend
|
||||
alias += chartInfo.elements[expressionIndex].expression
|
||||
}
|
||||
// proj_status_
|
||||
const name = alias + '-' + dataIndex
|
||||
@@ -146,6 +147,9 @@ export default {
|
||||
if (/\{\{.+\}\}/.test(aliasExpression)) {
|
||||
const labelValue = aliasExpression.replace(/(\{\{.+?\}\})/g, function (i) {
|
||||
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
|
||||
if (!legend) {
|
||||
return label
|
||||
}
|
||||
const reg = new RegExp(label + '=".+?"')
|
||||
let value = null
|
||||
if (reg.test(legend)) {
|
||||
@@ -257,7 +261,9 @@ export default {
|
||||
}
|
||||
},
|
||||
resize () {
|
||||
getChart(this.chartId) && getChart(this.chartId).resize()
|
||||
setTimeout(() => {
|
||||
getChart(this.chartId) && getChart(this.chartId).resize()
|
||||
}, 100)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
@@ -420,7 +420,7 @@ export default {
|
||||
})
|
||||
},
|
||||
resize () {
|
||||
this.$refs.chart.resize()
|
||||
this.$refs.chart && this.$refs.chart.resize()
|
||||
},
|
||||
refresh () {
|
||||
this.getChartData(true)
|
||||
@@ -532,7 +532,7 @@ export default {
|
||||
timeRange: {
|
||||
deep: true,
|
||||
handler (n) {
|
||||
this.refresh()
|
||||
// this.refresh()
|
||||
}
|
||||
},
|
||||
loading: {
|
||||
|
||||
@@ -495,7 +495,7 @@ export default {
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'average': {
|
||||
case 'avg': {
|
||||
result = classifies.map(group => {
|
||||
const groupData = group.map(t => parseFloat(t.data[1]))
|
||||
const sum = eval(groupData.join('+'))
|
||||
|
||||
@@ -34,7 +34,7 @@ function percent02 (value, index) {
|
||||
if (!numberWithEConvent(scientificNotationValue)) {
|
||||
return `${scientificNotationValue} %`
|
||||
}
|
||||
value = parseFloat((Number(value) * 100))
|
||||
value = parseFloat((Number(value) * 100).toFixed(2))
|
||||
return `${value} %`
|
||||
}
|
||||
function localFormat (value, index) {
|
||||
@@ -397,6 +397,9 @@ function asciiCompute2 (num, ascii, units, dot = 2, unitIndex = 0) {
|
||||
* unit:设置的单位
|
||||
* */
|
||||
function timeCompute (value, unit, dot = 0) {
|
||||
if (isNaN(value)) {
|
||||
return `0 ${unit}`
|
||||
}
|
||||
if (unit == 'year') {
|
||||
return `${value.toFixed(dot)} ${unit}`
|
||||
}
|
||||
@@ -725,7 +728,7 @@ export default {
|
||||
pow++
|
||||
value = value * 10
|
||||
}
|
||||
return Math.ceil(value + 1) / Math.pow(10, pow)
|
||||
return Math.floor(value + 1) / Math.pow(10, pow)
|
||||
}
|
||||
if (type === 'Time') {
|
||||
return value
|
||||
|
||||
@@ -1449,7 +1449,7 @@ export default {
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'average': {
|
||||
case 'avg': {
|
||||
result = classifies.map(group => {
|
||||
const groupData = group.map(t => parseFloat(t.data[1]))
|
||||
const sum = eval(groupData.join('+'))
|
||||
|
||||
@@ -99,23 +99,23 @@
|
||||
|
||||
</span>
|
||||
<span class="float-right">
|
||||
<button @click="previewTopology" v-if="!isPreview" class="nz-btn nz-btn-size-normal nz-btn-style-light"
|
||||
<button type="button" @click="previewTopology" v-if="!isPreview" class="nz-btn nz-btn-size-normal nz-btn-style-light"
|
||||
style="margin-right: 20px"
|
||||
>
|
||||
{{$t('project.topology.preview')}}
|
||||
</button>
|
||||
<button v-if="isPreview" class="nz-btn nz-btn-size-normal nz-btn-style-light" @click="previewExit"
|
||||
<button type="button" v-if="isPreview" class="nz-btn nz-btn-size-normal nz-btn-style-light" @click="previewExit"
|
||||
style="margin-right: 20px"
|
||||
>
|
||||
{{$t('project.topology.previewExit')}}
|
||||
</button>
|
||||
<button class="nz-btn nz-btn-size-normal nz-btn-style-normal" @click="saveTopology"
|
||||
<button type="button" class="nz-btn nz-btn-size-normal nz-btn-style-normal" @click="saveTopology"
|
||||
:disabled="prevent_opt.save"
|
||||
:class="{'nz-btn-disabled':prevent_opt.save}"
|
||||
style="margin-right: 20px">
|
||||
{{$t('project.topology.save')}}
|
||||
</button>
|
||||
<button class="nz-btn nz-btn-size-normal nz-btn-style-normal" style="margin-right: 20px" @click="cancelTopology">
|
||||
<button type="button" class="nz-btn nz-btn-size-normal nz-btn-style-normal" style="margin-right: 20px" @click="cancelTopology">
|
||||
{{$t('project.topology.exit')}}
|
||||
</button>
|
||||
</span>
|
||||
@@ -294,11 +294,11 @@
|
||||
</el-row>
|
||||
<div class="upload-pic-row" style="text-align: center">
|
||||
<span>
|
||||
<button class="nz-btn nz-btn-size-normal nz-btn-style-light" style="margin-right: 20px" @click="uploadPicShow=false">
|
||||
<button type="button" class="nz-btn nz-btn-size-normal nz-btn-style-light" style="margin-right: 20px" @click="uploadPicShow=false">
|
||||
{{$t('project.topology.exit')}}
|
||||
</button>
|
||||
|
||||
<button class="nz-btn nz-btn-size-normal nz-btn-style-normal" @click="imgUpload"
|
||||
<button type="button" class="nz-btn nz-btn-size-normal nz-btn-style-normal" @click="imgUpload"
|
||||
v-has="'topo_icon_save'" :disabled="prevent_opt.save"
|
||||
:class="{'nz-btn-disabled':prevent_opt.save}"
|
||||
style="margin-right: 20px">
|
||||
|
||||
@@ -25,7 +25,7 @@ export default {
|
||||
daysData: [],
|
||||
severityData: this.$store.getters.severityData,
|
||||
severityDataWeight: this.$store.getters.severityDataWeight,
|
||||
dateFormatStr: localStorage.getItem('nz-default-dateFormat') ? localStorage.getItem('nz-default-dateFormat') : 'YYYY-MM-DD'
|
||||
dateFormatStr: localStorage.getItem('nz-default-dateFormat') ? localStorage.getItem('nz-default-dateFormat') : 'YYYY-MM-DD HH:ss:mm'
|
||||
}
|
||||
},
|
||||
// watch: {
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
@@ -62,7 +62,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert-label-box">
|
||||
<div class="alert-label-title">Endpoint</div>
|
||||
<div class="alert-label-title">{{$t('asset.endpoint')}}</div>
|
||||
<div class="alert-label-value">
|
||||
<i class="nz-icon nz-icon-overview-endpoint monitorColor"></i>
|
||||
<span>{{alertLabelData && alertLabelData.endpointNum ? alertLabelData.endpointNum : 0}}</span></div>
|
||||
@@ -83,7 +83,7 @@
|
||||
<div class="alert-label-value">{{alertLabelData && alertLabelData.project && alertLabelData.project.name ?alertLabelData.project.name : '--'}}</div>
|
||||
</div>
|
||||
<div class="alert-label-box">
|
||||
<div class="alert-label-title">Endpoint</div>
|
||||
<div class="alert-label-title">{{$t('asset.endpoint')}}</div>
|
||||
<div class="alert-label-value">
|
||||
<i class="nz-icon nz-icon-overview-endpoint monitorColor"></i>
|
||||
<span>{{alertLabelData && alertLabelData.endpointNum ? alertLabelData.endpointNum : 0}}</span></div>
|
||||
@@ -100,7 +100,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
@@ -152,7 +152,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
@@ -202,7 +202,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
@@ -276,7 +276,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
@@ -318,7 +318,8 @@ export default {
|
||||
return {
|
||||
alertLabelData: null,
|
||||
loading: true,
|
||||
heightList: 0
|
||||
heightList: 0,
|
||||
boxWidth: 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -347,29 +348,45 @@ export default {
|
||||
calcPosition () {
|
||||
return function (position) {
|
||||
const clientHeight = (document.body.clientHeight < document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight
|
||||
const leftOffSetView = this.detailList ? -80 : 10
|
||||
const leftOffSet = this.detailList ? -80 : 10
|
||||
const topOffSet = this.detailList ? 60 : 22
|
||||
if (position.top > clientHeight / 2) {
|
||||
return {
|
||||
left: `${position.left + position.width + leftOffSet}px`,
|
||||
top: `${position.top - this.heightList + topOffSet}px`
|
||||
const clientWidth = (document.body.clientWidth < document.documentElement.clientWidth) ? document.body.clientWidth : document.documentElement.clientWidth
|
||||
let leftOffSetView = 0
|
||||
let leftOffSet = this.detailList ? -80 : 10
|
||||
let topOffSet = this.detailList ? 60 : 22
|
||||
let topOffSetView = 0
|
||||
let labelPosition = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
}
|
||||
if (this.alertTableDialog) {
|
||||
let dialog = document.querySelector('#dialog-alert-massage .el-dialog')
|
||||
if (!dialog) {
|
||||
dialog = document.querySelector('#viewGraphDialog .el-dialog')
|
||||
}
|
||||
} else if (this.alertTableDialog) {
|
||||
const dialog = document.querySelector('#dialog-alert-massage .el-dialog')
|
||||
const dialogHeight = dialog.getBoundingClientRect()
|
||||
if (dialogHeight) {
|
||||
return {
|
||||
left: `${position.left + position.width + 10 - dialogHeight.x}px`,
|
||||
top: `${position.top - dialogHeight.y}px`
|
||||
}
|
||||
console.log(dialogHeight, 'dialogHeight')
|
||||
leftOffSet = leftOffSet - dialogHeight.x
|
||||
leftOffSetView = dialogHeight.x
|
||||
topOffSet = topOffSet - dialogHeight.y
|
||||
topOffSetView = topOffSet
|
||||
}
|
||||
if (position.top > clientHeight / 2) {
|
||||
labelPosition = {
|
||||
left: `${position.left + position.width + leftOffSet}px`,
|
||||
top: `${position.top - this.heightList - topOffSetView}px`
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
left: `${position.left + position.width + leftOffSetView}px`,
|
||||
top: `${position.top}px`
|
||||
labelPosition = {
|
||||
left: `${position.left + position.width + leftOffSet}px`,
|
||||
top: `${position.top + topOffSet}px`
|
||||
}
|
||||
}
|
||||
if (position.left > clientWidth / 2) {
|
||||
delete labelPosition.left
|
||||
|
||||
labelPosition.right = (clientWidth - position.left - leftOffSetView) + 'px'
|
||||
}
|
||||
return labelPosition
|
||||
}
|
||||
},
|
||||
calcHeight () {
|
||||
@@ -486,8 +503,10 @@ export default {
|
||||
mounted () {
|
||||
if (this.$refs.alertLabels) {
|
||||
this.heightList = this.$refs.alertLabels.getBoundingClientRect().height
|
||||
this.boxWidth = this.$refs.alertLabels.getBoundingClientRect().width
|
||||
} else {
|
||||
this.heightList = ''
|
||||
this.heightList = 0
|
||||
this.boxWidth = 0
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
@@ -107,7 +107,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
@@ -158,7 +158,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
@@ -208,7 +208,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
@@ -282,7 +282,7 @@
|
||||
<div class="alert-label-value" v-if="alertLabelData">
|
||||
<i :class="alertLabelData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertLabelData.alertNum}}</div>
|
||||
|
||||
353
nezha-fronted/src/components/common/alert/alertMessageInfo.vue
Normal file
353
nezha-fronted/src/components/common/alert/alertMessageInfo.vue
Normal file
@@ -0,0 +1,353 @@
|
||||
<template>
|
||||
<!-- chart外层箱子 -->
|
||||
<div :class="{'panel-chart--fullscreen': isFullscreen}" class="panel-chart" :id="isFullscreen ? ('chart-screen-' + chartInfo.id ) : ('chart-local-' + chartInfo.id)">
|
||||
<!-- 全屏的header-->
|
||||
<chart-screen-header
|
||||
v-if="isFullscreen"
|
||||
:is-group="isGroup(chartInfo.type)"
|
||||
:isError="isError"
|
||||
:from="from"
|
||||
:chartData="chartData"
|
||||
:chart-info="chartInfo"
|
||||
:showAllData.sync="showAllData"
|
||||
:allDataLength="allDataLength"
|
||||
@loadMore="loadMore"
|
||||
@refresh="refresh"
|
||||
@dateChange="dateChange"
|
||||
@close="showFullscreen"
|
||||
class="alert-message-info-header"
|
||||
>
|
||||
<span slot="title-icon" v-if="infoData['state']" style="margin-left: 5px" class="alert-message-state" :class="{'gray-bg': infoData['state'] == 3, 'red-bg': infoData['state'] == 1,'yellow-bg': infoData['state'] == 2}">{{$t(stateOptions.find(state=>state.value == infoData['state']).label)}}</span>
|
||||
</chart-screen-header>
|
||||
<!-- chart -->
|
||||
<!-- 数据查询后传入chart组件,chart组件内不查询,只根据接传递的数据来渲染 -->
|
||||
<div class="alert-message-info-box">
|
||||
<div class="info-box-left">
|
||||
<chart
|
||||
ref="chart"
|
||||
v-if="chartInfo.alertRule && chartInfo.alertRule.type !== 3"
|
||||
:chart-data="chartData"
|
||||
:chart-info="chartInfo"
|
||||
:panelLock="panelLock"
|
||||
:filter="filter"
|
||||
:from="from"
|
||||
@refreshLogs="refreshLogs"
|
||||
:show-header="showHeader"
|
||||
:isError="isError"
|
||||
:loading="loading"
|
||||
:minusTime="minusTime"
|
||||
:multipleTime="multipleTime"
|
||||
:isFullscreen="isFullscreen"
|
||||
:showAllData="showAllData"
|
||||
></chart>
|
||||
<alertMessageInfoTab
|
||||
class="alert-message-info-tab"
|
||||
:noData="tabNoData"
|
||||
:infoData="infoData" />
|
||||
</div>
|
||||
<div class="info-box-right">
|
||||
<alertMessageInfoTimeLine :info-data="chartInfo" :time="time"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ChartScreenHeader from '@/components/chart/ChartScreenHeader'
|
||||
import chart from '@/components/chart/chart'
|
||||
import { isChartPie, isTimeSeries, getGroupHeight, isGroup } from '@/components/chart/chart/tools'
|
||||
import {alertMessage as alertMessageConstant, chartType, fromRoute} from '@/components/common/js/constants'
|
||||
import bus from '@/libs/bus'
|
||||
import axios from 'axios'
|
||||
import chartTempData from '@/components/charts/chartTempData'
|
||||
import logsData from '@/components/chart/logsData'
|
||||
import lodash from 'lodash'
|
||||
import alertMessageInfoTab from '@/components/common/alert/alertMessageInfoTab'
|
||||
import alertMessageInfoTimeLine from '@/components/common/alert/alertMessageInfoTimeLine'
|
||||
export default {
|
||||
name: 'panelChart',
|
||||
components: {
|
||||
alertMessageInfoTab,
|
||||
chart,
|
||||
ChartScreenHeader,
|
||||
alertMessageInfoTimeLine
|
||||
},
|
||||
props: {
|
||||
chartInfo: Object, // 其中的param json串已转化为对象
|
||||
timeRange: Array, // 时间范围
|
||||
isFullscreen: Boolean,
|
||||
panelLock: Boolean,
|
||||
chartDetailInfo: Object,
|
||||
from: String,
|
||||
filter: {},
|
||||
showHeader: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
chartData: [],
|
||||
loading: true,
|
||||
isError: false,
|
||||
multipleTime: false,
|
||||
minusTime: '',
|
||||
showAllData: false,
|
||||
allDataLength: 0,
|
||||
severityData: this.$store.getters.severityData,
|
||||
severityDataWeight: this.$store.getters.severityDataWeight,
|
||||
infoData: {},
|
||||
timeLineData: [],
|
||||
tabNoData: false,
|
||||
timeLineNoData: false,
|
||||
time: [],
|
||||
stateOptions: alertMessageConstant.states
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
headerH () {
|
||||
return this.$store.getters.getHeaderH
|
||||
},
|
||||
headerHPadding () {
|
||||
return this.$store.getters.getHeaderHPadding
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isGroup,
|
||||
dateChange (filter, multipleTime) {
|
||||
this.loading = true
|
||||
// TODO assetInfo、endpointInfo、echarts等进行不同的处理
|
||||
let startTime = bus.formateTimeToTime(filter.start_time)
|
||||
let endTime = bus.formateTimeToTime(filter.end_time)
|
||||
const step = bus.getStep(startTime, endTime)
|
||||
startTime = this.$stringTimeParseToUnix(startTime)
|
||||
endTime = this.$stringTimeParseToUnix(endTime)
|
||||
const elements = this.chartInfo.elements || []
|
||||
if (multipleTime.length) {
|
||||
const minusTime = (new Date(bus.formateTimeToTime(filter.start_time)).getTime() - new Date(bus.formateTimeToTime(multipleTime[0])).getTime())
|
||||
this.minusTime = minusTime
|
||||
this.multipleTime = true
|
||||
} else {
|
||||
this.minusTime = ''
|
||||
this.multipleTime = false
|
||||
}
|
||||
this.time = [startTime, endTime]
|
||||
this.chartInfo.loaded && this.chartInfo.alertRule && this.chartInfo.alertRule.type !== 3 && this.query(elements, startTime, endTime, step)
|
||||
},
|
||||
// 参数 isRefresh 标识是否是刷新操作
|
||||
getChartData (isRefresh, params) {
|
||||
this.loading = true
|
||||
// TODO assetInfo、endpointInfo、echarts等进行不同的处理
|
||||
let startTime = ''
|
||||
let endTime = ''
|
||||
if (isRefresh) { // 刷新则视情况更新时间范围
|
||||
const now = new Date(bus.computeTimezone(new Date().getTime()))
|
||||
const origin = new Date(this.timeRange[1])
|
||||
const numInterval = now.getTime() - origin.getTime()
|
||||
if (numInterval >= 60000) { // 大于1分钟,则start、end均往后移numInterval,否则时间不变
|
||||
startTime = bus.getNewTime(bus.formateTimeToTime(this.timeRange[0]), numInterval)
|
||||
endTime = bus.timeFormate(now, 'YYYY-MM-DD HH:mm:ss')
|
||||
} else {
|
||||
startTime = bus.formateTimeToTime(this.timeRange[0])
|
||||
endTime = bus.formateTimeToTime(this.timeRange[1])
|
||||
}
|
||||
} else {
|
||||
startTime = bus.formateTimeToTime(this.timeRange[0])
|
||||
endTime = bus.formateTimeToTime(this.timeRange[1])
|
||||
}
|
||||
const step = bus.getStep(startTime, endTime)
|
||||
startTime = this.$stringTimeParseToUnix(startTime)
|
||||
endTime = this.$stringTimeParseToUnix(endTime)
|
||||
this.time = [startTime, endTime]
|
||||
const elements = this.chartInfo.elements || []
|
||||
this.chartInfo.loaded && this.query(elements, startTime, endTime, step, params)
|
||||
},
|
||||
query (elements, startTime, endTime, step, params) {
|
||||
this.isError = false
|
||||
this.allDataLength = 0
|
||||
try {
|
||||
switch (this.chartInfo.datasource) {
|
||||
case 'metrics':
|
||||
case 'logs': {
|
||||
if (this.from === fromRoute.chartTemp) {
|
||||
setTimeout(() => {
|
||||
this.chartData = [chartTempData.data.result]
|
||||
this.chartData.forEach(item => {
|
||||
item.forEach(children => {
|
||||
children.elements = elements[0]
|
||||
})
|
||||
})
|
||||
this.loading = false
|
||||
}, 100)
|
||||
return
|
||||
}
|
||||
let urlPre = ''
|
||||
if (this.chartInfo.datasource === 'metrics') {
|
||||
urlPre += '/prom'
|
||||
} else if (this.chartInfo.datasource === 'logs') {
|
||||
urlPre += '/logs/loki'
|
||||
}
|
||||
let requests = elements.map((element) => {
|
||||
if (this.from === fromRoute.chartTemp) {
|
||||
return chartTempData
|
||||
}
|
||||
let query = `${urlPre}/api/v1/query_range?start=${startTime}&end=${endTime}&step=${step}`
|
||||
if (isTimeSeries(this.chartInfo.type)) {
|
||||
query += `&nullType=${this.chartInfo.param.nullType || 'null'}`
|
||||
}
|
||||
if (element.filter) {
|
||||
query += `&filter=${element.filter}`
|
||||
}
|
||||
if (this.chartInfo.datasource === 'logs') {
|
||||
query += '&format=1'
|
||||
if (!params || params.descending) {
|
||||
this.chartInfo.descending = true
|
||||
query += '&direction=backward'
|
||||
} else {
|
||||
this.chartInfo.descending = false
|
||||
query += '&direction=forward'
|
||||
}
|
||||
}
|
||||
// if (isChartPie(this.chartInfo.type)) {
|
||||
// query += `&statistics=${this.chartInfo.param.statistics || 'last'}`
|
||||
// }
|
||||
query += `&query=${encodeURIComponent(element.expression)}`
|
||||
return this.$get(query)
|
||||
})
|
||||
if (this.multipleTime) {
|
||||
const multipleRequests = elements.map((element) => {
|
||||
if (this.from === fromRoute.chartTemp) {
|
||||
return chartTempData
|
||||
}
|
||||
let query = `${urlPre}/api/v1/query_range?start=${startTime - this.minusTime / 1000}&end=${endTime - this.minusTime / 1000}&step=${step}`
|
||||
if (isTimeSeries(this.chartInfo.type)) {
|
||||
query += `&nullType=${this.chartInfo.param.nullType || 'null'}`
|
||||
}
|
||||
if (element.filter) {
|
||||
query += `&filter=${element.filter}`
|
||||
}
|
||||
if (this.chartInfo.datasource === 'logs') {
|
||||
query += '&format=1'
|
||||
}
|
||||
// if (isChartPie(this.chartInfo.type)) {
|
||||
// query += `&statistics=${this.chartInfo.param.statistics || 'last'}`
|
||||
// }
|
||||
query += `&query=${encodeURIComponent(element.expression)}`
|
||||
return this.$get(query)
|
||||
})
|
||||
requests = requests.concat(multipleRequests)
|
||||
}
|
||||
const chartData = []
|
||||
axios.all(requests).then((res) => {
|
||||
res.forEach((r, rIndex) => {
|
||||
if (rIndex < elements.length) {
|
||||
if (r.status === 'success') {
|
||||
r.data.result.forEach(item => {
|
||||
item.elements = elements[rIndex]
|
||||
this.allDataLength++
|
||||
})
|
||||
chartData.push(r.data.result)
|
||||
} else {
|
||||
chartData.push({ error: r.msg || r.error || r })
|
||||
this.isError = true
|
||||
}
|
||||
} else {
|
||||
if (r.status === 'success') {
|
||||
r.data.result.forEach(item => {
|
||||
this.allDataLength++
|
||||
item.values.forEach(values => {
|
||||
values[0] = values[0] + this.minusTime / 1000
|
||||
})
|
||||
})
|
||||
chartData.push(r.data.result)
|
||||
} else {
|
||||
chartData.push({ error: r.msg || r.error || r })
|
||||
this.isError = true
|
||||
}
|
||||
}
|
||||
})
|
||||
this.chartData = chartData
|
||||
if (this.chartInfo.type === 'log') {
|
||||
this.logChartDataFormat()
|
||||
}
|
||||
}).catch(res => {
|
||||
console.info(res)
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
resize () {
|
||||
this.$refs.chart.resize()
|
||||
},
|
||||
refresh () {
|
||||
this.getChartData(true)
|
||||
},
|
||||
refreshLogs (params) {
|
||||
this.getChartData(true, params)
|
||||
},
|
||||
logChartDataFormat () {
|
||||
this.chartData.forEach((item, index) => {
|
||||
const elements = this.chartInfo.elements[index]
|
||||
item.forEach(row => {
|
||||
row.elements = elements
|
||||
})
|
||||
})
|
||||
},
|
||||
showMultiple (type) {
|
||||
switch (type) {
|
||||
case 'line' :
|
||||
case 'area' :
|
||||
case 'point' :
|
||||
return true
|
||||
default: return false
|
||||
}
|
||||
},
|
||||
loadMore () {
|
||||
this.showAllData = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.chart && this.$refs.chart.$refs['chart' + this.chartInfo.id].initChart()
|
||||
})
|
||||
},
|
||||
showFullscreen (show) {
|
||||
this.$emit('showFullscreen', show, this.chartInfo)
|
||||
},
|
||||
getAlertMessageInfo () {
|
||||
this.tabNoData = false
|
||||
this.$get('/alert/message/' + this.chartInfo.id).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.infoData = res.data
|
||||
this.tabNoData = false
|
||||
} else {
|
||||
this.tabNoData = true
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
timeRange: {
|
||||
deep: true,
|
||||
handler (n) {
|
||||
this.refresh()
|
||||
}
|
||||
},
|
||||
loading: {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
handler (n) {
|
||||
// console.log(n)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.chartInfo.loaded && this.getChartData()
|
||||
this.showAllData = !this.showMultiple(this.chartInfo.type)
|
||||
this.getAlertMessageInfo()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div class="info-box-header">
|
||||
<div v-for="item in cardNames" :key="item.key" v-if="infoData[item.key]">
|
||||
<div class="info-box-title">{{item.label}}</div>
|
||||
<div v-if="item.key === 'summary' || item.key === 'description'" class="info-box-content">
|
||||
{{infoData[item.key]}}
|
||||
</div>
|
||||
<div v-if="item.key==='labels'" class="info-box-content">
|
||||
<span v-for="(item, i) in labelsSort(infoData.labels)" :key="i">
|
||||
<span
|
||||
@mouseenter="labelHover(infoData, item.label, true, true, $event)"
|
||||
@mouseleave="labelHover(infoData, item.label, false, true,)">
|
||||
<nz-alert-tag
|
||||
v-if="item.label !== 'alertname' && item.label !== 'severity'" :key="item.label" :cursor-point="tagType(item.label) !== 'info'"
|
||||
:label="item.label"
|
||||
:type="tagType(item.label)"
|
||||
style="margin: 5px 0 5px 5px;"
|
||||
>
|
||||
{{item.value}}
|
||||
</nz-alert-tag>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="item.key==='startAt'" class="info-box-content">
|
||||
{{utcTimeToTimezoneStr(infoData[item.key])}}
|
||||
</div>
|
||||
</div>
|
||||
<alertLabel
|
||||
v-if="alertLabelShow"
|
||||
:id="alertLabelId"
|
||||
:that="alertLabelObj"
|
||||
:type="alertLabelType"
|
||||
></alertLabel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import alertMessageLabelMixin from '@/components/common/alert/alertMessageLabelMixin'
|
||||
import alertLabelMixin from '@/components/common/mixin/alertLabelMixin'
|
||||
export default {
|
||||
name: 'alertMessageInfoDetail',
|
||||
props: {
|
||||
infoData: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
mixins: [alertMessageLabelMixin, alertLabelMixin],
|
||||
data () {
|
||||
return {
|
||||
cardNames: [
|
||||
{ key: 'summary', label: this.$t('alert.summary') },
|
||||
{ key: 'description', label: this.$t('overall.remark') },
|
||||
{ key: 'labels', label: this.$t('alert.list.labels') },
|
||||
{ key: 'startAt', label: this.$t('alert.startAt') }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-tabs v-model="activeName" type="card" v-if="!nodata">
|
||||
<el-tab-pane v-for="item in cardNames" :label="item.label" :name="item.key" :key="item.key">
|
||||
<div v-if="item.key === 'detail' && activeName === 'detail'">
|
||||
<alert-message-info-detail :info-data="infoData"/>
|
||||
</div>
|
||||
<div v-else-if="(activeName === item.key) && infoData[item.key]" class="no-position-alert-label">
|
||||
<!-- <searchItemInfo :obj="findData(item.key)" :severityData="severityData" :fa-loading="false"></searchItemInfo>-->
|
||||
<alertLabel
|
||||
v-if="item.key !=='alertRule'"
|
||||
:id="infoData[item.key].id"
|
||||
:that="findData2(item.key)"
|
||||
:alertTableDialog="true"
|
||||
:type="item.key"/>
|
||||
<alertRuleInfo
|
||||
v-else
|
||||
:id="infoData[item.key].id"
|
||||
:severity-data="severityData"
|
||||
:that="findData2(item.key)"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="item.key === 'trbShot' && activeName === 'trbShot'">
|
||||
<div v-html="infoData.alertRule.trbShot">
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div v-else class="table-no-data">
|
||||
<svg class="icon" aria-hidden="true">
|
||||
<use xlink:href="#nz-icon-no-data-list"></use>
|
||||
</svg>
|
||||
<div class="table-no-data__title">No results found</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import alertMessageInfoDetail from '@/components/common/alert/alertMessageInfoDetail'
|
||||
import searchItemInfo from '@/components/common/globalSearch/searchItemInfo'
|
||||
import alertLabel from '@/components/common/alert/alertLabel'
|
||||
import alertRuleInfo from '@/components/common/alert/alertRuleInfo'
|
||||
// import alertLabelMixin from '@/components/common/mixin/alertLabelMixin'
|
||||
export default {
|
||||
name: 'alertMessageInfoTab',
|
||||
components: {
|
||||
alertMessageInfoDetail,
|
||||
searchItemInfo,
|
||||
alertLabel,
|
||||
alertRuleInfo
|
||||
},
|
||||
// mixins: [alertLabelMixin],
|
||||
props: {
|
||||
infoData: {
|
||||
type: Object
|
||||
},
|
||||
nodata: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
severityData () {
|
||||
return this.$store.getters.severityData
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activeName: 'detail',
|
||||
cardNames: [{
|
||||
key: 'detail',
|
||||
label: this.$t('overall.detail')
|
||||
}],
|
||||
sysArr: [{
|
||||
key: 'alertRule',
|
||||
label: this.$t('alert.alertRule')
|
||||
}, {
|
||||
key: 'dc',
|
||||
label: this.$t('overall.dc')
|
||||
}, {
|
||||
key: 'asset',
|
||||
label: this.$t('overall.asset')
|
||||
}, {
|
||||
key: 'endpoint',
|
||||
label: this.$t('overall.endpoint')
|
||||
}, {
|
||||
key: 'module',
|
||||
label: this.$t('overall.module')
|
||||
}, {
|
||||
key: 'project',
|
||||
label: this.$t('overall.project')
|
||||
}]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
infoData: {
|
||||
immediate: true,
|
||||
handler (n) {
|
||||
if (n) {
|
||||
this.cardNames = [{
|
||||
key: 'detail',
|
||||
label: this.$t('overall.detail')
|
||||
}]
|
||||
this.sysArr.forEach(item => {
|
||||
if (n[item.key]) {
|
||||
this.cardNames.push(item)
|
||||
}
|
||||
})
|
||||
if (n.alertRule && n.alertRule.trbShot) {
|
||||
this.cardNames.push({
|
||||
key: 'trbShot',
|
||||
label: this.$t('alert.config.trbShot')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
},
|
||||
methods: {
|
||||
findData (key) {
|
||||
if (key) {
|
||||
const obj = {
|
||||
...this.$loadsh.cloneDeep(this.infoData[key]),
|
||||
type: key
|
||||
}
|
||||
if (key === 'dc') {
|
||||
obj.type = 'datacenter'
|
||||
} else if (key === 'alertRule') {
|
||||
obj.type = 'alertrule'
|
||||
}
|
||||
return { ...obj }
|
||||
}
|
||||
},
|
||||
findData2 (key) {
|
||||
if (key) {
|
||||
const obj = {
|
||||
...this.$loadsh.cloneDeep(this.infoData[key]),
|
||||
type: key,
|
||||
position: {
|
||||
top: 0,
|
||||
left: 0
|
||||
}
|
||||
}
|
||||
return { ...obj }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,242 @@
|
||||
<template>
|
||||
<div style="height: 100%;width: 100%">
|
||||
<div class="time-line-header">
|
||||
<span>{{$t('alert.relatedAlerts')}}</span>
|
||||
<div class="scope-icon-box">
|
||||
<div class="scope-box" v-for="item in scopeList" :class="item.isSelect ? 'is-select' : ''" :key="item.type" @click="scopeChange(item)" :title="item.label">
|
||||
<i class="nz-icon" :class="selectIcon(item)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-timeline v-my-loading="loading" v-if="!noData && timeLineData.length">
|
||||
<el-timeline-item
|
||||
v-for="(item,index) in timeLineData"
|
||||
:key="item.id"
|
||||
:class="{
|
||||
'only': timeLineData.length === 1 ,
|
||||
'has-time': item.startAt,
|
||||
'last': index === timeLineData.length-1 && index !==0
|
||||
}"
|
||||
:color="item.severity.color"
|
||||
:timestamp="item.startAt?item.startAt: ''"
|
||||
placement="top">
|
||||
<div >
|
||||
<div class='margin-b-10'>
|
||||
<span slot="title-icon" v-if="item['state']" style="margin-left: 5px" class="alert-message-state" :class="{'gray-bg': item['state'] == 3, 'red-bg': item['state'] == 1,'yellow-bg': item['state'] == 2}">{{$t(stateOptions.find(state=>state.value == item['state']).label)}}</span>
|
||||
<span class="time-line-item-header"> {{item.alertRule.name}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span v-for="(label, i) in labelsSort(JSON.parse(item.labels))" :key="i">
|
||||
<span
|
||||
@mouseenter="labelHover(item, label.label, true, true, $event)"
|
||||
@mouseleave="labelHover(item, label.label, false, true,)">
|
||||
<nz-alert-tag
|
||||
v-if="label.label !== 'alertname' && label.label !== 'severity'" :key="label.label" :cursor-point="tagType(label.label) !== 'info'"
|
||||
:label="label.label"
|
||||
:type="tagType(label.label)"
|
||||
style="margin: 5px 0 5px 5px;"
|
||||
>
|
||||
{{label.value}}
|
||||
</nz-alert-tag>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
<div v-if="timeLineData.length >= total" style="text-align: center">{{$t('overall.noMoreData')}}</div>
|
||||
<div v-else class="load-more-box">
|
||||
<el-button size="small" @click="getTimeLineData()" :loading="loading">{{$t('overall.loadMore')}}</el-button>
|
||||
</div>
|
||||
</el-timeline>
|
||||
<div class="table-no-data" v-else>
|
||||
<svg class="icon" aria-hidden="true">
|
||||
<use xlink:href="#nz-icon-no-data-list"></use>
|
||||
</svg>
|
||||
<div class="table-no-data__title">No results found</div>
|
||||
</div>
|
||||
<alertLabel
|
||||
v-if="alertLabelShow"
|
||||
:alertTableDialog="true"
|
||||
:id="alertLabelId"
|
||||
:that="alertLabelObj"
|
||||
:type="alertLabelType"
|
||||
></alertLabel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { alertMessage as alertMessageConstant } from '@/components/common/js/constants'
|
||||
import alertMessageLabelMixin from '@/components/common/alert/alertMessageLabelMixin'
|
||||
import alertLabelMixin from '@/components/common/mixin/alertLabelMixin'
|
||||
|
||||
export default {
|
||||
name: 'alertMessageInfoTimeLine',
|
||||
props: {
|
||||
infoData: {
|
||||
type: Object
|
||||
},
|
||||
time: {}
|
||||
},
|
||||
mixins: [alertMessageLabelMixin, alertLabelMixin],
|
||||
computed: {
|
||||
severityData () {
|
||||
return this.$store.getters.severityData
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
time: {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
handler (n) {
|
||||
if (n && n.length) {
|
||||
this.pageNo = 1
|
||||
this.getTimeLineData()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
pageNo: 1,
|
||||
pageSize: 20,
|
||||
scope: ['asset', 'datacenter', 'project', 'module', 'endpoint', 'alertrule', 'hash'],
|
||||
timeLineData: [],
|
||||
lastDataTime: '',
|
||||
loading: false,
|
||||
dateFormatStr: localStorage.getItem('nz-default-dateFormat') ? localStorage.getItem('nz-default-dateFormat') : 'YYYY-MM-DD HH:ss:mm',
|
||||
noData: false,
|
||||
stateOptions: alertMessageConstant.states,
|
||||
scopeList: [{
|
||||
key: 'asset',
|
||||
isSelect: true,
|
||||
label: this.$t('overall.asset')
|
||||
}, {
|
||||
key: 'datacenter',
|
||||
isSelect: true,
|
||||
label: this.$t('overall.dc')
|
||||
}, {
|
||||
key: 'project',
|
||||
isSelect: true,
|
||||
label: this.$t('overall.project')
|
||||
}, {
|
||||
key: 'module',
|
||||
isSelect: true,
|
||||
label: this.$t('overall.module')
|
||||
}, {
|
||||
key: 'endpoint',
|
||||
isSelect: true,
|
||||
label: this.$t('overall.endpoint')
|
||||
},
|
||||
{
|
||||
key: 'alertrule',
|
||||
isSelect: true,
|
||||
label: this.$t('alert.alertRule')
|
||||
}, {
|
||||
key: 'hash',
|
||||
isSelect: true,
|
||||
label: this.$t('overall.hash')
|
||||
}
|
||||
],
|
||||
total: 20,
|
||||
scopeChangeTimer: null
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// this.getTimeLineData(1)
|
||||
const dateFormatStr = localStorage.getItem('nz-default-dateFormat')
|
||||
if (dateFormatStr) {
|
||||
this.dateFormatStr = dateFormatStr.split(' ')[0]
|
||||
} else {
|
||||
this.dateFormatStr = 'YYYY-MM-DD'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getTimeLineData () {
|
||||
this.noData = false
|
||||
this.loading = true
|
||||
const params = {
|
||||
pageNo: this.pageNo,
|
||||
pageSize: this.pageSize,
|
||||
scope: this.scopeList.filter(item => item.isSelect).map(item => item.key).join(','),
|
||||
id: this.infoData.id,
|
||||
state: '',
|
||||
startAt: this.timezoneToUtcTimeStr(this.time[0] * 1000, 'YYYY-MM-DD HH:mm:ss'),
|
||||
endAt: this.timezoneToUtcTimeStr(this.time[1] * 1000, 'YYYY-MM-DD HH:mm:ss'),
|
||||
orderBy: '-startAt'
|
||||
}
|
||||
this.$get('/alert/message/rel', params).then(res => {
|
||||
this.loading = false
|
||||
if (res.code === 200) {
|
||||
this.total = res.data.total
|
||||
if (this.pageNo == 1) {
|
||||
this.timeLineData = res.data.list
|
||||
} else {
|
||||
this.timeLineData.push(...res.data.list)
|
||||
}
|
||||
this.disposeTime(this.pageNo)
|
||||
this.noData = false
|
||||
this.pageNo++
|
||||
} else {
|
||||
this.noData = true
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.noData = true
|
||||
})
|
||||
},
|
||||
disposeTime (pageNo) {
|
||||
let i = (pageNo - 1) * this.pageSize
|
||||
for (i; i < this.timeLineData.length; i++) {
|
||||
const lastDataTime = this.timestampStr(this.timeLineData[i].startAt, this.dateFormatStr)
|
||||
this.timeLineData[i].color = '#fa8'
|
||||
if (this.lastDataTime !== lastDataTime) {
|
||||
this.lastDataTime = lastDataTime
|
||||
this.timeLineData[i].startAt = lastDataTime
|
||||
} else {
|
||||
this.timeLineData[i].startAt = ''
|
||||
}
|
||||
}
|
||||
},
|
||||
selectIcon (item) {
|
||||
switch (item.key) {
|
||||
case 'asset' : return 'nz-icon-overview-project'
|
||||
case 'datacenter' : return 'nz-icon-Datacenter2'
|
||||
case 'project' : return 'nz-icon-project'
|
||||
case 'module' : return 'nz-icon-overview-module'
|
||||
case 'endpoint' : return 'nz-icon-overview-endpoint'
|
||||
case 'alertrule' : return 'nz-icon-Alertrule'
|
||||
case 'hash' : return 'nz-icon-module5'
|
||||
}
|
||||
return 'nz-icon-module5'
|
||||
},
|
||||
scopeChange (scope) {
|
||||
if (this.scopeChangeTimer) {
|
||||
clearInterval(this.scopeChangeTimer)
|
||||
this.scopeChangeTimer = null
|
||||
}
|
||||
this.loading = true
|
||||
const isSelectArr = this.scopeList.filter(item => item.isSelect)
|
||||
if (isSelectArr.length === this.scopeList.length) {
|
||||
this.scopeList.forEach(item => {
|
||||
item.isSelect = false
|
||||
})
|
||||
scope.isSelect = !scope.isSelect
|
||||
} else if (isSelectArr.length === 1 && isSelectArr[0].key === scope.key) {
|
||||
this.scopeList.forEach(item => {
|
||||
item.isSelect = true
|
||||
})
|
||||
} else {
|
||||
scope.isSelect = !scope.isSelect
|
||||
}
|
||||
this.scopeChangeTimer = setTimeout(() => {
|
||||
this.pageNo = 1
|
||||
this.getTimeLineData()
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,67 @@
|
||||
import nzAlertTag from '@/components/page/alert/nzAlertTag'
|
||||
export default {
|
||||
components: {
|
||||
nzAlertTag
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
exclusiveLabels: ['_id', 'severity', '__name__']
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tagType () {
|
||||
return (key) => {
|
||||
if (key == 'asset' || key == 'module' || key == 'project' || key == 'dc' || key == 'endpoint') {
|
||||
return 'normal'
|
||||
} else {
|
||||
return 'info'
|
||||
}
|
||||
}
|
||||
},
|
||||
tagValue () {
|
||||
return (key, value) => {
|
||||
if (key == 'type') {
|
||||
if (value == 1) {
|
||||
value = this.$t('project.project.projectName')
|
||||
} else if (value == 2) {
|
||||
value = this.$t('module.module.module')
|
||||
} else if (value == 3) {
|
||||
value = this.$t('asset.asset')
|
||||
}
|
||||
}
|
||||
return key + ':' + value
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
labelsSort (obj) {
|
||||
const buildIn = ['asset', 'endpoint', 'module', 'cpu', 'datacenter', 'project', 'parent_asset', 'user']
|
||||
if (typeof obj === 'string') obj = JSON.parse(obj)
|
||||
const labels = JSON.parse(JSON.stringify(obj))
|
||||
const result = []
|
||||
for (const key of this.exclusiveLabels) {
|
||||
Object.keys(labels).forEach(labelsKey => {
|
||||
if (labelsKey.indexOf(key) !== -1) {
|
||||
delete labels[labelsKey]
|
||||
}
|
||||
})
|
||||
}
|
||||
for (const key of buildIn) {
|
||||
if (key in labels) {
|
||||
if (key === 'datacenter') {
|
||||
result.push({ label: 'dc', value: labels.datacenter })
|
||||
delete labels.datacenter
|
||||
} else {
|
||||
result.push({ label: key, value: labels[key] })
|
||||
}
|
||||
delete labels[key]
|
||||
}
|
||||
}
|
||||
Object.keys(labels).sort().forEach(key => {
|
||||
result.push({ label: key, value: labels[key] })
|
||||
delete labels[key]
|
||||
})
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@
|
||||
<div class="alert-rule-value" v-if="alertRuleData">
|
||||
<i :class="alertRuleData.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{alertRuleData.alertNum}}</div>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
fullscreen
|
||||
:modal-append-to-body="false"
|
||||
>
|
||||
<panel-chart
|
||||
<alertMessageInfo
|
||||
:ref="'chart-fullscreen' + chartInfo.id"
|
||||
:chart-info="chartInfo"
|
||||
:from="fromRoute.alertMessage"
|
||||
@@ -98,7 +98,7 @@
|
||||
:is-fullscreen="true"
|
||||
:time-range="searchTime"
|
||||
@showFullscreen="showFullscreen"
|
||||
></panel-chart>
|
||||
></alertMessageInfo>
|
||||
</el-dialog>
|
||||
<el-dialog class="nz-dialog table-chart-dialog" :title="$t('alert.config.trbShot')"
|
||||
:visible.sync="dialogShowText"
|
||||
@@ -131,6 +131,7 @@ import chart from '@/components/page/dashboard/overview/chart'
|
||||
import { alertMessage as alertMessageConstant, fromRoute } from '@/components/common/js/constants'
|
||||
import alertSilenceBox from '@/components/common/rightBox/alertSilenceBox'
|
||||
import detailViewRightMixin from '@/components/common/mixin/detailViewRightMixin'
|
||||
import alertMessageInfo from '@/components/common/alert/alertMessageInfo'
|
||||
import panelChart from '@/components/chart/panelChart'
|
||||
import lodash from 'lodash'
|
||||
import lineData from '@/components/chart/defaultLineData'
|
||||
@@ -144,7 +145,8 @@ export default {
|
||||
alertMessageTable,
|
||||
alertSilenceBox,
|
||||
chart,
|
||||
panelChart
|
||||
panelChart,
|
||||
alertMessageInfo
|
||||
},
|
||||
props: {
|
||||
from: String
|
||||
@@ -426,9 +428,6 @@ export default {
|
||||
this.deleteBox.show = true
|
||||
},
|
||||
messageDetail (row) {
|
||||
if (row.alertRule.type == 3) {
|
||||
return
|
||||
}
|
||||
this.$get('/alert/rule/' + row.alertRule.id).then(res => {
|
||||
this.currentMsg = { ...row, alertRule: { ...res.data } }
|
||||
this.$nextTick(() => {
|
||||
@@ -635,8 +634,9 @@ export default {
|
||||
},
|
||||
queryDate () {
|
||||
this.chartLoading = true
|
||||
if (this.currentMsg.alertRule.type === 1) {
|
||||
const chartInfo = lodash.cloneDeep(lineData)
|
||||
let chartInfo = {}
|
||||
if (this.currentMsg.alertRule.type === 1 || this.currentMsg.alertRule.type === 3) {
|
||||
chartInfo = lodash.cloneDeep(lineData)
|
||||
chartInfo.elements = [{}]
|
||||
if (!isNaN(this.currentMsg.alertRule.threshold)) {
|
||||
chartInfo.param.enable.thresholds = true
|
||||
@@ -645,12 +645,9 @@ export default {
|
||||
color: '#d64f40'
|
||||
}]
|
||||
}
|
||||
chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, '')
|
||||
chartInfo.elements[0].filter = encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))
|
||||
chartInfo.unit = this.currentMsg.alertRule.unit
|
||||
this.showFullscreen(true, chartInfo)
|
||||
chartInfo.elements && (chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, ''))
|
||||
} else if (this.currentMsg.alertRule.type === 2) {
|
||||
const chartInfo = lodash.cloneDeep(logData)
|
||||
chartInfo = lodash.cloneDeep(logData)
|
||||
chartInfo.elements = [{}]
|
||||
if (!isNaN(this.currentMsg.alertRule.threshold)) {
|
||||
chartInfo.param.enable.thresholds = true
|
||||
@@ -659,11 +656,15 @@ export default {
|
||||
color: '#d64f40'
|
||||
}]
|
||||
}
|
||||
chartInfo.elements[0].expression = encodeURIComponent(this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, ''))
|
||||
chartInfo.elements[0].filter = encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))
|
||||
chartInfo.unit = this.currentMsg.alertRule.unit
|
||||
this.showFullscreen(true, chartInfo)
|
||||
chartInfo.elements && (chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\r|\n+/g, ''))
|
||||
}
|
||||
chartInfo.id = this.currentMsg.id
|
||||
chartInfo.name = this.currentMsg.alertRule.name
|
||||
chartInfo.isAlertMessage = true
|
||||
chartInfo.alertRule = this.currentMsg.alertRule
|
||||
chartInfo.elements && (chartInfo.elements[0].filter = encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels))))
|
||||
chartInfo.unit = this.currentMsg.alertRule.unit
|
||||
this.showFullscreen(true, chartInfo)
|
||||
},
|
||||
exportLog ({ limit, descending }) {
|
||||
const start = this.searchTime[0] ? this.searchTime[0] : getTime(-1, 'h')
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
<div style="cursor: pointer" v-else-if="item.key === 'alertNum'">
|
||||
<i :class="Number(getPathContent(item.key)) ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover('',true, $event)" @mouseleave="tooltipHover('',false, $event)"></i>
|
||||
<div v-if="alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: position.left + 'px',top:position.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{getPathContent(item.key)}}</div>
|
||||
|
||||
@@ -212,7 +212,7 @@ export const alertMessage = {
|
||||
export const statisticsList = [
|
||||
{ value: 'min', label: i18n.t('dashboard.panel.chartForm.statisticsVal.min') },
|
||||
{ value: 'max', label: i18n.t('dashboard.panel.chartForm.statisticsVal.max') },
|
||||
{ value: 'average', label: i18n.t('dashboard.panel.chartForm.statisticsVal.average') },
|
||||
{ value: 'avg', label: i18n.t('dashboard.panel.chartForm.statisticsVal.average') },
|
||||
{ value: 'total', label: i18n.t('dashboard.panel.chartForm.statisticsVal.total') },
|
||||
{ value: 'first', label: i18n.t('dashboard.panel.chartForm.statisticsVal.first') },
|
||||
{ value: 'last', label: i18n.t('dashboard.panel.chartForm.statisticsVal.last') },
|
||||
|
||||
@@ -13,6 +13,7 @@ export const clickoutside = {
|
||||
let oldValue
|
||||
try {
|
||||
oldValue = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
el.__newValue__ = oldValue
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
@@ -36,8 +37,8 @@ export const clickoutside = {
|
||||
return false
|
||||
}
|
||||
if (oldValue) {
|
||||
const newValue = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
if (unsavedChange == 'on' && !isEqual(oldValue, newValue)) {
|
||||
// const newValue = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
if (unsavedChange == 'on' && !isEqual(oldValue, el.__newValue__)) {
|
||||
MessageBox.confirm(i18n.t('tip.confirmCancel'), {
|
||||
confirmButtonText: i18n.t('tip.yes'),
|
||||
cancelButtonText: i18n.t('tip.no'),
|
||||
@@ -66,6 +67,9 @@ export const clickoutside = {
|
||||
el.__vueClickOutside__ = documentHandler
|
||||
document.addEventListener('mousedown', documentHandler)
|
||||
},
|
||||
update (el, binding, vnode) {
|
||||
el.__newValue__ = binding.value.obj
|
||||
},
|
||||
unbind (el, binding) {
|
||||
// 解除事件监听
|
||||
document.removeEventListener('mousedown', el.__vueClickOutside__)
|
||||
@@ -199,9 +203,9 @@ export const cancelWithChange = {
|
||||
if (!binding.value || !binding.value.obj) return
|
||||
const unsavedChange = localStorage.getItem('nz-unnsaved-change')
|
||||
const oldValue = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
el.__newValue__ = oldValue
|
||||
function domClick (e) {
|
||||
const newValue = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
if (unsavedChange == 'on' && !isEqual(oldValue, newValue)) {
|
||||
if (unsavedChange == 'on' && !isEqual(oldValue, el.__newValue__)) {
|
||||
MessageBox.confirm(i18n.t('tip.confirmCancel'), {
|
||||
confirmButtonText: i18n.t('tip.yes'),
|
||||
cancelButtonText: i18n.t('tip.no'),
|
||||
@@ -218,6 +222,9 @@ export const cancelWithChange = {
|
||||
el.__vueDomClick__ = domClick
|
||||
el.addEventListener('click', domClick)
|
||||
},
|
||||
update (el, binding, vnode) {
|
||||
el.__newValue__ = binding.value.obj
|
||||
},
|
||||
unbind: function (el, binding) {
|
||||
// 解除事件监听
|
||||
document.removeEventListener('click', el.__vueDomClick__)
|
||||
@@ -900,15 +907,32 @@ export function getMetricTypeValue (queryItem, type) {
|
||||
let copy = JSON.parse(JSON.stringify(queryItem))
|
||||
switch (type) {
|
||||
case 'min': {
|
||||
const min = copy.sort((x, y) => { return parseFloat(x[1]) - parseFloat(y[1]) })[0][1]
|
||||
let min = copy.sort((x, y) => {
|
||||
const x1 = isNaN(x[1]) && !x[1] ? 0 : x[1]
|
||||
const y1 = isNaN(y[1]) && !y[1] ? 0 : y[1]
|
||||
return x1 - y1
|
||||
})[0][1]
|
||||
if (isNaN(min)) {
|
||||
min = 0
|
||||
}
|
||||
return min
|
||||
}
|
||||
case 'max': {
|
||||
const max = copy.sort((x, y) => { return parseFloat(y[1]) - parseFloat(x[1]) })[0][1]
|
||||
let max = copy.sort((x, y) => {
|
||||
const x1 = isNaN(x[1]) && !x[1] ? 0 : x[1]
|
||||
const y1 = isNaN(y[1]) && !y[1] ? 0 : y[1]
|
||||
return y1 - x1
|
||||
})[0][1]
|
||||
if (isNaN(max)) {
|
||||
max = 0
|
||||
}
|
||||
return max
|
||||
}
|
||||
case 'average': {
|
||||
copy = copy.map(t => parseFloat(t[1]))
|
||||
case 'avg': {
|
||||
copy = copy.map(t => {
|
||||
const t1 = isNaN(t[1]) && !t[1] ? 0 : t[1]
|
||||
return parseFloat(t1)
|
||||
})
|
||||
const sum = eval(copy.join('+'))
|
||||
const avg = sum / copy.length
|
||||
return avg
|
||||
@@ -922,13 +946,30 @@ export function getMetricTypeValue (queryItem, type) {
|
||||
return first
|
||||
}
|
||||
case 'total': {
|
||||
copy = copy.map(t => parseFloat(t[1]))
|
||||
copy = copy.map(t => {
|
||||
const t1 = isNaN(t[1]) && !t[1] ? 0 : t[1]
|
||||
return parseFloat(t1)
|
||||
})
|
||||
const total = eval(copy.join('+'))
|
||||
return total
|
||||
}
|
||||
case 'range': {
|
||||
const min = copy.sort((x, y) => { return parseFloat(x[1]) - parseFloat(y[1]) })[0][1]
|
||||
const max = copy.sort((x, y) => { return parseFloat(y[1]) - parseFloat(x[1]) })[0][1]
|
||||
let min = copy.sort((x, y) => {
|
||||
const x1 = isNaN(x[1]) && !x[1] ? 0 : x[1]
|
||||
const y1 = isNaN(y[1]) && !y[1] ? 0 : y[1]
|
||||
return x1 - y1
|
||||
})[0][1]
|
||||
if (isNaN(min)) {
|
||||
min = 0
|
||||
}
|
||||
let max = copy.sort((x, y) => {
|
||||
const x1 = isNaN(x[1]) && !x[1] ? 0 : x[1]
|
||||
const y1 = isNaN(y[1]) && !y[1] ? 0 : y[1]
|
||||
return y1 - x1
|
||||
})[0][1]
|
||||
if (isNaN(max)) {
|
||||
max = 0
|
||||
}
|
||||
return max - min
|
||||
}
|
||||
case 'different': {
|
||||
|
||||
@@ -349,7 +349,7 @@ const cn = {
|
||||
statisticsVal: {
|
||||
min: 'Min',
|
||||
max: 'Max',
|
||||
average: 'Average',
|
||||
avg: 'Avg',
|
||||
total: 'Total',
|
||||
first: 'First',
|
||||
last: 'Last',
|
||||
|
||||
@@ -365,7 +365,7 @@ const en = {
|
||||
statisticsVal: {
|
||||
min: 'Min',
|
||||
max: 'Max',
|
||||
average: 'Average',
|
||||
avg: 'Avg',
|
||||
total: 'Total',
|
||||
first: 'First',
|
||||
last: 'Last',
|
||||
|
||||
@@ -167,14 +167,6 @@ export default {
|
||||
this.$i18n.locale = this.lang
|
||||
this.theme = res.data.user.theme
|
||||
this.userInfo = res.data.user
|
||||
// 获取可选语言
|
||||
get('/sys/dict/all?type=lang').then(response => {
|
||||
if (response.code === 200) {
|
||||
const langList = response.data.map(lang => ({ name: lang.name, value: lang.value }))
|
||||
this.$store.commit('setLangList', langList)
|
||||
localStorage.setItem('nz-language-list', JSON.stringify(langList))
|
||||
}
|
||||
})
|
||||
localStorage.setItem('nz-token', res.data.authToken)
|
||||
if (res.data.authFlag === 1) {
|
||||
if (res.data.authBind === 0) {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import alertLabel from '@/components/common/alert/alertLabel'
|
||||
export default {
|
||||
components: {
|
||||
alertLabel
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
alertLabelShow: false,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<el-tab-pane :label="$t('project.topology.data')" name="1">
|
||||
<el-form v-model="selection.pen.data" class="pens-data" label-position="top">
|
||||
<!--module-->
|
||||
<el-form-item v-if="!selection.pen.type&&!fromDiagram" class="sub-box half-form-item" label="Module"
|
||||
<el-form-item v-if="!selection.pen.type&&!fromDiagram" class="sub-box half-form-item" :label="$t('overall.module')"
|
||||
prop="moduleId">
|
||||
<el-select v-model="selection.pen.data.moduleId" :placeholder="$t('el.select.placeholder')"
|
||||
:popper-append-to-body="true" popper-class="asset-dropdown right-box-select-top" size="small"
|
||||
@@ -274,7 +274,7 @@
|
||||
<!--</div>-->
|
||||
<!--</el-collapse-item>-->
|
||||
<!--样式-->
|
||||
<el-collapse-item :title="'Style'" name="4" v-if="selection.pen">
|
||||
<el-collapse-item :title="$t('project.topology.style')" name="4" v-if="selection.pen">
|
||||
<div class="flex flex-warp">
|
||||
|
||||
<div class="props-pen-item" v-if="selection.pen&&!selection.pen.type">
|
||||
@@ -650,7 +650,7 @@
|
||||
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="'Font'" name="5" v-if="selection.pen&&!selection.pen.type">
|
||||
<el-collapse-item :title="$t('project.topology.font')" name="5" v-if="selection.pen&&!selection.pen.type">
|
||||
<div class="flex flex-warp">
|
||||
<div class="props-pen-item" style="width: 100%">
|
||||
<div>{{ $t('project.topology.textContent') }}</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="info-content pop-data-info-content" v-if="showInfo">
|
||||
<div class="info-box" v-my-loading="loading">
|
||||
<div class="info-box-title">Module info</div>
|
||||
<div class="info-box"v-my-loading="loading">
|
||||
<div class="info-box-title">{{$t('overall.module')}} {{$t('project.topo.icon.info')}}</div>
|
||||
<div class="info-box-content">
|
||||
<div class="content-box">
|
||||
<span class="content-title">ID</span>
|
||||
@@ -16,7 +16,7 @@
|
||||
<span class="content-text">{{moduleInfo.project ? moduleInfo.project.name : '--'}}</span>
|
||||
</div>
|
||||
<div class="content-box">
|
||||
<span class="content-title">{{ $t('project.endpoint.endpoints') }}</span>
|
||||
<span class="content-title">{{ $t('asset.endpoint') }}</span>
|
||||
<span class="content-text">
|
||||
<i class="nz-icon nz-icon-overview-endpoint monitorColor"></i>
|
||||
<span>{{moduleInfo.endpointNum ? moduleInfo.endpointNum : 0}}</span>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
>
|
||||
<template v-slot:default="slotProps">
|
||||
<endpoint-table
|
||||
style="height: calc(100% - 200px)"
|
||||
style="height: 100%"
|
||||
ref="dataTable"
|
||||
:orderByFa="orderBy"
|
||||
v-my-loading="tools.loading"
|
||||
|
||||
@@ -422,7 +422,7 @@
|
||||
</transition>
|
||||
|
||||
<!--thresholdConfig-->
|
||||
<div class="form__sub-title">
|
||||
<div class="form__sub-title" v-if="isThresholdConfig(chartConfig.type)">
|
||||
<span>{{$t('dashboard.panel.chartForm.threshold')}}</span>
|
||||
<el-switch
|
||||
v-model="chartConfig.param.enable.thresholds"
|
||||
@@ -431,7 +431,7 @@
|
||||
></el-switch>
|
||||
</div>
|
||||
<transition name="el-zoom-in-top">
|
||||
<el-row v-if="chartConfig.param.enable.thresholds">
|
||||
<el-row v-if="chartConfig.param.enable.thresholds && isThresholdConfig(chartConfig.type)">
|
||||
<el-form-item
|
||||
v-for="(item,index) in chartConfig.param.thresholds"
|
||||
:key="index"
|
||||
@@ -487,7 +487,7 @@
|
||||
<span @click="addColumns('')">
|
||||
<i class="nz-icon nz-icon-create-square" style="font-weight: normal; font-size: 17px; cursor: pointer;"></i>
|
||||
</span>
|
||||
<span class="nz-icon-copy">
|
||||
<span style="margin-right: 5px">
|
||||
<i @click="copyColumns(index)" class="nz-icon nz-icon-override"></i>
|
||||
</span>
|
||||
<span class="nz-icon-minus-medium">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div v-clickoutside="{obj:editChart, func:clickOutside}" :class="boxClass" class="right-box right-box-chart">
|
||||
<div v-clickoutside="{obj: editChart, func:clickOutside}" :class="boxClass" class="right-box right-box-chart">
|
||||
<transition v-if="from !== 'chartTemp'" name="right-box">
|
||||
<!-- <panel-box v-if="!showPanel.type" ref="panelBox2" :panel="panel" @reload="panelReload"></panel-box>-->
|
||||
</transition>
|
||||
@@ -207,6 +207,8 @@ export default {
|
||||
},
|
||||
// 保存endpoint
|
||||
save () {
|
||||
const self = this
|
||||
let resetFlag = false // 页面是否需要重排
|
||||
const arr = [this.$refs.chartForm.validate()]
|
||||
arr.push(this.$refs['childrenFrom' + this.editChart.datasource].$refs.chartForm.validate())
|
||||
Promise.all(arr).then(res => {
|
||||
@@ -234,14 +236,19 @@ export default {
|
||||
params.x = 0
|
||||
params.y = 0
|
||||
}
|
||||
if (!params.x && !params.y && params.groupId) { // group 内的坐标需要单独计算
|
||||
if (isNaN(params.y) && isNaN(params.y) && params.groupId) { // group 内的坐标需要单独计算
|
||||
params.x = 0
|
||||
params.y = 999
|
||||
}
|
||||
if (!params.x && !params.y) {
|
||||
if (isNaN(params.y) && isNaN(params.y)) {
|
||||
params.x = this.chartLastPosition.x + params.span > 12 ? 0 : this.chartLastPosition.x
|
||||
params.y = this.chartLastPosition.y + 12
|
||||
}
|
||||
if (params.x + params.span > 12) {
|
||||
params.x = 0
|
||||
params.y += 1
|
||||
resetFlag = true
|
||||
}
|
||||
delete params.panel
|
||||
if (params.type === 'table') {
|
||||
delete params.param.tags
|
||||
@@ -253,8 +260,18 @@ export default {
|
||||
this.$put('visual/panel/chart', params).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
|
||||
this.$emit('on-create-success', { id: this.panelId, name: this.panelName })
|
||||
this.esc(true)
|
||||
if (resetFlag) {
|
||||
bus.$emit('creat-chart-success', {
|
||||
...params,
|
||||
cb: function () {
|
||||
self.$emit('on-create-success', { id: this.panelId, name: this.panelName })
|
||||
self.esc(true)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
self.$emit('on-create-success', { id: this.panelId, name: this.panelName })
|
||||
self.esc(true)
|
||||
}
|
||||
} else {
|
||||
this.$message.error(response.msg)
|
||||
}
|
||||
@@ -263,8 +280,18 @@ export default {
|
||||
this.$post('visual/panel/chart', params).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
|
||||
this.$emit('on-create-success', { id: this.panelId, name: this.panelName })
|
||||
this.esc(true)
|
||||
if (resetFlag) {
|
||||
bus.$emit('creat-chart-success', {
|
||||
...params,
|
||||
cb: function () {
|
||||
self.$emit('on-create-success', { id: this.panelId, name: this.panelName })
|
||||
self.esc(true)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
self.$emit('on-create-success', { id: this.panelId, name: this.panelName })
|
||||
self.esc(true)
|
||||
}
|
||||
} else {
|
||||
this.$message.error(response.msg)
|
||||
}
|
||||
@@ -457,42 +484,53 @@ export default {
|
||||
if (obj.param && !obj.param.thresholds) {
|
||||
obj.param.thresholds = []
|
||||
}
|
||||
this.editChart = obj
|
||||
if (this.editChart.groupId === -1) {
|
||||
this.editChart.groupId = ''
|
||||
if (obj.groupId === -1) {
|
||||
obj.groupId = ''
|
||||
}
|
||||
if (this.editChart.param) {
|
||||
if (!this.editChart.param.min) {
|
||||
this.editChart.param.min = 0
|
||||
if (obj.param) {
|
||||
if (!obj.param.min) {
|
||||
obj.param.min = 0
|
||||
}
|
||||
if (!this.editChart.param.max) {
|
||||
this.editChart.param.max = 100
|
||||
if (!obj.param.max) {
|
||||
obj.param.max = 100
|
||||
}
|
||||
if (!this.editChart.param.link) {
|
||||
this.$set(this.editChart.param, 'link', '')
|
||||
if (!obj.param.text && obj.param.display) {
|
||||
obj.param.text = obj.param.display
|
||||
}
|
||||
if (!this.editChart.param.enable) {
|
||||
this.editChart.param.enable = {
|
||||
if (!obj.param.link) {
|
||||
this.$set(obj.param, 'link', '')
|
||||
}
|
||||
if (!obj.param.enable) {
|
||||
obj.param.enable = {
|
||||
thresholds: false,
|
||||
legend: false,
|
||||
valueMapping: false
|
||||
}
|
||||
}
|
||||
// this.editChart.varType = 1
|
||||
if (this.editChart.param.enable.legend && !this.editChart.param.legend) {
|
||||
this.editChart.param.legend = { placement: 'bottom', values: [], show: true }
|
||||
if (obj.param.enable.legend && !obj.param.legend) {
|
||||
obj.param.legend = { placement: 'bottom', values: [], show: true }
|
||||
}
|
||||
if (this.editChart.param.datasource && !this.editChart.param.datasource[0].legend) {
|
||||
this.editChart.param.datasource[0].legend = ''
|
||||
if (obj.param.datasource && !obj.param.datasource[0].legend) {
|
||||
obj.param.datasource[0].legend = ''
|
||||
}
|
||||
if (this.editChart.param.valueMapping) {
|
||||
this.editChart.param.valueMapping.forEach(item => {
|
||||
if (obj.param.valueMapping) {
|
||||
obj.param.valueMapping.forEach(item => {
|
||||
if (!item.show) {
|
||||
item.show = false
|
||||
}
|
||||
if (item.text && !item.display) {
|
||||
item.display = item.text
|
||||
} else if (!item.display) {
|
||||
item.display = '{{A.$value}}'
|
||||
}
|
||||
if (item.columns && !item.column) {
|
||||
item.column = item.columns
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
this.editChart = obj
|
||||
}
|
||||
},
|
||||
'editChart.type': {
|
||||
@@ -501,6 +539,12 @@ export default {
|
||||
this.editChart.groupId = ''
|
||||
}
|
||||
}
|
||||
},
|
||||
editChart: {
|
||||
deep: true,
|
||||
handler () {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,23 @@ export default {
|
||||
default: return false
|
||||
}
|
||||
},
|
||||
isThresholdConfig(type) {
|
||||
switch (type) {
|
||||
case 'line':
|
||||
case 'area':
|
||||
case 'point':
|
||||
return true
|
||||
case 'table':
|
||||
case 'stat':
|
||||
case 'hexagon':
|
||||
case 'gauge':
|
||||
case 'treemap':
|
||||
case 'pie':
|
||||
case 'bar':
|
||||
return false
|
||||
default: return false
|
||||
}
|
||||
},
|
||||
isShowLegendVlaues (type) {
|
||||
switch (type) {
|
||||
case 'line':
|
||||
|
||||
@@ -165,7 +165,7 @@ export default {
|
||||
label: this.$t('dashboard.panel.chartForm.legend'),
|
||||
value: 'legend'
|
||||
}, {
|
||||
label: this.$t('config.assetLabel.all'),
|
||||
label: this.$t('project.topology.none'),
|
||||
value: 'none'
|
||||
}
|
||||
],
|
||||
@@ -346,6 +346,7 @@ export default {
|
||||
},
|
||||
showMapping (index) {
|
||||
this.chartConfig.param.valueMapping[index].show = !this.chartConfig.param.valueMapping[index].show
|
||||
this.change()
|
||||
},
|
||||
mappingItemChange (index, type) {
|
||||
const mapping = this.chartConfig.param.valueMapping[index]
|
||||
@@ -416,6 +417,7 @@ export default {
|
||||
},
|
||||
showColumns (index) {
|
||||
this.chartConfig.param.columns[index].show = !this.chartConfig.param.columns[index].show
|
||||
this.change()
|
||||
},
|
||||
tagsChange (newTags) {
|
||||
this.chartConfig.param.tags = newTags
|
||||
|
||||
@@ -384,7 +384,7 @@
|
||||
</transition>
|
||||
|
||||
<!--thresholdConfig-->
|
||||
<div class="form__sub-title">
|
||||
<div class="form__sub-title" v-if="isThresholdConfig(chartConfig.type)">
|
||||
<span>{{$t('dashboard.panel.chartForm.threshold')}}</span>
|
||||
<el-switch
|
||||
v-model="chartConfig.param.enable.thresholds"
|
||||
@@ -393,7 +393,7 @@
|
||||
></el-switch>
|
||||
</div>
|
||||
<transition name="el-zoom-in-top">
|
||||
<el-row v-if="chartConfig.param.enable.thresholds">
|
||||
<el-row v-if="chartConfig.param.enable.thresholds && isThresholdConfig(chartConfig.type)">
|
||||
<el-form-item
|
||||
v-for="(item,index) in chartConfig.param.thresholds"
|
||||
:key="index"
|
||||
@@ -449,7 +449,7 @@
|
||||
<span @click="addColumns('')">
|
||||
<i class="nz-icon nz-icon-create-square" style="font-weight: normal; font-size: 17px; cursor: pointer;"></i>
|
||||
</span>
|
||||
<span class="nz-icon-copy">
|
||||
<span style="margin-right: 5px">
|
||||
<i @click="copyColumns(index)" class="nz-icon nz-icon-override"></i>
|
||||
</span>
|
||||
<span class="nz-icon-minus-medium">
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
</span>
|
||||
</template>
|
||||
<span v-else-if="item.prop === 'state'">
|
||||
<span class="alert-message-state" :class="{'green-bg': scope.row['state'] == 3, 'red-bg': scope.row['state'] == 1,'yellow-bg': scope.row['state'] == 2}">
|
||||
<span class="alert-message-state" :class="{'gray-bg': scope.row['state'] == 3, 'red-bg': scope.row['state'] == 1,'yellow-bg': scope.row['state'] == 2}">
|
||||
{{$t(stateOptions.find(state=>state.value == scope.row['state']).label)}}
|
||||
</span>
|
||||
</span>
|
||||
@@ -101,7 +101,7 @@
|
||||
fixed="right">
|
||||
<div slot="header" class="table-operation-title">{{$t('overall.option')}}</div>
|
||||
<div slot-scope="scope" class="table-operation-items">
|
||||
<button v-if="scope.row.alertRule&&scope.row.alertRule.type !== 3" class="table-operation-item" @click="$emit('messageDetail', scope.row)"><i class="nz-icon nz-icon-view1"></i></button>
|
||||
<button v-if="scope.row.alertRule" class="table-operation-item" @click="$emit('messageDetail', scope.row)"><i class="nz-icon nz-icon-view1"></i></button>
|
||||
<el-dropdown v-has="['alertMessage_expired', 'alertSilence_add']" size="medium" trigger="click" @command="tableOperation">
|
||||
<div class="table-operation-item table-operation-item--more">
|
||||
<i class="nz-icon nz-icon-more3"></i>
|
||||
@@ -139,19 +139,16 @@
|
||||
import bus from '../../../../libs/bus'
|
||||
import axios from 'axios'
|
||||
import table from '@/components/common/mixin/table'
|
||||
import nzAlertTag from '../../../page/alert/nzAlertTag'
|
||||
import chartDataFormat from '../../../charts/chartDataFormat'
|
||||
import alertRuleInfo from '../../alert/alertRuleInfo'
|
||||
import alertLabel from '../../alert/alertLabel'
|
||||
import { calcDurationByStringTimeB } from '../../js/tools'
|
||||
import { alertMessage as alertMessageConstant } from '@/components/common/js/constants'
|
||||
import alertLabelMixin from '@/components/common/mixin/alertLabelMixin'
|
||||
import alertMessageLabelMixin from '@/components/common/alert/alertMessageLabelMixin'
|
||||
export default {
|
||||
name: 'alertMessageTable',
|
||||
components: {
|
||||
nzAlertTag,
|
||||
alertRuleInfo: alertRuleInfo,
|
||||
alertLabel: alertLabel
|
||||
},
|
||||
props: {
|
||||
nowTime: {
|
||||
@@ -165,7 +162,7 @@ export default {
|
||||
loading: Boolean,
|
||||
chartAlertList: Boolean
|
||||
},
|
||||
mixins: [table, bus, alertLabelMixin],
|
||||
mixins: [table, bus, alertLabelMixin, alertMessageLabelMixin],
|
||||
data () {
|
||||
return {
|
||||
/* 二级列表相关 */
|
||||
@@ -176,7 +173,6 @@ export default {
|
||||
graphShow: false,
|
||||
chartDatas: [],
|
||||
sameLabels: ['instance', 'module', 'project', 'asset', 'endpoint', 'dc'],
|
||||
exclusiveLabels: ['_id', 'severity', '__name__'],
|
||||
legend: [],
|
||||
searchTime: [new Date().setHours(new Date().getHours() - 1), new Date()],
|
||||
currentMsg: {},
|
||||
@@ -254,29 +250,6 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tagType () {
|
||||
return (key) => {
|
||||
if (key == 'asset' || key == 'module' || key == 'project' || key == 'dc' || key == 'endpoint') {
|
||||
return 'normal'
|
||||
} else {
|
||||
return 'info'
|
||||
}
|
||||
}
|
||||
},
|
||||
tagValue () {
|
||||
return (key, value) => {
|
||||
if (key == 'type') {
|
||||
if (value == 1) {
|
||||
value = this.$t('project.project.projectName')
|
||||
} else if (value == 2) {
|
||||
value = this.$t('module.module.module')
|
||||
} else if (value == 3) {
|
||||
value = this.$t('asset.asset')
|
||||
}
|
||||
}
|
||||
return key + ':' + value
|
||||
}
|
||||
},
|
||||
getDuration () {
|
||||
return function (record) {
|
||||
if (record.endAt) {
|
||||
@@ -297,35 +270,6 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
labelsSort (obj) {
|
||||
const buildIn = ['asset', 'endpoint', 'module', 'cpu', 'datacenter', 'project', 'parent_asset', 'user']
|
||||
if (typeof obj === 'string') obj = JSON.parse(obj)
|
||||
const labels = JSON.parse(JSON.stringify(obj))
|
||||
const result = []
|
||||
for (const key of this.exclusiveLabels) {
|
||||
Object.keys(labels).forEach(labelsKey => {
|
||||
if (labelsKey.indexOf(key) !== -1) {
|
||||
delete labels[labelsKey]
|
||||
}
|
||||
})
|
||||
}
|
||||
for (const key of buildIn) {
|
||||
if (key in labels) {
|
||||
if (key === 'datacenter') {
|
||||
result.push({ label: 'dc', value: labels.datacenter })
|
||||
delete labels.datacenter
|
||||
} else {
|
||||
result.push({ label: key, value: labels[key] })
|
||||
}
|
||||
delete labels[key]
|
||||
}
|
||||
}
|
||||
Object.keys(labels).sort().forEach(key => {
|
||||
result.push({ label: key, value: labels[key] })
|
||||
delete labels[key]
|
||||
})
|
||||
return result
|
||||
},
|
||||
chartUnitChange: function (unit) {
|
||||
this.chartUnit = unit
|
||||
this.$nextTick(() => {
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<span style="cursor: pointer" @click="queryMessage(scope.row)">
|
||||
<i :class="scope.row.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover(scope.row,true, $event)" @mouseleave="tooltipHover(scope.row,false, $event)"></i>
|
||||
<div v-if="scope.row.alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: scope.row.left + 'px',top:scope.row.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{scope.row.alertNum}}</div>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<span style="cursor: pointer" @click="$emit('showBottomBox', 'alertMessageTab', scope.row)">
|
||||
<i :class="scope.row.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover(scope.row,true, $event)" @mouseleave="tooltipHover(scope.row,false, $event)"></i>
|
||||
<div v-if="scope.row.alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: scope.row.left + 'px',top:scope.row.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{scope.row.alertNum}}</div>
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
<span style="cursor: pointer" @click="showBottomBox('endpointAlertMessage', scope.row)">
|
||||
<i :class="scope.row.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover(scope.row,true, $event)" @mouseleave="tooltipHover(scope.row,false, $event)"></i>
|
||||
<div v-if="scope.row.alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: scope.row.left + 'px',top:scope.row.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{scope.row.alertNum}}</div>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<span style="cursor: pointer" @click="showBottomBox('moduleAlertMessage', scope.row)">
|
||||
<i :class="scope.row.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover(scope.row,true, $event)" @mouseleave="tooltipHover(scope.row,false, $event)"></i>
|
||||
<div v-if="scope.row.alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: scope.row.left + 'px',top:scope.row.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{scope.row.alertNum}}</div>
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<span style="cursor: pointer" @click="jumpAlertMessage(scope.row)">
|
||||
<i :class="scope.row.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert vertical-align-top;" @mouseenter="tooltipHover(scope.row,true, $event)" @mouseleave="tooltipHover(scope.row,false, $event)"></i>
|
||||
<div v-if="scope.row.alertNumtooltipShow" class="alert-days-info-tooltip" :style="{left: scope.row.left + 'px',top:scope.row.top + 'px'}">
|
||||
<div class="tooltip-title">Alert message (active)</div>
|
||||
<div class="tooltip-title">{{$t('project.topology.alert')}}({{$t('asset.pingActive')}})</div>
|
||||
<div class="severity-info" style='justify-content: space-between'>
|
||||
<div class="severity-name">{{$t('overall.result.total')}}</div>
|
||||
<div class="severity-value">{{scope.row.alertNum}}</div>
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
fullscreen
|
||||
:modal-append-to-body="false"
|
||||
>
|
||||
<panel-chart
|
||||
<alertMessageInfo
|
||||
:ref="'chart-fullscreen' + chartInfo.id"
|
||||
:chart-info="chartInfo"
|
||||
:from="fromRoute.alertMessage"
|
||||
@@ -121,7 +121,7 @@
|
||||
:is-fullscreen="true"
|
||||
:time-range="searchTimeDialog"
|
||||
@showFullscreen="showFullscreen"
|
||||
></panel-chart>
|
||||
></alertMessageInfo>
|
||||
</el-dialog>
|
||||
<!--全屏-->
|
||||
<el-dialog class="nz-dialog table-chart-dialog" :title="$t('alert.config.trbShot')"
|
||||
@@ -157,7 +157,7 @@ import { alertMessage as alertMessageConstant, fromRoute } from '@/components/co
|
||||
import alertSilenceBox from '@/components/common/rightBox/alertSilenceBox'
|
||||
import clickSearch from '@/components/common/labelFilter/clickSearch'
|
||||
import routerPathParams from '@/components/common/mixin/routerPathParams'
|
||||
import panelChart from '@/components/chart/panelChart'
|
||||
import alertMessageInfo from '@/components/common/alert/alertMessageInfo'
|
||||
import lineData from '@/components/chart/defaultLineData'
|
||||
import logData from '@/components/chart/defaultLogData'
|
||||
import lodash from 'lodash'
|
||||
@@ -172,7 +172,7 @@ export default {
|
||||
deleteButton,
|
||||
alertSilenceBox,
|
||||
clickSearch,
|
||||
panelChart
|
||||
alertMessageInfo
|
||||
},
|
||||
mixins: [dataListMixin, routerPathParams],
|
||||
data () {
|
||||
@@ -578,9 +578,6 @@ export default {
|
||||
})
|
||||
},
|
||||
messageDetail (row) {
|
||||
if (row.alertRule.type == 3) {
|
||||
return
|
||||
}
|
||||
this.$get('/alert/rule/' + row.alertRule.id).then(res => {
|
||||
this.currentMsg = { ...row, alertRule: { ...res.data } }
|
||||
this.$nextTick(() => {
|
||||
@@ -606,8 +603,9 @@ export default {
|
||||
},
|
||||
queryDate () {
|
||||
this.chartLoading = true
|
||||
if (this.currentMsg.alertRule.type === 1) {
|
||||
const chartInfo = lodash.cloneDeep(lineData)
|
||||
let chartInfo = {}
|
||||
if (this.currentMsg.alertRule.type === 1 || this.currentMsg.alertRule.type === 3) {
|
||||
chartInfo = lodash.cloneDeep(lineData)
|
||||
chartInfo.elements = [{}]
|
||||
if (!isNaN(this.currentMsg.alertRule.threshold)) {
|
||||
chartInfo.param.enable.thresholds = true
|
||||
@@ -616,12 +614,9 @@ export default {
|
||||
color: '#d64f40'
|
||||
}]
|
||||
}
|
||||
chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, '')
|
||||
chartInfo.elements[0].filter = encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))
|
||||
chartInfo.unit = this.currentMsg.alertRule.unit
|
||||
this.showFullscreen(true, chartInfo)
|
||||
chartInfo.elements && (chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, ''))
|
||||
} else if (this.currentMsg.alertRule.type === 2) {
|
||||
const chartInfo = lodash.cloneDeep(logData)
|
||||
chartInfo = lodash.cloneDeep(logData)
|
||||
chartInfo.elements = [{}]
|
||||
if (!isNaN(this.currentMsg.alertRule.threshold)) {
|
||||
chartInfo.param.enable.thresholds = true
|
||||
@@ -630,11 +625,15 @@ export default {
|
||||
color: '#d64f40'
|
||||
}]
|
||||
}
|
||||
chartInfo.elements[0].expression = encodeURIComponent(this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, ''))
|
||||
chartInfo.elements[0].filter = encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))
|
||||
chartInfo.unit = this.currentMsg.alertRule.unit
|
||||
this.showFullscreen(true, chartInfo)
|
||||
chartInfo.elements && (chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\r|\n+/g, ''))
|
||||
}
|
||||
chartInfo.id = this.currentMsg.id
|
||||
chartInfo.name = this.currentMsg.alertRule.name
|
||||
chartInfo.isAlertMessage = true
|
||||
chartInfo.alertRule = this.currentMsg.alertRule
|
||||
chartInfo.elements && (chartInfo.elements[0].filter = encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels))))
|
||||
chartInfo.unit = this.currentMsg.alertRule.unit
|
||||
this.showFullscreen(true, chartInfo)
|
||||
},
|
||||
exportLog ({ limit, descending }) {
|
||||
const start = this.searchTimeDialog[0] ? this.searchTimeDialog[0] : bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000)
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope" :column="item">
|
||||
<template v-if="item.prop === 'time'">{{utcTimeToTimezoneStr(scope.row.time)}}</template>
|
||||
<template v-if="item.prop === 'time'">{{timeFormate(scope.row.time)}}</template>
|
||||
<span v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</span>
|
||||
<template v-else>-</template>
|
||||
</template>
|
||||
|
||||
@@ -319,11 +319,11 @@ export default {
|
||||
nowTimeType: JSON.stringify(this.nowTimeType),
|
||||
searchTime: JSON.stringify(this.searchTime)
|
||||
}
|
||||
// this.dateChange()
|
||||
// this.getTableData()
|
||||
const path = this.fromRoute.panel
|
||||
this.updatePath(param, path)
|
||||
this.getData(this.filter)
|
||||
this.dateChange()
|
||||
// this.getData(this.filter)
|
||||
this.$refs.chartList.cleanData()
|
||||
},
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ export default new Vue({
|
||||
statisticsRlt = dataArray.reduce(function (a, b) {
|
||||
return b > a ? b : a
|
||||
})
|
||||
} else if (statistics === 'average') { // average:平均值
|
||||
} else if (statistics === 'avg') { // avg:平均值
|
||||
let sum = 0
|
||||
dataArray.forEach((item) => {
|
||||
sum = Number(sum) + Number(item)
|
||||
|
||||
@@ -14,7 +14,7 @@ import router from './router'
|
||||
import VueResource from 'vue-resource'
|
||||
import axios from 'axios'
|
||||
import { hasPermission, hasButton } from './permission'
|
||||
|
||||
import loadsh from 'lodash'
|
||||
import plTable from 'pl-table'
|
||||
import 'pl-table/themes/index.css'
|
||||
|
||||
@@ -62,6 +62,7 @@ Vue.prototype.$post = post
|
||||
Vue.prototype.$get = get
|
||||
Vue.prototype.$put = put
|
||||
Vue.prototype.$delete = del
|
||||
Vue.prototype.$loadsh = loadsh
|
||||
Vue.prototype.$CONSTANTS = constants
|
||||
Vue.prototype.$TOOLS = tools
|
||||
Vue.prototype.$bottomBoxWindow = bottomBoxWindow // 底部上滑框控制
|
||||
@@ -97,24 +98,24 @@ Vue.mixin({
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
utcTimeToTimezone: function (time) {
|
||||
utcTimeToTimezone: function (time) { // 将utc时间 转为系统设者的时间 返回时间戳
|
||||
if (time) {
|
||||
return bus.UTCTimeToConfigTimezone(time)
|
||||
}
|
||||
},
|
||||
utcTimeToTimezoneStr: function (time) {
|
||||
utcTimeToTimezoneStr: function (time) { // 将utc时间 转为系统设者的时间 返回String
|
||||
if (time) {
|
||||
return bus.timeFormate(bus.UTCTimeToConfigTimezone(time), localStorage.getItem('nz-default-dateFormat') ? localStorage.getItem('nz-default-dateFormat') : localStorage.getItem('nz-default-dateFormat') ? localStorage.getItem('nz-default-dateFormat') : 'YYYY-MM-DD HH:mm:ss')
|
||||
return bus.timeFormate(bus.UTCTimeToConfigTimezone(time), localStorage.getItem('nz-default-dateFormat') || 'YYYY-MM-DD HH:mm:ss')
|
||||
} else {
|
||||
return '-'
|
||||
}
|
||||
},
|
||||
timezoneToUtcTime: function (time) {
|
||||
timezoneToUtcTime: function (time) { // 将系统设者的时间 转为utc时间 返回时间戳
|
||||
if (time) {
|
||||
return bus.configTimezoneToUTCTime(time)
|
||||
}
|
||||
},
|
||||
timezoneToUtcTimeStr: function (time, fmt) {
|
||||
timezoneToUtcTimeStr: function (time, fmt) { // 将系统设者的时间 转为utc时间 返回String
|
||||
if (!fmt) {
|
||||
fmt = localStorage.getItem('nz-default-dateFormat') || 'YYYY-MM-DD HH:mm:ss'
|
||||
}
|
||||
@@ -122,7 +123,7 @@ Vue.mixin({
|
||||
return bus.timeFormate(this.timezoneToUtcTime(time), fmt)
|
||||
}
|
||||
},
|
||||
timestampStr: function (time, fmt) {
|
||||
timestampStr: function (time, fmt) { // 将utc时间 转为系统设者的时间 返回String
|
||||
const date = new Date(time)
|
||||
const localOffset = date.getTimezoneOffset() * 60 * 1000 // 默认 一分钟显示时区偏移的结果
|
||||
const dateStr = new Date(time).getTime() + localOffset
|
||||
@@ -135,6 +136,9 @@ Vue.mixin({
|
||||
return '-'
|
||||
}
|
||||
},
|
||||
timeFormate (time) {
|
||||
return bus.timeFormate(time)
|
||||
},
|
||||
hasButton (code) {
|
||||
return hasButton(this.$store.getters.buttonList, code)
|
||||
},
|
||||
|
||||
@@ -101,6 +101,14 @@ const user = {
|
||||
localStorage.setItem('nz-mfa-enable', Number(res.data.mfaAuthEnable) ? 1 : 0)
|
||||
store.commit('setLanguage', res.data.user.lang || defaultAppearance.language)
|
||||
store.commit('setTimeFormatMain', localStorage.getItem('nz-default-dateFormat') || 'YYYY-MM-DD HH:mm:ss')
|
||||
// 获取可选语言
|
||||
get('/sys/dict/all?type=lang').then(response => {
|
||||
if (response.code === 200) {
|
||||
const langList = response.data.map(lang => ({ name: lang.name, value: lang.value }))
|
||||
store.commit('setLangList', langList)
|
||||
localStorage.setItem('nz-language-list', JSON.stringify(langList))
|
||||
}
|
||||
})
|
||||
post('/sys/user/permissions', { token: res.data.token }).then(res => {
|
||||
const menuList = sortByOrderNum(res.data.menus)
|
||||
// localStorage.setItem('nz-user-permissions', JSON.stringify(res.data.buttons))
|
||||
|
||||
Reference in New Issue
Block a user