Compare commits
2 Commits
4ce5921d5c
...
b1d8806a59
Author | SHA1 | Date | |
---|---|---|---|
b1d8806a59 | |||
b2fc2d8d73 |
@ -4,6 +4,7 @@ import { type Ref, ref, type ShallowRef, shallowRef } from 'vue';
|
||||
|
||||
import type { RobotRealtimeInfo } from '../apis/robot';
|
||||
import type { EditorService } from '../services/editor.service';
|
||||
import { useViewState } from '../services/useViewState';
|
||||
import ws from '../services/ws';
|
||||
|
||||
// Define the structure of WebSocket messages for playback
|
||||
@ -51,6 +52,15 @@ export function usePlaybackWebSocket(editorService: ShallowRef<EditorService | u
|
||||
const currentSceneId = ref<string | null>(null);
|
||||
const sceneJson = ref<string | null>(null);
|
||||
|
||||
const { calculateCenterPoint, jumpToPosition } = useViewState();
|
||||
|
||||
const locateCenter = () => {
|
||||
if (editorService.value) {
|
||||
const { centerX, centerY } = calculateCenterPoint(editorService.value);
|
||||
jumpToPosition(editorService.value, centerX, centerY, false, 0.05);
|
||||
}
|
||||
};
|
||||
|
||||
const latestRobotData = new Map<string, RobotRealtimeInfo>();
|
||||
let animationFrameId: number;
|
||||
|
||||
@ -82,6 +92,11 @@ export function usePlaybackWebSocket(editorService: ShallowRef<EditorService | u
|
||||
// For seamless scene switching, we only update the scene JSON.
|
||||
// Time and playback state should continue uninterrupted.
|
||||
sceneJson.value = msg.data;
|
||||
// After receiving a new scene, automatically center the view.
|
||||
// Use a timeout to allow the new scene to be rendered first.
|
||||
setTimeout(() => {
|
||||
locateCenter();
|
||||
}, 100);
|
||||
} else if (msg.type === 'AMR') {
|
||||
(msg.data as RobotRealtimeInfo[]).forEach(robot => {
|
||||
latestRobotData.set(robot.id, robot);
|
||||
|
@ -6,6 +6,7 @@ import { isNil } from 'lodash-es';
|
||||
import { computed, onMounted, onUnmounted, provide, ref, type ShallowRef, shallowRef, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import type { RobotRealtimeInfo } from '../apis/robot';
|
||||
import { getSceneByGroupId, getSceneById, monitorRealSceneById, monitorSceneById } from '../apis/scene';
|
||||
import expandIcon from '../assets/icons/png/expand.png';
|
||||
import foldIcon from '../assets/icons/png/fold.png';
|
||||
@ -71,7 +72,7 @@ const client = shallowRef<WebSocket>();
|
||||
// 左侧边栏元素引用(用于 Ctrl/Cmd+F 聚焦搜索框)
|
||||
const leftSiderEl = shallowRef<HTMLElement>();
|
||||
const isPlaybackControllerVisible = ref<boolean>(true);
|
||||
const selectedDate = ref<Dayjs | null>(null);
|
||||
const selectedDate = ref<Dayjs>();
|
||||
|
||||
const playback = usePlaybackWebSocket(editor);
|
||||
|
||||
@ -85,9 +86,16 @@ watch(mode, async (newMode) => {
|
||||
}
|
||||
});
|
||||
|
||||
const handleDateChange = (date: Dayjs) => {
|
||||
watch(playback.sceneJson, async (newJson) => {
|
||||
if (newJson) {
|
||||
await editor.value?.load(newJson);
|
||||
// [关键修复] 场景加载后,立即重新初始化机器人
|
||||
await editor.value?.initRobots();
|
||||
}
|
||||
});
|
||||
|
||||
watch(selectedDate, (date) => {
|
||||
if (date) {
|
||||
selectedDate.value = date;
|
||||
const startOfDayTimestamp = date.startOf('day').valueOf();
|
||||
playback.seek(startOfDayTimestamp);
|
||||
// The total duration is now relative to the start of the day
|
||||
@ -95,7 +103,7 @@ const handleDateChange = (date: Dayjs) => {
|
||||
// Set current time to the beginning of the selected day for the slider
|
||||
playback.currentTime.value = startOfDayTimestamp;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const handleSeek = (relativeTime: number) => {
|
||||
if (selectedDate.value) {
|
||||
@ -552,9 +560,7 @@ const focusFindKeydownHandler = (event: KeyboardEvent) => {
|
||||
if (input) {
|
||||
event.preventDefault();
|
||||
input.focus();
|
||||
try {
|
||||
input.select?.();
|
||||
} catch {}
|
||||
input.select?.();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -583,12 +589,7 @@ const handleGlobalKeydown = (event: KeyboardEvent) => {
|
||||
<a-button type="primary" :loading="isSaving" @click="handleSaveViewState"> 保存比例 </a-button>
|
||||
<a-divider type="vertical" />
|
||||
|
||||
<a-date-picker
|
||||
v-if="isPlaybackMode"
|
||||
:value="selectedDate"
|
||||
@change="handleDateChange"
|
||||
placeholder="请选择回放日期"
|
||||
/>
|
||||
<a-date-picker v-if="isPlaybackMode" v-model:value="selectedDate" placeholder="请选择回放日期" />
|
||||
</a-space>
|
||||
</a-flex>
|
||||
</a-layout-header>
|
||||
|
Loading…
x
Reference in New Issue
Block a user