增加了单个设备的重启功能,并修复了刷新的错误。
This commit is contained in:
parent
7b7394bbac
commit
76c61d75df
@ -65,6 +65,9 @@ class DeviceCoordinator:
|
|||||||
# 事件回调
|
# 事件回调
|
||||||
self.event_callbacks: Dict[str, List[Callable]] = defaultdict(list)
|
self.event_callbacks: Dict[str, List[Callable]] = defaultdict(list)
|
||||||
|
|
||||||
|
# 状态变化回调存储
|
||||||
|
self._status_change_callback = None
|
||||||
|
|
||||||
# 性能统计
|
# 性能统计
|
||||||
self.stats = {
|
self.stats = {
|
||||||
'start_time': None,
|
'start_time': None,
|
||||||
@ -78,6 +81,20 @@ class DeviceCoordinator:
|
|||||||
|
|
||||||
self.logger.info("设备协调器初始化完成")
|
self.logger.info("设备协调器初始化完成")
|
||||||
|
|
||||||
|
def set_status_change_callback(self, callback: Callable):
|
||||||
|
"""
|
||||||
|
设置状态变化回调函数
|
||||||
|
|
||||||
|
Args:
|
||||||
|
callback: 状态变化回调函数
|
||||||
|
"""
|
||||||
|
self._status_change_callback = callback
|
||||||
|
# 为已存在的设备注册回调
|
||||||
|
for device_name, device in self.devices.items():
|
||||||
|
if device and hasattr(device, 'add_status_change_callback'):
|
||||||
|
device.add_status_change_callback(callback)
|
||||||
|
self.logger.info(f"{device_name} 设备状态变化回调已注册")
|
||||||
|
|
||||||
def initialize(self) -> bool:
|
def initialize(self) -> bool:
|
||||||
"""
|
"""
|
||||||
初始化所有设备
|
初始化所有设备
|
||||||
@ -530,7 +547,7 @@ class DeviceCoordinator:
|
|||||||
cleanup_start = time.time()
|
cleanup_start = time.time()
|
||||||
self.logger.info(f"正在彻底清理 {device_name} 设备...")
|
self.logger.info(f"正在彻底清理 {device_name} 设备...")
|
||||||
|
|
||||||
# 断开连接
|
# 断开连接但暂时不广播状态变化,避免重启过程中的状态冲突
|
||||||
if hasattr(device, 'disconnect'):
|
if hasattr(device, 'disconnect'):
|
||||||
try:
|
try:
|
||||||
device.disconnect()
|
device.disconnect()
|
||||||
@ -538,6 +555,12 @@ class DeviceCoordinator:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"断开 {device_name} 连接异常: {e}")
|
self.logger.warning(f"断开 {device_name} 连接异常: {e}")
|
||||||
|
|
||||||
|
# 静默设置设备状态为未连接,不触发状态变化通知
|
||||||
|
# 这样可以避免在重启过程中广播中间状态
|
||||||
|
if hasattr(device, 'is_connected'):
|
||||||
|
device.is_connected = False
|
||||||
|
self.logger.info(f"{device_name} 设备状态已静默更新为未连接(重启过程中)")
|
||||||
|
|
||||||
# 彻底清理资源
|
# 彻底清理资源
|
||||||
if hasattr(device, 'cleanup'):
|
if hasattr(device, 'cleanup'):
|
||||||
try:
|
try:
|
||||||
@ -605,6 +628,12 @@ class DeviceCoordinator:
|
|||||||
create_time = (time.time() - create_start) * 1000
|
create_time = (time.time() - create_start) * 1000
|
||||||
self.logger.info(f"{device_name} 设备实例重新创建成功 (耗时: {create_time:.1f}ms)")
|
self.logger.info(f"{device_name} 设备实例重新创建成功 (耗时: {create_time:.1f}ms)")
|
||||||
|
|
||||||
|
# 重新注册状态变化回调(如果有的话)
|
||||||
|
if hasattr(self, '_status_change_callback') and self._status_change_callback:
|
||||||
|
if hasattr(new_device, 'add_status_change_callback'):
|
||||||
|
new_device.add_status_change_callback(self._status_change_callback)
|
||||||
|
self.logger.info(f"{device_name} 设备状态变化回调已重新注册")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
create_time = (time.time() - create_start) * 1000
|
create_time = (time.time() - create_start) * 1000
|
||||||
self.logger.error(f"重新创建 {device_name} 设备实例失败: {e} (耗时: {create_time:.1f}ms)")
|
self.logger.error(f"重新创建 {device_name} 设备实例失败: {e} (耗时: {create_time:.1f}ms)")
|
||||||
@ -624,6 +653,14 @@ class DeviceCoordinator:
|
|||||||
init_time = (time.time() - init_start) * 1000
|
init_time = (time.time() - init_start) * 1000
|
||||||
self.logger.info(f"{device_name} 设备初始化成功 (耗时: {init_time:.1f}ms)")
|
self.logger.info(f"{device_name} 设备初始化成功 (耗时: {init_time:.1f}ms)")
|
||||||
|
|
||||||
|
# 设备初始化成功后,确保状态广播正确
|
||||||
|
# 此时设备应该已经通过initialize()方法中的set_connected(True)触发了状态变化通知
|
||||||
|
# 但为了确保状态一致性,我们再次确认状态
|
||||||
|
if hasattr(new_device, 'is_connected') and new_device.is_connected:
|
||||||
|
self.logger.info(f"{device_name} 设备重启后状态确认:已连接")
|
||||||
|
else:
|
||||||
|
self.logger.warning(f"{device_name} 设备重启后状态异常:未连接")
|
||||||
|
|
||||||
# 第六步:如果之前在推流,则启动推流
|
# 第六步:如果之前在推流,则启动推流
|
||||||
stream_time = 0
|
stream_time = 0
|
||||||
if was_streaming and hasattr(new_device, 'start_streaming'):
|
if was_streaming and hasattr(new_device, 'start_streaming'):
|
||||||
|
@ -187,13 +187,15 @@ class AppServer:
|
|||||||
# 初始化设备协调器(统一管理所有设备)
|
# 初始化设备协调器(统一管理所有设备)
|
||||||
self.logger.info('正在初始化设备协调器...')
|
self.logger.info('正在初始化设备协调器...')
|
||||||
self.device_coordinator = DeviceCoordinator(self.socketio)
|
self.device_coordinator = DeviceCoordinator(self.socketio)
|
||||||
|
# 设置状态变化回调
|
||||||
|
self.device_coordinator.set_status_change_callback(self._on_device_status_change)
|
||||||
# 调用初始化方法来初始化设备
|
# 调用初始化方法来初始化设备
|
||||||
if self.device_coordinator.initialize():
|
if self.device_coordinator.initialize():
|
||||||
self.logger.info('设备协调器初始化完成')
|
self.logger.info('设备协调器初始化完成')
|
||||||
# 获取设备管理器实例
|
# 获取设备管理器实例
|
||||||
self.device_managers = self.device_coordinator.get_device_managers()
|
self.device_managers = self.device_coordinator.get_device_managers()
|
||||||
|
|
||||||
# 为每个设备添加状态变化回调
|
# 为每个设备添加状态变化回调(双重保险)
|
||||||
for device_name, manager in self.device_managers.items():
|
for device_name, manager in self.device_managers.items():
|
||||||
if manager and hasattr(manager, 'add_status_change_callback'):
|
if manager and hasattr(manager, 'add_status_change_callback'):
|
||||||
manager.add_status_change_callback(self._on_device_status_change)
|
manager.add_status_change_callback(self._on_device_status_change)
|
||||||
@ -1488,7 +1490,7 @@ class AppServer:
|
|||||||
'device_type': device_type,
|
'device_type': device_type,
|
||||||
'message': f'{device_type} 设备重启成功!',
|
'message': f'{device_type} 设备重启成功!',
|
||||||
'timestamp': time.time()
|
'timestamp': time.time()
|
||||||
})
|
}, namespace='/devices')
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
self.logger.error(f'{device_type} 设备重启失败!')
|
self.logger.error(f'{device_type} 设备重启失败!')
|
||||||
@ -1497,7 +1499,7 @@ class AppServer:
|
|||||||
'device_type': device_type,
|
'device_type': device_type,
|
||||||
'message': f'{device_type} 设备重启失败!',
|
'message': f'{device_type} 设备重启失败!',
|
||||||
'timestamp': time.time()
|
'timestamp': time.time()
|
||||||
})
|
}, namespace='/devices')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -1509,7 +1511,7 @@ class AppServer:
|
|||||||
'error': str(e),
|
'error': str(e),
|
||||||
'message': f'重启 {device_type} 设备时发生异常',
|
'message': f'重启 {device_type} 设备时发生异常',
|
||||||
'timestamp': time.time()
|
'timestamp': time.time()
|
||||||
})
|
}, namespace='/devices')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -1649,7 +1651,8 @@ class AppServer:
|
|||||||
|
|
||||||
def broadcast_all_device_status(self):
|
def broadcast_all_device_status(self):
|
||||||
"""广播所有设备状态"""
|
"""广播所有设备状态"""
|
||||||
for device_name, manager in self.device_managers.items():
|
current_devices = self.device_coordinator.get_device_managers()
|
||||||
|
for device_name, manager in current_devices.items():
|
||||||
if manager is not None:
|
if manager is not None:
|
||||||
try:
|
try:
|
||||||
# 检查设备是否连接(使用is_connected属性)
|
# 检查设备是否连接(使用is_connected属性)
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
<div style="display: flex;align-items: center;">
|
<div style="display: flex;align-items: center;">
|
||||||
<div v-if="!isRecording" class="top-bar-left" @click="routeTo('/')" style="cursor: pointer;">
|
<div v-if="!isRecording" class="top-bar-left" @click="routeTo('/')" style="cursor: pointer;">
|
||||||
<img src="@/assets/svg/u14.svg" alt="">
|
<img src="@/assets/svg/u14.svg" alt="">
|
||||||
<!-- <el-icon class="back-icon" @click="handleBack"><ArrowLeft /></el-icon> -->
|
|
||||||
<span class="page-title">实时检测</span>
|
<span class="page-title">实时检测</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-left: 10px;">
|
<div style="padding-left: 10px;">
|
||||||
@ -17,7 +16,6 @@
|
|||||||
<img src="@/assets/sz.png" alt="" title="编辑相机参数" v-if="isConnected == true"
|
<img src="@/assets/sz.png" alt="" title="编辑相机参数" v-if="isConnected == true"
|
||||||
style="margin-left: 20px;cursor: pointer; width: 24px;height: 24px;"
|
style="margin-left: 20px;cursor: pointer; width: 24px;height: 24px;"
|
||||||
@click="cameraUpdate">
|
@click="cameraUpdate">
|
||||||
|
|
||||||
|
|
||||||
<!-- 录制时间 -->
|
<!-- 录制时间 -->
|
||||||
<div v-if="isRecording" class="icon-container">
|
<div v-if="isRecording" class="icon-container">
|
||||||
@ -97,12 +95,12 @@
|
|||||||
头部姿态
|
头部姿态
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-button type="primary" class="start-btn" @click="calibrationClick" :disabled="isRecording"
|
<el-button type="primary" class="start-btn" @click="calibrationClick"
|
||||||
style="background-color: #0099ff;font-size: 14px;
|
style="background-color: #0099ff;font-size: 14px;
|
||||||
--el-button-border-color: transparent !important;border-radius: 20px;height:26px;border:none;width: 100px;">
|
--el-button-border-color: transparent !important;border-radius: 20px;height:26px;border:none;width: 100px;">
|
||||||
校准
|
校准
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" class="start-btn" @click="clearAndStartTracking" :disabled="isRecording"
|
<el-button type="primary" class="start-btn" @click="clearAndStartTracking"
|
||||||
style="background-color: #0099ff;font-size: 14px;margin-left: 15px;
|
style="background-color: #0099ff;font-size: 14px;margin-left: 15px;
|
||||||
--el-button-border-color: transparent !important;border-radius: 20px;height:26px;border:none;width: 100px;">
|
--el-button-border-color: transparent !important;border-radius: 20px;height:26px;border:none;width: 100px;">
|
||||||
清零
|
清零
|
||||||
@ -581,13 +579,11 @@ import HistoryDashboard from '@/views/PatientProfile.vue'
|
|||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const isStart = ref(false)
|
const isRecording = ref(false)
|
||||||
const isConnected = ref(false)
|
const isConnected = ref(false)
|
||||||
const rtspImgSrc = ref('')
|
const rtspImgSrc = ref('')
|
||||||
const depthCameraImgSrc = ref('') // 深度相机视频流
|
const depthCameraImgSrc = ref('') // 深度相机视频流
|
||||||
const screenshotLoading = ref(false)
|
const screenshotLoading = ref(false)
|
||||||
const dataCollectionLoading = ref(false)
|
|
||||||
const isRecording = ref(false)
|
|
||||||
const cameraDialogVisible =ref(false) // 设置相机参数弹框
|
const cameraDialogVisible =ref(false) // 设置相机参数弹框
|
||||||
const contenGridRef =ref(null) // 实时检查整体box
|
const contenGridRef =ref(null) // 实时检查整体box
|
||||||
const wholeBodyRef = ref(null) // 身体姿态ref
|
const wholeBodyRef = ref(null) // 身体姿态ref
|
||||||
@ -893,16 +889,17 @@ const savePatient = async () => {
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function routeTo(path) {
|
const isPreventCombo = ref(false)
|
||||||
if( isPreventCombo.value == true){
|
function routeTo(path = '/') {
|
||||||
setTimeout(() => {
|
if (isPreventCombo.value === true) {
|
||||||
isPreventCombo.value = false
|
ElMessage.warning(`请勿连续点击回退按钮!`)
|
||||||
}, 2000);
|
|
||||||
ElMessage.warning(`请勿连击点击刷新按钮`)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isPreventCombo.value = true
|
isPreventCombo.value = true
|
||||||
router.push(`/`)
|
setTimeout(() => {
|
||||||
|
isPreventCombo.value = false
|
||||||
|
}, 2000)
|
||||||
|
router.push(path)
|
||||||
}
|
}
|
||||||
function cameraUpdate() { // 相机设置数据更新弹框
|
function cameraUpdate() { // 相机设置数据更新弹框
|
||||||
cameraForm.value = { // 相机参数
|
cameraForm.value = { // 相机参数
|
||||||
@ -1012,22 +1009,12 @@ function connectWebSocket() {
|
|||||||
|
|
||||||
socket.on('connect_error', (error) => {
|
socket.on('connect_error', (error) => {
|
||||||
console.error('❌ 主连接失败:', error.message)
|
console.error('❌ 主连接失败:', error.message)
|
||||||
isConnected.value = false
|
isConnected.value = false
|
||||||
// 如果正在录像,停止录像
|
|
||||||
if (isRecording.value) {
|
|
||||||
stopRecording()
|
|
||||||
isStart.value = false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on('disconnect', (reason) => {
|
socket.on('disconnect', (reason) => {
|
||||||
console.log('⚠️ 主连接断开:', reason)
|
console.log('⚠️ 主连接断开:', reason)
|
||||||
isConnected.value = false
|
isConnected.value = false
|
||||||
|
|
||||||
if (isRecording.value) {
|
|
||||||
stopRecording()
|
|
||||||
isStart.value = false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on('reconnect', (attemptNumber) => {
|
socket.on('reconnect', (attemptNumber) => {
|
||||||
@ -1077,24 +1064,25 @@ function connectWebSocket() {
|
|||||||
console.error('❌ 设备命名空间连接失败:', error.message)
|
console.error('❌ 设备命名空间连接失败:', error.message)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 监听设备重启消息事件
|
||||||
|
devicesSocket.on('device_restart_message', (data) => {
|
||||||
|
ElMessage.success({
|
||||||
|
message: data.message,
|
||||||
|
duration: 5000
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// 监听各设备数据事件
|
// 监听各设备数据事件
|
||||||
devicesSocket.on('camera_frame', (data) => {
|
devicesSocket.on('camera_frame', (data) => {
|
||||||
frameCount++
|
frameCount++
|
||||||
tempInfo.value.camera_frame = data
|
tempInfo.value.camera_frame = data
|
||||||
displayFrame(data.image)
|
displayFrame(data.image)
|
||||||
})
|
})
|
||||||
devicesSocket.on('device_restart_message', (data) => {
|
|
||||||
debugger
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
devicesSocket.on('femtobolt_frame', (data) => {
|
devicesSocket.on('femtobolt_frame', (data) => {
|
||||||
tempInfo.value.femtobolt_frame = data
|
tempInfo.value.femtobolt_frame = data
|
||||||
displayDepthCameraFrame(data.depth_image || data.image)
|
displayDepthCameraFrame(data.depth_image || data.image)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
devicesSocket.on('imu_data', (data) => {
|
devicesSocket.on('imu_data', (data) => {
|
||||||
tempInfo.value.imu_data = data
|
tempInfo.value.imu_data = data
|
||||||
@ -1164,41 +1152,76 @@ function startDeviceDataPush() {
|
|||||||
|
|
||||||
// 断开WebSocket连接函数
|
// 断开WebSocket连接函数
|
||||||
function disconnectWebSocket() {
|
function disconnectWebSocket() {
|
||||||
if (socket && socket.connected) {
|
try {
|
||||||
console.log('正在主动断开WebSocket连接...')
|
if (socket) {
|
||||||
|
if (socket.connected) {
|
||||||
|
console.log('正在主动断开WebSocket连接...')
|
||||||
|
|
||||||
// 断开主连接
|
// 移除所有事件监听器
|
||||||
socket.disconnect()
|
socket.removeAllListeners()
|
||||||
socket = null
|
|
||||||
isConnected.value = false
|
// 断开主连接
|
||||||
|
socket.disconnect()
|
||||||
|
|
||||||
|
console.log('✅ 主WebSocket连接已断开')
|
||||||
|
}
|
||||||
|
socket = null
|
||||||
|
isConnected.value = false
|
||||||
|
}
|
||||||
|
|
||||||
console.log('✅ 主WebSocket连接已断开')
|
// 断开统一设备命名空间连接
|
||||||
|
if (devicesSocket) {
|
||||||
|
if (devicesSocket.connected) {
|
||||||
|
// 取消订阅所有设备
|
||||||
|
try {
|
||||||
|
devicesSocket.emit('unsubscribe_device', { device_type: 'camera' })
|
||||||
|
devicesSocket.emit('unsubscribe_device', { device_type: 'femtobolt' })
|
||||||
|
devicesSocket.emit('unsubscribe_device', { device_type: 'imu' })
|
||||||
|
devicesSocket.emit('unsubscribe_device', { device_type: 'pressure' })
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('取消设备订阅时出错:', e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除所有事件监听器
|
||||||
|
devicesSocket.removeAllListeners()
|
||||||
|
|
||||||
|
// 断开连接
|
||||||
|
devicesSocket.disconnect()
|
||||||
|
|
||||||
|
console.log('🔗 统一设备命名空间连接已断开')
|
||||||
|
}
|
||||||
|
|
||||||
|
devicesSocket = null
|
||||||
|
cameraSocket = null
|
||||||
|
femtoboltSocket = null
|
||||||
|
imuSocket = null
|
||||||
|
pressureSocket = null
|
||||||
|
restartSocket = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置所有设备状态
|
||||||
|
cameraStatus.value = '未连接'
|
||||||
|
femtoboltStatus.value = '未连接'
|
||||||
|
imuStatus.value = '未连接'
|
||||||
|
pressureStatus.value = '未连接'
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('断开WebSocket连接时出错:', error)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocket重连函数
|
||||||
|
function reconnectWebSocket() {
|
||||||
|
console.log('开始重新连接WebSocket...')
|
||||||
|
|
||||||
// 断开统一设备命名空间连接
|
// 先断开现有连接
|
||||||
if (devicesSocket && devicesSocket.connected) {
|
disconnectWebSocket()
|
||||||
// 取消订阅所有设备
|
|
||||||
devicesSocket.emit('unsubscribe_device', { device_type: 'camera' })
|
|
||||||
devicesSocket.emit('unsubscribe_device', { device_type: 'femtobolt' })
|
|
||||||
devicesSocket.emit('unsubscribe_device', { device_type: 'imu' })
|
|
||||||
devicesSocket.emit('unsubscribe_device', { device_type: 'pressure' })
|
|
||||||
|
|
||||||
devicesSocket.disconnect()
|
|
||||||
devicesSocket = null
|
|
||||||
cameraSocket = null
|
|
||||||
femtoboltSocket = null
|
|
||||||
imuSocket = null
|
|
||||||
pressureSocket = null
|
|
||||||
restartSocket = null
|
|
||||||
|
|
||||||
console.log('🔗 统一设备命名空间连接已断开')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置所有设备状态
|
// 延迟一段时间后重新连接
|
||||||
cameraStatus.value = '未连接'
|
setTimeout(() => {
|
||||||
femtoboltStatus.value = '未连接'
|
connectWebSocket()
|
||||||
imuStatus.value = '未连接'
|
console.log('WebSocket重连完成')
|
||||||
pressureStatus.value = '未连接'
|
}, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1666,19 +1689,7 @@ async function sendDetectionData(data) {
|
|||||||
|
|
||||||
// 处理开始/停止按钮点击
|
// 处理开始/停止按钮点击
|
||||||
async function handleStartStop() {
|
async function handleStartStop() {
|
||||||
if (!isConnected.value) {
|
if (isRecording.value) {
|
||||||
ElMessage.warning('WebSocket未连接,无法操作')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if( isPreventCombo.value == true){
|
|
||||||
setTimeout(() => {
|
|
||||||
isPreventCombo.value = false
|
|
||||||
}, 2000);
|
|
||||||
ElMessage.warning(`请勿连击点击刷新按钮`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
isPreventCombo.value = true
|
|
||||||
if (isStart.value) {
|
|
||||||
// 停止录制视频
|
// 停止录制视频
|
||||||
await stopRecord()
|
await stopRecord()
|
||||||
} else {
|
} else {
|
||||||
@ -1739,8 +1750,7 @@ async function stopDetection() {
|
|||||||
})
|
})
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
|
||||||
}
|
}
|
||||||
isRecording.value = false
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ 停止检测失败:', error)
|
console.error('❌ 停止检测失败:', error)
|
||||||
ElMessage.error(`停止检测失败: ${error.message}`)
|
ElMessage.error(`停止检测失败: ${error.message}`)
|
||||||
@ -1787,11 +1797,7 @@ const loadPatientInfo = async () => {
|
|||||||
const handleBeforeUnload = (event) => {
|
const handleBeforeUnload = (event) => {
|
||||||
console.log('页面即将关闭,正在清理资源...')
|
console.log('页面即将关闭,正在清理资源...')
|
||||||
|
|
||||||
// 停止录像(如果正在录像)
|
|
||||||
if (isRecording.value) {
|
|
||||||
stopRecording()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 停止检测
|
// 停止检测
|
||||||
stopDetection()
|
stopDetection()
|
||||||
// 断开WebSocket连接
|
// 断开WebSocket连接
|
||||||
@ -1963,53 +1969,70 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
console.log('🔄 Detection组件正在卸载,开始清理资源...')
|
||||||
|
|
||||||
if (timerId.value) {
|
try {
|
||||||
clearInterval(timerId.value);
|
// 清理定时器
|
||||||
}
|
if (timerId.value) {
|
||||||
// 停止录像(如果正在录像)
|
clearInterval(timerId.value)
|
||||||
if (isRecording.value) {
|
timerId.value = null
|
||||||
stopRecording()
|
console.log('✅ 定时器已清理')
|
||||||
}
|
}
|
||||||
if(isStart.value == true){
|
|
||||||
stopRecord()
|
// 停止录制
|
||||||
}
|
if (isRecording.value === true) {
|
||||||
|
stopRecord()
|
||||||
|
console.log('✅ 录制已停止')
|
||||||
|
}
|
||||||
|
|
||||||
stopDetection()
|
// 停止检测
|
||||||
// 页面关闭时断开WebSocket连接
|
stopDetection()
|
||||||
disconnectWebSocket()
|
console.log('✅ 检测已停止')
|
||||||
|
|
||||||
|
// 断开WebSocket连接
|
||||||
|
disconnectWebSocket()
|
||||||
|
console.log('✅ WebSocket连接已断开')
|
||||||
// 清理图表资源
|
|
||||||
if (tiltCharts) {
|
// 清理图表资源
|
||||||
try {
|
if (tiltCharts) {
|
||||||
tiltCharts.dispose();
|
try {
|
||||||
} catch (e) {
|
tiltCharts.dispose()
|
||||||
console.warn('tiltCharts dispose error in onUnmounted:', e);
|
console.log('✅ tiltCharts已清理')
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('tiltCharts dispose error in onUnmounted:', e)
|
||||||
|
}
|
||||||
|
tiltCharts = null
|
||||||
}
|
}
|
||||||
tiltCharts = null;
|
|
||||||
}
|
if (rotationCharts) {
|
||||||
if (rotationCharts) {
|
try {
|
||||||
try {
|
rotationCharts.dispose()
|
||||||
rotationCharts.dispose();
|
console.log('✅ rotationCharts已清理')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('rotationCharts dispose error in onUnmounted:', e);
|
console.warn('rotationCharts dispose error in onUnmounted:', e)
|
||||||
|
}
|
||||||
|
rotationCharts = null
|
||||||
}
|
}
|
||||||
rotationCharts = null;
|
|
||||||
}
|
if (pitchCharts) {
|
||||||
if (pitchCharts) {
|
try {
|
||||||
try {
|
pitchCharts.dispose()
|
||||||
pitchCharts.dispose();
|
console.log('✅ pitchCharts已清理')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('pitchCharts dispose error in onUnmounted:', e);
|
console.warn('pitchCharts dispose error in onUnmounted:', e)
|
||||||
|
}
|
||||||
|
pitchCharts = null
|
||||||
}
|
}
|
||||||
pitchCharts = null;
|
|
||||||
|
// 移除页面关闭事件监听器
|
||||||
|
window.removeEventListener('beforeunload', handleBeforeUnload)
|
||||||
|
console.log('✅ beforeunload事件监听器已移除')
|
||||||
|
|
||||||
|
console.log('🎉 Detection组件资源清理完成')
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Detection组件卸载时出错:', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移除页面关闭事件监听器
|
|
||||||
window.removeEventListener('beforeunload', handleBeforeUnload)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const startRecord = async () => { // 开始录屏
|
const startRecord = async () => { // 开始录屏
|
||||||
@ -2020,7 +2043,6 @@ const startRecord = async () => { // 开始录屏
|
|||||||
if (!patientInfo.value || !patientInfo.value.sessionId) {
|
if (!patientInfo.value || !patientInfo.value.sessionId) {
|
||||||
throw new Error('缺少患者信息,无法开始录屏')
|
throw new Error('缺少患者信息,无法开始录屏')
|
||||||
}
|
}
|
||||||
isRecording.value = true
|
|
||||||
let screen_location = contenGridRef.value.getBoundingClientRect()
|
let screen_location = contenGridRef.value.getBoundingClientRect()
|
||||||
let femtobolt_location = wholeBodyRef.value.getBoundingClientRect()
|
let femtobolt_location = wholeBodyRef.value.getBoundingClientRect()
|
||||||
let camera_location = videoImgRef.value.getBoundingClientRect()
|
let camera_location = videoImgRef.value.getBoundingClientRect()
|
||||||
@ -2051,7 +2073,7 @@ const startRecord = async () => { // 开始录屏
|
|||||||
// 保存会话ID和检测开始时间
|
// 保存会话ID和检测开始时间
|
||||||
patientInfo.value.detectionStartTime = Date.now()
|
patientInfo.value.detectionStartTime = Date.now()
|
||||||
console.log('✅ 录屏会话创建成功,会话ID:', patientInfo.value.sessionId)
|
console.log('✅ 录屏会话创建成功,会话ID:', patientInfo.value.sessionId)
|
||||||
isStart.value = true
|
isRecording.value = true
|
||||||
ElMessage.success('录屏已开始')
|
ElMessage.success('录屏已开始')
|
||||||
} else {
|
} else {
|
||||||
throw new Error(result.message || '开始录屏失败')
|
throw new Error(result.message || '开始录屏失败')
|
||||||
@ -2085,7 +2107,6 @@ const stopRecord = async () => { // 停止录屏
|
|||||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
|
||||||
}
|
}
|
||||||
isRecording.value = false
|
isRecording.value = false
|
||||||
isStart.value = false
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ 停止检测失败:', error)
|
console.error('❌ 停止检测失败:', error)
|
||||||
@ -2096,21 +2117,23 @@ function routerClick(){
|
|||||||
historyDialogVisible.value = true
|
historyDialogVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isRestart = ref(false) // 防止连击
|
||||||
const isPreventCombo =ref(false) // 防止连击
|
|
||||||
|
|
||||||
// 单个刷新数据
|
// 单个刷新数据
|
||||||
function refreshClick(type) {
|
function refreshClick(type) {
|
||||||
if( isPreventCombo.value == true){
|
// 检查是否在冷却期内
|
||||||
setTimeout(() => {
|
if (isRestart.value === true) {
|
||||||
isPreventCombo.value = false
|
ElMessage.warning(`请勿连续点击设备重启按钮!请等待5秒后再试`)
|
||||||
}, 5000);
|
|
||||||
ElMessage.warning(`请勿连击点击刷新按钮`)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isPreventCombo.value = true
|
// 设置冷却状态
|
||||||
|
isRestart.value = true
|
||||||
|
// 5秒后重置状态
|
||||||
|
setTimeout(() => {
|
||||||
|
isRestart.value = false
|
||||||
|
}, 5000)
|
||||||
|
ElMessage.warning(`🚀 发送重启设备请求...`)
|
||||||
if (devicesSocket && devicesSocket.connected) {
|
if (devicesSocket && devicesSocket.connected) {
|
||||||
console.log('🚀 发送重启设备请求...')
|
|
||||||
if(type == 'camera'){
|
if(type == 'camera'){
|
||||||
devicesSocket.emit('restart_device', { device_type: 'camera' })
|
devicesSocket.emit('restart_device', { device_type: 'camera' })
|
||||||
}else if(type == 'femtobolt'){
|
}else if(type == 'femtobolt'){
|
||||||
@ -2120,13 +2143,8 @@ function refreshClick(type) {
|
|||||||
}else if(type == 'pressure'){
|
}else if(type == 'pressure'){
|
||||||
devicesSocket.emit('restart_device', { device_type: 'pressure' })
|
devicesSocket.emit('restart_device', { device_type: 'pressure' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.warn('⚠️ 设备Socket未连接,无法启动设备数据推送')
|
console.warn('⚠️ Socket服务未连接,无法重启设备!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
Reference in New Issue
Block a user