feat: 历史消息查询

dev/chat
Lei OT 1 year ago
parent 1668cc4df9
commit 15a377abbe

@ -1,8 +1,9 @@
import { groupBy } from '@/utils/utils';
import { groupBy, pick } from '@/utils/utils';
import { fetchJSON, postJSON } from '@/utils/request'
import { parseRenderMessageList } from '@/lib/msgUtils';
import { API_HOST } from '@/config';
import { isEmpty } from '@/utils/commons';
export const fetchTemplates = async () => {
const data = await fetchJSON(`${API_HOST}/listtemplates`);
@ -86,7 +87,7 @@ export const fetchConversationsSearch = async (params) => {
...ele,
customer_name: `${ele.whatsapp_name || ''}`.trim(),
whatsapp_name: `${ele.whatsapp_name || ''}`.trim(),
matchMsgList: parseRenderMessageList((ele.msglist_AsJOSN || []).reverse()),
matchMsgList: parseRenderMessageList((ele.msglist_AsJOSN || [])), // .reverse()),
}));
return list;
};
@ -99,10 +100,15 @@ export const fetchMessagesHistory = async (params) => {
const defaultParams = {
opisn: '',
whatsappid: '',
lasttime: '',
lasttime: '2024-01-01T00:00:00',
pagesize: MESSAGE_PAGE_SIZE,
pagedir: 'next',
};
const { errcode, result } = await fetchJSON(`${API_HOST}/get_item_messages`, {...defaultParams, ...params});
return errcode !== 0 ? [] : parseRenderMessageList((result || []).reverse());
const _params = pick(params, Object.keys(defaultParams));
if (isEmpty(_params.opisn) || isEmpty(_params.whatsappid)) {
return [];
}
const { errcode, result } = await fetchJSON(`${API_HOST}/get_item_messages`, {...defaultParams, ..._params});
const data = errcode !== 0 ? [] : result; // _params.pagedir === 'next' ? result.reverse() : result;
return parseRenderMessageList(data);
}

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

