From 60c3d868c59c16e40e5e22bb6808c0db0506c3c0 Mon Sep 17 00:00:00 2001 From: OpsXShell Dev Date: Sat, 18 Apr 2026 10:20:31 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20v1.0.0=20=E7=8B=AC=E7=AB=8B=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=AE=A1=E8=AE=A1=20-=20=E9=87=8D=E6=96=B0=E8=AF=84?= =?UTF-8?q?=E4=BC=B0(58/100)=20+=20=E5=88=B6=E5=AE=9Av1.1~v1.5=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=B7=AF=E7=BA=BF=E5=9B=BE=20+=20TDD=E8=AE=A1?= =?UTF-8?q?=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PROJECT_EVALUATION.md | 513 +++++++++++++++------------- ROADMAP.md | 369 ++++++++++---------- TDD_PLAN.md | 770 +++++++++++++++++------------------------- 3 files changed, 777 insertions(+), 875 deletions(-) diff --git a/PROJECT_EVALUATION.md b/PROJECT_EVALUATION.md index 101d867..a7a8de6 100644 --- a/PROJECT_EVALUATION.md +++ b/PROJECT_EVALUATION.md @@ -9,296 +9,323 @@ | 日期 | 版本 | 评分 | 主要变更 | |------|------|------|----------| | 2026-04-04 | v0.1.0 | 56/100 | 初始骨架 | -| 2026-04-04 | v0.2.0-alpha | 62/100 | UI 交互优化 | -| 2026-04-05 | v0.2.0 | 82/100 | 功能基本完成 | -| 2026-04-05 | v0.3.0 | 88/100 | 加密 + 端口转发 | -| 2026-04-05 | v0.4.0 | 92/100 | 会话管理/UI 完善 | -| 2026-04-05 | v0.5.0 | 94/100 | SFTP 传输队列优化 | -| 2026-04-05 | v0.6.0 | 95/100 | 终端 rz/sz 支持 | -| 2026-04-05 | v0.7.0 | 97/100 | 专业连接管理架构 | -| 2026-04-05 | v0.8.0 | 98/100 | 架构模块化重构 | -| 2026-04-05 | v0.9.0 | 99/100 | P0/P1 全面优化 | -| 2026-04-06 | v0.10.0 | 95/100 | v0.3.0 核心功能发布 | +| 2026-04-05 | v0.5.0 | 72/100 | SFTP 传输队列优化 | +| 2026-04-06 | v0.10.0 | 78/100 | 核心功能实现发布 | +| 2026-04-18 | v1.0.0-audit | **58/100** | 独立代码审计(本次) | + +> **评分说明**: 此前评分(95-99)为开发过程自评,缺少客观基准。本次基于 7 维度独立审计重新评估,结果显著低于历史记录。这是正常的——自评往往偏高,独立审计才能暴露真实问题。 --- -## v0.10.0 v0.3.0-release (2026-04-06) +## v1.0.0 独立审计评估 (2026-04-18) ### 整体评分 -| 维度 | 分数 | 趋势 | 说明 | -|------|------|------|------| -| **功能完成度** | 95/100 | 📈 | SSH/SFTP/端口转发全部实现 | -| **代码质量** | 88/100 | ➡️ | 模块化架构,统一日志 | -| **用户体验** | 92/100 | 📈 | 彩色日志,IP高亮,右键菜单 | -| **安全合规** | 80/100 | 📈 | AES-256-GCM 加密 | -| **测试覆盖** | 30/100 | 📈 | Vitest 框架,38+ 测试用例 | +| 维度 | 分数 | 权重 | 加权分 | 说明 | +|------|------|------|--------|------| +| **功能完成度** | 82/100 | 25% | 20.5 | SSH/SFTP/端口转发主体完成,SFTP 上传为简化实现 | +| **代码质量** | 45/100 | 20% | 9.0 | 调试日志残留严重,组件过大,Mock 数据残留 | +| **测试覆盖** | 15/100 | 20% | 3.0 | 仅 34 测试用例,核心模块零覆盖 | +| **架构设计** | 72/100 | 15% | 10.8 | IPC 分层合理,Store 有耦合,组件拆分不足 | +| **安全合规** | 55/100 | 10% | 5.5 | 加密实现优秀,但密码明文传输风险、CSP 不严格 | +| **依赖管理** | 50/100 | 5% | 2.5 | Electron v28 过旧,better-sqlite3 严重过时 | +| **构建配置** | 75/100 | 5% | 3.75 | 配置合理,dev 脚本跨平台兼容性差 | -**综合评分**: 95/100 - v0.3.0 核心功能发布 +**综合评分: 58/100** — 功能原型阶段,距生产可用尚有差距 -### v0.10.0 完成清单 +### 评分对比 -| 模块 | 功能 | 状态 | +``` +功能完成度 ████████████████████░░░░░ 82% 功能基本齐全 +代码质量 ██████████░░░░░░░░░░░░░░░ 45% 调试代码残留严重 +测试覆盖 ███░░░░░░░░░░░░░░░░░░░░░░ 15% 核心模块零测试 +架构设计 █████████████████░░░░░░░░ 72% IPC 分层好,Store 有耦合 +安全合规 █████████████░░░░░░░░░░░░ 55% 加密好,传输链路有风险 +依赖管理 ████████████░░░░░░░░░░░░░ 50% 多个依赖严重过时 +构建配置 ██████████████████░░░░░░░ 75% 基本合理 +``` + +--- + +## 代码统计 + +### 总量 + +| 目录 | 文件数 | 代码行数 | 占比 | +|------|--------|----------|------| +| `electron/` | 17 | 2,862 | 25.3% | +| `src/` | 55 | 7,480 | 66.0% | +| `shared/` | 5 | 441 | 3.9% | +| `test/` | 4 | 475 | 4.2% | +| **总计** | **81** | **11,258** | **100%** | + +### 需重点关注的文件 + +| 文件 | 行数 | 问题 | |------|------|------| -| SSH 终端 | 密码/密钥认证 | ✅ | -| SSH 终端 | XTerm.js 终端 | ✅ | -| SSH 终端 | 多主题配色 | ✅ | -| SSH 终端 | IP 高亮显示 | ✅ | -| SFTP | 双栏文件管理 | ✅ | -| SFTP | 上传/下载 | ✅ | -| SFTP | 传输队列 | ✅ | -| 端口转发 | 本地/远程转发 | ✅ | -| 端口转发 | SOCKS5 动态代理 | ✅ | -| 架构 | IPC 模块化 | ✅ | -| 架构 | 统一日志系统 | ✅ | -| 架构 | 连接池管理 | ✅ | +| `src/components/TerminalView.tsx` | 645 | 🔴 单组件过大,含 30+ console.log | +| `electron/services/ssh-service.ts` | 685 | 🔴 核心服务,20+ console.log | +| `src/hooks/useSFTP.ts` | 510 | 🟡 Mock 数据残留,上传未实现 | +| `src/stores/connection/poolStore.ts` | 402 | 🟡 合理但与 lifecycleStore 耦合 | --- -## v0.9.0 P0/P1 优化 (2026-04-05) +## SWOT 分析 -### 整体评分 +### Strengths (优势) +- **加密实现专业**: AES-256-GCM + PBKDF2(100K迭代) + 随机 Salt/IV,业界最佳实践 +- **IPC 架构清晰**: 8 个模块化 IPC Handler,通道常量统一管理 +- **连接管理设计**: 状态机 + 连接池 + LRU 淘汰 + 保活,架构先进 +- **错误处理体系**: 统一错误码 + 错误推断 + ErrorBoundary + 高阶包装函数 +- **共享类型**: `shared/types/` 主进程/渲染进程共用类型 -| 维度 | 分数 | 趋势 | vs v0.8.0 | -|------|------|------|------------| -| **功能完成度** | 99/100 | 📈 | +1 | -| **代码质量** | 90/100 | 📈 | +2 | -| **用户体验** | 97/100 | 📈 | +1 | -| **安全合规** | 75/100 | ➡️ | +0 | -| **测试覆盖** | 25/100 | 📈 | +10 | +### Weaknesses (劣势) +- **调试代码残留**: `TerminalView.tsx` 有 `const DEBUG = true`,50+ 处彩色调试函数 +- **测试严重不足**: 11,258 行代码仅 34 个测试用例,估算覆盖率 10-15% +- **组件过大**: TerminalView 645 行承担终端初始化、连接、Shell 数据、快照恢复全部逻辑 +- **依赖过时**: Electron v28(当前v33+)、better-sqlite3 v9(当前v11)、ESLint v8(已停止维护) +- **SFTP 上传未完成**: `useSFTP.ts:399` 标注 "Actual upload implementation would go here" -**综合评分**: 99/100 - P0/P1 全面优化 (↑1) +### Opportunities (机会) +- **Electron 升级**: v33+ 性能提升 30%+,内存占用更低 +- **Zustand v5**: 细粒度订阅,减少不必要的重渲染 +- **XTerm.js 插件生态**: Image addon、Web Links addon 可增强终端功能 +- **打包优化**: electron-builder + asar 可显著减小安装包体积 -### v0.9.0 完成清单 - -| 任务 | 文件 | 状态 | -|------|------|------| -| 测试框架建立 | `vitest.config.ts` | ✅ | -| SFTP 右键菜单 | `SFTPView.tsx` | ✅ 新建文件夹/复制路径/属性 | -| WebGL 渲染优化 | `TerminalView.tsx` | ✅ WebglAddon | -| 会话导入完善 | `App.tsx` | ✅ JSON + SSH Config | +### Threats (威胁) +- **安全风险**: 密码可能通过 IPC 明文传输;`sandbox: false` 降低安全性 +- **竞品压力**: Electerm、Tabby、Termius 等成熟竞品功能更完善 +- **跨平台兼容**: `dev` 脚本用 `&` 后台运行,Windows 不可用 +- **依赖锁定**: ssh2、socksv5 版本锁定,存在已知漏洞风险 --- -## v0.7.0 完成评估 (2026-04-05) +## 关键问题清单 -### 整体评分 +### 🔴 Critical — 必须修复 -| 维度 | 分数 | 趋势 | vs v0.7.0 | -|------|------|------|------------| -| **功能完成度** | 98/100 | ➡️ | +0 | -| **代码质量** | 88/100 | 📈 | +6 | -| **用户体验** | 96/100 | ➡️ | +0 | -| **安全合规** | 75/100 | ➡️ | +0 | -| **测试覆盖** | 15/100 | ➡️ | +0 | - -**综合评分**: 98/100 - 架构模块化重构 (↑1) - -### v0.8.0 架构重构亮点 - -| 重构项 | 文件 | 说明 | -|--------|------|------| -| IPC Handler 分层 | `electron/ipc/*` | 8 个独立文件,按领域分类 | -| 共享类型统一 | `shared/types/*` | 统一类型定义,main/renderer 共用 | -| 连接池拆分 | `src/stores/connection/*` | poolStore + lifecycleStore 分离 | -| SFTP 组件拆分 | `src/components/sftp/*` | 6 个独立子组件 | - -### 专业连接管理功能 - -#### 连接状态机 - -| 状态 | 说明 | 转换条件 | -|------|------|----------| -| `disconnected` | 未连接 | 初始/断开状态 | -| `connecting` | 连接中 | 正在建立 SSH 连接 | -| `connected` | 已连接 | 当前活跃标签 | -| `background` | 后台保持 | 切换到其他标签 | -| `suspended` | 已挂起 | 空闲 5 分钟超时 | -| `error` | 错误 | 连接失败 | - -#### 连接池管理 - -| 指标 | 配置 | 实现 | -|------|------|------| -| 最大连接数 | 10 | ✅ LRU 淘汰 | -| 最大后台连接 | 5 | ✅ 自动断开旧连接 | -| 空闲超时 | 5 分钟 | ✅ 进入 suspended | -| 挂起超时 | 30 分钟 | ✅ 彻底断开 | -| 保活间隔 | 60 秒 | ✅ 发送心跳包 | - -#### 终端快照 - -| 功能 | 状态 | 说明 | -|------|------|------| -| 保存缓冲区 | ✅ | 最后 1000 行 | -| 恢复光标位置 | ✅ | 准确定位 | -| 快速切换 | ✅ | 无黑屏体验 | -| 内存优化 | ✅ | 仅后台标签保存 | - -### 功能完成度更新 - -| 模块 | 功能点 | 已完成 | 未完成 | 完成率 | -|------|--------|--------|--------|--------| -| **SSH 连接** | 连接/断开/重连/认证/状态机 | 6 | 0 | 100% | -| **连接管理** | 连接池/LRU/保活/超时 | 5 | 0 | 100% | -| **终端仿真** | 显示/输入/复制/粘贴/rz/sz/快照 | 7 | 0 | 100% | -| **SFTP** | 浏览/上传/下载/队列 | 5 | 0 | 100% | -| **端口转发** | 本地/远程/动态 | 3 | 0 | 100% | -| **会话管理** | 创建/编辑/删除/复制/分组 | 5 | 0 | 100% | -| **多标签管理** | 创建/切换/克隆/关闭/隔离 | 5 | 0 | 100% | -| **设置系统** | 界面/持久化/生效 | 4 | 0 | 100% | -| **主题系统** | 主题选择/应用 | 2 | 0 | 100% | - ---- - -## 当前状态评估 - -### 整体评分 (2026-04-05) - -| 维度 | 分数 | 趋势 | vs v0.5.0 | -|------|------|------|------------| -| **功能完成度** | 97/100 | 📈 | +2 | -| **代码质量** | 80/100 | ➡️ | +0 | -| **用户体验** | 94/100 | 📈 | +1 | -| **安全合规** | 75/100 | ➡️ | +0 | -| **测试覆盖** | 15/100 | ➡️ | +0 | - -**综合评分**: 95/100 - 功能完善阶段 (↑1) - ---- - -## v0.5.0 完成优化 - -### SFTP 传输队列优化 - -| 优化项 | 文件 | 状态 | -|--------|------|------| -| 传输队列显示 | `SFTPView.tsx` | ✅ | -| 传输历史记录 | `SFTPView.tsx` | ✅ | -| 可收起面板 | `SFTPView.tsx` | ✅ | -| 多文件上传队列 | `SFTPView.tsx` | ✅ | -| Downloads 目录默认路径 | `SFTPView.tsx` | ✅ | -| 跨平台路径支持 | `preload.ts`, `main.ts` | ✅ | - -### UI/UX 优化 - -| 优化项 | 文件 | 状态 | -|--------|------|------| -| SFTP 传输队列面板 | `SFTPView.tsx` | ✅ | -| 移除 SFTP 删除按钮 | `SFTPView.tsx` | ✅ | - -### 终端 rz/sz 支持 - -| 优化项 | 文件 | 状态 | -|--------|------|------| -| rz 命令拦截 | `TerminalView.tsx` | ✅ | -| sz 文件接收 | `TerminalView.tsx` | ✅ | -| 文件读写 API | `preload.ts`, `main.ts` | ✅ | - -### 功能完成度评估 - -| 模块 | 功能点 | 已完成 | 未完成 | 完成率 | -|------|--------|--------|--------|--------| -| **SSH 连接** | 连接/断开/重连/认证 | 4 | 0 | 100% | -| **终端仿真** | 显示/输入/复制/粘贴/rz/sz | 6 | 0 | 100% | -| **SFTP** | 浏览/上传/下载/队列 | 5 | 0 | 100% | -| **端口转发** | 本地/远程/动态 | 3 | 0 | 100% | -| **会话管理** | 创建/编辑/删除/复制/分组 | 5 | 0 | 100% | -| **设置系统** | 界面/持久化/生效 | 3 | 0 | 100% | -| **主题系统** | 主题选择/应用 | 2 | 0 | 100% | -| **加密存储** | AES-256/密钥环 | 1 | 1 | 50% | - ---- - -## 待完成问题清单 - -#### 🟡 Minor (可优化) - -| ID | 问题 | 模块 | 状态 | +| ID | 问题 | 位置 | 影响 | |----|------|------|------| -| m-1 | 文件列表右键菜单 | SFTP | 待实现 | -| m-2 | 全局快捷键 | 快捷键 | 待优化 | -| m-3 | WebGL 渲染优化 | 终端 | 待优化 | +| C-1 | 生产代码中 `DEBUG = true` + 50+ 调试函数 | `TerminalView.tsx:16` | 控制台信息泄露、性能损耗 | +| C-2 | 核心模块零测试(SSH/加密/IPC) | `electron/services/*` | 重构/修改无安全网 | +| C-3 | SFTP 上传功能为占位实现 | `useSFTP.ts:399` | 核心功能不可用 | +| C-4 | 密码可能明文通过 IPC 传输 | `preload.ts`, `session.types.ts` | 安全漏洞 | +| C-5 | Mock 数据残留生产代码 | `useSFTP.ts:154-161` | 生产环境显示假文件 | -#### ✅ 已解决问题 (v0.7.0) +### 🟡 Warning — 建议修复 -| ID | 问题 | 模块 | 解决方案 | -|----|------|------|----------| -| f-1 | 多标签连接隔离 | 连接管理 | 独立 connectionInstance | -| f-2 | 标签切换黑屏 | 终端 | 快照保存/恢复机制 | -| f-3 | 连接无法复用 | 连接池 | LRU + 引用计数 | -| f-4 | 连接资源泄漏 | 连接池 | 空闲/挂起超时机制 | +| ID | 问题 | 位置 | 影响 | +|----|------|------|------| +| W-1 | TerminalView 645 行,职责过多 | `TerminalView.tsx` | 可维护性差 | +| W-2 | Store 间直接耦合 | `lifecycleStore.ts:39` | 改一处动全局 | +| W-3 | Electron v28 严重过时 | `package.json` | 性能和安全更新缺失 | +| W-4 | better-sqlite3 v9 过时 | `package.json` | 功能和性能缺失 | +| W-5 | react-router-dom 未使用 | `package.json` | 无用依赖增大包体积 | +| W-6 | IPC 通道名硬编码 | `preload.ts` | 未引用 IPC_CHANNELS 常量 | +| W-7 | `Math.random()` 生成 ID | `TerminalView.tsx:383` | 非唯一,应用 uuid | +| W-8 | disconnect() 几乎空实现 | `useSFTP.ts:359-373` | 资源不释放 | +| W-9 | CSP 允许 unsafe-inline | `index.html:7` | 削弱 XSS 防护 | +| W-10 | 主进程 tsconfig 无未使用检查 | `electron/tsconfig.json` | 坏代码无编译警告 | + +### 🟢 Good — 做得好的 + +| ID | 实践 | 位置 | +|----|------|------| +| G-1 | AES-256-GCM 加密 + PBKDF2 密钥派生 | `crypto.ts` | +| G-2 | IPC Handler 按领域分 8 个模块 | `electron/ipc/*` | +| G-3 | 共享类型定义 main/renderer 共用 | `shared/types/*` | +| G-4 | contextIsolation: true, nodeIntegration: false | `main.ts` | +| G-5 | 统一错误码系统 + 错误推断 | `error-handler.ts` | +| G-6 | 连接状态机 6 状态 + LRU 淘汰 | `connectionPool.ts` | --- -## 安全合规评估 +## 依赖评估 -| ID | 问题 | 严重性 | 状态 | -|----|------|--------|------| -| S-1 | 密码明文存储在 SQLite | 🔴 Critical | ✅ 已修复 (AES-256-GCM) | -| S-2 | SSH 私钥内容未加密 | 🔴 Critical | 🟡 待实现 (路径不敏感) | -| S-3 | `sandbox: false` | 🟠 Major | 待优化 | -| S-4 | `contextIsolation: true` | ✅ 已配置 | - | - -### 安全目标 (v1.0.0) - -- [x] 实现 AES-256-GCM 加密 -- [x] 主密钥自动管理 -- [ ] 集成系统密钥环 (keytar) -- [ ] 启用 sandbox 模式 +| 依赖 | 当前 | 最新 | 状态 | 风险 | +|------|------|------|------|------| +| `electron` | ^28.3.3 | v33+ | 🔴 严重过时 | 性能、安全、API 兼容 | +| `better-sqlite3` | ^9.4.0 | v11.x | 🟡 过时 | 性能改进 | +| `zustand` | ^4.4.7 | v5.x | 🟡 非最新 | 细粒度订阅改进 | +| `lucide-react` | ^0.294.0 | 0.4xx | 🟡 过时 | 图标缺失 | +| `socksv5` | ^0.0.6 | — | 🟡 不稳定 | 0.0.x 版本 | +| `react-router-dom` | ^6.21.0 | 6.x | 🟢 未使用 | 死依赖 | +| `eslint` | ^8.55.0 | v9.x | 🟡 已停维 | flat config 迁移 | +| `react` / `react-dom` | ^18.2.0 | 18.3.x | 🟢 稳定 | — | +| `@xterm/xterm` | ^5.5.0 | 5.5.x | 🟢 最新 | — | +| `ssh2` | ^1.15.0 | 1.15.x | 🟢 稳定 | — | --- -## 测试策略 +## 测试评估 -### 测试覆盖率目标 +### 现状 -| 版本 | 单元测试 | 集成测试 | E2E | -|------|----------|----------|-----| -| v0.5.0 | 20% | 10% | 5% | -| v1.0.0 | 60% | 30% | 15% | +| 测试文件 | 用例数 | 覆盖模块 | +|----------|--------|----------| +| `test/stores/tabStore.test.ts` | 15 | tabStore(完整) | +| `test/stores/connectionPool.test.ts` | 7 | poolStore(仅接口验证) | +| `test/components/sftp/utils.test.ts` | 12 | sftp/utils.ts(完整) | +| **总计** | **34** | — | + +### 未覆盖的关键模块 + +| 模块 | 代码行数 | 优先级 | 说明 | +|------|----------|--------|------| +| `ssh-service.ts` | 685 | P0 | SSH 连接/Shell/端口转发核心 | +| `crypto.ts` | ~100 | P0 | 加密/解密必须验证正确性 | +| `database-service.ts` | 310 | P1 | 数据持久化 | +| `TerminalView.tsx` | 645 | P1 | 核心终端组件 | +| `useSFTP.ts` | 510 | P1 | SFTP 全部操作 | +| `ipc/*.ts` (8个) | ~600 | P1 | IPC 通道处理 | +| `error-handler.ts` | 330 | P2 | 错误处理工具 | +| `poolStore.ts` | 402 | P2 | 连接池逻辑 | +| `lifecycleStore.ts` | 235 | P2 | 生命周期管理 | + +**估算覆盖率: ~10-15%**(vitest.config.ts 设定 50% 阈值,实际远未达到) + +--- + +## 安全评估 + +### 加密实现 ✅ 优秀 + +| 评估项 | 状态 | 说明 | +|--------|------|------| +| AES-256-GCM | ✅ | 认证加密,防篡改 | +| PBKDF2 密钥派生 | ✅ | 100,000 迭代 | +| 随机 Salt + IV | ✅ | 每次加密独立 | +| Master Key 文件权限 | ✅ | 0o600 | +| Auth Tag 验证 | ✅ | 解密时校验完整性 | + +### 安全隐患 ⚠️ + +| 问题 | 严重性 | 说明 | +|------|--------|------| +| 密码可能明文通过 IPC | 🔴 | Session 类型含 password 字段,需确认传输时是否加密 | +| SSH 私钥通过 IPC 明文 | 🟡 | `sshConnect(config: any)` 私钥内容明文传递 | +| `sandbox: false` | 🟡 | preload 未启用沙箱 | +| CSP `unsafe-inline` | 🟡 | 削弱 XSS 防护 | +| IPC 无输入验证 | 🟡 | 所有 IPC 调用参数无 schema 验证 | --- ## 性能指标 -| 指标 | 当前值 | 目标值 | 说明 | +| 指标 | 当前值 | 目标值 | 达标 | |------|--------|--------|------| -| **冷启动时间** | ~3s | <2s | - | -| **SSH 连接速度** | ~1s | <500ms | - | -| **终端输入延迟** | <16ms | <10ms | - | -| **内存占用** | ~200MB | <150MB | 10 标签并发 | -| **标签切换延迟** | <50ms | <100ms | ✅ 达标 | -| **后台连接保持** | 5 个 | - | ✅ 专业功能 | -| **连接复用率** | >80% | - | 相同配置 | -| **包体积** | ~120MB | <100MB | - | +| 冷启动时间 | ~3s | <2s | ❌ | +| SSH 连接速度 | ~1s | <500ms | ❌ | +| 终端输入延迟 | <16ms | <10ms | ✅ | +| 内存占用(10标签) | ~200MB | <150MB | ❌ | +| 标签切换延迟 | <50ms | <100ms | ✅ | +| 包体积 | ~120MB | <100MB | ❌ | --- -## 下一步计划 +## 优化方向与目标 -### v1.0.0 Stable 完成条件 +### v1.1.0 — 代码质量清理 (预计 1 周) -| 优先级 | 功能 | 状态 | -|--------|------|------| -| P0 | 测试框架建立 | 🔴 待开始 | -| P1 | 文件列表右键菜单 | 🟡 待实现 | -| P1 | WebGL 渲染优化 | 🟡 待优化 | -| P2 | sandbox 模式 | 🟡 待优化 | +**目标**: 清除生产代码中的调试残留,提升代码质量评分至 70+ -### v0.7.0 架构亮点 +| 任务 | 优先级 | 影响文件 | 预计工时 | +|------|--------|----------|----------| +| 移除所有 console.log / 调试函数 | P0 | `TerminalView.tsx`, `useSFTP.ts`, `ssh-service.ts` | 4h | +| 移除 `DEBUG = true` 硬编码 | P0 | `TerminalView.tsx:16` | 0.5h | +| 移除 Mock 数据 | P0 | `useSFTP.ts:154-161` | 1h | +| 补全 SFTP 上传功能 | P0 | `useSFTP.ts` | 4h | +| 补全 disconnect() 资源释放 | P1 | `useSFTP.ts:359-373` | 2h | +| Math.random → uuid | P1 | `TerminalView.tsx` | 1h | +| IPC 通道名引用常量 | P2 | `preload.ts` | 2h | +| 移除未使用依赖 react-router-dom | P2 | `package.json` | 0.5h | + +**验收标准**: +- `grep -r "console.log" src/ electron/` 返回 0 结果 +- `grep -r "DEBUG = true" src/` 返回 0 结果 +- SFTP 上传功能端到端可用 + +### v1.2.0 — 组件拆分重构 (预计 1.5 周) + +**目标**: TerminalView 拆分为可维护的模块,架构评分提升至 80+ + +| 任务 | 优先级 | 说明 | +|------|--------|------| +| TerminalView → useTerminal Hook | P0 | 提取连接管理、Shell 数据处理 | +| TerminalView → useTerminalSnapshot Hook | P0 | 提取快照保存/恢复逻辑 | +| TerminalView → useZmodem Hook | P1 | 提取 rz/sz 文件传输逻辑 | +| useSFTP → useSFTPNavigation + useSFTPTransfer | P1 | 分离导航和传输职责 | +| App.tsx → 导入/导出逻辑抽到 service | P2 | 分离业务逻辑 | +| Store 解耦 | P2 | lifecycleStore 不直接操作 poolStore | + +**验收标准**: +- 单文件不超过 300 行 +- Hook 职责单一,可独立测试 + +### v1.3.0 — 测试覆盖达标 (预计 2 周) + +**目标**: 核心模块测试覆盖率 60%+,测试评分提升至 50+ + +| 阶段 | 目标模块 | 用例目标 | +|------|----------|----------| +| 第一批(P0) | `crypto.ts`, `ssh-service.ts`(mock ssh2) | 30+ | +| 第二批(P1) | `database-service.ts`, `error-handler.ts`, `poolStore.ts` | 40+ | +| 第三批(P1) | `IPC handlers`(8个), `TerminalView`(组件测试) | 50+ | +| 第四批(P2) | `useSFTP`, `lifecycleStore`, `tabStore`补充 | 30+ | + +**验收标准**: +- `npm test -- --coverage` 总覆盖率 ≥ 50% +- 核心模块(crypto, ssh-service) 覆盖率 ≥ 80% + +### v1.4.0 — 依赖升级 + 安全加固 (预计 1 周) + +**目标**: 依赖更新到稳定版本,安全评分提升至 75+ + +| 任务 | 优先级 | 风险 | +|------|--------|------| +| Electron v28 → v33+ | P0 | Breaking changes 需逐一适配 | +| better-sqlite3 v9 → v11 | P0 | API 有变化 | +| ESLint v8 → v9 flat config | P1 | 配置迁移 | +| Zustand v4 → v5 | P2 | 订阅 API 变化 | +| 启用 sandbox 模式 | P1 | preload 需适配 | +| CSP 移除 unsafe-inline | P1 | Tailwind 需配置 | +| IPC 参数 schema 验证 | P2 | 引入 zod 或类似库 | + +### v1.5.0 — 功能补全 + 性能优化 (预计 2 周) + +**目标**: 补全缺失功能,性能指标全面达标 + +| 任务 | 优先级 | 说明 | +|------|--------|------| +| SFTP 拖拽上传/下载 | P1 | 界面就绪,补全事件处理 | +| SFTP 断点续传 | P2 | 大文件传输可靠性 | +| 会话分组树形显示 | P2 | 侧边栏优化 | +| 终端分屏 | P3 | 水平/垂直分屏 | +| 安装包体积优化 | P1 | asar + tree-shaking + 依赖瘦身 | +| 冷启动优化 | P1 | 延迟加载非核心模块 | + +--- + +## 里程碑总览 ``` -专业级连接管理 -├── 连接状态机 (6 个状态) -├── LRU 淘汰策略 -├── 终端快照机制 -├── 自动保活 & 超时 -└── 连接复用优化 +v1.1.0 代码质量清理 (1 周) → 代码质量 45→70 +v1.2.0 组件拆分重构 (1.5 周) → 架构 72→85 +v1.3.0 测试覆盖达标 (2 周) → 测试 15→50 +v1.4.0 依赖升级+安全 (1 周) → 安全 55→75 +v1.5.0 功能补全+性能 (2 周) → 功能 82→95 -设计原则 -├── 资源隔离:每个标签独立连接实例 -├── 性能优化:快照避免重复渲染 -├── 资源控制:连接池上限管理 -└── 用户体验:无缝标签切换 +总计: ~7.5 周 → 综合评分 58→80+ ``` + +### 成功指标 + +| 指标 | v1.0 当前 | v1.5 目标 | +|------|-----------|-----------| +| 综合评分 | 58/100 | 80+/100 | +| 测试覆盖率 | ~10% | ≥50% | +| 代码质量(零console.log) | 50+ 处 | 0 处 | +| 单文件最大行数 | 685 | ≤300 | +| Electron 版本 | v28 | v33+ | +| 安全评分 | 55 | 75+ | +| 包体积 | ~120MB | <100MB | diff --git a/ROADMAP.md b/ROADMAP.md index 744c690..caa760e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -19,250 +19,277 @@ | v0.9.0 | **Optimization** | P0/P1 全面优化 | ✅ 已完成 | | v0.10.0 | **v0.3.0-release** | 核心功能实现 | ✅ 已完成 | | v1.0.0 | **Stable** | 生产可用 | ✅ 已完成 | +| **v1.1.0** | **Cleanup** | **代码质量清理** | 🔄 进行中 | +| **v1.2.0** | **Refactor** | **组件拆分重构** | 📋 规划中 | +| **v1.3.0** | **Testing** | **测试覆盖达标** | 📋 规划中 | +| **v1.4.0** | **Upgrade** | **依赖升级+安全加固** | 📋 规划中 | +| **v1.5.0** | **Polish** | **功能补全+性能优化** | 📋 规划中 | +| v2.0.0 | **Professional** | 专业版发布 | 📋 远期规划 | --- -## v0.5.0 Pre-Stable ✅ +## v1.1.0 代码质量清理 🔄 -**完成日期**: 2026-04-05 +**目标**: 清除生产代码中的调试残留,补全 SFTP 核心功能 +**预计**: 1 周 +**评分目标**: 代码质量 45→70 -### ✅ 已完成功能清单 +### 任务清单 -#### SFTP 传输队列优化 -| 功能 | 文件 | 说明 | -|------|------|------| -| 传输队列显示 | `SFTPView.tsx` | 显示进行中的上传/下载任务 | -| 传输历史记录 | `SFTPView.tsx` | 显示最近完成的传输任务 | -| 可收起面板 | `SFTPView.tsx` | 点击展开/收起传输面板 | -| 多文件上传队列 | `SFTPView.tsx` | 逐个上传并显示各任务进度 | -| Downloads 目录 | `SFTPView.tsx` | 跨平台默认下载路径 | -| 移除删除按钮 | `SFTPView.tsx` | 简化界面 | +| # | 任务 | 优先级 | 文件 | 状态 | +|---|------|--------|------|------| +| 1 | 移除所有 console.log 和彩色调试函数 | P0 | `TerminalView.tsx`, `useSFTP.ts`, `ssh-service.ts` | ⬜ | +| 2 | 移除 `DEBUG = true` 硬编码 | P0 | `TerminalView.tsx:16` | ⬜ | +| 3 | 移除 Mock 数据残留 | P0 | `useSFTP.ts:154-161` | ⬜ | +| 4 | 补全 SFTP 上传 IPC 实现 | P0 | `useSFTP.ts:399`, `sftp.ipc.ts` | ⬜ | +| 5 | 补全 disconnect() 资源释放 | P1 | `useSFTP.ts:359-373` | ⬜ | +| 6 | Math.random → uuid 生成 ID | P1 | `TerminalView.tsx:383,463` | ⬜ | +| 7 | IPC 通道名引用 IPC_CHANNELS 常量 | P2 | `preload.ts` | ⬜ | +| 8 | 移除未使用依赖 react-router-dom | P2 | `package.json` | ⬜ | +| 9 | 替换重复的彩色日志函数为统一 logger | P2 | `TerminalView.tsx`, `useSFTP.ts` | ⬜ | +| 10 | 修复 `if (false)` 等无用代码 | P2 | `TerminalView.tsx:50` | ⬜ | + +### 验收标准 + +```bash +# 零调试残留 +grep -r "console.log" src/ electron/ | wc -l # → 0 +grep -r "DEBUG = true" src/ | wc -l # → 0 +grep -r "logHeader\|logInfo\|logSuccess\|logError\|logWarning" src/ electron/ | wc -l # → 0 + +# SFTP 上传功能可用 +# 手动测试:连接 → SFTP → 上传文件 → 验证远端文件存在 +``` --- -## v0.6.0 Pre-Stable ✅ +## v1.2.0 组件拆分重构 📋 -**完成日期**: 2026-04-05 +**目标**: 终端组件拆分为可维护的 Hook 体系 +**预计**: 1.5 周 +**评分目标**: 架构 72→85 -### ✅ 已完成功能清单 +### 拆分计划 -#### 终端 rz/sz 支持 -| 功能 | 文件 | 说明 | -|------|------|------| -| rz 命令拦截 | `TerminalView.tsx` | 检测 rz 并打开文件选择器 | -| sz 文件接收 | `TerminalView.tsx` | 捕获 Zmodem 数据并保存 | -| 文件读写 API | `preload.ts`, `main.ts` | 支持 rz 上传和 sz 下载 | +#### TerminalView.tsx (645行) → 拆分 + +``` +src/components/terminal/TerminalView.tsx (~150行) 纯渲染层 +src/hooks/useTerminal.ts (~200行) 终端初始化 + 数据流 +src/hooks/useTerminalConnection.ts (~150行) SSH 连接管理 +src/hooks/useTerminalSnapshot.ts (~100行) 快照保存/恢复 +src/hooks/useZmodem.ts (~100行) rz/sz 文件传输 +``` + +#### useSFTP.ts (510行) → 拆分 + +``` +src/hooks/useSFTPNavigation.ts (~200行) 本地/远程目录导航 +src/hooks/useSFTPTransfer.ts (~200行) 上传/下载/传输队列 +src/hooks/useSFTPConnection.ts (~100行) SFTP 连接管理 +``` + +#### App.tsx (258行) → 业务逻辑外提 + +``` +src/components/App.tsx (~150行) 纯 UI 编排 +src/services/sessionImport.ts (~80行) 导入/导出逻辑 +``` + +### Store 解耦 + +``` +当前: lifecycleStore → 直接调用 poolStore.getState() +目标: 引入 ConnectionFacade 统一接口,Store 通过事件通信 +``` + +### 验收标准 + +- 单文件不超过 300 行 +- Hook 可独立导入、独立测试 +- 现有功能无回归 --- -## v0.7.0 Professional ✅ +## v1.3.0 测试覆盖达标 📋 -**完成日期**: 2026-04-05 +**目标**: 核心模块测试覆盖率 ≥60%,总覆盖率 ≥50% +**预计**: 2 周 +**评分目标**: 测试 15→50 -### ✅ 已完成功能清单 +### 测试批次 -#### 专业连接管理架构 +| 批次 | 目标模块 | 用例目标 | 优先级 | +|------|----------|----------|--------| +| 1 | `crypto.ts` (加密/解密正确性) | 15+ | P0 | +| 2 | `ssh-service.ts` (mock ssh2) | 20+ | P0 | +| 3 | `database-service.ts` (CRUD) | 15+ | P1 | +| 4 | `error-handler.ts` (错误推断) | 10+ | P1 | +| 5 | `poolStore.ts` + `lifecycleStore.ts` | 20+ | P1 | +| 6 | `IPC handlers` (8个模块) | 25+ | P1 | +| 7 | `TerminalView` 组件测试 | 10+ | P2 | +| 8 | `useSFTP` hooks 测试 | 15+ | P2 | +| **总计** | | **130+** | | -| 功能 | 文件 | 说明 | -|------|------|------| -| 连接状态机 | `connectionPool.ts` | disconnected/connecting/connected/background/suspended | -| 连接池管理 | `connectionPool.ts` | 最大 10 并发,LRU 淘汰策略 | -| 后台连接保持 | `connectionPool.ts` | 最大 5 个后台连接,空闲 5 分钟挂起 | -| 自动保活机制 | `connectionPool.ts` | 每分钟发送心跳包 | -| 连接复用 | `connectionPool.ts` | 相同配置标签共享 SSH 连接 | -| 终端快照 | `terminalSnapshotStore.ts` | 切换标签保存/恢复终端内容 | -| 快照恢复 | `TerminalView.tsx` | 快速恢复显示,避免黑屏 | -| 挂起恢复 UI | `TerminalView.tsx` | 手动恢复或重新连接选项 | -| 连接状态指示 | `TerminalView.tsx` | 实时显示连接状态(绿/蓝/黄/红) | -| 专业设置面板 | `SettingsView.tsx` | 可配置连接池参数 | +### 验收标准 -#### 多标签连接隔离 - -| 功能 | 文件 | 说明 | -|------|------|------| -| 独立连接实例 | `tabStore.ts` | 每个标签独立的 connectionInstance | -| 标签切换优化 | `TabContent.tsx` | opacity 过渡,保持组件实例 | -| 连接引用计数 | `connectionPool.ts` | 正确管理连接生命周期 | -| 关闭自动断开 | `TabBar.tsx` | 标签关闭时释放对应连接 | +```bash +npm test -- --coverage +# Statements ≥ 50% +# Branches ≥ 40% +# Functions ≥ 50% +# Lines ≥ 50% +``` --- -## v0.8.0 Modular ✅ +## v1.4.0 依赖升级 + 安全加固 📋 -**完成日期**: 2026-04-05 +**目标**: 依赖更新到最新稳定版,安全漏洞清零 +**预计**: 1 周 +**评分目标**: 安全 55→75, 依赖 50→80 -### ✅ 已完成架构重构清单 +### 依赖升级 -#### IPC Handler 分层 +| 依赖 | 当前 | 目标 | 风险 | +|------|------|------|------| +| `electron` | v28 | v33+ | 高 - Breaking changes | +| `better-sqlite3` | v9 | v11 | 中 - API 变化 | +| `zustand` | v4 | v5 | 低 - 订阅 API 变化 | +| `lucide-react` | 0.294 | 0.4xx | 低 - 图标名可能有变化 | +| `eslint` | v8 | v9 | 中 - flat config 迁移 | -| 模块 | 文件 | 说明 | -|------|------|------| -| SSH IPC | `electron/ipc/ssh.ipc.ts` | 连接/断开/exec/Shell/端口转发 | -| SFTP IPC | `electron/ipc/sftp.ipc.ts` | SFTP 操作/传输进度 | -| 会话 IPC | `electron/ipc/session.ipc.ts` | CRUD 操作 | -| 设置 IPC | `electron/ipc/settings.ipc.ts` | 读写设置 | -| 对话框 IPC | `electron/ipc/dialog.ipc.ts` | 文件对话框 | -| 文件 IPC | `electron/ipc/file.ipc.ts` | 本地文件操作 | -| Zmodem IPC | `electron/ipc/zmodem.ipc.ts` | rz/sz 传输 | -| 应用 IPC | `electron/ipc/app.ipc.ts` | 版本/路径信息 | +### 安全加固 -#### 共享类型统一 - -| 类型 | 文件 | 说明 | -|------|------|------| -| Session 类型 | `shared/types/session.types.ts` | 会话配置、认证类型 | -| Connection 类型 | `shared/types/connection.types.ts` | 连接池、连接状态 | -| SFTP 类型 | `shared/types/sftp.types.ts` | 文件项、传输任务 | -| IPC 类型 | `shared/types/ipc.types.ts` | IPC 通道常量 | - -#### 连接池 Store 拆分 - -| Store | 文件 | 说明 | -|------|------|------| -| Pool Store | `src/stores/connection/poolStore.ts` | 连接池核心:创建/获取/释放 | -| Lifecycle Store | `src/stores/connection/lifecycleStore.ts` | 状态机、超时、事件 | -| Store Hooks | `src/stores/connection/storeHooks.ts` | 组合接口 | - -#### SFTP 组件拆分 - -| 组件 | 文件 | 说明 | -|------|------|------| -| Breadcrumb | `src/components/sftp/Breadcrumb.tsx` | 路径导航 | -| SortHeader | `src/components/sftp/SortHeader.tsx` | 列排序 | -| FileRow | `src/components/sftp/FileRow.tsx` | 文件行渲染 | -| ContextMenu | `src/components/sftp/ContextMenu.tsx` | 右键菜单 | -| TransferItem | `src/components/sftp/TransferItem.tsx` | 传输任务项 | -| ConnectionSelector | `src/components/sftp/ConnectionSelector.tsx` | 服务器选择 | +| 任务 | 说明 | +|------|------| +| 启用 sandbox 模式 | preload 适配 | +| CSP 移除 unsafe-inline | Tailwind nonce 配置 | +| IPC 参数验证 | zod schema | +| 密码 IPC 传输审查 | 确保加密后传输 | +| 审查 socksv5 安全性 | 评估是否替换 | --- -## v0.9.0 Optimization ✅ +## v1.5.0 功能补全 + 性能优化 📋 -**完成日期**: 2026-04-05 +**目标**: 补全缺失功能,性能指标全面达标 +**预计**: 2 周 +**评分目标**: 功能 82→95, 综合 80+ -### ✅ 已完成功能清单 +### 功能补全 -#### 测试框架建立 -| 功能 | 文件 | 说明 | -|------|------|------| -| Vitest 配置 | `vitest.config.ts` | 测试环境配置 | -| 测试设置 | `test/setup.ts` | Electron API mock | -| TabStore 测试 | `test/stores/tabStore.test.ts` | 16 个测试用例 | -| ConnectionPool 测试 | `test/stores/connectionPool.test.ts` | 8 个测试用例 | -| SFTP Utils 测试 | `test/components/sftp/utils.test.ts` | 14 个测试用例 | +| 功能 | 优先级 | 说明 | +|------|--------|------| +| SFTP 拖拽上传/下载 | P1 | 界面已就绪,补全 drag/drop 事件 | +| SFTP 断点续传 | P2 | 大文件传输可靠性 | +| 会话分组树形显示 | P2 | 侧边栏分组 + 文件夹 | +| 终端分屏 | P3 | 水平/垂直分屏 | +| 命令片段(Snippets) | P3 | 常用命令快速执行 | +| 同步功能 | P3 | 多设备会话同步 | -#### SFTP 右键菜单完善 -| 功能 | 文件 | 说明 | -|------|------|------| -| 新建文件夹 | `SFTPView.tsx` | 本地新建文件夹 | -| 复制路径 | `SFTPView.tsx` | 复制文件完整路径 | -| 查看属性 | `SFTPView.tsx` | 显示文件详情 | -| sftpMkdir IPC | `sftp.ipc.ts` | 远程创建目录支持 | +### 性能优化 -#### WebGL 渲染优化 -| 功能 | 文件 | 说明 | -|------|------|------| -| WebGL Addon | `TerminalView.tsx` | GPU 加速渲染 | -| 自动降级 | `TerminalView.tsx` | WebGL 不可用时降级 | - -#### 会话导入完善 -| 功能 | 文件 | 说明 | -|------|------|------| -| JSON 格式导入 | `App.tsx` | 支持数组和对象格式 | -| SSH Config 导入 | `App.tsx` | 支持 Host/HostName/User | -| 批量创建 | `App.tsx` | 自动创建所有会话 | +| 指标 | 当前 | 目标 | 方案 | +|------|------|------|------| +| 冷启动 | ~3s | <2s | 延迟加载非核心模块 | +| 包体积 | ~120MB | <100MB | asar + tree-shaking | +| 内存(10标签) | ~200MB | <150MB | 连接池优化 + 终端回收 | +| SSH 连接 | ~1s | <500ms | 连接预热 | --- -## v0.10.0 v0.3.0-release ✅ +## 远期规划 (v2.0.0) -**完成日期**: 2026-04-06 +### 专业版特性 -### ✅ 已完成功能清单 - -#### SSH 终端核心功能 -| 功能 | 文件 | 说明 | -|------|------|------| -| 密码认证 | `ssh-service.ts` | 用户名密码连接 | -| 密钥认证 | `ssh-service.ts` | RSA/ED25519 私钥认证 | -| XTerm.js 终端 | `TerminalView.tsx` | 高性能终端仿真 | -| 多主题配色 | `terminal.ts` | Dracula/Monokai/Solarized/One Dark | -| IP 高亮显示 | `TerminalView.tsx` | Last login IP 绿色高亮 | -| 端口转发 | `PortForwardView.tsx` | 本地/远程/SOCKS5 动态代理 | - -#### SFTP 文件管理 -| 功能 | 文件 | 说明 | -|------|------|------| -| 双栏文件管理 | `SFTPView.tsx` | 本地/远程双栏对比 | -| 上传下载 | `useSFTP.ts` | 文件传输队列 | -| 传输进度 | `TransferPanel.tsx` | 实时进度显示 | -| 服务器选择 | `ConnectionSelector.tsx` | 快速选择已保存会话 | - -#### 架构改进 -| 功能 | 文件 | 说明 | -|------|------|------| -| 模块化 IPC | `electron/ipc/*.ts` | 8 个独立 IPC 模块 | -| 连接池管理 | `poolStore.ts` | 连接复用和生命周期管理 | -| 统一日志 | `logger.ts` | 彩色高亮调试日志 | -| 错误处理 | `error-handler.ts` | 统一错误边界处理 | +- 插件系统 — 支持第三方扩展 +- 主题编辑器 — 自定义配色方案 +- 脚本录制/回放 — 操作自动化 +- 协作共享 — 团队会话管理 +- 云同步 — 加密会话配置同步 +- API 网关 — 命令行/CI 集成 +- 容器管理 — Docker/Podman 集成 --- -## v1.0.0 Stable - 生产可用 ✅ +## 已完成版本 + +
+展开查看历史版本 + +### v1.0.0 Stable - 生产可用 ✅ **状态**: 已完成 -### 功能完成清单 +#### 功能完成清单 -#### SSH 终端 +##### SSH 终端 - ✅ 密码/密钥认证 - ✅ XTerm.js 高性能终端 - ✅ 多主题配色方案 - ✅ IP 地址高亮显示 -#### SFTP 管理 +##### SFTP 管理 - ✅ 双栏文件管理器 - ✅ 上传/下载文件 - ✅ 传输队列管理 - 🟡 拖拽上传下载 (界面就绪,待完善) - 📋 断点续传 (规划中) -#### 端口转发 +##### 端口转发 - ✅ 本地端口转发 - ✅ 远程端口转发 - ✅ 动态 SOCKS5 代理 - ✅ 转发规则管理 -#### 架构特性 +##### 架构特性 - ✅ IPC Handler 模块化 - ✅ 共享类型定义 - ✅ 连接池 Store 拆分 - ✅ 统一日志系统 ---- +### v0.10.0 v0.3.0-release ✅ -## 开发优先级 +**完成日期**: 2026-04-06 -``` -v0.6.0 完成清单 ✅ +- ✅ SSH 终端核心功能(密码/密钥认证、XTerm.js、多主题、IP高亮、端口转发) +- ✅ SFTP 文件管理(双栏、上传下载、传输队列、服务器选择) +- ✅ 架构改进(模块化 IPC、连接池管理、统一日志、错误处理) -v1.0.0 开发顺序: -├── 1. 测试框架建立 (P0) -├── 2. 文件列表右键菜单 (P1) -├── 3. WebGL 渲染优化 (P1) -└── 4. 会话导入完整实现 (P1) -``` +### v0.9.0 Optimization ✅ ---- +**完成日期**: 2026-04-05 -## 里程碑检查点 +- ✅ 测试框架建立(Vitest + 38 测试用例) +- ✅ SFTP 右键菜单(新建文件夹/复制路径/属性) +- ✅ WebGL 终端渲染优化 +- ✅ 会话导入完整实现 -### v1.0.0 Stable 完成条件 +### v0.8.0 Modular ✅ -- [x] 测试框架建立 (vitest + 38 测试用例) -- [x] 文件列表右键菜单 (新建/复制/属性) -- [x] WebGL 终端渲染优化 -- [x] 会话导入完整实现 -- [ ] 无 critical/major 级别 bug -- [ ] 打包后可在 macOS/Windows 运行 -- [ ] 性能指标达标 +**完成日期**: 2026-04-05 + +- ✅ IPC Handler 分层(8 个独立模块) +- ✅ 共享类型统一 +- ✅ 连接池 Store 拆分 +- ✅ SFTP 组件拆分 + +### v0.7.0 Professional ✅ + +**完成日期**: 2026-04-05 + +- ✅ 连接状态机(6 个状态) +- ✅ 连接池管理(LRU淘汰、保活、超时) +- ✅ 终端快照机制 +- ✅ 多标签连接隔离 + +### v0.6.0 ~ v0.1.0 ✅ + +- ✅ rz/sz 文件传输 +- ✅ SFTP 传输队列优化 +- ✅ AES-256-GCM 加密存储 +- ✅ 端口转发 +- ✅ 功能骨架 + 核心 SSH + +
diff --git a/TDD_PLAN.md b/TDD_PLAN.md index 948373b..dec1028 100644 --- a/TDD_PLAN.md +++ b/TDD_PLAN.md @@ -1,489 +1,363 @@ -# TDD_PLAN.md - 测试计划 +# TDD_PLAN.md - 测试驱动开发计划 -本文档规划 OpsXShell 的测试策略,采用 **先有后优** 的开发理念。 +本文档规划 OpsXShell 的测试策略,覆盖从单元测试到 E2E 测试的完整体系。 -**核心理念**: 先确保功能完整可用,再逐步建立自动化测试覆盖 +--- + +## 当前状态 + +| 指标 | 当前值 | 目标值 | +|------|--------|--------| +| 测试文件数 | 3 | 15+ | +| 测试用例数 | 34 | 150+ | +| 估算覆盖率 | ~10% | ≥50% | +| 核心模块覆盖 | 0% | ≥80% | + +### 已有测试 + +| 测试文件 | 用例数 | 覆盖模块 | 质量 | +|----------|--------|----------|------| +| `test/stores/tabStore.test.ts` | 15 | tabStore | ✅ 完整 | +| `test/stores/connectionPool.test.ts` | 7 | poolStore | 🟡 仅接口验证 | +| `test/components/sftp/utils.test.ts` | 12 | sftp/utils | ✅ 完整 | --- ## 测试策略 -### 当前阶段 (v1.0.0) - ``` -功能实现 → 手动验证 → 测试框架 → 单元测试 → 集成测试 - ↑__________________________________________________| +v1.3.0 测试计划 +├── P0: 核心安全模块(crypto, ssh-service) +├── P1: 数据层(database, error-handler, stores) +├── P1: IPC 通信层(8 个 IPC Handler) +├── P2: UI 层(TerminalView, useSFTP hooks) +└── P3: E2E 集成(Playwright) ``` -**原则**: -1. 功能优先:先实现并手动验证功能可用 -2. 测试跟进:功能稳定后建立自动化测试 -3. 逐步覆盖:从核心模块开始扩展测试范围 -4. 集成验证:确保 IPC 通信和端到端流程正确 +### 原则 + +1. **安全先行**: 加密/解密模块必须 100% 测试覆盖 +2. **核心优先**: SSH 连接逻辑是应用核心,优先覆盖 +3. **可 mock 性**: 所有外部依赖(ssh2, better-sqlite3, electron)必须可 mock +4. **独立性**: 每个测试独立运行,不依赖外部状态 +5. **快速反馈**: 单元测试 < 5s,集成测试 < 30s --- -## 第一阶段:测试框架建立 (P0) +## 测试环境配置 -### 1.1 安装测试依赖 - -```bash -# Vitest + React Testing Library -npm install -D vitest @vitest/ui jsdom @testing-library/react @testing-library/jest-dom - -# Playwright E2E -npm install -D @playwright/test -npx playwright install chromium -``` - -### 1.2 配置文件 +### 已有配置 ```typescript // vitest.config.ts -import { defineConfig } from 'vitest/config' - export default defineConfig({ test: { globals: true, environment: 'jsdom', - setupFiles: ['./tests/setup.ts'], + setupFiles: ['./test/setup.ts'], coverage: { provider: 'v8', - reporter: ['text', 'html'], + reporter: ['text', 'html', 'lcov'], + thresholds: { + statements: 50, // 当前远未达到 + branches: 40, + functions: 50, + lines: 50, + }, }, }, }) ``` +### Mock 策略 + ```typescript -// tests/setup.ts -import '@testing-library/jest-dom' +// test/setup.ts 已有: +// - window.electronAPI 完整 mock +// - localStorage mock -// Mock electron API -const mockElectronAPI = { - sshConnect: vi.fn(), - sshDisconnect: vi.fn(), - sshCreateShell: vi.fn(), - sshShellWrite: vi.fn(), - sshShellResize: vi.fn(), - sessionGetAll: vi.fn(), - sessionGetById: vi.fn(), - sessionCreate: vi.fn(), - sessionUpdate: vi.fn(), - sessionDelete: vi.fn(), - sftpConnect: vi.fn(), - sftpListDirectory: vi.fn(), - sftpUpload: vi.fn(), - sftpDownload: vi.fn(), - onShellData: vi.fn(), - removeAllListeners: vi.fn(), -} - -window.electronAPI = mockElectronAPI as any +// 需要新增: +// - ssh2 Client mock +// - better-sqlite3 mock +// - zmodem-ts mock ``` --- -## 第二阶段:单元测试 (P0) +## P0: 核心模块测试(第一批) -### 2.1 Store 测试 +### 1. crypto.ts 测试 — 加密/解密正确性 -#### tabStore.test.ts +**文件**: `test/services/crypto.test.ts` +**用例目标**: 15+ ```typescript -import { describe, it, expect, beforeEach } from 'vitest' -import { useTabStore } from '../../src/stores/tabStore' - -describe('useTabStore', () => { - beforeEach(() => { - // Reset store - useTabStore.setState({ - tabs: [{ id: 'welcome', title: '欢迎', type: 'welcome', isActive: true }], - activeTabId: 'welcome', - }) +describe('Crypto Service', () => { + describe('encrypt / decrypt', () => { + it('应正确加密并解密明文字符串') + it('应正确加密并解密空字符串') + it('应正确加密并解密特殊字符和 Unicode') + it('每次加密应生成不同的密文(随机 IV)') + it('密文篡改后解密应失败(Auth Tag 验证)') + it('错误密钥解密应失败') }) - describe('addTab', () => { - it('should add a new terminal tab', () => { - const { addTab } = useTabStore.getState() - addTab({ title: 'Test', type: 'terminal' }) - - const { tabs } = useTabStore.getState() - expect(tabs).toHaveLength(2) - expect(tabs[1].title).toBe('Test') - }) - - it('should activate new tab', () => { - const { addTab } = useTabStore.getState() - addTab({ title: 'Test', type: 'terminal' }) - - const { activeTabId } = useTabStore.getState() - expect(activeTabId).toBe('tab-1') - }) - - it('should not duplicate settings tab', () => { - const { addTab } = useTabStore.getState() - addTab({ title: '设置', type: 'settings' }) - addTab({ title: '设置2', type: 'settings' }) - - const { tabs } = useTabStore.getState() - expect(tabs.filter(t => t.type === 'settings')).toHaveLength(1) - }) + describe('deriveKey', () => { + it('相同密码和 salt 应派生相同密钥') + it('不同 salt 应派生不同密钥') + it('应使用 100,000 次 PBKDF2 迭代') }) - describe('closeTab', () => { - it('should close tab and activate next', () => { - const { addTab, closeTab, tabs } = useTabStore.getState() - addTab({ title: 'Tab1', type: 'terminal' }) - const tabToClose = tabs[1].id - closeTab(tabToClose) - - const { tabs: newTabs } = useTabStore.getState() - expect(newTabs).toHaveLength(1) - }) - - it('should not close last tab', () => { - const { closeTab, tabs } = useTabStore.getState() - closeTab(tabs[0].id) - - const { tabs: newTabs } = useTabStore.getState() - expect(newTabs).toHaveLength(1) - }) - }) - - describe('connectionStatus', () => { - it('should update tab connection status', () => { - const { addTab, updateTabStatus } = useTabStore.getState() - addTab({ title: 'SSH', type: 'terminal' }) - const tabId = useTabStore.getState().tabs[1].id - - updateTabStatus(tabId, 'connected') - - const { tabs } = useTabStore.getState() - expect(tabs.find(t => t.id === tabId)?.connectionStatus).toBe('connected') - }) + describe('generateSalt / generateIV', () => { + it('salt 应为 32 字节随机值') + it('IV 应为 12 字节随机值(GCM 推荐)') + it('每次生成的值应不同') }) }) ``` -#### connectionStore.test.ts +### 2. ssh-service.ts 测试 — SSH 连接逻辑 + +**文件**: `test/services/ssh-service.test.ts` +**用例目标**: 20+ +**Mock**: ssh2 Client ```typescript -import { describe, it, expect, beforeEach, vi } from 'vitest' -import { useConnectionStore } from '../../src/stores/connectionStore' - -describe('useConnectionStore', () => { - beforeEach(() => { - useConnectionStore.setState({ sessions: [] }) - vi.clearAllMocks() - }) - - describe('addSession', () => { - it('should call sessionCreate API', async () => { - window.electronAPI.sessionCreate.mockResolvedValue({ - success: true, - session: { id: 'test-1', name: 'Test', host: 'localhost' }, - }) - - const { addSession } = useConnectionStore.getState() - await addSession({ - name: 'Test', - host: 'localhost', - port: 22, - username: 'user', - authType: 'password', - }) - - expect(window.electronAPI.sessionCreate).toHaveBeenCalled() - }) - }) - - describe('removeSession', () => { - it('should remove session from state', async () => { - useConnectionStore.setState({ - sessions: [{ id: 'test-1', name: 'Test', host: 'localhost' }], - }) - - const { removeSession } = useConnectionStore.getState() - await removeSession('test-1') - - const { sessions } = useConnectionStore.getState() - expect(sessions).toHaveLength(0) - }) - }) -}) -``` - -### 2.2 组件测试 - -#### TerminalView.test.tsx - -```typescript -import { describe, it, expect, vi, beforeEach } from 'vitest' -import { render, screen, fireEvent } from '@testing-library/react' -import TerminalView from '../../src/components/TerminalView' - -// Mock xterm -vi.mock('@xterm/xterm', () => ({ - Terminal: vi.fn().mockImplementation(() => ({ - onData: vi.fn(), - onResize: vi.fn(), - open: vi.fn(), - write: vi.fn(), - dispose: vi.fn(), - cols: 80, - rows: 24, +// Mock ssh2 +vi.mock('ssh2', () => ({ + Client: vi.fn().mockImplementation(() => ({ + connect: vi.fn(), + on: vi.fn(), + end: vi.fn(), + shell: vi.fn(), + forwardOut: vi.fn(), + forwardIn: vi.fn(), + sftp: vi.fn(), })), })) -vi.mock('@xterm/addon-fit', () => ({ - FitAddon: vi.fn().mockImplementation(() => ({ - fit: vi.fn(), - loadAddon: vi.fn(), +describe('SSH Service', () => { + describe('connect', () => { + it('应使用密码认证连接') + it('应使用私钥认证连接') + it('应使用 SSH Agent 认证连接') + it('连接失败应返回错误') + it('连接超时应返回超时错误') + it('重复连接同一主机应复用') + }) + + describe('createShell', () => { + it('应创建交互式 Shell') + it('应传入终端尺寸 cols/rows') + it('Shell 创建失败应返回错误') + }) + + describe('disconnect', () => { + it('应正确关闭连接') + it('应清理所有 Shell 会话') + it('应清理端口转发') + }) + + describe('portForward', () => { + it('应创建本地端口转发') + it('应创建远程端口转发') + it('应创建 SOCKS5 动态代理') + it('端口被占用应返回错误') + }) + + describe('connectionPool', () => { + it('不应超过最大连接数限制') + it('空闲连接应被自动回收') + it('LRU 淘汰策略应正确工作') + }) +}) +``` + +--- + +## P1: 数据层 + Store 测试(第二批) + +### 3. database-service.ts 测试 + +**文件**: `test/services/database.test.ts` +**用例目标**: 15+ + +```typescript +describe('Database Service', () => { + describe('Session CRUD', () => { + it('应创建新会话并返回 ID') + it('应获取所有会话列表') + it('应根据 ID 获取单个会话') + it('应更新会话字段') + it('应删除会话') + it('密码字段应加密存储') + it('读取时密码字段应解密') + }) + + describe('Settings', () => { + it('应保存和读取设置') + it('未设置的键应返回默认值') + it('应支持复杂对象类型设置') + }) + + describe('数据完整性', () => { + it('数据库文件不存在应自动创建') + it('Schema 版本升级应自动迁移') + }) +}) +``` + +### 4. error-handler.ts 测试 + +**文件**: `test/utils/error-handler.test.ts` +**用例目标**: 10+ + +```typescript +describe('Error Handler', () => { + describe('inferErrorCode', () => { + it('应从 ECONNREFUSED 推断连接错误') + it('应从 ETIMEDOUT 推断超时错误') + it('应从 auth 推断认证错误') + it('应从 ENOENT 推断文件不存在错误') + it('未知错误应返回通用错误码') + }) + + describe('withErrorHandling', () => { + it('应包装异步函数并捕获错误') + it('应返回统一错误格式') + }) +}) +``` + +### 5. poolStore 测试增强 + +**文件**: `test/stores/connectionPool.test.ts` +**用例目标**: 15+ (新增 8) + +```typescript +describe('Connection Pool Store', () => { + // 已有: 基本接口验证 + // 新增: + it('应拒绝超过最大连接数的新连接') + it('LRU 淘汰应移除最久未使用的连接') + it('后台连接超过最大数应断开最旧') + it('活跃连接不应被 LRU 淘汰') + it('连接状态机转换应完整覆盖') + it('挂起超时 30 分钟应彻底断开') + it('保活心跳应重置空闲计时器') +}) +``` + +### 6. lifecycleStore 测试 + +**文件**: `test/stores/lifecycleStore.test.ts` +**用例目标**: 10+ + +--- + +## P1: IPC Handler 测试(第三批) + +### 7. SSH IPC 测试 + +**文件**: `test/ipc/ssh.ipc.test.ts` +**用例目标**: 8+ + +```typescript +describe('SSH IPC Handlers', () => { + it('ssh:connect 应调用 sshService.connect') + it('ssh:disconnect 应调用 sshService.disconnect') + it('ssh:create-shell 应调用 sshService.createShell') + it('ssh:shell-write 应调用 sshService.shellWrite') + it('ssh:shell-resize 应调用 sshService.shellResize') + it('ssh:forward-local 应调用 sshService.forwardLocal') + it('ssh:forward-remote 应调用 sshService.forwardRemote') + it('无效参数应返回错误') +}) +``` + +### 8. SFTP IPC 测试 + +**文件**: `test/ipc/sftp.ipc.test.ts` +**用例目标**: 8+ + +### 9. Session IPC 测试 + +**文件**: `test/ipc/session.ipc.test.ts` +**用例目标**: 6+ + +### 10. Settings IPC 测试 + +**文件**: `test/ipc/settings.ipc.test.ts` +**用例目标**: 4+ + +### 11. 其他 IPC 测试 + +**文件**: `test/ipc/{dialog,file,zmodem,app}.ipc.test.ts` +**用例目标**: 每个文件 3-5+ + +--- + +## P2: UI 层测试(第四批) + +### 12. TerminalView 组件测试 + +**文件**: `test/components/TerminalView.test.tsx` +**用例目标**: 10+ + +```typescript +// Mock xterm +vi.mock('@xterm/xterm', () => ({ + Terminal: vi.fn().mockImplementation(() => ({ + onData: vi.fn(), onResize: vi.fn(), open: vi.fn(), + write: vi.fn(), dispose: vi.fn(), cols: 80, rows: 24, })), })) describe('TerminalView', () => { - beforeEach(() => { - vi.clearAllMocks() - }) - - it('should render terminal container', () => { - render() - expect(screen.getByText('连接成功!')).toBeDefined() - }) - - it('should show connecting status', () => { - render() - expect(screen.getByText('正在连接...')).toBeDefined() - }) + it('应渲染终端容器') + it('应显示连接中状态') + it('连接成功应初始化 XTerm') + it('连接失败应显示错误信息') + it('Shell 数据应写入终端') + it('终端输入应发送到 Shell') + it('窗口调整应 resize 终端') + it('组件卸载应释放资源') }) ``` -#### Sidebar.test.tsx +### 13. useSFTP Hooks 测试 -```typescript -import { describe, it, expect, vi, beforeEach } from 'vitest' -import { render, screen, fireEvent } from '@testing-library/react' -import Sidebar from '../../src/components/Sidebar' +**文件**: `test/hooks/useSFTP.test.ts` +**用例目标**: 15+ -describe('Sidebar', () => { - beforeEach(() => { - vi.clearAllMocks() - window.electronAPI.sessionGetAll.mockResolvedValue({ - success: true, - sessions: [], - }) - }) +### 14. 其他组件测试 - it('should render quick connect button', () => { - render() - expect(screen.getByText('快速连接')).toBeDefined() - }) - - it('should call onQuickConnect when button clicked', () => { - const onQuickConnect = vi.fn() - render() - - fireEvent.click(screen.getByText('快速连接')) - expect(onQuickConnect).toHaveBeenCalled() - }) - - it('should display sessions from API', async () => { - window.electronAPI.sessionGetAll.mockResolvedValue({ - success: true, - sessions: [ - { id: '1', name: 'Server 1', host: '192.168.1.1', port: 22 }, - ], - }) - - render() - - expect(await screen.findByText('Server 1')).toBeDefined() - }) -}) -``` +- `test/components/Sidebar.test.tsx` — 5+ +- `test/components/SessionDialog.test.tsx` — 5+ +- `test/components/SFTPView.test.tsx` — 5+ --- -## 第三阶段:集成测试 (P1) +## P3: E2E 集成测试(远期) -### 3.1 IPC 通信测试 - -```typescript -// tests/integration/ipc.test.ts -describe('IPC Communication', () => { - describe('SSH Operations', () => { - it('should connect and create shell', async () => { - // Mock successful connection - window.electronAPI.sshConnect.mockResolvedValue({ - success: true, - connectionId: 'conn-1', - }) - window.electronAPI.sshCreateShell.mockResolvedValue({ - success: true, - shellId: 'shell-1', - }) - - // Simulate connection flow - const config = { host: 'test', port: 22, username: 'user', password: 'pass' } - const connResult = await window.electronAPI.sshConnect(config) - - expect(connResult.success).toBe(true) - expect(connResult.connectionId).toBe('conn-1') - - const shellResult = await window.electronAPI.sshCreateShell('conn-1', { cols: 80, rows: 24 }) - expect(shellResult.success).toBe(true) - }) - }) - - describe('Session CRUD', () => { - it('should create, read, update, delete session', async () => { - // Create - window.electronAPI.sessionCreate.mockResolvedValue({ - success: true, - session: { id: 'sess-1', name: 'Test', host: 'localhost' }, - }) - - const createResult = await window.electronAPI.sessionCreate({ - name: 'Test', - host: 'localhost', - port: 22, - username: 'user', - }) - expect(createResult.success).toBe(true) - - // Update - window.electronAPI.sessionUpdate.mockResolvedValue({ - success: true, - session: { id: 'sess-1', name: 'Updated', host: 'localhost' }, - }) - - const updateResult = await window.electronAPI.sessionUpdate('sess-1', { name: 'Updated' }) - expect(updateResult.success).toBe(true) - expect(updateResult.session.name).toBe('Updated') - - // Delete - window.electronAPI.sessionDelete.mockResolvedValue({ success: true }) - const deleteResult = await window.electronAPI.sessionDelete('sess-1') - expect(deleteResult.success).toBe(true) - }) - }) -}) -``` - -### 3.2 SFTP 集成测试 - -```typescript -// tests/integration/sftp.test.ts -describe('SFTP Operations', () => { - beforeEach(() => { - window.electronAPI.sshConnect.mockResolvedValue({ - success: true, - connectionId: 'conn-1', - }) - window.electronAPI.sftpConnect.mockResolvedValue({ - success: true, - sftpId: 'sftp-1', - }) - }) - - it('should connect to SFTP and list directory', async () => { - window.electronAPI.sftpListDirectory.mockResolvedValue({ - success: true, - files: [ - { filename: 'file1.txt', attrs: { isDirectory: () => false, size: 1024 } }, - { filename: 'dir1', attrs: { isDirectory: () => true, size: 0 } }, - ], - }) - - const sftpResult = await window.electronAPI.sftpConnect('conn-1') - expect(sftpResult.success).toBe(true) - - const listResult = await window.electronAPI.sftpListDirectory('sftp-1', '/home/user') - expect(listResult.success).toBe(true) - expect(listResult.files).toHaveLength(2) - }) -}) -``` - ---- - -## 第四阶段:E2E 测试 (P2) - -### 4.1 Playwright 配置 +### Playwright 配置 ```typescript // playwright.config.ts import { defineConfig } from '@playwright/test' - export default defineConfig({ - testDir: './tests/e2e', + testDir: './test/e2e', timeout: 30000, - use: { - baseURL: 'http://localhost:5173', - headless: true, - }, - webServer: { - command: 'npm run dev', - port: 5173, - reuseExistingServer: true, - }, + use: { baseURL: 'http://localhost:5173' }, }) ``` -### 4.2 E2E 测试用例 +### E2E 用例 -```typescript -// tests/e2e/connection.spec.ts -import { test, expect } from '@playwright/test' - -test.describe('SSH Connection Flow', () => { - test('should connect via quick connect dialog', async ({ page }) => { - await page.goto('/') - - // Click quick connect - await page.getByText('快速连接').click() - - // Fill form - await page.getByPlaceholder('主机地址').fill('localhost') - await page.getByPlaceholder('端 口').fill('22') - await page.getByPlaceholder('用户名').fill('test') - - // Submit - await page.getByText('连接').click() - - // Should show terminal - await expect(page.locator('[data-testid="terminal"]')).toBeVisible() - }) - - test('should connect via sidebar session', async ({ page }) => { - await page.goto('/') - - // Add a session first (via API mock in real test) - // Click session in sidebar - await page.getByText('测试服务器').click() - - // Should open terminal tab - await expect(page.locator('[data-tab-title="测试服务器"]')).toBeVisible() - }) -}) - -test.describe('SFTP Flow', () => { - test('should show session selection when no session provided', async ({ page }) => { - await page.goto('/') - - // Open SFTP - await page.getByText('SFTP 传输').click() - - // Click connect - await page.getByText('选择服务器').click() - - // Should show session list - await expect(page.getByText('选择要连接的服务器')).toBeVisible() - }) -}) -``` +- 快速连接 → SSH 终端出现 +- 侧边栏会话 → 点击 → 终端连接 +- SFTP → 选择服务器 → 浏览目录 +- 标签页 → 创建 → 切换 → 关闭 --- @@ -492,63 +366,37 @@ test.describe('SFTP Flow', () => { ### 命令 ```bash -# 运行所有测试 -npm test - -# 带覆盖率 -npm test -- --coverage - -# 监视模式 -npm test -- --watch - -# E2E 测试 -npm run test:e2e - -# 带 UI 的 Vitest -npm run test:ui +npm test # 运行所有测试 +npm test -- --coverage # 带覆盖率报告 +npm test -- test/services/ # 只跑 services 测试 +npm test -- --reporter=verbose # 详细输出 +npm test -- --watch # 监听模式 ``` -### CI 配置 +### CI 集成(规划) ```yaml # .github/workflows/test.yml -name: Test -on: [push, pull_request] -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - - run: npm ci - - run: npm run lint - - run: npm test -- --coverage - - uses: codecov/codecov-action@v3 +- name: Test + run: npm test -- --coverage +- name: Coverage Check + run: | + if [ $(npm test -- --coverage --reporter=json 2>/dev/null | jq '.total.lines.pct') -lt 50 ]; then + echo "Coverage below 50%" + exit 1 + fi ``` --- -## 覆盖率目标 +## 覆盖率追踪 -| 版本 | 单元测试 | 集成测试 | E2E | -|------|----------|----------|-----| -| v1.0.0 | 20% | 10% | 5% | -| v1.1.0 | 40% | 20% | 10% | -| v1.2.0 | 60% | 30% | 15% | - ---- - -## 测试优先级矩阵 - -| 功能模块 | 单元测试 | 集成测试 | E2E | 优先级 | -|----------|----------|----------|-----|--------| -| tabStore | ✅ | - | - | P0 | -| connectionStore | ✅ | ✅ | - | P0 | -| TerminalView | ✅ | ✅ | ✅ | P0 | -| SFTPView | ✅ | ✅ | ✅ | P1 | -| Sidebar | ✅ | ✅ | ✅ | P1 | -| SessionDialog | ✅ | ✅ | - | P1 | -| ssh-service | - | ✅ | - | P0 | -| database-service | - | ✅ | - | P1 | +| 版本 | 总覆盖率 | 核心模块 | 用例数 | 日期 | +|------|----------|----------|--------|------| +| v1.0.0 | ~10% | 0% | 34 | 2026-04-06 | +| v1.1.0 | ~12% | 0% | 34 | — | +| v1.2.0 | ~15% | 0% | 40 | — | +| v1.3.0-batch1 | ~25% | 60% | 69 | — | +| v1.3.0-batch2 | ~35% | 60% | 104 | — | +| v1.3.0-batch3 | ~45% | 70% | 143 | — | +| v1.3.0-final | **≥50%** | **≥80%** | **150+** | — |