diff --git a/src/hooks/usePlaybackWebSocket.ts b/src/hooks/usePlaybackWebSocket.ts index cde2bcb..2e7c0e5 100644 --- a/src/hooks/usePlaybackWebSocket.ts +++ b/src/hooks/usePlaybackWebSocket.ts @@ -44,7 +44,10 @@ export interface UsePlaybackWebSocketReturn { changeSpeed: (speed: number) => void; // Placeholder for speed control } -export function usePlaybackWebSocket(editorService: ShallowRef): UsePlaybackWebSocketReturn { +export function usePlaybackWebSocket( + editorService: ShallowRef, + onFirstAmrData?: () => void, +): UsePlaybackWebSocketReturn { const client = shallowRef(null); const isConnected = ref(false); const isPlaying = ref(false); @@ -54,6 +57,7 @@ export function usePlaybackWebSocket(editorService: ShallowRef(null); const sceneJson = ref(null); const locationData = ref([]); // 新增:库位数据的响应式引用 + let hasReceivedAmrData = false; // 新增:用于确保 onFirstAmrData 只调用一次的标志 const { calculateCenterPoint, jumpToPosition } = useViewState(); @@ -104,6 +108,11 @@ export function usePlaybackWebSocket(editorService: ShallowRef { latestRobotData.set(robot.id, robot); }); + // [关键修复] 仅在第一次收到AMR数据时触发回调 + if (!hasReceivedAmrData) { + hasReceivedAmrData = true; + onFirstAmrData?.(); + } } else if (msg.type === 'LOCATION') { // 新增:处理库位数据 locationData.value = msg.data; diff --git a/src/pages/movement-supervision.vue b/src/pages/movement-supervision.vue index bf588d0..2cee57e 100644 --- a/src/pages/movement-supervision.vue +++ b/src/pages/movement-supervision.vue @@ -107,7 +107,10 @@ const leftSiderEl = shallowRef(); const isPlaybackControllerVisible = ref(true); const selectedDate = ref(); -const playback = usePlaybackWebSocket(editor); +const playback = usePlaybackWebSocket(editor, async () => { + // [关键修复] 只有在收到第一帧机器人数据后才初始化机器人图元 + await editor.value?.initRobots(); +}); watch(mode, async (newMode) => { if (newMode === 'live') { @@ -125,8 +128,8 @@ watch(mode, async (newMode) => { watch(playback.sceneJson, async (newJson) => { if (newJson) { await editor.value?.load(newJson); - // [关键修复] 场景加载后,立即重新初始化机器人 - await editor.value?.initRobots(); + // [移除] 不再需要在这里初始化机器人,交由 onFirstAmrData 回调处理 + // await editor.value?.initRobots(); } }); @@ -205,8 +208,8 @@ watch(playback.currentTime, (newTimestamp) => { watch(playback.sceneJson, async (newJson) => { if (newJson) { await editor.value?.load(newJson); - // [关键修复] 场景加载后,立即重新初始化机器人 - await editor.value?.initRobots(); + // [移除] 不再需要在这里初始化机器人,交由 onFirstAmrData 回调处理 + // await editor.value?.initRobots(); } }); @@ -258,7 +261,7 @@ const readScene = async () => { * 采用 requestAnimationFrame 优化高频数据渲染,确保动画流畅且不阻塞UI线程。 */ const monitorScene = async () => { - console.log(current.value?.id); + console.log('[实时模式] 开始监控场景, current:', current.value?.id); client.value?.close(); // 根据路由路径是否是真实场景监控决定使用哪个监控接口 const sidWithFloor = isMultiFloor.value ? `${props.sid}/${currentFloorIndex.value + 1}` : props.sid; @@ -278,6 +281,7 @@ const monitorScene = async () => { * @param updates 需要更新的机器人数据数组 */ const batchUpdateRobots = (updates: Array<{ id: string; data: RobotRealtimeInfo }>) => { + console.log('[实时模式] batchUpdateRobots 被调用,更新数量:', updates.length); if (!editor.value || updates.length === 0) return; // 用于收集所有图元(pen)的更新数据 @@ -299,6 +303,7 @@ const monitorScene = async () => { } = data; // 1. 更新机器人缓存的业务数据 + console.log('[实时模式] 更新机器人业务数据:', id, { x, y, active, angle }); editor.value?.updateRobot(id, { ...rest, isCharging: isCharging as any, @@ -338,6 +343,7 @@ const monitorScene = async () => { penUpdatePayload.y = y - 60; penUpdatePayload.visible = true; penUpdatePayload.locked = LockState.None; + console.log('[实时模式] 设置机器人可见性:', id, { x: x - 60, y: y - 60, visible: true }); } if (angle != null) { penUpdatePayload.rotate = -angle + 180; @@ -423,6 +429,7 @@ const monitorScene = async () => { */ ws.onmessage = (e) => { const data = JSON.parse(e.data || '{}'); + console.log('[实时模式] 收到WebSocket数据:', data); // 判断数据类型:type=99为自动门点,其他为机器人 if (data.type === 99) { @@ -431,6 +438,7 @@ const monitorScene = async () => { } else { // 机器人数据处理 const robotData = data as RobotRealtimeInfo; + console.log('[实时模式] 收到机器人数据:', robotData.id, { x: robotData.x, y: robotData.y, active: robotData.active }); latestRobotData.set(robotData.id, robotData); } }; @@ -541,9 +549,14 @@ onMounted(() => { onMounted(async () => { console.log('Current route in movement-supervision.vue:', window.location.href); if (mode.value === 'live') { + console.log('[实时模式] 初始化实时模式'); await readScene(); + // [关键修复] 实时模式下需要显式初始化机器人 + console.log('[实时模式] 初始化机器人图元'); + await editor.value?.initRobots(); await monitorScene(); } else { + console.log('[回放模式] 初始化回放模式'); playback.connect(props.sid); // [调试代码] 自动设置回放日期和时间 const debugDate = dayjs('2025-09-28 09:00:00'); @@ -551,7 +564,8 @@ onMounted(async () => { playback.seek(debugDate.valueOf()); } - await editor.value?.initRobots(); + // [移除] 不再需要在这里初始化机器人,交由 onFirstAmrData 回调处理 + // await editor.value?.initRobots(); storageLocationService.value?.startMonitoring({ interval: 1 }); // 自动保存和恢复视图状态