From a87909a73650d86992c9b2bd9dc9722a2c1f024f Mon Sep 17 00:00:00 2001 From: xudan Date: Fri, 26 Sep 2025 15:27:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=9C=BA=E5=99=A8?= =?UTF-8?q?=E4=BA=BA=E6=A0=87=E7=AD=BE=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=E5=92=8C=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E4=BB=A5=E6=94=AF=E6=8C=81=E6=9C=BA=E5=99=A8=E4=BA=BA?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E7=9A=84=E7=AE=A1=E7=90=86=E5=92=8C=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/robot/type.ts | 8 + src/apis/scene/type.ts | 4 +- src/components/modal/robot-add-modal.vue | 30 +- .../modal/robot-label-rename-modal.vue | 56 ++++ src/components/robot-groups.vue | 13 +- src/components/robot-labels.vue | 303 ++++++++++++++++++ src/pages/scene-editor.vue | 14 +- src/services/editor.service.ts | 122 ++++++- 8 files changed, 531 insertions(+), 19 deletions(-) create mode 100644 src/components/modal/robot-label-rename-modal.vue create mode 100644 src/components/robot-labels.vue diff --git a/src/apis/robot/type.ts b/src/apis/robot/type.ts index e3664cc..c559172 100644 --- a/src/apis/robot/type.ts +++ b/src/apis/robot/type.ts @@ -10,6 +10,13 @@ export interface RobotGroup { robots?: Array; // 机器人列表 } +export interface RobotLabel { + sid?: string; // 场景id + id: string; // 机器人标签id + label: string; // 机器人标签名称 + robots?: Array; // 机器人列表 +} + export type RobotPen = Pen & { robot: { type: RobotType; @@ -25,6 +32,7 @@ export type RobotPen = Pen & { }; export interface RobotInfo { gid?: string; // 机器人组id + lid?: string[]; // 机器人标签id id: string; // 机器人id label: string; // 机器人名称 brand: RobotBrand; // 机器人品牌 diff --git a/src/apis/scene/type.ts b/src/apis/scene/type.ts index 94da9f4..230b53c 100644 --- a/src/apis/scene/type.ts +++ b/src/apis/scene/type.ts @@ -1,4 +1,4 @@ -import type { RobotGroup, RobotInfo } from '@api/robot'; +import type { RobotGroup, RobotInfo, RobotLabel } from '@api/robot'; import type { Meta2dData } from '@meta2d/core'; import type { EditorColorConfig } from '../../services/color/color-config.service'; @@ -17,6 +17,7 @@ export interface GroupSceneDetail extends SceneDetail { export interface SceneData extends Meta2dData { robotGroups?: Array; // 机器人组信息 + robotLabels?: Array; // 机器人标签信息 robots?: Array; // 机器人信息 } @@ -24,6 +25,7 @@ export interface StandardScene { scale?: number; // 缩放比例 origin?: { x: number; y: number }; // 默认载入原点 robotGroups?: Array; // 机器人组信息 + robotLabels?: Array; // 机器人标签信息 robots?: Array; // 机器人信息 points?: Array; // 标准点位信息 routes?: Array; // 标准线路信息 diff --git a/src/components/modal/robot-add-modal.vue b/src/components/modal/robot-add-modal.vue index 81e7930..3308bcf 100644 --- a/src/components/modal/robot-add-modal.vue +++ b/src/components/modal/robot-add-modal.vue @@ -14,12 +14,23 @@ const editor = inject(props.token)!; export type RobotAddModalRef = Ref; type Ref = { - open: (gid: string) => void; + open: (id: string, type: 'group' | 'label') => void; }; -const open: Ref['open'] = async (id) => { - const res = await getAllRobots(); - robots.value = res.filter(({ id }) => isNil(editor.value.getRobotById(id))); - gid.value = id; +const open: Ref['open'] = async (id, t) => { + const allBackendRobots = await getAllRobots(); + targetId.value = id; + targetType.value = t; + + if (t === 'group') { + // 机器人组的逻辑:只显示尚未添加到场景中的机器人 + robots.value = allBackendRobots.filter(({ id }) => isNil(editor.value.getRobotById(id))); + } else { + // 机器人标签的逻辑:显示所有机器人,但排除已在该标签中的 + const label = editor.value.robotLabels.value?.find((l) => l.id === id); + const robotsInLabelIds = new Set(label?.robots ?? []); + robots.value = allBackendRobots.filter((robot) => !robotsInLabelIds.has(robot.id)); + } + keyword.value = ''; selected.value = []; show.value = true; @@ -28,7 +39,8 @@ defineExpose({ open }); const { t } = useI18n(); -const gid = ref(); +const targetId = ref(); +const targetType = ref<'group' | 'label'>(); const show = ref(false); const keyword = ref(''); @@ -41,7 +53,11 @@ const selected = ref([]); const submit = () => { try { const temp = selected.value.map((v) => robots.value.find(({ id }) => id === v)).filter((v) => !isNil(v)); - editor.value.addRobots(gid.value, temp); + if (targetType.value === 'group') { + editor.value.addRobots(targetId.value, temp); + } else { + editor.value.addRobotsToLabel(targetId.value!, temp); + } show.value = false; } catch (error) { if (isError(error)) { diff --git a/src/components/modal/robot-label-rename-modal.vue b/src/components/modal/robot-label-rename-modal.vue new file mode 100644 index 0000000..d592373 --- /dev/null +++ b/src/components/modal/robot-label-rename-modal.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/components/robot-groups.vue b/src/components/robot-groups.vue index 5890ca3..8efbf8a 100644 --- a/src/components/robot-groups.vue +++ b/src/components/robot-groups.vue @@ -45,7 +45,6 @@ const handleContextMenuClose = () => { //#endregion - const keyword = ref(''); //#region 机器人列表 @@ -93,12 +92,12 @@ const handleRobotRightClick = (event: MouseEvent, robot: RobotInfo) => { event.target.setAttribute('data-robot-id', robot.id); event.target.setAttribute('data-robot-type', 'robot'); } - + // 处理右键菜单 - handleContextMenu 内部会处理 preventDefault 和 stopPropagation handleContextMenu(event, contextMenuManager, { robotService: { - getRobotById: (id: string) => editor.value.getRobotById(id) - } + getRobotById: (id: string) => editor.value.getRobotById(id), + }, }); }; //#endregion @@ -153,7 +152,7 @@ const toRemoveRobots = () => - +