From de474f9e2869d4d82740b866e04f6bf1db5c6b58 Mon Sep 17 00:00:00 2001 From: Lei OT Date: Thu, 7 Mar 2024 14:49:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E9=99=84=E4=BB=B6:=20?= =?UTF-8?q?=E5=8F=91=E9=80=81=E7=9B=B8=E5=BA=94=E7=9A=84=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?;=20=0B=E6=B6=88=E6=81=AF=E7=B1=BB=E5=9E=8B=E8=A7=A3=E6=9E=90:?= =?UTF-8?q?=20contacts,=20location?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/msgUtils.js | 64 ++++++++++++++++--- .../Components/Input/MediaUpload.jsx | 23 ++++--- .../Components/InputComposer.jsx | 9 ++- .../Conversations/Components/MessagesList.jsx | 17 ++++- 4 files changed, 91 insertions(+), 22 deletions(-) diff --git a/src/lib/msgUtils.js b/src/lib/msgUtils.js index b0fa1b8..382a45a 100644 --- a/src/lib/msgUtils.js +++ b/src/lib/msgUtils.js @@ -37,7 +37,11 @@ const mediaMsg = { renderId: msg.id, to: msg.to, msgcontent: { - [msg.type]: { link: msg.data.dataUri, ...(msg.text ? { caption: msg.text } : {}) }, + [msg.type]: { + link: msg.data.dataUri, + ...(msg.text ? { caption: msg.text } : {}), + ...(msg.type === 'document' ? { filename: msg.name } : {}) + }, ...(msg.context ? { context: msg.context, message_origin: msg.message_origin.msgOrigin } : {}), }, }), @@ -126,6 +130,22 @@ export const sentMsgTypeMapped = { whatsapp_msg_type: 'video', }), }, + document: { + type: 'document', + contentToSend: (msg) => ({ + ...mediaMsg.contentToSend(msg), + msgtype: 'document', + }), + contentToRender: (msg) => ({ + ...msg, + ...mediaMsg.contentToRender(msg), + text: msg?.name || '', + title: msg?.name || '', + originText: msg?.name || '', + whatsapp_msg_type: 'document', + type: 'file', + }), + }, whatsappTemplate: { contentToSend: (msg) => ({ action: 'message', actionId: msg.id, renderId: msg.id, to: msg.to, msgtype: 'template', msgcontent: msg.template }), contentToRender: (msg) => { @@ -314,7 +334,11 @@ export const whatsappMsgTypeMapped = { }), }, // unsupported: { type: 'system', data: (msg) => ({ text: 'Message type is currently not supported.' }) }, - unsupported: { type: 'text', data: (msg) => ({ text: '[暂不支持此消息类型]' }) }, + unsupported: { + type: 'text', + data: (msg) => ({ id: msg.wamid, text: `[暂不支持此消息类型](${msg.wamid})` }), + renderForReply: (msg) => ({ id: msg.wamid, text: `[Message type unsupported](${msg.wamid})` }), + }, reaction: { type: 'text', data: (msg) => ({ id: msg.wamid, text: msg.reaction?.emoji || '' }), @@ -333,7 +357,30 @@ export const whatsappMsgTypeMapped = { message: msg.document?.caption || msg.document?.filename || '', }), }, - // location: 'location', + contacts: { + type: 'meetingLink', + data: (msg) => ({ + id: msg.wamid, + meetingID: msg.wamid, + title: msg.contacts.length === 1 ? `联系人` : `${msg.contacts.length} 位联系人`, + text: msg.contacts.map((ele) => `${ele.name.formatted_name}: ${ele.phones[0].wa_id}`).join('\n'), + data: msg.contacts.map((ele) => ({ id: ele.phones[0].wa_id, wa_id: ele.phones[0].wa_id, name: ele.name.formatted_name })), + }), + }, + location: { + type: 'location', + data: (msg) => ({ + id: msg.wamid, + title: msg.location.name || '位置信息', + text: msg.location.address || '位置', + src: msg.location.url || 'https://cdn.pixabay.com/photo/2016/03/22/04/23/map-1272165_1280.png', + data: { + longitude: msg.location?.longitude, + latitude: msg.location?.latitude, + }, + originText: msg.location?.address || '', + }), + }, // contact: 'contact', // 'contact-card': 'contact-card', // 'contact-card-with-photo': 'contact-card-with-photo', @@ -355,13 +402,14 @@ export const whatsappMsgTypeMapped = { */ export const parseRenderMessageItem = (msg) => { console.log('parseRenderMessageItem', msg); + const thisMsgType = Object.keys(receivedMsgTypeMapped).incluses(msg.type) ? msg.type : 'unsupported'; return { msgOrigin: msg, date: msg?.sendTime || msg?.createTime || '', - ...(whatsappMsgTypeMapped?.[msg.type]?.data(msg) || {}), + ...(whatsappMsgTypeMapped?.[thisMsgType]?.data(msg) || {}), conversationid: msg.conversationid, - ...(typeof whatsappMsgTypeMapped[msg.type].type === 'function' ? whatsappMsgTypeMapped[msg.type].type(msg) : { type: whatsappMsgTypeMapped[msg.type].type || 'text' }), - // type: whatsappMsgTypeMapped?.[msg.type]?.type || 'text', + ...(typeof whatsappMsgTypeMapped[thisMsgType].type === 'function' ? whatsappMsgTypeMapped[thisMsgType].type(msg) : { type: whatsappMsgTypeMapped[thisMsgType].type || 'text' }), + // type: whatsappMsgTypeMapped?.[thisMsgType]?.type || 'text', from: msg.from, sender: msg.from, senderName: msg?.customerProfile?.name || msg.from, @@ -378,8 +426,8 @@ export const parseRenderMessageItem = (msg) => { * reply: { message: msg.messageorigin, title: 'React from', titleColor: '#1ba784' } */ title: msg.messageorigin?.customerProfile?.name || 'me', - ...(typeof whatsappMsgTypeMapped[msg?.messageorigin?.type]?.renderForReply === 'function' - ? whatsappMsgTypeMapped[msg.messageorigin.type].renderForReply(msg.messageorigin) + ...(typeof whatsappMsgTypeMapped[(msg?.messageorigin?.type || 'unsupported')]?.renderForReply === 'function' + ? whatsappMsgTypeMapped[(msg?.messageorigin?.type || 'unsupported')].renderForReply(msg.messageorigin) : {}), titleColor: msg.messageorigin?.customerProfile?.name ? '#a791ff' : "#128c7e", }, diff --git a/src/views/Conversations/Components/Input/MediaUpload.jsx b/src/views/Conversations/Components/Input/MediaUpload.jsx index e3ef298..863c2e5 100644 --- a/src/views/Conversations/Components/Input/MediaUpload.jsx +++ b/src/views/Conversations/Components/Input/MediaUpload.jsx @@ -2,6 +2,7 @@ import { Upload, Button, message } from 'antd'; import { FileAddOutlined } from '@ant-design/icons'; import { v4 as uuid } from 'uuid'; import { API_HOST } from '@/config'; +import useConversationStore from '@/stores/ConversationStore'; const aliOSSHost = `https://haina-sale-system.oss-cn-shenzhen.aliyuncs.com/WAMedia/`; /** @@ -15,15 +16,19 @@ const aliOSSHost = `https://haina-sale-system.oss-cn-shenzhen.aliyuncs.com/WAMed * 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 = { - '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': ['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 fileTypesExt = { + sticker: ['webp'], + photo: ['jpeg', 'jpg', 'png'], + video: ['gif', 'mp4', '3gp'], + document: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv'], + audio: ['aac', 'mp4', 'm4a', 'mp3', 'amr', 'ogg'], }; const ImageUpload = ({ disabled, invokeUploadFileMessage, invokeSendUploadMessage }) => { + // const setComplexMsg = useConversationStore(state => state.setComplexMsg); + // const complexMsg = useConversationStore(state => state.complexMsg); + const beforeUpload = async (file) => { // 使用 FileReader 读取文件对象 const reader = new FileReader(); @@ -31,15 +36,15 @@ const ImageUpload = ({ disabled, invokeUploadFileMessage, invokeSendUploadMessag reader.onload = (event) => { const previewSrc = event.target.result; const suffix = file.name.slice(file.name.lastIndexOf('.')+1); - const type = Object.keys(fileTypes).find((type) => fileTypes[type].includes(suffix)); + const type = Object.keys(fileTypesExt).find((type) => fileTypesExt[type].includes(suffix)); const name = file.name; - // const filename = Date.now() + suffix; + const rename = Date.now() + '.' + suffix; const dataUri = aliOSSHost + file.name; const msgObj = { type: type, - name: name, + name: file.name, // status: 'loading', - data: { uri: previewSrc, dataUri: dataUri, width: '100%', height: 150, loading: 0.01 }, + data: { uri: previewSrc, dataUri: dataUri, link: dataUri, width: '100%', height: 150, loading: 0.01 }, id: uuid(), }; file.msgData = msgObj; diff --git a/src/views/Conversations/Components/InputComposer.jsx b/src/views/Conversations/Components/InputComposer.jsx index 06bb38a..390eb17 100644 --- a/src/views/Conversations/Components/InputComposer.jsx +++ b/src/views/Conversations/Components/InputComposer.jsx @@ -54,12 +54,12 @@ const InputComposer = () => { ...msgObj, id: `${currentConversation.sn}.${uuid()}`, }; - olog('sendMessage------------------', msgObjMerge) + // olog('sendMessage------------------', msgObjMerge) const contentToSend = sentMsgTypeMapped[msgObjMerge.type].contentToSend(msgObjMerge); - console.log('content to send-------------------------------------', contentToSend); + // console.log('content to send-------------------------------------', contentToSend); websocket.sendMessage({ ...contentToSend, opi_sn: userId, coli_sn: currentConversation.coli_sn }); const contentToRender = sentMsgTypeMapped[msgObjMerge.type].contentToRender(msgObjMerge); - console.log(contentToRender, 'contentToRender sendMessage------------------'); + // console.log(contentToRender, 'contentToRender sendMessage------------------'); sentOrReceivedNewMessage(contentToRender.conversationid, contentToRender); setTextContent(''); @@ -81,7 +81,9 @@ const InputComposer = () => { ...msgObj, id: `${currentConversation.sn}.${msgObj.id}`, }; + // olog('invoke upload', msgObjMerge) const contentToRender = sentMsgTypeMapped[msgObjMerge.type].contentToRender(msgObjMerge); + // console.log(contentToRender, 'contentToRender sendMessage------------------'); sentOrReceivedNewMessage(contentToRender.conversationid, contentToRender); }; @@ -97,6 +99,7 @@ const InputComposer = () => { id: `${currentConversation.sn}.${msgObj.id}`, }; const contentToSend = sentMsgTypeMapped[msgObjMerge.type].contentToSend(msgObjMerge); + // olog('invoke upload send +++ ', contentToSend) websocket.sendMessage({ ...contentToSend, opi_sn: userId, coli_sn: currentConversation.coli_sn }); } diff --git a/src/views/Conversations/Components/MessagesList.jsx b/src/views/Conversations/Components/MessagesList.jsx index a862d7b..5040359 100644 --- a/src/views/Conversations/Components/MessagesList.jsx +++ b/src/views/Conversations/Components/MessagesList.jsx @@ -6,8 +6,9 @@ import useConversationStore from '@/stores/ConversationStore'; import { useShallow } from 'zustand/react/shallow'; import { isEmpty, olog } from '@/utils/utils'; -const MessagesList = ({ reference, ...props }) => { +const MessagesList = ({ reference, contactsModalOpen, setContactsModalOpen, ...props }) => { const setReferenceMsg = useConversationStore(useShallow((state) => state.setReferenceMsg)); + olog('render message list'); const scrollToMessage = (id, index) => { const _i = index || props.dataSource.findIndex((msg) => msg.id === id); @@ -47,7 +48,7 @@ const MessagesList = ({ reference, ...props }) => { return false; case 'file': - window.open(msg.data.uri, '_blank', 'noopener,noreferrer'); + window.open(msg.data.link || msg.data.uri, '_blank', 'noopener,noreferrer'); return false; default: @@ -135,6 +136,18 @@ const MessagesList = ({ reference, ...props }) => { replyButton: ['text', 'document', 'image'].includes(message.whatsapp_msg_type) ? true : false, className: 'whitespace-pre-wrap', })} + {...(message.type === 'meetingLink' + ? { + actionButtons: [ + { + onClickButton: () => { + navigator.clipboard.writeText(message.text); + }, + Component: () =>
复制
, + }, + ], + } + : {})} /> // ))}