perf:【IoT 物联网】场景联动触发器优化
parent
081603788a
commit
a5d458b96d
|
|
@ -190,22 +190,20 @@ const handleValidate = (result: { valid: boolean; message: string }) => {
|
|||
emit('validate', result)
|
||||
}
|
||||
|
||||
const handleProductChange = (productId: number) => {
|
||||
const handleProductChange = (_: number) => {
|
||||
// 产品变化时清空设备和属性
|
||||
condition.value.productId = productId
|
||||
condition.value.deviceId = undefined
|
||||
condition.value.identifier = ''
|
||||
updateValidationResult()
|
||||
}
|
||||
|
||||
const handleDeviceChange = (deviceId: number) => {
|
||||
const handleDeviceChange = (_: number) => {
|
||||
// 设备变化时清空属性
|
||||
condition.value.deviceId = deviceId
|
||||
condition.value.identifier = ''
|
||||
updateValidationResult()
|
||||
}
|
||||
|
||||
const handlePropertyChange = (propertyInfo: { type: string; config: any }) => {
|
||||
debugger
|
||||
console.log(propertyInfo)
|
||||
propertyType.value = propertyInfo.type
|
||||
propertyConfig.value = propertyInfo.config
|
||||
|
||||
|
|
|
|||
|
|
@ -1,253 +0,0 @@
|
|||
<!-- 条件组配置组件 -->
|
||||
<template>
|
||||
<div class="p-16px">
|
||||
<!-- 条件组说明 -->
|
||||
<div
|
||||
v-if="group.conditions && group.conditions.length > 1"
|
||||
class="mb-12px flex items-center justify-center"
|
||||
>
|
||||
<div
|
||||
class="flex items-center gap-6px px-10px py-4px bg-green-50 border border-green-200 rounded-full text-11px text-green-600"
|
||||
>
|
||||
<Icon icon="ep:info-filled" />
|
||||
<span>组内所有条件必须同时满足(且关系)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-12px">
|
||||
<!-- 条件列表 -->
|
||||
<div v-if="group.conditions && group.conditions.length > 0" class="space-y-12px">
|
||||
<div
|
||||
v-for="(condition, index) in group.conditions"
|
||||
:key="`condition-${index}`"
|
||||
class="p-12px border border-[var(--el-border-color-lighter)] rounded-6px bg-[var(--el-fill-color-light)] shadow-sm hover:shadow-md transition-shadow"
|
||||
>
|
||||
<div class="flex items-center justify-between mb-12px">
|
||||
<div class="flex items-center gap-8px">
|
||||
<div class="flex items-center gap-6px">
|
||||
<div
|
||||
class="w-18px h-18px bg-green-500 text-white rounded-full flex items-center justify-center text-10px font-bold"
|
||||
>
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">条件</span>
|
||||
</div>
|
||||
<el-tag size="small" type="primary">
|
||||
{{ getConditionTypeName(condition.type) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
text
|
||||
@click="removeCondition(index)"
|
||||
v-if="group.conditions!.length > 1"
|
||||
>
|
||||
<Icon icon="ep:delete" />
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div class="p-12px bg-[var(--el-fill-color-blank)] rounded-4px">
|
||||
<ConditionConfig
|
||||
:model-value="condition"
|
||||
@update:model-value="(value) => updateCondition(index, value)"
|
||||
:trigger-type="triggerType"
|
||||
:product-id="productId"
|
||||
:device-id="deviceId"
|
||||
@validate="(result) => handleConditionValidate(index, result)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 条件间的"且"连接符 -->
|
||||
<div
|
||||
v-if="index < group.conditions!.length - 1"
|
||||
class="flex items-center justify-center py-8px"
|
||||
>
|
||||
<div class="flex items-center gap-6px">
|
||||
<!-- 连接线 -->
|
||||
<div class="w-24px h-1px bg-green-300"></div>
|
||||
<!-- 且标签 -->
|
||||
<div class="px-12px py-4px bg-green-100 border-2 border-green-300 rounded-full">
|
||||
<span class="text-12px font-600 text-green-600">且</span>
|
||||
</div>
|
||||
<!-- 连接线 -->
|
||||
<div class="w-24px h-1px bg-green-300"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<div v-else class="py-40px text-center">
|
||||
<el-empty description="暂无条件配置" :image-size="80">
|
||||
<template #description>
|
||||
<div class="space-y-8px">
|
||||
<p class="text-[var(--el-text-color-secondary)]">暂无条件配置</p>
|
||||
<p class="text-12px text-[var(--el-text-color-placeholder)]">
|
||||
条件组需要至少包含一个条件才能生效
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</el-empty>
|
||||
</div>
|
||||
|
||||
<!-- 添加条件按钮 -->
|
||||
<div
|
||||
v-if="
|
||||
group.conditions && group.conditions.length > 0 && group.conditions.length < maxConditions
|
||||
"
|
||||
class="text-center py-16px"
|
||||
>
|
||||
<el-button type="primary" plain @click="addCondition">
|
||||
<Icon icon="ep:plus" />
|
||||
继续添加条件
|
||||
</el-button>
|
||||
<span class="block mt-8px text-12px text-[var(--el-text-color-secondary)]">
|
||||
最多可添加 {{ maxConditions }} 个条件
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import ConditionConfig from './ConditionConfig.vue'
|
||||
import { ConditionFormData, ConditionGroupFormData } from '@/api/iot/rule/scene/scene.types'
|
||||
import { IotRuleSceneTriggerTypeEnum } from '@/views/iot/utils/constants'
|
||||
|
||||
/** 条件组配置组件 */
|
||||
defineOptions({ name: 'ConditionGroupConfig' })
|
||||
|
||||
interface Props {
|
||||
modelValue: ConditionGroupFormData
|
||||
triggerType: number
|
||||
productId?: number
|
||||
deviceId?: number
|
||||
maxConditions?: number
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:modelValue', value: ConditionGroupFormData): void
|
||||
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
|
||||
const group = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// 配置常量
|
||||
const maxConditions = computed(() => props.maxConditions || 3)
|
||||
|
||||
// 验证状态
|
||||
const conditionValidations = ref<{ [key: number]: { valid: boolean; message: string } }>({})
|
||||
const validationMessage = ref('')
|
||||
const isValid = ref(true)
|
||||
|
||||
// 条件类型映射
|
||||
const conditionTypeNames = {
|
||||
[IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST]: '属性条件',
|
||||
[IotRuleSceneTriggerTypeEnum.DEVICE_EVENT_POST]: '事件条件',
|
||||
[IotRuleSceneTriggerTypeEnum.DEVICE_SERVICE_INVOKE]: '服务条件'
|
||||
}
|
||||
|
||||
// 工具函数
|
||||
const getConditionTypeName = (type: number) => {
|
||||
return conditionTypeNames[type] || '未知条件'
|
||||
}
|
||||
|
||||
// 事件处理
|
||||
const updateCondition = (index: number, condition: ConditionFormData) => {
|
||||
if (group.value.conditions) {
|
||||
group.value.conditions[index] = condition
|
||||
}
|
||||
}
|
||||
|
||||
const addCondition = () => {
|
||||
if (!group.value.conditions) {
|
||||
group.value.conditions = []
|
||||
}
|
||||
|
||||
if (group.value.conditions.length >= maxConditions.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const newCondition: ConditionFormData = {
|
||||
type: 2, // 默认为设备属性条件
|
||||
productId: props.productId || 0,
|
||||
deviceId: props.deviceId || 0,
|
||||
identifier: '',
|
||||
operator: '=',
|
||||
param: ''
|
||||
}
|
||||
|
||||
group.value.conditions.push(newCondition)
|
||||
}
|
||||
|
||||
const removeCondition = (index: number) => {
|
||||
if (group.value.conditions) {
|
||||
group.value.conditions.splice(index, 1)
|
||||
delete conditionValidations.value[index]
|
||||
|
||||
// 重新索引验证结果
|
||||
const newValidations: { [key: number]: { valid: boolean; message: string } } = {}
|
||||
Object.keys(conditionValidations.value).forEach((key) => {
|
||||
const numKey = parseInt(key)
|
||||
if (numKey > index) {
|
||||
newValidations[numKey - 1] = conditionValidations.value[numKey]
|
||||
} else if (numKey < index) {
|
||||
newValidations[numKey] = conditionValidations.value[numKey]
|
||||
}
|
||||
})
|
||||
conditionValidations.value = newValidations
|
||||
|
||||
updateValidationResult()
|
||||
}
|
||||
}
|
||||
|
||||
const handleConditionValidate = (index: number, result: { valid: boolean; message: string }) => {
|
||||
conditionValidations.value[index] = result
|
||||
updateValidationResult()
|
||||
}
|
||||
|
||||
const updateValidationResult = () => {
|
||||
if (!group.value.conditions || group.value.conditions.length === 0) {
|
||||
isValid.value = false
|
||||
validationMessage.value = '请至少添加一个条件'
|
||||
emit('validate', { valid: false, message: validationMessage.value })
|
||||
return
|
||||
}
|
||||
|
||||
const validations = Object.values(conditionValidations.value)
|
||||
const allValid = validations.every((v) => v.valid)
|
||||
|
||||
if (allValid) {
|
||||
isValid.value = true
|
||||
validationMessage.value = '条件组配置验证通过'
|
||||
} else {
|
||||
isValid.value = false
|
||||
const errorMessages = validations.filter((v) => !v.valid).map((v) => v.message)
|
||||
validationMessage.value = `条件配置错误: ${errorMessages.join('; ')}`
|
||||
}
|
||||
|
||||
emit('validate', { valid: isValid.value, message: validationMessage.value })
|
||||
}
|
||||
|
||||
// 监听条件数量变化
|
||||
watch(
|
||||
() => group.value.conditions?.length,
|
||||
() => {
|
||||
updateValidationResult()
|
||||
}
|
||||
)
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
if (!group.value.conditions || group.value.conditions.length === 0) {
|
||||
addCondition()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
@ -137,6 +137,7 @@ const props = defineProps<{
|
|||
modelValue: ConditionGroupContainerFormData
|
||||
triggerType: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: ConditionGroupContainerFormData): void
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
|
|
|
|||
|
|
@ -102,18 +102,14 @@ import {
|
|||
/** 当前时间条件配置组件 */
|
||||
defineOptions({ name: 'CurrentTimeConditionConfig' })
|
||||
|
||||
interface Props {
|
||||
const props = defineProps<{
|
||||
modelValue: ConditionFormData
|
||||
}
|
||||
}>()
|
||||
|
||||
interface Emits {
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: ConditionFormData): void
|
||||
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
const condition = useVModel(props, 'modelValue', emit)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,13 @@
|
|||
<template #default>
|
||||
<div class="space-y-8px">
|
||||
<p class="m-0 text-14px text-[var(--el-text-color-primary)]">属性设置示例:</p>
|
||||
<pre class="m-0 p-8px bg-[var(--el-fill-color-light)] rounded-4px text-12px text-[var(--el-text-color-regular)] overflow-x-auto"><code>{ "temperature": 25, "power": true }</code></pre>
|
||||
<pre
|
||||
class="m-0 p-8px bg-[var(--el-fill-color-light)] rounded-4px text-12px text-[var(--el-text-color-regular)] overflow-x-auto"
|
||||
><code>{ "temperature": 25, "power": true }</code></pre>
|
||||
<p class="m-0 text-14px text-[var(--el-text-color-primary)]">服务调用示例:</p>
|
||||
<pre class="m-0 p-8px bg-[var(--el-fill-color-light)] rounded-4px text-12px text-[var(--el-text-color-regular)] overflow-x-auto"><code>{ "method": "restart", "params": { "delay": 5 } }</code></pre>
|
||||
<pre
|
||||
class="m-0 p-8px bg-[var(--el-fill-color-light)] rounded-4px text-12px text-[var(--el-text-color-regular)] overflow-x-auto"
|
||||
><code>{ "method": "restart", "params": { "delay": 5 } }</code></pre>
|
||||
</div>
|
||||
</template>
|
||||
</el-alert>
|
||||
|
|
@ -56,17 +60,14 @@ import { ActionFormData } from '@/api/iot/rule/scene/scene.types'
|
|||
/** 设备控制配置组件 */
|
||||
defineOptions({ name: 'DeviceControlConfig' })
|
||||
|
||||
interface Props {
|
||||
const props = defineProps<{
|
||||
modelValue: ActionFormData
|
||||
}
|
||||
}>()
|
||||
|
||||
interface Emits {
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: ActionFormData): void
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
const action = useVModel(props, 'modelValue', emit)
|
||||
|
||||
|
|
|
|||
|
|
@ -26,31 +26,6 @@
|
|||
|
||||
<!-- 状态和操作符选择 -->
|
||||
<el-row :gutter="16">
|
||||
<!-- 状态选择 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="设备状态" required>
|
||||
<el-select
|
||||
:model-value="condition.param"
|
||||
@update:model-value="(value) => updateConditionField('param', value)"
|
||||
placeholder="请选择设备状态"
|
||||
class="w-full"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in deviceStatusOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
>
|
||||
<div class="flex items-center gap-8px">
|
||||
<Icon :icon="option.icon" :class="option.iconClass" />
|
||||
<span>{{ option.label }}</span>
|
||||
<el-tag :type="option.tag" size="small">{{ option.description }}</el-tag>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 操作符选择 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作符" required>
|
||||
|
|
@ -76,35 +51,32 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 状态选择 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="设备状态" required>
|
||||
<el-select
|
||||
:model-value="condition.param"
|
||||
@update:model-value="(value) => updateConditionField('param', value)"
|
||||
placeholder="请选择设备状态"
|
||||
class="w-full"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in deviceStatusOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
>
|
||||
<div class="flex items-center gap-8px">
|
||||
<Icon :icon="option.icon" :class="option.iconClass" />
|
||||
<span>{{ option.label }}</span>
|
||||
<el-tag :type="option.tag" size="small">{{ option.description }}</el-tag>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 条件预览 -->
|
||||
<!-- TODO puhui999:可以去掉。。。因为表单选择了,可以看懂的呀。 -->
|
||||
<div
|
||||
v-if="conditionPreview"
|
||||
class="p-12px bg-[var(--el-fill-color-light)] rounded-6px border border-[var(--el-border-color-lighter)]"
|
||||
>
|
||||
<div class="flex items-center gap-8px mb-8px">
|
||||
<Icon icon="ep:view" class="text-[var(--el-color-info)] text-16px" />
|
||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">条件预览</span>
|
||||
</div>
|
||||
<div class="pl-24px">
|
||||
<code
|
||||
class="text-12px text-[var(--el-color-primary)] bg-[var(--el-fill-color-blank)] p-8px rounded-4px font-mono"
|
||||
>{{ conditionPreview }}</code
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 验证结果 -->
|
||||
<div v-if="validationMessage" class="mt-8px">
|
||||
<el-alert
|
||||
:title="validationMessage"
|
||||
:type="isValid ? 'success' : 'error'"
|
||||
:closable="false"
|
||||
show-icon
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -117,17 +89,14 @@ import { ConditionFormData } from '@/api/iot/rule/scene/scene.types'
|
|||
/** 设备状态条件配置组件 */
|
||||
defineOptions({ name: 'DeviceStatusConditionConfig' })
|
||||
|
||||
interface Props {
|
||||
const props = defineProps<{
|
||||
modelValue: ConditionFormData
|
||||
}
|
||||
}>()
|
||||
|
||||
interface Emits {
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: ConditionFormData): void
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
const condition = useVModel(props, 'modelValue', emit)
|
||||
|
||||
|
|
@ -169,22 +138,6 @@ const statusOperatorOptions = [
|
|||
const validationMessage = ref('')
|
||||
const isValid = ref(true)
|
||||
|
||||
// 计算属性
|
||||
const conditionPreview = computed(() => {
|
||||
if (!condition.value.param || !condition.value.operator) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const statusLabel =
|
||||
deviceStatusOptions.find((opt) => opt.value === condition.value.param)?.label ||
|
||||
condition.value.param
|
||||
const operatorLabel =
|
||||
statusOperatorOptions.find((opt) => opt.value === condition.value.operator)?.label ||
|
||||
condition.value.operator
|
||||
|
||||
return `设备状态 ${operatorLabel} ${statusLabel}`
|
||||
})
|
||||
|
||||
// 事件处理
|
||||
const updateConditionField = (field: keyof ConditionFormData, value: any) => {
|
||||
condition.value[field] = value
|
||||
|
|
|
|||
|
|
@ -68,14 +68,13 @@ import { IotRuleSceneTriggerTypeEnum as TriggerTypeEnum } from '@/views/iot/util
|
|||
/** 设备触发配置组件 */
|
||||
defineOptions({ name: 'DeviceTriggerConfig' })
|
||||
|
||||
// Props 和 Emits 定义
|
||||
const props = defineProps<{
|
||||
modelValue: TriggerFormData
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: TriggerFormData]
|
||||
validate: [result: { valid: boolean; message: string }]
|
||||
(e: 'update:modelValue', value: TriggerFormData): void
|
||||
(e: 'validate', value: { valid: boolean; message: string }): void
|
||||
}>()
|
||||
|
||||
const trigger = useVModel(props, 'modelValue', emit)
|
||||
|
|
@ -126,7 +125,6 @@ const addConditionGroup = () => {
|
|||
}
|
||||
|
||||
// 事件处理
|
||||
|
||||
const handleConditionGroupValidate = () => {
|
||||
updateValidationResult()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ defineProps<{
|
|||
modelValue?: ConditionFormData
|
||||
triggerType: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value?: ConditionFormData): void
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
|
|
|
|||
|
|
@ -104,19 +104,15 @@ import { useVModel } from '@vueuse/core'
|
|||
/** 主条件内部配置组件 */
|
||||
defineOptions({ name: 'MainConditionInnerConfig' })
|
||||
|
||||
interface Props {
|
||||
const props = defineProps<{
|
||||
modelValue: ConditionFormData
|
||||
triggerType: number
|
||||
}
|
||||
}>()
|
||||
|
||||
interface Emits {
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: ConditionFormData): void
|
||||
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
// 响应式数据
|
||||
const condition = useVModel(props, 'modelValue', emit)
|
||||
|
|
|
|||
|
|
@ -98,20 +98,16 @@ import {
|
|||
/** 子条件组配置组件 */
|
||||
defineOptions({ name: 'SubConditionGroupConfig' })
|
||||
|
||||
interface Props {
|
||||
const props = defineProps<{
|
||||
modelValue: SubConditionGroupFormData
|
||||
triggerType: number
|
||||
maxConditions?: number
|
||||
}
|
||||
}>()
|
||||
|
||||
interface Emits {
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: SubConditionGroupFormData): void
|
||||
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
const subGroup = useVModel(props, 'modelValue', emit)
|
||||
|
||||
|
|
|
|||
|
|
@ -25,18 +25,13 @@ import { Crontab } from '@/components/Crontab'
|
|||
/** 定时触发配置组件 */
|
||||
defineOptions({ name: 'TimerTriggerConfig' })
|
||||
|
||||
// TODO @puhui999:下面的 Props、Emits 可以合并到变量那;
|
||||
interface Props {
|
||||
const props = defineProps<{
|
||||
modelValue?: string
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
}>()
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: string): void
|
||||
(e: 'validate', result: { valid: boolean; message: string }): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
const localValue = useVModel(props, 'modelValue', emit, {
|
||||
defaultValue: '0 0 12 * * ?'
|
||||
|
|
|
|||
|
|
@ -29,17 +29,14 @@ import { IotRuleSceneTriggerConditionTypeEnum } from '@/api/iot/rule/scene/scene
|
|||
/** 条件类型选择器组件 */
|
||||
defineOptions({ name: 'ConditionTypeSelector' })
|
||||
|
||||
interface Props {
|
||||
defineProps<{
|
||||
modelValue?: number
|
||||
}
|
||||
}>()
|
||||
|
||||
interface Emits {
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: number): void
|
||||
(e: 'change', value: number): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
// 条件类型选项
|
||||
const conditionTypeOptions = [
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@
|
|||
>
|
||||
<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-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">
|
||||
|
|
@ -42,18 +42,15 @@ import { DeviceApi } from '@/api/iot/device/device'
|
|||
/** 设备选择器组件 */
|
||||
defineOptions({ name: 'DeviceSelector' })
|
||||
|
||||
interface Props {
|
||||
const props = defineProps<{
|
||||
modelValue?: number
|
||||
productId?: number
|
||||
}
|
||||
}>()
|
||||
|
||||
interface Emits {
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value?: number): void
|
||||
(e: 'change', value?: number): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
// 状态
|
||||
const deviceLoading = ref(false)
|
||||
|
|
|
|||
|
|
@ -39,19 +39,15 @@ import { useVModel } from '@vueuse/core'
|
|||
/** 操作符选择器组件 */
|
||||
defineOptions({ name: 'OperatorSelector' })
|
||||
|
||||
interface Props {
|
||||
const props = defineProps<{
|
||||
modelValue?: string
|
||||
propertyType?: string
|
||||
}
|
||||
}>()
|
||||
|
||||
interface Emits {
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: string): void
|
||||
|
||||
(e: 'change', value: string): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
const localValue = useVModel(props, 'modelValue', emit)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,14 @@
|
|||
>
|
||||
<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 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>
|
||||
<!-- TODO @puhui999:是不是用字典 -->
|
||||
<el-tag size="small" :type="product.status === 0 ? 'success' : 'danger'">
|
||||
{{ product.status === 0 ? '正常' : '禁用' }}
|
||||
</el-tag>
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="product.status" />
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
|
@ -70,8 +71,12 @@
|
|||
>
|
||||
<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.nickname || '无备注' }}</div>
|
||||
<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.nickname || '无备注' }}
|
||||
</div>
|
||||
</div>
|
||||
<el-tag size="small" :type="getDeviceStatusTag(device.state)">
|
||||
{{ getDeviceStatusText(device.state) }}
|
||||
|
|
@ -84,7 +89,10 @@
|
|||
</el-row>
|
||||
|
||||
<!-- 选择结果展示 -->
|
||||
<div v-if="localProductId && localDeviceId !== undefined" class="mt-16px p-12px bg-[var(--el-fill-color-light)] rounded-6px border border-[var(--el-border-color-lighter)]">
|
||||
<div
|
||||
v-if="localProductId && localDeviceId !== undefined"
|
||||
class="mt-16px p-12px bg-[var(--el-fill-color-light)] rounded-6px border border-[var(--el-border-color-lighter)]"
|
||||
>
|
||||
<div class="flex items-center gap-6px mb-8px">
|
||||
<Icon icon="ep:check" class="text-[var(--el-color-success)] text-16px" />
|
||||
<span class="text-14px font-500 text-[var(--el-text-color-primary)]">已选择设备</span>
|
||||
|
|
@ -92,14 +100,22 @@
|
|||
<div class="flex flex-col gap-6px ml-22px">
|
||||
<div class="flex items-center gap-8px">
|
||||
<span class="text-12px text-[var(--el-text-color-secondary)] min-w-40px">产品:</span>
|
||||
<span class="text-12px text-[var(--el-text-color-primary)] font-500">{{ selectedProduct?.name }}</span>
|
||||
<span class="text-12px text-[var(--el-text-color-primary)] font-500">{{
|
||||
selectedProduct?.name
|
||||
}}</span>
|
||||
<el-tag size="small" type="primary">{{ selectedProduct?.productKey }}</el-tag>
|
||||
</div>
|
||||
<div class="flex items-center gap-8px">
|
||||
<span class="text-12px text-[var(--el-text-color-secondary)] min-w-40px">设备:</span>
|
||||
<span v-if="deviceSelectionMode === 'all'" class="text-12px text-[var(--el-text-color-primary)] font-500">全部设备</span>
|
||||
<span v-else class="text-12px text-[var(--el-text-color-primary)] font-500">{{ selectedDevice?.deviceName }}</span>
|
||||
<el-tag v-if="deviceSelectionMode === 'all'" size="small" type="warning"> 全部 </el-tag>
|
||||
<span
|
||||
v-if="deviceSelectionMode === 'all'"
|
||||
class="text-12px text-[var(--el-text-color-primary)] font-500"
|
||||
>全部设备</span
|
||||
>
|
||||
<span v-else class="text-12px text-[var(--el-text-color-primary)] font-500">{{
|
||||
selectedDevice?.deviceName
|
||||
}}</span>
|
||||
<el-tag v-if="deviceSelectionMode === 'all'" size="small" type="warning"> 全部</el-tag>
|
||||
<el-tag v-else size="small" :type="getDeviceStatusTag(selectedDevice?.state)">
|
||||
{{ getDeviceStatusText(selectedDevice?.state) }}
|
||||
</el-tag>
|
||||
|
|
@ -113,6 +129,7 @@
|
|||
import { useVModel } from '@vueuse/core'
|
||||
import { ProductApi } from '@/api/iot/product/product'
|
||||
import { DeviceApi } from '@/api/iot/device/device'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
|
||||
/** 产品设备选择器组件 */
|
||||
defineOptions({ name: 'ProductDeviceSelector' })
|
||||
|
|
@ -124,7 +141,9 @@ interface Props {
|
|||
|
||||
interface Emits {
|
||||
(e: 'update:productId', value?: number): void
|
||||
|
||||
(e: 'update:deviceId', value?: number): void
|
||||
|
||||
(e: 'change', value: { productId?: number; deviceId?: number }): void
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,16 +17,14 @@
|
|||
>
|
||||
<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 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>
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="product.status" />
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
|
@ -34,21 +32,19 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { ProductApi } from '@/api/iot/product/product'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
|
||||
/** 产品选择器组件 */
|
||||
defineOptions({ name: 'ProductSelector' })
|
||||
|
||||
interface Props {
|
||||
defineProps<{
|
||||
modelValue?: number
|
||||
}
|
||||
}>()
|
||||
|
||||
interface Emits {
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value?: number): void
|
||||
(e: 'change', value?: number): void
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
}>()
|
||||
|
||||
// 状态
|
||||
const productLoading = ref(false)
|
||||
|
|
|
|||
Loading…
Reference in New Issue