perf:【IoT 物联网】场景联动触发器优化

This commit is contained in:
puhui999
2025-07-28 21:38:27 +08:00
parent 929bcb4059
commit d7b4db9b4e
15 changed files with 1815 additions and 453 deletions

View File

@ -0,0 +1,80 @@
<!-- 条件类型选择器组件 -->
<template>
<el-select
:model-value="modelValue"
@update:model-value="handleChange"
placeholder="请选择条件类型"
class="w-full"
>
<el-option
v-for="option in conditionTypeOptions"
:key="option.value"
:label="option.label"
:value="option.value"
>
<div class="flex items-center justify-between w-full">
<div class="flex items-center gap-8px">
<Icon :icon="option.icon" :class="option.iconClass" />
<span>{{ option.label }}</span>
</div>
<el-tag :type="option.tag" size="small">{{ option.category }}</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { IotRuleSceneTriggerConditionTypeEnum } from '@/api/iot/rule/scene/scene.types'
/** 条件类型选择器组件 */
defineOptions({ name: 'ConditionTypeSelector' })
interface Props {
modelValue?: number
}
interface Emits {
(e: 'update:modelValue', value: number): void
(e: 'change', value: number): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
// 条件类型选项
const conditionTypeOptions = [
{
value: IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS,
label: '设备状态',
description: '监控设备的在线/离线状态变化',
icon: 'ep:connection',
iconClass: 'text-blue-500',
tag: 'primary',
category: '设备'
},
{
value: IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY,
label: '设备属性',
description: '监控设备属性值的变化',
icon: 'ep:data-analysis',
iconClass: 'text-green-500',
tag: 'success',
category: '属性'
},
{
value: IotRuleSceneTriggerConditionTypeEnum.CURRENT_TIME,
label: '当前时间',
description: '基于当前时间的条件判断',
icon: 'ep:timer',
iconClass: 'text-orange-500',
tag: 'warning',
category: '时间'
}
]
// 事件处理
const handleChange = (value: number) => {
emit('update:modelValue', value)
emit('change', value)
}
</script>

View File

@ -0,0 +1,127 @@
<!-- 设备选择器组件 -->
<template>
<el-select
:model-value="modelValue"
@update:model-value="handleChange"
placeholder="请选择设备"
filterable
clearable
class="w-full"
:loading="deviceLoading"
:disabled="!productId"
>
<el-option
v-for="device in deviceList"
:key="device.id"
:label="device.deviceName"
:value="device.id"
>
<div class="flex items-center justify-between w-full py-4px">
<div class="flex-1">
<div class="text-14px font-500 text-[var(--el-text-color-primary)] mb-2px">{{
device.deviceName
}}</div>
<div class="text-12px text-[var(--el-text-color-secondary)]">{{ device.deviceKey }}</div>
</div>
<div class="flex items-center gap-4px">
<el-tag size="small" :type="getStatusType(device.status)">
{{ getStatusText(device.status) }}
</el-tag>
<el-tag size="small" :type="device.activeTime ? 'success' : 'info'">
{{ device.activeTime ? '已激活' : '未激活' }}
</el-tag>
</div>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { DeviceApi } from '@/api/iot/device/device'
/** 设备选择器组件 */
defineOptions({ name: 'DeviceSelector' })
interface Props {
modelValue?: number
productId?: number
}
interface Emits {
(e: 'update:modelValue', value?: number): void
(e: 'change', value?: number): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
// 状态
const deviceLoading = ref(false)
const deviceList = ref<any[]>([])
// 事件处理
const handleChange = (value?: number) => {
emit('update:modelValue', value)
emit('change', value)
}
// 获取设备列表
const getDeviceList = async () => {
if (!props.productId) {
deviceList.value = []
return
}
try {
deviceLoading.value = true
const res = await DeviceApi.getDeviceListByProductId(props.productId)
deviceList.value = res || []
} catch (error) {
console.error('获取设备列表失败:', error)
deviceList.value = []
} finally {
deviceLoading.value = false
}
}
// 设备状态映射
const getStatusType = (status: number) => {
switch (status) {
case 0:
return 'success' // 正常
case 1:
return 'danger' // 禁用
default:
return 'info'
}
}
const getStatusText = (status: number) => {
switch (status) {
case 0:
return '正常'
case 1:
return '禁用'
default:
return '未知'
}
}
// 监听产品变化
watch(
() => props.productId,
(newProductId) => {
if (newProductId) {
getDeviceList()
} else {
deviceList.value = []
// 清空当前选择的设备
if (props.modelValue) {
emit('update:modelValue', undefined)
emit('change', undefined)
}
}
},
{ immediate: true }
)
</script>

View File

@ -0,0 +1,81 @@
<!-- 产品选择器组件 -->
<template>
<el-select
:model-value="modelValue"
@update:model-value="handleChange"
placeholder="请选择产品"
filterable
clearable
class="w-full"
:loading="productLoading"
>
<el-option
v-for="product in productList"
:key="product.id"
:label="product.name"
:value="product.id"
>
<div class="flex items-center justify-between w-full py-4px">
<div class="flex-1">
<div class="text-14px font-500 text-[var(--el-text-color-primary)] mb-2px">{{
product.name
}}</div>
<div class="text-12px text-[var(--el-text-color-secondary)]">{{
product.productKey
}}</div>
</div>
<el-tag size="small" :type="product.status === 0 ? 'success' : 'danger'">
{{ product.status === 0 ? '正常' : '禁用' }}
</el-tag>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { ProductApi } from '@/api/iot/product/product'
/** 产品选择器组件 */
defineOptions({ name: 'ProductSelector' })
interface Props {
modelValue?: number
}
interface Emits {
(e: 'update:modelValue', value?: number): void
(e: 'change', value?: number): void
}
defineProps<Props>()
const emit = defineEmits<Emits>()
// 状态
const productLoading = ref(false)
const productList = ref<any[]>([])
// 事件处理
const handleChange = (value?: number) => {
emit('update:modelValue', value)
emit('change', value)
}
// 获取产品列表
const getProductList = async () => {
try {
productLoading.value = true
const res = await ProductApi.getSimpleProductList()
productList.value = res || []
} catch (error) {
console.error('获取产品列表失败:', error)
productList.value = []
} finally {
productLoading.value = false
}
}
// 组件挂载时获取产品列表
onMounted(() => {
getProductList()
})
</script>

View File

@ -130,41 +130,3 @@ export interface PropertySelectorItem {
event?: ThingModelEvent
service?: ThingModelService
}
/** 数据类型枚举 */
export enum DataTypeEnum {
INT = 'int',
FLOAT = 'float',
DOUBLE = 'double',
ENUM = 'enum',
BOOL = 'bool',
TEXT = 'text',
DATE = 'date',
STRUCT = 'struct',
ARRAY = 'array'
}
/** 访问模式枚举 */
export enum AccessModeEnum {
READ = 'r',
READ_write = 'rw'
}
/** 事件类型枚举 */
export enum EventTypeEnum {
INFO = 'info',
ALERT = 'alert',
ERROR = 'error'
}
/** 调用类型枚举 */
export enum CallTypeEnum {
ASYNC = 'async',
SYNC = 'sync'
}
/** 参数方向枚举 */
export enum ParamDirectionEnum {
INPUT = 'input',
OUTPUT = 'output'
}