yanghao 5 days ago
parent
commit
bd48f25fa0

+ 35 - 50
src/views/iot/alert/config/index.vue

@@ -1,35 +1,28 @@
 <template>
-  <ContentWrap>
+  <div
+    style="border: none; overflow: hidden; background-color: #fff"
+    class="rounded-md px-4 pt-4 mb-4">
     <!-- 搜索工作栏 -->
-    <el-form
-      class="-mb-15px"
-      :model="queryParams"
-      ref="queryFormRef"
-      :inline="true"
-      label-width="68px"
-    >
+    <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
       <el-form-item label="配置名称" prop="name">
         <el-input
           v-model="queryParams.name"
           placeholder="请输入配置名称"
           clearable
           @keyup.enter="handleQuery"
-          class="!w-240px"
-        />
+          class="!w-240px" />
       </el-form-item>
       <el-form-item label="配置状态" prop="status">
         <el-select
           v-model="queryParams.status"
           placeholder="请选择配置状态"
           clearable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
             :key="dict.value"
             :label="dict.label"
-            :value="dict.value"
-          />
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
@@ -40,8 +33,7 @@
           start-placeholder="开始日期"
           end-placeholder="结束日期"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-220px"
-        />
+          class="!w-220px" />
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@@ -50,86 +42,79 @@
           type="primary"
           plain
           @click="openForm('create')"
-          v-hasPermi="['iot:alert-config:create']"
-        >
+          v-hasPermi="['iot:alert-config:create']">
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
       </el-form-item>
     </el-form>
-  </ContentWrap>
+  </div>
 
   <!-- 列表 -->
-  <ContentWrap>
-    <el-table
+  <ContentWrap style="border: none">
+    <zm-table
       row-key="id"
-      v-loading="loading"
+      :loading="loading"
       :data="list"
       :stripe="true"
-      :show-overflow-tooltip="true"
-    >
-      <el-table-column label="配置编号" align="center" prop="id" />
-      <el-table-column label="配置名称" align="center" prop="name" />
-      <el-table-column label="配置描述" align="center" prop="description" />
-      <el-table-column label="告警级别" align="center" prop="level">
+      :show-overflow-tooltip="true">
+      <zm-table-column label="配置编号" align="center" prop="id" />
+      <zm-table-column label="配置名称" align="center" prop="name" />
+      <zm-table-column label="配置描述" align="center" prop="description" />
+      <zm-table-column label="告警级别" align="center" prop="level">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.IOT_ALERT_LEVEL" :value="scope.row.level" />
         </template>
-      </el-table-column>
-      <el-table-column label="配置状态" align="center" prop="status">
+      </zm-table-column>
+      <zm-table-column label="配置状态" align="center" prop="status">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
         </template>
-      </el-table-column>
-      <el-table-column label="关联场景联动规则" align="center" prop="sceneRuleIds" min-width="100">
+      </zm-table-column>
+      <zm-table-column label="关联场景联动规则" align="center" prop="sceneRuleIds" min-width="100">
         <template #default="scope"> {{ scope.row.sceneRuleIds?.length || 0 }} 条 </template>
-      </el-table-column>
-      <el-table-column label="接收人" align="center" prop="receiveUserNames" />
-      <el-table-column label="接收类型" align="center" prop="receiveTypes">
+      </zm-table-column>
+      <zm-table-column label="接收人" align="center" prop="receiveUserNames" />
+      <zm-table-column label="接收类型" align="center" prop="receiveTypes">
         <template #default="scope">
           <dict-tag
             v-for="(receiveType, index) in scope.row.receiveTypes"
             :key="index"
             :type="DICT_TYPE.IOT_ALERT_RECEIVE_TYPE"
             :value="receiveType"
-            class="mr-1"
-          />
+            class="mr-1" />
         </template>
-      </el-table-column>
-      <el-table-column
+      </zm-table-column>
+      <zm-table-column
         label="创建时间"
         align="center"
         prop="createTime"
         :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="操作" align="center" min-width="120px">
+        width="180px" />
+      <zm-table-column label="操作" align="center" min-width="120px" action>
         <template #default="scope">
           <el-button
             link
             type="primary"
             @click="openForm('update', scope.row.id)"
-            v-hasPermi="['iot:alert-config:update']"
-          >
+            v-hasPermi="['iot:alert-config:update']">
             编辑
           </el-button>
           <el-button
             link
             type="danger"
             @click="handleDelete(scope.row.id)"
-            v-hasPermi="['iot:alert-config:delete']"
-          >
+            v-hasPermi="['iot:alert-config:delete']">
             删除
           </el-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </zm-table-column>
+    </zm-table>
     <!-- 分页 -->
     <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
+      @pagination="getList" />
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->

+ 41 - 61
src/views/iot/alert/record/index.vue

@@ -1,27 +1,21 @@
 <template>
-  <ContentWrap>
+  <div
+    style="border: none; overflow: hidden; background-color: #fff"
+    class="rounded-md px-4 pt-4 mb-4">
     <!-- 搜索工作栏 -->
-    <el-form
-      class="-mb-15px"
-      :model="queryParams"
-      ref="queryFormRef"
-      :inline="true"
-      label-width="68px"
-    >
+    <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
       <el-form-item label="告警配置" prop="configId">
         <el-select
           v-model="queryParams.configId"
           placeholder="请选择告警配置"
           clearable
           filterable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="config in alertConfigList"
             :key="config.id"
             :label="config.name"
-            :value="config.id"
-          />
+            :value="config.id" />
         </el-select>
       </el-form-item>
       <el-form-item label="告警级别" prop="configLevel">
@@ -29,14 +23,12 @@
           v-model="queryParams.configLevel"
           placeholder="请选择告警级别"
           clearable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="dict in getIntDictOptions(DICT_TYPE.IOT_ALERT_LEVEL)"
             :key="dict.value"
             :label="dict.label"
-            :value="dict.value"
-          />
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="产品" prop="productId">
@@ -46,14 +38,12 @@
           clearable
           filterable
           @change="handleProductChange"
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="product in productList"
             :key="product.id"
             :label="product.name"
-            :value="product.id"
-          />
+            :value="product.id" />
         </el-select>
       </el-form-item>
       <el-form-item label="设备" prop="deviceId">
@@ -62,14 +52,12 @@
           placeholder="请选择设备"
           clearable
           filterable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="device in filteredDeviceList"
             :key="device.id"
             :label="device.deviceName"
-            :value="device.id"
-          />
+            :value="device.id" />
         </el-select>
       </el-form-item>
       <el-form-item label="是否处理" prop="processStatus">
@@ -77,14 +65,12 @@
           v-model="queryParams.processStatus"
           placeholder="请选择是否处理"
           clearable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
             :key="String(dict.value)"
             :label="dict.label"
-            :value="dict.value"
-          />
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
@@ -95,50 +81,47 @@
           start-placeholder="开始日期"
           end-placeholder="结束日期"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-220px"
