!859 feat(iot):【场景联动】定时触发,增加条件组

Merge pull request !859 from puhui999/feature/iot
This commit is contained in:
芋道源码
2026-01-25 13:39:46 +00:00
committed by Gitee
3 changed files with 207 additions and 6 deletions

View File

@@ -0,0 +1,174 @@
<!-- 定时触发器条件组配置组件 -->
<template>
<div class="space-y-16px">
<!-- 条件组容器头部 -->
<div
class="flex items-center justify-between p-16px bg-gradient-to-r from-blue-50 to-cyan-50 border border-blue-200 rounded-8px"
>
<div class="flex items-center gap-12px">
<div class="flex items-center gap-8px text-16px font-600 text-blue-700">
<div
class="w-24px h-24px bg-blue-500 text-white rounded-full flex items-center justify-center text-12px font-bold"
>
</div>
<span>附加条件组</span>
</div>
<el-tag size="small" type="info">定时触发时需满足以下条件</el-tag>
<el-tag size="small" type="warning">
{{ conditionGroups?.length || 0 }} 个子条件组
</el-tag>
</div>
<el-button
type="primary"
size="small"
@click="addConditionGroup"
:disabled="(conditionGroups?.length || 0) >= maxGroups"
>
<Icon icon="ep:plus" />
添加条件组
</el-button>
</div>
<!-- 条件组列表 -->
<div v-if="conditionGroups && conditionGroups.length > 0" class="space-y-16px">
<div
v-for="(group, groupIndex) in conditionGroups"
:key="`group-${groupIndex}`"
class="relative"
>
<!-- 条件组容器 -->
<div
class="border-2 border-orange-200 rounded-8px bg-orange-50 shadow-sm hover:shadow-md transition-shadow"
>
<div
class="flex items-center justify-between p-16px bg-gradient-to-r from-orange-50 to-yellow-50 border-b border-orange-200 rounded-t-6px"
>
<div class="flex items-center gap-12px">
<div class="flex items-center gap-8px text-16px font-600 text-orange-700">
<div
class="w-24px h-24px bg-orange-500 text-white rounded-full flex items-center justify-center text-12px font-bold"
>
{{ groupIndex + 1 }}
</div>
<span>子条件组 {{ groupIndex + 1 }}</span>
</div>
<el-tag size="small" type="warning" class="font-500">组内条件为"且"关系</el-tag>
<el-tag size="small" type="info"> {{ group?.length || 0 }}个条件 </el-tag>
</div>
<el-button
type="danger"
size="small"
text
@click="removeConditionGroup(groupIndex)"
class="hover:bg-red-50"
>
<Icon icon="ep:delete" />
删除组
</el-button>
</div>
<SubConditionGroupConfig
:model-value="group"
@update:model-value="(value) => updateConditionGroup(groupIndex, value)"
:trigger-type="IotRuleSceneTriggerTypeEnum.TIMER"
:max-conditions="maxConditionsPerGroup"
/>
</div>
<!-- 条件组间的""连接符 -->
<div
v-if="groupIndex < conditionGroups.length - 1"
class="flex items-center justify-center py-12px"
>
<div class="flex items-center gap-8px">
<!-- 连接线 -->
<div class="w-32px h-1px bg-orange-300"></div>
<!-- 或标签 -->
<div class="px-16px py-6px bg-orange-100 border-2 border-orange-300 rounded-full">
<span class="text-14px font-600 text-orange-600">或</span>
</div>
<!-- 连接线 -->
<div class="w-32px h-1px bg-orange-300"></div>
</div>
</div>
</div>
</div>
<!-- 空状态 -->
<div
v-else
class="p-24px border-2 border-dashed border-blue-200 rounded-8px text-center bg-blue-50"
>
<div class="flex flex-col items-center gap-12px">
<Icon icon="ep:plus" class="text-32px text-blue-400" />
<div class="text-blue-600">
<p class="text-14px font-500 mb-4px">暂无附加条件</p>
<p class="text-12px">定时触发时将直接执行动作</p>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import SubConditionGroupConfig from './SubConditionGroupConfig.vue'
import type { TriggerCondition } from '@/api/iot/rule/scene'
import { IotRuleSceneTriggerTypeEnum } from '@/views/iot/utils/constants'
/** 定时触发器条件组配置组件 */
defineOptions({ name: 'TimerConditionGroupConfig' })
const props = defineProps<{
modelValue?: TriggerCondition[][]
}>()
const emit = defineEmits<{
(e: 'update:modelValue', value: TriggerCondition[][]): void
}>()
const conditionGroups = useVModel(props, 'modelValue', emit)
const maxGroups = 3 // 最多 3 个条件组
const maxConditionsPerGroup = 3 // 每组最多 3 个条件
/** 添加条件组 */
const addConditionGroup = async () => {
if (!conditionGroups.value) {
conditionGroups.value = []
}
// 检查是否达到最大条件组数量限制
if (conditionGroups.value.length >= maxGroups) {
return
}
// 使用 nextTick 确保响应式更新完成后再添加新的条件组
await nextTick()
if (conditionGroups.value) {
conditionGroups.value.push([])
}
}
/**
* 移除条件组
* @param index 条件组索引
*/
const removeConditionGroup = (index: number) => {
if (conditionGroups.value) {
conditionGroups.value.splice(index, 1)
}
}
/**
* 更新条件组
* @param index 条件组索引
* @param group 条件组数据
*/
const updateConditionGroup = (index: number, group: TriggerCondition[]) => {
if (conditionGroups.value) {
conditionGroups.value[index] = group
}
}
</script>

