From a8adda7dc573b6d3697333739754f13d24939788 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 7 Aug 2025 14:29:59 +0800 Subject: [PATCH 01/16] =?UTF-8?q?perf:=20=E3=80=90IoT=20=E7=89=A9=E8=81=94?= =?UTF-8?q?=E7=BD=91=E3=80=91=E5=9C=BA=E6=99=AF=E8=81=94=E5=8A=A8=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=BD=92=E7=BA=B3=E4=BC=98=E5=8C=96=EF=BC=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=A4=9A=E4=BD=99=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/iot/rule/scene/index.ts | 43 ++- src/api/iot/rule/scene/scene.types.ts | 202 ----------- src/api/iot/thingmodel/index.ts | 105 +++++- .../iot/rule/scene/form/RuleSceneForm.vue | 2 +- .../scene/form/configs/ConditionConfig.vue | 2 +- .../configs/CurrentTimeConditionConfig.vue | 9 +- .../form/configs/DeviceControlConfig.vue | 3 +- .../configs/DeviceStatusConditionConfig.vue | 2 +- .../form/configs/DeviceTriggerConfig.vue | 31 +- .../form/configs/MainConditionConfig.vue | 12 +- .../form/configs/MainConditionInnerConfig.vue | 9 +- .../form/configs/SubConditionGroupConfig.vue | 2 +- .../scene/form/sections/ActionSection.vue | 2 +- .../scene/form/sections/BasicInfoSection.vue | 2 +- .../scene/form/sections/TriggerSection.vue | 10 +- .../form/selectors/ProductDeviceSelector.vue | 317 ------------------ .../scene/form/selectors/PropertySelector.vue | 30 +- src/views/iot/rule/scene/index.vue | 2 +- .../dataSpecs/ThingModelEnumDataSpecs.vue | 4 +- .../dataSpecs/ThingModelNumberDataSpecs.vue | 4 +- 20 files changed, 209 insertions(+), 584 deletions(-) delete mode 100644 src/api/iot/rule/scene/scene.types.ts delete mode 100644 src/views/iot/rule/scene/form/selectors/ProductDeviceSelector.vue diff --git a/src/api/iot/rule/scene/index.ts b/src/api/iot/rule/scene/index.ts index 9bbf8db6a..bd0a450d0 100644 --- a/src/api/iot/rule/scene/index.ts +++ b/src/api/iot/rule/scene/index.ts @@ -1,5 +1,46 @@ import request from '@/config/axios' -import { IotSceneRule } from './scene.types' + +// 场景联动 +export interface IotSceneRule { + id?: number // 场景编号 + name: string // 场景名称 + description?: string // 场景描述 + status: number // 场景状态:0-开启,1-关闭 + triggers: Trigger[] // 触发器数组 + actions: Action[] // 执行器数组 +} + +// 触发器结构 +export interface Trigger { + type: number // 触发类型 + productId?: number // 产品编号 + deviceId?: number // 设备编号 + identifier?: string // 物模型标识符 + operator?: string // 操作符 + value?: string // 参数值 + cronExpression?: string // CRON 表达式 + conditionGroups?: TriggerCondition[][] // 条件组(二维数组) +} + +// 触发条件结构 +export interface TriggerCondition { + type: number // 条件类型:1-设备状态,2-设备属性,3-当前时间 + productId?: number // 产品编号 + deviceId?: number // 设备编号 + identifier?: string // 标识符 + operator: string // 操作符 + param: string // 参数 +} + +// 执行器结构 +export interface Action { + type: number // 执行类型 + productId?: number // 产品编号 + deviceId?: number // 设备编号 + identifier?: string // 物模型标识符(服务调用时使用) + params?: string // 请求参数 + alertConfigId?: number // 告警配置编号 +} // IoT 场景联动 API export const RuleSceneApi = { diff --git a/src/api/iot/rule/scene/scene.types.ts b/src/api/iot/rule/scene/scene.types.ts deleted file mode 100644 index d8ba01faa..000000000 --- a/src/api/iot/rule/scene/scene.types.ts +++ /dev/null @@ -1,202 +0,0 @@ -/** - * IoT 场景联动接口定义 - */ - -// ========== IoT物模型TSL数据类型定义 ========== - -// TODO @puhui999:看看有些是不是在别的模块已经定义了。物模型的 - -/** 物模型TSL响应数据结构 */ -export interface IotThingModelTSLRespVO { - productId: number - productKey: string - properties: ThingModelProperty[] - events: ThingModelEvent[] - services: ThingModelService[] -} - -/** 物模型属性 */ -export interface ThingModelProperty { - identifier: string - name: string - accessMode: string - required?: boolean - dataType: string - description?: string - dataSpecs?: ThingModelDataSpecs - dataSpecsList?: ThingModelDataSpecs[] -} - -/** 物模型事件 */ -export interface ThingModelEvent { - identifier: string - name: string - required?: boolean - type: string - description?: string - outputParams?: ThingModelParam[] - method?: string -} - -/** 物模型服务 */ -export interface ThingModelService { - identifier: string - name: string - required?: boolean - callType: string - description?: string - inputParams?: ThingModelParam[] - outputParams?: ThingModelParam[] - method?: string -} - -/** 物模型参数 */ -export interface ThingModelParam { - identifier: string - name: string - direction: string - paraOrder?: number - dataType: string - dataSpecs?: ThingModelDataSpecs - dataSpecsList?: ThingModelDataSpecs[] -} - -/** 数值型数据规范 */ -export interface ThingModelNumericDataSpec { - dataType: 'int' | 'float' | 'double' - max: string - min: string - step: string - precise?: string - defaultValue?: string - unit?: string - unitName?: string -} - -/** 布尔/枚举型数据规范 */ -export interface ThingModelBoolOrEnumDataSpecs { - dataType: 'bool' | 'enum' - name: string - value: number -} - -/** 文本/时间型数据规范 */ -export interface ThingModelDateOrTextDataSpecs { - dataType: 'text' | 'date' - length?: number - defaultValue?: string -} - -/** 数组型数据规范 */ -export interface ThingModelArrayDataSpecs { - dataType: 'array' - size: number - childDataType: string - dataSpecsList?: ThingModelDataSpecs[] -} - -/** 结构体型数据规范 */ -export interface ThingModelStructDataSpecs { - dataType: 'struct' - identifier: string - name: string - accessMode: string - required?: boolean - childDataType: string - dataSpecs?: ThingModelDataSpecs - dataSpecsList?: ThingModelDataSpecs[] -} - -/** 数据规范联合类型 */ -export type ThingModelDataSpecs = - | ThingModelNumericDataSpec - | ThingModelBoolOrEnumDataSpecs - | ThingModelDateOrTextDataSpecs - | ThingModelArrayDataSpecs - | ThingModelStructDataSpecs - -/** 属性选择器内部使用的统一数据结构 */ -export interface PropertySelectorItem { - identifier: string - name: string - description?: string - dataType: string - type: number // IoTThingModelTypeEnum - accessMode?: string - required?: boolean - unit?: string - range?: string - eventType?: string - callType?: string - inputParams?: ThingModelParam[] - outputParams?: ThingModelParam[] - property?: ThingModelProperty - event?: ThingModelEvent - service?: ThingModelService -} - -// ========== 场景联动规则相关接口定义 ========== - -// 后端 DO 接口 - 匹配后端数据结构 -interface IotSceneRule { - id?: number // 场景编号 - name: string // 场景名称 - description?: string // 场景描述 - status: number // 场景状态:0-开启,1-关闭 - triggers: Trigger[] // 触发器数组 - actions: Action[] // 执行器数组 -} - -// 触发器 DO 结构 -interface Trigger { - type: number // 触发类型 - productId?: number // 产品编号 - deviceId?: number // 设备编号 - identifier?: string // 物模型标识符 - operator?: string // 操作符 - value?: string // 参数值 - cronExpression?: string // CRON 表达式 - conditionGroups?: TriggerCondition[][] // 条件组(二维数组) -} - -// 触发条件 DO 结构 -interface TriggerCondition { - type: number // 条件类型:1-设备状态,2-设备属性,3-当前时间 - productId?: number // 产品编号 - deviceId?: number // 设备编号 - identifier?: string // 标识符 - operator: string // 操作符 - param: string // 参数 -} - -// 执行器 DO 结构 -interface Action { - type: number // 执行类型 - productId?: number // 产品编号 - deviceId?: number // 设备编号 - identifier?: string // 物模型标识符(服务调用时使用) - params?: string // 请求参数 - alertConfigId?: number // 告警配置编号 -} - -// 表单验证规则类型 -interface ValidationRule { - required?: boolean - message?: string - trigger?: string | string[] - type?: string - min?: number - max?: number - enum?: any[] -} - -interface FormValidationRules { - [key: string]: ValidationRule[] -} - -// 表单数据类型别名 -export type TriggerFormData = Trigger - -// TODO @puhui999:这个文件,目标最终没有哈,和别的模块一致; - -export { IotSceneRule, Trigger, TriggerCondition, Action, ValidationRule, FormValidationRules } diff --git a/src/api/iot/thingmodel/index.ts b/src/api/iot/thingmodel/index.ts index 2ad37caed..bcf9e0707 100644 --- a/src/api/iot/thingmodel/index.ts +++ b/src/api/iot/thingmodel/index.ts @@ -40,7 +40,7 @@ export interface ThingModelService { } /** dataSpecs 数值型数据结构 */ -export interface DataSpecsNumberDataVO { +export interface DataSpecsNumberData { dataType: 'int' | 'float' | 'double' // 数据类型,取值为 INT、FLOAT 或 DOUBLE max: string // 最大值,必须与 dataType 设置一致,且为 STRING 类型 min: string // 最小值,必须与 dataType 设置一致,且为 STRING 类型 @@ -52,13 +52,114 @@ export interface DataSpecsNumberDataVO { } /** dataSpecs 枚举型数据结构 */ -export interface DataSpecsEnumOrBoolDataVO { +export interface DataSpecsEnumOrBoolData { dataType: 'enum' | 'bool' defaultValue?: string // 默认值,可选 name: string // 枚举项的名称 value: number | undefined // 枚举值 } +/** 物模型TSL响应数据结构 */ +export interface IotThingModelTSLResp { + productId: number + productKey: string + properties: ThingModelProperty[] + events: ThingModelEvent[] + services: ThingModelService[] +} + +/** 物模型属性 */ +export interface ThingModelProperty { + identifier: string + name: string + accessMode: string + required?: boolean + dataType: string + description?: string + dataSpecs?: ThingModelProperty + dataSpecsList?: ThingModelProperty[] +} + +/** 物模型事件 */ +export interface ThingModelEvent { + identifier: string + name: string + required?: boolean + type: string + description?: string + outputParams?: ThingModelParam[] + method?: string +} + +/** 物模型服务 */ +export interface ThingModelService { + identifier: string + name: string + required?: boolean + callType: string + description?: string + inputParams?: ThingModelParam[] + outputParams?: ThingModelParam[] + method?: string +} + +/** 物模型参数 */ +export interface ThingModelParam { + identifier: string + name: string + direction: string + paraOrder?: number + dataType: string + dataSpecs?: ThingModelProperty + dataSpecsList?: ThingModelProperty[] +} + +/** 数值型数据规范 */ +export interface ThingModelNumericDataSpec { + dataType: 'int' | 'float' | 'double' + max: string + min: string + step: string + precise?: string + defaultValue?: string + unit?: string + unitName?: string +} + +/** 布尔/枚举型数据规范 */ +export interface ThingModelBoolOrEnumDataSpecs { + dataType: 'bool' | 'enum' + name: string + value: number +} + +/** 文本/时间型数据规范 */ +export interface ThingModelDateOrTextDataSpecs { + dataType: 'text' | 'date' + length?: number + defaultValue?: string +} + +/** 数组型数据规范 */ +export interface ThingModelArrayDataSpecs { + dataType: 'array' + size: number + childDataType: string + dataSpecsList?: ThingModelProperty[] +} + +/** 结构体型数据规范 */ +export interface ThingModelStructDataSpecs { + dataType: 'struct' + identifier: string + name: string + accessMode: string + required?: boolean + childDataType: string + dataSpecs?: ThingModelProperty + dataSpecsList?: ThingModelProperty[] +} + // IoT 产品物模型 API export const ThingModelApi = { // 查询产品物模型分页 diff --git a/src/views/iot/rule/scene/form/RuleSceneForm.vue b/src/views/iot/rule/scene/form/RuleSceneForm.vue index 0362bc4bf..9abcb6981 100644 --- a/src/views/iot/rule/scene/form/RuleSceneForm.vue +++ b/src/views/iot/rule/scene/form/RuleSceneForm.vue @@ -36,7 +36,7 @@ import { useVModel } from '@vueuse/core' import BasicInfoSection from './sections/BasicInfoSection.vue' import TriggerSection from './sections/TriggerSection.vue' import ActionSection from './sections/ActionSection.vue' -import { IotSceneRule } from '@/api/iot/rule/scene/scene.types' +import { IotSceneRule } from '@/api/iot/rule/scene' import { RuleSceneApi } from '@/api/iot/rule/scene' import { IotRuleSceneTriggerTypeEnum, diff --git a/src/views/iot/rule/scene/form/configs/ConditionConfig.vue b/src/views/iot/rule/scene/form/configs/ConditionConfig.vue index 9574c58ce..8a9fcee99 100644 --- a/src/views/iot/rule/scene/form/configs/ConditionConfig.vue +++ b/src/views/iot/rule/scene/form/configs/ConditionConfig.vue @@ -123,7 +123,7 @@ import DeviceSelector from '../selectors/DeviceSelector.vue' import PropertySelector from '../selectors/PropertySelector.vue' import OperatorSelector from '../selectors/OperatorSelector.vue' import ValueInput from '../inputs/ValueInput.vue' -import { TriggerCondition } from '@/api/iot/rule/scene/scene.types' +import type { TriggerCondition } from '@/api/iot/rule/scene' import { IotRuleSceneTriggerConditionTypeEnum, IotRuleSceneTriggerConditionParameterOperatorEnum diff --git a/src/views/iot/rule/scene/form/configs/CurrentTimeConditionConfig.vue b/src/views/iot/rule/scene/form/configs/CurrentTimeConditionConfig.vue index 0cf1087c8..bcf052979 100644 --- a/src/views/iot/rule/scene/form/configs/CurrentTimeConditionConfig.vue +++ b/src/views/iot/rule/scene/form/configs/CurrentTimeConditionConfig.vue @@ -94,17 +94,18 @@ - - diff --git a/src/views/iot/rule/scene/form/selectors/PropertySelector.vue b/src/views/iot/rule/scene/form/selectors/PropertySelector.vue index c8d237a4d..03c648f7f 100644 --- a/src/views/iot/rule/scene/form/selectors/PropertySelector.vue +++ b/src/views/iot/rule/scene/form/selectors/PropertySelector.vue @@ -160,12 +160,38 @@ import { useVModel } from '@vueuse/core' import { InfoFilled } from '@element-plus/icons-vue' import { IotRuleSceneTriggerTypeEnum, IoTThingModelTypeEnum } from '@/views/iot/utils/constants' +import type { + IotThingModelTSLResp, + ThingModelEvent, + ThingModelParam, + ThingModelProperty, + ThingModelService +} from '@/api/iot/thingmodel' import { ThingModelApi } from '@/api/iot/thingmodel' -import type { IotThingModelTSLRespVO, PropertySelectorItem } from '@/api/iot/rule/scene/scene.types' /** 属性选择器组件 */ defineOptions({ name: 'PropertySelector' }) +/** 属性选择器内部使用的统一数据结构 */ +export interface PropertySelectorItem { + identifier: string + name: string + description?: string + dataType: string + type: number // IoTThingModelTypeEnum + accessMode?: string + required?: boolean + unit?: string + range?: string + eventType?: string + callType?: string + inputParams?: ThingModelParam[] + outputParams?: ThingModelParam[] + property?: ThingModelProperty + event?: ThingModelEvent + service?: ThingModelService +} + const props = defineProps<{ modelValue?: string triggerType: number @@ -183,7 +209,7 @@ const localValue = useVModel(props, 'modelValue', emit) // 状态 const loading = ref(false) const propertyList = ref([]) -const thingModelTSL = ref(null) +const thingModelTSL = ref(null) // 计算属性 const propertyGroups = computed(() => { diff --git a/src/views/iot/rule/scene/index.vue b/src/views/iot/rule/scene/index.vue index 4a587072c..50200ebdf 100644 --- a/src/views/iot/rule/scene/index.vue +++ b/src/views/iot/rule/scene/index.vue @@ -239,7 +239,7 @@ import { DICT_TYPE, getIntDictOptions, getDictLabel } from '@/utils/dict' import { ContentWrap } from '@/components/ContentWrap' import RuleSceneForm from './form/RuleSceneForm.vue' -import { IotSceneRule } from '@/api/iot/rule/scene/scene.types' +import { IotSceneRule } from '@/api/iot/rule/scene' import { RuleSceneApi } from '@/api/iot/rule/scene' import { IotRuleSceneTriggerTypeEnum, diff --git a/src/views/iot/thingmodel/dataSpecs/ThingModelEnumDataSpecs.vue b/src/views/iot/thingmodel/dataSpecs/ThingModelEnumDataSpecs.vue index 2820aeac4..71d47789f 100644 --- a/src/views/iot/thingmodel/dataSpecs/ThingModelEnumDataSpecs.vue +++ b/src/views/iot/thingmodel/dataSpecs/ThingModelEnumDataSpecs.vue @@ -46,14 +46,14 @@ import { useVModel } from '@vueuse/core' import { isEmpty } from '@/utils/is' import { IoTDataSpecsDataTypeEnum } from '@/views/iot/utils/constants' -import { DataSpecsEnumOrBoolDataVO } from '@/api/iot/thingmodel' +import { DataSpecsEnumOrBoolData } from '@/api/iot/thingmodel' /** 枚举型的 dataSpecs 配置组件 */ defineOptions({ name: 'ThingModelEnumDataSpecs' }) const props = defineProps<{ modelValue: any }>() const emits = defineEmits(['update:modelValue']) -const dataSpecsList = useVModel(props, 'modelValue', emits) as Ref +const dataSpecsList = useVModel(props, 'modelValue', emits) as Ref const message = useMessage() /** 添加枚举项 */ diff --git a/src/views/iot/thingmodel/dataSpecs/ThingModelNumberDataSpecs.vue b/src/views/iot/thingmodel/dataSpecs/ThingModelNumberDataSpecs.vue index 0a8857dee..d7a47c36b 100644 --- a/src/views/iot/thingmodel/dataSpecs/ThingModelNumberDataSpecs.vue +++ b/src/views/iot/thingmodel/dataSpecs/ThingModelNumberDataSpecs.vue @@ -60,14 +60,14 @@ diff --git a/src/views/iot/rule/scene/form/sections/TriggerSection.vue b/src/views/iot/rule/scene/form/sections/TriggerSection.vue index ce6163851..fb45b670f 100644 --- a/src/views/iot/rule/scene/form/sections/TriggerSection.vue +++ b/src/views/iot/rule/scene/form/sections/TriggerSection.vue @@ -66,11 +66,31 @@ /> - + class="flex flex-col gap-16px" + > +
+ + 定时触发配置 +
+ + +
+ + + +
+ @@ -95,7 +115,7 @@ -- Gitee From 416411732f1b3283f7e73aef50dd8f9d5e5798c2 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 7 Aug 2025 14:50:14 +0800 Subject: [PATCH 04/16] =?UTF-8?q?perf:=20=E3=80=90IoT=20=E7=89=A9=E8=81=94?= =?UTF-8?q?=E7=BD=91=E3=80=91=E5=9C=BA=E6=99=AF=E8=81=94=E5=8A=A8=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20ConditionGroupContainerConfig=20=E7=9A=84=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E7=9B=B4=E6=8E=A5=E5=86=85=E8=81=94=E5=9C=A8=E4=B8=BB?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scene/form/configs/ConditionConfig.vue | 1 - .../configs/ConditionGroupContainerConfig.vue | 233 ------------------ .../form/configs/DeviceTriggerConfig.vue | 213 +++++++++++++++- 3 files changed, 207 insertions(+), 240 deletions(-) delete mode 100644 src/views/iot/rule/scene/form/configs/ConditionGroupContainerConfig.vue diff --git a/src/views/iot/rule/scene/form/configs/ConditionConfig.vue b/src/views/iot/rule/scene/form/configs/ConditionConfig.vue index 8a9fcee99..98644b98a 100644 --- a/src/views/iot/rule/scene/form/configs/ConditionConfig.vue +++ b/src/views/iot/rule/scene/form/configs/ConditionConfig.vue @@ -77,7 +77,6 @@ - -
- -
-
-
-
- 组 -
- 附加条件组 -
- 与“主条件”为且关系 - {{ modelValue?.length || 0 }} 个子条件组 -
-
- - - 添加子条件组 - - - - 删除条件组 - -
-
- - -
- -
-
- -
-
-
-
-
- {{ subGroupIndex + 1 }} -
- 子条件组 {{ subGroupIndex + 1 }} -
- 组内条件为"且"关系 - - {{ subGroup.conditions?.length || 0 }}个条件 - -
- - - 删除组 - -
- - -
- - -
-
- -
- -
- -
- -
-
-
-
-
-
- - -
-
- -
-

