订单进入会话, 获取新会话列表
parent
6e4fc488a7
commit
22cf54f313
@ -1,18 +0,0 @@
|
|||||||
const initialState = {
|
|
||||||
websocket: null,
|
|
||||||
websocketOpened: null,
|
|
||||||
websocketRetrying: null,
|
|
||||||
websocketRetrytimes: null,
|
|
||||||
|
|
||||||
errors: [], // 错误信息
|
|
||||||
|
|
||||||
conversationsList: [], // 对话列表
|
|
||||||
templates: [],
|
|
||||||
customerOrderProfile: {},
|
|
||||||
|
|
||||||
activeConversations: {}, // 激活的对话的消息列表: { [conversationId]: [] }
|
|
||||||
currentConversation: {}, // 当前对话
|
|
||||||
|
|
||||||
referenceMsg: {},
|
|
||||||
};
|
|
||||||
export default initialState;
|
|
@ -1,156 +0,0 @@
|
|||||||
import initialState from '@/records/ConversationState';
|
|
||||||
|
|
||||||
const NAME_SPACE = 'CONVERSATION/';
|
|
||||||
|
|
||||||
const ConversationReducer = (state = initialState, action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case NAME_SPACE + 'INIT_WEBSOCKET':
|
|
||||||
return { ...state, websocket: action.payload };
|
|
||||||
case NAME_SPACE + 'MODIFY_WEBSOCKET_STATE':
|
|
||||||
return { ...state, websocketOpened: action.payload, };
|
|
||||||
case NAME_SPACE + 'MODIFY_WEBSOCKET_RETRYTIMES':
|
|
||||||
return { ...state, websocketRetrytimes: action.payload, websocketRetrying: action.payload > 0 };
|
|
||||||
|
|
||||||
case NAME_SPACE + 'SET_CONVERSATION_LIST':{
|
|
||||||
const conversationsMapped = action.payload.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
|
|
||||||
return { ...state, conversationsList: action.payload, activeConversations: conversationsMapped };
|
|
||||||
}
|
|
||||||
case NAME_SPACE + 'ADD_TO_CONVERSATIONS_LIST':{
|
|
||||||
const { activeConversations } = state;
|
|
||||||
const conversationsIds = Object.keys(activeConversations);
|
|
||||||
const newConversations = action.payload.filter((conversation) => !conversationsIds.includes(`${conversation.sn}`));
|
|
||||||
const newConversationsMapped = newConversations.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
conversationsList: [...newConversations, ...state.conversationsList],
|
|
||||||
activeConversations: { ...activeConversations, ...newConversationsMapped },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case NAME_SPACE + 'DEL_CONVERSATIONS_ITEM': {
|
|
||||||
const { conversationsList, activeConversations, currentConversation, customerOrderProfile } = state;
|
|
||||||
const targetId = action.payload.sn;
|
|
||||||
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
|
|
||||||
conversationsList.splice(targetIndex, 1);
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
conversationsList: [...conversationsList],
|
|
||||||
activeConversations: { ...activeConversations, [`${targetId}`]: [] },
|
|
||||||
currentConversation: {},
|
|
||||||
customerOrderProfile: {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case NAME_SPACE + 'SET_TEMPLATE_LIST':
|
|
||||||
return { ...state, templates: action.payload };
|
|
||||||
|
|
||||||
case NAME_SPACE + 'SET_CUSTOMER_ORDER_PROFILE':
|
|
||||||
return { ...state, customerOrderProfile: action.payload };
|
|
||||||
|
|
||||||
case NAME_SPACE + 'SET_CURRENT_CONVERSATION': {
|
|
||||||
// 清空未读
|
|
||||||
const { conversationsList } = state;
|
|
||||||
const targetId = action.payload.sn;
|
|
||||||
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
|
|
||||||
targetIndex !== -1 ? conversationsList.splice(targetIndex, 1, {
|
|
||||||
...conversationsList[targetIndex],
|
|
||||||
unread_msg_count: 0,
|
|
||||||
}) : null;
|
|
||||||
|
|
||||||
return { ...state, currentConversation: action.payload, conversationsList: [...conversationsList] };
|
|
||||||
}
|
|
||||||
case NAME_SPACE + 'SET_ACTIVE_CONVERSATIONS': {
|
|
||||||
const { activeConversations } = state;
|
|
||||||
return { ...state, activeConversations: { ...activeConversations, ...action.payload } };
|
|
||||||
}
|
|
||||||
case NAME_SPACE + 'UPDATE_SENT_MESSAGE_ITEM': {
|
|
||||||
console.log('UPDATE_SENT_MESSAGE_ITEM-----------------------------------------------------------------', action);
|
|
||||||
// 更新会话中的消息
|
|
||||||
const { activeConversations, conversationsList, } = state;
|
|
||||||
const message = action.payload;
|
|
||||||
const targetId = message.conversationid;
|
|
||||||
const targetMsgs = (activeConversations[String(targetId)] || []).map((ele) => {
|
|
||||||
// 更新状态
|
|
||||||
// * 已读的不再更新状态, 有时候投递结果在已读之后返回
|
|
||||||
if (ele.id === ele.actionId && ele.actionId === message.actionId) {
|
|
||||||
return { ...ele, id: message.id, status: ele.status === 'read' ? ele.status : message.status, dateString: message.dateString };
|
|
||||||
} else if (ele.id === message.id) {
|
|
||||||
return { ...ele, id: message.id, status: ele.status === 'read' ? ele.status : message.status, dateString: message.dateString };
|
|
||||||
}
|
|
||||||
return ele;
|
|
||||||
});
|
|
||||||
// 显示会话中其他客户端发送的消息
|
|
||||||
const targetMsgsIds = targetMsgs.map((ele) => ele.id);
|
|
||||||
if ( ! targetMsgsIds.includes(message.id)) {
|
|
||||||
targetMsgs.push(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新列表的时间
|
|
||||||
if (message.type !== 'error') {
|
|
||||||
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
|
|
||||||
conversationsList.splice(targetIndex, 1, {
|
|
||||||
...conversationsList[targetIndex],
|
|
||||||
last_received_time: message.date,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
activeConversations: { ...state.activeConversations, [String(targetId)]: targetMsgs },
|
|
||||||
conversationsList: [...conversationsList],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case NAME_SPACE + 'RECEIVED_MESSAGE_LIST': {
|
|
||||||
const { targetId, data } = action.payload;
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
activeConversations: { ...state.activeConversations, [String(targetId)]: data },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case NAME_SPACE + 'SENT_NEW_MESSAGE':
|
|
||||||
case NAME_SPACE + 'RECEIVED_NEW_MESSAGE': {
|
|
||||||
const { activeConversations, conversationsList, currentConversation } = state;
|
|
||||||
const { targetId, message } = action.payload;
|
|
||||||
const targetMsgs = activeConversations[String(targetId)] || [];
|
|
||||||
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
|
|
||||||
const newConversation =
|
|
||||||
targetId !== -1
|
|
||||||
? {
|
|
||||||
...conversationsList[targetIndex],
|
|
||||||
last_received_time: message.date,
|
|
||||||
unread_msg_count:
|
|
||||||
String(targetId) !== String(currentConversation.sn) && message.sender !== 'me'
|
|
||||||
? conversationsList[targetIndex].unread_msg_count + 1
|
|
||||||
: conversationsList[targetIndex].unread_msg_count,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
...message,
|
|
||||||
sn: targetId,
|
|
||||||
last_received_time: message.date,
|
|
||||||
unread_msg_count: message.sender === 'me' ? 0 : 1,
|
|
||||||
};
|
|
||||||
conversationsList.splice(targetIndex, 1);
|
|
||||||
conversationsList.unshift(newConversation);
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
activeConversations: { ...activeConversations, [String(targetId)]: [...targetMsgs, message] },
|
|
||||||
conversationsList: [...conversationsList],
|
|
||||||
currentConversation: {
|
|
||||||
...state.currentConversation,
|
|
||||||
last_received_time: String(targetId) === String(currentConversation.sn) ? message.date : currentConversation.last_received_time,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case NAME_SPACE + 'SET_REFERENCE_MSG':
|
|
||||||
return {...state, referenceMsg: action.payload};
|
|
||||||
case NAME_SPACE + 'ADD_ERROR': {
|
|
||||||
console.log('add error', state.errors, action.payload);
|
|
||||||
const prelist = state.errors || [];
|
|
||||||
return { ...state, errors: [...prelist, action.payload] };
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// throw new Error(`Unknown action: ${action.type}`);
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export default ConversationReducer;
|
|
@ -1,12 +0,0 @@
|
|||||||
import {createContext, useContext} from 'react';
|
|
||||||
|
|
||||||
export const ConversationContext = createContext();
|
|
||||||
|
|
||||||
export const useConversationContext = () => useContext(ConversationContext);
|
|
||||||
|
|
||||||
|
|
||||||
export const ConversationStateContext = createContext();
|
|
||||||
export const ConversationDispatchContext = createContext();
|
|
||||||
|
|
||||||
export const useConversationState = () => useContext(ConversationStateContext);
|
|
||||||
export const useConversationDispatch = () => useContext(ConversationDispatchContext);
|
|
@ -1,102 +0,0 @@
|
|||||||
import { useContext, useReducer, useEffect } from 'react';
|
|
||||||
import { ConversationStateContext, ConversationDispatchContext } from '@/stores/ConversationContext';
|
|
||||||
import ConversationReducer from '@/reducers/ConversationReducer';
|
|
||||||
import {
|
|
||||||
initWebsocket,
|
|
||||||
updateWebsocketState,
|
|
||||||
updateWebsocketRetrytimes,
|
|
||||||
addError,
|
|
||||||
fetchConversationsList,
|
|
||||||
fetchTemplates,
|
|
||||||
receivedConversationList,
|
|
||||||
receivedTemplates,
|
|
||||||
updateMessageItem,
|
|
||||||
receivedNewMessage,
|
|
||||||
} from '@/actions/ConversationActions';
|
|
||||||
import initialState from '@/records/ConversationState';
|
|
||||||
|
|
||||||
import { AuthContext } from '@/stores/AuthContext';
|
|
||||||
|
|
||||||
import { RealTimeAPI } from '@/lib/realTimeAPI';
|
|
||||||
import { receivedMsgTypeMapped } from '@/lib/msgUtils';
|
|
||||||
import { isEmpty } from '@/utils/utils';
|
|
||||||
|
|
||||||
// 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:
|
|
||||||
|
|
||||||
const ConversationProvider = ({ children }) => {
|
|
||||||
const { loginUser } = useContext(AuthContext);
|
|
||||||
const { userId } = loginUser;
|
|
||||||
|
|
||||||
const [state, dispatch] = useReducer(ConversationReducer, { ...initialState, websocket: null });
|
|
||||||
|
|
||||||
console.log('ConversationProvider', state, dispatch);
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// console.log('invoke provider');
|
|
||||||
// const realtimeAPI = new RealTimeAPI(
|
|
||||||
// {
|
|
||||||
// url: `${WS_URL}?opisn=${userId || ''}&_spam=${Date.now().toString()}`,
|
|
||||||
// protocol: 'WhatsApp',
|
|
||||||
// },
|
|
||||||
// () => {dispatch(updateWebsocketState(true)); dispatch(updateWebsocketRetrytimes(0));},
|
|
||||||
// () => dispatch(updateWebsocketState(false)),
|
|
||||||
// (n) => dispatch(updateWebsocketRetrytimes(n))
|
|
||||||
// );
|
|
||||||
|
|
||||||
// realtimeAPI.onError(() => dispatch(addError('Error')));
|
|
||||||
// realtimeAPI.onMessage(handleMessage);
|
|
||||||
// realtimeAPI.onCompletion(() => dispatch(addError('Connection broken')));
|
|
||||||
|
|
||||||
// dispatch(initWebsocket(realtimeAPI));
|
|
||||||
// return () => {
|
|
||||||
// realtimeAPI.disconnect();
|
|
||||||
// };
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// fetchConversationsList({ opisn: userId }).then((data) => {
|
|
||||||
// dispatch(receivedConversationList(data));
|
|
||||||
// });
|
|
||||||
|
|
||||||
// fetchTemplates().then((data) => dispatch(receivedTemplates(data)));
|
|
||||||
|
|
||||||
// return () => {};
|
|
||||||
// }, []);
|
|
||||||
const handleMessage = (data) => {
|
|
||||||
console.log('handleMessage------------------');
|
|
||||||
console.log(data);
|
|
||||||
const { errcode, errmsg, result } = data;
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let resultType = result?.action || result.type;
|
|
||||||
if (errcode !== 0) {
|
|
||||||
// addError('Error Connecting to Server');
|
|
||||||
resultType = 'error';
|
|
||||||
}
|
|
||||||
console.log(resultType, 'result.type');
|
|
||||||
const msgObj = receivedMsgTypeMapped[resultType].getMsg(result);
|
|
||||||
const msgRender = receivedMsgTypeMapped[resultType].contentToRender(msgObj);
|
|
||||||
const msgUpdate = receivedMsgTypeMapped[resultType].contentToUpdate(msgObj);
|
|
||||||
console.log('msgRender msgUpdate', msgRender, msgUpdate);
|
|
||||||
if (['whatsapp.message.updated', 'message', 'error'].includes(resultType)) {
|
|
||||||
dispatch(updateMessageItem(msgUpdate));
|
|
||||||
// return false;
|
|
||||||
}
|
|
||||||
if (!isEmpty(msgRender)) {
|
|
||||||
dispatch(receivedNewMessage(msgRender.conversationid, msgRender));
|
|
||||||
}
|
|
||||||
console.log('handleMessage*******************');
|
|
||||||
};
|
|
||||||
// return <ConversationContext.Provider value={{ ...state, dispatch }}>{children}</ConversationContext.Provider>;
|
|
||||||
return (
|
|
||||||
<ConversationStateContext.Provider value={{ ...state }}>
|
|
||||||
<ConversationDispatchContext.Provider value={dispatch}>{children}</ConversationDispatchContext.Provider>
|
|
||||||
</ConversationStateContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ConversationProvider;
|
|
Loading…
Reference in New Issue