feat: v0.3.0 版本 - SSH终端、SFTP、端口转发功能实现

核心功能:
- SSH终端: 密码/密钥认证、XTerm.js终端、多主题配色、IP高亮
- SFTP管理: 双栏文件管理、上传下载、传输队列
- 端口转发: 本地/远程转发、SOCKS5动态代理、规则管理

架构改进:
- 拆分大型组件 (SFTPView/TabBar/Sidebar)
- 添加统一日志和错误处理
- 修复React严格模式下的终端黑屏问题

UI更新:
- 新增端口转发视图
- 更新UI预览文档
- 左侧栏右键菜单支持SFTP快捷打开
This commit is contained in:
Logan.Li committed 2026-04-06 01:20:47 +08:00
1 parent cf1c054381
commit 484d850abd
105 files changed
+25330 -64

No files matched your search

+101
View File
@@ -0,0 +1,101 @@
const { contextBridge, ipcRenderer } = require('electron')
// 暴露 API 到渲染进程
const api = {
// SSH 相关
sshConnect: (config: any) => ipcRenderer.invoke('ssh:connect', config),
sshDisconnect: (connectionId: string) => ipcRenderer.invoke('ssh:disconnect', connectionId),
sshExec: (connectionId: string, command: string) => ipcRenderer.invoke('ssh:exec', connectionId, command),
sshCreateShell: (connectionId: string, options?: any, shellId?: string) => ipcRenderer.invoke('ssh:createShell', connectionId, options, shellId),
sshShellWrite: (shellId: string, data: string | Uint8Array) => ipcRenderer.invoke('ssh:shellWrite', shellId, data),
sshShellResize: (shellId: string, cols: number, rows: number) => ipcRenderer.invoke('ssh:shellResize', shellId, cols, rows),
// 会话管理
sessionGetAll: () => ipcRenderer.invoke('session:getAll'),
sessionGetById: (id: string) => ipcRenderer.invoke('session:getById', id),
sessionCreate: (session: any) => ipcRenderer.invoke('session:create', session),
sessionUpdate: (id: string, updates: any) => ipcRenderer.invoke('session:update', id, updates),
sessionDelete: (id: string) => ipcRenderer.invoke('session:delete', id),
// SFTP
sftpConnect: (connectionId: string) => ipcRenderer.invoke('sftp:connect', connectionId),
sftpListDirectory: (sftpId: string, path: string) => ipcRenderer.invoke('sftp:listDirectory', sftpId, path),
sftpUpload: (sftpId: string, localPath: string, remotePath: string) => ipcRenderer.invoke('sftp:upload', sftpId, localPath, remotePath),
sftpDownload: (sftpId: string, remotePath: string, localPath: string) => ipcRenderer.invoke('sftp:download', sftpId, remotePath, localPath),
sftpRename: (sftpId: string, oldPath: string, newPath: string) => ipcRenderer.invoke('sftp:rename', sftpId, oldPath, newPath),
sftpDelete: (sftpId: string, path: string, isDirectory: boolean) => ipcRenderer.invoke('sftp:delete', sftpId, path, isDirectory),
sftpMkdir: (sftpId: string, path: string) => ipcRenderer.invoke('sftp:mkdir', sftpId, path),
// 端口转发
sshForwardLocal: (connectionId: string, localPort: number, remoteHost: string, remotePort: number) =>
ipcRenderer.invoke('ssh:forwardLocal', connectionId, localPort, remoteHost, remotePort),
sshForwardRemote: (connectionId: string, remotePort: number, localHost: string, localPort: number) =>
ipcRenderer.invoke('ssh:forwardRemote', connectionId, remotePort, localHost, localPort),
sshForwardDynamic: (connectionId: string, localPort: number) =>
ipcRenderer.invoke('ssh:forwardDynamic', connectionId, localPort),
// 设置
settingsGet: (key: string) => ipcRenderer.invoke('settings:get', key),
settingsSet: (key: string, value: any) => ipcRenderer.invoke('settings:set', key, value),
// 对话框
showSaveDialog: (options: any) => ipcRenderer.invoke('dialog:showSaveDialog', options),
showOpenDialog: (options: any) => ipcRenderer.invoke('dialog:showOpenDialog', options),
// 文件操作
readFile: (filePath: string) => ipcRenderer.invoke('file:read', filePath),
writeFile: (filePath: string, data: string) => ipcRenderer.invoke('file:write', filePath, data),
// 本地文件系统
getHomePath: () => ipcRenderer.invoke('local:getHome'),
getDownloadsPath: () => ipcRenderer.invoke('app:getDownloadsPath'),
localReadDir: (dirPath: string) => ipcRenderer.invoke('local:readDir', dirPath),
localGetStats: (filePath: string) => ipcRenderer.invoke('local:getStats', filePath),
localDelete: (filePath: string) => ipcRenderer.invoke('local:delete', filePath),
localRename: (oldPath: string, newPath: string) => ipcRenderer.invoke('local:rename', oldPath, newPath),
localMkdir: (dirPath: string) => ipcRenderer.invoke('local:mkdir', dirPath),
// Zmodem rz/sz
zmodemSend: (shellId: string) => ipcRenderer.invoke('zmodem:send', shellId),
zmodemReceive: (shellId: string) => ipcRenderer.invoke('zmodem:receive', shellId),
zmodemCancel: (sessionId: string) => ipcRenderer.invoke('zmodem:cancel', sessionId),
// Zmodem events
onZmodemProgress: (callback: (event: any, sessionId: string, progress: any) => void) => {
ipcRenderer.on('zmodem:progress', callback)
},
onZmodemComplete: (callback: (event: any, sessionId: string, result: any) => void) => {
ipcRenderer.on('zmodem:complete', callback)
},
// 应用信息
getVersion: () => ipcRenderer.invoke('app:getVersion'),
// 事件监听
onMenuNewSession: (callback: () => void) => {
ipcRenderer.on('menu-new-session', callback)
},
onMenuQuickConnect: (callback: () => void) => {
ipcRenderer.on('menu-quick-connect', callback)
},
onMenuImportSessions: (callback: () => void) => {
ipcRenderer.on('menu-import-sessions', callback)
},
onMenuExportSessions: (callback: () => void) => {
ipcRenderer.on('menu-export-sessions', callback)
},
onShellData: (callback: (event: any, connectionId: string, shellId: string, data: Buffer) => void) => {
ipcRenderer.on('ssh:shellData', callback)
},
onSFTPProgress: (callback: (event: any, sftpId: string, progress: any) => void) => {
ipcRenderer.on('sftp:progress', callback)
},
removeListener: (channel: string, callback: (...args: any[]) => void) => {
ipcRenderer.removeListener(channel, callback)
},
removeAllListeners: (channel: string) => {
ipcRenderer.removeAllListeners(channel)
}
}
contextBridge.exposeInMainWorld('electronAPI', api)