修复导出时的日期选择问题

This commit is contained in:
xuncha
2026-03-20 16:01:31 +08:00
parent 4c70ebcaf9
commit a331f45f87

View File

@@ -2796,7 +2796,9 @@ function ExportPage() {
emojiMessages: typeof metric.emojiMessages === 'number' ? metric.emojiMessages : previous.emojiMessages, emojiMessages: typeof metric.emojiMessages === 'number' ? metric.emojiMessages : previous.emojiMessages,
transferMessages: typeof metric.transferMessages === 'number' ? metric.transferMessages : previous.transferMessages, transferMessages: typeof metric.transferMessages === 'number' ? metric.transferMessages : previous.transferMessages,
redPacketMessages: typeof metric.redPacketMessages === 'number' ? metric.redPacketMessages : previous.redPacketMessages, redPacketMessages: typeof metric.redPacketMessages === 'number' ? metric.redPacketMessages : previous.redPacketMessages,
callMessages: typeof metric.callMessages === 'number' ? metric.callMessages : previous.callMessages callMessages: typeof metric.callMessages === 'number' ? metric.callMessages : previous.callMessages,
firstTimestamp: typeof metric.firstTimestamp === 'number' ? metric.firstTimestamp : previous.firstTimestamp,
lastTimestamp: typeof metric.lastTimestamp === 'number' ? metric.lastTimestamp : previous.lastTimestamp
} }
if ( if (
previous.totalMessages === nextMetric.totalMessages && previous.totalMessages === nextMetric.totalMessages &&
@@ -4033,21 +4035,42 @@ function ExportPage() {
const normalizedSessionIds = Array.from(new Set((sessionIds || []).map(id => String(id || '').trim()).filter(Boolean))) const normalizedSessionIds = Array.from(new Set((sessionIds || []).map(id => String(id || '').trim()).filter(Boolean)))
if (normalizedSessionIds.length === 0) return null if (normalizedSessionIds.length === 0) return null
const sessionRowMap = new Map<string, SessionRow>()
for (const session of sessions) {
sessionRowMap.set(session.username, session)
}
let minTimestamp: number | undefined let minTimestamp: number | undefined
let maxTimestamp: number | undefined let maxTimestamp: number | undefined
const resolvedSessionIds = new Set<string>() const resolvedSessionBounds = new Map<string, { hasMin: boolean; hasMax: boolean }>()
const absorbMetric = (sessionId: string, metric?: { firstTimestamp?: number; lastTimestamp?: number } | null) => { const absorbMetric = (sessionId: string, metric?: { firstTimestamp?: number; lastTimestamp?: number } | null) => {
if (!metric) return if (!metric) return
const firstTimestamp = normalizeTimestampSeconds(metric.firstTimestamp) const firstTimestamp = normalizeTimestampSeconds(metric.firstTimestamp)
const lastTimestamp = normalizeTimestampSeconds(metric.lastTimestamp) const lastTimestamp = normalizeTimestampSeconds(metric.lastTimestamp)
if (typeof firstTimestamp !== 'number' || typeof lastTimestamp !== 'number') return if (typeof firstTimestamp !== 'number' && typeof lastTimestamp !== 'number') return
resolvedSessionIds.add(sessionId)
if (minTimestamp === undefined || firstTimestamp < minTimestamp) minTimestamp = firstTimestamp const previous = resolvedSessionBounds.get(sessionId) || { hasMin: false, hasMax: false }
if (maxTimestamp === undefined || lastTimestamp > maxTimestamp) maxTimestamp = lastTimestamp const nextState = {
hasMin: previous.hasMin || typeof firstTimestamp === 'number',
hasMax: previous.hasMax || typeof lastTimestamp === 'number'
}
resolvedSessionBounds.set(sessionId, nextState)
if (typeof firstTimestamp === 'number' && (minTimestamp === undefined || firstTimestamp < minTimestamp)) {
minTimestamp = firstTimestamp
}
if (typeof lastTimestamp === 'number' && (maxTimestamp === undefined || lastTimestamp > maxTimestamp)) {
maxTimestamp = lastTimestamp
}
} }
for (const sessionId of normalizedSessionIds) { for (const sessionId of normalizedSessionIds) {
const sessionRow = sessionRowMap.get(sessionId)
absorbMetric(sessionId, {
firstTimestamp: undefined,
lastTimestamp: sessionRow?.sortTimestamp || sessionRow?.lastTimestamp
})
absorbMetric(sessionId, sessionContentMetrics[sessionId]) absorbMetric(sessionId, sessionContentMetrics[sessionId])
if (sessionDetail?.wxid === sessionId) { if (sessionDetail?.wxid === sessionId) {
absorbMetric(sessionId, { absorbMetric(sessionId, {
@@ -4068,23 +4091,37 @@ function ExportPage() {
} }
} }
const missingSessionIds = () => normalizedSessionIds.filter(sessionId => !resolvedSessionIds.has(sessionId)) const missingSessionIds = () => normalizedSessionIds.filter(sessionId => {
const resolved = resolvedSessionBounds.get(sessionId)
return !resolved?.hasMin || !resolved?.hasMax
})
const staleSessionIds = new Set<string>()
if (missingSessionIds().length > 0) { if (missingSessionIds().length > 0) {
applyStatsResult(await window.electronAPI.chat.getExportSessionStats( const cacheResult = await window.electronAPI.chat.getExportSessionStats(
missingSessionIds(), missingSessionIds(),
{ includeRelations: false, allowStaleCache: true, cacheOnly: true } { includeRelations: false, allowStaleCache: true, cacheOnly: true }
)
applyStatsResult(cacheResult)
for (const sessionId of cacheResult?.needsRefresh || []) {
staleSessionIds.add(String(sessionId || '').trim())
}
}
const sessionsNeedingFreshStats = Array.from(new Set([
...missingSessionIds(),
...Array.from(staleSessionIds).filter(Boolean)
]))
if (sessionsNeedingFreshStats.length > 0) {
applyStatsResult(await window.electronAPI.chat.getExportSessionStats(
sessionsNeedingFreshStats,
{ includeRelations: false }
)) ))
} }
if (missingSessionIds().length > 0) { if (missingSessionIds().length > 0) {
applyStatsResult(await window.electronAPI.chat.getExportSessionStats(
missingSessionIds(),
{ includeRelations: false, allowStaleCache: true }
))
}
if (resolvedSessionIds.size !== normalizedSessionIds.length) {
return null return null
} }
if (typeof minTimestamp !== 'number' || typeof maxTimestamp !== 'number') { if (typeof minTimestamp !== 'number' || typeof maxTimestamp !== 'number') {
@@ -4095,7 +4132,7 @@ function ExportPage() {
minDate: new Date(minTimestamp * 1000), minDate: new Date(minTimestamp * 1000),
maxDate: new Date(maxTimestamp * 1000) maxDate: new Date(maxTimestamp * 1000)
} }
}, [applySessionMediaMetricsFromStats, sessionContentMetrics, sessionDetail]) }, [applySessionMediaMetricsFromStats, sessionContentMetrics, sessionDetail, sessions])
const openTimeRangeDialog = useCallback(() => { const openTimeRangeDialog = useCallback(() => {
void (async () => { void (async () => {