| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | <template> | 
					
						
							|  |  |  |     <div class="manage-form-container"> | 
					
						
							|  |  |  |         <!-- 搜索和筛选区域 --> | 
					
						
							| 
									
										
										
										
											2025-09-19 10:20:18 +08:00
										 |  |  |         <div class="search-filter-section"> | 
					
						
							|  |  |  |             <el-row gutter="12" align="middle"> | 
					
						
							|  |  |  |                 <el-col :span="2"> | 
					
						
							|  |  |  |                     <el-select v-model="searchForm.deviceType" placeholder="设备类型" clearable> | 
					
						
							|  |  |  |                         <el-option label="全部类型" value="" /> | 
					
						
							|  |  |  |                         <el-option label="逆变器" value="逆变器" /> | 
					
						
							|  |  |  |                         <el-option label="传感器" value="传感器" /> | 
					
						
							|  |  |  |                         <el-option label="电表" value="电表" /> | 
					
						
							|  |  |  |                         <el-option label="摄像头" value="摄像头" /> | 
					
						
							|  |  |  |                         <el-option label="控制器" value="控制器" /> | 
					
						
							|  |  |  |                     </el-select> | 
					
						
							|  |  |  |                 </el-col> | 
					
						
							|  |  |  |                 <el-col :span="2"> | 
					
						
							|  |  |  |                     <el-select v-model="searchForm.status" placeholder="设备状态" clearable> | 
					
						
							|  |  |  |                         <el-option label="全部状态" value="" /> | 
					
						
							|  |  |  |                         <el-option label="正常" value="normal" /> | 
					
						
							|  |  |  |                         <el-option label="异常" value="abnormal" /> | 
					
						
							|  |  |  |                         <el-option label="中断" value="interrupt" /> | 
					
						
							|  |  |  |                     </el-select> | 
					
						
							|  |  |  |                 </el-col> | 
					
						
							|  |  |  |                 <el-col :span="2"> | 
					
						
							|  |  |  |                     <el-select v-model="searchForm.protocol" placeholder="通讯状态" clearable> | 
					
						
							|  |  |  |                         <el-option label="全部状态" value="" /> | 
					
						
							|  |  |  |                         <el-option label="Modbus TCP" value="Modbus TCP" /> | 
					
						
							|  |  |  |                         <el-option label="其他协议" value="其他" /> | 
					
						
							|  |  |  |                     </el-select> | 
					
						
							|  |  |  |                 </el-col> | 
					
						
							|  |  |  |                 <el-col :span="2"> | 
					
						
							|  |  |  |                     <el-select v-model="searchForm.station" placeholder="所属电站" clearable> | 
					
						
							|  |  |  |                         <el-option label="全部电站" value="" /> | 
					
						
							|  |  |  |                         <el-option label="兴电基站1" value="兴电基站1" /> | 
					
						
							|  |  |  |                         <el-option label="兴电基站2" value="兴电基站2" /> | 
					
						
							|  |  |  |                         <el-option label="兴电基站3" value="兴电基站3" /> | 
					
						
							|  |  |  |                         <el-option label="兴电基站4" value="兴电基站4" /> | 
					
						
							|  |  |  |                         <el-option label="兴电基站5" value="兴电基站5" /> | 
					
						
							|  |  |  |                     </el-select> | 
					
						
							|  |  |  |                 </el-col> | 
					
						
							|  |  |  |                 <el-col :span="2"> | 
					
						
							|  |  |  |                     <el-button type="primary" @click="handleSearch" style="width: 100%"> | 
					
						
							|  |  |  |                         <el-icon><Search /></el-icon> | 
					
						
							|  |  |  |                         搜索 | 
					
						
							|  |  |  |                     </el-button> | 
					
						
							|  |  |  |                 </el-col> | 
					
						
							|  |  |  |                 <el-col :span="3"> | 
					
						
							|  |  |  |                     <el-button type="primary" @click="handleAddDevice" style="width: 100%"> | 
					
						
							|  |  |  |                         <el-icon><CirclePlus /></el-icon> | 
					
						
							|  |  |  |                         添加设备 | 
					
						
							|  |  |  |                     </el-button> | 
					
						
							|  |  |  |                 </el-col> | 
					
						
							|  |  |  |                 <el-col :span="3"> | 
					
						
							|  |  |  |                     <el-button type="primary" @click="handleBatchConfig" style="width: 100%"> | 
					
						
							|  |  |  |                         <el-icon><Setting /></el-icon> | 
					
						
							|  |  |  |                         批量配置 | 
					
						
							|  |  |  |                     </el-button> | 
					
						
							|  |  |  |                 </el-col> | 
					
						
							|  |  |  |             </el-row> | 
					
						
							|  |  |  |         </div> | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |         <!-- 设备信息表格 --> | 
					
						
							| 
									
										
										
										
											2025-09-19 10:20:18 +08:00
										 |  |  |         <el-table v-loading="loading" :data="deviceList" style="width: 100%"> | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |             <el-table-column prop="deviceId" label="设备ID" min-width="120" align="center" /> | 
					
						
							|  |  |  |             <el-table-column prop="deviceName" label="设备名称" min-width="120" align="center" /> | 
					
						
							|  |  |  |             <el-table-column prop="deviceType" label="类型" min-width="100" align="center"> | 
					
						
							|  |  |  |                 <template #default="scope"> | 
					
						
							|  |  |  |                     <el-tag :type="getDeviceTypeTagType(scope.row.deviceType)" :effect="'light'"> | 
					
						
							|  |  |  |                         {{ scope.row.deviceType }} | 
					
						
							|  |  |  |                     </el-tag> | 
					
						
							|  |  |  |                 </template> | 
					
						
							|  |  |  |             </el-table-column> | 
					
						
							|  |  |  |             <el-table-column prop="station" label="所属电站" min-width="120" align="center" /> | 
					
						
							|  |  |  |             <el-table-column prop="protocol" label="通讯协议" min-width="100" align="center" /> | 
					
						
							|  |  |  |             <el-table-column prop="ipAddress" label="IP地址" min-width="120" align="center" /> | 
					
						
							|  |  |  |             <el-table-column prop="lastOnlineTime" label="最后在线时间" min-width="150" align="center" /> | 
					
						
							|  |  |  |             <el-table-column prop="status" label="状态" min-width="80"> | 
					
						
							|  |  |  |                 <template #default="scope"> | 
					
						
							| 
									
										
										
										
											2025-09-19 10:20:18 +08:00
										 |  |  |                     <el-tag :type="getStatusTagType(scope.row.status)" :effect="light"> | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |                         {{ getStatusText(scope.row.status) }} | 
					
						
							|  |  |  |                     </el-tag> | 
					
						
							|  |  |  |                 </template> | 
					
						
							|  |  |  |             </el-table-column> | 
					
						
							|  |  |  |             <el-table-column label="操作" min-width="150" fixed="right"> | 
					
						
							|  |  |  |                 <template #default="scope"> | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |                     <span style="color: #1890ff; cursor: pointer; margin-right: 15px;" @click="handleDetails(scope.row)"> | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |                         查看 | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |                     </span> | 
					
						
							|  |  |  |                     <span style="color: #666666; cursor: pointer; margin-right: 15px;" @click="handleConfig(scope.row)"> | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |                         配置 | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |                     </span> | 
					
						
							|  |  |  |                     <span style="color: #666666; cursor: pointer;" @click="handleDelete(scope.row)"> | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |                         删除 | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |                     </span> | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |                 </template> | 
					
						
							|  |  |  |             </el-table-column> | 
					
						
							|  |  |  |         </el-table> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <!-- 分页区域 --> | 
					
						
							|  |  |  |         <div class="pagination-container"> | 
					
						
							|  |  |  |             <el-pagination v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize" | 
					
						
							| 
									
										
										
										
											2025-09-19 10:20:18 +08:00
										 |  |  |                 :page-sizes="[10, 20, 50, 100]" layout="prev, pager, next, jumper" | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |                 :total="pagination.total" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  | </template> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <script setup> | 
					
						
							| 
									
										
										
										
											2025-09-19 10:20:18 +08:00
										 |  |  | import { Search, CirclePlus, Setting } from '@element-plus/icons-vue'; | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  | import { ref, reactive, watch } from 'vue'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 定义props接收数据
 | 
					
						
							|  |  |  | const props = defineProps({ | 
					
						
							|  |  |  |   tableData: { | 
					
						
							|  |  |  |     type: Object, | 
					
						
							|  |  |  |     default: () => ({ | 
					
						
							|  |  |  |       list: [], | 
					
						
							|  |  |  |       total: 0 | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // 搜索表单数据
 | 
					
						
							|  |  |  | const searchForm = reactive({ | 
					
						
							|  |  |  |     deviceType: '', | 
					
						
							|  |  |  |     station: '', | 
					
						
							|  |  |  |     protocol: '', | 
					
						
							|  |  |  |     status: '', | 
					
						
							|  |  |  |     keyword: '' | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 表格加载状态
 | 
					
						
							|  |  |  | const loading = ref(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 分页数据
 | 
					
						
							|  |  |  | const pagination = reactive({ | 
					
						
							|  |  |  |     currentPage: 1, | 
					
						
							|  |  |  |     pageSize: 10, | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |     total: 0 | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 设备列表数据
 | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  | const deviceList = ref([]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 监听props变化并更新设备列表
 | 
					
						
							|  |  |  | watch(() => props.tableData, (newData) => { | 
					
						
							|  |  |  |   deviceList.value = newData.list || []; | 
					
						
							|  |  |  |   pagination.total = newData.total || 0; | 
					
						
							|  |  |  | }, { immediate: true, deep: true }); | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // 获取状态文本
 | 
					
						
							|  |  |  | const getStatusText = (status) => { | 
					
						
							|  |  |  |     const statusMap = { | 
					
						
							|  |  |  |         normal: '正常', | 
					
						
							|  |  |  |         interrupt: '中断', | 
					
						
							|  |  |  |         abnormal: '异常' | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     return statusMap[status] || status; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 获取状态标签类型
 | 
					
						
							|  |  |  | const getStatusTagType = (status) => { | 
					
						
							|  |  |  |     const typeMap = { | 
					
						
							|  |  |  |         normal: 'success', | 
					
						
							|  |  |  |         interrupt: 'warning', | 
					
						
							|  |  |  |         abnormal: 'danger' | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     return typeMap[status] || 'default'; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-19 10:20:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // 获取设备类型标签类型
 | 
					
						
							|  |  |  | const getDeviceTypeTagType = (deviceType) => { | 
					
						
							|  |  |  |     const typeMap = { | 
					
						
							|  |  |  |         '逆变器': 'primary', | 
					
						
							|  |  |  |         '传感器': 'success', | 
					
						
							|  |  |  |         '电表': 'warning', | 
					
						
							|  |  |  |         '摄像头': 'info', | 
					
						
							|  |  |  |         '控制器': 'danger' | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     return typeMap[deviceType] || 'default'; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 处理搜索
 | 
					
						
							|  |  |  | const handleSearch = () => { | 
					
						
							|  |  |  |     loading.value = true; | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |     pagination.currentPage = 1; | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |     // 模拟搜索请求
 | 
					
						
							|  |  |  |     setTimeout(() => { | 
					
						
							|  |  |  |         loading.value = false; | 
					
						
							|  |  |  |         ElMessage.success('搜索成功'); | 
					
						
							|  |  |  |         // 实际项目中这里应该调用API获取数据
 | 
					
						
							|  |  |  |     }, 500); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 处理添加设备
 | 
					
						
							|  |  |  | const handleAddDevice = () => { | 
					
						
							|  |  |  |     // 实际项目中这里应该打开添加设备的弹窗或跳转到添加页面
 | 
					
						
							|  |  |  |     ElMessage.success('打开添加设备窗口'); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 处理批量配置
 | 
					
						
							|  |  |  | const handleBatchConfig = () => { | 
					
						
							|  |  |  |     // 实际项目中这里应该打开批量配置的弹窗
 | 
					
						
							|  |  |  |     ElMessage.success('打开批量配置窗口'); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 处理查看详情
 | 
					
						
							|  |  |  | const handleDetails = (row) => { | 
					
						
							|  |  |  |     // 实际项目中这里应该打开设备详情的弹窗或跳转到详情页面
 | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |     ElMessage.success(`查看设备${row.deviceId}详情`); | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 处理配置
 | 
					
						
							|  |  |  | const handleConfig = (row) => { | 
					
						
							|  |  |  |     // 实际项目中这里应该打开设备配置的弹窗
 | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |     ElMessage.success(`配置设备${row.deviceId}`); | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 处理删除
 | 
					
						
							|  |  |  | const handleDelete = (row) => { | 
					
						
							|  |  |  |     ElMessageBox.confirm( | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |         `确定要删除设备${row.deviceId}吗?`, | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |         '提示', | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             confirmButtonText: '确定', | 
					
						
							|  |  |  |             cancelButtonText: '取消', | 
					
						
							|  |  |  |             type: 'warning' | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |         .then(() => { | 
					
						
							|  |  |  |             // 实际项目中这里应该调用API删除设备
 | 
					
						
							|  |  |  |             ElMessage.success('删除成功'); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         .catch(() => { | 
					
						
							|  |  |  |             ElMessage.info('已取消删除'); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 处理分页大小变化
 | 
					
						
							|  |  |  | const handleSizeChange = (size) => { | 
					
						
							|  |  |  |     pagination.pageSize = size; | 
					
						
							|  |  |  |     // 实际项目中这里应该重新请求数据
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 处理分页页码变化
 | 
					
						
							|  |  |  | const handleCurrentChange = (current) => { | 
					
						
							|  |  |  |     pagination.currentPage = current; | 
					
						
							|  |  |  |     // 实际项目中这里应该重新请求数据
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <style scoped> | 
					
						
							|  |  |  | .manage-form-container { | 
					
						
							|  |  |  |     background-color: #fff; | 
					
						
							|  |  |  |     padding: 20px; | 
					
						
							|  |  |  |     border-radius: 8px; | 
					
						
							|  |  |  |     min-height: 100%; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-19 10:20:18 +08:00
										 |  |  | .search-filter-section { | 
					
						
							|  |  |  |     margin-bottom: 24px; | 
					
						
							|  |  |  |     padding: 16px; | 
					
						
							|  |  |  |     background-color: #f5f7fa; | 
					
						
							|  |  |  |     border-radius: 8px; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 下拉选择框样式优化 */ | 
					
						
							|  |  |  | :deep(.el-select) { | 
					
						
							|  |  |  |     width: 100%; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :deep(.el-input__wrapper) { | 
					
						
							|  |  |  |     border-radius: 6px; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 按钮样式优化 */ | 
					
						
							|  |  |  | :deep(.el-button) { | 
					
						
							|  |  |  |     border-radius: 6px; | 
					
						
							|  |  |  |     font-size: 14px; | 
					
						
							|  |  |  |     transition: all 0.3s ease; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :deep(.el-button--primary) { | 
					
						
							|  |  |  |     background-color: #1890ff; | 
					
						
							|  |  |  |     border-color: #1890ff; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :deep(.el-button--primary:hover) { | 
					
						
							|  |  |  |     background-color: #40a9ff; | 
					
						
							|  |  |  |     border-color: #40a9ff; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 响应式设计 */ | 
					
						
							|  |  |  | @media screen and (max-width: 1200px) { | 
					
						
							|  |  |  |     .search-filter-section .el-col { | 
					
						
							|  |  |  |         margin-bottom: 12px; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @media screen and (max-width: 768px) { | 
					
						
							|  |  |  |     .search-filter-section { | 
					
						
							|  |  |  |         padding: 12px; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     .search-filter-section .el-row { | 
					
						
							|  |  |  |         display: flex; | 
					
						
							|  |  |  |         flex-direction: column; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     .search-filter-section .el-col { | 
					
						
							|  |  |  |         width: 100% !important; | 
					
						
							|  |  |  |         margin-bottom: 12px; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .action-buttons { | 
					
						
							|  |  |  |     margin-bottom: 20px; | 
					
						
							|  |  |  |     display: flex; | 
					
						
							|  |  |  |     gap: 10px; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .pagination-container { | 
					
						
							|  |  |  |     margin-top: 20px; | 
					
						
							|  |  |  |     display: flex; | 
					
						
							|  |  |  |     justify-content: flex-end; | 
					
						
							|  |  |  |     align-items: center; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 表格样式优化 */ | 
					
						
							|  |  |  | :deep(.el-table) { | 
					
						
							|  |  |  |     border-radius: 8px; | 
					
						
							|  |  |  |     overflow: hidden; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :deep(.el-table__header-wrapper) { | 
					
						
							|  |  |  |     background-color: #fafafa; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :deep(.el-table__row:hover) { | 
					
						
							|  |  |  |     background-color: #f5f7fa; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 分页样式优化 */ | 
					
						
							|  |  |  | :deep(.el-pagination) { | 
					
						
							|  |  |  |     display: flex; | 
					
						
							|  |  |  |     justify-content: flex-end; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | </style> |