From f72acd987c4b884f2f9aaf7d7214e2840a8e6f2d Mon Sep 17 00:00:00 2001 From: Lei OT Date: Wed, 6 Mar 2024 14:08:34 +0800 Subject: [PATCH] =?UTF-8?q?MediaUpload:=20=E4=B8=8A=E4=BC=A0=E9=A9=AC?= =?UTF-8?q?=E4=B8=8A=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/msgUtils.js | 93 +++++++++++++++---- src/stores/ConversationStore.js | 8 +- .../Components/Input/MediaUpload.jsx | 68 +++++--------- .../Components/InputComposer.jsx | 35 ++++++- .../Conversations/Components/MessagesList.jsx | 2 +- 5 files changed, 137 insertions(+), 69 deletions(-) diff --git a/src/lib/msgUtils.js b/src/lib/msgUtils.js index 059c7ff..b0fa1b8 100644 --- a/src/lib/msgUtils.js +++ b/src/lib/msgUtils.js @@ -37,7 +37,7 @@ const mediaMsg = { renderId: msg.id, to: msg.to, msgcontent: { - [msg.type]: { link: msg.data.dataUri, caption: msg.text }, + [msg.type]: { link: msg.data.dataUri, ...(msg.text ? { caption: msg.text } : {}) }, ...(msg.context ? { context: msg.context, message_origin: msg.message_origin.msgOrigin } : {}), }, }), @@ -45,7 +45,7 @@ const mediaMsg = { ...msg, actionId: msg.id, conversationid: msg.id.split('.')[0], - data: { ...msg.data, status: {download: true, click: true,}}, + data: { ...msg.data, status: { download: msg.data?.loading ? false : true, click: true, loading: msg.data.loading } }, ...(msg.context ? { reply: { @@ -101,6 +101,19 @@ export const sentMsgTypeMapped = { whatsapp_msg_type: 'image', }), }, + sticker: { + type: 'sticker', + contentToSend: (msg) => ({ + ...mediaMsg.contentToSend({...msg, type: 'sticker'}), + msgtype: 'sticker', + }), + contentToRender: (msg) => ({ + ...msg, + ...mediaMsg.contentToRender(msg), + whatsapp_msg_type: 'sticker', + type: 'photo', + }), + }, video: { type: 'video', contentToSend: (msg) => ({ @@ -216,24 +229,55 @@ export const whatsappMsgTypeMapped = { data: (msg) => ({ id: msg.wamid, text: msg.image.caption, - data: { id: msg.wamid, uri: msg.image.link, width: '100%', height: 200, alt: msg.image.caption, }, + data: { + id: msg.wamid, + uri: msg.image.link, + width: '100%', + height: 200, + alt: msg.image.caption, + status: { + click: true, + loading: 0, + download: true, + }, + }, originText: msg.image?.caption || '', onOpen: () => { console.log('Open image', msg.image.link); }, }), renderForReply: (msg) => ({ - id: msg.wamid, photoURL: msg.image.link, width: '100%', height: 200, alt: '', + id: msg.wamid, + photoURL: msg.image.link, + width: '100%', + height: 200, + alt: '', }), }, sticker: { type: 'photo', data: (msg) => ({ id: msg.wamid, - data: { id: msg.wamid, uri: msg.sticker.link, width: '100%', height: 120, alt: '' }, + data: { + id: msg.wamid, + uri: msg.sticker.link, + width: '100%', + height: 120, + alt: '', + status: { + click: true, + loading: 0, + download: true, + }, + }, }), renderForReply: (msg) => ({ - id: msg.wamid, photoURL: msg.sticker.link, width: '100%', height: 200, alt: '', message: '[表情]' + id: msg.wamid, + photoURL: msg.sticker.link, + width: '100%', + height: 200, + alt: '', + message: '[表情]', }), }, video: { @@ -251,7 +295,13 @@ export const whatsappMsgTypeMapped = { }, }), renderForReply: (msg) => ({ - id: msg.wamid, videoURL: msg.video.link, photoURL: msg.video.link, message: msg.video?.caption || '[视频]', width: 200, height: 200, alt: '', + id: msg.wamid, + videoURL: msg.video.link, + photoURL: msg.video.link, + message: msg.video?.caption || '[视频]', + width: 200, + height: 200, + alt: '', }), }, audio: { @@ -267,13 +317,20 @@ export const whatsappMsgTypeMapped = { unsupported: { type: 'text', data: (msg) => ({ text: '[暂不支持此消息类型]' }) }, reaction: { type: 'text', - data: (msg) => ({ id: msg.wamid, text: msg.reaction?.emoji || '', }), + data: (msg) => ({ id: msg.wamid, text: msg.reaction?.emoji || '' }), }, document: { type: 'file', - data: (msg) => ({ id: msg.wamid, title: msg.document?.filename || '', text: msg.document?.caption || msg.document?.filename || '', data: { uri: msg.document.link, extension: 'PDF', status: { click: false, download: true, loading: 0, } }, originText: msg.document?.caption || msg.document?.filename || '', }), + data: (msg) => ({ + id: msg.wamid, + title: msg.document?.filename || '', + text: msg.document?.caption || msg.document?.filename || '', + data: { uri: msg.document.link, extension: 'PDF', status: { click: false, download: true, loading: 0 } }, + originText: msg.document?.caption || msg.document?.filename || '', + }), renderForReply: (msg) => ({ - id: msg.wamid, message: msg.document?.caption || msg.document?.filename || '', + id: msg.wamid, + message: msg.document?.caption || msg.document?.filename || '', }), }, // location: 'location', @@ -284,8 +341,8 @@ export const whatsappMsgTypeMapped = { template: { type: 'text', data: (msg) => { - const templateDataMapped = msg.template?.components ? msg.template.components.reduce((r, v) => ({...r, [v.type]: v}), {}) : null; - return { id: msg.wamid, text: autoLinkText(templateDataMapped?.body?.text || templateDataMapped?.body?.parameters?.[0]?.text || ''), title: msg.template.name } + const templateDataMapped = msg.template?.components ? msg.template.components.reduce((r, v) => ({ ...r, [v.type]: v }), {}) : null; + return { id: msg.wamid, text: autoLinkText(templateDataMapped?.body?.text || templateDataMapped?.body?.parameters?.[0]?.text || ''), title: msg.template.name }; }, renderForReply: (msg) => { const templateDataMapped = msg.template?.components ? msg.template.components.reduce((r, v) => ({ ...r, [v.type]: v }), {}) : null; @@ -411,9 +468,11 @@ export const handleNotification = (title, _options) => { } // 通知弹窗被点击后的回调 - notification.onclick = () => { - // window.parent.parent.focus(); - window.focus(); // 显示当前标签页 - notification.close(); // 关闭通知,适用于设置了手动关闭的通知 - }; + if (typeof notification !== 'undefined') { + notification.onclick = () => { + // window.parent.parent.focus(); + window.focus(); // 显示当前标签页 + notification.close(); // 关闭通知,适用于设置了手动关闭的通知 + }; + } }; diff --git a/src/stores/ConversationStore.js b/src/stores/ConversationStore.js index f4a74c9..cc6f808 100644 --- a/src/stores/ConversationStore.js +++ b/src/stores/ConversationStore.js @@ -90,7 +90,7 @@ const websocketSlice = (set, get) => ({ }, 500); }, handleMessage: (data) => { - console.log('handleMessage------------------'); + olog('handleMessage------------------'); console.log(data); const { updateMessageItem, sentOrReceivedNewMessage } = get(); const { errcode, errmsg, result } = data; @@ -110,7 +110,6 @@ const websocketSlice = (set, get) => ({ console.log('msgRender msgUpdate', msgRender, msgUpdate); if (['whatsapp.message.updated', 'message', 'error'].includes(resultType)) { updateMessageItem(msgUpdate); - // return false; } if (!isEmpty(msgRender)) { sentOrReceivedNewMessage(msgRender.conversationid, msgRender); @@ -203,7 +202,7 @@ const messageSlice = (set, get) => ({ // msgUpdate console.log('UPDATE_SENT_MESSAGE_ITEM-----------------------------------------------------------------'); // 更新会话中的消息 - const { activeConversations, conversationsList } = get(); + const { activeConversations } = get(); const targetId = message.conversationid; const targetMsgs = (activeConversations[String(targetId)] || []).map((ele) => { // 更新状态 @@ -211,7 +210,8 @@ const messageSlice = (set, get) => ({ if (ele.id === ele.actionId && ele.actionId === message.actionId) { return { ...ele, id: message.id, status: ele.status === 'read' ? ele.status : message.status, dateString: message.dateString }; } else if (ele.id === message.id) { - return { ...ele, id: message.id, status: ele.status === 'read' ? ele.status : message.status, dateString: message.dateString }; + const renderStatus = message?.data?.status ? { status: { ...ele.data.status, loading: 0, download: true } } : {}; + return { ...ele, id: message.id, status: ele.status === 'read' ? ele.status : message.status, dateString: message.dateString, data: { ...ele.data, ...renderStatus } }; } return ele; }); diff --git a/src/views/Conversations/Components/Input/MediaUpload.jsx b/src/views/Conversations/Components/Input/MediaUpload.jsx index 82a855d..e3ef298 100644 --- a/src/views/Conversations/Components/Input/MediaUpload.jsx +++ b/src/views/Conversations/Components/Input/MediaUpload.jsx @@ -1,9 +1,5 @@ -import { useState } from 'react'; import { Upload, Button, message } from 'antd'; -import { - FileImageOutlined, -} from '@ant-design/icons'; -import useConversationStore from '@/stores/ConversationStore'; +import { FileAddOutlined } from '@ant-design/icons'; import { v4 as uuid } from 'uuid'; import { API_HOST } from '@/config'; @@ -17,31 +13,17 @@ const aliOSSHost = `https://haina-sale-system.oss-cn-shenzhen.aliyuncs.com/WAMed * * video * ext: 3g2;3gp;3gp2;3gpp;amr;amv;asf;avi;bdmv;bik;d2v;divx;drc;dsa;dsm;dss;dsv;evo;f4v;flc;fli;flic;flv;hdmov;ifo;ivf;m1v;m2p;m2t;m2ts;m2v;m4b;m4p;m4v;mkv;mp2v;mp4;mp4v;mpe;mpeg;mpg;mpls;mpv2;mpv4;mov;mts;ogm;ogv;pss;pva;qt;ram;ratdvd;rm;rmm;rmvb;roq;rpm;smil;smk;swf;tp;tpr;ts;vob;vp6;webm;wm;wmp;wmv + * */ const fileTypes = { - 'photo': ['ani','bmp','gif','ico','jpe','jpeg','jpg','pcx','png','psd','tga','tif','tiff','wmf'], + 'sticker': ['webp'], + 'photo': ['ani','bmp','ico','jpe','jpeg','jpg','pcx','png','psd','tga','tif','tiff','wmf'], 'audio': ['aac','ac3','aif','aifc','aiff','au','cda','dts','fla','flac','it','m1a','m2a','m3u','m4a','mid','midi','mka','mod','mp2','mp3','mpa','ogg','ra','rmi','spc','rmi','snd','umx','voc','wav','wma','xm'], - 'video': ['3g2','3gp','3gp2','3gpp','amr','amv','asf','avi','bdmv','bik','d2v','divx','drc','dsa','dsm','dsv','evo','f4v','flc','fli','flic','flv','hdmov','ifo','ivf','m1v','m2p','m2t','m2ts','m2v','m4b','m4p','m4v','mkv','mp2v','mp4','mp4v','mpe','mpeg','mpg','mpls','mpv2','mpv4','mov','mts','ogm','ogv','pss','pva','qt','ram','ratdvd','rm','rmm','rmvb','roq','rpm','smil','smk','swf','tp','tpr','ts','vob','vp6','webm','wm','wmp','wmv'], + 'video': ['gif','3g2','3gp','3gp2','3gpp','amr','amv','asf','avi','bdmv','bik','d2v','divx','drc','dsa','dsm','dsv','evo','f4v','flc','fli','flic','flv','hdmov','ifo','ivf','m1v','m2p','m2t','m2ts','m2v','m4b','m4p','m4v','mkv','mp2v','mp4','mp4v','mpe','mpeg','mpg','mpls','mpv2','mpv4','mov','mts','ogm','ogv','pss','pva','qt','ram','ratdvd','rm','rmm','rmvb','roq','rpm','smil','smk','swf','tp','tpr','ts','vob','vp6','webm','wm','wmp','wmv'], }; -const ImageUpload = ({ disabled }) => { - // const currentConversation = useConversationStore(state => state.currentConversation); - const setComplexMsg = useConversationStore(state => state.setComplexMsg); - const complexMsg = useConversationStore(state => state.complexMsg); - // const aliOSSToken = useConversationStore(state => state.aliOSSToken); - - const [uploading, setUploading] = useState(false); +const ImageUpload = ({ disabled, invokeUploadFileMessage, invokeSendUploadMessage }) => { - const handleSendImage = (file) => { - const msgObj = { - type: file.type, // 'photo', - name: file.name, - status: 'loading', - data: { uri: file.previewSrc, dataUri: file.dataUri, width: '100%', height: 150 }, - id: uuid(), - }; - setComplexMsg(msgObj); - }; const beforeUpload = async (file) => { // 使用 FileReader 读取文件对象 const reader = new FileReader(); @@ -53,7 +35,15 @@ const ImageUpload = ({ disabled }) => { const name = file.name; // const filename = Date.now() + suffix; const dataUri = aliOSSHost + file.name; - handleSendImage({ previewSrc, dataUri, type, suffix, name}); + const msgObj = { + type: type, + name: name, + // status: 'loading', + data: { uri: previewSrc, dataUri: dataUri, width: '100%', height: 150, loading: 0.01 }, + id: uuid(), + }; + file.msgData = msgObj; + invokeUploadFileMessage(msgObj); }; // 把文件对象作为一个 dataURL 读入 reader.readAsDataURL(file); @@ -62,41 +52,27 @@ const ImageUpload = ({ disabled }) => { const uploadProps = { name: 'file', action: `${API_HOST}/WAFileUpload`, + // action: 'https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188', // test: headers: { 'X-Requested-With': null }, showUploadList: false, - // onChange: handleChange, - // onRemove, - // data: getExtraData, beforeUpload, + maxCount: 1, }; return ( { - // console.log('fileList', info.fileList); - setUploading(info.file.status === 'uploading'); - setComplexMsg({...complexMsg, status: 'loading'}) - if (info.file.status !== 'uploading') { - // console.log(info.file, info.fileList); - setComplexMsg({...complexMsg, status: info.file.status}) + onChange={({file}) => { + if (file.status === 'done') { + invokeSendUploadMessage(file.msgData); } - if (info.file.status === 'done') { - // 会闪烁 - setComplexMsg({ - ...complexMsg, - status: info.file.status, - data: { ...complexMsg.data, uri: complexMsg.data.dataUri, [`${complexMsg.type}URL`]: complexMsg.data.dataUri }, - }); - // message.success(`${info.file.name} file uploaded successfully`); - } else if (info.file.status === 'error') { + if (file.status === 'error') { message.error(`添加失败`); - setComplexMsg({ ...complexMsg, status: info.file.status, data: { ...complexMsg.data, uri: '', [`${complexMsg.type}URL`]: '' } }); } }} > -