feat: 新增告警节点

This commit is contained in:
zhanghao 2026-07-23 16:50:58 +08:00
parent 5440b127ee
commit 3df96271a6
3 changed files with 104 additions and 67 deletions

View File

@ -372,7 +372,8 @@ export const transformSdAgentNodeData = (source) => {
export const transformRecognizeNodeData = (source) => {
// 初始化结果对象
const result = {
nodeParams: []
nodeParams: [],
alarmRules: []
};
// 遍历每一个顶级节点
@ -387,7 +388,19 @@ export const transformRecognizeNodeData = (source) => {
}
if (name === 'alarmRules') {
result[name] = children || [];
if (Array.isArray(item.input)) {
result[name] = item.input;
return;
}
// 兼容旧数据:旧结构把 level/operator/threshold/message
// 作为 alarmRules.children 中的字段描述保存。
const legacyRule = Object.fromEntries(
(children || [])
.filter(child => ['level', 'operator', 'threshold', 'message'].includes(child.name))
.map(child => [child.name, child.input])
);
result[name] = Object.keys(legacyRule).length ? [legacyRule] : [];
return;
}
@ -422,4 +435,4 @@ export const transformRecognizeNodeData = (source) => {
});
return result;
}
}

View File

@ -44,56 +44,39 @@
</div>
</el-collapse-item>
<el-collapse-item name="2" title="告警级别" icon-position="left">
<div class="form__container">
<div v-for="(property, index) in RecognizeNodeData.alarmRules" :key="index">
<el-row>
<el-form-item :label="index === 0 ? '参数名' : ''" :prop="`alarmRules.${index}.name`" :rules="[
{ required: true, message: '请输入参数名', trigger: 'blur' },
]">
<el-input :disabled="true" class="param-name" v-model="property.name" placeholder="请输入"
clearable />
</el-form-item>
<el-form-item :label="index === 0 ? '参数值' : ''" :prop="`alarmRules.${index}.input`">
<el-select v-model="property.type" class="param-type" @change="handleTypeChange(index)">
<el-option label="引用" value="quote" />
<el-option label="输入" value="input" />
</el-select>
<el-form-item v-if="property.type === 'input'" :rules="[
{
required: property?.required ?? true,
message: '请输入参数值',
trigger: 'blur',
},
]" :prop="`alarmRules.${index}.input`">
<el-input-number class="param-value" v-if="property.componentType === 'number'"
v-model="property.input" :min="0" :max="property.max || Infinity"
:controls="false" :step-strictly="true" placeholder="请输入" clearable />
<el-select v-model="property.input" class="param-value"
v-else-if="property.componentType === 'select'">
<el-option v-for="item in property.selectOptions" :key="item.value"
:label="item.label" :value="item.value" />
</el-select>
<el-input class="param-value" v-else v-model="property.input" placeholder="请输入"
clearable />
</el-form-item>
<el-form-item v-if="property.type === 'quote'" :rules="[
{
required: true,
message: '请选择参数值',
trigger: 'blur',
},
]" :prop="`alarmRules.${index}.quote`">
<el-cascader :ref="(el) => {
if (el) cascaderRefs[index] = el;
}
" v-model="property.quote" :checkStrictly="true" :options="quoteOptions" placeholder="请选择"
@visible-change="
(visible) => visibleChange(visible, index, property.quote)
" @change="(value) => cascaderChange(value, index, RecognizeNodeData, 'alarmRules')" />
</el-form-item>
</el-form-item>
</el-row>
</div>
<template #title>
告警级别
<el-button :circle="true" size="small" @click="addAlarmRule" class="addFormItem">
<el-icon :size="14"><Plus /></el-icon>
</el-button>
</template>
<div class="form__container alarm-rules">
<el-row v-for="(rule, index) in RecognizeNodeData.alarmRules" :key="index">
<el-form-item label="告警级别" :prop="`alarmRules.${index}.level`"
:rules="[{ required: true, message: '请输入告警级别', trigger: 'change' }]">
<el-input-number v-model="rule.level" :min="1" :max="3" :step="1"
:step-strictly="true" />
</el-form-item>
<el-form-item label="比较符" :prop="`alarmRules.${index}.operator`"
:rules="[{ required: true, message: '请选择比较符', trigger: 'change' }]">
<el-select v-model="rule.operator" placeholder="请选择">
<el-option v-for="operator in alarmOperators" :key="operator.value"
:label="operator.label" :value="operator.value" />
</el-select>
</el-form-item>
<el-form-item label="阈值" :prop="`alarmRules.${index}.threshold`"
:rules="[{ required: true, message: '请输入阈值', trigger: 'change' }]">
<el-input-number v-model="rule.threshold" :controls="false" />
</el-form-item>
<el-form-item label="告警信息" :prop="`alarmRules.${index}.message`"
:rules="[{ required: true, message: '请输入告警信息', trigger: 'blur' }]">
<el-input v-model="rule.message" placeholder="请输入告警信息" clearable />
</el-form-item>
<el-button type="danger" link class="deleteBtn" @click="deleteAlarmRule(index)">
<el-icon><Minus /></el-icon>
</el-button>
</el-row>
<el-empty v-if="!RecognizeNodeData.alarmRules.length" description="暂无告警规则" :image-size="60" />
</div>
</el-collapse-item>
<el-collapse-item name="3" icon-position="left">
@ -127,7 +110,7 @@
import { ref, reactive, watch, nextTick } from 'vue'
import { Plus, Minus } from '@element-plus/icons-vue'
import FormItemRecursive from '../FormItemRecursive.vue'
import { getInput, transformRecognizeNodeData } from '@/utils/flow'
import { transformRecognizeNodeData } from '@/utils/flow'
import { useQuote } from './useQuote.js'
const props = defineProps({
@ -167,6 +150,29 @@ const addFormItem = (e, type) => {
//
const RecognizeNodeData = ref({})
const alarmOperators = [
{ label: '大于GT', value: 'GT' },
{ label: '大于等于GTE', value: 'GTE' },
{ label: '小于LT', value: 'LT' },
{ label: '小于等于LTE', value: 'LTE' },
{ label: '等于EQ', value: 'EQ' },
{ label: '不等于NE', value: 'NE' }
]
const addAlarmRule = (e) => {
e.stopPropagation()
RecognizeNodeData.value.alarmRules.push({
level: 1,
operator: 'GTE',
threshold: 0,
message: ''
})
}
const deleteAlarmRule = (index) => {
RecognizeNodeData.value.alarmRules.splice(index, 1)
}
const addRecognizeItem = (e) => {
e.stopPropagation();
RecognizeNodeData.value.outputParams.push({ name: "", type: "string", input: "" });
@ -197,7 +203,7 @@ const initData = () => {
...transformedData,
outputParams
};
console.log('RecognizeNodeData', RecognizeNodeData.value)
console.log('RecognizeNodeData', JSON.stringify(RecognizeNodeData.value))
}
watch(
@ -220,11 +226,18 @@ const validateAndSave = async () => {
}
const nodeParams = []
nodeParams.push({ name: "config", type: "input", input: "", children: RecognizeNodeData.value.config, required: true })
nodeParams.push({ name: "invokeTts", type: "input", input: RecognizeNodeData.value.invokeTts })
if (RecognizeNodeData.value.invokeTts) {
nodeParams.push({ name: "tts", type: "input", input: "", children: RecognizeNodeData.value.tts })
}
nodeParams.push(...RecognizeNodeData.value.nodeParams)
nodeParams.push({
name: "alarmRules",
type: "input",
input: RecognizeNodeData.value.alarmRules.map(({ level, operator, threshold, message }) => ({
level,
operator,
threshold,
message
})),
disabled: true
})
lf.setProperties(props.data.id, {
...props.data.properties,
nodeParams,
@ -324,4 +337,20 @@ defineExpose({ validateAndSave })
cursor: pointer;
}
}
</style>
.alarm-rules {
:deep(.el-row) {
flex-wrap: nowrap;
.el-form-item {
flex: 1;
}
.el-select,
.el-input,
.el-input-number {
width: 100%;
}
}
}
</style>

View File

@ -447,12 +447,7 @@ function handler(params) {
nodeParams: [
{ name: 'imageUrl', type: "input", input: "", disabled: true },
{ name: 'resultName', type: "input", input: "", disabled: true },
{ name: "alarmRules", type: "input", input: "", children: [
{ name: 'level', type: "input", componentType: 'number', max: 3, step: 1, input: 1, disabled: true },
{ name: 'operator', type: "input", input: "", disabled: true },
{ name: 'threshold', type: "input", componentType: 'number', max: 3, step: 1, input: 1, disabled: true },
{ name: 'message', type: "input", input: "", disabled: true },
]}
{ name: "alarmRules", type: "input", input: [], disabled: true }
],
outputParams: []
},