mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 15:25:50 +00:00
Adjust txt/excel export message formatting
This commit is contained in:
@@ -305,6 +305,57 @@ class ExportService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private formatPlainExportContent(
|
||||||
|
content: string,
|
||||||
|
localType: number,
|
||||||
|
options: { exportVoiceAsText?: boolean },
|
||||||
|
voiceTranscript?: string
|
||||||
|
): string {
|
||||||
|
const safeContent = content || ''
|
||||||
|
|
||||||
|
if (localType === 3) return '[图片]'
|
||||||
|
if (localType === 1) return this.stripSenderPrefix(safeContent)
|
||||||
|
if (localType === 34) {
|
||||||
|
if (options.exportVoiceAsText) {
|
||||||
|
return voiceTranscript || '[语音消息 - 转文字失败]'
|
||||||
|
}
|
||||||
|
return '[其他消息]'
|
||||||
|
}
|
||||||
|
if (localType === 10000 || localType === 266287972401) {
|
||||||
|
return this.cleanSystemMessage(safeContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalized = this.normalizeAppMessageContent(safeContent)
|
||||||
|
const isAppMessage = normalized.includes('<appmsg') || normalized.includes('<msg>')
|
||||||
|
if (localType === 49 || isAppMessage) {
|
||||||
|
const typeMatch = /<type>(\d+)<\/type>/i.exec(normalized)
|
||||||
|
const subType = typeMatch ? parseInt(typeMatch[1], 10) : 0
|
||||||
|
const title = this.extractXmlValue(normalized, 'title') || this.extractXmlValue(normalized, 'appname')
|
||||||
|
if (subType === 6) {
|
||||||
|
const fileName = this.extractXmlValue(normalized, 'filename') || title || '文件'
|
||||||
|
return `[文件]${fileName}`
|
||||||
|
}
|
||||||
|
if (subType === 19 || normalized.includes('<recorditem')) {
|
||||||
|
const forwardName =
|
||||||
|
this.extractXmlValue(normalized, 'nickname') ||
|
||||||
|
this.extractXmlValue(normalized, 'title') ||
|
||||||
|
this.extractXmlValue(normalized, 'des') ||
|
||||||
|
this.extractXmlValue(normalized, 'displayname')
|
||||||
|
return forwardName ? `[转发的聊天记录]${forwardName}` : '[转发的聊天记录]'
|
||||||
|
}
|
||||||
|
if (subType === 33 || subType === 36) {
|
||||||
|
const appName = this.extractXmlValue(normalized, 'appname') || title || '小程序'
|
||||||
|
return `[小程序]${appName}`
|
||||||
|
}
|
||||||
|
if (title) {
|
||||||
|
return `[链接]${title}`
|
||||||
|
}
|
||||||
|
return '[其他消息]'
|
||||||
|
}
|
||||||
|
|
||||||
|
return '[其他消息]'
|
||||||
|
}
|
||||||
|
|
||||||
private stripSenderPrefix(content: string): string {
|
private stripSenderPrefix(content: string): string {
|
||||||
return content.replace(/^[\s]*([a-zA-Z0-9_-]+):(?!\/\/)/, '')
|
return content.replace(/^[\s]*([a-zA-Z0-9_-]+):(?!\/\/)/, '')
|
||||||
}
|
}
|
||||||
@@ -1967,10 +2018,6 @@ class ExportService {
|
|||||||
for (let i = 0; i < sortedMessages.length; i++) {
|
for (let i = 0; i < sortedMessages.length; i++) {
|
||||||
const msg = sortedMessages[i]
|
const msg = sortedMessages[i]
|
||||||
|
|
||||||
// 从缓存获取媒体信息
|
|
||||||
const mediaKey = `${msg.localType}_${msg.localId}`
|
|
||||||
const mediaItem = mediaCache.get(mediaKey) || null
|
|
||||||
|
|
||||||
// 确定发送者信息
|
// 确定发送者信息
|
||||||
let senderRole: string
|
let senderRole: string
|
||||||
let senderWxid: string
|
let senderWxid: string
|
||||||
@@ -2018,16 +2065,12 @@ class ExportService {
|
|||||||
const row = worksheet.getRow(currentRow)
|
const row = worksheet.getRow(currentRow)
|
||||||
row.height = 24
|
row.height = 24
|
||||||
|
|
||||||
// 确定内容:优先使用预处理的缓存
|
const contentValue = this.formatPlainExportContent(
|
||||||
let contentValue: string
|
msg.content,
|
||||||
if (mediaItem) {
|
msg.localType,
|
||||||
contentValue = mediaItem.relativePath
|
options,
|
||||||
} else if (msg.localType === 34 && options.exportVoiceAsText) {
|
voiceTranscriptMap.get(msg.localId)
|
||||||
// 使用预处理的语音转文字结果
|
)
|
||||||
contentValue = voiceTranscriptMap.get(msg.localId) || '[语音消息 - 转文字失败]'
|
|
||||||
} else {
|
|
||||||
contentValue = this.parseMessageContent(msg.content, msg.localType) || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调试日志
|
// 调试日志
|
||||||
if (msg.localType === 3 || msg.localType === 47) {
|
if (msg.localType === 3 || msg.localType === 47) {
|
||||||
@@ -2190,24 +2233,16 @@ class ExportService {
|
|||||||
phase: 'exporting'
|
phase: 'exporting'
|
||||||
})
|
})
|
||||||
|
|
||||||
const columnOrder = this.normalizeTxtColumns(options.txtColumns)
|
|
||||||
const columnLabelMap = new Map(TXT_COLUMN_DEFINITIONS.map((col) => [col.id, col.label]))
|
|
||||||
const lines: string[] = []
|
const lines: string[] = []
|
||||||
lines.push(columnOrder.map((id) => columnLabelMap.get(id) || id).join('\t'))
|
|
||||||
|
|
||||||
for (let i = 0; i < sortedMessages.length; i++) {
|
for (let i = 0; i < sortedMessages.length; i++) {
|
||||||
const msg = sortedMessages[i]
|
const msg = sortedMessages[i]
|
||||||
const mediaKey = `${msg.localType}_${msg.localId}`
|
const contentValue = this.formatPlainExportContent(
|
||||||
const mediaItem = mediaCache.get(mediaKey) || null
|
msg.content,
|
||||||
|
msg.localType,
|
||||||
let contentValue: string
|
options,
|
||||||
if (mediaItem) {
|
voiceTranscriptMap.get(msg.localId)
|
||||||
contentValue = mediaItem.relativePath
|
)
|
||||||
} else if (msg.localType === 34 && options.exportVoiceAsText) {
|
|
||||||
contentValue = voiceTranscriptMap.get(msg.localId) || '[语音消息 - 转文字失败]'
|
|
||||||
} else {
|
|
||||||
contentValue = this.parseMessageContent(msg.content, msg.localType) || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
let senderRole: string
|
let senderRole: string
|
||||||
let senderWxid: string
|
let senderWxid: string
|
||||||
@@ -2242,21 +2277,9 @@ class ExportService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const values: Record<string, string> = {
|
lines.push(`${this.formatTimestamp(msg.createTime)} '${senderRole}'`)
|
||||||
index: String(i + 1),
|
lines.push(contentValue)
|
||||||
time: this.formatTimestamp(msg.createTime),
|
lines.push('')
|
||||||
senderRole,
|
|
||||||
senderNickname,
|
|
||||||
senderWxid,
|
|
||||||
senderRemark,
|
|
||||||
messageType: this.getMessageTypeName(msg.localType),
|
|
||||||
content: contentValue
|
|
||||||
}
|
|
||||||
|
|
||||||
const line = columnOrder
|
|
||||||
.map((id) => this.sanitizeTxtValue(values[id] ?? ''))
|
|
||||||
.join('\t')
|
|
||||||
lines.push(line)
|
|
||||||
|
|
||||||
if ((i + 1) % 200 === 0) {
|
if ((i + 1) % 200 === 0) {
|
||||||
const progress = 60 + Math.floor((i + 1) / sortedMessages.length * 30)
|
const progress = 60 + Math.floor((i + 1) / sortedMessages.length * 30)
|
||||||
|
|||||||
Reference in New Issue
Block a user