【功能完善】IoT: 规则场景触发器相关组件

This commit is contained in:
puhui999 2025-03-21 14:46:19 +08:00
parent 6745594e3a
commit bb2b32b051
2 changed files with 30 additions and 231 deletions

View File

@ -1,241 +1,51 @@
<template>
<div class="condition-selector">
<el-select
v-model="selectedOperator"
:placeholder="placeholder || '请选择操作符'"
class="condition-select"
@change="handleOperatorChange"
>
<el-option
v-for="item in operatorOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
<div class="operator-option">
<span>{{ item.label }}</span>
<span class="operator-symbol">{{ item.symbol }}</span>
</div>
</el-option>
</el-select>
<!-- 普通输入值 -->
<template v-if="!isRangeOperator && !isListOperator">
<el-input
v-model="inputValue"
:placeholder="valuePlaceholder || '请输入值'"
class="value-input"
@change="handleValueChange"
/>
</template>
<!-- 范围值输入 -->
<template v-if="isRangeOperator">
<div class="range-input">
<el-input
v-model="rangeValue.min"
placeholder="最小值"
class="range-input-item"
@change="handleRangeValueChange"
/>
<span class="range-separator"></span>
<el-input
v-model="rangeValue.max"
placeholder="最大值"
class="range-input-item"
@change="handleRangeValueChange"
/>
</div>
</template>
<!-- 列表值输入 -->
<template v-if="isListOperator">
<el-select
v-model="listValue"
:placeholder="valuePlaceholder || '请选择值'"
multiple
filterable
allow-create
class="list-select"
@change="handleListValueChange"
>
<el-option
v-for="item in listOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</div>
<el-select
v-model="selectedOperator"
class="condition-selector"
clearable
:placeholder="placeholder"
>
<el-option label="等于" value="=" />
<el-option label="不等于" value="!=" />
<el-option label="大于" value=">" />
<el-option label="大于等于" value=">=" />
<el-option label="小于" value="<" />
<el-option label="小于等于" value="<=" />
<el-option label="在列表中" value="in" />
<el-option label="不在列表中" value="not in" />
<el-option label="在范围内" value="between" />
<el-option label="不在范围内" value="not between" />
<el-option label="包含" value="like" />
<el-option label="非空" value="not null" />
</el-select>
</template>
<script setup lang="ts">
import { ref, computed, watch, defineEmits, defineProps } from 'vue'
import { IotRuleSceneTriggerConditionParameterOperatorEnum } from '@/api/iot/rule/scene/scene.types'
import { computed } from 'vue'
interface ConditionValue {
operator: IotRuleSceneTriggerConditionParameterOperatorEnum
value: string
}
//
/** 条件选择器 */
defineOptions({ name: 'ConditionSelector' })
const props = defineProps({
modelValue: {
type: Object as () => ConditionValue,
required: true
},
placeholder: {
type: String,
default: ''
default: '请选择条件'
},
valuePlaceholder: {
modelValue: {
type: String,
default: ''
},
listOptions: {
type: Array as () => { label: string, value: string | number }[],
default: () => []
}
})
//
const emit = defineEmits(['update:modelValue'])
//
const operatorOptions = [
{ label: '等于', value: IotRuleSceneTriggerConditionParameterOperatorEnum.EQ, symbol: '=' },
{ label: '不等于', value: IotRuleSceneTriggerConditionParameterOperatorEnum.NE, symbol: '≠' },
{ label: '大于', value: IotRuleSceneTriggerConditionParameterOperatorEnum.GT, symbol: '>' },
{ label: '小于', value: IotRuleSceneTriggerConditionParameterOperatorEnum.LT, symbol: '<' },
{ label: '大于等于', value: IotRuleSceneTriggerConditionParameterOperatorEnum.GTE, symbol: '≥' },
{ label: '小于等于', value: IotRuleSceneTriggerConditionParameterOperatorEnum.LTE, symbol: '≤' },
{ label: '在...之间', value: IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN, symbol: '↔' },
{ label: '不在...之间', value: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN, symbol: '⟷' },
{ label: '在列表中', value: IotRuleSceneTriggerConditionParameterOperatorEnum.IN, symbol: '∈' },
{ label: '不在列表中', value: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_IN, symbol: '∉' }
]
//
const selectedOperator = ref(props.modelValue.operator || '')
//
const inputValue = ref(props.modelValue.value || '')
//
const rangeValue = ref({
min: '',
max: ''
const selectedOperator = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
})
//
const listValue = ref([])
//
const isRangeOperator = computed(() => {
return ['between', 'notBetween'].includes(selectedOperator.value)
})
//
const isListOperator = computed(() => {
return ['in', 'notIn'].includes(selectedOperator.value)
})
//
const handleOperatorChange = () => {
updateModelValue()
}
//
const handleValueChange = () => {
updateModelValue()
}
//
const handleRangeValueChange = () => {
updateModelValue()
}
//
const handleListValueChange = () => {
updateModelValue()
}
//
const updateModelValue = () => {
const value = isRangeOperator.value
? `${rangeValue.value.min},${rangeValue.value.max}`
: isListOperator.value
? listValue.value.join(',')
: inputValue.value
emit('update:modelValue', {
operator: selectedOperator.value,
value
})
}
// modelValue
watch(() => props.modelValue, (newVal) => {
if (newVal) {
selectedOperator.value = newVal.operator || ''
if (isRangeOperator.value && newVal.value) {
const [min, max] = newVal.value.split(',')
rangeValue.value = { min, max }
} else if (isListOperator.value && newVal.value) {
listValue.value = newVal.value.split(',')
} else {
inputValue.value = newVal.value || ''
}
}
}, { deep: true })
</script>
<style scoped>
.condition-selector {
display: flex;
gap: 8px;
align-items: flex-start;
width: 100%;
}
.condition-select {
width: 120px;
}
.value-input {
flex: 1;
}
.operator-option {
display: flex;
justify-content: space-between;
align-items: center;
}
.operator-symbol {
font-size: 14px;
color: var(--el-text-color-secondary);
}
.range-input {
display: flex;
gap: 8px;
align-items: center;
flex: 1;
}
.range-input-item {
flex: 1;
}
.range-separator {
padding: 0 4px;
color: var(--el-text-color-regular);
}
.list-select {
flex: 1;
}
</style>
</style>

View File

@ -13,19 +13,7 @@
:value="dict.value"
/>
</el-select>
<el-select
v-model="conditionParameter.operator"
class="!w-180px mr-10px"
clearable
placeholder="请选择条件"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_MESSAGE_TYPE_ENUM)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
<ConditionSelector v-model="conditionParameter.operator" class="!w-180px mr-10px" />
<el-input v-model="conditionParameter.value" class="!w-240px mr-10px" placeholder="请输入值">
<template #append> 单位 </template>
</el-input>
@ -35,6 +23,7 @@
</template>
<script setup lang="ts">
import ConditionSelector from './ConditionSelector.vue'
import { IotRuleSceneTriggerConditionParameter } from '@/api/iot/rule/scene/scene.types'
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import { useVModel } from '@vueuse/core'