diff --git a/electron/services/chatService.ts b/electron/services/chatService.ts index e50817e..4c5e43e 100644 --- a/electron/services/chatService.ts +++ b/electron/services/chatService.ts @@ -5209,39 +5209,36 @@ class ChatService { return { success: true, detail: cachedDetail.detail } } - const [tableStatsResult, statsResult] = await Promise.allSettled([ - wcdbService.getMessageTableStats(normalizedSessionId), - (async (): Promise => { - const cachedStats = this.getSessionStatsCacheEntry(normalizedSessionId) - if (cachedStats && this.supportsRequestedRelation(cachedStats.entry, false)) { - return this.fromSessionStatsCacheStats(cachedStats.entry.stats) - } - const myWxid = this.configService.get('myWxid') || '' - const selfIdentitySet = new Set(this.buildIdentityKeys(myWxid)) - const stats = await this.getOrComputeSessionExportStats(normalizedSessionId, false, selfIdentitySet) - this.setSessionStatsCacheEntry(normalizedSessionId, stats, false) - return stats - })() - ]) - - const statsSnapshot = statsResult.status === 'fulfilled' - ? statsResult.value - : null - const firstMessageTime = statsSnapshot && Number.isFinite(statsSnapshot.firstTimestamp) - ? Math.max(0, Math.floor(statsSnapshot.firstTimestamp as number)) - : undefined - const latestMessageTime = statsSnapshot && Number.isFinite(statsSnapshot.lastTimestamp) - ? Math.max(0, Math.floor(statsSnapshot.lastTimestamp as number)) - : undefined + const tableStatsResult = await wcdbService.getMessageTableStats(normalizedSessionId) const messageTables: { dbName: string; tableName: string; count: number }[] = [] - if (tableStatsResult.status === 'fulfilled' && tableStatsResult.value.success && tableStatsResult.value.tables) { - for (const row of tableStatsResult.value.tables) { + let firstMessageTime: number | undefined + let latestMessageTime: number | undefined + if (tableStatsResult.success && tableStatsResult.tables) { + for (const row of tableStatsResult.tables) { messageTables.push({ dbName: basename(row.db_path || ''), tableName: row.table_name || '', count: parseInt(row.count || '0', 10) }) + + const firstTs = this.getRowInt( + row, + ['first_timestamp', 'firstTimestamp', 'first_time', 'firstTime', 'min_create_time', 'minCreateTime'], + 0 + ) + if (firstTs > 0 && (firstMessageTime === undefined || firstTs < firstMessageTime)) { + firstMessageTime = firstTs + } + + const lastTs = this.getRowInt( + row, + ['last_timestamp', 'lastTimestamp', 'last_time', 'lastTime', 'max_create_time', 'maxCreateTime'], + 0 + ) + if (lastTs > 0 && (latestMessageTime === undefined || lastTs > latestMessageTime)) { + latestMessageTime = lastTs + } } } diff --git a/src/pages/ExportPage.tsx b/src/pages/ExportPage.tsx index 3b56b13..01e219f 100644 --- a/src/pages/ExportPage.tsx +++ b/src/pages/ExportPage.tsx @@ -3514,7 +3514,7 @@ function ExportPage() { window.electronAPI.chat.getSessionDetailExtra(normalizedSessionId), window.electronAPI.chat.getExportSessionStats( [normalizedSessionId], - { includeRelations: false, forceRefresh: true, preferAccurateSpecialTypes: true } + { includeRelations: false, allowStaleCache: true } ) ]) @@ -3535,59 +3535,56 @@ function ExportPage() { } } - let refreshIncludeRelations = false - let shouldRefreshStats = false if (statsResultSettled.status === 'fulfilled' && statsResultSettled.value.success) { const metric = statsResultSettled.value.data?.[normalizedSessionId] as SessionExportMetric | undefined const cacheMeta = statsResultSettled.value.cache?.[normalizedSessionId] as SessionExportCacheMeta | undefined - refreshIncludeRelations = Boolean(cacheMeta?.includeRelations) if (metric) { - applySessionDetailStats(normalizedSessionId, metric, cacheMeta, refreshIncludeRelations) + applySessionDetailStats(normalizedSessionId, metric, cacheMeta, false) } else if (cacheMeta) { setSessionDetail((prev) => { if (!prev || prev.wxid !== normalizedSessionId) return prev return { ...prev, - relationStatsLoaded: refreshIncludeRelations || prev.relationStatsLoaded, statsUpdatedAt: cacheMeta.updatedAt, statsStale: cacheMeta.stale } }) } - shouldRefreshStats = Array.isArray(statsResultSettled.value.needsRefresh) && - statsResultSettled.value.needsRefresh.includes(normalizedSessionId) } - if (shouldRefreshStats) { - setIsRefreshingSessionDetailStats(true) - void (async () => { - try { - const freshResult = await window.electronAPI.chat.getExportSessionStats( - [normalizedSessionId], - { includeRelations: refreshIncludeRelations, forceRefresh: true, preferAccurateSpecialTypes: true } - ) - if (requestSeq !== detailRequestSeqRef.current) return - if (freshResult.success && freshResult.data) { - const metric = freshResult.data[normalizedSessionId] as SessionExportMetric | undefined - const cacheMeta = freshResult.cache?.[normalizedSessionId] as SessionExportCacheMeta | undefined - if (metric) { - applySessionDetailStats( - normalizedSessionId, - metric, - cacheMeta, - refreshIncludeRelations ? true : undefined - ) - } - } - } catch (error) { - console.error('导出页刷新会话统计失败:', error) - } finally { - if (requestSeq === detailRequestSeqRef.current) { - setIsRefreshingSessionDetailStats(false) + setIsRefreshingSessionDetailStats(true) + void (async () => { + try { + // 后台精确补算三类重字段(转账/红包/通话),不阻塞首屏基础统计显示。 + const freshResult = await window.electronAPI.chat.getExportSessionStats( + [normalizedSessionId], + { includeRelations: false, forceRefresh: true, preferAccurateSpecialTypes: true } + ) + if (requestSeq !== detailRequestSeqRef.current) return + if (freshResult.success && freshResult.data) { + const metric = freshResult.data[normalizedSessionId] as SessionExportMetric | undefined + const cacheMeta = freshResult.cache?.[normalizedSessionId] as SessionExportCacheMeta | undefined + if (metric) { + applySessionDetailStats(normalizedSessionId, metric, cacheMeta, false) + } else if (cacheMeta) { + setSessionDetail((prev) => { + if (!prev || prev.wxid !== normalizedSessionId) return prev + return { + ...prev, + statsUpdatedAt: cacheMeta.updatedAt, + statsStale: cacheMeta.stale + } + }) } } - })() - } + } catch (error) { + console.error('导出页刷新会话统计失败:', error) + } finally { + if (requestSeq === detailRequestSeqRef.current) { + setIsRefreshingSessionDetailStats(false) + } + } + })() } catch (error) { console.error('导出页加载会话详情补充统计失败:', error) } finally { @@ -3619,36 +3616,6 @@ function ExportPage() { if (metric) { applySessionDetailStats(normalizedSessionId, metric, cacheMeta, true) } - - const needRefresh = relationResult.success && - Array.isArray(relationResult.needsRefresh) && - relationResult.needsRefresh.includes(normalizedSessionId) - - if (needRefresh) { - setIsRefreshingSessionDetailStats(true) - void (async () => { - try { - const freshResult = await window.electronAPI.chat.getExportSessionStats( - [normalizedSessionId], - { includeRelations: true, forceRefresh: true, preferAccurateSpecialTypes: true } - ) - if (requestSeq !== detailRequestSeqRef.current) return - if (freshResult.success && freshResult.data) { - const freshMetric = freshResult.data[normalizedSessionId] as SessionExportMetric | undefined - const freshMeta = freshResult.cache?.[normalizedSessionId] as SessionExportCacheMeta | undefined - if (freshMetric) { - applySessionDetailStats(normalizedSessionId, freshMetric, freshMeta, true) - } - } - } catch (error) { - console.error('导出页刷新会话关系统计失败:', error) - } finally { - if (requestSeq === detailRequestSeqRef.current) { - setIsRefreshingSessionDetailStats(false) - } - } - })() - } } catch (error) { console.error('导出页加载会话关系统计失败:', error) } finally {