feat: 优化样式

This commit is contained in:
Baobhan Sith
2025-05-10 09:56:38 +08:00
parent 05747a46e1
commit bdaea68d20
6 changed files with 94 additions and 7 deletions
@@ -283,7 +283,7 @@ const localAvailableInputs = computed(() => {
<section class="p-4 border border-border rounded bg-input flex flex-col overflow-y-auto max-h-64 flex-shrink-0"> <section class="p-4 border border-border rounded bg-input flex flex-col overflow-y-auto max-h-64 flex-shrink-0">
<h3 class="mt-0 mb-4 text-base font-semibold text-text-secondary border-b border-border-light pb-2">{{ t('focusSwitcher.shortcutSettings', '快捷键设置') }}</h3> <h3 class="mt-0 mb-4 text-base font-semibold text-text-secondary border-b border-border-light pb-2">{{ t('focusSwitcher.shortcutSettings', '快捷键设置') }}</h3>
<div class="grid grid-cols-[repeat(auto-fill,minmax(280px,1fr))] gap-3"> <div class="grid grid-cols-[repeat(auto-fill,minmax(280px,1fr))] gap-3">
<div v-for="input in focusSwitcherStore.availableInputs" :key="input.id" class="flex items-center justify-between bg-input p-2 rounded border border-border-light"> <div v-for="input in focusSwitcherStore.availableInputs" :key="input.id" class="flex items-center justify-between bg-input p-2 rounded border border-border/50">
<span class="item-label flex-grow mr-3 overflow-hidden text-ellipsis whitespace-nowrap text-sm">{{ input.label }}</span> <span class="item-label flex-grow mr-3 overflow-hidden text-ellipsis whitespace-nowrap text-sm">{{ input.label }}</span>
<input <input
type="text" type="text"
+26
View File
@@ -1197,5 +1197,31 @@
"time": { "time": {
"unknown": "Unknown time", "unknown": "Unknown time",
"invalidDate": "Invalid date" "invalidDate": "Invalid date"
},
"sshSuspend": {
"notifications": {
"markedForSuspendInfo": "Session {id} marked for suspend. It will be suspended when the tab is closed or the application exits.",
"wsNotConnectedError": "WebSocket not connected. Cannot perform suspend/resume action.",
"sessionNotFoundError": "Session not found or WebSocket manager unavailable.",
"notMarkedWarning": "Session was not marked for suspend.",
"fetchListError": "Failed to fetch suspended sessions list: {error}",
"resumeErrorInfoNotFound": "Resume error: Suspended session {id} not found in the list.",
"resumeErrorConnectionConfigNotFound": "Resume error: Original connection configuration for {id} not found.",
"resumeErrorGeneric": "Failed to resume session: {error}",
"terminatedSuccess": "Suspended session \"{name}\" terminated successfully.",
"terminateError": "Failed to terminate suspended session: {error}",
"entryRemovedSuccess": "Suspended session entry \"{name}\" removed successfully.",
"entryRemovedError": "Failed to remove suspended session entry: {error}",
"nameEditedSuccess": "Suspended session name updated to \"{name}\".",
"nameEditedError": "Failed to edit suspended session name: {error}",
"markedForSuspendSuccess": "Session {id} successfully marked for suspend.",
"markForSuspendError": "Failed to mark session for suspend: {error}",
"unmarkedSuccess": "Session {id} unmarked from suspend successfully.",
"unmarkError": "Failed to unmark session from suspend: {error}",
"defaultSessionName": "Session",
"resumeSuccess": "Session \"{name}\" resumed successfully.",
"resumeErrorBackend": "Backend failed to resume session: {error}",
"autoTerminated": "Suspended session \"{name}\" was auto-terminated by the backend due to: {reason}"
}
} }
} }
+30
View File
@@ -1156,5 +1156,35 @@
"keyUpdateNote": "既存のキーを保持するには、秘密鍵を空のままにしてください。パスフレーズは必要に応じて再入力する必要があります。", "keyUpdateNote": "既存のキーを保持するには、秘密鍵を空のままにしてください。パスフレーズは必要に応じて再入力する必要があります。",
"passphraseUpdateNote": "パスフレーズを保持または削除するには空のままにします。更新するには新しいパスフレーズを入力してください。" "passphraseUpdateNote": "パスフレーズを保持または削除するには空のままにします。更新するには新しいパスフレーズを入力してください。"
} }
},
"time": {
"unknown": "不明な時間",
"invalidDate": "無効な日付"
},
"sshSuspend": {
"notifications": {
"markedForSuspendInfo": "セッション {id} は中断マークが付けられました。タブを閉じるかアプリケーションを終了すると中断されます。",
"wsNotConnectedError": "WebSocket が接続されていません。中断/再開アクションを実行できません。",
"sessionNotFoundError": "セッションが見つからないか、WebSocket マネージャーが利用できません。",
"notMarkedWarning": "セッションに中断マークは付けられていませんでした。",
"fetchListError": "中断されたセッションリストの取得に失敗しました: {error}",
"resumeErrorInfoNotFound": "再開エラー: 中断されたセッション {id} がリストに見つかりません。",
"resumeErrorConnectionConfigNotFound": "再開エラー: {id} の元の接続設定が見つかりません。",
"resumeErrorGeneric": "セッションの再開に失敗しました: {error}",
"terminatedSuccess": "中断されたセッション「{name}」は正常に終了しました。",
"terminateError": "中断されたセッションの終了に失敗しました: {error}",
"entryRemovedSuccess": "中断されたセッションエントリ「{name}」は正常に削除されました。",
"entryRemovedError": "中断されたセッションエントリの削除に失敗しました: {error}",
"nameEditedSuccess": "中断されたセッション名は「{name}」に更新されました。",
"nameEditedError": "中断されたセッション名の編集に失敗しました: {error}",
"markedForSuspendSuccess": "セッション {id} は正常に中断マークが付けられました。",
"markForSuspendError": "セッションの中断マーク付けに失敗しました: {error}",
"unmarkedSuccess": "セッション {id} の中断マークは正常に解除されました。",
"unmarkError": "セッションの中断マーク解除に失敗しました: {error}",
"defaultSessionName": "セッション",
"resumeSuccess": "セッション「{name}」は正常に再開されました。",
"resumeErrorBackend": "バックエンドがセッションの再開に失敗しました: {error}",
"autoTerminated": "中断されたセッション「{name}」は、理由: {reason} によりバックエンドによって自動終了されました。"
} }
}
} }
+26
View File
@@ -1199,5 +1199,31 @@
"time": { "time": {
"unknown": "未知时间", "unknown": "未知时间",
"invalidDate": "无效日期" "invalidDate": "无效日期"
},
"sshSuspend": {
"notifications": {
"markedForSuspendInfo": "会话 {id} 已标记为挂起。关闭标签页或退出应用程序时,该会话将被挂起。",
"wsNotConnectedError": "WebSocket 未连接。无法执行挂起/恢复操作。",
"sessionNotFoundError": "未找到会话或 WebSocket 管理器不可用。",
"notMarkedWarning": "会话未被标记为待挂起。",
"fetchListError": "获取挂起的会话列表失败: {error}",
"resumeErrorInfoNotFound": "恢复错误:在列表中未找到已挂起的会话 {id}。",
"resumeErrorConnectionConfigNotFound": "恢复错误:未找到 {id} 的原始连接配置。",
"resumeErrorGeneric": "恢复会话失败: {error}",
"terminatedSuccess": "已成功终止挂起的会话 \"{name}\"。",
"terminateError": "终止挂起的会话失败: {error}",
"entryRemovedSuccess": "已成功移除挂起的会话条目 \"{name}\"。",
"entryRemovedError": "移除挂起的会话条目失败: {error}",
"nameEditedSuccess": "已挂起会话名称已更新为 \"{name}\"。",
"nameEditedError": "编辑已挂起会话名称失败: {error}",
"markedForSuspendSuccess": "会话 {id} 已成功标记为待挂起。",
"markForSuspendError": "标记会话为待挂起失败: {error}",
"unmarkedSuccess": "会话 {id} 已成功取消标记挂起。",
"unmarkError": "取消标记会话挂起失败: {error}",
"defaultSessionName": "会话",
"resumeSuccess": "会话 \"{name}\" 已成功恢复。",
"resumeErrorBackend": "后端恢复会话失败: {error}",
"autoTerminated": "已挂起的会话 \"{name}\" 因以下原因被后端自动终止: {reason}"
}
} }
} }
@@ -492,8 +492,13 @@ const handleSshSuspendResumedNotif = async (payload: SshSuspendResumedNotifPaylo
message: t('sshSuspend.notifications.resumeErrorGeneric', { error: String(error) }), message: t('sshSuspend.notifications.resumeErrorGeneric', { error: String(error) }),
}); });
} }
// 成功恢复后,挂起列表中移除 (或者等 SSH_SUSPEND_ENTRY_REMOVED_RESP) // 成功恢复后,立即从前端挂起列表中移除
fetchSuspendedSshSessions(); // 在这里主动刷新一次,确保列表更新 const resumedSessionIndex = suspendedSshSessions.value.findIndex(s => s.suspendSessionId === payload.suspendSessionId);
if (resumedSessionIndex !== -1) {
suspendedSshSessions.value.splice(resumedSessionIndex, 1);
console.log(`[${t('term.sshSuspend')}] Successfully resumed and removed session ${payload.suspendSessionId} from the frontend list.`);
}
// 可选:fetchSuspendedSshSessions(); // 如果仍然需要与后端同步最新列表,可以保留,但即时性由上面的 splice 保证
} else { } else {
uiNotificationsStore.addNotification({ uiNotificationsStore.addNotification({
type: 'error', type: 'error',
@@ -9,7 +9,7 @@
type="text" type="text"
v-model="searchTerm" v-model="searchTerm"
:placeholder="$t('suspendedSshSessions.searchPlaceholder')" :placeholder="$t('suspendedSshSessions.searchPlaceholder')"
class="w-full pl-10 pr-4 py-2 border border-border rounded-md bg-input text-foreground focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary" class="w-full pl-10 pr-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"
@input="filterSessions" @input="filterSessions"
/> />
</div> </div>
@@ -31,7 +31,7 @@
<li <li
v-for="session in filteredSessions" v-for="session in filteredSessions"
:key="session.suspendSessionId" :key="session.suspendSessionId"
class="session-item p-3 mb-2 border rounded-md bg-surface-ground" class="session-item p-3 mb-2 border border-border/70 rounded-md bg-surface-ground"
:class="{ 'opacity-60': session.backendSshStatus === 'disconnected_by_backend' }" :class="{ 'opacity-60': session.backendSshStatus === 'disconnected_by_backend' }"
> >
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
@@ -86,7 +86,7 @@
:title="$t('suspendedSshSessions.action.resume')" :title="$t('suspendedSshSessions.action.resume')"
class="px-3 py-1.5 text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-colors duration-150 inline-flex items-center" class="px-3 py-1.5 text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-colors duration-150 inline-flex items-center"
> >
<i class="fas fa-play mr-1.5"></i> <i class="fas fa-play mr-1.5" style="color: white;"></i>
{{ $t('suspendedSshSessions.action.resume') }} {{ $t('suspendedSshSessions.action.resume') }}
</button> </button>
<button <button
@@ -94,7 +94,7 @@
:title="$t('suspendedSshSessions.action.remove')" :title="$t('suspendedSshSessions.action.remove')"
class="px-3 py-1.5 text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition-colors duration-150 inline-flex items-center" class="px-3 py-1.5 text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition-colors duration-150 inline-flex items-center"
> >
<i class="fas fa-trash-alt mr-1.5"></i> <i class="fas fa-trash-alt mr-1.5" style="color: white;"></i>
{{ $t('suspendedSshSessions.action.remove') }} {{ $t('suspendedSshSessions.action.remove') }}
</button> </button>
</div> </div>