-        />
+          class="!w-220px" />
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
       </el-form-item>
     </el-form>
-  </ContentWrap>
+  </div>
 
   <!-- 列表 -->
-  <ContentWrap>
-    <el-table
+  <ContentWrap style="border: none">
+    <zm-table
       row-key="id"
-      v-loading="loading"
+      :loading="loading"
       :data="list"
       :stripe="true"
-      :show-overflow-tooltip="true"
-    >
-      <el-table-column label="记录编号" align="center" prop="id" />
-      <el-table-column label="告警名称" align="center" prop="configName" />
-      <el-table-column label="告警级别" align="center" prop="configLevel">
+      :show-overflow-tooltip="true">
+      <zm-table-column label="记录编号" align="center" prop="id" />
+      <zm-table-column label="告警名称" align="center" prop="configName" />
+      <zm-table-column label="告警级别" align="center" prop="configLevel">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.IOT_ALERT_LEVEL" :value="scope.row.configLevel" />
         </template>
-      </el-table-column>
-      <el-table-column label="产品名称" align="center" prop="productId">
+      </zm-table-column>
+      <zm-table-column label="产品名称" align="center" prop="productId">
         <template #default="scope">
           {{ getProductName(scope.row.productId) }}
         </template>
-      </el-table-column>
-      <el-table-column label="设备名称" align="center" prop="deviceId">
+      </zm-table-column>
+      <zm-table-column label="设备名称" align="center" prop="deviceId">
         <template #default="scope">
           {{ getDeviceName(scope.row.deviceId) }}
         </template>
-      </el-table-column>
-      <el-table-column label="触发的设备消息" align="center" prop="deviceMessage">
+      </zm-table-column>
+      <zm-table-column label="触发的设备消息" align="center" prop="deviceMessage">
         <template #default="scope">
           <el-popover
             placement="top-start"
             :width="600"
             trigger="hover"
-            v-if="scope.row.deviceMessage"
-          >
+            v-if="scope.row.deviceMessage">
             <template #reference>
               <el-button link type="primary">
                 <Icon icon="ep:view" class="mr-5px" />
@@ -149,41 +132,38 @@
           </el-popover>
           <span v-else class="text-gray-400">-</span>
         </template>
-      </el-table-column>
-      <el-table-column label="是否处理" align="center" prop="processStatus">
+      </zm-table-column>
+      <zm-table-column label="是否处理" align="center" prop="processStatus">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.processStatus" />
         </template>
-      </el-table-column>
-      <el-table-column label="处理结果" align="center" prop="processRemark" />
-      <el-table-column
+      </zm-table-column>
+      <zm-table-column label="处理结果" align="center" prop="processRemark" />
+      <zm-table-column
         label="创建时间"
         align="center"
         prop="createTime"
         :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="操作" align="center" min-width="120px">
+        width="180px" />
+      <zm-table-column label="操作" align="center" min-width="120px" action>
         <template #default="scope">
           <el-button
             v-if="!scope.row.processStatus"
             link
             type="primary"
             @click="handleProcess(scope.row)"
-            v-hasPermi="['iot:alert-record:process']"
-          >
+            v-hasPermi="['iot:alert-record:process']">
             处理
           </el-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </zm-table-column>
+    </zm-table>
     <!-- 分页 -->
     <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
+      @pagination="getList" />
   </ContentWrap>
 </template>
 

+ 54 - 81
src/views/iot/device/device/index.vue

@@ -1,26 +1,23 @@
 <template>
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <!-- 搜索工作栏 -->
     <el-form
       class="-mb-15px"
       :model="queryParams"
       ref="queryFormRef"
       :inline="true"
-      label-width="68px"
-    >
+      label-width="68px">
       <el-form-item label="产品" prop="productId">
         <el-select
           v-model="queryParams.productId"
           placeholder="请选择产品"
           clearable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="product in products"
             :key="product.id"
             :label="product.name"
-            :value="product.id"
-          />
+            :value="product.id" />
         </el-select>
       </el-form-item>
       <el-form-item label="DeviceName" prop="deviceName">
@@ -29,8 +26,7 @@
           placeholder="请输入 DeviceName"
           clearable
           @keyup.enter="handleQuery"
-          class="!w-240px"
-        />
+          class="!w-240px" />
       </el-form-item>
       <el-form-item label="备注名称" prop="nickname">
         <el-input
@@ -38,22 +34,19 @@
           placeholder="请输入备注名称"
           clearable
           @keyup.enter="handleQuery"
-          class="!w-240px"
-        />
+          class="!w-240px" />
       </el-form-item>
       <el-form-item label="设备类型" prop="deviceType">
         <el-select
           v-model="queryParams.deviceType"
           placeholder="请选择设备类型"
           clearable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="dict in getIntDictOptions(DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE)"
             :key="dict.value"
             :label="dict.label"
-            :value="dict.value"
-          />
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="设备状态" prop="status">
@@ -61,14 +54,12 @@
           v-model="queryParams.status"
           placeholder="请选择设备状态"
           clearable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="dict in getIntDictOptions(DICT_TYPE.IOT_DEVICE_STATE)"
             :key="dict.value"
             :label="dict.label"
-            :value="dict.value"
-          />
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="设备分组" prop="groupId">
@@ -76,14 +67,12 @@
           v-model="queryParams.groupId"
           placeholder="请选择设备分组"
           clearable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="group in deviceGroups"
             :key="group.id"
             :label="group.name"
-            :value="group.id"
-          />
+            :value="group.id" />
         </el-select>
       </el-form-item>
       <el-form-item class="float-right !mr-0 !mb-0">
@@ -109,8 +98,7 @@
           type="primary"
           plain
           @click="openForm('create')"
-          v-hasPermi="['iot:device:create']"
-        >
+          v-hasPermi="['iot:device:create']">
           <Icon icon="ep:plus" class="mr-5px" />
           新增
         </el-button>
@@ -119,8 +107,7 @@
           plain
           @click="handleExport"
           :loading="exportLoading"
-          v-hasPermi="['iot:device:export']"
-        >
+          v-hasPermi="['iot:device:export']">
           <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
         <el-button type="warning" plain @click="handleImport" v-hasPermi="['iot:device:import']">
@@ -131,8 +118,7 @@
           plain
           @click="openGroupForm"
           :disabled="selectedIds.length === 0"
-          v-hasPermi="['iot:device:update']"
-        >
+          v-hasPermi="['iot:device:update']">
           <Icon icon="ep:folder-add" class="mr-5px" /> 添加到分组
         </el-button>
         <el-button
@@ -140,8 +126,7 @@
           plain
           @click="handleDeleteList"
           :disabled="selectedIds.length === 0"
-          v-hasPermi="['iot:device:delete']"
-        >
+          v-hasPermi="['iot:device:delete']">
           <Icon icon="ep:delete" class="mr-5px" /> 批量删除
         </el-button>
       </el-form-item>
