From 2f25fd12395397906a9c424144c6d8766fa5c8eb Mon Sep 17 00:00:00 2001 From: hicccc77 <98377878+hicccc77@users.noreply.github.com> Date: Sun, 15 Mar 2026 19:08:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=85=B3=E9=94=AE=E8=AF=8D=E6=90=9C=E7=B4=A2?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - wcdbCore: 绑定 wcdb_search_messages DLL 函数,添加 searchMessages 方法 - wcdbWorker: 添加 searchMessages case - wcdbService: 添加 searchMessages 代理方法 - chatService: 添加 searchMessages,结果解析为 Message 对象 - main: 注册 chat:searchMessages IPC handler --- electron/main.ts | 4 ++++ electron/services/chatService.ts | 14 ++++++++++++ electron/services/wcdbCore.ts | 38 ++++++++++++++++++++++++++++++++ electron/services/wcdbService.ts | 4 ++++ electron/wcdbWorker.ts | 3 +++ 5 files changed, 63 insertions(+) diff --git a/electron/main.ts b/electron/main.ts index d636dd5..076c16d 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -1563,6 +1563,10 @@ function registerIpcHandlers() { return chatService.getMessageById(sessionId, localId) }) + ipcMain.handle('chat:searchMessages', async (_, keyword: string, sessionId?: string, limit?: number, offset?: number, beginTimestamp?: number, endTimestamp?: number) => { + return chatService.searchMessages(keyword, sessionId, limit, offset, beginTimestamp, endTimestamp) + }) + ipcMain.handle('chat:execQuery', async (_, kind: string, path: string | null, sql: string) => { return chatService.execQuery(kind, path, sql) }) diff --git a/electron/services/chatService.ts b/electron/services/chatService.ts index 0b81fe2..aa958e6 100644 --- a/electron/services/chatService.ts +++ b/electron/services/chatService.ts @@ -6580,6 +6580,20 @@ class ChatService { } } + async searchMessages(keyword: string, sessionId?: string, limit?: number, offset?: number, beginTimestamp?: number, endTimestamp?: number): Promise<{ success: boolean; messages?: Message[]; error?: string }> { + try { + const result = await wcdbService.searchMessages(keyword, sessionId, limit, offset, beginTimestamp, endTimestamp) + if (!result.success || !result.messages) { + return { success: false, error: result.error || '搜索失败' } + } + const messages = result.messages.map((row: any) => this.parseMessage(row)).filter(Boolean) as Message[] + return { success: true, messages } + } catch (e) { + console.error('ChatService: searchMessages 失败:', e) + return { success: false, error: String(e) } + } + } + private parseMessage(row: any): Message { const rawContent = this.decodeMessageContent( this.getRowField(row, [ diff --git a/electron/services/wcdbCore.ts b/electron/services/wcdbCore.ts index 517fedf..a9b99dd 100644 --- a/electron/services/wcdbCore.ts +++ b/electron/services/wcdbCore.ts @@ -106,6 +106,7 @@ export class WcdbCore { private wcdbGetEmoticonCdnUrl: any = null private wcdbGetDbStatus: any = null private wcdbGetVoiceData: any = null + private wcdbSearchMessages: any = null private wcdbGetSnsTimeline: any = null private wcdbGetSnsAnnualStats: any = null private wcdbInstallSnsBlockDeleteTrigger: any = null @@ -817,6 +818,13 @@ export class WcdbCore { this.wcdbGetVoiceData = null } + // wcdb_status wcdb_search_messages(wcdb_handle handle, const char* session_id, const char* keyword, int32_t limit, int32_t offset, int32_t begin_timestamp, int32_t end_timestamp, char** out_json) + try { + this.wcdbSearchMessages = this.lib.func('int32 wcdb_search_messages(int64 handle, const char* sessionId, const char* keyword, int32 limit, int32 offset, int32 beginTimestamp, int32 endTimestamp, _Out_ void** outJson)') + } catch { + this.wcdbSearchMessages = null + } + // wcdb_status wcdb_get_sns_timeline(wcdb_handle handle, int32_t limit, int32_t offset, const char* username, const char* keyword, int32_t start_time, int32_t end_time, char** out_json) try { this.wcdbGetSnsTimeline = this.lib.func('int32 wcdb_get_sns_timeline(int64 handle, int32 limit, int32 offset, const char* username, const char* keyword, int32 startTime, int32 endTime, _Out_ void** outJson)') @@ -2279,6 +2287,36 @@ export class WcdbCore { }) } + async searchMessages(keyword: string, sessionId?: string, limit?: number, offset?: number, beginTimestamp?: number, endTimestamp?: number): Promise<{ success: boolean; messages?: any[]; error?: string }> { + if (!this.ensureReady()) return { success: false, error: 'WCDB 未连接' } + if (!this.wcdbSearchMessages) return { success: false, error: '当前 DLL 版本不支持搜索消息' } + try { + const handle = this.handle + await new Promise(resolve => setImmediate(resolve)) + if (handle === null || this.handle !== handle) return { success: false, error: '连接已断开' } + const outPtr = [null as any] + const result = this.wcdbSearchMessages( + handle, + sessionId || '', + keyword, + limit || 50, + offset || 0, + beginTimestamp || 0, + endTimestamp || 0, + outPtr + ) + if (result !== 0 || !outPtr[0]) { + return { success: false, error: `搜索消息失败: ${result}` } + } + const jsonStr = this.decodeJsonPtr(outPtr[0]) + if (!jsonStr) return { success: false, error: '解析搜索结果失败' } + const messages = JSON.parse(jsonStr) + return { success: true, messages } + } catch (e) { + return { success: false, error: String(e) } + } + } + async getSnsTimeline(limit: number, offset: number, usernames?: string[], keyword?: string, startTime?: number, endTime?: number): Promise<{ success: boolean; timeline?: any[]; error?: string }> { if (!this.ensureReady()) return { success: false, error: 'WCDB 未连接' } if (!this.wcdbGetSnsTimeline) return { success: false, error: '当前 DLL 版本不支持获取朋友圈' } diff --git a/electron/services/wcdbService.ts b/electron/services/wcdbService.ts index 286ddae..b5fcb24 100644 --- a/electron/services/wcdbService.ts +++ b/electron/services/wcdbService.ts @@ -406,6 +406,10 @@ export class WcdbService { return this.callWorker('getMessageById', { sessionId, localId }) } + async searchMessages(keyword: string, sessionId?: string, limit?: number, offset?: number, beginTimestamp?: number, endTimestamp?: number): Promise<{ success: boolean; messages?: any[]; error?: string }> { + return this.callWorker('searchMessages', { keyword, sessionId, limit, offset, beginTimestamp, endTimestamp }) + } + /** * 获取语音数据 */ diff --git a/electron/wcdbWorker.ts b/electron/wcdbWorker.ts index 8a49cad..5d02904 100644 --- a/electron/wcdbWorker.ts +++ b/electron/wcdbWorker.ts @@ -140,6 +140,9 @@ if (parentPort) { case 'getMessageById': result = await core.getMessageById(payload.sessionId, payload.localId) break + case 'searchMessages': + result = await core.searchMessages(payload.keyword, payload.sessionId, payload.limit, payload.offset, payload.beginTimestamp, payload.endTimestamp) + break case 'getVoiceData': result = await core.getVoiceData(payload.sessionId, payload.createTime, payload.candidates, payload.localId, payload.svrId) if (!result.success) {