diff --git a/package-lock.json b/package-lock.json index 055769f..60210b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,8 @@ "packages/*" ], "dependencies": { - "pinia-plugin-persistedstate": "^4.2.0" + "pinia-plugin-persistedstate": "^4.2.0", + "vuedraggable": "^4.1.0" }, "devDependencies": { "@types/qrcode": "^1.5.5", @@ -5154,6 +5155,12 @@ "node": ">= 10" } }, + "node_modules/sortablejs": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", + "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==", + "license": "MIT" + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -6092,6 +6099,18 @@ "typescript": "*" } }, + "node_modules/vuedraggable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz", + "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==", + "license": "MIT", + "dependencies": { + "sortablejs": "1.14.0" + }, + "peerDependencies": { + "vue": "^3.0.1" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index 8275777..25b0d1f 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "homepage": "https://github.com/Heavrnl/nexus-terminal#readme", "description": "", "dependencies": { - "pinia-plugin-persistedstate": "^4.2.0" + "pinia-plugin-persistedstate": "^4.2.0", + "vuedraggable": "^4.1.0" }, "devDependencies": { "@types/qrcode": "^1.5.5", diff --git a/packages/backend/src/websocket.ts b/packages/backend/src/websocket.ts index f25c39f..6d57d13 100644 --- a/packages/backend/src/websocket.ts +++ b/packages/backend/src/websocket.ts @@ -195,6 +195,10 @@ export const initializeWebSocket = (server: http.Server, sessionParser: RequestH // 5. 设置 Shell 事件转发 shellStream.on('data', (data: Buffer) => { + // --- 添加日志:打印收到的原始数据 --- + console.log(`SSH Data (会话: ${newSessionId}, 原始): `, data.toString()); // 添加原始数据日志 (尝试 utf8) + console.log(`SSH Data (会话: ${newSessionId}, Hex): `, data.toString('hex')); // 添加 Hex 日志 + // ------------------------------------ if (ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: 'ssh:output', payload: data.toString('base64'), encoding: 'base64' })); } diff --git a/packages/frontend/src/components/LayoutConfigurator.vue b/packages/frontend/src/components/LayoutConfigurator.vue new file mode 100644 index 0000000..20f843c --- /dev/null +++ b/packages/frontend/src/components/LayoutConfigurator.vue @@ -0,0 +1,465 @@ + + + + + diff --git a/packages/frontend/src/components/LayoutNodeEditor.vue b/packages/frontend/src/components/LayoutNodeEditor.vue new file mode 100644 index 0000000..a82a450 --- /dev/null +++ b/packages/frontend/src/components/LayoutNodeEditor.vue @@ -0,0 +1,353 @@ + + + + + diff --git a/packages/frontend/src/components/LayoutRenderer.vue b/packages/frontend/src/components/LayoutRenderer.vue new file mode 100644 index 0000000..c65accf --- /dev/null +++ b/packages/frontend/src/components/LayoutRenderer.vue @@ -0,0 +1,350 @@ + + + + + diff --git a/packages/frontend/src/components/Terminal.vue b/packages/frontend/src/components/Terminal.vue index f739509..6f66232 100644 --- a/packages/frontend/src/components/Terminal.vue +++ b/packages/frontend/src/components/Terminal.vue @@ -17,7 +17,7 @@ const props = defineProps<{ const emit = defineEmits<{ (e: 'data', data: string): void; // 用户输入事件 (e: 'resize', dimensions: { cols: number; rows: number }): void; // 终端大小调整事件 - (e: 'ready', terminal: Terminal): void; // 终端准备就绪事件 + (e: 'ready', payload: { sessionId: string; terminal: Terminal }): void; // *** 修正:ready 事件传递包含 sessionId 和 terminal 实例的对象 *** }>(); const terminalRef = ref(null); // 终端容器的引用 @@ -185,8 +185,10 @@ onMounted(() => { } }, { immediate: true }); // 立即执行一次 watch - // 触发 ready 事件 - emit('ready', terminal); + // 触发 ready 事件,传递 sessionId 和 terminal 实例 + if (terminal) { // 确保 terminal 实例已创建 + emit('ready', { sessionId: props.sessionId, terminal: terminal }); + } // 聚焦终端 terminal.focus(); diff --git a/packages/frontend/src/components/TerminalTabBar.vue b/packages/frontend/src/components/TerminalTabBar.vue index d90f748..372c2e1 100644 --- a/packages/frontend/src/components/TerminalTabBar.vue +++ b/packages/frontend/src/components/TerminalTabBar.vue @@ -1,7 +1,7 @@