会话无订单时的切换; 测试地址; 测试会话;

dev/chat
Lei OT 2 years ago
parent b91314db0f
commit d0ea6c8b7b

@ -82,7 +82,7 @@ const whatsappMsgMapped = {
// console.log('_r', _r); // console.log('_r', _r);
// return parseRenderMessageItem(contentObj); // return parseRenderMessageItem(contentObj);
}, },
contentToUpdate: (msgcontent) => ({ ...msgcontent, id: msgcontent.id, status: msgcontent.status }), contentToUpdate: (msgcontent) => ({ ...msgcontent, id: msgcontent.wamid, status: msgcontent.status }),
}, },
}; };
export const receivedMsgTypeMapped = { export const receivedMsgTypeMapped = {
@ -199,6 +199,6 @@ export const parseRenderMessageList = (messages) => {
* WhatsApp Templates params * WhatsApp Templates params
*/ */
export const whatsappTemplatesParamMapped = { export const whatsappTemplatesParamMapped = {
'say_hello': [['customer_name']], 'asia_highlights_has_receive_your_inquiry': [['customer_name']],
'asia_highlights_has_receive_your_inquiry': [['agent_name']], 'hello_from_asia_highlights': [['agent_name']], // todo:
}; };

@ -18,7 +18,8 @@ export async function fetchJSON(url, data) {
return await response.json(); return await response.json();
} }
const API_HOST = 'http://202.103.68.144:8888'; // const API_HOST = 'http://202.103.68.144:8888';
const API_HOST = 'https://p9axztuwd7x8a7.mycht.cn/whatsapp_callback';
export const useConversations = ({loginUser, realtimeAPI}) => { export const useConversations = ({loginUser, realtimeAPI}) => {
const { userId } = loginUser; const { userId } = loginUser;
@ -28,7 +29,7 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
const [activeConversations, setActiveConversations] = useState({}); // all active conversation const [activeConversations, setActiveConversations] = useState({}); // all active conversation
const [currentID, setCurrentID] = useState(); const [currentID, setCurrentID] = useState();
const [conversationsList, setConversationsList] = useState([]); // open conversations const [conversationsList, setConversationsList] = useState([]); // open conversations
const [currentConversation, setCurrentConversation] = useState({ id: '', customer_name: '', order_sn: '' }); const [currentConversation, setCurrentConversation] = useState({ sn: '', customer_name: '', coli_sn: '' });
const currentConversationRef = useRef(currentConversation); const currentConversationRef = useRef(currentConversation);
useEffect(() => { useEffect(() => {
currentConversationRef.current = currentConversation; currentConversationRef.current = currentConversation;
@ -67,13 +68,16 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
const getConversationsList = async () => { const getConversationsList = async () => {
const data = await fetchJSON('http://127.0.0.1:4523/m2/3888351-0-default/142426823'); const { result: data } = await fetchJSON(`${API_HOST}/getconversations`, { opisn: userId });
const dataMapped = data.reduce((r, v) => ({ ...r, [v.id]: [] }), {}); // const _data = [];
setConversationsList(data); const _data = testConversations;
const list = [..._data, ...data];
const dataMapped = list.reduce((r, v) => ({ ...r, [v.sn]: [] }), {});
setConversationsList(list);
setActiveConversations({...dataMapped, ...activeConversations}); setActiveConversations({...dataMapped, ...activeConversations});
console.log(data, dataMapped); console.log(list, dataMapped);
if (data && data.length) { if (list && list.length) {
switchConversation(data[0]); switchConversation(list[0]);
} }
}; };
@ -88,28 +92,43 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
const [customerOrderProfile, setCustomerProfile] = useState({}); const [customerOrderProfile, setCustomerProfile] = useState({});
const getCustomerProfile = async (colisn) => { const getCustomerProfile = async (colisn) => {
const data = await fetchJSON(`${API_HOST}/getorderinfo`, { colisn }); const { result } = await fetchJSON(`${API_HOST}/getorderinfo`, { colisn });
setCustomerProfile(data.result?.[0] || {}); const data = result?.[0] || {};
setCustomerProfile(data);
if (!isEmpty(data.conversation)) {
setConversationsList((pre) => [...data.conversations, ...pre]);
setCurrentConversation(data.conversation[0]);
const thisCMapped = data.conversation.reduce((r, v) => ({ ...r, [v.sn]: [] }), {});
setActiveConversations((pre) => ({ ...pre, ...thisCMapped }));
setMessages([]); // todo: 获取当前会话的历史消息
} else {
// reset chat window
setMessages([]);
setCurrentConversation({ sn: '', customer_name: '', coli_sn: '' });
// todo: 加入新会话
}
}; };
const switchConversation = (cc) => { const switchConversation = (cc) => {
setCurrentID(cc.id); setCurrentID(cc.sn);
setCurrentConversation(cc); setCurrentConversation({...cc, id: cc.sn, customer_name: cc.whatsapp_name});
// const _all = [];
const _all = all.map((ele) => receivedMsgTypeMapped['whatsapp.inbound_message.received'].contentToRender(ele)); // debug: 0
// todo: update msg status
// const _all = all2.map((ele) => receivedMsgTypeMapped['whatsapp.message.updated'].contentToRender(ele)); // debug: 0
setMessages([..._all, ...(activeConversations[cc.id] || [])]);
// Get customer profile when switching conversation // Get customer profile when switching conversation
// getCustomerProfile(??); // getCustomerProfile(??);
}; };
// Get customer profile when switching conversation // Get customer profile when switching conversation
// useEffect(() => { useEffect(() => {
// const colisn = currentConversation.order_sn; console.log('currentConversation', currentConversation);
// getCustomerProfile(colisn); // const colisn = currentConversation.coli_sn;
// return () => {}; // getCustomerProfile(colisn);
// }, [currentConversation]); const _all = [];
// const _all = all.map((ele) => receivedMsgTypeMapped['whatsapp.inbound_message.received'].contentToRender(ele)); // debug: 0
// todo: update msg status
// const _all = all2.map((ele) => receivedMsgTypeMapped['whatsapp.message.updated'].contentToRender(ele)); // debug: 0
setMessages([..._all, ...(activeConversations[currentID] || [])]);
return () => {};
}, [currentConversation]);
/** /**
* ***************************************************************************************************** * *****************************************************************************************************
@ -149,7 +168,7 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
const addMessage = (message) => { const addMessage = (message) => {
setMessages((prevMessages) => [...prevMessages, message]); setMessages((prevMessages) => [...prevMessages, message]);
addMessageToConversations(currentConversationRef.current.id, message); addMessageToConversations(currentConversationRef.current.sn, message);
}; };
const updateMessage = (message) => { const updateMessage = (message) => {
@ -164,7 +183,7 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
return targetMsgs; return targetMsgs;
}); });
// 更新会话中的消息 // 更新会话中的消息
const targetId = currentConversationRef.current.id; const targetId = currentConversationRef.current.sn;
setActiveConversations((prevList) => ({ setActiveConversations((prevList) => ({
...prevList, ...prevList,
[targetId]: targetMsgs, [targetId]: targetMsgs,
@ -565,3 +584,38 @@ const AllTemplates = [
'statusUpdateEvent': 'APPROVED', 'statusUpdateEvent': 'APPROVED',
}, },
]; ];
const testConversations = [
{
'sn': 3001,
'opi_sn': 354,
'coli_sn': 0,
'whatsapp_phone_number': '+8618777396951',
"last_received_time": new Date().toDateString(),
"last_send_time": new Date().toDateString(),
'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2),
'whatsapp_name': 'LiaoYijun',
'customer_name': 'LiaoYijun',
},
{
'sn': 3002,
'opi_sn': 354,
'coli_sn': 0,
'whatsapp_phone_number': '+8613317835586',
"last_received_time": new Date().toDateString(),
"last_send_time": new Date().toDateString(),
'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2),
'whatsapp_name': 'QinQianSheng',
'customer_name': 'QinQianSheng',
},
// {
// 'sn': 3003,
// 'opi_sn': 354,
// 'coli_sn': 240129003,
// 'whatsapp_phone_number': '+8618777396951',
// "last_received_time": new Date().toDateString(),
// "last_send_time": new Date().toDateString(),
// 'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2),
// 'whatsapp_name': 'LeiYuanTing',
// },
];

@ -11,9 +11,6 @@ import { useConversationContext } from '@/stores/Conversations/ConversationConte
import './Conversations.css'; import './Conversations.css';
import { useAuthContext } from '@/stores/AuthContext.js'; import { useAuthContext } from '@/stores/AuthContext.js';
import dayjs from 'dayjs';
import utc from 'dayjs-plugin-utc';
dayjs.extend(utc);
const { Sider, Content, Header, Footer } = Layout; const { Sider, Content, Header, Footer } = Layout;
@ -47,15 +44,15 @@ const ChatWindow = (() => {
<Layout className='h-full'> <Layout className='h-full'>
<Header className='ant-layout-sider-light ant-card p-1 h-auto'> <Header className='ant-layout-sider-light ant-card p-1 h-auto'>
<Flex gap={16}> <Flex gap={16}>
<Avatar src={`https://api.dicebear.com/7.x/avataaars/svg?seed=${currentConversation.customer_name}`}>{currentConversation.customer_name}</Avatar> <Avatar src={`https://api.dicebear.com/7.x/avataaars/svg?seed=${currentConversation.customer_name}`} />
<Flex flex={'1'} justify='space-between'> <Flex flex={'1'} justify='space-between'>
<Flex vertical={true} justify='space-between'> <Flex vertical={true} justify='space-between'>
<Typography.Text strong>{currentConversation.customer_name}</Typography.Text> <Typography.Text strong>{currentConversation.customer_name}</Typography.Text>
{/* <Typography.Text>{contact?.phone}</Typography.Text> */} <Typography.Text>{currentConversation.whatsapp_phone_number}</Typography.Text>
</Flex> </Flex>
<Flex vertical={true} justify='space-between'> <Flex vertical={true} justify='space-between'>
<Typography.Text> <Typography.Text>
<LocalTimeClock /> <Typography.Text strong>{order?.location} </Typography.Text> {/* <LocalTimeClock /> <Typography.Text strong>{order?.location} </Typography.Text> */}
</Typography.Text> </Typography.Text>
{/* <Typography.Text>{customerDateTime}</Typography.Text> */} {/* <Typography.Text>{customerDateTime}</Typography.Text> */}
</Flex> </Flex>

@ -16,12 +16,14 @@ const Conversations = (() => {
setChatlist( setChatlist(
(conversationsList || []).map((item) => ({ (conversationsList || []).map((item) => ({
...item, ...item,
avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${item.customer_name}`, avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${item.whatsapp_name}`,
alt: item.customer_name, alt: item.whatsapp_name,
title: item.customer_name, id: item.sn,
subtitle: item.lastMessage, title: item.whatsapp_name,
date: item.last_time, subtitle: item.whatsapp_phone_number,
unread: item.new_msgs, // subtitle: item.lastMessage,
date: item.last_received_time, // last_send_time
unread: item.unread_msg_count,
})) }))
); );
@ -30,12 +32,14 @@ const Conversations = (() => {
const onSwitchConversation = (item) => { const onSwitchConversation = (item) => {
switchConversation(item); switchConversation(item);
navigate(`/order/chat/${item.order_sn}`, { replace: true }); if (item.coli_sn) {
navigate(`/order/chat/${item.coli_sn}`, { replace: true });
}
} }
return ( return (
<> <>
<ChatList className='chat-list' dataSource={chatlist} onClick={(item) => onSwitchConversation(item)} /> <ChatList className='' dataSource={chatlist} onClick={(item) => onSwitchConversation(item)} />
</> </>
); );
}); });

@ -1,13 +1,7 @@
import { Card, Flex, Avatar, Typography, Radio, Button, Table } from 'antd'; import { Card, Flex, Avatar, Typography, Radio, Button, Table } from 'antd';
import { useAuthContext } from '@/stores/AuthContext.js'; import { useAuthContext } from '@/stores/AuthContext.js';
import { useConversationContext } from '@/stores/Conversations/ConversationContext'; import { useConversationContext } from '@/stores/Conversations/ConversationContext';
import { import { HomeOutlined, LoadingOutlined, SettingFilled, SmileOutlined, SyncOutlined, PhoneOutlined, MailOutlined } from '@ant-design/icons';
HomeOutlined,
LoadingOutlined,
SettingFilled,
SmileOutlined,
SyncOutlined,PhoneOutlined,MailOutlined
} from '@ant-design/icons';
import CreatePayment from './CreatePayment'; import CreatePayment from './CreatePayment';
import QuotesHistory from './QuotesHistory'; import QuotesHistory from './QuotesHistory';

@ -11,13 +11,15 @@ const InputBox = (({ onSend }) => {
const { currentConversation, templates } = useConversationContext(); const { currentConversation, templates } = useConversationContext();
const [textContent, setTextContent] = useState(''); const [textContent, setTextContent] = useState('');
const talkabled = ! isEmpty( currentConversation.sn);
const handleSendText = () => { const handleSendText = () => {
if (typeof onSend === 'function' && textContent.trim() !== '') { if (typeof onSend === 'function' && textContent.trim() !== '') {
const msgObj = { const msgObj = {
type: 'text', type: 'text',
text: textContent, text: textContent,
sender: 'me', sender: 'me',
to: currentConversation.channel_id, to: currentConversation.whatsapp_phone_number,
id: `${currentConversation.id}.${uuid()}`, // Date.now().toString(16), id: `${currentConversation.id}.${uuid()}`, // Date.now().toString(16),
date: new Date(), date: new Date(),
status: 'waiting', status: 'waiting',
@ -33,7 +35,7 @@ const InputBox = (({ onSend }) => {
const _conversation = {...cloneDeep(currentConversation), }; const _conversation = {...cloneDeep(currentConversation), };
const msgObj = { const msgObj = {
type: 'whatsappTemplate', type: 'whatsappTemplate',
to: currentConversation.channel_id, to: currentConversation.whatsapp_phone_number,
id: `${currentConversation.id}.${uuid()}`, id: `${currentConversation.id}.${uuid()}`,
date: new Date(), date: new Date(),
status: 'waiting', status: 'waiting',
@ -46,16 +48,17 @@ const InputBox = (({ onSend }) => {
? { components: [ ? { components: [
{ {
'type': 'body', 'type': 'body',
'parameters': [ 'parameters': whatsappTemplatesParamMapped[fromTemplate.name].map((v) => ({ type: 'text', text: getNestedValue(_conversation, v) }))
{ // [
'type': 'text', // {
'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name][0]) , // 'type': 'text',
}, // 'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name][0]) ,
{ // debug: // },
'type': 'text', // { // debug:
'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name]?.[1] || whatsappTemplatesParamMapped[fromTemplate.name][0]) , // 'type': 'text',
}, // 'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name]?.[1] || whatsappTemplatesParamMapped[fromTemplate.name][0]) ,
], // },
// ],
}, },
], } ], }
: {}), : {}),
@ -92,14 +95,14 @@ const InputBox = (({ onSend }) => {
)} )}
/> />
} }
title='📋模板消息' title='🙋打招呼'
trigger='click' trigger='click'
open={openTemplates} open={openTemplates}
onOpenChange={handleOpenChange}> onOpenChange={handleOpenChange}>
{/* <Button type="primary">Click me</Button> */} {/* <Button type="primary">Click me</Button> */}
<Button type='primary' shape='circle' icon={<MessageOutlined />} size={'large'} /> <Button type='primary' shape='circle' icon={<MessageOutlined />} size={'large'} disabled={!talkabled} />
</Popover> </Popover>
<Input.Search <Input.Search disabled={!talkabled}
placeholder='Type message here' placeholder='Type message here'
enterButton='Send' enterButton='Send'
size='large' size='large'

@ -1,6 +1,12 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Typography } from 'antd'; import { Typography } from 'antd';
import { useConversationContext } from '@/stores/Conversations/ConversationContext'; import { useConversationContext } from '@/stores/Conversations/ConversationContext';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
dayjs.extend(utc);
dayjs.extend(timezone);
const LocalTimeClock = ((props) => { const LocalTimeClock = ((props) => {
const { customerOrderProfile: orderInfo } = useConversationContext(); const { customerOrderProfile: orderInfo } = useConversationContext();

@ -3,7 +3,9 @@ import { ConversationContext, useConversations, } from '@/stores/Conversations/C
import { AuthContext } from '@/stores/AuthContext'; import { AuthContext } from '@/stores/AuthContext';
import { RealTimeAPI } from '@/lib/realTimeAPI'; import { RealTimeAPI } from '@/lib/realTimeAPI';
const WS_URL = 'ws://202.103.68.157:8888/whatever/'; // const WS_URL = 'ws://202.103.68.144:8888/whatever/';
// const WS_URL = 'ws://120.79.9.217:10022/whatever/';
const WS_URL = 'wss://p9axztuwd7x8a7.mycht.cn/whatsapp_callback'; // prod:
export const ConversationProvider = ({ children, loginUser, realtimeAPI }) => { export const ConversationProvider = ({ children, loginUser, realtimeAPI }) => {

Loading…
Cancel
Save