暂无子条件组

-

点击上方"添加子条件组"按钮开始配置

-
-
-
-
- - - diff --git a/src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue b/src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue index aa94efd2f..d3f39ee66 100644 --- a/src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue +++ b/src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue @@ -39,11 +39,128 @@
- +
+ +
+
+
+
+ 组 +
+ 附加条件组 +
+ 与"主条件"为且关系 + + {{ trigger.conditionGroups?.length || 0 }} 个子条件组 + +
+
+ + + 添加子条件组 + + + + 删除条件组 + +
+
+ + +
+ +
+
+ +
+
+
+
+
+ {{ subGroupIndex + 1 }} +
+ 子条件组 {{ subGroupIndex + 1 }} +
+ 组内条件为"且"关系 + {{ subGroup?.length || 0 }}个条件 +
+ + + 删除组 + +
+ + +
+ + +
+
+ +
+ +
+ +
+ +
+
+
+
+
+
+ + +
+
+ +
+

暂无子条件组

+

点击上方"添加子条件组"按钮开始配置

+
+
+
+
@@ -52,7 +169,7 @@ import { useVModel } from '@vueuse/core' import MainConditionInnerConfig from './MainConditionInnerConfig.vue' -import ConditionGroupContainerConfig from './ConditionGroupContainerConfig.vue' +import SubConditionGroupConfig from './SubConditionGroupConfig.vue' import type { Trigger } from '@/api/iot/rule/scene' /** 设备触发配置组件 */ @@ -71,6 +188,13 @@ const emit = defineEmits<{ const trigger = useVModel(props, 'modelValue', emit) +// 配置常量 +const maxSubGroups = 3 // 最多 3 个子条件组 +const maxConditionsPerGroup = 3 // 每组最多 3 个条件 + +// 验证状态 +const subGroupValidations = ref<{ [key: number]: { valid: boolean; message: string } }>({}) + // 事件处理 const updateCondition = (condition: Trigger) => { trigger.value = condition @@ -85,7 +209,84 @@ const handleTriggerTypeChange = (type: number) => { emit('trigger-type-change', type) } +// 条件组相关方法 +const addSubGroup = () => { + if (!trigger.value.conditionGroups) { + trigger.value.conditionGroups = [] + } + + // 检查是否达到最大子组数量限制 + if (trigger.value.conditionGroups?.length >= maxSubGroups) { + return + } + + // 使用 nextTick 确保响应式更新完成后再添加新的子组 + nextTick(() => { + if (trigger.value.conditionGroups) { + trigger.value.conditionGroups.push([]) + } + }) +} + +const removeSubGroup = (index: number) => { + if (trigger.value.conditionGroups) { + trigger.value.conditionGroups.splice(index, 1) + delete subGroupValidations.value[index] + + // 重新索引验证结果 + const newValidations: { [key: number]: { valid: boolean; message: string } } = {} + Object.keys(subGroupValidations.value).forEach((key) => { + const numKey = parseInt(key) + if (numKey > index) { + newValidations[numKey - 1] = subGroupValidations.value[numKey] + } else if (numKey < index) { + newValidations[numKey] = subGroupValidations.value[numKey] + } + }) + subGroupValidations.value = newValidations + + updateValidationResult() + } +} + +const updateSubGroup = (index: number, subGroup: any) => { + if (trigger.value.conditionGroups) { + trigger.value.conditionGroups[index] = subGroup + } +} + const removeConditionGroup = () => { trigger.value.conditionGroups = undefined } + +const handleSubGroupValidate = (index: number, result: { valid: boolean; message: string }) => { + subGroupValidations.value[index] = result + updateValidationResult() +} + +const updateValidationResult = () => { + if (!trigger.value.conditionGroups || trigger.value.conditionGroups.length === 0) { + emit('validate', { valid: true, message: '条件组容器为空,验证通过' }) + return + } + + const validations = Object.values(subGroupValidations.value) + const allValid = validations.every((v: any) => v.valid) + + if (allValid) { + emit('validate', { valid: true, message: '条件组容器配置验证通过' }) + } else { + const errorMessages = validations.filter((v: any) => !v.valid).map((v: any) => v.message) + emit('validate', { valid: false, message: `子条件组配置错误: ${errorMessages.join('; ')}` }) + } +} + +// 监听变化 +watch( + () => trigger.value.conditionGroups, + () => { + updateValidationResult() + }, + { deep: true, immediate: true } +) -- Gitee From d077604bc941b16ff44fc98d60619a97354f7b40 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 7 Aug 2025 15:09:15 +0800 Subject: [PATCH 05/16] =?UTF-8?q?perf:=20=E3=80=90IoT=20=E7=89=A9=E8=81=94?= =?UTF-8?q?=E7=BD=91=E3=80=91=E5=9C=BA=E6=99=AF=E8=81=94=E5=8A=A8=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20ActionTypeSelector=20=E7=9A=84=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E5=86=85=E8=81=94=E5=9C=A8=E4=B8=BB=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scene/form/sections/ActionSection.vue | 32 +++-- .../form/selectors/ActionTypeSelector.vue | 113 ------------------ src/views/iot/utils/constants.ts | 24 +--- 3 files changed, 26 insertions(+), 143 deletions(-) delete mode 100644 src/views/iot/rule/scene/form/selectors/ActionTypeSelector.vue diff --git a/src/views/iot/rule/scene/form/sections/ActionSection.vue b/src/views/iot/rule/scene/form/sections/ActionSection.vue index 893bf6ece..23fe572b6 100644 --- a/src/views/iot/rule/scene/form/sections/ActionSection.vue +++ b/src/views/iot/rule/scene/form/sections/ActionSection.vue @@ -1,5 +1,4 @@ -