style: 将右键菜单渲染到顶层

将 WorkspaceConnectionList 组件中的连接右键菜单和标签右键菜单
通过 Vue 的 Teleport 功能直接渲染到 document.body
This commit is contained in:
Baobhan Sith
2025-05-26 19:37:32 +08:00
parent e68b11251a
commit 0c7b8d85f3
@@ -907,75 +907,79 @@ const cancelEditingTag = () => {
</div> </div>
<!-- Context Menu --> <!-- Context Menu -->
<div <teleport to="body">
v-if="contextMenuVisible" <div
class="fixed bg-background border border-border/50 shadow-xl rounded-lg py-1.5 z-50 min-w-[180px] context-menu" v-if="contextMenuVisible"
:style="{ top: `${contextMenuPosition.y}px`, left: `${contextMenuPosition.x}px` }" class="fixed bg-background border border-border/50 shadow-xl rounded-lg py-1.5 z-[9999] min-w-[180px] context-menu"
@click.stop :style="{ top: `${contextMenuPosition.y}px`, left: `${contextMenuPosition.x}px` }"
> @click.stop
<ul class="list-none p-0 m-0"> >
<li class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1" @click="handleMenuAction('add')"> <ul class="list-none p-0 m-0">
<i class="fas fa-plus mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i> <li class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1" @click="handleMenuAction('add')">
<span>{{ t('connections.addConnection') }}</span> <i class="fas fa-plus mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i>
</li> <span>{{ t('connections.addConnection') }}</span>
<li v-if="contextTargetConnection" class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1" @click="handleMenuAction('edit')"> </li>
<i class="fas fa-edit mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i> <li v-if="contextTargetConnection" class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1" @click="handleMenuAction('edit')">
<span>{{ t('connections.actions.edit') }}</span> <i class="fas fa-edit mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i>
</li> <span>{{ t('connections.actions.edit') }}</span>
<li v-if="contextTargetConnection" class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1" @click="handleMenuAction('clone')"> </li>
<i class="fas fa-clone mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i> <li v-if="contextTargetConnection" class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1" @click="handleMenuAction('clone')">
<span>{{ t('connections.actions.clone') }}</span> <i class="fas fa-clone mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i>
</li> <span>{{ t('connections.actions.clone') }}</span>
<li v-if="contextTargetConnection" class="group px-4 py-1.5 cursor-pointer flex items-center text-error hover:bg-error/10 text-sm transition-colors duration-150 rounded-md mx-1" @click="handleMenuAction('delete')"> </li>
<i class="fas fa-trash-alt mr-3 w-4 text-center text-error/80 group-hover:text-error"></i> <li v-if="contextTargetConnection" class="group px-4 py-1.5 cursor-pointer flex items-center text-error hover:bg-error/10 text-sm transition-colors duration-150 rounded-md mx-1" @click="handleMenuAction('delete')">
<span>{{ t('connections.actions.delete') }}</span> <i class="fas fa-trash-alt mr-3 w-4 text-center text-error/80 group-hover:text-error"></i>
</li> <span>{{ t('connections.actions.delete') }}</span>
</ul> </li>
</div> </ul>
</div>
</teleport>
<!-- 标签右键菜单 --> <!-- 标签右键菜单 -->
<div <teleport to="body">
v-if="tagContextMenuVisible" <div
class="fixed bg-background border border-border/50 shadow-xl rounded-lg py-1.5 z-50 min-w-[200px] tag-context-menu" v-if="tagContextMenuVisible"
:style="{ top: `${tagContextMenuPosition.y}px`, left: `${tagContextMenuPosition.x}px` }" class="fixed bg-background border border-border/50 shadow-xl rounded-lg py-1.5 z-[9999] min-w-[200px] tag-context-menu"
@click.stop :style="{ top: `${tagContextMenuPosition.y}px`, left: `${tagContextMenuPosition.x}px` }"
> @click.stop
<ul class="list-none p-0 m-0"> >
<li <ul class="list-none p-0 m-0">
v-if="contextTargetTagGroup && contextTargetTagGroup.connections.some((c: ConnectionInfo) => c.type === 'SSH')" <li
class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1" v-if="contextTargetTagGroup && contextTargetTagGroup.connections.some((c: ConnectionInfo) => c.type === 'SSH')"
@click="handleTagMenuAction('connectAll')" class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1"
> @click="handleTagMenuAction('connectAll')"
<i class="fas fa-network-wired mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i> >
<span>{{ t('workspaceConnectionList.connectAllSshInGroupMenu') }}</span> <i class="fas fa-network-wired mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i>
</li> <span>{{ t('workspaceConnectionList.connectAllSshInGroupMenu') }}</span>
<li </li>
v-else-if="contextTargetTagGroup" <li
class="group px-4 py-1.5 flex items-center text-text-disabled text-sm rounded-md mx-1 cursor-not-allowed" v-else-if="contextTargetTagGroup"
> class="group px-4 py-1.5 flex items-center text-text-disabled text-sm rounded-md mx-1 cursor-not-allowed"
<i class="fas fa-ban mr-3 w-4 text-center text-text-disabled"></i> >
<span>{{ t('workspaceConnectionList.noSshConnectionsToConnectMenu') }}</span> <i class="fas fa-ban mr-3 w-4 text-center text-text-disabled"></i>
</li> <span>{{ t('workspaceConnectionList.noSshConnectionsToConnectMenu') }}</span>
<li class="my-1 border-t border-border/50" v-if="contextTargetTagGroup && contextTargetTagGroup.tagId !== null"></li> </li>
<li <li class="my-1 border-t border-border/50" v-if="contextTargetTagGroup && contextTargetTagGroup.tagId !== null"></li>
v-if="contextTargetTagGroup && contextTargetTagGroup.tagId !== null" <li
class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1" v-if="contextTargetTagGroup && contextTargetTagGroup.tagId !== null"
@click="handleTagMenuAction('manageTag')" class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-primary/10 hover:text-primary text-sm transition-colors duration-150 rounded-md mx-1"
> @click="handleTagMenuAction('manageTag')"
<i class="fas fa-tags mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i> >
<span>{{ t('workspaceConnectionList.manageTags.menuItem') }}</span> <i class="fas fa-tags mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i>
</li> <span>{{ t('workspaceConnectionList.manageTags.menuItem') }}</span>
<li class="my-1 border-t border-border/50" v-if="contextTargetTagGroup && contextTargetTagGroup.tagId !== null && contextTargetTagGroup.connections.length > 0"></li> </li>
<li <li class="my-1 border-t border-border/50" v-if="contextTargetTagGroup && contextTargetTagGroup.tagId !== null && contextTargetTagGroup.connections.length > 0"></li>
v-if="contextTargetTagGroup && contextTargetTagGroup.tagId !== null && contextTargetTagGroup.connections.length > 0" <li
class="group px-4 py-1.5 cursor-pointer flex items-center text-error hover:bg-error/10 text-sm transition-colors duration-150 rounded-md mx-1" v-if="contextTargetTagGroup && contextTargetTagGroup.tagId !== null && contextTargetTagGroup.connections.length > 0"
@click="handleTagMenuAction('deleteAllConnections')" class="group px-4 py-1.5 cursor-pointer flex items-center text-error hover:bg-error/10 text-sm transition-colors duration-150 rounded-md mx-1"
> @click="handleTagMenuAction('deleteAllConnections')"
<i class="fas fa-trash-alt mr-3 w-4 text-center text-error/80 group-hover:text-error"></i> >
<span>{{ t('workspaceConnectionList.deleteAllConnectionsInGroupMenu') }}</span> <i class="fas fa-trash-alt mr-3 w-4 text-center text-error/80 group-hover:text-error"></i>
</li> <span>{{ t('workspaceConnectionList.deleteAllConnectionsInGroupMenu') }}</span>
</ul> </li>
</div> </ul>
</div>
</teleport>
<teleport to="body"> <teleport to="body">
<ManageTagConnectionsModal <ManageTagConnectionsModal