浏览代码

修改页面 建筑设备管理 组态信息 动态列表显示

bzd_lxf 2 天之前
父节点
当前提交
a94c6e8cae
共有 1 个文件被更改,包括 1691 次插入950 次删除
  1. 1691 950
      pm_ui/src/views/buildingEquipmentMonitoring/index.vue

+ 1691 - 950
pm_ui/src/views/buildingEquipmentMonitoring/index.vue

@@ -1,1231 +1,1972 @@
 <template>
   <div class="device-management-system">
     <!-- 查询条件区域 -->
-    <el-card class="filter-card">
-      <el-form :model="queryParams" ref="searchForm" :inline="true" class="search-form">
-        <el-form-item label="设备ID">
-          <el-input v-model="queryParams.deviceId" placeholder="请输入设备ID" clearable />
-        </el-form-item>
-
-        <el-form-item label="设备名称">
-          <el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable />
-        </el-form-item>
-
+    <div class="search-form">
+      <el-form :model="queryParams" ref="searchForm" :inline="true">
         <el-form-item label="设备类型">
-          <el-select v-model="queryParams.deviceType" placeholder="请选择设备类型" clearable style="width: 180px;">
-            <el-option label="全部" value="" />
-            <el-option label="控制器" value="CONTROLLER" />
-            <el-option label="传感器" value="SENSOR" />
-            <el-option label="执行器" value="ACTUATOR" />
-            <el-option label="广播设备" value="BROADCASTER" />
-            <el-option label="监控设备" value="MONITOR" />
-            <el-option label="报警设备" value="ALARM" />
-            <el-option label="输入设备" value="INPUT" />
+          <el-select
+              v-model="queryParams.device_type"
+              placeholder="请选择设备类型"
+              clearable
+              style="width: 240px;"
+              @change="handleDeviceTypeChange"
+              size="large"
+          >
+            <el-option
+                v-for="(label, value) in deviceTypes"
+                :key="value"
+                :label="`${label}(${value})`"
+                :value="value"
+            />
           </el-select>
         </el-form-item>
 
-        <el-form-item label="楼层">
-          <el-select v-model="queryParams.floor" placeholder="请选择楼层" clearable style="width: 180px;">
-            <el-option label="全部" value="" />
-            <el-option label="1楼" value="1F" />
-            <el-option label="2楼" value="2F" />
-            <el-option label="3楼" value="3F" />
-            <el-option label="4楼" value="4F" />
-            <el-option label="5楼" value="5F" />
-          </el-select>
+        <el-form-item>
+          <el-button
+              type="primary"
+              :icon="Search"
+              @click="handleSearch"
+              :loading="isLoading"
+              size="large"
+          >
+            搜索
+          </el-button>
+          <el-button
+              :icon="Refresh"
+              @click="resetSearch"
+              size="large"
+          >
+            重置
+          </el-button>
         </el-form-item>
+      </el-form>
+    </div>
 
-        <el-form-item label="区域">
-          <el-input v-model="queryParams.area" placeholder="请输入区域" clearable />
-        </el-form-item>
+    <!-- 数据表格区域 -->
+    <div class="table-container">
+      <!-- 表格头部 -->
+      <div class="table-header">
+        <div class="header-left">
+          <el-icon class="header-icon"><Monitor /></el-icon>
+          <span class="header-title">设备列表</span>
+        </div>
+        <div class="header-actions">
+          <el-tooltip content="刷新数据" placement="top">
+            <el-button
+                size="default"
+                :icon="Refresh"
+                @click="getList"
+                :loading="isLoading"
+                circle
+            />
+          </el-tooltip>
+          <el-tooltip :content="isCardView ? '切换到表格视图' : '切换到卡片视图'" placement="top">
+            <el-button
+                type="primary"
+                size="default"
+                :icon="View"
+                @click="toggleTableView"
+                circle
+            />
+          </el-tooltip>
+        </div>
+      </div>
 
-        <el-form-item label="运行状态">
-          <el-select v-model="queryParams.status" placeholder="请选择运行状态" clearable style="width: 180px;">
-            <el-option label="全部" value="" />
-            <el-option label="正常" value="正常" />
-            <el-option label="警告" value="警告" />
-            <el-option label="故障" value="故障" />
-            <el-option label="离线" value="离线" />
-          </el-select>
-        </el-form-item>
+      <!-- 默认空状态 -->
+      <div v-if="!queryParams.device_type" class="empty-state">
+        <div class="empty-content">
+          <div class="empty-icon">
+            <el-icon size="120"><Monitor /></el-icon>
+          </div>
+          <h3 class="empty-title">欢迎使用设备管理系统</h3>
+          <p class="empty-description">请选择设备类型开始查询设备信息</p>
+        </div>
+      </div>
 
-        <el-form-item>
-          <el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
-          <el-button :icon="Refresh" @click="resetSearch">重置</el-button>
-          <el-button type="success" :icon="Download" @click="exportData">导出</el-button>
-        </el-form-item>
-      </el-form>
-    </el-card>
-
-    <!-- 统计卡片 -->
-    <el-row :gutter="20" class="stats-row">
-      <el-col :span="6">
-        <el-card class="stats-card">
-          <el-statistic title="设备总数" :value="statsData.total">
-            <template #prefix>
-              <el-icon><Monitor /></el-icon>
-            </template>
-          </el-statistic>
-        </el-card>
-      </el-col>
-      <el-col :span="6">
-        <el-card class="stats-card normal">
-          <el-statistic title="正常运行" :value="statsData.normal">
-            <template #prefix>
-              <el-icon><CircleCheck /></el-icon>
+      <!-- 表格视图 -->
+      <div v-else-if="!isCardView" class="table-view">
+        <el-table
+            :data="deviceList"
+            v-loading="isLoading"
+            :height="tableHeight"
+            style="width: 100%"
+            @row-click="handleRowClick"
+            empty-text="暂无设备数据"
+            border
+            :row-class-name="tableRowClassName"
+            highlight-current-row
+        >
+          <el-table-column label="设备名称" width="200" fixed="left">
+            <template #default="scope">
+              <div class="device-info">
+                <div class="device-name">
+                  <el-link
+                      type="primary"
+                      @click.stop="handleRowClick(scope.row)"
+                  >
+                    {{ scope.row.deviceName }}
+                  </el-link>
+                </div>
+                <div class="device-type">{{ deviceTypes[queryParams.device_type] }}</div>
+              </div>
             </template>
-          </el-statistic>
-        </el-card>
-      </el-col>
-      <el-col :span="6">
-        <el-card class="stats-card warning">
-          <el-statistic title="警告设备" :value="statsData.warning">
-            <template #prefix>
-              <el-icon><Warning /></el-icon>
+          </el-table-column>
+
+          <!-- 动态列 -->
+          <el-table-column
+              v-for="column in dynamicColumns"
+              :key="column.prop"
+              :label="column.label"
+              :prop="column.prop"
+              :width="column.width"
+              align="center"
+              show-overflow-tooltip
+          >
+            <template #default="scope">
+              <div class="cell-content">
+                <div
+                    :class="['status-indicator', getCellClass(column.prop, scope.row[column.prop])]"
+                    v-if="column.type === 'status'"
+                >
+                  <el-tag
+                      :type="scope.row[column.prop] === '是' ? 'success' : 'info'"
+                      size="small"
+                  >
+                    <el-icon v-if="scope.row[column.prop] === '是'"><CircleCheck /></el-icon>
+                    <el-icon v-else><CircleClose /></el-icon>
+                    {{ scope.row[column.prop] }}
+                  </el-tag>
+                </div>
+                <div
+                    v-else-if="column.type === 'number'"
+                    :class="['number-display', getNumberClass(column.prop, scope.row[column.prop])]"
+                >
+                  <span class="number-value">{{ formatNumber(scope.row[column.prop]) }}</span>
+                  <span class="unit" v-if="column.unit">{{ column.unit }}</span>
+                </div>
+                <span v-else class="text-value">{{ scope.row[column.prop] }}</span>
+              </div>
             </template>
-          </el-statistic>
-        </el-card>
-      </el-col>
-      <el-col :span="6">
-        <el-card class="stats-card error">
-          <el-statistic title="故障设备" :value="statsData.fault">
-            <template #prefix>
-              <el-icon><CircleClose /></el-icon>
+          </el-table-column>
+
+          <el-table-column label="操作" width="200" fixed="right" align="center">
+            <template #default="scope">
+              <el-button
+                  type="primary"
+                  size="small"
+                  @click.stop="handleView(scope.row)"
+                  icon="View"
+              >
+                详情
+              </el-button>
+              <el-button
+                  type="success"
+                  size="small"
+                  @click.stop="handleViewConfiguration(scope.row)"
+                  icon="Setting"
+              >
+                组态信息
+              </el-button>
             </template>
-          </el-statistic>
-        </el-card>
-      </el-col>
-    </el-row>
+          </el-table-column>
+        </el-table>
+      </div>
 
-    <!-- 数据表格区域 -->
-    <el-card class="data-table">
-      <template #header>
-        <div class="card-header">
-          <span>设备列表</span>
-          <div class="header-actions">
-            <el-button type="primary" size="small" :icon="Plus" @click="handleAdd">新增设备</el-button>
-            <el-button size="small" :icon="Refresh" @click="getList" :loading="isLoading">刷新</el-button>
+      <!-- 卡片视图 -->
+      <div v-else class="card-view">
+        <div class="cards-grid">
+          <div
+              v-for="device in deviceList"
+              :key="device.deviceName"
+              class="device-card-wrapper"
+          >
+            <el-card class="device-card" @click="handleRowClick(device)">
+              <template #header>
+                <div class="device-card-header">
+                  <div class="device-title">
+                    <div class="device-avatar-large">
+                      <el-icon class="device-type-icon"><Monitor /></el-icon>
+                    </div>
+                    <div class="device-info">
+                      <h4 class="device-name">{{ device.deviceName }}</h4>
+                      <p class="device-type">{{ deviceTypes[queryParams.device_type] }}</p>
+                    </div>
+                  </div>
+                  <el-tag
+                      :type="getDeviceStatusType(device)"
+                      size="large"
+                      effect="dark"
+                  >
+                    {{ getDeviceStatus(device) }}
+                  </el-tag>
+                </div>
+              </template>
+
+              <div class="device-card-content">
+                <div class="parameters-grid">
+                  <div
+                      v-for="(value, key) in getCardDisplayData(device)"
+                      :key="key"
+                      class="parameter-item"
+                  >
+                    <div class="parameter-label">{{ key }}</div>
+                    <div class="parameter-value" :class="getCellClass(key, value)">
+                      {{ formatCardValue(key, value) }}
+                    </div>
+                  </div>
+                </div>
+              </div>
+
+              <template #footer>
+                <div class="device-card-actions">
+                  <el-button
+                      type="primary"
+                      size="default"
+                      @click.stop="handleView(device)"
+                  >
+                    <el-icon><View /></el-icon>
+                    查看详情
+                  </el-button>
+                  <el-button
+                      type="success"
+                      size="default"
+                      @click.stop="handleViewConfiguration(device)"
+                  >
+                    <el-icon><Setting /></el-icon>
+                    组态信息
+                  </el-button>
+                </div>
+              </template>
+            </el-card>
           </div>
         </div>
