mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
优化导出
This commit is contained in:
@@ -26,6 +26,7 @@ interface ConfigSchema {
|
||||
whisperDownloadSource: string
|
||||
autoTranscribeVoice: boolean
|
||||
transcribeLanguages: string[]
|
||||
exportDefaultConcurrency: number
|
||||
}
|
||||
|
||||
export class ConfigService {
|
||||
@@ -54,7 +55,8 @@ export class ConfigService {
|
||||
whisperModelDir: '',
|
||||
whisperDownloadSource: 'tsinghua',
|
||||
autoTranscribeVoice: false,
|
||||
transcribeLanguages: ['zh']
|
||||
transcribeLanguages: ['zh'],
|
||||
exportDefaultConcurrency: 2
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ export interface ExportOptions {
|
||||
txtColumns?: string[]
|
||||
sessionLayout?: 'shared' | 'per-session'
|
||||
displayNamePreference?: 'group-nickname' | 'remark' | 'nickname'
|
||||
exportConcurrency?: number
|
||||
}
|
||||
|
||||
const TXT_COLUMN_DEFINITIONS: Array<{ id: string; label: string }> = [
|
||||
@@ -1288,6 +1289,7 @@ class ExportService {
|
||||
): Promise<{ rows: any[]; memberSet: Map<string, { member: ChatLabMember; avatarUrl?: string }>; firstTime: number | null; lastTime: number | null }> {
|
||||
const rows: any[] = []
|
||||
const memberSet = new Map<string, { member: ChatLabMember; avatarUrl?: string }>()
|
||||
const senderSet = new Set<string>()
|
||||
let firstTime: number | null = null
|
||||
let lastTime: number | null = null
|
||||
|
||||
@@ -1321,16 +1323,7 @@ class ExportService {
|
||||
const localId = parseInt(row.local_id || row.localId || '0', 10)
|
||||
|
||||
const actualSender = isSend ? cleanedMyWxid : (senderUsername || sessionId)
|
||||
const memberInfo = await this.getContactInfo(actualSender)
|
||||
if (!memberSet.has(actualSender)) {
|
||||
memberSet.set(actualSender, {
|
||||
member: {
|
||||
platformId: actualSender,
|
||||
accountName: memberInfo.displayName
|
||||
},
|
||||
avatarUrl: memberInfo.avatarUrl
|
||||
})
|
||||
}
|
||||
senderSet.add(actualSender)
|
||||
|
||||
// 提取媒体相关字段
|
||||
let imageMd5: string | undefined
|
||||
@@ -1375,6 +1368,30 @@ class ExportService {
|
||||
await wcdbService.closeMessageCursor(cursor.cursor)
|
||||
}
|
||||
|
||||
if (senderSet.size > 0) {
|
||||
const usernames = Array.from(senderSet)
|
||||
const [nameResult, avatarResult] = await Promise.all([
|
||||
wcdbService.getDisplayNames(usernames),
|
||||
wcdbService.getAvatarUrls(usernames)
|
||||
])
|
||||
|
||||
const nameMap = nameResult.success && nameResult.map ? nameResult.map : {}
|
||||
const avatarMap = avatarResult.success && avatarResult.map ? avatarResult.map : {}
|
||||
|
||||
for (const username of usernames) {
|
||||
const displayName = nameMap[username] || username
|
||||
const avatarUrl = avatarMap[username]
|
||||
memberSet.set(username, {
|
||||
member: {
|
||||
platformId: username,
|
||||
accountName: displayName
|
||||
},
|
||||
avatarUrl
|
||||
})
|
||||
this.contactCache.set(username, { displayName, avatarUrl })
|
||||
}
|
||||
}
|
||||
|
||||
return { rows, memberSet, firstTime, lastTime }
|
||||
}
|
||||
|
||||
@@ -1856,6 +1873,16 @@ class ExportService {
|
||||
const sessionInfo = await this.getContactInfo(sessionId)
|
||||
const myInfo = await this.getContactInfo(cleanedMyWxid)
|
||||
|
||||
const contactCache = new Map<string, { success: boolean; contact?: any; error?: string }>()
|
||||
const getContactCached = async (username: string) => {
|
||||
if (contactCache.has(username)) {
|
||||
return contactCache.get(username)!
|
||||
}
|
||||
const result = await wcdbService.getContact(username)
|
||||
contactCache.set(username, result)
|
||||
return result
|
||||
}
|
||||
|
||||
onProgress?.({
|
||||
current: 0,
|
||||
total: 100,
|
||||
@@ -1934,6 +1961,16 @@ class ExportService {
|
||||
? await this.getGroupNicknamesForRoom(sessionId)
|
||||
: new Map<string, string>()
|
||||
|
||||
const contactCache = new Map<string, { success: boolean; contact?: any; error?: string }>()
|
||||
const getContactCached = async (username: string) => {
|
||||
if (contactCache.has(username)) {
|
||||
return contactCache.get(username)!
|
||||
}
|
||||
const result = await wcdbService.getContact(username)
|
||||
contactCache.set(username, result)
|
||||
return result
|
||||
}
|
||||
|
||||
// ========== 阶段3:构建消息列表 ==========
|
||||
onProgress?.({
|
||||
current: 55,
|
||||
@@ -1962,7 +1999,7 @@ class ExportService {
|
||||
|
||||
// 获取发送者信息用于名称显示
|
||||
const senderWxid = msg.senderUsername
|
||||
const contact = await wcdbService.getContact(senderWxid)
|
||||
const contact = await getContactCached(senderWxid)
|
||||
const senderNickname = contact.success && contact.contact?.nickName
|
||||
? contact.contact.nickName
|
||||
: (senderInfo.displayName || senderWxid)
|
||||
@@ -2005,7 +2042,7 @@ class ExportService {
|
||||
const { chatlab, meta } = this.getExportMeta(sessionId, sessionInfo, isGroup)
|
||||
|
||||
// 获取会话的昵称和备注信息
|
||||
const sessionContact = await wcdbService.getContact(sessionId)
|
||||
const sessionContact = await getContactCached(sessionId)
|
||||
const sessionNickname = sessionContact.success && sessionContact.contact?.nickName
|
||||
? sessionContact.contact.nickName
|
||||
: sessionInfo.displayName
|
||||
@@ -2098,8 +2135,18 @@ class ExportService {
|
||||
const sessionInfo = await this.getContactInfo(sessionId)
|
||||
const myInfo = await this.getContactInfo(cleanedMyWxid)
|
||||
|
||||
const contactCache = new Map<string, { success: boolean; contact?: any; error?: string }>()
|
||||
const getContactCached = async (username: string) => {
|
||||
if (contactCache.has(username)) {
|
||||
return contactCache.get(username)!
|
||||
}
|
||||
const result = await wcdbService.getContact(username)
|
||||
contactCache.set(username, result)
|
||||
return result
|
||||
}
|
||||
|
||||
// 获取会话的备注信息
|
||||
const sessionContact = await wcdbService.getContact(sessionId)
|
||||
const sessionContact = await getContactCached(sessionId)
|
||||
const sessionRemark = sessionContact.success && sessionContact.contact?.remark ? sessionContact.contact.remark : ''
|
||||
const sessionNickname = sessionContact.success && sessionContact.contact?.nickName ? sessionContact.contact.nickName : sessionId
|
||||
|
||||
@@ -2328,7 +2375,7 @@ class ExportService {
|
||||
senderWxid = msg.senderUsername
|
||||
|
||||
// 用 getContact 获取联系人详情,分别取昵称和备注
|
||||
const contactDetail = await wcdbService.getContact(msg.senderUsername)
|
||||
const contactDetail = await getContactCached(msg.senderUsername)
|
||||
if (contactDetail.success && contactDetail.contact) {
|
||||
// nickName 才是真正的昵称
|
||||
senderNickname = contactDetail.contact.nickName || msg.senderUsername
|
||||
@@ -2343,7 +2390,7 @@ class ExportService {
|
||||
} else {
|
||||
// 单聊对方消息 - 用 getContact 获取联系人详情
|
||||
senderWxid = sessionId
|
||||
const contactDetail = await wcdbService.getContact(sessionId)
|
||||
const contactDetail = await getContactCached(sessionId)
|
||||
if (contactDetail.success && contactDetail.contact) {
|
||||
senderNickname = contactDetail.contact.nickName || sessionId
|
||||
senderRemark = contactDetail.contact.remark || ''
|
||||
@@ -2567,7 +2614,7 @@ class ExportService {
|
||||
senderNickname = myInfo.displayName || cleanedMyWxid
|
||||
} else if (isGroup && msg.senderUsername) {
|
||||
senderWxid = msg.senderUsername
|
||||
const contactDetail = await wcdbService.getContact(msg.senderUsername)
|
||||
const contactDetail = await getContactCached(msg.senderUsername)
|
||||
if (contactDetail.success && contactDetail.contact) {
|
||||
senderNickname = contactDetail.contact.nickName || msg.senderUsername
|
||||
senderRemark = contactDetail.contact.remark || ''
|
||||
@@ -2578,7 +2625,7 @@ class ExportService {
|
||||
}
|
||||
} else {
|
||||
senderWxid = sessionId
|
||||
const contactDetail = await wcdbService.getContact(sessionId)
|
||||
const contactDetail = await getContactCached(sessionId)
|
||||
if (contactDetail.success && contactDetail.contact) {
|
||||
senderNickname = contactDetail.contact.nickName || sessionId
|
||||
senderRemark = contactDetail.contact.remark || ''
|
||||
@@ -3005,13 +3052,20 @@ class ExportService {
|
||||
const sessionLayout = exportMediaEnabled
|
||||
? (options.sessionLayout ?? 'per-session')
|
||||
: 'shared'
|
||||
let completedCount = 0
|
||||
const rawConcurrency = typeof options.exportConcurrency === 'number'
|
||||
? Math.floor(options.exportConcurrency)
|
||||
: 2
|
||||
const clampedConcurrency = Math.max(1, Math.min(rawConcurrency, 6))
|
||||
const sessionConcurrency = (exportMediaEnabled && sessionLayout === 'shared')
|
||||
? 1
|
||||
: clampedConcurrency
|
||||
|
||||
for (let i = 0; i < sessionIds.length; i++) {
|
||||
const sessionId = sessionIds[i]
|
||||
await parallelLimit(sessionIds, sessionConcurrency, async (sessionId) => {
|
||||
const sessionInfo = await this.getContactInfo(sessionId)
|
||||
|
||||
onProgress?.({
|
||||
current: i + 1,
|
||||
current: completedCount,
|
||||
total: sessionIds.length,
|
||||
currentSession: sessionInfo.displayName,
|
||||
phase: 'exporting'
|
||||
@@ -3053,7 +3107,15 @@ class ExportService {
|
||||
failCount++
|
||||
console.error(`导出 ${sessionId} 失败:`, result.error)
|
||||
}
|
||||
}
|
||||
|
||||
completedCount++
|
||||
onProgress?.({
|
||||
current: completedCount,
|
||||
total: sessionIds.length,
|
||||
currentSession: sessionInfo.displayName,
|
||||
phase: 'exporting'
|
||||
})
|
||||
})
|
||||
|
||||
onProgress?.({
|
||||
current: sessionIds.length,
|
||||
|
||||
Reference in New Issue
Block a user