Просмотр исходного кода

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

YunaiV 1 год назад
Родитель
Сommit
5021c711a7

+ 1 - 1
src/api/iot/rule/scene/scene.types.ts

@@ -144,7 +144,7 @@ interface RuleSceneFormData {
   name: string
   description?: string
   status: number
-  trigger: TriggerFormData // 改为单个触发器
+  trigger: TriggerFormData
   actions: ActionFormData[]
 }
 

+ 12 - 9
src/views/iot/rule/scene/form/RuleSceneForm.vue

@@ -1,5 +1,5 @@
-<!-- IoT场景联动规则表单 - 主表单组件 -->
 <template>
+  <!-- TODO @puhui999:这个抽屉的高度太高了?! -->
   <el-drawer
     v-model="drawerVisible"
     :title="drawerTitle"
@@ -28,7 +28,6 @@
         <ActionSection v-model:actions="formData.actions" @validate="handleActionValidate" />
       </el-form>
     </div>
-
     <template #footer>
       <el-button :disabled="submitLoading" type="primary" @click="handleSubmit">确 定</el-button>
       <el-button @click="handleClose">取 消</el-button>
@@ -55,11 +54,13 @@ import { generateUUID } from '@/utils'
 /** IoT 场景联动规则表单 - 主表单组件 */
 defineOptions({ name: 'RuleSceneForm' })
 
+// TODO @puhui999:是不是融合到 props
 interface Props {
   modelValue: boolean
   ruleScene?: IotRuleScene
 }
 
