diff --git a/packages/frontend/src/components/WorkspaceConnectionList.vue b/packages/frontend/src/components/WorkspaceConnectionList.vue index 67af31e..a769e31 100644 --- a/packages/frontend/src/components/WorkspaceConnectionList.vue +++ b/packages/frontend/src/components/WorkspaceConnectionList.vue @@ -324,17 +324,50 @@ const handleConnect = (connectionId: number, event?: MouseEvent | KeyboardEvent) // 显示右键菜单 const showContextMenu = (event: MouseEvent, connection: ConnectionInfo) => { - console.log(`[WkspConnList] showContextMenu (右键) called for ID: ${connection.id}. Event:`, event); - event.preventDefault(); // 再次确保阻止默认行为 - event.stopPropagation(); // 阻止事件冒泡 - event.stopImmediatePropagation(); // 尝试更强力地阻止事件链 - console.log('[WkspConnList] Right-click default prevented and propagation stopped.'); - contextTargetConnection.value = connection; - contextMenuPosition.value = { x: event.clientX, y: event.clientY }; - contextMenuVisible.value = true; - // 添加全局点击监听器以关闭菜单 - document.addEventListener('click', closeContextMenu, { once: true }); - return false; // 彻底停止事件处理 +console.log(`[WkspConnList] showContextMenu (右键) called for ID: ${connection.id}. Event:`, event); +event.preventDefault(); // 再次确保阻止默认行为 +event.stopPropagation(); // 阻止事件冒泡 +event.stopImmediatePropagation(); // 尝试更强力地阻止事件链 +console.log('[WkspConnList] Right-click default prevented and propagation stopped.'); +contextTargetConnection.value = connection; +contextMenuPosition.value = { x: event.clientX, y: event.clientY }; +contextMenuVisible.value = true; +// 添加全局点击监听器以关闭菜单 +document.addEventListener('click', closeContextMenu, { once: true }); + +// 使用 nextTick 获取菜单尺寸并调整位置以防止超出屏幕 +nextTick(() => { + const menuElement = document.querySelector('.context-menu') as HTMLElement; + if (menuElement) { + const menuRect = menuElement.getBoundingClientRect(); + let finalX = contextMenuPosition.value.x; + let finalY = contextMenuPosition.value.y; + const menuWidth = menuRect.width; + const menuHeight = menuRect.height; + + // 调整水平位置 + if (finalX + menuWidth > window.innerWidth) { + finalX = window.innerWidth - menuWidth - 5; + } + + // 调整垂直位置 + if (finalY + menuHeight > window.innerHeight) { + finalY = window.innerHeight - menuHeight - 5; + } + + // 确保菜单不超出屏幕左上角 + finalX = Math.max(5, finalX); + finalY = Math.max(5, finalY); + + // 更新位置 + if (finalX !== contextMenuPosition.value.x || finalY !== contextMenuPosition.value.y) { + console.log(`[WkspConnList] Adjusting context menu position: (${contextMenuPosition.value.x}, ${contextMenuPosition.value.y}) -> (${finalX}, ${finalY})`); + contextMenuPosition.value = { x: finalX, y: finalY }; + } + } +}); + +return false; // 彻底停止事件处理 }; // 关闭右键菜单 @@ -392,14 +425,46 @@ const handleMenuAction = (action: 'add' | 'edit' | 'delete' | 'clone') => { // // 显示标签右键菜单 const showTagContextMenu = (event: MouseEvent, groupData: (typeof filteredAndGroupedConnections.value)[0]) => { - event.preventDefault(); - event.stopPropagation(); // 阻止事件冒泡到上层,例如关闭连接右键菜单的 document click listener - closeContextMenu(); // 如果连接的右键菜单是打开的,先关闭它 - contextTargetTagGroup.value = groupData; - tagContextMenuPosition.value = { x: event.clientX, y: event.clientY }; - tagContextMenuVisible.value = true; - // 添加全局点击监听器以关闭菜单 - document.addEventListener('click', closeTagContextMenu, { once: true }); +event.preventDefault(); +event.stopPropagation(); // 阻止事件冒泡到上层,例如关闭连接右键菜单的 document click listener +closeContextMenu(); // 如果连接的右键菜单是打开的,先关闭它 +contextTargetTagGroup.value = groupData; +tagContextMenuPosition.value = { x: event.clientX, y: event.clientY }; +tagContextMenuVisible.value = true; +// 添加全局点击监听器以关闭菜单 +document.addEventListener('click', closeTagContextMenu, { once: true }); + +// 使用 nextTick 获取菜单尺寸并调整位置以防止超出屏幕 +nextTick(() => { + const menuElement = document.querySelector('.tag-context-menu') as HTMLElement; + if (menuElement) { + const menuRect = menuElement.getBoundingClientRect(); + let finalX = tagContextMenuPosition.value.x; + let finalY = tagContextMenuPosition.value.y; + const menuWidth = menuRect.width; + const menuHeight = menuRect.height; + + // 调整水平位置 + if (finalX + menuWidth > window.innerWidth) { + finalX = window.innerWidth - menuWidth - 5; + } + + // 调整垂直位置 + if (finalY + menuHeight > window.innerHeight) { + finalY = window.innerHeight - menuHeight - 5; + } + + // 确保菜单不超出屏幕左上角 + finalX = Math.max(5, finalX); + finalY = Math.max(5, finalY); + + // 更新位置 + if (finalX !== tagContextMenuPosition.value.x || finalY !== tagContextMenuPosition.value.y) { + console.log(`[WkspConnList] Adjusting tag context menu position: (${tagContextMenuPosition.value.x}, ${tagContextMenuPosition.value.y}) -> (${finalX}, ${finalY})`); + tagContextMenuPosition.value = { x: finalX, y: finalY }; + } + } +}); }; // 关闭标签右键菜单 @@ -844,7 +909,7 @@ const cancelEditingTag = () => {
@@ -871,7 +936,7 @@ const cancelEditingTag = () => {
diff --git a/packages/frontend/src/views/CommandHistoryView.vue b/packages/frontend/src/views/CommandHistoryView.vue index d05b566..3073566 100644 --- a/packages/frontend/src/views/CommandHistoryView.vue +++ b/packages/frontend/src/views/CommandHistoryView.vue @@ -64,7 +64,7 @@
@@ -249,11 +249,43 @@ defineExpose({ focusSearchInput }); // +++ 右键菜单方法 +++ const showCommandHistoryContextMenu = (event: MouseEvent, entry: CommandHistoryEntryFE) => { - event.preventDefault(); - commandHistoryContextTargetEntry.value = entry; - commandHistoryContextMenuPosition.value = { x: event.clientX, y: event.clientY }; - commandHistoryContextMenuVisible.value = true; - document.addEventListener('click', closeCommandHistoryContextMenu, { once: true }); +event.preventDefault(); +commandHistoryContextTargetEntry.value = entry; +commandHistoryContextMenuPosition.value = { x: event.clientX, y: event.clientY }; +commandHistoryContextMenuVisible.value = true; +document.addEventListener('click', closeCommandHistoryContextMenu, { once: true }); + +// 使用 nextTick 获取菜单尺寸并调整位置以防止超出屏幕 +nextTick(() => { + const menuElement = document.querySelector('.command-history-context-menu') as HTMLElement; + if (menuElement) { + const menuRect = menuElement.getBoundingClientRect(); + let finalX = commandHistoryContextMenuPosition.value.x; + let finalY = commandHistoryContextMenuPosition.value.y; + const menuWidth = menuRect.width; + const menuHeight = menuRect.height; + + // 调整水平位置 + if (finalX + menuWidth > window.innerWidth) { + finalX = window.innerWidth - menuWidth - 5; + } + + // 调整垂直位置 + if (finalY + menuHeight > window.innerHeight) { + finalY = window.innerHeight - menuHeight - 5; + } + + // 确保菜单不超出屏幕左上角 + finalX = Math.max(5, finalX); + finalY = Math.max(5, finalY); + + // 更新位置 + if (finalX !== commandHistoryContextMenuPosition.value.x || finalY !== commandHistoryContextMenuPosition.value.y) { + console.log(`[CommandHistoryView] Adjusting command history context menu position: (${commandHistoryContextMenuPosition.value.x}, ${commandHistoryContextMenuPosition.value.y}) -> (${finalX}, ${finalY})`); + commandHistoryContextMenuPosition.value = { x: finalX, y: finalY }; + } + } +}); }; const closeCommandHistoryContextMenu = () => { diff --git a/packages/frontend/src/views/QuickCommandsView.vue b/packages/frontend/src/views/QuickCommandsView.vue index b05f53c..a9bafb1 100644 --- a/packages/frontend/src/views/QuickCommandsView.vue +++ b/packages/frontend/src/views/QuickCommandsView.vue @@ -159,7 +159,7 @@
@@ -556,11 +556,43 @@ const cancelEditingTag = () => { // +++ 右键菜单方法 +++ const showQuickCommandContextMenu = (event: MouseEvent, command: QuickCommandFE) => { - event.preventDefault(); - quickCommandContextTargetCommand.value = command; - quickCommandContextMenuPosition.value = { x: event.clientX, y: event.clientY }; - quickCommandContextMenuVisible.value = true; - document.addEventListener('click', closeQuickCommandContextMenu, { once: true }); +event.preventDefault(); +quickCommandContextTargetCommand.value = command; +quickCommandContextMenuPosition.value = { x: event.clientX, y: event.clientY }; +quickCommandContextMenuVisible.value = true; +document.addEventListener('click', closeQuickCommandContextMenu, { once: true }); + +// 使用 nextTick 获取菜单尺寸并调整位置以防止超出屏幕 +nextTick(() => { + const menuElement = document.querySelector('.quick-command-context-menu') as HTMLElement; + if (menuElement) { + const menuRect = menuElement.getBoundingClientRect(); + let finalX = quickCommandContextMenuPosition.value.x; + let finalY = quickCommandContextMenuPosition.value.y; + const menuWidth = menuRect.width; + const menuHeight = menuRect.height; + + // 调整水平位置 + if (finalX + menuWidth > window.innerWidth) { + finalX = window.innerWidth - menuWidth - 5; + } + + // 调整垂直位置 + if (finalY + menuHeight > window.innerHeight) { + finalY = window.innerHeight - menuHeight - 5; + } + + // 确保菜单不超出屏幕左上角 + finalX = Math.max(5, finalX); + finalY = Math.max(5, finalY); + + // 更新位置 + if (finalX !== quickCommandContextMenuPosition.value.x || finalY !== quickCommandContextMenuPosition.value.y) { + console.log(`[QuickCmdView] Adjusting quick command context menu position: (${quickCommandContextMenuPosition.value.x}, ${quickCommandContextMenuPosition.value.y}) -> (${finalX}, ${finalY})`); + quickCommandContextMenuPosition.value = { x: finalX, y: finalY }; + } + } +}); }; const closeQuickCommandContextMenu = () => {