修复: 文件系统初始化守卫与传输收尾等七处
- filesystemSvc 守卫17绑定方法,异步初始化完成前返回明确错误 - MovePath 跨盘剪切建 move emitter,失败清理目标盘残留 - SFTP 空目录下载/上传补 MkdirAll 落地 - drawio 下载失败等待者立即返回,不再空轮询30分钟 - batch 高亮补 %1 与 %%i 规则 - 错误文案转换抽 errMessage 共享函数,11处归一 - log.Printf 统一 slog.Warn
This commit is contained in:
@@ -9,6 +9,7 @@ import { HttpTransport } from './http-transport'
|
||||
import { SftpTransport } from './sftp-transport'
|
||||
import { OssTransport } from './oss-transport'
|
||||
import { getFileServerBaseURL } from './file-server'
|
||||
import { errMessage } from '@/utils/errors'
|
||||
import {
|
||||
LoadConnectionProfiles, SaveConnectionProfile, DeleteConnectionProfile,
|
||||
SftpGetSystemInfo, GetLocalSystemInfo,
|
||||
@@ -268,7 +269,7 @@ class ConnectionManagerImpl {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) { info._error = true; info._errorMsg = errMsg(e) }
|
||||
} catch (e) { info._error = true; info._errorMsg = errMessage(e) }
|
||||
|
||||
this._sysInfoCache.set(profileId, info)
|
||||
this._sysInfoChangeCallbacks.forEach(cb => cb(profileId, info))
|
||||
@@ -320,7 +321,7 @@ class ConnectionManagerImpl {
|
||||
} catch (err) {
|
||||
// 回退目标可能已不在池中(死连接重建时 disconnectProfile 先移除),指向池外会让 getTransport 静默回落本地造成 UI 幻影
|
||||
this._activeId = (prevActiveId && this._pool.has(prevActiveId)) ? prevActiveId : 'local-default'
|
||||
this.setProfileState(profileId, 'error', err instanceof Error ? err.message : String(err))
|
||||
this.setProfileState(profileId, 'error', errMessage(err))
|
||||
this.notifyChange()
|
||||
throw err
|
||||
}
|
||||
@@ -433,7 +434,7 @@ class ConnectionManagerImpl {
|
||||
this.fetchSystemInfo(profileId).catch(() => {})
|
||||
} catch (err) {
|
||||
this._pool.delete(profileId)
|
||||
this.setProfileState(profileId, 'error', errMsg(err))
|
||||
this.setProfileState(profileId, 'error', errMessage(err))
|
||||
this.setState('error')
|
||||
throw err
|
||||
}
|
||||
@@ -453,7 +454,7 @@ class ConnectionManagerImpl {
|
||||
this.updateProfile(profileId, { lastConnected: Date.now() })
|
||||
} catch (err) {
|
||||
this._pool.delete(profileId)
|
||||
this.setProfileState(profileId, 'error', errMsg(err))
|
||||
this.setProfileState(profileId, 'error', errMessage(err))
|
||||
this.setState('error')
|
||||
throw err
|
||||
}
|
||||
@@ -474,13 +475,13 @@ class ConnectionManagerImpl {
|
||||
this.updateProfile(profileId, { lastConnected: Date.now() })
|
||||
this.fetchSystemInfo(profileId).catch(() => {})
|
||||
}).catch((e) => {
|
||||
this.setProfileState(profileId, 'error', errMsg(e))
|
||||
this.setProfileState(profileId, 'error', errMessage(e))
|
||||
if (this._activeId !== profileId) return
|
||||
this.setState('error')
|
||||
})
|
||||
} catch (err) {
|
||||
this._pool.delete(profileId)
|
||||
this.setProfileState(profileId, 'error', errMsg(err))
|
||||
this.setProfileState(profileId, 'error', errMessage(err))
|
||||
this.setState('error')
|
||||
throw err
|
||||
}
|
||||
@@ -489,11 +490,6 @@ class ConnectionManagerImpl {
|
||||
|
||||
export const connectionManager = new ConnectionManagerImpl()
|
||||
|
||||
/** 任意抛出值转错误文案 */
|
||||
function errMsg(e: unknown): string {
|
||||
return e instanceof Error ? e.message : String(e)
|
||||
}
|
||||
|
||||
/** snake_case → camelCase */
|
||||
function snakeToCamel(obj: Record<string, any>): Record<string, any> {
|
||||
const result: Record<string, any> = {}
|
||||
|
||||
@@ -155,6 +155,7 @@ import { connectionManager } from '@/api/connection-manager'
|
||||
import { STORAGE_KEYS, DEFAULTS, UI_TEXT, VALIDATION_RULES, FILE_EXTENSIONS, FILE_SIZE_THRESHOLDS } from '@/utils/constants'
|
||||
import { isAutoRestoreDisabled, clearAutoRestoreDisabled } from '@/utils/freezeWatchdog'
|
||||
import { parseWailsEventData } from '@/utils/wailsEvent'
|
||||
import { errMessage } from '@/utils/errors'
|
||||
import { createResizeHandler } from '@/utils/resize'
|
||||
|
||||
// 导入类型
|
||||
@@ -524,7 +525,7 @@ const handleConnectionChanged = async (profileId: string) => {
|
||||
try {
|
||||
await switchConnection(profileId)
|
||||
} catch (err) {
|
||||
Message.error(`连接失败: ${err instanceof Error ? err.message : String(err)}`)
|
||||
Message.error(`连接失败: ${errMessage(err)}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,7 +648,7 @@ const handleOpenFavorite = async (file: FavoriteFile) => {
|
||||
await loadCommonPaths()
|
||||
} catch (e) {
|
||||
console.error('切换连接失败:', e)
|
||||
Message.error(`无法连接: ${e instanceof Error ? e.message : String(e)}`)
|
||||
Message.error(`无法连接: ${errMessage(e)}`)
|
||||
return
|
||||
}
|
||||
} else if (!file.profileId) {
|
||||
@@ -1011,7 +1012,7 @@ const handlePasteClipboard = async () => {
|
||||
} catch (error) {
|
||||
failed++
|
||||
console.error('[Clipboard] 粘贴失败:', item.path, error)
|
||||
Message.error(`粘贴失败: ${item.name} - ${error instanceof Error ? error.message : error}`)
|
||||
Message.error(`粘贴失败: ${item.name} - ${errMessage(error)}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1033,7 +1034,7 @@ const handleDownloadToLocal = async (file: FileItem) => {
|
||||
const localPath = await connectionManager.getTransport().downloadToFile(file.path, dstDir)
|
||||
Message.success(`已下载到: ${localPath}`)
|
||||
} catch (error) {
|
||||
Message.error(`下载失败: ${error instanceof Error ? error.message : error}`)
|
||||
Message.error(`下载失败: ${errMessage(error)}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1067,7 +1068,7 @@ const handleExternalDrop = async (paths: string[]) => {
|
||||
Message.success(`已复制 ${paths.length} 个项目`)
|
||||
}
|
||||
} catch (error) {
|
||||
Message.error(`拖入失败: ${error instanceof Error ? error.message : error}`)
|
||||
Message.error(`拖入失败: ${errMessage(error)}`)
|
||||
await loadDirectory(targetDir)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,8 +108,8 @@ export async function loadLanguageExtension(language) {
|
||||
if (stream.eatSpace()) return null
|
||||
if (stream.match(/^"(?:[^"\r\n]|"")*"?/)) return 'string'
|
||||
if (stream.eat('^')) return 'operator'
|
||||
// !var! 延迟变量、%var% 环境变量、%~d0 类批处理参数
|
||||
if (stream.match(/^!\w+!/) || stream.match(/^%\w+%/) || stream.match(/^%~[a-z]*[\d*]/i)) return 'atom'
|
||||
// !var! 延迟变量、%var% 环境变量、%~d0 类批处理参数、%1 位置参数、%%i for 循环变量
|
||||
if (stream.match(/^!\w+!/) || stream.match(/^%\w+%/) || stream.match(/^%~[a-z]*[\d*]/i) || stream.match(/^%\d/) || stream.match(/^%%\w+/)) return 'atom'
|
||||
if (stream.match(/^\w+/)) {
|
||||
return batchKeywords.has(stream.current().toLowerCase()) ? 'keyword' : null
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 任意抛出值转错误文案(Error 取 message,其余 String 化)
|
||||
*/
|
||||
|
||||
export function errMessage(e: unknown): string {
|
||||
return e instanceof Error ? e.message : String(e)
|
||||
}
|
||||
Reference in New Issue
Block a user