Files
opsxshell/AGENTS.md
T
Logan.Li 514d62644e v2.0.0: 主题系统+SSH私钥解析修复+会话持久化+连接池优化+UI打磨
核心修复:
- ssh-service.ts: 新增 resolvePrivateKey(),将私钥文件路径(~/.ssh/id_rsa)解析为内容后传给 ssh2,
  解决 'Cannot parse privateKey: Unsupported key format' 错误
- useTerminalConnection.ts + sessionHelper.ts: 根据 authType 过滤字段,password/agent 认证不再传 privateKey
- sessionStore.ts: addSession() 现在先调用 sessionCreate() 持久化到 SQLite,解决恢复标签'无可用连接信息'问题
- database-service.ts: updateSession() 补充 private_key_path 字段持久化
- SessionDialog.tsx: 默认 username='root'、privateKey='~/.ssh/id_rsa'

UI/UX:
- 语义化主题系统(app-theme.ts),强制深色模式,全局无边框设计
- macOS 标题栏支持双击最大化(window:toggleMaximize IPC)
- macOS 菜单栏('OpsXShell' 应用菜单 + Settings Cmd+,)
- WelcomeView 4卡片布局,移除 Settings 按钮
- TabBar/TabItem 背景色统一(bg-dark-800/900),消除白色边框线

架构优化:
- SFTP 生命周期修复(useSFTP.ts useRef + autoConnectAttempted guard)
- 连接池竞态修复,支持快速多标签连接
- IPC 接口规范化,安全错误处理
- Vite 代码分割优化

质量: lint零错误 | tsc零错误 | build成功 | 49 tests pass
2026-04-22 11:15:41 +08:00

