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/common/table/special/endpointQueryTab.vue

481 lines
16 KiB
Vue
Raw Normal View History

2021-04-20 19:27:49 +08:00
<template>
2021-11-01 17:23:01 +08:00
<div class="full-width-height endpoint-query-tab">
2021-04-20 19:27:49 +08:00
<el-table
id="endpointTable"
ref="dataTable"
:data="currentTableData"
2022-03-25 15:40:05 +08:00
v-my-loading="loading"
2021-08-26 10:43:08 +08:00
:height="'calc(100% - 48px)'"
2021-04-20 19:27:49 +08:00
border
@header-dragend="dragend"
@selection-change="selectChange"
>
<el-table-column
:resizable="false"
align="center"
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="element"
:resizable="true"
:min-width="1000"
column-key="element"
:show-overflow-tooltip="true"
2023-03-17 12:46:56 +08:00
:label="$t('dashboard.dashboard.chartForm.element')">
2021-04-20 19:27:49 +08:00
<template v-slot="scope">
<el-popover trigger="hover" placement="right">
<meta-data :metaDataList="metaDataList" :metaName="scope.row.metricTip.metric" />
<span slot="reference"><i @mouseover="metricMetaData(scope.row)" class="nz-icon nz-icon-info-normal metric-tip-icon"></i></span>
2021-04-20 19:27:49 +08:00
</el-popover>
<span style="word-break: break-all;" v-html="hideSameLabels?scope.row.colorSimpleElement: scope.row.colorElement"></span>
</template>
</el-table-column>
<el-table-column
:resizable="false"
prop="value"
column-key="value"
:label="$t('overall.value')"
2021-04-20 19:27:49 +08:00
min-width="180">
</el-table-column>
2021-10-25 11:09:34 +08:00
<template slot="empty">
2021-10-25 14:45:28 +08:00
<div v-if="!loading" class="table-no-data">
2021-10-25 11:09:34 +08:00
<svg class="icon" aria-hidden="true">
<use xlink:href="#nz-icon-no-data-list"></use>
</svg>
2021-10-28 17:53:27 +08:00
<div class="table-no-data__title">No results found</div>
2021-10-25 11:09:34 +08:00
</div>
<div v-else>&nbsp;</div>
</template>
2021-04-20 19:27:49 +08:00
</el-table>
<div class="query-page-option">
<Pagination ref="Pagination" :pageObj="pageObj" :tableId="tableId" @pageNo='pageNo' @pageSize='pageSize'></Pagination>
</div>
<el-dialog
v-if="graphShow"
:visible.sync="graphShow"
:show-close="false"
class="nz-dialog chart-fullscreen endpoint-query-metrics"
destroy-on-close
fullscreen
:modal-append-to-body="false"
>
<panel-chart
:ref="'chart-fullscreen' + chartInfo.id"
:chart-info="chartInfo"
:from="fromRoute.endpointQuery"
:filter="{}"
:is-fullscreen="true"
@saveChart="saveChart"
:time-range="searchTime"
@showFullscreen="showFullscreen"
></panel-chart>
2021-04-20 19:27:49 +08:00
</el-dialog>
<transition name="right-box">
<chart-right-box
v-if="chartRightBoxShow"
2022-03-25 15:40:05 +08:00
v-my-loading="rightBox.loading"
ref="addChartModal"
:chart="chart"
:showPanel="{}"
2023-03-15 15:39:06 +08:00
:from="fromRoute.dashboard"
:panel-data="panelData"
@close="closeChartBox"
@on-create-success="createSuccess"
></chart-right-box>
</transition>
2021-04-20 19:27:49 +08:00
</div>
</template>
<script>
import chartRightBox from '@/components/common/rightBox/chart/chartRightBox'
2021-04-20 19:27:49 +08:00
import bus from '../../../../libs/bus'
import { sameLabels, fromRoute } from '@/components/common/js/constants'
import metaData from '@/components/common/metaData'
import panelChart from '@/components/chart/panelChart'
import lodash from 'lodash'
import lineData from '@/components/chart/defaultLineData'
2021-04-20 19:27:49 +08:00
export default {
name: 'endpointQueryTab',
2021-04-20 19:27:49 +08:00
components: {
metaData,
panelChart,
chartRightBox
2021-04-20 19:27:49 +08:00
},
props: {
from: {},
obj: {},
formatTime: {},
hideSameLabels: {},
queryExpression: {}
},
watch: {
obj: {
immediate: true,
deep: true,
async handler (n) {
2021-04-20 19:27:49 +08:00
if (n) {
this.currentEndpoint = JSON.parse(JSON.stringify(n))
await this.getPreference()
2021-04-20 19:27:49 +08:00
this.queryEndpoint()
}
}
},
queryExpression (n, o) {
const temp = this
setTimeout(function () {
temp.tableFilter()
}, 500)
},
formatTime (n, o) {
const temp = this
setTimeout(function () {
temp.queryEndpoint()
}, 100)
},
batchDeleteObjs: {
immediate: true,
deep: true,
handler (n) {
if (n) {
this.$emit('selectedEndpointsChange', n)
}
}
2021-04-20 19:27:49 +08:00
}
},
data () {
return {
fromRoute,
2021-04-20 19:27:49 +08:00
tableData: [],
currentTableData: [],
2021-04-20 19:27:49 +08:00
batchDeleteObjs: [],
currentEndpoint: {},
sameLabels: sameLabels,
2021-04-20 19:27:49 +08:00
loading: false,
panelData: {},
graphShow: false,
chartUnit: 5,
rightBox: { show: false },
minusTime: 0,
searchTime: bus.getTimezontDateRange(),
tableId: 'endpointQueryTable',
pageObj: {
pageSize: 20,
pageNo: 1,
total: 0
},
2023-03-15 15:39:06 +08:00
metaDataList: [],
letter: [
'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z'
]
2021-04-20 19:27:49 +08:00
}
},
methods: {
// 获取用户偏好
async getPreference () {
const res = await this.$get('/sys/user/preference', { key: this.tableId })
if (res.data[this.tableId]) {
const data = JSON.parse(res.data[this.tableId])
this.pageObj.pageSize = data.pageSize
}
},
// 设置用户偏好
setPreference () {
const params = {
pageSize: this.pageObj.pageSize
}
this.$put('/sys/user/preference', { [this.tableId]: JSON.stringify(params) }).then(res => {
if (res.code !== 200) {
this.$message.error(res.msg || res.error)
}
})
},
2021-04-20 19:27:49 +08:00
selectChange (selection) { // selection 选中的row的数组
this.batchDeleteObjs = selection
this.$emit('changSelection', selection)
},
queryEndpoint () {
this.loading = true
this.queryElementTips()
this.queryData = []
this.tableData = []
this.tableDataCopy = ''
setTimeout(() => {
this.$get('/prom/api/v1/query?query=' + encodeURIComponent("{endpoint_id='" + this.currentEndpoint.id + "'}") + '&time=' + this.$stringTimeParseToUnix(bus.formateTimeToTime(this.formatTime))).then(response => {
2021-04-20 19:27:49 +08:00
this.loading = false
if (response.status === 'success') {
const results = response.data.result
this.queryData = JSON.parse(JSON.stringify(results))
this.tableData = this.handlerTableData(results)
this.tableDataCopy = JSON.stringify(this.tableData)
this.pageObj.total = this.tableData.length
2021-04-20 19:27:49 +08:00
this.$nextTick(this.$refs.dataTable.doLayout())
if (!this.scrollbarWrap) {
this.$nextTick(() => {
this.handleCurrentChange()
// this.scrollbarWrap = this.$refs.dataTable.$refs.singleTable.bodyWrapper
2021-04-20 19:27:49 +08:00
// this.toTopBtnHandler(this.scrollbarWrap)
})
}
}
})
}, 450)
},
queryElementTips: async function () {
this.elementMetricDatas = []
// const response = await axios.get('/metric/metadata?endpointId=' + this.currentEndpoint.id)
const response = JSON.parse(localStorage.getItem('endpointQueryData'))
if (response && response.status === 200) {
if (response.data.msg === 'success') {
this.elementMetricDatas = response.data.data.list
}
}
},
getPanelData () { // 获取panel数据
return new Promise((resolve, reject) => {
2023-03-15 15:39:06 +08:00
this.$get('visual/dashboard?pageNo=1&pageSize=-1').then(response => {
if (response.code === 200) {
this.panelData = response.data.list
resolve()
}
})
2021-04-20 19:27:49 +08:00
})
},
handlerTableData (results) {
const tableData = []
for (const result of results) {
const metricName = result.metric.__name__
let temp = metricName
let simpleTemp = metricName// 显示简略信息隐藏same labels后的结果
const metricColor = ''
const bracketsColor = '#eb7b18'// #eb7b18
const labelColor = '#65bbd1'// #66d9ef
const valueColor = '#61c261'// #74e680
let colorTemp = `<span style="${metricColor}">${metricName}</span>`
let colorSimpleTemp = `<span>${metricName}</span>`
let metricTip = {}
const queryInfos = (this.elementMetricDatas.filter((item) => {
return item.metric === temp
}))
if (queryInfos && queryInfos.length > 0) {
metricTip = queryInfos[0]
} else {
metricTip.metric = temp
}
delete result.metric.__name__
temp += '{'
simpleTemp += '{'
colorTemp += `<span style="color: ${bracketsColor}">{</span>`
colorSimpleTemp += `<span style="color: ${bracketsColor}">{</span>`
const keys = Object.keys(result.metric)
for (const index in keys) {
const key = keys[index]
temp += key + "='" + result.metric[key] + "',"
colorTemp += `<span style="color: ${labelColor}">${key}</span>=<span style="color: ${valueColor}">'${result.metric[key]}'</span>,`
if (!this.sameLabels.some((i) => { return i == key })) {
simpleTemp += key + "='" + result.metric[key] + "',"
colorSimpleTemp += `<span style="color: ${labelColor}">${key}</span>=<span style="color: ${valueColor}">'${result.metric[key]}'</span>,`
}
}
if (temp.indexOf(',') !== -1) {
temp = temp.substr(0, temp.length - 1)
}
if (simpleTemp.indexOf(',') !== -1) {
simpleTemp = simpleTemp.substr(0, simpleTemp.length - 1)
}
if (colorTemp.indexOf(',') !== -1) {
colorTemp = colorTemp.substr(0, colorTemp.length - 1)
}
if (colorSimpleTemp.indexOf(',') !== -1) {
colorSimpleTemp = colorSimpleTemp.substr(0, colorSimpleTemp.length - 1)
}
temp += '}'
simpleTemp += '}'
colorTemp += `<span style="color: ${bracketsColor}">}</span>`
colorSimpleTemp += `<span style="color: ${bracketsColor}">}</span>`
if (!/.+\{.+\}/.test(simpleTemp)) {
simpleTemp = simpleTemp.substr(0, simpleTemp.length - 2)
}
if (!/.+\{<\/span><span.+?>.+?\}/.test(colorSimpleTemp)) {
const metricReg = new RegExp('<span.*?>' + metricName + '<\/span>')
colorSimpleTemp = metricReg.exec(colorSimpleTemp)[0]
}
const edpQueryData = { element: temp, simpleElement: simpleTemp, colorElement: colorTemp, colorSimpleElement: colorSimpleTemp, value: result.value[1], type: (result.metric.type ? result.metric.type : '2'), metricTip: metricTip }
// this.tableData.push(edpQueryData);
tableData.push(edpQueryData)
}
this.loading = false
return tableData
},
tableFilter () {
const temp = this
const tableDatas = JSON.parse(this.tableDataCopy)
this.tableData = tableDatas.filter((item) => {
const element = temp.hideSameLabels ? item.simpleElement : item.element
return element.indexOf(this.queryExpression) !== -1
})
this.pageObj.pageNo = 1
this.handleCurrentChange()
2021-04-20 19:27:49 +08:00
},
dragend () {
this.$nextTick(() => {
this.$refs.dataTable.doLayout()
})
},
getTime (size, unit) { // 计算时间
const now = !this.formatTime ? new Date(bus.computeTimezone(new Date().getTime())) : new Date(this.formatTime)
if (unit) {
switch (unit) {
case 'y':
now.setFullYear(now.getFullYear() + size)
break
case 'M':
now.setMonth(now.getMonth() + size)
break
case 'd':
now.setDate(now.getDate() + size)
break
case 'h':
now.setHours(now.getHours() + size)
break
case 'm':
now.setMinutes(now.getMinutes() + size)
break
case 's':
now.setSeconds(now.getSeconds() + size)
break
default:
console.error('unit error')
}
} else {
now.setSeconds(now.getSeconds() + size)
}
const year = now.getFullYear()
let month = now.getMonth() + 1
month = month < 10 ? '0' + month : month
let day = now.getDate()
day = day < 10 ? '0' + day : day
let hour = now.getHours()
hour = hour < 10 ? '0' + hour : hour
let minute = now.getMinutes()
minute = minute < 10 ? '0' + minute : minute
let second = now.getSeconds()
second = second < 10 ? '0' + second : second
return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second
},
viewGraph () {
if (this.batchDeleteObjs.length < 1) {
return
}
this.$nextTick(() => {
const chartInfo = lodash.cloneDeep(lineData)
const elements = lodash.cloneDeep(chartInfo.elements[0])
chartInfo.elements = []
chartInfo.name = this.$t('project.endpoint.dialogTitle')
2021-04-20 19:27:49 +08:00
for (const endpoint of this.batchDeleteObjs) {
const element = lodash.cloneDeep(elements)
element.expression = endpoint.element
chartInfo.elements.push(element)
2021-04-20 19:27:49 +08:00
}
2023-03-15 15:39:06 +08:00
chartInfo.elements.forEach((item, index) => {
item.name = this.transformNumToLetter(index)
})
this.showFullscreen(true, chartInfo)
2021-04-20 19:27:49 +08:00
})
},
saveChart (chart) { // 新增chart
this.getPanelData().then(() => {
delete chart.oldElements
chart.id = ''
chart.name = ''
chart.panelName = ''
this.chart = chart
this.graphShow = false
if (!this.chart.groupId) {
this.chart.groupId = undefined
}
this.$store.dispatch('dispatchEditChart', {
chart: this.chart,
type: 'add'
})
})
2021-04-20 19:27:49 +08:00
},
createSuccess (panel) {
2023-03-15 15:39:06 +08:00
this.$confirm(this.$t('dashboard.metric.goDashboardTip'), this.$t('tip.saveSuccess'), {
2021-04-20 19:27:49 +08:00
confirmButtonText: this.$t('tip.yes'),
cancelButtonText: this.$t('tip.no'),
type: 'success'
}).then(() => {
bus.$emit('menu-change', 'panel')
this.$store.state.showPanel.id = panel.id
this.$store.state.showPanel.name = panel.name
this.$router.push({
2023-03-15 15:39:06 +08:00
path: '/dashboard',
2021-04-20 19:27:49 +08:00
query: {
t: +new Date()
}
})
})
},
pageNo (val) {
this.pageObj.pageNo = val
this.handleCurrentChange()
},
pageSize (val) {
this.pageObj.pageSize = val
this.setPreference()
this.handleCurrentChange()
},
handleCurrentChange () {
this.pageObj.total = this.tableData.length
this.currentTableData = this.tableData.slice(
(this.pageObj.pageNo - 1) * this.pageObj.pageSize,
this.pageObj.pageNo * this.pageObj.pageSize
)
},
metricMetaData (data) {
this.$get('/prom/api/v1/metadata?' + 'metric=' + data.metricTip.metric + '&limit=' + 1).then(res => {
if (res.code === 200) {
this.metaDataList = res.data[data.metricTip.metric]
}
})
},
showFullscreen (show, chartInfo) {
this.chartInfo = chartInfo
this.graphShow = show
},
closeChartBox (refresh) {
// this.rightBox.chart.show = false
this.chart = {}
this.$store.dispatch('clearPanel')
/* if (refresh) {
this.getData(this.filter)
} */
2023-03-15 15:39:06 +08:00
},
transformNumToLetter (num) { // 相当于26进制 获取idaddExpression
const self = this
let letter = ''
const loopNum = parseInt(num / 26)
if (loopNum > 0) {
letter += this.transformNumToLetter(loopNum - 1)
}
letter += self.letter[num % 26]
return letter
}
2021-04-20 19:27:49 +08:00
},
computed: {
chartRightBoxShow () {
return this.$store.getters.getShowRightBox
}
2021-04-20 19:27:49 +08:00
},
created () {
}
}
</script>