MediaUpload: 上传马上发送

dev/chat
Lei OT 2 years ago
parent 89c6cb3134
commit f72acd987c

@ -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(); // 关闭通知,适用于设置了手动关闭的通知
};
}
};

@ -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;
});

@ -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 (
<Upload
{...uploadProps}
onChange={(info) => {
// 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`]: '' } });
}
}}
>
<Button key={'addPic'} type='text' disabled={disabled} icon={<FileImageOutlined />} size={'middle'} className='text-primary rounded-none' />
<Button key={'addPic'} type='text' disabled={disabled} icon={<FileAddOutlined />} size={'middle'} className='text-primary rounded-none' />
</Upload>
);
};

@ -67,6 +67,39 @@ const InputComposer = () => {
setComplexMsg({});
};
/**
* 先推到消息记录上面, 再发送
*/
const invokeUploadFileMessage = (msgObj) => {
const msgObjMerge = {
sender: 'me',
senderName: 'me',
to: currentConversation.whatsapp_phone_number,
date: new Date(),
status: 'waiting',
...(referenceMsg.id ? { context: { message_id: referenceMsg.id }, message_origin: referenceMsg } : {}),
...msgObj,
id: `${currentConversation.sn}.${msgObj.id}`,
};
const contentToRender = sentMsgTypeMapped[msgObjMerge.type].contentToRender(msgObjMerge);
sentOrReceivedNewMessage(contentToRender.conversationid, contentToRender);
};
const invokeSendUploadMessage = (msgObj) => {
const msgObjMerge = {
sender: 'me',
senderName: 'me',
to: currentConversation.whatsapp_phone_number,
date: new Date(),
status: 'waiting',
...(referenceMsg.id ? { context: { message_id: referenceMsg.id }, message_origin: referenceMsg } : {}),
...msgObj,
id: `${currentConversation.sn}.${msgObj.id}`,
};
const contentToSend = sentMsgTypeMapped[msgObjMerge.type].contentToSend(msgObjMerge);
websocket.sendMessage({ ...contentToSend, opi_sn: userId, coli_sn: currentConversation.coli_sn });
}
const focusInput = () => {
textInputRef.current.focus({ cursor: 'end', preventScroll: true, });
};
@ -139,7 +172,7 @@ const InputComposer = () => {
<Flex gap={4} className='*:text-primary *:rounded-none'>
<InputTemplate key='templates' disabled={!talkabled || textabled} invokeSendMessage={invokeSendMessage} />
<InputEmoji key='emoji' disabled={!textabled} inputEmoji={addEmoji} />
<InputMediaUpload key={'addNewMedia'} disabled={!textabled} />
<InputMediaUpload key={'addNewMedia'} disabled={!textabled} {...{invokeUploadFileMessage, invokeSendUploadMessage}} />
{/* <Button type='text' className='' icon={<YoutubeOutlined />} size={'middle'} />
<Button type='text' className='' icon={<AudioOutlined />} size={'middle'} />
<Button type='text' className='' icon={<FolderAddOutlined />} size={'middle'} />

@ -139,7 +139,7 @@ const MessagesList = ({ reference, ...props }) => {
// </Dropdown>
))}
</div>
<Button onClick={toBottom} shape={'circle'} className=' absolute bottom-1 right-4' icon={<DownOutlined />} />
<Button onClick={toBottom} ghost type={'dashed'} shape={'circle'} className=' absolute bottom-1 right-4' icon={<DownOutlined />} />
<Image src={null} preview={{ visible: previewVisible, src: previewSrc, onClose: onPreviewClose }} />
</div>
);

Loading…
Cancel
Save