From 5b6117ec28adf9f0ba545b939dd3f45d96048885 Mon Sep 17 00:00:00 2001 From: cc <98377878+hicccc77@users.noreply.github.com> Date: Wed, 8 Apr 2026 19:32:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A7=81=E8=A7=A3=E6=84=8F?= =?UTF-8?q?=E5=A4=96=E5=90=AF=E5=8A=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/main.ts | 3 +- electron/services/insightService.ts | 63 ++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/electron/main.ts b/electron/main.ts index cfc436f..8cb84e2 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -182,7 +182,6 @@ const applyAutoUpdateChannel = (reason: 'startup' | 'settings' = 'startup') => { autoUpdater.channel = nextUpdaterChannel lastAppliedUpdaterChannel = nextUpdaterChannel lastAppliedUpdaterFeedUrl = nextFeedUrl - console.log(`[Update](${reason}) 当前版本 ${appVersion},当前轨道: ${currentTrack},渠道偏好: ${track},更新通道: ${autoUpdater.channel},feed=${nextFeedUrl},allowDowngrade=${autoUpdater.allowDowngrade}`) } applyAutoUpdateChannel('startup') @@ -1619,6 +1618,7 @@ function registerIpcHandlers() { applyAutoUpdateChannel('settings') } void messagePushService.handleConfigChanged(key) + void insightService.handleConfigChanged(key) return result }) @@ -1644,6 +1644,7 @@ function registerIpcHandlers() { } configService?.clear() messagePushService.handleConfigCleared() + insightService.handleConfigCleared() return true }) diff --git a/electron/services/insightService.ts b/electron/services/insightService.ts index 305cfd6..8cd04d7 100644 --- a/electron/services/insightService.ts +++ b/electron/services/insightService.ts @@ -38,6 +38,13 @@ const API_TIMEOUT_MS = 45_000 /** 沉默天数阈值默认值 */ const DEFAULT_SILENCE_DAYS = 3 +const INSIGHT_CONFIG_KEYS = new Set([ + 'aiInsightEnabled', + 'aiInsightScanIntervalHours', + 'dbPath', + 'decryptKey', + 'myWxid' +]) // ─── 类型 ──────────────────────────────────────────────────────────────────── @@ -234,15 +241,57 @@ class InsightService { start(): void { if (this.started) return this.started = true - insightLog('INFO', '已启动') - this.scheduleSilenceScan() + void this.refreshConfiguration('startup') } stop(): void { this.started = false + this.clearTimers() + this.clearRuntimeCache() + this.processing = false + insightLog('INFO', '已停止') + } + + async handleConfigChanged(key: string): Promise { + const normalizedKey = String(key || '').trim() + if (!INSIGHT_CONFIG_KEYS.has(normalizedKey)) return + + // 数据库相关配置变更后,丢弃缓存并强制下次重连 + if (normalizedKey === 'dbPath' || normalizedKey === 'decryptKey' || normalizedKey === 'myWxid') { + this.clearRuntimeCache() + } + + await this.refreshConfiguration(`config:${normalizedKey}`) + } + + handleConfigCleared(): void { + this.clearTimers() + this.clearRuntimeCache() + this.processing = false + } + + private async refreshConfiguration(_reason: string): Promise { + if (!this.started) return + if (!this.isEnabled()) { + this.clearTimers() + this.clearRuntimeCache() + this.processing = false + return + } + this.scheduleSilenceScan() + } + + private clearRuntimeCache(): void { this.dbConnected = false this.sessionCache = null this.sessionCacheAt = 0 + this.lastActivityAnalysis.clear() + this.lastSeenTimestamp.clear() + this.todayTriggers.clear() + this.todayDate = getStartOfDay() + } + + private clearTimers(): void { if (this.dbDebounceTimer !== null) { clearTimeout(this.dbDebounceTimer) this.dbDebounceTimer = null @@ -255,7 +304,6 @@ class InsightService { clearTimeout(this.silenceInitialDelayTimer) this.silenceInitialDelayTimer = null } - insightLog('INFO', '已停止') } /** @@ -452,9 +500,12 @@ class InsightService { // ── 沉默联系人扫描 ────────────────────────────────────────────────────────── private scheduleSilenceScan(): void { + this.clearTimers() + if (!this.started || !this.isEnabled()) return + // 等待扫描完成后再安排下一次,避免并发堆积 const scheduleNext = () => { - if (!this.started) return + if (!this.started || !this.isEnabled()) return const intervalHours = (this.config.get('aiInsightScanIntervalHours') as number) || 4 const intervalMs = Math.max(0.1, intervalHours) * 60 * 60 * 1000 insightLog('INFO', `下次沉默扫描将在 ${intervalHours} 小时后执行`) @@ -474,7 +525,6 @@ class InsightService { private async runSilenceScan(): Promise { if (!this.isEnabled()) { - insightLog('INFO', '沉默扫描:AI 见解未启用,跳过') return } if (this.processing) { @@ -502,6 +552,7 @@ class InsightService { let silentCount = 0 for (const session of sessions) { + if (!this.isEnabled()) return const sessionId = session.username?.trim() || '' if (!sessionId || sessionId.endsWith('@chatroom')) continue if (sessionId.toLowerCase().includes('placeholder')) continue @@ -654,6 +705,7 @@ class InsightService { }): Promise { const { sessionId, displayName, triggerReason, silentDays } = params if (!sessionId) return + if (!this.isEnabled()) return const apiBaseUrl = this.config.get('aiInsightApiBaseUrl') as string const apiKey = this.config.get('aiInsightApiKey') as string @@ -747,6 +799,7 @@ class InsightService { insightLog('INFO', `模型选择跳过 ${displayName}`) return } + if (!this.isEnabled()) return const insight = result.slice(0, 120) const notifTitle = `见解 · ${displayName}`