fix(playback): 增加库位数据支持,优化回放模式下的数据处理逻辑
This commit is contained in:
parent
85f7b94313
commit
1fbdb5efcb
@ -8,7 +8,7 @@ import ws from '../services/ws';
|
|||||||
|
|
||||||
// Define the structure of WebSocket messages for playback
|
// Define the structure of WebSocket messages for playback
|
||||||
type PlaybackMessage = {
|
type PlaybackMessage = {
|
||||||
type: 'AMR' | 'SCENE';
|
type: 'AMR' | 'SCENE' | 'LOCATION';
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
data: any;
|
data: any;
|
||||||
};
|
};
|
||||||
@ -18,6 +18,7 @@ type PlaybackSceneData = {
|
|||||||
totalDuration: number;
|
totalDuration: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Hook's return type definition
|
||||||
// Hook's return type definition
|
// Hook's return type definition
|
||||||
export interface UsePlaybackWebSocketReturn {
|
export interface UsePlaybackWebSocketReturn {
|
||||||
// Connection status
|
// Connection status
|
||||||
@ -31,6 +32,7 @@ export interface UsePlaybackWebSocketReturn {
|
|||||||
// Data for rendering
|
// Data for rendering
|
||||||
currentSceneId: Ref<string | null>;
|
currentSceneId: Ref<string | null>;
|
||||||
sceneJson: Ref<string | null>;
|
sceneJson: Ref<string | null>;
|
||||||
|
locationData: Ref<any[]>; // 新增:用于存储库位数据
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
connect: (historySceneId: string) => void;
|
connect: (historySceneId: string) => void;
|
||||||
@ -50,6 +52,7 @@ export function usePlaybackWebSocket(editorService: ShallowRef<EditorService | u
|
|||||||
const totalDuration = ref(0);
|
const totalDuration = ref(0);
|
||||||
const currentSceneId = ref<string | null>(null);
|
const currentSceneId = ref<string | null>(null);
|
||||||
const sceneJson = ref<string | null>(null);
|
const sceneJson = ref<string | null>(null);
|
||||||
|
const locationData = ref<any[]>([]); // 新增:库位数据的响应式引用
|
||||||
|
|
||||||
const { calculateCenterPoint, jumpToPosition } = useViewState();
|
const { calculateCenterPoint, jumpToPosition } = useViewState();
|
||||||
|
|
||||||
@ -100,6 +103,9 @@ export function usePlaybackWebSocket(editorService: ShallowRef<EditorService | u
|
|||||||
(msg.data as RobotRealtimeInfo[]).forEach((robot) => {
|
(msg.data as RobotRealtimeInfo[]).forEach((robot) => {
|
||||||
latestRobotData.set(robot.id, robot);
|
latestRobotData.set(robot.id, robot);
|
||||||
});
|
});
|
||||||
|
} else if (msg.type === 'LOCATION') {
|
||||||
|
// 新增:处理库位数据
|
||||||
|
locationData.value = msg.data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -230,6 +236,7 @@ export function usePlaybackWebSocket(editorService: ShallowRef<EditorService | u
|
|||||||
totalDuration,
|
totalDuration,
|
||||||
currentSceneId,
|
currentSceneId,
|
||||||
sceneJson,
|
sceneJson,
|
||||||
|
locationData, // 新增
|
||||||
connect,
|
connect,
|
||||||
disconnect,
|
disconnect,
|
||||||
play,
|
play,
|
||||||
|
|||||||
@ -112,9 +112,12 @@ const playback = usePlaybackWebSocket(editor);
|
|||||||
watch(mode, async (newMode) => {
|
watch(mode, async (newMode) => {
|
||||||
if (newMode === 'live') {
|
if (newMode === 'live') {
|
||||||
playback.disconnect();
|
playback.disconnect();
|
||||||
|
storageLocationService.value?.setPlaybackMode(false);
|
||||||
await monitorScene();
|
await monitorScene();
|
||||||
|
storageLocationService.value?.startMonitoring({ interval: 1 });
|
||||||
} else {
|
} else {
|
||||||
client.value?.close();
|
client.value?.close();
|
||||||
|
storageLocationService.value?.setPlaybackMode(true);
|
||||||
playback.connect(props.sid); // Connect once using props.sid
|
playback.connect(props.sid); // Connect once using props.sid
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -127,6 +130,44 @@ watch(playback.sceneJson, async (newJson) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(playback.locationData, (newData) => {
|
||||||
|
if (newData) {
|
||||||
|
storageLocationService.value?.handlePlaybackData(newData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mockLocationInterval: NodeJS.Timeout;
|
||||||
|
onMounted(() => {
|
||||||
|
// 仅在回放模式下启动模拟数据
|
||||||
|
if (isPlaybackMode.value) {
|
||||||
|
let occupied = false;
|
||||||
|
mockLocationInterval = setInterval(() => {
|
||||||
|
const mockData = {
|
||||||
|
type: 'LOCATION',
|
||||||
|
timestamp: playback.currentTime.value,
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
id: '666',
|
||||||
|
label: '1-1',
|
||||||
|
stationName: 'AP190',
|
||||||
|
occupied: occupied,
|
||||||
|
locked: false,
|
||||||
|
disabled: false,
|
||||||
|
emptyTray: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
// 模拟数据推送
|
||||||
|
storageLocationService.value?.handlePlaybackData(mockData.data);
|
||||||
|
occupied = !occupied; // 切换状态
|
||||||
|
}, 2000); // 每2秒更新一次
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearInterval(mockLocationInterval);
|
||||||
|
});
|
||||||
|
|
||||||
watch(selectedDate, (date) => {
|
watch(selectedDate, (date) => {
|
||||||
if (date) {
|
if (date) {
|
||||||
const startOfDayTimestamp = date.startOf('day').valueOf();
|
const startOfDayTimestamp = date.startOf('day').valueOf();
|
||||||
|
|||||||
@ -115,6 +115,7 @@ export class StorageLocationService {
|
|||||||
private config: StorageLocationConfig;
|
private config: StorageLocationConfig;
|
||||||
// 渲染调度标记,避免在高频事件中重复 render
|
// 渲染调度标记,避免在高频事件中重复 render
|
||||||
private renderScheduled = false;
|
private renderScheduled = false;
|
||||||
|
private isPlaybackMode = false;
|
||||||
|
|
||||||
constructor(editor: EditorService, sceneId: string, config?: Partial<StorageLocationConfig>) {
|
constructor(editor: EditorService, sceneId: string, config?: Partial<StorageLocationConfig>) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
@ -472,6 +473,9 @@ export class StorageLocationService {
|
|||||||
* @param options 监控选项
|
* @param options 监控选项
|
||||||
*/
|
*/
|
||||||
async startMonitoring(options: { interval?: number } = {}) {
|
async startMonitoring(options: { interval?: number } = {}) {
|
||||||
|
if (this.isPlaybackMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.stopMonitoring();
|
this.stopMonitoring();
|
||||||
|
|
||||||
// 监控库位状态
|
// 监控库位状态
|
||||||
@ -765,6 +769,70 @@ export class StorageLocationService {
|
|||||||
this.storageLocations.value.clear();
|
this.storageLocations.value.clear();
|
||||||
this.editor = null;
|
this.editor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setPlaybackMode(isPlayback: boolean) {
|
||||||
|
this.isPlaybackMode = isPlayback;
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePlaybackData(data: any[]) {
|
||||||
|
const stationToPointIdMap = this.buildStationToPointIdMap();
|
||||||
|
|
||||||
|
const locationsByPointId = new Map<string, StorageLocationInfo[]>();
|
||||||
|
data.forEach((location) => {
|
||||||
|
const pointId = stationToPointIdMap.get(location.stationName);
|
||||||
|
if (pointId) {
|
||||||
|
if (!locationsByPointId.has(pointId)) {
|
||||||
|
locationsByPointId.set(pointId, []);
|
||||||
|
}
|
||||||
|
locationsByPointId.get(pointId)!.push({
|
||||||
|
...location,
|
||||||
|
is_occupied: location.occupied,
|
||||||
|
is_locked: location.locked,
|
||||||
|
is_disabled: location.disabled,
|
||||||
|
is_empty_tray: location.emptyTray,
|
||||||
|
layer_name: location.label,
|
||||||
|
station_name: location.stationName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const changedPointIds = this.getChangedPointIds(locationsByPointId);
|
||||||
|
if (changedPointIds.size === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.storageLocations.value = locationsByPointId;
|
||||||
|
|
||||||
|
storageStateMap.clear();
|
||||||
|
for (const [pointId, list] of locationsByPointId.entries()) {
|
||||||
|
const inner = new Map<string, StorageState>();
|
||||||
|
list.forEach((loc) => {
|
||||||
|
inner.set(loc.layer_name, {
|
||||||
|
occupied: loc.is_occupied,
|
||||||
|
locked: loc.is_locked,
|
||||||
|
disabled: loc.is_disabled,
|
||||||
|
isEmptyTray: loc.is_empty_tray,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
storageStateMap.set(pointId, inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updatePointBorderColorsOptimized(changedPointIds);
|
||||||
|
|
||||||
|
for (const pointId of changedPointIds) {
|
||||||
|
const pointPen = this.editor?.getPenById(pointId);
|
||||||
|
const storageNames = pointPen?.point?.associatedStorageLocations;
|
||||||
|
if (pointPen && Array.isArray(storageNames) && storageNames.length > 0) {
|
||||||
|
const existing = this.getStorageLocationPens(pointId);
|
||||||
|
if (existing.length > 0) {
|
||||||
|
this.update(pointId, storageNames);
|
||||||
|
} else {
|
||||||
|
this.create(pointId, storageNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.scheduleRender();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 新增:简化的库位更新API ====================
|
// ==================== 新增:简化的库位更新API ====================
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user