mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 07:16:51 +00:00
perf(export): speed up session detail stats loading
This commit is contained in:
@@ -5209,39 +5209,36 @@ class ChatService {
|
|||||||
return { success: true, detail: cachedDetail.detail }
|
return { success: true, detail: cachedDetail.detail }
|
||||||
}
|
}
|
||||||
|
|
||||||
const [tableStatsResult, statsResult] = await Promise.allSettled([
|
const tableStatsResult = await wcdbService.getMessageTableStats(normalizedSessionId)
|
||||||
wcdbService.getMessageTableStats(normalizedSessionId),
|
|
||||||
(async (): Promise<ExportSessionStats | null> => {
|
|
||||||
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<string>(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 messageTables: { dbName: string; tableName: string; count: number }[] = []
|
const messageTables: { dbName: string; tableName: string; count: number }[] = []
|
||||||
if (tableStatsResult.status === 'fulfilled' && tableStatsResult.value.success && tableStatsResult.value.tables) {
|
let firstMessageTime: number | undefined
|
||||||
for (const row of tableStatsResult.value.tables) {
|
let latestMessageTime: number | undefined
|
||||||
|
if (tableStatsResult.success && tableStatsResult.tables) {
|
||||||
|
for (const row of tableStatsResult.tables) {
|
||||||
messageTables.push({
|
messageTables.push({
|
||||||
dbName: basename(row.db_path || ''),
|
dbName: basename(row.db_path || ''),
|
||||||
tableName: row.table_name || '',
|
tableName: row.table_name || '',
|
||||||
count: parseInt(row.count || '0', 10)
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3514,7 +3514,7 @@ function ExportPage() {
|
|||||||
window.electronAPI.chat.getSessionDetailExtra(normalizedSessionId),
|
window.electronAPI.chat.getSessionDetailExtra(normalizedSessionId),
|
||||||
window.electronAPI.chat.getExportSessionStats(
|
window.electronAPI.chat.getExportSessionStats(
|
||||||
[normalizedSessionId],
|
[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) {
|
if (statsResultSettled.status === 'fulfilled' && statsResultSettled.value.success) {
|
||||||
const metric = statsResultSettled.value.data?.[normalizedSessionId] as SessionExportMetric | undefined
|
const metric = statsResultSettled.value.data?.[normalizedSessionId] as SessionExportMetric | undefined
|
||||||
const cacheMeta = statsResultSettled.value.cache?.[normalizedSessionId] as SessionExportCacheMeta | undefined
|
const cacheMeta = statsResultSettled.value.cache?.[normalizedSessionId] as SessionExportCacheMeta | undefined
|
||||||
refreshIncludeRelations = Boolean(cacheMeta?.includeRelations)
|
|
||||||
if (metric) {
|
if (metric) {
|
||||||
applySessionDetailStats(normalizedSessionId, metric, cacheMeta, refreshIncludeRelations)
|
applySessionDetailStats(normalizedSessionId, metric, cacheMeta, false)
|
||||||
} else if (cacheMeta) {
|
} else if (cacheMeta) {
|
||||||
setSessionDetail((prev) => {
|
setSessionDetail((prev) => {
|
||||||
if (!prev || prev.wxid !== normalizedSessionId) return prev
|
if (!prev || prev.wxid !== normalizedSessionId) return prev
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
relationStatsLoaded: refreshIncludeRelations || prev.relationStatsLoaded,
|
|
||||||
statsUpdatedAt: cacheMeta.updatedAt,
|
statsUpdatedAt: cacheMeta.updatedAt,
|
||||||
statsStale: cacheMeta.stale
|
statsStale: cacheMeta.stale
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
shouldRefreshStats = Array.isArray(statsResultSettled.value.needsRefresh) &&
|
|
||||||
statsResultSettled.value.needsRefresh.includes(normalizedSessionId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldRefreshStats) {
|
setIsRefreshingSessionDetailStats(true)
|
||||||
setIsRefreshingSessionDetailStats(true)
|
void (async () => {
|
||||||
void (async () => {
|
try {
|
||||||
try {
|
// 后台精确补算三类重字段(转账/红包/通话),不阻塞首屏基础统计显示。
|
||||||
const freshResult = await window.electronAPI.chat.getExportSessionStats(
|
const freshResult = await window.electronAPI.chat.getExportSessionStats(
|
||||||
[normalizedSessionId],
|
[normalizedSessionId],
|
||||||
{ includeRelations: refreshIncludeRelations, forceRefresh: true, preferAccurateSpecialTypes: true }
|
{ includeRelations: false, forceRefresh: true, preferAccurateSpecialTypes: true }
|
||||||
)
|
)
|
||||||
if (requestSeq !== detailRequestSeqRef.current) return
|
if (requestSeq !== detailRequestSeqRef.current) return
|
||||||
if (freshResult.success && freshResult.data) {
|
if (freshResult.success && freshResult.data) {
|
||||||
const metric = freshResult.data[normalizedSessionId] as SessionExportMetric | undefined
|
const metric = freshResult.data[normalizedSessionId] as SessionExportMetric | undefined
|
||||||
const cacheMeta = freshResult.cache?.[normalizedSessionId] as SessionExportCacheMeta | undefined
|
const cacheMeta = freshResult.cache?.[normalizedSessionId] as SessionExportCacheMeta | undefined
|
||||||
if (metric) {
|
if (metric) {
|
||||||
applySessionDetailStats(
|
applySessionDetailStats(normalizedSessionId, metric, cacheMeta, false)
|
||||||
normalizedSessionId,
|
} else if (cacheMeta) {
|
||||||
metric,
|
setSessionDetail((prev) => {
|
||||||
cacheMeta,
|
if (!prev || prev.wxid !== normalizedSessionId) return prev
|
||||||
refreshIncludeRelations ? true : undefined
|
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 {
|
||||||
|
if (requestSeq === detailRequestSeqRef.current) {
|
||||||
|
setIsRefreshingSessionDetailStats(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('导出页加载会话详情补充统计失败:', error)
|
console.error('导出页加载会话详情补充统计失败:', error)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -3619,36 +3616,6 @@ function ExportPage() {
|
|||||||
if (metric) {
|
if (metric) {
|
||||||
applySessionDetailStats(normalizedSessionId, metric, cacheMeta, true)
|
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) {
|
} catch (error) {
|
||||||
console.error('导出页加载会话关系统计失败:', error)
|
console.error('导出页加载会话关系统计失败:', error)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user