| 
					
				 | 
			
			
				@@ -3,7 +3,6 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <!-- 查询条件区域 --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <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> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -13,7 +12,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         </el-form-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <el-form-item label="设备类型"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <el-select v-model="queryParams.deviceType" placeholder="请选择设备类型" style="width: 180px;"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <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" /> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -25,13 +24,14 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           </el-select> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         </el-form-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <!-- 空间定位条件 --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <el-form-item label="楼层"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <el-select v-model="queryParams.floor" placeholder="请选择楼层" style="width: 180px;"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -39,115 +39,482 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           <el-input v-model="queryParams.area" placeholder="请输入区域" clearable /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         </el-form-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <!-- 实时状态条件 --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <el-form-item label="运行状态"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <el-select v-model="queryParams.status" placeholder="请选择运行状态" style="width: 180px;"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <el-form-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <el-button type="primary" icon="Search" @click="handleSearch">搜索</el-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <el-button icon="Refresh" @click="resetSearch">重置</el-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            </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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            </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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          </el-statistic> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        </el-card> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      </el-col> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </el-row> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <!-- 数据表格区域 --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       <el-table 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           :data="deviceList" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           border 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          size="small" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           v-loading="isLoading" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           row-key="deviceId" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           @row-click="handleRowClick" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          :height="tableHeight" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          style="width: 100%" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       > 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-table-column label="设备ID" prop="deviceId" align="center" width="140" /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-table-column label="设备名称" prop="deviceName" align="center" width="140" /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <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"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            {{ mapDeviceType(scope.row.deviceType) }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <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="120" /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <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>{{ scope.row.floor }}-{{ scope.row.area }}</div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            <div class="small-text">({{ scope.row.location }})</div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <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"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            <el-tag :color="scope.row.statusColor">{{ scope.row.status }}</el-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <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="160"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <el-table-column label="当前告警" align="center" width="180"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           <template #default="scope"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            <div v-if="scope.row.alarmCode">{{ scope.row.alarmCode }}</div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            <div v-else>-</div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <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-column label="控制协议" prop="controlProtocol" align="center" width="120" />--> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       </el-table> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       <!-- 分页组件 --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      <pagination 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <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" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          v-model:page="queryParams.pageNum" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          v-model:limit="queryParams.pageSize" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          @pagination="getList" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          layout="total, sizes, prev, pager, next, jumper" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          @size-change="handleSizeChange" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          @current-change="handlePageChange" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          class="pagination-container" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     </el-card> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <!-- 详情弹窗 --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    <el-dialog :visible.sync="detailDialogOpen" title="设备详情" width="800px"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      <el-descriptions :column="2" border> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="设备ID" span="1">{{ detailDevice.deviceId }}</el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="设备名称" span="1">{{ detailDevice.deviceName }}</el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="设备类型" span="1">{{ mapDeviceType(detailDevice.deviceType) }}</el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="型号" span="1">{{ detailDevice.model }}</el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="安装位置" span="2"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          {{ detailDevice.floor }}-{{ detailDevice.area }} ({{ detailDevice.location }}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        </el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="运行状态" span="2"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <el-tag :color="detailDevice.statusColor">{{ detailDevice.status }}</el-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        </el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="模型文件" span="2"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <el-link :href="detailDevice.modelPath" type="primary" target="_blank">查看模型</el-link> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        </el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="动画参数" span="2"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <pre class="small-text">{{ detailDevice.animationParams }}</pre> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        </el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="当前告警" span="2" v-if="detailDevice.alarmCode"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <el-alert 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              title="{{ detailDevice.alarmDescription }}" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              type="danger" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              :closable="false" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              show-icon 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <div class="mt-2">告警代码: {{ detailDevice.alarmCode }}</div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <div>触发时间: {{ detailDevice.triggerTime }}</div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        </el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="控制协议" span="1">{{ detailDevice.controlProtocol }}</el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <el-descriptions-item label="指令集" span="1">{{ detailDevice.commandSet }}</el-descriptions-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      </el-descriptions> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <el-dialog 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        v-model="detailDialogOpen" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        title="设备详情" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        width="900px" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        destroy-on-close 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    > 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <el-tabs v-model="activeTab" type="card"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <!-- 基本信息 --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <el-tab-pane label="基本信息" name="basic"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <el-descriptions :column="2" border> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <el-descriptions-item label="设备ID"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              <el-tag>{{ detailDevice.deviceId }}</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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            </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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <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"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              <template #default="scope"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                {{ formatTime(scope.row.time) }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            </el-table-column> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <el-table-column label="操作类型" prop="type" width="120"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              <template #default="scope"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                <el-tag :type="getHistoryTypeTag(scope.row.type)" size="small"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  {{ scope.row.type }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                </el-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              </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"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              <template #default="scope"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                <el-tag :type="scope.row.result === '成功' ? 'success' : 'danger'" size="small"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  {{ scope.row.result }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                </el-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            </el-table-column> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          </el-table> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        </el-tab-pane> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      </el-tabs> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       <template #footer> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <el-button @click="detailDialogOpen = false">关闭</el-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <el-button type="primary" @click="saveDeviceInfo">保存</el-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </el-dialog> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <!-- 3D查看弹窗 --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <el-dialog 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        v-model="view3DDialogOpen" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        :title="`3D视图 - ${current3DDevice.deviceName}`" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        width="90%" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        top="5vh" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        destroy-on-close 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    > 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     </el-dialog> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 <script setup> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { ref, reactive, computed } from 'vue'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { ElMessage } from 'element-plus'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import {getBuildingEquipmentMonitoringList} from "@/api/buildingEquipmentMonitoring/buildingEquipmentMonitoring"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { ElMessage, ElMessageBox } from 'element-plus'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Search, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Refresh, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Download, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Monitor, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  CircleCheck, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Warning, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  CircleClose, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Plus, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  View, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Operation, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Delete, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Location, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VideoPlay, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VideoPause, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  FullScreen 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} from '@element-plus/icons-vue'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { getBuildingEquipmentMonitoringList } from "@/api/buildingEquipmentMonitoring/buildingEquipmentMonitoring"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// import * as THREE from 'three'; // 如果使用Three.js 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 查询参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 状态管理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const queryParams = reactive({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   deviceId: '', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   deviceName: '', 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -160,54 +527,147 @@ const queryParams = reactive({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   interfaceName: "三维设备监控中心" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 表格数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 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 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++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return stats; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 快速控制命令 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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 remoteControlForm = reactive({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  command: '', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  delay: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  remark: '' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 历史记录数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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; // 考虑统计卡片的高度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+onMounted(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  calculateTableHeight(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  window.addEventListener('resize', calculateTableHeight); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getList(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 初始化3D场景 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // init3DScene(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+onUnmounted(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  window.removeEventListener('resize', calculateTableHeight); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 清理3D资源 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // cleanup3DScene(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 获取数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const getList = async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   isLoading.value = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let response = await getBuildingEquipmentMonitoringList(queryParams); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 过滤条件处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const response = await getBuildingEquipmentMonitoringList(queryParams); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let filteredData = response.data.list || []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 设备ID过滤 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 应用过滤条件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (queryParams.deviceId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      filteredData = filteredData.filter(item => item.deviceId.includes(queryParams.deviceId)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      filteredData = filteredData.filter(item => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          item.deviceId.toLowerCase().includes(queryParams.deviceId.toLowerCase()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 设备名称过滤 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (queryParams.deviceName) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      filteredData = filteredData.filter(item => item.deviceName.includes(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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 区域过滤 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (queryParams.area) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      filteredData = filteredData.filter(item => item.area.includes(queryParams.area)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      filteredData = filteredData.filter(item => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          item.area.toLowerCase().includes(queryParams.area.toLowerCase()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 状态过滤 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (queryParams.status) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       filteredData = filteredData.filter(item => item.status === queryParams.status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 添加额外的模拟数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // 分页处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    total.value = response.data.total || 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    deviceList.value = filteredData; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -224,12 +684,11 @@ const handleSearch = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 重置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const resetSearch = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  queryParams.deviceId = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  queryParams.deviceName = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  queryParams.deviceType = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  queryParams.floor = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  queryParams.area = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  queryParams.status = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Object.keys(queryParams).forEach(key => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (key !== 'pageNum' && key !== 'pageSize' && key !== 'interfaceName') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      queryParams[key] = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   queryParams.pageNum = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   getList(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -246,15 +705,67 @@ const handleSizeChange = (newSize) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   getList(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 行点击事件(打开详情弹窗) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 行点击事件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const handleRowClick = (row) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  detailDevice.value = { ...row }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  detailDevice.value = JSON.parse(JSON.stringify(row)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   detailDialogOpen.value = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  activeTab.value = 'basic'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 新增设备 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleAdd = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.info('新增设备功能开发中...'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 查看3D 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleView3D = (row) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  current3DDevice.value = row; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  view3DDialogOpen.value = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 初始化3D模型 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    init3DModel(row); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }, 100); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 控制设备 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleControl = (row) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  currentControlDevice.value = row; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  controlDialogOpen.value = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  remoteControlForm.command = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  remoteControlForm.delay = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  remoteControlForm.remark = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 删除设备 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleDelete = async (row) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await ElMessageBox.confirm( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        `确定要删除设备 "${row.deviceName}" 吗?`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '删除确认', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          confirmButtonText: '确定', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          cancelButtonText: '取消', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          type: 'warning', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 模拟删除操作 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ElMessage.success('删除成功'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    getList(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } catch { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ElMessage.info('已取消删除'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 导出数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const exportData = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.success('正在导出数据...'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 实际导出逻辑 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 设备类型映射 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const mapDeviceType = (type) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const typeMap = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     'CONTROLLER': '控制器', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     'SENSOR': '传感器', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     'ACTUATOR': '执行器', 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -262,28 +773,459 @@ const mapDeviceType = (type) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     'MONITOR': '监控设备', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     'ALARM': '报警设备', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     'INPUT': '输入设备', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }[type] || type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return typeMap[type] || type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 获取设备类型标签样式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const getDeviceTypeTag = (type) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const tagMap = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'CONTROLLER': 'primary', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'SENSOR': 'success', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'ACTUATOR': 'warning', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'BROADCASTER': 'info', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'MONITOR': '', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'ALARM': 'danger', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'INPUT': '' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return tagMap[type] || ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 获取状态样式类 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const getStatusClass = (status) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const classMap = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '正常': 'status-normal', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '警告': 'status-warning', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '故障': 'status-error', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '离线': 'status-offline' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return classMap[status] || 'status-offline'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 获取状态标签类型 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const getStatusTagType = (status) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const typeMap = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '正常': 'success', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '警告': 'warning', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '故障': 'danger', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '离线': 'info' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return typeMap[status] || 'info'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 获取历史记录类型标签 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const getHistoryTypeTag = (type) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const typeMap = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '状态变更': 'primary', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '参数调整': 'warning', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '告警处理': 'danger', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    '维护记录': 'success' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return typeMap[type] || ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 格式化时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const formatTime = (time) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!time) return '-'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const date = new Date(time); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return date.toLocaleString('zh-CN'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 格式化日期 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const formatDate = (date) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!date) return '-'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const d = new Date(date); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return d.toLocaleDateString('zh-CN'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 格式化JSON 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const formatJson = (json) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const obj = JSON.parse(json || '{}'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return JSON.stringify(obj, null, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } catch { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return json || '{}'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 发送控制命令 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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 handleModeChange = (value) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.info(`已切换到${value === 'auto' ? '自动' : value === 'manual' ? '手动' : '定时'}模式`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 处理功率调节 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handlePowerChange = (value) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.info(`功率已调节至${value}%`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-getList() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 处理温度调节 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleTempChange = (value) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.info(`温度已设定为${value}°C`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 执行远程控制 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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 saveDeviceInfo = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.success('设备信息保存成功'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  detailDialogOpen.value = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 3D模型相关方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const init3DModel = (device) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 这里可以初始化Three.js场景 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  console.log('初始化3D模型:', device.deviceId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const load3DModel = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.info('正在加载3D模型...'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 加载3D模型逻辑 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const downloadModel = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (detailDevice.value.modelPath) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ElMessage.success('开始下载模型文件'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 下载逻辑 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ElMessage.warning('暂无模型文件'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const resetView = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.info('视角已重置'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 重置3D视角 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const toggleRotation = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rotationEnabled.value = !rotationEnabled.value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 切换旋转状态 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const toggleWireframe = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  wireframeMode.value = !wireframeMode.value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ElMessage.info(`已切换到${wireframeMode.value ? '线框' : '实体'}模式`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 切换渲染模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const fullscreen3D = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const viewer = document.querySelector('.three-d-viewer'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (viewer.requestFullscreen) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    viewer.requestFullscreen(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </script> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 <style scoped> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.device-management-system { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  padding: 20px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #f5f7fa; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  min-height: 100vh; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .filter-card { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   margin-bottom: 20px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  padding: 20px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.search-form { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  padding: 10px 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 统计卡片 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.stats-row { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-bottom: 20px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.stats-card { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  transition: all 0.3s; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.stats-card:hover { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  transform: translateY(-2px); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.15); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.stats-card.normal :deep(.el-statistic__number) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: #67c23a; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.stats-card.warning :deep(.el-statistic__number) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: #e6a23c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.stats-card.error :deep(.el-statistic__number) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: #f56c6c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .data-table { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  min-height: 500px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.card-header { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  justify-content: space-between; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-.small-text { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.header-actions { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gap: 10px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 位置信息样式 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.location-info { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  justify-content: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gap: 5px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  font-weight: 500; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.location-detail { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   font-size: 12px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   color: #909399; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-top: 4px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 状态样式 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.status-wrapper { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  justify-content: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gap: 6px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.status-dot { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  width: 8px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  height: 8px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  border-radius: 50%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: inline-block; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  animation: blink 2s infinite; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.status-normal { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #67c23a; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.status-warning { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #e6a23c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.status-error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #f56c6c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-.mt-2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  margin-top: 8px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.status-offline { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #909399; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  animation: none; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@keyframes blink { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  0%, 100% { opacity: 1; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  50% { opacity: 0.5; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.no-alarm { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: #909399; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  font-size: 12px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.pagination-container { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-top: 20px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  justify-content: flex-end; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 详情弹窗样式 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.status-display { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  padding: 20px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.status-item { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-bottom: 15px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  font-size: 14px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.status-item .label { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  width: 80px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: #606266; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.alarm-info { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  padding: 10px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.alarm-details { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-top: 15px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  font-size: 14px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  line-height: 1.8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: #606266; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 3D模型查看器 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.model-viewer { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: grid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grid-template-columns: 2fr 1fr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gap: 20px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  height: 500px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.model-preview { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #1a1a1a; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  border-radius: 4px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  justify-content: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  position: relative; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  overflow: hidden; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.model-info { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  overflow-y: auto; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.json-display { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  font-family: 'Consolas', 'Monaco', monospace; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  font-size: 12px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  line-height: 1.5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: #606266; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #f5f7fa; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  padding: 10px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  border-radius: 4px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  overflow: auto; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  max-height: 200px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 控制面板 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.control-panel { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  padding: 20px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.control-panel h4 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-bottom: 15px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: #303133; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.control-btn { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  width: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-bottom: 10px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.unit { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-left: 10px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  color: #909399; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 3D查看器 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.three-d-viewer { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  height: 70vh; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  flex-direction: column; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.viewer-toolbar { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  padding: 10px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #f5f7fa; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  border-bottom: 1px solid #e4e7ed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  justify-content: space-between; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.viewer-container { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  flex: 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #1a1a1a; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  position: relative; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  overflow: hidden; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.viewer-container canvas { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  width: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  height: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.viewer-info { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  padding: 10px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  background-color: #f5f7fa; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  border-top: 1px solid #e4e7ed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+.mb-4 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  margin-bottom: 16px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 响应式设计 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@media (max-width: 1200px) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  .stats-row { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    margin-bottom: 10px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  .model-viewer { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grid-template-columns: 1fr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    height: auto; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  .model-preview { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    height: 300px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 暗色主题支持 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@media (prefers-color-scheme: dark) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  .device-management-system { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    background-color: #1a1a1a; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  .json-display { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    background-color: #2a2a2a; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    color: #e0e0e0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </style> 
			 |