fix: preserve alert configuration intent

This commit is contained in:
zxr
2026-07-21 22:15:59 +08:00
parent 7e61f330dc
commit b4dba77229
8 changed files with 51 additions and 26 deletions

View File

@@ -76,6 +76,8 @@ export interface SyslogRule {
keyword_regex: string
source_match: string
message_regex: string
recovery_match_regex: string
lifecycle_key: string
alert_name: string
severity_code: string
severity_mapping_json: string
@@ -92,6 +94,8 @@ export interface TrapRule {
priority: number
oid_prefix: string
varbind_match_regex: string
recovery_match_regex: string
lifecycle_key: string
alert_name: string
severity_code: string
policy_id: number

View File

@@ -1,4 +1,4 @@
import { computed } from 'vue'
import { computed, type Ref } from 'vue'
import type { FormItem } from '@/components/search-form/types'
import { SUPPRESSION_TYPE_OPTIONS } from '@/api/ops/suppression'
import type { PolicyOption } from '../types'
@@ -6,7 +6,7 @@ import type { PolicyOption } from '../types'
/**
* 获取筛选表单项配置
*/
export const useFormItems = (policyOptions: PolicyOption[]) => {
export const useFormItems = (policyOptions: Ref<PolicyOption[]>) => {
return computed<FormItem[]>(() => [
{
field: 'keyword',
@@ -32,7 +32,7 @@ export const useFormItems = (policyOptions: PolicyOption[]) => {
options: [
{ value: '', label: '全部' },
{ value: '0', label: '仅全局规则' },
...policyOptions.map((p) => ({ value: String(p.id), label: p.name })),
...policyOptions.value.map((p) => ({ value: String(p.id), label: p.name })),
],
},
{

View File

@@ -136,7 +136,7 @@ const {
} = useTable()
// 筛选表单项配置
const formItems = useFormItems(policyOptions.value)
const formItems = useFormItems(policyOptions)
// 表格列配置
const tableColumns = computed(() => getTableColumns())

View File

@@ -81,30 +81,29 @@ export const validateJsonFields = (formData: SuppressionRule, fields: string[]):
}
/**
* 构建更新数据(只传非空字段)
* 构建完整更新数据,显式传递空值以支持清除旧配置
*/
export const buildUpdateData = (formData: SuppressionRule): SuppressionUpdateParams => {
const updateData: SuppressionUpdateParams = { id: formData.id! }
if (formData.name) updateData.name = formData.name
if (formData.type) updateData.type = formData.type
if (formData.description) updateData.description = formData.description
updateData.enabled = formData.enabled
if (formData.priority && formData.priority > 0) updateData.priority = formData.priority
if (formData.policy_id && formData.policy_id > 0) updateData.policy_id = formData.policy_id
if (formData.dedup_window && formData.dedup_window > 0) updateData.dedup_window = formData.dedup_window
if (formData.dedup_keys) updateData.dedup_keys = formData.dedup_keys
if (formData.aggregate_window && formData.aggregate_window > 0) updateData.aggregate_window = formData.aggregate_window
if (formData.group_by) updateData.group_by = formData.group_by
if (formData.aggregate_count && formData.aggregate_count > 0) updateData.aggregate_count = formData.aggregate_count
if (formData.source_matchers) updateData.source_matchers = formData.source_matchers
if (formData.target_matchers) updateData.target_matchers = formData.target_matchers
if (formData.throttle_count && formData.throttle_count > 0) updateData.throttle_count = formData.throttle_count
if (formData.throttle_window && formData.throttle_window > 0) updateData.throttle_window = formData.throttle_window
if (formData.schedule) updateData.schedule = formData.schedule
if (formData.matchers) updateData.matchers = formData.matchers
return updateData
return {
id: formData.id!,
name: formData.name,
type: formData.type,
description: formData.description ?? '',
enabled: formData.enabled ?? true,
priority: formData.priority ?? 0,
policy_id: formData.policy_id ?? 0,
dedup_window: formData.dedup_window ?? 0,
dedup_keys: formData.dedup_keys ?? '',
aggregate_window: formData.aggregate_window ?? 0,
group_by: formData.group_by ?? '',
aggregate_count: formData.aggregate_count ?? 0,
source_matchers: formData.source_matchers ?? '',
target_matchers: formData.target_matchers ?? '',
throttle_count: formData.throttle_count ?? 0,
throttle_window: formData.throttle_window ?? 0,
schedule: formData.schedule ?? '',
matchers: formData.matchers ?? '',
}
}
/**

View File

@@ -527,6 +527,9 @@ const handleSubmit = async () => {
// 提取规则数据
const submitRules = formData.value.rules.map((r) => {
const { _metrics, _metricsLoading, ...rest } = r as any
if (rest.rule_type === 'dynamic' && ['==', '!='].includes(rest.compare_op)) {
rest.compare_op = '>'
}
return rest
})

View File

@@ -644,6 +644,9 @@ const handleSubmit = async () => {
// 提取规则数据
const submitRules = formData.value.rules.map((r) => {
const { _metrics, _metricsLoading, ...rest } = r as any
if (rest.rule_type === 'dynamic' && ['==', '!='].includes(rest.compare_op)) {
rest.compare_op = '>'
}
return rest
})

View File

@@ -74,6 +74,12 @@
<a-form-item field="message_regex" label="消息正则">
<a-input v-model="formData.message_regex" placeholder="匹配 Syslog 正文" />
</a-form-item>
<a-form-item field="recovery_match_regex" label="恢复消息正则">
<a-input v-model="formData.recovery_match_regex" placeholder="命中后发送 resolved留空表示无恢复消息" />
</a-form-item>
<a-form-item field="lifecycle_key" label="生命周期标识">
<a-input v-model="formData.lifecycle_key" placeholder="故障与恢复使用同一稳定标识" />
</a-form-item>
<a-form-item field="resource_uid_extract_regex" label="资源 UID 提取正则">
<a-input v-model="formData.resource_uid_extract_regex" placeholder="命名分组 resource_uid 或首个捕获组" />
</a-form-item>
@@ -156,6 +162,8 @@ const emptyForm = (): SyslogRule => ({
source_match: '',
keyword_regex: '',
message_regex: '',
recovery_match_regex: '',
lifecycle_key: '',
alert_name: '',
severity_code: '',
severity_mapping_json: '',

View File

@@ -68,6 +68,12 @@
<a-form-item field="varbind_match_regex" label="Varbind 匹配正则">
<a-input v-model="formData.varbind_match_regex" placeholder="可选" />
</a-form-item>
<a-form-item field="recovery_match_regex" label="恢复 Trap 正则">
<a-input v-model="formData.recovery_match_regex" placeholder="匹配恢复 OID 或 Varbind" />
</a-form-item>
<a-form-item field="lifecycle_key" label="生命周期标识">
<a-input v-model="formData.lifecycle_key" placeholder="故障与恢复使用同一稳定标识" />
</a-form-item>
<a-form-item field="alert_name" label="告警名称">
<a-input v-model="formData.alert_name" />
</a-form-item>
@@ -142,6 +148,8 @@ const emptyForm = (): TrapRule => ({
priority: 0,
oid_prefix: '',
varbind_match_regex: '',
recovery_match_regex: '',
lifecycle_key: '',
alert_name: '',
severity_code: '',
policy_id: 0,