From e76f0739e647fe8a7e0e2618914e2faff554b1b7 Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期一, 17 十一月 2025 17:33:23 +0800
Subject: [PATCH] 解决冲突

---
 mes-web/src/views/device/DeviceManagement.vue |  343 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 343 insertions(+), 0 deletions(-)

diff --git a/mes-web/src/views/device/DeviceManagement.vue b/mes-web/src/views/device/DeviceManagement.vue
new file mode 100644
index 0000000..72924c3
--- /dev/null
+++ b/mes-web/src/views/device/DeviceManagement.vue
@@ -0,0 +1,343 @@
+<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>
\ No newline at end of file

--
Gitblit v1.8.0