You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Global-sales/src/views/Conversations/Online/ConversationsList.jsx

280 lines
12 KiB
JavaScript

import { useEffect, useState, useRef } from 'react';
import { useParams, useNavigate, useLocation } from 'react-router-dom';
import { Dropdown, Input, Button, Empty, Tooltip } from 'antd';
import { PlusOutlined, WhatsAppOutlined, LoadingOutlined, HistoryOutlined, FireOutlined } from '@ant-design/icons';
import { fetchConversationsList, fetchOrderConversationsList, fetchConversationItemClose, fetchConversationsSearch, postNewConversationItem } from '@/actions/ConversationActions';
import { ChatItem } from 'react-chat-elements';
import ConversationsNewItem from './ConversationsNewItem';
import { isEmpty, olog } from '@/utils/commons';
import useConversationStore from '@/stores/ConversationStore';
import useAuthStore from '@/stores/AuthStore';
import { useVisibilityState } from '@/hooks/useVisibilityState';
/**
* []
*/
const Conversations = ({ mobile }) => {
const routerReplace = mobile === undefined ? true : false; // : true;
const routePrefix = mobile === undefined ? `/order/chat` : `/m/chat`;
const { state: orderRow } = useLocation();
const { coli_guest_WhatsApp } = orderRow || {};
const { order_sn } = useParams();
const navigate = useNavigate();
const userId = useAuthStore((state) => state.loginUser.userId);
const initialState = useConversationStore((state) => state.initialState);
const [currentConversation, setCurrentConversation] = useConversationStore((state) => [state.currentConversation, state.setCurrentConversation]);
const conversationsList = useConversationStore((state) => state.conversationsList);
const [conversationsListLoading, setConversationsListLoading] = useConversationStore((state) => [state.conversationsListLoading, state.setConversationsListLoading]);
const addToConversationList = useConversationStore((state) => state.addToConversationList);
const delConversationitem = useConversationStore((state) => state.delConversationitem);
const closedConversationsList = useConversationStore((state) => state.closedConversationsList);
const setClosedConversationList = useConversationStore((state) => state.setClosedConversationList);
const isVisible = useVisibilityState();
const [tabSelectedConversation, setTabSelectedConversation] = useState({});
const [tabCnt, setTabCnt] = useState(-1);
async function refreshConversationList() {
setConversationsListLoading(mobile !== undefined ? true : false);
const _list = await fetchConversationsList({opisn:userId});
addToConversationList(_list);
setConversationsListLoading(false);
}
useEffect(() => {
if (mobile !== undefined) {
setCurrentConversation({});
}
return () => {};
}, []);
useEffect(() => {
if (isVisible) {
refreshConversationList();
}
return () => {};
}, [isVisible]);
const [dataSource, setDataSource] = useState(conversationsList);
useEffect(() => {
setDataSource(conversationsList);
return () => {};
}, [conversationsList.length]);
const [switchToC, setSwitchToC] = useState({});
const [shouldFetchCList, setShouldFetchCList] = useState(true);
useEffect(() => {
if (order_sn && shouldFetchCList && initialState) {
getOrderConversationList(order_sn);
}
return () => {};
}, [order_sn, shouldFetchCList, initialState]);
const getOrderConversationList = async (colisn, WHATSAPP_ID = null) => {
const { whatsapp_phone_number } = switchToC;
const whatsappID = WHATSAPP_ID || coli_guest_WhatsApp || whatsapp_phone_number || '';
// let findCurrentOrderChats = conversationsList.filter((item) => `${item.coli_sn}` === `${colisn}`);
// 使用opisn + whatsappID 判断, 解决订单修改whatsappID号码之后获取新会话, 登录账号此处省略
let findCurrentOrderChats = conversationsList.filter((item) => `${item.whatsapp_phone_number}` === `${whatsappID}`);
let findCurrentIndex = isEmpty(findCurrentOrderChats) ? -1 : 0; // findCurrentOrderChats.length-1;
let findCurrent = findCurrentOrderChats[findCurrentIndex];
if (findCurrentIndex !== -1) {
addToConversationList(findCurrentOrderChats);
} else if (!isEmpty(whatsappID)) {
const data = await fetchOrderConversationsList({ opisn: userId, colisn: colisn, whatsappid: whatsappID });
if (!isEmpty(data)) {
addToConversationList(data);
findCurrentIndex = 0; // data.length-1; // data.lastIndexOf((item) => item.coli_sn === Number(colisn));
findCurrent = data[findCurrentIndex];
} else {
// findCurrentIndex = conversationsList.findIndex((item) => item.coli_sn === Number(colisn)); // data.findIndex((item) => item.sn === currentConversation.sn);
}
} else if (isEmpty(whatsappID)) {
// 刷新页面
findCurrentIndex = conversationsList.findIndex((item) => `${item.coli_sn}` === `${colisn}`);
findCurrent = conversationsList[findCurrentIndex];
}
if (findCurrentIndex >= 0) {
setCurrentConversation(findCurrent);
return findCurrent;
} else {
// reset chat window
setCurrentConversation({ sn: '', customer_name: '', coli_sn: order_sn });
return false;
}
};
const onSwitchConversation = async (item) => {
setCurrentConversation(item);
if (isEmpty(item.coli_sn)) {
navigate(routePrefix, { replace: true });
} else {
setSwitchToC(item);
setShouldFetchCList(false);
navigate(`${routePrefix}/${item.coli_sn}`, { replace: routerReplace });
}
// if (!isEmpty(item.coli_sn)) {
// setSwitchToC(item);
// setShouldFetchCList(false);
// navigate(`/order/chat/${item.coli_sn}`, { replace: true });
// } else {
// navigate(`/order/chat`, { replace: true });
// }
// switchConversation(item);
};
const handleConversationItemClose = async (item) => {
await fetchConversationItemClose({ conversationid: item.sn, opisn: item.opi_sn });
delConversationitem(item);
if (String(order_sn) === String(item.coli_sn)) {
navigate(routePrefix, { replace: routerReplace });
}
const _clist = await fetchConversationsSearch({ opisn: userId, session_enable: 0 });
setClosedConversationList(_clist);
};
const searchInputRef = useRef(null);
const [searchContent, setSearchContent] = useState('');
const handleSearchConversations = (val) => {
if (val.toLowerCase().trim() !== '') {
const res = conversationsList.filter(
(item) => (item.whatsapp_name.toLowerCase()).includes(val.toLowerCase().trim())
|| (item.whatsapp_phone_number.toLowerCase()).includes(val.toLowerCase().trim())
|| (item.coli_id.toLowerCase()).includes(val.toLowerCase().trim())
);
setDataSource(res);
return false;
}
setDataSource(conversationsList);
};
const [newChatModalVisible, setNewChatModalVisible] = useState(false);
const [newChatFormValues, setNewChatFormValues] = useState();
const handleNewChat = async (values) => {
// console.log(values);
const hasNewCurrent = await getOrderConversationList(values.coli_sn, values.phone_number);
if (hasNewCurrent !== false) {
//
}
setNewChatModalVisible(false);
// const newItem = await postNewConversationItem({...values, opi_sn: userId });
// if ( ! isEmpty(newItem)) {
// addToConversationList(newItem);
// setCurrentConversation(newItem);
// }
// setNewChatFormValues(values);
}
const [activeList, setActiveList] = useState(true);
// const closedVisible = closedConversationsList.length > 0;
const toggleClosedConversationsList = () => {
const _active = activeList;
setDataSource(_active ? closedConversationsList : conversationsList);
setActiveList(!activeList);
setCurrentConversation({});
}
return (
<div className='flex flex-col h-inherit'>
<div className='flex gap-1'>
{[404, 383].includes(userId) && <Button onClick={() => setNewChatModalVisible(true)} icon={<PlusOutlined />} type={'primary'} />}
<Input.Search
className=''
ref={searchInputRef}
onSearch={handleSearchConversations}
allowClear
value={searchContent}
onChange={(e) => {
setSearchContent(e.target.value);
handleSearchConversations(e.target.value);
setTabCnt(-1);
setTabSelectedConversation({});
}}
onKeyDown={(e) => {
if (e.key === 'Tab') {
e.preventDefault();
const _this = tabCnt >= dataSource.length - 1 ? 0 : tabCnt + 1;
setTabCnt(_this);
setTabSelectedConversation(dataSource[_this]);
}
}}
onPressEnter={(e) => {
handleSearchConversations(e.target.value);
searchInputRef.current.blur();
onSwitchConversation(dataSource[tabCnt < 0 ? 0 : tabCnt]);
setTabCnt(-1);
setTabSelectedConversation({});
return false;
}}
placeholder={`搜索名称/号码/订单号${conversationsListLoading ? '...' : ''}`}
/>
<Tooltip key={'conversation-list'} title={activeList ? '历史会话' : '活跃会话'}>
<Button
onClick={toggleClosedConversationsList}
icon={activeList ? <HistoryOutlined className='text-neutral-500' /> : <FireOutlined className=' text-orange-500' />}
type='text'
/>
</Tooltip>
</div>
<div className='flex-1 overflow-x-hidden overflow-y-auto relative'>
{conversationsListLoading && dataSource.length === 0 ? (
<div className='text-center py-2'>
<LoadingOutlined className='text-primary ' />
</div>
) : null}
{dataSource.map((item) => (
<Dropdown
key={item.sn}
menu={{
items: [{ label: '关闭会话', key: 'close', danger: true }],
onClick: ({ key, domEvent }) => {
domEvent.stopPropagation();
switch (key) {
case 'close':
return handleConversationItemClose(item);
default:
return;
}
},
}}
trigger={['contextMenu']}>
<ChatItem
{...item}
key={item.sn}
id={item.sn}
letterItem={{ id: item.whatsapp_name || item.whatsapp_phone_number, letter: (item.whatsapp_name || item.whatsapp_phone_number).slice(0, 5) }}
alt={item.whatsapp_name}
title={item.whatsapp_name || item.whatsapp_phone_number}
subtitle={item.coli_id}
date={item.last_received_time || item.last_send_time}
unread={item.unread_msg_count}
className={[
String(item.sn) === String(currentConversation.sn) ? '__active text-primary bg-whatsapp-bg' : '',
String(item.sn) === String(tabSelectedConversation?.sn) ? ' bg-neutral-200' : '',
].join(' ')}
statusText={<WhatsAppOutlined key={'channel'} className='text-whatsapp' />}
statusColor={'#fff'}
onClick={() => onSwitchConversation(item)}
/>
</Dropdown>
))}
{dataSource.length === 0 && <Empty description={'无数据'} />}
</div>
<ConversationsNewItem
initialValues={{ coli_id: currentConversation.coli_id, coli_sn: currentConversation.coli_sn }}
open={newChatModalVisible}
onCreate={handleNewChat}
onCancel={() => setNewChatModalVisible(false)}
/>
</div>
);
};
export default Conversations;