@@ -149,14 +134,13 @@
   </ContentWrap>
 
   <!-- 列表 -->
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <template v-if="viewMode === 'card'">
       <el-row :gutter="16">
         <el-col v-for="item in list" :key="item.id" :xs="24" :sm="12" :md="12" :lg="6" class="mb-4">
           <el-card
             class="h-full transition-colors relative overflow-hidden"
-            :body-style="{ padding: '0' }"
-          >
+            :body-style="{ padding: '0' }">
             <!-- 添加渐变背景层 -->
             <div
               class="absolute top-0 left-0 right-0 h-[50px] pointer-events-none"
@@ -164,8 +148,7 @@
                 item.state === DeviceStateEnum.ONLINE
                   ? 'bg-gradient-to-b from-[#eefaff] to-transparent'
                   : 'bg-gradient-to-b from-[#fff1f1] to-transparent'
-              ]"
-            >
+              ]">
             </div>
             <div class="p-4 relative">
               <!-- 标题区域 -->
@@ -173,7 +156,10 @@
                 <div class="mr-2.5 flex items-center">
                   <el-image :src="defaultIconUrl" class="w-[18px] h-[18px]" />
                 </div>
-                <div class="text-[16px] font-600 flex-1 overflow-hidden text-ellipsis whitespace-nowrap">{{ item.deviceName }}</div>
+                <div
+                  class="text-[16px] font-600 flex-1 overflow-hidden text-ellipsis whitespace-nowrap"
+                  >{{ item.deviceName }}</div
+                >
                 <!-- 添加设备状态标签 -->
                 <div class="inline-flex items-center">
                   <div
@@ -182,13 +168,11 @@
                       item.state === DeviceStateEnum.ONLINE
                         ? 'bg-[var(--el-color-success)]'
                         : 'bg-[var(--el-color-danger)]'
-                    "
-                  >
+                    ">
                   </div>
                   <el-text
                     class="!text-xs font-bold"
-                    :type="item.state === DeviceStateEnum.ONLINE ? 'success' : 'danger'"
-                  >
+                    :type="item.state === DeviceStateEnum.ONLINE ? 'success' : 'danger'">
                     {{ getDictLabel(DICT_TYPE.IOT_DEVICE_STATE, item.state) }}
                   </el-text>
                 </div>
@@ -210,8 +194,7 @@
                   <div class="mb-2.5 last:mb-0">
                     <span class="text-[#717c8e] mr-2.5">备注名称</span>
                     <span
-                      class="text-[var(--el-text-color-primary)] inline-block align-middle overflow-hidden text-ellipsis whitespace-nowrap max-w-[130px]"
-                    >
+                      class="text-[var(--el-text-color-primary)] inline-block align-middle overflow-hidden text-ellipsis whitespace-nowrap max-w-[130px]">
                       {{ item.nickname || item.deviceName }}
                     </span>
                   </div>
@@ -231,8 +214,7 @@
                   type="primary"
                   plain
                   @click="openForm('update', item.id)"
-                  v-hasPermi="['iot:device:update']"
-                >
+                  v-hasPermi="['iot:device:update']">
                   <Icon icon="ep:edit-pen" class="mr-1" />
                   编辑
                 </el-button>
@@ -240,8 +222,7 @@
                   class="flex-1 !px-2 !h-[32px] !ml-[10px] text-[13px]"
                   type="warning"
                   plain
-                  @click="openDetail(item.id)"
-                >
+                  @click="openDetail(item.id)">
                   <Icon icon="ep:view" class="mr-1" />
                   详情
                 </el-button>
@@ -249,8 +230,7 @@
                   class="flex-1 !px-2 !h-[32px] !ml-[10px] text-[13px]"
                   type="info"
                   plain
-                  @click="openModel(item.id)"
-                >
+                  @click="openModel(item.id)">
                   <Icon icon="ep:tickets" class="mr-1" />
                   数据
                 </el-button>
@@ -260,8 +240,7 @@
                   type="danger"
                   plain
                   @click="handleDelete(item.id)"
-                  v-hasPermi="['iot:device:delete']"
-                >
+                  v-hasPermi="['iot:device:delete']">
                   <Icon icon="ep:delete" />
                 </el-button>
               </div>
@@ -272,34 +251,33 @@
     </template>
 
     <!-- 列表视图 -->
-    <el-table
+    <zm-table
       v-else
-      v-loading="loading"
+      :loading="loading"
       :data="list"
       :stripe="true"
       :show-overflow-tooltip="true"
-      @selection-change="handleSelectionChange"
-    >
-      <el-table-column type="selection" width="55" />
-      <el-table-column label="DeviceName" align="center" prop="deviceName">
+      @selection-change="handleSelectionChange">
+      <zm-table-column type="selection" width="55" />
+      <zm-table-column label="DeviceName" align="center" prop="deviceName">
         <template #default="scope">
           <el-link @click="openDetail(scope.row.id)">{{ scope.row.deviceName }}</el-link>
         </template>
-      </el-table-column>
-      <el-table-column label="备注名称" align="center" prop="nickname" />
-      <el-table-column label="所属产品" align="center" prop="productId">
+      </zm-table-column>
+      <zm-table-column label="备注名称" align="center" prop="nickname" />
+      <zm-table-column label="所属产品" align="center" prop="productId">
         <template #default="scope">
           <el-link @click="openProductDetail(scope.row.productId)">
             {{ products.find((p) => p.id === scope.row.productId)?.name || '-' }}
           </el-link>
         </template>
-      </el-table-column>
-      <el-table-column label="设备类型" align="center" prop="deviceType">
+      </zm-table-column>
+      <zm-table-column label="设备类型" align="center" prop="deviceType">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE" :value="scope.row.deviceType" />
         </template>
-      </el-table-column>
-      <el-table-column label="所属分组" align="center" prop="groupId">
+      </zm-table-column>
+      <zm-table-column label="所属分组" align="center" prop="groupId">
         <template #default="scope">
           <template v-if="scope.row.groupIds?.length">
             <el-tag v-for="id in scope.row.groupIds" :key="id" class="ml-5px" size="small">
@@ -307,27 +285,25 @@
             </el-tag>
           </template>
         </template>
-      </el-table-column>
-      <el-table-column label="设备状态" align="center" prop="status">
+      </zm-table-column>
+      <zm-table-column label="设备状态" align="center" prop="status">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.IOT_DEVICE_STATE" :value="scope.row.status" />
         </template>
-      </el-table-column>
-      <el-table-column
+      </zm-table-column>
+      <zm-table-column
         label="最后上线时间"
         align="center"
         prop="onlineTime"
         :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="操作" align="center" min-width="120px">
+        width="180px" />
+      <zm-table-column label="操作" align="center" min-width="90px" action>
         <template #default="scope">
           <el-button
             link
             type="primary"
             @click="openDetail(scope.row.id)"
