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:
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -573,6 +573,7 @@
|
||||
"noSession": "アクティブなセッションはありません",
|
||||
"fileManagerHint": "SSH セッションを有効にするとリモートファイルを参照できます。",
|
||||
"tabs": {
|
||||
"quickCommands": "クイックコマンド",
|
||||
"files": "ファイル",
|
||||
"history": "履歴",
|
||||
"editor": "エディター"
|
||||
|
||||
@@ -1285,6 +1285,7 @@
|
||||
"noSession": "未激活会话",
|
||||
"fileManagerHint": "激活一个 SSH 会话后即可浏览远程文件。",
|
||||
"tabs": {
|
||||
"quickCommands": "快捷指令",
|
||||
"files": "文件",
|
||||
"history": "历史命令",
|
||||
"editor": "编辑器"
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user