From cb3c2855c0510554a1b4ba71b751aa02a3b2a114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B5=E6=91=87=E5=B0=8F=E5=AD=90?= <969409112@qq.com> Date: Sun, 26 Jul 2026 20:46:51 +0800 Subject: [PATCH] =?UTF-8?q?fix(paths):=20=E5=90=8C=E6=AD=A5=20imageKeyRoot?= =?UTF-8?q?=20=E4=B8=8E=20dbRoot=EF=BC=8C=E4=BB=85=E8=AF=86=E5=88=AB=20xwe?= =?UTF-8?q?chat=5Ffiles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 之前的状态面板(chat.getCurrentAccountRoot())和自动获取图片密钥(settings.imageKeyRoot) 走两个完全不同的来源,二者漂移导致状态显示 D 盘但实际扫描到 C 盘。 index.ts: - key:autoGetImageKey 优先级调整为 chat.getCurrentAccountRoot() → self.accountRoot → settings.imageKeyRoot → settings.dbRoot,让运行时识别的目录永远最优先。 - db:init:保存 dbRoot 时同步更新 imageKeyRoot,避免 settings 缓存漂移。 - db:reopenWithRoot:用户手动切换根目录时同步更新 imageKeyRoot。 settings-store.ts: - loadSettings:dbRoot 修正时同步 imageKeyRoot;若 imageKeyRoot 指向旧路径或不存在, 回退到 dbRoot。 - 新增 redirectLegacyWeChatFilesToXwechat():当 settings 里的 dbRoot/imageKeyRoot 仍指向 V3 时代的 "Documents\WeChat Files" 路径时,自动重定向到同目录下的 xwechat_files(如果存在)。 老用户升级时无需手动迁移。 wcdb4-client / windows-db-root-discovery / key-service-win: - 候选目录列表只保留 xwechat_files 形态(Documents\xwechat_files、 AppData\Roaming\Tencent\xwechat_files、macOS 的 Library/Containers/.../xwechat_files), 移除 V3 时代的 "WeChat Files" 候选。 - DB_ROOT_NAMES 只包含 xwechat_files,自动扫描也只认 V4 路径。 V3 数据(V1 头 dat / WeChat Files 目录结构)如果用户机器上还存在,仅作为残留, 不会被 WechatExplorer 当成有效数据源。 --- src/main/index.ts | 20 ++++++++++++++-- src/main/services/settings-store.ts | 33 ++++++++++++++++++++++++--- src/main/wcdb4-client.ts | 3 +-- src/main/windows-db-root-discovery.ts | 3 ++- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 2e572f2..74a44d3 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -297,7 +297,12 @@ app.whenReady().then(async () => { const nextWechatDb = await WechatDb.create(key, settings.dbRoot) const resolvedRoot = nextWechatDb.getWcdb4Client().getAccountRoot() if (resolvedRoot && resolvedRoot !== settings.dbRoot) { - saveSettings({ ...settings, dbRoot: resolvedRoot }) + // 同步更新 imageKeyRoot,避免自动获取图片密钥时扫描到错误目录 + saveSettings({ + ...settings, + dbRoot: resolvedRoot, + imageKeyRoot: resolvedRoot + }) } chat.setChatDb(nextWechatDb) const wcdb4Client = nextWechatDb.getWcdb4Client() @@ -411,7 +416,13 @@ app.whenReady().then(async () => { ipcMain.handle('key:autoGetImageKey', async (event, options?: { save?: boolean }) => { const settings = loadSettings() const self = chat.getSelfAccountInfo() - const accountRoot = settings.imageKeyRoot || self?.accountRoot || settings.dbRoot + // 优先级:chat 真实识别到的根 → self.accountRoot → settings.imageKeyRoot → settings.dbRoot + // 必须先看 chat.getCurrentAccountRoot(),否则 settings 缓存漂移会导致扫错目录。 + const accountRoot = + chat.getCurrentAccountRoot() || + self?.accountRoot || + settings.imageKeyRoot || + settings.dbRoot const wxid = self?.wxid const onStatus = (message: string): void => { if (!event.sender.isDestroyed()) event.sender.send('key:imageKeyStatus', { message }) @@ -788,6 +799,11 @@ app.whenReady().then(async () => { ipcMain.handle('db:reopenWithRoot', (_, accountRoot: string) => { const ok = chat.reopenWithRoot(accountRoot) if (!ok) return { success: false, error: '数据库未初始化或重新打开失败' } + // 同步 imageKeyRoot,避免自动获取扫描到旧目录 + const settings = loadSettings() + if (accountRoot && accountRoot !== settings.imageKeyRoot) { + saveSettings({ ...settings, imageKeyRoot: accountRoot }) + } const info = chat.getSelfAccountInfo() return { success: true, info } }) diff --git a/src/main/services/settings-store.ts b/src/main/services/settings-store.ts index 5d6a61e..fc135c5 100644 --- a/src/main/services/settings-store.ts +++ b/src/main/services/settings-store.ts @@ -4,6 +4,22 @@ import path from 'path' import os from 'os' import { discoverWindowsDbRoots } from '../windows-db-root-discovery' +/** + * 把 V3 时代的 "...\\Documents\\WeChat Files" 路径重定向到 + * "...\\Documents\\xwechat_files"(V4)。如果 xwechat_files 不存在则保留原值。 + * 仅支持 WeChat 4.0:自动纠正用户机器上残留的旧路径。 + */ +function redirectLegacyWeChatFilesToXwechat(candidate: string): string { + if (!candidate) return candidate + const normalized = candidate.replace(/[\\/]+$/, '') + const lowered = normalized.toLowerCase() + const legacyMarker = `${path.sep}wechat files` + if (!lowered.endsWith(legacyMarker)) return candidate + const redirected = `${normalized.slice(0, -legacyMarker.length)}${path.sep}xwechat_files` + if (fs.existsSync(redirected)) return redirected + return candidate +} + export interface AppSettings { dbRoot: string apiEnabled: boolean @@ -25,16 +41,17 @@ function getDefaultDbRoot(): string { function getDefaultDbRootCandidates(home: string): string[] { if (process.platform !== 'win32') { + // macOS 仅支持 WeChat 4.0 路径(xwechat_files) return [ path.join(home, 'Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files') ] } + // 仅支持 WeChat 4.0:剔除 V3 时代的 "WeChat Files" 目录, + // 只认 xwechat_files(含 Documents\ 和 AppData\Roaming\Tencent\ 两种合法位置)。 const candidates = [ ...getWeflowDbPathCandidates(home), - path.join(home, 'Documents', 'WeChat Files'), path.join(home, 'Documents', 'xwechat_files'), - path.join(home, 'WeChat Files'), path.join(os.homedir(), 'AppData', 'Roaming', 'Tencent', 'xwechat_files') ] @@ -123,9 +140,19 @@ export function loadSettings(): AppSettings { if (process.platform === 'win32' && !isUsableDbRoot(cache.dbRoot)) { cache.dbRoot = getDefaultDbRoot() } - if (!cache.imageKeyRoot) { + // 同步:imageKeyRoot 必须跟随 dbRoot 更新, + // 否则自动获取会扫错目录(旧 bug:状态面板显示 D 盘,自动获取扫 C 盘)。 + if (!cache.imageKeyRoot || !isUsableDbRoot(cache.imageKeyRoot)) { cache.imageKeyRoot = cache.dbRoot } + // V4-only 兜底:如果 imageKeyRoot 指向旧的 "WeChat Files"(V3 路径), + // 重定向到同一父目录下的 xwechat_files(V4)。 + if (cache.imageKeyRoot) { + cache.imageKeyRoot = redirectLegacyWeChatFilesToXwechat(cache.imageKeyRoot) + } + if (cache.dbRoot) { + cache.dbRoot = redirectLegacyWeChatFilesToXwechat(cache.dbRoot) + } return cache } } catch (error) { diff --git a/src/main/wcdb4-client.ts b/src/main/wcdb4-client.ts index dcf065f..e10504d 100644 --- a/src/main/wcdb4-client.ts +++ b/src/main/wcdb4-client.ts @@ -311,11 +311,10 @@ export class Wcdb4Client { private static getDefaultRootCandidates(): string[] { const home = os.homedir() if (process.platform === 'win32') { + // 仅支持 WeChat 4.0:只认 xwechat_files,V3 时代的 "WeChat Files" 不再加入候选 const candidates = [ ...Wcdb4Client.getWeflowDbPathCandidates(home), - path.join(home, 'Documents', 'WeChat Files'), path.join(home, 'Documents', 'xwechat_files'), - path.join(home, 'WeChat Files'), path.join(home, 'AppData', 'Roaming', 'Tencent', 'xwechat_files') ] candidates.push(...discoverWindowsDbRoots()) diff --git a/src/main/windows-db-root-discovery.ts b/src/main/windows-db-root-discovery.ts index aa74fb8..5da052e 100644 --- a/src/main/windows-db-root-discovery.ts +++ b/src/main/windows-db-root-discovery.ts @@ -1,7 +1,8 @@ import fs from 'fs-extra' import path from 'path' -const DB_ROOT_NAMES = new Set(['xwechat_files', 'wechat files']) +// 仅支持 WeChat 4.0:只扫描 xwechat_files;旧 V3 时代的 "WeChat Files" 不再纳入候选 +const DB_ROOT_NAMES = new Set(['xwechat_files']) const SKIPPED_DIRECTORY_NAMES = new Set([ '$recycle.bin', 'system volume information',