-            v-hasPermi="['iot:product:query']"
-          >
+            v-hasPermi="['iot:product:query']">
             查看
           </el-button>
           <el-button link type="primary" @click="openModel(scope.row.id)"> 日志 </el-button>
@@ -335,29 +311,26 @@
             link
             type="primary"
             @click="openForm('update', scope.row.id)"
-            v-hasPermi="['iot:device:update']"
-          >
+            v-hasPermi="['iot:device:update']">
             编辑
           </el-button>
           <el-button
             link
             type="danger"
             @click="handleDelete(scope.row.id)"
-            v-hasPermi="['iot:device:delete']"
-          >
+            v-hasPermi="['iot:device:delete']">
             删除
           </el-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </zm-table-column>
+    </zm-table>
 
     <!-- 分页 -->
     <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
+      @pagination="getList" />
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->

+ 21 - 29
src/views/iot/device/group/index.vue

@@ -1,21 +1,19 @@
 <template>
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <!-- 搜索工作栏 -->
     <el-form
       class="-mb-15px"
       :model="queryParams"
       ref="queryFormRef"
       :inline="true"
-      label-width="68px"
-    >
+      label-width="68px">
       <el-form-item label="分组名字" prop="name">
         <el-input
           v-model="queryParams.name"
           placeholder="请输入分组名字"
           clearable
           @keyup.enter="handleQuery"
-          class="!w-240px"
-        />
+          class="!w-240px" />
       </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
         <el-date-picker
@@ -25,8 +23,7 @@
           start-placeholder="开始日期"
           end-placeholder="结束日期"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-220px"
-        />
+          class="!w-220px" />
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@@ -35,8 +32,7 @@
           type="primary"
           plain
           @click="openForm('create')"
-          v-hasPermi="['iot:device-group:create']"
-        >
+          v-hasPermi="['iot:device-group:create']">
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
       </el-form-item>
@@ -44,52 +40,48 @@
   </ContentWrap>
 
   <!-- 列表 -->
-  <ContentWrap>
-    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      <el-table-column label="分组 ID" align="center" prop="id" />
-      <el-table-column label="分组名字" align="center" prop="name" />
-      <el-table-column label="分组状态" align="center" prop="status">
+  <ContentWrap style="border: none">
+    <zm-table :loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <zm-table-column label="分组 ID" align="center" prop="id" />
+      <zm-table-column label="分组名字" align="center" prop="name" />
+      <zm-table-column label="分组状态" align="center" prop="status">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
         </template>
-      </el-table-column>
-      <el-table-column label="分组描述" align="center" prop="description" />
-      <el-table-column
+      </zm-table-column>
+      <zm-table-column label="分组描述" align="center" prop="description" />
+      <zm-table-column
         label="创建时间"
         align="center"
         prop="createTime"
         :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="设备数量" align="center" prop="deviceCount" />
-      <el-table-column label="操作" align="center" min-width="120px">
+        width="180px" />
+      <zm-table-column label="设备数量" align="center" prop="deviceCount" />
+      <zm-table-column label="操作" align="center" width="120px" action>
         <template #default="scope">
           <el-button
             link
             type="primary"
             @click="openForm('update', scope.row.id)"
-            v-hasPermi="['iot:device-group:update']"
-          >
+            v-hasPermi="['iot:device-group:update']">
             编辑
           </el-button>
           <el-button
             link
             type="danger"
             @click="handleDelete(scope.row.id)"
-            v-hasPermi="['iot:device-group:delete']"
-          >
+            v-hasPermi="['iot:device-group:delete']">
             删除
           </el-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </zm-table-column>
+    </zm-table>
     <!-- 分页 -->
     <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
+      @pagination="getList" />
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->

+ 8 - 4
src/views/iot/home/components/ComparisonCard.vue

@@ -40,11 +40,15 @@ const props = defineProps({
 
 <style lang="scss" scoped>
 .stat-card {
-  transition: all 0.3s;
+  height: 100%;
 
-  &:hover {
-    transform: translateY(-5px);
-    box-shadow: 0 5px 15px rgb(0 0 0 / 8%);
+  :deep(.el-card__body) {
+    padding: 24px;
+  }
+
+  :deep(.el-divider) {
+    margin: 12px 0;
+    border-color: #f0f0f0;
   }
 }
 </style>

+ 15 - 0
src/views/iot/home/components/DeviceCountCard.vue

@@ -129,3 +129,18 @@ onMounted(async () => {
   })
 })
 </script>
+
+<style lang="scss" scoped>
+.chart-card {
+  height: 100%;
+
+  :deep(.el-card__header) {
+    padding: 16px 20px;
+    border-bottom: 1px solid #f0f0f0;
+  }
+
+  :deep(.el-card__body) {
+    padding: 20px;
+  }
+}
+</style>

+ 27 - 8
src/views/iot/home/index.vue

@@ -8,8 +8,7 @@
         :todayCount="statsData.productCategoryTodayCount"
         icon="ep:menu"
         iconColor="text-blue-400"
-        :loading="loading"
-      />
+        :loading="loading" />
     </el-col>
     <el-col :span="6">
       <ComparisonCard
@@ -18,8 +17,7 @@
         :todayCount="statsData.productTodayCount"
         icon="ep:box"
         iconColor="text-orange-400"
-        :loading="loading"
-      />
+        :loading="loading" />
     </el-col>
     <el-col :span="6">
       <ComparisonCard
@@ -28,8 +26,7 @@
         :todayCount="statsData.deviceTodayCount"
         icon="ep:cpu"
         iconColor="text-purple-400"
-        :loading="loading"
-      />
+        :loading="loading" />
     </el-col>
     <el-col :span="6">
       <ComparisonCard
@@ -38,8 +35,7 @@
         :todayCount="statsData.deviceMessageTodayCount"
         icon="ep:message"
         iconColor="text-teal-400"
-        :loading="loading"
-      />
+        :loading="loading" />
     </el-col>
   </el-row>
 
@@ -112,3 +108,26 @@ onMounted(() => {
   getStats()
 })
 </script>
+
+<style lang="scss" scoped>
+:deep(.el-card) {
+  border: none !important;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+  border-radius: 8px;
+  transition: all 0.3s ease;
+
+  &:hover {
+    box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.1);
+    transform: translateY(-2px);
+  }
+
+  .el-card__header {
+    border-bottom: 1px solid #f0f0f0;
+    padding: 16px 20px;
+  }
+
+  .el-card__body {
+    padding: 20px;
+  }
+}
+</style>

+ 29 - 42
src/views/iot/ota/firmware/index.vue

@@ -1,21 +1,19 @@
 <template>
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <!-- 搜索工作栏 -->
     <el-form
       class="-mb-15px"
       :model="queryParams"
       ref="queryFormRef"
       :inline="true"
