review:【iot 物联网】场景联动的 review
This commit is contained in:
@ -4,6 +4,8 @@
|
||||
|
||||
// ========== IoT物模型TSL数据类型定义 ==========
|
||||
|
||||
// TODO @puhui999:看看有些是不是在别的模块已经定义了。物模型的
|
||||
|
||||
/** 物模型TSL响应数据结构 */
|
||||
export interface IotThingModelTSLRespVO {
|
||||
productId: number
|
||||
@ -294,6 +296,8 @@ interface FormValidationRules {
|
||||
[key: string]: ValidationRule[]
|
||||
}
|
||||
|
||||
// TODO @puhui999:这个文件,目标最终没有哈,和别的模块一致;
|
||||
|
||||
export {
|
||||
IotRuleScene,
|
||||
IotRuleSceneDO,
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
<template>
|
||||
<!-- 场景联动规则表单抽屉 - 优化高度和布局 -->
|
||||
<el-drawer
|
||||
v-model="drawerVisible"
|
||||
:title="drawerTitle"
|
||||
@ -12,10 +11,8 @@
|
||||
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="110px">
|
||||
<!-- 基础信息配置 -->
|
||||
<BasicInfoSection v-model="formData" :rules="formRules" />
|
||||
|
||||
<!-- 触发器配置 -->
|
||||
<TriggerSection v-model:triggers="formData.triggers" @validate="handleTriggerValidate" />
|
||||
|
||||
<!-- 执行器配置 -->
|
||||
<ActionSection v-model:actions="formData.actions" @validate="handleActionValidate" />
|
||||
</el-form>
|
||||
@ -45,6 +42,7 @@ import { ElMessage } from 'element-plus'
|
||||
import { generateUUID } from '@/utils'
|
||||
|
||||
// 导入全局的 CommonStatusEnum
|
||||
// TODO @puhui999:这里直接复用全局的哈;
|
||||
const CommonStatusEnum = {
|
||||
ENABLE: 0, // 开启
|
||||
DISABLE: 1 // 关闭
|
||||
@ -120,6 +118,7 @@ const convertFormToVO = (formData: RuleSceneFormData): IotRuleSceneDO => {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO @puhui999:下面好像没用到?
|
||||
/**
|
||||
* 将后端 DO 数据转换为表单格式
|
||||
* 由于数据结构已对齐,转换变得非常简单
|
||||
@ -209,6 +208,7 @@ const actionValidation = ref({ valid: true, message: '' })
|
||||
const isEdit = ref(false)
|
||||
const drawerTitle = computed(() => (isEdit.value ? '编辑场景联动规则' : '新增场景联动规则'))
|
||||
|
||||
// TODO @puhui999:方法的注释风格统一;
|
||||
// 事件处理
|
||||
const handleTriggerValidate = (result: { valid: boolean; message: string }) => {
|
||||
triggerValidation.value = result
|
||||
@ -218,6 +218,7 @@ const handleActionValidate = (result: { valid: boolean; message: string }) => {
|
||||
actionValidation.value = result
|
||||
}
|
||||
|
||||
// TODO @puhui999:API 调用
|
||||
const handleSubmit = async () => {
|
||||
// 校验表单
|
||||
if (!formRef.value) return
|
||||
|
||||
@ -52,6 +52,7 @@
|
||||
<!-- 属性/事件/服务选择 -->
|
||||
<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)"
|
||||
@ -76,6 +77,7 @@
|
||||
</el-col>
|
||||
|
||||
<!-- 值输入 -->
|
||||
<!-- TODO @puhui999:框子大小占满哈。 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="比较值" required>
|
||||
<ValueInput
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
</div>
|
||||
<span>附加条件组</span>
|
||||
</div>
|
||||
<el-tag size="small" type="success">与主条件为且关系</el-tag>
|
||||
<el-tag size="small" type="info"> {{ modelValue?.length || 0 }}个子条件组 </el-tag>
|
||||
<el-tag size="small" type="success">与“主条件”为且关系</el-tag>
|
||||
<el-tag size="small" type="info"> {{ modelValue?.length || 0 }} 个子条件组 </el-tag>
|
||||
</div>
|
||||
<div class="flex items-center gap-8px">
|
||||
<el-button
|
||||
@ -140,9 +140,10 @@ const emit = defineEmits<{
|
||||
|
||||
const container = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// TODO @puhui999:这个限制去掉好了;
|
||||
// 配置常量
|
||||
const maxSubGroups = 3 // 最多3个子条件组
|
||||
const maxConditionsPerGroup = 3 // 每组最多3个条件
|
||||
const maxSubGroups = 3 // 最多 3 个子条件组
|
||||
const maxConditionsPerGroup = 3 // 每组最多 3 个条件
|
||||
|
||||
// 验证状态
|
||||
const subGroupValidations = ref<{ [key: number]: { valid: boolean; message: string } }>({})
|
||||
|
||||
@ -43,9 +43,9 @@
|
||||
>
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<span>{{ option.label }}</span>
|
||||
<span class="text-12px text-[var(--el-text-color-secondary)]">{{
|
||||
option.description
|
||||
}}</span>
|
||||
<span class="text-12px text-[var(--el-text-color-secondary)]">
|
||||
{{ option.description }}
|
||||
</span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
@ -101,6 +101,7 @@ const emit = defineEmits<{
|
||||
const condition = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// 设备状态选项
|
||||
// TODO @puhui999:这个要不直接字段,简洁一点;
|
||||
const deviceStatusOptions = [
|
||||
{
|
||||
value: 'online',
|
||||
@ -121,6 +122,7 @@ const deviceStatusOptions = [
|
||||
]
|
||||
|
||||
// 状态操作符选项
|
||||
// TODO @puhui999:value、label 看看能不能复用枚举值;
|
||||
const statusOperatorOptions = [
|
||||
{
|
||||
value: '=',
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 主条件配置 -->
|
||||
<!-- TODO @puhui999:和“主条件”,是不是和“附加条件组”弄成一个风格,都是占一行;有个绿条; -->
|
||||
<div v-else class="space-y-16px">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-8px">
|
||||
|
||||
@ -199,6 +199,7 @@ const handleValidate = (result: { valid: boolean; message: string }) => {
|
||||
}
|
||||
|
||||
// 验证逻辑
|
||||
// TODO @puhui999:这个校验,是不是用更原生的 validator 哈。项目风格更统一点。
|
||||
const updateValidationResult = () => {
|
||||
if (isDevicePropertyTrigger.value) {
|
||||
// 设备属性触发验证
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
<div class="p-16px space-y-24px">
|
||||
<!-- 触发器列表 -->
|
||||
<!-- TODO 每个触发器,有个外框,会不会好点? -->
|
||||
<div v-if="triggers.length > 0" class="space-y-24px">
|
||||
<div
|
||||
v-for="(triggerItem, index) in triggers"
|
||||
|
||||
@ -22,11 +22,11 @@
|
||||
>
|
||||
<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 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 class="text-12px text-[var(--el-text-color-secondary)]">
|
||||
{{ product.productKey }}
|
||||
</div>
|
||||
</div>
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="product.status" />
|
||||
@ -71,11 +71,11 @@
|
||||
>
|
||||
<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 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 class="text-12px text-[var(--el-text-color-secondary)]">
|
||||
{{ device.nickname || '无备注' }}
|
||||
</div>
|
||||
</div>
|
||||
<el-tag size="small" :type="getDeviceStatusTag(device.state)">
|
||||
@ -100,9 +100,9 @@
|
||||
<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">
|
||||
@ -112,9 +112,9 @@
|
||||
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>
|
||||
<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) }}
|
||||
@ -141,9 +141,7 @@ interface Props {
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:productId', value?: number): void
|
||||
|
||||
(e: 'update:deviceId', value?: number): void
|
||||
|
||||
(e: 'change', value: { productId?: number; deviceId?: number }): void
|
||||
}
|
||||
|
||||
@ -200,16 +198,15 @@ const getDeviceStatusTag = (state?: number) => {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO @puhui999:注释风格哈
|
||||
// 事件处理
|
||||
const handleProductChange = async (productId?: number) => {
|
||||
localProductId.value = productId
|
||||
localDeviceId.value = undefined
|
||||
deviceList.value = []
|
||||
|
||||
if (productId) {
|
||||
await getDeviceList(productId)
|
||||
}
|
||||
|
||||
emitChange()
|
||||
}
|
||||
|
||||
@ -220,7 +217,6 @@ const handleDeviceChange = (deviceId?: number) => {
|
||||
|
||||
const handleDeviceSelectionModeChange = (mode: 'specific' | 'all') => {
|
||||
deviceSelectionMode.value = mode
|
||||
|
||||
if (mode === 'all') {
|
||||
// 全部设备时,设备 ID 设为 0
|
||||
localDeviceId.value = 0
|
||||
@ -228,7 +224,6 @@ const handleDeviceSelectionModeChange = (mode: 'specific' | 'all') => {
|
||||
// 选择设备时,清空设备 ID
|
||||
localDeviceId.value = undefined
|
||||
}
|
||||
|
||||
emitChange()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user