783 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md - OpsXShell 项目开发指南
本文件为 AI 编程助手提供项目开发指导。
---
## 项目概述
**OpsXShell** 是跨平台 SSH/SFTP 终端工具 · 简洁高效 · 安全可靠 · 基于 Electron + React + TypeScript 构建。
### 核心功能
- 🔐 **SSH 终端** - 支持密码、密钥、SSH Agent 多种认证方式
- 📁 **SFTP 文件管理** - 双栏可视化文件管理,拖拽上传下载
- 🔄 **端口转发** - 本地/远程端口转发支持
- 📑 **多标签页** - 类浏览器标签管理,支持会话恢复
- 🎨 **现代 UI** - 基于 Tailwind CSS 的深色主题界面
- 🔒 **安全可靠** - 敏感数据使用 AES-256-GCM 加密存储
- 🌐 **跨平台** - 支持 Windows、macOS、Linux
- ⚡ **Zmodem 支持** - 集成 rz/sz 文件传输协议
### 当前版本状态
- **版本**: v2.0.0
- **状态**: 已发布 (Release) - 安全增强版
- **已完成**: 核心 SSH/SFTP 功能、加密存储、多标签页系统、Zmodem 传输
- **v2.0 优化**: safeStorage 主密钥加密、路径遍历防护、PBKDF2 600K 迭代、类型安全、工程化建设、性能优化
- **技术债务**: 部分组件仍在迁移到新的连接池架构
---
## 技术栈
| 层级 | 技术 | 版本 |
|------|------|------|
| 框架 | Electron | 28+ |
| 前端框架 | React | 18 |
| 语言 | TypeScript | 5 |
| 构建工具 | Vite | 5 |
| 状态管理 | Zustand | 4.4+ |
| 终端仿真 | XTerm.js | 5.5+ |
| SSH/SFTP | ssh2 | 1.15+ |
| Zmodem | zmodem-ts | 1.0.8 |
| 数据库 | better-sqlite3 | 9.4+ |
| 样式 | Tailwind CSS | 3.3+ |
| 图标 | Lucide React | 0.294+ |
| 测试 | Vitest | 4.1+ |
---
## 项目结构
```
opsxshell/
├── electron/ # Electron 主进程
│ ├── main.ts # 主进程入口 - 窗口创建、应用生命周期、菜单
│ ├── preload.ts # 上下文桥接,暴露 API 到渲染进程
│ ├── tsconfig.json # 主进程 TS 配置 (CommonJS)
│ ├── ipc/ # IPC 处理器(按功能模块组织)
│ │ ├── index.ts # IPC 注册入口
│ │ ├── ssh.ipc.ts # SSH 连接、Shell、端口转发
│ │ ├── sftp.ipc.ts # SFTP 文件操作
│ │ ├── session.ipc.ts # 会话 CRUD
│ │ ├── settings.ipc.ts # 应用设置
│ │ ├── dialog.ipc.ts # 文件对话框
│ │ ├── file.ipc.ts # 文件系统操作
│ │ ├── zmodem.ipc.ts # Zmodem 传输
│ │ └── app.ipc.ts # 应用信息
│ └── services/ # 主进程服务
│ ├── ssh-service.ts # SSH 连接、Shell 会话、SFTP 操作
│ ├── database-service.ts # SQLite 持久化存储
│ ├── crypto.ts # AES-256-GCM 加密工具
│ ├── key-service.ts # 主密钥管理
│ └── zmodem-service.ts # Zmodem 文件传输服务
├── src/ # 渲染进程 (React)
│ ├── components/ # UI 组件
│ │ ├── index.ts # 🆕 统一导出
│ │ ├── App.tsx # 根组件
│ │ ├── SessionDialog.tsx # 会话编辑对话框
│ │ ├── QuickConnectDialog.tsx # 快速连接对话框
│ │ ├── WelcomeView.tsx # 欢迎页面
│ │ │
│ │ ├── layout/ # 🆕 布局组件
│ │ │ ├── Sidebar.tsx # 侧边栏
│ │ │ ├── TabBar.tsx # 标签栏
│ │ │ ├── TabContent.tsx # 标签内容
│ │ │ └── StatusBar.tsx # 状态栏
│ │ │
│ │ ├── sftp/ # SFTP 模块
│ │ │ ├── index.ts
│ │ │ ├── SFTPView.tsx # SFTP 主视图
│ │ │ ├── Breadcrumb.tsx
│ │ │ ├── ConnectionSelector.tsx
│ │ │ ├── ContextMenu.tsx
│ │ │ ├── FileRow.tsx
│ │ │ ├── SortHeader.tsx
│ │ │ ├── TransferItem.tsx
│ │ │ ├── types.ts
│ │ │ └── utils.ts
│ │ │
│ │ ├── terminal/ # 终端模块
│ │ │ ├── index.ts
│ │ │ ├── TerminalView.tsx # 终端视图
│ │ │ └── types.ts
│ │ │
│ │ ├── settings/ # 🆕 设置模块
│ │ │ └── SettingsView.tsx # 设置页面
│ │ │
│ │ └── common/ # 🆕 通用组件
│ │ ├── index.ts
│ │ ├── Button.tsx # 按钮
│ │ ├── Modal.tsx # 模态框
│ │ ├── Loading.tsx # 加载状态
│ │ └── ErrorBoundary.tsx # 错误边界
│ ├── stores/ # Zustand 状态管理
│ │ ├── index.ts # 🆕 统一导出
│ │ ├── tabStore.ts # 标签页状态管理
│ │ ├── settingsStore.ts # 应用设置
│ │ ├── terminalSnapshotStore.ts # 终端快照
│ │ └── connection/ # 连接管理架构
│ │ ├── index.ts # 统一导出
│ │ ├── types.ts # 类型定义
│ │ ├── poolStore.ts # 连接池核心
│ │ ├── lifecycleStore.ts # 连接生命周期
│ │ ├── storeHooks.ts # Store Hooks
│ │ └── sessionHelper.ts # 会话配置获取
│ ├── themes/ # 主题配置
│ │ └── terminal.ts # 终端主题
│ │
│ ├── hooks/ # 🆕 自定义 Hooks
│ │ ├── index.ts # 统一导出
│ │ ├── useTerminal.ts # 终端管理
│ │ ├── useSFTP.ts # SFTP 操作
│ │ ├── useConnection.ts # 连接管理
│ │ └── useSettings.ts # 设置操作
│ │
│ ├── constants/ # 🆕 常量管理
│ │ ├── index.ts # 统一导出
│ │ ├── terminal.ts # 终端常量
│ │ ├── sftp.ts # SFTP 常量
│ │ └── keybindings.ts # 快捷键
│ │
│ ├── utils/ # 工具函数
│ │ ├── index.ts # 统一导出
│ │ ├── logger.ts # 统一日志系统
│ │ ├── error-handler.ts # 统一错误处理
│ │ ├── validators.ts # 输入校验
│ │ └── formatters.ts # 格式化工具
│ │
│ ├── electron.d.ts # Electron API 类型声明
│ ├── main.tsx # React 渲染入口
│ └── index.css # 全局样式(Tailwind + 自定义样式)
├── shared/ # 共享类型定义(主进程/渲染进程共用)
│ └── types/
│ ├── session.types.ts # 会话相关类型
│ ├── connection.types.ts # 连接相关类型
│ ├── sftp.types.ts # SFTP 类型
│ ├── ipc.types.ts # IPC 类型
│ └── index.ts # 统一导出
├── test/ # 测试文件
│ ├── setup.ts # 测试环境配置(mock Electron API)
│ ├── stores/ # Store 测试
│ │ ├── tabStore.test.ts
│ │ └── connectionPool.test.ts
│ └── components/sftp/ # 组件测试
│ └── utils.test.ts
├── dist/ # 前端构建输出 (Vite)
├── dist-electron/ # 主进程构建输出
├── package.json # 项目配置 + electron-builder 配置
├── vite.config.ts # Vite 配置
├── vitest.config.ts # Vitest 测试配置
├── tailwind.config.js # Tailwind CSS 配置
├── tsconfig.json # 渲染进程 TS 配置
├── tsconfig.node.json # Node 类型配置
├── index.html # 入口 HTML(含 CSP 配置)
└── .eslintrc.cjs # ESLint 配置
```
---
## 架构详解
### Electron 双进程模型
```
┌─────────────────────────────────────────────────────────────┐
│ 主进程 (Node.js) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ ssh-service │ │ database │ │ key-service │ │
│ │ (ssh2) │ │ (SQLite) │ │ (加密密钥管理) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │zmodem-service│ │ IPC │ │
│ │ (zmodem-ts) │ │ Handlers │ │
│ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ipcMain.handle() / event.sender.send() │
│ │ │
│ ┌──────────────┴──────────────┐ │
│ │ contextBridge │ │
│ │ (electron/preload.ts) │ │
│ └──────────────┬──────────────┘ │
└──────────────────────────┼──────────────────────────────────┘
│ IPC (安全隔离)
┌──────────────────────────┼──────────────────────────────────┐
│ 渲染进程 (Chromium) │
│ ┌──────────────┴──────────────┐ │
│ │ window.electronAPI │ │
│ └──────────────┬──────────────┘ │
│ │ │
│ ┌─────────────┐ ┌──────┴──────┐ ┌─────────────────────┐ │
│ │ React UI │ │ Zustand │ │ XTerm.js 终端 │ │
│ │ 组件 │ │ Stores │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
### IPC 通信接口
渲染进程通过 `window.electronAPI` 与主进程通信。完整类型定义在 `src/electron.d.ts`。
#### 核心 IPC 通道
```typescript
// SSH 操作
const { success, connectionId, error } = await window.electronAPI.sshConnect(config)
const { success, shellId } = await window.electronAPI.sshCreateShell(connectionId, { cols, rows })
await window.electronAPI.sshShellWrite(shellId, data)
await window.electronAPI.sshShellResize(shellId, cols, rows)
await window.electronAPI.sshDisconnect(connectionId)
// Shell 数据推送(主进程 → 渲染进程)
window.electronAPI.onShellData((event, connectionId, shellId, data: Buffer) => {
terminal.write(data)
})
// SFTP 操作
const { sftpId } = await window.electronAPI.sftpConnect(connectionId)
const { files } = await window.electronAPI.sftpListDirectory(sftpId, path)
await window.electronAPI.sftpUpload(sftpId, localPath, remotePath)
// 会话管理
const { sessions } = await window.electronAPI.sessionGetAll()
const { session } = await window.electronAPI.sessionCreate(sessionData)
await window.electronAPI.sessionUpdate(id, updates)
await window.electronAPI.sessionDelete(id)
```
### 数据流
1. **SSH 连接流程**:
```
QuickConnectDialog/SessionDialog
↓
window.electronAPI.sshConnect()
↓
ipcMain.handle('ssh:connect')
↓
ssh-service.connect()
↓
ssh2.Client.connect()
```
2. **Shell 数据流**:
```
ssh2 ClientChannel (data事件)
↓
event.sender.send('ssh:shellData')
↓
ipcRenderer.on('ssh:shellData')
↓
window.electronAPI.onShellData()
↓
XTerm.write(data)
```
3. **会话持久化**:
```
connectionStore.addSession()
↓
window.electronAPI.sessionCreate()
↓
database-service.createSession()
↓
SQLite (密码加密存储)
```
---
## 构建和运行命令
### 环境要求
- Node.js 18+
- npm 9+ 或 yarn 1.22+
### 开发命令
```bash
# 安装依赖
npm install
# 启动开发服务器(Vite + Electron)
npm run dev
# 说明:会先启动 Vite dev server (端口 5173),然后启动 Electron
# 运行 ESLint 检查
npm run lint
# 运行测试
npm run test # 运行所有测试
npm run test:watch # 监视模式
npm run test:coverage # 生成覆盖率报告
```
### 生产构建
```bash
# 构建生产版本(前端 + Electron 主进程)
npm run build
# 构建步骤分解:
# 1. tsc - 检查渲染进程 TypeScript
# 2. vite build - 构建前端到 dist/
# 3. npm run build:electron - 编译主进程到 dist-electron/
```
### 打包分发
```bash
# 打包当前平台
npm run dist
# 平台特定打包
npm run dist:win # Windows (NSIS)
npm run dist:mac # macOS (DMG, x64 + arm64)
npm run dist:linux # Linux (AppImage)
# 输出目录: release/
```
---
## 代码规范
### 文件组织
- **组件**: `src/components/*.tsx` - PascalCase 命名
- **子组件目录**: `src/components/{feature}/*.tsx` - 功能相关子组件
- **Stores**: `src/stores/*Store.ts` 或 `src/stores/{feature}/store.ts` - camelCase
- **服务**: `electron/services/*-service.ts` - kebab-case
- **IPC 处理器**: `electron/ipc/{feature}.ipc.ts` - kebab-case
- **类型**: 共享类型定义在 `shared/types/*.types.ts`
### 命名约定
```typescript
// 组件: PascalCase
export default function TerminalView() {}
// Hooks: camelCase + use 前缀
const useConnectionStore = create<ConnectionState>(...)
// 接口: PascalCase
interface SSHConfig { ... }
interface TabState { ... }
// 常量: UPPER_SNAKE_CASE (局部) 或 camelCase (模块级)
const ALGORITHM = 'aes-256-gcm'
const keyService = new KeyService()
```
### 类型安全
- 所有 IPC 接口必须在 `src/electron.d.ts` 中声明
- 共享类型定义在 `shared/types/` 目录
- 使用严格的 TypeScript 配置 (`strict: true`)
- Zustand Store 必须定义 State 接口
```typescript
// 示例:完整的类型定义
interface Tab {
id: string
title: string
type: 'welcome' | 'terminal' | 'sftp' | 'settings'
sessionId?: string
connectionConfig?: SSHConnectionConfig
isActive: boolean
}
interface TabState {
tabs: Tab[]
activeTabId: string | null
addTab: (tab: Omit<Tab, 'id' | 'isActive'>) => void
// ...
}
```
### IPC 错误处理
所有 IPC 处理器必须返回统一的响应格式:
```typescript
// 主进程
ipcMain.handle('xxx:action', async (event, params) => {
try {
const result = await doSomething(params)
return { success: true, data: result }
} catch (error: any) {
return { success: false, error: error.message }
}
})
// 渲染进程
const result = await window.electronAPI.xxxAction(params)
if (result.success) {
// 处理成功
} else {
// 处理错误: result.error
}
```
---
## 安全规范
### ✅ 必须遵守
1. **始终启用 contextIsolation**
```typescript
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true, // ✅ 必须
nodeIntegration: false, // ✅ 必须
}
```
2. **通过 preload 暴露 API**
```typescript
// preload.ts - 唯一使用 node 能力的地方
contextBridge.exposeInMainWorld('electronAPI', api)
```
3. **敏感数据加密**
- 所有密码使用 `simpleEncrypt/simpleDecrypt` 加密存储
- 主密钥存储在 `app.getPath('userData')/encryption.key`
- 密钥文件权限设置为 `0o600`
4. **资源清理**
```typescript
app.on('before-quit', () => {
sshService.disconnectAll()
dbService?.close()
})
```
5. **CSP 配置**
```html
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';">
```
### ❌ 禁止行为
1. ❌ 在渲染进程直接使用 `require('ssh2')` 或其他 Node 模块
2. ❌ 暴露 `nodeIntegration: true` 或 `contextIsolation: false`
3. ❌ 明文存储密码或密钥
4. ❌ 忽略 SSH 连接关闭(会导致资源泄漏)
5. ❌ 事件监听不清理(组件卸载时调用 `removeAllListeners`)
---
## 日志与错误处理
### 统一日志系统
使用 `src/utils/logger.ts` 替代 `console.log`:
```typescript
import { createLogger } from '../utils/logger'
const logger = createLogger('ModuleName')
// 使用
logger.debug('调试信息', { detail: 'xxx' })
logger.info('操作成功', { id: 'xxx' })
logger.warn('警告信息')
logger.error('操作失败', error)
```
**日志级别**:
- `DEBUG` - 开发调试信息(生产环境不输出)
- `INFO` - 关键操作记录
- `WARN` - 警告信息
- `ERROR` - 错误信息
### 统一错误处理
使用 `src/utils/error-handler.ts`:
```typescript
import { handleError, createError, ErrorCode } from '../utils/error-handler'
// 1. 转换未知错误
try {
await riskyOperation()
} catch (error) {
const appError = handleError(error, 'context')
// appError.message - 用户友好消息
// appError.recoverable - 是否可恢复
// appError.action - 建议操作
}
// 2. 创建特定错误
const error = createError(ErrorCode.CONNECTION_TIMEOUT, 'detail')
```
**错误码分类**:
- `1xxx` - 连接错误
- `11xx` - SSH 错误
- `12xx` - SFTP 错误
- `13xx` - 会话错误
- `14xx` - 验证错误
- `9xxx` - 系统错误
---
## 数据库架构
SQLite 数据库存储在 `app.getPath('userData')/opsxshell.db`:
### 表结构
```sql
-- 会话表
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
host TEXT NOT NULL,
port INTEGER DEFAULT 22,
username TEXT NOT NULL,
auth_type TEXT CHECK(auth_type IN ('password', 'key', 'agent')),
password TEXT, -- 加密存储
private_key_path TEXT, -- 私钥路径(不加密)
passphrase_encrypted TEXT, -- 私钥密码(加密)
group_name TEXT DEFAULT 'default',
tags TEXT, -- JSON 数组
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 连接历史表
CREATE TABLE connection_history (
id TEXT PRIMARY KEY,
session_id TEXT REFERENCES sessions(id),
connected_at DATETIME DEFAULT CURRENT_TIMESTAMP,
disconnected_at DATETIME,
duration INTEGER,
status TEXT
);
-- 设置表
CREATE TABLE settings (
key TEXT PRIMARY KEY,
value TEXT, -- JSON 格式
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 密钥表
CREATE TABLE keys (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
type TEXT CHECK(type IN ('rsa', 'ed25519', 'ecdsa')),
private_key_encrypted TEXT NOT NULL,
public_key TEXT,
passphrase_encrypted TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 端口转发规则表
CREATE TABLE port_forwards (
id TEXT PRIMARY KEY,
session_id TEXT REFERENCES sessions(id),
type TEXT CHECK(type IN ('local', 'remote', 'dynamic')),
local_host TEXT,
local_port INTEGER,
remote_host TEXT,
remote_port INTEGER,
is_active BOOLEAN DEFAULT FALSE
);
```
---
## 测试策略
### 测试框架
- **测试运行器**: Vitest
- **测试环境**: jsdom
- **断言库**: @testing-library/jest-dom
- **React 测试**: @testing-library/react
### 测试文件位置
```
test/
├── setup.ts # 测试环境配置
├── stores/ # Store 测试
│ ├── tabStore.test.ts
│ └── connectionPool.test.ts
└── components/ # 组件测试
└── sftp/
└── utils.test.ts
```
### 编写测试
```typescript
import { describe, it, expect, beforeEach } from 'vitest'
import { useTabStore } from '../../src/stores/tabStore'
describe('TabStore', () => {
beforeEach(() => {
// Reset store to initial state
useTabStore.setState({
tabs: [{ id: 'welcome', title: '欢迎', type: 'welcome', isActive: true }],
activeTabId: 'welcome',
})
})
it('应该添加新的终端标签', () => {
const { addTab } = useTabStore.getState()
addTab({ title: 'Terminal', type: 'terminal' })
const { tabs } = useTabStore.getState()
expect(tabs).toHaveLength(2)
})
})
```
### Mock Electron API
测试环境中已配置完整的 Electron API mock,详见 `test/setup.ts`。
---
## 开发指南
### 添加新的 IPC 接口
1. **在 `src/electron.d.ts` 添加类型声明**:
```typescript
interface ElectronAPI {
newMethod: (param: string) => Promise<IPCResponse>
}
```
2. **在 `electron/preload.ts` 暴露 API**:
```typescript
const api = {
newMethod: (param: string) => ipcRenderer.invoke('xxx:newMethod', param),
}
```
3. **在 `electron/ipc/` 添加处理器**:
```typescript
// electron/ipc/feature.ipc.ts
export const FEATURE_CHANNELS = {
NEW_METHOD: 'xxx:newMethod',
} as const
export function registerFeatureIPCHandlers(options: Options): void {
ipcMain.handle(FEATURE_CHANNELS.NEW_METHOD, async (event, param) => {
try {
const result = await doSomething(param)
return { success: true, data: result }
} catch (error: any) {
return { success: false, error: error.message }
}
})
}
```
4. **在 `electron/ipc/index.ts` 注册处理器**:
```typescript
import { registerFeatureIPCHandlers } from './feature.ipc'
export function registerAllIPCHandlers(options: IPCOptions): void {
registerFeatureIPCHandlers({ ... })
}
```
### 添加新的 UI 组件
1. 在 `src/components/` 创建组件文件(PascalCase)
2. 如果需要状态,在 `src/stores/` 创建对应的 Store
3. 在 `TabContent.tsx` 添加渲染逻辑(如果是新标签类型)
### 添加终端主题
1. 在 `src/themes/terminal.ts` 添加主题配置:
```typescript
'my-theme': {
name: 'My Theme',
background: '#xxxxxx',
foreground: '#xxxxxx',
// ... 所有必需的颜色
}
```
2. 在 `src/stores/settingsStore.ts` 的 `terminalTheme` 类型中添加新主题
---
## 连接池架构(新)
项目正在迁移到新的连接池架构,位于 `src/stores/connection/`。
### 连接状态
```typescript
type ConnectionState =
| 'disconnected' // 初始/已关闭
| 'connecting' // 正在连接
| 'connected' // 活跃连接
| 'background' // 后台保持
| 'suspended' // 挂起(长时间未操作)
| 'error' // 连接错误
| 'reconnecting' // 正在重连
```
### 使用新的连接管理
```typescript
import { useConnectionStore, getSessionConfig } from '../stores/connection'
// 在组件中使用
const connectionStore = useConnectionStore()
// 创建连接
const result = await connectionStore.createConnection(tabId, config)
// 断开连接
await connectionStore.disconnectConnection(connectionId, 'reason')
```
### 旧版兼容
`src/stores/connectionPool.ts` 提供向后兼容的导出,旧代码仍可继续使用:
```typescript
import { useConnectionPool } from '../stores/connectionPool'
// 实际指向新的实现
```
---
## 常见问题
| 问题 | 解决方案 |
|------|----------|
| 开发时 Electron 无法加载页面 | 确保 Vite 开发服务器在端口 5173 运行 |
| SSH 连接失败 | 检查主机、端口、认证方式配置;查看主进程控制台日志 |
| XTerm.js 显示异常 | 确保容器有明确宽高,调用 `fitAddon.fit()` |
| 数据库初始化失败 | 检查应用数据目录权限 (`app.getPath('userData')`) |
| 加密解密失败 | 检查主密钥文件是否存在且权限正确 |
| 构建后应用白屏 | 检查 `vite.config.ts` 中 `base: './'` 配置 |
| better-sqlite3 构建失败 | 运行 `npm run rebuild` 或 `npx electron-rebuild` |
---
## 参考资源
- [Electron 文档](https://www.electronjs.org/docs)
- [React 文档](https://react.dev)
- [XTerm.js 文档](https://xtermjs.org)
- [ssh2 文档](https://github.com/mscdex/ssh2)
- [Zustand 文档](https://zustand.docs.pmnd.rs)
- [Tailwind CSS 文档](https://tailwindcss.com/docs)
- [better-sqlite3 文档](https://github.com/WiseLibs/better-sqlite3)
- [zmodem-ts 文档](https://github.com/FGasper/zmodem-ts)