From 8f3a85044b6e4b56a8dd0b104ca023933f1f129c Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期三, 03 十二月 2025 16:58:36 +0800
Subject: [PATCH] 统一卧转立扫码、卧转立、大车、大理片笼的定时器逻辑和步骤状态;添加设备拓扑图清除数据、联机状态切换按钮,
---
mes-web/src/views/plcTest/components/DeviceGroup/GroupTopology.vue | 203 +++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 191 insertions(+), 12 deletions(-)
diff --git a/mes-web/src/views/plcTest/components/DeviceGroup/GroupTopology.vue b/mes-web/src/views/plcTest/components/DeviceGroup/GroupTopology.vue
index 8729075..b9a5872 100644
--- a/mes-web/src/views/plcTest/components/DeviceGroup/GroupTopology.vue
+++ b/mes-web/src/views/plcTest/components/DeviceGroup/GroupTopology.vue
@@ -44,9 +44,19 @@
<div class="node-name">{{ device.deviceName || device.deviceCode }}</div>
<div class="node-type">{{ getDeviceTypeLabel(device.deviceType) }}</div>
<div class="node-status">
- <el-tag :type="getStatusType(device.status)" size="small">
- {{ getStatusLabel(device.status) }}
+ <el-tag :type="getStatusType(getDeviceStatus(device))" size="small">
+ {{ getStatusLabel(getDeviceStatus(device)) }}
</el-tag>
+ </div>
+ <div class="node-actions">
+ <el-button
+ size="small"
+ text
+ @click.stop="clearPlc(device)"
+ :loading="clearingDeviceId === (device.deviceId || device.id)"
+ >
+ 娓呯┖ PLC
+ </el-button>
</div>
</div>
</div>
@@ -91,9 +101,28 @@
{{ getDeviceTypeLabel(selectedDevice.deviceType) }}
</el-descriptions-item>
<el-descriptions-item label="鐘舵��">
- <el-tag :type="getStatusType(selectedDevice.status)">
- {{ getStatusLabel(selectedDevice.status) }}
- </el-tag>
+ <div class="status-control">
+ <el-tag :type="getStatusType(getDeviceStatus(selectedDevice))">
+ {{ getStatusLabel(getDeviceStatus(selectedDevice)) }}
+ </el-tag>
+ <el-switch
+ v-if="isLoadVehicleDevice(selectedDevice)"
+ :model-value="Boolean(selectedDevice.onlineState)"
+ active-text="鑱旀満"
+ inactive-text="鑴辨満"
+ :loading="togglingDeviceId === (selectedDevice.deviceId || selectedDevice.id)"
+ size="small"
+ @change="(val) => toggleOnlineState(selectedDevice, val)"
+ />
+ <el-button
+ size="small"
+ text
+ @click="clearPlc(selectedDevice)"
+ :loading="clearingDeviceId === (selectedDevice.deviceId || selectedDevice.id)"
+ >
+ 娓呯┖ PLC
+ </el-button>
+ </div>
</el-descriptions-item>
<el-descriptions-item label="PLC IP" v-if="selectedDevice.plcIp">
{{ selectedDevice.plcIp }}
@@ -115,7 +144,7 @@
</template>
<script setup>
-import { computed, ref, watch } from 'vue'
+import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import {
Refresh,
@@ -127,7 +156,7 @@
Box,
Folder
} from '@element-plus/icons-vue'
-import { deviceGroupApi } from '@/api/device/deviceManagement'
+import { deviceGroupApi, deviceInteractionApi } from '@/api/device/deviceManagement'
const props = defineProps({
group: {
@@ -140,6 +169,10 @@
const devices = ref([])
const layoutMode = ref('horizontal') // 'horizontal' | 'vertical'
const selectedDevice = ref(null)
+const togglingDeviceId = ref(null)
+const clearingDeviceId = ref(null)
+const refreshIntervalMs = 5000
+let refreshTimer = null
const fetchDevices = async () => {
if (!props.group) {
@@ -163,11 +196,14 @@
? rawList.data
: []
// 鎸夋墽琛岄『搴忔帓搴�
- devices.value = deviceList.sort((a, b) => {
- const orderA = a.executionOrder || a.order || 0
- const orderB = b.executionOrder || b.order || 0
- return orderA - orderB
- })
+ devices.value = deviceList
+ .map((device) => normalizeDevice(device))
+ .sort((a, b) => {
+ const orderA = a.executionOrder || a.order || 0
+ const orderB = b.executionOrder || b.order || 0
+ return orderA - orderB
+ })
+ syncSelectedDevice()
} catch (error) {
ElMessage.error(error?.message || '鍔犺浇璁惧鍒楄〃澶辫触')
devices.value = []
@@ -178,6 +214,21 @@
const handleRefresh = () => {
fetchDevices()
+}
+
+const stopAutoRefresh = () => {
+ if (refreshTimer) {
+ clearInterval(refreshTimer)
+ refreshTimer = null
+ }
+}
+
+const startAutoRefresh = () => {
+ stopAutoRefresh()
+ if (!props.group) return
+ refreshTimer = setInterval(() => {
+ fetchDevices()
+ }, refreshIntervalMs)
}
const toggleLayout = () => {
@@ -250,13 +301,129 @@
() => {
fetchDevices()
selectedDevice.value = null
+ startAutoRefresh()
},
{ immediate: true }
)
+onMounted(() => {
+ startAutoRefresh()
+})
+
+onUnmounted(() => {
+ stopAutoRefresh()
+})
+
// 鐐瑰嚮鑺傜偣閫夋嫨璁惧
const handleNodeClick = (device) => {
selectedDevice.value = device
+}
+
+const syncSelectedDevice = () => {
+ if (!selectedDevice.value) return
+ const deviceId = selectedDevice.value.deviceId || selectedDevice.value.id
+ if (!deviceId) return
+ const updated = devices.value.find(
+ (item) => (item.deviceId || item.id) === deviceId
+ )
+ if (updated) {
+ selectedDevice.value = updated
+ }
+}
+
+const isLoadVehicleDevice = (device) => {
+ if (!device || !device.deviceType) return false
+ const type = device.deviceType.toUpperCase()
+ return type.includes('VEHICLE') || type.includes('澶ц溅')
+}
+
+const normalizeDevice = (device) => {
+ if (!device) return device
+ const normalized = { ...device }
+ if (normalized.onlineState !== undefined) {
+ normalized.onlineState = toBoolean(normalized.onlineState)
+ } else if (normalized.isOnline === true || normalized.isOnline === false) {
+ normalized.onlineState = normalized.isOnline
+ } else if (normalized.status) {
+ normalized.onlineState = String(normalized.status).toUpperCase() === 'ONLINE'
+ }
+ if (isLoadVehicleDevice(normalized) && normalized.onlineState !== undefined) {
+ normalized.status = normalized.onlineState ? 'ONLINE' : 'OFFLINE'
+ }
+ return normalized
+}
+
+const toBoolean = (value) => {
+ if (value === true || value === false) return value
+ if (typeof value === 'number') return value !== 0
+ const str = String(value).trim().toLowerCase()
+ if (str === 'true' || str === '1') return true
+ if (str === 'false' || str === '0') return false
+ return Boolean(value)
+}
+
+const getDeviceStatus = (device) => {
+ if (!device) return 'UNKNOWN'
+ if (isLoadVehicleDevice(device) && device.onlineState !== undefined) {
+ return device.onlineState ? 'ONLINE' : 'OFFLINE'
+ }
+ if (device.isOnline === true || device.isOnline === false) {
+ return device.isOnline ? 'ONLINE' : 'OFFLINE'
+ }
+ if (device.status) return device.status
+ if (device.deviceStatus) return device.deviceStatus
+ return 'UNKNOWN'
+}
+
+const toggleOnlineState = async (device, value) => {
+ if (!device) return
+ const deviceId = device.deviceId || device.id
+ if (!deviceId) {
+ ElMessage.warning('璁惧ID涓嶅瓨鍦紝鏃犳硶璁剧疆鑱旀満鐘舵��')
+ return
+ }
+ try {
+ togglingDeviceId.value = deviceId
+ await deviceInteractionApi.executeOperation({
+ deviceId,
+ operation: 'setOnlineState',
+ params: {
+ onlineState: value
+ }
+ })
+ device.onlineState = value
+ device.status = value ? 'ONLINE' : 'OFFLINE'
+ if (selectedDevice.value && (selectedDevice.value.deviceId === deviceId || selectedDevice.value.id === deviceId)) {
+ selectedDevice.value.onlineState = device.onlineState
+ selectedDevice.value.status = device.status
+ }
+ ElMessage.success(`宸插皢 ${device.deviceName || device.deviceCode} 璁剧疆涓�${value ? '鑱旀満' : '鑴辨満'}`)
+ } catch (error) {
+ ElMessage.error(error?.message || '璁剧疆鑱旀満鐘舵�佸け璐�')
+ } finally {
+ togglingDeviceId.value = null
+ }
+}
+
+const clearPlc = async (device) => {
+ if (!device) return
+ const deviceId = device.deviceId || device.id
+ if (!deviceId) {
+ ElMessage.warning('璁惧ID涓嶅瓨鍦紝鏃犳硶娓呯┖PLC')
+ return
+ }
+ try {
+ clearingDeviceId.value = deviceId
+ await deviceInteractionApi.executeOperation({
+ deviceId,
+ operation: 'clearPlc'
+ })
+ ElMessage.success(`宸叉竻绌� ${device.deviceName || device.deviceCode} 鐨凱LC鏁版嵁`)
+ } catch (error) {
+ ElMessage.error(error?.message || '娓呯┖PLC澶辫触')
+ } finally {
+ clearingDeviceId.value = null
+ }
}
defineExpose({
@@ -422,6 +589,12 @@
justify-content: center;
}
+.node-actions {
+ margin-top: 6px;
+ display: flex;
+ justify-content: center;
+}
+
.node-order {
position: absolute;
top: -8px;
@@ -447,6 +620,12 @@
justify-content: center;
}
+.status-control {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
/* 姘村钩甯冨眬锛氱澶村湪鑺傜偣鍙充晶 */
.topology-node-wrapper.layout-horizontal .node-arrow {
margin-left: 20px;
--
Gitblit v1.8.0