HomeSense Studio v2 终端与设备控制台重构交接文档
本文件总结了当前终端重构的进展、核心设计思路、技术架构及后续接班开发计划。
1. 核心目标与当前状态
当前任务是移除 Mock 配置,转向真实、解耦的本地/SSH/ADB 终端适配。目前已完成大部分后端与前端的基础链路改造,完成了本地 SSH 通道与按需凭证解析。
当前主要变动与状态:
- 后端端口移至 3100:为了避免与前端常规端口冲突,NestJS 后端默认端口由 3000 改为
3100(apps/server/src/main.ts中通过process.env.PORT || 3100指定)。 - 前端配置环境变量:
apps/web/.env文件配置了VITE_API_BASE=http://localhost:3100,Vite 开发服务器当前在5181端口运行。 - Mock 服务白名单:前端
mock-server.ts已将/api/terminal加入到REAL_API_PREFIXES白名单,保证所有终端相关请求均穿透 Mock 直达真实 NestJS 后端。 - 密钥安全存放(Git-ignored):私钥和 ADB 配对密钥被安全地存放在后端的本地文件系统中:
apps/server/runtime-keys/ssh/apps/server/runtime-keys/adb/- 避免将敏感的认证信息(如
n8n_watchdog密钥)提交到公共 Git 仓库。
2. 数据库与后端架构
2.1 数据库设计 (terminal_targets 表)
在 SQLite 中实现了配置数据库,独立存储设备的接入通道和认证凭证:
sql
CREATE TABLE IF NOT EXISTS terminal_targets (
id INTEGER NOT NULL,
name TEXT NOT NULL,
kind TEXT NOT NULL, -- 'ssh' | 'adb' | 'local'
target_json TEXT NOT NULL, -- 存储主机、端口、用户名、私钥文件名等配置 JSON
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
PRIMARY KEY (id AUTOINCREMENT)
)2.2 核心模块关系
KeyStore(keystore.ts):负责读写runtime-keys/下的文件,不对前端暴露密钥文件内容,仅对内提供解析。TargetResolver(target-resolver.ts):将前端请求的配置 ID 或设备 ID 解析为包含主机地址、端口、凭证名称的ProtocolTarget对象。SSHProtocol/LocalProtocol/AdbProtocol:- 适配不同类型的终端通道。
LocalProtocol在 Windows 上使用node-pty/ConPTY跑本地 PowerShell/CMD。SSHProtocol基于ssh2模块建立远程加密 shell 会话。
TerminalGateway(terminal.gateway.ts):WebSocket 网关(绑定路径为/api/terminal/ws),升级 HTTP 并处理输入输出流,将 WebSocket 数据流通过Subject泵送到具体的协议处理器。
3. 前端重构架构
前端去除了原来的单页面强制铺满设计,改为高可复用的终端卡片组件:
TerminalPanel.vue(通用组件):- 封装
xterm.js及fit-addon插件。 - 通过
ResizeObserver动态计算宽高,并向后端发送resize消息调节伪终端的行/列数。 - 管理 WebSocket 状态的开启与清理,统一处理
stdout、session_opened、exit等控制帧。
- 封装
DeviceDetailView.vue(设备详情页整合):- 在设备详情页中提供控制台展开区,直接内嵌
TerminalPanel.vue,实现快速操作。
- 在设备详情页中提供控制台展开区,直接内嵌
SessionView.vue(全屏独立会话页面):- 负责承载全屏长会话终端,同样内嵌
TerminalPanel.vue,支持通过 URL 参数target_id连接特定凭据的目标。
- 负责承载全屏长会话终端,同样内嵌
AuthorizationsView.vue(凭据授权管理页):- 完全实现了 SSH 配置卡片的增删改查。
- 用户可以新建通道(SSH/Local)、选择并配置私钥别名、测试连接并实时验证握手结果。
4. 接下来的工作规划 (待办事项)
开发已基本贯通真实物理连接链路,下一步应该集中力量解决会话持久化与生命周期管理:
- 后端 Session 存储 (
TerminalSessionStore):- 当前 WebSocket 刷新或断开会导致 PTY 进程被直接 Kill。
- 需要引入内存 Session 管理器:当连接断开时,保持 PTY 进程存活;等待客户端重新
attach。 - 实现 Ring Buffer 环形缓冲区:每个活动 Session 在后端保留最近的(如 1000 行)输出历史,在新连接重新
attach时主动下发以恢复终端视窗。
- 终端生命周期控制 UI:
- 前端应允许用户自主选择终端的关闭方式:
- “暂离 / 保持运行” (Detach):关闭面板但保持 PTY 活跃。
- “彻底终止” (Kill / Terminate):向后端发送退出码,彻底销毁 PTY 进程并断开 WebSocket。
- 前端应允许用户自主选择终端的关闭方式:
- 多标签终端支持 (Tabs):
- 允许单个设备面板中并存多个 Shell 会话(例如左侧跑 ADB Shell 调试,右侧通过本地 PowerShell 查看日志)。
- 未来演进(流媒体与 Agent 接管):
- 保证底层 Protocol 具备可拦截和可读取的流接口,使得未来的 Agent (比如 Coding Agent) 可以直接作为虚拟客户端,挂载到同一个 Session ID 旁听或发送指令。
交接日期:2026/06/08主分支:master / main开发环境端口:Vite(5181) | NestJS(3100)