-      label-width="68px"
-    >
+      label-width="68px">
       <el-form-item label="固件名称" prop="name">
         <el-input
           v-model="queryParams.name"
           placeholder="请输入固件名称"
           clearable
           @keyup.enter="handleQuery"
-          class="!w-240px"
-        />
+          class="!w-240px" />
       </el-form-item>
       <el-form-item label="产品" prop="productId">
         <el-select
@@ -23,14 +21,12 @@
           placeholder="请选择产品"
           clearable
           @keyup.enter="handleQuery"
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="product in productList"
             :key="product.id"
             :label="product.name"
-            :value="product.id"
-          />
+            :value="product.id" />
         </el-select>
       </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
@@ -41,8 +37,7 @@
           start-placeholder="开始日期"
           end-placeholder="结束日期"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-220px"
-        />
+          class="!w-220px" />
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@@ -51,8 +46,7 @@
           type="primary"
           plain
           @click="openForm('create')"
-          v-hasPermi="['iot:ota-firmware:create']"
-        >
+          v-hasPermi="['iot:ota-firmware:create']">
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
       </el-form-item>
@@ -60,79 +54,72 @@
   </ContentWrap>
 
   <!-- 列表 -->
-  <ContentWrap>
-    <el-table
+  <ContentWrap style="border: none">
+    <zm-table
       row-key="id"
-      v-loading="loading"
+      :loading="loading"
       :data="list"
       :stripe="true"
-      :show-overflow-tooltip="true"
-    >
-      <el-table-column label="固件编号" align="center" prop="id" />
-      <el-table-column label="固件名称" align="center" prop="name" />
-      <el-table-column label="固件版本" align="center" prop="description" />
-      <el-table-column label="版本号" align="center" prop="version" />
-      <el-table-column label="所属产品" align="center" prop="productId">
+      :show-overflow-tooltip="true">
+      <zm-table-column label="固件编号" align="center" prop="id" />
+      <zm-table-column label="固件名称" align="center" prop="name" />
+      <zm-table-column label="固件版本" align="center" prop="description" />
+      <zm-table-column label="版本号" align="center" prop="version" />
+      <zm-table-column label="所属产品" align="center" prop="productId">
         <template #default="scope">
           <el-link
             @click="openProductDetail(scope.row.productId)"
-            v-if="getProductName(scope.row.productId)"
-          >
+            v-if="getProductName(scope.row.productId)">
             {{ getProductName(scope.row.productId) }}
           </el-link>
           <span v-else>加载中...</span>
         </template>
-      </el-table-column>
-      <el-table-column label="固件文件" align="center" prop="fileUrl">
+      </zm-table-column>
+      <zm-table-column label="固件文件" align="center" prop="fileUrl">
         <template #default="scope">
           <el-link :href="scope.row.fileUrl" target="_blank" download>
             <Icon icon="ep:download" class="mr-5px" />
             下载固件
           </el-link>
         </template>
-      </el-table-column>
-      <el-table-column
+      </zm-table-column>
+      <zm-table-column
         label="创建时间"
         align="center"
         prop="createTime"
         :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="操作" align="center" min-width="180px">
+        width="180px" />
+      <zm-table-column label="操作" align="center" min-width="180px" action>
         <template #default="scope">
           <el-button
             link
             @click="openFirmwareDetail(scope.row.id)"
-            v-hasPermi="['iot:ota-firmware:query']"
-          >
+            v-hasPermi="['iot:ota-firmware:query']">
             详情
           </el-button>
           <el-button
             link
             type="primary"
             @click="openForm('update', scope.row.id)"
-            v-hasPermi="['iot:ota-firmware:update']"
-          >
+            v-hasPermi="['iot:ota-firmware:update']">
             编辑
           </el-button>
           <el-button
             link
             type="danger"
             @click="handleDelete(scope.row.id)"
-            v-hasPermi="['iot:ota-firmware:delete']"
-          >
+            v-hasPermi="['iot:ota-firmware:delete']">
             删除
           </el-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </zm-table-column>
+    </zm-table>
     <!-- 分页 -->
     <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
+      @pagination="getList" />
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->

+ 21 - 29
src/views/iot/product/category/index.vue

@@ -1,21 +1,19 @@
 <template>
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <!-- 搜索工作栏 -->
     <el-form
       class="-mb-15px"
       :model="queryParams"
       ref="queryFormRef"
       :inline="true"
-      label-width="68px"
-    >
+      label-width="68px">
       <el-form-item label="分类名字" prop="name">
         <el-input
           v-model="queryParams.name"
           placeholder="请输入分类名字"
           clearable
           @keyup.enter="handleQuery"
-          class="!w-240px"
-        />
+          class="!w-240px" />
       </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
         <el-date-picker
@@ -25,8 +23,7 @@
           start-placeholder="开始日期"
           end-placeholder="结束日期"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-220px"
-        />
+          class="!w-220px" />
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@@ -35,8 +32,7 @@
           type="primary"
           plain
           @click="openForm('create')"
-          v-hasPermi="['iot:product-category:create']"
-        >
+          v-hasPermi="['iot:product-category:create']">
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
       </el-form-item>
@@ -44,52 +40,48 @@
   </ContentWrap>
 
   <!-- 列表 -->
-  <ContentWrap>
-    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      <el-table-column label="ID" align="center" prop="id" />
-      <el-table-column label="名字" align="center" prop="name" />
-      <el-table-column label="排序" align="center" prop="sort" />
-      <el-table-column label="状态" align="center" prop="status">
+  <ContentWrap style="border: none">
+    <zm-table :loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <zm-table-column label="ID" align="center" prop="id" />
+      <zm-table-column label="名字" align="center" prop="name" />
+      <zm-table-column label="排序" align="center" prop="sort" />
+      <zm-table-column label="状态" align="center" prop="status">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
         </template>
-      </el-table-column>
-      <el-table-column label="描述" align="center" prop="description" />
-      <el-table-column
+      </zm-table-column>
+      <zm-table-column label="描述" align="center" prop="description" />
+      <zm-table-column
         label="创建时间"
         align="center"
         prop="createTime"
         :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="操作" align="center" min-width="120px">
+        width="180px" />
+      <zm-table-column label="操作" align="center" width="120px" action>
         <template #default="scope">
           <el-button
             link
             type="primary"
             @click="openForm('update', scope.row.id)"
-            v-hasPermi="['iot:product-category:update']"
-          >
+            v-hasPermi="['iot:product-category:update']">
             编辑
           </el-button>
           <el-button
             link
             type="danger"
             @click="handleDelete(scope.row.id)"
-            v-hasPermi="['iot:product-category:delete']"
-          >
+            v-hasPermi="['iot:product-category:delete']">
             删除
           </el-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </zm-table-column>
+    </zm-table>
     <!-- 分页 -->
     <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
+      @pagination="getList" />
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->

+ 34 - 49
src/views/iot/product/product/index.vue

