Browse Source

复制粘贴上传图片完善

master
La123123 4 weeks ago
parent
commit
7113d7b550
  1. 196
      im-uniapp/pages/chat/chat-box.vue

196
im-uniapp/pages/chat/chat-box.vue

@ -270,6 +270,8 @@ export default {
scrollViewHeight: 0,
maxTmpId: 0,
isFileOpen: false,
isPasting: false, //
hasPasteListener: false, //
};
},
methods: {
@ -1081,11 +1083,24 @@ export default {
.context((res) => {
this.editorCtx = res.context;
// #ifdef H5
// 使document
setTimeout(() => {
document.addEventListener('paste', this.onDocumentPaste);
console.log('已添加粘贴事件监听到document');
}, 100);
// 使
if (!window.__pasteHandlerAdded__) {
window.__pasteHandlerAdded__ = true;
//
if (window.__isPasting__ === undefined) {
window.__isPasting__ = false;
}
console.log('[chat-box] 首次添加粘贴事件监听器');
//
if (this.pasteHandler) {
document.removeEventListener('paste', this.pasteHandler);
}
// 使bindthisthis
this.pasteHandler = this.onDocumentPaste.bind(this);
document.addEventListener('paste', this.pasteHandler);
}
// #endif
})
.exec();
@ -1099,8 +1114,11 @@ export default {
onEditorBlur(e) {
this.isFocus = false;
},
onDocumentPaste(e) {
async onDocumentPaste(e) {
// #ifdef H5
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] 粘贴事件触发, isPasting: ${window.__isPasting__}`);
// editor
const activeElement = document.activeElement;
const isInEditor = activeElement && (
@ -1109,25 +1127,37 @@ export default {
);
if (!isInEditor) {
console.log(`[${timestamp}] 不在editor中,忽略`);
return;
}
// 使
if (window.__isPasting__) {
console.log(`[${timestamp}] 全局isPasting为true,忽略重复触发`);
e.preventDefault();
e.stopPropagation();
return;
}
console.log('文档粘贴事件触发', e);
const items = (e.clipboardData || e.originalEvent.clipboardData).items;
console.log('剪贴板项', items);
let hasImage = false;
for (let i = 0; i < items.length; i++) {
const item = items[i];
console.log('剪贴板项', i, item);
if (item.kind === 'file' && item.type.startsWith('image/')) {
console.log(`[${timestamp}] 检测到图片,开始处理`);
e.preventDefault();
e.stopPropagation();
hasImage = true;
window.__isPasting__ = true;
try {
const file = item.getAsFile();
console.log('获取到的图片文件', file);
//
const reader = new FileReader();
reader.onload = (event) => {
const base64 = event.target.result;
console.log('转换后的base64', base64);
// base64
const base64 = await this.fileToBase64(file);
console.log(`[${timestamp}] base64转换完成,长度: ${base64.length}`);
//
const tempFile = {
path: base64,
@ -1135,26 +1165,66 @@ export default {
size: file.size,
name: file.name || 'pasted-image.png'
};
//
this.handlePasteImage(tempFile);
};
reader.readAsDataURL(file);
await this.handlePasteImage(tempFile);
} catch (error) {
console.log(`[${timestamp}] 处理粘贴图片失败:`, error);
} finally {
window.__isPasting__ = false;
}
break;
}
}
//
if (!hasImage) {
console.log(`[${timestamp}] 没有检测到图片`);
this.isPasting = false;
}
// #endif
},
handlePasteImage(file) {
console.log('handlePasteImage被调用', file);
async fileToBase64(file) {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] fileToBase64被调用,文件大小:`, file.size);
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
console.log(`[${timestamp}] fileToBase64 onload,结果长度:`, event.target.result.length);
resolve(event.target.result);
};
reader.onerror = (error) => {
console.log(`[${timestamp}] fileToBase64 onerror:`, error);
reject(error);
};
reader.readAsDataURL(file);
});
},
async handlePasteImage(file) {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] handlePasteImage被调用, isPasting: ${window.__isPasting__}, chat:`, this.chat);
// chat
if (!this.chat) {
console.log(`[${timestamp}] handlePasteImage: chat为空,忽略`);
return;
}
try {
//
if (this.isBanned) {
this.showBannedTip();
return;
}
let data = {
originUrl: file.path,
thumbUrl: file.path,
};
let msgInfo = {
tmpId: this.generateId(),
fileId: file.uid,
@ -1166,36 +1236,46 @@ export default {
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);
const size = await this.getImageSize(file);
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.chatStore.updateMessage(msgInfo, this.chat);
this.scrollToBottom();
});
//
this.uploadPastedImage(file);
await this.uploadPastedImage(file);
} catch (error) {
console.log(`[${timestamp}] 处理粘贴图片失败:`, error);
this.isPasting = false;
}
},
uploadPastedImage(file) {
console.log('uploadPastedImage被调用', file);
async uploadPastedImage(file) {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] uploadPastedImage被调用`);
// #ifdef H5
try {
// base64Blob
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) {
@ -1208,43 +1288,39 @@ export default {
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);
console.log(`[${timestamp}] 开始上传图片`);
// 使fetch
const response = await fetch(UNI_APP.BASE_URL + `/image/upload?isPermanent=false&thumbSize=50`, {
method: 'POST',
body: formData
});
const data = await response.json();
console.log(`[${timestamp}] 上传响应:`, data);
if (data.code === 200) {
console.log('上传成功,响应数据', data.data);
//
console.log(`[${timestamp}] 上传成功,准备发送消息`);
//
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);
this.chatStore.updateMessage(msgInfo, file.chat);
//
const m = await this.sendMessageRequest(msgInfo);
console.log(`[${timestamp}] 消息发送成功`);
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);
console.log(`[${timestamp}] 上传失败:`, data);
uni.showToast({
icon: "none",
title: data.message || "上传失败",
@ -1253,9 +1329,8 @@ export default {
msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED;
this.chatStore.updateMessage(msgInfo, file.chat);
}
},
fail: (err) => {
console.error("上传图片失败", err);
} catch (error) {
console.log(`[${timestamp}] 上传异常:`, error);
uni.showToast({
icon: "none",
title: "上传失败",
@ -1264,7 +1339,6 @@ export default {
msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED;
this.chatStore.updateMessage(msgInfo, file.chat);
}
});
// #endif
},
onAudioStateChange(state, msgInfo) {
@ -1772,8 +1846,10 @@ export default {
this.unListenKeyboard();
// #ifdef H5
//
if (this.onDocumentPaste) {
document.removeEventListener('paste', this.onDocumentPaste);
if (this.hasPasteListener && this.pasteHandler) {
document.removeEventListener('paste', this.pasteHandler);
this.hasPasteListener = false;
this.pasteHandler = null;
}
// #endif
},

Loading…
Cancel
Save