View File

@@ -90,6 +90,12 @@
/>
</el-form-item>
</div>
<!-- 附加条件组配置 -->
<TimerConditionGroupConfig
:model-value="triggerItem.conditionGroups"
@update:model-value="(value) => updateTriggerConditionGroups(index, value)"
/>
</div>
</div>
</div>
@@ -115,8 +121,9 @@
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import DeviceTriggerConfig from '../configs/DeviceTriggerConfig.vue'
import TimerConditionGroupConfig from '../configs/TimerConditionGroupConfig.vue'
import { Crontab } from '@/components/Crontab'
import type { Trigger } from '@/api/iot/rule/scene'
import type { Trigger, TriggerCondition } from '@/api/iot/rule/scene'
import {
getTriggerTypeLabel,
IotRuleSceneTriggerTypeEnum,
@@ -197,6 +204,15 @@ const updateTriggerCronConfig = (index: number, cronExpression?: string) => {
triggers.value[index].cronExpression = cronExpression
}
/**
* 更新触发器条件组配置
* @param index 触发器索引
* @param conditionGroups 条件组数组
*/
const updateTriggerConditionGroups = (index: number, conditionGroups: TriggerCondition[][]) => {
triggers.value[index].conditionGroups = conditionGroups
}
/**
* 处理触发器类型变化事件
* @param index 触发器索引

View File

@@ -219,13 +219,23 @@ const thingModelTSL = ref<IotThingModelTSLResp | null>(null) // 物模型TSL数
const propertyGroups = computed(() => {
const groups: { label: string; options: any[] }[] = []
if (props.triggerType === IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST) {
groups.push({
label: THING_MODEL_GROUP_LABELS.PROPERTY,
options: propertyList.value.filter((p) => p.type === IoTThingModelTypeEnum.PROPERTY)
})
// 设备属性上报触发器 或 定时触发器(条件组中的设备属性条件)
if (
props.triggerType === IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST ||
props.triggerType === IotRuleSceneTriggerTypeEnum.TIMER
) {
const propertyOptions = propertyList.value.filter(
(p) => p.type === IoTThingModelTypeEnum.PROPERTY
)
if (propertyOptions.length > 0) {
groups.push({
label: THING_MODEL_GROUP_LABELS.PROPERTY,
options: propertyOptions
})
}
}
// 设备事件上报触发器
if (props.triggerType === IotRuleSceneTriggerTypeEnum.DEVICE_EVENT_POST) {
groups.push({
label: THING_MODEL_GROUP_LABELS.EVENT,
@@ -233,6 +243,7 @@ const propertyGroups = computed(() => {
})
}
// 设备服务调用触发器
if (props.triggerType === IotRuleSceneTriggerTypeEnum.DEVICE_SERVICE_INVOKE) {
groups.push({
label: THING_MODEL_GROUP_LABELS.SERVICE,