+// TODO @puhui999:Emits 是不是融合到 emit
 interface Emits {
   (e: 'update:modelValue', value: boolean): void
   (e: 'success'): void
@@ -68,11 +69,11 @@ interface Emits {
 const props = defineProps<Props>()
 const emit = defineEmits<Emits>()
 
-const drawerVisible = useVModel(props, 'modelValue', emit)
+const drawerVisible = useVModel(props, 'modelValue', emit) // 是否可见
 
-/**
- * 创建默认的表单数据
- */
+// TODO @puhui999:使用 /** 注释风格哈 */
+
+/** 创建默认的表单数据 */
 const createDefaultFormData = (): RuleSceneFormData => {
   return {
     name: '',
@@ -93,8 +94,9 @@ const createDefaultFormData = (): RuleSceneFormData => {
   }
 }
 
+// TODO @puhui999:使用 convertFormToVO;下面也是类似哈;
 /**
- * 将表单数据转换为API请求格式
+ * 将表单数据转换为 API 请求格式
  */
 const transformFormToApi = (formData: RuleSceneFormData): IotRuleScene => {
   return {
@@ -196,7 +198,6 @@ const handleSubmit = async () => {
   if (!formRef.value) return
   const valid = await formRef.value.validate()
   if (!valid) return
-
   // 验证触发器和执行器
   if (!triggerValidation.value.valid) {
     ElMessage.error(triggerValidation.value.message)
@@ -214,6 +215,7 @@ const handleSubmit = async () => {
     const apiData = transformFormToApi(formData.value)
 
     // 这里应该调用API保存数据
+    // TODO @puhui999:貌似还没接入
     console.log('提交数据:', apiData)
 
     // 模拟API调用
@@ -250,7 +252,7 @@ watch(drawerVisible, (visible) => {
   }
 })
 
-// 监听props变化
+// 监听 props 变化
 watch(
   () => props.ruleScene,
   () => {
@@ -261,6 +263,7 @@ watch(
 )
 </script>
 
+<!-- TODO @puhui999:看看下面样式,哪些是必要添加的 -->
 <style scoped>
 /* 滚动条样式 */
 .h-\[calc\(100vh-120px\)\]::-webkit-scrollbar {

+ 1 - 0
src/views/iot/rule/scene/form/configs/ConditionConfig.vue

@@ -91,6 +91,7 @@
       </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)]"

+ 2 - 1
src/views/iot/rule/scene/form/configs/ConditionGroupContainerConfig.vue

@@ -1,7 +1,7 @@
-<!-- 条件组容器配置组件 -->
 <template>
   <div class="flex flex-col gap-16px">
     <!-- 条件组容器头部 -->
+    <!-- TODO @puhui999:这个是不是删除,不然有两个“附件条件组”的 header -->
     <div
       class="flex items-center justify-between p-16px bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200 rounded-8px"
     >
@@ -39,6 +39,7 @@
     <!-- 子条件组列表 -->
     <div v-if="modelValue.subGroups && modelValue.subGroups.length > 0" class="space-y-16px">
       <!-- 逻辑关系说明 -->
+      <!-- TODO @puhui999:这个可以去掉。。。提示有点太多了。 -->
       <div v-if="modelValue.subGroups.length > 1" class="flex items-center justify-center">
         <div
           class="flex items-center gap-8px px-12px py-6px bg-orange-50 border border-orange-200 rounded-full text-12px text-orange-600"

+ 22 - 10
src/views/iot/rule/scene/form/configs/CurrentTimeConditionConfig.vue

@@ -1,7 +1,9 @@
 <!-- 当前时间条件配置组件 -->
 <template>
   <div class="flex flex-col gap-16px">
-    <div class="flex items-center gap-8px p-12px px-16px bg-orange-50 rounded-6px border border-orange-200">
+    <div
+      class="flex items-center gap-8px p-12px px-16px bg-orange-50 rounded-6px border border-orange-200"
+    >
       <Icon icon="ep:timer" class="text-orange-500 text-18px" />
       <span class="text-14px font-500 text-orange-700">当前时间条件配置</span>
     </div>
@@ -89,13 +91,20 @@
     </el-row>
 
     <!-- 条件预览 -->
-    <div v-if="conditionPreview" class="p-12px bg-[var(--el-fill-color-light)] rounded-6px border border-[var(--el-border-color-lighter)]">
+    <!-- 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>
+        <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>
 
@@ -113,7 +122,10 @@
 
 <script setup lang="ts">
 import { useVModel } from '@vueuse/core'
-import { ConditionFormData, IotRuleSceneTriggerTimeOperatorEnum } from '@/api/iot/rule/scene/scene.types'
+import {
+  ConditionFormData,
+  IotRuleSceneTriggerTimeOperatorEnum
+} from '@/api/iot/rule/scene/scene.types'
 
 /** 当前时间条件配置组件 */
 defineOptions({ name: 'CurrentTimeConditionConfig' })
@@ -203,22 +215,22 @@ const conditionPreview = computed(() => {
   if (!condition.value.operator) {
     return ''
   }
-  
-  const operatorOption = timeOperatorOptions.find(opt => opt.value === condition.value.operator)
+
+  const operatorOption = timeOperatorOptions.find((opt) => opt.value === condition.value.operator)
   const operatorLabel = operatorOption?.label || condition.value.operator
-  
+
   if (condition.value.operator === IotRuleSceneTriggerTimeOperatorEnum.TODAY.value) {
     return `当前时间 ${operatorLabel}`
   }
-  
+
   if (!condition.value.timeValue) {
     return `当前时间 ${operatorLabel} [未设置时间]`
   }
-  
+
   if (needsSecondTimeInput.value && condition.value.timeValue2) {
     return `当前时间 ${operatorLabel} ${condition.value.timeValue} 和 ${condition.value.timeValue2}`
   }
-  
+
   return `当前时间 ${operatorLabel} ${condition.value.timeValue}`
 })
 

+ 1 - 0
src/views/iot/rule/scene/form/configs/DeviceStatusConditionConfig.vue

@@ -79,6 +79,7 @@
     </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)]"

+ 2 - 3
src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue

@@ -17,7 +17,7 @@
           <span class="text-14px font-500 text-[var(--el-text-color-primary)]">附加条件组</span>
           <el-tag size="small" type="success">与主条件为且关系</el-tag>
           <el-tag size="small" type="info">
-            {{ trigger.conditionGroup?.subGroups?.length || 0 }}个子条件组
+            {{ trigger.conditionGroup?.subGroups?.length || 0 }} 个子条件组
           </el-tag>
         </div>
         <el-button
@@ -70,6 +70,7 @@ import {
 /** 设备触发配置组件 */
 defineOptions({ name: 'DeviceTriggerConfig' })
 
+// TODO @puhui999:下面的 Props、Emits 可以合并到变量那;
 interface Props {
   modelValue: TriggerFormData
 }
@@ -92,8 +93,6 @@ const mainConditionValidation = ref<{ valid: boolean; message: string }>({
 const validationMessage = ref('')
 const isValid = ref(true)
 
-// 计算属性
-
 // 初始化主条件
 const initMainCondition = () => {
   if (!trigger.value.mainCondition) {

+ 1 - 0
src/views/iot/rule/scene/form/configs/MainConditionConfig.vue

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

+ 3 - 1
src/views/iot/rule/scene/form/configs/MainConditionInnerConfig.vue

@@ -1,4 +1,3 @@
-<!-- 主条件内部配置组件 - 不显示条件类型选择 -->
 <template>
   <div class="space-y-16px">
     <!-- 触发事件类型显示 -->
@@ -76,6 +75,7 @@
       </el-row>
 
       <!-- 条件预览 -->
+      <!-- TODO puhui999:可以去掉。。。因为表单选择了,可以看懂的呀。 -->
       <div v-if="conditionPreview" class="mt-12px">
         <div class="text-12px text-[var(--el-text-color-secondary)]">
           预览:{{ conditionPreview }}
@@ -133,6 +133,7 @@ const emit = defineEmits<Emits>()
 
 // 响应式数据
 const condition = useVModel(props, 'modelValue', emit)
+// TODO @puhui999:是不是 validationMessage 非空,就是不通过哈;
 const isValid = ref(true)
 const validationMessage = ref('')
 const propertyType = ref('')
@@ -159,6 +160,7 @@ const conditionPreview = computed(() => {
 })
 
 // 获取触发类型文本
+// TODO @puhui999:是不是有枚举可以服用哈;
 const getTriggerTypeText = (type: number) => {
   switch (type) {
     case IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST:

+ 1 - 1
src/views/iot/rule/scene/form/configs/SubConditionGroupConfig.vue

@@ -1,4 +1,3 @@
-<!-- 子条件组配置组件 -->
 <template>
   <div class="p-16px">
     <!-- 空状态 -->
@@ -66,6 +65,7 @@
         </div>
 
         <!-- 条件间的"且"连接符 -->
+        <!-- TODO @puhu999:建议去掉,有点元素太丰富了。 -->
         <div
           v-if="conditionIndex < subGroup.conditions!.length - 1"
           class="flex items-center justify-center py-8px"

+ 9 - 5
src/views/iot/rule/scene/form/configs/TimerTriggerConfig.vue

@@ -1,13 +1,16 @@
-<!-- 定时触发配置组件 -->
 <template>
   <div class="flex flex-col gap-16px">
-    <div class="flex items-center gap-8px p-12px px-16px bg-[var(--el-fill-color-light)] rounded-6px border border-[var(--el-border-color-lighter)]">
+    <div
+      class="flex items-center gap-8px p-12px px-16px bg-[var(--el-fill-color-light)] rounded-6px border border-[var(--el-border-color-lighter)]"
+    >
       <Icon icon="ep:timer" class="text-[var(--el-color-danger)] text-18px" />
       <span class="text-14px font-500 text-[var(--el-text-color-primary)]">定时触发配置</span>
     </div>
 
-    <!-- CRON表达式配置 -->
-    <div class="p-16px border border-[var(--el-border-color-lighter)] rounded-6px bg-[var(--el-fill-color-blank)]">
+    <!-- CRON 表达式配置 -->
+    <div
+      class="p-16px border border-[var(--el-border-color-lighter)] rounded-6px bg-[var(--el-fill-color-blank)]"
+    >
       <el-form-item label="CRON表达式" required>
         <Crontab v-model="localValue" />
       </el-form-item>
@@ -22,6 +25,7 @@ import { Crontab } from '@/components/Crontab'
 /** 定时触发配置组件 */
 defineOptions({ name: 'TimerTriggerConfig' })
 
+// TODO @puhui999:下面的 Props、Emits 可以合并到变量那;
 interface Props {
   modelValue?: string
 }
@@ -37,4 +41,4 @@ const emit = defineEmits<Emits>()
 const localValue = useVModel(props, 'modelValue', emit, {
   defaultValue: '0 0 12 * * ?'
 })
-</script>
+</script>

+ 3 - 0
src/views/iot/rule/scene/form/sections/BasicInfoSection.vue

@@ -8,6 +8,7 @@
           <span class="text-16px font-600 text-[var(--el-text-color-primary)]">基础信息</span>
         </div>
         <div class="flex items-center gap-8px">
+          <!-- TODO @puhui999:dict-tag 可以哇? -->
           <el-tag :type="formData.status === 0 ? 'success' : 'danger'" size="small">
             {{ formData.status === 0 ? '启用' : '禁用' }}
           </el-tag>
@@ -65,6 +66,8 @@ import { RuleSceneFormData } from '@/api/iot/rule/scene/scene.types'
 /** 基础信息配置组件 */
 defineOptions({ name: 'BasicInfoSection' })
 
+// TODO @puhui999:下面的 Props、Emits 可以合并到变量那;
+
 interface Props {
   modelValue: RuleSceneFormData
   rules?: any

+ 7 - 1
src/views/iot/rule/scene/form/sections/TriggerSection.vue

@@ -1,6 +1,6 @@
-<!-- 场景触发器配置组件 -->
 <template>
   <el-card class="border border-[var(--el-border-color-light)] rounded-8px" shadow="never">
+    <!-- TODO @puhui999:触发器还是多个。。。每个触发器里面有事件类型 + 附加条件组(最好文案上,和阿里 iot 保持相对一致) -->
     <template #header>
       <div class="flex items-center gap-8px">
         <Icon icon="ep:lightning" class="text-[var(--el-color-primary)] text-18px" />
@@ -36,6 +36,7 @@
       />
 
       <!-- 定时触发配置 -->
+      <!-- TODO @puhui999:这里要不 v-else 好了? -->
       <TimerTriggerConfig
         v-if="trigger.type === TriggerTypeEnum.TIMER"
         :model-value="trigger.cronExpression"
@@ -57,6 +58,7 @@ import {
 /** 触发器配置组件 */
 defineOptions({ name: 'TriggerSection' })
 
+// TODO @puhui999:下面的 Props、Emits 可以合并到变量那;
 interface Props {
   trigger: TriggerFormData
 }
@@ -71,6 +73,7 @@ const emit = defineEmits<Emits>()
 const trigger = useVModel(props, 'trigger', emit)
 
 // 触发器类型选项
+// TODO @puhui999:/Users/yunai/Java/yudao-ui-admin-vue3/src/views/iot/utils/constants.ts
 const triggerTypeOptions = [
   {
     value: TriggerTypeEnum.DEVICE_STATE_UPDATE,
@@ -95,6 +98,7 @@ const triggerTypeOptions = [
 ]
 
 // 工具函数
+// TODO @puhui999:/Users/yunai/Java/yudao-ui-admin-vue3/src/views/iot/utils/constants.ts
 const isDeviceTrigger = (type: number) => {
   const deviceTriggerTypes = [
     TriggerTypeEnum.DEVICE_STATE_UPDATE,
@@ -111,10 +115,12 @@ const updateTriggerType = (type: number) => {
   onTriggerTypeChange(type)
 }
 
+// TODO @puhui999:updateTriggerDeviceConfig
 const updateTrigger = (newTrigger: TriggerFormData) => {
   trigger.value = newTrigger
 }
 
+// TODO @puhui999:updateTriggerCronConfig
 const updateTriggerCronExpression = (cronExpression?: string) => {
   trigger.value.cronExpression = cronExpression
 }

+ 73 - 33
src/views/iot/rule/scene/index.vue

@@ -4,10 +4,12 @@
     <div class="flex justify-between items-start mb-20px">
       <div class="flex-1">
         <h2 class="flex items-center m-0 mb-8px text-24px font-600 text-[#303133]">
-          <Icon icon="ep:connection" class="mr-12px text-[#409eff]" />
+          <Icon icon="ep:connection" class="ml-5px mr-12px text-[#409eff]" />
           场景联动规则
         </h2>
-        <p class="m-0 text-[#606266] text-14px"> 通过配置触发条件和执行动作,实现设备间的智能联动控制 </p>
+        <p class="m-0 text-[#606266] text-14px">
+          通过配置触发条件和执行动作,实现设备间的智能联动控制
+        </p>
       </div>
       <div>
         <el-button type="primary" @click="handleAdd">
@@ -66,52 +68,80 @@
     <!-- 统计卡片 -->
     <el-row :gutter="16" class="mb-16px">
       <el-col :span="6">
-        <el-card class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px" shadow="hover">
+        <el-card
+          class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px"
+          shadow="hover"
+        >
           <div class="flex items-center">
-            <div class="w-48px h-48px rounded-8px flex items-center justify-center text-24px text-white mr-16px bg-gradient-to-br from-[#667eea] to-[#764ba2]">
+            <div
+              class="w-48px h-48px rounded-8px flex items-center justify-center text-24px text-white mr-16px bg-gradient-to-br from-[#667eea] to-[#764ba2]"
+            >
               <Icon icon="ep:document" />
             </div>
             <div>
-              <div class="text-24px font-600 text-[#303133] leading-none">{{ statistics.total }}</div>
+              <div class="text-24px font-600 text-[#303133] leading-none">{{
+                statistics.total
+              }}</div>
               <div class="text-14px text-[#909399] mt-4px">总规则数</div>
             </div>
           </div>
         </el-card>
       </el-col>
       <el-col :span="6">
-        <el-card class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px" shadow="hover">
+        <el-card
+          class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px"
+          shadow="hover"
+        >
           <div class="flex items-center">
-            <div class="w-48px h-48px rounded-8px flex items-center justify-center text-24px text-white mr-16px bg-gradient-to-br from-[#f093fb] to-[#f5576c]">
+            <div
+              class="w-48px h-48px rounded-8px flex items-center justify-center text-24px text-white mr-16px bg-gradient-to-br from-[#f093fb] to-[#f5576c]"
+            >
               <Icon icon="ep:check" />
             </div>
             <div>
-              <div class="text-24px font-600 text-[#303133] leading-none">{{ statistics.enabled }}</div>
+              <div class="text-24px font-600 text-[#303133] leading-none">{{
+                statistics.enabled
+              }}</div>
               <div class="text-14px text-[#909399] mt-4px">启用规则</div>
             </div>
           </div>
         </el-card>
       </el-col>
       <el-col :span="6">
-        <el-card class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px" shadow="hover">
+        <el-card
+          class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px"
+          shadow="hover"
+        >
           <div class="flex items-center">
-            <div class="w-48px h-48px rounded-8px flex items-center justify-center text-24px text-white mr-16px bg-gradient-to-br from-[#4facfe] to-[#00f2fe]">
+            <div
+              class="w-48px h-48px rounded-8px flex items-center justify-center text-24px text-white mr-16px bg-gradient-to-br from-[#4facfe] to-[#00f2fe]"
+            >
               <Icon icon="ep:close" />
             </div>
             <div>
-              <div class="text-24px font-600 text-[#303133] leading-none">{{ statistics.disabled }}</div>
+              <div class="text-24px font-600 text-[#303133] leading-none">{{
+                statistics.disabled
+              }}</div>
               <div class="text-14px text-[#909399] mt-4px">禁用规则</div>
             </div>
           </div>
         </el-card>
       </el-col>
       <el-col :span="6">
-        <el-card class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px" shadow="hover">
+        <el-card
+          class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px"
+          shadow="hover"
+        >
           <div class="flex items-center">
-            <div class="w-48px h-48px rounded-8px flex items-center justify-center text-24px text-white mr-16px bg-gradient-to-br from-[#43e97b] to-[#38f9d7]">
+            <div
+              class="w-48px h-48px rounded-8px flex items-center justify-center text-24px text-white mr-16px bg-gradient-to-br from-[#43e97b] to-[#38f9d7]"
+            >
               <Icon icon="ep:lightning" />
             </div>
             <div>
-              <div class="text-24px font-600 text-[#303133] leading-none">{{ statistics.triggered }}</div>
+              <div class="text-24px font-600 text-[#303133] leading-none">{{
+                statistics.triggered
+              }}</div>
               <div class="text-14px text-[#909399] mt-4px">今日触发</div>
             </div>
           </div>
@@ -134,6 +164,7 @@
             </div>
           </template>
         </el-table-column>
+        <!-- TODO puhui999:貌似展示不太对劲。。。一个字,一个 tab 哈了。 -->
         <el-table-column label="触发条件" min-width="250">
           <template #default="{ row }">
             <div class="flex flex-wrap gap-4px">
@@ -149,6 +180,7 @@
             </div>
           </template>
         </el-table-column>
+        <!-- TODO puhui999:貌似展示不太对劲。。。一个字,一个 tab 哈了。 -->
         <el-table-column label="执行动作" min-width="250">
           <template #default="{ row }">
             <div class="flex flex-wrap gap-4px">
@@ -177,7 +209,7 @@
             {{ formatDate(row.createTime) }}
           </template>
         </el-table-column>
-        <el-table-column label="操作" width="200" fixed="right">
+        <el-table-column label="操作" width="210" fixed="right">
           <template #default="{ row }">
             <div class="flex gap-8px">
               <el-button type="primary" link @click="handleEdit(row)">
@@ -190,9 +222,10 @@
                 @click="handleToggleStatus(row)"
               >
                 <Icon :icon="row.status === 0 ? 'ep:video-pause' : 'ep:video-play'" />
+                <!-- TODO @puhui999:字典翻译 -->
                 {{ row.status === 0 ? '禁用' : '启用' }}
               </el-button>
-              <el-button type="danger" link @click="handleDelete(row.id)">
+              <el-button type="danger" class="!mr-10px" link @click="handleDelete(row.id)">
                 <Icon icon="ep:delete" />
                 删除
               </el-button>
@@ -211,7 +244,10 @@
     </el-card>
 
     <!-- 批量操作 -->
-    <div v-if="selectedRows.length > 0" class="fixed bottom-20px left-1/2 transform -translate-x-1/2 z-1000">
+    <div
+      v-if="selectedRows.length > 0"
+      class="fixed bottom-20px left-1/2 transform -translate-x-1/2 z-1000"
+    >
       <el-card shadow="always">
         <div class="flex items-center gap-16px">
           <span class="font-500 text-[#303133]"> 已选择 {{ selectedRows.length }} 项 </span>
@@ -266,8 +302,8 @@ const selectedRows = ref<IotRuleScene[]>([]) // 选中的行数据
 const queryFormRef = ref() // 搜索的表单
 
 // 表单状态
-const formVisible = ref(false)
-const currentRule = ref<IotRuleScene>()
+const formVisible = ref(false) // 是否可见
+const currentRule = ref<IotRuleScene>() // 表单数据
 
 // 统计数据
 const statistics = ref({
@@ -277,13 +313,12 @@ const statistics = ref({
   triggered: 0
 })
 
-/**
- * 格式化CRON表达式显示
- */
+/** 格式化 CRON 表达式显示 */
+// TODO @puhui999:这个能不能 cron 组件里翻译哈;
 const formatCronExpression = (cron: string): string => {
   if (!cron) return ''
 
-  // 简单的CRON表达式解析和格式化
+  // 简单的 CRON 表达式解析和格式化
   const parts = cron.trim().split(' ')
   if (parts.length < 5) return cron
 
@@ -322,10 +357,9 @@ const formatCronExpression = (cron: string): string => {
   return description || cron
 }
 
-/**
- * 获取规则摘要信息
- */
+/** 获取规则摘要信息 */
 const getRuleSceneSummary = (rule: IotRuleScene) => {
+  // TODO @puhui999:是不是可以使用字段,或者枚举?
   const triggerSummary =
     rule.triggers?.map((trigger) => {
       switch (trigger.type) {
@@ -344,6 +378,7 @@ const getRuleSceneSummary = (rule: IotRuleScene) => {
       }
     }) || []
 
+  // TODO @puhui999:是不是可以使用字段,或者枚举?
   const actionSummary =
     rule.actions?.map((action) => {
       switch (action.type) {
@@ -367,6 +402,7 @@ const getRuleSceneSummary = (rule: IotRuleScene) => {
 }
 
 /** 查询列表 */
+// TODO @puhui999:这里使用真实数据;
 const getList = async () => {
   loading.value = true
   try {
@@ -440,6 +476,7 @@ const updateStatistics = () => {
     total: list.value.length,
     enabled: list.value.filter((item) => item.status === 0).length,
     disabled: list.value.filter((item) => item.status === 1).length,
+    // TODO @puhui999:这里缺了 lastTriggeredTime 定义
     triggered: list.value.filter((item) => item.lastTriggeredTime).length
   }
 }
@@ -467,18 +504,20 @@ const resetQuery = () => {
   handleQuery()
 }
 
-/** 添加/修改操作 */
+/** 添加操作 */
 const handleAdd = () => {
   currentRule.value = undefined
   formVisible.value = true
 }
 
+/** 修改操作 */
 const handleEdit = (row: IotRuleScene) => {
   currentRule.value = row
   formVisible.value = true
 }
 
 /** 删除按钮操作 */
+// TODO @puhui999:貌似 id 没用上
 const handleDelete = async (id: number) => {
   try {
     // 删除的二次确认
@@ -500,6 +539,7 @@ const handleToggleStatus = async (row: IotRuleScene) => {
     const text = row.status === 0 ? '禁用' : '启用'
     await message.confirm('确认要' + text + '"' + row.name + '"吗?')
     // 发起修改状态
+    // TODO @puhui999:这里缺了
     // await RuleSceneApi.updateRuleSceneStatus(row.id, row.status === 0 ? 1 : 0)
 
     // 模拟状态切换
@@ -523,6 +563,7 @@ const handleBatchEnable = async () => {
   try {
     await message.confirm(`确定要启用选中的 ${selectedRows.value.length} 个规则吗?`)
     // 这里应该调用批量启用API
+    // TODO @puhui999:这里缺了
     // await RuleSceneApi.updateRuleSceneStatusBatch(selectedRows.value.map(row => row.id), 0)
 
     // 模拟批量启用
@@ -539,6 +580,7 @@ const handleBatchDisable = async () => {
   try {
     await message.confirm(`确定要禁用选中的 ${selectedRows.value.length} 个规则吗?`)
     // 这里应该调用批量禁用API
+    // TODO @puhui999:这里缺了
     // await RuleSceneApi.updateRuleSceneStatusBatch(selectedRows.value.map(row => row.id), 1)
 
     // 模拟批量禁用
@@ -550,18 +592,18 @@ const handleBatchDisable = async () => {
   } catch {}
 }
 
+/** 批量删除操作 */
 const handleBatchDelete = async () => {
   try {
     await ElMessageBox.confirm(`确定要删除选中的 ${selectedRows.value.length} 个规则吗?`, '提示', {
       type: 'warning'
     })
 
+    // TODO @puhui999:这里缺了
     // 这里应该调用批量删除API
     message.success('批量删除成功')
-    getList()
-  } catch (error) {
-    // 用户取消操作
-  }
+    await getList()
+  } catch (error) {}
 }
 
 // 初始化
@@ -569,5 +611,3 @@ onMounted(() => {
   getList()
 })
 </script>
-
-

+ 7 - 1
src/views/iot/rule/scene/utils/validation.ts

@@ -1,3 +1,4 @@
+// TODO @puhui999:貌似很多地方,都用不到啦?这个文件
 /**
  * IoT 场景联动表单验证工具函数
  */
@@ -37,9 +38,10 @@ export const getBaseValidationRules = (): FormValidationRules => ({
 })
 
 /** 验证CRON表达式格式 */
+// TODO @puhui999:这个可以拿到 cron 组件里哇?
 export function validateCronExpression(cron: string): boolean {
   if (!cron || cron.trim().length === 0) return false
-  // 基础的 CRON 表达式正则验证(支持6位和7位格式)
+  // 基础的 CRON 表达式正则验证(支持 6 位和 7 位格式)
   const cronRegex =
     /^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])) (\*|([0-6])|\*\/([0-6]))( (\*|([1-9][0-9]{3})|\*\/([1-9][0-9]{3})))?$/
   return cronRegex.test(cron.trim())
@@ -58,6 +60,7 @@ export function validateDeviceNames(deviceNames: string[]): boolean {
 export function validateCompareValue(operator: string, value: string): boolean {
   if (!value || value.trim().length === 0) return false
   const trimmedValue = value.trim()
+  // TODO @puhui999:这里要用下枚举哇?
   switch (operator) {
     case 'between':
     case 'not between':
@@ -81,11 +84,13 @@ export function validateCompareValue(operator: string, value: string): boolean {
     case '!=':
     case 'like':
     case 'not null':
+    // TODO @puhui999:这里要不加个 default 抛出异常?
     default:
       return true
   }
 }
 
+// TODO @puhui999:貌似没用到?
 /** 验证触发器配置 */
 export function validateTriggerConfig(trigger: TriggerConfig): {
   valid: boolean
@@ -136,6 +141,7 @@ export function validateTriggerConfig(trigger: TriggerConfig): {
   return { valid: true }
 }
 
+// TODO @puhui999:貌似没用到?
 /** 验证执行器配置 */
 export function validateActionConfig(action: ActionConfig): { valid: boolean; message?: string } {
   if (!action.type) {