feat: 优化消息发送逻辑和编辑器功能
- 在vite配置中启用vueDevTools工具 - 重构PanelFooter.vue中的图片消息发送逻辑,改为直接调用onSendMessage - 修改CustomEditor.vue的消息发送逻辑,支持分类型处理消息内容 - 增加编辑器引用元素的检查逻辑,避免无效引用 - 优化图片上传后的URL替换逻辑,确保编辑器内容更新
This commit is contained in:
parent
f279248a51
commit
17c1368346
@ -312,7 +312,16 @@ const handleKeydown = (event) => {
|
|||||||
console.log('editorHtml.value', editorHtml.value)
|
console.log('editorHtml.value', editorHtml.value)
|
||||||
// 确保编辑器内容不为空(文本、图片、文件或表情)
|
// 确保编辑器内容不为空(文本、图片、文件或表情)
|
||||||
// 由于我们已经在 handleInput 中处理了表情文本,editorContent.value 应该包含表情文本
|
// 由于我们已经在 handleInput 中处理了表情文本,editorContent.value 应该包含表情文本
|
||||||
if (editorContent.value.trim()) {
|
// if (editorContent.value.trim()) {
|
||||||
|
if (true) {
|
||||||
|
// 检查引用元素是否存在,如果不存在但 quoteData 有值,则清除 quoteData
|
||||||
|
const editor = editorRef.value
|
||||||
|
const quoteElement = editor?.querySelector('.editor-quote')
|
||||||
|
if (!quoteElement && quoteData.value) {
|
||||||
|
console.log('引用元素已被删除,但 quoteData 仍有值,清除 quoteData')
|
||||||
|
quoteData.value = null
|
||||||
|
}
|
||||||
|
|
||||||
// 解析并输出编辑器内容
|
// 解析并输出编辑器内容
|
||||||
const messageData = parseEditorContent()
|
const messageData = parseEditorContent()
|
||||||
console.log('编辑器内容解析结果:', JSON.stringify(messageData, null, 2))
|
console.log('编辑器内容解析结果:', JSON.stringify(messageData, null, 2))
|
||||||
@ -335,9 +344,9 @@ const handleKeydown = (event) => {
|
|||||||
const sendMessage = () => {
|
const sendMessage = () => {
|
||||||
console.log('发送消息');
|
console.log('发送消息');
|
||||||
// 检查编辑器是否有内容:文本内容(包括表情文本)
|
// 检查编辑器是否有内容:文本内容(包括表情文本)
|
||||||
if (!editorContent.value.trim()) {
|
// if (!editorContent.value.trim()) {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
console.log('发送消息1');
|
console.log('发送消息1');
|
||||||
const messageData = parseEditorContent()
|
const messageData = parseEditorContent()
|
||||||
|
|
||||||
@ -353,38 +362,51 @@ const sendMessage = () => {
|
|||||||
image: quoteData.value.image
|
image: quoteData.value.image
|
||||||
} : null
|
} : null
|
||||||
})
|
})
|
||||||
|
messageData.items.forEach(item => {
|
||||||
if (editingMessage.value) {
|
// 处理文本内容
|
||||||
// 编辑消息
|
if (item.type === 1) {
|
||||||
emit('editor-event', {
|
const data={
|
||||||
event: 'edit_message',
|
items:[{
|
||||||
data: {
|
content:item.content,
|
||||||
...messageData,
|
type:1
|
||||||
msg_id: editingMessage.value.msg_id
|
}],
|
||||||
},
|
mentionUids:messageData.mentionUids,
|
||||||
callBack: (success) => {
|
mentions:[],
|
||||||
if (success) {
|
quoteId:messageData.quoteId,
|
||||||
clearEditor()
|
|
||||||
editingMessage.value = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
console.log('发送前',data)
|
||||||
} else {
|
emit(
|
||||||
// 发送新消息
|
'editor-event',
|
||||||
const eventType = messageData.items.length > 1 ? 'mixed_event' :
|
emitCall('text_event', data,(ok)=>{
|
||||||
messageData.items[0].type === 1 ? 'text_event' :
|
console.log('发送后',ok)
|
||||||
messageData.items[0].type + '_event'
|
})
|
||||||
console.log('发送消息2',eventType);
|
)
|
||||||
emit('editor-event', {
|
}else if(item.type === 2){
|
||||||
event: eventType,
|
//图片消息
|
||||||
data: messageData,
|
}else if(item.type === 3){
|
||||||
callBack: (success) => {
|
console.log('发送图片消息')
|
||||||
if (success) {
|
const data={
|
||||||
clearEditor()
|
height:0,
|
||||||
|
width:0,
|
||||||
|
size:10000,
|
||||||
|
url:item.content,
|
||||||
}
|
}
|
||||||
|
emit(
|
||||||
|
'editor-event',
|
||||||
|
emitCall(
|
||||||
|
'image_event',
|
||||||
|
data,
|
||||||
|
(ok) => {
|
||||||
|
// 成功发送后清空编辑器
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}else if(item.type === 4){
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析编辑器内容
|
// 解析编辑器内容
|
||||||
@ -505,7 +527,7 @@ const parseEditorContent = () => {
|
|||||||
const result = {
|
const result = {
|
||||||
items: items.length > 0 ? items : [{ type: 1, content: '' }],
|
items: items.length > 0 ? items : [{ type: 1, content: '' }],
|
||||||
mentionUids,
|
mentionUids,
|
||||||
quoteId: quoteData.value?.msg_id || 0
|
quoteId: quoteElements.length > 0 && quoteData.value ? quoteData.value.msg_id ||'' : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果有引用信息,添加到结果中
|
// 如果有引用信息,添加到结果中
|
||||||
@ -632,9 +654,19 @@ async function onUploadFile(e) {
|
|||||||
// 上传图片并获取永久URL
|
// 上传图片并获取永久URL
|
||||||
uploadImg(form).then(({ code, data, message }) => {
|
uploadImg(form).then(({ code, data, message }) => {
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
// 上传成功后,可以将临时URL替换为永久URL
|
// 上传成功后,将临时URL替换为永久URL
|
||||||
// 但这里我们不做替换,因为临时URL在当前会话中已足够使用
|
|
||||||
console.log('图片上传成功:', data.ori_url);
|
console.log('图片上传成功:', data.ori_url);
|
||||||
|
|
||||||
|
// 查找编辑器中刚插入的图片元素并替换其src为永久URL
|
||||||
|
const editorImages = editorRef.value.querySelectorAll('img.editor-image');
|
||||||
|
// 查找最后插入的图片(通常是最近添加的那个)
|
||||||
|
const lastImage = editorImages[editorImages.length - 1];
|
||||||
|
if (lastImage && lastImage.src === tempUrl) {
|
||||||
|
// 替换为永久URL
|
||||||
|
lastImage.src = data.ori_url;
|
||||||
|
// 触发输入事件更新编辑器内容
|
||||||
|
handleInput({ target: editorRef.value });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
window['$message'].error(message);
|
window['$message'].error(message);
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,13 @@ import {
|
|||||||
} from '@/store'
|
} from '@/store'
|
||||||
import ws from '@/connect'
|
import ws from '@/connect'
|
||||||
import { ServePublishMessage, ServeSendVote } from '@/api/chat'
|
import { ServePublishMessage, ServeSendVote } from '@/api/chat'
|
||||||
import CustomEditor from '@/components/editor/CustomEditor.vue'
|
|
||||||
import { throttle, getVideoImage } from '@/utils/common'
|
import { throttle, getVideoImage } from '@/utils/common'
|
||||||
import { parseTime } from '@/utils/datetime'
|
import { parseTime } from '@/utils/datetime'
|
||||||
import Editor from '@/components/editor/Editor.vue'
|
import Editor from '@/components/editor/Editor.vue'
|
||||||
import MultiSelectFooter from './MultiSelectFooter.vue'
|
import MultiSelectFooter from './MultiSelectFooter.vue'
|
||||||
import HistoryRecord from '@/components/talk/HistoryRecord.vue'
|
import HistoryRecord from '@/components/talk/HistoryRecord.vue'
|
||||||
import {scrollToBottom} from '@/utils/dom.ts'
|
import {scrollToBottom} from '@/utils/dom.ts'
|
||||||
|
import CustomEditor from '@/components/editor/CustomEditor.vue'
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const talkStore = useTalkStore()
|
const talkStore = useTalkStore()
|
||||||
const editorStore = useEditorStore()
|
const editorStore = useEditorStore()
|
||||||
@ -61,11 +61,11 @@ const onSendMessage = (data = {}, callBack: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ServePublishMessage(message)
|
ServePublishMessage(message)
|
||||||
.then(({ code, message }) => {
|
.then(({ code, message, msg }) => {
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
callBack(true)
|
callBack(true)
|
||||||
} else {
|
} else {
|
||||||
window['$message'].warning(message)
|
window['$message'].warning(message || msg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@ -95,60 +95,8 @@ const onSendTextEvent = throttle((value: any) => {
|
|||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
// 发送图片消息
|
// 发送图片消息
|
||||||
const onSendImageEvent = ({ data }) => {
|
const onSendImageEvent = ({ data, callBack }) => {
|
||||||
console.log('onSendImageEvent')
|
onSendMessage({ type: 'image', ...data }, callBack)
|
||||||
|
|
||||||
// 先创建一个带有上传ID的临时消息对象,用于显示进度
|
|
||||||
const uploadId = `image-${Date.now()}-${Math.floor(Math.random() * 1000)}`
|
|
||||||
|
|
||||||
// 创建本地预览URL
|
|
||||||
const previewUrl = URL.createObjectURL(data)
|
|
||||||
|
|
||||||
// 创建临时消息记录
|
|
||||||
const tempMessage = {
|
|
||||||
msg_id: uploadId,
|
|
||||||
sequence: Date.now(),
|
|
||||||
talk_type: props.talk_type,
|
|
||||||
msg_type: 3, // 图片消息类型
|
|
||||||
user_id: props.uid,
|
|
||||||
receiver_id: props.receiver_id,
|
|
||||||
is_revoke: 0,
|
|
||||||
is_mark: 0,
|
|
||||||
is_read: 1,
|
|
||||||
content: '',
|
|
||||||
created_at: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}'),
|
|
||||||
extra: {
|
|
||||||
url: previewUrl, // 使用本地预览URL
|
|
||||||
size: data.size,
|
|
||||||
is_uploading: true,
|
|
||||||
upload_id: uploadId,
|
|
||||||
percentage: 0
|
|
||||||
},
|
|
||||||
isCheck: false,
|
|
||||||
send_status: 1,
|
|
||||||
float: 'right' // 我发送的消息显示在右侧
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直接添加到对话记录中
|
|
||||||
dialogueStore.addDialogueRecord(tempMessage)
|
|
||||||
nextTick(()=>{
|
|
||||||
scrollToBottom()
|
|
||||||
})
|
|
||||||
uploadsStore.initUploadFile(
|
|
||||||
data,
|
|
||||||
props.talk_type,
|
|
||||||
props.receiver_id,
|
|
||||||
uploadId,
|
|
||||||
async (percentage) => {
|
|
||||||
dialogueStore.updateUploadProgress(uploadId, percentage)
|
|
||||||
},
|
|
||||||
async () => {
|
|
||||||
// 清理本地预览URL
|
|
||||||
URL.revokeObjectURL(previewUrl)
|
|
||||||
dialogueStore.batchDelDialogueRecord([uploadId])
|
|
||||||
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送视频消息
|
// 发送视频消息
|
||||||
|
@ -46,9 +46,9 @@ export default defineConfig(({ mode }) => {
|
|||||||
vueJsx({}),
|
vueJsx({}),
|
||||||
compressPlugin(),
|
compressPlugin(),
|
||||||
UnoCSS(),
|
UnoCSS(),
|
||||||
// vueDevTools({
|
vueDevTools({
|
||||||
// launchEditor: 'trae',
|
launchEditor: 'trae',
|
||||||
// })
|
})
|
||||||
],
|
],
|
||||||
define: {
|
define: {
|
||||||
__APP_ENV__: env.APP_ENV
|
__APP_ENV__: env.APP_ENV
|
||||||
|
Loading…
Reference in New Issue
Block a user