Browse Source

复制粘贴上传图片完善

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

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

@ -270,6 +270,8 @@ export default {
scrollViewHeight: 0, scrollViewHeight: 0,
maxTmpId: 0, maxTmpId: 0,
isFileOpen: false, isFileOpen: false,
isPasting: false, //
hasPasteListener: false, //
}; };
}, },
methods: { methods: {
@ -1081,11 +1083,24 @@ export default {
.context((res) => { .context((res) => {
this.editorCtx = res.context; this.editorCtx = res.context;
// #ifdef H5 // #ifdef H5
// 使document // 使
setTimeout(() => { if (!window.__pasteHandlerAdded__) {
document.addEventListener('paste', this.onDocumentPaste); window.__pasteHandlerAdded__ = true;
console.log('已添加粘贴事件监听到document'); //
}, 100); 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 // #endif
}) })
.exec(); .exec();
@ -1099,8 +1114,11 @@ export default {
onEditorBlur(e) { onEditorBlur(e) {
this.isFocus = false; this.isFocus = false;
}, },
onDocumentPaste(e) { async onDocumentPaste(e) {
// #ifdef H5 // #ifdef H5
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] 粘贴事件触发, isPasting: ${window.__isPasting__}`);
// editor // editor
const activeElement = document.activeElement; const activeElement = document.activeElement;
const isInEditor = activeElement && ( const isInEditor = activeElement && (
@ -1109,25 +1127,37 @@ export default {
); );
if (!isInEditor) { if (!isInEditor) {
console.log(`[${timestamp}] 不在editor中,忽略`);
return;
}
// 使
if (window.__isPasting__) {
console.log(`[${timestamp}] 全局isPasting为true,忽略重复触发`);
e.preventDefault();
e.stopPropagation();
return; return;
} }
console.log('文档粘贴事件触发', e);
const items = (e.clipboardData || e.originalEvent.clipboardData).items; const items = (e.clipboardData || e.originalEvent.clipboardData).items;
console.log('剪贴板项', items); let hasImage = false;
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
const item = items[i]; const item = items[i];
console.log('剪贴板项', i, item);
if (item.kind === 'file' && item.type.startsWith('image/')) { if (item.kind === 'file' && item.type.startsWith('image/')) {
console.log(`[${timestamp}] 检测到图片,开始处理`);
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const file = item.getAsFile(); hasImage = true;
console.log('获取到的图片文件', file); window.__isPasting__ = true;
//
const reader = new FileReader(); try {
reader.onload = (event) => { const file = item.getAsFile();
const base64 = event.target.result;
console.log('转换后的base64', base64); // base64
const base64 = await this.fileToBase64(file);
console.log(`[${timestamp}] base64转换完成,长度: ${base64.length}`);
// //
const tempFile = { const tempFile = {
path: base64, path: base64,
@ -1135,136 +1165,180 @@ export default {
size: file.size, size: file.size,
name: file.name || 'pasted-image.png' name: file.name || 'pasted-image.png'
}; };
// //
this.handlePasteImage(tempFile); await this.handlePasteImage(tempFile);
}; } catch (error) {
reader.readAsDataURL(file); console.log(`[${timestamp}] 处理粘贴图片失败:`, error);
} finally {
window.__isPasting__ = false;
}
break; break;
} }
} }
//
if (!hasImage) {
console.log(`[${timestamp}] 没有检测到图片`);
this.isPasting = false;
}
// #endif // #endif
}, },
handlePasteImage(file) {
console.log('handlePasteImage被调用', file); async fileToBase64(file) {
// const timestamp = new Date().toISOString();
if (this.isBanned) { console.log(`[${timestamp}] fileToBase64被调用,文件大小:`, file.size);
this.showBannedTip(); 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; return;
} }
let data = {
originUrl: file.path, try {
thumbUrl: file.path, //
}; if (this.isBanned) {
let msgInfo = { this.showBannedTip();
tmpId: this.generateId(), return;
fileId: file.uid, }
sendId: this.mine.id,
content: JSON.stringify(data), let data = {
sendTime: new Date().getTime(), originUrl: file.path,
selfSend: true, thumbUrl: file.path,
type: this.$enums.MESSAGE_TYPE.IMAGE, };
readedCount: 0,
status: this.$enums.MESSAGE_STATUS.SENDING, let msgInfo = {
}; tmpId: this.generateId(),
console.log('创建的消息信息', msgInfo); fileId: file.uid,
// id sendId: this.mine.id,
this.fillTargetId(msgInfo, this.chat.targetId); content: JSON.stringify(data),
// sendTime: new Date().getTime(),
this.chatStore.insertMessage(msgInfo, this.chat); selfSend: true,
// type: this.$enums.MESSAGE_TYPE.IMAGE,
this.moveChatToTop(); readedCount: 0,
// file status: this.$enums.MESSAGE_STATUS.SENDING,
file.msgInfo = msgInfo; };
file.chat = this.chat;
// // id
let chat = this.chat; this.fillTargetId(msgInfo, this.chat.targetId);
this.getImageSize(file).then((size) => {
console.log('获取到图片尺寸', size); //
this.chatStore.insertMessage(msgInfo, this.chat);
//
this.moveChatToTop();
// file
file.msgInfo = msgInfo;
file.chat = this.chat;
//
const size = await this.getImageSize(file);
msgInfo = JSON.parse(JSON.stringify(msgInfo)); msgInfo = JSON.parse(JSON.stringify(msgInfo));
data.width = size.width; data.width = size.width;
data.height = size.height; data.height = size.height;
msgInfo.content = JSON.stringify(data); msgInfo.content = JSON.stringify(data);
this.chatStore.updateMessage(msgInfo, chat); this.chatStore.updateMessage(msgInfo, this.chat);
this.scrollToBottom(); 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 // #ifdef H5
// base64Blob try {
const base64Data = file.path.split(',')[1]; // base64Blob
console.log('base64数据长度', base64Data.length); const base64Data = file.path.split(',')[1];
const byteCharacters = atob(base64Data); const byteCharacters = atob(base64Data);
const byteArrays = []; const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += 512) { for (let offset = 0; offset < byteCharacters.length; offset += 512) {
const slice = byteCharacters.slice(offset, offset + 512); const slice = byteCharacters.slice(offset, offset + 512);
const byteNumbers = new Array(slice.length); const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) { for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(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);
} }
}, const byteArray = new Uint8Array(byteNumbers);
fail: (err) => { byteArrays.push(byteArray);
console.error("上传图片失败", err); }
const blob = new Blob(byteArrays, { type: 'image/png' });
// FormData
const formData = new FormData();
formData.append('file', blob, file.name);
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(`[${timestamp}] 上传成功,准备发送消息`);
//
let msgInfo = JSON.parse(JSON.stringify(file.msgInfo));
msgInfo.content = JSON.stringify(data.data);
msgInfo.receipt = this.isReceipt;
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);
} else {
console.log(`[${timestamp}] 上传失败:`, data);
uni.showToast({ uni.showToast({
icon: "none", icon: "none",
title: "上传失败", title: data.message || "上传失败",
}); });
let msgInfo = JSON.parse(JSON.stringify(file.msgInfo)); let msgInfo = JSON.parse(JSON.stringify(file.msgInfo));
msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED; msgInfo.status = this.$enums.MESSAGE_STATUS.FAILED;
this.chatStore.updateMessage(msgInfo, file.chat); this.chatStore.updateMessage(msgInfo, file.chat);
} }
}); } catch (error) {
console.log(`[${timestamp}] 上传异常:`, error);
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 // #endif
}, },
onAudioStateChange(state, msgInfo) { onAudioStateChange(state, msgInfo) {
@ -1772,8 +1846,10 @@ export default {
this.unListenKeyboard(); this.unListenKeyboard();
// #ifdef H5 // #ifdef H5
// //
if (this.onDocumentPaste) { if (this.hasPasteListener && this.pasteHandler) {
document.removeEventListener('paste', this.onDocumentPaste); document.removeEventListener('paste', this.pasteHandler);
this.hasPasteListener = false;
this.pasteHandler = null;
} }
// #endif // #endif
}, },

Loading…
Cancel
Save