stye: 修改 Process state tooltip位置

This commit is contained in:
zhangyu
2022-09-14 11:14:45 +08:00
parent 688503a1f7
commit c507ed4155
5 changed files with 247 additions and 91 deletions

View File

@@ -9,8 +9,8 @@ export default {
exportToHtml (name) { exportToHtml (name) {
const vars = this.$store.getters.getVariablesArr.map(item => { const vars = this.$store.getters.getVariablesArr.map(item => {
return { return {
"name": item.name, name: item.name,
"value": item.checked.join('|') value: item.checked.join('|')
} }
}) })
const params = { const params = {
@@ -52,7 +52,7 @@ export default {
window.URL.revokeObjectURL(href) // 释放blob对象 window.URL.revokeObjectURL(href) // 释放blob对象
} }
this.$refs.topTool.closeDialog() this.$refs.topTool.closeDialog()
}, error => { }, () => {
this.$message.error('123') this.$message.error('123')
}) })
} }

View File

@@ -39,7 +39,7 @@
<template slot-scope="scope" :column="item"> <template slot-scope="scope" :column="item">
<template v-if="item.prop === 'commandLine'"> <template v-if="item.prop === 'commandLine'">
<div style="height:24px;display: flex;align-items: center;"> <div style="height:24px;display: flex;align-items: center;">
<el-popover trigger="hover" placement="top" v-if="typeof scope.row.state != 'undefined' && scope.row.state != null"> <el-popover trigger="hover" placement="right" v-if="typeof scope.row.state != 'undefined' && scope.row.state != null">
<div> <div>
<span class="metirc-tip-list">{{$t('overall.state')}}&nbsp;:&nbsp;&nbsp;</span><span>{{ scope.row.state }}</span> <span class="metirc-tip-list">{{$t('overall.state')}}&nbsp;:&nbsp;&nbsp;</span><span>{{ scope.row.state }}</span>
</div> </div>

View File

