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) => { export const transformRecognizeNodeData = (source) => {
// 初始化结果对象 // 初始化结果对象
const result = { const result = {
nodeParams: [] nodeParams: [],
alarmRules: []
}; };
// 遍历每一个顶级节点 // 遍历每一个顶级节点
@ -387,7 +388,19 @@ export const transformRecognizeNodeData = (source) => {
} }
if (name === 'alarmRules') { 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; return;
} }
@ -422,4 +435,4 @@ export const transformRecognizeNodeData = (source) => {
}); });
return result; return result;
} }

View File

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