feat: v0.3.0 版本 - SSH终端、SFTP、端口转发功能实现
核心功能: - SSH终端: 密码/密钥认证、XTerm.js终端、多主题配色、IP高亮 - SFTP管理: 双栏文件管理、上传下载、传输队列 - 端口转发: 本地/远程转发、SOCKS5动态代理、规则管理 架构改进: - 拆分大型组件 (SFTPView/TabBar/Sidebar) - 添加统一日志和错误处理 - 修复React严格模式下的终端黑屏问题 UI更新: - 新增端口转发视图 - 更新UI预览文档 - 左侧栏右键菜单支持SFTP快捷打开
This commit is contained in:
1 parent
cf1c054381
commit
484d850abd
105 files changed
+25330
-64
No files matched your search
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Connection Types - 统一的连接类型定义
|
||||
* 在主进程和渲染进程间共享
|
||||
*/
|
||||
|
||||
import type { SSHConnectionConfig } from './session.types'
|
||||
|
||||
// Re-export for convenience
|
||||
export type { SSHConnectionConfig as ConnectionConfig } from './session.types'
|
||||
|
||||
// 连接状态
|
||||
export type ConnectionState =
|
||||
| 'disconnected' // 初始/已关闭
|
||||
| 'connecting' // 正在连接
|
||||
| 'connected' // 活跃连接
|
||||
| 'background' // 后台保持
|
||||
| 'suspended' // 挂起 (长时间未操作)
|
||||
| 'error' // 连接错误
|
||||
| 'reconnecting' // 正在重连
|
||||
|
||||
// 连接统计信息
|
||||
export interface ConnectionStats {
|
||||
connectedAt: number // 连接建立时间
|
||||
lastActivityAt: number // 最后活动时间
|
||||
lastBackgroundAt?: number // 进入后台时间
|
||||
bytesTransferred: number // 传输字节数
|
||||
commandsExecuted: number // 执行的命令数 (估算)
|
||||
}
|
||||
|
||||
// 连接池配置
|
||||
export interface PoolConfig {
|
||||
maxConnections: number // 最大连接数 (默认 10)
|
||||
maxBackgroundConnections: number // 最大后台连接数 (默认 5)
|
||||
idleTimeoutMs: number // 空闲超时 (默认 5 分钟)
|
||||
suspendTimeoutMs: number // 挂起超时 (默认 30 分钟)
|
||||
keepaliveIntervalMs: number // 保活间隔 (默认 60 秒)
|
||||
maxReconnectAttempts: number // 最大重连次数 (默认 3)
|
||||
}
|
||||
|
||||
// 连接池中的连接项
|
||||
export interface PooledConnection {
|
||||
connectionId: string
|
||||
config: SSHConnectionConfig
|
||||
state: ConnectionState
|
||||
error?: string
|
||||
|
||||
// 引用管理
|
||||
refCount: number // 引用计数
|
||||
tabIds: Set<string> // 哪些标签在使用这个连接
|
||||
activeTabId: string | null // 当前活跃的标签
|
||||
|
||||
// 会话 ID
|
||||
sessionId?: string
|
||||
|
||||
// Shell/SFTP 会话
|
||||
shellIds: Set<string> // 该连接上创建的 shell 会话
|
||||
sftpIds: Set<string> // 该连接上创建的 sftp 会话
|
||||
|
||||
// 统计
|
||||
stats: ConnectionStats
|
||||
|
||||
// 定时器 ID (浏览器环境)
|
||||
keepaliveInterval?: number // 保活定时器 ID
|
||||
idleTimeout?: number // 空闲超时定时器 ID
|
||||
|
||||
// 重连
|
||||
reconnectAttempts: number // 重连尝试次数
|
||||
maxReconnectAttempts: number // 最大重连次数
|
||||
}
|
||||
|
||||
// 连接结果
|
||||
export interface ConnectionResult {
|
||||
success: boolean
|
||||
connectionId?: string
|
||||
error?: string
|
||||
isExisting?: boolean
|
||||
}
|
||||
|
||||
// Shell 会话信息
|
||||
export interface ShellInfo {
|
||||
shellId: string
|
||||
connectionId: string
|
||||
cols: number
|
||||
rows: number
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Shared Types - 统一类型导出
|
||||
* 在主进程和渲染进程间共享
|
||||
*/
|
||||
|
||||
// Re-export all types
|
||||
export * from './session.types'
|
||||
export * from './connection.types'
|
||||
export * from './sftp.types'
|
||||
export * from './ipc.types'
|
||||
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* IPC Types - 统一的 IPC 类型定义
|
||||
* 定义所有 IPC 请求/响应的类型
|
||||
*/
|
||||
|
||||
import type { Session } from './session.types'
|
||||
|
||||
// ============== SSH IPC ==============
|
||||
|
||||
export interface SSHConnectRequest {
|
||||
host: string
|
||||
port: number
|
||||
username: string
|
||||
password?: string
|
||||
privateKey?: string
|
||||
passphrase?: string
|
||||
}
|
||||
|
||||
export interface SSHConnectResponse {
|
||||
success: boolean
|
||||
connectionId?: string
|
||||
error?: string
|
||||
}
|
||||
|
||||
export interface SSHExecRequest {
|
||||
connectionId: string
|
||||
command: string
|
||||
}
|
||||
|
||||
export interface SSHExecResponse {
|
||||
success: boolean
|
||||
output?: string
|
||||
error?: string
|
||||
}
|
||||
|
||||
export interface SSHCreateShellRequest {
|
||||
connectionId: string
|
||||
cols?: number
|
||||
rows?: number
|
||||
}
|
||||
|
||||
export interface SSHCreateShellResponse {
|
||||
success: boolean
|
||||
shellId?: string
|
||||
error?: string
|
||||
}
|
||||
|
||||
export interface SSHShellWriteRequest {
|
||||
shellId: string
|
||||
data: string
|
||||
}
|
||||
|
||||
export interface SSHShellResizeRequest {
|
||||
shellId: string
|
||||
cols: number
|
||||
rows: number
|
||||
}
|
||||
|
||||
// ============== Port Forward IPC ==============
|
||||
|
||||
export interface SSHForwardLocalRequest {
|
||||
connectionId: string
|
||||
localPort: number
|
||||
remoteHost: string
|
||||
remotePort: number
|
||||
}
|
||||
|
||||
export interface SSHForwardRemoteRequest {
|
||||
connectionId: string
|
||||
remotePort: number
|
||||
localHost: string
|
||||
localPort: number
|
||||
}
|
||||
|
||||
export interface SSHForwardDynamicRequest {
|
||||
connectionId: string
|
||||
localPort: number
|
||||
}
|
||||
|
||||
export interface SSHForwardResponse {
|
||||
success: boolean
|
||||
boundPort?: number
|
||||
error?: string
|
||||
}
|
||||
|
||||
// ============== Session IPC ==============
|
||||
|
||||
export interface SessionCreateResponse {
|
||||
success: boolean
|
||||
session?: Session
|
||||
error?: string
|
||||
}
|
||||
|
||||
export interface SessionUpdateResponse {
|
||||
success: boolean
|
||||
session?: Session
|
||||
error?: string
|
||||
}
|
||||
|
||||
export interface SessionDeleteResponse {
|
||||
success: boolean
|
||||
error?: string
|
||||
}
|
||||
|
||||
// ============== Settings IPC ==============
|
||||
|
||||
export interface SettingsGetRequest {
|
||||
key: string
|
||||
}
|
||||
|
||||
export interface SettingsSetRequest {
|
||||
key: string
|
||||
value: unknown
|
||||
}
|
||||
|
||||
// ============== Dialog IPC ==============
|
||||
|
||||
export interface DialogOptions {
|
||||
title?: string
|
||||
defaultPath?: string
|
||||
filters?: { name: string; extensions: string[] }[]
|
||||
properties?: ('openFile' | 'openDirectory' | 'multiSelections')[]
|
||||
}
|
||||
|
||||
export interface DialogResult {
|
||||
canceled: boolean
|
||||
filePath?: string
|
||||
filePaths?: string[]
|
||||
}
|
||||
|
||||
// ============== File IPC ==============
|
||||
|
||||
export interface FileReadRequest {
|
||||
filePath: string
|
||||
}
|
||||
|
||||
export interface FileWriteRequest {
|
||||
filePath: string
|
||||
data: string
|
||||
}
|
||||
|
||||
export interface FileOperationResponse {
|
||||
success: boolean
|
||||
error?: string
|
||||
}
|
||||
|
||||
export interface FileStats {
|
||||
size: number
|
||||
modified: number
|
||||
isDirectory: boolean
|
||||
isFile: boolean
|
||||
}
|
||||
|
||||
export interface DirEntry {
|
||||
name: string
|
||||
path: string
|
||||
isDirectory: boolean
|
||||
}
|
||||
|
||||
// ============== Zmodem IPC ==============
|
||||
|
||||
export interface ZmodemProgress {
|
||||
sessionId: string
|
||||
fileName: string
|
||||
progress: number
|
||||
bytesTransferred: number
|
||||
totalBytes: number
|
||||
}
|
||||
|
||||
export interface ZmodemComplete {
|
||||
sessionId: string
|
||||
success: boolean
|
||||
fileName?: string
|
||||
error?: string
|
||||
}
|
||||
|
||||
// ============== App IPC ==============
|
||||
|
||||
export interface AppVersionResponse {
|
||||
version: string
|
||||
}
|
||||
|
||||
// ============== IPC Channel Names ==============
|
||||
|
||||
export const IPC_CHANNELS = {
|
||||
// SSH
|
||||
SSH_CONNECT: 'ssh:connect',
|
||||
SSH_DISCONNECT: 'ssh:disconnect',
|
||||
SSH_EXEC: 'ssh:exec',
|
||||
SSH_CREATE_SHELL: 'ssh:createShell',
|
||||
SSH_SHELL_WRITE: 'ssh:shellWrite',
|
||||
SSH_SHELL_RESIZE: 'ssh:shellResize',
|
||||
SSH_FORWARD_LOCAL: 'ssh:forwardLocal',
|
||||
SSH_FORWARD_REMOTE: 'ssh:forwardRemote',
|
||||
SSH_FORWARD_DYNAMIC: 'ssh:forwardDynamic',
|
||||
|
||||
// SFTP
|
||||
SFTP_CONNECT: 'sftp:connect',
|
||||
SFTP_LIST_DIRECTORY: 'sftp:listDirectory',
|
||||
SFTP_UPLOAD: 'sftp:upload',
|
||||
SFTP_DOWNLOAD: 'sftp:download',
|
||||
SFTP_RENAME: 'sftp:rename',
|
||||
SFTP_DELETE: 'sftp:delete',
|
||||
|
||||
// Session
|
||||
SESSION_CREATE: 'session:create',
|
||||
SESSION_GET_ALL: 'session:getAll',
|
||||
SESSION_GET_BY_ID: 'session:getById',
|
||||
SESSION_UPDATE: 'session:update',
|
||||
SESSION_DELETE: 'session:delete',
|
||||
|
||||
// Settings
|
||||
SETTINGS_GET: 'settings:get',
|
||||
SETTINGS_SET: 'settings:set',
|
||||
|
||||
// Dialog
|
||||
DIALOG_SHOW_SAVE: 'dialog:showSaveDialog',
|
||||
DIALOG_SHOW_OPEN: 'dialog:showOpenDialog',
|
||||
|
||||
// App
|
||||
APP_GET_VERSION: 'app:getVersion',
|
||||
APP_GET_DOWNLOADS_PATH: 'app:getDownloadsPath',
|
||||
|
||||
// File
|
||||
FILE_READ: 'file:read',
|
||||
FILE_WRITE: 'file:write',
|
||||
LOCAL_GET_HOME: 'local:getHome',
|
||||
LOCAL_READ_DIR: 'local:readDir',
|
||||
LOCAL_GET_STATS: 'local:getStats',
|
||||
LOCAL_DELETE: 'local:delete',
|
||||
LOCAL_RENAME: 'local:rename',
|
||||
LOCAL_MKDIR: 'local:mkdir',
|
||||
|
||||
// Zmodem
|
||||
ZMODEM_SEND: 'zmodem:send',
|
||||
ZMODEM_RECEIVE: 'zmodem:receive',
|
||||
ZMODEM_CANCEL: 'zmodem:cancel',
|
||||
|
||||
// Events (renderer listens)
|
||||
SHELL_DATA: 'ssh:shellData',
|
||||
SFTP_PROGRESS: 'sftp:progress',
|
||||
ZMODEM_PROGRESS: 'zmodem:progress',
|
||||
ZMODEM_COMPLETE: 'zmodem:complete',
|
||||
MENU_NEW_SESSION: 'menu-new-session',
|
||||
MENU_QUICK_CONNECT: 'menu-quick-connect',
|
||||
MENU_IMPORT_SESSIONS: 'menu-import-sessions',
|
||||
MENU_EXPORT_SESSIONS: 'menu-export-sessions',
|
||||
} as const
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Session Types - 统一的会话类型定义
|
||||
* 在主进程和渲染进程间共享
|
||||
*/
|
||||
|
||||
// 认证方式
|
||||
export type AuthType = 'password' | 'key' | 'agent'
|
||||
|
||||
// 会话配置 (用于快速连接)
|
||||
export interface SSHConnectionConfig {
|
||||
host: string
|
||||
port: number
|
||||
username: string
|
||||
password?: string
|
||||
privateKey?: string
|
||||
passphrase?: string
|
||||
}
|
||||
|
||||
// 持久化会话
|
||||
export interface Session {
|
||||
id: string
|
||||
name: string
|
||||
host: string
|
||||
port: number
|
||||
username: string
|
||||
authType: AuthType
|
||||
password?: string // 加密存储
|
||||
privateKey?: string // 私钥路径或内容
|
||||
passphrase?: string // 私钥密码
|
||||
group?: string
|
||||
tags?: string[]
|
||||
createdAt?: number
|
||||
updatedAt?: number
|
||||
}
|
||||
|
||||
// 会话创建请求
|
||||
export interface SessionCreateRequest {
|
||||
name: string
|
||||
host: string
|
||||
port: number
|
||||
username: string
|
||||
authType: AuthType
|
||||
password?: string
|
||||
privateKey?: string
|
||||
passphrase?: string
|
||||
group?: string
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
// 会话更新请求
|
||||
export type SessionUpdateRequest = Partial<Omit<Session, 'id' | 'createdAt' | 'updatedAt'>>
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* SFTP Types - 统一的 SFTP 类型定义
|
||||
* 在主进程和渲染进程间共享
|
||||
*/
|
||||
|
||||
// 文件项
|
||||
export interface FileItem {
|
||||
name: string
|
||||
path: string
|
||||
type: 'file' | 'directory' | 'symlink'
|
||||
size: number
|
||||
modified: number // Unix timestamp
|
||||
permissions: string
|
||||
}
|
||||
|
||||
// 传输任务
|
||||
export interface TransferTask {
|
||||
id: string
|
||||
type: 'upload' | 'download'
|
||||
fileName: string
|
||||
filePath: string
|
||||
status: 'pending' | 'transferring' | 'completed' | 'failed' | 'canceled'
|
||||
progress: number
|
||||
error?: string
|
||||
total: number
|
||||
transferred: number
|
||||
speed?: number // bytes per second
|
||||
startTime?: number
|
||||
}
|
||||
|
||||
// 传输进度
|
||||
export interface TransferProgress {
|
||||
taskId: string
|
||||
transferred: number
|
||||
total: number
|
||||
speed: number
|
||||
}
|
||||
|
||||
// 文件列表排序
|
||||
export type SortField = 'name' | 'size' | 'modified' | 'type'
|
||||
export type SortOrder = 'asc' | 'desc'
|
||||
|
||||
// SFTP 操作结果
|
||||
export interface SFTPOperationResult {
|
||||
success: boolean
|
||||
error?: string
|
||||
}
|
||||
Reference in new issue
Block a user