@@ -1,21 +1,19 @@
 <template>
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <!-- 搜索工作栏 -->
     <el-form
       ref="queryFormRef"
       :inline="true"
       :model="queryParams"
       class="-mb-15px"
-      label-width="68px"
-    >
+      label-width="68px">
       <el-form-item label="产品名称" prop="name">
         <el-input
           v-model="queryParams.name"
           class="!w-240px"
           clearable
           placeholder="请输入产品名称"
-          @keyup.enter="handleQuery"
-        />
+          @keyup.enter="handleQuery" />
       </el-form-item>
       <el-form-item label="ProductKey" prop="productKey">
         <el-input
@@ -23,8 +21,7 @@
           class="!w-240px"
           clearable
           placeholder="请输入产品标识"
-          @keyup.enter="handleQuery"
-        />
+          @keyup.enter="handleQuery" />
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery">
@@ -39,8 +36,7 @@
           v-hasPermi="['iot:product:create']"
           plain
           type="primary"
-          @click="openForm('create')"
-        >
+          @click="openForm('create')">
           <Icon class="mr-5px" icon="ep:plus" />
           新增
         </el-button>
@@ -49,8 +45,7 @@
           :loading="exportLoading"
           plain
           type="success"
-          @click="handleExport"
-        >
+          @click="handleExport">
           <Icon class="mr-5px" icon="ep:download" />
           导出
         </el-button>
@@ -70,7 +65,7 @@
   </ContentWrap>
 
   <!-- 卡片视图 -->
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <el-row v-if="viewMode === 'card'" :gutter="16">
       <el-col v-for="item in list" :key="item.id" :lg="6" :md="12" :sm="12" :xs="24" class="mb-4">
         <el-card :body-style="{ padding: '0' }" class="h-full transition-colors">
@@ -97,7 +92,8 @@
                 </div>
                 <div class="mb-2.5 last:mb-0">
                   <span class="text-[#717c8e] mr-2.5">产品标识</span>
-                  <span class="text-[var(--el-text-color-primary)] inline-block align-middle overflow-hidden text-ellipsis whitespace-nowrap max-w-[140px]">
+                  <span
+                    class="text-[var(--el-text-color-primary)] inline-block align-middle overflow-hidden text-ellipsis whitespace-nowrap max-w-[140px]">
                     {{ item.productKey }}
                   </span>
                 </div>
@@ -117,8 +113,7 @@
                 class="flex-1 !px-2 !h-[32px] text-[13px]"
                 plain
                 type="primary"
-                @click="openForm('update', item.id)"
-              >
+                @click="openForm('update', item.id)">
                 <Icon class="mr-1" icon="ep:edit-pen" />
                 编辑
               </el-button>
@@ -126,8 +121,7 @@
                 class="flex-1 !px-2 !h-[32px] !ml-[10px] text-[13px]"
                 plain
                 type="warning"
-                @click="openDetail(item.id)"
-              >
+                @click="openDetail(item.id)">
                 <Icon class="mr-1" icon="ep:view" />
                 详情
               </el-button>
@@ -135,8 +129,7 @@
                 class="flex-1 !px-2 !h-[32px] !ml-[10px] text-[13px]"
                 plain
                 type="success"
-                @click="openObjectModel(item)"
-              >
+                @click="openObjectModel(item)">
                 <Icon class="mr-1" icon="ep:scale-to-original" />
                 物模型
               </el-button>
@@ -147,8 +140,7 @@
                 class="!px-2 !h-[32px] text-[13px]"
                 plain
                 type="danger"
-                @click="handleDelete(item.id)"
-              >
+                @click="handleDelete(item.id)">
                 <Icon icon="ep:delete" />
               </el-button>
             </div>
@@ -158,60 +150,55 @@
     </el-row>
 
     <!-- 列表视图 -->
-    <el-table v-else v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
-      <el-table-column align="center" label="ID" prop="id" />
-      <el-table-column align="center" label="ProductKey" prop="productKey" />
-      <el-table-column align="center" label="品类" prop="categoryName" />
-      <el-table-column align="center" label="设备类型" prop="deviceType">
+    <zm-table v-else :loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
+      <zm-table-column align="center" label="ID" prop="id" />
+      <zm-table-column align="center" label="ProductKey" prop="productKey" />
+      <zm-table-column align="center" label="品类" prop="categoryName" />
+      <zm-table-column align="center" label="设备类型" prop="deviceType">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE" :value="scope.row.deviceType" />
         </template>
-      </el-table-column>
-      <el-table-column align="center" label="产品图标" prop="icon">
+      </zm-table-column>
+      <zm-table-column align="center" label="产品图标" prop="icon">
         <template #default="scope">
           <el-image
             v-if="scope.row.icon"
             :preview-src-list="[scope.row.icon]"
             :src="scope.row.icon"
-            class="w-40px h-40px"
-          />
+            class="w-40px h-40px" />
           <span v-else>-</span>
         </template>
-      </el-table-column>
-      <el-table-column align="center" label="产品图片" prop="picture">
+      </zm-table-column>
+      <zm-table-column align="center" label="产品图片" prop="picture">
         <template #default="scope">
           <el-image
             v-if="scope.row.picUrl"
             :preview-src-list="[scope.row.picture]"
             :src="scope.row.picUrl"
-            class="w-40px h-40px"
-          />
+            class="w-40px h-40px" />
           <span v-else>-</span>
         </template>
-      </el-table-column>
-      <el-table-column
+      </zm-table-column>
+      <zm-table-column
         :formatter="dateFormatter"
         align="center"
         label="创建时间"
         prop="createTime"
-        width="180px"
-      />
-      <el-table-column align="center" label="操作">
+        width="180px" />
+      <zm-table-column align="center" label="操作" action>
         <template #default="scope">
           <el-button
             v-hasPermi="['iot:product:query']"
             link
             type="primary"
-            @click="openDetail(scope.row.id)"
-          >
+            @click="openDetail(scope.row.id)">
             查看
           </el-button>
           <el-button
             v-hasPermi="['iot:product:update']"
             link
             type="primary"
-            @click="openForm('update', scope.row.id)"
-          >
+            @click="openForm('update', scope.row.id)">
             编辑
           </el-button>
           <el-button
@@ -219,21 +206,19 @@
             :disabled="scope.row.status === 1"
             link
             type="danger"
-            @click="handleDelete(scope.row.id)"
-          >
+            @click="handleDelete(scope.row.id)">
             删除
           </el-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </zm-table-column>
+    </zm-table>
 
     <!-- 分页 -->
     <Pagination
       v-model:limit="queryParams.pageSize"
       v-model:page="queryParams.pageNo"
       :total="total"
-      @pagination="getList"
-    />
+      @pagination="getList" />
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->

+ 1 - 1
src/views/iot/rule/data/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-tabs v-model="activeTab" type="border-card">
+  <el-tabs v-model="activeTab">
     <el-tab-pane label="规则" name="rule">
       <RuleIndex />
     </el-tab-pane>