-      </template>
 
-      <el-table
-          :data="deviceList"
-          border
-          v-loading="isLoading"
-          row-key="deviceId"
-          @row-click="handleRowClick"
-          :height="tableHeight"
-          style="width: 100%"
-      >
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="设备ID" prop="deviceId" align="center" width="140" fixed>
-          <template #default="scope">
-            <el-link type="primary" @click.stop="handleRowClick(scope.row)">
-              {{ scope.row.deviceId }}
-            </el-link>
-          </template>
-        </el-table-column>
-        <el-table-column label="设备名称" prop="deviceName" align="center" width="160" show-overflow-tooltip />
-        <el-table-column label="设备类型" prop="deviceType" align="center" width="120">
-          <template #default="scope">
-            <el-tag :type="getDeviceTypeTag(scope.row.deviceType)">
-              {{ mapDeviceType(scope.row.deviceType) }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="型号" prop="model" align="center" width="140" show-overflow-tooltip />
-        <el-table-column label="安装位置" align="center" min-width="200">
-          <template #default="scope">
-            <div class="location-info">
-              <el-icon><Location /></el-icon>
-              <span>{{ scope.row.floor }}-{{ scope.row.area }}</span>
-            </div>
-            <div class="location-detail">{{ scope.row.location }}</div>
-          </template>
-        </el-table-column>
-        <el-table-column label="运行状态" align="center" width="120">
-          <template #default="scope">
-            <div class="status-wrapper">
-              <span class="status-dot" :class="getStatusClass(scope.row.status)"></span>
-              <span>{{ scope.row.status }}</span>
-            </div>
-          </template>
-        </el-table-column>
-        <el-table-column label="当前告警" align="center" width="180">
-          <template #default="scope">
-            <el-tooltip v-if="scope.row.alarmCode" :content="scope.row.alarmDescription" placement="top">
-              <el-tag type="danger" size="small">
-                <el-icon><Warning /></el-icon>
-                {{ scope.row.alarmCode }}
-              </el-tag>
-            </el-tooltip>
-            <span v-else class="no-alarm">无告警</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="最后更新" prop="lastUpdateTime" align="center" width="160">
-          <template #default="scope">
-            {{ formatTime(scope.row.lastUpdateTime) }}
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" width="200" fixed="right">
-          <template #default="scope">
-            <el-button type="primary" link size="small" @click.stop="handleView3D(scope.row)">
-              <el-icon><View /></el-icon>
-              3D查看
-            </el-button>
-            <el-button type="warning" link size="small" @click.stop="handleControl(scope.row)">
-              <el-icon><Operation /></el-icon>
-              控制
-            </el-button>
-            <el-button type="danger" link size="small" @click.stop="handleDelete(scope.row)">
-              <el-icon><Delete /></el-icon>
-              删除
-            </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
+        <div v-if="deviceList.length === 0 && !isLoading" class="empty-result">
+          <el-empty description="暂无设备数据">
+            <template #image>
+              <div class="empty-image">
+                <el-icon size="80"><Monitor /></el-icon>
+              </div>
+            </template>
+          </el-empty>
+        </div>
+      </div>
 
       <!-- 分页组件 -->
-      <el-pagination
-          v-show="total > 0"
-          v-model:current-page="queryParams.pageNum"
-          v-model:page-size="queryParams.pageSize"
-          :page-sizes="[10, 20, 50, 100]"
-          :total="total"
-          layout="total, sizes, prev, pager, next, jumper"
-          @size-change="handleSizeChange"
-          @current-change="handlePageChange"
-          class="pagination-container"
-      />
-    </el-card>
-
-    <!-- 详情弹窗 -->
+      <div v-show="total > 0" class="pagination-container">
+        <el-pagination
+            v-model:current-page="queryParams.pageNum"
+            v-model:page-size="queryParams.pageSize"
+            :page-sizes="[10, 20, 50, 100]"
+            :total="total"
+            layout="total, sizes, prev, pager, next, jumper"
+            @size-change="handleSizeChange"
+            @current-change="handlePageChange"
+            background
+        />
+      </div>
+    </div>
+
+    <!-- 设备详情弹窗 -->
     <el-dialog
         v-model="detailDialogOpen"
         title="设备详情"
         width="900px"
+        top="5vh"
         destroy-on-close
+        class="detail-dialog"
     >
-      <el-tabs v-model="activeTab" type="card">
+      <div v-if="currentDevice" class="device-detail">
         <!-- 基本信息 -->
-        <el-tab-pane label="基本信息" name="basic">
-          <el-descriptions :column="2" border>
-            <el-descriptions-item label="设备ID">
-              <el-tag>{{ detailDevice.deviceId }}</el-tag>
+        <div class="detail-section">
+          <h3>基本信息</h3>
+          <el-descriptions :column="3" border>
+            <el-descriptions-item label="设备名称" :span="2">
+              <el-tag type="primary" size="large" effect="dark">
+                {{ currentDevice.deviceName }}
+              </el-tag>
             </el-descriptions-item>
-            <el-descriptions-item label="设备名称">{{ detailDevice.deviceName }}</el-descriptions-item>
             <el-descriptions-item label="设备类型">
-              <el-tag :type="getDeviceTypeTag(detailDevice.deviceType)">
-                {{ mapDeviceType(detailDevice.deviceType) }}
-              </el-tag>
+              <span>{{ deviceTypes[queryParams.device_type] || '未知' }}</span>
             </el-descriptions-item>
-            <el-descriptions-item label="型号">{{ detailDevice.model }}</el-descriptions-item>
-            <el-descriptions-item label="制造商">{{ detailDevice.manufacturer || '未知' }}</el-descriptions-item>
-            <el-descriptions-item label="序列号">{{ detailDevice.serialNumber || '未知' }}</el-descriptions-item>
-            <el-descriptions-item label="安装位置" :span="2">
-              <el-icon><Location /></el-icon>
-              {{ detailDevice.floor }}-{{ detailDevice.area }} ({{ detailDevice.location }})
+            <el-descriptions-item label="设备状态" :span="3">
+              <el-tag :type="getDeviceStatusType(currentDevice)" size="large" effect="dark">
+                <el-icon style="margin-right: 4px;">
+                  <CircleCheck v-if="getDeviceStatus(currentDevice) === '运行中'" />
+                  <Warning v-else-if="getDeviceStatus(currentDevice) === '故障'" />
+                  <Monitor v-else />
+                </el-icon>
+                {{ getDeviceStatus(currentDevice) }}
+              </el-tag>
             </el-descriptions-item>
-            <el-descriptions-item label="安装日期">{{ formatDate(detailDevice.installDate) }}</el-descriptions-item>
-            <el-descriptions-item label="维保到期">{{ formatDate(detailDevice.maintenanceDate) }}</el-descriptions-item>
           </el-descriptions>
-        </el-tab-pane>
-
-        <!-- 运行状态 -->
-        <el-tab-pane label="运行状态" name="status">
-          <el-row :gutter="20">
-            <el-col :span="12">
-              <el-card>
-                <template #header>
-                  <span>当前状态</span>
-                </template>
-                <div class="status-display">
-                  <div class="status-item">
-                    <span class="label">运行状态:</span>
-                    <div class="status-wrapper">
-                      <span class="status-dot" :class="getStatusClass(detailDevice.status)"></span>
-                      <span>{{ detailDevice.status }}</span>
-                    </div>
-                  </div>
-                  <div class="status-item">
-                    <span class="label">在线状态:</span>
-                    <el-tag :type="detailDevice.isOnline ? 'success' : 'danger'">
-                      {{ detailDevice.isOnline ? '在线' : '离线' }}
-                    </el-tag>
-                  </div>
-                  <div class="status-item">
-                    <span class="label">最后更新:</span>
-                    <span>{{ formatTime(detailDevice.lastUpdateTime) }}</span>
-                  </div>
-                </div>
-              </el-card>
-            </el-col>
-            <el-col :span="12">
-              <el-card>
-                <template #header>
-                  <span>告警信息</span>
-                </template>
-                <div v-if="detailDevice.alarmCode" class="alarm-info">
-                  <el-alert
-                      :title="detailDevice.alarmDescription"
-                      type="error"
-                      :closable="false"
-                      show-icon
-                  />
-                  <div class="alarm-details">
-                    <div>告警代码: {{ detailDevice.alarmCode }}</div>
-                    <div>触发时间: {{ formatTime(detailDevice.triggerTime) }}</div>
-                    <div>告警级别: {{ detailDevice.alarmLevel || '高' }}</div>
-                  </div>
-                </div>
-                <el-empty v-else description="暂无告警" />
-              </el-card>
-            </el-col>
-          </el-row>
-        </el-tab-pane>
-
-        <!-- 3D模型 -->
-        <el-tab-pane label="3D模型" name="model">
-          <div class="model-viewer">
-            <div class="model-preview" ref="modelContainer">
-              <!-- 这里可以集成 Three.js 或其他3D库来显示模型 -->
-              <el-empty description="3D模型预览区域">
-                <el-button type="primary" @click="load3DModel">加载3D模型</el-button>
-              </el-empty>
-            </div>
-            <div class="model-info">
-              <el-descriptions :column="1" border size="small">
-                <el-descriptions-item label="模型文件">
-                  <el-link type="primary" @click="downloadModel">
-                    {{ detailDevice.modelPath || '暂无模型文件' }}
-                  </el-link>
-                </el-descriptions-item>
-                <el-descriptions-item label="动画参数">
-                  <pre class="json-display">{{ formatJson(detailDevice.animationParams) }}</pre>
-                </el-descriptions-item>
-              </el-descriptions>
-            </div>
-          </div>
-        </el-tab-pane>
-
-        <!-- 控制面板 -->
-        <el-tab-pane label="控制面板" name="control">
-          <el-card>
-            <el-descriptions :column="2" border class="mb-4">
-              <el-descriptions-item label="控制协议">{{ detailDevice.controlProtocol }}</el-descriptions-item>
-              <el-descriptions-item label="指令集">{{ detailDevice.commandSet }}</el-descriptions-item>
-              <el-descriptions-item label="通信地址">{{ detailDevice.commAddress || '192.168.1.100' }}</el-descriptions-item>
-              <el-descriptions-item label="通信端口">{{ detailDevice.commPort || '8080' }}</el-descriptions-item>
-            </el-descriptions>
-
-            <div class="control-panel">
-              <h4>快速控制</h4>
-              <el-row :gutter="20">
-                <el-col :span="8" v-for="cmd in quickCommands" :key="cmd.id">
-                  <el-button
-                      :type="cmd.type"
-                      :icon="cmd.icon"
-                      @click="sendCommand(cmd)"
-                      :loading="cmd.loading"
-                      class="control-btn"
-                  >
-                    {{ cmd.name }}
-                  </el-button>
-                </el-col>
-              </el-row>
-
-              <el-divider />
-
-              <h4>参数调节</h4>
-              <el-form :model="controlParams" label-width="100px">
-                <el-form-item label="运行模式">
-                  <el-select v-model="controlParams.mode" @change="handleModeChange">
-                    <el-option label="自动" value="auto" />
-                    <el-option label="手动" value="manual" />
-                    <el-option label="定时" value="timer" />
-                  </el-select>
-                </el-form-item>
-                <el-form-item label="功率调节">
-                  <el-slider
-                      v-model="controlParams.power"
-                      :min="0"
-                      :max="100"
-                      :marks="{ 0: '0%', 50: '50%', 100: '100%' }"
-                      @change="handlePowerChange"
-                  />
-                </el-form-item>
-                <el-form-item label="温度设定" v-if="detailDevice.deviceType === 'CONTROLLER'">
-                  <el-input-number
-                      v-model="controlParams.temperature"
-                      :min="16"
-                      :max="30"
-                      @change="handleTempChange"
-                  />
-                  <span class="unit">°C</span>
-                </el-form-item>
-              </el-form>
-            </div>
-          </el-card>
-        </el-tab-pane>
-
-        <!-- 历史记录 -->
-        <el-tab-pane label="历史记录" name="history">
-          <el-table :data="historyData" border size="small" max-height="400">
-            <el-table-column label="时间" prop="time" width="180">
+        </div>
+
+        <!-- 参数表格 -->
+        <div class="detail-section">
+          <h3>设备参数</h3>
+          <el-table
+              :data="getDetailTableData(currentDevice)"
+              border
+              max-height="450"
+          >
+            <el-table-column label="参数名称" prop="name" width="200">
               <template #default="scope">
-                {{ formatTime(scope.row.time) }}
+                <div class="param-name">
+                  <el-icon class="param-icon"><Setting /></el-icon>
+                  <span>{{ scope.row.name }}</span>
+                </div>
               </template>
             </el-table-column>
-            <el-table-column label="操作类型" prop="type" width="120">
+            <el-table-column label="当前值" prop="value" align="center">
               <template #default="scope">
-                <el-tag :type="getHistoryTypeTag(scope.row.type)" size="small">
-                  {{ scope.row.type }}
-                </el-tag>
+                <div class="param-value-cell">
+              <span :class="['param-value', getCellClass(scope.row.name, scope.row.value)]">
+                {{ formatDetailValue(scope.row.name, scope.row.value) }}
+              </span>
+                  <span v-if="scope.row.unit" class="param-unit">{{ scope.row.unit }}</span>
+                </div>
               </template>
             </el-table-column>
-            <el-table-column label="操作内容" prop="content" show-overflow-tooltip />
-            <el-table-column label="操作人" prop="operator" width="120" />
-            <el-table-column label="结果" prop="result" width="100">
+            <el-table-column label="状态" prop="status" width="120" align="center">
               <template #default="scope">
-                <el-tag :type="scope.row.result === '成功' ? 'success' : 'danger'" size="small">
-                  {{ scope.row.result }}
+                <el-tag
+                    :type="scope.row.status === '正常' ? 'success' : 'warning'"
+                    size="default"
+                    effect="dark"
+                >
+                  <el-icon style="margin-right: 4px;">
+                    <CircleCheck v-if="scope.row.status === '正常'" />
+                    <Warning v-else />
+                  </el-icon>
+                  {{ scope.row.status }}
                 </el-tag>
               </template>
             </el-table-column>
           </el-table>
-        </el-tab-pane>
-      </el-tabs>
-
+        </div>
+      </div>
       <template #footer>
-        <el-button @click="detailDialogOpen = false">关闭</el-button>
-        <el-button type="primary" @click="saveDeviceInfo">保存</el-button>
+        <div class="dialog-footer">
+          <el-button @click="detailDialogOpen = false">关闭</el-button>
+        </div>
       </template>
     </el-dialog>
 
-    <!-- 3D查看弹窗 -->
+    <!-- 组态信息弹窗 -->
     <el-dialog
-        v-model="view3DDialogOpen"
-        :title="`3D视图 - ${current3DDevice.deviceName}`"
-        width="90%"
-        top="5vh"
-        destroy-on-close
+        v-model="configurationDialogOpen"
+        :title="`组态信息 - ${currentConfigDevice?.deviceName || ''}`"
+        top="16vh"
     >
-      <div class="three-d-viewer">
-        <div class="viewer-toolbar">
-          <el-button-group>
-            <el-button @click="resetView" :icon="Refresh">重置视角</el-button>
-            <el-button @click="toggleRotation" :icon="rotationEnabled ? VideoPause : VideoPlay">
-              {{ rotationEnabled ? '停止' : '开始' }}旋转
-            </el-button>
-            <el-button @click="toggleWireframe" :icon="View">
-              {{ wireframeMode ? '实体' : '线框' }}模式
-            </el-button>
-          </el-button-group>
-          <el-button type="primary" @click="fullscreen3D" :icon="FullScreen">全屏</el-button>
-        </div>
-        <div class="viewer-container" ref="viewer3D">
-          <!-- Three.js 渲染容器 -->
-          <canvas ref="canvas3D"></canvas>
-        </div>
-        <div class="viewer-info">
-          <el-descriptions :column="4" size="small">
-            <el-descriptions-item label="设备ID">{{ current3DDevice.deviceId }}</el-descriptions-item>
-            <el-descriptions-item label="当前状态">
-              <el-tag :type="getStatusTagType(current3DDevice.status)">
-                {{ current3DDevice.status }}
-              </el-tag>
-            </el-descriptions-item>
-            <el-descriptions-item label="温度">{{ current3DDevice.temperature || 25 }}°C</el-descriptions-item>
-            <el-descriptions-item label="运行时长">{{ current3DDevice.runTime || '120' }}小时</el-descriptions-item>
-          </el-descriptions>
-        </div>
+      <div class="configuration-iframe-container">
+        <iframe
+            v-if="currentVideoUrl"
+            :src="currentVideoUrl"
+            class="configuration-iframe"
+            frameborder="0"
+            allowfullscreen
+        ></iframe>
       </div>
-    </el-dialog>
-
-    <!-- 控制弹窗 -->
-    <el-dialog
-        v-model="controlDialogOpen"
-        :title="`设备控制 - ${currentControlDevice.deviceName}`"
-        width="600px"
-    >
-      <el-alert
-          title="请谨慎操作,错误的控制指令可能导致设备损坏"
-          type="warning"
-          show-icon
-          :closable="false"
-          class="mb-4"
-      />
-
-      <el-form :model="remoteControlForm" label-width="120px">
-        <el-form-item label="控制指令">
-          <el-select v-model="remoteControlForm.command" placeholder="请选择控制指令">
-            <el-option label="开机" value="POWER_ON" />
-            <el-option label="关机" value="POWER_OFF" />
-            <el-option label="重启" value="RESTART" />
-            <el-option label="复位" value="RESET" />
-            <el-option label="紧急停止" value="EMERGENCY_STOP" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="执行延时">
-          <el-input-number v-model="remoteControlForm.delay" :min="0" :max="60" />
-          <span class="unit">秒</span>
-        </el-form-item>
-        <el-form-item label="备注">
-          <el-input
-              v-model="remoteControlForm.remark"
-              type="textarea"
-              :rows="3"
-              placeholder="请输入操作备注"
-          />
-        </el-form-item>
-      </el-form>
 
       <template #footer>
-        <el-button @click="controlDialogOpen = false">取消</el-button>
-        <el-button type="primary" @click="executeControl" :loading="controlLoading">
-          执行控制
-        </el-button>
+        <div class="dialog-footer">
+          <el-button @click="configurationDialogOpen = false">关闭</el-button>
+          <el-button type="primary" @click="refreshConfiguration">
+            <el-icon><Refresh /></el-icon>
+            刷新
+          </el-button>
+        </div>
       </template>
     </el-dialog>
   </div>
 </template>
 
-<script setup>
-import { ref, reactive, computed, onMounted, onUnmounted } from 'vue';
-import { ElMessage, ElMessageBox } from 'element-plus';
+<script setup name="BuildingEquipmentMonitoring">
+import { ref, reactive, onMounted } from 'vue';
+import { ElMessage } from 'element-plus';
 import {
   Search,
   Refresh,
-  Download,
   Monitor,
   CircleCheck,
-  Warning,
   CircleClose,
-  Plus,
   View,
-  Operation,
-  Delete,
-  Location,
-  VideoPlay,
-  VideoPause,
-  FullScreen
+  Setting,
+  Warning,
+  Close
 } from '@element-plus/icons-vue';
-import { getBuildingEquipmentMonitoringList } from "@/api/buildingEquipmentMonitoring/buildingEquipmentMonitoring";
-// import * as THREE from 'three'; // 如果使用Three.js
-
-// 状态管理
-const queryParams = reactive({
-  deviceId: '',
-  deviceName: '',
-  deviceType: '',
-  floor: '',
-  area: '',
-  status: '',
-  pageNum: 1,
-  pageSize: 10,
-  interfaceName: "三维设备监控中心"
-});
+import axios from 'axios';
 
+// 响应式数据
+const deviceTypes = ref({});
 const deviceList = ref([]);
 const total = ref(0);
 const isLoading = ref(false);
 const detailDialogOpen = ref(false);
-const view3DDialogOpen = ref(false);
-const controlDialogOpen = ref(false);
-const detailDevice = ref({});
-const current3DDevice = ref({});
-const currentControlDevice = ref({});
-const activeTab = ref('basic');
+const currentDevice = ref({});
+const dynamicColumns = ref([]);
 const tableHeight = ref(600);
-const rotationEnabled = ref(true);
-const wireframeMode = ref(false);
-const controlLoading = ref(false);
-
-// 统计数据
-const statsData = computed(() => {
-  const stats = {
-    total: deviceList.value.length,
-    normal: 0,
-    warning: 0,
-    fault: 0
-  };
-
-  deviceList.value.forEach(device => {
-    if (device.status === '正常') stats.normal++;
-    else if (device.status === '警告') stats.warning++;
-    else if (device.status === '故障') stats.fault++;
-  });
+const isCardView = ref(false);
 
-  return stats;
-});
+// 组态信息相关
+const configurationDialogOpen = ref(false);
+const currentConfigDevice = ref(null);
+const currentVideoUrl = ref('');
 
-// 快速控制命令
-const quickCommands = ref([
-  { id: 1, name: '启动', type: 'success', icon: VideoPlay, loading: false },
-  { id: 2, name: '停止', type: 'danger', icon: VideoPause, loading: false },
-  { id: 3, name: '重启', type: 'warning', icon: Refresh, loading: false }
-]);
-
-// 控制参数
-const controlParams = reactive({
-  mode: 'auto',
-  power: 50,
-  temperature: 25
+// 查询参数
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  device_type: ''
 });
 
-// 远程控制表单
-const remoteControlForm = reactive({
-  command: '',
-  delay: 0,
-  remark: ''
+// 生命周期
+onMounted(() => {
+  loadDeviceTypes();
+  calculateTableHeight();
+  window.addEventListener('resize', calculateTableHeight);
 });
 
-// 历史记录数据
-const historyData = ref([
-  { time: new Date(), type: '状态变更', content: '设备启动', operator: '系统', result: '成功' },
-  { time: new Date(Date.now() - 3600000), type: '参数调整', content: '温度设定从23°C调整到25°C', operator: '张开阳', result: '成功' },
-  { time: new Date(Date.now() - 7200000), type: '告警处理', content: '清除温度过高告警', operator: '李中仁', result: '成功' }
-]);
-
 // 计算表格高度
 const calculateTableHeight = () => {
   const windowHeight = window.innerHeight;
-  tableHeight.value = windowHeight - 420; // 考虑统计卡片的高度
+  tableHeight.value = windowHeight - 400;
 };
 
-onMounted(() => {
-  calculateTableHeight();
-  window.addEventListener('resize', calculateTableHeight);
-  getList();
-  // 初始化3D场景
-  // init3DScene();
-});
-
-onUnmounted(() => {
-  window.removeEventListener('resize', calculateTableHeight);
-  // 清理3D资源
-  // cleanup3DScene();
-});
-
-// 获取数据
-const getList = async () => {
-  isLoading.value = true;
+// 加载设备类型
+const loadDeviceTypes = async () => {
   try {
-    const response = await getBuildingEquipmentMonitoringList(queryParams);
-    let filteredData = response.data.list || [];
-
-    // 应用过滤条件
-    if (queryParams.deviceId) {
-      filteredData = filteredData.filter(item =>
-          item.deviceId.toLowerCase().includes(queryParams.deviceId.toLowerCase())
-      );
-    }
-
-    if (queryParams.deviceName) {
-      filteredData = filteredData.filter(item =>
-          item.deviceName.toLowerCase().includes(queryParams.deviceName.toLowerCase())
-      );
-    }
-
-    if (queryParams.deviceType) {
-      filteredData = filteredData.filter(item => item.deviceType === queryParams.deviceType);
-    }
-
-    if (queryParams.floor) {
-      filteredData = filteredData.filter(item => item.floor === queryParams.floor);
+    const response = await axios.get(`${__LOCAL_API__}/intell/deviceType`);
+    if (response.data.code === 200) {
+      deviceTypes.value = response.data.data;
     }
+  } catch (error) {
+    ElMessage.error('加载设备类型失败');
+    console.error(error);
+  }
+};
 
-    if (queryParams.area) {
-      filteredData = filteredData.filter(item =>
-          item.area.toLowerCase().includes(queryParams.area.toLowerCase())
-      );
-    }
+// 获取设备列表
+const getList = async () => {
+  if (!queryParams.device_type) {
+    ElMessage.warning('请先选择设备类型');
+    return;
+  }
 
-    if (queryParams.status) {
-      filteredData = filteredData.filter(item => item.status === queryParams.status);
+  isLoading.value = true;
+  try {
+    const params = {
+      pageNum: queryParams.pageNum,
+      pageSize: queryParams.pageSize,
+      device_type: queryParams.device_type
+    };
+
+    const response = await axios.get(`${__LOCAL_API__}/intell/getDevices`, { params });
+
+    if (response.data.code === 200) {
+      const { data, total: totalCount } = response.data;
+      total.value = totalCount;
+
+      // 转换数据格式
+      const convertedData = Object.entries(data).map(([deviceName, deviceData]) => ({
+        deviceName,
+        ...deviceData
+      }));
+
+      deviceList.value = convertedData;
+      generateDynamicColumns(convertedData);
     }
-
-    // 添加额外的模拟数据
-    filteredData = filteredData.map(item => ({
-      ...item,
-      isOnline: Math.random() > 0.1,
-      lastUpdateTime: new Date(Date.now() - Math.random() * 3600000),
-      temperature: 20 + Math.random() * 10,
-      runTime: Math.floor(Math.random() * 1000),
-      manufacturer: ['西门子', '施耐德', 'ABB', '霍尼韦尔'][Math.floor(Math.random() * 4)],
-      serialNumber: `SN${Date.now().toString().slice(-8)}`,
-      installDate: new Date(Date.now() - Math.random() * 365 * 24 * 3600000),
-      maintenanceDate: new Date(Date.now() + Math.random() * 365 * 24 * 3600000),
-      commAddress: `192.168.1.${Math.floor(Math.random() * 255)}`,
-      commPort: 8080 + Math.floor(Math.random() * 100)
-    }));
-
-    total.value = filteredData.length;
-
-    // 分页处理
-    const start = (queryParams.pageNum - 1) * queryParams.pageSize;
-    const end = start + queryParams.pageSize;
-    deviceList.value = filteredData.slice(start, end);
-
   } catch (error) {
     ElMessage.error('获取设备数据失败');
-    console.error(error);
   } finally {
     isLoading.value = false;
   }
 };
 
-// 搜索
-const handleSearch = () => {
-  queryParams.pageNum = 1;
-  getList();
+// 获取组态信息 - 简化版本,只设置URL
+const getConfigurationInfo = async (device) => {
+  // 构建组态信息URL
+  currentVideoUrl.value = `${__LOCAL_API__}/intell/configurationDiagram?id=${queryParams.device_type}-${device.deviceName}`;
 };
 
-// 重置
-const resetSearch = () => {
-  Object.keys(queryParams).forEach(key => {
-    if (key !== 'pageNum' && key !== 'pageSize' && key !== 'interfaceName') {
-      queryParams[key] = '';
+// 刷新组态信息
+const refreshConfiguration = () => {
+  if (currentConfigDevice.value && currentVideoUrl.value) {
+    // 通过重新设置src来刷新iframe
+    const iframe = document.querySelector('.configuration-iframe');
+    if (iframe) {
+      const currentSrc = iframe.src;
+      iframe.src = '';
+      setTimeout(() => {
+        iframe.src = currentSrc;
+      }, 100);
     }
-  });
-  queryParams.pageNum = 1;
-  getList();
+  }
 };
 
-// 分页
-const handlePageChange = (newPage) => {
-  queryParams.pageNum = newPage;
-  getList();
-};
+// 生成动态表格列
+const generateDynamicColumns = (data) => {
+  if (data.length === 0) {
+    dynamicColumns.value = [];
+    return;
+  }
 
-const handleSizeChange = (newSize) => {
-  queryParams.pageSize = newSize;
-  queryParams.pageNum = 1;
-  getList();
-};
+  const columns = [];
+  const firstDevice = data[0];
 
-// 行点击事件
-const handleRowClick = (row) => {
-  detailDevice.value = JSON.parse(JSON.stringify(row));
-  detailDialogOpen.value = true;
-  activeTab.value = 'basic';
+  Object.keys(firstDevice).forEach(key => {
+    if (key === 'deviceName') return;
+
+    const column = {
+      prop: key,
+      label: key,
+      width: getColumnWidth(key),
+      type: getColumnType(key),
+      unit: getColumnUnit(key)
+    };
+
+    columns.push(column);
+  });
+
+  dynamicColumns.value = columns;
 };
 
-// 新增设备
-const handleAdd = () => {
-  ElMessage.info('新增设备功能开发中...');
+// 获取列宽度
+const getColumnWidth = (columnName) => {
+  const widthMap = {
+    '冬夏季模式': 120,
+    '运行状态': 120,
+    '自动状态': 120,
+    '故障报警': 120,
+    '过滤网压差': 120,
+    '防冻开关': 120,
+    '风机压差': 120,
+    '送风温度': 120,
+    '回风温度': 120,
+    '新风温度': 120,
+    '送风湿度': 120,
+    '回风二氧化碳': 140,
+    '水阀反馈': 120,
+    '回风阀反馈': 120,
+    '新风阀反馈': 120
+  };
+  return widthMap[columnName] || 130;
 };
 
-// 查看3D
-const handleView3D = (row) => {
-  current3DDevice.value = row;
-  view3DDialogOpen.value = true;
-  // 初始化3D模型
-  setTimeout(() => {
-    init3DModel(row);
-  }, 100);
+// 获取列类型
+const getColumnType = (columnName) => {
+  const statusColumns = ['冬夏季模式', '运行状态', '自动状态', '故障报警', '过滤网压差', '防冻开关', '风机压差'];
+  const numberColumns = ['送风温度', '回风温度', '新风温度', '送风湿度', '回风二氧化碳', '水阀反馈', '回风阀反馈', '新风阀反馈'];
+
+  if (statusColumns.includes(columnName)) return 'status';
+  if (numberColumns.includes(columnName)) return 'number';
+  return 'text';
 };
 
-// 控制设备
-const handleControl = (row) => {
-  currentControlDevice.value = row;
-  controlDialogOpen.value = true;
-  remoteControlForm.command = '';
-  remoteControlForm.delay = 0;
-  remoteControlForm.remark = '';
+// 获取列单位
+const getColumnUnit = (columnName) => {
+  const unitMap = {
+    '送风温度': '°C',
+    '回风温度': '°C',
+    '新风温度': '°C',
+    '送风湿度': '%',
+    '回风二氧化碳': 'ppm',
+    '水阀反馈': '%',
+    '回风阀反馈': '%',
+    '新风阀反馈': '%'
+  };
+  return unitMap[columnName] || '';
 };
 
-// 删除设备
-const handleDelete = async (row) => {
-  try {
-    await ElMessageBox.confirm(
-        `确定要删除设备 "${row.deviceName}" 吗?`,
-        '删除确认',
-        {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning',
-        }
-    );
-
-    // 模拟删除操作
-    ElMessage.success('删除成功');
-    getList();
-  } catch {
-    ElMessage.info('已取消删除');
+// 获取单元格样式类
+const getCellClass = (columnName, value) => {
+  const type = getColumnType(columnName);
+
+  if (type === 'status') {
+    return value === '是' ? 'status-active' : 'status-inactive';
+  }
+
+  if (type === 'number') {
+    const numValue = parseFloat(value);
+    if (isNaN(numValue)) return 'value-invalid';
+    if (numValue === 0) return 'value-zero';
+    if (columnName.includes('温度') && (numValue < 18 || numValue > 35)) return 'value-warning';
+    if (columnName.includes('湿度') && (numValue < 30 || numValue > 80)) return 'value-warning';
+    if (columnName.includes('反馈') && numValue > 95) return 'value-high';
+    return 'value-normal';
   }
-};
 
-// 导出数据
-const exportData = () => {
-  ElMessage.success('正在导出数据...');
-  // 实际导出逻辑
+  return '';
 };
 
-// 设备类型映射
-const mapDeviceType = (type) => {
-  const typeMap = {
-    'CONTROLLER': '控制器',
-    'SENSOR': '传感器',
-    'ACTUATOR': '执行器',
-    'BROADCASTER': '广播设备',
-    'MONITOR': '监控设备',
-    'ALARM': '报警设备',
-    'INPUT': '输入设备',
-  };
-  return typeMap[type] || type;
+// 获取数字样式类
+const getNumberClass = (columnName, value) => {
+  const numValue = parseFloat(value);
+  if (isNaN(numValue)) return 'number-invalid';
+  if (numValue === 0) return 'number-zero';
+  if (numValue > 90) return 'number-high';
+  return 'number-normal';
 };
 
-// 获取设备类型标签样式
-const getDeviceTypeTag = (type) => {
-  const tagMap = {
-    'CONTROLLER': 'primary',
-    'SENSOR': 'success',
-    'ACTUATOR': 'warning',
-    'BROADCASTER': 'info',
-    'MONITOR': '',
-    'ALARM': 'danger',
-    'INPUT': ''
-  };
-  return tagMap[type] || '';
+// 格式化数字
+const formatNumber = (value) => {
+  const num = parseFloat(value);
+  if (isNaN(num)) return value;
+  return num.toFixed(2);
 };
 
-// 获取状态样式类
-const getStatusClass = (status) => {
-  const classMap = {
-    '正常': 'status-normal',
-    '警告': 'status-warning',
-    '故障': 'status-error',
-    '离线': 'status-offline'
-  };
-  return classMap[status] || 'status-offline';
+// 获取设备状态
+const getDeviceStatus = (device) => {
+  if (device.故障报警 === '是') return '故障';
+  if (device.运行状态 === '是') return '运行中';
+  if (device.自动状态 === '是') return '自动';
+  return '待机';
 };
 
-// 获取状态标签类型
-const getStatusTagType = (status) => {
+// 获取设备状态类型
+const getDeviceStatusType = (device) => {
+  const status = getDeviceStatus(device);
   const typeMap = {
-    '正常': 'success',
-    '警告': 'warning',
     '故障': 'danger',
-    '离线': 'info'
+    '运行中': 'success',
+    '自动': 'primary',
+    '待机': 'info'
   };
   return typeMap[status] || 'info';
 };
 
-// 获取历史记录类型标签
-const getHistoryTypeTag = (type) => {
-  const typeMap = {
-    '状态变更': 'primary',
-    '参数调整': 'warning',
-    '告警处理': 'danger',
-    '维护记录': 'success'
-  };
-  return typeMap[type] || '';
-};
+// 获取卡片显示数据
+const getCardDisplayData = (device) => {
+  const importantKeys = ['运行状态', '故障报警', '送风温度', '水阀反馈', '自动状态', '过滤网压差'];
+  const result = {};
 
-// 格式化时间
-const formatTime = (time) => {
-  if (!time) return '-';
-  const date = new Date(time);
-  return date.toLocaleString('zh-CN');
-};
+  importantKeys.forEach(key => {
+    if (device[key] !== undefined) {
+      result[key] = device[key];
+    }
+  });
 
-// 格式化日期
-const formatDate = (date) => {
-  if (!date) return '-';
-  const d = new Date(date);
-  return d.toLocaleDateString('zh-CN');
-};
+  const allKeys = Object.keys(device).filter(key => key !== 'deviceName');
+  let count = Object.keys(result).length;
 
-// 格式化JSON
-const formatJson = (json) => {
-  try {
-    const obj = JSON.parse(json || '{}');
-    return JSON.stringify(obj, null, 2);
-  } catch {
-    return json || '{}';
+  for (const key of allKeys) {
+    if (count >= 6) break;
+    if (!result[key]) {
+      result[key] = device[key];
+      count++;
+    }
   }
+
+  return result;
 };
 
-// 发送控制命令
-const sendCommand = async (cmd) => {
-  cmd.loading = true;
-  try {
-    // 模拟发送命令
-    await new Promise(resolve => setTimeout(resolve, 1000));
-    ElMessage.success(`${cmd.name}命令执行成功`);
-
-    // 更新历史记录
-    historyData.value.unshift({
-      time: new Date(),
-      type: '设备控制',
-      content: `执行${cmd.name}操作`,
-      operator: '当前用户',
-      result: '成功'
-    });
-  } catch (error) {
-    ElMessage.error(`${cmd.name}命令执行失败`);
-  } finally {
-    cmd.loading = false;
+// 格式化卡片值
+const formatCardValue = (key, value) => {
+  const type = getColumnType(key);
+  if (type === 'number') {
+    const unit = getColumnUnit(key);
+    return `${formatNumber(value)}${unit}`;
   }
+  return value;
 };
 
-// 处理模式变更
-const handleModeChange = (value) => {
-  ElMessage.info(`已切换到${value === 'auto' ? '自动' : value === 'manual' ? '手动' : '定时'}模式`);
-};
+// 获取详情表格数据
+const getDetailTableData = (device) => {
+  const data = [];
+  Object.entries(device).forEach(([key, value]) => {
+    if (key === 'deviceName') return;
+
+    const type = getColumnType(key);
+    let status = '正常';
+
+    if (type === 'status' && value === '是' && (key.includes('故障') || key.includes('压差'))) {
+      status = '异常';
+    } else if (type === 'number') {
+      const numValue = parseFloat(value);
+      if (isNaN(numValue) || numValue === 0) {
+        status = '异常';
+      }
+    }
 
-// 处理功率调节
-const handlePowerChange = (value) => {
-  ElMessage.info(`功率已调节至${value}%`);
-};
+    data.push({
+      name: key,
+      value: value,
+      unit: getColumnUnit(key),
+      status: status
+    });
+  });
 
-// 处理温度调节
-const handleTempChange = (value) => {
-  ElMessage.info(`温度已设定为${value}°C`);
+  return data;
 };
 
-// 执行远程控制
-const executeControl = async () => {
-  if (!remoteControlForm.command) {
-    ElMessage.warning('请选择控制指令');
-    return;
-  }
-
-  controlLoading.value = true;
-  try {
-    // 模拟控制执行
-    await new Promise(resolve => setTimeout(resolve, 2000));
-    ElMessage.success('控制指令执行成功');
-    controlDialogOpen.value = false;
-
-    // 刷新数据
-    getList();
-  } catch (error) {
-    ElMessage.error('控制指令执行失败');
-  } finally {
-    controlLoading.value = false;
+// 格式化详情值
+const formatDetailValue = (name, value) => {
+  const type = getColumnType(name);
+  if (type === 'number') {
+    return formatNumber(value);
   }
+  return value;
 };
 
-// 保存设备信息
-const saveDeviceInfo = () => {
-  ElMessage.success('设备信息保存成功');
-  detailDialogOpen.value = false;
+// 表格行样式
+const tableRowClassName = ({ row }) => {
+  if (row.故障报警 === '是') return 'warning-row';
+  if (row.运行状态 !== '是') return 'offline-row';
+  return '';
 };
 
-// 3D模型相关方法
-const init3DModel = (device) => {
-  // 这里可以初始化Three.js场景
-  console.log('初始化3D模型:', device.deviceId);
+// 事件处理
+const handleSearch = () => {
+  queryParams.pageNum = 1;
+  getList();
 };
 
-const load3DModel = () => {
-  ElMessage.info('正在加载3D模型...');
-  // 加载3D模型逻辑
+const resetSearch = () => {
+  queryParams.device_type = '';
+  queryParams.pageNum = 1;
+  deviceList.value = [];
+  dynamicColumns.value = [];
+  total.value = 0;
 };
 
-const downloadModel = () => {
-  if (detailDevice.value.modelPath) {
-    ElMessage.success('开始下载模型文件');
-    // 下载逻辑
+const handleDeviceTypeChange = () => {
+  queryParams.pageNum = 1;
+  if (queryParams.device_type) {
+    getList();
   } else {
-    ElMessage.warning('暂无模型文件');
+    deviceList.value = [];
+    dynamicColumns.value = [];
+    total.value = 0;
   }
 };
 
-const resetView = () => {
-  ElMessage.info('视角已重置');
-  // 重置3D视角
+const handlePageChange = (newPage) => {
+  queryParams.pageNum = newPage;
+  getList();
+};
+
+const handleSizeChange = (newSize) => {
+  queryParams.pageSize = newSize;
+  queryParams.pageNum = 1;
+  getList();
+};
+
+const toggleTableView = () => {
+  isCardView.value = !isCardView.value;
 };
 
-const toggleRotation = () => {
-  rotationEnabled.value = !rotationEnabled.value;
-  // 切换旋转状态
+const handleRowClick = (row) => {
+  currentDevice.value = row;
+  detailDialogOpen.value = true;
 };
 
-const toggleWireframe = () => {
-  wireframeMode.value = !wireframeMode.value;
-  ElMessage.info(`已切换到${wireframeMode.value ? '线框' : '实体'}模式`);
-  // 切换渲染模式
+const handleView = (device) => {
+  currentDevice.value = device;
+  detailDialogOpen.value = true;
 };
 
-const fullscreen3D = () => {
-  const viewer = document.querySelector('.three-d-viewer');
-  if (viewer.requestFullscreen) {
-    viewer.requestFullscreen();
-  }
+// 查看组态信息
+const handleViewConfiguration = (device) => {
+  currentConfigDevice.value = device;
+  configurationDialogOpen.value = true;
+  getConfigurationInfo(device);
 };
+
 </script>
 
 <style scoped>
+/* ===== 基础样式 ===== */
 .device-management-system {
   padding: 20px;
-  background-color: #f5f7fa;
-  min-height: 100vh;
-}
-
-.filter-card {
-  margin-bottom: 20px;
-  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  background: #f5f7fa;
+  min-height: 90vh;
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+  line-height: 1.6;
+  animation: fadeIn 0.5s ease-in-out;
 }
 
+/* ===== 搜索表单样式 ===== */
 .search-form {
-  padding: 10px 0;
-}
-
-/* 统计卡片 */
-.stats-row {
+  background: #fff;
+  padding: 20px;
+  border-radius: 12px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
   margin-bottom: 20px;
+  border: 1px solid #e4e7ed;
+  transition: box-shadow 0.3s ease;
 }
 
-.stats-card {
-  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-  transition: all 0.3s;
+.search-form:hover {
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
 }
 
-.stats-card:hover {
-  transform: translateY(-2px);
-  box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.15);
+.search-form .el-form {
+  margin-bottom: 0;
 }
 
-.stats-card.normal :deep(.el-statistic__number) {
-  color: #67c23a;
+.search-form .el-form-item {
+  margin-bottom: 0;
 }
 
-.stats-card.warning :deep(.el-statistic__number) {
-  color: #e6a23c;
+.search-form .el-form-item__label {
+  font-weight: 600;
+  color: #303133;
 }
 
-.stats-card.error :deep(.el-statistic__number) {
-  color: #f56c6c;
+/* ===== 表格容器样式 ===== */
+.table-container {
+  background: #fff;
+  border-radius: 12px;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+  overflow: hidden;
+  margin-bottom: 20px;
+  transition: box-shadow 0.3s ease;
 }
 
-.data-table {
-  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+.table-container:hover {
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
 }
 
-.card-header {
+/* ===== 表格头部样式 ===== */
+.table-header {
   display: flex;
   justify-content: space-between;
   align-items: center;
+  padding: 16px 20px;
+  border-bottom: 1px solid #e4e7ed;
+  background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
 }
 
-.header-actions {
-  display: flex;
-  gap: 10px;
-}
-
-/* 位置信息样式 */
-.location-info {
+.header-left {
   display: flex;
   align-items: center;
-  justify-content: center;
-  gap: 5px;
-  font-weight: 500;
+  gap: 8px;
 }
 
-.location-detail {
-  font-size: 12px;
-  color: #909399;
-  margin-top: 4px;
+.header-icon {
+  font-size: 20px;
+  color: #409eff;
 }
 
-/* 状态样式 */
-.status-wrapper {
+.header-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.header-actions {
   display: flex;
-  align-items: center;
-  justify-content: center;
-  gap: 6px;
+  gap: 8px;
 }
 
-.status-dot {
-  width: 8px;
-  height: 8px;
-  border-radius: 50%;
-  display: inline-block;
-  animation: blink 2s infinite;
+/* ===== 表格样式优化 ===== */
+.table-view {
+  padding: 0;
+}
+
+/* 表格基础样式 */
+:deep(.el-table) {
+  border-radius: 0;
+  overflow: hidden;
+}
+
+/* 表格头部样式 */
+:deep(.el-table th) {
+  background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+  color: #303133;
+  font-weight: 600;
+  padding: 14px 12px;
+  border-bottom: 2px solid #e4e7ed;
+}
+
+/* 表格单元格样式 */
+:deep(.el-table td) {
+  padding: 12px;
+  border-bottom: 1px solid #f0f2f5;
+}
+
+/* 去掉隔行变色,统一背景色 */
+:deep(.el-table__row) {
+  background-color: #ffffff;
+  transition: all 0.3s ease;
+}
+
+/* 悬停效果 */
+:deep(.el-table__row:hover) {
+  background-color: #f0f9ff !important;
+  transform: translateY(-1px);
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+}
+
+/* 选中行样式 - 加深颜色便于区分 */
+:deep(.el-table__row.current-row) {
+  background-color: #e6f4ff !important;
+  border-left: 4px solid #409eff;
+}
+
+:deep(.el-table__row.current-row:hover) {
+  background-color: #d4edff !important;
+}
+
+/* 表格行状态样式 */
+:deep(.warning-row) {
+  background-color: #fef0f0 !important;
+  border-left: 4px solid #f56c6c;
+}
+
+:deep(.warning-row:hover) {
+  background-color: #fde2e2 !important;
 }
 
-.status-normal {
-  background-color: #67c23a;
+:deep(.offline-row) {
+  background-color: #f5f7fa !important;
+  color: #909399;
 }
 
-.status-warning {
-  background-color: #e6a23c;
+:deep(.offline-row:hover) {
+  background-color: #ebeef5 !important;
 }
 
-.status-error {
-  background-color: #f56c6c;
+/* ===== 设备信息样式 ===== */
+.device-info {
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+  padding: 8px;
+  border-radius: 6px;
+  transition: all 0.3s ease;
 }
 
-.status-offline {
-  background-color: #909399;
-  animation: none;
+.device-info:hover {
+  background: rgba(64, 158, 255, 0.05);
+  transform: translateY(-2px);
 }
 
-@keyframes blink {
-  0%, 100% { opacity: 1; }
-  50% { opacity: 0.5; }
+.device-name {
+  font-weight: 600;
+  color: #303133;
+  font-size: 14px;
 }
 
-.no-alarm {
+.device-type {
   color: #909399;
   font-size: 12px;
+  background: #f0f2f5;
+  padding: 2px 6px;
+  border-radius: 4px;
+  display: inline-block;
+  width: fit-content;
 }
 
-.pagination-container {
-  margin-top: 20px;
+/* ===== 单元格内容样式 ===== */
+.cell-content {
   display: flex;
-  justify-content: flex-end;
+  align-items: center;
+  justify-content: center;
+  gap: 4px;
 }
 
-/* 详情弹窗样式 */
-.status-display {
-  padding: 20px;
+.status-indicator {
+  display: flex;
+  align-items: center;
+  gap: 4px;
 }
 
-.status-item {
+.number-display {
   display: flex;
   align-items: center;
-  margin-bottom: 15px;
-  font-size: 14px;
+  gap: 2px;
 }
 
-.status-item .label {
-  width: 80px;
-  color: #606266;
+.number-value {
+  font-weight: 600;
+  transition: all 0.3s ease;
 }
 
-.alarm-info {
-  padding: 10px;
+.number-value:hover {
+  transform: scale(1.05);
 }
 
-.alarm-details {
-  margin-top: 15px;
-  font-size: 14px;
-  line-height: 1.8;
-  color: #606266;
+.unit {
+  font-size: 11px;
+  color: #909399;
+}
+
+/* ===== 数值状态样式 ===== */
+.value-normal .number-value {
+  color: #67c23a;
+}
+
+.value-warning .number-value {
+  color: #e6a23c;
+}
+
+.value-high .number-value {
+  color: #f56c6c;
+}
+
+.value-zero .number-value {
+  color: #909399;
+}
+
+.value-invalid .number-value {
+  color: #f56c6c;
+}
+
+/* ===== 卡片视图样式 ===== */
+.card-view {
+  padding: 20px;
 }
 
-/* 3D模型查看器 */
-.model-viewer {
+.cards-grid {
   display: grid;
-  grid-template-columns: 2fr 1fr;
+  grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
   gap: 20px;
-  height: 500px;
+  margin-bottom: 20px;
 }
 
-.model-preview {
-  background-color: #1a1a1a;
-  border-radius: 4px;
+.device-card-wrapper {
+  animation: cardFadeIn 0.6s ease-out;
+}
+
+.device-card {
+  border-radius: 12px;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+  transition: all 0.3s ease;
+  cursor: pointer;
+  border: 1px solid #e4e7ed;
+  overflow: hidden;
+}
+
+.device-card:hover {
+  transform: translateY(-4px);
+  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
+  border-color: #409eff;
+}
+
+.device-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 0;
+}
+
+.device-title {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+.device-avatar-large {
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
+  background: linear-gradient(135deg, #409eff 0%, #3a8ee6 100%);
   display: flex;
   align-items: center;
   justify-content: center;
-  position: relative;
-  overflow: hidden;
+  color: #fff;
+  font-size: 20px;
+}
+
+.device-card-header .device-info {
+  flex: 1;
 }
 
-.model-info {
-  overflow-y: auto;
+.device-card-header .device-name {
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+  margin: 0;
 }
 
-.json-display {
-  font-family: 'Consolas', 'Monaco', monospace;
+.device-card-header .device-type {
   font-size: 12px;
-  line-height: 1.5;
-  color: #606266;
-  background-color: #f5f7fa;
-  padding: 10px;
-  border-radius: 4px;
-  overflow: auto;
-  max-height: 200px;
+  color: #909399;
+  margin: 4px 0 0 0;
 }
 
-/* 控制面板 */
-.control-panel {
-  padding: 20px;
+.device-card-content {
+  padding: 0;
 }
 
-.control-panel h4 {
-  margin-bottom: 15px;
-  color: #303133;
+.parameters-grid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 12px;
 }
 
-.control-btn {
-  width: 100%;
-  margin-bottom: 10px;
+.parameter-item {
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+  padding: 12px;
+  background: #f8f9fa;
+  border-radius: 8px;
+  transition: all 0.3s ease;
 }
 
-.unit {
-  margin-left: 10px;
+.parameter-item:hover {
+  background: #e3f2fd;
+  transform: translateY(-2px);
+}
+
+.parameter-label {
+  font-size: 12px;
   color: #909399;
+  font-weight: 500;
 }
 
-/* 3D查看器 */
-.three-d-viewer {
-  height: 70vh;
+.parameter-value {
+  font-size: 14px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.device-card-actions {
   display: flex;
-  flex-direction: column;
+  justify-content: center;
+  gap: 8px;
+  padding: 0;
 }
 
-.viewer-toolbar {
-  padding: 10px;
-  background-color: #f5f7fa;
-  border-bottom: 1px solid #e4e7ed;
+/* ===== 空状态样式 ===== */
+.empty-state {
+  text-align: center;
+  padding: 80px 20px;
+  color: #909399;
+}
+
+.empty-content {
+  max-width: 400px;
+  margin: 0 auto;
+}
+
+.empty-icon {
+  color: #c0c4cc;
+  margin-bottom: 24px;
+  animation: float 3s ease-in-out infinite;
+}
+
+.empty-title {
+  font-size: 20px;
+  color: #303133;
+  margin: 0 0 12px 0;
+  font-weight: 600;
+}
+
+.empty-description {
+  font-size: 14px;
+  color: #909399;
+  margin: 0 0 24px 0;
+  line-height: 1.6;
+}
+
+.empty-result {
+  padding: 40px 20px;
+  text-align: center;
+}
+
+.empty-image {
+  color: #c0c4cc;
+}
+
+/* ===== 分页样式 ===== */
+.pagination-container {
   display: flex;
-  justify-content: space-between;
-  align-items: center;
+  justify-content: flex-end;
+  padding: 20px 24px;
+  background-color: #fff;
+  border-top: 1px solid #f0f2f5;
 }
 
-.viewer-container {
-  flex: 1;
-  background-color: #1a1a1a;
-  position: relative;
+/* ===== 组态信息弹窗样式 ===== */
+.configuration-iframe-container {
+  width: 100%;
+  height: 70vh; /* 调整高度 */
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
   overflow: hidden;
+  background: #f5f7fa;
 }
 
-.viewer-container canvas {
+.configuration-iframe {
   width: 100%;
   height: 100%;
+  border: none;
+  display: block;
+}
+
+/* 弹窗样式覆盖 */
+:deep(.el-dialog) {
+  margin: 0 auto !important;
+  border-radius: 12px;
+  overflow: hidden;
+}
+:deep(.el-dialog__header) {
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  color: #fff;
+  padding: 20px 24px;
+  margin: 0;
+}
+:deep(.el-dialog__title) {
+  color: #fff;
+  font-weight: 600;
+  font-size: 18px;
+}
+
+:deep(.el-dialog__headerbtn .el-dialog__close) {
+  color: #fff;
+  font-size: 20px;
+}
+
+/* 组态弹窗特殊处理 */
+:deep(.el-dialog__body) {
+  padding: 16px !important; /* 减少内边距 */
+  max-height: none;
+  overflow: hidden;
+}
+
+/* 响应式调整 */
+@media (max-width: 1200px) {
+  .configuration-iframe-container {
+    height: 80vh;
+  }
+}
+
+@media (max-width: 768px) {
+  .configuration-iframe-container {
+    height: 75vh;
+  }
+
+  :deep(.el-dialog) {
+    width: 98% !important;
+    top: 1vh !important;
+  }
+}
+
+@media (max-width: 480px) {
+  .configuration-iframe-container {
+    height: 70vh;
+  }
+
+  :deep(.el-dialog) {
+    width: 100% !important;
+    top: 0 !important;
+    margin: 0 !important;
+  }
+}
+
+/* ===== 设备详情弹窗内容样式 ===== */
+.device-detail {
+  display: flex;
+  flex-direction: column;
+  gap: 24px;
+}
+
+.detail-section {
+  background: #f8f9fa;
+  padding: 20px;
+  border-radius: 8px;
+  border-left: 4px solid #409eff;
+}
+
+.detail-section h3 {
+  margin: 0 0 16px 0;
+  color: #303133;
+  font-size: 16px;
+  font-weight: 600;
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.detail-section h3::before {
+  content: '';
+  width: 4px;
+  height: 16px;
+  background: #409eff;
+  border-radius: 2px;
+}
+
+/* ===== 参数表格样式 ===== */
+.param-name {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.param-icon {
+  color: #409eff;
+  font-size: 14px;
+}
+
+.param-value-cell {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+  justify-content: center;
+}
+
+.param-value {
+  font-weight: 600;
+}
+
+.param-unit {
+  font-size: 12px;
+  color: #909399;
+}
+
+/* ===== 按钮样式优化 ===== */
+.el-button {
+  border-radius: 6px;
+  font-weight: 500;
+  transition: all 0.3s ease;
+}
+
+.el-button--primary {
+  background: linear-gradient(135deg, #409eff 0%, #3a8ee6 100%);
+  border: none;
+  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
+}
+
+.el-button--primary:hover {
+  background: linear-gradient(135deg, #3a8ee6 0%, #337ecc 100%);
+  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
+  transform: translateY(-1px);
+}
+
+.el-button--success {
+  background: linear-gradient(135deg, #67c23a 0%, #5daf34 100%);
+  border: none;
+  box-shadow: 0 2px 8px rgba(103, 194, 58, 0.3);
+}
+
+.el-button--success:hover {
+  background: linear-gradient(135deg, #5daf34 0%, #529b2e 100%);
+  box-shadow: 0 4px 12px rgba(103, 194, 58, 0.4);
+  transform: translateY(-1px);
+}
+
+.el-button[circle] {
+  transition: all 0.3s ease;
+}
+
+.el-button[circle]:hover {
+  transform: rotate(180deg) scale(1.1);
+}
+
+/* ===== 标签样式优化 ===== */
+.el-tag {
+  border-radius: 4px;
+  font-weight: 500;
+  border: none;
+  font-size: 11px;
+  padding: 4px 8px;
+  transition: all 0.3s ease;
+}
+
+.el-tag:hover {
+  transform: scale(1.05);
+}
+
+.el-tag--success {
+  background: linear-gradient(135deg, #4CAF50 0%, #009688 100%);
+  color: #fff;
+}
+
+.el-tag--danger {
+  background: linear-gradient(135deg, #f56c6c 0%, #f25c5c 100%);
+  color: #fff;
+}
+
+.el-tag--warning {
+  background: linear-gradient(135deg, #e6a23c 0%, #d19e3c 100%);
+  color: #fff;
+}
+
+.el-tag--info {
+  background: linear-gradient(135deg, #673AB7 0%, #9E9E9E 100%);
+  color: #fff;
 }
 
-.viewer-info {
-  padding: 10px;
-  background-color: #f5f7fa;
-  border-top: 1px solid #e4e7ed;
+.el-tag--primary {
+  background: linear-gradient(135deg, #409eff 0%, #3a8ee6 100%);
+  color: #fff;
 }
 
-.mb-4 {
-  margin-bottom: 16px;
+/* ===== 动画定义 ===== */
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+    transform: translateY(20px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
+
+@keyframes cardFadeIn {
+  from {
+    opacity: 0;
+    transform: translateY(20px) scale(0.95);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0) scale(1);
+  }
+}
+
+@keyframes dialogSlideIn {
+  from {
+    opacity: 0;
+    transform: scale(0.8) translateY(-50px);
+  }
+  to {
+    opacity: 1;
+    transform: scale(1) translateY(0);
+  }
+}
+
+@keyframes float {
+  0%, 100% {
+    transform: translateY(0px);
+  }
+  50% {
+    transform: translateY(-10px);
+  }
 }
 
-/* 响应式设计 */
+/* ===== 响应式设计 ===== */
 @media (max-width: 1200px) {
-  .stats-row {
-    margin-bottom: 10px;
+  .device-management-system {
+    padding: 16px;
+  }
+
+  .cards-grid {
+    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+    gap: 16px;
+  }
+
+  .configuration-iframe-container {
+    height: 70vh;
+  }
+}
+
+@media (max-width: 768px) {
+  .device-management-system {
+    padding: 12px;
+  }
+
+  .search-form {
+    padding: 16px;
+  }
+
+  .table-header {
+    padding: 16px;
+    flex-direction: column;
+    gap: 12px;
+    align-items: flex-start;
+  }
+
+  .header-actions {
+    align-self: flex-end;
+  }
+
+  .cards-grid {
+    grid-template-columns: 1fr;
+    gap: 12px;
   }
 
-  .model-viewer {
+  .parameters-grid {
     grid-template-columns: 1fr;
-    height: auto;
+    gap: 8px;
+  }
+
+  .parameter-item {
+    padding: 8px;
+  }
+
+  .device-card-actions {
+    flex-direction: column;
+    gap: 8px;
+  }
+
+  :deep(.el-table td) {
+    padding: 8px 4px;
+    font-size: 12px;
+  }
+
+  :deep(.el-table th) {
+    padding: 8px 4px;
+    font-size: 12px;
+  }
+
+  .device-info,
+  .cell-content {
+    font-size: 11px;
+  }
+
+  .pagination-container {
+    padding: 16px;
+    justify-content: center;
+  }
+
+  :deep(.el-dialog) {
+    width: 95% !important;
+    margin: 0 auto;
+  }
+
+  .detail-section {
+    padding: 16px;
+  }
+
+  .configuration-iframe-container {
+    height: 60vh;
+  }
+}
+
+@media (max-width: 480px) {
+  .device-management-system {
+    padding: 8px;
+  }
+
+  .search-form {
+    padding: 12px;
+  }
+
+  .search-form .el-form {
+    display: flex;
+    flex-direction: column;
+  }
+
+  .search-form .el-form-item {
+    width: 100%;
+  }
+
+  .search-form .el-input,
+  .search-form .el-select {
+    width: 100% !important;
+  }
+
+  .table-header {
+    padding: 12px;
+  }
+
+  .header-title {
+    font-size: 16px;
+  }
+
+  .empty-state {
+    padding: 40px 12px;
+  }
+
+  .empty-title {
+    font-size: 18px;
+  }
+
+  .empty-description {
+    font-size: 13px;
+  }
+
+  .device-card {
+    margin: 0 4px;
+  }
+
+  .device-card-header {
+    flex-direction: column;
+    gap: 12px;
+    align-items: flex-start;
+  }
+
+  .configuration-iframe-container {
+    height: 50vh;
+  }
+
+  .dialog-footer {
+    flex-direction: column;
+    gap: 8px;
+  }
+
+  .dialog-footer .el-button {
+    width: 100%;
+  }
+}
+
+/* ===== 滚动条样式 ===== */
+:deep(.el-dialog__body)::-webkit-scrollbar,
+:deep(.el-table__body-wrapper)::-webkit-scrollbar {
+  width: 6px;
+  height: 6px;
+}
+
+:deep(.el-dialog__body)::-webkit-scrollbar-track,
+:deep(.el-table__body-wrapper)::-webkit-scrollbar-track {
+  background: #f1f1f1;
+  border-radius: 3px;
+}
+
+:deep(.el-dialog__body)::-webkit-scrollbar-thumb,
+:deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb {
+  background: #c1c1c1;
+  border-radius: 3px;
+}
+
+:deep(.el-dialog__body)::-webkit-scrollbar-thumb:hover,
+:deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb:hover {
+  background: #a8a8a8;
+}
+
+/* ===== 输入框和选择器样式优化 ===== */
+:deep(.el-input__wrapper) {
+  border-radius: 6px;
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+  transition: all 0.3s ease;
+}
+
+:deep(.el-input__wrapper:hover) {
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
+}
+
+:deep(.el-input__wrapper.is-focus) {
+  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
+}
+
+:deep(.el-select .el-input__wrapper) {
+  border-radius: 6px;
+}
+
+/* ===== 分页样式优化 ===== */
+:deep(.el-pagination) {
+  --el-pagination-button-color: #606266;
+  --el-pagination-hover-color: #409eff;
+}
+
+:deep(.el-pagination .el-pager li) {
+  border-radius: 6px;
+  margin: 0 2px;
+  transition: all 0.3s ease;
+}
+
+:deep(.el-pagination .el-pager li:hover) {
+  transform: translateY(-2px);
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+}
+
+:deep(.el-pagination .el-pager li.is-active) {
+  background: linear-gradient(135deg, #409eff 0%, #3a8ee6 100%);
+  color: #fff;
+  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
+}
+
+:deep(.el-pagination__total) {
+  margin-right: 16px;
+  color: #606266;
+  font-weight: 500;
+}
+
+:deep(.el-pagination__sizes) {
+  margin-right: 16px;
+}
+
+/* ===== 描述列表样式优化 ===== */
+:deep(.el-descriptions) {
+  background: #fff;
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+:deep(.el-descriptions__label) {
+  background: #fafbfc !important;
+  font-weight: 600;
+  color: #303133;
+  border-right: 1px solid #e4e7ed;
+}
+
+:deep(.el-descriptions__content) {
+  background: #fff !important;
+  color: #606266;
+}
+
+/* ===== 表格固定列阴影 ===== */
+:deep(.el-table__fixed-right) {
+  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
+}
+
+:deep(.el-table__fixed-left) {
+  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
+}
+
+/* ===== 工具提示样式 ===== */
+:deep(.el-tooltip__popper) {
+  background: rgba(0, 0, 0, 0.8);
+  border-radius: 6px;
+  backdrop-filter: blur(10px);
+}
+
+/* ===== 加载动画优化 ===== */
+:deep(.el-loading-mask) {
+  background-color: rgba(255, 255, 255, 0.9);
+  backdrop-filter: blur(2px);
+}
+
+:deep(.el-loading-spinner) {
+  animation: loadingRotate 1.5s linear infinite;
+}
+
+@keyframes loadingRotate {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+/* ===== 表格边框优化 ===== */
+:deep(.el-table--border) {
+  border: 1px solid #ebeef5;
+  border-radius: 0;
+}
+
+:deep(.el-table--border::after) {
+  display: none;
+}
+
+/* ===== 空数据状态优化 ===== */
+:deep(.el-table__empty-block) {
+  padding: 60px 0;
+}
+
+:deep(.el-table__empty-text) {
+  color: #909399;
+  font-size: 14px;
+}
+
+/* ===== 焦点样式增强 ===== */
+.el-button:focus,
+.el-input:focus,
+.el-select:focus {
+  outline: 2px solid #409eff;
+  outline-offset: 2px;
+}
+
+/* ===== 选择状态样式 ===== */
+::selection {
+  background: rgba(64, 158, 255, 0.3);
+  color: #303133;
+}
+
+/* ===== 表单验证样式 ===== */
+:deep(.el-form-item.is-error .el-input__wrapper) {
+  box-shadow: 0 0 0 1px #f56c6c inset;
+}
+
+:deep(.el-form-item.is-success .el-input__wrapper) {
+  box-shadow: 0 0 0 1px #67c23a inset;
+}
+
+/* ===== 性能优化 ===== */
+.device-management-system * {
+  box-sizing: border-box;
+}
+
+.device-card:hover,
+:deep(.el-table__row:hover),
+.parameter-item:hover {
+  will-change: transform;
+}
+
+/* ===== 无障碍支持 ===== */
+@media (prefers-reduced-motion: reduce) {
+  *,
+  *::before,
+  *::after {
+    animation-duration: 0.01ms !important;
+    animation-iteration-count: 1 !important;
+    transition-duration: 0.01ms !important;
+  }
+}
+
+/* ===== 高对比度模式 ===== */
+@media (prefers-contrast: high) {
+  .device-management-system {
+    background: #fff;
+    color: #000;
+  }
+
+  .search-form,
+  .table-container,
+  .device-card {
+    border: 2px solid #000;
+    background: #fff;
   }
 
-  .model-preview {
-    height: 300px;
+  .el-button--primary {
+    background: #000;
+    color: #fff;
+    border: 2px solid #000;
+  }
+
+  .el-button--success {
+    background: #006400;
+    color: #fff;
+    border: 2px solid #006400;
+  }
+
+  .el-tag {
+    border: 1px solid #000;
+    color: #000;
+    background: #fff;
+  }
+
+  :deep(.el-table__row.current-row) {
+    background-color: #000 !important;
+    color: #fff;
+  }
+
+  .configuration-iframe-container {
+    border: 2px solid #000;
   }
 }
 
-/* 暗色主题支持 */
-@media (prefers-color-scheme: dark) {
+/* ===== 打印样式 ===== */
+@media print {
+  .search-form,
+  .pagination-container,
+  .header-actions,
+  .el-button,
+  .dialog-footer {
+    display: none !important;
+  }
+
   .device-management-system {
-    background-color: #1a1a1a;
+    background: #fff;
+    padding: 0;
+  }
+
+  .table-container {
+    box-shadow: none;
+    border: 1px solid #000;
+  }
+
+  .table-header {
+    background: #f5f7fa !important;
+    color: #000 !important;
+    border-bottom: 2px solid #000;
+  }
+
+  :deep(.el-table th) {
+    background: #f5f7fa !important;
+    color: #000 !important;
+    border: 1px solid #000;
+  }
+
+  :deep(.el-table td) {
+    background: #fff !important;
+    color: #000 !important;
+    border: 1px solid #000;
+  }
+
+  :deep(.el-table__row) {
+    background-color: #fff !important;
+  }
+
+  .device-card {
+    break-inside: avoid;
+    margin-bottom: 20px;
+    border: 1px solid #000;
+  }
+}
+
+/* ===== 最终样式确保 ===== */
+.device-management-system {
+  position: relative;
+  z-index: 1;
+}
+
+/* 确保表格行选中状态优先级最高 */
+:deep(.el-table tbody tr.current-row > td) {
+  background-color: #e6f4ff !important;
+}
+
+:deep(.el-table tbody tr.current-row:hover > td) {
+  background-color: #d4edff !important;
+}
+
+/* 确保警告行状态 */
+:deep(.el-table tbody tr.warning-row > td) {
+  background-color: #fef0f0 !important;
+}
+
+:deep(.el-table tbody tr.warning-row:hover > td) {
+  background-color: #fde2e2 !important;
+}
+
+/* 确保离线行状态 */
+:deep(.el-table tbody tr.offline-row > td) {
+  background-color: #f5f7fa !important;
+  color: #909399;
+}
+
+:deep(.el-table tbody tr.offline-row:hover > td) {
+  background-color: #ebeef5 !important;
+}
+
+/* 确保弹窗层级正确 */
+:deep(.el-overlay-dialog) {
+  z-index: 2000;
+  top: 10vh;
+}
+
+/* 确保按钮组在小屏幕上的布局 */
+@media (max-width: 600px) {
+  .device-card-actions {
+    flex-direction: column;
+    gap: 8px;
   }
 
-  .json-display {
-    background-color: #2a2a2a;
-    color: #e0e0e0;
+  .device-card-actions .el-button {
+    width: 100%;
+    margin: 0;
   }
 }
+
+/* 最终确保所有交互元素的可访问性 */
+.el-button,
+.el-link,
+.device-card,
+.parameter-item {
+  cursor: pointer;
+  user-select: none;
+}
+
+.el-button:disabled,
+.el-link:disabled {
+  cursor: not-allowed;
+  opacity: 0.6;
+}
+
+/* 确保文本选择的一致性 */
+.device-name,
+.parameter-label,
+.parameter-value {
+  user-select: text;
+}
+
+/* 最终的全局重置确保 */
+* {
+  box-sizing: border-box;
+}
+
+*:focus {
+  outline: none;
+}
+
+*:focus-visible {
+  outline: 2px solid #409eff;
+  outline-offset: 2px;
+}
 </style>