This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
nezha-nezha-fronted/nezha-fronted/src/components/charts/chart-alert-list.vue

1116 lines
41 KiB
Vue
Raw Normal View History

2020-05-31 22:33:16 +08:00
<style lang="scss">
@import './chart.scss';
2020-05-28 17:32:23 +08:00
</style>
<template>
<div class="nz-chart-resize" :id="id">
<div class="resize-shadow" ref="resizeShadow"></div>
<div class="resize-box resize-box-alert" ref="resizeBox">
<div class="chart-alert-info table-container" :id="'chartTableDiv'+chartIndex" @mouseenter="caretShow=true" @mouseleave="caretShow=false">
<loading :ref="'localLoading'+chartIndex"></loading>
2021-07-02 14:03:17 +08:00
<div v-if="showTitle" class="clearfix chartTitle" :class="{'dragTitle':dragTitleShow, 'drag-disabled': !data.draggable}" :id="'chartTitle'+chartIndex" v-show="!isPreview">
2020-05-28 17:32:23 +08:00
<el-popover
v-if="isError"
:close-delay=10
placement="top-start"
trigger="hover"
2020-05-28 17:32:23 +08:00
popper-class="chart-error-popper">
<div >{{errorContent}}</div>
<span slot="reference" class="panel-info-corner panel-info-corner--error">
<i class="nz-icon nz-icon-warning fa"></i>
<span class="panel-info-corner-inner"></span>
2020-05-28 17:32:23 +08:00
</span>
</el-popover>
<el-dropdown trigger="click" class="nz-chart-top" :key="'chartDropdown'+chartIndex" v-clickoutside="clickos" :class="{'move-able':!isLock}">
2020-05-28 17:32:23 +08:00
<el-dropdown-menu style="display: none"></el-dropdown-menu>
<span class="el-dropdown-link chart-title">
2021-09-02 14:43:06 +08:00
<!-- <span class="chart-title-text">{{chartData?chartData.name:'-'}}</span>-->
<span class="chart-title-text" v-on:mouseover="changeActive()" :mouseout="removeActive()">{{chartData?chartData.name:'-'}}</span>
<transition name="el-fade-in-linear">
<span v-show="chartDataList" class="chart-title-pit" >{{chartData.name}}</span>
</transition>
<span class="chart-title-icon" :class="{'visible':caretShow,'hidden':!caretShow}">
<span v-if="chartData&&chartData.remark">
<el-tooltip :content="chartData.remark" placement="top" effect="light">
<i class="nz-icon nz-icon-info-normal"></i>
</el-tooltip>
</span>
2021-04-14 18:46:58 +08:00
<span v-has="'panel_chart_edit'" :title="$t('dashboard.refresh')" class="" @click="refreshChart">
<i class="nz-icon nz-icon-replay"></i>
</span>
<span @click="showAllScreen" v-if="from !== 'chartTemp'" class="" :title="$t('dashboard.screen')">
<i class="nz-icon nz-icon-maxview"></i>
</span>
<span><i class="el-icon-more" @click.stop="dropdownMenuShow=!dropdownMenuShow"></i></span>
</span>
2020-05-28 17:32:23 +08:00
</span>
<ul slot="dropdown" v-show="dropdownMenuShow" :id="'dropdownUl'+chartIndex" class="el-dropdown-menu nz-chart-dropdown" style="" >
<li @click="editChart" class="el-dropdown-menu__item">
<i class="nz-icon nz-icon-edit" style="font-size: 16px;"></i><span>{{$t('dashboard.edit')}}</span></li>
2021-04-14 18:46:58 +08:00
<li v-has="'panel_chart_delete'" class="el-dropdown-menu__item" @click="removeChart">
2020-09-10 17:00:32 +08:00
<i class="nz-icon nz-icon-delete" style="font-size: 16px;"></i>{{$t('dashboard.delete')}}</li>
2021-04-14 18:46:58 +08:00
<li v-has="'panel_chart_add'" class="el-dropdown-menu__item" @click="duplicate">
2020-05-28 17:32:23 +08:00
<i class="el-icon-copy-document" style="font-size: 16px;"></i>{{$t('dashboard.duplicate')}}</li>
<li v-has="'panel_chart_edit'" v-if="from !== 'chartTemp'&&chartData&&chartData.pid" class="el-dropdown-menu__item" @click="$emit('sync')">
<i class="nz-icon nz-icon-sync" style="font-size: 16px;"></i>{{$t('overall.syncChart')}}</li>
2020-05-28 17:32:23 +08:00
</ul>
</el-dropdown>
</div>
2021-08-11 14:01:28 +08:00
<div class="mt-10 table-container nz-table2" v-cloak v-show="firstShow || isPreview" :style="isPreview?'height:100%':''">
<alertMessageTable
2021-02-07 18:19:59 +08:00
:id="'tableContainer'+chartIndex"
:tableData="storedTableData"
:loading="loadingTable"
:height="'calc(100% - 46px)'"
:customTableTitle="tableTitle"
:tableId="''"
:detailList="false"
:projectAlertId="'tableContainer'+chartIndex"
@tableDataSort="tableDataSort"
@del="deleteMessage"
@showText="showText"
@messageDetail="messageDetail"
2020-05-28 17:32:23 +08:00
ref="alertListTable"
:form="'chartList'"
:fromPath="'/alertList'"
style="height: calc(100% - 50px)"
:showTopBtn="false"
></alertMessageTable>
<Pagination :pageObj="pageObj" @pageNo='pageNo' @pageSize='pageSize' ref="Pagination" :append-to-body="false" pop-class="out-popper-fix" style="margin-top: 15px;"></Pagination>
2020-05-28 17:32:23 +08:00
</div>
<!--全屏-->
<el-dialog class="nz-dialog table-chart-dialog" id="dialog-alert-massage" :title="$t('dashboard.panel.view')" :visible.sync="screenModal" width="96%" @close="screenDialogClose" :modal-append-to-body="false">
<div slot="title">
2021-04-07 16:41:11 +08:00
<span class="nz-dialog-title">{{data.name}}</span>
<div class="float-right panel-calendar dialog-tool">
2021-02-04 11:21:00 +08:00
<pick-time :refresh-data-func="dateChange" v-model="searchTime" :show-time-picker="false" :use-chart-unit="false" ref="pickTime" style="height: 28px;" id="alert-chart"></pick-time>
2020-05-28 17:32:23 +08:00
</div>
<!-- <span class="float-right dialog-tool" @click="screenRefreshChart"><i class="global-active-color nz-icon nz-icon-refresh"/></span>-->
</div>
<alertMessageTable
:id="'tableContainerScreen'+chartIndex"
:tableData="storedScreanTableData"
:detailList="false"
2020-08-04 09:30:32 +08:00
:loading="loadingTable"
:height="'calc(100% - 20px)'"
:customTableTitle="tableTitle"
:tableId="''"
:projectAlertId="'tableContainer'+chartIndex"
@tableDataSort="tableDataSort"
@del="deleteMessage"
@messageDetail="messageDetail"
ref="alertListScreenTable"
:form="'chartList'"
:fromPath="'/alertList'"
style="height: calc(100% - 50px)"
:showOption="false"
:chart-alert-list="true"
></alertMessageTable>
<Pagination :pageObj="screenPageObj" @pageNo='screenPageNo' @pageSize='screenPageSize' ref="Pagination" ></Pagination>
<loading :ref="'localLoadingScreen'+chartIndex"></loading>
2020-05-28 17:32:23 +08:00
</el-dialog>
<div class="export-xlsx">
<el-dialog :visible.sync="deleteBox.show" :title="$t('overall.delete')" :modal-append-to-body='false' :show-close="true" width="300px" @close="closeDialog" class="nz-message">
<div class="upload-body">
<el-input type="textarea" :placeholder="$t('overall.remark')" v-model="deleteBox.remark"></el-input>
<div style="text-align: right; margin-top: 10px;">
2021-02-04 11:21:00 +08:00
<button @click="closeDialog" class="el-button el-button--default el-button--small" >
<span>{{$t('tip.no')}}</span>
</button>
<button @click="deleteMessage" class="el-button el-button--default el-button--small el-button--primary">
<span>{{$t('tip.yes')}}</span>
</button>
</div>
</div>
</el-dialog>
</div>
<el-dialog class="line-chart-block-modal nz-dialog endpoint-dialog"
:title="$t('overall.detail')"
:visible.sync="graphShow"
width="90%"
:append-to-body="true"
id="viewGraphDialog"
@close="dialogClose" :modal-append-to-body="false">
<div slot="title">
{{$t("project.endpoint.dialogTitle")}}
<div class="float-right panel-calendar dialog-tool" style="display: flex">
<pick-time :refresh-data-func="queryDate" :use-refresh="true" :use-chart-unit="false" v-model="searchTimeDialog" style="height: 28px;" id="alert-sub-chart"></pick-time>
</div>
</div>
<div style="width: 100%;height: 100%" v-loading="chartLoading">
<chart v-if="resultType === 'matrix'" ref="messageChart" :unit="chartUnit" name="alertMessageChart"></chart>
<log-tab v-if="resultType === 'streamsFormat'" ref="logDetailScreen" :log-data="logData" :showSwitch="false" :tab-index="tabIndex" @exportLog="exportLog" @limitChange="queryLogData"></log-tab>
</div>
</el-dialog>
<!--全屏-->
<el-dialog class="nz-dialog table-chart-dialog" :title="$t('alert.config.trbShot')"
:visible.sync="dialogShowText"
width="96%" @close="dialogShowText = false" :modal-append-to-body="false">
<div slot="title">
<span class="nz-dialog-title">{{$t('alert.config.trbShot')}}</span>
</div>
<div class="rich-text-screen-container" >
<div id="chartScreenContainer" ref="chartScreenContainer" class="text-content" >
<el-scrollbar style="height: 100%;" class="el-scrollbar-normal">
<div style="height: 100%;" v-html="dialogText" ></div>
</el-scrollbar>
2020-05-28 17:32:23 +08:00
</div>
</div>
</el-dialog>
</div>
<span class="vue-resizable-handle" @mousedown="startResize" v-if="!isPreview && data.resizable&&!isLock"></span>
2020-05-28 17:32:23 +08:00
</div>
</div>
2020-05-28 17:32:23 +08:00
</template>
<script>
2021-03-19 18:52:19 +08:00
import bus from '../../libs/bus'
2020-05-28 17:32:23 +08:00
import chartDataFormat from './chartDataFormat'
2021-03-19 18:52:19 +08:00
import loading from '../common/loading'
import axios from 'axios'
import pickTime from '../common/pickTime'
import chart from '../page/dashboard/overview/chart'
2021-04-13 20:33:12 +08:00
import alertMessageTable from '@/components/common/table/alert/alertMessageTable.vue'
2021-09-02 14:43:06 +08:00
import chartDataList from '@/components/common/mixin/chartDataList'
2020-05-28 17:32:23 +08:00
export default {
name: 'chartTable',
2020-05-28 17:32:23 +08:00
components: {
2021-03-19 18:52:19 +08:00
loading: loading,
chart: chart,
'pick-time': pickTime,
alertMessageTable: alertMessageTable
2020-05-28 17:32:23 +08:00
},
props: {
// 看板id
panelId: {
type: Number,
2021-03-19 18:52:19 +08:00
default: 0
},
2021-07-02 14:03:17 +08:00
showTitle: {
type: Boolean,
default: true
},
editChartId: {
type: String,
2021-03-19 18:52:19 +08:00
default: 'editChartId'
},
2021-03-19 18:52:19 +08:00
chartIndex: {
type: Number,
2021-03-19 18:52:19 +08:00
default: 0
},
2021-03-19 18:52:19 +08:00
chartInfo: {},
chartData: {},
2021-03-19 18:52:19 +08:00
id: { type: String },
from: { type: String },
isLock: { type: Boolean, default: false }
},
2021-09-02 14:43:06 +08:00
mixins: [chartDataList],
2021-03-19 18:52:19 +08:00
data () {
return {
2021-05-21 22:15:40 +08:00
currentMsg: null,
tableHeight: 0,
2021-03-19 18:52:19 +08:00
data: {}, // 该图表信息,chartItem
unit: {},
isError: false,
errorContent: '',
pageObj: {
pageNo: 1,
pageSize: this.$CONSTANTS.defaultPageSize,
total: 0
},
loadingTable: false, // 表格数据加载loading
screenPageObj: {
pageNo: 1,
pageSize: this.$CONSTANTS.defaultPageSize,
total: 0
},
storedTableData: [],
requestIndex: 0,
storedScreanTableData: [],
images: '',
// toolbox: false,
loading: Object,
panelIdInner: '', // 看板id=panelId,原写作chart,由set_data获取
firstLoad: false, // 是否第一次加载
// showLoading:true,
// showLoadingScreen:false,
// showTable:true,
chartType: 'alertLIst', // 图表类型
screenModal: false,
// 查询数据使用
filter: {
start_time: '',
end_time: ''
},
stableFilter: {}, // 保存数据使用,初始化起止时间,单图or多图等
firstShow: false, // 默认不显示操作按钮,
caretShow: false,
dragTitleShow: false,
dropdownMenuShow: false,
minHeight: 200,
chartSpaceHeight: 5, // top-border: 1,bottom-border: 1,padding-bottome:3
titleHeight: 38, // title-height:28,magrin-bottom:10
pageHeight: 40,
divFirstShow: false,
searchTime: [new Date().setHours(new Date().getHours() - 1), new Date()], // 全屏显示的时间
oldSearchTime: [],
searchLabel: {},
tableTitle: [
{
label: 'ID',
prop: 'id',
show: true,
2021-07-07 14:49:51 +08:00
width: 160
}, {
2021-03-19 18:52:19 +08:00
label: this.$t('alert.alertName'),
prop: 'alertRule',
2021-07-07 14:49:51 +08:00
show: true
}, {
2021-03-19 18:52:19 +08:00
label: this.$t('alert.list.labels'),
prop: 'labels',
show: true,
NotSet: true,
2021-07-07 14:49:51 +08:00
minWidth: 250
2021-03-19 18:52:19 +08:00
}, {
label: this.$t('alert.severity'),
prop: 'severityId',
2021-03-19 18:52:19 +08:00
show: true,
2021-07-07 14:49:51 +08:00
width: 110
2021-03-19 18:52:19 +08:00
}, {
label: this.$t('alert.summary'),
prop: 'summary',
show: true,
minWidth: 200
2021-03-19 18:52:19 +08:00
}, {
label: this.$t('overall.remark'),
2021-03-19 18:52:19 +08:00
prop: 'description',
2021-07-02 11:45:22 +08:00
show: true,
minWidth: 200
2021-03-19 18:52:19 +08:00
}, {
label: this.$t('alert.list.state'),
prop: 'state',
show: true,
width: 100
}, {
2021-03-19 18:52:19 +08:00
label: this.$t('alert.startAt'),
prop: 'startAt',
2021-07-02 11:45:22 +08:00
show: true,
2021-07-07 14:49:51 +08:00
width: 150
2021-03-19 18:52:19 +08:00
}, {
label: this.$t('config.terminallog.duration'),
prop: 'duration',
show: true,
width: 150
}, {
2021-03-19 18:52:19 +08:00
label: this.$t('alert.endAt'),
prop: 'endAt',
2021-07-02 11:45:22 +08:00
show: true,
width: 160
2021-03-19 18:52:19 +08:00
}
],
tablelable: [],
dropCol: [],
toTopBtnTop: this.$tableHeight.toTopBtnTop, // to-top按钮的top属性
tableHover: false, // 控制滚动条和top按钮同时出现
showTopBtn: false,
graphShow: false,
chartDatas: [],
searchTimeDialog: [],
2021-03-19 18:52:19 +08:00
chartUnit: 5,
deleteBox: { show: false, ids: '', remark: '', state: 2 },
isPreview: false,
ps: null,
resultType: '',
logData: [],
chartLoading: false,
dialogShowText: false,
dialogText: ''
2021-03-19 18:52:19 +08:00
}
},
2020-05-28 17:32:23 +08:00
computed: {
2021-03-19 18:52:19 +08:00
tagType () {
2020-05-28 17:32:23 +08:00
return (key) => {
if (key == 'asset' || key == 'module' || key == 'project' || key == 'datacenter' || key == 'endpoint') {
2021-03-19 18:52:19 +08:00
return 'normal'
2020-05-28 17:32:23 +08:00
} else {
2021-03-19 18:52:19 +08:00
return 'info'
2020-05-28 17:32:23 +08:00
}
}
},
2021-03-19 18:52:19 +08:00
tagValue () {
2020-05-28 17:32:23 +08:00
return (key, value) => {
if (key == 'type') {
2021-03-19 18:52:19 +08:00
if (value == 1) {
value = this.$t('project.project.projectName')
2020-05-28 17:32:23 +08:00
} else if (value == 2) {
2021-03-19 18:52:19 +08:00
value = this.$t('module.module.module')
2020-05-28 17:32:23 +08:00
} else if (value == 3) {
2021-03-19 18:52:19 +08:00
value = this.$t('asset.asset')
2020-05-28 17:32:23 +08:00
}
}
2021-03-19 18:52:19 +08:00
return key + '' + value
2020-05-28 17:32:23 +08:00
}
}
},
2021-03-19 18:52:19 +08:00
watch: {
chartInfo: {
deep: true,
immediate: true,
handler (n, o) {
if (n.id) {
if (!n.param.state && n.param.state != Number) {
n.param.state = '1'
}
if (n.param.severity && n.param.severity != Number) {
n.param.severity = 1
}
}
2021-03-19 18:52:19 +08:00
this.data = Object.assign({}, n)
2020-05-28 17:32:23 +08:00
}
},
2021-03-19 18:52:19 +08:00
panelId: {
immediate: true,
handler (n, o) {
this.panelIdInner = n
}
},
dropdownMenuShow (n) {
this.$emit('dropmenu-change', n)
}
},
methods: {
startResize (e) {
const vm = this
this.$chartResizeTool.start(vm, this.data, e)
},
2021-05-21 22:15:40 +08:00
formatThreshold (value, unit) {
2021-03-19 18:52:19 +08:00
const unitMethod = chartDataFormat.getUnit(unit)
if (unitMethod && value) {
return unitMethod.compute(value, null, 2)
} else {
return value
}
},
2021-05-21 22:15:40 +08:00
computeDistance (str) {
2021-03-19 18:52:19 +08:00
let width = 0
const html = document.createElement('span')
html.innerText = str
html.className = 'getTextWidth'
document.querySelector('body').appendChild(html)
width = document.querySelector('.getTextWidth').offsetWidth
document.querySelector('.getTextWidth').remove()
return Number('-' + (width + 5))
},
2021-05-21 22:15:40 +08:00
returnMarkArea () {
2021-03-19 18:52:19 +08:00
if (this.currentMsg) {
if (this.currentMsg.alertRule.operator == '>' || this.currentMsg.alertRule.operator == '>=') {
return [{ yAxis: this.currentMsg.alertRule.threshold }, {}]
} else {
return [{}, { yAxis: this.currentMsg.alertRule.threshold }]
2020-05-28 17:32:23 +08:00
}
2021-03-19 18:52:19 +08:00
}
},
detail (obj) {
this.chartDatas = []
this.legend = []
this.graphShow = true
this.currentMsg = obj
this.chartUnit = obj.alertRule.unit ? obj.alertRule.unit : 5
this.$nextTick(() => {
this.queryDate()
2021-03-19 18:52:19 +08:00
})
},
dialogClose () {
this.graphShow = false
},
closeDialog () {
this.importBox.show = false
this.deleteBox.show = false
},
2021-05-21 22:15:40 +08:00
screenDialogClose () {
2021-03-19 18:52:19 +08:00
this.screenModal = false
this.deleteBox.ids = []
this.$refs.alertListScreenTable.$refs.dataTable.clearSelection()
2021-03-19 18:52:19 +08:00
},
selectChange (s) {
const ids = []
this.deleteBox.ids = ''
s.forEach(item => {
ids.push(item.id)
})
this.deleteBox.ids = ids.join(',')
},
deleteMessage (row) {
const self = this
this.$confirm(this.$t('tip.confirmDelete'), {
confirmButtonText: this.$t('tip.yes'),
cancelButtonText: this.$t('tip.no'),
type: 'warning'
}).then(() => {
this.$delete('alert/message' + '?ids=' + row.id + '&state=3').then(response => {
if (response.code === 200) {
self.delFlag = true
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.deleteSuccess') })
self.getAlertList()
} else {
this.$message.error(response.msg)
}
})
2021-03-19 18:52:19 +08:00
})
},
2021-05-21 22:15:40 +08:00
chartUnitChange (unit) {
2021-03-19 18:52:19 +08:00
this.chartUnit = unit
this.$nextTick(() => {
this.queryDate()
2021-03-19 18:52:19 +08:00
})
},
messageDetail (row) {
this.$get('/alert/rule/' + row.alertRule.id).then(res => {
this.currentMsg = { ...row, alertRule: { ...res.data } }
this.graphShow = true
this.$nextTick(() => {
this.queryDate()
})
})
},
2021-03-19 18:52:19 +08:00
queryChartDate () {
const $temp = this
const start = this.searchTime[0] ? this.searchTime[0] : bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000)
const end = this.searchTime[1] ? this.searchTime[1] : bus.computeTimezoneTime(new Date().getTime())
this.searchTimeDialog = [start, end]
2021-03-19 18:52:19 +08:00
const timeDiff = (new Date(end).getTime() - new Date(start).getTime()) / 1000 / (24 * 60 * 60)
let step = '15s'
if (timeDiff < 1) {
step = '15s'
} else if (timeDiff < 7) {
step = '5m'
} else if (timeDiff < 30) {
step = '10m'
} else {
step = '30m'
}
if (this.$refs.messageChart) {
this.$refs.messageChart.startLoading()
}
const axiosArr = []
2021-05-21 22:15:40 +08:00
const paramStr = this.currentMsg ? JSON.stringify(this.promQueryParamConvert(this.currentMsg)) : null
2021-03-19 18:52:19 +08:00
if (paramStr && paramStr.trim() != '""') {
2021-06-25 17:38:34 +08:00
axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + paramStr.substring(1, paramStr.length - 1) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step))
2021-03-19 18:52:19 +08:00
this.legend = []
this.chartDatas = []
axios.all(axiosArr).then(res => {
this.chartLoading = false
2021-03-19 18:52:19 +08:00
try {
res.forEach((response, promIndex) => {
if (response.status == 200) {
if (response.data.status == 'success') {
const queryData = response.data.data.result[0]
if (queryData) {
const chartData = {
type: 'line',
symbol: 'none', // 去掉点
smooth: 0.2, // 曲线变平滑
name: '',
lineStyle: {
width: 1,
opacity: 0.9
},
markLine: {
silent: true,
symbol: ['circle', 'circle'],
label: {
distance: this.computeDistance(chartDataFormat.getUnit(this.currentMsg.alertRule.unit ? this.currentMsg.alertRule.unit : 2).compute(this.currentMsg.alertRule.threshold)),
2021-05-21 22:15:40 +08:00
formatter (params) {
2021-03-19 18:52:19 +08:00
return chartDataFormat.getUnit($temp.currentMsg.alertRule.unit ? $temp.currentMsg.alertRule.unit : 2).compute(params.value)
}
},
lineStyle: {
2021-03-19 18:52:19 +08:00
color: '#d64f40',
width: 2,
type: 'dotted'
},
2021-03-19 18:52:19 +08:00
data: [{
yAxis: Number(this.currentMsg.alertRule.threshold)
}]
},
markArea: {
itemStyle: {
color: '#d64f40',
opacity: 0.1
},
2021-03-19 18:52:19 +08:00
data: [
this.returnMarkArea()
]
2020-05-28 18:29:15 +08:00
}
2020-05-28 17:32:23 +08:00
}
2021-03-19 18:52:19 +08:00
chartData.name += '{'
let alias = chartData.name
alias += '{'
Object.keys(queryData.metric).forEach((item, index) => {
const label = item
const value = queryData.metric[label]
chartData.name += label + "='" + value + "',"
})
chartData.name = chartData.name.charAt(chartData.name.length - 1) == ',' ? chartData.name.substr(0, chartData.name.length - 1) : chartData.name
chartData.name += '}'
const legend = {
name: chartData.name,
alias: alias,
isGray: false
}
this.legend.push(legend)
chartData.data = queryData.values.map((dpsItem, dpsIndex) => {
return [bus.computeTimezone(dpsItem[0]) * 1000, parseFloat(dpsItem[1]).toFixed(2)]
})
this.chartDatas.push(chartData)
2020-05-28 17:32:23 +08:00
}
2021-03-19 18:52:19 +08:00
} else {
this.$message.error(response.data.error)
console.error(response.data)
2020-05-28 17:32:23 +08:00
}
}
2021-03-19 18:52:19 +08:00
})
this.$nextTick(() => {
this.$refs.messageChart.setRandomColors(this.chartDatas.length)
this.$refs.messageChart.setLegend(this.legend)
this.$refs.messageChart.setSeries(this.chartDatas)
this.$refs.messageChart.endLoading()
})
} catch (err) {
this.$message.error(err)
this.$refs.messageChart.endLoading()
}
2021-03-19 18:52:19 +08:00
})
}
},
2021-05-21 22:15:40 +08:00
getAlertList (filterType, isPreview = false, chartInfo) {
2021-03-19 18:52:19 +08:00
this.resize()
this.loadingTable = true
this.isPreview = isPreview
const queryParam = {
pageSize: this.pageObj.pageSize,
pageNo: this.pageObj.pageNo
}
let chart
if (chartInfo) {
chart = Object.assign({}, chartInfo)
} else {
chart = Object.assign({}, this.chartInfo)
}
if (chart && chart.param) { // 按照粒度project>module>endpoint 查询只传最细粒度
const param = chart.param
2021-05-21 22:15:40 +08:00
if (param.endpointId) {
2021-05-21 15:09:02 +08:00
queryParam.endpointIds = param.endpointId
2021-03-19 18:52:19 +08:00
} else {
2021-05-21 22:15:40 +08:00
if (param.moduleId) {
2021-05-21 15:09:02 +08:00
queryParam.moduleIds = param.moduleId
2021-03-19 18:52:19 +08:00
} else {
2021-05-21 22:15:40 +08:00
if (param.projectId) {
2021-05-21 15:09:02 +08:00
queryParam.projectIds = param.projectId
2021-03-19 18:52:19 +08:00
}
}
}
2021-05-21 22:15:40 +08:00
if (param.ruleId) {
queryParam.ruleIds = param.ruleId
2021-03-19 18:52:19 +08:00
}
2021-05-21 22:15:40 +08:00
if (param.severity) {
queryParam.severityIds = param.severity
}
2021-05-21 22:15:40 +08:00
if (param.state) {
2021-03-19 18:52:19 +08:00
queryParam.state = param.state
}
2021-03-19 18:52:19 +08:00
}
if (this.searchLabel.orderBy) {
queryParam.orderBy = this.searchLabel.orderBy
}
// this.startLoading(filterType);
this.$get('/alert/message', queryParam).then(response => {
2021-05-21 22:15:40 +08:00
if (response.code === 200) {
2021-03-19 18:52:19 +08:00
this.storedTableData = response.data.list
this.storedScreanTableData = response.data.list
this.pageObj.total = response.data.total
this.isError = false
this.errorContent = ''
this.divFirstShow = true
this.firstShow = true // 展示操作按键
this.loadingTable = false
this.endLoading(filterType)
} else {
this.isError = true
this.errorContent = response.msg
}
})
},
2021-05-21 22:15:40 +08:00
getAlerScreetList (filterType, isPreview = false, chartInfo) {
2021-03-19 18:52:19 +08:00
this.resize()
this.loadingTable = true
this.isPreview = isPreview
const queryParam = {
pageSize: this.screenPageObj.pageSize,
pageNo: this.screenPageObj.pageNo
}
let chart
if (chartInfo) {
chart = Object.assign({}, chartInfo)
} else {
chart = Object.assign({}, this.chartInfo)
}
if (chart && chart.param) { // 按照粒度project>module>endpoint 查询只传最细粒度
const param = chart.param
if (param.endpointId && param.endpointId != '') {
2021-05-21 22:15:40 +08:00
queryParam.endpointIds = param.endpointId
2021-03-19 18:52:19 +08:00
} else {
if (param.moduleId && param.moduleId != '') {
2021-05-21 22:15:40 +08:00
queryParam.moduleIds = param.moduleId
2021-03-19 18:52:19 +08:00
} else {
if (param.projectId && param.projectId != '') {
2021-05-21 22:15:40 +08:00
queryParam.projectIds = param.projectId
}
}
2021-03-19 18:52:19 +08:00
}
2021-03-19 18:52:19 +08:00
if (param.ruleId && param.ruleId != '') {
2021-05-21 22:15:40 +08:00
queryParam.ruleIds = param.ruleId
}
2021-03-19 18:52:19 +08:00
if (param.severity && param.severity != '') {
2021-05-21 22:15:40 +08:00
queryParam.severityIds = param.severity
}
2021-03-19 18:52:19 +08:00
if (param.state && param.state != '') {
queryParam.state = param.state
}
2021-03-19 18:52:19 +08:00
}
if (this.searchLabel.orderBy) {
queryParam.orderBy = this.searchLabel.orderBy
}
this.startLoading(filterType)
this.$get('/alert/message', queryParam).then(response => {
if (response.code == 200) {
this.storedTableData = response.data.list
this.storedScreanTableData = response.data.list
const axiosAll = []
this.$nextTick(() => {
this.storedScreanTableData.forEach((item) => {
item.labels = JSON.parse(item.labels)
2021-05-21 22:15:40 +08:00
if (item.alertRule.buildIn !== 1) {
2021-03-19 18:52:19 +08:00
const paramStr = JSON.stringify(this.promQueryParamConvert(item))
2021-06-25 17:38:34 +08:00
axiosAll.push(axios.get('/prom/api/v1/query?query=' + paramStr.substring(1, paramStr.length - 1)))
2021-03-19 18:52:19 +08:00
} else {
axiosAll.push('')
}
})
axios.all(axiosAll).then(res => {
res.forEach((item, index) => {
let current = []
const response2 = item.data
if (response2.data && response2.data.result && response2.data.result.length > 0) {
current = response2.data.result[0].value.map((item, i) => {
if (i == 0) {
return bus.computeTimezone(item)
} else {
return parseFloat(item).toFixed(2)
}
})
} else {
current = [null, null]
}
this.storedScreanTableData[index].current = current
})
this.$set(this.storedScreanTableData, [...this.storedScreanTableData])
})
})
this.screenPageObj.total = response.data.total
this.isError = false
this.errorContent = ''
this.divFirstShow = true
2020-05-28 17:32:23 +08:00
2021-03-19 18:52:19 +08:00
this.firstShow = true // 展示操作按键
this.loadingTable = false
this.endLoading(filterType)
} else {
this.isError = true
this.errorContent = response.msg
}
2021-03-19 18:52:19 +08:00
})
},
screenRefreshChart () {
this.getAlerScreetList()
},
promQueryParamConvert (obj) {
let r = '(' + obj.alertRule.expr.replace(/\"/g, '\'') + ')'
let intoLabels = false
obj.labels = JSON.parse(obj.labels)
if (Object.keys(obj.labels).length > 0) {
r += (function () {
let group = ' and ' + '(group({'
let by = ' by ('
2021-03-19 18:52:19 +08:00
for (const k in obj.labels) {
if (k != 'alertname' && k != 'severity' && k != 'severity_id' && k != 'rule_type') {
intoLabels = true
group += k
group += '='
group += ("'" + obj.labels[k] + "',")
by += k
by += ','
2020-05-28 17:32:23 +08:00
}
2021-03-19 18:52:19 +08:00
}
if (intoLabels) {
group = group.substring(0, group.length - 1)
by = by.substring(0, by.length - 1)
group += '})'
by += ')'
return group + by + ')'
} else {
return ''
}
}())
2021-03-19 18:52:19 +08:00
}
return r
2021-03-19 18:52:19 +08:00
},
elementsetShow (s, e) {
const eventfixed = {
shezhi: 0,
screen: 0
}
eventfixed[s] = 1
e.preventDefault()
this.$store.commit('setHeaderTable', this.tablelable)
this.$store.commit('setEventfixed', eventfixed)
const h = document.documentElement.clientHeight
const w = document.documentElement.clientWidth
const dw = this.$refs.elementset.$el.offsetWidth
const dh = this.$refs.elementset.$el.offsetHeight
const positionx =
e.clientX + dw <= w - 10 ? e.clientX + 14 : e.clientX + 14 - dw
const positiony =
e.clientY + dh <= h - 10
? e.clientY + 20
: e.clientY + 20 - (e.clientY + dh - h)
this.$store.commit('setPosition', { positionx, positiony })
},
elementsetHide () {
// 悬浮点击空白隐藏
this.$refs.elementset.elementsetHide()
},
tablelabelEmit (data) {
// 获取子组件传过来的参数
this.$store.commit('setHeaderTable', data)
this.tablelable = data
},
pageNo (val) {
this.pageObj.pageNo = val
this.getAlertList()
},
pageSize (val) {
this.pageObj.pageSize = val
this.getAlertList()
},
2020-05-28 17:32:23 +08:00
2021-03-19 18:52:19 +08:00
screenPageNo (val) {
this.screenPageObj.pageNo = val
this.getAlerScreetList()
},
screenPageSize (val) {
this.screenPageObj.pageSize = val
this.getAlerScreetList()
2020-05-28 17:32:23 +08:00
},
2021-03-19 18:52:19 +08:00
startLoading (area) {
if (area === 'showFullScreen') {
// this.showLoadingScreen = true;
this.$refs['localLoadingScreen' + this.chartIndex].startLoading()
} else {
// this.showLoading = true;
this.$refs['localLoading' + this.chartIndex].startLoading()
2020-05-28 17:32:23 +08:00
}
},
2021-03-19 18:52:19 +08:00
endLoading (area) {
if (area === 'showFullScreen') {
// this.showLoadingScreen = false;
this.$refs['localLoadingScreen' + this.chartIndex].endLoading()
} else {
// this.showLoading = false;
this.$refs['localLoading' + this.chartIndex].endLoading()
}
},
resize (chartItem) {
const deHeight = this.$chartResizeTool.titleHeight + this.$chartResizeTool.chartTableBlankHeight
// const container = document.querySelector('#chartTableDiv' + this.chartIndex + ' .table-container')
// container.style.height = `calc(100% - ${deHeight}px)`
2021-03-19 18:52:19 +08:00
this.tableHeight = 'calc(100% - 34px)'
},
showLoad (chartItem) {
// 设置高度 chart-table
this.$nextTick(() => {
this.resize(chartItem)
})
this.startLoading()
this.divFirstShow = true
},
// 重新请求数据 刷新操作-local
refreshChart () {
this.dropdownMenuShow = false
this.startLoading()
this.firstShow = false
this.$emit('on-refresh-data', this.data.id)
},
// 编辑图表
editChart () {
this.dropdownMenuShow = false
this.$emit('on-edit-chart-block', this.data.id)
},
// 删除该图表
removeChart () {
this.dropdownMenuShow = false
this.$emit('on-remove-chart-block', this.data.id)
},
// 全屏时间条件查询
dateChange (time) {
// this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss');
// this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss');
// this.showTable = false;
this.seriesItemScreen = []
for (let i = 0; i < 8; i++) {
this.seriesItemScreen.push({ // 表格数据
// label: '',//label
// metric: '',//metric列
element: '',
time: '', // 采集时间
value: ''// 数值
})
}
2021-03-19 18:52:19 +08:00
// this.startLoading('screen');
// this.tableLoading = true;
// this.firstShow = false;
this.$emit('on-search-data', this.data.id, this.searchTime)
},
clickos () {
this.dropdownMenuShow = false
},
clearChart () {
this.data = {}
},
duplicate () {
this.dropdownMenuShow = false
this.$emit('on-duplicate-chart-block', this.data.id)
2020-05-28 17:32:23 +08:00
},
2021-03-19 18:52:19 +08:00
// 全屏查看
showAllScreen () {
this.dropdownMenuShow = false
// this.storedScreanTableData = this.storedTableData
this.storedScreanTableData = JSON.parse(JSON.stringify(this.storedTableData))
2021-03-19 18:52:19 +08:00
this.screenModal = true
this.deleteBox.ids = []
// this.$refs.alertListTable.$refs.alertListTable.clearSelection()
// this.$refs.alertListScreenTable.$refs.dataTable.clearSelection()
2021-03-19 18:52:19 +08:00
this.screenPageObj = { ...this.pageObj }
},
// 设置数据, filter区分
setData (chartItem, seriesItem, panelId, filter, area, errorMsg) {
// console.info(chartItem,title)
},
// 数据排序
tableDataSort (item) {
let orderBy = ''
if (item.order === 'ascending') {
orderBy = item.prop
}
if (item.order === 'descending') {
orderBy = '-' + item.prop
}
this.$set(this.searchLabel, 'orderBy', orderBy)
this.getAlertList()
2021-09-02 14:43:06 +08:00
},
queryDate () {
this.chartLoading = true
if (this.currentMsg.alertRule.type === 1) {
this.resultType = 'matrix'
this.$nextTick(() => {
this.queryChartDate()
})
} else if (this.currentMsg.alertRule.type === 2) {
this.queryLogData(1000)
}
},
exportLog ({ limit, descending }) {
const start = this.searchTimeDialog[0] ? this.searchTimeDialog[0] : bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000)
const end = this.searchTimeDialog[1] ? this.searchTimeDialog[1] : bus.computeTimezoneTime(new Date().getTime())
const params = {
logql: this.expressions,
start: start,
end: end,
direction: descending ? 'backward' : 'forward',
limit
}
axios.get('/logs/loki/export', { responseType: 'blob', params: params }).then(res => {
if (window.navigator.msSaveOrOpenBlob) {
// 兼容ie11
const blobObject = new Blob([res.data])
window.navigator.msSaveOrOpenBlob(blobObject, 'log')
} else {
const url = URL.createObjectURL(new Blob([res.data]))
const a = document.createElement('a')
document.body.appendChild(a) // 此处增加了将创建的添加到body当中
a.href = url
a.download = 'log'
a.target = '_blank'
a.click()
a.remove() // 将a标签移除
}
}, error => {
const $self = this
const reader = new FileReader()
reader.onload = function (event) {
const responseText = reader.result
const exception = JSON.parse(responseText)
if (exception.message) {
$self.$message.error(exception.message)
} else {
console.error(error)
}
}
reader.readAsText(error.response.data)
})
},
queryLogData (limit) { // log的chart和table是一个请求
if (!limit) {
limit = 1000
}
const start = this.searchTimeDialog[0] ? this.searchTimeDialog[0] : bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000)
const end = this.searchTimeDialog[1] ? this.searchTimeDialog[1] : bus.computeTimezoneTime(new Date().getTime())
this.expressions = [this.currentMsg.alertRule.expr]
this.$get('/logs/loki/api/v1/query_range?format=1&query=' + this.currentMsg.alertRule.expr + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&limit=' + limit).then(res => {
this.chartLoading = false
const logData = [res.data]
this.resultType = res.data.resultType
this.$nextTick(() => {
if (this.$refs.logDetail) {
this.$refs.logDetail.time = this.chartData.param.time
this.$refs.logDetail.wrapLines = this.chartData.param.wrapLines
this.$refs.logDetail.operations.descending = this.chartData.param.descending
}
// logData.forEach((item, index) => {
// item.result.forEach(result => {
// result.elements = this.expressions[index]
// })
// })
this.logData = logData
this.resultType === 'matrix' && this.loadLogGraph()
})
})
},
loadLogGraph () {
const graphData = this.logData.filter(l => l.resultType === 'matrix')
if (graphData && graphData.length > 0) {
this.$refs.messageChart.startLoading()
const queryExpression = []
let series = []
const legend = []
this.expressions.forEach((item, index) => {
if (item !== '') {
queryExpression.push(item)
}
})
this.logData.forEach((response, index) => {
if (response.resultType === 'matrix') {
const data = response.result
if (!data || data.length < 1) {
return
}
data.forEach((result, i) => {
const seriesItem = {
name: '',
symbol: 'emptyCircle', // 去掉点
symbolSize: [2, 2],
showSymbol: false,
smooth: 0.2, // 曲线变平滑
data: [],
lineStyle: {
width: 1,
opacity: 0.9
},
type: 'line'
}
seriesItem.data = result.values.map((item) => {
return [item[0] * 1000, item[1]]
})
let host = ''// up,
let alias = ''
if (result.metric && Object.keys(result.metric).length > 0) {
const metric = Object.keys(result.metric)
if (metric.__name__) {
host = `${metric.__name__}{`// up,
}
metric.forEach((tag, i) => {
if (tag !== '__name__') {
host += `${tag}="${result.metric[tag]}",`
}
})
if (host.endsWith(',')) {
host = host.substr(0, host.length - 1)
}
if (metric.__name__) {
host += '}'
}
// 处理legend别名
// alias = this.dealLegendAlias(host, this.chartData.elements[index].legend)
if (!alias || alias === '') {
alias = host
}
} else {
alias = queryExpression[index]
}
seriesItem.name = alias + '-' + index
series.push(seriesItem)
legend.push({ name: seriesItem.name, alias: alias, isGray: false })
})
}
})
this.$refs.messageChart.setLegend(legend)
this.$refs.messageChart.setRandomColors(series.length)
if (!series.length) {
series = ''
}
this.$refs.messageChart.setSeries(series)
this.defaultChartVisible = true
this.$nextTick(() => {
this.$refs.messageChart.endLoading()
this.$refs.messageChart.resize()
})
}
},
showText (row) {
this.dialogShowText = true
this.dialogText = row.alertRule.trbShot
}
2021-03-19 18:52:19 +08:00
},
created () {
// 是否存在分页缓存
const pageSize = localStorage.getItem('nz-pageSize-' + localStorage.getItem('nz-username') + '-' + this.tableId)
if (pageSize != 'undefined' && pageSize != null) {
this.pageObj.pageSize = pageSize
}
},
mounted () {
this.firstLoad = false
this.tablelable = localStorage.getItem('nz-tableTitle-' + localStorage.getItem('nz-username') + '-' + '/alertList')
? JSON.parse(localStorage.getItem('nz-tableTitle-' + localStorage.getItem('nz-username') + '-' + '/alertList'))
: this.tableTitle
this.dropCol = localStorage.getItem('nz-tableTitle-' + localStorage.getItem('nz-username') + '-' + '/alertList')
? JSON.parse(localStorage.getItem('nz-tableTitle-' + localStorage.getItem('nz-username') + '-' + '/alertList'))
: this.tableTitle
},
beforeDestroy () {
this.clearChart()
if (this.ps) {
this.ps.destroy()
}
}
}
2020-05-28 17:32:23 +08:00
</script>
2021-07-02 14:03:17 +08:00
<style scoped>
.table-container{
height: calc(100% - 40px);
}
</style>