From 28110912ca4803e5793f181517d7bf2d7a5ea2ad Mon Sep 17 00:00:00 2001
From: HuBingJie <3146306518@qq.com>
Date: 星期五, 05 十二月 2025 00:32:49 +0800
Subject: [PATCH] 1
---
代码管理/WCS/WCS/WIDESEAWCS_Client/src/views/Home.vue | 1948 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1,941 insertions(+), 7 deletions(-)
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WCS/WIDESEAWCS_Client/src/views/Home.vue" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WCS/WIDESEAWCS_Client/src/views/Home.vue"
index 820437a..b893e82 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WCS/WIDESEAWCS_Client/src/views/Home.vue"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WCS/WIDESEAWCS_Client/src/views/Home.vue"
@@ -1,24 +1,1958 @@
<template>
- <div class="title"></div>
+ <div class="rgv-monitor">
+ <div class="monitor-header">
+ <div class="title">璁惧鐘舵�佺洃鎺�</div>
+ <div class="control-panel">
+ <!-- 鐩戞帶绫诲瀷鍒囨崲 -->
+ <div class="monitor-type-switch">
+ <el-button-group>
+ <el-button :type="currentMonitorType === 'inbound' ? 'primary' : ''" @click="switchMonitorType('inbound')">
+ 鍏ュ簱鐩戞帶
+ </el-button>
+ <el-button :type="currentMonitorType === 'outbound' ? 'primary' : ''"
+ @click="switchMonitorType('outbound')">
+ 鍑哄簱鐩戞帶
+ </el-button>
+ <el-button :type="currentMonitorType === 'safetydoor' ? 'primary' : ''"
+ @click="switchMonitorType('safetydoor')">
+ 瀹夊叏闂ㄧ洃鎺�
+ </el-button>
+ <el-button :type="currentMonitorType === 'platform' ? 'primary' : ''"
+ @click="switchMonitorType('platform')">
+ 绔欏彴鐩戞帶
+ </el-button>
+ </el-button-group>
+ </div>
+
+ <!-- 涓�閿搷浣滄寜閽紙瀹夊叏闂ㄥ拰绔欏彴鐩戞帶鏃朵笉鏄剧ず锛� -->
+ <div class="one-click-operations"
+ v-if="currentMonitorType !== 'safetydoor' && currentMonitorType !== 'platform'">
+ <el-button-group>
+ <el-button type="primary"
+ @mousedown="startOneClickInitHold"
+ @mouseup="cancelOneClickInitHold"
+ @mouseleave="cancelOneClickInitHold"
+ @touchstart.prevent="startOneClickInitHold"
+ @touchend="cancelOneClickInitHold"
+ @touchcancel="cancelOneClickInitHold"
+ :loading="oneClickLoading.init">
+ 涓�閿垵濮嬪寲
+ </el-button>
+ <el-button type="warning" @click="handleOneClickOperation('reset')" :loading="oneClickLoading.reset">
+ 涓�閿浣�
+ </el-button>
+ <el-button type="success" @click="handleOneClickOperation('start')" :loading="oneClickLoading.start">
+ 涓�閿惎鍔�
+ </el-button>
+ <el-button type="danger" @click="handleOneClickOperation('stop')" :loading="oneClickLoading.stop">
+ 涓�閿殏鍋�
+ </el-button>
+ </el-button-group>
+ </div>
+
+ <el-button :type="isMonitoring ? 'danger' : 'primary'" @click="toggleMonitoring">
+ {{ isMonitoring ? '鍋滄鐩戞帶' : '鍚姩鐩戞帶' }}
+ </el-button>
+ <el-button type="warning" @click="refreshData">鍒锋柊鏁版嵁</el-button>
+ </div>
+ </div>
+
+ <!-- 鐩戞帶鐘舵�佹樉绀� -->
+ <div class="monitor-status">
+ <el-alert :title="getMonitorStatusTitle()" :type="isMonitoring ? 'success' : 'info'" :closable="false"
+ show-icon />
+ </div>
+
+ <div class="devices-container">
+ <!-- 鍔ㄦ�佹覆鏌撹澶� -->
+ <div class="device-card" v-for="(deviceData, deviceKey) in currentDeviceData" :key="deviceKey">
+ <div class="device-header">
+ <h3>{{ getDeviceDisplayName(deviceKey) }}</h3>
+ <div class="status-indicator" :class="getStatusClass(deviceData)"></div>
+ </div>
+ <div class="device-content">
+ <template v-if="deviceData && Object.keys(deviceData).length > 0">
+ <!-- RGV璁惧鏄剧ず -->
+ <template v-if="currentMonitorType !== 'safetydoor' && currentMonitorType !== 'platform'">
+ <!-- 鍒濆鍖栫姸鎬佹樉绀� -->
+ <div class="data-row" v-if="deviceData['鍒濆鍖栨湭瀹屾垚鏍囧織浣�'] !== undefined">
+ <span class="label">鍒濆鍖栫姸鎬�:</span>
+ <span class="value" :class="deviceData['鍒濆鍖栨湭瀹屾垚鏍囧織浣�'] === 1 ? 'fault-text' : ''">
+ {{ deviceData['鍒濆鍖栨湭瀹屾垚鏍囧織浣�'] === 0 ? '宸插畬鎴�' : '鏈畬鎴�' }}
+ </span>
+ </div>
+
+ <div class="data-row" v-for="(value, key) in deviceData" :key="key" v-if="key !== '鍒濆鍖栨湭瀹屾垚鏍囧織浣�'">
+ <span class="label">{{ getFieldDisplayName(key) }}:</span>
+ <span class="value" :class="getValueClass(key, value, deviceKey)">
+ {{ getFormattedValue(key, value, deviceKey) }}
+ <!-- 涓轰笂鍗囦俊鍙峰拰涓嬮檷淇″彿娣诲姞鎸囩ず鐏� -->
+ <span v-if="key === '涓婂崌淇″彿鍒颁綅'" class="signal-indicator" :class="getSignalClass(value)"></span>
+ <span v-if="key === '涓嬮檷淇″彿鍒颁綅'" class="signal-indicator" :class="getSignalClass(value)"></span>
+ </span>
+ </div>
+ </template>
+
+ <!-- 瀹夊叏闂ㄨ澶囨樉绀� -->
+ <template v-else-if="currentMonitorType === 'safetydoor'">
+ <div class="data-row" v-for="(value, key) in deviceData" :key="key">
+ <span class="label">{{ getFieldDisplayName(key) }}:</span>
+ <span class="value" :class="getSafetyDoorValueClass(key, value)">
+ {{ getSafetyDoorFormattedValue(key, value) }}
+ <!-- 瀹夊叏闂ㄧ姸鎬佹寚绀虹伅 -->
+ <span v-if="key === '瀹夊叏闂ㄦ寚绀虹伅鐘舵��'" class="safety-light" :class="getSafetyLightClass(value)"></span>
+ <span v-if="key === '瀹夊叏闂ㄦ�ュ仠鐘舵��'" class="emergency-stop" :class="getEmergencyStopClass(value)"></span>
+ </span>
+ </div>
+ </template>
+
+ <!-- 绔欏彴璁惧鏄剧ず -->
+ <template v-else-if="currentMonitorType === 'platform'">
+ <div class="data-row" v-for="(value, key) in deviceData" :key="key">
+ <span class="label">{{ getFieldDisplayName(key) }}:</span>
+ <span class="value" :class="getPlatformValueClass(key, value)">
+ {{ getPlatformFormattedValue(key, value) }}
+ <!-- 绔欏彴鍏夌數淇″彿鎸囩ず鐏� -->
+ <span v-if="key === '鍏夌數淇″彿'" class="signal-indicator" :class="getSignalClass(value)"></span>
+ </span>
+ </div>
+ </template>
+ </template>
+ <div v-else class="no-data">
+ 璁惧鏈繛鎺ユ垨鏆傛棤鏁版嵁
+ </div>
+
+ <!-- 鎿嶄綔鎸夐挳鍖哄煙锛堝畨鍏ㄩ棬鍜岀珯鍙扮洃鎺ф椂涓嶆樉绀猴級 -->
+ <div class="operation-buttons"
+ v-if="currentMonitorType !== 'safetydoor' && currentMonitorType !== 'platform'">
+ <!-- 瀛愯溅鎿嶄綔鎸夐挳 -->
+ <template v-if="getDeviceType(deviceKey) === 'child'">
+ <el-button type="primary" size="small"
+ @mousedown="startInitHold(deviceKey)"
+ @mouseup="cancelInitHold(deviceKey)"
+ @mouseleave="cancelInitHold(deviceKey)"
+ @touchstart.prevent="startInitHold(deviceKey)"
+ @touchend="cancelInitHold(deviceKey)"
+ @touchcancel="cancelInitHold(deviceKey)"
+ :loading="loadingStates[deviceKey]?.cs">
+ {{ getInitializationButtonText(deviceData) }}
+ </el-button>
+ <el-button :type="getModeButtonType(deviceData)" size="small" @click="handleModeToggle(deviceKey)"
+ :loading="loadingStates[deviceKey]?.modeToggle">
+ {{ getCurrentModeText(deviceData) }}
+ </el-button>
+ <el-button type="warning" size="small" @click="handleOperation(deviceKey, 'fw')"
+ :loading="loadingStates[deviceKey]?.fw">
+ 澶嶄綅
+ </el-button>
+ <!-- 闀挎寜锛氫笂鍗�/涓嬮檷锛堟寜涓�=1锛屾澗寮�=0锛� -->
+ <el-button type="success" size="small"
+ @pointerdown.prevent="handleLiftPress(deviceKey, 'ss')"
+ @pointerup="handleLiftRelease(deviceKey, 'ss')"
+ @pointercancel="handleLiftRelease(deviceKey, 'ss')"
+ :disabled="!isManualMode(deviceData) || deviceData['涓婂崌淇″彿鍒颁綅'] === 1"
+ :loading="activeLift && activeLift.deviceKey === deviceKey && activeLift.operationType === 'ss'">
+ 涓婂崌
+ </el-button>
+ <el-button type="info" size="small"
+ @pointerdown.prevent="handleLiftPress(deviceKey, 'xj')"
+ @pointerup="handleLiftRelease(deviceKey, 'xj')"
+ @pointercancel="handleLiftRelease(deviceKey, 'xj')"
+ :disabled="!isManualMode(deviceData) || deviceData['涓嬮檷淇″彿鍒颁綅'] === 1"
+ :loading="activeLift && activeLift.deviceKey === deviceKey && activeLift.operationType === 'xj'">
+ 涓嬮檷
+ </el-button>
+ <!-- 淇濋殰锛氭墜鍔ㄥ仠姝㈡寜閽紙鐐瑰嚮鍗冲彂0锛� -->
+ <el-button type="warning" size="small"
+ @click="stopLift(deviceKey, 'ss')"
+ :disabled="!isManualMode(deviceData)">
+ 鍋滄涓婂崌
+ </el-button>
+ <el-button type="warning" size="small"
+ @click="stopLift(deviceKey, 'xj')"
+ :disabled="!isManualMode(deviceData)">
+ 鍋滄涓嬮檷
+ </el-button>
+ </template>
+
+ <!-- 姣嶈溅鎿嶄綔鎸夐挳 -->
+ <template v-else-if="getDeviceType(deviceKey) === 'mother'">
+ <el-button type="primary" size="small"
+ @mousedown="startInitHold(deviceKey)"
+ @mouseup="cancelInitHold(deviceKey)"
+ @mouseleave="cancelInitHold(deviceKey)"
+ @touchstart.prevent="startInitHold(deviceKey)"
+ @touchend="cancelInitHold(deviceKey)"
+ @touchcancel="cancelInitHold(deviceKey)"
+ :loading="loadingStates[deviceKey]?.cs">
+ {{ getInitializationButtonText(deviceData) }}
+ </el-button>
+ <el-button :type="getModeButtonType(deviceData)" size="small" @click="handleModeToggle(deviceKey)"
+ :loading="loadingStates[deviceKey]?.modeToggle">
+ {{ getCurrentModeText(deviceData) }}
+ </el-button>
+ <el-button type="warning" size="small" @click="handleOperation(deviceKey, 'fw')"
+ :loading="loadingStates[deviceKey]?.fw">
+ 澶嶄綅
+ </el-button>
+ <!-- 闆疯揪寮�鍏虫寜閽� -->
+ <el-button :type="getRadarButtonType(deviceData)" size="small" @click="handleRadarToggle(deviceKey)"
+ :loading="loadingStates[deviceKey]?.radarToggle" :disabled="!isManualMode(deviceData)">
+ {{ getRadarButtonText(deviceData) }}
+ </el-button>
+ </template>
+
+ <!-- 鍘熸枡杞︽搷浣滄寜閽� -->
+ <template v-else-if="getDeviceType(deviceKey) === 'material'">
+ <el-button type="primary" size="small"
+ @mousedown="startInitHold(deviceKey)"
+ @mouseup="cancelInitHold(deviceKey)"
+ @mouseleave="cancelInitHold(deviceKey)"
+ @touchstart.prevent="startInitHold(deviceKey)"
+ @touchend="cancelInitHold(deviceKey)"
+ @touchcancel="cancelInitHold(deviceKey)"
+ :loading="loadingStates[deviceKey]?.cs">
+ {{ getInitializationButtonText(deviceData) }}
+ </el-button>
+ <el-button :type="getModeButtonType(deviceData)" size="small" @click="handleModeToggle(deviceKey)"
+ :loading="loadingStates[deviceKey]?.modeToggle">
+ {{ getCurrentModeText(deviceData) }}
+ </el-button>
+ <el-button type="warning" size="small" @click="handleOperation(deviceKey, 'fw')"
+ :loading="loadingStates[deviceKey]?.fw">
+ 澶嶄綅
+ </el-button>
+ <!-- 闆疯揪寮�鍏虫寜閽� -->
+ <el-button :type="getRadarButtonType(deviceData)" size="small" @click="handleRadarToggle(deviceKey)"
+ :loading="loadingStates[deviceKey]?.radarToggle" :disabled="!isManualMode(deviceData)">
+ {{ getRadarButtonText(deviceData) }}
+ </el-button>
+ <!-- 闀挎寜锛氫笂鍗�/涓嬮檷锛堟寜涓�=1锛屾澗寮�=0锛� -->
+ <el-button type="success" size="small"
+ @pointerdown.prevent="handleLiftPress(deviceKey, 'ss')"
+ @pointerup="handleLiftRelease(deviceKey, 'ss')"
+ @mousedown.prevent="handleLiftPress(deviceKey, 'ss')"
+ @mouseup="handleLiftRelease(deviceKey, 'ss')"
+ @touchstart.prevent="handleLiftPress(deviceKey, 'ss')"
+ @touchend="handleLiftRelease(deviceKey, 'ss')"
+ @touchcancel="handleLiftRelease(deviceKey, 'ss')"
+ :disabled="!isManualMode(deviceData) || deviceData['涓婂崌淇″彿鍒颁綅'] === 1"
+ :loading="activeLift && activeLift.deviceKey === deviceKey && activeLift.operationType === 'ss'">
+ 涓婂崌
+ </el-button>
+ <el-button type="info" size="small"
+ @pointerdown.prevent="handleLiftPress(deviceKey, 'xj')"
+ @pointerup="handleLiftRelease(deviceKey, 'xj')"
+ @pointercancel="handleLiftRelease(deviceKey, 'xj')"
+ :disabled="!isManualMode(deviceData) || deviceData['涓嬮檷淇″彿鍒颁綅'] === 1"
+ :loading="activeLift && activeLift.deviceKey === deviceKey && activeLift.operationType === 'xj'">
+ 涓嬮檷
+ </el-button>
+ <!-- 淇濋殰锛氭墜鍔ㄥ仠姝㈡寜閽紙鐐瑰嚮鍗冲彂0锛� -->
+ <el-button type="warning" size="small"
+ @click="stopLift(deviceKey, 'ss')"
+ :disabled="!isManualMode(deviceData)">
+ 鍋滄涓婂崌
+ </el-button>
+ <el-button type="warning" size="small"
+ @click="stopLift(deviceKey, 'xj')"
+ :disabled="!isManualMode(deviceData)">
+ 鍋滄涓嬮檷
+ </el-button>
+ </template>
+ </div>
+
+ <!-- 鍦板潃鎿嶄綔鍖哄煙锛堝畨鍏ㄩ棬鍜岀珯鍙扮洃鎺ф椂涓嶆樉绀猴級 -->
+ <div class="address-operation"
+ v-if="currentMonitorType !== 'safetydoor' && currentMonitorType !== 'platform'">
+ <div class="address-title">鍦板潃鎿嶄綔</div>
+ <div class="address-input-group">
+ <el-select v-model="addressValues[deviceKey]" placeholder="閫夋嫨鐩爣鍦板潃" size="small"
+ style="width: 200px; margin-right: 10px;">
+ <el-option v-for="address in getDeviceAddresses(deviceKey)" :key="address.value" :label="address.label"
+ :value="address.value" />
+ </el-select>
+ <el-button type="info" size="small" @click="handleAddressOperation(deviceKey)"
+ :loading="loadingStates[deviceKey]?.dz" :disabled="!addressValues[deviceKey]">
+ 鍓嶅線鍦板潃
+ </el-button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- 鍏ㄥ眬鎿嶄綔闈㈡澘锛堝畨鍏ㄩ棬鍜岀珯鍙扮洃鎺ф椂涓嶆樉绀猴級 -->
+ <div class="operation-panel" v-if="currentMonitorType !== 'safetydoor' && currentMonitorType !== 'platform'">
+ <!-- <el-button type="primary" @click="showOperationDialog = true">楂樼骇鎿嶄綔</el-button> -->
+ </div>
+
+ <!-- 鎿嶄綔瀵硅瘽妗� -->
+ <el-dialog v-model="showOperationDialog" title="璁惧楂樼骇鎿嶄綔" width="600px">
+ <div>璁惧鍒濆鍖栥�佸啓鍏ュ弬鏁扮瓑楂樼骇鎿嶄綔鐣岄潰</div>
+ </el-dialog>
+ </div>
</template>
<script>
-import { ref, reactive } from 'vue'
-
export default {
- setup() {
+ name: 'RgvMonitor',
+ data() {
return {
+ currentMonitorType: 'inbound', // 'inbound' 鎴� 'outbound' 鎴� 'safetydoor' 鎴� 'platform'
+ isMonitoring: false,
+ monitoringLoading: false,
+ showOperationDialog: false,
+ pollingTimer: null,
+ loadingStates: {},
+ addressValues: {},
+ // 闀挎寜鍒濆鍖栫浉鍏�
+ holdTimers: {}, // 璁惧绾у垵濮嬪寲闀挎寜瀹氭椂鍣�
+ oneClickInitTimer: null, // 涓�閿垵濮嬪寲闀挎寜瀹氭椂鍣�
+ holdDuration: 3000, // 鎸変綇3绉掕Е鍙�
+ activeLift: null, // { deviceKey, operationType } 褰撳墠鎸変笅涓殑鍗囬檷鎿嶄綔
+ monitoringPaused: false, // 闀挎寜鏈熼棿鏆傚仠鐩戞帶鍒锋柊
+ liftPressPromises: {}, // key: `${deviceKey}-${operationType}` -> Promise for press(1)
+ signalPollingTimer: null, // 鍗囬檷闀挎寜鏈熼棿鐨勮交閲忎俊鍙疯疆璇�
+ signalPollInterval: 1200, // 杞婚噺淇″彿杞闂撮殧(ms)
+ lastLiftPressAt: {}, // 璁板綍姣忎釜(deviceKey-op)鏈�鍚庢寜涓嬬殑鏃堕棿鎴�
+ liftReleaseInProgress: {}, // 姝e湪鍙戦�侀噴鏀�(0)鐨勬爣璁帮紝闃查噸澶�
+ // 鐐瑰嚮寮忓崌闄嶆帶鍒剁姸鎬�
+ activeLiftStates: {}, // { [deviceKey]: { ss: boolean, xj: boolean } }
+ liftAutoStopTimeouts: {}, // { [deviceKey-op]: timeoutId }
+ liftCommandTimeoutMs: 10000, // 鍗囬檷鎸囦护鏈�澶ф寔缁椂闂达紝瓒呮椂鑷姩鍋滄
+
+ // 涓�閿搷浣滃姞杞界姸鎬�
+ oneClickLoading: {
+ init: false,
+ reset: false,
+ start: false,
+ stop: false
+ },
+
+ // 璁惧鏁版嵁
+ inboundDeviceData: {
+ rgV101: null,
+ rgV103: null,
+ rgV104: null,
+ rgV105: null,
+ rgV107: null,
+ rgV108: null,
+ rgV109: null,
+ },
+ outboundDeviceData: {
+ rgV116: null,
+ rgV115: null,
+ rgV111: null,
+ rgV112: null,
+ rgV110: null,
+ rgV114: null,
+ rgV118: null
+ },
+ safetyDoorDeviceData: {
+ aqm001: null,
+ aqm002: null,
+ aqm003: null
+ },
+ platformDeviceData: {
+ '1001': null,
+ '1002': null,
+ '2016': null,
+ '2017': null,
+ '2018': null,
+ '2019': null,
+ '1021': null,
+ '1061': null,
+ '1131': null,
+ '1171': null
+ },
+
+ // 瀛楁鏄剧ず鍚嶇О鏄犲皠
+ fieldDisplayNames: {
+ '宸ヤ綔妯″紡': '宸ヤ綔妯″紡',
+ '褰撳墠浣嶇疆': '褰撳墠浣嶇疆',
+ '鏈夎揣鐘舵��': '鏈夎揣鐘舵��',
+ '鐩爣鍦板潃': '鐩爣鍦板潃',
+ '浠诲姟鐘舵��': '浠诲姟鐘舵��',
+ 'rgV浠诲姟缂栧彿': '浠诲姟缂栧彿',
+ '鏁呴殰浠g爜': '鏁呴殰浠g爜',
+ '涓婂崌淇″彿鍒颁綅': '涓婂崌淇″彿',
+ '涓嬮檷淇″彿鍒颁綅': '涓嬮檷淇″彿',
+ '鍒濆鍖栨湭瀹屾垚鏍囧織浣�': '鍒濆鍖栫姸鎬�',
+ '闆疯揪鐘舵��': '闆疯揪鐘舵��',
+ '璐у弶鐘舵��': '璐у弶鐘舵��',
+ // 瀹夊叏闂ㄥ瓧娈�
+ '瀹夊叏闂ㄦ寚绀虹伅鐘舵��': '鎸囩ず鐏姸鎬�',
+ '瀹夊叏闂ㄨ姹傚紑闂�': '璇锋眰寮�闂�',
+ '瀹夊叏闂ㄦ柇鐢电姸鎬�': '鏂數鐘舵��',
+ '瀹夊叏闂ㄦ�ュ仠鐘舵��': '鎬ュ仠鐘舵��',
+ '瀹夊叏闂ㄩ攣鐘舵��': '闂ㄩ攣鐘舵��',
+ '瀹夊叏闂ㄥ浣嶇姸鎬�': '澶嶄綅鐘舵��',
+ '鎶ヨ淇℃伅': '鎶ヨ淇℃伅',
+ '寮�闂ㄤ俊鎭�': '寮�闂ㄤ俊鎭�',
+ // 绔欏彴瀛楁
+ '鍏夌數淇″彿': '鍏夌數淇″彿',
+ '浠诲姟id': '浠诲姟ID'
+ },
+
+ // 璁惧鏄剧ず鍚嶇О鏄犲皠
+ deviceDisplayNames: {
+ // 鍏ュ簱璁惧
+ 'rgV101': 'RGV101 - 鍘熸枡鍏ュ簱杞�',
+ 'rgV103': 'RGV103 - 姣嶈溅',
+ 'rgV104': 'RGV104 - 瀛愯溅',
+ 'rgV105': 'RGV105 - 姣嶈溅',
+ 'rgV107': 'RGV107 - 瀛愯溅',
+ 'rgV108': 'RGV108 - 姣嶈溅',
+ 'rgV109': 'RGV109 - 姣嶈溅',
+ // 鍑哄簱璁惧
+ 'rgV110': 'RGV110 - 姣嶈溅',
+ 'rgV111': 'RGV111 - 瀛愯溅',
+ 'rgV112': 'RGV112 - 姣嶈溅',
+ 'rgV114': 'RGV114 - 姣嶈溅',
+ 'rgV115': 'RGV115 - 姣嶈溅',
+ 'rgV116': 'RGV116 - 瀛愯溅',
+ 'rgV118': 'RGV118 - 鍘熸枡鍑哄簱杞�',
+ // 瀹夊叏闂ㄨ澶�
+ 'aqm001': 'AQM001 - 1#瀹夊叏闂�',
+ 'aqm002': 'AQM002 - 2#瀹夊叏闂�',
+ 'aqm003': 'AQM003 - 3#瀹夊叏闂�',
+ // 绔欏彴璁惧
+ '1001': '1001 - 1#绔欏彴',
+ '1002': '1002 - 2#绔欏彴',
+ '2016': '2016 - 3#绔欏彴',
+ '2017': '2017 - 4#绔欏彴',
+ '2018': '2018 - 5#绔欏彴',
+ '2019': '2019 - 6#绔欏彴',
+ '1021': '1021 - 7#绔欏彴',
+ '1061': '1061 - 8#绔欏彴',
+ '1131': '1131 - 9#绔欏彴',
+ '1171': '1171 - 10#绔欏彴'
+ },
+
+ // 鎿嶄綔绫诲瀷鏄犲皠
+ operationTypes: {
+ 'cs': '鍒濆鍖�',
+ 'sd': '鍒囨崲鍒版墜鍔ㄦā寮�',
+ 'zd': '鍒囨崲鍒拌嚜鍔ㄦā寮�',
+ 'dz': '鍓嶅線鍦板潃',
+ 'kld': '寮�闆疯揪',
+ 'gld': '鍏抽浄杈�',
+ 'fw': '澶嶄綅',
+ 'ss': '涓婂崌',
+ 'xj': '涓嬮檷',
+ },
+
+ // 鎶ヨ浠g爜鏄犲皠
+ motherCarAlarmCodes: {
+ 0: '鏃犳姤璀�',
+ 1: 'RGV灏忚溅鎬ュ仠琚寜涓�',
+ 2: '鍓嶈繘闄愪綅鎶ヨ',
+ 3: '鍚庨��闄愪綅鎶ヨ',
+ 4: 'PLC妯″潡鏁呴殰',
+ 5: 'PLC鎵╁睍妯″潡鏁呴殰',
+ 6: 'RGV闀挎椂闂寸┖杞晠闅�',
+ 7: '鐩殑鍦颁笉绛変簬瀹為檯浣嶇疆鏁呴殰',
+ 8: '涓庢�绘帶閫氳鏁呴殰',
+ 9: '琛岃蛋鍙橀鍣ㄦ晠闅�',
+ 10: '鍙栬揣鏃惰嚜韬湁璐х墿鎶ヨ',
+ 11: '鏀捐揣鏃惰嚜韬棤璐х墿鎶ヨ',
+ 12: '鍋滄鏃朵綅缃繃鍐叉姤璀�'
+ },
+
+ childCarAlarmCodes: {
+ 0: '鏃犳姤璀�',
+ 1: 'RGV灏忚溅鎬ュ仠琚寜涓�',
+ 2: '鍓嶈繘闄愪綅鎶ヨ',
+ 3: '鍚庨��闄愪綅鎶ヨ',
+ 4: 'PLC妯″潡鏁呴殰',
+ 5: 'PLC鎵╁睍妯″潡鏁呴殰',
+ 6: '鎵爜瀹氫綅鏁呴殰',
+ 7: 'RGV闀挎椂闂寸┖杞晠闅�',
+ 8: '鐩殑鍦颁笉绛変簬瀹為檯浣嶇疆鏁呴殰',
+ 9: '涓庢�绘帶閫氳鏁呴殰',
+ 10: '琛岃蛋鍙橀鍣ㄦ晠闅�',
+ 11: '娑插帇鍗曞厓杩囪浇淇濇姢鏁呴殰',
+ 12: '娑插帇涓婂崌瓒呮椂鎶ヨ',
+ 13: '娑插帇涓嬮檷瓒呮椂鎶ヨ',
+ 14: '鍙栬揣鏃惰嚜韬湁璐х墿鎶ヨ',
+ 15: '鏀捐揣鏃惰嚜韬棤璐х墿鎶ヨ',
+ 16: '鍙栬揣妫�娴嬩笉鍒拌揣鐗╂姤璀�'
+ },
+
+ // 鍦� data() 涓慨鏀� materialCarAlarmCodes
+ materialCarAlarmCodes: {
+ 0: '鏃犳姤璀�',
+ 1: 'RGV灏忚溅鎬ュ仠琚寜涓�',
+ 2: '姝h浆闆疯揪鎶ヨ',
+ 3: '鍙嶈浆闆疯揪鎶ヨ',
+ 4: '鍓嶈繘闄愪綅鎶ヨ',
+ 5: '鍚庨��闄愪綅鎶ヨ',
+ 6: '',
+ 7: 'PLC妯″潡鏁呴殰',
+ 8: 'PLC鎵╁睍妯″潡鏁呴殰',
+ 9: '绉伴噸妯″潡鏁呴殰',
+ 10: '鎵爜瀹氫綅鏁呴殰',
+ 11: 'RGV闀挎椂闂寸┖杞晠闅�',
+ 12: '鐩殑鍦颁笉绛変簬瀹為檯浣嶇疆鏁呴殰',
+ 13: '涓庢�绘帶閫氳鏁呴殰',
+ 14: '鍓嶉浄杈惧睆钄借鍛�',
+ 15: '鍚庨浄杈惧睆钄借鍛�',
+ 16: '琛岃蛋鍙橀鍣ㄦ晠闅�',
+ 17: '浼哥缉鍙夊彉棰戝櫒鏁呴殰',
+ 18: '娑插帇鍗曞厓杩囪浇淇濇姢鏁呴殰',
+ 19: '娑插帇涓婂崌瓒呮椂鎶ヨ',
+ 20: '娑插帇涓嬮檷瓒呮椂鎶ヨ',
+ 21: '浼哥缉鍙変几鍑鸿秴鏃舵姤璀�',
+ 22: '浼哥缉鍙夌缉鍥炶秴鏃舵姤璀�',
+ 23: '澶栧舰妫�娴嬫姤璀�',
+ 24: '绉伴噸瓒呴噸鎶ヨ',
+ 25: '璐у弶浼稿嚭鏋侀檺闄愪綅鎶ヨ',
+ 26: '璐у弶缂╁洖鏋侀檺闄愪綅鎶ヨ',
+ 27: '鍙栬揣鏃惰嚜韬湁璐х墿鎶ヨ',
+ 28: '鏀捐揣鏃惰嚜韬棤璐х墿鎶ヨ',
+ 29: '璐у弶鏈洖鍒板垵濮嬩綅鎶ヨ',
+ 30: '瑙﹀彂浠呯Щ鍔ㄥ懡浠ゆ椂璐у弶涓嶅湪鍒濆浣嶆姤璀�',
+ 31: '璐у弶鍒拌揪鍒濆浣嶄絾涓綅浼犳劅鍣ㄦ湭妫�娴嬪埌鎶ヨ',
+ 32: '琛岃蛋杞存病鍒颁綅绂佹璐у弶浼稿嚭',
+ 33: '鍙栬揣寮傚父鎶ヨ',
+ 34: '鏀捐揣寮傚父鎶ヨ',
+ 35: '澶栧瀷妫�娴�-鍓嶈秴鍑烘姤璀�',
+ 36: '澶栧瀷妫�娴�-鍚庤秴鍑烘姤璀�',
+ 37: '澶栧瀷妫�娴�-宸﹁秴鍑烘姤璀�',
+ 38: '澶栧瀷妫�娴�-鍙宠秴鍑烘姤璀�',
+ 39: '澶栧瀷妫�娴�-涓婅秴鍑烘姤璀�'
+ },
+
+ // 瀹夊叏闂ㄦ寚绀虹伅鐘舵�佹槧灏�
+ safetyDoorLightCodes: {
+ 0: '鏃犺緭鍑�',
+ 1: '绾㈢伅甯镐寒+铚傞福',
+ 2: '缁跨伅甯镐寒',
+ 3: '榛勭伅闂儊(2HZ)',
+ 4: '榛勭伅甯镐寒'
+ },
+
+ // 璁惧绫诲瀷鍒嗙被
+ deviceTypes: {
+ // 鍏ュ簱璁惧
+ motherCars: ['rgV103', 'rgV105', 'rgV108', 'rgV109'],
+ childCars: ['rgV104', 'rgV107'],
+ materialCars: ['rgV101'],
+ // 鍑哄簱璁惧
+ outboundMotherCars: ['rgV110', 'rgV112', 'rgV114', 'rgV115'],
+ outboundChildCars: ['rgV111', 'rgV116'],
+ outboundMaterialCars: ['rgV118'],
+ // 瀹夊叏闂ㄨ澶�
+ safetyDoors: ['aqm001', 'aqm002', 'aqm003'],
+ // 绔欏彴璁惧
+ platforms: ['1001', '1002', '2016', '2017', '2018', '2019', '1021', '1061', '1131', '1171']
+ },
+
+ // 璁惧鍦板潃鏄犲皠
+ deviceAddresses: {
+ // 鍏ュ簱璁惧鍦板潃
+ 'rgV101': [
+ { value: '1001', label: '1001 - 鍘熸枡鍏ュ簱浣�' },
+ { value: '1002', label: '1002 - 鍘熸枡鍑哄簱浣�' },
+ { value: '1021', label: '1021 - 涓浆浣�' }
+ ],
+ 'rgV103': [
+ { value: '1031', label: '1031 - 姣嶈溅鍋滆溅浣�1' },
+ { value: '1032', label: '1032 - 姣嶈溅鍋滆溅浣�2' }
+ ],
+ 'rgV104': [
+ { value: '3', label: '鍋滈潬鐐�1' },
+ { value: '5', label: '鍋滈潬鐐�2' },
+ { value: '1031', label: '1031 - 瀛愯溅鍙栬揣浣�' },
+ { value: '1051', label: '1051 - 瀛愯溅鍙栬揣浣�' }
+
+ ],
+ 'rgV105': [
+ { value: '1051', label: '1051 - 姣嶈溅鍋滆溅浣�1' },
+ { value: '1052', label: '1052 - 姣嶈溅鍋滆溅浣�2' }
+ ],
+ 'rgV107': [
+ { value: '3', label: '鍋滈潬鐐�1' },
+ { value: '5', label: '鍋滈潬鐐�2' },
+ { value: '1081', label: '1081 - 瀛愯溅鍙栬揣浣�' },
+ { value: '1091', label: '1091 - 瀛愯溅鍙栬揣浣�' }
+ ],
+ 'rgV108': [
+ { value: '1081', label: '1081 - 姣嶈溅鍋滆溅浣�1' },
+ { value: '1082', label: '1082 - 姣嶈溅鍋滆溅浣�2' }
+ ],
+ 'rgV109': [
+ { value: '1091', label: '1091 - 姣嶈溅鍋滆溅浣�1' },
+ { value: '1092', label: '1092 - 姣嶈溅鍋滆溅浣�2' }
+ ],
+ // 鍑哄簱璁惧鍦板潃
+ 'rgV110': [
+ { value: '1101', label: '1101 - 姣嶈溅鍋滆溅浣�1' },
+ { value: '1102', label: '1102 - 姣嶈溅鍋滆溅浣�2' }
+ ],
+ 'rgV111': [
+ { value: '3', label: '鍋滈潬鐐�1' },
+ { value: '5', label: '鍋滈潬鐐�2' },
+ { value: '1101', label: '1101 - 瀛愯溅鍙栬揣浣�' },
+ { value: '1121', label: '1121 - 瀛愯溅鍙栬揣浣�' }
+ ],
+ 'rgV112': [
+ { value: '1121', label: '1121 - 姣嶈溅鍋滆溅浣�1' },
+ { value: '1122', label: '1122 - 姣嶈溅鍋滆溅浣�2' }
+ ],
+ 'rgV114': [
+ { value: '1141', label: '1141 - 姣嶈溅鍋滆溅浣�1' },
+ { value: '1142', label: '1142 - 姣嶈溅鍋滆溅浣�2' },
+ ],
+ 'rgV115': [
+ { value: '1151', label: '1151 - 姣嶈溅鍋滆溅浣�1' },
+ { value: '1152', label: '1152 - 姣嶈溅鍋滆溅浣�2' }
+ ],
+ 'rgV116': [
+ { value: '3', label: '鍋滈潬鐐�1' },
+ { value: '5', label: '鍋滈潬鐐�2' },
+ { value: '1151', label: '1151 - 瀛愯溅鍙栬揣浣�' },
+ { value: '1141', label: '1141 - 瀛愯溅鍙栬揣浣�' }
+ ],
+ 'rgV118': [
+ { value: '2016', label: '2016 - 鍘熸枡澶勭悊浣�1' },
+ { value: '2017', label: '2017 - 鍘熸枡澶勭悊浣�2' },
+ { value: '2018', label: '2018 - 鍘熸枡澶勭悊浣�3' },
+ { value: '2019', label: '2019 - 鍘熸枡澶勭悊浣�4' }
+ ]
+ },
+
+ // 鐗规畩瀛楁鐨勫�兼牸寮忓寲
+ valueFormatters: {
+ '宸ヤ綔妯″紡': (value) => {
+ const modes = { 0: '鎵嬪姩妯″紡', 1: '鑷姩妯″紡' }
+ return modes[value] || `鏈煡妯″紡(${value})`
+ },
+ '鏈夎揣鐘舵��': (value) => value === 0 ? '鏃犺揣' : '鏈夎揣',
+ '浠诲姟鐘舵��': (value) => {
+ const statusMap = { 0: '绌洪棽', 1: '鎵ц涓�', 2: '瀹屾垚' }
+ return statusMap[value] || `鏈煡鐘舵��(${value})`
+ },
+ '鏁呴殰浠g爜': (value, deviceKey) => {
+ return this.getAlarmText(value, deviceKey)
+ },
+ '涓婂崌淇″彿鍒颁綅': (value) => value === 0 ? '鏈埌浣�' : '宸插埌浣�',
+ '涓嬮檷淇″彿鍒颁綅': (value) => value === 0 ? '鏈埌浣�' : '宸插埌浣�',
+ '鍒濆鍖栨湭瀹屾垚鏍囧織浣�': (value) => value === 0 ? '宸插畬鎴�' : '鏈畬鎴�',
+ '闆疯揪鐘舵��': (value) => value === 0 ? '鍏抽棴' : '寮�鍚�',
+ '璐у弶鐘舵��': (value) => value === 0 ? '缂╁洖' : '浼稿嚭'
+ },
+
+ // 瀹夊叏闂ㄥ瓧娈靛�兼牸寮忓寲
+ safetyDoorValueFormatters: {
+ '瀹夊叏闂ㄦ寚绀虹伅鐘舵��': (value) => {
+ return this.safetyDoorLightCodes[value] || `鏈煡鐘舵��(${value})`
+ },
+ '瀹夊叏闂ㄨ姹傚紑闂�': (value) => value === 0 ? '姝e父' : '璇锋眰寮�闂�',
+ '瀹夊叏闂ㄦ柇鐢电姸鎬�': (value) => value === 0 ? '鏂數' : '涓婄數',
+ '瀹夊叏闂ㄦ�ュ仠鐘舵��': (value) => value === 0 ? '鎬ュ仠' : '姝e父',
+ '瀹夊叏闂ㄩ攣鐘舵��': (value) => value === 0 ? '寮�闂�' : '鍏抽棬',
+ '瀹夊叏闂ㄥ浣嶇姸鎬�': (value) => value === 0 ? '姝e父' : '澶嶄綅涓�',
+ '鎶ヨ淇℃伅': (value) => value === 0 ? '姝e父' : '鎶ヨ',
+ '寮�闂ㄤ俊鎭�': (value) => value === 0 ? '鍏抽棬' : '寮�闂�'
+ },
+
+ // 绔欏彴瀛楁鍊兼牸寮忓寲
+ platformValueFormatters: {
+ '鍏夌數淇″彿': (value) => value === 0 ? '鏃犱俊鍙�' : '鏈変俊鍙�',
+ '浠诲姟id': (value) => value === 0 ? '鏃犱换鍔�' : `浠诲姟${value}`
+ }
+ }
+ },
+ computed: {
+ // 褰撳墠鏄剧ず鐨勮澶囨暟鎹�
+ currentDeviceData() {
+ switch (this.currentMonitorType) {
+ case 'inbound':
+ return this.inboundDeviceData
+ case 'outbound':
+ return this.outboundDeviceData
+ case 'safetydoor':
+ return this.safetyDoorDeviceData
+ case 'platform':
+ return this.platformDeviceData
+ default:
+ return this.inboundDeviceData
+ }
+ }
+ },
+ methods: {
+ // 鏆傚仠/鎭㈠鐩戞帶杞
+ pauseMonitoring() {
+ this.monitoringPaused = true
+ if (this.pollingTimer) {
+ clearTimeout(this.pollingTimer)
+ this.pollingTimer = null
+ }
+ },
+ resumeMonitoring() {
+ // 浠呭綋娌℃湁浠讳綍闀挎寜/鍗囬檷鍦ㄨ繘琛屾椂鎵嶆仮澶�
+ if (!this.activeLift && !this.isHoldActive()) {
+ this.monitoringPaused = false
+ if (this.isMonitoring && !this.pollingTimer) {
+ this.startPolling()
+ }
+ }
+ },
+ // 鍗囬檷闀挎寜鏈熼棿浠呰疆璇㈠綋鍓嶈澶囩殑"涓�/涓嬪埌浣�"淇″彿锛岄伩鍏嶅叏閲忓埛鏂帮紙瀹炰緥鏂规硶锛�
+ startLiftSignalPolling(deviceKey) {
+ this.stopLiftSignalPolling()
+ this.signalPollingTimer = setInterval(async () => {
+ // 浠呭湪褰撳墠浠嶅浜庤璁惧鐨勫崌闄嶉暱鎸変笖鐩戞帶寮�鍚椂鏈夋晥锛屽惁鍒欒嚜鍔ㄥ仠姝�
+ if (!this.isMonitoring || !this.activeLift || this.activeLift.deviceKey !== deviceKey) {
+ this.stopLiftSignalPolling()
+ return
+ }
+ try {
+ const response = await this.http.post('api/Rgvoperainform/GetDeviceStatusDto', {
+ off: 1,
+ monitorType: this.currentMonitorType
+ })
+ if (response && response.status && response.data) {
+ const keys = Object.keys(response.data)
+ const respKey = keys.find(k => k.toLowerCase() === String(deviceKey).toLowerCase())
+ const dev = respKey ? response.data[respKey] : null
+ if (!dev) return
+ const updateMap = (mapObj) => {
+ if (!mapObj) return null
+ const devOld = mapObj[deviceKey] || {}
+ const patch = { ...devOld }
+ const riseVal = Object.prototype.hasOwnProperty.call(dev, '涓婂崌淇″彿鍒颁綅') ? dev['涓婂崌淇″彿鍒颁綅']
+ : (Object.prototype.hasOwnProperty.call(dev, 'RGV_Risingsignalplace') ? dev['RGV_Risingsignalplace']
+ : (Object.prototype.hasOwnProperty.call(dev, 'RiseArrived') ? dev['RiseArrived'] : undefined))
+ const downVal = Object.prototype.hasOwnProperty.call(dev, '涓嬮檷淇″彿鍒颁綅') ? dev['涓嬮檷淇″彿鍒颁綅']
+ : (Object.prototype.hasOwnProperty.call(dev, 'RGV_Descentsignal') ? dev['RGV_Descentsignal']
+ : (Object.prototype.hasOwnProperty.call(dev, 'DescendArrived') ? dev['DescendArrived'] : undefined))
+ if (riseVal !== undefined) patch['涓婂崌淇″彿鍒颁綅'] = riseVal
+ if (downVal !== undefined) patch['涓嬮檷淇″彿鍒颁綅'] = downVal
+ return { ...mapObj, [deviceKey]: patch }
+ }
+
+ let patched = false
+ const tryPatch = (getter, setter) => {
+ const next = updateMap(getter)
+ if (next) {
+ setter(next)
+ patched = true
+ }
+ }
+
+ if (this.currentMonitorType === 'inbound') tryPatch(this.inboundDeviceData, v => this.inboundDeviceData = v)
+ if (this.currentMonitorType === 'outbound') tryPatch(this.outboundDeviceData, v => this.outboundDeviceData = v)
+ if (this.currentMonitorType === 'safetydoor') tryPatch(this.safetyDoorDeviceData, v => this.safetyDoorDeviceData = v)
+ if (this.currentMonitorType === 'platform') tryPatch(this.platformDeviceData, v => this.platformDeviceData = v)
+
+ if (!patched) {
+ tryPatch(this.inboundDeviceData, v => this.inboundDeviceData = v)
+ tryPatch(this.outboundDeviceData, v => this.outboundDeviceData = v)
+ tryPatch(this.safetyDoorDeviceData, v => this.safetyDoorDeviceData = v)
+ tryPatch(this.platformDeviceData, v => this.platformDeviceData = v)
+ }
+
+ if (typeof this.$forceUpdate === 'function') this.$forceUpdate()
+ }
+ } catch (e) {
+ // 蹇界暐杞婚噺杞閿欒
+ }
+ }, this.signalPollInterval)
+ },
+ stopLiftSignalPolling() {
+ if (this.signalPollingTimer) {
+ clearInterval(this.signalPollingTimer)
+ this.signalPollingTimer = null
+ }
+ },
+ // 鏄惁瀛樺湪闀挎寜涓殑鍒濆鍖栵紙璁惧绾ф垨涓�閿級
+ isHoldActive() {
+ if (this.oneClickInitTimer) return true
+ // holdTimers 涓湁浠讳綍涓�涓湁鏁堝畾鏃跺櫒鍗宠涓洪暱鎸変腑
+ return Object.values(this.holdTimers || {}).some(t => !!t)
+ },
+ // 寮�濮嬭澶囩骇鍒濆鍖栭暱鎸�
+ startInitHold(deviceKey) {
+ this.pauseMonitoring()
+ if (this.holdTimers[deviceKey]) {
+ clearTimeout(this.holdTimers[deviceKey])
+ }
+ this.holdTimers[deviceKey] = setTimeout(() => {
+ this.handleOperation(deviceKey, 'cs')
+ this.holdTimers[deviceKey] = null
+ // 鍒濆鍖栬Е鍙戝畬鎴愬悗锛屾仮澶嶇洃鎺у苟纭繚鏃犳畫鐣欒交閲忚疆璇�
+ this.stopLiftSignalPolling()
+ this.resumeMonitoring()
+ }, this.holdDuration)
+ },
+
+ // 鍙栨秷璁惧绾у垵濮嬪寲闀挎寜
+ cancelInitHold(deviceKey) {
+ const t = this.holdTimers[deviceKey]
+ if (t) {
+ clearTimeout(t)
+ this.holdTimers[deviceKey] = null
+ // 鍙栨秷鍒濆鍖栭暱鎸夛紝鎭㈠鐩戞帶骞跺仠姝㈣交閲忚疆璇�
+ this.stopLiftSignalPolling()
+ this.resumeMonitoring()
+ }
+ },
+
+ // 寮�濮嬩竴閿垵濮嬪寲闀挎寜
+ startOneClickInitHold() {
+ this.pauseMonitoring()
+ if (this.oneClickInitTimer) {
+ clearTimeout(this.oneClickInitTimer)
+ }
+ this.oneClickInitTimer = setTimeout(() => {
+ this.handleOneClickOperation('init')
+ this.oneClickInitTimer = null
+ this.resumeMonitoring()
+ }, this.holdDuration)
+ },
+
+ // 鍙栨秷涓�閿垵濮嬪寲闀挎寜
+ cancelOneClickInitHold() {
+ if (this.oneClickInitTimer) {
+ clearTimeout(this.oneClickInitTimer)
+ this.oneClickInitTimer = null
+ this.resumeMonitoring()
+ }
+ },
+
+ // 鎸変笅鍗囬檷锛氬彂閫佸弬鏁�1
+ async handleLiftPress(deviceKey, operationType) {
+ // operationType: 'ss' or 'xj'
+ console.log('[LIFT][PRESS] event received', { deviceKey, operationType, ts: Date.now() })
+ if (this.activeLift && this.activeLift.deviceKey === deviceKey && this.activeLift.operationType === operationType) {
+ console.log('[LIFT][PRESS] skipped because same activeLift exists')
+ return
+ }
+ this.activeLift = { deviceKey, operationType }
+ // 浠呭綋宸插紑鍚洃鎺ф椂锛屾墠鏆傚仠鍏ㄥ眬杞骞跺紑鍚交閲忎俊鍙疯疆璇�
+ if (this.isMonitoring) {
+ this.pauseMonitoring()
+ this.startLiftSignalPolling(deviceKey)
+ }
+ // 璁板綍鎸変笅鏃堕棿鎴�
+ this.lastLiftPressAt[`${deviceKey}-${operationType}`] = Date.now()
+ // 涓嶇瓑寰咃紝搴忓垪鍖栧瓨鍌≒romise锛屼繚璇乺elease鏃舵寜椤哄簭鍙戦��
+ const key = `${deviceKey}-${operationType}`
+ console.log('[LIFT][PRESS] sending 1', { key, DelKeys: [deviceKey, operationType, 1] })
+ this.liftPressPromises[key] = this.http.post('api/Rgvoperainform/DeviceOperation', {
+ DelKeys: [deviceKey, operationType, 1],
+ Extra: true
+ }).then((response) => {
+ console.log('[LIFT][PRESS] response', { key, status: response && response.status, message: response && response.message })
+ if (!response.status) {
+ this.$message.error(response.message || `${this.operationTypes[operationType]}澶辫触`)
+ }
+ }).catch((error) => {
+ console.error('[LIFT][PRESS] error', { key, error })
+ this.$message.error(`${this.operationTypes[operationType]}璇锋眰澶辫触: ` + error.message)
+ })
+ },
+
+ // 鏉惧紑鍗囬檷锛氬彂閫佸弬鏁�0
+ async handleLiftRelease(deviceKey, operationType) {
+ console.log('[LIFT][RELEASE] event received', { deviceKey, operationType, ts: Date.now() })
+ if (!this.activeLift || this.activeLift.deviceKey !== deviceKey || this.activeLift.operationType !== operationType) {
+ console.log('[LIFT][RELEASE] skipped because activeLift not match', { activeLift: this.activeLift })
+ return
+ }
+ const key = `${deviceKey}-${operationType}`
+ if (this.liftReleaseInProgress[key]) {
+ // 宸叉湁閲婃斁璇锋眰鍦ㄨ繘琛岋紝閬垮厤閲嶅鍙戦��0锛堝彲鑳芥潵鑷厓绱犱簨浠�+鍏ㄥ眬浜嬩欢鐨勫弻瑙﹀彂锛�
+ console.log('[LIFT][RELEASE] skipped because release in progress', { key })
+ return
+ }
+ this.liftReleaseInProgress[key] = true
+ // 閲婃斁涓�寮�濮嬪氨鍋滄杞婚噺杞锛岄伩鍏嶇户缁崰鐢ㄧ綉缁滃鑷�0鍙戦�佸欢杩�
+ this.stopLiftSignalPolling()
+ // 闃叉鎸変笅鍚庢瀬鐭椂闂村唴灏辫Е鍙戦噴鏀惧鑷�0鍏堜簬1鎴�"鐪嬭捣鏉ュ彧鍙戜簡0"
+ const pressedAt = this.lastLiftPressAt[key] || 0
+ const elapsed = Date.now() - pressedAt
+ console.log('[LIFT][RELEASE] timing', { key, pressedAt, elapsed })
+ if (elapsed < 120) {
+ console.log('[LIFT][RELEASE] delaying to ensure press first', { delayMs: 120 - elapsed })
+ await new Promise(r => setTimeout(r, 120 - elapsed))
+ }
+ try {
+ const pressPromise = this.liftPressPromises[key]
+ if (pressPromise) {
+ console.log('[LIFT][RELEASE] awaiting press promise', { key })
+ // 鍔犺秴鏃朵繚鎶わ紝鑻ress闀挎椂闂存湭杩斿洖锛屼篃涓嶈鏃犻檺绛夛紝鏈�澶氱瓑300ms
+ const timeout = new Promise((_, rej) => setTimeout(() => rej(new Error('press wait timeout')), 300))
+ await Promise.race([pressPromise, timeout]).catch(err => {
+ console.warn('[LIFT][RELEASE] press await timeout or error, continue to send 0', err && err.message)
+ })
+ }
+ console.log('[LIFT][RELEASE] sending 0', { key, DelKeys: [deviceKey, operationType, 0] })
+ const response = await this.http.post('api/Rgvoperainform/DeviceOperation', {
+ DelKeys: [deviceKey, operationType, 0],
+ Extra: true
+ })
+ console.log('[LIFT][RELEASE] response', { key, status: response && response.status, message: response && response.message })
+ if (!response.status) {
+ this.$message.error(response.message || `${this.operationTypes[operationType]}鍋滄澶辫触`)
+ }
+ } catch (error) {
+ console.error('[LIFT][RELEASE] error', { key, error })
+ this.$message.error(`${this.operationTypes[operationType]}鍋滄璇锋眰澶辫触: ` + error.message)
+ } finally {
+ console.log('[LIFT][RELEASE] finalize cleanup', { key })
+ this.activeLift = null
+ delete this.liftPressPromises[key]
+ delete this.lastLiftPressAt[key]
+ delete this.liftReleaseInProgress[key]
+ this.stopLiftSignalPolling()
+ // 鎭㈠鍏ㄥ眬2s杞
+ this.resumeMonitoring()
+ }
+ },
+ // 鍏ュ簱缁х画浠诲姟
+ async handleInNormal(deviceKey) {
+ this.setLoadingState(deviceKey, 'inNormal', true);
+
+ try {
+ const response = await this.http.post("api/RgvOperation/WriteInNormal", {}, "鏁版嵁澶勭悊涓�...");
+
+ if (response.status) {
+ this.$message.success('鍏ュ簱缁х画浠诲姟鎴愬姛');
+ if (this.isMonitoring) this.refreshData();
+ } else {
+ this.$message.error(response.message || '鍏ュ簱缁х画浠诲姟澶辫触');
+ }
+ } catch (error) {
+ this.$message.error('鍏ュ簱缁х画浠诲姟璇锋眰澶辫触: ' + error.message);
+ } finally {
+ this.setLoadingState(deviceKey, 'inNormal', false);
+ }
+ },
+
+ // 鍏ュ簱寮傚父鎺掗櫎
+ async handleInAbnormal(deviceKey) {
+ this.setLoadingState(deviceKey, 'inAbnormal', true);
+
+ try {
+ const response = await this.http.post("api/RgvOperation/WriteInAbnormal", {}, "鏁版嵁澶勭悊涓�...");
+
+ if (response.status) {
+ this.$message.success('鍏ュ簱寮傚父鎺掗櫎鎴愬姛');
+ if (this.isMonitoring) this.refreshData();
+ } else {
+ this.$message.error(response.message || '鍏ュ簱寮傚父鎺掗櫎澶辫触');
+ }
+ } catch (error) {
+ this.$message.error('鍏ュ簱寮傚父鎺掗櫎璇锋眰澶辫触: ' + error.message);
+ } finally {
+ this.setLoadingState(deviceKey, 'inAbnormal', false);
+ }
+ },
+
+ // 鑾峰彇鐩戞帶鐘舵�佹爣棰�
+ getMonitorStatusTitle() {
+ const typeNames = {
+ 'inbound': '鍏ュ簱',
+ 'outbound': '鍑哄簱',
+ 'safetydoor': '瀹夊叏闂�',
+ 'platform': '绔欏彴'
+ }
+ const status = this.isMonitoring ? '杩愯涓�' : '宸插仠姝�'
+ return `${typeNames[this.currentMonitorType]}鐩戞帶鐘舵��: ${status}`
+ },
+
+ // 瀹夊叏闂ㄥ瓧娈靛�兼牸寮忓寲
+ getSafetyDoorFormattedValue(fieldKey, value) {
+ const formatter = this.safetyDoorValueFormatters[fieldKey]
+ return formatter ? formatter(value) : value
+ },
+
+ // 瀹夊叏闂ㄥ瓧娈靛�兼牱寮�
+ getSafetyDoorValueClass(fieldKey, value) {
+ if (fieldKey === '瀹夊叏闂ㄦ�ュ仠鐘舵��' && value === 0) {
+ return 'fault-text'
+ }
+ if (fieldKey === '瀹夊叏闂ㄦ柇鐢电姸鎬�' && value === 0) {
+ return 'fault-text'
+ }
+ if (fieldKey === '鎶ヨ淇℃伅' && value === 1) {
+ return 'fault-text'
+ }
+ return ''
+ },
+
+ // 绔欏彴瀛楁鍊兼牸寮忓寲
+ getPlatformFormattedValue(fieldKey, value) {
+ const formatter = this.platformValueFormatters[fieldKey]
+ return formatter ? formatter(value) : value
+ },
+
+ // 绔欏彴瀛楁鍊兼牱寮�
+ getPlatformValueClass(fieldKey, value) {
+ if (fieldKey === '鍏夌數淇″彿' && value === 1) {
+ return 'normal-text'
+ }
+ return ''
+ },
+
+ // 瀹夊叏闂ㄦ寚绀虹伅鏍峰紡
+ getSafetyLightClass(value) {
+ const classMap = {
+ 0: 'light-off',
+ 1: 'light-red',
+ 2: 'light-green',
+ 3: 'light-yellow-blink',
+ 4: 'light-yellow'
+ }
+ return classMap[value] || 'light-off'
+ },
+
+ // 鎬ュ仠鐘舵�佹牱寮�
+ getEmergencyStopClass(value) {
+ return value === 0 ? 'emergency-stop-active' : 'emergency-stop-normal'
+ },
+
+ // 涓�閿搷浣滃鐞�
+ async handleOneClickOperation(operationType) {
+ // 鏍规嵁褰撳墠鐩戞帶绫诲瀷璁剧疆鍙傛暟
+ const monitorType = this.currentMonitorType === 'inbound' ? 'Inbound' : 'Outbound'
+
+ this.oneClickLoading[operationType] = true
+
+ try {
+ const operationNames = {
+ init: '涓�閿垵濮嬪寲',
+ reset: '涓�閿浣�',
+ start: '涓�閿惎鍔�',
+ stop: '涓�閿殏鍋�'
+ }
+
+ const response = await this.http.post('api/Rgvoperainform/OneClickOperation', {
+ operationType: operationType,
+ monitorType: monitorType
+ }, `${operationNames[operationType]}涓�...`)
+
+ if (response.status) {
+ this.$message.success(`${operationNames[operationType]} ${monitorType}绔澶囨垚鍔焋)
+ this.refreshData()
+ } else {
+ this.$message.error(response.message || `${operationNames[operationType]}澶辫触`)
+ }
+ } catch (error) {
+ this.$message.error(`${operationNames[operationType]}璇锋眰澶辫触: ` + error.message)
+ } finally {
+ this.oneClickLoading[operationType] = false
+ }
+ },
+
+ // 鑾峰彇鍒濆鍖栨寜閽樉绀烘枃鏈�
+ getInitializationButtonText(deviceData) {
+ if (!deviceData) return '鍒濆鍖�'
+ return deviceData['鍒濆鍖栨湭瀹屾垚鏍囧織浣�'] === 0 ? '宸插垵濮嬪寲' : '鍒濆鍖�'
+ },
+
+ // 鐐瑰嚮寮忓崌闄嶏細鐘舵�佹煡璇�
+ isLifting(deviceKey) {
+ const st = this.activeLiftStates[deviceKey]
+ return !!(st && st.ss === true)
+ },
+ isLowering(deviceKey) {
+ const st = this.activeLiftStates[deviceKey]
+ return !!(st && st.xj === true)
+ },
+
+ // 鍚姩鍗囬檷锛堢偣鍑讳竴娆″彂1锛�
+ async startLift(deviceKey, operationType) {
+ // operationType: 'ss' | 'xj'
+ const isManual = this.isManualMode && this.isManualMode(this.currentMonitorDataMap()?.[deviceKey])
+ if (!isManual) {
+ this.$message.warning('璇峰垏鎹负鎵嬪姩妯″紡鍚庡啀鎿嶄綔')
+ return
+ }
+ // 浜掓枼涓庨槻閲�
+ const st = this.activeLiftStates[deviceKey] || { ss: false, xj: false }
+ if ((operationType === 'ss' && (st.ss || st.xj)) || (operationType === 'xj' && (st.xj || st.ss))) {
+ return
+ }
+ // 璁剧疆鍚姩鎬�
+ this.activeLiftStates = { ...this.activeLiftStates, [deviceKey]: { ...st, [operationType]: true } }
+ try {
+ const resp = await this.http.post('api/Rgvoperainform/DeviceOperation', {
+ DelKeys: [deviceKey, operationType, 1],
+ Extra: true
+ })
+ if (!resp.status) {
+ this.$message.error((this.operationTypes && this.operationTypes[operationType]) ? `${this.operationTypes[operationType]}澶辫触` : '鎸囦护鍙戦�佸け璐�')
+ // 鍥炴粴鐘舵��
+ const cur = this.activeLiftStates[deviceKey] || {}
+ this.activeLiftStates = { ...this.activeLiftStates, [deviceKey]: { ...cur, [operationType]: false } }
+ return
+ }
+ // 鎴愬姛鍚庡惎鍔ㄨ秴鏃惰嚜鍔ㄥ仠姝�
+ const key = `${deviceKey}-${operationType}`
+ this.clearLiftTimeout(key)
+ this.liftAutoStopTimeouts[key] = setTimeout(() => {
+ // 瓒呮椂鑷姩鍙戦��0
+ this.stopLift(deviceKey, operationType, true)
+ this.$message.warning('鍗囬檷鍔ㄤ綔瓒呮椂锛屽凡鑷姩鍋滄')
+ }, this.liftCommandTimeoutMs)
+ } catch (e) {
+ this.$message.error('璇锋眰澶辫触: ' + e.message)
+ // 鍥炴粴鐘舵��
+ const cur = this.activeLiftStates[deviceKey] || {}
+ this.activeLiftStates = { ...this.activeLiftStates, [deviceKey]: { ...cur, [operationType]: false } }
+ }
+ },
+
+ // 鍋滄鍗囬檷锛堢偣鍑讳竴娆″彂0锛�
+ async stopLift(deviceKey, operationType, fromTimeout = false) {
+ // 鍗充娇鏈褰曚负鍚姩鎬侊紝涔熷厑璁稿彂閫�0锛屼繚璇佸仠姝㈡寜閽湪鎵嬪姩妯″紡涓嬪缁堝彲鐢�
+ const st = this.activeLiftStates[deviceKey] || { ss: false, xj: false }
+ try {
+ const resp = await this.http.post('api/Rgvoperainform/DeviceOperation', {
+ DelKeys: [deviceKey, operationType, 0],
+ Extra: true
+ })
+ if (!resp.status && !fromTimeout) {
+ this.$message.error((this.operationTypes && this.operationTypes[operationType]) ? `${this.operationTypes[operationType]}鍋滄澶辫触` : '鍋滄鎸囦护澶辫触')
+ return
+ }
+ } catch (e) {
+ if (!fromTimeout) this.$message.error('鍋滄璇锋眰澶辫触: ' + e.message)
+ } finally {
+ // 缃负鍋滄鎬佸苟娓呯悊瓒呮椂瀹氭椂鍣�
+ const cur = this.activeLiftStates[deviceKey] || {}
+ this.activeLiftStates = { ...this.activeLiftStates, [deviceKey]: { ...cur, [operationType]: false } }
+ const key = `${deviceKey}-${operationType}`
+ this.clearLiftTimeout(key)
+ }
+ },
+
+ clearLiftTimeout(key) {
+ if (this.liftAutoStopTimeouts[key]) {
+ clearTimeout(this.liftAutoStopTimeouts[key])
+ delete this.liftAutoStopTimeouts[key]
+ }
+ },
+
+ // 鍒囨崲鐩戞帶绫诲瀷
+ switchMonitorType(type) {
+ if (this.currentMonitorType !== type) {
+ // 鍋滄褰撳墠鐩戞帶
+ if (this.isMonitoring) {
+ this.stopMonitoring()
+ }
+ this.currentMonitorType = type
+ // 濡傛灉涔嬪墠鏄洃鎺х姸鎬侊紝鑷姩鍚姩鏂扮被鍨嬬殑鐩戞帶
+ if (this.isMonitoring) {
+ this.startMonitoring()
+ }
+ }
+ },
+
+ // 鑾峰彇淇″彿鎸囩ず鐏被鍚�
+ getSignalClass(value) {
+ return value === 1 ? 'signal-active' : 'signal-inactive'
+ },
+
+ // 鐩戞帶鎺у埗鏂规硶
+ async toggleMonitoring() {
+ if (this.monitoringLoading) return
+ if (this.isMonitoring) {
+ this.stopMonitoring()
+ } else {
+ await this.startMonitoring()
+ }
+ },
+
+ async startMonitoring() {
+ try {
+ this.monitoringLoading = true
+ const param = {
+ off: 1,
+ monitorType: this.currentMonitorType
+ }
+
+ const response = await this.http.post('api/Rgvoperainform/GetDeviceStatusDto', param)
+
+ if (response.status) {
+ this.isMonitoring = true
+ // 鏍规嵁鐩戞帶绫诲瀷鏇存柊瀵瑰簲鐨勮澶囨暟鎹�
+ switch (this.currentMonitorType) {
+ case 'inbound':
+ this.inboundDeviceData = response.data
+ break
+ case 'outbound':
+ this.outboundDeviceData = response.data
+ break
+ case 'safetydoor':
+ this.safetyDoorDeviceData = response.data
+ break
+ case 'platform':
+ this.platformDeviceData = response.data
+ break
+ }
+ this.startPolling()
+ this.$message.success(`${this.getMonitorStatusTitle()}宸插惎鍔╜)
+ } else {
+ this.$message.error(response.message || `鍚姩${this.currentMonitorType}鐩戞帶澶辫触`)
+ }
+ } catch (error) {
+ this.$message.error('璇锋眰澶辫触: ' + error.message)
+ } finally {
+ this.monitoringLoading = false
+ }
+ },
+
+ stopMonitoring() {
+ this.isMonitoring = false
+ if (this.pollingTimer) {
+ clearTimeout(this.pollingTimer)
+ this.pollingTimer = null
+ }
+
+ this.http.post('api/Rgvoperainform/GetDeviceStatusDto', {
+ off: 0,
+ monitorType: this.currentMonitorType
+ })
+
+ this.$message.info(`${this.getMonitorStatusTitle()}宸插仠姝)
+ },
+
+ startPolling() {
+ this.pollingTimer = setTimeout(() => {
+ if (this.isMonitoring && !this.monitoringPaused) {
+ this.refreshData()
+ this.startPolling()
+ }
+ }, 2000)
+ },
+
+ async refreshData() {
+ if (!this.isMonitoring) return
+ if (this.monitoringPaused) return
+
+ try {
+ const response = await this.http.post('api/Rgvoperainform/GetDeviceStatusDto', {
+ off: 1,
+ monitorType: this.currentMonitorType
+ })
+ if (response.status) {
+ // 鍦ㄥ崌闄嶉暱鎸夋椂锛屼粎鍚堝苟褰撳墠璁惧鐨勫埌浣嶄俊鍙凤紝閬垮厤澶ч潰绉噸缁橀�犳垚鎵撴柇
+ if (this.activeLift) {
+ const { deviceKey } = this.activeLift
+ const respKeys = Object.keys(response.data || {})
+ const respKey = respKeys.find(k => k.toLowerCase() === String(deviceKey).toLowerCase())
+ const dev = respKey ? response.data[respKey] : null
+ const mergeSignals = (mapObj, setter) => {
+ if (!mapObj) return false
+ const old = mapObj[deviceKey]
+ if (!old) return false
+ const patch = { ...old }
+ const riseVal = Object.prototype.hasOwnProperty.call(dev || {}, '涓婂崌淇″彿鍒颁綅') ? dev['涓婂崌淇″彿鍒颁綅']
+ : (Object.prototype.hasOwnProperty.call(dev || {}, 'RGV_Risingsignalplace') ? dev['RGV_Risingsignalplace']
+ : (Object.prototype.hasOwnProperty.call(dev || {}, 'RiseArrived') ? dev['RiseArrived'] : undefined))
+ const downVal = Object.prototype.hasOwnProperty.call(dev || {}, '涓嬮檷淇″彿鍒颁綅') ? dev['涓嬮檷淇″彿鍒颁綅']
+ : (Object.prototype.hasOwnProperty.call(dev || {}, 'RGV_Descentsignal') ? dev['RGV_Descentsignal']
+ : (Object.prototype.hasOwnProperty.call(dev || {}, 'DescendArrived') ? dev['DescendArrived'] : undefined))
+ if (riseVal !== undefined) patch['涓婂崌淇″彿鍒颁綅'] = riseVal
+ if (downVal !== undefined) patch['涓嬮檷淇″彿鍒颁綅'] = downVal
+ setter({ ...mapObj, [deviceKey]: patch })
+ if (typeof this.$forceUpdate === 'function') this.$forceUpdate()
+ return true
+ }
+
+ let merged = false
+ if (this.currentMonitorType === 'inbound') merged = mergeSignals(this.inboundDeviceData, v => this.inboundDeviceData = v)
+ if (this.currentMonitorType === 'outbound') merged = mergeSignals(this.outboundDeviceData, v => this.outboundDeviceData = v)
+ if (this.currentMonitorType === 'safetydoor') merged = mergeSignals(this.safetyDoorDeviceData, v => this.safetyDoorDeviceData = v)
+ if (this.currentMonitorType === 'platform') merged = mergeSignals(this.platformDeviceData, v => this.platformDeviceData = v)
+
+ if (!merged) {
+ merged = mergeSignals(this.inboundDeviceData, v => this.inboundDeviceData = v) ||
+ mergeSignals(this.outboundDeviceData, v => this.outboundDeviceData = v) ||
+ mergeSignals(this.safetyDoorDeviceData, v => this.safetyDoorDeviceData = v) ||
+ mergeSignals(this.platformDeviceData, v => this.platformDeviceData = v)
+ }
+ } else {
+ // 闈為暱鎸夛紝姝e父鏇挎崲鏁版嵁闆�
+ switch (this.currentMonitorType) {
+ case 'inbound':
+ this.inboundDeviceData = response.data
+ break
+ case 'outbound':
+ this.outboundDeviceData = response.data
+ break
+ case 'safetydoor':
+ this.safetyDoorDeviceData = response.data
+ break
+ case 'platform':
+ this.platformDeviceData = response.data
+ break
+ }
+ // 鐐瑰嚮寮忥細妫�娴嬪埌浣嶅悗鑷姩鍋滄瀵瑰簲鍔ㄤ綔
+ this.autoStopLiftIfArrived()
+ }
+ }
+ } catch (error) {
+ console.error('鍒锋柊鏁版嵁澶辫触:', error)
+ }
+ },
+
+ // 鑻ヨ澶囧湪鐐瑰嚮寮忓崌闄嶄腑锛屾娴嬪埌涓�/涓嬪埌浣嶅垯鑷姩鍙戦�佸仠姝�
+ autoStopLiftIfArrived() {
+ const dataMap = this.currentMonitorDataMap()
+ if (!dataMap) return
+ Object.keys(this.activeLiftStates).forEach(deviceKey => {
+ const state = this.activeLiftStates[deviceKey] || {}
+ const dev = dataMap[deviceKey]
+ if (!dev) return
+ if (state.ss && (dev['涓婂崌淇″彿鍒颁綅'] === 1 || dev['RGV_Risingsignalplace'] === 1 || dev['RiseArrived'] === 1)) {
+ this.stopLift(deviceKey, 'ss')
+ }
+ if (state.xj && (dev['涓嬮檷淇″彿鍒颁綅'] === 1 || dev['RGV_Descentsignal'] === 1 || dev['DescendArrived'] === 1)) {
+ this.stopLift(deviceKey, 'xj')
+ }
+ })
+ },
+
+ // 杩斿洖褰撳墠鐩戞帶绫诲瀷鐨勬暟鎹槧灏�
+ currentMonitorDataMap() {
+ switch (this.currentMonitorType) {
+ case 'inbound': return this.inboundDeviceData
+ case 'outbound': return this.outboundDeviceData
+ case 'safetydoor': return this.safetyDoorDeviceData
+ case 'platform': return this.platformDeviceData
+ default: return null
+ }
+ },
+
+ // 鍏朵粬鍘熸湁鏂规硶淇濇寔涓嶅彉
+ getStatusClass(device) {
+ if (!device || Object.keys(device).length === 0) return 'offline'
+
+ // 瀹夊叏闂ㄧ姸鎬佸垽鏂�
+ if (this.currentMonitorType === 'safetydoor') {
+ if (device['瀹夊叏闂ㄦ�ュ仠鐘舵��'] === 0) return 'fault'
+ if (device['瀹夊叏闂ㄦ柇鐢电姸鎬�'] === 0) return 'offline'
+ if (device['鎶ヨ淇℃伅'] === 1) return 'fault'
+ return 'normal'
+ }
+
+ // 绔欏彴鐘舵�佸垽鏂�
+ if (this.currentMonitorType === 'platform') {
+ if (device['鍏夌數淇″彿'] === 1) return 'running'
+ return 'normal'
+ }
+
+ // RGV璁惧鐘舵�佸垽鏂�
+ if (device['鏁呴殰浠g爜'] !== 0) return 'fault'
+ if (device['浠诲姟鐘舵��'] === 1) return 'running'
+ if (device['宸ヤ綔妯″紡'] === 0) return 'manual'
+ return 'normal'
+ },
+
+ getDeviceDisplayName(deviceKey) {
+ return this.deviceDisplayNames[deviceKey] || deviceKey.toUpperCase()
+ },
+
+ getFieldDisplayName(fieldKey) {
+ return this.fieldDisplayNames[fieldKey] || fieldKey
+ },
+
+ getFormattedValue(fieldKey, value, deviceKey) {
+ const formatter = this.valueFormatters[fieldKey]
+ return formatter ? formatter(value, deviceKey) : value
+ },
+
+ getValueClass(fieldKey, value, deviceKey) {
+ if (fieldKey === '鏁呴殰浠g爜' && value !== 0) {
+ return 'fault-text'
+ }
+ return ''
+ },
+
+ // 鑾峰彇璁惧绫诲瀷
+ getDeviceType(deviceKey) {
+ if (this.deviceTypes.motherCars.includes(deviceKey) ||
+ this.deviceTypes.outboundMotherCars.includes(deviceKey)) {
+ return 'mother'
+ } else if (this.deviceTypes.childCars.includes(deviceKey) ||
+ this.deviceTypes.outboundChildCars.includes(deviceKey)) {
+ return 'child'
+ } else if (this.deviceTypes.materialCars.includes(deviceKey) ||
+ this.deviceTypes.outboundMaterialCars.includes(deviceKey)) {
+ return 'material'
+ } else if (this.deviceTypes.safetyDoors.includes(deviceKey)) {
+ return 'safetydoor'
+ } else if (this.deviceTypes.platforms.includes(deviceKey)) {
+ return 'platform'
+ }
+ return 'unknown'
+ },
+
+ // 鑾峰彇璁惧鍙敤鐨勭洰鏍囧湴鍧�
+ getDeviceAddresses(deviceKey) {
+ return this.deviceAddresses[deviceKey] || []
+ },
+
+ // 鑾峰彇鎶ヨ鏂囨湰
+ getAlarmText(alarmCode, deviceKey) {
+ if (alarmCode === 0) return '鏃犳姤璀�'
+
+ const deviceType = this.getDeviceType(deviceKey)
+ let alarmMap = {}
+
+ switch (deviceType) {
+ case 'mother':
+ alarmMap = this.motherCarAlarmCodes
+ break
+ case 'child':
+ alarmMap = this.childCarAlarmCodes
+ break
+ case 'material':
+ alarmMap = this.materialCarAlarmCodes
+ break
+ default:
+ alarmMap = this.motherCarAlarmCodes
+ }
+
+ return alarmMap[alarmCode] || `鏈繛鎺�(${alarmCode})`
+ },
+
+ // 鑾峰彇褰撳墠妯″紡鏄剧ず鏂囨湰
+ getCurrentModeText(deviceData) {
+ if (!deviceData || !deviceData['宸ヤ綔妯″紡']) return '鐐瑰嚮鍒囨崲鑷姩'
+ return deviceData['宸ヤ綔妯″紡'] === 1 ? '鐐瑰嚮鍒囨崲鎵嬪姩' : '鐐瑰嚮鍒囨崲鑷姩'
+ },
+
+ // 鑾峰彇妯″紡鎸夐挳绫诲瀷锛堥鑹诧級
+ getModeButtonType(deviceData) {
+ if (!deviceData || !deviceData['宸ヤ綔妯″紡']) return 'success'
+ return deviceData['宸ヤ綔妯″紡'] === 1 ? 'warning' : 'success'
+ },
+
+ // 鍒ゆ柇鏄惁涓烘墜鍔ㄦā寮忥紙浠呭綋鏄庣‘涓�1=鑷姩鏃惰涓洪潪鎵嬪姩锛泆ndefined/0閮芥寜鎵嬪姩澶勭悊锛�
+ isManualMode(deviceData) {
+ if (!deviceData) return false
+ return deviceData['宸ヤ綔妯″紡'] !== 1
+ },
+
+ // 鑾峰彇闆疯揪鎸夐挳鏂囨湰
+ getRadarButtonText(deviceData) {
+ if (!deviceData) return '寮�鍚浄杈�'
+ return deviceData['闆疯揪鐘舵��'] === 1 ? '鍏抽棴闆疯揪' : '寮�鍚浄杈�'
+ },
+
+ // 鑾峰彇闆疯揪鎸夐挳绫诲瀷
+ getRadarButtonType(deviceData) {
+ if (!deviceData) return 'info'
+ return deviceData['闆疯揪鐘舵��'] === 1 ? 'warning' : 'info'
+ },
+
+ // 璁剧疆鍔犺浇鐘舵��
+ setLoadingState(deviceKey, operationType, loading) {
+ if (!this.loadingStates[deviceKey]) {
+ this.loadingStates[deviceKey] = {}
+ }
+ this.loadingStates[deviceKey][operationType] = loading
+ this.loadingStates = { ...this.loadingStates }
+ },
+
+ // 鎵嬪姩/鑷姩妯″紡鍒囨崲
+ async handleModeToggle(deviceKey) {
+ this.setLoadingState(deviceKey, 'modeToggle', true)
+
+ try {
+ const deviceData = this.currentDeviceData[deviceKey]
+ const currentMode = deviceData?.['宸ヤ綔妯″紡'] || 0
+
+ const operationType = currentMode === 0 ? 'zd' : 'sd'
+
+ const response = await this.http.post('api/Rgvoperainform/DeviceOperation', {
+ DelKeys: [deviceKey, operationType],
+ Extra: true
+ }, `${this.operationTypes[operationType]}涓�...`)
+
+ if (response.status) {
+ this.$message.success(`${this.getDeviceDisplayName(deviceKey)} ${this.operationTypes[operationType]}鎴愬姛`)
+ if (this.isMonitoring) this.refreshData()
+ } else {
+ this.$message.error(response.message || `${this.operationTypes[operationType]}澶辫触`)
+ }
+ } catch (error) {
+ this.$message.error(`妯″紡鍒囨崲璇锋眰澶辫触: ` + error.message)
+ } finally {
+ this.setLoadingState(deviceKey, 'modeToggle', false)
+ }
+ },
+
+ // 闆疯揪寮�鍏冲垏鎹�
+ async handleRadarToggle(deviceKey) {
+ this.setLoadingState(deviceKey, 'radarToggle', true)
+
+ try {
+ const deviceData = this.currentDeviceData[deviceKey]
+ const currentRadarState = deviceData?.['闆疯揪鐘舵��'] || 0
+
+ const operationType = currentRadarState === 0 ? 'kld' : 'gld'
+
+ const response = await this.http.post('api/Rgvoperainform/DeviceOperation', {
+ DelKeys: [deviceKey, operationType],
+ Extra: true
+ }, `${this.operationTypes[operationType]}涓�...`)
+
+ if (response.status) {
+ this.$message.success(`${this.getDeviceDisplayName(deviceKey)} ${this.operationTypes[operationType]}鎴愬姛`)
+ this.refreshData()
+ } else {
+ this.$message.error(response.message || `${this.operationTypes[operationType]}澶辫触`)
+ }
+ } catch (error) {
+ this.$message.error(`闆疯揪鎿嶄綔璇锋眰澶辫触: ` + error.message)
+ } finally {
+ this.setLoadingState(deviceKey, 'radarToggle', false)
+ }
+ },
+
+ // 鍦板潃鎿嶄綔
+ async handleAddressOperation(deviceKey) {
+ const address = this.addressValues[deviceKey]
+ if (!address) {
+ this.$message.warning('璇烽�夋嫨鐩爣鍦板潃')
+ return
+ }
+
+ this.setLoadingState(deviceKey, 'dz', true)
+
+ try {
+ const response = await this.http.post('api/Rgvoperainform/DeviceOperation', {
+ DelKeys: [deviceKey, 'dz', address],
+ Extra: true
+ }, '鍓嶅線鍦板潃涓�...')
+
+ if (response.status) {
+ this.$message.success(`${this.getDeviceDisplayName(deviceKey)} 鍓嶅線鍦板潃 ${address} 鎴愬姛`)
+ if (this.isMonitoring) this.refreshData()
+ } else {
+ this.$message.error(response.message || '鍓嶅線鍦板潃澶辫触')
+ }
+ } catch (error) {
+ this.$message.error('鍓嶅線鍦板潃璇锋眰澶辫触: ' + error.message)
+ } finally {
+ this.setLoadingState(deviceKey, 'dz', false)
+ }
+ },
+
+ // 缁熶竴鎿嶄綔澶勭悊鍑芥暟
+ async handleOperation(deviceKey, operationType) {
+ this.setLoadingState(deviceKey, operationType, true)
+
+ try {
+ // 涓婂崌/涓嬮檷闇�瑕佺涓変釜鍙傛暟缃綅
+ const delKeys = (operationType === 'ss' || operationType === 'xj')
+ ? [deviceKey, operationType, 1]
+ : [deviceKey, operationType]
+
+ const response = await this.http.post('api/Rgvoperainform/DeviceOperation', {
+ DelKeys: delKeys,
+ Extra: true
+ }, `${this.operationTypes[operationType]}涓�...`)
+
+ if (response.status) {
+ const operationName = this.operationTypes[operationType]
+ this.$message.success(`${this.getDeviceDisplayName(deviceKey)} ${operationName}鎿嶄綔鎴愬姛`)
+ if (this.isMonitoring) this.refreshData()
+ } else {
+ this.$message.error(response.message || `${this.operationTypes[operationType]}鎿嶄綔澶辫触`)
+ }
+ } catch (error) {
+ this.$message.error(`${this.operationTypes[operationType]}璇锋眰澶辫触: ` + error.message)
+ } finally {
+ this.setLoadingState(deviceKey, operationType, false)
+ }
+ }
+ },
+
+ mounted() {
+ // 鍏ㄥ眬閲婃斁鍏滃簳锛岄槻姝㈡寚閽堢Щ鍑烘寜閽尯鍩熸垨绐楀彛瀵艰嚧鏃犳硶鍙戦�� 0
+ this._liftGlobalRelease = () => {
+ if (this.activeLift) {
+ const { deviceKey, operationType } = this.activeLift
+ this.handleLiftRelease(deviceKey, operationType)
+ }
+ }
+ window.addEventListener('mouseup', this._liftGlobalRelease)
+ window.addEventListener('touchend', this._liftGlobalRelease, { passive: true })
+ window.addEventListener('blur', this._liftGlobalRelease)
+ document.addEventListener('visibilitychange', () => {
+ if (document.hidden) this._liftGlobalRelease()
+ })
+ },
+
+ beforeUnmount() {
+ this.stopMonitoring()
+ if (this._liftGlobalRelease) {
+ window.removeEventListener('mouseup', this._liftGlobalRelease)
+ window.removeEventListener('touchend', this._liftGlobalRelease)
+ window.removeEventListener('blur', this._liftGlobalRelease)
}
}
}
</script>
<style scoped>
+/* 娣诲姞绔欏彴姝e父鏂囨湰鏍峰紡 */
+.normal-text {
+ color: #67C23A;
+ font-weight: bold;
+}
+
+/* 鍘熸湁鐨勬牱寮忎繚鎸佷笉鍙橈紝娣诲姞瀹夊叏闂ㄧ浉鍏虫牱寮� */
+
+/* 瀹夊叏闂ㄦ寚绀虹伅鏍峰紡 */
+.safety-light {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ display: inline-block;
+ margin-left: 8px;
+ border: 1px solid #ccc;
+}
+
+.safety-light.light-off {
+ background-color: #909399;
+}
+
+.safety-light.light-red {
+ background-color: #F56C6C;
+ box-shadow: 0 0 6px #F56C6C;
+ animation: blink 1s infinite;
+}
+
+.safety-light.light-green {
+ background-color: #67C23A;
+ box-shadow: 0 0 6px #67C23A;
+}
+
+.safety-light.light-yellow {
+ background-color: #E6A23C;
+ box-shadow: 0 0 6px #E6A23C;
+}
+
+.safety-light.light-yellow-blink {
+ background-color: #E6A23C;
+ box-shadow: 0 0 6px #E6A23C;
+ animation: blink 0.5s infinite;
+}
+
+/* 鎬ュ仠鐘舵�佹寚绀� */
+.emergency-stop {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ display: inline-block;
+ margin-left: 8px;
+}
+
+.emergency-stop.emergency-stop-normal {
+ background-color: #67C23A;
+ box-shadow: 0 0 4px #67C23A;
+}
+
+.emergency-stop.emergency-stop-active {
+ background-color: #F56C6C;
+ box-shadow: 0 0 4px #F56C6C;
+ animation: blink 0.8s infinite;
+}
+
+/* 鐩戞帶绫诲瀷鍒囨崲鏍峰紡 */
+.monitor-type-switch {
+ margin-right: 20px;
+}
+
+.one-click-operations {
+ margin-right: 20px;
+}
+
+.control-panel {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+}
+
+/* 淇″彿鎸囩ず鐏牱寮� */
+.signal-indicator {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ display: inline-block;
+ margin-left: 8px;
+}
+
+.signal-indicator.signal-active {
+ background-color: #67C23A;
+ box-shadow: 0 0 4px #67C23A;
+}
+
+.signal-indicator.signal-inactive {
+ background-color: #DCDFE6;
+ border: 1px solid #C0C4CC;
+}
+
+/* 淇敼value鏍峰紡浠ュ绾虫寚绀虹伅 */
+.value {
+ color: #303133;
+ font-weight: 500;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+/* 鍏朵粬鍘熸湁鏍峰紡淇濇寔涓嶅彉 */
+.rgv-monitor {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
+}
+
+.monitor-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ padding: 0 10px;
+}
+
.title {
- line-height: 70vh;
+ font-size: 24px;
+ font-weight: bold;
+ color: #409EFF;
+}
+
+.monitor-status {
+ margin-bottom: 20px;
+}
+
+.devices-container {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
+ gap: 20px;
+ margin-bottom: 20px;
+}
+
+.device-card {
+ background: white;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ overflow: hidden;
+ transition: all 0.3s ease;
+}
+
+.device-card:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15);
+}
+
+.device-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+}
+
+.device-header h3 {
+ margin: 0;
+ font-size: 16px;
+}
+
+.status-indicator {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+}
+
+.status-indicator.normal {
+ background-color: #67C23A;
+ box-shadow: 0 0 8px #67C23A;
+}
+
+.status-indicator.running {
+ background-color: #409EFF;
+ box-shadow: 0 0 8px #409EFF;
+ animation: pulse 1.5s infinite;
+}
+
+.status-indicator.fault {
+ background-color: #F56C6C;
+ box-shadow: 0 0 8px #F56C6C;
+ animation: blink 1s infinite;
+}
+
+.status-indicator.manual {
+ background-color: #E6A23C;
+ box-shadow: 0 0 8px #E6A23C;
+ animation: pulse 1.5s infinite;
+}
+
+.status-indicator.offline {
+ background-color: #909399;
+}
+
+.device-content {
+ padding: 20px;
+}
+
+.data-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 8px 0;
+ border-bottom: 1px solid #ebeef5;
+}
+
+.data-row:last-child {
+ border-bottom: none;
+}
+
+.label {
+ font-weight: 500;
+ color: #606266;
+}
+
+.fault-text {
+ color: #F56C6C;
+ font-weight: bold;
+}
+
+.no-data {
text-align: center;
- font-size: 28px;
- color: orange;
+ color: #909399;
+ padding: 40px 0;
+ font-style: italic;
+}
+
+.operation-buttons {
+ margin-top: 15px;
+ padding-top: 15px;
+ border-top: 1px dashed #ebeef5;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ justify-content: center;
+}
+
+.address-operation {
+ margin-top: 15px;
+ padding-top: 15px;
+ border-top: 1px dashed #ebeef5;
+}
+
+.address-title {
+ font-weight: 500;
+ color: #606266;
+ margin-bottom: 10px;
+ text-align: center;
+}
+
+.address-input-group {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 10px;
+}
+
+.operation-panel {
+ text-align: center;
+ padding: 20px;
+}
+
+@keyframes pulse {
+ 0% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.5;
+ }
+
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes blink {
+
+ 0%,
+ 50% {
+ opacity: 1;
+ }
+
+ 51%,
+ 100% {
+ opacity: 0.3;
+ }
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+ .devices-container {
+ grid-template-columns: 1fr;
+ }
+
+ .monitor-header {
+ flex-direction: column;
+ gap: 15px;
+ align-items: flex-start;
+ }
+
+ .control-panel {
+ flex-direction: column;
+ align-items: flex-start;
+ width: 100%;
+ }
+
+ .monitor-type-switch,
+ .one-click-operations {
+ margin-right: 0;
+ margin-bottom: 10px;
+ width: 100%;
+ }
+
+ .monitor-type-switch .el-button-group,
+ .one-click-operations .el-button-group {
+ width: 100%;
+ }
+
+ .monitor-type-switch .el-button,
+ .one-click-operations .el-button {
+ flex: 1;
+ }
+
+ .operation-buttons {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .operation-buttons .el-button {
+ width: 100%;
+ }
+
+ .address-input-group {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .address-input-group .el-select,
+ .address-input-group .el-button {
+ width: 100%;
+ }
}
</style>
\ No newline at end of file
--
Gitblit v1.9.3