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/page/dashboard/explore/promqlInput.vue

1183 lines
37 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="promqlInput" :class=" errorMsg || appendMsg ? 'mb10' : ''">
<div class="query-row" ref="queryRow" style="position: relative">
<!--explore页面的样式-->
<template v-if="styleType == 1">
<div
v-if="plugins.indexOf('metric-input') > -1"
class="input-box"
style="margin-right: 0;"
@click="dropDownVisible = false"
>
<div
:id="pqid + 'editor'+index"
v-if="type !== 'log'"
class="not-fixed-height no-resize no-close"
style="padding-right: 24px;box-sizing: border-box"
>
</div>
<div class="zy" style="position: relative;overflow-x: hidden;display: block;border: 1px solid #dedede;width: 100%" v-if="type == 'log'">
<MonacoEditor
v-if="type == 'log'"
v-model="expressionList[index]"
theme="nz"
class="not-fixed-height no-resize"
ref="monacoEditor"
style="width: calc(100% - 24px)"
:style="{
height: monacoEditorHeight + 'px'
}"
language="logql"
:options="MONACO_EDITOR_OPTIONS"
@editorWillMount="handelBeforeMount"
@editorDidMount="handleMount"
@change="expressionChange"
/>
</div>
<div v-if="errorMsg" class="append-msg error" style="position: absolute">
<span>{{ errorMsg }}</span>
</div>
<div v-if="appendMsg" class="append-msg error" style="position: absolute">
<span>{{ appendMsg }}</span>
</div>
<i class="nz-icon nz-icon-sousuoliebiao" style="position: absolute; right: 6px" @click="queryPromptShowChange"/>
<queryPrompt v-if="queryPromptShow" @close="queryPromptShowChange" :type="type" :width="queryPromptWidth" :position="queryPromptPosition" class="no-style-class" @selectMetric="selectMetric" @selectLog="selectLog"/>
</div>
<explore-history v-if="historyshow" :type="type" @close="showHistoryBox(false)" @selectHistory="selectHistory"/>
</template>
<!--right-box里的样式-->
<template v-if="styleType === 2 || styleType === 3">
<el-row
v-if="
plugins.indexOf('metric-input') > -1 ||
plugins.indexOf('metric-selector') > -1
"
style="width: 100%"
>
<el-col
:class="
'metric-null-input-box'
"
:style="{ height: '100%' }"
>
<div
class="input-box"
@click="dropDownVisible = false"
v-if="plugins.indexOf('metric-input') > -1"
>
<div
:id="pqid + 'editor'+index"
v-if="type !== 'log'"
class="not-fixed-height no-resize no-close"
style="padding-right: 24px;box-sizing: border-box"
>
</div>
<div class="zy" style="position: relative;overflow-x: hidden;display: block;border: 1px solid #dedede;width: 100%" v-if="type == 'log'">
<MonacoEditor
v-if="type == 'log'"
v-model="expressionList[index]"
theme="nz"
class="not-fixed-height no-resize"
ref="monacoEditor"
style="width: calc(100% - 24px)"
:style="{
height: monacoEditorHeight + 'px'
}"
language="logql"
:options="MONACO_EDITOR_OPTIONS"
@editorWillMount="handelBeforeMount"
@editorDidMount="handleMount"
@change="expressionChange"
/>
</div>
</div>
<div class="append-msg error" v-if="errorMsg">
<span>{{ errorMsg }}</span>
</div>
<div class="append-msg error" v-if="appendMsg">
<span>{{ appendMsg }}</span>
</div>
</el-col>
<i class="nz-icon nz-icon-sousuoliebiao" style="position: absolute;right: 15px;height: 24px; width: 24px;line-height: 24px;" @click="queryPromptShowChange"/>
<queryPrompt v-if="queryPromptShow" @close="queryPromptShowChange" :type="type" :width="queryPromptWidth" :position="queryPromptPosition" class="no-style-class" @selectMetric="selectMetric" @selectLog="selectLog"/>
</el-row>
</template>
</div>
<div v-if="styleType == 2 && showRemove">
<div
class="option"
@click="addExpression"
:title="$t('tip.add')"
v-if="plugins.indexOf('add') > -1"
>
<i class="nz-icon nz-icon-plus"></i>
</div>
<div
class="option"
style="margin-left: 5px; line-height: 32px"
@click="removeExpression"
:title="$t('overall.delete')"
v-if="plugins.indexOf('remove') > -1"
>
<i class="nz-icon nz-icon-minus"></i>
</div>
</div>
<el-dialog
:visible.sync="tempBoxShow"
:append-to-body="true"
:width="'auto'"
:custom-class="'nz-temp-box'"
:destroy-on-close="true"
@closed="tempBoxClose"
center
>
<el-form
v-model="tempBox"
class="temp-form-box"
ref="tempFormBox"
v-if="tempBoxShow"
>
<span class="temp-form-box-title">Expression</span>
<el-form-item prop="expression">
<el-input
class="temp-form-box-input"
v-model="tempBox.expression"
size="small"
disabled
></el-input>
</el-form-item>
<span class="temp-form-box-title" v-if="tempBox.vars.length"
>Variable</span
>
<el-form-item
v-for="(item, index) in tempBox.vars"
:prop="item"
:key="index"
>
<el-row>
<el-col :span="7" class="temp-form-box-col">
<el-input
class="temp-form-box-input"
v-model="tempBox.vars[index]"
:id="'tempBox' + index"
size="small"
:disabled="true"
></el-input>
</el-col>
<el-col :span="16" v-if="format(item).key">
<select-alert-silence
:filter-silence="filterSilence"
:silence-data="format(item).arr"
:panel-lock="false"
:placement="'bottom-start'"
:typeContentLoading="typeContentLoading"
@selectSilence="
(val) => {
silenceChange(val, item);
}
"
ref="selectPanel"
style="width: 240px"
>
<template v-slot:header>
<div class="explore-select-header">
<el-input
:placeholder="$t('overall.search')"
clearable
size="mini"
style="width: 300px; padding: 0 10px"
v-model="filterSilence"
id="panel-list-search"
></el-input>
</div>
</template>
<template v-slot:trigger>
<el-input
class="panel-name"
placeholder=""
readonly="readonly"
v-model="tempBox[item]"
size="small"
>
<span
slot="suffix"
class="
el-input__icon
el-icon-circle-close
el-input__clear
"
@click.stop="clearValue(item)"
></span>
</el-input>
</template>
</select-alert-silence>
</el-col>
<el-col :span="17" v-else>
<el-input
v-model="tempBox[item]"
:id="'tempBox' + item"
size="small"
></el-input>
</el-col>
</el-row>
</el-form-item>
</el-form>
<span slot="footer">
<button
id="temp-box-esc"
class="nz-btn nz-btn-size-normal nz-btn-style-light"
@click="tempBoxShowChange(false)"
>
<span>{{ $t("overall.cancel") }}</span>
</button>
<button
id="chart-box-save"
v-has="`expressionTemplate_add`"
:disabled="prevent_opt.save"
class="nz-btn nz-btn-size-normal nz-btn-style-normal"
@click="tempBoxShowChange(true)"
>
<span>{{ $t("overall.save") }}</span>
</button>
</span>
</el-dialog>
</div>
</template>
<script>
import selectAlertSilence from '../../../common/alert/selectAlertSilence'
import { get } from '@/http'
import { PromQLExtension } from '@prometheus-io/codemirror-promql'
import { baseTheme, promqlHighlighter, lightTheme } from './CMTheme.tsx'
import { newCompleteStrategy } from '@prometheus-io/codemirror-promql/dist/esm/complete'
// import {basicSetup} from '@codemirror/basic-setup';
import { EditorView, highlightSpecialChars, keymap, ViewUpdate, placeholder } from '@codemirror/view'
import { EditorState, Prec, Compartment } from '@codemirror/state'
import { bracketMatching, indentOnInput, syntaxHighlighting, syntaxTree } from '@codemirror/language'
import { defaultKeymap, history, historyKeymap, insertNewlineAndIndent } from '@codemirror/commands'
import { highlightSelectionMatches } from '@codemirror/search'
import { lintKeymap } from '@codemirror/lint'
import {
autocompletion,
completionKeymap,
CompletionContext,
CompletionResult,
closeBrackets,
closeBracketsKeymap
} from '@codemirror/autocomplete'
import exploreHistory from '@/components/page/dashboard/explore/histoyrComponent/exploreHistory'
import MonacoEditor from '@/components/page/dashboard/explore/MonacoVue/vue-monaco'
import queryPrompt from '@/components/page/dashboard/explore/queryPrompt/queryPrompt'
import logqlMixin from '@/components/page/dashboard/explore/logql/logqlMixin'
import bus from '@/libs/bus'
export default {
name: 'promqlInput',
mixins: [logqlMixin],
components: {
selectAlertSilence,
exploreHistory,
MonacoEditor,
queryPrompt
},
props: {
index: { type: Number },
pqid: {
type: String, default: ''
},
expressionList: { type: Array },
state: { type: Number },
plugins: { type: Array },
styleType: Number,
historyParam: { type: Object },
showRemove: { type: Boolean, default: true },
projectRightBox: { type: Boolean, default: false },
metricOptionsParent: { type: Array },
inputId: String,
required: {
type: Boolean, default: false
},
showTemp: {
type: Boolean,
default: true
},
typeContentLoading: {
type: Boolean,
default: false
},
fromFatherData: {
type: Boolean,
default: false
},
type: {
type: String // metric和log两种为空时视为metric
},
isTopo: {
type: Boolean,
default: false
}
// metricOptions: {type: Array},
// metricStore: {type: Array}
},
data () {
return {
oldcCodeLength: '',
showPrompt: false,
newView: null,
codeMirrorValue: [],
dropDownVisible: false,
// metricStore:[],
metricOptions: [],
cascaderValue: '',
errorMsg: null,
appendMsg: null,
firstAddEvent: true,
tempBoxShow: false,
tempBox: {
expression: '',
vars: []
},
tempBoxShowLoading: false,
assetOption: [],
moduleOption: [],
endpointOption: [],
datacenterOption: [],
projectOption: [],
filterSilence: '',
tempBoxId: {},
loading: false,
firstInit: true,
historyshow: false,
queryPromptShow: false,
queryPromptWidth: 0,
queryPromptPosition: {
top: 0,
left: 0
}
}
},
computed: {
cascaderProps () {
if (this.type === 'log') {
return {
lazy: true,
lazyLoad (node, resolve) {
const { level } = node
if (level === 0) {
get('/logs/loki/api/v1/labels').then(res => {
if (res.data) {
const nodes = res.data.sort().map(d => ({
value: d,
label: d,
leaf: false
}))
resolve(nodes)
} else {
resolve([])
}
})
} else if (level === 1) {
get(`/logs/loki/api/v1/label/${node.value}/values`).then(res => {
if (res.data) {
const nodes = res.data.sort().map(d => ({
value: d,
label: d,
leaf: true
}))
resolve(nodes)
} else {
resolve([])
}
})
}
}
}
} else {
return { emitPath: false }
}
}
// width () {
// return
// }
},
mounted () {
if (!this.fromFatherData && this.type !== 'log') {
this.queryMetrics()
}
},
methods: {
async initCodeMirror () {
const self = this
let baseUrl = this.$axios.defaults.baseURL
if (!baseUrl || baseUrl == '/') {
baseUrl = window.location.protocol + '//' + window.location.host
}
const defaultHeaders = {
Authorization: localStorage.getItem('nz-token')
}
const promqlExtension = new PromQLExtension()
.activateCompletion(true)
.activateLinter(true)
.setComplete({
completeStrategy: new HistoryCompleteStrategy(
newCompleteStrategy({
remote: {
url: baseUrl + '/prom/',
fetchFn: (resource, options = {}) => {
const params = options.body?.toString()
const search = params ? `?${params}` : ''
return fetch(resource + search, {
method: 'Get',
headers: new Headers(
defaultHeaders
)
})
}
},
maxMetricsMetadata: 99999
})
)
})
function HistoryCompleteStrategy (CompleteStrategy) {
const obj = {}
obj.complete = CompleteStrategy
obj.queryHistory = []
obj.promQL = function (context) {
return Promise.resolve(this.complete.promQL(context)).then((res) => {
const { state, pos } = context
const tree = syntaxTree(state).resolve(pos, -1)
const start = res != null ? res.from : tree.from
if (start !== 0) {
return res
}
const historyItems = {
from: start,
to: pos,
options: this.queryHistory.map((q) => ({
label: q.length < 80 ? q : q.slice(0, 76).concat('...'),
detail: 'past query',
apply: q,
info: q.length < 80 ? undefined : q
})),
span: /^[a-zA-Z0-9_:]+$/
}
// 过滤 非logs的函数
if (res !== null) {
historyItems.options = historyItems.options.concat(res.options)
}
// console.log(historyItems)
return historyItems
})
}
return obj
}
const highlighter = syntaxHighlighting(promqlHighlighter)
const dynamicConfigCompartment = new Compartment()
const dynamicConfig = [
highlighter,
promqlExtension.asExtension(),
lightTheme
]
if (!this.newView) {
const EditorViewstate = EditorState.create({
doc: self.codeMirrorValue[self.index],
extensions: [
// basicSetup,
baseTheme,
highlightSpecialChars(),
history(),
EditorState.allowMultipleSelections.of(true),
indentOnInput(),
bracketMatching(),
closeBrackets(),
autocompletion(),
highlightSelectionMatches(),
EditorView.lineWrapping,
keymap.of([...closeBracketsKeymap, ...defaultKeymap, ...historyKeymap, ...completionKeymap, ...lintKeymap]),
placeholder('Expression (press Shift+Enter for newlines)'),
dynamicConfigCompartment.of(dynamicConfig),
keymap.of([
{
key: 'Escape',
run: (v) => {
v.contentDOM.blur()
return false
}
}
]),
Prec.highest(
keymap.of([
{
key: 'Enter',
run: (v) => {
self.newChange()
return true
}
},
{
key: 'Shift-Enter',
run: insertNewlineAndIndent
}
])
),
EditorView.updateListener.of((update) => {
self.newChange(update.state.doc.toString())
})
],
editorState: {
changeByRange: self.newChange,
changes: self.newDoc,
facet: self.newChange
}
})
const view = new EditorView({
state: EditorViewstate,
// parent: document.getElementById('editor')
parent: document.getElementById(this.pqid + 'editor' + self.index)
})
self.newView = view
} else {
const to = self.oldcCodeLength
const from = self.oldcCodeLength
self.newView.dispatch(
self.newView.state.update({
effects: dynamicConfigCompartment.reconfigure(dynamicConfig),
changes: { from: 0, to, insert: self.codeMirrorValue[self.index] }
})
)
}
},
newChange (val) {
if (this.firstInit && this.isTopo) {
return
}
if (val) {
this.oldcCodeLength = val.length
this.codeMirrorValue[this.index] = val
// this.expressionList[this.index] = val
this.$set(this.expressionList, this.index, val)
this.metricKeyDown(val)
} else {
this.oldcCodeLength = 0
this.codeMirrorValue[this.index] = ''
// this.expressionList[this.index] = ''
this.$set(this.expressionList, this.index, '')
this.$emit('change', '')
}
},
newDoc (val) {
// console.log('doc', val)
},
promqlInputChange (val) {
if (this.type === 'metrics') {
try {
const text = this.newView.state.doc.toString()
this.newView.dispatch(
this.newView.state.update({
changes: { from: 0, to: text.length, insert: this.codeMirrorValue[this.index] }
})
)
} catch (error) {}
}
},
fetchFn (a, b) {
const params = {}
if (b) {
params['match[]'] = b.body.get('match[]')
params.start = b.body.get('start')
params.end = b.body.get('end')
a += '?match[]=' + b.body.get('match[]')
return fetch(a, {
...b,
// body: JSON.stringify(params),
redirect: 'follow',
headers: {
Authorization: localStorage.getItem('nz-token'),
'content-type': 'application/x-www-form-urlencoded'
}
})
}
return fetch(a, {
...b,
headers: {
Authorization: localStorage.getItem('nz-token')
}
})
},
closeDropdown () {
this.dropDownVisible = false
},
clearExpression: function () {
this.expressionChange()
this.cascaderValue = ''
},
enableExpression: function () {
this.$emit('enableExpression', this.index)
},
addExpression: function () {
this.$emit('addExpression', this.index)
},
copyExpression () {
this.$emit('copyExpression', this.index)
},
removeExpression: function () {
this.$emit('removeExpression', this.index)
},
toggleDropdown () {
this.dropDownVisible = !this.dropDownVisible
this.getMetricOptions()
},
getMetricOptions () {
if (!this.metricOptions.length) {
this.queryMetrics()
}
},
queryMetrics: function () {
this.loading = true
this.$get('prom/api/v1/label/__name__/values').then(response => {
if (response.status == 'success') {
const metrics = response.data.sort()
const metricMap = new Map()
metrics.forEach((item) => {
let key = ''
if (/^[a-zA-Z_:][a-zA-Z0-9_:]*/.test(item)) {
key = item.split(/[_:]/, 1)[0]
} else {
key = item
}
if (metricMap.get(key)) {
const values = metricMap.get(key)
values.push({ label: item, value: item })
} else {
const values = [{ label: item, value: item }]
metricMap.set(key, values)
}
// this.metricStore.push({label:item,value:item,insertText:item})
})
for (const key of metricMap.keys()) {
const option = {
label: key,
value: key
}
if (metricMap.get(key) && metricMap.get(key).length > 1) {
option.children = metricMap.get(key)
}
this.metricOptions.push(option)
}
if (this.showTemp) {
this.getExprTemp()
}
}
})
},
filterInput: function (queryString, cb) {
const metrics = Object.assign([], this.metricStore)
const result = queryString
? metrics.filter((item) => {
return item.value.toLowerCase().indexOf(queryString.toLowerCase()) != -1
})
: metrics
cb(result)
},
metricChange: function (value) {
this.expressionList[this.index] = value
this.codeMirrorValue[this.index] = value
this.dropDownVisible = false
this.$emit('change', value)
// this.initCodeMirror()
this.$forceUpdate()
this.cascaderValue = ''
},
metricChangeNew (value) {
// console.log(value)
if (!value) return
this.insertText(value)
this.dropDownVisible = false
this.$emit('change', value)
this.$forceUpdate()
this.cascaderValue = ''
},
logLabelChange (value) {
if (!value || value.length === 0) return
this.expressionList[this.index] = `{${value[0]}="${value[1]}"}`
this.codeMirrorValue[this.index] = `{${value[0]}="${value[1]}"}`
this.dropDownVisible = false
this.$emit('change', value)
this.$forceUpdate()
this.cascaderValue = ''
},
metricKeyDown (val) {
if (this.required) {
this.metricChange(val)
}
},
expressionChange: function () {
if (this.$refs.monacoEditor) {
setTimeout(() => {
this.heightChange()
}, 100)
}
this.$emit('change')
},
setError: function (errMsg) {
this.errorMsg = errMsg
},
getExprTemp () {
this.$get('/expression/tmpl/gname').then(res => {
this.loading = false
if (res.code === 200) {
res.data.list.forEach(item => {
this.metricOptions.unshift({
label: item,
value: item,
children: [],
temp: true,
child: false
})
})
}
})
},
lazyLoad (node, data) {
if (data.temp) {
if (!data.child) {
this.tempBoxShowLoading = true
this.$get('/expression/tmpl?pageSize=-1&gname=' + data.value).then(res => {
this.tempBoxShowLoading = false
if (res.code === 200) {
res.data.list.forEach(item => {
item.label = item.name
item.value = false
item.temp = true
item.child = true
})
this.metricOptions.find(item => item.value === data.value).children = res.data.list
// el-cascader-panel监听到options变化 会触发scrollIntoView函数
const temp = this.$refs.metricSelector.scrollIntoView
this.$refs.metricSelector.scrollIntoView = function () {}
this.$nextTick(() => {
this.$refs.metricSelector.scrollIntoView = temp
})
}
})
} else {
this.dropDownVisible = false
this.$get('/expression/tmpl/' + data.id).then(res => {
if (res.code === 200) {
if (!res.data.vars || !res.data.vars.length) {
this.metricChange(data.expression)
this.initCodeMirror()
return
}
res.data.vars.forEach(item => {
res.data[item] = ''
const arr = item.split('.')
const keyword = arr[0].toLowerCase()
this.getAllOptins(keyword, keyword + 'Option')
})
this.tempBox = {
...this.tempBox,
...res.data
}
setTimeout(() => {
this.tempBoxShow = true
}, 100)
}
})
}
} else if (data.children && (!data.children.length || data.children.length > 100) && this.type !== 'log') {
setTimeout(() => {
new Promise(resolve => {
const children = this.$store.state.metricsList.find(item => item.value === data.value).children
resolve(children)
}).then((children) => {
const childrenCopy = JSON.parse(JSON.stringify(children))
const findChild = this.metricOptions.find(item => item.label === data.label)
if (childrenCopy.length > 100) {
childrenCopy.splice(100, childrenCopy.length)
childrenCopy.push({
label: 'More',
value: false,
parent: data.label,
more: true
})
findChild.children = childrenCopy
} else {
findChild.children = childrenCopy
}
this.metricOptions.forEach(item => {
if (!item.temp && item.children && item.value != data.value) {
item.children = []
}
})
// el-cascader-panel监听到options变化 会触发scrollIntoView函数
const temp = this.$refs.metricSelector.scrollIntoView
this.$refs.metricSelector.scrollIntoView = function () {}
this.$nextTick(() => {
this.$refs.metricSelector.scrollIntoView = temp
})
})
})
} else if (data.more) {
setTimeout(() => {
new Promise(resolve => {
const children = this.$store.state.metricsList.find(item => item.label === data.parent).children
resolve(children)
}).then((children) => {
let childrenCopy = JSON.parse(JSON.stringify(children))
const findChild = this.metricOptions.find(item => item.label === data.parent)
if (childrenCopy.length > 100) {
childrenCopy = childrenCopy.splice(findChild.children.length, 100)
findChild.children.splice(findChild.children.length - 1, 1)
findChild.children.push(...childrenCopy)
if (findChild.children.length < children.length - 1) {
findChild.children.push({
label: 'More',
value: false,
parent: data.parent,
more: true
})
} else {
findChild.children.splice(findChild.children.length - 1, 1)
}
} else {
findChild.children = childrenCopy
}
// el-cascader-panel监听到options变化 会触发scrollIntoView函数
const temp = this.$refs.metricSelector.scrollIntoView
this.$refs.metricSelector.scrollIntoView = function () {}
this.$nextTick(() => {
this.$refs.metricSelector.scrollIntoView = temp
})
})
})
}
},
tempBoxShowChange (flag) {
this.tempBoxShow = flag
if (flag) {
this.cascaderValue = ''
const params = {}
params.expression = this.tempBox.expression
params.varsVal = {}
let returnFlag = false
let errorStr = ''
this.tempBox.vars.forEach((item) => {
params.varsVal[item] = this.tempBoxId[item] || this.tempBox[item]
if (!this.tempBox[item]) {
errorStr += item + ','
returnFlag = true
}
})
if (returnFlag) {
this.$message({
message: this.$t('config.exprTemp.errorStr', { errorStr: errorStr }),
type: 'error'
})
return
}
if (this.tempBox.vars.length == 0) {
this.tempBoxShow = false
// eslint-disable-next-line vue/no-mutating-props
// this.expressionList[this.index] = params.expression
this.insertText(params.expression)
this.$emit('change', params.expression)
return
}
this.$post('/expression/tmpl/render', params).then(res => {
if (res.code === 200) {
this.tempBoxShow = false
// this.expressionList[this.index] = res.data.expression
this.insertText(res.data.expression)
this.$emit('change', res.data.expression)
}
})
} else {
this.tempBox = {}
}
},
format (str) {
const arr = str.split('.')
const keyword = arr[0].toLowerCase()
switch (keyword) {
case 'asset':
case 'module':
case 'endpoint':
case 'datacenter':
case 'project':
return {
arr: this[keyword + 'Option'],
key: keyword,
value: ((keyword == 'module' || keyword == 'project' || keyword == 'datacenter') ? 'name' : 'host')
}
default:
return {
key: false
}
}
},
getAllOptins (key, arr) {
switch (key) {
case 'asset':
this.$get('asset/asset', { pageNo: 1, pageSize: -1 }).then(response => {
if (response.code == 200) {
const arr = []
response.data.list.forEach(asset => {
asset.name = asset.sn
const dcF = arr.find(dc => dc.id === asset.dc.id)
if (dcF) {
dcF.children.push(asset)
} else {
const dc = { ...asset.dc }
dc.children = [asset]
arr.push(dc)
}
})
this.assetOption = arr
}
})
break
case 'module':
this.$get('monitor/module/tree', { pageNo: 1, pageSize: -1 }).then(response => {
if (response.code == 200) {
this.moduleOption = response.data.list
}
})
break
case 'endpoint':
this.$get('monitor/endpoint/tree', { pageNo: 1, pageSize: -1 }).then(response => {
if (response.code == 200) {
this.endpointOption = response.data.list
}
})
break
case 'datacenter':
this.$get('dc', { pageNo: 1, pageSize: -1 }).then(response => {
if (response.code == 200) {
this.datacenterOption = response.data.list
}
})
break
case 'project':
this.$get('monitor/project', { pageNo: 1, pageSize: -1 }).then(response => {
if (response.code == 200) {
this.projectOption = response.data.list
}
})
break
default:
break
}
},
silenceChange (val, key) {
this.tempBox[key] = val.name
this.tempBoxId[key] = val.id
},
clearValue (key) {
this.tempBox[key] = ''
},
tempBoxClose () {
this.cascaderValue = ''
},
selectHistory (str) {
this.insertText(str)
},
insertText (insertTxt) {
// 获取el-input中的input元素
// const elInput = this.$refs.elInput.$el.firstElementChild
// 获取el-input的值
// const txt = elInput.value
// 获取选区开始位置
// const startPos = elInput.selectionStart
// 获取选区结束位置
// const endPos = elInput.selectionEnd
// if (startPos === undefined || endPos === undefined) return
// 将文本插入光标位置
// this.expressionList[this.index] = txt.substring(0, startPos) + insertTxt + txt.substring(endPos)
// 将光标移至文本末尾
// elInput.focus()
// elInput.selectionStart = startPos + insertTxt.length
// elInput.selectionEnd = startPos + insertTxt.length
this.expressionList[this.index] = insertTxt
this.codeMirrorValue[this.index] = insertTxt
this.initCodeMirror()
},
/* setMsg:function(){
this.appendMsg
} */
prettyCode () {
this.$nextTick(() => {
const text = this.newView.state.doc.toString()
this.newView.dispatch(
this.newView.state.update({
changes: { from: 0, to: text.length, insert: this.codeMirrorValue[this.index] }
})
)
})
},
showHistoryBox (flag) {
this.historyshow = flag
},
queryPromptShowChange: bus.debounce(function (val) {
if (!this.queryPromptShow) {
this.setPosition()
}
this.queryPromptShow = !this.queryPromptShow
}, 100),
hideQueryPromptShow () {
this.queryPromptShow = false
},
setPosition () {
this.queryPromptWidth = this.$refs.queryRow.offsetWidth
const position = this.$refs.queryRow.getBoundingClientRect() // 定位元素位置
const windowWidth = window.innerWidth// 窗口宽度
const windowHeight = window.innerHeight// 窗口高度
const boxHeight = 400
const parentHeight = this.$refs.queryRow.offsetHeight + 10
let top = 0
const left = position.left
if (position.top + parentHeight + boxHeight > windowHeight - 100) {
top = position.top - boxHeight - 10
} else {
top = position.top + parentHeight
}
this.queryPromptPosition = {
top: top,
left: left
}
},
selectMetric (item) {
if (!item.id) {
this.metricChangeNew(item.name)
} else if (item.id) {
this.dropDownVisible = false
this.$get('/expression/tmpl/' + item.id).then(res => {
if (res.code === 200) {
if (!res.data.vars || !res.data.vars.length) {
this.metricChange(item.expression)
this.initCodeMirror()
return
}
res.data.vars.forEach(item => {
res.data[item] = ''
const arr = item.split('.')
const keyword = arr[0].toLowerCase()
this.getAllOptins(keyword, keyword + 'Option')
})
this.tempBox = {
...this.tempBox,
...res.data
}
setTimeout(() => {
this.tempBoxShow = true
}, 100)
}
})
}
},
selectLog (str) {
if (!str || str.length === 0) return
this.expressionList[this.index] = str
this.codeMirrorValue[this.index] = str
this.dropDownVisible = false
this.$emit('change', str)
this.$forceUpdate()
this.cascaderValue = ''
}
},
watch: {
dropDownVisible (n, o) {
if (this.$refs.metricSelector) {
this.$refs.metricSelector.dropDownVisible = n
if (!this.expressionList[this.index] || this.expressionList[this.index] == '') {
this.cascaderValue = ''
}
}
},
metricOptionsParent: {
deep: true,
immediate: true,
handler (n, o) {
if (n) {
this.metricOptions = JSON.parse(JSON.stringify(n))
}
}
},
expressionList: {
deep: true,
immediate: true,
handler (n, o) {
this.codeMirrorValue[this.index] = n[this.index]
if (this.isTopo && this.firstInit) {
setTimeout(() => {
const text = this.newView.state.doc.toString()
this.newView.dispatch(
this.newView.state.update({
changes: { from: 0, to: text.length, insert: this.codeMirrorValue[this.index] }
})
)
this.firstInit = false
}, 200)
}
}
},
// codeMirrorValue:{
// deep:true,
// imediate:true,
// handler(n){
// if(n){
// this.oldcCodeLength = n.length
// }
// }
// }
type: {
deep: true,
immediate: true,
handler (n) {
if (n !== 'log') {
this.$nextTick(() => {
this.initCodeMirror()
})
}
}
}
},
beforeDestroy () {
this.newView = null
}
}
</script>
<style>
.input-box .el-input__inner {
height: 30px;
}
.nz-temp-box /deep/ .el-dialog__body {
padding: 10px 20px 0 20px;
}
.nz-temp-box /deep/ .el-dialog__footer {
margin-top: 0;
}
.nz-temp-box .nz-btn-style-light {
margin-right: 10px;
}
.nz-temp-box .nz-btn-style-normal {
margin-left: 10px;
}
</style>