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/DeviceGroupList.vue | 748 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 748 insertions(+), 0 deletions(-)
diff --git a/mes-web/src/views/device/DeviceGroupList.vue b/mes-web/src/views/device/DeviceGroupList.vue
new file mode 100644
index 0000000..9d4163c
--- /dev/null
+++ b/mes-web/src/views/device/DeviceGroupList.vue
@@ -0,0 +1,748 @@
+<template>
+ <div class="device-group-list">
+ <!-- 鎼滅储鍜岀瓫閫夊尯鍩� -->
+ <div class="search-section">
+ <el-form :model="searchForm" :inline="true" class="search-form">
+ <el-form-item label="缁勭被鍨�">
+ <el-select v-model="searchForm.groupType" placeholder="閫夋嫨缁勭被鍨�" clearable>
+ <el-option label="璁惧缁�" value="璁惧缁�" />
+ <el-option label="绠$悊缁�" value="绠$悊缁�" />
+ <el-option label="鐩戞帶缁�" value="鐩戞帶缁�" />
+ <el-option label="缁存姢缁�" value="缁存姢缁�" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="缁勭姸鎬�">
+ <el-select v-model="searchForm.groupStatus" placeholder="閫夋嫨缁勭姸鎬�" clearable>
+ <el-option label="鍚敤" value="ENABLED" />
+ <el-option label="绂佺敤" value="DISABLED" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鎼滅储鍏抽敭璇�">
+ <el-input v-model="searchForm.keyword" placeholder="缁勫悕绉版垨鎻忚堪" clearable style="width: 200px;">
+ <template #append>
+ <el-button @click="handleSearch">
+ <el-icon><Search /></el-icon>
+ </el-button>
+ </template>
+ </el-input>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleSearch">鎼滅储</el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+
+ <!-- 鎵归噺鎿嶄綔鍖哄煙 -->
+ <div class="batch-operation" v-if="selectedGroups.length > 0">
+ <el-alert
+ :title="`宸查�夋嫨 ${selectedGroups.length} 涓澶囩粍`"
+ type="info"
+ show-icon
+ :closable="false"
+ />
+ <div class="batch-buttons">
+ <el-button type="success" size="small" @click="batchEnable">鎵归噺鍚敤</el-button>
+ <el-button type="warning" size="small" @click="batchDisable">鎵归噺绂佺敤</el-button>
+ <el-button type="danger" size="small" @click="batchDelete">鎵归噺鍒犻櫎</el-button>
+ <el-button size="small" @click="clearSelection">鍙栨秷閫夋嫨</el-button>
+ </div>
+ </div>
+
+ <!-- 璁惧缁勫垪琛� -->
+ <div class="table-section">
+ <el-table
+ ref="groupTable"
+ v-loading="tableLoading"
+ :data="groupList"
+ @selection-change="handleSelectionChange"
+ border
+ stripe
+ style="width: 100%"
+ >
+ <el-table-column type="selection" width="55" />
+ <el-table-column prop="groupName" label="缁勫悕绉�" min-width="150" />
+ <el-table-column prop="groupCode" label="缁勭紪鐮�" width="130" />
+ <el-table-column prop="groupType" label="缁勭被鍨�" width="100">
+ <template #default="scope">
+ <el-tag :type="getGroupTypeTag(scope.row.groupType)">
+ {{ scope.row.groupType }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="description" label="鎻忚堪" min-width="200" />
+ <el-table-column prop="groupStatus" label="缁勭姸鎬�" width="100">
+ <template #default="scope">
+ <el-tag :type="getGroupStatusTag(scope.row.groupStatus)" size="small">
+ {{ getGroupStatusText(scope.row.groupStatus) }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="enabled" label="鍚敤鐘舵��" width="100">
+ <template #default="scope">
+ <el-switch
+ v-model="scope.row.enabled"
+ @change="handleStatusChange(scope.row)"
+ />
+ </template>
+ </el-table-column>
+ <el-table-column prop="deviceCount" label="璁惧鏁伴噺" width="100" align="center">
+ <template #default="scope">
+ <el-tag type="info" size="small">{{ scope.row.deviceCount || 0 }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="onlineDeviceCount" label="鍦ㄧ嚎璁惧" width="100" align="center">
+ <template #default="scope">
+ <el-tag type="success" size="small">{{ scope.row.onlineDeviceCount || 0 }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="sortOrder" label="鎺掑簭" width="80" align="center" />
+ <el-table-column label="鎿嶄綔" width="280" fixed="right">
+ <template #default="scope">
+ <el-button type="primary" size="small" @click="editGroup(scope.row)">
+ 缂栬緫
+ </el-button>
+ <el-button type="success" size="small" @click="manageDevices(scope.row)">
+ 璁惧绠$悊
+ </el-button>
+ <el-button type="warning" size="small" :loading="groupPlcLoading" @click="triggerGroupPlcRequest(scope.row)">
+ PLC璇锋眰
+ </el-button>
+ <el-button type="info" size="small" @click="viewGroupPlcStatus(scope.row)">
+ PLC鐘舵��
+ </el-button>
+ <el-button type="success" size="small" @click="viewStatistics(scope.row)">
+ 缁熻
+ </el-button>
+ <el-dropdown @command="(command) => handleCommand(command, scope.row)">
+ <el-button type="info" size="small">
+ 鏇村<el-icon><ArrowDown /></el-icon>
+ </el-button>
+ <template #dropdown>
+ <el-dropdown-menu>
+ <el-dropdown-item command="view">鏌ョ湅璇︽儏</el-dropdown-item>
+ <el-dropdown-item command="copy">澶嶅埗閰嶇疆</el-dropdown-item>
+ <el-dropdown-item command="export">瀵煎嚭閰嶇疆</el-dropdown-item>
+ <el-dropdown-item command="test">娴嬭瘯杩炴帴</el-dropdown-item>
+ <el-dropdown-item command="plc-report">PLC姹囨姤</el-dropdown-item>
+ <el-dropdown-item command="delete" divided>鍒犻櫎缁�</el-dropdown-item>
+ </el-dropdown-menu>
+ </template>
+ </el-dropdown>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+
+ <!-- 鍒嗛〉 -->
+ <div class="pagination-section">
+ <el-pagination
+ v-model:current-page="pagination.page"
+ v-model:page-size="pagination.size"
+ :page-sizes="[10, 20, 50, 100]"
+ :total="pagination.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
+ </div>
+
+ <!-- 璁惧绠$悊寮圭獥 -->
+ <el-dialog
+ v-model="deviceDialogVisible"
+ :title="`璁惧缁勶細${currentGroup?.groupName} - 璁惧绠$悊`"
+ width="80%"
+ :close-on-click-modal="false"
+ >
+ <div class="device-management">
+ <div class="dialog-header">
+ <div class="device-stats">
+ <el-statistic title="鎬昏澶囨暟" :value="currentGroup?.deviceCount || 0" />
+ <el-statistic title="鍦ㄧ嚎璁惧" :value="currentGroup?.onlineDeviceCount || 0" />
+ <el-statistic title="绂荤嚎璁惧" :value="(currentGroup?.deviceCount || 0) - (currentGroup?.onlineDeviceCount || 0)" />
+ </div>
+ <div class="dialog-buttons">
+ <el-button type="primary" @click="addDevices">娣诲姞璁惧</el-button>
+ <el-button type="danger" @click="removeDevices" :disabled="selectedDevicesInGroup.length === 0">
+ 绉婚櫎璁惧
+ </el-button>
+ </div>
+ </div>
+
+ <el-table
+ v-loading="deviceLoading"
+ :data="groupDeviceList"
+ @selection-change="handleDeviceSelectionChange"
+ border
+ stripe
+ >
+ <el-table-column type="selection" width="55" />
+ <el-table-column prop="deviceName" label="璁惧鍚嶇О" />
+ <el-table-column prop="deviceCode" label="璁惧缂栫爜" />
+ <el-table-column prop="deviceType" label="璁惧绫诲瀷" />
+ <el-table-column prop="plcIp" label="PLC IP" />
+ <el-table-column prop="deviceStatus" label="璁惧鐘舵��">
+ <template #default="scope">
+ <el-tag :type="getDeviceStatusTag(scope.row.deviceStatus)" size="small">
+ {{ getDeviceStatusText(scope.row.deviceStatus) }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+
+ <template #footer>
+ <el-button @click="deviceDialogVisible = false">鍏抽棴</el-button>
+ </template>
+ </el-dialog>
+
+ <!-- 缁熻璇︽儏寮圭獥 -->
+ <el-dialog
+ v-model="statisticsDialogVisible"
+ title="璁惧缁勭粺璁�"
+ width="60%"
+ >
+ <div class="statistics-content">
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <h4>璁惧绫诲瀷鍒嗗竷</h4>
+ <div class="chart-container" style="height: 200px; background: #f5f7fa; display: flex; align-items: center; justify-content: center;">
+ <p>鍥捐〃鍔熻兘寮�鍙戜腑...</p>
+ </div>
+ </el-col>
+ <el-col :span="12">
+ <h4>璁惧鐘舵�佸垎甯�</h4>
+ <div class="chart-container" style="height: 200px; background: #f5f7fa; display: flex; align-items: center; justify-content: center;">
+ <p>鍥捐〃鍔熻兘寮�鍙戜腑...</p>
+ </div>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20" style="margin-top: 20px;">
+ <el-col :span="24">
+ <h4>璇︾粏淇℃伅</h4>
+ <el-descriptions :column="2" border>
+ <el-descriptions-item label="鎬昏澶囨暟">{{ currentGroup?.deviceCount || 0 }}</el-descriptions-item>
+ <el-descriptions-item label="鍦ㄧ嚎璁惧">{{ currentGroup?.onlineDeviceCount || 0 }}</el-descriptions-item>
+ <el-descriptions-item label="绂荤嚎璁惧">{{ (currentGroup?.deviceCount || 0) - (currentGroup?.onlineDeviceCount || 0) }}</el-descriptions-item>
+ <el-descriptions-item label="鍚敤鐜�">{{ getEnableRate() }}%</el-descriptions-item>
+ </el-descriptions>
+ </el-col>
+ </el-row>
+ </div>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Search, ArrowDown } from '@element-plus/icons-vue'
+import { deviceGroupApi, devicePlcApi } from '@/api/device/deviceManagement'
+
+// 鍝嶅簲寮忔暟鎹�
+const groupTable = ref(null)
+const tableLoading = ref(false)
+const groupList = ref([])
+const selectedGroups = ref([])
+const groupPlcLoading = ref(false)
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+ groupType: '',
+ groupStatus: '',
+ keyword: ''
+})
+
+// 鍒嗛〉淇℃伅
+const pagination = reactive({
+ page: 1,
+ size: 10,
+ total: 0
+})
+
+// 璁惧绠$悊寮圭獥鐩稿叧
+const deviceDialogVisible = ref(false)
+const deviceLoading = ref(false)
+const currentGroup = ref(null)
+const groupDeviceList = ref([])
+const selectedDevicesInGroup = ref([])
+
+// 缁熻寮圭獥
+const statisticsDialogVisible = ref(false)
+
+// 浜嬩欢瀹氫箟
+const emit = defineEmits(['group-selected', 'refresh-statistics'])
+
+// 鏂规硶瀹氫箟
+const loadGroupList = async () => {
+ try {
+ tableLoading.value = true
+ const params = {
+ page: pagination.page,
+ size: pagination.size,
+ groupType: searchForm.groupType || undefined,
+ groupStatus: searchForm.groupStatus || undefined,
+ keyword: searchForm.keyword || undefined
+ }
+
+ const response = await deviceGroupApi.getList(params)
+ // MyBatis-Plus Page 瀵硅薄缁撴瀯锛歿 records: [], total: 0 }
+ if (response && response.data) {
+ groupList.value = response.data.records || response.data.content || response.data.list || []
+ pagination.total = response.data.total || response.data.totalElements || 0
+ } else {
+ groupList.value = []
+ pagination.total = 0
+ }
+ } catch (error) {
+ console.error('鍔犺浇璁惧缁勫垪琛ㄥけ璐�:', error)
+ ElMessage.error('鍔犺浇璁惧缁勫垪琛ㄥけ璐�: ' + (error.response?.data?.message || error.message))
+ groupList.value = []
+ pagination.total = 0
+ } finally {
+ tableLoading.value = false
+ }
+}
+
+const handleSearch = () => {
+ pagination.page = 1
+ loadGroupList()
+}
+
+const resetSearch = () => {
+ searchForm.groupType = ''
+ searchForm.groupStatus = ''
+ searchForm.keyword = ''
+ pagination.page = 1
+ loadGroupList()
+}
+
+const handleSelectionChange = (selection) => {
+ selectedGroups.value = selection
+}
+
+const clearSelection = () => {
+ groupTable.value?.clearSelection()
+ selectedGroups.value = []
+}
+
+const groupPlcLabelMap = {
+ request: 'PLC璇锋眰',
+ report: 'PLC姹囨姤'
+}
+
+const handleGroupPlcOperation = async (groupId, operation) => {
+ if (!groupId) {
+ ElMessage.warning('璇峰厛閫夋嫨璁惧缁�')
+ return
+ }
+ groupPlcLoading.value = true
+ try {
+ let response
+ switch (operation) {
+ case 'request':
+ response = await devicePlcApi.triggerGroupRequest(groupId)
+ break
+ case 'report':
+ response = await devicePlcApi.triggerGroupReport(groupId)
+ break
+ default:
+ throw new Error('鏈煡鐨勮澶囩粍PLC鎿嶄綔')
+ }
+ const results = response?.data || []
+ const successCount = results.filter(item => item.success).length
+ const label = groupPlcLabelMap[operation] || 'PLC鎿嶄綔'
+ if (results.length === 0) {
+ ElMessage.info(`${label}鏈繑鍥炵粨鏋渀)
+ } else if (successCount === results.length) {
+ ElMessage.success(`${label}鎴愬姛锛�${successCount}/${results.length}锛塦)
+ } else {
+ ElMessage.warning(`${label}閮ㄥ垎鎴愬姛锛�${successCount}/${results.length}锛塦)
+ }
+ } catch (error) {
+ const label = groupPlcLabelMap[operation] || 'PLC鎿嶄綔'
+ console.error('璁惧缁凱LC鎿嶄綔澶辫触:', error)
+ ElMessage.error(`${label}澶辫触锛�${error.response?.data?.message || error.message}`)
+ } finally {
+ groupPlcLoading.value = false
+ }
+}
+
+const triggerGroupPlcRequest = (row) => handleGroupPlcOperation(row.id || row.groupId, 'request')
+const triggerGroupPlcReport = (row) => handleGroupPlcOperation(row.id || row.groupId, 'report')
+
+const viewGroupPlcStatus = async (row) => {
+ try {
+ const response = await devicePlcApi.getGroupStatus(row.id || row.groupId)
+ const statusList = response?.data || []
+ if (!statusList.length) {
+ ElMessage.info('鏈幏鍙栧埌PLC鐘舵�佹暟鎹�')
+ return
+ }
+ const htmlContent = statusList.map(item => {
+ const header = `${item.deviceName || item.deviceCode || item.deviceId}`
+ const body = JSON.stringify(item.data || {}, null, 2)
+ return `<div style="margin-bottom:12px"><strong>${header}</strong><pre style="margin:4px 0 0;max-height:260px;overflow:auto;">${body}</pre></div>`
+ }).join('')
+ await ElMessageBox.alert(htmlContent, `PLC鐘舵�� - ${row.groupName || row.groupCode}`, {
+ dangerouslyUseHTMLString: true,
+ confirmButtonText: '鍏抽棴'
+ })
+ } catch (error) {
+ console.error('鑾峰彇璁惧缁凱LC鐘舵�佸け璐�:', error)
+ ElMessage.error('鑾峰彇璁惧缁凱LC鐘舵�佸け璐�')
+ }
+}
+
+const handleStatusChange = async (row) => {
+ try {
+ const groupId = row.id || row.groupId
+ if (row.enabled) {
+ await deviceGroupApi.enable({ groupId })
+ ElMessage.success('璁惧缁勫惎鐢ㄦ垚鍔�')
+ } else {
+ await deviceGroupApi.disable({ groupId })
+ ElMessage.success('璁惧缁勭鐢ㄦ垚鍔�')
+ }
+ emit('refresh-statistics')
+ loadGroupList() // 鍒锋柊鍒楄〃
+ } catch (error) {
+ console.error('鏇存柊璁惧缁勭姸鎬佸け璐�:', error)
+ row.enabled = !row.enabled // 鎭㈠鐘舵��
+ ElMessage.error('鏇存柊璁惧缁勭姸鎬佸け璐�: ' + (error.response?.data?.message || error.message))
+ }
+}
+
+const batchEnable = async () => {
+ try {
+ const groupIds = selectedGroups.value.map(item => item.id || item.groupId)
+ await deviceGroupApi.batchEnable({ groupIds })
+ ElMessage.success(`鎴愬姛鍚敤 ${groupIds.length} 涓澶囩粍`)
+ clearSelection()
+ loadGroupList()
+ emit('refresh-statistics')
+ } catch (error) {
+ console.error('鎵归噺鍚敤澶辫触:', error)
+ ElMessage.error('鎵归噺鍚敤澶辫触: ' + (error.response?.data?.message || error.message))
+ }
+}
+
+const batchDisable = async () => {
+ try {
+ const groupIds = selectedGroups.value.map(item => item.id || item.groupId)
+ await deviceGroupApi.batchDisable({ groupIds })
+ ElMessage.success(`鎴愬姛绂佺敤 ${groupIds.length} 涓澶囩粍`)
+ clearSelection()
+ loadGroupList()
+ emit('refresh-statistics')
+ } catch (error) {
+ console.error('鎵归噺绂佺敤澶辫触:', error)
+ ElMessage.error('鎵归噺绂佺敤澶辫触: ' + (error.response?.data?.message || error.message))
+ }
+}
+
+const batchDelete = async () => {
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ら�変腑鐨� ${selectedGroups.value.length} 涓澶囩粍鍚楋紵姝ゆ搷浣滀笉鍙仮澶嶏紒`,
+ '鎵归噺鍒犻櫎纭',
+ {
+ confirmButtonText: '纭畾鍒犻櫎',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }
+ )
+
+ const groupIds = selectedGroups.value.map(item => item.id || item.groupId)
+ // 閫愪釜鍒犻櫎
+ for (const groupId of groupIds) {
+ await deviceGroupApi.delete({ groupId })
+ }
+ ElMessage.success(`鎴愬姛鍒犻櫎 ${groupIds.length} 涓澶囩粍`)
+ clearSelection()
+ loadGroupList()
+ emit('refresh-statistics')
+ } catch (error) {
+ if (error !== 'cancel') {
+ console.error('鎵归噺鍒犻櫎澶辫触:', error)
+ ElMessage.error('鎵归噺鍒犻櫎澶辫触')
+ }
+ }
+}
+
+const editGroup = (row) => {
+ emit('group-selected', row)
+}
+
+const manageDevices = async (row) => {
+ currentGroup.value = row
+ deviceDialogVisible.value = true
+ await loadGroupDevices(row.id || row.groupId)
+}
+
+const loadGroupDevices = async (groupId) => {
+ try {
+ deviceLoading.value = true
+ const response = await deviceGroupApi.getGroupDevices(groupId)
+ if (response && response.data) {
+ groupDeviceList.value = response.data || []
+ } else {
+ groupDeviceList.value = []
+ }
+ } catch (error) {
+ console.error('鍔犺浇缁勮澶囧垪琛ㄥけ璐�:', error)
+ ElMessage.error('鍔犺浇缁勮澶囧垪琛ㄥけ璐�: ' + (error.response?.data?.message || error.message))
+ groupDeviceList.value = []
+ } finally {
+ deviceLoading.value = false
+ }
+}
+
+const viewStatistics = (row) => {
+ currentGroup.value = row
+ statisticsDialogVisible.value = true
+}
+
+const handleDeviceSelectionChange = (selection) => {
+ selectedDevicesInGroup.value = selection
+}
+
+const addDevices = () => {
+ // 娣诲姞璁惧鍒扮粍閫昏緫
+ ElMessage.info('娣诲姞璁惧鍔熻兘寮�鍙戜腑...')
+}
+
+const removeDevices = async () => {
+ try {
+ if (selectedDevicesInGroup.value.length === 0) {
+ ElMessage.warning('璇烽�夋嫨瑕佺Щ闄ょ殑璁惧')
+ return
+ }
+
+ await ElMessageBox.confirm(
+ `纭畾瑕佷粠璁惧缁勪腑绉婚櫎閫変腑鐨� ${selectedDevicesInGroup.value.length} 涓澶囧悧锛焋,
+ '绉婚櫎璁惧纭'
+ )
+
+ const deviceIds = selectedDevicesInGroup.value.map(item => item.id || item.deviceId)
+ // 鎵归噺绉婚櫎璁惧
+ await deviceGroupApi.batchRemoveDevicesFromGroup({
+ groupId: currentGroup.value.id || currentGroup.value.groupId,
+ deviceIds
+ })
+ ElMessage.success(`鎴愬姛绉婚櫎 ${deviceIds.length} 涓澶嘸)
+ loadGroupDevices(currentGroup.value.id || currentGroup.value.groupId)
+ } catch (error) {
+ if (error !== 'cancel') {
+ console.error('绉婚櫎璁惧澶辫触:', error)
+ ElMessage.error('绉婚櫎璁惧澶辫触')
+ }
+ }
+}
+
+const handleCommand = async (command, row) => {
+ switch (command) {
+ case 'view':
+ // 鏌ョ湅璇︽儏閫昏緫
+ ElMessage.info('鏌ョ湅璇︽儏鍔熻兘寮�鍙戜腑...')
+ break
+ case 'copy':
+ // 澶嶅埗閰嶇疆閫昏緫
+ ElMessage.info('澶嶅埗閰嶇疆鍔熻兘寮�鍙戜腑...')
+ break
+ case 'export':
+ // 瀵煎嚭閰嶇疆閫昏緫
+ ElMessage.info('瀵煎嚭閰嶇疆鍔熻兘寮�鍙戜腑...')
+ break
+ case 'test':
+ // 娴嬭瘯杩炴帴閫昏緫
+ try {
+ const response = await deviceGroupApi.healthCheck({ groupId: row.id || row.groupId })
+ ElMessage.success('杩炴帴娴嬭瘯鎴愬姛')
+ } catch (error) {
+ ElMessage.error('杩炴帴娴嬭瘯澶辫触: ' + (error.response?.data?.message || error.message))
+ }
+ break
+ case 'plc-report':
+ await triggerGroupPlcReport(row)
+ break
+ case 'delete':
+ await ElMessageBox.confirm('纭畾瑕佸垹闄よ璁惧缁勫悧锛�', '鍒犻櫎纭', {
+ confirmButtonText: '纭畾鍒犻櫎',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ })
+ await deviceGroupApi.delete({ groupId: row.id || row.groupId })
+ ElMessage.success('璁惧缁勫垹闄ゆ垚鍔�')
+ loadGroupList()
+ emit('refresh-statistics')
+ break
+ }
+}
+
+const handleSizeChange = (size) => {
+ pagination.size = size
+ pagination.page = 1
+ loadGroupList()
+}
+
+const handleCurrentChange = (page) => {
+ pagination.page = page
+ loadGroupList()
+}
+
+// 宸ュ叿鍑芥暟
+const getGroupTypeTag = (type) => {
+ const typeMap = {
+ '璁惧缁�': 'primary',
+ '绠$悊缁�': 'success',
+ '鐩戞帶缁�': 'warning',
+ '缁存姢缁�': 'info'
+ }
+ return typeMap[type] || 'info'
+}
+
+const getGroupStatusTag = (status) => {
+ const statusMap = {
+ 'ENABLED': 'success',
+ 'DISABLED': 'info'
+ }
+ return statusMap[status] || 'info'
+}
+
+const getGroupStatusText = (status) => {
+ const statusMap = {
+ 'ENABLED': '鍚敤',
+ 'DISABLED': '绂佺敤'
+ }
+ return statusMap[status] || status
+}
+
+const getDeviceStatusTag = (status) => {
+ const statusMap = {
+ 'ONLINE': 'success',
+ 'OFFLINE': 'info',
+ 'MAINTENANCE': 'warning',
+ 'DISABLED': 'danger'
+ }
+ return statusMap[status] || 'info'
+}
+
+const getDeviceStatusText = (status) => {
+ const statusMap = {
+ 'ONLINE': '鍦ㄧ嚎',
+ 'OFFLINE': '绂荤嚎',
+ 'MAINTENANCE': '缁存姢涓�',
+ 'DISABLED': '绂佺敤'
+ }
+ return statusMap[status] || status
+}
+
+const getEnableRate = () => {
+ if (!currentGroup.value || !currentGroup.value.deviceCount) return 0
+ return Math.round((currentGroup.value.onlineDeviceCount / currentGroup.value.deviceCount) * 100)
+}
+
+// 鏆撮湶鏂规硶
+const refresh = () => {
+ loadGroupList()
+}
+
+defineExpose({
+ refresh
+})
+
+// 缁勪欢鎸傝浇鏃跺姞杞芥暟鎹�
+onMounted(() => {
+ loadGroupList()
+})
+</script>
+
+<style scoped>
+.device-group-list {
+ padding: 20px;
+}
+
+.search-section {
+ margin-bottom: 20px;
+ padding: 16px;
+ background-color: #f5f7fa;
+ border-radius: 8px;
+}
+
+.batch-operation {
+ margin-bottom: 16px;
+ padding: 16px;
+ background-color: #e6f7ff;
+ border: 1px solid #91d5ff;
+ border-radius: 8px;
+}
+
+.batch-buttons {
+ margin-top: 12px;
+ display: flex;
+ gap: 8px;
+}
+
+.table-section {
+ margin-bottom: 20px;
+}
+
+.pagination-section {
+ display: flex;
+ justify-content: center;
+}
+
+.device-management {
+ padding: 20px 0;
+}
+
+.dialog-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ padding-bottom: 16px;
+ border-bottom: 1px solid #ebeef5;
+}
+
+.device-stats {
+ display: flex;
+ gap: 40px;
+}
+
+.dialog-buttons {
+ display: flex;
+ gap: 12px;
+}
+
+.statistics-content {
+ padding: 20px 0;
+}
+
+.chart-container {
+ border: 1px solid #ebeef5;
+ border-radius: 8px;
+}
+
+:deep(.el-table .cell) {
+ white-space: nowrap;
+}
+
+:deep(.el-dropdown-menu__item.is-divided) {
+ border-top: 1px solid #ebeef5;
+ margin-top: 6px;
+ padding-top: 10px;
+}
+
+:deep(.el-statistic .el-statistic__title) {
+ font-weight: normal;
+ color: #666;
+}
+
+:deep(.el-statistic .el-statistic__content) {
+ font-size: 24px;
+ font-weight: bold;
+ color: #409eff;
+}
+</style>
\ No newline at end of file
--
Gitblit v1.8.0