perf:【IoT 物联网】场景联动触发器优化
This commit is contained in:
@ -89,24 +89,6 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- 条件预览 -->
|
|
||||||
<!-- TODO puhui999:可以去掉。。。因为表单选择了,可以看懂的呀。 -->
|
|
||||||
<div
|
|
||||||
v-if="conditionPreview"
|
|
||||||
class="p-12px bg-[var(--el-fill-color-light)] rounded-6px border border-[var(--el-border-color-lighter)]"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-8px mb-8px">
|
|
||||||
<Icon icon="ep:view" class="text-[var(--el-color-info)] text-16px" />
|
|
||||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">条件预览</span>
|
|
||||||
</div>
|
|
||||||
<div class="pl-24px">
|
|
||||||
<code
|
|
||||||
class="text-12px text-[var(--el-color-primary)] bg-[var(--el-fill-color-blank)] p-8px rounded-4px font-mono"
|
|
||||||
>{{ conditionPreview }}</code
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 当前时间条件配置 -->
|
<!-- 当前时间条件配置 -->
|
||||||
@ -147,18 +129,15 @@ import {
|
|||||||
/** 单个条件配置组件 */
|
/** 单个条件配置组件 */
|
||||||
defineOptions({ name: 'ConditionConfig' })
|
defineOptions({ name: 'ConditionConfig' })
|
||||||
|
|
||||||
interface Props {
|
const props = defineProps<{
|
||||||
modelValue: ConditionFormData
|
modelValue: ConditionFormData
|
||||||
triggerType: number
|
triggerType: number
|
||||||
}
|
}>()
|
||||||
|
|
||||||
interface Emits {
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: ConditionFormData): void
|
(e: 'update:modelValue', value: ConditionFormData): void
|
||||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||||
}
|
}>()
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
|
||||||
const emit = defineEmits<Emits>()
|
|
||||||
|
|
||||||
const condition = useVModel(props, 'modelValue', emit)
|
const condition = useVModel(props, 'modelValue', emit)
|
||||||
|
|
||||||
@ -172,34 +151,6 @@ const validationMessage = ref('')
|
|||||||
const isValid = ref(true)
|
const isValid = ref(true)
|
||||||
const valueValidation = ref({ valid: true, message: '' })
|
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 ConditionFormData, value: any) => {
|
||||||
;(condition.value as any)[field] = value
|
;(condition.value as any)[field] = value
|
||||||
@ -241,18 +192,20 @@ const handleValidate = (result: { valid: boolean; message: string }) => {
|
|||||||
|
|
||||||
const handleProductChange = (productId: number) => {
|
const handleProductChange = (productId: number) => {
|
||||||
// 产品变化时清空设备和属性
|
// 产品变化时清空设备和属性
|
||||||
condition.value.deviceId = undefined
|
condition.value.productId = productId
|
||||||
condition.value.identifier = ''
|
condition.value.identifier = ''
|
||||||
updateValidationResult()
|
updateValidationResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDeviceChange = (deviceId: number) => {
|
const handleDeviceChange = (deviceId: number) => {
|
||||||
// 设备变化时清空属性
|
// 设备变化时清空属性
|
||||||
condition.value.identifier = ''
|
condition.value.deviceId = deviceId
|
||||||
updateValidationResult()
|
updateValidationResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePropertyChange = (propertyInfo: { type: string; config: any }) => {
|
const handlePropertyChange = (propertyInfo: { type: string; config: any }) => {
|
||||||
|
debugger
|
||||||
|
console.log(propertyInfo)
|
||||||
propertyType.value = propertyInfo.type
|
propertyType.value = propertyInfo.type
|
||||||
propertyConfig.value = propertyInfo.config
|
propertyConfig.value = propertyInfo.config
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-16px">
|
<div class="flex flex-col gap-16px">
|
||||||
<!-- 条件组容器头部 -->
|
<!-- 条件组容器头部 -->
|
||||||
<!-- TODO @puhui999:这个是不是删除,不然有两个“附件条件组”的 header -->
|
|
||||||
<div
|
<div
|
||||||
class="flex items-center justify-between p-16px bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200 rounded-8px"
|
class="flex items-center justify-between p-16px bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200 rounded-8px"
|
||||||
>
|
>
|
||||||
@ -39,16 +38,6 @@
|
|||||||
<!-- 子条件组列表 -->
|
<!-- 子条件组列表 -->
|
||||||
<div v-if="modelValue.subGroups && modelValue.subGroups.length > 0" class="space-y-16px">
|
<div v-if="modelValue.subGroups && modelValue.subGroups.length > 0" class="space-y-16px">
|
||||||
<!-- 逻辑关系说明 -->
|
<!-- 逻辑关系说明 -->
|
||||||
<!-- TODO @puhui999:这个可以去掉。。。提示有点太多了。 -->
|
|
||||||
<div v-if="modelValue.subGroups.length > 1" class="flex items-center justify-center">
|
|
||||||
<div
|
|
||||||
class="flex items-center gap-8px px-12px py-6px bg-orange-50 border border-orange-200 rounded-full text-12px text-orange-600"
|
|
||||||
>
|
|
||||||
<Icon icon="ep:info-filled" />
|
|
||||||
<span>子条件组之间为"或"关系,满足任意一组即可触发</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div
|
<div
|
||||||
v-for="(subGroup, subGroupIndex) in modelValue.subGroups"
|
v-for="(subGroup, subGroupIndex) in modelValue.subGroups"
|
||||||
@ -144,19 +133,15 @@ import {
|
|||||||
/** 条件组容器配置组件 */
|
/** 条件组容器配置组件 */
|
||||||
defineOptions({ name: 'ConditionGroupContainerConfig' })
|
defineOptions({ name: 'ConditionGroupContainerConfig' })
|
||||||
|
|
||||||
interface Props {
|
const props = defineProps<{
|
||||||
modelValue: ConditionGroupContainerFormData
|
modelValue: ConditionGroupContainerFormData
|
||||||
triggerType: number
|
triggerType: number
|
||||||
}
|
}>()
|
||||||
|
const emit = defineEmits<{
|
||||||
interface Emits {
|
|
||||||
(e: 'update:modelValue', value: ConditionGroupContainerFormData): void
|
(e: 'update:modelValue', value: ConditionGroupContainerFormData): void
|
||||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||||
(e: 'remove'): void
|
(e: 'remove'): void
|
||||||
}
|
}>()
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
|
||||||
const emit = defineEmits<Emits>()
|
|
||||||
|
|
||||||
const container = useVModel(props, 'modelValue', emit)
|
const container = useVModel(props, 'modelValue', emit)
|
||||||
|
|
||||||
|
|||||||
@ -89,34 +89,6 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- 条件预览 -->
|
|
||||||
<!-- puhui999:可以去掉。。。因为表单选择了,可以看懂的呀。 -->
|
|
||||||
<div
|
|
||||||
v-if="conditionPreview"
|
|
||||||
class="p-12px bg-[var(--el-fill-color-light)] rounded-6px border border-[var(--el-border-color-lighter)]"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-8px mb-8px">
|
|
||||||
<Icon icon="ep:view" class="text-[var(--el-color-info)] text-16px" />
|
|
||||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">条件预览</span>
|
|
||||||
</div>
|
|
||||||
<div class="pl-24px">
|
|
||||||
<code
|
|
||||||
class="text-12px text-[var(--el-color-primary)] bg-[var(--el-fill-color-blank)] p-8px rounded-4px font-mono"
|
|
||||||
>{{ conditionPreview }}</code
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 验证结果 -->
|
|
||||||
<div v-if="validationMessage" class="mt-8px">
|
|
||||||
<el-alert
|
|
||||||
:title="validationMessage"
|
|
||||||
:type="isValid ? 'success' : 'error'"
|
|
||||||
:closable="false"
|
|
||||||
show-icon
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -136,6 +108,7 @@ interface Props {
|
|||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'update:modelValue', value: ConditionFormData): void
|
(e: 'update:modelValue', value: ConditionFormData): void
|
||||||
|
|
||||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,29 +184,6 @@ const needsSecondTimeInput = computed(() => {
|
|||||||
return condition.value.operator === IotRuleSceneTriggerTimeOperatorEnum.BETWEEN_TIME.value
|
return condition.value.operator === IotRuleSceneTriggerTimeOperatorEnum.BETWEEN_TIME.value
|
||||||
})
|
})
|
||||||
|
|
||||||
const conditionPreview = computed(() => {
|
|
||||||
if (!condition.value.operator) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
const operatorOption = timeOperatorOptions.find((opt) => opt.value === condition.value.operator)
|
|
||||||
const operatorLabel = operatorOption?.label || condition.value.operator
|
|
||||||
|
|
||||||
if (condition.value.operator === IotRuleSceneTriggerTimeOperatorEnum.TODAY.value) {
|
|
||||||
return `当前时间 ${operatorLabel}`
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!condition.value.timeValue) {
|
|
||||||
return `当前时间 ${operatorLabel} [未设置时间]`
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsSecondTimeInput.value && condition.value.timeValue2) {
|
|
||||||
return `当前时间 ${operatorLabel} ${condition.value.timeValue} 和 ${condition.value.timeValue2}`
|
|
||||||
}
|
|
||||||
|
|
||||||
return `当前时间 ${operatorLabel} ${condition.value.timeValue}`
|
|
||||||
})
|
|
||||||
|
|
||||||
// 事件处理
|
// 事件处理
|
||||||
const updateConditionField = (field: keyof ConditionFormData, value: any) => {
|
const updateConditionField = (field: keyof ConditionFormData, value: any) => {
|
||||||
condition.value[field] = value
|
condition.value[field] = value
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<!-- 条件组配置 -->
|
<!-- 条件组配置 -->
|
||||||
<div v-if="trigger.mainCondition" class="space-y-16px">
|
<div v-if="trigger.mainCondition" class="space-y-16px">
|
||||||
<div class="flex items-center justify-between">
|
<div v-if="!trigger.conditionGroup" class="flex items-center justify-between">
|
||||||
<div class="flex items-center gap-8px">
|
<div class="flex items-center gap-8px">
|
||||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">附加条件组</span>
|
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">附加条件组</span>
|
||||||
<el-tag size="small" type="success">与主条件为且关系</el-tag>
|
<el-tag size="small" type="success">与主条件为且关系</el-tag>
|
||||||
|
|||||||
@ -67,14 +67,6 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- 条件预览 -->
|
|
||||||
<!-- TODO puhui999:可以去掉。。。因为表单选择了,可以看懂的呀。 -->
|
|
||||||
<div v-if="conditionPreview" class="mt-12px">
|
|
||||||
<div class="text-12px text-[var(--el-text-color-secondary)]">
|
|
||||||
预览:{{ conditionPreview }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 设备状态条件配置 -->
|
<!-- 设备状态条件配置 -->
|
||||||
@ -147,13 +139,6 @@ const isDeviceStatusTrigger = computed(() => {
|
|||||||
return props.triggerType === IotRuleSceneTriggerTypeEnum.DEVICE_STATE_UPDATE
|
return props.triggerType === IotRuleSceneTriggerTypeEnum.DEVICE_STATE_UPDATE
|
||||||
})
|
})
|
||||||
|
|
||||||
const conditionPreview = computed(() => {
|
|
||||||
if (!condition.value.productId || !condition.value.deviceId || !condition.value.identifier) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
return `设备[${condition.value.deviceId}]的${condition.value.identifier} ${condition.value.operator} ${condition.value.param}`
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取触发类型文本
|
// 获取触发类型文本
|
||||||
// TODO @puhui999:是不是有枚举可以服用哈;
|
// TODO @puhui999:是不是有枚举可以服用哈;
|
||||||
const getTriggerTypeText = (type: number) => {
|
const getTriggerTypeText = (type: number) => {
|
||||||
|
|||||||
@ -63,24 +63,6 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 条件间的"且"连接符 -->
|
|
||||||
<!-- TODO @puhu999:建议去掉,有点元素太丰富了。 -->
|
|
||||||
<div
|
|
||||||
v-if="conditionIndex < subGroup.conditions!.length - 1"
|
|
||||||
class="flex items-center justify-center py-8px"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-8px">
|
|
||||||
<!-- 连接线 -->
|
|
||||||
<div class="w-24px h-1px bg-green-300"></div>
|
|
||||||
<!-- 且标签 -->
|
|
||||||
<div class="px-12px py-4px bg-green-100 border border-green-300 rounded-full">
|
|
||||||
<span class="text-12px font-600 text-green-600">且</span>
|
|
||||||
</div>
|
|
||||||
<!-- 连接线 -->
|
|
||||||
<div class="w-24px h-1px bg-green-300"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 添加条件按钮 -->
|
<!-- 添加条件按钮 -->
|
||||||
@ -108,9 +90,9 @@
|
|||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
import ConditionConfig from './ConditionConfig.vue'
|
import ConditionConfig from './ConditionConfig.vue'
|
||||||
import {
|
import {
|
||||||
SubConditionGroupFormData,
|
|
||||||
ConditionFormData,
|
ConditionFormData,
|
||||||
IotRuleSceneTriggerConditionTypeEnum
|
IotRuleSceneTriggerConditionTypeEnum,
|
||||||
|
SubConditionGroupFormData
|
||||||
} from '@/api/iot/rule/scene/scene.types'
|
} from '@/api/iot/rule/scene/scene.types'
|
||||||
|
|
||||||
/** 子条件组配置组件 */
|
/** 子条件组配置组件 */
|
||||||
@ -124,6 +106,7 @@ interface Props {
|
|||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'update:modelValue', value: SubConditionGroupFormData): void
|
(e: 'update:modelValue', value: SubConditionGroupFormData): void
|
||||||
|
|
||||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -134,21 +134,17 @@ import type { IotThingModelTSLRespVO, PropertySelectorItem } from './types'
|
|||||||
/** 属性选择器组件 */
|
/** 属性选择器组件 */
|
||||||
defineOptions({ name: 'PropertySelector' })
|
defineOptions({ name: 'PropertySelector' })
|
||||||
|
|
||||||
interface Props {
|
const props = defineProps<{
|
||||||
modelValue?: string
|
modelValue?: string
|
||||||
triggerType: number
|
triggerType: number
|
||||||
productId?: number
|
productId?: number
|
||||||
deviceId?: number
|
deviceId?: number
|
||||||
}
|
}>()
|
||||||
|
|
||||||
interface Emits {
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: string): void
|
(e: 'update:modelValue', value: string): void
|
||||||
|
|
||||||
(e: 'change', value: { type: string; config: any }): void
|
(e: 'change', value: { type: string; config: any }): void
|
||||||
}
|
}>()
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
|
||||||
const emit = defineEmits<Emits>()
|
|
||||||
|
|
||||||
const localValue = useVModel(props, 'modelValue', emit)
|
const localValue = useVModel(props, 'modelValue', emit)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user