From 698d2c96d7d520f53648bdadd7f9b31bc128f291 Mon Sep 17 00:00:00 2001 From: tisonhuang Date: Mon, 2 Mar 2026 18:45:47 +0800 Subject: [PATCH] fix(chat): avoid group members sidebar stuck on first init --- electron/main.ts | 1 - electron/services/groupAnalyticsService.ts | 41 +++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/electron/main.ts b/electron/main.ts index 4f9aed9..1062f49 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -1425,7 +1425,6 @@ function registerIpcHandlers() { return groupAnalyticsService.getGroupMembersPanelData(chatroomId, normalizedOptions) } ) - }) ipcMain.handle('groupAnalytics:getGroupMessageRanking', async (_, chatroomId: string, limit?: number, startTime?: number, endTime?: number) => { return groupAnalyticsService.getGroupMessageRanking(chatroomId, limit, startTime, endTime) diff --git a/electron/services/groupAnalyticsService.ts b/electron/services/groupAnalyticsService.ts index 0688970..40ef8a3 100644 --- a/electron/services/groupAnalyticsService.ts +++ b/electron/services/groupAnalyticsService.ts @@ -63,6 +63,8 @@ interface GroupMemberContactInfo { class GroupAnalyticsService { private configService: ConfigService private readonly groupMembersPanelCacheTtlMs = 10 * 60 * 1000 + private readonly groupMembersPanelMembersTimeoutMs = 12 * 1000 + private readonly groupMembersPanelFullTimeoutMs = 25 * 1000 private readonly groupMembersPanelCache = new Map() private readonly groupMembersPanelInFlight = new Map< string, @@ -485,6 +487,31 @@ class GroupAnalyticsService { } } + private async withPromiseTimeout( + promise: Promise, + timeoutMs: number, + timeoutResult: T + ): Promise { + if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) { + return promise + } + + let timeoutTimer: ReturnType | null = null + const timeoutPromise = new Promise((resolve) => { + timeoutTimer = setTimeout(() => { + resolve(timeoutResult) + }, timeoutMs) + }) + + try { + return await Promise.race([promise, timeoutPromise]) + } finally { + if (timeoutTimer) { + clearTimeout(timeoutTimer) + } + } + } + private async buildGroupMemberContactLookup(usernames: string[]): Promise> { const lookup = new Map() const candidates = this.buildIdCandidates(usernames) @@ -911,7 +938,19 @@ class GroupAnalyticsService { const conn = await this.ensureConnected() if (!conn.success) return { success: false, error: conn.error } - const fresh = await this.loadGroupMembersPanelDataFresh(normalizedChatroomId, includeMessageCounts) + const timeoutMs = includeMessageCounts + ? this.groupMembersPanelFullTimeoutMs + : this.groupMembersPanelMembersTimeoutMs + const fresh = await this.withPromiseTimeout( + this.loadGroupMembersPanelDataFresh(normalizedChatroomId, includeMessageCounts), + timeoutMs, + { + success: false, + error: includeMessageCounts + ? '群成员发言统计加载超时,请稍后重试' + : '群成员列表加载超时,请稍后重试' + } + ) if (!fresh.success || !fresh.data) { return { success: false, error: fresh.error || '获取群成员面板数据失败' } }