fix(workspace): refine workbench defaults and cursor

Add Quick Commands as the default Workbench tab and update
the default three-column layout proportions to better match
the intended workspace design.

Also fix terminal hover cursor behavior and add locale and
docs updates for the new default interaction.
This commit is contained in:
yinjianm
2026-03-25 04:18:26 +08:00
parent f2f9c754f8
commit 10df92ffa3
9 changed files with 114 additions and 10 deletions
@@ -739,6 +739,17 @@ watchEffect(() => {
/* z-index 调整或移除,因为背景层不再在此组件内 */
}
.terminal-inner-container,
.terminal-inner-container :deep(.xterm),
.terminal-inner-container :deep(.xterm-screen),
.terminal-inner-container :deep(.xterm-viewport) {
cursor: default !important;
}
.terminal-inner-container :deep(.xterm .xterm-cursor-pointer) {
cursor: pointer !important;
}
/* 文字描边和阴影样式 */
.terminal-inner-container.has-text-stroke :deep(.xterm-rows span),
.terminal-inner-container.has-text-stroke :deep(.xterm-rows div > span), /* 更具体地针对嵌套 span */
@@ -3,13 +3,14 @@ import { computed, ref, watch, type PropType } from 'vue';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import CommandHistoryView from '../views/CommandHistoryView.vue';
import QuickCommandsView from '../views/QuickCommandsView.vue';
import FileManager from './FileManager.vue';
import FileEditorContainer from './FileEditorContainer.vue';
import { useSessionStore } from '../stores/session.store';
import type { FileTab } from '../stores/fileEditor.store';
import type { WebSocketDependencies } from '../composables/useSftpActions';
type WorkbenchTab = 'files' | 'history' | 'editor';
type WorkbenchTab = 'quickCommands' | 'files' | 'history' | 'editor';
const props = defineProps({
tabs: {
@@ -42,9 +43,14 @@ const { t } = useI18n();
const sessionStore = useSessionStore();
const { sessions } = storeToRefs(sessionStore);
const activeWorkbenchTab = ref<WorkbenchTab>('files');
const activeWorkbenchTab = ref<WorkbenchTab>('quickCommands');
const workbenchTabs = computed(() => [
{
id: 'quickCommands' as const,
label: t('workspace.workbench.tabs.quickCommands', '快捷指令'),
icon: 'fas fa-bolt',
},
{
id: 'files' as const,
label: t('workspace.workbench.tabs.files', '文件'),
@@ -106,7 +112,7 @@ watch(
{{ t('workspace.workbench.label', '工作台') }}
</span>
</div>
<div class="mt-3 grid grid-cols-3 gap-2">
<div class="mt-3 grid grid-cols-2 gap-2 xl:grid-cols-4">
<button
v-for="tab in workbenchTabs"
:key="tab.id"
@@ -126,6 +132,10 @@ watch(
</div>
<div class="relative flex-1 min-h-0 overflow-hidden bg-background">
<div v-show="activeWorkbenchTab === 'quickCommands'" class="absolute inset-0 min-h-0 workbench-quick-commands">
<QuickCommandsView />
</div>
<div v-show="activeWorkbenchTab === 'files'" class="absolute inset-0 min-h-0">
<FileManager
v-if="hasFileManagerContext"
@@ -163,3 +173,58 @@ watch(
</div>
</div>
</template>
<style scoped>
.workbench-quick-commands {
background:
linear-gradient(180deg, rgba(15, 17, 22, 0.98) 0%, rgba(12, 14, 18, 1) 100%);
}
.workbench-quick-commands :deep(> div),
.workbench-quick-commands :deep(> div > div) {
background: transparent;
}
.workbench-quick-commands :deep(input) {
background: rgba(255, 255, 255, 0.06);
border-color: rgba(255, 255, 255, 0.12);
color: #f5f7fa;
box-shadow: none;
}
.workbench-quick-commands :deep(input::placeholder) {
color: rgba(226, 232, 240, 0.55);
}
.workbench-quick-commands :deep(button) {
box-shadow: none;
}
.workbench-quick-commands :deep([data-command-id]) {
position: relative;
border-radius: 10px;
color: #f8fafc;
}
.workbench-quick-commands :deep([data-command-id]::before) {
content: '';
position: absolute;
left: 0.2rem;
top: 0.2rem;
bottom: 0.2rem;
width: 1px;
background: rgba(255, 255, 255, 0.08);
}
.workbench-quick-commands :deep([data-command-id]:hover) {
background: rgba(139, 92, 246, 0.14);
}
.workbench-quick-commands :deep([data-command-id].bg-primary\/20) {
background: linear-gradient(90deg, rgba(139, 92, 246, 0.3), rgba(139, 92, 246, 0.18));
}
.workbench-quick-commands :deep(.font-semibold.flex.items-center) {
color: #f8fafc;
}
</style>
+1
View File
@@ -1281,6 +1281,7 @@
"noSession": "No active session",
"fileManagerHint": "Activate an SSH session to browse remote files.",
"tabs": {
"quickCommands": "Quick Commands",
"files": "Files",
"history": "History",
"editor": "Editor"
+1
View File
@@ -573,6 +573,7 @@
"noSession": "アクティブなセッションはありません",
"fileManagerHint": "SSH セッションを有効にするとリモートファイルを参照できます。",
"tabs": {
"quickCommands": "クイックコマンド",
"files": "ファイル",
"history": "履歴",
"editor": "エディター"
+1
View File
@@ -1285,6 +1285,7 @@
"noSession": "未激活会话",
"fileManagerHint": "激活一个 SSH 会话后即可浏览远程文件。",
"tabs": {
"quickCommands": "快捷指令",
"files": "文件",
"history": "历史命令",
"editor": "编辑器"
+28 -5
View File
@@ -56,6 +56,29 @@ function isLegacyDefaultLayout(node: LayoutNode | null): boolean {
);
}
function isLegacyWorkbenchLayout(node: LayoutNode | null): boolean {
if (!node || node.type !== 'container' || node.direction !== 'horizontal' || !node.children || node.children.length !== 3) {
return false;
}
const [leftColumn, centerColumn, rightColumn] = node.children;
return Boolean(
isPaneNode(leftColumn, 'workbench') &&
leftColumn?.size === 23 &&
centerColumn?.type === 'container' &&
centerColumn.direction === 'vertical' &&
centerColumn.size === 57 &&
centerColumn.children?.length === 2 &&
isPaneNode(centerColumn.children[0], 'terminal') &&
centerColumn.children[0]?.size === 94 &&
isPaneNode(centerColumn.children[1], 'commandBar') &&
centerColumn.children[1]?.size === 6 &&
isPaneNode(rightColumn, 'statusMonitor') &&
rightColumn?.size === 20
);
}
// 定义默认布局结构
const getDefaultLayout = (): LayoutNode => ({
id: generateId(), // Generate new ID
@@ -66,13 +89,13 @@ const getDefaultLayout = (): LayoutNode => ({
id: generateId(), // Generate new ID
type: "pane",
component: "workbench",
size: 23
size: 17
},
{
id: generateId(), // Generate new ID
type: "container",
direction: "vertical",
size: 57,
size: 66,
children: [
{
id: generateId(), // Generate new ID
@@ -92,7 +115,7 @@ const getDefaultLayout = (): LayoutNode => ({
id: generateId(), // Generate new ID
type: "pane",
component: "statusMonitor",
size: 20
size: 17
}
]
});
@@ -202,8 +225,8 @@ function normalizeLoadedLayout(node: LayoutNode | null): LayoutNode | null {
const layoutWithIds = ensureNodeIds(node);
if (!layoutWithIds) return null;
if (isLegacyDefaultLayout(layoutWithIds)) {
console.log('[Layout Store] Detected legacy workspace default layout, migrating to workbench layout.');
if (isLegacyDefaultLayout(layoutWithIds) || isLegacyWorkbenchLayout(layoutWithIds)) {
console.log('[Layout Store] Detected legacy workspace default layout, migrating to the latest workbench layout.');
return ensureNodeIds(getDefaultLayout());
}