diff --git a/electron/main.ts b/electron/main.ts index 46b96a9..31e2d34 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -972,6 +972,17 @@ function registerIpcHandlers() { } }) + ipcMain.handle('log:clear', async () => { + try { + const logPath = join(app.getPath('userData'), 'logs', 'wcdb.log') + await mkdir(dirname(logPath), { recursive: true }) + await writeFile(logPath, '', 'utf8') + return { success: true } + } catch (e) { + return { success: false, error: String(e) } + } + }) + ipcMain.handle('diagnostics:getExportCardLogs', async (_, options?: { limit?: number }) => { return exportCardDiagnosticsService.snapshot(options?.limit) }) diff --git a/electron/preload.ts b/electron/preload.ts index 2f2874c..2dcc561 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -70,6 +70,7 @@ contextBridge.exposeInMainWorld('electronAPI', { log: { getPath: () => ipcRenderer.invoke('log:getPath'), read: () => ipcRenderer.invoke('log:read'), + clear: () => ipcRenderer.invoke('log:clear'), debug: (data: any) => ipcRenderer.send('log:debug', data) }, diff --git a/electron/services/chatService.ts b/electron/services/chatService.ts index 3a6741a..0b81fe2 100644 --- a/electron/services/chatService.ts +++ b/electron/services/chatService.ts @@ -359,16 +359,15 @@ class ChatService { // 这种方式更高效,且不占用 JS 线程,并能直接监听 session/message 目录变更 wcdbService.setMonitor((type, json) => { this.handleSessionStatsMonitorChange(type, json) + const windows = BrowserWindow.getAllWindows() // 广播给所有渲染进程窗口 - BrowserWindow.getAllWindows().forEach((win) => { + windows.forEach((win) => { if (!win.isDestroyed()) { win.webContents.send('wcdb-change', { type, json }) } }) }) } - }) - } /** * 预热 media 数据库列表缓存(后台异步执行) diff --git a/electron/services/wcdbCore.ts b/electron/services/wcdbCore.ts index c118a79..a56cf78 100644 --- a/electron/services/wcdbCore.ts +++ b/electron/services/wcdbCore.ts @@ -173,7 +173,6 @@ export class WcdbCore { } } catch {} } - this.connectMonitorPipe(pipePath) return true } catch (e) { @@ -194,8 +193,14 @@ export class WcdbCore { let buffer = '' this.monitorPipeClient.on('data', (data: Buffer) => { - buffer += data.toString('utf8') - const lines = buffer.split('\n') + const rawChunk = data.toString('utf8') + // macOS 侧可能使用 '\0' 或无换行分隔,统一归一化并兜底拆包 + const normalizedChunk = rawChunk + .replace(/\u0000/g, '\n') + .replace(/}\s*{/g, '}\n{') + + buffer += normalizedChunk + const lines = buffer.split(/\r?\n/) buffer = lines.pop() || '' for (const line of lines) { if (line.trim()) { @@ -207,9 +212,23 @@ export class WcdbCore { } } } + + // 兜底:如果没有分隔符但已形成完整 JSON,则直接上报 + const tail = buffer.trim() + if (tail.startsWith('{') && tail.endsWith('}')) { + try { + const parsed = JSON.parse(tail) + this.monitorCallback?.(parsed.action || 'update', tail) + buffer = '' + } catch { + // 不可解析则继续等待下一块数据 + } + } }) - this.monitorPipeClient.on('error', () => {}) + this.monitorPipeClient.on('error', () => { + // 保持静默,与现有错误处理策略一致 + }) this.monitorPipeClient.on('close', () => { this.monitorPipeClient = null diff --git a/electron/services/wcdbService.ts b/electron/services/wcdbService.ts index 6aee8e9..2f5715f 100644 --- a/electron/services/wcdbService.ts +++ b/electron/services/wcdbService.ts @@ -136,7 +136,7 @@ export class WcdbService { */ setMonitor(callback: (type: string, json: string) => void): void { this.monitorListener = callback; - this.callWorker('setMonitor').catch(() => { }); + this.callWorker<{ success?: boolean }>('setMonitor').catch(() => { }); } /** diff --git a/electron/wcdbWorker.ts b/electron/wcdbWorker.ts index 333527a..8a49cad 100644 --- a/electron/wcdbWorker.ts +++ b/electron/wcdbWorker.ts @@ -20,15 +20,17 @@ if (parentPort) { result = { success: true } break case 'setMonitor': - core.setMonitor((type, json) => { + { + const monitorOk = core.setMonitor((type, json) => { parentPort!.postMessage({ id: -1, type: 'monitor', payload: { type, json } }) }) - result = { success: true } + result = { success: monitorOk } break + } case 'testConnection': result = await core.testConnection(payload.dbPath, payload.hexKey, payload.wxid) break diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx index db39015..7f36e75 100644 --- a/src/pages/SettingsPage.tsx +++ b/src/pages/SettingsPage.tsx @@ -897,6 +897,21 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { } } + const handleClearLog = async () => { + const confirmed = window.confirm('确定清空 wcdb.log 吗?') + if (!confirmed) return + try { + const result = await window.electronAPI.log.clear() + if (!result.success) { + showMessage(result.error || '清空日志失败', false) + return + } + showMessage('日志已清空', true) + } catch (e: any) { + showMessage(`清空日志失败: ${e}`, false) + } + } + const handleClearAnalyticsCache = async () => { if (isClearingCache) return setIsClearingAnalyticsCache(true) @@ -1427,6 +1442,9 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) { + diff --git a/src/types/electron.d.ts b/src/types/electron.d.ts index 64806fc..efe7735 100644 --- a/src/types/electron.d.ts +++ b/src/types/electron.d.ts @@ -69,6 +69,7 @@ export interface ElectronAPI { log: { getPath: () => Promise read: () => Promise<{ success: boolean; content?: string; error?: string }> + clear: () => Promise<{ success: boolean; error?: string }> debug: (data: any) => void } diagnostics: {