@@ -32,26 +32,41 @@
<!-- <template slot="added-text">{{$t('dashboard.metricPreview.runQuery')}}</template> --> <!-- <template slot="added-text">{{$t('dashboard.metricPreview.runQuery')}}</template> -->
<template slot="added-text">{{$t('overall.query')}}</template> <template slot="added-text">{{$t('overall.query')}}</template>
</pick-time> </pick-time>
<button v-if="showMetrics" <el-dropdown trigger="click" :size="'medium'">
id="explore-save-chart" <button id="more" class="top-tool-btn" :title="$t('overall.more')">
v-has="'main_add'" <i class="nz-icon nz-icon-more2"></i>
:class="{'nz-btn-disabled btn-disabled-cursor-not-allowed' : saveDisabled}" </button>
:disabled="saveDisabled" <el-dropdown-menu slot="dropdown" class="right-box-select-top right-public-box-dropdown-top">
class="top-tool-btn top-tool-btn--text" <el-dropdown-item :disabled="saveDisabled">
type="button" <div>
@click="saveChart"> <i class="nz-icon nz-icon-add" />
{{$t('dashboard.metric.saveChart')}} <span v-if="showMetrics"
</button> id="explore-save-chart"
<button v-else v-has="'main_add'"
id="explore-save-chart-logs" :class="{'btn-disabled-cursor-not-allowed' : saveDisabled}"
v-has="'main_add'" :disabled="saveDisabled"
:class="{'nz-btn-disabled btn-disabled-cursor-not-allowed' : saveDisabled}" class="top-tool-btn top-tool-btn--text"
:disabled="saveDisabled" type="button"
class="top-tool-btn top-tool-btn--text" @click="saveChart">
type="button" {{$t('dashboard.metric.saveChart')}}
@click="saveChartLogs"> </span>
{{$t('dashboard.metric.saveChart')}} <span v-else
</button> id="explore-save-chart-logs"
v-has="'main_add'"
:class="{'btn-disabled-cursor-not-allowed' : saveDisabled}"
:disabled="saveDisabled"
class="top-tool-btn top-tool-btn--text"
type="button"
@click="saveChartLogs">
{{$t('dashboard.metric.saveChart')}}
</span>
</div>
</el-dropdown-item>
<el-dropdown-item>
<div id="chart-export-html" @click="exportToHtml"><i class="nz-icon nz-icon-kuaizhao"></i>{{ $t('overall.snapshoot') }}</div>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div> </div>
</div> </div>
<div id="explore-promql-box" class="top-tools" style="padding-top: 0; flex-wrap: wrap"> <div id="explore-promql-box" class="top-tools" style="padding-top: 0; flex-wrap: wrap">
@@ -1662,6 +1677,50 @@ export default {
} }
letter += self.letter[num % 26] letter += self.letter[num % 26]
return letter return letter
},
exportToHtml (name) {
const params = {
type: this.showMetrics ? 1 : 2,
start: this.momentStrToTimestamp(this.filterTime[0]) / 1000,
end: this.momentStrToTimestamp(this.filterTime[1]) / 1000,
unit: this.chartUnit,
expressions: [...this.expressions]
}
this.$get('/visual/explore/snapshot', params, 'blob').then(res => {
const self = this
let fileName = this.showMetrics ? 'Metrics explore' : 'Logs explore'
const resFileName = ''
if (resFileName) {
fileName = resFileName
}
if (res.type == 'application/json') {
const reader = new FileReader() // 创建一个FileReader实例
reader.readAsText(res, 'utf-8') // 读取文件,结果用字符串形式表示
reader.onload = function () { // 读取完成后,**获取reader.result**
const { msg } = JSON.parse(reader.result)
self.$message.error(msg) // 弹出错误提示
}
return
}
if (window.navigator.msSaveOrOpenBlob) {
// 兼容ie11
const blobObject = new Blob([res])
window.navigator.msSaveOrOpenBlob(blobObject, fileName + '.html')
} else {
const blob = new Blob([res])
const link = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 下载链接
link.href = href
link.download = fileName + '.html' // 下载后文件名
document.body.appendChild(link)
link.click() // 点击下载
document.body.removeChild(link) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放blob对象
}
this.$refs.topTool.closeDialog()
}, () => {
this.$message.error('123')
})
} }
}, },
watch: { watch: {

View File

@@ -1,11 +1,21 @@
<template> <template>
<div class="explore list-page"> <div class="explore list-page" style="background: #f9f9f9;padding: 10px 15px;">
<div> <div style="display: flex;justify-content: space-between">
<span>{{dataJson.type}}</span> <span>{{dataJson.type == 1 ? 'Metric expression' : 'Log expression'}}</span>
<span>{{dataJson.unit}}</span> <span>
<chart-unit v-model="chartUnit" class="margin-r-10"></chart-unit>
</span>
</div> </div>
<div v-for="(item, index) in dataJson.data" :key = 'index'> <div v-for="(item, index) in dataJson.data" :key = 'index' style="display: flex;margin-bottom: 10px">
{{item.expression}} <div style="flex: 1;margin-right: 10px;border: 1px solid #333;border-radius: 2px;">{{item.expression}}</div>
<button
class="top-tool-btn"
:title="item.state?$t('overall.enabled'):$t('profile.close')"
@click="stateChange(index)"
>
<i v-if="item.state" class="nz-icon nz-icon-mimakejian"></i>
<i v-else class="nz-icon nz-icon-mimabukejian" style="fontSize:16px"></i>
</button>
</div> </div>
<el-collapse v-model="collapseValue" class="explore-collapse" @change="logsCollapseChange"> <el-collapse v-model="collapseValue" class="explore-collapse" @change="logsCollapseChange">
<!--metric--> <!--metric-->
@@ -99,14 +109,21 @@ import chartDataFormat from '@/components/chart/chartDataFormat'
import bus from '@/libs/bus' import bus from '@/libs/bus'
import chart from '@/components/page/dashboard/overview/chart' import chart from '@/components/page/dashboard/overview/chart'
import logTab from '@/components/page/dashboard/explore/logTab' import logTab from '@/components/page/dashboard/explore/logTab'
import axios from "axios"; import chartUnit from '@/components/common/chartUnit'
const dataJson = window.dataJson || {} const dataJson = window.dataJson || {}
export default { export default {
name: 'exploreItemHtml', name: 'exploreItemHtml',
props: {
triggerButtonClass: { // 触发下拉事件的按钮的class
type: String,
default: 'top-tool-btn'
}
},
components: { components: {
chart, chart,
logTab logTab,
'chart-unit': chartUnit
}, },
data () { data () {
return { return {
@@ -125,6 +142,8 @@ export default {
showCustomTableTitle: false, // 自定义列弹框是否显示 showCustomTableTitle: false, // 自定义列弹框是否显示
customTableTitle: [] // 自定义列工具的数据 customTableTitle: [] // 自定义列工具的数据
}, },
tableId: 'explore',
tableTitle: [],
tableData: [], tableData: [],
historyParam: { useHistory: true, key: 'expore-history' }, historyParam: { useHistory: true, key: 'expore-history' },
showTab: ['1', '2'], showTab: ['1', '2'],
@@ -134,6 +153,15 @@ export default {
} }
}, },
mounted () { mounted () {
dataJson.data.forEach(item => {
item.state = true
})
if (this.dataJson.type == 1) {
this.showMetrics = true
} else {
this.showMetrics = false
}
this.chartUnit = this.dataJson.unit || 1
this.expressionChange() this.expressionChange()
}, },
methods: { methods: {
@@ -158,6 +186,10 @@ export default {
this.pageObj.pageSize = val this.pageObj.pageSize = val
this.tableData = this.filterShowData(this.storedTableData, this.pageObj) this.tableData = this.filterShowData(this.storedTableData, this.pageObj)
}, },
stateChange (index) {
this.dataJson.data[index].state = !this.dataJson.data[index].state
this.expressionChange()
},
expressionChange () { expressionChange () {
this.filterTime = [dataJson.start, dataJson.end] this.filterTime = [dataJson.start, dataJson.end]
this.pageObj.pageNo = 1 this.pageObj.pageNo = 1
@@ -182,6 +214,9 @@ export default {
this.tableData = [] this.tableData = []
this.tableTitle = [] this.tableTitle = []
res.forEach((response, index) => { res.forEach((response, index) => {
if (!response.state) {
return
}
if (response.data) { if (response.data) {
const data = response.data.result const data = response.data.result
if (data) { if (data) {
@@ -253,6 +288,9 @@ export default {
const legend = [] const legend = []
if (res.length > 0) { if (res.length > 0) {
res.forEach((response, index) => { res.forEach((response, index) => {
if (!response.state) {
return
}
const promqlIndex = promqlInputIndexs[index] const promqlIndex = promqlInputIndexs[index]
console.log(response) console.log(response)
if (response.data) { if (response.data) {
@@ -401,74 +439,133 @@ export default {
}, },
queryLogData (limit) { // log的chart和table是一个请求 queryLogData (limit) { // log的chart和table是一个请求
this.chartLoading = true this.chartLoading = true
if (!limit) {
limit = this.$refs.logDetail ? this.$refs.logDetail.getLimit() : 100
}
this.$refs.logDetail && this.$refs.logDetail.resetOperation() this.$refs.logDetail && this.$refs.logDetail.resetOperation()
if (this.expressions.length > 0) { let res = this.dataJson.data
const requestArr = [] if (res.length > 0) {
// 过滤掉state为0的元素 this.chartLoading = false
this.expressions.forEach((item, index) => { const errorRowIndex = []
if (item != '' && this.promqlKeys[index].state) { res.forEach((r, i) => {
requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(item) + '&start=' + this.$stringTimeParseToUnix(bus.formateTimeToTime(this.filterTime[0])) + '&end=' + this.$stringTimeParseToUnix(bus.formateTimeToTime(this.filterTime[1])) + '&limit=' + limit)) if (!r.state) {
return
}
if (typeof r === 'string') {
errorRowIndex.push(i)
} }
}) })
if (requestArr.length > 0) { if (errorRowIndex.length > 0) {
this.showIntroduce = false this.$message.error(this.$t('tip.errorInRow') + ': ' + errorRowIndex.map(e => e + 1).join(' ,'))
this.saveDisabled = false res = res.filter((r, i) => errorRowIndex.indexOf(i) === -1)
} }
axios.all(requestArr).then(res => { res = res.filter((r, i) => r.state)
this.chartLoading = false if (res.length > 0) {
const errorRowIndex = [] const logData = res.map(r => r.data)
res.forEach((r, i) => { if (logData[0].result.length > 0) {
if (typeof r === 'string') { this.logTabNoData = false
errorRowIndex.push(i) } else {
} this.logTabNoData = true
})
if (errorRowIndex.length > 0) {
this.$message.error(this.$t('tip.errorInRow') + ': ' + errorRowIndex.map(e => e + 1).join(' ,'))
res = res.filter((r, i) => errorRowIndex.indexOf(i) === -1)
} }
if (res.length > 0) { const hasGraph = logData.some(d => d.resultType === 'matrix')
const logData = res.map(r => r.data) const hasLog = logData.some(d => d.resultType === 'streamsFormat')
if (logData[0].result.length > 0) { const graphTabIndex = this.showTab.indexOf('1')
this.logTabNoData = false if (hasGraph) {
} else { if (graphTabIndex === -1) {
this.logTabNoData = true this.showTab.push('1')
} }
const hasGraph = logData.some(d => d.resultType === 'matrix') } else {
const hasLog = logData.some(d => d.resultType === 'streamsFormat') if (graphTabIndex > -1) {
const graphTabIndex = this.showTab.indexOf('1') this.showTab.splice(graphTabIndex, 1)
if (hasGraph) {
if (graphTabIndex === -1) {
this.showTab.push('1')
}
} else {
if (graphTabIndex > -1) {
this.showTab.splice(graphTabIndex, 1)
}
} }
const logTabIndex = this.showTab.indexOf('2') }
if (hasLog) { const logTabIndex = this.showTab.indexOf('2')
if (logTabIndex === -1) { if (hasLog) {
this.showTab.push('2') if (logTabIndex === -1) {
} this.showTab.push('2')
} else {
if (logTabIndex > -1) {
this.showTab.splice(logTabIndex, 1)
}
} }
this.$nextTick(() => { } else {
this.logData = logData if (logTabIndex > -1) {
hasGraph && this.loadLogGraph() this.showTab.splice(logTabIndex, 1)
}
}
this.$nextTick(() => {
this.logData = logData
hasGraph && this.loadLogGraph()
})
}
}
},
loadLogGraph () {
const graphData = this.logData.filter(l => l.resultType === 'matrix')
if (graphData && graphData.length > 0) {
this.$refs.logChart.startLoading()
const queryExpression = []
let series = []
const legend = []
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'
}
let legendName = ''
seriesItem.data = result.values.map((item) => {
return [item[0] * 1000, item[1]]
})
if (result.metric && Object.keys(result.metric).length > 0) {
const metric = Object.assign({}, result.metric)
seriesItem.name += metric.__name__ ? metric.__name__ : ''
seriesItem.name += '{'
delete metric.__name__
for (const key in metric) {
seriesItem.name += key + '=' + '"' + metric[key] + '",'
}
legendName = seriesItem.name.substr(0, seriesItem.name.length - 1)
legendName += '}'
} else {
legendName = queryExpression[index]
}
seriesItem.name = legendName + '-' + index
series.push(seriesItem)
legend.push({ name: seriesItem.name, alias: legendName, isGray: false })
}) })
} }
}).catch(e => { })
this.chartLoading = false this.defaultChartVisible = true
this.$message.error(this.$t('terminallog.statusItem.unknownError')) this.$nextTick(() => {
this.$refs.logChart.setLegend(legend)
this.$refs.logChart.setRandomColors(series.length)
if (!series.length) {
series = ''
}
this.$refs.logChart.setSeries(series)
this.$refs.logChart.endLoading()
}) })
} }
}, },
updateCustomTableTitle (custom) {
this.tools.customTableTitle = custom
this.$refs.exploreTable.doLayout()
}
},
watch: {
chartUnit: {
handler (n, o) {
this.expressionChange()
}
}
} }
} }
</script> </script>

View File

@@ -13,12 +13,12 @@
<div style="display: flex;flex-direction: column"> <div style="display: flex;flex-direction: column">
<!-- <i class="nz-icon nz-icon-arrow-down"/>--> <!-- <i class="nz-icon nz-icon-arrow-down"/>-->
<div style="font-size: 18px;font-weight: 600;color: #333;margin-bottom: 3px;text-align: right" v-if="!dataJson.unit"> {{dataJson.panel.data.name}} </div> <div style="font-size: 18px;font-weight: 600;color: #333;margin-bottom: 3px;text-align: right" v-if="!dataJson.type"> {{dataJson.panel.data.name}} </div>
<div style="font-size: 18px;font-weight: 600;color: #333;margin-bottom: 3px;text-align: right" v-if="dataJson.unit"> Explore </div> <div style="font-size: 18px;font-weight: 600;color: #333;margin-bottom: 3px;text-align: right" v-if="dataJson.type"> Explore </div>
<span> {{dateFormat(dataJson.start * 1000)}} - {{dateFormat(dataJson.end * 1000)}} ({{dataJson.timezone}})</span> <span> {{dateFormat(dataJson.start * 1000)}} - {{dateFormat(dataJson.end * 1000)}} ({{dataJson.timezone}})</span>
</div> </div>
</div> </div>
<div v-if="!dataJson.unit" id="dashboardScrollbar" class="box-content" ref="dashboardScrollbar" style='overflow:hidden; overflow-y: auto;height: calc(100% - 60px);display: flex;flex-direction: column'> <div v-if="!dataJson.type" id="dashboardScrollbar" class="box-content" ref="dashboardScrollbar" style='overflow:hidden; overflow-y: auto;height: calc(100% - 60px);display: flex;flex-direction: column'>
<chartList <chartList
ref="chartList" ref="chartList"
name="panel" name="panel"
@@ -38,7 +38,7 @@
:loading="chartListLoading" :loading="chartListLoading"
/> />
</div> </div>
<div v-if="dataJson.unit" id="explore" class="explores"> <div v-if="dataJson.type" id="explore" class="explores">
<exploreItem <exploreItem
ref="exploreItem" ref="exploreItem"
:key="dataJson.type" :key="dataJson.type"