mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 07:16:51 +00:00
转账导出优化
This commit is contained in:
@@ -348,6 +348,51 @@ class ExportService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从转账消息 XML 中提取并解析 "谁转账给谁" 描述
|
||||||
|
* @param content 原始消息内容 XML
|
||||||
|
* @param myWxid 当前用户 wxid
|
||||||
|
* @param groupNicknamesMap 群昵称映射
|
||||||
|
* @param getContactName 联系人名称解析函数
|
||||||
|
* @returns "A 转账给 B" 或 null
|
||||||
|
*/
|
||||||
|
private async resolveTransferDesc(
|
||||||
|
content: string,
|
||||||
|
myWxid: string,
|
||||||
|
groupNicknamesMap: Map<string, string>,
|
||||||
|
getContactName: (username: string) => Promise<string>
|
||||||
|
): Promise<string | null> {
|
||||||
|
const xmlType = this.extractXmlValue(content, 'type')
|
||||||
|
if (xmlType !== '2000') return null
|
||||||
|
|
||||||
|
const payerUsername = this.extractXmlValue(content, 'payer_username')
|
||||||
|
const receiverUsername = this.extractXmlValue(content, 'receiver_username')
|
||||||
|
if (!payerUsername || !receiverUsername) return null
|
||||||
|
|
||||||
|
const cleanedMyWxid = myWxid ? this.cleanAccountDirName(myWxid) : ''
|
||||||
|
|
||||||
|
const resolveName = async (username: string): Promise<string> => {
|
||||||
|
// 当前用户自己
|
||||||
|
if (myWxid && (username === myWxid || username === cleanedMyWxid)) {
|
||||||
|
const groupNick = groupNicknamesMap.get(username) || groupNicknamesMap.get(username.toLowerCase())
|
||||||
|
if (groupNick) return groupNick
|
||||||
|
return '我'
|
||||||
|
}
|
||||||
|
// 群昵称
|
||||||
|
const groupNick = groupNicknamesMap.get(username) || groupNicknamesMap.get(username.toLowerCase())
|
||||||
|
if (groupNick) return groupNick
|
||||||
|
// 联系人名称
|
||||||
|
return getContactName(username)
|
||||||
|
}
|
||||||
|
|
||||||
|
const [payerName, receiverName] = await Promise.all([
|
||||||
|
resolveName(payerUsername),
|
||||||
|
resolveName(receiverUsername)
|
||||||
|
])
|
||||||
|
|
||||||
|
return `${payerName} 转账给 ${receiverName}`
|
||||||
|
}
|
||||||
|
|
||||||
private looksLikeBase64(s: string): boolean {
|
private looksLikeBase64(s: string): boolean {
|
||||||
if (s.length % 4 !== 0) return false
|
if (s.length % 4 !== 0) return false
|
||||||
return /^[A-Za-z0-9+/=]+$/.test(s)
|
return /^[A-Za-z0-9+/=]+$/.test(s)
|
||||||
@@ -2003,7 +2048,8 @@ class ExportService {
|
|||||||
phase: 'exporting'
|
phase: 'exporting'
|
||||||
})
|
})
|
||||||
|
|
||||||
const chatLabMessages: ChatLabMessage[] = allMessages.map(msg => {
|
const chatLabMessages: ChatLabMessage[] = []
|
||||||
|
for (const msg of allMessages) {
|
||||||
const memberInfo = collected.memberSet.get(msg.senderUsername)?.member || {
|
const memberInfo = collected.memberSet.get(msg.senderUsername)?.member || {
|
||||||
platformId: msg.senderUsername,
|
platformId: msg.senderUsername,
|
||||||
accountName: msg.senderUsername,
|
accountName: msg.senderUsername,
|
||||||
@@ -2024,6 +2070,22 @@ class ExportService {
|
|||||||
content = this.parseMessageContent(msg.content, msg.localType, sessionId, msg.createTime)
|
content = this.parseMessageContent(msg.content, msg.localType, sessionId, msg.createTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 转账消息:追加 "谁转账给谁" 信息
|
||||||
|
if (content && content.startsWith('[转账]') && msg.content) {
|
||||||
|
const transferDesc = await this.resolveTransferDesc(
|
||||||
|
msg.content,
|
||||||
|
cleanedMyWxid,
|
||||||
|
groupNicknamesMap,
|
||||||
|
async (username) => {
|
||||||
|
const info = await this.getContactInfo(username)
|
||||||
|
return info.displayName || username
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (transferDesc) {
|
||||||
|
content = content.replace('[转账]', `[转账] (${transferDesc})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const message: ChatLabMessage = {
|
const message: ChatLabMessage = {
|
||||||
sender: msg.senderUsername,
|
sender: msg.senderUsername,
|
||||||
accountName: memberInfo.accountName,
|
accountName: memberInfo.accountName,
|
||||||
@@ -2127,8 +2189,8 @@ class ExportService {
|
|||||||
message.chatRecords = chatRecords
|
message.chatRecords = chatRecords
|
||||||
}
|
}
|
||||||
|
|
||||||
return message
|
chatLabMessages.push(message)
|
||||||
})
|
}
|
||||||
|
|
||||||
const avatarMap = options.exportAvatars
|
const avatarMap = options.exportAvatars
|
||||||
? await this.exportAvatars(
|
? await this.exportAvatars(
|
||||||
@@ -2341,6 +2403,25 @@ class ExportService {
|
|||||||
content = this.parseMessageContent(msg.content, msg.localType)
|
content = this.parseMessageContent(msg.content, msg.localType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 转账消息:追加 "谁转账给谁" 信息
|
||||||
|
if (content && content.startsWith('[转账]') && msg.content) {
|
||||||
|
const transferDesc = await this.resolveTransferDesc(
|
||||||
|
msg.content,
|
||||||
|
cleanedMyWxid,
|
||||||
|
groupNicknamesMap,
|
||||||
|
async (username) => {
|
||||||
|
const c = await getContactCached(username)
|
||||||
|
if (c.success && c.contact) {
|
||||||
|
return c.contact.remark || c.contact.nickName || c.contact.alias || username
|
||||||
|
}
|
||||||
|
return username
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (transferDesc) {
|
||||||
|
content = content.replace('[转账]', `[转账] (${transferDesc})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取发送者信息用于名称显示
|
// 获取发送者信息用于名称显示
|
||||||
const senderWxid = msg.senderUsername
|
const senderWxid = msg.senderUsername
|
||||||
const contact = await getContactCached(senderWxid)
|
const contact = await getContactCached(senderWxid)
|
||||||
@@ -2784,6 +2865,26 @@ class ExportService {
|
|||||||
voiceTranscriptMap.get(msg.localId)
|
voiceTranscriptMap.get(msg.localId)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
// 转账消息:追加 "谁转账给谁" 信息
|
||||||
|
let enrichedContentValue = contentValue
|
||||||
|
if (contentValue.startsWith('[转账]') && msg.content) {
|
||||||
|
const transferDesc = await this.resolveTransferDesc(
|
||||||
|
msg.content,
|
||||||
|
cleanedMyWxid,
|
||||||
|
groupNicknamesMap,
|
||||||
|
async (username) => {
|
||||||
|
const c = await getContactCached(username)
|
||||||
|
if (c.success && c.contact) {
|
||||||
|
return c.contact.remark || c.contact.nickName || c.contact.alias || username
|
||||||
|
}
|
||||||
|
return username
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (transferDesc) {
|
||||||
|
enrichedContentValue = contentValue.replace('[转账]', `[转账] (${transferDesc})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 调试日志
|
// 调试日志
|
||||||
if (msg.localType === 3 || msg.localType === 47) {
|
if (msg.localType === 3 || msg.localType === 47) {
|
||||||
}
|
}
|
||||||
@@ -2793,7 +2894,7 @@ class ExportService {
|
|||||||
if (useCompactColumns) {
|
if (useCompactColumns) {
|
||||||
worksheet.getCell(currentRow, 3).value = senderRole
|
worksheet.getCell(currentRow, 3).value = senderRole
|
||||||
worksheet.getCell(currentRow, 4).value = this.getMessageTypeName(msg.localType)
|
worksheet.getCell(currentRow, 4).value = this.getMessageTypeName(msg.localType)
|
||||||
worksheet.getCell(currentRow, 5).value = contentValue
|
worksheet.getCell(currentRow, 5).value = enrichedContentValue
|
||||||
} else {
|
} else {
|
||||||
worksheet.getCell(currentRow, 3).value = senderNickname
|
worksheet.getCell(currentRow, 3).value = senderNickname
|
||||||
worksheet.getCell(currentRow, 4).value = senderWxid
|
worksheet.getCell(currentRow, 4).value = senderWxid
|
||||||
@@ -2801,7 +2902,7 @@ class ExportService {
|
|||||||
worksheet.getCell(currentRow, 6).value = senderGroupNickname
|
worksheet.getCell(currentRow, 6).value = senderGroupNickname
|
||||||
worksheet.getCell(currentRow, 7).value = senderRole
|
worksheet.getCell(currentRow, 7).value = senderRole
|
||||||
worksheet.getCell(currentRow, 8).value = this.getMessageTypeName(msg.localType)
|
worksheet.getCell(currentRow, 8).value = this.getMessageTypeName(msg.localType)
|
||||||
worksheet.getCell(currentRow, 9).value = contentValue
|
worksheet.getCell(currentRow, 9).value = enrichedContentValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置每个单元格的样式
|
// 设置每个单元格的样式
|
||||||
@@ -2948,6 +3049,11 @@ class ExportService {
|
|||||||
senderUsernames.add(sessionId)
|
senderUsernames.add(sessionId)
|
||||||
await this.preloadContacts(senderUsernames, contactCache)
|
await this.preloadContacts(senderUsernames, contactCache)
|
||||||
|
|
||||||
|
// 获取群昵称(用于转账描述等)
|
||||||
|
const groupNicknamesMap = isGroup
|
||||||
|
? await this.getGroupNicknamesForRoom(sessionId)
|
||||||
|
: new Map<string, string>()
|
||||||
|
|
||||||
const sortedMessages = collected.rows.sort((a, b) => a.createTime - b.createTime)
|
const sortedMessages = collected.rows.sort((a, b) => a.createTime - b.createTime)
|
||||||
|
|
||||||
const { exportMediaEnabled, mediaRootDir, mediaRelativePrefix } = this.getMediaLayout(outputPath, options)
|
const { exportMediaEnabled, mediaRootDir, mediaRelativePrefix } = this.getMediaLayout(outputPath, options)
|
||||||
@@ -3033,6 +3139,26 @@ class ExportService {
|
|||||||
voiceTranscriptMap.get(msg.localId)
|
voiceTranscriptMap.get(msg.localId)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
// 转账消息:追加 "谁转账给谁" 信息
|
||||||
|
let enrichedContentValue = contentValue
|
||||||
|
if (contentValue.startsWith('[转账]') && msg.content) {
|
||||||
|
const transferDesc = await this.resolveTransferDesc(
|
||||||
|
msg.content,
|
||||||
|
cleanedMyWxid,
|
||||||
|
groupNicknamesMap,
|
||||||
|
async (username) => {
|
||||||
|
const c = await getContactCached(username)
|
||||||
|
if (c.success && c.contact) {
|
||||||
|
return c.contact.remark || c.contact.nickName || c.contact.alias || username
|
||||||
|
}
|
||||||
|
return username
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (transferDesc) {
|
||||||
|
enrichedContentValue = contentValue.replace('[转账]', `[转账] (${transferDesc})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let senderRole: string
|
let senderRole: string
|
||||||
let senderWxid: string
|
let senderWxid: string
|
||||||
let senderNickname: string
|
let senderNickname: string
|
||||||
@@ -3067,7 +3193,7 @@ class ExportService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lines.push(`${this.formatTimestamp(msg.createTime)} '${senderRole}'`)
|
lines.push(`${this.formatTimestamp(msg.createTime)} '${senderRole}'`)
|
||||||
lines.push(contentValue)
|
lines.push(enrichedContentValue)
|
||||||
lines.push('')
|
lines.push('')
|
||||||
|
|
||||||
if ((i + 1) % 200 === 0) {
|
if ((i + 1) % 200 === 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user