diff --git a/src/pages/movement-supervision.vue b/src/pages/movement-supervision.vue index 2a0326f..41424c7 100644 --- a/src/pages/movement-supervision.vue +++ b/src/pages/movement-supervision.vue @@ -98,7 +98,9 @@ const monitorScene = async () => { const batchUpdateRobots = (updates: Array<{ id: string; data: RobotRealtimeInfo }>) => { if (!editor.value || updates.length === 0) return; - // 先更新所有机器人的状态信息,包括光圈渲染所需的状态 + // 用于收集所有图元(pen)的更新数据 + const allPenUpdates: any[] = []; + updates.forEach(({ id, data }) => { const { x, @@ -114,76 +116,66 @@ const monitorScene = async () => { ...rest } = data; - // 更新机器人基本信息 - // 同步扩展状态(充电/载货/不接单)到机器人信息表,便于服务内读取 + // 1. 更新机器人缓存的业务数据 editor.value?.updateRobot(id, { ...rest, - isCharging: isCharging as any as boolean, - isCarrying: isCarrying as any as boolean, - isNotAcceptingOrders: isNotAcceptingOrders as any as boolean, + isCharging: isCharging as any, + isCarrying: isCarrying as any, + isNotAcceptingOrders: isNotAcceptingOrders as any, }); - // 处理路径坐标转换,参考refreshRobot方法的逻辑 - let processedPath: Array<{ x: number; y: number }> | undefined; + // 2. 准备图元(pen)的更新负载对象,将多个更新合并 + const penUpdatePayload: any = { id }; + const robotState: any = {}; + + // 2.1 处理路径并将其放入 robotState if (points?.length) { - // 新路径:相对于机器人中心的坐标 - const cx = x || 37; // 机器人中心X坐标,默认37 - const cy = y || 37; // 机器人中心Y坐标,默认37 - processedPath = points.map((p) => ({ x: p.x - cx, y: p.y - cy })); + const cx = x || 37; + const cy = y || 37; + robotState.path = points.map((p) => ({ x: p.x - cx, y: p.y - cy })); } - // 更新机器人状态,触发光圈渲染 - const robotState = { - active, - isWaring, - isFault, - path: processedPath, - angle, - isCharging, - isCarrying, - isNotAcceptingOrders, - }; - if (Object.values(robotState).some((v) => v !== undefined)) { - editor.value?.setValue({ id, robot: robotState }, { render: false, history: false, doEvent: false }); + // 2.2 合并其他机器人状态 + if (active !== undefined) robotState.active = active; + if (isWaring !== undefined) robotState.isWaring = isWaring; + if (isFault !== undefined) robotState.isFault = isFault; + if (isCharging !== undefined) robotState.isCharging = isCharging; + if (isCarrying !== undefined) robotState.isCarrying = isCarrying; + if (isNotAcceptingOrders !== undefined) robotState.isNotAcceptingOrders = isNotAcceptingOrders; + + // 将合并后的状态赋给 payload + if (Object.keys(robotState).length > 0) { + penUpdatePayload.robot = robotState; } - }); - // 批量设置位置和可见性(仅在提供坐标时更新) - const positionUpdates = updates - .map(({ id, data }) => { - const { x, y, angle } = data; - // 仅当提供 x、y 或 angle 时才更新位置/角度,避免因缺省数据误将可见性设为 false - if (isNil(x) && isNil(y) && angle == null) { - return undefined; - } - const payload: any = { id }; - if (!isNil(x) && !isNil(y)) { - const newX = x - 60; - const newY = y - 60; - payload.x = newX; - payload.y = newY; - payload.visible = true; - payload.locked = LockState.None; - } - if (angle != null) { - // 后端 angle 为逆时针,把转换改为“先取反再加偏移” - payload.rotate = -angle + 180; - } - return payload; - }) - .filter((v) => v); + // 2.3 合并位置、可见性和角度 + if (!isNil(x) && !isNil(y)) { + penUpdatePayload.x = x - 60; + penUpdatePayload.y = y - 60; + penUpdatePayload.visible = true; + penUpdatePayload.locked = LockState.None; + } + if (angle != null) { + penUpdatePayload.rotate = -angle + 180; + } - // 使用Meta2D的批量更新方法,减少渲染调用 - positionUpdates.forEach((update) => { - editor.value?.setValue(update, { render: false, history: false, doEvent: false }); - }); + // 只有当有实际更新时才推入数组 + if (Object.keys(penUpdatePayload).length > 1) { + allPenUpdates.push(penUpdatePayload); + } - // 更新状态覆盖图标(按优先级:载货 > 不接单 > 充电),大小为机器人图片一半并居中叠加 - updates.forEach(({ id }) => { + // 3. 更新状态覆盖图标 (此API调用如果不能合并,则保留在循环内) editor.value?.updateRobotStatusOverlay?.(id, false); }); - // 批量更新完成后,统一渲染一次 + // 4. 使用Meta2D的批量更新方法一次性提交所有更改 + if (allPenUpdates.length > 0) { + allPenUpdates.forEach((update) => { + editor.value?.setValue(update, { render: false, history: false, doEvent: false }); + }); + } + + // 5. 批量更新完成后,统一渲染一次 editor.value?.render(); };