update
This commit is contained in:
@@ -387,7 +387,7 @@ const testButtonText = computed(() => {
|
||||
</form> <!-- End Form -->
|
||||
|
||||
<!-- Form Actions -->
|
||||
<div class="flex justify-between items-center pt-5 mt-6 border-t border-border flex-shrink-0">
|
||||
<div class="flex justify-between items-center pt-5 mt-6 flex-shrink-0">
|
||||
<div class="flex flex-col items-start gap-1"> <!-- Test Area -->
|
||||
<div class="flex items-center gap-2"> <!-- Button and Icon -->
|
||||
<button type="button" @click="handleTestConnection" :disabled="isLoading || testStatus === 'testing'"
|
||||
|
||||
@@ -1,33 +1,35 @@
|
||||
<template>
|
||||
<div class="fixed inset-0 bg-overlay flex justify-center items-center z-[1050]" @click.self="closeForm">
|
||||
<div class="bg-background text-foreground p-6 rounded-lg border border-border shadow-xl w-[90%] max-w-lg"> <!-- Changed bg-dialog to bg-background, text-dialog-text to text-foreground -->
|
||||
<h2 class="m-0 mb-6 text-center text-xl font-medium">{{ isEditing ? t('quickCommands.form.titleEdit', '编辑快捷指令') : t('quickCommands.form.titleAdd', '添加快捷指令') }}</h2>
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<div class="mb-4">
|
||||
<label for="qc-name" class="block mb-2 font-bold text-text-secondary text-sm">{{ t('quickCommands.form.name', '名称:') }}</label>
|
||||
<div class="bg-background text-foreground p-6 rounded-xl border border-border/50 shadow-2xl w-[90%] max-w-lg">
|
||||
<h2 class="m-0 mb-6 text-center text-xl font-semibold">{{ isEditing ? t('quickCommands.form.titleEdit', '编辑快捷指令') : t('quickCommands.form.titleAdd', '添加快捷指令') }}</h2>
|
||||
<form @submit.prevent="handleSubmit" class="space-y-5">
|
||||
<div>
|
||||
<label for="qc-name" class="block mb-1.5 text-sm font-medium text-text-secondary">{{ t('quickCommands.form.name', '名称:') }}</label>
|
||||
<input
|
||||
id="qc-name"
|
||||
type="text"
|
||||
v-model="formData.name"
|
||||
:placeholder="t('quickCommands.form.namePlaceholder', '可选,用于快速识别')"
|
||||
class="w-full px-3 py-2 border border-border rounded bg-input text-foreground text-base focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-colors duration-150"
|
||||
class="w-full px-4 py-2 border border-border/50 rounded-lg bg-input text-foreground text-sm shadow-sm focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary transition duration-150 ease-in-out"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="qc-command" class="block mb-2 font-bold text-text-secondary text-sm">{{ t('quickCommands.form.command', '指令:') }} <span class="text-error">*</span></label>
|
||||
<div>
|
||||
<label for="qc-command" class="block mb-1.5 text-sm font-medium text-text-secondary">{{ t('quickCommands.form.command', '指令:') }} <span class="text-error">*</span></label>
|
||||
<textarea
|
||||
id="qc-command"
|
||||
v-model="formData.command"
|
||||
required
|
||||
rows="3"
|
||||
rows="4"
|
||||
:placeholder="t('quickCommands.form.commandPlaceholder', '例如:ls -alh /home/user')"
|
||||
class="w-full px-3 py-2 border border-border rounded bg-input text-foreground text-base resize-vertical min-h-[80px] focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-colors duration-150"
|
||||
class="w-full px-4 py-2 border border-border/50 rounded-lg bg-input text-foreground text-sm resize-y min-h-[100px] shadow-sm focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary transition duration-150 ease-in-out"
|
||||
></textarea>
|
||||
<small v-if="commandError" class="text-error text-xs mt-1 block">{{ commandError }}</small>
|
||||
</div>
|
||||
<div class="flex justify-end mt-6 pt-2 border-t border-border">
|
||||
<button type="button" @click="closeForm" class="py-2 px-4 rounded text-sm transition-colors duration-150 bg-button text-button-text hover:bg-button-hover border border-border mr-2">{{ t('common.cancel', '取消') }}</button>
|
||||
<button type="submit" :disabled="isSubmitting || !!commandError" class="py-2 px-4 rounded text-sm transition-colors duration-150 bg-primary text-white hover:bg-primary-dark disabled:bg-gray-400 disabled:opacity-70 disabled:cursor-not-allowed">
|
||||
<div class="flex justify-end mt-8 pt-4 border-t border-border/50">
|
||||
<!-- Secondary/Cancel Button -->
|
||||
<button type="button" @click="closeForm" class="py-2 px-5 rounded-lg text-sm font-medium transition-colors duration-150 bg-background border border-border/50 text-text-secondary hover:bg-border hover:text-foreground mr-3">{{ t('common.cancel', '取消') }}</button>
|
||||
<!-- Primary/Submit Button -->
|
||||
<button type="submit" :disabled="isSubmitting || !!commandError" class="py-2 px-5 rounded-lg text-sm font-semibold transition-colors duration-150 bg-primary text-white border-none shadow-md hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary disabled:bg-gray-400 disabled:opacity-70 disabled:cursor-not-allowed">
|
||||
{{ isSubmitting ? t('common.saving', '保存中...') : (isEditing ? t('common.save', '保存') : t('quickCommands.form.add', '添加')) }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -221,26 +221,25 @@ onBeforeUnmount(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center px-2.5 py-1.5 bg-background min-h-[30px] gap-1.5">
|
||||
<div class="flex-grow flex items-center bg-transparent relative gap-1.5">
|
||||
<div class="flex items-center px-2 py-1.5 bg-background gap-2"> <!-- Removed border-t and border-border/50 -->
|
||||
<div class="flex-grow flex items-center bg-transparent relative gap-2"> <!-- Adjusted gap -->
|
||||
<!-- Focus Switcher Config Button -->
|
||||
<button
|
||||
@click="focusSwitcherStore.toggleConfigurator(true)"
|
||||
class="flex-shrink-0 flex items-center justify-center w-7 h-7 text-text-secondary rounded transition-colors duration-200 hover:bg-black/10 hover:text-foreground"
|
||||
class="flex-shrink-0 flex items-center justify-center w-8 h-8 border border-border/50 rounded-lg text-text-secondary transition-colors duration-200 hover:bg-border hover:text-foreground"
|
||||
:title="t('commandInputBar.configureFocusSwitch', '配置焦点切换')"
|
||||
>
|
||||
<i class="fas fa-keyboard text-base text-primary transition-colors duration-200"></i>
|
||||
<i class="fas fa-keyboard text-base"></i> <!-- Removed text-primary -->
|
||||
</button>
|
||||
<!-- Command Input -->
|
||||
<input
|
||||
type="text"
|
||||
v-model="commandInput"
|
||||
:placeholder="t('commandInputBar.placeholder')"
|
||||
class="flex-grow px-2.5 py-1.5 border border-border rounded text-sm bg-input text-foreground outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-all duration-300 ease-in-out"
|
||||
class="flex-grow min-w-0 px-4 py-1.5 border border-border/50 rounded-lg bg-input text-foreground text-sm shadow-sm focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary transition-all duration-300 ease-in-out"
|
||||
:class="{ 'basis-3/4': isSearching, 'basis-full': !isSearching }"
|
||||
ref="commandInputRef"
|
||||
data-focus-id="commandInput"
|
||||
|
||||
@keydown="handleCommandInputKeydown"
|
||||
@blur="handleCommandInputBlur"
|
||||
/>
|
||||
@@ -251,7 +250,7 @@ onBeforeUnmount(() => {
|
||||
type="text"
|
||||
v-model="searchTerm"
|
||||
:placeholder="t('commandInputBar.searchPlaceholder')"
|
||||
class="flex-grow px-2.5 py-1.5 border border-border rounded text-sm bg-input text-foreground outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-all duration-300 ease-in-out basis-1/4 ml-1.5"
|
||||
class="flex-grow min-w-0 px-4 py-1.5 border border-border/50 rounded-lg bg-input text-foreground text-sm shadow-sm focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary transition-all duration-300 ease-in-out basis-1/4"
|
||||
data-focus-id="terminalSearch"
|
||||
@keydown.enter.prevent="findNext"
|
||||
@keydown.shift.enter.prevent="findPrevious"
|
||||
@@ -261,30 +260,30 @@ onBeforeUnmount(() => {
|
||||
/>
|
||||
|
||||
<!-- Search Controls -->
|
||||
<div class="flex items-center gap-1 flex-shrink-0">
|
||||
<div class="flex items-center gap-1 flex-shrink-0"> <!-- Adjusted gap -->
|
||||
<button
|
||||
@click="toggleSearch"
|
||||
class="flex items-center justify-center w-7 h-7 text-text-secondary rounded transition-colors duration-200 hover:bg-black/10 hover:text-foreground"
|
||||
class="flex items-center justify-center w-8 h-8 border border-border/50 rounded-lg text-text-secondary transition-colors duration-200 hover:bg-border hover:text-foreground"
|
||||
:title="isSearching ? t('commandInputBar.closeSearch') : t('commandInputBar.openSearch')"
|
||||
>
|
||||
<i v-if="!isSearching" class="fas fa-search text-base text-primary transition-colors duration-200"></i>
|
||||
<i v-else class="fas fa-times text-base text-primary transition-colors duration-200"></i>
|
||||
<i v-if="!isSearching" class="fas fa-search text-base"></i>
|
||||
<i v-else class="fas fa-times text-base"></i>
|
||||
</button>
|
||||
|
||||
<template v-if="isSearching">
|
||||
<button
|
||||
@click="findPrevious"
|
||||
class="flex items-center justify-center w-7 h-7 text-text-secondary rounded transition-colors duration-200 hover:bg-black/10 hover:text-foreground"
|
||||
class="flex items-center justify-center w-8 h-8 border border-border/50 rounded-lg text-text-secondary transition-colors duration-200 hover:bg-border hover:text-foreground"
|
||||
:title="t('commandInputBar.findPrevious')"
|
||||
>
|
||||
<i class="fas fa-arrow-up text-base text-primary transition-colors duration-200"></i>
|
||||
<i class="fas fa-arrow-up text-base"></i>
|
||||
</button>
|
||||
<button
|
||||
@click="findNext"
|
||||
class="flex items-center justify-center w-7 h-7 text-text-secondary rounded transition-colors duration-200 hover:bg-black/10 hover:text-foreground"
|
||||
class="flex items-center justify-center w-8 h-8 border border-border/50 rounded-lg text-text-secondary transition-colors duration-200 hover:bg-border hover:text-foreground"
|
||||
:title="t('commandInputBar.findNext')"
|
||||
>
|
||||
<i class="fas fa-arrow-down text-base text-primary transition-colors duration-200"></i>
|
||||
<i class="fas fa-arrow-down text-base"></i>
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -910,7 +910,7 @@ defineExpose({ focusSearchInput, startPathEdit });
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col h-full overflow-hidden bg-background text-foreground text-sm font-sans">
|
||||
<div class="flex items-center justify-between flex-wrap gap-2 p-2 bg-header border-b border-border flex-shrink-0">
|
||||
<div class="flex items-center justify-between flex-wrap gap-2 p-2 bg-header flex-shrink-0">
|
||||
<!-- Path Bar -->
|
||||
<div class="flex items-center bg-background border border-border rounded px-1.5 py-0.5 overflow-hidden min-w-[100px] flex-shrink">
|
||||
<span v-show="!isEditingPath" class="text-text-secondary whitespace-nowrap overflow-x-auto pr-2">
|
||||
@@ -1045,7 +1045,7 @@ defineExpose({ focusSearchInput, startPathEdit });
|
||||
</div>
|
||||
|
||||
<!-- File Table -->
|
||||
<table ref="tableRef" class="w-full border-collapse table-fixed border border-border rounded" @contextmenu.prevent>
|
||||
<table ref="tableRef" class="w-full border-collapse table-fixed border-border rounded" @contextmenu.prevent>
|
||||
<colgroup>
|
||||
<col :style="{ width: `${colWidths.type}px` }">
|
||||
<col :style="{ width: `${colWidths.name}px` }">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<!-- Root element with padding, background, border, and text styles -->
|
||||
<div class="status-monitor p-4 border-l border-border bg-background text-foreground h-full overflow-y-auto text-sm">
|
||||
<div class="status-monitor p-4 bg-background text-foreground h-full overflow-y-auto text-sm">
|
||||
<!-- Title with margin, border, padding, font size, and color -->
|
||||
<h4 class="mt-0 mb-4 border-b border-border pb-2 text-base font-medium">
|
||||
{{ t('statusMonitor.title') }}
|
||||
|
||||
@@ -301,96 +301,109 @@ const scrollToHighlighted = async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full flex flex-col overflow-hidden bg-background text-sm text-foreground">
|
||||
<div v-if="connectionsLoading || tagsLoading" class="p-4 text-center text-text-secondary">
|
||||
{{ t('common.loading') }}
|
||||
<div class="h-full flex flex-col overflow-hidden bg-background text-foreground">
|
||||
<!-- Loading / Error State -->
|
||||
<div v-if="connectionsLoading || tagsLoading" class="flex items-center justify-center h-full text-text-secondary">
|
||||
<i class="fas fa-spinner fa-spin mr-2"></i> {{ t('common.loading') }}
|
||||
</div>
|
||||
<div v-else-if="connectionsError || tagsError" class="p-4 text-center text-red-600">
|
||||
{{ connectionsError || tagsError }}
|
||||
<div v-else-if="connectionsError || tagsError" class="flex items-center justify-center h-full text-error px-4 text-center">
|
||||
<i class="fas fa-exclamation-triangle mr-2"></i> {{ connectionsError || tagsError }}
|
||||
</div>
|
||||
|
||||
<!-- 搜索和添加栏 -->
|
||||
<div class="flex p-2 border-b border-border bg-header">
|
||||
<input
|
||||
type="text"
|
||||
v-model="searchTerm"
|
||||
:placeholder="t('workspaceConnectionList.searchPlaceholder')"
|
||||
ref="searchInputRef"
|
||||
class="flex-grow min-w-0 px-3 py-1.5 border border-border rounded-l-md text-sm outline-none bg-background text-foreground focus:border-primary focus:ring-2 focus:ring-primary focus:ring-opacity-50 transition-colors duration-150"
|
||||
data-focus-id="connectionListSearch"
|
||||
@keydown="handleKeyDown"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
<button
|
||||
class="px-3 py-1.5 border border-border border-l-0 bg-background cursor-pointer rounded-r-md text-text-secondary hover:bg-border hover:text-foreground transition-colors duration-150"
|
||||
@click="handleMenuAction('add')"
|
||||
:title="t('connections.addConnection')"
|
||||
>
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Main Content Area -->
|
||||
<div v-else class="flex flex-col h-full">
|
||||
<!-- Search and Add Bar -->
|
||||
<div class="flex p-2 border-b border-border/50"> <!-- Reduced padding p-3 to p-2 -->
|
||||
<input
|
||||
type="text"
|
||||
v-model="searchTerm"
|
||||
:placeholder="t('workspaceConnectionList.searchPlaceholder')"
|
||||
ref="searchInputRef"
|
||||
class="flex-grow min-w-0 px-4 py-1.5 border border-border/50 rounded-lg bg-input text-foreground text-sm shadow-sm focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary transition duration-150 ease-in-out"
|
||||
data-focus-id="connectionListSearch"
|
||||
@keydown="handleKeyDown"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
<button
|
||||
class="ml-2 w-8 h-8 bg-primary text-white border-none rounded-lg text-sm font-semibold cursor-pointer shadow-md transition-colors duration-200 ease-in-out hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary disabled:bg-gray-400 disabled:cursor-not-allowed disabled:opacity-70 flex-shrink-0 flex items-center justify-center"
|
||||
@click="handleMenuAction('add')"
|
||||
:title="t('connections.addConnection')"
|
||||
>
|
||||
<i class="fas fa-plus text-white"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 连接列表区域 -->
|
||||
<div class="flex-grow overflow-y-auto" ref="listAreaRef">
|
||||
<div v-if="connectionsLoading || tagsLoading" class="p-4 text-center text-text-secondary">
|
||||
{{ t('common.loading') }}
|
||||
</div>
|
||||
<div v-else-if="connectionsError || tagsError" class="p-4 text-center text-red-600">
|
||||
{{ connectionsError || tagsError }}
|
||||
</div>
|
||||
<div v-else-if="filteredAndGroupedConnections.length === 0 && connections.length > 0" class="p-4 text-center text-text-secondary">
|
||||
{{ t('workspaceConnectionList.noResults') }} "{{ searchTerm }}"
|
||||
</div>
|
||||
<div v-else-if="connections.length === 0" class="p-4 text-center text-text-secondary">
|
||||
{{ t('connections.noConnections') }}
|
||||
</div>
|
||||
<div v-else>
|
||||
<!-- 循环分组 -->
|
||||
<div v-for="groupData in filteredAndGroupedConnections" :key="groupData.groupName" class="mb-0 last:mb-0">
|
||||
<div class="group px-3 py-2 font-semibold cursor-pointer bg-header border-t border-b border-border flex items-center text-foreground hover:bg-border transition-colors duration-150" @click="toggleGroup(groupData.groupName)">
|
||||
<i :class="['fas', expandedGroups[groupData.groupName] ? 'fa-chevron-down' : 'fa-chevron-right', 'mr-2 w-4 text-center text-text-secondary group-hover:text-foreground transition-transform duration-200 ease-in-out']"></i>
|
||||
<span>{{ groupData.groupName }}</span>
|
||||
</div>
|
||||
<!-- 连接项列表 -->
|
||||
<ul v-show="expandedGroups[groupData.groupName]" class="list-none p-0 m-0">
|
||||
<li
|
||||
v-for="conn in groupData.connections"
|
||||
:key="conn.id"
|
||||
class="group py-2 pr-4 pl-6 cursor-pointer flex items-center border-b border-border whitespace-nowrap overflow-hidden text-ellipsis text-foreground hover:bg-header/50 transition-colors duration-150"
|
||||
:class="{ 'bg-primary/10 text-primary': conn.id === highlightedConnectionId }"
|
||||
:data-conn-id="conn.id"
|
||||
@click.left="handleConnect(conn.id)"
|
||||
@contextmenu.prevent="showContextMenu($event, conn)"
|
||||
<!-- Connection List Area -->
|
||||
<div class="flex-grow overflow-y-auto p-2" ref="listAreaRef">
|
||||
<!-- No Results / No Connections State -->
|
||||
<div v-if="filteredAndGroupedConnections.length === 0 && connections.length > 0" class="p-6 text-center text-text-secondary">
|
||||
<i class="fas fa-search text-xl mb-2"></i>
|
||||
<p>{{ t('workspaceConnectionList.noResults') }} "{{ searchTerm }}"</p>
|
||||
</div>
|
||||
<div v-else-if="connections.length === 0" class="p-6 text-center text-text-secondary">
|
||||
<i class="fas fa-plug text-xl mb-2"></i>
|
||||
<p>{{ t('connections.noConnections') }}</p>
|
||||
<button
|
||||
class="mt-4 px-4 py-2 bg-primary text-white border-none rounded-lg text-sm font-semibold cursor-pointer shadow-md transition-colors duration-200 ease-in-out hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary"
|
||||
@click="handleMenuAction('add')"
|
||||
>
|
||||
{{ t('connections.addFirstConnection') }} <!-- Need translation -->
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Groups and Connections -->
|
||||
<div v-else>
|
||||
<div v-for="groupData in filteredAndGroupedConnections" :key="groupData.groupName" class="mb-1 last:mb-0">
|
||||
<!-- Group Header -->
|
||||
<div
|
||||
class="group px-3 py-2 font-semibold cursor-pointer flex items-center text-foreground rounded-md hover:bg-header/80 transition-colors duration-150"
|
||||
@click="toggleGroup(groupData.groupName)"
|
||||
>
|
||||
<i class="fas fa-server mr-2.5 w-4 text-center text-text-secondary group-hover:text-foreground" :class="{ 'text-primary': conn.id === highlightedConnectionId }"></i>
|
||||
<span class="overflow-hidden text-ellipsis whitespace-nowrap flex-grow" :title="conn.name || conn.host">
|
||||
{{ conn.name || conn.host }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<i :class="['fas', expandedGroups[groupData.groupName] ? 'fa-chevron-down' : 'fa-chevron-right', 'mr-2 w-4 text-center text-text-secondary group-hover:text-foreground transition-transform duration-200 ease-in-out', {'transform rotate-0': !expandedGroups[groupData.groupName]}]"></i>
|
||||
<span class="text-sm">{{ groupData.groupName }}</span>
|
||||
</div>
|
||||
<!-- Connection Items List -->
|
||||
<ul v-show="expandedGroups[groupData.groupName]" class="list-none p-0 m-0 pl-3">
|
||||
<li
|
||||
v-for="conn in groupData.connections"
|
||||
:key="conn.id"
|
||||
class="group my-0.5 py-2 pr-3 pl-4 cursor-pointer flex items-center rounded-md whitespace-nowrap overflow-hidden text-ellipsis text-foreground hover:bg-primary/10 transition-colors duration-150"
|
||||
:class="{ 'bg-primary/20 text-white font-medium': conn.id === highlightedConnectionId }"
|
||||
:data-conn-id="conn.id"
|
||||
@click.left="handleConnect(conn.id)"
|
||||
@contextmenu.prevent="showContextMenu($event, conn)"
|
||||
@mousedown.middle.prevent="handleOpenInNewTab(conn.id)"
|
||||
@auxclick.prevent="handleOpenInNewTab(conn.id)"
|
||||
>
|
||||
<i class="fas fa-server mr-2.5 w-4 text-center text-text-secondary group-hover:text-primary" :class="{ 'text-white': conn.id === highlightedConnectionId }"></i>
|
||||
<span class="overflow-hidden text-ellipsis whitespace-nowrap flex-grow text-sm" :title="conn.name || conn.host">
|
||||
{{ conn.name || conn.host }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右键菜单 -->
|
||||
<!-- Context Menu -->
|
||||
<div
|
||||
v-if="contextMenuVisible"
|
||||
class="fixed bg-background border border-border shadow-lg rounded-md py-1 z-50 min-w-[160px]"
|
||||
class="fixed bg-background border border-border/50 shadow-xl rounded-lg py-1.5 z-50 min-w-[180px]"
|
||||
: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-header text-sm transition-colors duration-150" @click="handleMenuAction('add')">
|
||||
<i class="fas fa-plus mr-3 w-4 text-center text-text-secondary group-hover:text-foreground"></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')">
|
||||
<i class="fas fa-plus mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i>
|
||||
<span>{{ t('connections.addConnection') }}</span>
|
||||
</li>
|
||||
<li v-if="contextTargetConnection" class="group px-4 py-1.5 cursor-pointer flex items-center text-foreground hover:bg-header text-sm transition-colors duration-150" @click="handleMenuAction('edit')">
|
||||
<i class="fas fa-edit mr-3 w-4 text-center text-text-secondary group-hover:text-foreground"></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')">
|
||||
<i class="fas fa-edit mr-3 w-4 text-center text-text-secondary group-hover:text-primary"></i>
|
||||
<span>{{ t('connections.actions.edit') }}</span>
|
||||
</li>
|
||||
<li v-if="contextTargetConnection" class="group px-4 py-1.5 cursor-pointer flex items-center text-red-600 hover:bg-red-500/10 text-sm transition-colors duration-150" @click="handleMenuAction('delete')">
|
||||
<i class="fas fa-trash-alt mr-3 w-4 text-center text-red-500 group-hover:text-red-600"></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')">
|
||||
<i class="fas fa-trash-alt mr-3 w-4 text-center text-error/80 group-hover:text-error"></i>
|
||||
<span>{{ t('connections.actions.delete') }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user