From 303f603eb1d6cb5bf9cbc36b56cf6772f524c3bf Mon Sep 17 00:00:00 2001 From: La123123 <617330105@qq.com> Date: Mon, 20 Apr 2026 09:42:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=8D=E5=88=B6=E7=B2=98=E8=B4=B4=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-uniapp/pages/chat/chat-box.vue | 181 ++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/im-uniapp/pages/chat/chat-box.vue b/im-uniapp/pages/chat/chat-box.vue index 046954f..84aa86e 100644 --- a/im-uniapp/pages/chat/chat-box.vue +++ b/im-uniapp/pages/chat/chat-box.vue @@ -1080,6 +1080,13 @@ export default { .select("#editor") .context((res) => { this.editorCtx = res.context; + // #ifdef H5 + // 只使用document监听粘贴事件,避免重复触发 + setTimeout(() => { + document.addEventListener('paste', this.onDocumentPaste); + console.log('已添加粘贴事件监听到document'); + }, 100); + // #endif }) .exec(); }); @@ -1092,6 +1099,174 @@ export default { onEditorBlur(e) { this.isFocus = false; }, + onDocumentPaste(e) { + // #ifdef H5 + // 检查是否在editor中粘贴 + const activeElement = document.activeElement; + const isInEditor = activeElement && ( + activeElement.closest('#editor') || + activeElement.closest('.ql-editor') + ); + + if (!isInEditor) { + return; + } + + console.log('文档粘贴事件触发', e); + const items = (e.clipboardData || e.originalEvent.clipboardData).items; + console.log('剪贴板项', items); + for (let i = 0; i < items.length; i++) { + const item = items[i]; + console.log('剪贴板项', i, item); + if (item.kind === 'file' && item.type.startsWith('image/')) { + e.preventDefault(); + e.stopPropagation(); + const file = item.getAsFile(); + console.log('获取到的图片文件', file); + // 将文件转换为临时路径 + const reader = new FileReader(); + reader.onload = (event) => { + const base64 = event.target.result; + console.log('转换后的base64', base64); + // 创建临时文件对象 + const tempFile = { + path: base64, + uid: this.generateId(), + size: file.size, + name: file.name || 'pasted-image.png' + }; + // 调用现有的图片上传逻辑 + this.handlePasteImage(tempFile); + }; + reader.readAsDataURL(file); + break; + } + } + // #endif + }, + handlePasteImage(file) { + console.log('handlePasteImage被调用', file); + // 检查是否被封禁 + if (this.isBanned) { + this.showBannedTip(); + return; + } + let data = { + originUrl: file.path, + thumbUrl: file.path, + }; + let msgInfo = { + tmpId: this.generateId(), + fileId: file.uid, + sendId: this.mine.id, + content: JSON.stringify(data), + sendTime: new Date().getTime(), + selfSend: true, + type: this.$enums.MESSAGE_TYPE.IMAGE, + readedCount: 0, + status: this.$enums.MESSAGE_STATUS.SENDING, + }; + console.log('创建的消息信息', msgInfo); + // 填充对方id + this.fillTargetId(msgInfo, this.chat.targetId); + // 插入消息 + this.chatStore.insertMessage(msgInfo, this.chat); + // 会话置顶 + this.moveChatToTop(); + // 借助file对象保存 + file.msgInfo = msgInfo; + file.chat = this.chat; + // 更新图片宽高 + let chat = this.chat; + this.getImageSize(file).then((size) => { + console.log('获取到图片尺寸', size); + msgInfo = JSON.parse(JSON.stringify(msgInfo)); + data.width = size.width; + data.height = size.height; + msgInfo.content = JSON.stringify(data); + this.chatStore.updateMessage(msgInfo, chat); + this.scrollToBottom(); + }); + // 上传图片到服务器 + this.uploadPastedImage(file); + }, + uploadPastedImage(file) { + console.log('uploadPastedImage被调用', file); + // #ifdef H5 + // 将base64转换为Blob + const base64Data = file.path.split(',')[1]; + console.log('base64数据长度', base64Data.length); + const byteCharacters = atob(base64Data); + const byteArrays = []; + for (let offset = 0; offset < byteCharacters.length; offset += 512) { + const slice = byteCharacters.slice(offset, offset + 512); + const byteNumbers = new Array(slice.length); + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i); + } + const byteArray = new Uint8Array(byteNumbers); + byteArrays.push(byteArray); + } + const blob = new Blob(byteArrays, { type: 'image/png' }); + console.log('创建的Blob对象', blob); + + // 创建FormData + const formData = new FormData(); + formData.append('file', blob, file.name); + console.log('创建的FormData', formData); + + // 上传图片 + console.log('开始上传图片'); + uni.uploadFile({ + url: UNI_APP.BASE_URL + `/image/upload?isPermanent=false&thumbSize=50`, + filePath: file.path, + name: 'file', + success: (res) => { + console.log('上传响应', res); + const data = JSON.parse(res.data); + if (data.code === 200) { + console.log('上传成功,响应数据', data.data); + // 上传成功,更新消息 + let msgInfo = JSON.parse(JSON.stringify(file.msgInfo)); + msgInfo.content = JSON.stringify(data.data); + msgInfo.receipt = this.isReceipt; + this.sendMessageRequest(msgInfo) + .then((m) => { + console.log('消息发送成功', m); + msgInfo.id = m.id; + msgInfo.status = m.status; + this.isReceipt = false; + this.chatStore.updateMessage(msgInfo, file.chat); + }) + .catch(() => { + console.log('消息发送失败'); + msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED; + this.chatStore.updateMessage(msgInfo, file.chat); + }); + } else { + console.log('上传失败,响应码', data.code); + uni.showToast({ + icon: "none", + title: data.message || "上传失败", + }); + let msgInfo = JSON.parse(JSON.stringify(file.msgInfo)); + msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED; + this.chatStore.updateMessage(msgInfo, file.chat); + } + }, + fail: (err) => { + console.error("上传图片失败", err); + uni.showToast({ + icon: "none", + title: "上传失败", + }); + let msgInfo = JSON.parse(JSON.stringify(file.msgInfo)); + msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED; + this.chatStore.updateMessage(msgInfo, file.chat); + } + }); + // #endif + }, onAudioStateChange(state, msgInfo) { const playingAudio = this.$refs["message" + msgInfo.id][0]; if (state == "PLAYING" && playingAudio != this.playingAudio) { @@ -1595,6 +1770,12 @@ export default { }, onUnload() { this.unListenKeyboard(); + // #ifdef H5 + // 移除粘贴事件监听 + if (this.onDocumentPaste) { + document.removeEventListener('paste', this.onDocumentPaste); + } + // #endif }, };