@ -10,6 +10,8 @@ export const useFormStore = create(
setChatHistorySelectChat: (chatHistorySelectChat) => set({ chatHistorySelectChat }),
msgHistorySelectMatch: {},
setMsgHistorySelectMatch: (msgHistorySelectMatch) => set({ msgHistorySelectMatch }),
msgListParams: {},
setMsgListParams: (msgListParams) => set(state => ({ msgListParams: {...state.msgListParams, ...msgListParams} })),
// 订单跟踪页面
orderFollowForm: {

@ -1,7 +1,8 @@
import { memo, useCallback, useEffect, useRef, useState, forwardRef } from 'react';
import { Divider, Button, Input, Layout, DatePicker, Form, List, Spin, Flex } from 'antd';
import { LoadingOutlined } from '@ant-design/icons';
import { ChatItem, MessageBox } from 'react-chat-elements';
import { fetchConversationsList, fetchMessages, MESSAGE_PAGE_SIZE, fetchConversationsSearch, fetchMessagesHistory } from '@/actions/ConversationActions';
import { MESSAGE_PAGE_SIZE, fetchConversationsSearch, fetchMessagesHistory } from '@/actions/ConversationActions';
import { cloneDeep, flush, isEmpty, pick, stringToColour } from '@/utils/utils';
import useFormStore from '@/stores/FormStore';
@ -19,10 +20,12 @@ const { RangePicker } = DatePicker;
const SearchForm = memo(function ({ initialValues, onSubmit }) {
const [form] = Form.useForm();
function handleSubmit(values) {
const multiAgents = (values?.agent || []).map(ele => ele.value).join(',');
const multiCustomers = (values?.customer || []).map(ele => ele.value).join(',');
onSubmit?.({
...values,
opisn: values?.agent?.value || '',
whatsapp_id: values?.customer?.value || '',
opisn: multiAgents,
whatsapp_id: multiCustomers,
...(isNotEmpty(values.msgDateRange) ? {
from_date: values.msgDateRange[0].format('YYYY-MM-DD'),
end_date: values.msgDateRange[1].format('YYYY-MM-DD'),
@ -37,10 +40,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} />
<SearchInput placeholder='搜索顾问' fetchOptions={fetchSalesAgent} mode={'tags'} />
</Form.Item>
<Form.Item label='客人' name='customer' style={{ width: '200px' }}>
<SearchInput placeholder='搜索客人' fetchOptions={fetchCustomerList} />
<SearchInput placeholder='搜索客人' fetchOptions={fetchCustomerList} mode={'tags'} />
</Form.Item>
<Form.Item label='订单号' name='coli_id'>
<Input placeholder='订单号' allowClear />
@ -65,16 +68,20 @@ function ChatHistory() {
const [formValues, setFormValues] = useFormStore(((state) => [state.chatHistoryForm, state.setChatHistoryForm]));
const [selectedConversation, setSelectedConversation] = useFormStore(((state) => [state.chatHistorySelectChat, state.setChatHistorySelectChat]));
const [selectMatch, setSelectedMatch] = useFormStore(((state) => [state.msgHistorySelectMatch, state.setMsgHistorySelectMatch]));
const [paramsForMsgList, setParamsForMsgList] = useFormStore(((state) => [state.msgListParams, state.setMsgListParams]));
// { opisn, whatsappid, lasttime, pagesize, pagedir }
const handleSubmit = useCallback((values) => {
setFormValues({ ...values });
}, []);
const [conversationsListLoading, setConversationsListLoading] = useState(false);
const [messageListPreLoading, setMessageListPreLoading] = useState(false);
const [messageListLoading, setMessageListLoading] = useState(false);
const [conversationsList, setConversationsList] = useState([]);
const [chatItemMessages, setChatItemMessages] = useState([]);
const [paramsForMsgList, setParamsForMsgList] = useState({ loadNextPage: true, loadPrePage: true, }); // { opisn, whatsappid, lasttime, pagesize, pagedir }
// const [paramsForMsgList, setParamsForMsgList] = useState({ loadNextPage: true, loadPrePage: true, }); // { opisn, whatsappid, lasttime, pagesize, pagedir }
// const [selectMatch, setSelectedMatch] = useState({});
const getConversationsList = async () => {
const allEmpty = Object.values(cloneDeep(formValues)).every((val) => {
@ -83,61 +90,116 @@ function ChatHistory() {
if (allEmpty) return;
setConversationsListLoading(true);
setChatItemMessages([]);
setParamsForMsgList({});
setSelectedMatch({});
const params = flush(pick(formValues, ['opisn', 'whatsapp_id', 'search', 'from_date', 'end_date', 'coli_id']));
const data = await fetchConversationsSearch(params);
setConversationsListLoading(false);
setConversationsList(data);
if (data.length === 1) {
setSelectedConversation(data[0]);
// await getMessagesNext(data[0]);
}
};
const getMessagesPre = async (chatItem) => {
setMessageListLoading(true);
const data = await fetchMessagesHistory({ opisn: chatItem.opi_sn, whatsappid: chatItem.whatsapp_phone_number, lasttime: chatItem?.pretime || '', pagedir: 'pre', });
setMessageListLoading(false);
setMessageListPreLoading(true);
const data = await fetchMessagesHistory({ ...chatItem, lasttime: chatItem.pretime, pagedir: 'pre', });
setMessageListPreLoading(false);
setChatItemMessages(prevValue => data.concat(prevValue));
const thisPreTime = data.length > 0 ? data[0].orgmsgtime : '';
const loadPrePage = !(data.length === 0 || data.length < MESSAGE_PAGE_SIZE);
setSelectedConversation({ ...chatItem, pretime: thisPreTime, loadPrePage });
setParamsForMsgList({ loadPrePage });
};
const getMessagesNext = async (chatItem) => {
console.log(chatItem);
setMessageListLoading(true);
const data = await fetchMessagesHistory({ opisn: chatItem.opi_sn, whatsappid: chatItem.whatsappid, lasttime: chatItem?.lasttime || '', pagedir: 'next', });
const data = await fetchMessagesHistory({...chatItem, pagedir: 'next', });
setMessageListLoading(false);
setChatItemMessages(prevValue => prevValue.concat(data.reverse()));
const thisLastTime = data.length > 0 ? data[0].orgmsgtime : '';
setChatItemMessages(prevValue => prevValue.concat(data));
const loadNextPage = !(data.length === 0 || data.length < MESSAGE_PAGE_SIZE);
// const thisPreTime = data.length > 0 ? data[data.length - 1].orgmsgtime : '';
// const loadPrePage = !(data.length === 0 || data.length < MESSAGE_PAGE_SIZE);
setParamsForMsgList(preVal => ({ ...preVal, lasttime: thisLastTime, loadNextPage }));
// setSelectedConversation({ ...chatItem, lasttime: thisLastTime, loadNextPage, pretime: thisPreTime, loadPrePage});
setParamsForMsgList({loadNextPage});
};
// ,
const scrollToSelectedMessage = (selected) => {
const findIndex = chatItemMessages.findIndex(item => item.id === selected.id);
if (findIndex !== -1) {
scrollToMessage(selected.id, findIndex);
}
}
const handleMatchMsgClick = async (selected) => {
const findIndex = chatItemMessages.findIndex(item => item.id === selected.id);
if (findIndex === -1) {
setMessageListLoading(true);
await getMessagesPre({...paramsForMsgList, pagesize: 10000 });
setMessageListLoading(false);
}
setSelectedMatch(selected);
}
// ,
useEffect(() => {
setChatItemMessages([]);
setSelectedMatch(selectedConversation.matchMsgList?.[0] || {});
setParamsForMsgList(preVal => ({ ...preVal, opi_sn: selectedConversation.opi_sn, whatsappid: selectedConversation.whatsapp_phone_number }));
// if (selectedConversation.whatsapp_phone_number) {
// // getMessagesNext({...selectedConversation, loadNextPage: true, lasttime: null });
// }
if (selectMatch.sn) {
scrollToSelectedMessage(selectMatch);
}
return () => {};
}, [selectedConversation.conversationid]);
}, [selectMatch.sn]);
// ,
useEffect(() => {
setChatItemMessages([]);
setParamsForMsgList(preVal => ({ ...preVal, preTime: selectMatch.orgmsgtime, lasttime: selectMatch.orgmsgtime, loadPrePage:true, loadNextPage: true, }));
getMessagesNext({...paramsForMsgList, lasttime: selectMatch.orgmsgtime});
return () => {};
}, [selectMatch.sn]);
setParamsForMsgList({});
setSelectedMatch({});
if (isEmpty(selectedConversation.conversationid)) {
return () => {};
}
const firstActionPageParams = { opisn: selectedConversation.opi_sn, whatsappid: selectedConversation.whatsapp_phone_number };
if (isEmpty(selectedConversation.matchMsgList)) {
firstActionPageParams.loadPrePage = false;
firstActionPageParams.loadNextPage = true;
} else {
firstActionPageParams.pretime = selectedConversation.matchMsgList[0].orgmsgtime;
firstActionPageParams.lasttime = selectedConversation.matchMsgList[0].orgmsgtime;
firstActionPageParams.loadPrePage = true;
firstActionPageParams.loadNextPage = true;
}
setParamsForMsgList(firstActionPageParams);
async function getFirstNext() {
await getMessagesNext(firstActionPageParams);
}
async function getFirstPre() {
await getMessagesPre(firstActionPageParams);
}
// getFirstPre();
getFirstNext();
// useEffect(() => {
// getMessagesNext(paramsForMsgList);
// return () => {};
// }, [paramsForMsgList.lasttime]);
return () => {};
}, [selectedConversation.conversationid]);
// ,
useEffect(() => {
if (chatItemMessages.length > 0) {
setParamsForMsgList({pretime: chatItemMessages[0].orgmsgtime, lasttime: chatItemMessages[chatItemMessages.length - 1].orgmsgtime });
}
return () => {};
}, [chatItemMessages])
const onLoadMore = () => {
getMessagesNext(paramsForMsgList);
// window.dispatchEvent(new Event('resize'));
};
const loadMore = !messageListLoading && paramsForMsgList.loadNextPage ? (
<div className='text-center pt-3 mb-3 h-8 leading-8 border-dotted border-0 border-t border-slate-300'>
<Button onClick={onLoadMore}>load more</Button>
</div>
) : null;
const onLoadMorePre = () => {
getMessagesPre(paramsForMsgList);
// window.dispatchEvent(new Event('resize'));
};
const loadMorePre =
paramsForMsgList.loadPrePage && chatItemMessages.length > 0 ? (
<div className='text-center pt-3 mb-3 h-8 leading-8 border-dotted border-0 border-t border-slate-300'>
{messageListPreLoading ? <LoadingOutlined className='text-primary' /> : <Button onClick={onLoadMorePre}>load more previous </Button>}
</div>
) : null;
useEffect(() => {
getConversationsList();
@ -189,25 +251,6 @@ function ChatHistory() {
}
};
const onLoadMore = () => {
getMessagesNext(paramsForMsgList);
// window.dispatchEvent(new Event('resize'));
};
const loadMore = !messageListLoading && paramsForMsgList.loadNextPage ? (
<div className='text-center pt-3 mb-3 h-8 leading-8 border-dotted border-0 border-t border-slate-300'>
<Button onClick={onLoadMore}>loading more</Button>
</div>
) : null;
const onLoadMorePre = () => {
getMessagesPre(paramsForMsgList);
// window.dispatchEvent(new Event('resize'));
};
const loadMorePre = !messageListLoading && paramsForMsgList.loadPrePage ? (
<div className='text-center pt-3 mb-3 h-8 leading-8 border-dotted border-0 border-t border-slate-300'>
<Button onClick={onLoadMorePre}>loading more</Button>
</div>
) : null;
const messagesEndRef = useRef(null);
const messageRefs = useRef([]);
const scrollToMessage = (id, index) => {
@ -247,7 +290,7 @@ function ChatHistory() {
</Sider>
<Content style={{ maxHeight: 'calc(100vh - 279px)', height: 'calc(100vh - 279px)', minWidth: '360px' }}>
<Flex className='h-full relative'>
{(selectedConversation.matchMsgList || []).length > 0 && <div className='w-80 overflow-y-auto overflow-x-hidden'>
{(selectedConversation.matchMsgList || []).length > 1 && isNotEmpty(formValues.search) && <div className='w-80 overflow-y-auto overflow-x-hidden'>
{(selectedConversation.matchMsgList).map((item) => (
<ChatItem
{...item}
@ -260,11 +303,11 @@ function ChatHistory() {
date={item.msgtime}
// dateString={item.msgtime}
className={String(item.sn) === String(selectMatch?.sn) ? '__active text-primary bg-neutral-100' : ' bg-white'}
onClick={() => setSelectedMatch(item)}
onClick={() => handleMatchMsgClick(item)}
/>
))}
</div>}
<div className='h-full relative flex-1' ref={messagesEndRef}>
<div className='h-full relative flex-1 border-dashed border-y-0 border-r-0 border-l border-slate-200' ref={messagesEndRef}>
<List
loading={messageListLoading}
header={loadMorePre}
@ -287,7 +330,7 @@ function ChatHistory() {
onOpen={() => handlePreview(message)}
onTitleClick={() => handlePreview(message)}
notch={false}
title={message.type === 'text' ? '' : message.title}
title={message.whatsapp_msg_type === 'text' ? '' : message.title}
text={<RenderText str={message?.text || ''} />}
copiableDate={true}
dateString={message.dateString || message.localDate}

Loading…
Cancel
Save