From aa4e3388fcaaf9ce4939432a2097c08b8ec1b1e0 Mon Sep 17 00:00:00 2001 From: xuncha <1658671838@qq.com> Date: Thu, 14 May 2026 22:11:32 +0800 Subject: [PATCH] =?UTF-8?q?[Bug]:=20=E5=B9=B4=E5=BA=A6=E6=8A=A5=E5=91=8A?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=8A=9F=E8=83=BD=E6=97=A0=E6=B3=95=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20Fixes=20#953?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/services/accountDirResolver.ts | 73 ++++++++++++++++++++++++ electron/services/annualReportService.ts | 5 +- electron/services/dualReportService.ts | 5 +- 3 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 electron/services/accountDirResolver.ts diff --git a/electron/services/accountDirResolver.ts b/electron/services/accountDirResolver.ts new file mode 100644 index 0000000..1ad8c7a --- /dev/null +++ b/electron/services/accountDirResolver.ts @@ -0,0 +1,73 @@ +import { existsSync, readdirSync, statSync } from 'fs' +import { join } from 'path' + +const accountDirCache = new Map() + +const cleanAccountDirName = (dirName: string): string => { + const trimmed = dirName.trim() + if (!trimmed) return trimmed + + if (trimmed.toLowerCase().startsWith('wxid_')) { + const match = trimmed.match(/^(wxid_[^_]+)/i) + if (match) return match[1] + return trimmed + } + + const suffixMatch = trimmed.match(/^(.+)_([a-zA-Z0-9]{4})$/) + if (suffixMatch) return suffixMatch[1] + + return trimmed +} + +const isDirectory = (path: string): boolean => { + try { + return statSync(path).isDirectory() + } catch { + return false + } +} + +export const resolveAccountDir = (dbPath?: string, wxid?: string): string | null => { + if (!dbPath || !wxid) return null + + const cleanedWxid = cleanAccountDirName(wxid) + const normalized = dbPath.replace(/[\\/]+$/, '') + const cacheKey = `${normalized}|${cleanedWxid.toLowerCase()}` + + const cached = accountDirCache.get(cacheKey) + if (cached && existsSync(cached)) return cached + if (cached && !existsSync(cached)) { + accountDirCache.delete(cacheKey) + } + + const lowerWxid = cleanedWxid.toLowerCase() + if (!lowerWxid.startsWith('wxid_')) { + const direct = join(normalized, cleanedWxid) + if (existsSync(direct) && isDirectory(direct)) { + accountDirCache.set(cacheKey, direct) + return direct + } + } + + try { + const entries = readdirSync(normalized) + for (const entry of entries) { + const entryPath = join(normalized, entry) + if (!isDirectory(entryPath)) continue + + const lowerEntry = entry.toLowerCase() + const isExactMatch = lowerEntry === lowerWxid + const isSuffixMatch = lowerEntry.startsWith(`${lowerWxid}_`) + const shouldMatch = lowerWxid.startsWith('wxid_') + ? isSuffixMatch + : (isExactMatch || isSuffixMatch) + + if (shouldMatch) { + accountDirCache.set(cacheKey, entryPath) + return entryPath + } + } + } catch { } + + return null +} diff --git a/electron/services/annualReportService.ts b/electron/services/annualReportService.ts index bf56492..04faedf 100644 --- a/electron/services/annualReportService.ts +++ b/electron/services/annualReportService.ts @@ -1,6 +1,6 @@ import { parentPort } from 'worker_threads' import { wcdbService } from './wcdbService' -import { ConfigService } from './config' +import { resolveAccountDir } from './accountDirResolver' export interface TopContact { username: string @@ -159,8 +159,7 @@ class AnnualReportService { if (!dbPath) return { success: false, error: '未配置数据库路径' } if (!decryptKey) return { success: false, error: '未配置解密密钥' } - const configService = ConfigService.getInstance() - const accountDir = configService.getAccountDir(dbPath, wxid) + const accountDir = resolveAccountDir(dbPath, wxid) if (!accountDir) return { success: false, error: '未找到账号目录' } const ok = await wcdbService.open(accountDir, decryptKey) diff --git a/electron/services/dualReportService.ts b/electron/services/dualReportService.ts index 07a6d4a..1d8de7b 100644 --- a/electron/services/dualReportService.ts +++ b/electron/services/dualReportService.ts @@ -1,6 +1,6 @@ import { parentPort } from 'worker_threads' import { wcdbService } from './wcdbService' -import { ConfigService } from './config' +import { resolveAccountDir } from './accountDirResolver' export interface DualReportMessage { @@ -110,8 +110,7 @@ class DualReportService { if (!dbPath) return { success: false, error: '未配置数据库路径' } if (!decryptKey) return { success: false, error: '未配置解密密钥' } - const configService = ConfigService.getInstance() - const accountDir = configService.getAccountDir(dbPath, wxid) + const accountDir = resolveAccountDir(dbPath, wxid) if (!accountDir) return { success: false, error: '无法找到账号目录' } const ok = await wcdbService.open(accountDir, decryptKey) if (!ok) return { success: false, error: 'WCDB 打开失败' }