perf: 【IoT 物联网】优化场景联动 review 提到的逻辑
parent
6bfd888b54
commit
1c4222de35
|
@ -63,7 +63,7 @@
|
|||
class="w-full"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in getStatusOperatorOptions()"
|
||||
v-for="option in statusOperatorOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
|
@ -82,7 +82,7 @@
|
|||
class="w-full"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in getDeviceStatusOptions()"
|
||||
v-for="option in deviceStatusOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
|
@ -163,8 +163,7 @@ import {
|
|||
IotRuleSceneTriggerConditionTypeEnum,
|
||||
IotRuleSceneTriggerConditionParameterOperatorEnum,
|
||||
getConditionTypeOptions,
|
||||
getDeviceStatusOptions,
|
||||
getStatusOperatorOptions
|
||||
IoTDeviceStatusEnum
|
||||
} from '@/views/iot/utils/constants'
|
||||
|
||||
/** 单个条件配置组件 */
|
||||
|
@ -179,6 +178,30 @@ const emit = defineEmits<{
|
|||
(e: 'update:modelValue', value: TriggerCondition): void
|
||||
}>()
|
||||
|
||||
/** 获取设备状态选项 */
|
||||
const deviceStatusOptions = [
|
||||
{
|
||||
value: IoTDeviceStatusEnum.ONLINE.value,
|
||||
label: IoTDeviceStatusEnum.ONLINE.label
|
||||
},
|
||||
{
|
||||
value: IoTDeviceStatusEnum.OFFLINE.value,
|
||||
label: IoTDeviceStatusEnum.OFFLINE.label
|
||||
}
|
||||
]
|
||||
|
||||
/** 获取状态操作符选项 */
|
||||
const statusOperatorOptions = [
|
||||
{
|
||||
value: IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.value,
|
||||
label: IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.name
|
||||
},
|
||||
{
|
||||
value: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.value,
|
||||
label: IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.name
|
||||
}
|
||||
]
|
||||
|
||||
const condition = useVModel(props, 'modelValue', emit)
|
||||
|
||||
const propertyType = ref<string>('string') // 属性类型
|
||||
|
|
|
@ -187,8 +187,8 @@ import {
|
|||
IotRuleSceneTriggerTypeEnum,
|
||||
triggerTypeOptions,
|
||||
getTriggerTypeLabel,
|
||||
deviceStatusChangeOptions,
|
||||
IotRuleSceneTriggerConditionParameterOperatorEnum
|
||||
IotRuleSceneTriggerConditionParameterOperatorEnum,
|
||||
IoTDeviceStatusEnum
|
||||
} from '@/views/iot/utils/constants'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
|
@ -205,6 +205,18 @@ const emit = defineEmits<{
|
|||
(e: 'trigger-type-change', value: number): void
|
||||
}>()
|
||||
|
||||
/** 获取设备状态变更选项(用于触发器配置) */
|
||||
const deviceStatusChangeOptions = [
|
||||
{
|
||||
label: IoTDeviceStatusEnum.ONLINE.label,
|
||||
value: IoTDeviceStatusEnum.ONLINE.value
|
||||
},
|
||||
{
|
||||
label: IoTDeviceStatusEnum.OFFLINE.label,
|
||||
value: IoTDeviceStatusEnum.OFFLINE.value
|
||||
}
|
||||
]
|
||||
|
||||
const condition = useVModel(props, 'modelValue', emit)
|
||||
const propertyType = ref('') // 属性类型
|
||||
const propertyConfig = ref<any>(null) // 属性配置
|
||||
|
|
|
@ -1,148 +1,139 @@
|
|||
<!-- JSON参数输入组件 - 通用版本 -->
|
||||
<template>
|
||||
<div class="w-full min-w-0">
|
||||
<!-- 参数配置 -->
|
||||
<div v-if="hasConfig" class="space-y-12px">
|
||||
<!-- JSON 输入框 -->
|
||||
<div class="relative">
|
||||
<el-input
|
||||
v-model="paramsJson"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
:placeholder="placeholder"
|
||||
@input="handleParamsChange"
|
||||
:class="{ 'is-error': jsonError }"
|
||||
/>
|
||||
<!-- 查看详细示例弹出层 -->
|
||||
<div class="absolute top-8px right-8px">
|
||||
<el-popover
|
||||
placement="left-start"
|
||||
:width="450"
|
||||
trigger="click"
|
||||
:show-arrow="true"
|
||||
:offset="8"
|
||||
popper-class="json-params-detail-popover"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button
|
||||
type="info"
|
||||
:icon="InfoFilled"
|
||||
circle
|
||||
size="small"
|
||||
:title="JSON_PARAMS_INPUT_CONSTANTS.VIEW_EXAMPLE_TITLE"
|
||||
/>
|
||||
</template>
|
||||
<!-- 参数配置 -->
|
||||
<div class="w-full space-y-12px">
|
||||
<!-- JSON 输入框 -->
|
||||
<div class="relative">
|
||||
<el-input
|
||||
v-model="paramsJson"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
:placeholder="placeholder"
|
||||
@input="handleParamsChange"
|
||||
:class="{ 'is-error': jsonError }"
|
||||
/>
|
||||
<!-- 查看详细示例弹出层 -->
|
||||
<div class="absolute top-8px right-8px">
|
||||
<el-popover
|
||||
placement="left-start"
|
||||
:width="450"
|
||||
trigger="click"
|
||||
:show-arrow="true"
|
||||
:offset="8"
|
||||
popper-class="json-params-detail-popover"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button
|
||||
type="info"
|
||||
:icon="InfoFilled"
|
||||
circle
|
||||
size="small"
|
||||
:title="JSON_PARAMS_INPUT_CONSTANTS.VIEW_EXAMPLE_TITLE"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 弹出层内容 -->
|
||||
<div class="json-params-detail-content">
|
||||
<div class="flex items-center gap-8px mb-16px">
|
||||
<Icon :icon="titleIcon" class="text-[var(--el-color-primary)] text-18px" />
|
||||
<span class="text-16px font-600 text-[var(--el-text-color-primary)]">
|
||||
{{ title }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- 弹出层内容 -->
|
||||
<div class="json-params-detail-content">
|
||||
<div class="flex items-center gap-8px mb-16px">
|
||||
<Icon :icon="titleIcon" class="text-[var(--el-color-primary)] text-18px" />
|
||||
<span class="text-16px font-600 text-[var(--el-text-color-primary)]">
|
||||
{{ title }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="space-y-16px">
|
||||
<!-- 参数列表 -->
|
||||
<div v-if="paramsList.length > 0">
|
||||
<div class="flex items-center gap-8px mb-8px">
|
||||
<Icon :icon="paramsIcon" class="text-[var(--el-color-primary)] text-14px" />
|
||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">
|
||||
{{ paramsLabel }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="ml-22px space-y-8px">
|
||||
<div
|
||||
v-for="param in paramsList"
|
||||
:key="param.identifier"
|
||||
class="flex items-center justify-between p-8px bg-[var(--el-fill-color-lighter)] rounded-4px"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="text-12px font-500 text-[var(--el-text-color-primary)]">
|
||||
{{ param.name }}
|
||||
<el-tag v-if="param.required" size="small" type="danger" class="ml-4px">
|
||||
{{ JSON_PARAMS_INPUT_CONSTANTS.REQUIRED_TAG }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="text-11px text-[var(--el-text-color-secondary)]">
|
||||
{{ param.identifier }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-8px">
|
||||
<el-tag :type="getParamTypeTag(param.dataType)" size="small">
|
||||
{{ getParamTypeName(param.dataType) }}
|
||||
<div class="space-y-16px">
|
||||
<!-- 参数列表 -->
|
||||
<div v-if="paramsList.length > 0">
|
||||
<div class="flex items-center gap-8px mb-8px">
|
||||
<Icon :icon="paramsIcon" class="text-[var(--el-color-primary)] text-14px" />
|
||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">
|
||||
{{ paramsLabel }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="ml-22px space-y-8px">
|
||||
<div
|
||||
v-for="param in paramsList"
|
||||
:key="param.identifier"
|
||||
class="flex items-center justify-between p-8px bg-[var(--el-fill-color-lighter)] rounded-4px"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="text-12px font-500 text-[var(--el-text-color-primary)]">
|
||||
{{ param.name }}
|
||||
<el-tag v-if="param.required" size="small" type="danger" class="ml-4px">
|
||||
{{ JSON_PARAMS_INPUT_CONSTANTS.REQUIRED_TAG }}
|
||||
</el-tag>
|
||||
<span class="text-11px text-[var(--el-text-color-secondary)]">
|
||||
{{ getExampleValue(param) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-11px text-[var(--el-text-color-secondary)]">
|
||||
{{ param.identifier }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-12px ml-22px">
|
||||
<div class="text-12px text-[var(--el-text-color-secondary)] mb-6px">
|
||||
{{ JSON_PARAMS_INPUT_CONSTANTS.COMPLETE_JSON_FORMAT }}
|
||||
<div class="flex items-center gap-8px">
|
||||
<el-tag :type="getParamTypeTag(param.dataType)" size="small">
|
||||
{{ getParamTypeName(param.dataType) }}
|
||||
</el-tag>
|
||||
<span class="text-11px text-[var(--el-text-color-secondary)]">
|
||||
{{ getExampleValue(param) }}
|
||||
</span>
|
||||
</div>
|
||||
<pre
|
||||
class="p-12px bg-[var(--el-fill-color-light)] rounded-4px text-11px text-[var(--el-text-color-primary)] overflow-x-auto border-l-3px border-[var(--el-color-primary)]"
|
||||
>
|
||||
<code>{{ generateExampleJson() }}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 无参数提示 -->
|
||||
<div v-else>
|
||||
<div class="text-center py-16px">
|
||||
<p class="text-14px text-[var(--el-text-color-secondary)]">{{
|
||||
emptyMessage
|
||||
}}</p>
|
||||
<div class="mt-12px ml-22px">
|
||||
<div class="text-12px text-[var(--el-text-color-secondary)] mb-6px">
|
||||
{{ JSON_PARAMS_INPUT_CONSTANTS.COMPLETE_JSON_FORMAT }}
|
||||
</div>
|
||||
<pre
|
||||
class="p-12px bg-[var(--el-fill-color-light)] rounded-4px text-11px text-[var(--el-text-color-primary)] overflow-x-auto border-l-3px border-[var(--el-color-primary)]"
|
||||
>
|
||||
<code>{{ generateExampleJson() }}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 无参数提示 -->
|
||||
<div v-else>
|
||||
<div class="text-center py-16px">
|
||||
<p class="text-14px text-[var(--el-text-color-secondary)]">{{ emptyMessage }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 验证状态和错误提示 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-8px">
|
||||
<Icon
|
||||
:icon="
|
||||
jsonError
|
||||
? JSON_PARAMS_INPUT_ICONS.STATUS_ICONS.ERROR
|
||||
: JSON_PARAMS_INPUT_ICONS.STATUS_ICONS.SUCCESS
|
||||
"
|
||||
:class="jsonError ? 'text-[var(--el-color-danger)]' : 'text-[var(--el-color-success)]'"
|
||||
class="text-14px"
|
||||
/>
|
||||
<span
|
||||
:class="jsonError ? 'text-[var(--el-color-danger)]' : 'text-[var(--el-color-success)]'"
|
||||
class="text-12px"
|
||||
>
|
||||
{{ jsonError || JSON_PARAMS_INPUT_CONSTANTS.JSON_FORMAT_CORRECT }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 快速填充按钮 -->
|
||||
<div v-if="paramsList.length > 0" class="flex items-center gap-8px">
|
||||
<span class="text-12px text-[var(--el-text-color-secondary)]">{{
|
||||
JSON_PARAMS_INPUT_CONSTANTS.QUICK_FILL_LABEL
|
||||
}}</span>
|
||||
<el-button size="small" type="primary" plain @click="fillExampleJson">
|
||||
{{ JSON_PARAMS_INPUT_CONSTANTS.EXAMPLE_DATA_BUTTON }}
|
||||
</el-button>
|
||||
<el-button size="small" type="danger" plain @click="clearParams">{{
|
||||
JSON_PARAMS_INPUT_CONSTANTS.CLEAR_BUTTON
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 无配置提示 -->
|
||||
<div v-else class="text-center py-20px">
|
||||
<p class="text-14px text-[var(--el-text-color-secondary)]">{{ noConfigMessage }}</p>
|
||||
<!-- 验证状态和错误提示 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-8px">
|
||||
<Icon
|
||||
:icon="
|
||||
jsonError
|
||||
? JSON_PARAMS_INPUT_ICONS.STATUS_ICONS.ERROR
|
||||
: JSON_PARAMS_INPUT_ICONS.STATUS_ICONS.SUCCESS
|
||||
"
|
||||
:class="jsonError ? 'text-[var(--el-color-danger)]' : 'text-[var(--el-color-success)]'"
|
||||
class="text-14px"
|
||||
/>
|
||||
<span
|
||||
:class="jsonError ? 'text-[var(--el-color-danger)]' : 'text-[var(--el-color-success)]'"
|
||||
class="text-12px"
|
||||
>
|
||||
{{ jsonError || JSON_PARAMS_INPUT_CONSTANTS.JSON_FORMAT_CORRECT }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 快速填充按钮 -->
|
||||
<div v-if="paramsList.length > 0" class="flex items-center gap-8px">
|
||||
<span class="text-12px text-[var(--el-text-color-secondary)]">{{
|
||||
JSON_PARAMS_INPUT_CONSTANTS.QUICK_FILL_LABEL
|
||||
}}</span>
|
||||
<el-button size="small" type="primary" plain @click="fillExampleJson">
|
||||
{{ JSON_PARAMS_INPUT_CONSTANTS.EXAMPLE_DATA_BUTTON }}
|
||||
</el-button>
|
||||
<el-button size="small" type="danger" plain @click="clearParams">{{
|
||||
JSON_PARAMS_INPUT_CONSTANTS.CLEAR_BUTTON
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -162,7 +153,7 @@ import {
|
|||
/** JSON参数输入组件 - 通用版本 */
|
||||
defineOptions({ name: 'JsonParamsInput' })
|
||||
|
||||
export interface JsonParamsConfig {
|
||||
interface JsonParamsConfig {
|
||||
// 服务配置
|
||||
service?: {
|
||||
name: string
|
||||
|
@ -207,19 +198,6 @@ const localValue = useVModel(props, 'modelValue', emit, {
|
|||
const paramsJson = ref('') // JSON参数字符串
|
||||
const jsonError = ref('') // JSON验证错误信息
|
||||
|
||||
// 计算属性:是否有配置
|
||||
const hasConfig = computed(() => {
|
||||
// TODO @puhui999: 后续统一处理
|
||||
console.log(props.config)
|
||||
// return !!(
|
||||
// props.config?.service ||
|
||||
// props.config?.event ||
|
||||
// props.config?.properties ||
|
||||
// props.config?.custom
|
||||
// )
|
||||
return true
|
||||
})
|
||||
|
||||
// 计算属性:参数列表
|
||||
const paramsList = computed(() => {
|
||||
switch (props.type) {
|
||||
|
|
|
@ -6,15 +6,10 @@
|
|||
<div class="flex items-center gap-8px">
|
||||
<Icon icon="ep:setting" class="text-[var(--el-color-primary)] text-18px" />
|
||||
<span class="text-16px font-600 text-[var(--el-text-color-primary)]">执行器配置</span>
|
||||
<el-tag size="small" type="info">{{ actions.length }}/{{ maxActions }}</el-tag>
|
||||
<el-tag size="small" type="info">{{ actions.length }} 个执行器</el-tag>
|
||||
</div>
|
||||
<div class="flex items-center gap-8px">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="addAction"
|
||||
:disabled="actions.length >= maxActions"
|
||||
>
|
||||
<el-button type="primary" size="small" @click="addAction">
|
||||
<Icon icon="ep:plus" />
|
||||
添加执行器
|
||||
</el-button>
|
||||
|
@ -103,14 +98,14 @@
|
|||
|
||||
<!-- 告警配置 - 只有恢复告警时才显示 -->
|
||||
<AlertConfig
|
||||
v-if="action.type === ActionTypeEnum.ALERT_RECOVER"
|
||||
v-if="action.type === IotRuleSceneActionTypeEnum.ALERT_RECOVER"
|
||||
:model-value="action.alertConfigId"
|
||||
@update:model-value="(value) => updateActionAlertConfig(index, value)"
|
||||
/>
|
||||
|
||||
<!-- 触发告警提示 - 触发告警时显示 -->
|
||||
<div
|
||||
v-if="action.type === ActionTypeEnum.ALERT_TRIGGER"
|
||||
v-if="action.type === IotRuleSceneActionTypeEnum.ALERT_TRIGGER"
|
||||
class="border border-[var(--el-border-color-light)] rounded-6px p-16px bg-[var(--el-fill-color-blank)]"
|
||||
>
|
||||
<div class="flex items-center gap-8px mb-8px">
|
||||
|
@ -127,14 +122,11 @@
|
|||
</div>
|
||||
|
||||
<!-- 添加提示 -->
|
||||
<div v-if="actions.length > 0 && actions.length < maxActions" class="text-center py-16px">
|
||||
<div v-if="actions.length > 0" class="text-center py-16px">
|
||||
<el-button type="primary" plain @click="addAction">
|
||||
<Icon icon="ep:plus" />
|
||||
继续添加执行器
|
||||
</el-button>
|
||||
<span class="block mt-8px text-12px text-[var(--el-text-color-secondary)]">
|
||||
最多可添加 {{ maxActions }} 个执行器
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
@ -146,13 +138,9 @@ import DeviceControlConfig from '../configs/DeviceControlConfig.vue'
|
|||
import AlertConfig from '../configs/AlertConfig.vue'
|
||||
import type { Action } from '@/api/iot/rule/scene'
|
||||
import {
|
||||
IotRuleSceneActionTypeEnum as ActionTypeEnum,
|
||||
isDeviceAction,
|
||||
isAlertAction,
|
||||
getActionTypeLabel,
|
||||
getActionTypeOptions,
|
||||
getActionTypeTag,
|
||||
SCENE_RULE_CONFIG
|
||||
IotRuleSceneActionTypeEnum
|
||||
} from '@/views/iot/utils/constants'
|
||||
|
||||
/** 执行器配置组件 */
|
||||
|
@ -168,7 +156,34 @@ const emit = defineEmits<{
|
|||
|
||||
const actions = useVModel(props, 'actions', emit)
|
||||
|
||||
const maxActions = SCENE_RULE_CONFIG.MAX_ACTIONS // 最大执行器数量
|
||||
/** 获取执行器标签类型(用于 el-tag 的 type 属性) */
|
||||
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'
|
||||
}
|
||||
|
||||
/** 判断是否为设备执行器类型 */
|
||||
const isDeviceAction = (type: number): boolean => {
|
||||
const deviceActionTypes = [
|
||||
IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET,
|
||||
IotRuleSceneActionTypeEnum.DEVICE_SERVICE_INVOKE
|
||||
] as number[]
|
||||
return deviceActionTypes.includes(type)
|
||||
}
|
||||
|
||||
/** 判断是否为告警执行器类型 */
|
||||
const isAlertAction = (type: number): boolean => {
|
||||
const alertActionTypes = [
|
||||
IotRuleSceneActionTypeEnum.ALERT_TRIGGER,
|
||||
IotRuleSceneActionTypeEnum.ALERT_RECOVER
|
||||
] as number[]
|
||||
return alertActionTypes.includes(type)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建默认的执行器数据
|
||||
|
@ -176,7 +191,7 @@ const maxActions = SCENE_RULE_CONFIG.MAX_ACTIONS // 最大执行器数量
|
|||
*/
|
||||
const createDefaultActionData = (): Action => {
|
||||
return {
|
||||
type: ActionTypeEnum.DEVICE_PROPERTY_SET, // 默认为设备属性设置
|
||||
type: IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET, // 默认为设备属性设置
|
||||
productId: undefined,
|
||||
deviceId: undefined,
|
||||
identifier: undefined, // 物模型标识符(服务调用时使用)
|
||||
|
@ -189,10 +204,6 @@ const createDefaultActionData = (): Action => {
|
|||
* 添加执行器
|
||||
*/
|
||||
const addAction = () => {
|
||||
if (actions.value.length >= maxActions) {
|
||||
return
|
||||
}
|
||||
|
||||
const newAction = createDefaultActionData()
|
||||
actions.value.push(newAction)
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
|
||||
<!-- 定时触发配置 -->
|
||||
<div
|
||||
v-else-if="triggerItem.type === TriggerTypeEnum.TIMER"
|
||||
v-else-if="triggerItem.type === IotRuleSceneTriggerTypeEnum.TIMER"
|
||||
class="flex flex-col gap-16px"
|
||||
>
|
||||
<div
|
||||
|
@ -119,8 +119,7 @@ import { Crontab } from '@/components/Crontab'
|
|||
import type { Trigger } from '@/api/iot/rule/scene'
|
||||
import {
|
||||
getTriggerTypeLabel,
|
||||
getTriggerTagType,
|
||||
IotRuleSceneTriggerTypeEnum as TriggerTypeEnum,
|
||||
IotRuleSceneTriggerTypeEnum,
|
||||
isDeviceTrigger
|
||||
} from '@/views/iot/utils/constants'
|
||||
|
||||
|
@ -137,10 +136,18 @@ const emit = defineEmits<{
|
|||
|
||||
const triggers = useVModel(props, 'triggers', emit)
|
||||
|
||||
/** 获取触发器标签类型(用于 el-tag 的 type 属性) */
|
||||
const getTriggerTagType = (type: number): 'primary' | 'success' | 'info' | 'warning' | 'danger' => {
|
||||
if (type === IotRuleSceneTriggerTypeEnum.TIMER) {
|
||||
return 'warning'
|
||||
}
|
||||
return isDeviceTrigger(type) ? 'success' : 'info'
|
||||
}
|
||||
|
||||
/** 添加触发器 */
|
||||
const addTrigger = () => {
|
||||
const newTrigger: Trigger = {
|
||||
type: TriggerTypeEnum.DEVICE_STATE_UPDATE,
|
||||
type: IotRuleSceneTriggerTypeEnum.DEVICE_STATE_UPDATE,
|
||||
productId: undefined,
|
||||
deviceId: undefined,
|
||||
identifier: undefined,
|
||||
|
|
|
@ -24,12 +24,7 @@
|
|||
<div class="text-12px text-[var(--el-text-color-secondary)]">{{ device.deviceKey }}</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-4px" v-if="device.id > 0">
|
||||
<el-tag size="small" :type="getDeviceEnableStatusTagType(device.status)">
|
||||
{{ getDeviceEnableStatusText(device.status) }}
|
||||
</el-tag>
|
||||
<el-tag size="small" :type="getDeviceActiveStatus(device.activeTime).tagType">
|
||||
{{ getDeviceActiveStatus(device.activeTime).text }}
|
||||
</el-tag>
|
||||
<dict-tag :type="DICT_TYPE.IOT_DEVICE_STATE" :value="device.state" />
|
||||
</div>
|
||||
</div>
|
||||
</el-option>
|
||||
|
@ -38,12 +33,8 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { DeviceApi } from '@/api/iot/device/device'
|
||||
import {
|
||||
getDeviceEnableStatusText,
|
||||
getDeviceEnableStatusTagType,
|
||||
getDeviceActiveStatus,
|
||||
DEVICE_SELECTOR_OPTIONS
|
||||
} from '@/views/iot/utils/constants'
|
||||
import { DEVICE_SELECTOR_OPTIONS } from '@/views/iot/utils/constants'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
|
||||
/** 设备选择器组件 */
|
||||
defineOptions({ name: 'DeviceSelector' })
|
||||
|
|
|
@ -55,13 +55,6 @@ export const IotDeviceMessageMethodEnum = {
|
|||
}
|
||||
}
|
||||
|
||||
// IoT 产品物模型类型枚举类
|
||||
export const IotThingModelTypeEnum = {
|
||||
PROPERTY: 1, // 属性
|
||||
SERVICE: 2, // 服务
|
||||
EVENT: 3 // 事件
|
||||
}
|
||||
|
||||
// IoT 产品物模型服务调用方式枚举
|
||||
export const IoTThingModelServiceCallTypeEnum = {
|
||||
ASYNC: {
|
||||
|
@ -331,60 +324,12 @@ export const getActionTypeOptions = () => [
|
|||
}
|
||||
]
|
||||
|
||||
/** 判断是否为设备执行器类型 */
|
||||
export const isDeviceAction = (type: number): boolean => {
|
||||
const deviceActionTypes = [
|
||||
IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET,
|
||||
IotRuleSceneActionTypeEnum.DEVICE_SERVICE_INVOKE
|
||||
] as number[]
|
||||
return deviceActionTypes.includes(type)
|
||||
}
|
||||
|
||||
/** 判断是否为告警执行器类型 */
|
||||
export const isAlertAction = (type: number): boolean => {
|
||||
const alertActionTypes = [
|
||||
IotRuleSceneActionTypeEnum.ALERT_TRIGGER,
|
||||
IotRuleSceneActionTypeEnum.ALERT_RECOVER
|
||||
] as number[]
|
||||
return alertActionTypes.includes(type)
|
||||
}
|
||||
|
||||
/** 获取执行器类型标签 */
|
||||
export const getActionTypeLabel = (type: number): string => {
|
||||
const option = getActionTypeOptions().find((opt) => opt.value === type)
|
||||
return option?.label || '未知类型'
|
||||
}
|
||||
|
||||
/** 获取执行器标签类型(用于 el-tag 的 type 属性) */
|
||||
// TODO @puhui999:这种跟界面相关的,可以拿到对应组件里;
|
||||
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'
|
||||
}
|
||||
|
||||
// TODO @puhui999:建议不设置最大值哈。
|
||||
/** 场景联动规则配置常量 */
|
||||
export const SCENE_RULE_CONFIG = {
|
||||
MAX_ACTIONS: 5, // 最大执行器数量
|
||||
MAX_TRIGGERS: 10, // 最大触发器数量
|
||||
MAX_CONDITIONS: 20 // 最大条件数量
|
||||
} as const
|
||||
|
||||
// TODO @puhui999:下面这个要去掉么?
|
||||
/** IoT 设备消息类型枚举 */
|
||||
export const IotDeviceMessageTypeEnum = {
|
||||
PROPERTY: 'property', // 属性
|
||||
SERVICE: 'service', // 服务
|
||||
EVENT: 'event' // 事件
|
||||
} as const
|
||||
|
||||
/** IoT 场景联动触发条件参数操作符枚举 */
|
||||
export const IotRuleSceneTriggerConditionParameterOperatorEnum = {
|
||||
EQUALS: { name: '等于', value: '=' }, // 等于
|
||||
|
@ -424,42 +369,41 @@ export const getConditionTypeOptions = () => [
|
|||
}
|
||||
]
|
||||
|
||||
/** 设备状态枚举 */
|
||||
/** 设备状态枚举 - 统一的设备状态管理 */
|
||||
export const IoTDeviceStatusEnum = {
|
||||
// 在线状态
|
||||
ONLINE: {
|
||||
label: '在线',
|
||||
value: 'online'
|
||||
value: 'online',
|
||||
tagType: 'success'
|
||||
},
|
||||
OFFLINE: {
|
||||
label: '离线',
|
||||
value: 'offline'
|
||||
}
|
||||
} as const
|
||||
|
||||
/** 设备启用状态枚举 */
|
||||
// TODO @puhui999:这个是不是和 IoTDeviceStatusEnum 合并下;额外增加一个 value2
|
||||
export const IoTDeviceEnableStatusEnum = {
|
||||
value: 'offline',
|
||||
tagType: 'danger'
|
||||
},
|
||||
// 启用状态
|
||||
ENABLED: {
|
||||
label: '正常',
|
||||
value: 0,
|
||||
value2: 'enabled',
|
||||
tagType: 'success'
|
||||
},
|
||||
DISABLED: {
|
||||
label: '禁用',
|
||||
value: 1,
|
||||
value2: 'disabled',
|
||||
tagType: 'danger'
|
||||
}
|
||||
} as const
|
||||
|
||||
/** 设备激活状态枚举 */
|
||||
// TODO @puhui999:这个是不是搞到界面里。label 就是 IoTDeviceStatusEnum,然后 tag 界面里处理;;或者也可以在想想,= = 主要设备状态有 3 个枚举,嘿嘿~
|
||||
export const IoTDeviceActiveStatusEnum = {
|
||||
},
|
||||
// 激活状态
|
||||
ACTIVATED: {
|
||||
label: '已激活',
|
||||
value2: 'activated',
|
||||
tagType: 'success'
|
||||
},
|
||||
NOT_ACTIVATED: {
|
||||
label: '未激活',
|
||||
value2: 'not_activated',
|
||||
tagType: 'info'
|
||||
}
|
||||
} as const
|
||||
|
@ -472,72 +416,6 @@ export const DEVICE_SELECTOR_OPTIONS = {
|
|||
}
|
||||
} 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 deviceStatusChangeOptions = [
|
||||
{
|
||||
label: IoTDeviceStatusEnum.ONLINE.label,
|
||||
value: IoTDeviceStatusEnum.ONLINE.value
|
||||
},
|
||||
{
|
||||
label: IoTDeviceStatusEnum.OFFLINE.label,
|
||||
value: IoTDeviceStatusEnum.OFFLINE.value
|
||||
}
|
||||
]
|
||||
|
||||
/** 获取设备启用状态文本 */
|
||||
export const getDeviceEnableStatusText = (status: number): string => {
|
||||
// TODO @puhui999:设备有 3 个状态,上线、离线,未激活;
|
||||
const statusItem = Object.values(IoTDeviceEnableStatusEnum).find((item) => item.value === status)
|
||||
return statusItem?.label || '未知'
|
||||
}
|
||||
|
||||
/** 获取设备启用状态标签类型 */
|
||||
// TODO @puhui999:这个是不是可以直接在界面里处理;或者也可以在想想,= = 主要设备状态有 3 个枚举,嘿嘿~
|
||||
export const getDeviceEnableStatusTagType = (
|
||||
status: number
|
||||
): 'primary' | 'success' | 'info' | 'warning' | 'danger' => {
|
||||
const statusItem = Object.values(IoTDeviceEnableStatusEnum).find((item) => item.value === status)
|
||||
return statusItem?.tagType || 'info'
|
||||
}
|
||||
|
||||
/** 获取设备激活状态文本和标签类型 */
|
||||
// TODO @puhui999:这个是不是可以直接在界面里处理;或者也可以在想想,= = 主要设备状态有 3 个枚举,嘿嘿~
|
||||
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' }, // 在时间之前
|
||||
|
@ -555,17 +433,6 @@ export const getTriggerTypeLabel = (type: number): string => {
|
|||
return option?.label || '未知类型'
|
||||
}
|
||||
|
||||
// TODO @puhui999:这种跟界面相关的,可以拿到对应组件里;
|
||||
/** 获取触发器标签类型(用于 el-tag 的 type 属性) */
|
||||
export const getTriggerTagType = (
|
||||
type: number
|
||||
): 'primary' | 'success' | 'info' | 'warning' | 'danger' => {
|
||||
if (type === IotRuleSceneTriggerTypeEnum.TIMER) {
|
||||
return 'warning'
|
||||
}
|
||||
return isDeviceTrigger(type) ? 'success' : 'info'
|
||||
}
|
||||
|
||||
// ========== JSON 参数输入组件相关常量 ==========
|
||||
|
||||
/** JSON 参数输入组件类型枚举 */
|
||||
|
|
Loading…
Reference in New Issue