+ 28 - 39
src/views/iot/rule/data/rule/index.vue

@@ -1,35 +1,31 @@
 <template>
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <!-- 搜索工作栏 -->
     <el-form
       class="-mb-15px"
       :model="queryParams"
       ref="queryFormRef"
       :inline="true"
-      label-width="68px"
-    >
+      label-width="68px">
       <el-form-item label="规则名称" prop="name">
         <el-input
           v-model="queryParams.name"
           placeholder="请输入规则名称"
           clearable
           @keyup.enter="handleQuery"
-          class="!w-240px"
-        />
+          class="!w-240px" />
       </el-form-item>
       <el-form-item label="规则状态" prop="status">
         <el-select
           v-model="queryParams.status"
           placeholder="请选择规则状态"
           clearable
-          class="!w-240px"
-        >
+          class="!w-240px">
           <el-option
             v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
             :key="dict.value"
             :label="dict.label"
-            :value="dict.value"
-          />
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
@@ -40,8 +36,7 @@
           start-placeholder="开始日期"
           end-placeholder="结束日期"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-220px"
-        />
+          class="!w-220px" />
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@@ -50,8 +45,7 @@
           type="primary"
           plain
           @click="openForm('create')"
-          v-hasPermi="['iot:data-rule:create']"
-        >
+          v-hasPermi="['iot:data-rule:create']">
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
       </el-form-item>
@@ -59,63 +53,58 @@
   </ContentWrap>
 
   <!-- 列表 -->
-  <ContentWrap>
-    <el-table
+  <ContentWrap style="border: none">
+    <zm-table
       row-key="id"
-      v-loading="loading"
+      :loading="loading"
       :data="list"
       :stripe="true"
-      :show-overflow-tooltip="true"
-    >
-      <el-table-column label="规则编号" align="center" prop="id" />
-      <el-table-column label="规则名称" align="center" prop="name" />
-      <el-table-column label="规则描述" align="center" prop="description" />
-      <el-table-column label="规则状态" align="center" prop="status">
+      :show-overflow-tooltip="true">
+      <zm-table-column label="规则编号" align="center" prop="id" />
+      <zm-table-column label="规则名称" align="center" prop="name" />
+      <zm-table-column label="规则描述" align="center" prop="description" />
+      <zm-table-column label="规则状态" align="center" prop="status">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
         </template>
-      </el-table-column>
-      <el-table-column label="数据源" align="center" prop="sourceConfigs">
+      </zm-table-column>
+      <zm-table-column label="数据源" align="center" prop="sourceConfigs">
         <template #default="scope"> {{ scope.row.sourceConfigs?.length || 0 }} 个 </template>
-      </el-table-column>
-      <el-table-column label="数据目的" align="center" prop="sinkIds">
+      </zm-table-column>
+      <zm-table-column label="数据目的" align="center" prop="sinkIds">
         <template #default="scope"> {{ scope.row.sinkIds?.length || 0 }} 个 </template>
-      </el-table-column>
-      <el-table-column
+      </zm-table-column>
+      <zm-table-column
         label="创建时间"
         align="center"
         prop="createTime"
         :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="操作" align="center" min-width="120px">
+        width="180px" />
+      <zm-table-column label="操作" align="center" min-width="120px" action>
         <template #default="scope">
           <el-button
             link
             type="primary"
             @click="openForm('update', scope.row.id)"
-            v-hasPermi="['iot:data-rule:update']"
-          >
+            v-hasPermi="['iot:data-rule:update']">
             编辑
           </el-button>
           <el-button
             link
             type="danger"
             @click="handleDelete(scope.row.id)"
-            v-hasPermi="['iot:data-rule:delete']"
-          >
+            v-hasPermi="['iot:data-rule:delete']">
             删除
           </el-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </zm-table-column>
+    </zm-table>
     <!-- 分页 -->
     <Pagination
       :total="total"
       v-model:page="queryParams.pageNo"
       v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
+      @pagination="getList" />
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->

+ 26 - 38
src/views/iot/rule/data/sink/index.vue

@@ -1,35 +1,31 @@
 <template>
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <!-- 搜索工作栏 -->
     <el-form
       ref="queryFormRef"
       :inline="true"
       :model="queryParams"
       class="-mb-15px"
-      label-width="68px"
-    >
+      label-width="68px">
       <el-form-item label="目的名称" prop="name">
         <el-input
           v-model="queryParams.name"
           class="!w-240px"
           clearable
           placeholder="请输入目的名称"
-          @keyup.enter="handleQuery"
-        />
+          @keyup.enter="handleQuery" />
       </el-form-item>
       <el-form-item label="目的状态" prop="status">
         <el-select
           v-model="queryParams.status"
           class="!w-240px"
           clearable
-          placeholder="请选择目的状态"
-        >
+          placeholder="请选择目的状态">
           <el-option
             v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
             :key="dict.value"
             :label="dict.label"
-            :value="dict.value"
-          />
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="目的类型" prop="type">
@@ -37,14 +33,12 @@
           v-model="queryParams.type"
           class="!w-240px"
           clearable
-          placeholder="请选择目的类型"
-        >
+          placeholder="请选择目的类型">
           <el-option
             v-for="dict in getIntDictOptions(DICT_TYPE.IOT_DATA_SINK_TYPE_ENUM)"
             :key="dict.value"
             :label="dict.label"
-            :value="dict.value"
-          />
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
@@ -55,8 +49,7 @@
           end-placeholder="结束日期"
           start-placeholder="开始日期"
           type="daterange"
-          value-format="YYYY-MM-DD HH:mm:ss"
-        />
+          value-format="YYYY-MM-DD HH:mm:ss" />
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery">
@@ -71,8 +64,7 @@
           v-hasPermi="['iot:data-sink:create']"
           plain
           type="primary"
-          @click="openForm('create')"
-        >
+          @click="openForm('create')">
           <Icon class="mr-5px" icon="ep:plus" />
           新增
         </el-button>
@@ -81,56 +73,52 @@
   </ContentWrap>
 
   <!-- 列表 -->
-  <ContentWrap>
-    <el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
-      <el-table-column align="center" label="目的编号" prop="id" />
-      <el-table-column align="center" label="目的名称" prop="name" />
-      <el-table-column align="center" label="目的描述" prop="description" />
-      <el-table-column align="center" label="目的状态" prop="status">
+  <ContentWrap style="border: none">
+    <zm-table :loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
+      <zm-table-column align="center" label="目的编号" prop="id" />
+      <zm-table-column align="center" label="目的名称" prop="name" />
+      <zm-table-column align="center" label="目的描述" prop="description" />
+      <zm-table-column align="center" label="目的状态" prop="status">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
         </template>
-      </el-table-column>
-      <el-table-column align="center" label="目的类型" prop="type">
+      </zm-table-column>
+      <zm-table-column align="center" label="目的类型" prop="type">
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.IOT_DATA_SINK_TYPE_ENUM" :value="scope.row.type" />
         </template>
