Conversation
There was a problem hiding this comment.
Pull request overview
该 PR 旨在修复 Windows 平台下包含中文路径时的数据库可用性问题:前端不再拦截中文路径(仅非 Windows 继续校验),并在后端 WCDB 访问路径上通过 Junction/短路径等方式尝试规避 DLL 对非 ASCII 路径的限制。
Changes:
- 在 preload + 类型声明中新增
electronAPI.app.getPlatform(),供渲染进程判断平台。 - Welcome/Settings 页的路径校验调整为:仅非 Windows 平台拦截中文路径。
wcdbCore增加 Windows 下的 Junction/8.3 short path 处理,并在 analytics 缓存落盘前确保目录存在。
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types/electron.d.ts | 为 electronAPI.app 增加 getPlatform 类型声明 |
| electron/preload.ts | 暴露 getPlatform() 给渲染进程使用 |
| src/pages/WelcomePage.tsx | 非 Windows 才拦截中文路径;Windows 放行 |
| src/pages/SettingsPage.tsx | 同上:非 Windows 才拦截中文路径 |
| electron/services/wcdbCore.ts | Windows 下新增 Junction + short path + sns.db hardlink 兼容逻辑 |
| electron/services/analyticsService.ts | 写入缓存文件前递归创建目录 |
| package-lock.json | 依赖锁文件变更(含 peer 标记变动) |
Comments suppressed due to low confidence (2)
electron/services/wcdbCore.ts:1590
open()在调用ensureDbJunction()后,如果后续因dbStoragePath不存在 / 找不到session.db/wcdbOpenAccount失败而提前return false,当前不会清理已创建的 junction(只在close()时清理)。建议在open()内对这些失败分支做cleanupDbJunction(),或用try/finally在失败时回收。
const effectiveDbPath = this.ensureDbJunction(dbPath)
const dbStoragePath = this.resolveDbStoragePath(effectiveDbPath, wxid)
this.writeLog(`open dbPath=${dbPath} wxid=${wxid} dbStorage=${dbStoragePath || 'null'}`, true)
if (!dbStoragePath || !existsSync(dbStoragePath)) {
console.error('数据库目录不存在:', dbPath)
this.writeLog(`open failed: dbStorage not found for ${dbPath}`)
lastDllInitError = this.formatInitProtectionError(-3001)
return false
electron/services/wcdbCore.ts:1295
testConnection()现在即使当前已有相同参数的活动连接,也会走“打开测试句柄 -> wcdbShutdown -> 尝试恢复连接”的流程;代码注释也表明 shutdown 会断开当前连接。这可能在设置页反复点“测试连接”时造成不必要的断连/重连。建议恢复“参数完全相同则直接返回成功”的快速路径,避免影响正在使用的连接。
try {
// 记录当前活动连接,用于在测试结束后恢复(避免影响聊天页等正在使用的连接)
const hadActiveConnection = this.handle !== null
const prevPath = this.currentPath
const prevKey = this.currentKey
const prevWxid = this.currentWxid
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // wcdb_status wcdb_cloud_report(const char* stats_json) | ||
| try { | ||
| this.wcdbCloudReport = this.lib.func('int32 wcdb_cloud_report(const char* statsJson)') | ||
| } catch { |
There was a problem hiding this comment.
wcdbCloudInit 的加载失败时把 wcdbCloudReport 置空了,而且当前代码也不再加载 wcdb_cloud_report 符号,这会导致 cloudReport() 永远返回“not supported”。建议分别加载 wcdb_cloud_init / wcdb_cloud_report,并在各自的 catch 中置空对应字段。
| } catch { | |
| } catch { | |
| this.wcdbCloudInit = null | |
| } | |
| // wcdb_status wcdb_cloud_report() | |
| try { | |
| this.wcdbCloudReport = this.lib.func('int32 wcdb_cloud_report()') | |
| } catch { |
| private ensureDbJunction(dbBasePath: string): string { | ||
| if (process.platform !== 'win32') return dbBasePath | ||
| if (!/[^\x00-\x7F]/.test(dbBasePath)) return dbBasePath | ||
| try { | ||
| const mountPoint = join(tmpdir(), 'weflow_db_junc') | ||
| if (this.dbJunctionPath === mountPoint && this.dbJunctionTarget === dbBasePath && existsSync(mountPoint)) { | ||
| return mountPoint | ||
| } | ||
| if (existsSync(mountPoint)) { | ||
| try { rmdirSync(mountPoint) } catch {} | ||
| } | ||
| symlinkSync(dbBasePath, mountPoint, 'junction') | ||
| this.dbJunctionPath = mountPoint |
There was a problem hiding this comment.
ensureDbJunction 把 junction 放在 tmpdir() 下,但 Windows 的临时目录路径本身可能包含中文(例如用户名为中文),这样 mountPoint 仍然是非 ASCII,可能无法达到“让 DLL 获得全 ASCII 路径”的目的。建议把 mountPoint 基于一个可保证 ASCII 的目录(或对 tmpdir() 先取 8.3 short path/另选 ProgramData 等)。
| @@ -1263,15 +1312,16 @@ export class WcdbCore { | |||
|
|
|||
| // 递归查找 session.db | |||
| const sessionDbPath = this.findSessionDb(dbStoragePath) | |||
| this.writeLog(`testConnection sessionDb=${sessionDbPath || 'null'}`) | |||
|
|
|||
| if (!sessionDbPath) { | |||
| return { success: false, error: this.formatInitProtectionError(-3002) } | |||
| } | |||
There was a problem hiding this comment.
testConnection() 调用 ensureDbJunction() 后在多处失败分支直接返回(如 dbStorage/session.db 不存在、openAccount 失败),目前不会清理可能已创建的 junction。建议将 junction 清理放到 finally,并在成功/失败路径都执行回收。
| this.writeLog(`testConnection exception: ${String(e)}`) | ||
| return { success: false, error: this.formatInitProtectionError(-3004) } | ||
| console.error('测试数据库连接异常:', e) | ||
| return { success: false, error: String(e) } |
There was a problem hiding this comment.
testConnection() 的异常兜底现在直接返回 String(e),会丢失此前用 formatInitProtectionError(-3004) 生成的统一错误码/文案;前端(如 WelcomePage)有按 -3001 等错误码做分支处理的逻辑。建议保持返回统一的格式化错误(并可额外记录原始异常到日志)。
| return { success: false, error: String(e) } | |
| return { success: false, error: this.formatInitProtectionError(-3004) } |
| const filePath = this.getCacheFilePath() | ||
| const dir = require('path').dirname(filePath) | ||
| await mkdir(dir, { recursive: true }) |
There was a problem hiding this comment.
这里用 require('path').dirname 与顶部的 ESM import 风格不一致,而且已从 path 引入了 join。建议改为直接从 path import dirname(或复用已有 import),避免在 TS 文件里混用 require。
No description provided.