From ce2dc59e0384335ea0b25b78ea0b4c9cd848af21 Mon Sep 17 00:00:00 2001 From: zyh Date: Thu, 30 Jun 2022 15:47:54 +0800 Subject: [PATCH] =?UTF-8?q?NEZ-1987=20feat=EF=BC=9Aalert=20rule=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E9=A1=B5=E9=9D=A2=E5=BC=80=E5=8F=91=EF=BC=88=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E9=98=88=E5=80=BC=E5=91=8A=E8=AD=A6=E8=A7=84?= =?UTF-8?q?=E5=88=99=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/rightBox/alertRuleBox.scss | 56 ++- .../common/rightBox/alertRuleBox.vue | 350 +++++++++++------- .../common/table/alert/alertRuleTable.vue | 61 +-- .../src/components/page/alert/alertRule.vue | 114 +++--- 4 files changed, 356 insertions(+), 225 deletions(-) diff --git a/nezha-fronted/src/assets/css/components/common/rightBox/alertRuleBox.scss b/nezha-fronted/src/assets/css/components/common/rightBox/alertRuleBox.scss index bcaf315f8..cc397314b 100644 --- a/nezha-fronted/src/assets/css/components/common/rightBox/alertRuleBox.scss +++ b/nezha-fronted/src/assets/css/components/common/rightBox/alertRuleBox.scss @@ -45,15 +45,17 @@ border: $--border-color-light; } .alert-rule-split-title{ - background: $--background-color-base; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 10px; + margin-bottom: 20px; + line-height: 32px; font-size: 14px; + font-weight: bold; color: $--color-text-primary; - letter-spacing: 0; - font-weight: 400; - line-height: 24px; - padding-left: 10px; - margin-bottom: 10px; - height: 24px; + background-color: $--right-box-sub-title-background-color; + border: 1px solid $--right-box-sub-title-border-color; } .el-form-item__content .el-input-group.el-input-group--prepend { vertical-align: middle; @@ -76,6 +78,46 @@ color: #FFFFFF; } } + .threshold-list{ + border: 1px solid $--border-color-light; + padding: 16px; + .threshold-item{ + display: flex; + align-items: center; + line-height: 1; + .threshold-item-left{ + width: 64px; + height: 26px; + border-radius: 4px; + background-color:$--color-success; + color: #fff; + text-align: center; + line-height: 26px; + } + .threshold-item-center{ + margin: 0 24px; + color: $--color-text-regular; + font-size: 14px; + } + .threshold-item-msg{ + color: $--color-text-regular; + font-size: 14px; + } + .hide-icon{ + width: 38px; + .el-input__inner{ + border: none; + text-align: center; + } + } + } + .el-form-item__content{ + line-height: 31px !important; + } + .el-form-item__error{ + padding-top: 2px; + } + } } .severity-item{ color: $--color-text-secondary; diff --git a/nezha-fronted/src/components/common/rightBox/alertRuleBox.vue b/nezha-fronted/src/components/common/rightBox/alertRuleBox.vue index 49e512c69..23541757f 100644 --- a/nezha-fronted/src/components/common/rightBox/alertRuleBox.vue +++ b/nezha-fronted/src/components/common/rightBox/alertRuleBox.vue @@ -18,10 +18,10 @@ - + - - - - -
-
{{item.name}}
-
{{item.remark}}
-
-
-
- -
+ +
{{$t('alert.config.condition')}}
- - + - + - - - - - - - - - - - + +
+ +
+
{{item.name}}
+
+ {{$t('alert.config.when')}} Result + + + +
+ +
+
+ +
+
{{$t('alert.config.normal')}}
+ +
+ {{$t('alert.config.detectionNormal')}} + {{$t('alert.config.secondNormal')}} +
+
+
+
@@ -116,18 +118,30 @@ + { required: showSnmpTrap, message: this.$t('validate.required'), trigger: 'change' }, + ]" + > + + + + + - + - - - - - + + +
{{ $t('alert.config.notificationConfig') }}
@@ -155,6 +167,83 @@ + + + + + + + + + + + + + + + + + + + + + + + {{item.name}}@{{item.username}} + + + + + + + + + + + +
{{ $t('alert.config.effectiveConfig') }}
@@ -244,82 +333,8 @@ }"> -
{{ $t('alert.config.notificationConfig') }}
- - - - - - - - - - - - - - - - - - - - - - - {{item.name}}@{{item.username}} - - - - - - - - - - + +
{{ $t('overall.more') }}
@@ -352,7 +367,8 @@ import promqlInputMixin from '@/components/common/mixin/promqlInput' export default { name: 'alertRuleBox', props: { - alertRule: Object + alertRule: Object, + severityData: Array }, components: { 'promql-input': promqlInput, @@ -453,12 +469,15 @@ export default { { label: '<=', value: '<=' + }, + { + label: '~=', + value: '~=' } ], unitOptions: chartDataFormat.unitOptions(), userData: [], - severityData: [], notifyData: [], MetricsType: 1, weekList: [ @@ -489,6 +508,15 @@ export default { }, methods: { nzNumber: nzNumber, + thresholdValidator (rule, value, callback) { + if (rule.item.operator === '~=' || !value) { + callback() + } else if (isNaN(Number(value))) { + callback(new Error(this.$t('validate.number'))) + } else { + callback() + } + }, clickOutside () { this.esc(false) }, @@ -502,10 +530,20 @@ export default { if (this.editAlertRule.type !== 3) { this.editAlertRule.expr = this.expressions[0] } + // 处理condition 删除掉不需要的属性 + const condition = this.editAlertRule.condition.map(item => { + return { + id: item.id, + weight: item.weight, + operator: item.operator, + value: item.value + } + }) const params = { ...this.editAlertRule, method: this.editAlertRule.method.join(','), - type: this.editAlertRule.type + type: this.editAlertRule.type, + condition } this.$refs.alertRuleForm.validate((valid) => { if (valid) { @@ -570,16 +608,6 @@ export default { metricChange (val) { this.editAlertRule.expr = val }, - getSeverityData () { - this.$get('alert/severity', { pageNo: 1, pageSize: -1 }).then(response => { - if (response.code == 200) { - this.severityData = response.data.list - if (!this.editAlertRule.id && this.severityData.length > 0) { - this.editAlertRule.severityId = this.severityData[0].id - } - } - }) - }, getNotifyData () { this.$get('alert/notify/method', { pageNo: 1, pageSize: -1 }).then(response => { if (response.code == 200) { @@ -631,11 +659,18 @@ export default { }, afterInitRich () { this.$refs.alertName.focus() + }, + // 比较符号变化 + operatorChange (item, index, value) { + if (item.operator === '~=' || value === '~=') { + item.value = '' + this.$refs.alertRuleForm.clearValidate('condition.' + index + '.value') // 移除from表单的 condition 验证 + } + item.operator = value } }, mounted () { this.getUserList() - this.getSeverityData() this.getNotifyData() }, watch: { @@ -645,6 +680,35 @@ export default { handler (n, o) { this.isEdit = true this.editAlertRule = JSON.parse(JSON.stringify(n)) + // 给condition赋值 + if (this.editAlertRule.condition && this.editAlertRule.condition.length) { + this.$set(this.editAlertRule, 'condition', this.severityData.map(item => { + item = { + ...item, + value: '', + operator: '>' + } + this.editAlertRule.condition.forEach(subItem => { + if (item.id === subItem.id) { + item = { + ...item, + operator: subItem.operator, + value: subItem.value + } + } + }) + return item + })) + } else { + this.$set(this.editAlertRule, 'condition', this.severityData.map(item => { + return { + ...item, + value: '', + operator: '>' + } + })) + } + if (this.editAlertRule.id || this.editAlertRule.name) { this.expressions = [this.editAlertRule.expr] this.showTypeSelect = true // 当 edit 时禁用 type下拉框 diff --git a/nezha-fronted/src/components/common/table/alert/alertRuleTable.vue b/nezha-fronted/src/components/common/table/alert/alertRuleTable.vue index 8c20f519b..7b9885a07 100644 --- a/nezha-fronted/src/components/common/table/alert/alertRuleTable.vue +++ b/nezha-fronted/src/components/common/table/alert/alertRuleTable.vue @@ -188,61 +188,71 @@ export default { show: true, width: 80, sortable: 'custom' - }, { + }, + { label: this.$t('alert.alertName'), prop: 'name', show: true, minWidth: 200, sortable: 'custom' - }, { + }, + { label: this.$t('overall.type'), prop: 'type', show: true, minWidth: 200, sortable: 'custom' - }, { + }, + { label: this.$t('alert.config.expr'), prop: 'expr', minWidth: 200, show: true - }, { - label: this.$t('alert.config.operator'), - prop: 'operator', - minWidth: 100, - show: true - }, { - label: this.$t('alert.config.threshold'), - prop: 'threshold', - minWidth: 100, - show: true - }, { + }, + // { + // label: this.$t('alert.config.operator'), + // prop: 'operator', + // minWidth: 100, + // show: true + // }, { + // label: this.$t('alert.config.threshold'), + // prop: 'threshold', + // minWidth: 100, + // show: true + // }, + { label: this.$t('alert.config.for'), prop: 'last', minWidth: 100, show: true - }, { - label: this.$t('alert.severity'), - prop: 'severity', - show: true, - minWidth: 100, - sortable: 'custom' - }, { + }, + // { + // label: this.$t('alert.severity'), + // prop: 'severity', + // show: true, + // minWidth: 100, + // sortable: 'custom' + // }, + { label: this.$t('alert.summary'), prop: 'summary', minWidth: 200, show: true - }, { + }, + { label: this.$t('overall.remark'), prop: 'description', minWidth: 200, show: true - }, { + }, + { label: this.$t('alert.alert'), prop: 'alertNum', show: true, width: 120, sortable: 'custom' - }, { + }, + { label: this.$t('alert.receiver'), prop: 'receivers', show: false, @@ -253,7 +263,8 @@ export default { prop: 'method', show: false, minWidth: 100 - }, { + }, + { label: this.$t('overall.state'), prop: 'state', show: true, diff --git a/nezha-fronted/src/components/page/alert/alertRule.vue b/nezha-fronted/src/components/page/alert/alertRule.vue index 74511d50a..7c477490a 100644 --- a/nezha-fronted/src/components/page/alert/alertRule.vue +++ b/nezha-fronted/src/components/page/alert/alertRule.vue @@ -133,7 +133,7 @@ - + @@ -186,12 +186,12 @@ export default { unit: 2, operator: '>', last: 60, - severityId: '', + // severityId: '', summary: '', description: '', method: [], name: '', - threshold: '', + // threshold: '', receiver: [], autoExpired: 1, schedEnable: 0, @@ -201,7 +201,8 @@ export default { notifyActive: 0, notifyExpired: 0, timeout: 300, - trbShot: '' + trbShot: '', + condition: [] }, blankSilenceObject: { id: '', @@ -221,33 +222,38 @@ export default { silenceBoxShow: false, searchMsg: { // 给搜索框子组件传递的信息 zheze_none: true, - searchLabelList: [{ - id: 1, - name: 'ID', - type: 'input', - label: 'ids', - disabled: false - }, { - id: 2, - name: this.$t('alert.alertName'), - type: 'input', - label: 'name', - disabled: false - }, { - id: 4, - name: this.$t('alert.severity'), - type: 'severity', - label: 'severityIds', - readonly: true, - disabled: false - }, { - id: 5, - name: this.$t('overall.type'), - type: 'alertTypes', - label: 'type', - readonly: true, - disabled: false - }] + searchLabelList: [ + { + id: 1, + name: 'ID', + type: 'input', + label: 'ids', + disabled: false + }, + { + id: 2, + name: this.$t('alert.alertName'), + type: 'input', + label: 'name', + disabled: false + }, + // { + // id: 4, + // name: this.$t('alert.severity'), + // type: 'severity', + // label: 'severityIds', + // readonly: true, + // disabled: false + // }, + { + id: 5, + name: this.$t('overall.type'), + type: 'alertTypes', + label: 'type', + readonly: true, + disabled: false + } + ] }, searchTime: bus.getTimezontDateRange(), needAlertDaysData: true, @@ -367,6 +373,13 @@ export default { }, copy (u) { this.edit(u, true) + }, + getSeverityData () { + this.$get('alert/severity', { pageNo: 1, pageSize: -1 }).then(response => { + if (response.code == 200) { + this.severityData = response.data.list + } + }) } }, created () { @@ -391,25 +404,25 @@ export default { }, jsonKey: 'val' }, - severityIds: { - target: this.searchLabel, - isSearchInput: true, - propertyName: 'severityIds', - type: 'string', - defaultJson: { - disabled: false, - id: 4, - label: 'severityIds', - name: 'Priority', - readonly: true, - type: 'severity', - val: '', - valnum: '', - valString: '', - listStr: 'severitySelect' - }, - jsonKey: 'valnum' - }, + // severityIds: { + // target: this.searchLabel, + // isSearchInput: true, + // propertyName: 'severityIds', + // type: 'string', + // defaultJson: { + // disabled: false, + // id: 4, + // label: 'severityIds', + // name: 'Priority', + // readonly: true, + // type: 'severity', + // val: '', + // valnum: '', + // valString: '', + // listStr: 'severitySelect' + // }, + // jsonKey: 'valnum' + // }, type: { target: this.searchLabel, isSearchInput: true, @@ -445,6 +458,7 @@ export default { } } this.initQueryFromPath(searchKeys) + this.getSeverityData() }, mounted () { },