perf: 历史记录的每页加载, 5000; fix: 处理当前客户端收到新会话. 包括发出的;

fix: 消息数重复累计
websocket 连接重复初始化
dev/mobile
Lei OT 2 years ago
parent 64cdb3fd84
commit bf5b36832c

@ -29,8 +29,8 @@ function DebounceSelect({ fetchOptions, debounceTimeout = 800, ...props }) {
filterOption={false}
showSearch
allowClear
{...props}
maxTagCount={1}
{...props}
onSearch={debounceFetcher}
notFoundContent={fetching ? <Spin size='small' /> : null}
optionFilterProp='label'

@ -235,6 +235,8 @@ export const receivedMsgTypeMapped = {
id: msgcontent.wamid,
status: msgStatusRenderMapped[(msgcontent?.status || 'failed')],
conversationid: msgcontent.actionId.split('.')[0], // msgcontent.conversation.sn,
date: msgcontent.createTime,
sender: 'me',
}),
},
'error': {
@ -384,7 +386,7 @@ export const whatsappMsgTypeMapped = {
}),
renderForReply: (msg) => ({
id: msg.wamid,
message: '[联系人]',
message: '[联系人] ' + msg.contacts[0].name.formatted_name + '...',
}),
},
location: {

@ -8,6 +8,18 @@ import { WS_URL } from '@/config';
// const WS_URL = 'ws://202.103.68.144:8888/whatever/';
// const WS_URL = 'ws://120.79.9.217:10022/whatever/';
const conversationRow = {
sn: '',
opi_sn: '',
coli_sn: '',
coli_id: '',
last_received_time: '',
last_send_time: '',
unread_msg_count: '',
whatsapp_name: '',
customer_name: '',
whatsapp_phone_number: '',
};
const initialConversationState = {
// websocket: null,
@ -217,7 +229,7 @@ const messageSlice = (set, get) => ({
// msgUpdate
console.log('UPDATE_SENT_MESSAGE_ITEM-----------------------------------------------------------------');
// 更新会话中的消息
const { activeConversations, conversationsList } = get();
const { activeConversations, conversationsList, currentConversation } = get();
const targetId = message.conversationid;
const targetMsgs = (activeConversations[String(targetId)] || []).map((ele) => {
// 更新状态
@ -236,18 +248,32 @@ const messageSlice = (set, get) => ({
targetMsgs.push(message);
}
// 更新列表的时间
if (message.status === 'received') { // 'delivered'
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
let newConversations = [];
if (targetIndex !== -1 && message.status === 'received') { // 'delivered'
// 更新列表的时间
conversationsList.splice(targetIndex, 1, {
...conversationsList[targetIndex],
last_received_time: message.deliverTime, // todo: 需要+8 hours
});
} else if (targetIndex === -1) {
// 当前客户端不存在的会话 todo: 设置为当前(在WhatsApp返回号码不一致时)
newConversations = [{
...conversationRow,
...message,
sn: targetId,
opi_sn: currentConversation.opi_sn, // todo: coli sn
last_received_time: message.date,
unread_msg_count: 0,
whatsapp_name: message?.senderName || message?.sender || '',
customer_name: message?.senderName || message?.sender || '',
whatsapp_phone_number: message.from,
}];
}
return set({
activeConversations: { ...activeConversations, [String(targetId)]: targetMsgs },
conversationsList: [...conversationsList],
conversationsList: [...newConversations, ...conversationsList],
});
},
sentOrReceivedNewMessage: (targetId, message) => {
@ -257,7 +283,7 @@ const messageSlice = (set, get) => ({
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
const lastReceivedTime = message.type !== 'system' && message.sender !== 'me' ? message.date : null;
const newConversation =
targetId !== -1
targetIndex !== -1
? {
...conversationsList[targetIndex],
last_received_time: lastReceivedTime || conversationsList[targetIndex].last_received_time,
@ -267,15 +293,20 @@ const messageSlice = (set, get) => ({
: conversationsList[targetIndex].unread_msg_count,
}
: {
...conversationRow,
...message,
sn: targetId,
opi_sn: currentConversation.opi_sn, // todo: coli sn
last_received_time: message.date,
unread_msg_count: message.sender === 'me' ? 0 : 1,
whatsapp_name: message?.senderName || message?.sender || '',
customer_name: message?.senderName || message?.sender || '',
whatsapp_phone_number: message.from,
};
conversationsList.splice(targetIndex, 1);
conversationsList.unshift(newConversation);
return set({
totalNotify: totalNotify + newConversation.unread_msg_count,
totalNotify: totalNotify + (message.sender === 'me' ? 0 : 1),
activeConversations: { ...activeConversations, [String(targetId)]: [...targetMsgs, message] },
conversationsList: [...conversationsList],
currentConversation: {

@ -19,15 +19,21 @@ function AuthApp() {
const loginUser = useAuthStore(state => state.loginUser)
const href = useHref()
const [connectWebsocket, fetchInitialData, disconnectWebsocket ] = useConversationStore((state) => [
state.connectWebsocket,
state.fetchInitialData,
state.disconnectWebsocket,
]);
useEffect(() => {
Notification.requestPermission();
if (loginUser.userId > 0) {
useConversationStore.getState().connectWebsocket(loginUser.userId)
useConversationStore.getState().fetchInitialData(loginUser.userId) // userIdStr
connectWebsocket(loginUser.userId);
fetchInitialData(loginUser.userId); // userIdStr
}
return () => {
useConversationStore.getState().disconnectWebsocket();
}
disconnectWebsocket();
};
}, [])
useEffect(() => {
@ -37,21 +43,6 @@ function AuthApp() {
}
}, [href])
useEffect(() => {
if (loginUser.userId > 0) {
useConversationStore.getState().connectWebsocket(loginUser.userId)
useConversationStore.getState().fetchInitialData(loginUser.userId) // userIdStr
}
return () => {
useConversationStore.getState().disconnectWebsocket()
}
}, [])
useEffect(() => {
Notification.requestPermission()
return () => {}
}, [])
const {
token: { colorBgContainer },
} = theme.useToken()
@ -69,7 +60,7 @@ function AuthApp() {
renderEmpty={() => <Empty description={false} />}
>
<AntApp>
<ErrorBoundary>
<ErrorBoundary>
<Outlet />
</ErrorBoundary>
</AntApp>

@ -14,6 +14,8 @@ const { Sider, Content, Header, Footer } = Layout;
const { Search } = Input;
const { RangePicker } = DatePicker;
const BIG_PAGE_SIZE = MESSAGE_PAGE_SIZE * 100;
// https://media-xsp2-1.cdn.whatsapp.net/v/t61.24694-24/424735646_380563021285029_2962758854250800176_n.jpg?ccb=11-4&oh=01_AdTogiVdUE-ToI9uH-VQKTTLyDbP7bocXUQe1OETOeCgcg&oe=65F7C6AB&_nc_sid=e6ed6c&_nc_cat=104
// eslint-disable-next-line react/display-name
@ -40,10 +42,10 @@ const SearchForm = memo(function ({ initialValues, onSubmit }) {
onFinish={handleSubmit}
style={{}}>
<Form.Item label='顾问' name='agent' style={{ width: '200px' }} rules={[{required: true, message: '请选择顾问'}]}>
<SearchInput placeholder='搜索顾问' fetchOptions={fetchSalesAgent} mode={'tags'} />
<SearchInput placeholder='搜索顾问' fetchOptions={fetchSalesAgent} mode={'tags'} maxTagCount={0} />
</Form.Item>
<Form.Item label='客人' name='customer' style={{ width: '200px' }}>
<SearchInput placeholder='搜索客人' fetchOptions={fetchCustomerList} mode={'tags'} />
<SearchInput placeholder='搜索客人' fetchOptions={fetchCustomerList} mode={'tags'} maxTagCount={0} />
</Form.Item>
<Form.Item label='订单号' name='coli_id'>
<Input placeholder='订单号' allowClear />
@ -103,18 +105,18 @@ function ChatHistory() {
const getMessagesPre = async (chatItem) => {
setMessageListPreLoading(true);
const data = await fetchMessagesHistory({ ...chatItem, lasttime: chatItem.pretime, pagedir: 'pre', });
const data = await fetchMessagesHistory({ ...chatItem, lasttime: chatItem.pretime, pagedir: 'pre', pagesize: BIG_PAGE_SIZE });
setMessageListPreLoading(false);
setChatItemMessages(prevValue => data.concat(prevValue));
const loadPrePage = !(data.length === 0 || data.length < MESSAGE_PAGE_SIZE);
const loadPrePage = !(data.length === 0 || data.length < BIG_PAGE_SIZE);
setParamsForMsgList({ loadPrePage });
};
const getMessagesNext = async (chatItem) => {
setMessageListLoading(true);
const data = await fetchMessagesHistory({...chatItem, pagedir: 'next', });
const data = await fetchMessagesHistory({...chatItem, pagedir: 'next', pagesize: BIG_PAGE_SIZE });
setMessageListLoading(false);
setChatItemMessages(prevValue => prevValue.concat(data));
const loadNextPage = !(data.length === 0 || data.length < MESSAGE_PAGE_SIZE);
const loadNextPage = !(data.length === 0 || data.length < BIG_PAGE_SIZE);
setParamsForMsgList({loadNextPage});
};
@ -129,7 +131,7 @@ function ChatHistory() {
const findIndex = chatItemMessages.findIndex(item => item.id === selected.id);
if (findIndex === -1) {
setMessageListLoading(true);
await getMessagesPre({...paramsForMsgList, pagesize: 10000 });
await getMessagesPre({...paramsForMsgList });
setMessageListLoading(false);
}
setSelectedMatch(selected);
@ -253,10 +255,12 @@ function ChatHistory() {
const messagesEndRef = useRef(null);
const messageRefs = useRef([]);
const [focusMsg, setFocusMsg] = useState('');
const scrollToMessage = (id, index) => {
const _i = index || chatItemMessages.findIndex((msg) => msg.id === id);
if (_i >= 0) {
messageRefs.current[_i].scrollIntoView({ behavior: 'smooth', block: 'start' });
setFocusMsg(id);
}
};
// eslint-disable-next-line react/display-name
@ -338,6 +342,7 @@ function ChatHistory() {
'whitespace-pre-wrap mb-2',
message.whatsapp_msg_type === 'sticker' ? 'bg-transparent' : '',
message.sender === 'me' ? 'whatsappme-container' : '',
focusMsg === message.id ? 'message-box-focus' : '',
].join(' ')}
style={{
backgroundColor: message.sender === 'me' ? '#ccd4ae' : '#fff',

@ -11,6 +11,7 @@ const MessagesList = ({ messages, handlePreview, reference, longListLoading, get
// const messagesEndRef = useRef(null);
const messageRefs = useRef([]);
const [focusMsg, setFocusMsg] = useState('');
const scrollToBottom = (force = false) => {
if (reference.current && (shouldScrollBottom || force)) {
@ -22,6 +23,7 @@ const MessagesList = ({ messages, handlePreview, reference, longListLoading, get
const _i = index || messages.findIndex((msg) => msg.id === id);
if (_i >= 0) {
messageRefs.current[_i].scrollIntoView({ behavior: 'smooth', block: 'start' });
setFocusMsg(id);
}
};
@ -100,12 +102,16 @@ const MessagesList = ({ messages, handlePreview, reference, longListLoading, get
styles: { backgroundColor: '#ccd4ae' },
notchStyle: { fill: '#ccd4ae' },
replyButton: ['text', 'document', 'image'].includes(message.whatsapp_msg_type) && message.status !== 'failed' ? true : false,
className: 'whatsappme-container whitespace-pre-wrap',
}
: {
replyButton: ['text', 'document', 'image'].includes(message.whatsapp_msg_type) ? true : false,
className: ['whitespace-pre-wrap', message.whatsapp_msg_type === 'sticker' ? 'bg-transparent' : ''].join(' '),
})}
className={[
'whitespace-pre-wrap',
message.whatsapp_msg_type === 'sticker' ? 'bg-transparent' : '',
message.sender === 'me' ? 'whatsappme-container' : '',
focusMsg === message.id ? 'message-box-focus' : '',
].join(' ')}
{...(message.type === 'meetingLink'
? {
actionButtons: [

@ -184,3 +184,28 @@
-webkit-user-select: auto;
-moz-user-select: auto;
}*/
@-webkit-keyframes message-box-default-focus-x {
from {
background-color: #fff;
}
to {
background-color: #ece5dd;
}
}
@keyframes message-box-default-focus-x {
from {
background-color: #fff;
}
to {
background-color: #ece5dd;
}
}
.chatwindow-wrapper .message-box-focus {
animation-iteration-count: 2;
-webkit-animation-iteration-count: 2;
-webkit-animation-duration: 1s;
animation-name: message-box-default-focus-x;
animation-duration: 1s;
}

Loading…
Cancel
Save