perf: 【IoT 物联网】场景联动收拢常量定义

pull/808/head
puhui999 2025-08-07 17:09:17 +08:00
parent 9684857174
commit 93311f8bd7
9 changed files with 282 additions and 261 deletions

View File

@ -148,18 +148,6 @@ export const DeviceApi = {
return await request.get({ url: `/iot/device/get-auth-info`, params: { id } })
},
// 根据 ProductKey 和 DeviceNames 获取设备列表
// TODO @puhui999有没可能搞成基于 id 的查询哈?
getDevicesByProductKeyAndNames: async (productKey: string, deviceNames: string[]) => {
return await request.get({
url: `/iot/device/list-by-product-key-and-names`,
params: {
productKey,
deviceNames: deviceNames.join(',')
}
})
},
// 查询设备消息分页
getDeviceMessagePage: async (params: any) => {
return await request.get({ url: `/iot/device/message/page`, params })

View File

@ -58,7 +58,6 @@ const updateModelValue = () => {
emit('update:modelValue', result)
}
// TODO @puhui999 cursor
/** 监听项目变化 */
watch(items, updateModelValue, { deep: true })
watch(

View File

@ -13,7 +13,7 @@
class="w-full"
>
<el-option
v-for="option in conditionTypeOptions"
v-for="option in getConditionTypeOptions()"
:key="option.value"
:label="option.label"
:value="option.value"
@ -47,7 +47,10 @@
</el-row>
<!-- 设备状态条件配置 -->
<div v-if="condition.type === ConditionTypeEnum.DEVICE_STATUS" class="flex flex-col gap-16px">
<div
v-if="condition.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS"
class="flex flex-col gap-16px"
>
<!-- 状态和操作符选择 -->
<el-row :gutter="16">
<!-- 操作符选择 -->
@ -60,7 +63,7 @@
class="w-full"
>
<el-option
v-for="option in statusOperatorOptions"
v-for="option in getStatusOperatorOptions()"
:key="option.value"
:label="option.label"
:value="option.value"
@ -79,7 +82,7 @@
class="w-full"
>
<el-option
v-for="option in deviceStatusOptions"
v-for="option in getDeviceStatusOptions()"
:key="option.value"
:label="option.label"
:value="option.value"
@ -91,13 +94,15 @@
</div>
<!-- 设备属性条件配置 -->
<div v-else-if="condition.type === ConditionTypeEnum.DEVICE_PROPERTY" class="space-y-16px">
<div
v-else-if="condition.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY"
class="space-y-16px"
>
<!-- 属性配置 -->
<el-row :gutter="16">
<!-- 属性/事件/服务选择 -->
<el-col :span="6">
<el-form-item label="监控项" required>
<!-- TODO @puhui999是不是不展示整数小数这个类型一行只展示属性名 + 标识更简洁一点然后标识是 tag因为已经有个 tip -->
<PropertySelector
:model-value="condition.identifier"
@update:model-value="(value) => updateConditionField('identifier', value)"
@ -138,7 +143,7 @@
<!-- 当前时间条件配置 -->
<CurrentTimeConditionConfig
v-else-if="condition.type === ConditionTypeEnum.CURRENT_TIME"
v-else-if="condition.type === IotRuleSceneTriggerConditionTypeEnum.CURRENT_TIME"
:model-value="condition"
@update:model-value="updateCondition"
/>
@ -156,7 +161,10 @@ import ValueInput from '../inputs/ValueInput.vue'
import type { TriggerCondition } from '@/api/iot/rule/scene'
import {
IotRuleSceneTriggerConditionTypeEnum,
IotRuleSceneTriggerConditionParameterOperatorEnum
IotRuleSceneTriggerConditionParameterOperatorEnum,
getConditionTypeOptions,
getDeviceStatusOptions,
getStatusOperatorOptions
} from '@/views/iot/utils/constants'
/** 单个条件配置组件 */
@ -173,48 +181,6 @@ const emit = defineEmits<{
const condition = useVModel(props, 'modelValue', emit)
//
const ConditionTypeEnum = IotRuleSceneTriggerConditionTypeEnum
//
const conditionTypeOptions = [
{
value: IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS,
label: '设备状态'
},
{
value: IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY,
label: '设备属性'
},
{
value: IotRuleSceneTriggerConditionTypeEnum.CURRENT_TIME,
label: '当前时间'
}
]
//
const deviceStatusOptions = [
{
value: 'online',
label: '在线'
},
{
value: 'offline',
label: '离线'
}
]
//
const statusOperatorOptions = [
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.value,
label: IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.name
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.value,
label: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.name
}
]
//
const propertyType = ref<string>('string')
const propertyConfig = ref<any>(null)
@ -222,8 +188,8 @@ const propertyConfig = ref<any>(null)
//
const isDeviceCondition = computed(() => {
return (
condition.value.type === ConditionTypeEnum.DEVICE_STATUS ||
condition.value.type === ConditionTypeEnum.DEVICE_PROPERTY
condition.value.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS ||
condition.value.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY
)
})
@ -240,7 +206,7 @@ const updateCondition = (newCondition: TriggerCondition) => {
const handleConditionTypeChange = (type: number) => {
//
if (type === ConditionTypeEnum.DEVICE_STATUS) {
if (type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS) {
condition.value.identifier = undefined
//
if ('timeValue' in condition.value) {
@ -249,11 +215,11 @@ const handleConditionTypeChange = (type: number) => {
if ('timeValue2' in condition.value) {
delete (condition.value as any).timeValue2
}
} else if (type === ConditionTypeEnum.CURRENT_TIME) {
} else if (type === IotRuleSceneTriggerConditionTypeEnum.CURRENT_TIME) {
condition.value.identifier = undefined
condition.value.productId = undefined
condition.value.deviceId = undefined
} else if (type === ConditionTypeEnum.DEVICE_PROPERTY) {
} else if (type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY) {
//
if ('timeValue' in condition.value) {
delete (condition.value as any).timeValue

View File

@ -157,8 +157,12 @@
placeholder="请选择操作符"
class="w-full"
>
<el-option label="变为在线" value="online" />
<el-option label="变为离线" value="offline" />
<el-option
v-for="option in deviceStatusChangeOptions"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</el-form-item>
</el-col>
@ -168,7 +172,7 @@
<!-- 其他触发类型的提示 -->
<div v-else class="text-center py-20px">
<p class="text-14px text-[var(--el-text-color-secondary)] mb-4px">
当前触发事件类型{{ getTriggerTypeText(triggerType) }}
当前触发事件类型{{ getTriggerTypeLabel(triggerType) }}
</p>
<p class="text-12px text-[var(--el-text-color-placeholder)]">
此触发类型暂不需要配置额外条件
@ -186,7 +190,12 @@ import ValueInput from '../inputs/ValueInput.vue'
import JsonParamsInput from '../inputs/JsonParamsInput.vue'
import type { Trigger } from '@/api/iot/rule/scene'
import { IotRuleSceneTriggerTypeEnum, getTriggerTypeOptions } from '@/views/iot/utils/constants'
import {
IotRuleSceneTriggerTypeEnum,
getTriggerTypeOptions,
getTriggerTypeLabel,
getDeviceStatusChangeOptions
} from '@/views/iot/utils/constants'
import { useVModel } from '@vueuse/core'
/** 主条件内部配置组件 */
@ -249,25 +258,9 @@ const eventConfig = computed(() => {
return undefined
})
//
// TODO @puhui999
const getTriggerTypeText = (type: number) => {
switch (type) {
case IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST:
return '设备属性上报'
case IotRuleSceneTriggerTypeEnum.DEVICE_EVENT_POST:
return '设备事件上报'
case IotRuleSceneTriggerTypeEnum.DEVICE_SERVICE_INVOKE:
return '设备服务调用'
case IotRuleSceneTriggerTypeEnum.DEVICE_STATE_UPDATE:
return '设备状态变化'
default:
return '未知类型'
}
}
//
// 使
const triggerTypeOptions = getTriggerTypeOptions()
const deviceStatusChangeOptions = getDeviceStatusChangeOptions()
//
const updateConditionField = (field: keyof Trigger, value: any) => {

View File

@ -45,7 +45,7 @@
<Icon icon="ep:setting" class="text-[var(--el-color-success)] text-16px" />
<span>执行器 {{ index + 1 }}</span>
<el-tag :type="getActionTypeTag(action.type)" size="small">
{{ getActionTypeName(action.type) }}
{{ getActionTypeLabel(action.type) }}
</el-tag>
</div>
<div>
@ -139,7 +139,9 @@ import {
isDeviceAction,
isAlertAction,
getActionTypeLabel,
getActionTypeOptions
getActionTypeOptions,
getActionTypeTag,
SCENE_RULE_CONFIG
} from '@/views/iot/utils/constants'
/** 执行器配置组件 */
@ -169,22 +171,8 @@ const createDefaultActionData = (): Action => {
}
}
const maxActions = 5 //
//
const getActionTypeName = (type: number) => {
return getActionTypeLabel(type)
}
const getActionTypeTag = (type: number) => {
const actionTypeTags = {
[ActionTypeEnum.DEVICE_PROPERTY_SET]: 'primary',
[ActionTypeEnum.DEVICE_SERVICE_INVOKE]: 'success',
[ActionTypeEnum.ALERT_TRIGGER]: 'danger',
[ActionTypeEnum.ALERT_RECOVER]: 'warning'
}
return actionTypeTags[type] || 'info'
}
// 使
const maxActions = SCENE_RULE_CONFIG.MAX_ACTIONS
/** 添加执行器 */
const addAction = () => {

View File

@ -118,9 +118,9 @@ import DeviceTriggerConfig from '../configs/DeviceTriggerConfig.vue'
import { Crontab } from '@/components/Crontab'
import type { Trigger } from '@/api/iot/rule/scene'
import {
getTriggerTypeOptions,
getTriggerTypeLabel,
getTriggerTagType,
IotRuleSceneTriggerTypeEnum as TriggerTypeEnum,
IotRuleSceneTriggerTypeEnum,
isDeviceTrigger
} from '@/views/iot/utils/constants'
@ -137,23 +137,6 @@ const emit = defineEmits<{
const triggers = useVModel(props, 'triggers', emit)
// constants
const triggerTypeOptions = getTriggerTypeOptions()
//
// TODO @puhui999
const getTriggerTypeLabel = (type: number): string => {
const option = triggerTypeOptions.find((opt) => opt.value === type)
return option?.label || '未知类型'
}
const getTriggerTagType = (type: number): string => {
if (type === IotRuleSceneTriggerTypeEnum.TIMER) {
return 'warning'
}
return isDeviceTrigger(type) ? 'success' : 'info'
}
//
const addTrigger = () => {
const newTrigger: Trigger = {

View File

@ -24,11 +24,11 @@
<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 size="small" :type="getDeviceEnableStatusTagType(device.status)">
{{ getDeviceEnableStatusText(device.status) }}
</el-tag>
<el-tag size="small" :type="device.activeTime ? 'success' : 'info'">
{{ device.activeTime ? '已激活' : '未激活' }}
<el-tag size="small" :type="getDeviceActiveStatus(device.activeTime).tagType">
{{ getDeviceActiveStatus(device.activeTime).text }}
</el-tag>
</div>
</div>
@ -38,6 +38,12 @@
<script setup lang="ts">
import { DeviceApi } from '@/api/iot/device/device'
import {
getDeviceEnableStatusText,
getDeviceEnableStatusTagType,
getDeviceActiveStatus,
DEVICE_SELECTOR_OPTIONS
} from '@/views/iot/utils/constants'
/** 设备选择器组件 */
defineOptions({ name: 'DeviceSelector' })
@ -77,33 +83,12 @@ const getDeviceList = async () => {
console.error('获取设备列表失败:', error)
deviceList.value = []
} finally {
deviceList.value.push({ id: 0, deviceName: '全部设备' })
deviceList.value.push(DEVICE_SELECTOR_OPTIONS.ALL_DEVICES)
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 '未知'
}
}
// constants.ts
//
watch(

View File

@ -18,20 +18,17 @@
:label="property.name"
:value="property.identifier"
>
<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">
{{ property.name }}
</div>
<div class="text-12px text-[var(--el-text-color-secondary)]">
{{ property.identifier }}
</div>
</div>
<div class="flex-shrink-0">
<el-tag :type="getPropertyTypeTag(property.dataType)" size="small">
{{ getPropertyTypeName(property.dataType) }}
</el-tag>
</div>
<div class="flex items-center justify-between w-full py-2px">
<span class="text-14px font-500 text-[var(--el-text-color-primary)] flex-1 truncate">
{{ property.name }}
</span>
<el-tag
:type="getDataTypeTagType(property.dataType)"
size="small"
class="ml-8px flex-shrink-0"
>
{{ property.identifier }}
</el-tag>
</div>
</el-option>
</el-option-group>
@ -65,8 +62,8 @@
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">
{{ selectedProperty.name }}
</span>
<el-tag :type="getPropertyTypeTag(selectedProperty.dataType)" size="small">
{{ getPropertyTypeName(selectedProperty.dataType) }}
<el-tag :type="getDataTypeTagType(selectedProperty.dataType)" size="small">
{{ getDataTypeName(selectedProperty.dataType) }}
</el-tag>
</div>
@ -119,7 +116,7 @@
访问模式
</span>
<span class="text-12px text-[var(--el-text-color-primary)] flex-1">
{{ getAccessModeText(selectedProperty.accessMode) }}
{{ getAccessModeLabel(selectedProperty.accessMode) }}
</span>
</div>
@ -133,7 +130,7 @@
事件类型
</span>
<span class="text-12px text-[var(--el-text-color-primary)] flex-1">
{{ getEventTypeText(selectedProperty.eventType) }}
{{ getEventTypeLabel(selectedProperty.eventType) }}
</span>
</div>
@ -147,7 +144,7 @@
调用类型
</span>
<span class="text-12px text-[var(--el-text-color-primary)] flex-1">
{{ getCallTypeText(selectedProperty.callType) }}
{{ getThingModelServiceCallTypeLabel(selectedProperty.callType) }}
</span>
</div>
</div>
@ -162,7 +159,12 @@ import { InfoFilled } from '@element-plus/icons-vue'
import {
IotRuleSceneTriggerTypeEnum,
IoTThingModelTypeEnum,
IoTDataSpecsDataTypeEnum
getAccessModeLabel,
getEventTypeLabel,
getThingModelServiceCallTypeLabel,
getDataTypeName,
getDataTypeTagType,
THING_MODEL_GROUP_LABELS
} from '@/views/iot/utils/constants'
import type {
IotThingModelTSLResp,
@ -177,7 +179,7 @@ import { ThingModelApi } from '@/api/iot/thingmodel'
defineOptions({ name: 'PropertySelector' })
/** 属性选择器内部使用的统一数据结构 */
export interface PropertySelectorItem {
interface PropertySelectorItem {
identifier: string
name: string
description?: string
@ -221,21 +223,21 @@ const propertyGroups = computed(() => {
if (props.triggerType === IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST) {
groups.push({
label: '设备属性',
label: THING_MODEL_GROUP_LABELS.PROPERTY,
options: propertyList.value.filter((p) => p.type === IoTThingModelTypeEnum.PROPERTY)
})
}
if (props.triggerType === IotRuleSceneTriggerTypeEnum.DEVICE_EVENT_POST) {
groups.push({
label: '设备事件',
label: THING_MODEL_GROUP_LABELS.EVENT,
options: propertyList.value.filter((p) => p.type === IoTThingModelTypeEnum.EVENT)
})
}
if (props.triggerType === IotRuleSceneTriggerTypeEnum.DEVICE_SERVICE_INVOKE) {
groups.push({
label: '设备服务',
label: THING_MODEL_GROUP_LABELS.SERVICE,
options: propertyList.value.filter((p) => p.type === IoTThingModelTypeEnum.SERVICE)
})
}
@ -247,66 +249,6 @@ const selectedProperty = computed(() => {
return propertyList.value.find((p) => p.identifier === localValue.value)
})
//
const getPropertyTypeName = (dataType: string) => {
const typeMap = {
[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 = {
[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 getAccessModeText = (accessMode: string) => {
const modeMap = {
r: '只读',
w: '只写',
rw: '读写'
}
return modeMap[accessMode] || accessMode
}
// -
const getEventTypeText = (eventType: string) => {
const typeMap = {
info: '信息',
alert: '告警',
error: '故障'
}
return typeMap[eventType] || eventType
}
// -
const getCallTypeText = (callType: string) => {
const typeMap = {
sync: '同步',
async: '异步'
}
return typeMap[callType] || callType
}
//
const handleChange = (value: string) => {
const property = propertyList.value.find((p) => p.identifier === value)
@ -336,36 +278,17 @@ const getThingModelTSL = async () => {
thingModelTSL.value = tslData
parseThingModelData()
} else {
// TSL
await getThingModelList()
console.error('获取物模型TSL失败: 返回数据为空')
propertyList.value = []
}
} catch (error) {
console.error('获取物模型TSL失败:', error)
// TSL
await getThingModelList()
propertyList.value = []
} finally {
loading.value = false
}
}
/**
* 获取物模型列表备用方案
*/
const getThingModelList = async () => {
if (!props.productId) {
propertyList.value = []
return
}
try {
const data = await ThingModelApi.getThingModelList({ productId: props.productId })
propertyList.value = data || []
} catch (error) {
console.error('获取物模型列表失败:', error)
propertyList.value = []
}
}
// TSL
const parseThingModelData = () => {
const tsl = thingModelTSL.value
@ -484,7 +407,7 @@ watch(
/* 下拉选项样式 */
:deep(.el-select-dropdown__item) {
height: auto;
padding: 8px 20px;
padding: 6px 20px;
}
/* 弹出层内容样式 */

View File

@ -158,6 +158,47 @@ export const getDataTypeOptionsLabel = (value: string) => {
return dataType && `${dataType.value}(${dataType.label})`
}
/** 获取数据类型显示名称(用于属性选择器) */
export const getDataTypeName = (dataType: string): string => {
const typeMap = {
[IoTDataSpecsDataTypeEnum.INT]: '整数',
[IoTDataSpecsDataTypeEnum.FLOAT]: '浮点数',
[IoTDataSpecsDataTypeEnum.DOUBLE]: '双精度',
[IoTDataSpecsDataTypeEnum.TEXT]: '字符串',
[IoTDataSpecsDataTypeEnum.BOOL]: '布尔值',
[IoTDataSpecsDataTypeEnum.ENUM]: '枚举',
[IoTDataSpecsDataTypeEnum.DATE]: '日期',
[IoTDataSpecsDataTypeEnum.STRUCT]: '结构体',
[IoTDataSpecsDataTypeEnum.ARRAY]: '数组'
}
return typeMap[dataType] || dataType
}
/** 获取数据类型标签类型(用于 el-tag 的 type 属性) */
export const getDataTypeTagType = (
dataType: string
): 'primary' | 'success' | 'info' | 'warning' | 'danger' => {
const tagMap = {
[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'
} as const
return tagMap[dataType] || 'info'
}
/** 物模型组标签常量 */
export const THING_MODEL_GROUP_LABELS = {
PROPERTY: '设备属性',
EVENT: '设备事件',
SERVICE: '设备服务'
} as const
// IoT OTA 任务设备范围枚举
export const IoTOtaTaskDeviceScopeEnum = {
ALL: {
@ -314,6 +355,26 @@ export const getActionTypeLabel = (type: number): string => {
return option?.label || '未知类型'
}
/** 获取执行器标签类型(用于 el-tag 的 type 属性) */
export const getActionTypeTag = (
type: number
): 'primary' | 'success' | 'info' | 'warning' | 'danger' => {
const actionTypeTags = {
[IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET]: 'primary',
[IotRuleSceneActionTypeEnum.DEVICE_SERVICE_INVOKE]: 'success',
[IotRuleSceneActionTypeEnum.ALERT_TRIGGER]: 'danger',
[IotRuleSceneActionTypeEnum.ALERT_RECOVER]: 'warning'
} as const
return actionTypeTags[type] || 'info'
}
/** 场景联动规则配置常量 */
export const SCENE_RULE_CONFIG = {
MAX_ACTIONS: 5, // 最大执行器数量
MAX_TRIGGERS: 10, // 最大触发器数量
MAX_CONDITIONS: 20 // 最大条件数量
} as const
/** IoT 设备消息类型枚举 */
export const IotDeviceMessageTypeEnum = {
PROPERTY: 'property', // 属性
@ -344,6 +405,131 @@ export const IotRuleSceneTriggerConditionTypeEnum = {
CURRENT_TIME: 3 // 当前时间
} as const
/** 获取条件类型选项 */
export const getConditionTypeOptions = () => [
{
value: IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS,
label: '设备状态'
},
{
value: IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY,
label: '设备属性'
},
{
value: IotRuleSceneTriggerConditionTypeEnum.CURRENT_TIME,
label: '当前时间'
}
]
/** 设备状态枚举 */
export const IoTDeviceStatusEnum = {
ONLINE: {
label: '在线',
value: 'online'
},
OFFLINE: {
label: '离线',
value: 'offline'
}
} as const
/** 设备启用状态枚举 */
export const IoTDeviceEnableStatusEnum = {
ENABLED: {
label: '正常',
value: 0,
tagType: 'success'
},
DISABLED: {
label: '禁用',
value: 1,
tagType: 'danger'
}
} as const
/** 设备激活状态枚举 */
export const IoTDeviceActiveStatusEnum = {
ACTIVATED: {
label: '已激活',
tagType: 'success'
},
NOT_ACTIVATED: {
label: '未激活',
tagType: 'info'
}
} as const
/** 设备选择器特殊选项 */
export const DEVICE_SELECTOR_OPTIONS = {
ALL_DEVICES: {
id: 0,
deviceName: '全部设备'
}
} as const
/** 获取设备状态选项 */
export const getDeviceStatusOptions = () => [
{
value: IoTDeviceStatusEnum.ONLINE.value,
label: IoTDeviceStatusEnum.ONLINE.label
},
{
value: IoTDeviceStatusEnum.OFFLINE.value,
label: IoTDeviceStatusEnum.OFFLINE.label
}
]
/** 获取状态操作符选项 */
export const getStatusOperatorOptions = () => [
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.value,
label: IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.name
},
{
value: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.value,
label: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.name
}
]
/** 获取设备状态变更选项(用于触发器配置) */
export const getDeviceStatusChangeOptions = () => [
{
label: '变为在线',
value: IoTDeviceStatusEnum.ONLINE.value
},
{
label: '变为离线',
value: IoTDeviceStatusEnum.OFFLINE.value
}
]
/** 获取设备启用状态文本 */
export const getDeviceEnableStatusText = (status: number): string => {
const statusItem = Object.values(IoTDeviceEnableStatusEnum).find((item) => item.value === status)
return statusItem?.label || '未知'
}
/** 获取设备启用状态标签类型 */
export const getDeviceEnableStatusTagType = (
status: number
): 'primary' | 'success' | 'info' | 'warning' | 'danger' => {
const statusItem = Object.values(IoTDeviceEnableStatusEnum).find((item) => item.value === status)
return statusItem?.tagType || 'info'
}
/** 获取设备激活状态文本和标签类型 */
export const getDeviceActiveStatus = (activeTime?: string | null) => {
const isActivated = !!activeTime
return {
text: isActivated
? IoTDeviceActiveStatusEnum.ACTIVATED.label
: IoTDeviceActiveStatusEnum.NOT_ACTIVATED.label,
tagType: isActivated
? IoTDeviceActiveStatusEnum.ACTIVATED.tagType
: IoTDeviceActiveStatusEnum.NOT_ACTIVATED.tagType
}
}
/** IoT 场景联动触发时间操作符枚举 */
export const IotRuleSceneTriggerTimeOperatorEnum = {
BEFORE_TIME: { name: '在时间之前', value: 'before_time' }, // 在时间之前
@ -363,3 +549,13 @@ export const getTriggerTypeLabel = (type: number): string => {
const option = options.find((item) => item.value === type)
return option?.label || '未知类型'
}
/** 获取触发器标签类型(用于 el-tag 的 type 属性) */
export const getTriggerTagType = (
type: number
): 'primary' | 'success' | 'info' | 'warning' | 'danger' => {
if (type === IotRuleSceneTriggerTypeEnum.TIMER) {
return 'warning'
}
return isDeviceTrigger(type) ? 'success' : 'info'
}