diff --git a/src/api/iot/rule/scene/scene.types.ts b/src/api/iot/rule/scene/scene.types.ts index b1e899305211f76a02a5b2188e7ac12cb4bd9b60..7e37716834e752ce3c327cc2db9ae89b3e71e608 100644 --- a/src/api/iot/rule/scene/scene.types.ts +++ b/src/api/iot/rule/scene/scene.types.ts @@ -2,91 +2,140 @@ * IoT 场景联动接口定义 */ -// TODO @puhui999:枚举挪到 views/iot/utils/constants.ts 里 -// 枚举定义 -const IotRuleSceneTriggerTypeEnum = { - DEVICE_STATE_UPDATE: 1, // 设备上下线变更 - DEVICE_PROPERTY_POST: 2, // 物模型属性上报 - DEVICE_EVENT_POST: 3, // 设备事件上报 - DEVICE_SERVICE_INVOKE: 4, // 设备服务调用 - TIMER: 100 // 定时触发 -} as const - -const IotRuleSceneActionTypeEnum = { - DEVICE_PROPERTY_SET: 1, // 设备属性设置, - DEVICE_SERVICE_INVOKE: 2, // 设备服务调用 - ALERT_TRIGGER: 100, // 告警触发 - ALERT_RECOVER: 101 // 告警恢复 -} as const - -const IotDeviceMessageTypeEnum = { - PROPERTY: 'property', // 属性 - SERVICE: 'service', // 服务 - EVENT: 'event' // 事件 -} as const - -// TODO @puhui999:这个貌似可以不要? -const IotDeviceMessageIdentifierEnum = { - PROPERTY_SET: 'set', // 属性设置 - SERVICE_INVOKE: '${identifier}' // 服务调用 -} as const - -const IotRuleSceneTriggerConditionParameterOperatorEnum = { - EQUALS: { name: '等于', value: '=' }, // 等于 - NOT_EQUALS: { name: '不等于', value: '!=' }, // 不等于 - GREATER_THAN: { name: '大于', value: '>' }, // 大于 - GREATER_THAN_OR_EQUALS: { name: '大于等于', value: '>=' }, // 大于等于 - LESS_THAN: { name: '小于', value: '<' }, // 小于 - LESS_THAN_OR_EQUALS: { name: '小于等于', value: '<=' }, // 小于等于 - IN: { name: '在...之中', value: 'in' }, // 在...之中 - NOT_IN: { name: '不在...之中', value: 'not in' }, // 不在...之中 - BETWEEN: { name: '在...之间', value: 'between' }, // 在...之间 - NOT_BETWEEN: { name: '不在...之间', value: 'not between' }, // 不在...之间 - LIKE: { name: '字符串匹配', value: 'like' }, // 字符串匹配 - NOT_NULL: { name: '非空', value: 'not null' } // 非空 -} as const - -// 条件类型枚举 -const IotRuleSceneTriggerConditionTypeEnum = { - DEVICE_STATUS: 1, // 设备状态 - DEVICE_PROPERTY: 2, // 设备属性 - CURRENT_TIME: 3 // 当前时间 -} as const - -// 时间运算符枚举 -const IotRuleSceneTriggerTimeOperatorEnum = { - BEFORE_TIME: { name: '在时间之前', value: 'before_time' }, // 在时间之前 - AFTER_TIME: { name: '在时间之后', value: 'after_time' }, // 在时间之后 - BETWEEN_TIME: { name: '在时间之间', value: 'between_time' }, // 在时间之间 - AT_TIME: { name: '在指定时间', value: 'at_time' }, // 在指定时间 - BEFORE_TODAY: { name: '在今日之前', value: 'before_today' }, // 在今日之前 - AFTER_TODAY: { name: '在今日之后', value: 'after_today' }, // 在今日之后 - TODAY: { name: '在今日之间', value: 'today' } // 在今日之间 -} as const - -// TODO @puhui999:下面 IotAlertConfigReceiveTypeEnum、DeviceStateEnum 没用到,貌似可以删除下? -const IotAlertConfigReceiveTypeEnum = { - SMS: 1, // 短信 - MAIL: 2, // 邮箱 - NOTIFY: 3 // 通知 -} as const - -// 设备状态枚举 -const DeviceStateEnum = { - INACTIVE: 0, // 未激活 - ONLINE: 1, // 在线 - OFFLINE: 2 // 离线 -} as const - -// TODO @puhui999:这个全局已经有啦 -// 通用状态枚举 -const CommonStatusEnum = { - ENABLE: 0, // 开启 - DISABLE: 1 // 关闭 -} as const - -// 基础接口 -// TODO @puhui999:这个貌似可以不要? +// ========== IoT物模型TSL数据类型定义 ========== + +/** 物模型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 +} + +// ========== 场景联动规则相关接口定义 ========== + +// 基础接口(如果项目中有全局的 BaseDO,可以使用全局的) interface TenantBaseDO { createTime?: Date // 创建时间 updateTime?: Date // 更新时间 @@ -138,67 +187,48 @@ interface ActionConfig { alertConfigId?: number // 告警配置ID(告警恢复时必填) } -// 表单数据接口 +// 表单数据接口 - 直接对应后端 DO 结构 interface RuleSceneFormData { id?: number name: string description?: string status: number - trigger: TriggerFormData + triggers: TriggerFormData[] // 支持多个触发器 actions: ActionFormData[] } +// 触发器表单数据 - 直接对应 TriggerDO interface TriggerFormData { - type: number - productId?: number - deviceId?: number - identifier?: string - operator?: string - value?: string - cronExpression?: string - // 新的条件结构 - mainCondition?: ConditionFormData // 主条件(必须满足) - conditionGroup?: ConditionGroupContainerFormData // 条件组容器(可选,与主条件为且关系) -} - -interface ActionFormData { - type: number - productId?: number - deviceId?: number - params?: Record - alertConfigId?: number -} - -// 条件组容器(包含多个子条件组,子条件组间为或关系) -interface ConditionGroupContainerFormData { - subGroups: SubConditionGroupFormData[] // 子条件组数组,子条件组间为或关系 + type: number // 触发类型 + productId?: number // 产品编号 + deviceId?: number // 设备编号 + identifier?: string // 物模型标识符 + operator?: string // 操作符 + value?: string // 参数值 + cronExpression?: string // CRON 表达式 + conditionGroups?: TriggerConditionFormData[][] // 条件组(二维数组) } -// 子条件组(内部条件为且关系) -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 // 场景名称(必填) @@ -208,14 +238,46 @@ interface IotRuleScene extends TenantBaseDO { actions: ActionConfig[] // 执行器数组(必填,至少一个) } -// 工具类型 - 从枚举中提取类型 -export type TriggerType = - (typeof IotRuleSceneTriggerTypeEnum)[keyof typeof IotRuleSceneTriggerTypeEnum] -export type ActionType = - (typeof IotRuleSceneActionTypeEnum)[keyof typeof IotRuleSceneActionTypeEnum] -export type MessageType = (typeof IotDeviceMessageTypeEnum)[keyof typeof IotDeviceMessageTypeEnum] -export type OperatorType = - (typeof IotRuleSceneTriggerConditionParameterOperatorEnum)[keyof typeof IotRuleSceneTriggerConditionParameterOperatorEnum]['value'] +// 后端 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 // 告警配置编号 +} // 表单验证规则类型 interface ValidationRule { @@ -234,6 +296,10 @@ interface FormValidationRules { export { IotRuleScene, + IotRuleSceneDO, + TriggerDO, + TriggerConditionDO, + ActionDO, TriggerConfig, TriggerCondition, TriggerConditionParameter, @@ -241,25 +307,8 @@ export { ActionDeviceControl, RuleSceneFormData, TriggerFormData, + TriggerConditionFormData, ActionFormData, - ConditionGroupFormData, - ConditionGroupContainerFormData, - SubConditionGroupFormData, - ConditionFormData, - IotRuleSceneTriggerTypeEnum, - IotRuleSceneActionTypeEnum, - IotDeviceMessageTypeEnum, - IotDeviceMessageIdentifierEnum, - IotRuleSceneTriggerConditionParameterOperatorEnum, - IotRuleSceneTriggerConditionTypeEnum, - IotRuleSceneTriggerTimeOperatorEnum, - IotAlertConfigReceiveTypeEnum, - DeviceStateEnum, - CommonStatusEnum, - TriggerType, - ActionType, - MessageType, - OperatorType, ValidationRule, FormValidationRules } diff --git a/src/views/iot/rule/scene/form/RuleSceneForm.vue b/src/views/iot/rule/scene/form/RuleSceneForm.vue index 3b00fdb7ac68af750487b6daa473c978ad8c451b..b765f230d5c244b3532d722fc5bff8978b354175 100644 --- a/src/views/iot/rule/scene/form/RuleSceneForm.vue +++ b/src/views/iot/rule/scene/form/RuleSceneForm.vue @@ -1,5 +1,5 @@ @@ -40,116 +39,106 @@ import { useVModel } from '@vueuse/core' import BasicInfoSection from './sections/BasicInfoSection.vue' import TriggerSection from './sections/TriggerSection.vue' import ActionSection from './sections/ActionSection.vue' -import { - RuleSceneFormData, - IotRuleScene, - IotRuleSceneActionTypeEnum, - IotRuleSceneTriggerTypeEnum, - CommonStatusEnum -} from '@/api/iot/rule/scene/scene.types' -import { getBaseValidationRules } from '../utils/validation' +import { IotRuleSceneDO, RuleSceneFormData } from '@/api/iot/rule/scene/scene.types' +import { IotRuleSceneTriggerTypeEnum } from '@/views/iot/utils/constants' import { ElMessage } from 'element-plus' import { generateUUID } from '@/utils' +// 导入全局的 CommonStatusEnum +const CommonStatusEnum = { + ENABLE: 0, // 开启 + DISABLE: 1 // 关闭 +} as const + /** IoT 场景联动规则表单 - 主表单组件 */ defineOptions({ name: 'RuleSceneForm' }) -// TODO @puhui999:是不是融合到 props -interface Props { +/** 组件属性定义 */ +const props = defineProps<{ + /** 抽屉显示状态 */ modelValue: boolean - ruleScene?: IotRuleScene -} +}>() -// TODO @puhui999:Emits 是不是融合到 emit -interface Emits { +/** 组件事件定义 */ +const emit = defineEmits<{ (e: 'update:modelValue', value: boolean): void (e: 'success'): void -} - -const props = defineProps() -const emit = defineEmits() +}>() const drawerVisible = useVModel(props, 'modelValue', emit) // 是否可见 -// TODO @puhui999:使用 /** 注释风格哈 */ - /** 创建默认的表单数据 */ const createDefaultFormData = (): RuleSceneFormData => { return { name: '', description: '', status: CommonStatusEnum.ENABLE, // 默认启用状态 - trigger: { - type: IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST, - productId: undefined, - deviceId: undefined, - identifier: undefined, - operator: undefined, - value: undefined, - cronExpression: undefined, - mainCondition: undefined, - conditionGroup: undefined - }, + triggers: [ + { + type: IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST, + productId: undefined, + deviceId: undefined, + identifier: undefined, + operator: undefined, + value: undefined, + cronExpression: undefined, + conditionGroups: [] // 空的条件组数组 + } + ], actions: [] } } -// TODO @puhui999:使用 convertFormToVO;下面也是类似哈; /** - * 将表单数据转换为 API 请求格式 + * 将表单数据转换为后端 DO 格式 + * 由于数据结构已对齐,转换变得非常简单 */ -const transformFormToApi = (formData: RuleSceneFormData): IotRuleScene => { +const convertFormToVO = (formData: RuleSceneFormData): IotRuleSceneDO => { return { id: formData.id, name: formData.name, description: formData.description, status: Number(formData.status), - triggers: [ - { - type: formData.trigger.type, - productKey: formData.trigger.productId - ? `product_${formData.trigger.productId}` - : undefined, - deviceNames: formData.trigger.deviceId - ? [`device_${formData.trigger.deviceId}`] - : undefined, - cronExpression: formData.trigger.cronExpression, - conditions: [] // TODO: 实现新的条件转换逻辑 - } - ], + triggers: formData.triggers.map((trigger) => ({ + type: trigger.type, + productId: trigger.productId, + deviceId: trigger.deviceId, + identifier: trigger.identifier, + operator: trigger.operator, + value: trigger.value, + cronExpression: trigger.cronExpression, + 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: 'property', - identifier: 'set', - params: action.params || {} - } - : undefined + productId: action.productId, + deviceId: action.deviceId, + params: action.params, + alertConfigId: action.alertConfigId })) || [] - } as IotRuleScene + } } /** - * 将 API 响应数据转换为表单格式 + * 将后端 DO 数据转换为表单格式 + * 由于数据结构已对齐,转换变得非常简单 */ -const transformApiToForm = (apiData: IotRuleScene): RuleSceneFormData => { - const firstTrigger = apiData.triggers?.[0] - return { - ...apiData, - status: Number(apiData.status), // 确保状态为数字类型 - trigger: firstTrigger - ? { - ...firstTrigger, - type: Number(firstTrigger.type) - } - : { +const convertVOToForm = (apiData: IotRuleSceneDO): RuleSceneFormData => { + // 转换所有触发器 + const triggers = apiData.triggers?.length + ? 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, productId: undefined, deviceId: undefined, @@ -157,13 +146,23 @@ const transformApiToForm = (apiData: IotRuleScene): RuleSceneFormData => { operator: undefined, value: undefined, cronExpression: undefined, - mainCondition: undefined, - conditionGroup: undefined - }, + conditionGroups: [] + } + ] + + return { + 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: action.productId, + deviceId: action.deviceId, + params: action.params || {}, + alertConfigId: action.alertConfigId, // 为每个执行器添加唯一标识符,解决组件索引重用问题 key: generateUUID() })) || [] @@ -173,7 +172,33 @@ const transformApiToForm = (apiData: IotRuleScene): RuleSceneFormData => { // 表单数据和状态 const formRef = ref() const formData = ref(createDefaultFormData()) -const formRules = getBaseValidationRules() +const formRules = reactive({ + name: [ + { required: true, message: '场景名称不能为空', trigger: 'blur' }, + { type: 'string', min: 1, max: 50, message: '场景名称长度应在1-50个字符之间', trigger: 'blur' } + ], + status: [ + { required: true, message: '场景状态不能为空', trigger: 'change' }, + { + type: 'enum', + enum: [CommonStatusEnum.ENABLE, CommonStatusEnum.DISABLE], + message: '状态值必须为启用或禁用', + trigger: 'change' + } + ], + description: [ + { type: 'string', max: 200, message: '场景描述不能超过200个字符', trigger: 'blur' } + ], + triggers: [ + { required: true, message: '触发器数组不能为空', trigger: 'change' }, + { type: 'array', min: 1, message: '至少需要一个触发器', trigger: 'change' } + ], + actions: [ + { required: true, message: '执行器数组不能为空', trigger: 'change' }, + { type: 'array', min: 1, message: '至少需要一个执行器', trigger: 'change' } + ] +}) + const submitLoading = ref(false) // 验证状态 @@ -181,7 +206,7 @@ const triggerValidation = ref({ valid: true, message: '' }) const actionValidation = ref({ valid: true, message: '' }) // 计算属性 -const isEdit = computed(() => !!props.ruleScene?.id) +const isEdit = ref(false) const drawerTitle = computed(() => (isEdit.value ? '编辑场景联动规则' : '新增场景联动规则')) // 事件处理 @@ -211,12 +236,23 @@ const handleSubmit = async () => { // 提交请求 submitLoading.value = true try { + console.log(formData.value) // 转换数据格式 - const apiData = transformFormToApi(formData.value) - - // 这里应该调用API保存数据 - // TODO @puhui999:貌似还没接入 - console.log('提交数据:', apiData) + const apiData = convertFormToVO(formData.value) + if (true) { + console.log('转换后', apiData) + return + } + // 调用API保存数据 + if (isEdit.value) { + // 更新场景联动规则 + // await RuleSceneApi.updateRuleScene(apiData) + console.log('更新数据:', apiData) + } else { + // 创建场景联动规则 + // await RuleSceneApi.createRuleScene(apiData) + console.log('创建数据:', apiData) + } // 模拟API调用 await new Promise((resolve) => setTimeout(resolve, 1000)) @@ -224,6 +260,9 @@ const handleSubmit = async () => { ElMessage.success(isEdit.value ? '更新成功' : '创建成功') drawerVisible.value = false emit('success') + } catch (error) { + console.error('保存失败:', error) + ElMessage.error(isEdit.value ? '更新失败' : '创建失败') } finally { submitLoading.value = false } @@ -233,93 +272,30 @@ const handleClose = () => { drawerVisible.value = false } -// 初始化表单数据 +/** 初始化表单数据 */ const initFormData = () => { - if (props.ruleScene) { - formData.value = transformApiToForm(props.ruleScene) - } else { - formData.value = createDefaultFormData() - } + // TODO @puhui999: 编辑的情况后面实现 + formData.value = createDefaultFormData() } // 监听抽屉显示 watch(drawerVisible, (visible) => { if (visible) { initFormData() - nextTick(() => { - formRef.value?.clearValidate() - }) + // TODO @puhui999: 重置表单的情况 + // nextTick(() => { + // formRef.value?.clearValidate() + // }) } }) // 监听 props 变化 -watch( - () => props.ruleScene, - () => { - if (drawerVisible.value) { - initFormData() - } - } -) +// watch( +// () => props.ruleScene, +// () => { +// if (drawerVisible.value) { +// initFormData() +// } +// } +// ) - - - diff --git a/src/views/iot/rule/scene/form/configs/ConditionConfig.vue b/src/views/iot/rule/scene/form/configs/ConditionConfig.vue index 8b20ec3e92641c638bebbe59ea01ae13fa2a1108..7e49c8bc7575fb7e092160b114f624f1dce035b7 100644 --- a/src/views/iot/rule/scene/form/configs/ConditionConfig.vue +++ b/src/views/iot/rule/scene/form/configs/ConditionConfig.vue @@ -89,24 +89,6 @@ - - - -
-
- - 条件预览 -
-
- {{ conditionPreview }} -
-
@@ -139,26 +121,24 @@ 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 { TriggerConditionFormData } from '@/api/iot/rule/scene/scene.types' import { - ConditionFormData, - IotRuleSceneTriggerConditionTypeEnum -} from '@/api/iot/rule/scene/scene.types' + IotRuleSceneTriggerConditionTypeEnum, + IotRuleSceneTriggerConditionParameterOperatorEnum +} from '@/views/iot/utils/constants' /** 单个条件配置组件 */ defineOptions({ name: 'ConditionConfig' }) -interface Props { - modelValue: ConditionFormData +const props = defineProps<{ + modelValue: TriggerConditionFormData triggerType: number -} +}>() -interface Emits { - (e: 'update:modelValue', value: ConditionFormData): void +const emit = defineEmits<{ + (e: 'update:modelValue', value: TriggerConditionFormData): void (e: 'validate', result: { valid: boolean; message: string }): void -} - -const props = defineProps() -const emit = defineEmits() +}>() const condition = useVModel(props, 'modelValue', emit) @@ -172,41 +152,13 @@ const validationMessage = ref('') const isValid = ref(true) const valueValidation = ref({ valid: true, message: '' }) -// 计算属性 -const conditionPreview = computed(() => { - if (!condition.value.identifier || !condition.value.operator || !condition.value.param) { - return '' - } - - const propertyName = propertyConfig.value?.name || condition.value.identifier - const operatorText = getOperatorText(condition.value.operator) - const value = condition.value.param - - return `当 ${propertyName} ${operatorText} ${value} 时触发` -}) - -// 工具函数 -const getOperatorText = (operator: string) => { - const operatorMap = { - '=': '等于', - '!=': '不等于', - '>': '大于', - '>=': '大于等于', - '<': '小于', - '<=': '小于等于', - in: '包含于', - between: '介于' - } - return operatorMap[operator] || operator -} - // 事件处理 -const updateConditionField = (field: keyof ConditionFormData, value: any) => { +const updateConditionField = (field: keyof TriggerConditionFormData, value: any) => { ;(condition.value as any)[field] = value emit('update:modelValue', condition.value) } -const updateCondition = (newCondition: ConditionFormData) => { +const updateCondition = (newCondition: TriggerConditionFormData) => { condition.value = newCondition emit('update:modelValue', condition.value) } @@ -215,19 +167,29 @@ const handleConditionTypeChange = (type: number) => { // 清理不相关的字段 if (type === ConditionTypeEnum.DEVICE_STATUS) { condition.value.identifier = undefined - condition.value.timeValue = undefined - condition.value.timeValue2 = undefined + // 清理时间相关字段(如果存在) + if ('timeValue' in condition.value) { + delete (condition.value as any).timeValue + } + if ('timeValue2' in condition.value) { + delete (condition.value as any).timeValue2 + } } else if (type === ConditionTypeEnum.CURRENT_TIME) { condition.value.identifier = undefined condition.value.productId = undefined condition.value.deviceId = undefined } else if (type === ConditionTypeEnum.DEVICE_PROPERTY) { - condition.value.timeValue = undefined - condition.value.timeValue2 = undefined + // 清理时间相关字段(如果存在) + if ('timeValue' in condition.value) { + delete (condition.value as any).timeValue + } + if ('timeValue2' in condition.value) { + delete (condition.value as any).timeValue2 + } } - // 重置操作符和参数 - condition.value.operator = '=' + // 重置操作符和参数,使用枚举中的默认值 + condition.value.operator = IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.value condition.value.param = '' updateValidationResult() @@ -239,14 +201,14 @@ const handleValidate = (result: { valid: boolean; message: string }) => { emit('validate', result) } -const handleProductChange = (productId: number) => { +const handleProductChange = (_: number) => { // 产品变化时清空设备和属性 condition.value.deviceId = undefined condition.value.identifier = '' updateValidationResult() } -const handleDeviceChange = (deviceId: number) => { +const handleDeviceChange = (_: number) => { // 设备变化时清空属性 condition.value.identifier = '' updateValidationResult() diff --git a/src/views/iot/rule/scene/form/configs/ConditionGroupConfig.vue b/src/views/iot/rule/scene/form/configs/ConditionGroupConfig.vue deleted file mode 100644 index dff6fe598620d45e167def6a72c1dacb8e1f5f1a..0000000000000000000000000000000000000000 --- a/src/views/iot/rule/scene/form/configs/ConditionGroupConfig.vue +++ /dev/null @@ -1,255 +0,0 @@ - - - - diff --git a/src/views/iot/rule/scene/form/configs/ConditionGroupContainerConfig.vue b/src/views/iot/rule/scene/form/configs/ConditionGroupContainerConfig.vue index 0c88213438ca981e13876473ce24a2581b4860b4..caa2ec9b2e1598f3c3dde4cf6f32f3bc1a68ed08 100644 --- a/src/views/iot/rule/scene/form/configs/ConditionGroupContainerConfig.vue +++ b/src/views/iot/rule/scene/form/configs/ConditionGroupContainerConfig.vue @@ -1,7 +1,6 @@