refactor(TiptapEditor): 重构消息转换逻辑以支持多消息分段处理
重构 tiptapToMessage 函数,将单条消息处理改为支持多条消息分段处理 优化消息内容处理流程,添加文本缓冲区和图片单独处理逻辑 简化消息发送逻辑,移除 msgType 判断改为直接处理不同类型消息 清理已注释的导航功能代码
This commit is contained in:
parent
dd170cb50d
commit
8be8afc675
@ -457,71 +457,106 @@ function onRecorderEvent(file) {
|
|||||||
|
|
||||||
// 将Tiptap内容转换为消息格式
|
// 将Tiptap内容转换为消息格式
|
||||||
function tiptapToMessage() {
|
function tiptapToMessage() {
|
||||||
if (!editor.value) return { items: [], mentions: [], mentionUids: [], quoteId: '', msgType: 1 }
|
if (!editor.value) return []
|
||||||
|
|
||||||
const json = editor.value.getJSON()
|
const json = editor.value.getJSON()
|
||||||
const resp = {
|
const messages = []
|
||||||
items: [],
|
let quoteId = null
|
||||||
mentions: [],
|
let currentTextBuffer = ''
|
||||||
mentionUids: [],
|
let currentMentions = []
|
||||||
quoteId: '',
|
let currentMentionUids = new Set()
|
||||||
msgType: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理引用
|
const flushTextBuffer = () => {
|
||||||
const quoteNode = json.content?.find((node) => node.type === 'quote')
|
const content = currentTextBuffer.trim()
|
||||||
if (quoteNode) {
|
if (content) {
|
||||||
resp.quoteId = quoteNode.attrs.id
|
const data = {
|
||||||
}
|
items: [{ type: 1, content: content }],
|
||||||
|
mentions: [...currentMentions],
|
||||||
// 处理内容
|
mentionUids: Array.from(currentMentionUids)
|
||||||
let textContent = ''
|
}
|
||||||
let hasImage = false
|
if (quoteId) {
|
||||||
|
data.quoteId = quoteId
|
||||||
const processNode = (node) => {
|
quoteId = null
|
||||||
if (node.type === 'text') {
|
}
|
||||||
textContent += node.text
|
messages.push({ type: 'text', data })
|
||||||
} 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 = ''
|
||||||
|
currentMentions = []
|
||||||
|
currentMentionUids.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.content) {
|
const processInlines = nodes => {
|
||||||
json.content.forEach(processNode)
|
nodes.forEach(node => {
|
||||||
}
|
if (node.type === 'text') {
|
||||||
|
currentTextBuffer += node.text
|
||||||
// 如果有文本内容,添加到items
|
} else if (node.type === 'mention') {
|
||||||
if (textContent.trim()) {
|
currentTextBuffer += `@${node.attrs.label} `
|
||||||
resp.items.unshift({
|
const uid = parseInt(node.attrs.id)
|
||||||
type: 1,
|
if (!currentMentionUids.has(uid)) {
|
||||||
content: textContent.trim()
|
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) {
|
||||||
if (resp.items.length > 1) {
|
const quoteIndex = json.content.findIndex(node => node.type === 'quote')
|
||||||
resp.msgType = 12 // 混合消息
|
if (quoteIndex > -1) {
|
||||||
} else if (resp.items.length === 1) {
|
quoteId = json.content[quoteIndex].attrs.id
|
||||||
resp.msgType = resp.items[0].type
|
json.content.splice(quoteIndex, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 })
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.mentionUids = resp.mentions.map((item) => item.atid)
|
flushTextBuffer()
|
||||||
|
|
||||||
return resp
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将Tiptap内容转换为纯文本
|
// 将Tiptap内容转换为纯文本
|
||||||
@ -550,52 +585,36 @@ function isEditorEmpty() {
|
|||||||
* 根据编辑器内容类型发送不同类型的消息
|
* 根据编辑器内容类型发送不同类型的消息
|
||||||
*/
|
*/
|
||||||
function onSendMessage() {
|
function onSendMessage() {
|
||||||
if (!editor.value) return
|
if (!editor.value || isEditorEmpty()) return
|
||||||
|
|
||||||
if (isEditorEmpty()) return
|
const messages = tiptapToMessage()
|
||||||
|
|
||||||
const data = tiptapToMessage()
|
if (messages.length === 0) {
|
||||||
|
return
|
||||||
if (data.items.length === 0 || (data.items[0].type === 1 && !data.items[0].content.trim())) {
|
|
||||||
return // 没有内容不发送
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (data.msgType) {
|
let canClear = true
|
||||||
case 1: // 文字消息
|
messages.forEach(msg => {
|
||||||
if (data.items[0].content.length > 1024) {
|
if (msg.type === 'text') {
|
||||||
return window['$message'].info('发送内容超长,请分条发送')
|
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))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 发送文本消息
|
if (canClear) {
|
||||||
emit(
|
editor.value?.commands.clearContent(true)
|
||||||
'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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,45 +747,7 @@ const navs = reactive([
|
|||||||
uploadFileRef.value.click() // 触发文件上传
|
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