diff --git a/src/api/iot/rule/scene/scene.types.ts b/src/api/iot/rule/scene/scene.types.ts index 29fc5f533..3e712f3d8 100644 --- a/src/api/iot/rule/scene/scene.types.ts +++ b/src/api/iot/rule/scene/scene.types.ts @@ -107,7 +107,7 @@ interface ActionConfig { alertConfigId?: number // 告警配置ID(告警恢复时必填) } -// 表单数据接口 +// 表单数据接口 - 直接对应后端 DO 结构 interface RuleSceneFormData { id?: number name: string @@ -117,57 +117,38 @@ interface RuleSceneFormData { actions: ActionFormData[] } +// 触发器表单数据 - 直接对应 TriggerDO interface TriggerFormData { - type: number - productId?: number - deviceId?: number - identifier?: string - operator?: string - value?: string - cronExpression?: string - // 新的条件结构 - mainCondition?: ConditionFormData // 主条件(必须满足) - conditionGroup?: ConditionGroupContainerFormData // 条件组容器(可选,与主条件为且关系) + type: number // 触发类型 + productId?: number // 产品编号 + deviceId?: number // 设备编号 + identifier?: string // 物模型标识符 + operator?: string // 操作符 + value?: string // 参数值 + cronExpression?: string // CRON 表达式 + conditionGroups?: TriggerConditionFormData[][] // 条件组(二维数组) } -interface ActionFormData { - type: number - productId?: number - deviceId?: number - params?: Record - alertConfigId?: number -} - -// 条件组容器(包含多个子条件组,子条件组间为或关系) -interface ConditionGroupContainerFormData { - subGroups: SubConditionGroupFormData[] // 子条件组数组,子条件组间为或关系 -} - -// 子条件组(内部条件为且关系) -interface SubConditionGroupFormData { - conditions: ConditionFormData[] // 条件数组,条件间为且关系 -} - -// 保留原有接口用于兼容性 -interface ConditionGroupFormData { - conditions: ConditionFormData[] - // 注意:条件组内部的条件固定为"且"关系,条件组之间固定为"或"关系 - // logicOperator 字段保留用于兼容性,但在UI中固定为 'AND' - logicOperator: 'AND' | 'OR' -} - -interface ConditionFormData { +// 触发条件表单数据 - 直接对应 TriggerConditionDO +interface TriggerConditionFormData { type: number // 条件类型:1-设备状态,2-设备属性,3-当前时间 - productId?: number // 产品ID(设备状态和设备属性时必填) - deviceId?: number // 设备ID(设备状态和设备属性时必填) - identifier?: string // 标识符(设备属性时必填) + productId?: number // 产品编号 + deviceId?: number // 设备编号 + identifier?: string // 标识符 operator: string // 操作符 param: string // 参数值 - timeValue?: string // 时间值(当前时间条件时使用) - timeValue2?: string // 第二个时间值(时间范围条件时使用) } -// 主接口 +// 执行器表单数据 - 直接对应 ActionDO +interface ActionFormData { + type: number // 执行类型 + productId?: number // 产品编号 + deviceId?: number // 设备编号 + params?: Record // 请求参数 + alertConfigId?: number // 告警配置编号 +} + +// 主接口 - 原有的 API 接口格式(保持兼容性) interface IotRuleScene extends TenantBaseDO { id?: number // 场景编号(新增时为空) name: string // 场景名称(必填) @@ -177,6 +158,47 @@ interface IotRuleScene extends TenantBaseDO { actions: ActionConfig[] // 执行器数组(必填,至少一个) } +// 后端 DO 接口 - 匹配后端数据结构 +interface IotRuleSceneDO { + id?: number // 场景编号 + name: string // 场景名称 + description?: string // 场景描述 + status: number // 场景状态:0-开启,1-关闭 + triggers: TriggerDO[] // 触发器数组 + actions: ActionDO[] // 执行器数组 +} + +// 触发器 DO 结构 +interface TriggerDO { + type: number // 触发类型 + productId?: number // 产品编号 + deviceId?: number // 设备编号 + identifier?: string // 物模型标识符 + operator?: string // 操作符 + value?: string // 参数值 + cronExpression?: string // CRON 表达式 + conditionGroups?: TriggerConditionDO[][] // 条件组(二维数组) +} + +// 触发条件 DO 结构 +interface TriggerConditionDO { + type: number // 条件类型 + productId?: number // 产品编号 + deviceId?: number // 设备编号 + identifier?: string // 标识符 + operator: string // 操作符 + param: string // 参数 +} + +// 执行器 DO 结构 +interface ActionDO { + type: number // 执行类型 + productId?: number // 产品编号 + deviceId?: number // 设备编号 + params?: Record // 请求参数 + alertConfigId?: number // 告警配置编号 +} + // 工具类型 - 从枚举中提取类型 // TriggerType 现在从 constants.ts 中的枚举提取 export type ActionType = @@ -202,6 +224,10 @@ interface FormValidationRules { export { IotRuleScene, + IotRuleSceneDO, + TriggerDO, + TriggerConditionDO, + ActionDO, TriggerConfig, TriggerCondition, TriggerConditionParameter, @@ -209,11 +235,8 @@ export { ActionDeviceControl, RuleSceneFormData, TriggerFormData, + TriggerConditionFormData, ActionFormData, - ConditionGroupFormData, - ConditionGroupContainerFormData, - SubConditionGroupFormData, - ConditionFormData, IotRuleSceneActionTypeEnum, IotDeviceMessageTypeEnum, IotRuleSceneTriggerConditionParameterOperatorEnum, diff --git a/src/views/iot/rule/scene/form/RuleSceneForm.vue b/src/views/iot/rule/scene/form/RuleSceneForm.vue index 57437196d..5f565024f 100644 --- a/src/views/iot/rule/scene/form/RuleSceneForm.vue +++ b/src/views/iot/rule/scene/form/RuleSceneForm.vue @@ -41,9 +41,11 @@ import TriggerSection from './sections/TriggerSection.vue' import ActionSection from './sections/ActionSection.vue' import { IotRuleScene, + IotRuleSceneDO, IotRuleSceneActionTypeEnum, RuleSceneFormData, - TriggerFormData + TriggerFormData, + TriggerConditionFormData } from '@/api/iot/rule/scene/scene.types' import { IotRuleSceneTriggerTypeEnum } from '@/views/iot/utils/constants' import { ElMessage } from 'element-plus' @@ -91,8 +93,7 @@ const createDefaultFormData = (): RuleSceneFormData => { operator: undefined, value: undefined, cronExpression: undefined, - mainCondition: undefined, - conditionGroup: undefined + conditionGroups: [] // 空的条件组数组 } ], actions: [] @@ -100,49 +101,10 @@ const createDefaultFormData = (): RuleSceneFormData => { } /** - * 将表单数据转换为 API 请求格式 + * 将表单数据转换为后端 DO 格式 + * 由于数据结构已对齐,转换变得非常简单 */ -const convertFormToVO = (formData: RuleSceneFormData): IotRuleScene => { - // 构建单个触发器的条件 - const buildTriggerConditions = (trigger: TriggerFormData) => { - const conditions: any[] = [] - - // 处理主条件 - if (trigger.mainCondition) { - const mainCondition = trigger.mainCondition - conditions.push({ - type: mainCondition.type === 2 ? 'property' : 'event', - identifier: mainCondition.identifier || '', - parameters: [ - { - operator: mainCondition.operator, - value: mainCondition.param - } - ] - }) - } - - // 处理条件组 - if (trigger.conditionGroup?.subGroups) { - trigger.conditionGroup.subGroups.forEach((subGroup) => { - subGroup.conditions.forEach((condition) => { - conditions.push({ - type: condition.type === 2 ? 'property' : 'event', - identifier: condition.identifier || '', - parameters: [ - { - operator: condition.operator, - value: condition.param - } - ] - }) - }) - }) - } - - return conditions - } - +const convertFormToVO = (formData: RuleSceneFormData): IotRuleSceneDO => { return { id: formData.id, name: formData.name, @@ -150,79 +112,41 @@ const convertFormToVO = (formData: RuleSceneFormData): IotRuleScene => { status: Number(formData.status), triggers: formData.triggers.map((trigger) => ({ type: trigger.type, - productKey: trigger.productId ? `product_${trigger.productId}` : undefined, - deviceNames: trigger.deviceId ? [`device_${trigger.deviceId}`] : undefined, + productId: trigger.productId, + deviceId: trigger.deviceId, + identifier: trigger.identifier, + operator: trigger.operator, + value: trigger.value, cronExpression: trigger.cronExpression, - conditions: buildTriggerConditions(trigger) + conditionGroups: trigger.conditionGroups || [] })), - actions: - formData.actions?.map((action) => ({ - type: action.type, - alertConfigId: action.alertConfigId, - deviceControl: - action.type === IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET || - action.type === IotRuleSceneActionTypeEnum.DEVICE_SERVICE_INVOKE - ? { - productKey: action.productId ? `product_${action.productId}` : '', - deviceNames: action.deviceId ? [`device_${action.deviceId}`] : [], - type: - action.type === IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET - ? 'property' - : 'service', - identifier: - action.type === IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET ? 'set' : 'invoke', - params: action.params || {} - } - : undefined - })) || [] - } as IotRuleScene + actions: formData.actions?.map((action) => ({ + type: action.type, + productId: action.productId, + deviceId: action.deviceId, + params: action.params, + alertConfigId: action.alertConfigId + })) || [] + } } /** - * 将 API 响应数据转换为表单格式 + * 将后端 DO 数据转换为表单格式 + * 由于数据结构已对齐,转换变得非常简单 */ -const convertVOToForm = (apiData: IotRuleScene): RuleSceneFormData => { - // 解析单个触发器的条件 - const parseConditions = (trigger: any) => { - if (!trigger?.conditions?.length) { - return { - mainCondition: undefined, - conditionGroup: undefined - } - } - - // 简化处理:将第一个条件作为主条件 - const firstCondition = trigger.conditions[0] - const mainCondition = { - type: firstCondition.type === 'property' ? 2 : 3, - productId: undefined, // 需要从 productKey 解析 - deviceId: undefined, // 需要从 deviceNames 解析 - identifier: firstCondition.identifier, - operator: firstCondition.parameters?.[0]?.operator || '=', - param: firstCondition.parameters?.[0]?.value || '' - } - - return { - mainCondition, - conditionGroup: undefined // 暂时简化处理 - } - } - +const convertVOToForm = (apiData: IotRuleSceneDO): RuleSceneFormData => { // 转换所有触发器 const triggers = apiData.triggers?.length - ? apiData.triggers.map((trigger) => { - const conditionData = parseConditions(trigger) - return { - type: Number(trigger.type), - productId: undefined, // 需要从 productKey 解析 - deviceId: undefined, // 需要从 deviceNames 解析 - identifier: undefined, - operator: undefined, - value: undefined, - cronExpression: trigger.cronExpression, - ...conditionData - } - }) + ? apiData.triggers.map((trigger: any) => ({ + type: Number(trigger.type), + productId: trigger.productId, + deviceId: trigger.deviceId, + identifier: trigger.identifier, + operator: trigger.operator, + value: trigger.value, + cronExpression: trigger.cronExpression, + conditionGroups: trigger.conditionGroups || [] + })) : [ { type: IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST, @@ -232,22 +156,23 @@ const convertVOToForm = (apiData: IotRuleScene): RuleSceneFormData => { operator: undefined, value: undefined, cronExpression: undefined, - mainCondition: undefined, - conditionGroup: undefined + conditionGroups: [] } ] return { - ...apiData, + id: apiData.id, + name: apiData.name, + description: apiData.description, status: Number(apiData.status), triggers, actions: - apiData.actions?.map((action) => ({ - ...action, + apiData.actions?.map((action: any) => ({ type: Number(action.type), - productId: undefined, // 需要从 deviceControl.productKey 解析 - deviceId: undefined, // 需要从 deviceControl.deviceNames 解析 - params: action.deviceControl?.params || {}, + productId: action.productId, + deviceId: action.deviceId, + params: action.params || {}, + alertConfigId: action.alertConfigId, // 为每个执行器添加唯一标识符,解决组件索引重用问题 key: generateUUID() })) || [] @@ -321,9 +246,13 @@ const handleSubmit = async () => { // 提交请求 submitLoading.value = true try { + console.log(formData.value) // 转换数据格式 const apiData = convertFormToVO(formData.value) - + if (true) { + console.log('转换后', apiData) + return + } // 调用API保存数据 if (isEdit.value) { // 更新场景联动规则 diff --git a/src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue b/src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue index e16d558ec..5301e5ebe 100644 --- a/src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue +++ b/src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue @@ -1,10 +1,10 @@ - +