<template>
|
<div class="device-management">
|
<!-- 页面标题和操作按钮 -->
|
<div class="page-header">
|
<div class="title-section">
|
<h2>设备管理</h2>
|
<p>管理多设备联合测试的设备配置和设备组</p>
|
</div>
|
<div class="action-section">
|
<el-button type="primary" @click="showCreateDeviceDialog">
|
<el-icon><Plus /></el-icon>
|
创建设备
|
</el-button>
|
<el-button type="success" @click="showCreateGroupDialog">
|
<el-icon><Plus /></el-icon>
|
创建设备组
|
</el-button>
|
</div>
|
</div>
|
|
<!-- 统计卡片 -->
|
<div class="statistics-section">
|
<el-row :gutter="20">
|
<el-col :span="6">
|
<div class="stat-card">
|
<div class="stat-icon">
|
<el-icon size="24"><Monitor /></el-icon>
|
</div>
|
<div class="stat-content">
|
<div class="stat-value">{{ statistics.totalDevices }}</div>
|
<div class="stat-label">设备总数</div>
|
</div>
|
</div>
|
</el-col>
|
<el-col :span="6">
|
<div class="stat-card">
|
<div class="stat-icon">
|
<el-icon size="24"><CircleCheck /></el-icon>
|
</div>
|
<div class="stat-content">
|
<div class="stat-value">{{ statistics.onlineDevices }}</div>
|
<div class="stat-label">在线设备</div>
|
</div>
|
</div>
|
</el-col>
|
<el-col :span="6">
|
<div class="stat-card">
|
<div class="stat-icon">
|
<el-icon size="24"><Grid /></el-icon>
|
</div>
|
<div class="stat-content">
|
<div class="stat-value">{{ statistics.totalGroups }}</div>
|
<div class="stat-label">设备组数</div>
|
</div>
|
</div>
|
</el-col>
|
<el-col :span="6">
|
<div class="stat-card">
|
<div class="stat-icon">
|
<el-icon size="24"><Setting /></el-icon>
|
</div>
|
<div class="stat-content">
|
<div class="stat-value">{{ statistics.enabledGroups }}</div>
|
<div class="stat-label">启用组数</div>
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
</div>
|
|
<!-- Tab切换 -->
|
<div class="tab-section">
|
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
<el-tab-pane label="设备配置" name="devices">
|
<DeviceConfigList
|
ref="deviceConfigListRef"
|
@device-selected="handleDeviceSelected"
|
@refresh-statistics="loadStatistics"
|
/>
|
</el-tab-pane>
|
<el-tab-pane label="设备组管理" name="groups">
|
<DeviceGroupList
|
ref="deviceGroupListRef"
|
@group-selected="handleGroupSelected"
|
@refresh-statistics="loadStatistics"
|
/>
|
</el-tab-pane>
|
</el-tabs>
|
</div>
|
|
<!-- 设备配置弹窗 -->
|
<DeviceEditDialog
|
v-model="deviceDialogVisible"
|
:deviceData="selectedDevice"
|
@success="handleDeviceFormSuccess"
|
/>
|
|
<!-- 设备组配置弹窗 -->
|
<DeviceGroupEditDialog
|
v-model:visible="groupDialogVisible"
|
:data="selectedGroup"
|
@success="handleGroupFormSuccess"
|
/>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted } from 'vue'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { Plus, Monitor, CircleCheck, Grid, Setting } from '@element-plus/icons-vue'
|
import DeviceConfigList from './DeviceConfigList.vue'
|
import DeviceGroupList from './DeviceGroupList.vue'
|
import DeviceEditDialog from './DeviceEditDialog.vue'
|
import DeviceGroupEditDialog from './DeviceGroupEditDialog.vue'
|
import {
|
getDeviceStatistics,
|
getDeviceGroupStatistics,
|
deviceConfigApi
|
} from '@/api/device/deviceManagement'
|
|
// 响应式数据
|
const activeTab = ref('devices')
|
const deviceDialogVisible = ref(false)
|
const groupDialogVisible = ref(false)
|
const deviceFormMode = ref('create')
|
const groupFormMode = ref('create')
|
const selectedDevice = ref(null)
|
const selectedGroup = ref(null)
|
const deviceConfigListRef = ref(null)
|
const deviceGroupListRef = ref(null)
|
|
// 统计数据
|
const statistics = reactive({
|
totalDevices: 0,
|
onlineDevices: 0,
|
offlineDevices: 0,
|
maintenanceDevices: 0,
|
totalGroups: 0,
|
enabledGroups: 0,
|
disabledGroups: 0,
|
maintenanceGroups: 0
|
})
|
|
// 方法定义
|
const showCreateDeviceDialog = () => {
|
selectedDevice.value = null
|
deviceFormMode.value = 'create'
|
deviceDialogVisible.value = true
|
}
|
|
const showCreateGroupDialog = () => {
|
selectedGroup.value = null
|
groupFormMode.value = 'create'
|
groupDialogVisible.value = true
|
}
|
|
const handleDeviceSelected = async (device) => {
|
try {
|
const res = await deviceConfigApi.getById(device.id || device.deviceId)
|
const detail = res?.data || {}
|
selectedDevice.value = { ...device, ...detail }
|
} catch (error) {
|
console.error('获取设备详情失败:', error)
|
ElMessage.warning('获取设备详情失败,使用列表数据进行编辑')
|
selectedDevice.value = device
|
}
|
deviceFormMode.value = 'edit'
|
deviceDialogVisible.value = true
|
}
|
|
const handleGroupSelected = (group) => {
|
selectedGroup.value = group
|
groupFormMode.value = 'edit'
|
groupDialogVisible.value = true
|
}
|
|
const handleTabChange = (tabName) => {
|
console.log('Tab切换到:', tabName)
|
}
|
|
const handleDeviceFormSuccess = () => {
|
deviceDialogVisible.value = false
|
// 刷新设备列表和统计数据
|
if (activeTab.value === 'devices') {
|
refreshDeviceList()
|
}
|
loadStatistics()
|
}
|
|
const handleGroupFormSuccess = () => {
|
groupDialogVisible.value = false
|
// 刷新设备组列表和统计数据
|
if (activeTab.value === 'groups') {
|
refreshDeviceGroupList()
|
}
|
loadStatistics()
|
}
|
|
const refreshDeviceList = () => {
|
if (deviceConfigListRef.value && deviceConfigListRef.value.refresh) {
|
deviceConfigListRef.value.refresh()
|
}
|
}
|
|
const refreshDeviceGroupList = () => {
|
if (deviceGroupListRef.value && deviceGroupListRef.value.refresh) {
|
deviceGroupListRef.value.refresh()
|
}
|
}
|
|
// 加载统计数据
|
const loadStatistics = async () => {
|
try {
|
const [deviceStatsRes, groupStatsRes] = await Promise.all([
|
getDeviceStatistics({}),
|
getDeviceGroupStatistics({})
|
])
|
|
const deviceStats = deviceStatsRes?.data || {}
|
const groupStats = groupStatsRes?.data || {}
|
|
Object.assign(statistics, {
|
totalDevices: deviceStats.totalDevices || deviceStats.total || 0,
|
onlineDevices: deviceStats.onlineDevices || deviceStats.online || 0,
|
offlineDevices: deviceStats.offlineDevices || deviceStats.offline || 0,
|
maintenanceDevices: deviceStats.maintenanceDevices || deviceStats.maintenance || 0,
|
totalGroups: groupStats.totalGroups || groupStats.total || 0,
|
enabledGroups: groupStats.enabledGroups || groupStats.enabled || 0,
|
disabledGroups: groupStats.disabledGroups || groupStats.disabled || 0,
|
maintenanceGroups: groupStats.maintenanceGroups || groupStats.maintenance || 0
|
})
|
} catch (error) {
|
console.error('加载统计数据失败:', error)
|
ElMessage.error('加载统计数据失败: ' + (error.response?.data?.message || error.message))
|
}
|
}
|
|
// 组件挂载时加载数据
|
onMounted(() => {
|
loadStatistics()
|
})
|
</script>
|
|
<style scoped>
|
.device-management {
|
padding: 20px;
|
background-color: #f5f7fa;
|
min-height: 100vh;
|
}
|
|
.page-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: flex-start;
|
margin-bottom: 24px;
|
background: white;
|
padding: 24px;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.title-section h2 {
|
margin: 0 0 8px 0;
|
color: #1f2937;
|
font-size: 24px;
|
font-weight: 600;
|
}
|
|
.title-section p {
|
margin: 0;
|
color: #6b7280;
|
font-size: 14px;
|
}
|
|
.action-section {
|
display: flex;
|
gap: 12px;
|
}
|
|
.statistics-section {
|
margin-bottom: 24px;
|
}
|
|
.stat-card {
|
background: white;
|
padding: 20px;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
display: flex;
|
align-items: center;
|
gap: 16px;
|
}
|
|
.stat-icon {
|
width: 48px;
|
height: 48px;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
border-radius: 12px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
color: white;
|
}
|
|
.stat-content {
|
flex: 1;
|
}
|
|
.stat-value {
|
font-size: 28px;
|
font-weight: 700;
|
color: #1f2937;
|
margin-bottom: 4px;
|
}
|
|
.stat-label {
|
font-size: 14px;
|
color: #6b7280;
|
}
|
|
.tab-section {
|
background: white;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
overflow: hidden;
|
}
|
|
:deep(.el-tabs__content) {
|
padding: 0;
|
}
|
|
:deep(.el-tabs__header) {
|
margin: 0;
|
background-color: #fafafa;
|
padding: 0 24px;
|
}
|
|
:deep(.el-tabs__item) {
|
padding: 16px 24px;
|
font-size: 14px;
|
font-weight: 500;
|
}
|
</style>
|