mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
perf(export): further optimize detail loading and prioritize session stats
This commit is contained in:
@@ -87,6 +87,7 @@ let onboardingWindow: BrowserWindow | null = null
|
||||
// Splash 启动窗口
|
||||
let splashWindow: BrowserWindow | null = null
|
||||
const sessionChatWindows = new Map<string, BrowserWindow>()
|
||||
const sessionChatWindowSources = new Map<string, 'chat' | 'export'>()
|
||||
const keyService = new KeyService()
|
||||
|
||||
let mainWindowReady = false
|
||||
@@ -123,6 +124,32 @@ interface AnnualReportYearsTaskState {
|
||||
updatedAt: number
|
||||
}
|
||||
|
||||
interface OpenSessionChatWindowOptions {
|
||||
source?: 'chat' | 'export'
|
||||
}
|
||||
|
||||
const normalizeSessionChatWindowSource = (source: unknown): 'chat' | 'export' => {
|
||||
return String(source || '').trim().toLowerCase() === 'export' ? 'export' : 'chat'
|
||||
}
|
||||
|
||||
const loadSessionChatWindowContent = (
|
||||
win: BrowserWindow,
|
||||
sessionId: string,
|
||||
source: 'chat' | 'export'
|
||||
) => {
|
||||
const query = new URLSearchParams({
|
||||
sessionId,
|
||||
source
|
||||
}).toString()
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
win.loadURL(`${process.env.VITE_DEV_SERVER_URL}#/chat-window?${query}`)
|
||||
return
|
||||
}
|
||||
win.loadFile(join(__dirname, '../dist/index.html'), {
|
||||
hash: `/chat-window?${query}`
|
||||
})
|
||||
}
|
||||
|
||||
const annualReportYearsLoadTasks = new Map<string, AnnualReportYearsTaskState>()
|
||||
const annualReportYearsTaskByCacheKey = new Map<string, string>()
|
||||
const annualReportYearsSnapshotCache = new Map<string, { snapshot: AnnualReportYearsProgressPayload; updatedAt: number; taskId: string }>()
|
||||
@@ -688,12 +715,18 @@ function createChatHistoryWindow(sessionId: string, messageId: number) {
|
||||
/**
|
||||
* 创建独立的会话聊天窗口(单会话,复用聊天页右侧消息区域)
|
||||
*/
|
||||
function createSessionChatWindow(sessionId: string) {
|
||||
function createSessionChatWindow(sessionId: string, options?: OpenSessionChatWindowOptions) {
|
||||
const normalizedSessionId = String(sessionId || '').trim()
|
||||
if (!normalizedSessionId) return null
|
||||
const normalizedSource = normalizeSessionChatWindowSource(options?.source)
|
||||
|
||||
const existing = sessionChatWindows.get(normalizedSessionId)
|
||||
if (existing && !existing.isDestroyed()) {
|
||||
const trackedSource = sessionChatWindowSources.get(normalizedSessionId) || 'chat'
|
||||
if (trackedSource !== normalizedSource) {
|
||||
loadSessionChatWindowContent(existing, normalizedSessionId, normalizedSource)
|
||||
sessionChatWindowSources.set(normalizedSessionId, normalizedSource)
|
||||
}
|
||||
if (existing.isMinimized()) {
|
||||
existing.restore()
|
||||
}
|
||||
@@ -730,10 +763,9 @@ function createSessionChatWindow(sessionId: string) {
|
||||
autoHideMenuBar: true
|
||||
})
|
||||
|
||||
const sessionParam = `sessionId=${encodeURIComponent(normalizedSessionId)}`
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
win.loadURL(`${process.env.VITE_DEV_SERVER_URL}#/chat-window?${sessionParam}`)
|
||||
loadSessionChatWindowContent(win, normalizedSessionId, normalizedSource)
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
win.webContents.on('before-input-event', (event, input) => {
|
||||
if (input.key === 'F12' || (input.control && input.shift && input.key === 'I')) {
|
||||
if (win.webContents.isDevToolsOpened()) {
|
||||
@@ -744,10 +776,6 @@ function createSessionChatWindow(sessionId: string) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
win.loadFile(join(__dirname, '../dist/index.html'), {
|
||||
hash: `/chat-window?${sessionParam}`
|
||||
})
|
||||
}
|
||||
|
||||
win.once('ready-to-show', () => {
|
||||
@@ -759,10 +787,12 @@ function createSessionChatWindow(sessionId: string) {
|
||||
const tracked = sessionChatWindows.get(normalizedSessionId)
|
||||
if (tracked === win) {
|
||||
sessionChatWindows.delete(normalizedSessionId)
|
||||
sessionChatWindowSources.delete(normalizedSessionId)
|
||||
}
|
||||
})
|
||||
|
||||
sessionChatWindows.set(normalizedSessionId, win)
|
||||
sessionChatWindowSources.set(normalizedSessionId, normalizedSource)
|
||||
return win
|
||||
}
|
||||
|
||||
@@ -1071,8 +1101,8 @@ function registerIpcHandlers() {
|
||||
})
|
||||
|
||||
// 打开会话聊天窗口(同会话仅保留一个窗口并聚焦)
|
||||
ipcMain.handle('window:openSessionChatWindow', (_, sessionId: string) => {
|
||||
const win = createSessionChatWindow(sessionId)
|
||||
ipcMain.handle('window:openSessionChatWindow', (_, sessionId: string, options?: OpenSessionChatWindowOptions) => {
|
||||
const win = createSessionChatWindow(sessionId, options)
|
||||
return Boolean(win)
|
||||
})
|
||||
|
||||
@@ -1410,6 +1440,7 @@ function registerIpcHandlers() {
|
||||
forceRefresh?: boolean
|
||||
allowStaleCache?: boolean
|
||||
preferAccurateSpecialTypes?: boolean
|
||||
cacheOnly?: boolean
|
||||
}) => {
|
||||
return chatService.getExportSessionStats(sessionIds, options)
|
||||
})
|
||||
|
||||
@@ -99,8 +99,8 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
ipcRenderer.invoke('window:openImageViewerWindow', imagePath, liveVideoPath),
|
||||
openChatHistoryWindow: (sessionId: string, messageId: number) =>
|
||||
ipcRenderer.invoke('window:openChatHistoryWindow', sessionId, messageId),
|
||||
openSessionChatWindow: (sessionId: string) =>
|
||||
ipcRenderer.invoke('window:openSessionChatWindow', sessionId)
|
||||
openSessionChatWindow: (sessionId: string, options?: { source?: 'chat' | 'export' }) =>
|
||||
ipcRenderer.invoke('window:openSessionChatWindow', sessionId, options)
|
||||
},
|
||||
|
||||
// 数据库路径
|
||||
@@ -174,7 +174,13 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
getSessionDetailExtra: (sessionId: string) => ipcRenderer.invoke('chat:getSessionDetailExtra', sessionId),
|
||||
getExportSessionStats: (
|
||||
sessionIds: string[],
|
||||
options?: { includeRelations?: boolean; forceRefresh?: boolean; allowStaleCache?: boolean; preferAccurateSpecialTypes?: boolean }
|
||||
options?: {
|
||||
includeRelations?: boolean
|
||||
forceRefresh?: boolean
|
||||
allowStaleCache?: boolean
|
||||
preferAccurateSpecialTypes?: boolean
|
||||
cacheOnly?: boolean
|
||||
}
|
||||
) => ipcRenderer.invoke('chat:getExportSessionStats', sessionIds, options),
|
||||
getGroupMyMessageCountHint: (chatroomId: string) =>
|
||||
ipcRenderer.invoke('chat:getGroupMyMessageCountHint', chatroomId),
|
||||
|
||||
@@ -164,6 +164,7 @@ interface ExportSessionStatsOptions {
|
||||
forceRefresh?: boolean
|
||||
allowStaleCache?: boolean
|
||||
preferAccurateSpecialTypes?: boolean
|
||||
cacheOnly?: boolean
|
||||
}
|
||||
|
||||
interface ExportSessionStatsCacheMeta {
|
||||
@@ -5354,6 +5355,7 @@ class ChatService {
|
||||
const forceRefresh = options.forceRefresh === true
|
||||
const allowStaleCache = options.allowStaleCache === true
|
||||
const preferAccurateSpecialTypes = options.preferAccurateSpecialTypes === true
|
||||
const cacheOnly = options.cacheOnly === true
|
||||
|
||||
const normalizedSessionIds = Array.from(
|
||||
new Set(
|
||||
@@ -5377,32 +5379,34 @@ class ChatService {
|
||||
? this.getGroupMyMessageCountHintEntry(sessionId)
|
||||
: null
|
||||
const cachedResult = this.getSessionStatsCacheEntry(sessionId)
|
||||
if (!forceRefresh && !preferAccurateSpecialTypes) {
|
||||
if (cachedResult && this.supportsRequestedRelation(cachedResult.entry, includeRelations)) {
|
||||
const stale = now - cachedResult.entry.updatedAt > this.sessionStatsCacheTtlMs
|
||||
if (!stale || allowStaleCache) {
|
||||
resultMap[sessionId] = this.fromSessionStatsCacheStats(cachedResult.entry.stats)
|
||||
if (groupMyMessagesHint && Number.isFinite(groupMyMessagesHint.entry.messageCount)) {
|
||||
resultMap[sessionId].groupMyMessages = groupMyMessagesHint.entry.messageCount
|
||||
}
|
||||
cacheMeta[sessionId] = {
|
||||
updatedAt: cachedResult.entry.updatedAt,
|
||||
stale,
|
||||
includeRelations: cachedResult.entry.includeRelations,
|
||||
source: cachedResult.source
|
||||
}
|
||||
if (stale) {
|
||||
needsRefreshSet.add(sessionId)
|
||||
}
|
||||
continue
|
||||
const canUseCache = cacheOnly || (!forceRefresh && !preferAccurateSpecialTypes)
|
||||
if (canUseCache && cachedResult && this.supportsRequestedRelation(cachedResult.entry, includeRelations)) {
|
||||
const stale = now - cachedResult.entry.updatedAt > this.sessionStatsCacheTtlMs
|
||||
if (!stale || allowStaleCache || cacheOnly) {
|
||||
resultMap[sessionId] = this.fromSessionStatsCacheStats(cachedResult.entry.stats)
|
||||
if (groupMyMessagesHint && Number.isFinite(groupMyMessagesHint.entry.messageCount)) {
|
||||
resultMap[sessionId].groupMyMessages = groupMyMessagesHint.entry.messageCount
|
||||
}
|
||||
cacheMeta[sessionId] = {
|
||||
updatedAt: cachedResult.entry.updatedAt,
|
||||
stale,
|
||||
includeRelations: cachedResult.entry.includeRelations,
|
||||
source: cachedResult.source
|
||||
}
|
||||
if (stale) {
|
||||
needsRefreshSet.add(sessionId)
|
||||
}
|
||||
}
|
||||
// allowStaleCache 仅对“已有缓存”生效;无缓存会话仍需进入计算流程。
|
||||
if (allowStaleCache && cachedResult) {
|
||||
needsRefreshSet.add(sessionId)
|
||||
continue
|
||||
}
|
||||
}
|
||||
// allowStaleCache/cacheOnly 仅对“已有缓存”生效;无缓存会话不会直接算重查询。
|
||||
if (canUseCache && allowStaleCache && cachedResult) {
|
||||
needsRefreshSet.add(sessionId)
|
||||
continue
|
||||
}
|
||||
if (cacheOnly) {
|
||||
continue
|
||||
}
|
||||
pendingSessionIds.push(sessionId)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user