review:【iot 物联网】场景联动的 review

This commit is contained in:
YunaiV
2025-08-02 11:38:45 +08:00
parent e188ea5de6
commit bb0920c4b9
9 changed files with 38 additions and 30 deletions

View File

@ -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,

View File

@ -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 @puhui999API 调用
const handleSubmit = async () => {
// 校验表单
if (!formRef.value) return

View File

@ -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

View File

@ -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 } }>({})

View File

@ -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 @puhui999value、label 看看能不能复用枚举值;
const statusOperatorOptions = [
{
value: '=',

View File

@ -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">

View File

@ -199,6 +199,7 @@ const handleValidate = (result: { valid: boolean; message: string }) => {
}
// 验证逻辑
// TODO @puhui999这个校验是不是用更原生的 validator 哈。项目风格更统一点。
const updateValidationResult = () => {
if (isDevicePropertyTrigger.value) {
// 设备属性触发验证

View File

@ -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"

View File

@ -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()
}