This commit is contained in:
Baobhan Sith
2025-04-16 16:45:54 +08:00
parent 84f0368811
commit d56f176007
8 changed files with 350 additions and 74 deletions
@@ -0,0 +1,76 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
const emit = defineEmits(['send-command']);
const { t } = useI18n();
const commandInput = ref('');
const sendCommand = () => {
const command = commandInput.value.trim();
if (command) {
console.log(`[CommandInputBar] Sending command: ${command}`);
emit('send-command', command + '\n'); // 发送命令并附加换行符,模拟回车
commandInput.value = ''; // 清空输入框
}
};
</script>
<template>
<div class="command-input-bar">
<div class="input-wrapper">
<input
type="text"
v-model="commandInput"
:placeholder="t('commandInputBar.placeholder')"
class="command-input"
@keydown.enter="sendCommand"
/>
<!-- 可以在这里添加按钮 -->
</div>
<!-- 可以在这里添加其他按钮 -->
</div>
</template>
<style scoped>
.command-input-bar {
display: flex;
align-items: center;
padding: 5px 10px;
background-color: #f0f0f0; /* 背景色,可调整 */
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
min-height: 40px; /* 保证一定高度 */
}
.input-wrapper {
flex-grow: 1; /* 让输入框容器占据大部分空间 */
display: flex;
justify-content: center; /* 水平居中输入框 */
}
.command-input {
padding: 6px 10px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 0.9em;
width: 60%; /* 输入框宽度,可调整 */
max-width: 800px; /* 最大宽度 */
outline: none;
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}
.command-input:focus {
border-color: #007bff;
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}
/* 可以添加按钮样式 */
/*
.command-input-bar button {
margin-left: 10px;
padding: 6px 12px;
}
*/
</style>
@@ -1,5 +1,7 @@
<script setup lang="ts">
import { PropType } from 'vue';
import { ref, PropType } from 'vue'; // 导入 ref
import WorkspaceConnectionListComponent from './WorkspaceConnectionList.vue'; // 导入连接列表组件
import { useSessionStore } from '../stores/session.store'; // 导入 session store
// 导入会话状态类型
import type { SessionTabInfoWithStatus } from '../stores/session.store'; // 导入更新后的类型
@@ -28,6 +30,22 @@ const closeSession = (event: MouseEvent, sessionId: string) => {
event.stopPropagation(); // 阻止事件冒泡到标签点击事件
emit('close-session', sessionId);
};
// --- 新增:弹出窗口状态和处理 ---
const sessionStore = useSessionStore();
const showConnectionListPopup = ref(false);
const togglePopup = () => {
showConnectionListPopup.value = !showConnectionListPopup.value;
};
// 处理从弹出列表中选择连接的事件
const handlePopupConnect = (connectionId: number) => {
console.log(`[TabBar] Popup connect request for ID: ${connectionId}`);
// 使用 sessionStore 的方法来处理连接请求(它现在总是新建标签)
sessionStore.handleConnectRequest(connectionId);
showConnectionListPopup.value = false; // 关闭弹出窗口
};
</script>
<template>
@@ -48,8 +66,23 @@ const closeSession = (event: MouseEvent, sessionId: string) => {
</button>
</li>
</ul>
<!-- 可以添加一个 "+" 按钮来打开新标签/连接 -->
<!-- <button class="add-tab-button">+</button> -->
<!-- 新增 "+" 按钮 -->
<button class="add-tab-button" @click="togglePopup" title="新建连接标签页">
<i class="fas fa-plus"></i>
</button>
<!-- 新增连接列表弹出窗口 -->
<div v-if="showConnectionListPopup" class="connection-list-popup" @click.self="togglePopup">
<div class="popup-content">
<button class="popup-close-button" @click="togglePopup">&times;</button>
<h3>选择要连接的服务器</h3>
<WorkspaceConnectionListComponent
@connect-request="handlePopupConnect"
@open-new-session="handlePopupConnect"
class="popup-connection-list"
/>
</div>
</div>
</div>
</template>
@@ -60,7 +93,8 @@ const closeSession = (event: MouseEvent, sessionId: string) => {
border-bottom: 1px solid #bdbdbd;
overflow-x: auto; /* 如果标签过多则允许水平滚动 */
white-space: nowrap;
padding: 0 0.5rem; /* 左右留出一点空间 */
/* padding: 0 0.5rem; */ /* 移除左右内边距,让标签列表和按钮自己控制 */
padding-right: 0.5rem; /* 只保留右侧内边距给按钮 */
height: 2.5rem; /* 固定标签栏高度 */
box-sizing: border-box; /* 确保 padding 不会增加总高度 */
}
@@ -83,8 +117,8 @@ const closeSession = (event: MouseEvent, sessionId: string) => {
.tab-list {
list-style: none;
padding: 0;
margin: 0;
padding: 0; /* 确保列表无内边距 */
margin: 0; /* 确保列表无外边距 */
display: flex;
}
@@ -156,18 +190,91 @@ const closeSession = (event: MouseEvent, sessionId: string) => {
color: #333333;
}
/* 可选:添加新标签按钮样式 */
/*
/* 添加新标签按钮样式 */
.add-tab-button {
background: none;
border: none;
padding: 0.5rem 0.8rem;
border-left: 1px solid #bdbdbd; /* 左侧分隔线 */
padding: 0 0.8rem;
/* margin-left: 0.5rem; */ /* 移除左外边距 */
cursor: pointer;
font-size: 1.2em;
font-size: 1.1em;
color: #616161;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
flex-shrink: 0; /* 防止按钮被压缩 */
}
.add-tab-button:hover {
background-color: #d0d0d0;
}
*/
.add-tab-button i {
line-height: 1; /* 确保图标垂直居中 */
}
/* 弹出窗口样式 */
.connection-list-popup {
position: fixed; /* 固定定位,覆盖整个屏幕 */
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* 半透明背景 */
display: flex;
justify-content: center;
align-items: center;
z-index: 1000; /* 确保在最上层 */
}
.popup-content {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
width: 80%;
max-width: 500px; /* 限制最大宽度 */
max-height: 80vh; /* 限制最大高度 */
display: flex;
flex-direction: column;
position: relative; /* 为了关闭按钮定位 */
}
.popup-close-button {
position: absolute;
top: 10px;
right: 10px;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: #aaa;
line-height: 1;
}
.popup-close-button:hover {
color: #333;
}
.popup-content h3 {
margin-top: 0;
margin-bottom: 15px;
text-align: center;
color: #333;
}
.popup-connection-list {
flex-grow: 1; /* 让列表占据剩余空间 */
overflow-y: auto; /* 列表内容滚动 */
/* 可能需要覆盖 WorkspaceConnectionList 的一些默认样式 */
border: 1px solid #eee;
border-radius: 4px;
}
/* 覆盖 WorkspaceConnectionList 内部样式(如果需要) */
/* :deep(.popup-connection-list .search-add-bar) { */
/* display: none; */ /* 不再隐藏搜索栏 */
/* } */
:deep(.popup-connection-list .connection-list-area) {
padding: 0; /* 保持移除内边距 */
}
</style>
@@ -108,19 +108,26 @@ const toggleGroup = (groupName: string) => {
expandedGroups.value[groupName] = !expandedGroups.value[groupName];
};
// 处理单击连接
// 处理单击连接 (左键)
const handleConnect = (connectionId: number) => {
console.log(`[WkspConnList] handleConnect (左键) called for ID: ${connectionId}`);
emit('connect-request', connectionId);
console.log(`[WkspConnList] Emitted 'connect-request' for ID: ${connectionId}`);
closeContextMenu(); // 点击连接后关闭菜单
};
// 显示右键菜单
const showContextMenu = (event: MouseEvent, connection: ConnectionInfo) => {
console.log(`[WkspConnList] showContextMenu (右键) called for ID: ${connection.id}. Event:`, event);
event.preventDefault(); // 再次确保阻止默认行为
event.stopPropagation(); // 阻止事件冒泡
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; // 彻底停止事件处理
};
// 关闭右键菜单
@@ -159,7 +166,9 @@ onMounted(() => {
// 处理中键点击(在新标签页打开)
const handleOpenInNewTab = (connectionId: number) => {
console.log(`[WkspConnList] handleOpenInNewTab (中键/辅助键) called for ID: ${connectionId}`);
emit('open-new-session', connectionId);
console.log(`[WkspConnList] Emitted 'open-new-session' for ID: ${connectionId}`);
closeContextMenu(); // 如果右键菜单是打开的,也关闭它
};
</script>