refactor(TiptapEditor): 重构消息转换逻辑以支持多消息分段处理
重构 tiptapToMessage 函数,将单条消息处理改为支持多条消息分段处理 优化消息内容处理流程,添加文本缓冲区和图片单独处理逻辑 简化消息发送逻辑,移除 msgType 判断改为直接处理不同类型消息 清理已注释的导航功能代码
This commit is contained in:
parent
dd170cb50d
commit
8be8afc675
@ -457,71 +457,106 @@ function onRecorderEvent(file) {
|
||||
|
||||
// 将Tiptap内容转换为消息格式
|
||||
function tiptapToMessage() {
|
||||
if (!editor.value) return { items: [], mentions: [], mentionUids: [], quoteId: '', msgType: 1 }
|
||||
if (!editor.value) return []
|
||||
|
||||
const json = editor.value.getJSON()
|
||||
const resp = {
|
||||
items: [],
|
||||
mentions: [],
|
||||
mentionUids: [],
|
||||
quoteId: '',
|
||||
msgType: 1
|
||||
const messages = []
|
||||
let quoteId = null
|
||||
let currentTextBuffer = ''
|
||||
let currentMentions = []
|
||||
let currentMentionUids = new Set()
|
||||
|
||||
const flushTextBuffer = () => {
|
||||
const content = currentTextBuffer.trim()
|
||||
if (content) {
|
||||
const data = {
|
||||
items: [{ type: 1, content: content }],
|
||||
mentions: [...currentMentions],
|
||||
mentionUids: Array.from(currentMentionUids)
|
||||
}
|
||||
if (quoteId) {
|
||||
data.quoteId = quoteId
|
||||
quoteId = null
|
||||
}
|
||||
messages.push({ type: 'text', data })
|
||||
}
|
||||
currentTextBuffer = ''
|
||||
currentMentions = []
|
||||
currentMentionUids.clear()
|
||||
}
|
||||
|
||||
// 处理引用
|
||||
const quoteNode = json.content?.find((node) => node.type === 'quote')
|
||||
if (quoteNode) {
|
||||
resp.quoteId = quoteNode.attrs.id
|
||||
}
|
||||
|
||||
// 处理内容
|
||||
let textContent = ''
|
||||
let hasImage = false
|
||||
|
||||
const processNode = (node) => {
|
||||
const processInlines = nodes => {
|
||||
nodes.forEach(node => {
|
||||
if (node.type === 'text') {
|
||||
textContent += node.text
|
||||
currentTextBuffer += node.text
|
||||
} else if (node.type === 'mention') {
|
||||
textContent += ` @${node.attrs.label} `
|
||||
resp.mentions.push({
|
||||
name: `@${node.attrs.label}`,
|
||||
atid: parseInt(node.attrs.id)
|
||||
})
|
||||
} else if (node.type === 'emoji') {
|
||||
textContent += node.attrs.alt
|
||||
} else if (node.type === 'image') {
|
||||
hasImage = true
|
||||
resp.items.push({
|
||||
type: 3,
|
||||
content: node.attrs.src
|
||||
})
|
||||
} else if (node.content) {
|
||||
node.content.forEach(processNode)
|
||||
currentTextBuffer += `@${node.attrs.label} `
|
||||
const uid = parseInt(node.attrs.id)
|
||||
if (!currentMentionUids.has(uid)) {
|
||||
currentMentionUids.add(uid)
|
||||
currentMentions.push({ name: `@${node.attrs.label}`, atid: uid })
|
||||
}
|
||||
} else if (node.type === 'emoji') {
|
||||
currentTextBuffer += node.attrs.alt
|
||||
} else if (node.type === 'hardBreak') {
|
||||
currentTextBuffer += '\n'
|
||||
} else if (node.type === 'image') {
|
||||
// 处理段落内的图片
|
||||
flushTextBuffer()
|
||||
const data = {
|
||||
...getImageInfo(node.attrs.src),
|
||||
url: node.attrs.src
|
||||
}
|
||||
if (quoteId) {
|
||||
data.quoteId = quoteId
|
||||
quoteId = null
|
||||
}
|
||||
messages.push({ type: 'image', data })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (json.content) {
|
||||
json.content.forEach(processNode)
|
||||
const quoteIndex = json.content.findIndex(node => node.type === 'quote')
|
||||
if (quoteIndex > -1) {
|
||||
quoteId = json.content[quoteIndex].attrs.id
|
||||
json.content.splice(quoteIndex, 1)
|
||||
}
|
||||
|
||||
// 如果有文本内容,添加到items
|
||||
if (textContent.trim()) {
|
||||
resp.items.unshift({
|
||||
type: 1,
|
||||
content: textContent.trim()
|
||||
json.content.forEach(node => {
|
||||
if (node.type === 'paragraph') {
|
||||
if (node.content) {
|
||||
processInlines(node.content)
|
||||
}
|
||||
currentTextBuffer += '\n' // Add newline after each paragraph
|
||||
} else if (node.type === 'image') {
|
||||
flushTextBuffer()
|
||||
const data = {
|
||||
...getImageInfo(node.attrs.src),
|
||||
url: node.attrs.src
|
||||
}
|
||||
if (quoteId) {
|
||||
data.quoteId = quoteId
|
||||
quoteId = null
|
||||
}
|
||||
messages.push({ type: 'image', data })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 设置消息类型
|
||||
if (resp.items.length > 1) {
|
||||
resp.msgType = 12 // 混合消息
|
||||
} else if (resp.items.length === 1) {
|
||||
resp.msgType = resp.items[0].type
|
||||
flushTextBuffer()
|
||||
|
||||
if (messages.length > 0) {
|
||||
const lastMessage = messages[messages.length - 1]
|
||||
if (lastMessage.type === 'text') {
|
||||
lastMessage.data.items[0].content = lastMessage.data.items[0].content.trim()
|
||||
if (!lastMessage.data.items[0].content) {
|
||||
messages.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp.mentionUids = resp.mentions.map((item) => item.atid)
|
||||
|
||||
return resp
|
||||
return messages
|
||||
}
|
||||
|
||||
// 将Tiptap内容转换为纯文本
|
||||
@ -550,52 +585,36 @@ function isEditorEmpty() {
|
||||
* 根据编辑器内容类型发送不同类型的消息
|
||||
*/
|
||||
function onSendMessage() {
|
||||
if (!editor.value) return
|
||||
if (!editor.value || isEditorEmpty()) return
|
||||
|
||||
if (isEditorEmpty()) return
|
||||
const messages = tiptapToMessage()
|
||||
|
||||
const data = tiptapToMessage()
|
||||
|
||||
if (data.items.length === 0 || (data.items[0].type === 1 && !data.items[0].content.trim())) {
|
||||
return // 没有内容不发送
|
||||
if (messages.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (data.msgType) {
|
||||
case 1: // 文字消息
|
||||
if (data.items[0].content.length > 1024) {
|
||||
return window['$message'].info('发送内容超长,请分条发送')
|
||||
let canClear = true
|
||||
messages.forEach(msg => {
|
||||
if (msg.type === 'text') {
|
||||
if (msg.data.items[0].content.length > 1024) {
|
||||
window['$message'].info('发送内容超长,请分条发送')
|
||||
canClear = false
|
||||
return
|
||||
}
|
||||
emit('editor-event', emitCall('text_event', msg.data))
|
||||
} else if (msg.type === 'image') {
|
||||
const data = {
|
||||
height: 0,
|
||||
width: 0,
|
||||
size: 10000,
|
||||
url: msg.data.url,
|
||||
}
|
||||
emit('editor-event', emitCall('image_event', data))
|
||||
}
|
||||
|
||||
// 发送文本消息
|
||||
emit(
|
||||
'editor-event',
|
||||
emitCall('text_event', data, (ok) => {
|
||||
ok && editor.value?.commands.clearContent(true) // 成功发送后清空编辑器
|
||||
})
|
||||
)
|
||||
break
|
||||
case 3: // 图片消息
|
||||
// 发送图片消息
|
||||
emit(
|
||||
'editor-event',
|
||||
emitCall(
|
||||
'image_event',
|
||||
{ ...getImageInfo(data.items[0].content), url: data.items[0].content, size: 10000 },
|
||||
(ok) => {
|
||||
ok && editor.value?.commands.clearContent(true) // 成功发送后清空编辑器
|
||||
}
|
||||
)
|
||||
)
|
||||
break
|
||||
case 12: // 图文混合消息
|
||||
// 发送混合消息
|
||||
emit(
|
||||
'editor-event',
|
||||
emitCall('mixed_event', data, (ok) => {
|
||||
ok && editor.value?.commands.clearContent(true) // 成功发送后清空编辑器
|
||||
})
|
||||
)
|
||||
break
|
||||
|
||||
if (canClear) {
|
||||
editor.value?.commands.clearContent(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -728,45 +747,7 @@ const navs = reactive([
|
||||
uploadFileRef.value.click() // 触发文件上传
|
||||
}
|
||||
},
|
||||
// 以下功能已被注释掉,但保留代码
|
||||
// {
|
||||
// title: '代码',
|
||||
// icon: markRaw(SourceCode),
|
||||
// show: true,
|
||||
// click: () => {
|
||||
// isShowEditorCode.value = true
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// title: '语音消息',
|
||||
// icon: markRaw(IconVoice),
|
||||
// show: true,
|
||||
// click: () => {
|
||||
// isShowEditorRecorder.value = true
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// title: '地理位置',
|
||||
// icon: markRaw(Local),
|
||||
// show: true,
|
||||
// click: () => {}
|
||||
// },
|
||||
// {
|
||||
// title: '群投票',
|
||||
// icon: markRaw(Ranking),
|
||||
// show: computed(() => props.vote),
|
||||
// click: () => {
|
||||
// isShowEditorVote.value = true
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// title: '历史记录',
|
||||
// icon: markRaw(History),
|
||||
// show: true,
|
||||
// click: () => {
|
||||
// emit('editor-event', emitCall('history_event'))
|
||||
// }
|
||||
// }
|
||||
|
||||
])
|
||||
|
||||
// 监听聊天索引变化,切换聊天时加载对应草稿
|
||||
|
Loading…
Reference in New Issue
Block a user