会话切换

dev/mobile
Lei OT 2 years ago
parent 5c174ebe8b
commit b2721cd1ee

@ -17,7 +17,24 @@ export async function fetchJSON(url, data) {
const response = await fetch(`${host}${url}${ifp}${params}`);
return await response.json();
}
export async function postJSON(url, obj) {
try {
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(obj),
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
return await response.json();
} catch (error) {
console.error('fetch error:', error);
throw error;
}
}
// const API_HOST = 'http://202.103.68.144:8888';
const API_HOST = 'https://p9axztuwd7x8a7.mycht.cn/whatsapp_callback';
@ -54,7 +71,7 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
}, []);
useEffect(() => {
getConversationsList();
getConversationsList(); // todo: 和刷新订单会话页面有冲突
getTemplates();
return () => {};
}, []);
@ -66,12 +83,15 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
// return () => {};
// }, [conversationsList]);
const poseConversationItemClose = async (item) => {
const res = await postJSON(`${API_HOST}/closeconversation`, { opisn: userId, conversationid: item.sn });
}
const getConversationsList = async () => {
const { result: data } = await fetchJSON(`${API_HOST}/getconversations`, { opisn: userId });
// const _data = [];
const _data = testConversations;
const list = [..._data, ...data];
const list = [..._data, ...data.map(ele => ({...ele, customer_name: ele.whatsapp_name.trim()}))];
const dataMapped = list.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
setConversationsList(list);
setActiveConversations({...dataMapped, ...activeConversations});
@ -137,7 +157,8 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
// Get customer profile when switching conversation
useEffect(() => {
console.log('currentConversation', currentConversation);
setMessages([...(activeConversations[currentID] || [])]);
setCurrentID(currentConversation.sn);
setMessages([...(activeConversations[currentConversation.sn] || [])]);
return () => {};
}, [currentConversation]);
@ -159,8 +180,8 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
if (targetId !== currentID) {
setConversationsList((prevList) => {
return prevList.map((ele) => {
if (ele.id === targetId) {
return { ...ele, new_msgs: ele.new_msgs + 1 };
if (ele.sn === targetId) {
return { ...ele, new_msgs: ele.new_msgs + 1, last_received_time: message.date };
}
return ele;
});
@ -178,8 +199,10 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
const addMessage = (message) => {
setMessages((prevMessages) => [...prevMessages, message]);
addMessageToConversations(message.conversationid, message);
if (message.conversationid === currentID) {
setMessages((prevMessages) => [...prevMessages, message]);
}
};
const updateMessage = (message) => {
@ -202,6 +225,15 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
...prevList,
[targetId]: targetMsgs,
}));
// 更新列表的时间
setConversationsList((prevList) => {
return prevList.map((ele) => {
if (ele.sn === targetId) {
return { ...ele, new_msgs: ele.new_msgs + 1, last_received_time: message.date };
}
return ele;
});
});
};
@ -252,7 +284,8 @@ export const useConversations = ({loginUser, realtimeAPI}) => {
getConversationsList,
switchConversation,
templates: templatesList, // setTemplates, getTemplates,
customerOrderProfile, getCustomerProfile
customerOrderProfile, getCustomerProfile,
poseConversationItemClose
};
};

@ -68,11 +68,10 @@ const ChatWindow = (() => {
<InputBox onSend={(v) => sendMessage(v)} />
</Footer>
</Layout>
{/* <InputBox onSend={(v) => sendMessage(v)} /> */}
</Content>
<Sider width={300} theme={'light'} className='h-full overflow-y-auto' style={{ maxHeight: 'calc(100vh - 198px)', height: 'calc(100vh - 198px)' }}>
<CustomerProfile customer={{}} />
<CustomerProfile />
</Sider>
</Layout>
</Spin>

@ -9,21 +9,27 @@ import { useGetJson } from '@/hooks/userFetch';
*/
const Conversations = (() => {
const navigate = useNavigate();
const { switchConversation, conversationsList } = useConversationContext();
const { switchConversation, conversationsList, poseConversationItemClose } = useConversationContext();
// console.log(conversationsList);
const [chatlist, setChatlist] = useState([]);
useEffect(() => {
setChatlist(
(conversationsList || []).map((item) => ({
...item,
avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${item.whatsapp_name}`,
alt: item.whatsapp_name,
avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${item.whatsapp_name.trim() || item.whatsapp_phone_number}`,
id: item.sn,
title: item.whatsapp_name,
subtitle: item.whatsapp_phone_number,
alt: item.whatsapp_name,
title: item.whatsapp_name.trim() || item.whatsapp_phone_number,
// subtitle: item.whatsapp_phone_number,
// subtitle: item.lastMessage,
date: item.last_received_time, // last_send_time
unread: item.unread_msg_count,
showMute: true,
muted: false,
// showVideoCall: true,
// statusColor: '#ccd5ae',
// statusColorType: 'badge',
// statusText: 'online'
}))
);
@ -39,7 +45,13 @@ const Conversations = (() => {
return (
<>
<ChatList className='' dataSource={chatlist} onClick={(item) => onSwitchConversation(item)} />
<ChatList className='' dataSource={chatlist} onClick={(item) => onSwitchConversation(item)}
// onContextMenu={(item, i, e) => {
// console.log(item, i, e);
// return ( <p>ppp</p> )
// }}
onClickMute={poseConversationItemClose}
/>
</>
);
});

@ -27,8 +27,8 @@ const CustomerProfile = (({ customer }) => {
const { quotes, contact, last_contact, ...order } = orderInfo;
return (
<div className=' divide-x-0 divide-y divide-slate-300 divide-dotted'>
<Card className='p-2'
<div className=' divide-x-0 divide-y divide-dashed divide-gray-300 '>
<Card className='p-2 '
bordered={false}
title={order?.order_no}
extra={<Radio.Group size={'small'} options={orderTags} value={'important'} onChange={({ target: { value } }) => {}} optionType='button' buttonStyle={'solid'} />}>
@ -42,7 +42,7 @@ const CustomerProfile = (({ customer }) => {
<Typography.Text strong >{contact?.[0]?.name}</Typography.Text>
{contact?.[0]?.phone && <Typography.Text ><PhoneOutlined className=' pr-1' />{contact?.[0]?.phone}</Typography.Text>}
{contact?.[0]?.email && <Typography.Text ><MailOutlined className=' pr-1' />{contact?.[0]?.email}</Typography.Text>}
<Typography.Text ><WhatsAppOutlined className='pr-1 text-whatsapp' />{contact?.[0]?.whatsapp_phone_number}</Typography.Text>
{contact?.[0]?.whatsapp_phone_number && <Typography.Text ><WhatsAppOutlined className='pr-1 text-whatsapp' />{contact?.[0]?.whatsapp_phone_number}</Typography.Text>}
{/* <div>{order?.order_no}</div> */}
{/* <div>
{order?.location} <span>{order?.local_datetime}</span>
@ -59,11 +59,11 @@ const CustomerProfile = (({ customer }) => {
<QuotesHistory />
</Flex>
</Flex>
<pre className='p-2 overflow-auto max-h-32 m-0' dangerouslySetInnerHTML={{__html: order?.order_detail}}></pre>
<Flex vertical={true} className='p-2 '>
<pre className='p-2 overflow-auto max-h-72 m-0' dangerouslySetInnerHTML={{__html: order?.order_detail}}></pre>
{/* <Flex vertical={true} className='p-2 '>
<Typography.Text strong>沟通记录</Typography.Text>
<Table size={'small'} columns={[{ title: '进程', dataIndex: 'title' }, { title: '状态', dataIndex: 'title2' },]} />
</Flex>
</Flex> */}
</div>
);
});

@ -4,14 +4,14 @@ import { Input, Button, Tabs, List, Space, Popover, Flex } from 'antd';
import { useConversationContext } from '@/stores/Conversations/ConversationContext';
import { LikeOutlined, MessageOutlined, StarOutlined, SendOutlined, PlusOutlined, PlusCircleOutlined } from '@ant-design/icons';
import { cloneDeep, getNestedValue, isEmpty } from '@/utils/utils';
import { v4 as uuid } from "uuid";
import { v4 as uuid } from 'uuid';
import { whatsappTemplatesParamMapped } from '@/lib/msgUtils';
const InputBox = (({ onSend }) => {
const InputBox = ({ onSend }) => {
const { currentConversation, templates } = useConversationContext();
const [textContent, setTextContent] = useState('');
const talkabled = ! isEmpty( currentConversation.sn);
const talkabled = !isEmpty(currentConversation.sn);
const handleSendText = () => {
if (typeof onSend === 'function' && textContent.trim() !== '') {
@ -32,7 +32,7 @@ const InputBox = (({ onSend }) => {
const handleSendTemplate = (fromTemplate) => {
console.log(fromTemplate, 'fromTemplate');
if (typeof onSend === 'function') {
const _conversation = {...cloneDeep(currentConversation), };
const _conversation = { ...cloneDeep(currentConversation) };
const msgObj = {
type: 'whatsappTemplate',
to: currentConversation.whatsapp_phone_number,
@ -45,22 +45,24 @@ const InputBox = (({ onSend }) => {
name: fromTemplate.name,
language: { code: fromTemplate.language },
...(fromTemplate.components.body[0]?.example?.body_text?.[0]?.length > 0
? { components: [
{
'type': 'body',
'parameters': whatsappTemplatesParamMapped[fromTemplate.name].map((v) => ({ type: 'text', text: getNestedValue(_conversation, v) || '' }))
// [
// {
// 'type': 'text',
// 'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name][0]) ,
// },
// { // debug:
// 'type': 'text',
// 'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name]?.[1] || whatsappTemplatesParamMapped[fromTemplate.name][0]) ,
// },
// ],
},
], }
? {
components: [
{
'type': 'body',
'parameters': whatsappTemplatesParamMapped[fromTemplate.name].map((v) => ({ type: 'text', text: getNestedValue(_conversation, v) || '' })),
// [
// {
// 'type': 'text',
// 'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name][0]) ,
// },
// { // debug:
// 'type': 'text',
// 'text': getNestedValue(_conversation, whatsappTemplatesParamMapped[fromTemplate.name]?.[1] || whatsappTemplatesParamMapped[fromTemplate.name][0]) ,
// },
// ],
},
],
}
: {}),
},
template_origin: fromTemplate,
@ -84,13 +86,19 @@ const InputBox = (({ onSend }) => {
itemLayout='horizontal'
dataSource={templates}
renderItem={(item, index) => (
<List.Item
actions={[
<Button onClick={() => handleSendTemplate(item)} size={'small'} type='link' key={'send'} icon={<SendOutlined />}>
Send
</Button>,
]}>
<List.Item.Meta className=' text-neutral-800' title={item.components.header?.[0]?.text || item.name} description={item.components.body?.[0]?.text} />
<List.Item>
<List.Item.Meta
className=' text-neutral-800'
title={
<Flex justify={'space-between'}>
<>{item.components.header?.[0]?.text || item.name}</>
<Button onClick={() => handleSendTemplate(item)} size={'small'} type='link' key={'send'} icon={<SendOutlined />}>
Send
</Button>
</Flex>
}
description={item.components.body?.[0]?.text}
/>
</List.Item>
)}
/>
@ -99,12 +107,13 @@ const InputBox = (({ onSend }) => {
trigger='click'
open={openTemplates}
onOpenChange={handleOpenChange}>
{/* <Button type="primary">Click me</Button> */}
<Button type='primary' shape='circle' icon={<MessageOutlined />} size={'large'} disabled={!talkabled} />
</Popover>
<Input.Search disabled={!talkabled}
<Input.Search
disabled={!talkabled}
placeholder='Type message here'
enterButton='Send'
// enterButton={'Send'}
enterButton={<SendOutlined />}
size='large'
onSearch={handleSendText}
value={textContent}
@ -114,6 +123,6 @@ const InputBox = (({ onSend }) => {
<div></div>
</div>
);
});
};
export default InputBox;

@ -1,15 +1,20 @@
/** @type {import('tailwindcss').Config} */
import colors from 'tailwindcss/colors'
export default {
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
darkMode: 'media',
theme: {
colors: {
'whatsapp': '#25D366',
'whatsapp-dark': '#075E54',
'whatsapp-second': '#128c7e',
'whatsapp-gossip': '#dcf8c6',
'whatsapp-bg': '#ece5dd',
'whatsappme': '#ccd5ae',
...colors,
'whatsapp': {
DEFAULT: '#25D366',
dark: '#075E54',
second: '#128c7e',
gossip: '#dcf8c6',
bg: '#ece5dd',
me: '#ccd5ae',
},
},
extend: {
// gridTemplateColumns: {
@ -19,6 +24,7 @@ export default {
},
plugins: [],
corePlugins: {
preflight: false
preflight: false,
divideColor: true,
}
};

Loading…
Cancel
Save