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

pull/805/MERGE
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数据类型定义 ========== // ========== IoT物模型TSL数据类型定义 ==========
// TODO @puhui999看看有些是不是在别的模块已经定义了。物模型的
/** 物模型TSL响应数据结构 */ /** 物模型TSL响应数据结构 */
export interface IotThingModelTSLRespVO { export interface IotThingModelTSLRespVO {
productId: number productId: number
@ -294,6 +296,8 @@ interface FormValidationRules {
[key: string]: ValidationRule[] [key: string]: ValidationRule[]
} }
// TODO @puhui999这个文件目标最终没有哈和别的模块一致
export { export {
IotRuleScene, IotRuleScene,
IotRuleSceneDO, IotRuleSceneDO,

View File

@ -1,5 +1,4 @@
<template> <template>
<!-- 场景联动规则表单抽屉 - 优化高度和布局 -->
<el-drawer <el-drawer
v-model="drawerVisible" v-model="drawerVisible"
:title="drawerTitle" :title="drawerTitle"
@ -12,10 +11,8 @@
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="110px"> <el-form ref="formRef" :model="formData" :rules="formRules" label-width="110px">
<!-- 基础信息配置 --> <!-- 基础信息配置 -->
<BasicInfoSection v-model="formData" :rules="formRules" /> <BasicInfoSection v-model="formData" :rules="formRules" />
<!-- 触发器配置 --> <!-- 触发器配置 -->
<TriggerSection v-model:triggers="formData.triggers" @validate="handleTriggerValidate" /> <TriggerSection v-model:triggers="formData.triggers" @validate="handleTriggerValidate" />
<!-- 执行器配置 --> <!-- 执行器配置 -->
<ActionSection v-model:actions="formData.actions" @validate="handleActionValidate" /> <ActionSection v-model:actions="formData.actions" @validate="handleActionValidate" />
</el-form> </el-form>
@ -45,6 +42,7 @@ import { ElMessage } from 'element-plus'
import { generateUUID } from '@/utils' import { generateUUID } from '@/utils'
// CommonStatusEnum // CommonStatusEnum
// TODO @puhui999
const CommonStatusEnum = { const CommonStatusEnum = {
ENABLE: 0, // ENABLE: 0, //
DISABLE: 1 // DISABLE: 1 //
@ -120,6 +118,7 @@ const convertFormToVO = (formData: RuleSceneFormData): IotRuleSceneDO => {
} }
} }
// TODO @puhui999
/** /**
* 将后端 DO 数据转换为表单格式 * 将后端 DO 数据转换为表单格式
* 由于数据结构已对齐转换变得非常简单 * 由于数据结构已对齐转换变得非常简单
@ -209,6 +208,7 @@ const actionValidation = ref({ valid: true, message: '' })
const isEdit = ref(false) const isEdit = ref(false)
const drawerTitle = computed(() => (isEdit.value ? '编辑场景联动规则' : '新增场景联动规则')) const drawerTitle = computed(() => (isEdit.value ? '编辑场景联动规则' : '新增场景联动规则'))
// TODO @puhui999
// //
const handleTriggerValidate = (result: { valid: boolean; message: string }) => { const handleTriggerValidate = (result: { valid: boolean; message: string }) => {
triggerValidation.value = result triggerValidation.value = result
@ -218,6 +218,7 @@ const handleActionValidate = (result: { valid: boolean; message: string }) => {
actionValidation.value = result actionValidation.value = result
} }
// TODO @puhui999API
const handleSubmit = async () => { const handleSubmit = async () => {
// //
if (!formRef.value) return if (!formRef.value) return

View File

@ -52,6 +52,7 @@
<!-- 属性/事件/服务选择 --> <!-- 属性/事件/服务选择 -->
<el-col :span="6"> <el-col :span="6">
<el-form-item label="监控项" required> <el-form-item label="监控项" required>
<!-- TODO @puhui999是不是不展示整数小数这个类型一行只展示属性名 + 标识更简洁一点然后标识是 tag因为已经有个 tip -->
<PropertySelector <PropertySelector
:model-value="condition.identifier" :model-value="condition.identifier"
@update:model-value="(value) => updateConditionField('identifier', value)" @update:model-value="(value) => updateConditionField('identifier', value)"
@ -76,6 +77,7 @@
</el-col> </el-col>
<!-- 值输入 --> <!-- 值输入 -->
<!-- TODO @puhui999框子大小占满哈 -->
<el-col :span="12"> <el-col :span="12">
<el-form-item label="比较值" required> <el-form-item label="比较值" required>
<ValueInput <ValueInput

View File

@ -13,8 +13,8 @@
</div> </div>
<span>附加条件组</span> <span>附加条件组</span>
</div> </div>
<el-tag size="small" type="success">主条件为且关系</el-tag> <el-tag size="small" type="success">主条件为且关系</el-tag>
<el-tag size="small" type="info"> {{ modelValue?.length || 0 }}个子条件组 </el-tag> <el-tag size="small" type="info"> {{ modelValue?.length || 0 }} 个子条件组 </el-tag>
</div> </div>
<div class="flex items-center gap-8px"> <div class="flex items-center gap-8px">
<el-button <el-button
@ -140,9 +140,10 @@ const emit = defineEmits<{
const container = useVModel(props, 'modelValue', emit) const container = useVModel(props, 'modelValue', emit)
// TODO @puhui999
// //
const maxSubGroups = 3 // 3 const maxSubGroups = 3 // 3
const maxConditionsPerGroup = 3 // 3 const maxConditionsPerGroup = 3 // 3
// //
const subGroupValidations = ref<{ [key: number]: { valid: boolean; message: string } }>({}) const subGroupValidations = ref<{ [key: number]: { valid: boolean; message: string } }>({})

View File

@ -43,9 +43,9 @@
> >
<div class="flex items-center justify-between w-full"> <div class="flex items-center justify-between w-full">
<span>{{ option.label }}</span> <span>{{ option.label }}</span>
<span class="text-12px text-[var(--el-text-color-secondary)]">{{ <span class="text-12px text-[var(--el-text-color-secondary)]">
option.description {{ option.description }}
}}</span> </span>
</div> </div>
</el-option> </el-option>
</el-select> </el-select>
@ -101,6 +101,7 @@ const emit = defineEmits<{
const condition = useVModel(props, 'modelValue', emit) const condition = useVModel(props, 'modelValue', emit)
// //
// TODO @puhui999
const deviceStatusOptions = [ const deviceStatusOptions = [
{ {
value: 'online', value: 'online',
@ -121,6 +122,7 @@ const deviceStatusOptions = [
] ]
// //
// TODO @puhui999valuelabel
const statusOperatorOptions = [ const statusOperatorOptions = [
{ {
value: '=', value: '=',

View File

@ -20,6 +20,7 @@
</div> </div>
<!-- 主条件配置 --> <!-- 主条件配置 -->
<!-- TODO @puhui999主条件是不是和附加条件组弄成一个风格都是占一行有个绿条 -->
<div v-else class="space-y-16px"> <div v-else class="space-y-16px">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="flex items-center gap-8px"> <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 = () => { const updateValidationResult = () => {
if (isDevicePropertyTrigger.value) { if (isDevicePropertyTrigger.value) {
// //

View File

@ -16,6 +16,7 @@
<div class="p-16px space-y-24px"> <div class="p-16px space-y-24px">
<!-- 触发器列表 --> <!-- 触发器列表 -->
<!-- TODO 每个触发器有个外框会不会好点 -->
<div v-if="triggers.length > 0" class="space-y-24px"> <div v-if="triggers.length > 0" class="space-y-24px">
<div <div
v-for="(triggerItem, index) in triggers" 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 items-center justify-between w-full py-4px">
<div class="flex-1"> <div class="flex-1">
<div class="text-14px font-500 text-[var(--el-text-color-primary)] mb-2px" <div class="text-14px font-500 text-[var(--el-text-color-primary)] mb-2px">
>{{ product.name }} {{ product.name }}
</div> </div>
<div class="text-12px text-[var(--el-text-color-secondary)]" <div class="text-12px text-[var(--el-text-color-secondary)]">
>{{ product.productKey }} {{ product.productKey }}
</div> </div>
</div> </div>
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="product.status" /> <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 items-center justify-between w-full py-4px">
<div class="flex-1"> <div class="flex-1">
<div class="text-14px font-500 text-[var(--el-text-color-primary)] mb-2px" <div class="text-14px font-500 text-[var(--el-text-color-primary)] mb-2px">
>{{ device.deviceName }} {{ device.deviceName }}
</div> </div>
<div class="text-12px text-[var(--el-text-color-secondary)]" <div class="text-12px text-[var(--el-text-color-secondary)]">
>{{ device.nickname || '无备注' }} {{ device.nickname || '无备注' }}
</div> </div>
</div> </div>
<el-tag size="small" :type="getDeviceStatusTag(device.state)"> <el-tag size="small" :type="getDeviceStatusTag(device.state)">
@ -100,9 +100,9 @@
<div class="flex flex-col gap-6px ml-22px"> <div class="flex flex-col gap-6px ml-22px">
<div class="flex items-center gap-8px"> <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-secondary)] min-w-40px">产品</span>
<span class="text-12px text-[var(--el-text-color-primary)] font-500">{{ <span class="text-12px text-[var(--el-text-color-primary)] font-500">
selectedProduct?.name {{ selectedProduct?.name }}
}}</span> </span>
<el-tag size="small" type="primary">{{ selectedProduct?.productKey }}</el-tag> <el-tag size="small" type="primary">{{ selectedProduct?.productKey }}</el-tag>
</div> </div>
<div class="flex items-center gap-8px"> <div class="flex items-center gap-8px">
@ -112,9 +112,9 @@
class="text-12px text-[var(--el-text-color-primary)] font-500" class="text-12px text-[var(--el-text-color-primary)] font-500"
>全部设备</span >全部设备</span
> >
<span v-else class="text-12px text-[var(--el-text-color-primary)] font-500">{{ <span v-else class="text-12px text-[var(--el-text-color-primary)] font-500">
selectedDevice?.deviceName {{ selectedDevice?.deviceName }}
}}</span> </span>
<el-tag v-if="deviceSelectionMode === 'all'" size="small" type="warning"> </el-tag> <el-tag v-if="deviceSelectionMode === 'all'" size="small" type="warning"> </el-tag>
<el-tag v-else size="small" :type="getDeviceStatusTag(selectedDevice?.state)"> <el-tag v-else size="small" :type="getDeviceStatusTag(selectedDevice?.state)">
{{ getDeviceStatusText(selectedDevice?.state) }} {{ getDeviceStatusText(selectedDevice?.state) }}
@ -141,9 +141,7 @@ interface Props {
interface Emits { interface Emits {
(e: 'update:productId', value?: number): void (e: 'update:productId', value?: number): void
(e: 'update:deviceId', value?: number): void (e: 'update:deviceId', value?: number): void
(e: 'change', value: { productId?: number; deviceId?: 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) => { const handleProductChange = async (productId?: number) => {
localProductId.value = productId localProductId.value = productId
localDeviceId.value = undefined localDeviceId.value = undefined
deviceList.value = [] deviceList.value = []
if (productId) { if (productId) {
await getDeviceList(productId) await getDeviceList(productId)
} }
emitChange() emitChange()
} }
@ -220,7 +217,6 @@ const handleDeviceChange = (deviceId?: number) => {
const handleDeviceSelectionModeChange = (mode: 'specific' | 'all') => { const handleDeviceSelectionModeChange = (mode: 'specific' | 'all') => {
deviceSelectionMode.value = mode deviceSelectionMode.value = mode
if (mode === 'all') { if (mode === 'all') {
// ID 0 // ID 0
localDeviceId.value = 0 localDeviceId.value = 0
@ -228,7 +224,6 @@ const handleDeviceSelectionModeChange = (mode: 'specific' | 'all') => {
// ID // ID
localDeviceId.value = undefined localDeviceId.value = undefined
} }
emitChange() emitChange()
} }