perf: 【IoT 物联网】场景联动移除自定义校验规则简化校验逻辑

pull/808/head
puhui999 2025-08-07 16:31:07 +08:00
parent 09be0a10b1
commit 9684857174
9 changed files with 149 additions and 441 deletions

View File

@ -106,7 +106,6 @@ const props = defineProps<{
const emit = defineEmits<{
(e: 'update:modelValue', value: TriggerCondition): void
(e: 'validate', result: { valid: boolean; message: string }): void
}>()
const condition = useVModel(props, 'modelValue', emit)
@ -155,10 +154,6 @@ const timeOperatorOptions = [
}
]
//
const validationMessage = ref('')
const isValid = ref(true)
//
const needsTimeInput = computed(() => {
const timeOnlyOperators = [
@ -181,62 +176,16 @@ const needsSecondTimeInput = computed(() => {
//
const updateConditionField = (field: keyof TriggerCondition, value: any) => {
condition.value[field] = value
updateValidationResult()
}
const updateValidationResult = () => {
if (!condition.value.operator) {
isValid.value = false
validationMessage.value = '请选择时间条件'
emit('validate', { valid: false, message: validationMessage.value })
return
}
//
if (condition.value.operator === IotRuleSceneTriggerTimeOperatorEnum.TODAY.value) {
isValid.value = true
validationMessage.value = '当前时间条件配置验证通过'
emit('validate', { valid: true, message: validationMessage.value })
return
}
if (needsTimeInput.value && !condition.value.timeValue) {
isValid.value = false
validationMessage.value = '请设置时间值'
emit('validate', { valid: false, message: validationMessage.value })
return
}
if (needsSecondTimeInput.value && !condition.value.timeValue2) {
isValid.value = false
validationMessage.value = '请设置结束时间'
emit('validate', { valid: false, message: validationMessage.value })
return
}
isValid.value = true
validationMessage.value = '当前时间条件配置验证通过'
emit('validate', { valid: true, message: validationMessage.value })
}
//
watch(
() => [condition.value.operator, condition.value.timeValue, condition.value.timeValue2],
() => {
updateValidationResult()
},
{ immediate: true }
)
//
watch(
() => condition.value.operator,
(newOperator) => {
if (newOperator === IotRuleSceneTriggerTimeOperatorEnum.TODAY.value) {
condition.value.timeValue = undefined
condition.value.timeValue2 = undefined
;(condition.value as any).timeValue = undefined(condition.value as any).timeValue2 = undefined
} else if (!needsSecondTimeInput.value) {
condition.value.timeValue2 = undefined
;(condition.value as any).timeValue2 = undefined
}
}
)

View File

@ -55,7 +55,6 @@
type="service"
:config="{ service: selectedService }"
placeholder="请输入JSON格式的服务参数"
@validate="handleParamsValidate"
/>
</el-form-item>
</div>
@ -70,7 +69,6 @@
type="property"
:config="{ properties: thingModelProperties }"
placeholder="请输入JSON格式的控制参数"
@validate="handleParamsValidate"
/>
</el-form-item>
</div>
@ -86,7 +84,8 @@ import type { Action } from '@/api/iot/rule/scene'
import type { ThingModelProperty, ThingModelService } from '@/api/iot/thingmodel'
import {
IotRuleSceneActionTypeEnum,
IoTThingModelAccessModeEnum
IoTThingModelAccessModeEnum,
IoTDataSpecsDataTypeEnum
} from '@/views/iot/utils/constants'
import { ThingModelApi } from '@/api/iot/thingmodel'
@ -126,12 +125,6 @@ const paramsValue = computed({
}
})
//
const handleParamsValidate = (result: { valid: boolean; message: string }) => {
//
console.log('参数验证结果:', result)
}
const isPropertySetAction = computed(() => {
//
return action.value.type === IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET
@ -301,16 +294,16 @@ const loadServiceFromTSL = async (productId: number, serviceIdentifier: string)
*/
const getDefaultValueForParam = (param: any) => {
switch (param.dataType) {
case 'int':
case IoTDataSpecsDataTypeEnum.INT:
return 0
case 'float':
case 'double':
case IoTDataSpecsDataTypeEnum.FLOAT:
case IoTDataSpecsDataTypeEnum.DOUBLE:
return 0.0
case 'bool':
case IoTDataSpecsDataTypeEnum.BOOL:
return false
case 'text':
case IoTDataSpecsDataTypeEnum.TEXT:
return ''
case 'enum':
case IoTDataSpecsDataTypeEnum.ENUM:
// 使
if (param.dataSpecs?.dataSpecsList && param.dataSpecs.dataSpecsList.length > 0) {
return param.dataSpecs.dataSpecsList[0].value

View File

@ -29,7 +29,6 @@
:model-value="trigger"
@update:model-value="updateCondition"
:trigger-type="trigger.type"
@validate="handleValidate"
@trigger-type-change="handleTriggerTypeChange"
/>
</div>
@ -123,7 +122,6 @@
@update:model-value="(value) => updateSubGroup(subGroupIndex, value)"
:trigger-type="trigger.type"
:max-conditions="maxConditionsPerGroup"
@validate="(result) => handleSubGroupValidate(subGroupIndex, result)"
/>
</div>
@ -182,7 +180,6 @@ const props = defineProps<{
const emit = defineEmits<{
(e: 'update:modelValue', value: Trigger): void
(e: 'validate', value: { valid: boolean; message: string }): void
(e: 'trigger-type-change', type: number): void
}>()
@ -192,18 +189,11 @@ 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
}
const handleValidate = (result: { valid: boolean; message: string }) => {
emit('validate', result)
}
const handleTriggerTypeChange = (type: number) => {
trigger.value.type = type
emit('trigger-type-change', type)
@ -231,21 +221,6 @@ const addSubGroup = () => {
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()
}
}
@ -258,35 +233,4 @@ const updateSubGroup = (index: number, subGroup: any) => {
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 }
)
</script>

View File

@ -100,7 +100,6 @@
type="service"
:config="serviceConfig"
placeholder="请输入JSON格式的服务参数"
@validate="handleValueValidate"
/>
<!-- 事件上报参数配置 -->
<JsonParamsInput
@ -109,7 +108,6 @@
type="event"
:config="eventConfig"
placeholder="请输入JSON格式的事件参数"
@validate="handleValueValidate"
/>
<!-- 普通值输入 -->
<ValueInput
@ -119,7 +117,6 @@
:property-type="propertyType"
:operator="condition.operator"
:property-config="propertyConfig"
@validate="handleValueValidate"
/>
</el-form-item>
</el-col>
@ -202,15 +199,11 @@ const props = defineProps<{
const emit = defineEmits<{
(e: 'update:modelValue', value: Trigger): void
(e: 'validate', result: { valid: boolean; message: string }): void
(e: 'trigger-type-change', value: number): void
}>()
//
const condition = useVModel(props, 'modelValue', emit)
// TODO @puhui999 validationMessage
const isValid = ref(true)
const validationMessage = ref('')
const propertyType = ref('')
const propertyConfig = ref<any>(null)
@ -279,7 +272,6 @@ const triggerTypeOptions = getTriggerTypeOptions()
//
const updateConditionField = (field: keyof Trigger, value: any) => {
;(condition.value as any)[field] = value
updateValidationResult()
}
const handleTriggerTypeChange = (type: number) => {
@ -290,13 +282,11 @@ const handleProductChange = () => {
//
condition.value.deviceId = undefined
condition.value.identifier = ''
updateValidationResult()
}
const handleDeviceChange = () => {
//
condition.value.identifier = ''
updateValidationResult()
}
const handlePropertyChange = (propertyInfo: any) => {
@ -312,88 +302,9 @@ const handlePropertyChange = (propertyInfo: any) => {
condition.value.operator = '='
}
}
updateValidationResult()
}
const handleOperatorChange = () => {
updateValidationResult()
//
}
//
const handleValueValidate = (result: { valid: boolean; message: string }) => {
isValid.value = result.valid
validationMessage.value = result.message
emit('validate', result)
updateValidationResult()
}
//
// TODO @puhui999 validator
const updateValidationResult = () => {
if (isDevicePropertyTrigger.value) {
//
if (!condition.value.productId) {
isValid.value = false
validationMessage.value = '请选择产品'
emit('validate', { valid: false, message: validationMessage.value })
return
}
if (!condition.value.deviceId) {
isValid.value = false
validationMessage.value = '请选择设备'
emit('validate', { valid: false, message: validationMessage.value })
return
}
if (!condition.value.identifier) {
isValid.value = false
validationMessage.value = '请选择监控项'
emit('validate', { valid: false, message: validationMessage.value })
return
}
//
if (
props.triggerType !== IotRuleSceneTriggerTypeEnum.DEVICE_SERVICE_INVOKE &&
props.triggerType !== IotRuleSceneTriggerTypeEnum.DEVICE_EVENT_POST &&
!condition.value.operator
) {
isValid.value = false
validationMessage.value = '请选择操作符'
emit('validate', { valid: false, message: validationMessage.value })
return
}
if (!condition.value.value) {
isValid.value = false
validationMessage.value = '请输入比较值'
emit('validate', { valid: false, message: validationMessage.value })
return
}
}
isValid.value = true
validationMessage.value = '主条件配置验证通过'
emit('validate', { valid: true, message: validationMessage.value })
}
//
watch(
() => [
condition.value.productId,
condition.value.deviceId,
condition.value.identifier,
//
props.triggerType !== IotRuleSceneTriggerTypeEnum.DEVICE_SERVICE_INVOKE &&
props.triggerType !== IotRuleSceneTriggerTypeEnum.DEVICE_EVENT_POST
? condition.value.operator
: null,
condition.value.value
],
() => {
updateValidationResult()
},
{ immediate: true }
)
</script>

View File

@ -56,7 +56,6 @@
:model-value="condition"
@update:model-value="(value) => updateCondition(conditionIndex, value)"
:trigger-type="triggerType"
@validate="(result) => handleConditionValidate(conditionIndex, result)"
/>
</div>
</div>
@ -100,7 +99,6 @@ const props = defineProps<{
const emit = defineEmits<{
(e: 'update:modelValue', value: TriggerCondition[]): void
(e: 'validate', result: { valid: boolean; message: string }): void
}>()
const subGroup = useVModel(props, 'modelValue', emit)
@ -108,9 +106,6 @@ const subGroup = useVModel(props, 'modelValue', emit)
//
const maxConditions = computed(() => props.maxConditions || 3)
//
const conditionValidations = ref<{ [key: number]: { valid: boolean; message: string } }>({})
//
const addCondition = () => {
// subGroup.value
@ -143,21 +138,6 @@ const addCondition = () => {
const removeCondition = (index: number) => {
if (subGroup.value) {
subGroup.value.splice(index, 1)
delete conditionValidations.value[index]
//
const newValidations: { [key: number]: { valid: boolean; message: string } } = {}
Object.keys(conditionValidations.value).forEach((key) => {
const numKey = parseInt(key)
if (numKey > index) {
newValidations[numKey - 1] = conditionValidations.value[numKey]
} else if (numKey < index) {
newValidations[numKey] = conditionValidations.value[numKey]
}
})
conditionValidations.value = newValidations
updateValidationResult()
}
}
@ -166,35 +146,4 @@ const updateCondition = (index: number, condition: TriggerCondition) => {
subGroup.value[index] = condition
}
}
const handleConditionValidate = (index: number, result: { valid: boolean; message: string }) => {
conditionValidations.value[index] = result
updateValidationResult()
}
const updateValidationResult = () => {
if (!subGroup.value || subGroup.value.length === 0) {
emit('validate', { valid: false, message: '子条件组至少需要一个条件' })
return
}
const validations = Object.values(conditionValidations.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(
() => subGroup.value,
() => {
updateValidationResult()
},
{ deep: true, immediate: true }
)
</script>

View File

@ -136,6 +136,7 @@
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { InfoFilled } from '@element-plus/icons-vue'
import { IoTDataSpecsDataTypeEnum } from '@/views/iot/utils/constants'
/** JSON参数输入组件 - 通用版本 */
defineOptions({ name: 'JsonParamsInput' })
@ -169,7 +170,6 @@ interface Props {
interface Emits {
(e: 'update:modelValue', value: string): void
(e: 'validate', result: { valid: boolean; message: string }): void
}
const props = withDefaults(defineProps<Props>(), {
@ -317,7 +317,6 @@ const handleParamsChange = () => {
//
if (typeof parsed !== 'object' || parsed === null) {
jsonError.value = '参数必须是一个有效的 JSON 对象'
emit('validate', { valid: false, message: jsonError.value })
return
}
@ -325,7 +324,6 @@ const handleParamsChange = () => {
for (const param of paramsList.value) {
if (param.required && (!parsed[param.identifier] || parsed[param.identifier] === '')) {
jsonError.value = `参数 ${param.name} 为必填项`
emit('validate', { valid: false, message: jsonError.value })
return
}
}
@ -334,10 +332,9 @@ const handleParamsChange = () => {
}
//
emit('validate', { valid: true, message: 'JSON格式正确' })
jsonError.value = ''
} catch (error) {
jsonError.value = `JSON格式错误: ${error instanceof Error ? error.message : '未知错误'}`
emit('validate', { valid: false, message: jsonError.value })
}
}
@ -352,7 +349,6 @@ const clearParams = () => {
paramsJson.value = ''
localValue.value = ''
jsonError.value = ''
emit('validate', { valid: true, message: '' })
}
//
@ -373,35 +369,35 @@ const getParamTypeName = (dataType: string) => {
const getParamTypeTag = (dataType: string) => {
const tagMap = {
int: 'primary',
float: 'success',
double: 'success',
text: 'info',
bool: 'warning',
enum: 'danger',
date: 'primary',
struct: 'info',
array: 'warning'
[IoTDataSpecsDataTypeEnum.INT]: 'primary',
[IoTDataSpecsDataTypeEnum.FLOAT]: 'success',
[IoTDataSpecsDataTypeEnum.DOUBLE]: 'success',
[IoTDataSpecsDataTypeEnum.TEXT]: 'info',
[IoTDataSpecsDataTypeEnum.BOOL]: 'warning',
[IoTDataSpecsDataTypeEnum.ENUM]: 'danger',
[IoTDataSpecsDataTypeEnum.DATE]: 'primary',
[IoTDataSpecsDataTypeEnum.STRUCT]: 'info',
[IoTDataSpecsDataTypeEnum.ARRAY]: 'warning'
}
return tagMap[dataType] || 'info'
}
const getExampleValue = (param: any) => {
switch (param.dataType) {
case 'int':
case IoTDataSpecsDataTypeEnum.INT:
return '25'
case 'float':
case 'double':
case IoTDataSpecsDataTypeEnum.FLOAT:
case IoTDataSpecsDataTypeEnum.DOUBLE:
return '25.5'
case 'bool':
case IoTDataSpecsDataTypeEnum.BOOL:
return 'false'
case 'text':
case IoTDataSpecsDataTypeEnum.TEXT:
return '"auto"'
case 'enum':
case IoTDataSpecsDataTypeEnum.ENUM:
return '"option1"'
case 'struct':
case IoTDataSpecsDataTypeEnum.STRUCT:
return '{}'
case 'array':
case IoTDataSpecsDataTypeEnum.ARRAY:
return '[]'
default:
return '""'

View File

@ -132,19 +132,12 @@
</el-tooltip>
</template>
</el-input>
<!-- 验证提示 -->
<div v-if="validationMessage" class="mt-4px">
<el-text :type="isValid ? 'success' : 'danger'" size="small">
<Icon :icon="isValid ? 'ep:check' : 'ep:warning-filled'" />
{{ validationMessage }}
</el-text>
</div>
</div>
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { IoTDataSpecsDataTypeEnum } from '@/views/iot/utils/constants'
/** 值输入组件 */
defineOptions({ name: 'ValueInput' })
@ -158,7 +151,6 @@ interface Props {
interface Emits {
(e: 'update:modelValue', value: string): void
(e: 'validate', result: { valid: boolean; message: string }): void
}
const props = defineProps<Props>()
@ -173,8 +165,6 @@ const rangeStart = ref('')
const rangeEnd = ref('')
const dateValue = ref('')
const numberValue = ref<number>()
const validationMessage = ref('')
const isValid = ref(true)
//
const enumOptions = computed(() => {
@ -199,14 +189,18 @@ const listPreview = computed(() => {
//
const isNumericType = () => {
return ['int', 'float', 'double'].includes(props.propertyType || '')
return [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE
].includes(props.propertyType || '')
}
const getInputType = () => {
switch (props.propertyType) {
case 'int':
case 'float':
case 'double':
case IoTDataSpecsDataTypeEnum.INT:
case IoTDataSpecsDataTypeEnum.FLOAT:
case IoTDataSpecsDataTypeEnum.DOUBLE:
return 'number'
default:
return 'text'
@ -215,22 +209,22 @@ const getInputType = () => {
const getPlaceholder = () => {
const typeMap = {
string: '请输入字符串',
int: '请输入整数',
float: '请输入浮点数',
double: '请输入双精度数',
struct: '请输入JSON格式数据',
array: '请输入数组格式数据'
[IoTDataSpecsDataTypeEnum.TEXT]: '请输入字符串',
[IoTDataSpecsDataTypeEnum.INT]: '请输入整数',
[IoTDataSpecsDataTypeEnum.FLOAT]: '请输入浮点数',
[IoTDataSpecsDataTypeEnum.DOUBLE]: '请输入双精度数',
[IoTDataSpecsDataTypeEnum.STRUCT]: '请输入JSON格式数据',
[IoTDataSpecsDataTypeEnum.ARRAY]: '请输入数组格式数据'
}
return typeMap[props.propertyType || ''] || '请输入值'
}
const getPrecision = () => {
return props.propertyType === 'int' ? 0 : 2
return props.propertyType === IoTDataSpecsDataTypeEnum.INT ? 0 : 2
}
const getStep = () => {
return props.propertyType === 'int' ? 1 : 0.1
return props.propertyType === IoTDataSpecsDataTypeEnum.INT ? 1 : 0.1
}
const getMin = () => {
@ -243,7 +237,7 @@ const getMax = () => {
//
const handleChange = () => {
validateValue()
//
}
const handleRangeChange = () => {
@ -252,106 +246,16 @@ const handleRangeChange = () => {
} else {
localValue.value = ''
}
validateValue()
}
const handleDateChange = (value: string) => {
localValue.value = value || ''
validateValue()
}
const handleNumberChange = (value: number | undefined) => {
localValue.value = value?.toString() || ''
validateValue()
}
//
const validateValue = () => {
if (!localValue.value) {
isValid.value = false
validationMessage.value = '请输入值'
emit('validate', { valid: false, message: validationMessage.value })
return
}
//
if (isNumericType()) {
const num = parseFloat(localValue.value)
if (isNaN(num)) {
isValid.value = false
validationMessage.value = '请输入有效的数字'
emit('validate', { valid: false, message: validationMessage.value })
return
}
//
const min = getMin()
const max = getMax()
if (min !== undefined && num < min) {
isValid.value = false
validationMessage.value = `值不能小于 ${min}`
emit('validate', { valid: false, message: validationMessage.value })
return
}
if (max !== undefined && num > max) {
isValid.value = false
validationMessage.value = `值不能大于 ${max}`
emit('validate', { valid: false, message: validationMessage.value })
return
}
}
//
if (props.operator === 'between') {
const parts = localValue.value.split(',')
if (parts.length !== 2) {
isValid.value = false
validationMessage.value = '范围格式错误'
emit('validate', { valid: false, message: validationMessage.value })
return
}
const start = parseFloat(parts[0])
const end = parseFloat(parts[1])
if (isNaN(start) || isNaN(end)) {
isValid.value = false
validationMessage.value = '范围值必须是数字'
emit('validate', { valid: false, message: validationMessage.value })
return
}
if (start >= end) {
isValid.value = false
validationMessage.value = '起始值必须小于结束值'
emit('validate', { valid: false, message: validationMessage.value })
return
}
}
//
if (props.operator === 'in') {
if (listPreview.value.length === 0) {
isValid.value = false
validationMessage.value = '请输入至少一个值'
emit('validate', { valid: false, message: validationMessage.value })
return
}
}
//
isValid.value = true
validationMessage.value = '输入值验证通过'
emit('validate', { valid: true, message: validationMessage.value })
}
//
watch(
() => localValue.value,
() => {
validateValue()
}
)
//
watch(
() => props.operator,
@ -363,11 +267,4 @@ watch(
numberValue.value = undefined
}
)
//
onMounted(() => {
if (localValue.value) {
validateValue()
}
})
</script>

View File

@ -35,7 +35,10 @@
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { IotRuleSceneTriggerConditionParameterOperatorEnum } from '@/views/iot/utils/constants'
import {
IotRuleSceneTriggerConditionParameterOperatorEnum,
IoTDataSpecsDataTypeEnum
} from '@/views/iot/utils/constants'
/** 操作符选择器组件 */
defineOptions({ name: 'OperatorSelector' })
@ -60,7 +63,14 @@ const allOperators = [
symbol: '=',
description: '值完全相等时触发',
example: 'temperature = 25',
supportedTypes: ['int', 'float', 'double', 'string', 'bool', 'enum']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE,
IoTDataSpecsDataTypeEnum.TEXT,
IoTDataSpecsDataTypeEnum.BOOL,
IoTDataSpecsDataTypeEnum.ENUM
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.value,
@ -68,7 +78,14 @@ const allOperators = [
symbol: '≠',
description: '值不相等时触发',
example: 'power != false',
supportedTypes: ['int', 'float', 'double', 'string', 'bool', 'enum']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE,
IoTDataSpecsDataTypeEnum.TEXT,
IoTDataSpecsDataTypeEnum.BOOL,
IoTDataSpecsDataTypeEnum.ENUM
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN.value,
@ -76,7 +93,12 @@ const allOperators = [
symbol: '>',
description: '值大于指定值时触发',
example: 'temperature > 30',
supportedTypes: ['int', 'float', 'double', 'date']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE,
IoTDataSpecsDataTypeEnum.DATE
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN_OR_EQUALS.value,
@ -84,7 +106,12 @@ const allOperators = [
symbol: '≥',
description: '值大于或等于指定值时触发',
example: 'humidity >= 80',
supportedTypes: ['int', 'float', 'double', 'date']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE,
IoTDataSpecsDataTypeEnum.DATE
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN.value,
@ -92,7 +119,12 @@ const allOperators = [
symbol: '<',
description: '值小于指定值时触发',
example: 'temperature < 10',
supportedTypes: ['int', 'float', 'double', 'date']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE,
IoTDataSpecsDataTypeEnum.DATE
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN_OR_EQUALS.value,
@ -100,7 +132,12 @@ const allOperators = [
symbol: '≤',
description: '值小于或等于指定值时触发',
example: 'battery <= 20',
supportedTypes: ['int', 'float', 'double', 'date']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE,
IoTDataSpecsDataTypeEnum.DATE
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.IN.value,
@ -108,7 +145,12 @@ const allOperators = [
symbol: '∈',
description: '值在指定列表中时触发',
example: 'status in [1,2,3]',
supportedTypes: ['int', 'float', 'string', 'enum']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.TEXT,
IoTDataSpecsDataTypeEnum.ENUM
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_IN.value,
@ -116,7 +158,12 @@ const allOperators = [
symbol: '∉',
description: '值不在指定列表中时触发',
example: 'status not in [1,2,3]',
supportedTypes: ['int', 'float', 'string', 'enum']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.TEXT,
IoTDataSpecsDataTypeEnum.ENUM
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN.value,
@ -124,7 +171,12 @@ const allOperators = [
symbol: '⊆',
description: '值在指定范围内时触发',
example: 'temperature between 20,30',
supportedTypes: ['int', 'float', 'double', 'date']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE,
IoTDataSpecsDataTypeEnum.DATE
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN.value,
@ -132,7 +184,12 @@ const allOperators = [
symbol: '⊄',
description: '值不在指定范围内时触发',
example: 'temperature not between 20,30',
supportedTypes: ['int', 'float', 'double', 'date']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE,
IoTDataSpecsDataTypeEnum.DATE
]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.LIKE.value,
@ -140,7 +197,7 @@ const allOperators = [
symbol: '≈',
description: '字符串匹配指定模式时触发',
example: 'message like "%error%"',
supportedTypes: ['string']
supportedTypes: [IoTDataSpecsDataTypeEnum.TEXT]
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_NULL.value,
@ -148,7 +205,15 @@ const allOperators = [
symbol: '≠∅',
description: '值非空时触发',
example: 'data not null',
supportedTypes: ['int', 'float', 'double', 'string', 'bool', 'enum', 'date']
supportedTypes: [
IoTDataSpecsDataTypeEnum.INT,
IoTDataSpecsDataTypeEnum.FLOAT,
IoTDataSpecsDataTypeEnum.DOUBLE,
IoTDataSpecsDataTypeEnum.TEXT,
IoTDataSpecsDataTypeEnum.BOOL,
IoTDataSpecsDataTypeEnum.ENUM,
IoTDataSpecsDataTypeEnum.DATE
]
}
]

View File

@ -159,7 +159,11 @@
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { InfoFilled } from '@element-plus/icons-vue'
import { IotRuleSceneTriggerTypeEnum, IoTThingModelTypeEnum } from '@/views/iot/utils/constants'
import {
IotRuleSceneTriggerTypeEnum,
IoTThingModelTypeEnum,
IoTDataSpecsDataTypeEnum
} from '@/views/iot/utils/constants'
import type {
IotThingModelTSLResp,
ThingModelEvent,
@ -246,30 +250,30 @@ const selectedProperty = computed(() => {
//
const getPropertyTypeName = (dataType: string) => {
const typeMap = {
int: '整数',
float: '浮点数',
double: '双精度',
text: '字符串',
bool: '布尔值',
enum: '枚举',
date: '日期',
struct: '结构体',
array: '数组'
[IoTDataSpecsDataTypeEnum.INT]: '整数',
[IoTDataSpecsDataTypeEnum.FLOAT]: '浮点数',
[IoTDataSpecsDataTypeEnum.DOUBLE]: '双精度',
[IoTDataSpecsDataTypeEnum.TEXT]: '字符串',
[IoTDataSpecsDataTypeEnum.BOOL]: '布尔值',
[IoTDataSpecsDataTypeEnum.ENUM]: '枚举',
[IoTDataSpecsDataTypeEnum.DATE]: '日期',
[IoTDataSpecsDataTypeEnum.STRUCT]: '结构体',
[IoTDataSpecsDataTypeEnum.ARRAY]: '数组'
}
return typeMap[dataType] || dataType
}
const getPropertyTypeTag = (dataType: string) => {
const tagMap = {
int: 'primary',
float: 'success',
double: 'success',
text: 'info',
bool: 'warning',
enum: 'danger',
date: 'primary',
struct: 'info',
array: 'warning'
[IoTDataSpecsDataTypeEnum.INT]: 'primary',
[IoTDataSpecsDataTypeEnum.FLOAT]: 'success',
[IoTDataSpecsDataTypeEnum.DOUBLE]: 'success',
[IoTDataSpecsDataTypeEnum.TEXT]: 'info',
[IoTDataSpecsDataTypeEnum.BOOL]: 'warning',
[IoTDataSpecsDataTypeEnum.ENUM]: 'danger',
[IoTDataSpecsDataTypeEnum.DATE]: 'primary',
[IoTDataSpecsDataTypeEnum.STRUCT]: 'info',
[IoTDataSpecsDataTypeEnum.ARRAY]: 'warning'
}
return tagMap[dataType] || 'info'
}