-      </el-table-column>
-      <el-table-column
+      </zm-table-column>
+      <zm-table-column
         :formatter="dateFormatter"
         align="center"
         label="创建时间"
         prop="createTime"
-        width="180px"
-      />
-      <el-table-column align="center" fixed="right" label="操作" width="120px">
+        width="180px" />
+      <zm-table-column align="center" fixed="right" label="操作" width="120px" action>
         <template #default="scope">
           <el-button
             v-hasPermi="['iot:data-sink:update']"
             link
             type="primary"
-            @click="openForm('update', scope.row.id)"
-          >
+            @click="openForm('update', scope.row.id)">
             编辑
           </el-button>
           <el-button
             v-hasPermi="['iot:data-sink:delete']"
             link
             type="danger"
-            @click="handleDelete(scope.row.id)"
-          >
+            @click="handleDelete(scope.row.id)">
             删除
           </el-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </zm-table-column>
+    </zm-table>
     <!-- 分页 -->
     <Pagination
       v-model:limit="queryParams.pageSize"
       v-model:page="queryParams.pageNo"
       :total="total"
-      @pagination="getList"
-    />
+      @pagination="getList" />
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->

+ 36 - 46
src/views/iot/rule/scene/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <ContentWrap>
+  <ContentWrap style="border: none">
     <!-- 页面头部 -->
     <div class="flex justify-between items-start mb-20px">
       <div class="flex-1">
@@ -20,36 +20,32 @@
     </div>
 
     <!-- 搜索和筛选 -->
-    <el-card class="mb-16px" shadow="never">
+    <el-card class="mb-16px" shadow="never" style="border: none">
       <el-form
         ref="queryFormRef"
         :model="queryParams"
         :inline="true"
         label-width="80px"
-        @submit.prevent
-      >
+        @submit.prevent>
         <el-form-item label="规则名称">
           <el-input
             v-model="queryParams.name"
             placeholder="请输入规则名称"
             clearable
             @keyup.enter="handleQuery"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item label="规则状态">
           <el-select
             v-model="queryParams.status"
             placeholder="请选择状态"
             clearable
-            class="!w-240px"
-          >
+            class="!w-240px">
             <el-option
               v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
               :key="dict.value"
               :label="dict.label"
-              :value="dict.value"
-            />
+              :value="dict.value" />
           </el-select>
         </el-form-item>
         <el-form-item>
@@ -69,13 +65,12 @@
     <el-row :gutter="16" class="mb-16px">
       <el-col :span="6">
         <el-card
+          style="border: none"
           class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px"
-          shadow="hover"
-        >
+          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]"
-            >
+              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>
@@ -89,13 +84,12 @@
       </el-col>
       <el-col :span="6">
         <el-card
+          style="border: none"
           class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px"
-          shadow="hover"
-        >
+          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]"
-            >
+              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>
@@ -109,13 +103,12 @@
       </el-col>
       <el-col :span="6">
         <el-card
+          style="border: none"
           class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px"
-          shadow="hover"
-        >
+          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]"
-            >
+              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>
@@ -129,13 +122,12 @@
       </el-col>
       <el-col :span="6">
         <el-card
+          style="border: none"
           class="cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-2px"
-          shadow="hover"
-        >
+          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]"
-            >
+              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:timer" />
             </div>
             <div>
@@ -150,10 +142,10 @@
     </el-row>
 
     <!-- 数据表格 -->
-    <el-card class="mb-20px" shadow="never">
-      <el-table v-loading="loading" :data="list" stripe @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" />
-        <el-table-column label="规则名称" prop="name" min-width="200">
+    <el-card class="mb-20px" shadow="never" style="border: none">
+      <zm-table :loading="loading" :data="list" stripe @selection-change="handleSelectionChange">
+        <zm-table-column type="selection" width="55" />
+        <zm-table-column label="规则名称" prop="name" min-width="200">
           <template #default="{ row }">
             <div class="flex items-center gap-8px">
               <span class="font-500 text-[#303133]">{{ row.name }}</span>
@@ -163,9 +155,9 @@
               {{ row.description }}
             </div>
           </template>
-        </el-table-column>
+        </zm-table-column>
         <!-- 触发条件列 -->
-        <el-table-column label="触发条件" min-width="280">
+        <zm-table-column label="触发条件" min-width="280">
           <template #default="{ row }">
             <div class="space-y-4px">
               <div class="flex flex-wrap gap-4px">
@@ -188,9 +180,9 @@
               </div>
             </div>
           </template>
-        </el-table-column>
+        </zm-table-column>
         <!-- 执行动作列 -->
-        <el-table-column label="执行动作" min-width="250">
+        <zm-table-column label="执行动作" min-width="250">
           <template #default="{ row }">
             <div class="flex flex-wrap gap-4px">
               <el-tag type="success" size="small" class="m-0">
@@ -198,21 +190,21 @@
               </el-tag>
             </div>
           </template>
-        </el-table-column>
-        <el-table-column label="最近触发" prop="lastTriggeredTime" width="180">
+        </zm-table-column>
+        <zm-table-column label="最近触发" prop="lastTriggeredTime" width="180">
           <template #default="{ row }">
             <span v-if="row.lastTriggeredTime">
               {{ formatDate(row.lastTriggeredTime) }}
             </span>
             <span v-else class="text-gray-400">未触发</span>
           </template>
-        </el-table-column>
-        <el-table-column label="创建时间" prop="createTime" width="180">
+        </zm-table-column>
+        <zm-table-column label="创建时间" prop="createTime" width="180">
           <template #default="{ row }">
             {{ formatDate(row.createTime) }}
           </template>
-        </el-table-column>
-        <el-table-column label="操作" width="210" fixed="right">
+        </zm-table-column>
+        <zm-table-column label="操作" width="210" fixed="right" action>
           <template #default="{ row }">
             <div>
               <el-button type="primary" link @click="handleEdit(row)">
@@ -222,8 +214,7 @@
               <el-button
                 :type="row.status === 0 ? 'warning' : 'success'"
                 link
-                @click="handleToggleStatus(row)"
-              >
+                @click="handleToggleStatus(row)">
                 <Icon :icon="row.status === 0 ? 'ep:video-pause' : 'ep:video-play'" />
                 {{ getDictLabel(DICT_TYPE.COMMON_STATUS, row.status) }}
               </el-button>
@@ -233,16 +224,15 @@
               </el-button>
             </div>
           </template>
-        </el-table-column>
-      </el-table>
+        </zm-table-column>
+      </zm-table>
 
       <!-- 分页 -->
       <Pagination
         :total="total"
         v-model:page="queryParams.pageNo"
         v-model:limit="queryParams.pageSize"
-        @pagination="getList"
-      />
+        @pagination="getList" />
     </el-card>
 
     <!-- 表单对话框 -->