Merge branch 'dev-3.7' of git.mesalab.cn:nezha/nezha-fronted into dev-3.8

This commit is contained in:
zyh
2023-04-23 14:30:02 +08:00
39 changed files with 519 additions and 157 deletions

View File

@@ -47,6 +47,7 @@
min-width: 200px;
}
}
.detail-top-search-dropdown{
max-height: 300px;
overflow-y: auto;
@@ -80,6 +81,7 @@
}
.children-title-name{
min-width: 180px;
flex-shrink: 0;
height: 36px;
padding-right: 20px;
@@ -96,6 +98,26 @@
background: $--background-color-base !important;
}
}
.detail-top-search-dropdown-special.detail-top-search-dropdown {
width: 680px;
max-width: unset !important;
.nz-dropdown-menu__item{
width: 100% !important;
.children-title-name {
width: 33%;
box-sizing: border-box;
}
.nz-dropdown-menu__item-box {
width: 66%;
display: flex;
flex-wrap: wrap;
.nz-dropdown-menu__item-hover {
width: calc(50% - 2px);
box-sizing: border-box;
}
}
}
}
.clear-all-select{
padding: 0 20px;
padding-left: 42px;

View File

@@ -143,6 +143,7 @@
width: 120px;
display: inline-block;
padding: 3px 0;
vertical-align: middle;
}
.content-text {
width: 175px;
@@ -150,6 +151,10 @@
font-size: 12px;
display: inline-block;
padding: 3px 5px;
vertical-align: middle;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap
}
.module-type {
border: 1px solid #DCDCDC;

View File

@@ -222,7 +222,7 @@
position: absolute;
right: 0;
top: 50px;
z-index: 1;
z-index: 11;
}
.facade-top{

View File

@@ -195,7 +195,7 @@
position: absolute;
right: 0;
top: 50px;
z-index: 1;
z-index: 11;
}
.facade-top{

View File

@@ -31,6 +31,10 @@
.right-box-alert-rule .right-box__container .el-form-item__content .el-input-group--prepend {
width: 100%;
}
.right-box__container .el-form-item__content .input-box .el-textarea .el-input__count {
right: 6px;
}
.rich-text-editor {
line-height: 24px;
@@ -113,7 +117,10 @@
.threshold-list {
border: 1px solid $--border-color-light;
padding: 16px;
margin-bottom: 16px;
.threshold-list-content {
margin-bottom: 0;
}
.threshold-item {
display: flex;
align-items: center;

View File

@@ -161,8 +161,10 @@
font-size: 14px;
color: $--color-text-regular;
letter-spacing: 0;
font-weight: 400;
margin: 30px 0 11px 0;
line-height: 20px;
font-weight: 600;
font-style: oblique;
padding: 30px 0 10px 0;
}
.data-top{
width: 100%;

View File

@@ -169,8 +169,10 @@
font-size: 14px;
color: $--color-text-regular;
letter-spacing: 0;
font-weight: 400;
margin: 30px 0 11px 0;
line-height: 20px;
font-weight: 600;
font-style: oblique;
padding: 30px 0 10px 0;
}
.data-top{
width: 100%;

View File

@@ -750,6 +750,12 @@ export default {
},
// deep: true,
immediate: true
},
chartData: {
immediate: true,
handler (n) {
this.initChart()
}
}
},
created () {

View File

@@ -230,7 +230,6 @@ export default {
})
setTimeout(() => {
this.alertDaysData = newWeekDays
console.log(this.alertDaysData)
this.trendLoading = false
})
return

View File

@@ -119,9 +119,20 @@ export default {
}
// Thresholds 只对左Y轴有效
if (s.yAxisIndex != 1) {
chartInfo.param.thresholds = chartInfo.param.thresholds.reverse()
s.markLine.data = chartInfo.param.thresholds.map(threshold => {
return {
yAxis: threshold.value || 0,
label: {
show: true,
formatter () {
if (threshold.label) {
return threshold.label
} else {
return threshold.value || 0
}
}
},
lineStyle: {
color: threshold.color,
width: 2,

View File

@@ -40,13 +40,13 @@
<span v-else>--</span>
</div>
</div>
<div class="alert-label-box">
<div class="alert-label-title">{{$t('alert.severity')}}</div>
<div class="alert-label-value"><i class="nz-icon nz-icon-circle" :style="{color:severityColor,'font-size':'12px','margin-right':'5px'}"></i>{{alertRuleData.severityId ? severityData.find(s => alertRuleData.severityId === s.id).name : '--'}}</div>
</div>
<!-- <div class="alert-label-box">-->
<!-- <div class="alert-label-title">{{$t('alert.severity')}}</div>-->
<!-- <div class="alert-label-value"><i class="nz-icon nz-icon-circle" :style="{color:severityColor,'font-size':'12px','margin-right':'5px'}"></i>{{alertRuleData.severityId ? severityData.find(s => alertRuleData.severityId === s.id).name : '&#45;&#45;'}}</div>-->
<!-- </div>-->
<div class="alert-label-box">
<div class="alert-label-title">{{$t('alert.config.expr')}}</div>
<div class="alert-label-value">{{alertRuleData.expr ? (alertRuleData.expr + alertRuleData.operator + formatThreshold(alertRuleData.threshold,alertRuleData.unit)) : '--'}}</div>
<div class="alert-label-value">{{alertRuleData.expr ? alertRuleData.expr : '--'}}</div>
</div>
<div class="alert-label-box">
<div class="alert-label-title">{{$t('alert.alertNum')}}</div>
@@ -100,6 +100,15 @@ export default {
that: {},
severityData: Array
},
watch: {
id: {
immediate: true,
deep: true,
handler (n) {
this.init()
}
},
},
data () {
return {
loading: true,
@@ -181,52 +190,58 @@ export default {
},
tipHoverRule (tipLoading) {
this.$emit('tipHoverRule', tipLoading)
},
init () {
if (!this.id) {
return
}
this.$get('/alert/rule/' + this.id).then((res) => {
if (res.msg === 'success') {
this.loading = false
this.alertRuleData = res.data
this.severityDataColor()
this.alertColor = this.returnColor(res.data.alert)
const weekDays = this.getWeeksTime()
if (this.trendTimer) {
clearTimeout(this.trendTimer)
this.trendTimer = null
}
this.trendTimer = setTimeout(() => {
this.trendLoading = true
const params = {
type: 'total',
dimension: 'priority',
step: 'd'
}
params['rule' + 'Id'] = this.id
this.$get('/stat/alertMessage/trend', params).then((res) => {
if (!res.data) {
return
}
const alertDaysData = res.data.result ? res.data.result[0].values : []
const newWeekDays = JSON.parse(JSON.stringify(weekDays))
alertDaysData.forEach(item => {
item.values.forEach(time => {
const findItem = newWeekDays.find(days => days.time == time[0])
if (findItem) {
findItem[item.metric.priority] = time[1]
}
})
})
setTimeout(() => {
this.alertDaysData = newWeekDays
this.trendLoading = false
})
})
})
} else {
this.$message.error(res.msg)
}
})
}
},
mounted () {
this.$get('/alert/rule/' + this.id).then((res) => {
if (res.msg === 'success') {
this.loading = false
this.alertRuleData = res.data
this.severityDataColor()
this.alertColor = this.returnColor(res.data.alert)
const weekDays = this.getWeeksTime()
if (this.trendTimer) {
clearTimeout(this.trendTimer)
this.trendTimer = null
}
this.trendTimer = setTimeout(() => {
this.trendLoading = true
const params = {
type: 'total',
dimension: 'priority',
step: 'd'
}
params['rule' + 'Id'] = this.id
this.$get('/stat/alertMessage/trend', params).then((res) => {
if (!res.data) {
return
}
const alertDaysData = res.data.result ? res.data.result[0].values : []
const newWeekDays = JSON.parse(JSON.stringify(weekDays))
alertDaysData.forEach(item => {
item.values.forEach(time => {
const findItem = newWeekDays.find(days => days.time == time[0])
if (findItem) {
findItem[item.metric.priority] = time[1]
}
})
})
setTimeout(() => {
this.alertDaysData = newWeekDays
this.trendLoading = false
})
})
})
} else {
this.$message.error(res.msg)
}
})
}
}

View File

@@ -53,7 +53,7 @@
<!-- </div>-->
<div class="alert-label-box">
<div class="alert-label-title">{{$t('alert.config.expr')}}</div>
<div class="alert-label-value">{{alertRuleData.expr ? (alertRuleData.expr + alertRuleData.operator + formatThreshold(alertRuleData.threshold,alertRuleData.unit)) : '--'}}</div>
<div class="alert-label-value">{{alertRuleData.expr ? alertRuleData.expr : '--'}}</div>
</div>
<div class="alert-label-box">
<div class="alert-label-title">{{$t('alert.alertNum')}}</div>

View File

@@ -19,7 +19,7 @@
<el-select v-model="state" class="margin-r-10" size="small" value-key="value" :disabled="from === fromRoute.alertSilence" @change="getTableData" popper-class="right-box-select-top right-public-box-dropdown-top" style="width: 110px">
<el-option v-for="item in stateOptions" :key="item.value" :label="$t(item.label)" :value="item.value"></el-option>
</el-select>
<pick-time v-model="searchTimeHeader" :default-pick="10" :refresh-data-func="getTableData" :show-empty="true" :use-chart-unit="false" :use-refresh="false" :sign="sign"></pick-time>
<pick-time ref="pickTime" v-model="searchTimeHeader" :default-pick="10" :refresh-data-func="dateChange" :show-empty="true" :use-chart-unit="false" :use-refresh="false" :sign="sign"></pick-time>
</template>
<template v-slot>
<alertMessageTable
@@ -164,7 +164,10 @@ export default {
this.state = '2'
}
this.searchLabel = {}
this.getTableData()
// this.getTableData()
setTimeout(() => {
this.$refs.pickTime && this.$refs.pickTime.$refs.timePicker.refresh()
}, 100)
}
}
},
@@ -342,6 +345,9 @@ export default {
})
})
},
dateChange () {
this.getTableData()
},
getTableData (state) {
if (state) {
this.state = state
@@ -630,7 +636,8 @@ export default {
if (this.$refs.dataTable) {
this.$refs.dataTable.$refs.dataTable.bodyWrapper.scrollTop = 0
}
this.getTableData()
// this.getTableData()
this.$refs.pickTime && this.$refs.pickTime.$refs.timePicker.refresh()
},
fillProject (module) {
this.$get('project', { id: module.projectId }).then(response => {
@@ -667,26 +674,36 @@ export default {
queryDate () {
this.chartLoading = true
let chartInfo = {}
const severityData = JSON.parse(localStorage.getItem('nz-severityDataWeight'))
const conditionArr = JSON.parse(this.currentMsg.alertRule.condition)
if (this.currentMsg.alertRule.type === 1 || this.currentMsg.alertRule.type === 3) {
chartInfo = lodash.cloneDeep(lineData)
chartInfo.elements = [{}]
if (!isNaN(this.currentMsg.alertRule.threshold)) {
if (conditionArr.length) {
chartInfo.param.enable.thresholds = true
chartInfo.param.thresholds = [{
value: this.currentMsg.alertRule.threshold,
color: '#d64f40'
}]
chartInfo.param.thresholds = conditionArr.map(item => {
const findItem = severityData.find(severity => severity.id === item.id)
if (findItem) {
item.color = findItem.color
item.label = findItem.name
}
return item
}).filter(item => item.value)
}
chartInfo.elements && (chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, ''))
} else if (this.currentMsg.alertRule.type === 2) {
chartInfo = lodash.cloneDeep(logData)
chartInfo.elements = [{}]
if (!isNaN(this.currentMsg.alertRule.threshold)) {
if (conditionArr.length) {
chartInfo.param.enable.thresholds = true
chartInfo.param.thresholds = [{
value: this.currentMsg.alertRule.threshold,
color: '#d64f40'
}]
chartInfo.param.thresholds = conditionArr.map(item => {
const findItem = severityData.find(severity => severity.id === item.id)
if (findItem) {
item.color = findItem.color
item.label = findItem.name
}
return item
}).filter(item => item.value)
}
chartInfo.elements && (chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\r|\n+/g, ''))
}

View File

@@ -13,7 +13,7 @@
>
<template v-slot:title><span :title="obj.name">{{obj.name}}</span></template>
<template v-slot:top-tool-right>
<el-input v-model="matchContent" class="margin-r-10" placeholder="" size="small" @keyup.enter.native="queryLogData()">
<el-input v-model="matchContent" class="margin-r-10" placeholder="" size="small" @keyup.enter.native="dateChange()">
<el-select slot="prepend" v-model="matchSymbol" class="symbol-select" size="small" style="width: 60px;">
<el-option value="|=">
<span style="font-family: Inter-Regular">|=</span>
@@ -28,9 +28,9 @@
<span style="font-family: Inter-Regular">!~</span>
</el-option>
</el-select>
<button slot="suffix" class="search-icon-btn"><i class="el-icon-search" @click="queryLogData()"></i></button>
<button slot="suffix" class="search-icon-btn"><i class="el-icon-search" @click="dateChange()"></i></button>
</el-input>
<pick-time id="explore" ref="pickTime" v-model="filterTime" :refresh-data-func="queryLogData" :sign="sign" :use-chart-unit="false" :use-refresh="false">
<pick-time id="explore" ref="pickTime" v-model="filterTime" :refresh-data-func="getData" :sign="sign" :use-chart-unit="false" :use-refresh="false">
<template slot="added-text">{{$t('overall.query')}}</template>
</pick-time>
</template>
@@ -72,7 +72,8 @@ export default {
matchSymbol: '|=',
matchContent: '',
loading: true,
endpointLoading: false
endpointLoading: false,
limit: 100
}
},
methods: {
@@ -114,8 +115,17 @@ export default {
reader.readAsText(error.response.data)
})
},
queryLogData (limit = 100) { // log的chart和table是一个请求
dateChange () {
this.$refs.pickTime && this.$refs.pickTime.$refs.timePicker.refresh()
},
getData () {
this.queryLogData()
},
queryLogData (limit) { // log的chart和table是一个请求
this.loading = true
if (limit) {
this.limit = limit
}
if (this.expressions.length > 0) {
const requestArr = []
this.expressions.forEach((item, index) => {
@@ -124,7 +134,7 @@ export default {
this.matchContent && (expr = `${item} ${this.matchSymbol} "${this.matchContent}"`)
const statTime = bus.formateTimeToTime(this.filterTime[0])
const endTime = bus.formateTimeToTime(this.filterTime[1])
requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(expr) + '&start=' + this.$stringTimeParseToUnix(statTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&limit=' + limit))
requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(expr) + '&start=' + this.$stringTimeParseToUnix(statTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&limit=' + this.limit))
}
})
axios.all(requestArr).then(res => {

View File

@@ -131,7 +131,7 @@ export default {
type: Boolean
}
},
inject: ['getTableData'],
inject: ['getTableData', 'delCallBack'],
methods: {
batchDelete: function () {
if (!this.single) {
@@ -215,6 +215,9 @@ export default {
return this.idStr.indexOf(item.id) !== -1
})
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.deleteSuccess') })
if (this.delCallBack) {
this.delCallBack(this.idStr)
}
// this.$emit('after')
} else {
this.$message.error(res.msg)

View File

@@ -89,15 +89,17 @@
</div>
<i class="nz-icon nz-icon-arrow-down search-value"/>
</div>
<el-dropdown-menu slot="dropdown" class="right-box-select-top right-public-box-dropdown-top detail-top-search-dropdown right-box-max-width">
<el-dropdown-menu slot="dropdown" class="right-box-select-top right-public-box-dropdown-top detail-top-search-dropdown right-box-max-width detail-top-search-dropdown-special">
<div style="text-align: center;"><el-input style="width: calc(100% - 40px)" size="small" v-model="searchStr" @input="(val)=>{searchStrChange(val,key)}" suffix-icon="el-icon-search"/></div>
<el-checkbox-group v-model="selectValue[item.key]">
<el-dropdown-item v-for="(item3,index3) in item.children" :key="index3" class="nz-dropdown-menu__item">
<span :title="item3.name" class="children-title-name"> {{item3.name}}</span>
<div :key="index4" v-for="(item4,index4) in item3.children" class="el-dropdown-menu__item nz-dropdown-menu__item-hover">
<el-checkbox :label="item3.id+'-'+item4.id" :title="item4.name" :a="item3.id+'-'+item4.id">{{item4.name}}</el-checkbox>
<span class="right-box-select-num">{{item4.num || 0}}</span>
</div>
<div class="nz-dropdown-menu__item-box">
<div :key="index4" v-for="(item4,index4) in item3.children" class="el-dropdown-menu__item nz-dropdown-menu__item-hover">
<el-checkbox :label="item3.id+'-'+item4.id" :title="item4.name" :a="item3.id+'-'+item4.id">{{item4.name}}</el-checkbox>
<span class="right-box-select-num">{{item4.num || 0}}</span>
</div>
</div>
</el-dropdown-item>
</el-checkbox-group>
</el-dropdown-menu>

View File

@@ -78,6 +78,22 @@
@showFullscreen="showFullscreen"
></panel-chart>
</el-dialog>
<delete-button
ref="deleteButton"
:from="'endpoint'"
:forceDeleteShow="forceDeleteShow"
:deleteTitle="deleteTitle"
type=''
:title="$t('overall.delete')"
:api="api"
:single="single"
:delete-objs="singleDelete"
@before="delFlag=true"
></delete-button>
<diagnosis-tab
ref="diagnosisTab"
:diagnosisTabData ="diagnosisTabData"
></diagnosis-tab>
</div>
</template>
@@ -86,12 +102,16 @@ import { fromRoute } from '@/components/common/js/constants'
import { bottomBoxWindow } from '@/components/common/js/tools'
import detailViewRight from '@/components/common/detailView/view/detailViewRight'
import panelChart from '@/components/chart/panelChart'
import deleteButton from '@/components/common/deleteButton'
import diagnosisTab from '@/components/common/diagnosisTab'
export default {
name: 'nzDataList',
components: {
detailViewRight,
panelChart
panelChart,
deleteButton,
diagnosisTab
},
props: {
from: {
@@ -138,6 +158,15 @@ export default {
},
topologyChartInfo () {
return this.$store.getters.getTopologyChartInfo
},
showDeleteTableRel () {
return this.$store.getters.getShowDeleteTableRel
},
deleteTableRel () {
return this.$store.getters.getDeleteTableRel
},
diagnosisTab () {
return this.$store.getters.getDiagnosisTab
}
},
data () {
@@ -159,7 +188,12 @@ export default {
showCustomTableTitle: false // 自定义列弹框是否显示
},
showLayout: [],
timeRange: [new Date(), new Date()]
timeRange: [new Date(), new Date()],
single: true,
deleteTitle: '',
forceDeleteShow: false,
singleDelete: [],
diagnosisTabData: {}
}
},
methods: {
@@ -197,6 +231,27 @@ export default {
},
showFullscreen (flag) {
this.$store.commit('setTopologyShow', flag)
},
delTableRelRow (url, row, forceDeleteShow = false, single = false, deleteTitle = '') {
this.api = url
this.singleDelete = [row]
this.forceDeleteShow = forceDeleteShow
this.single = single
this.deleteTitle = deleteTitle
this.$refs.deleteButton.batchDelete()
},
delTableRow (ids) { // 接收一个 删除的id数组 判断当前底部弹窗id 是否包含 包含则关闭当前弹窗
if (ids.indexOf(this.bottomBox.object.id) !== -1) {
this.bottomBox = {
object: {},
mainResizeShow: true, // dom高度改变时是否展示|隐藏
subResizeShow: true,
isFullScreen: false, // 全屏状态
showSubList: false, // 是否显示二级列表
targetTab: '', // 显示二级列表中的哪个页签
inTransform: false // 搜索框相关搜索条件下拉框是否在transform里
}
}
}
},
watch: {
@@ -210,6 +265,14 @@ export default {
handler (n) {
this.showLayout = [...n]
}
},
showDeleteTableRel (n) {
if (n) {
this.delTableRelRow(this.deleteTableRel.url, this.deleteTableRel.row, this.deleteTableRel.forceDeleteShow, this.deleteTableRel.single, this.deleteTableRel.deleteTitle)
}
},
diagnosisTab (n) {
this.diagnosisTabData = n
}
}
}

View File

@@ -524,7 +524,6 @@ export default {
})
return item
})
console.log(res.data.condition)
this.alertLabelData = res.data
} else {
this.$message.error(res.msg)

View File

@@ -51,7 +51,8 @@ export default {
},
provide () {
return {
getTableData: this.getTableData
getTableData: this.getTableData,
delCallBack: this.delCallBack
}
},
methods: {

View File

@@ -180,7 +180,12 @@ export default {
if (this.trendPromiseIndex < this.trendPromise.length) {
Promise.all(this.trendPromise[this.trendPromiseIndex]).then(response => {
response.forEach((res, index) => {
const item = this.tableData[index + this.trendPromiseIndex * 10]
const arr = res.responseURL && res.responseURL.split('=')
let id = ''
if (arr) {
id = arr[arr.length - 1]
}
const item = this.tableData.find(row => row.id == id)
if (!res.data) {
return
}
@@ -194,13 +199,15 @@ export default {
}
})
})
item.alertDaysData = newWeekDays
item.trendLoading = false
if (item) {
item.alertDaysData = newWeekDays
item.trendLoading = false
}
})
this.trendPromiseIndex++
this.renderTrend()
}).catch((msg) => {
console.log(msg)
// console.log(msg)
})
}
}
@@ -247,7 +254,7 @@ export default {
dimension: 'priority',
step: 'd'
}
params[this.trendKey] = item.id
params[this.trendKey] = item.id // 添加其他参数 这个要放在最后 用于获取对应的id
trendArr.push(this.$get('/stat/alertMessage/trend', params))
if (trendArr.length > 9) {
this.trendPromise.push(trendArr)

View File

@@ -73,7 +73,7 @@ export default {
nodesArr: [],
offsetX: 0,
offsetY: 0,
moduleId: '',
moduleId: ''
}
},
mixins: [topoUtil],
@@ -156,6 +156,8 @@ export default {
pen.imageId = pen.data.imageId
if (imageInfo) {
pen.image = `/topology/icon/0/${imageInfo.unit}/${imageInfo.name}`
} else {
pen.image = ''
}
}
pen.data = {
@@ -438,9 +440,9 @@ export default {
}
},
beforeEdit () {
const endTime = new Date().getTime()
const startTime = endTime - 60 * this.params.timeType * 1000
this.getQueryValues(this.querysArray, startTime, endTime)
// const endTime = new Date().getTime()
// const startTime = endTime - 60 * this.params.timeType * 1000
// this.getQueryValues(this.querysArray, startTime, endTime)
this.editFlag = true
this.contextmenu = {
left: null,
@@ -510,8 +512,14 @@ export default {
},
// 具体内容点击
nodeTools (node, tool) {
const findItem = this.allModules.find(item => item.id == node.moduleId)
if (findItem) {
this.moduleName = findItem.name
} else {
this.$message.error(this.$t('MODULE_NOTFOUND'))
return
}
this.moduleId = node.moduleId
this.moduleName = node.moduleName
if (tool.id === 'total') {
this.popDataShowUpdate('', false, node)
return

View File

@@ -11,7 +11,7 @@ export default {
},
initEdit (id) {
const endTime = new Date().getTime()
const startTime = endTime - 60 * this.params.timeType * 1000
const startTime = endTime - 60 * getTopology(id).data().timeType * 1000
const elements = getTopology(id).data().elements || []
this.getQueryValues(elements, startTime, endTime)
bus.$emit('changeSelectPens', [])
@@ -155,6 +155,15 @@ export default {
pen.moduleId = pen.data.moduleId
delete pen.data.moduleId
}
if (!isNaN(pen.imageId) && pen.imageId) {
const imageInfo = this.iconArray.find(item => item.id === pen.imageId)
if (imageInfo) {
pen.image = `/topology/icon/0/${imageInfo.unit}/${imageInfo.name}`
} else {
pen.image = ''
}
}
if (pen.icon) {
pen.iconFamily = 'nz-icon'
}

View File

@@ -314,7 +314,7 @@
</div>
<div class="form-row-item">
<div class="form-row-key">
{{$t('水平反转')}}
{{$t('project.topology.flipX')}}
</div>
<div class="form-row-value">
<el-switch
@@ -327,7 +327,7 @@
</div>
<div class="form-row-item">
<div class="form-row-key">
{{$t('垂直反转')}}
{{$t('project.topology.flipY')}}
</div>
<div class="form-row-value">
<el-switch
@@ -443,12 +443,12 @@
<div class="form-row-value">
<div style="display: inline-block;width: calc(30% - 3px)">
<el-select v-model="pen.data.textParent" size="small">
<el-option v-for="item in queryValues.filter(query => query.type === 'title')" :key="item.id" :value="item.name" :label='item.name'></el-option>
<el-option v-for="item in queryValues.filter(query => query.type === 'title')" :key="item.id" :value="item.name" :label='item.name' :title="item.name" style="width: 133px"></el-option>
</el-select>
</div>
<div style="display: inline-block;width: calc(70% - 13px);margin-left: 10px">
<el-select v-model="pen.data.textLegend" size="small">
<el-option v-for="item in queryValues.filter(query => (query.parent === pen.data.textParent) && query.type === 'item')" :key="item.id" :value="item.name" :label='item.name'></el-option>
<el-option v-for="item in queryValues.filter(query => (query.parent === pen.data.textParent) && query.type === 'item')" :key="item.id" :value="item.name" :label='item.name' :title="item.name" style="width: 302px"> </el-option>
</el-select>
</div>
</div>

View File

@@ -69,6 +69,7 @@
>
<meta2dTooltip
ref="meta2dTooltip"
:meta2dId="meta2dId"
:params="chartParams"
/>
</div>

View File

@@ -337,7 +337,6 @@ export default {
},
beforeAvatarUpload (file, fileList) {
const this_ = this
console.log(file.raw.type)
const isJPG = (file.raw.type === 'image/jpeg' || file.raw.type === 'image/png' || file.raw.type === 'image/gif')
const isLt2M = (file.size / 1024 / 1024) < 2
if (!isJPG) {

View File

@@ -25,6 +25,7 @@ export default {
name: 'meta2dTooltip',
props: {
params: {},
meta2dId: {}
},
mixins: [topoUtil],
computed: {
@@ -51,6 +52,7 @@ export default {
return
}
this.chartInfo.type = this.params.chartType || 'line'
this.chartInfo.id = this.meta2dId + 'meta2DTooltip'
const chartData = []
const elements = []
const obj = {}
@@ -79,7 +81,7 @@ export default {
elements.push(element)
}
})
if (chartData.length && this.$refs.panelChart) {
if (chartData && this.$refs.panelChart) {
this.chartInfo.elements = elements
this.$refs.panelChart.chartData = chartData
this.$refs.panelChart.loading = false

View File

@@ -38,7 +38,7 @@
</div>
<div class="content-box">
<span class="content-title">{{ $t('overall.remark') }}</span>
<span class="content-text">{{moduleInfo.remark?moduleInfo.remark:'--'}}</span>
<span class="content-text" :title="moduleInfo.remark?moduleInfo.remark:'--'">{{moduleInfo.remark?moduleInfo.remark:'--'}}</span>
</div>
</div>
</div>

View File

@@ -76,12 +76,20 @@
<el-input id="alert-box-input-oid" v-model="editAlertRule.expr" size="small" type="text"></el-input>
</el-form-item>
<!--threshold-->
<el-form-item :label="$t('alert.config.threshold')" key="threshold">
<div class="threshold-list">
<div class="threshold-list">
<el-form-item
:label="$t('alert.config.threshold')"
key="threshold"
class="threshold-list-content"
prop="condition"
:rules="[
{ required: true, message: $t('validate.required'), trigger: 'blur'},
{ validator: conditionValidator, trigger: 'change'},
]">
<el-form-item v-for="(item,index) of editAlertRule.condition" :key="'threshold-list' + index" :prop="'condition.' + index + '.value'"
:rules="[
{ required: true, message: $t('validate.required'), trigger: 'blur'},
{ validator: thresholdValidator, trigger: 'blur' , item:item},
{ validator: showError, trigger: 'blur' , item:item},
]"
>
<div class="threshold-item">
@@ -89,13 +97,14 @@
<div class="threshold-item-center">
<span>{{$t('alert.config.when')}} Result</span>
<el-select :disabled="!showSnmpTrap" :value="item.operator" @change="operatorChange(item,index,$event)" class="hide-icon" popper-class="prevent-clickoutside" size="small">
<el-option v-for="subItem in operators" :id="'operator-'+subItem.key" :key="'Result' + subItem.value" :label="subItem.label" :value="subItem.value"></el-option>
<el-option v-for="subItem in filterOperators" :id="'operator-'+subItem.key" :key="'Result' + subItem.value" :label="subItem.label" :value="subItem.value"></el-option>
</el-select>
</div>
<el-input v-model="item.value" :placeholder="item.operator==='=~'?$t('alert.config.enterRegular'):$t('alert.config.enterThreshold')" size="small" type="text" style="flex:1"/>
<el-input v-model="item.value" @change="thresholdBlur" :placeholder="item.operator==='=~'?$t('alert.config.enterRegular'):$t('alert.config.enterThreshold')" size="small" type="text" style="flex:1"/>
</div>
</el-form-item>
<el-form-item prop="timeout" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" style="margin-bottom:0;">
</el-form-item>
<el-form-item class="hide-error" prop="timeout" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" style="margin-bottom:0;">
<div class="threshold-item">
<div class="threshold-item-left" style="margin-right:24px">{{$t('alert.config.normal')}}</div>
<el-input-number
@@ -112,8 +121,7 @@
</div>
</div>
</el-form-item>
</div>
</el-form-item>
</div>
<!--inr-->
<el-form-item v-if="showSnmpTrap" :label="$t('alert.config.inr')" prop="inr" class="half-form-item">
<el-input-number :min="15" :max="86400" id="alert-box-input-inr" :controls="false" v-model="editAlertRule.inr" :placeholder="$t('alert.config.inrPlaceholder')" size="small" type="text" :disabled="!showSnmpTrap"></el-input-number>
@@ -354,6 +362,15 @@ export default {
richTextEditor
},
mixins: [editRigthBox, promqlInputMixin],
computed: {
filterOperators () {
if (this.editAlertRule.type != 3) {
return this.operators.filter(item => item.value !== '=~')
} else {
return this.operators.filter(item => item.value == '=~')
}
}
},
data () {
const nzOid = (rule, value, callback) => {
if (this.editAlertRule.type === 3) {
@@ -496,6 +513,39 @@ export default {
callback()
}
},
thresholdBlur () {
this.$refs.alertRuleForm.validateField('condition')
},
conditionValidator (rule, value, callback) {
let flag = true
if (value.length) {
value.forEach(item => {
if (item.value) {
flag = false
}
})
}
if (flag) {
this.conditionValidatorError = true
this.editAlertRule.condition.forEach((item, index) => {
this.$refs.alertRuleForm.validateField('condition.' + index + '.value') // 移除from表单的 condition 验证
})
callback(new Error())
} else {
this.conditionValidatorError = false
this.editAlertRule.condition.forEach((item, index) => {
this.$refs.alertRuleForm.validateField('condition.' + index + '.value') // 移除from表单的 condition 验证
})
callback()
}
},
showError (rule, value, callback) {
if (this.conditionValidatorError) {
callback(new Error(this.$t('alert.config.thresholdOnly')))
} else {
callback()
}
},
clickOutside () {
this.esc(false)
},
@@ -517,7 +567,7 @@ export default {
operator: item.operator,
value: item.value
}
})
}).filter(item => item.value)
const params = {
...this.editAlertRule,
method: this.editAlertRule.method.join(','),
@@ -624,6 +674,13 @@ export default {
this.$nextTick(() => {
this.showSnmpTrap = true
})
// type为1时 不能输入正则
this.editAlertRule.condition.forEach((item, index) => {
item.operator = '>'
item.value = ''
this.$refs.alertRuleForm.clearValidate('condition.' + index + '.value') // 移除from表单的 condition 验证
})
this.$refs.alertRuleForm.clearValidate('condition') // 移除from表单的 condition 验证
} else if (val === 2) {
this.showMetrics = false
this.expressions = ['']
@@ -633,6 +690,13 @@ export default {
this.showSnmpTrap = true
})
this.$refs.alertRuleForm.clearValidate('expr') // 移除from表单的 expr 验证
// type为2时 不能输入正则
this.editAlertRule.condition.forEach((item, index) => {
item.operator = '>'
item.value = ''
this.$refs.alertRuleForm.clearValidate('condition.' + index + '.value') // 移除from表单的 condition 验证
})
this.$refs.alertRuleForm.clearValidate('condition') // 移除from表单的 condition 验证
} else if (val === 3) {
this.showSnmpTrap = false // showSnmpTrap 为 false 时,展示 OID
this.showMetrics = false
@@ -645,6 +709,7 @@ export default {
item.value = ''
this.$refs.alertRuleForm.clearValidate('condition.' + index + '.value') // 移除from表单的 condition 验证
})
this.$refs.alertRuleForm.clearValidate('condition') // 移除from表单的 condition 验证
}
},
afterInitRich () {
@@ -654,8 +719,9 @@ export default {
operatorChange (item, index, value) {
if (item.operator === '=~' || value === '=~') {
item.value = ''
this.$refs.alertRuleForm.clearValidate('condition.' + index + '.value') // 移除from表单的 condition 验证
this.$refs.alertRuleForm.clearValidate('condition.' + index + '.value') // 移除from表单的 condition 其中一个的验证
}
this.$refs.alertRuleForm.clearValidate('condition') // 移除from表单的 condition 验证
item.operator = value
}
},

View File

@@ -34,7 +34,7 @@
</span>
</el-popover>
</div>
<el-input size="mini" v-model="searchStr" @focus="searchInputFocus" @keydown.native="keydown" @keyup.native="keyup" ref="searchStr" @keypress="keypress" :readonly="inputReadonly" @input="changeSearchStr"></el-input>
<el-input size="mini" v-model="searchStr" @focus="searchInputFocus" @keydown.native="keydown" @keyup.native="keyup" ref="searchStr" @keypress.native="keypress" :readonly="inputReadonly" @input="changeSearchStr"></el-input>
</div>
</div>
<div class="search-content">
@@ -119,6 +119,7 @@ export default {
selectArr: [], // 已被选择的条件
key: '', // 当前被选中的 key
symbol: false, // 当前被选中的 symbol
selectSymbolValue: '', // 当前被选中的 symbol 的值
value: '', // 当前被选中的 value
keyShow: false, // key 的下拉
symbolShow: false, // symbol 的下拉 显示根据key的类型 自定义的不包含 大于小于
@@ -209,6 +210,8 @@ export default {
// console.log(e, 'keydown')
if (e.keyCode == 8 && !this.searchStr && this.selectArr.length) {
this.selectArr.pop()
} else if (e.keyCode == 8) {
// console.log(this.oldSearchStr, this.searchStr)
}
// 5
if (e.keyCode == 38) { // 向上
@@ -247,18 +250,6 @@ export default {
this.$refs.searchStr.focus()
return
}
// 2 3
const index = this.searchStr.indexOf(':')
if (index === -1) {
this.symbol = false
this.inputReadonly = false
this.contentShow('key')
} else if (index === this.searchStr.length - 1 && !this.symbol) {
this.contentShow('symbol')
} else {
this.symbol = true
this.contentShow('value')
}
// 4
if (e.keyCode == 13 && index !== -1 && this.symbol) {
this.addSelectArr(this.searchStr)
@@ -280,7 +271,7 @@ export default {
if (index === -1) {
this.symbol = false
this.contentShow('key')
} else if (index === this.searchStr.length - 1 && !this.symbol) {
} else if ((index == this.searchStr.length - 1) && !this.symbol) {
this.contentShow('symbol')
} else {
this.symbol = true
@@ -289,6 +280,7 @@ export default {
},
selectSymbol (item) {
this.symbol = true
this.selectSymbolValue = item.value
switch (item.value) {
case '=' :
this.$refs.searchStr.focus()
@@ -334,6 +326,53 @@ export default {
this.setValueList('')
this.contentShow('value')
},
delSymbol () {
const length = this.searchStr.length
switch (this.selectSymbolValue) {
case '=' :
this.$refs.searchStr.focus()
break
case '≠' :
this.searchStr = this.searchStr.substring(1)
this.$refs.searchStr.focus()
break
case '>=' :
// this.searchStr = this.searchStr + '>='
// this.$refs.searchStr.focus()
break
case '<=' :
// this.searchStr = this.searchStr + '<='
// this.$refs.searchStr.focus()
break
case '>' :
// this.searchStr = this.searchStr + '>'
// this.$refs.searchStr.focus()
break
case '<' :
// this.searchStr = this.searchStr + '<'
// this.$refs.searchStr.focus()
break
case 'wildcard' :
this.searchStr = this.searchStr.substring(1)
this.$refs.searchStr.focus()
break
case 'not wildcard' :
this.searchStr = this.searchStr.substring(2)
this.$refs.searchStr.focus()
break
case 'exist' :
// this.selectValue('*')
// this.$refs.searchStr.focus()
break
case 'not exist' :
this.searchStr = this.searchStr.substring(2)
// this.searchStr = '-' + this.searchStr + '*'
// this.selectValue('*')
this.$refs.searchStr.focus()
break
}
this.selectSymbolValue = ''
},
selectValue (value) {
this.searchStr = this.searchStr + value
this.addSelectArr(this.searchStr)
@@ -348,8 +387,16 @@ export default {
this.keyShow = false // key 的下拉
this.symbolShow = false // symbol 的下拉
this.valueShow = false // value 的下拉
if (key) {
this[key + 'Show'] = true
console.log(key)
if (key === 'symbol') {
this.setSymBolList()
this.symbolShow = true
}
if (key === 'key') {
this.keyShow = true
}
if (key === 'value') {
this.valueShow = true
}
const keyStr = this.searchStr.split(':')[0]
// console.log(keyStr, this.searchStr.split(':'))
@@ -412,6 +459,7 @@ export default {
key,
value: [value]
})
this.setSearchList()
}
},
removeSelectArr (index) {
@@ -511,6 +559,28 @@ export default {
this.searchList = n.searchLabelList || []
this.oldSearchList = n.searchLabelList || []
}
},
searchStr: {
handler (n, o) {
console.log(n, o)
// 2 3
const index = this.searchStr.indexOf(':')
if (index === -1) {
this.symbol = false
this.inputReadonly = false
this.contentShow('key')
} else if (index === this.searchStr.length - 1 && !this.symbol) {
this.contentShow('symbol')
} else {
this.symbol = true
this.contentShow('value')
}
if (n.indexOf(':') === -1 && o.indexOf(':') !== -1) {
this.symbol = false
this.delSymbol()
}
// if (n.indexOf(':'))
}
}
}
}

View File

@@ -249,7 +249,8 @@ export default {
tableDataInitNum: 0,
alertRuleShow: false,
alertRuleId: '',
alertRuleObj: ''
alertRuleObj: '',
timeRule: ''
}
},
computed: {
@@ -518,7 +519,7 @@ export default {
},
// alertName鼠标划入
alertMessageHover (item, loading, e) {
clearTimeout(this.timer)
clearTimeout(this.timeRule)
if (e) {
const dom = e.currentTarget
const position = dom.getBoundingClientRect()
@@ -527,13 +528,13 @@ export default {
this.alertRuleObj = item
}
this.$set(item.alertRule, 'loading', loading)
this.timer = setTimeout(() => {
this.timeRule = setTimeout(() => {
this.alertRuleShow = loading
}, 500)
this.flag = loading
},
tipHoverRule (tipLoading) {
clearTimeout(this.timer)
clearTimeout(this.timeRule)
if (this.flag === false) {
this.alertRuleShow = tipLoading
}

View File

@@ -2,7 +2,7 @@
<el-table
id="pingTable"
ref="dataTable"
:height="'calc(100% - 10px)'"
:height="'calc(100% - 80px)'"
:row-key="rowKey"
:data="tableData"
border

View File

@@ -2,7 +2,7 @@
<el-table
id="traceTable"
ref="dataTable"
:height="'calc(100% - 10px)'"
:height="'calc(100% - 80px)'"
:data="tableData"
:row-key="rowKey"
border

View File

@@ -546,6 +546,10 @@ export default {
} else {
this.isPopoverDisabled = false
}
},
refresh () {
this.setSearchTime(this.nowTimeType.type, this.nowTimeType.value, this.searchTime)
this.$emit('change', this.searchTime)
}
},
watch: {
@@ -557,6 +561,7 @@ export default {
if (showTime) {
this.showTime = Object.assign({}, showTime)
this.searchTime = this.$parent.searchTime
this.nowTimeType = this.showTime
}
if (this.showEmpty && this.defaultPick === 12) {
this.searchTime = []

View File

@@ -18,8 +18,8 @@
<button id="asset-filter" :class="[dataListLayout.indexOf('clickSearch') > -1?'is-focus':'' ]" class="top-tool-btn margin-r-10" @click.stop="showClickSearch" :title="$t('dashboard.dashboard.chartForm.filter')">
<i class="nz-icon nz-icon-funnel"></i>
</button>
<pick-time v-model="searchTime" sign="message" :default-pick="10" :refresh-data-func="getTableData" :show-empty="true" :use-chart-unit="false" :use-refresh="false"></pick-time>
<button id="roles-add" v-has="'alertMessage_edit'" :title="$t('overall.exportExcel')" class="top-tool-btn margin-r-10" type="button" @click="showExportDialog">
<pick-time ref="pickTime" v-model="searchTime" sign="message" :default-pick="10" :refresh-data-func="dateChange" :show-empty="true" :use-chart-unit="false" :use-refresh="false"></pick-time>
<button id="roles-add" v-has="'alertMessage_view'" :title="$t('overall.exportExcel')" class="top-tool-btn margin-r-10" type="button" @click="showExportDialog">
<i class="nz-icon-download1 nz-icon"></i>
</button>
<top-tool-more-options
@@ -718,26 +718,36 @@ export default {
queryDate () {
this.chartLoading = true
let chartInfo = {}
const severityData = JSON.parse(localStorage.getItem('nz-severityDataWeight'))
const conditionArr = JSON.parse(this.currentMsg.alertRule.condition)
if (this.currentMsg.alertRule.type === 1 || this.currentMsg.alertRule.type === 3) {
chartInfo = lodash.cloneDeep(lineData)
chartInfo.elements = [{}]
if (!isNaN(this.currentMsg.alertRule.threshold)) {
if (conditionArr.length) {
chartInfo.param.enable.thresholds = true
chartInfo.param.thresholds = [{
value: this.currentMsg.alertRule.threshold,
color: '#d64f40'
}]
chartInfo.param.thresholds = conditionArr.map(item => {
const findItem = severityData.find(severity => severity.id === item.id)
if (findItem) {
item.color = findItem.color
item.label = findItem.name
}
return item
}).filter(item => item.value)
}
chartInfo.elements && (chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, ''))
} else if (this.currentMsg.alertRule.type === 2) {
chartInfo = lodash.cloneDeep(logData)
chartInfo.elements = [{}]
if (!isNaN(this.currentMsg.alertRule.threshold)) {
if (conditionArr.length) {
chartInfo.param.enable.thresholds = true
chartInfo.param.thresholds = [{
value: this.currentMsg.alertRule.threshold,
color: '#d64f40'
}]
chartInfo.param.thresholds = conditionArr.map(item => {
const findItem = severityData.find(severity => severity.id === item.id)
if (findItem) {
item.color = findItem.color
item.label = findItem.name
}
return item
}).filter(item => item.value)
}
chartInfo.elements && (chartInfo.elements[0].expression = this.currentMsg.alertRule.expr.replace(/\r|\n+/g, ''))
}
@@ -869,6 +879,10 @@ export default {
})
}
},
dateChange () {
this.getTableData()
},
getTableData (state) {
if (state) {
this.state = state
@@ -1196,7 +1210,8 @@ export default {
if (this.$refs.dataTable) {
this.$refs.dataTable.$refs.dataTable.bodyWrapper.scrollTop = 0
}
this.getTableData()
// this.getTableData()
this.$refs.pickTime && this.$refs.pickTime.$refs.timePicker.refresh()
},
computeDistance (str) {
let width = 0

View File

@@ -82,7 +82,7 @@
</el-table-column>
</el-table>
<template v-if="exploreItem">
<div v-if="exploreLogTable" class="table-no-data">
<div v-if="exploreLogTable && !tableData.length" class="table-no-data">
<svg class="icon" aria-hidden="true">
<use xlink:href="#nz-icon-no-data-list"></use>
</svg>
@@ -91,7 +91,7 @@
<div v-else>&nbsp;</div>
</template>
<template v-else>
<div v-if="loadingBottom" class="table-no-data">
<div v-if="loadingBottom && !tableData.length" class="table-no-data">
<svg class="icon" aria-hidden="true">
<use xlink:href="#nz-icon-no-data-list"></use>
</svg>

View File

@@ -134,6 +134,7 @@ export default {
},
methods: {
getTableData (params) {
console.log('213123123')
if (params && Object.keys(params).length > 0) {
for (const key in params) {
this.$set(this.searchLabel, key, params[key])
@@ -194,6 +195,17 @@ export default {
}
}
})
},
delCallBack (id) {
console.log(id, 'id')
if (id.indexOf(this.$store.state.currentProject.id) !== -1) {
console.log(123, id)
this.$store.commit('currentProjectChange', {
id: '',
name: '',
remark: ''
})
}
}
},
computed: {

View File

@@ -61,11 +61,11 @@ import hljs from 'highlight.js'
VMdPreview.use(githubTheme, {
Hljs: hljs
})
Pace.options = {
minTime: 0.1,
ghostTime: 0.1,
restartOnRequestAfter: 0.1
}
// Pace.options = {
// minTime: 0.1,
// ghostTime: 0.1,
// restartOnRequestAfter: 0.1
// }
window.Meta2d = Meta2d
Vue.use(VMdPreview)
Vue.use(Pace)

View File

@@ -139,6 +139,9 @@ export function get (url, params, responseType) {
headers: response.headers
})
}
if (url.indexOf('/stat/alertMessage/trend') !== -1) {
response.data.responseURL = response.request.responseURL
}
resolve(response.data)
}).catch(err => {
if (err.response) {

View File

@@ -33,7 +33,7 @@ router.beforeEach((to, from, next) => {
localStorage.setItem('nz-sys-timezone', res.data.timezone || '')
localStorage.setItem('nz-sys-bgImg', res.data.system_bgImg || '')
localStorage.setItem('nz-default-theme', res.data.theme || '')
localStorage.setItem('nz-default-dateFormat', res.data.dateFormat || '')
localStorage.setItem('nz-default-dateFormat', res.data.dateFormat || 'YYYY-MM-DD HH:mm:ss')
changeFavicon(res.data.system_favicon)
}
resolve()