perf:【IoT 物联网】场景联动触发器样式优化
parent
fc09addd7d
commit
26a4f0fee1
|
@ -7,6 +7,7 @@
|
|||
v-model="trigger"
|
||||
:trigger-type="trigger.type"
|
||||
@validate="handleMainConditionValidate"
|
||||
@trigger-type-change="handleTriggerTypeChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -42,6 +43,7 @@ const props = defineProps<{
|
|||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: TriggerFormData): void
|
||||
(e: 'validate', value: { valid: boolean; message: string }): void
|
||||
(e: 'trigger-type-change', type: number): void
|
||||
}>()
|
||||
|
||||
const trigger = useVModel(props, 'modelValue', emit)
|
||||
|
@ -83,6 +85,11 @@ const handleMainConditionValidate = (result: { valid: boolean; message: string }
|
|||
updateValidationResult()
|
||||
}
|
||||
|
||||
const handleTriggerTypeChange = (type: number) => {
|
||||
trigger.value.type = type
|
||||
emit('trigger-type-change', type)
|
||||
}
|
||||
|
||||
// 事件处理
|
||||
const handleConditionGroupValidate = () => {
|
||||
updateValidationResult()
|
||||
|
|
|
@ -1,38 +1,33 @@
|
|||
<!-- 主条件配置组件 -->
|
||||
<template>
|
||||
<div class="flex flex-col gap-16px">
|
||||
<!-- 条件配置提示 -->
|
||||
<div
|
||||
v-if="!modelValue"
|
||||
class="p-16px border-2 border-dashed border-[var(--el-border-color)] rounded-8px text-center"
|
||||
>
|
||||
<div class="flex flex-col items-center gap-12px">
|
||||
<Icon icon="ep:plus" class="text-32px text-[var(--el-text-color-placeholder)]" />
|
||||
<div class="text-[var(--el-text-color-secondary)]">
|
||||
<p class="text-14px font-500 mb-4px">请配置主条件</p>
|
||||
<p class="text-12px">主条件是触发器的核心条件,必须满足才能触发场景</p>
|
||||
</div>
|
||||
<el-button type="primary" @click="addMainCondition">
|
||||
<Icon icon="ep:plus" />
|
||||
添加主条件
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主条件配置 -->
|
||||
<!-- TODO @puhui999:和“主条件”,是不是和“附加条件组”弄成一个风格,都是占一行;有个绿条; -->
|
||||
<div v-else class="space-y-16px">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-8px">
|
||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">主条件</span>
|
||||
<el-tag size="small" type="primary">必须满足</el-tag>
|
||||
<div class="space-y-16px">
|
||||
<!-- 主条件头部 - 与附加条件组保持一致的绿色风格 -->
|
||||
<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"
|
||||
>
|
||||
<div class="flex items-center gap-12px">
|
||||
<div class="flex items-center gap-8px text-16px font-600 text-green-700">
|
||||
<div
|
||||
class="w-24px h-24px bg-green-500 text-white rounded-full flex items-center justify-center text-12px font-bold"
|
||||
>
|
||||
主
|
||||
</div>
|
||||
<span>主条件</span>
|
||||
</div>
|
||||
<el-tag size="small" type="success">必须满足</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主条件内容配置 -->
|
||||
<MainConditionInnerConfig
|
||||
:model-value="modelValue"
|
||||
@update:model-value="updateCondition"
|
||||
:trigger-type="triggerType"
|
||||
@validate="handleValidate"
|
||||
@trigger-type-change="handleTriggerTypeChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -45,29 +40,18 @@ import { IotRuleSceneTriggerConditionTypeEnum } from '@/views/iot/utils/constant
|
|||
/** 主条件配置组件 */
|
||||
defineOptions({ name: 'MainConditionConfig' })
|
||||
|
||||
defineProps<{
|
||||
modelValue?: TriggerFormData
|
||||
const props = defineProps<{
|
||||
modelValue: TriggerFormData
|
||||
triggerType: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value?: TriggerFormData): void
|
||||
(e: 'update:modelValue', value: TriggerFormData): void
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
(e: 'trigger-type-change', type: number): void
|
||||
}>()
|
||||
|
||||
// 事件处理
|
||||
const addMainCondition = () => {
|
||||
const newCondition: TriggerFormData = {
|
||||
type: IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY, // 默认为设备属性
|
||||
productId: undefined,
|
||||
deviceId: undefined,
|
||||
identifier: '',
|
||||
operator: '=',
|
||||
value: ''
|
||||
}
|
||||
emit('update:modelValue', newCondition)
|
||||
}
|
||||
|
||||
const updateCondition = (condition: TriggerFormData) => {
|
||||
emit('update:modelValue', condition)
|
||||
}
|
||||
|
@ -76,7 +60,7 @@ const handleValidate = (result: { valid: boolean; message: string }) => {
|
|||
emit('validate', result)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
addMainCondition()
|
||||
})
|
||||
const handleTriggerTypeChange = (type: number) => {
|
||||
emit('trigger-type-change', type)
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,23 @@
|
|||
<template>
|
||||
<div class="space-y-16px">
|
||||
<!-- 触发事件类型选择 -->
|
||||
<el-form-item label="触发事件类型" required>
|
||||
<el-select
|
||||
:model-value="triggerType"
|
||||
@update:model-value="handleTriggerTypeChange"
|
||||
placeholder="请选择触发事件类型"
|
||||
class="w-full"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in triggerTypeOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 设备属性条件配置 -->
|
||||
<div v-if="isDevicePropertyTrigger" class="space-y-16px">
|
||||
<!-- 产品设备选择 -->
|
||||
|
@ -57,8 +75,8 @@
|
|||
<el-col :span="12">
|
||||
<el-form-item label="比较值" required>
|
||||
<ValueInput
|
||||
:model-value="condition.param"
|
||||
@update:model-value="(value) => updateConditionField('param', value)"
|
||||
:model-value="condition.value"
|
||||
@update:model-value="(value) => updateConditionField('value', value)"
|
||||
:property-type="propertyType"
|
||||
:operator="condition.operator"
|
||||
:property-config="propertyConfig"
|
||||
|
@ -97,21 +115,22 @@ import PropertySelector from '../selectors/PropertySelector.vue'
|
|||
import OperatorSelector from '../selectors/OperatorSelector.vue'
|
||||
import ValueInput from '../inputs/ValueInput.vue'
|
||||
import DeviceStatusConditionConfig from './DeviceStatusConditionConfig.vue'
|
||||
import { ConditionFormData } from '@/api/iot/rule/scene/scene.types'
|
||||
import { IotRuleSceneTriggerTypeEnum } from '@/views/iot/utils/constants'
|
||||
import { TriggerFormData } from '@/api/iot/rule/scene/scene.types'
|
||||
import { IotRuleSceneTriggerTypeEnum, getTriggerTypeOptions } from '@/views/iot/utils/constants'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
/** 主条件内部配置组件 */
|
||||
defineOptions({ name: 'MainConditionInnerConfig' })
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: ConditionFormData
|
||||
modelValue: TriggerFormData
|
||||
triggerType: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: ConditionFormData): void
|
||||
(e: 'update:modelValue', value: TriggerFormData): void
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
(e: 'trigger-type-change', value: number): void
|
||||
}>()
|
||||
|
||||
// 响应式数据
|
||||
|
@ -152,17 +171,24 @@ const getTriggerTypeText = (type: number) => {
|
|||
}
|
||||
}
|
||||
|
||||
// 触发器类型选项
|
||||
const triggerTypeOptions = getTriggerTypeOptions()
|
||||
|
||||
// 事件处理
|
||||
const updateConditionField = (field: keyof ConditionFormData, value: any) => {
|
||||
const updateConditionField = (field: keyof TriggerFormData, value: any) => {
|
||||
condition.value[field] = value
|
||||
updateValidationResult()
|
||||
}
|
||||
|
||||
const updateCondition = (value: ConditionFormData) => {
|
||||
const updateCondition = (value: TriggerFormData) => {
|
||||
emit('update:modelValue', value)
|
||||
updateValidationResult()
|
||||
}
|
||||
|
||||
const handleTriggerTypeChange = (type: number) => {
|
||||
emit('trigger-type-change', type)
|
||||
}
|
||||
|
||||
const handleProductChange = () => {
|
||||
// 产品变化时清空设备和属性
|
||||
condition.value.deviceId = undefined
|
||||
|
@ -231,7 +257,7 @@ const updateValidationResult = () => {
|
|||
return
|
||||
}
|
||||
|
||||
if (!condition.value.param) {
|
||||
if (!condition.value.value) {
|
||||
isValid.value = false
|
||||
validationMessage.value = '请输入比较值'
|
||||
emit('validate', { valid: false, message: validationMessage.value })
|
||||
|
@ -251,7 +277,7 @@ watch(
|
|||
condition.value.deviceId,
|
||||
condition.value.identifier,
|
||||
condition.value.operator,
|
||||
condition.value.param
|
||||
condition.value.value
|
||||
],
|
||||
() => {
|
||||
updateValidationResult()
|
||||
|
|
|
@ -16,20 +16,26 @@
|
|||
|
||||
<div class="p-16px space-y-24px">
|
||||
<!-- 触发器列表 -->
|
||||
<!-- TODO 每个触发器,有个外框,会不会好点? -->
|
||||
<div v-if="triggers.length > 0" class="space-y-24px">
|
||||
<div
|
||||
v-for="(triggerItem, index) in triggers"
|
||||
:key="`trigger-${index}`"
|
||||
class="border border-[var(--el-border-color-light)] rounded-8px p-16px relative"
|
||||
class="border-2 border-green-200 rounded-8px bg-green-50 shadow-sm hover:shadow-md transition-shadow"
|
||||
>
|
||||
<!-- 触发器头部 -->
|
||||
<div class="flex items-center justify-between mb-16px">
|
||||
<div class="flex items-center gap-8px">
|
||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">
|
||||
触发器 {{ index + 1 }}
|
||||
</span>
|
||||
<el-tag size="small" :type="getTriggerTagType(triggerItem.type)">
|
||||
<!-- 触发器头部 - 绿色主题 -->
|
||||
<div
|
||||
class="flex items-center justify-between p-16px bg-gradient-to-r from-green-50 to-emerald-50 border-b border-green-200 rounded-t-6px"
|
||||
>
|
||||
<div class="flex items-center gap-12px">
|
||||
<div class="flex items-center gap-8px text-16px font-600 text-green-700">
|
||||
<div
|
||||
class="w-24px h-24px bg-green-500 text-white rounded-full flex items-center justify-center text-12px font-bold"
|
||||
>
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
<span>触发器 {{ index + 1 }}</span>
|
||||
</div>
|
||||
<el-tag size="small" :type="getTriggerTagType(triggerItem.type)" class="font-500">
|
||||
{{ getTriggerTypeLabel(triggerItem.type) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
|
@ -40,6 +46,7 @@
|
|||
size="small"
|
||||
text
|
||||
@click="removeTrigger(index)"
|
||||
class="hover:bg-red-50"
|
||||
>
|
||||
<Icon icon="ep:delete" />
|
||||
删除
|
||||
|
@ -47,37 +54,24 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 触发事件类型选择 -->
|
||||
<el-form-item label="触发事件类型" required>
|
||||
<el-select
|
||||
:model-value="triggerItem.type"
|
||||
@update:model-value="(value) => updateTriggerType(index, value)"
|
||||
placeholder="请选择触发事件类型"
|
||||
class="w-full"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in triggerTypeOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 触发器内容区域 -->
|
||||
<div class="p-16px space-y-16px">
|
||||
<!-- 设备触发配置 -->
|
||||
<DeviceTriggerConfig
|
||||
v-if="isDeviceTrigger(triggerItem.type)"
|
||||
:model-value="triggerItem"
|
||||
:index="index"
|
||||
@update:model-value="(value) => updateTriggerDeviceConfig(index, value)"
|
||||
@trigger-type-change="(type) => updateTriggerType(index, type)"
|
||||
/>
|
||||
|
||||
<!-- 设备触发配置 -->
|
||||
<DeviceTriggerConfig
|
||||
v-if="isDeviceTrigger(triggerItem.type)"
|
||||
:model-value="triggerItem"
|
||||
:index="index"
|
||||
@update:model-value="(value) => updateTriggerDeviceConfig(index, value)"
|
||||
/>
|
||||
|
||||
<!-- 定时触发配置 -->
|
||||
<TimerTriggerConfig
|
||||
v-else-if="triggerItem.type === TriggerTypeEnum.TIMER"
|
||||
:model-value="triggerItem.cronExpression"
|
||||
@update:model-value="(value) => updateTriggerCronConfig(index, value)"
|
||||
/>
|
||||
<!-- 定时触发配置 -->
|
||||
<TimerTriggerConfig
|
||||
v-else-if="triggerItem.type === TriggerTypeEnum.TIMER"
|
||||
:model-value="triggerItem.cronExpression"
|
||||
@update:model-value="(value) => updateTriggerCronConfig(index, value)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue