// TODO @puhui999:貌似很多地方,都用不到啦?这个文件 /** * IoT 场景联动表单验证工具函数 */ import { FormValidationRules, TriggerConfig, ActionConfig } from '@/api/iot/rule/scene/scene.types' import { IotRuleSceneTriggerTypeEnum, IotRuleSceneActionTypeEnum, CommonStatusEnum } from '@/api/iot/rule/scene/scene.types' /** 基础表单验证规则 */ export const getBaseValidationRules = (): FormValidationRules => ({ 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' } ] }) /** 验证CRON表达式格式 */ // TODO @puhui999:这个可以拿到 cron 组件里哇? export function validateCronExpression(cron: string): boolean { if (!cron || cron.trim().length === 0) return false // 基础的 CRON 表达式正则验证(支持 6 位和 7 位格式) const cronRegex = /^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])) (\*|([0-6])|\*\/([0-6]))( (\*|([1-9][0-9]{3})|\*\/([1-9][0-9]{3})))?$/ return cronRegex.test(cron.trim()) } /** 验证设备名称数组 */ export function validateDeviceNames(deviceNames: string[]): boolean { return ( Array.isArray(deviceNames) && deviceNames.length > 0 && deviceNames.every((name) => name && name.trim().length > 0) ) } /** 验证比较值格式 */ export function validateCompareValue(operator: string, value: string): boolean { if (!value || value.trim().length === 0) return false const trimmedValue = value.trim() // TODO @puhui999:这里要用下枚举哇? switch (operator) { case 'between': case 'not between': const betweenValues = trimmedValue.split(',') return ( betweenValues.length === 2 && betweenValues.every((v) => v.trim().length > 0) && !isNaN(Number(betweenValues[0].trim())) && !isNaN(Number(betweenValues[1].trim())) ) case 'in': case 'not in': const inValues = trimmedValue.split(',') return inValues.length > 0 && inValues.every((v) => v.trim().length > 0) case '>': case '>=': case '<': case '<=': return !isNaN(Number(trimmedValue)) case '=': case '!=': case 'like': case 'not null': // TODO @puhui999:这里要不加个 default 抛出异常? default: return true } } // TODO @puhui999:貌似没用到? /** 验证触发器配置 */ export function validateTriggerConfig(trigger: TriggerConfig): { valid: boolean message?: string } { if (!trigger.type) { return { valid: false, message: '触发类型不能为空' } } // 定时触发验证 if (trigger.type === IotRuleSceneTriggerTypeEnum.TIMER) { if (!trigger.cronExpression) { return { valid: false, message: 'CRON表达式不能为空' } } if (!validateCronExpression(trigger.cronExpression)) { return { valid: false, message: 'CRON表达式格式不正确' } } return { valid: true } } // 设备触发验证 if (!trigger.productKey) { return { valid: false, message: '产品标识不能为空' } } if (!trigger.deviceNames || !validateDeviceNames(trigger.deviceNames)) { return { valid: false, message: '设备名称不能为空' } } // 设备状态变更无需额外条件验证 if (trigger.type === IotRuleSceneTriggerTypeEnum.DEVICE_STATE_UPDATE) { return { valid: true } } // 其他设备触发类型需要验证条件 if (!trigger.conditions || trigger.conditions.length === 0) { return { valid: false, message: '触发条件不能为空' } } // 验证每个条件的参数 for (const condition of trigger.conditions) { if (!condition.parameters || condition.parameters.length === 0) { return { valid: false, message: '触发条件参数不能为空' } } for (const param of condition.parameters) { if (!param.operator) { return { valid: false, message: '操作符不能为空' } } if (!validateCompareValue(param.operator, param.value)) { return { valid: false, message: `操作符 "${param.operator}" 对应的比较值格式不正确` } } } } return { valid: true } } // TODO @puhui999:貌似没用到? /** 验证执行器配置 */ export function validateActionConfig(action: ActionConfig): { valid: boolean; message?: string } { if (!action.type) { return { valid: false, message: '执行类型不能为空' } } // 告警触发/恢复验证 if ( action.type === IotRuleSceneActionTypeEnum.ALERT_TRIGGER || action.type === IotRuleSceneActionTypeEnum.ALERT_RECOVER ) { if (!action.alertConfigId) { return { valid: false, message: '告警配置ID不能为空' } } return { valid: true } } // 设备控制验证 if ( action.type === IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET || action.type === IotRuleSceneActionTypeEnum.DEVICE_SERVICE_INVOKE ) { if (!action.deviceControl) { return { valid: false, message: '设备控制配置不能为空' } } const { deviceControl } = action if (!deviceControl.productKey) { return { valid: false, message: '产品标识不能为空' } } if (!deviceControl.deviceNames || !validateDeviceNames(deviceControl.deviceNames)) { return { valid: false, message: '设备名称不能为空' } } if (!deviceControl.type) { return { valid: false, message: '消息类型不能为空' } } if (!deviceControl.identifier) { return { valid: false, message: '消息标识符不能为空' } } if (!deviceControl.params || Object.keys(deviceControl.params).length === 0) { return { valid: false, message: '参数不能为空' } } return { valid: true } } return { valid: false, message: '未知的执行类型' } }