189 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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: '未知的执行类型' }
}