From b4311eeeb53cbe0f9a69c2df70931cc397df40ee Mon Sep 17 00:00:00 2001 From: xudan Date: Wed, 15 Oct 2025 10:25:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9C=A8=E5=9C=BA=E6=99=AF=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=E4=B8=AD=E6=96=B0=E5=A2=9E=E6=9C=BA=E5=99=A8?= =?UTF-8?q?=E4=BA=BA=E6=95=B0=E6=8D=AE=E5=90=88=E5=B9=B6=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E5=9C=BA=E6=99=AF=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E6=94=AF=E6=8C=81=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E5=A4=9A=E6=A5=BC=E5=B1=82=E6=9C=BA=E5=99=A8=E4=BA=BA=E7=BB=84?= =?UTF-8?q?=E5=92=8C=E6=A0=87=E7=AD=BE=EF=BC=8C=E6=8F=90=E5=8D=87=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=A4=84=E7=90=86=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/scene-editor.vue | 14 +++++--- src/services/editor-robot.service.ts | 49 ++++++++++++++++++++++++++++ src/services/editor.service.ts | 7 +++- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/pages/scene-editor.vue b/src/pages/scene-editor.vue index 699b7c8..908cb51 100644 --- a/src/pages/scene-editor.vue +++ b/src/pages/scene-editor.vue @@ -277,7 +277,7 @@ const importScene = async () => { currentFloorIndex.value = 0; previousFloorIndex.value = 0; // 加载第一个楼层到编辑器 - await editor.value?.load(floorScenes.value[0], editable.value, undefined, requireImportTransform.value); + await editor.value?.load(floorScenes.value[0], editable.value, undefined, requireImportTransform.value, true); message.success(`成功导入 ${sceneData.length} 个楼层,当前显示第一层。`); } else { message.warn('导入的场景文件是一个空数组,已加载空场景。'); @@ -293,7 +293,7 @@ const importScene = async () => { currentFloorIndex.value = 0; previousFloorIndex.value = 0; // 直接加载(editor.load可以接受对象或字符串) - await editor.value?.load(sceneData, editable.value, undefined, requireImportTransform.value); + await editor.value?.load(sceneData, editable.value, undefined, requireImportTransform.value, true); message.success('成功导入单楼层场景。'); } else { message.error('导入失败,场景文件为空或格式不正确。'); @@ -332,7 +332,7 @@ const handleImportSmapConfirm = async ({ smapFile, keepProperties }: { smapFile: if (sceneJson) { requireImportTransform.value = true; - editor.value?.load(sceneJson, editable.value, undefined, requireImportTransform.value); + editor.value?.load(sceneJson, editable.value, undefined, requireImportTransform.value, true); } }; @@ -450,7 +450,13 @@ const handleFloorChange = async (value: any) => { // 加载新楼层 currentFloorIndex.value = newFloorIndex; previousFloorIndex.value = newFloorIndex; - await editor.value.load(floorScenes.value[newFloorIndex], editable.value, undefined, requireImportTransform.value); + await editor.value.load( + floorScenes.value[newFloorIndex], + editable.value, + undefined, + requireImportTransform.value, + true, // Merge robot data + ); } else { currentFloorIndex.value = newFloorIndex; previousFloorIndex.value = newFloorIndex; diff --git a/src/services/editor-robot.service.ts b/src/services/editor-robot.service.ts index 766a36e..b8c4c1d 100644 --- a/src/services/editor-robot.service.ts +++ b/src/services/editor-robot.service.ts @@ -55,6 +55,55 @@ export class EditorRobotService { this.syncRobotLabels(); } + public mergeRobotsData(groups?: RobotGroup[], robots?: RobotInfo[], labels?: RobotLabel[]): void { + const existingGroups = clone(this.robotGroups$$.value); + const existingLabels = clone(this.robotLabels$$.value); + + // Merge robot groups + groups?.forEach(newGroup => { + const existingGroup = existingGroups.find(g => g.id === newGroup.id || g.label === newGroup.label); + if (existingGroup) { + // Merge robots within the group + newGroup.robots?.forEach(robotId => { + if (!existingGroup.robots?.includes(robotId)) { + existingGroup.robots?.push(robotId); + } + }); + } else { + existingGroups.push(newGroup); + } + }); + + // Merge robot labels + labels?.forEach(newLabel => { + const existingLabel = existingLabels.find(l => l.id === newLabel.id || l.label === newLabel.label); + if (existingLabel) { + // Merge robots within the label + newLabel.robots?.forEach(robotId => { + if (!existingLabel.robots?.includes(robotId)) { + existingLabel.robots?.push(robotId); + } + }); + } else { + existingLabels.push(newLabel); + } + }); + + // Merge robots + robots?.forEach(robot => { + if (!this.robotMap.has(robot.id)) { + this.robotMap.set(robot.id, robot); + } + }); + + this.robotGroups$$.next(existingGroups); + this.robotLabels$$.next(existingLabels); + + this.syncRobots(); + this.syncRobotGroups(); + this.syncRobotLabels(); + } + public get robots(): RobotInfo[] { return Array.from(this.robotMap.values()); } diff --git a/src/services/editor.service.ts b/src/services/editor.service.ts index 0c5b1c6..6739a4d 100644 --- a/src/services/editor.service.ts +++ b/src/services/editor.service.ts @@ -78,6 +78,7 @@ export class EditorService extends Meta2d { editable = false, detail?: Partial, isImport = false, + isMerge = false, ): Promise { const sceneData = (isString(map) ? (map ? JSON.parse(map) : {}) : map); const scene: StandardScene = sceneData || {}; @@ -93,7 +94,11 @@ export class EditorService extends Meta2d { this.open(); this.setState(editable); - this.robotService.loadInitialData(robotGroups, robots, robotLabels); + if (isMerge) { + this.robotService.mergeRobotsData(robotGroups, robots, robotLabels); + } else { + this.robotService.loadInitialData(robotGroups, robots, robotLabels); + } await this.#loadScenePoints(points, isImport); this.#loadSceneRoutes(routes, isImport); await this.#loadSceneAreas(areas, isImport);