diff --git a/src/actions/ConversationActions.js b/src/actions/ConversationActions.js index 991eb94..fe5295d 100644 --- a/src/actions/ConversationActions.js +++ b/src/actions/ConversationActions.js @@ -87,6 +87,7 @@ export const fetchConversationsSearch = async (params) => { ...ele, customer_name: `${ele.whatsapp_name || ''}`.trim(), whatsapp_name: `${ele.whatsapp_name || ''}`.trim(), + OPI_Name: `${ele.OPI_Name || ''}`.trim(), matchMsgList: parseRenderMessageList((ele.msglist_AsJOSN || [])), // .reverse()), })); return list; diff --git a/src/components/SearchInput.jsx b/src/components/SearchInput.jsx index 58feb91..ef75603 100644 --- a/src/components/SearchInput.jsx +++ b/src/components/SearchInput.jsx @@ -36,7 +36,7 @@ function DebounceSelect({ fetchOptions, debounceTimeout = 800, ...props }) { optionFilterProp='label' > {options.map((d) => ( - + {d.label} ))} diff --git a/src/main.jsx b/src/main.jsx index 445cc29..3bbeae8 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -29,7 +29,7 @@ const router = createBrowserRouter([ element: , errorElement: , children: [ - { + { element: , children: [ { index: true, element: }, @@ -41,11 +41,12 @@ const router = createBrowserRouter([ { path: 'account/profile', element: }, ] }, - { - path: 'm', + { + path: 'm', element: , children: [ { path: 'conversation', element: }, + { path: 'chat/:order_sn', element: }, { path: 'chat', element: }, ] }, diff --git a/src/stores/ConversationStore.js b/src/stores/ConversationStore.js index 6a52695..f171ec5 100644 --- a/src/stores/ConversationStore.js +++ b/src/stores/ConversationStore.js @@ -32,12 +32,16 @@ const initialConversationState = { // templates: [], - // conversationsList: [], // 对话列表 - // currentConversation: {}, // 当前对话 + conversationsList: [], // 对话列表 + currentConversation: {}, // 当前对话 - // activeConversations: {}, // 激活的对话的消息列表: { [conversationId]: [] } + activeConversations: {}, // 激活的对话的消息列表: { [conversationId]: [] } - // referenceMsg: {}, + referenceMsg: {}, + complexMsg: {}, + + totalNotify: 0, + msgListLoading: false, }; @@ -219,6 +223,7 @@ const messageSlice = (set, get) => ({ totalNotify: 0, msgListLoading: false, activeConversations: {}, + refreshTotalNotify: () => set((state) => ({ totalNotify: state.conversationsList.reduce((r, c) => r+c.unread_msg_count, 0) })), setMsgLoading: (msgListLoading) => set({ msgListLoading }), receivedMessageList: (conversationid, msgList) => set((state) => ({ @@ -343,15 +348,9 @@ export const useConversationStore = create( setInitial(true); - // const autoGetMsgs = conversationsList.length > 5 ? 5 : conversationsList.length; - // for (let index = 0; index < autoGetMsgs; index++) { - // const chatItem = conversationsList[index]; - // const msgData = await fetchMessages({ opisn: chatItem.opi_sn, whatsappid: chatItem.whatsapp_phone_number }); - // receivedMessageList(chatItem.sn, msgData); - // } - // for (const chatItem of conversationsList) { - // } }, + + reset: () => set(initialConversationState), })) ); diff --git a/src/views/AuthApp.jsx b/src/views/AuthApp.jsx index 5adfc21..631d184 100644 --- a/src/views/AuthApp.jsx +++ b/src/views/AuthApp.jsx @@ -52,7 +52,8 @@ function AuthApp() { theme={{ token: { colorPrimary: colorPrimary, - borderRadius: borderRadius + borderRadius: borderRadius, + fontFamily: "-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Noto Color Emoji','Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'", }, algorithm: theme.defaultAlgorithm, }} diff --git a/src/views/ChatHistory.jsx b/src/views/ChatHistory.jsx index 1e6880c..cf91dc6 100644 --- a/src/views/ChatHistory.jsx +++ b/src/views/ChatHistory.jsx @@ -35,32 +35,33 @@ const SearchForm = memo(function ({ initialValues, onSubmit }) { }); } return ( -
- - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +
+ + + +
+
); }); @@ -89,7 +90,7 @@ function ChatHistory() { const allEmpty = Object.values(cloneDeep(formValues)).every((val) => { return val === null || val === '' || val === undefined; }); - if (allEmpty) return; + // if (allEmpty) return; setConversationsListLoading(true); setChatItemMessages([]); setParamsForMsgList({}); @@ -224,11 +225,11 @@ function ChatHistory() { return prev; }, []); return ( - + {(objArr || []).map((part, index) => { if (part.type === 'link') { return ( - + {part.key} ); @@ -284,8 +285,9 @@ function ChatHistory() { letterItem={{ id: item.whatsapp_name || item.whatsapp_phone_number, letter: (item.whatsapp_name || item.whatsapp_phone_number).split(" ")[0] }} alt={`${item.whatsapp_name}`} title={item.whatsapp_name || item.whatsapp_phone_number} - subtitle={item.coli_id} + subtitle={`${item.OPI_Name || ''} ${item.coli_id || ''}`} date={item.last_received_time} + // dateString={item.last_received_time} className={String(item.conversationid) === String(selectedConversation.conversationid) ? '__active text-primary bg-neutral-100' : ''} onClick={() => setSelectedConversation(item)} /> @@ -300,7 +302,7 @@ function ChatHistory() { {...item} key={item.sn} id={item.sn} - letterItem={{ id: item.senderName, letter: (item.senderName).split(" ")[0] }} + letterItem={{ id: (item.sender === 'me' ? (selectedConversation.OPI_Name || item.senderName) : item.senderName), letter: (item.sender === 'me' ? (selectedConversation.OPI_Name || item.senderName) : item.senderName).split(" ")[0] }} alt={`${item.senderName}`} title={item.senderName} subtitle={item.originText} @@ -362,7 +364,7 @@ function ChatHistory() { : {})} renderAddCmp={
- {message.senderName} + {selectedConversation.OPI_Name || message.senderName} {message.dateString || message.localDate} {message.statusCN}
diff --git a/src/views/Conversations/Components/ConversationsList.jsx b/src/views/Conversations/Components/ConversationsList.jsx index 675653d..83c0736 100644 --- a/src/views/Conversations/Components/ConversationsList.jsx +++ b/src/views/Conversations/Components/ConversationsList.jsx @@ -10,7 +10,8 @@ import useAuthStore from '@/stores/AuthStore'; /** * [] */ -const Conversations = () => { +const Conversations = ({ mobile }) => { + const routerReplace = mobile === undefined ? false : true; const { state: orderRow } = useLocation(); const { coli_guest_WhatsApp } = orderRow || {}; const { order_sn } = useParams(); @@ -22,8 +23,6 @@ const Conversations = () => { const conversationsList = useConversationStore((state) => state.conversationsList); const addToConversationList = useConversationStore((state) => state.addToConversationList); const delConversationitem = useConversationStore((state) => state.delConversationitem); - const receivedMessageList = useConversationStore((state) => state.receivedMessageList); - const setMsgLoading = useConversationStore((state) => state.setMsgLoading); const [tabSelectedConversation, setTabSelectedConversation] = useState({}); const [tabCnt, setTabCnt] = useState(-1); @@ -70,34 +69,16 @@ const Conversations = () => { return false; } }; - const getMessages = async (item) => { - setMsgLoading(true); - const data = await fetchMessages({ opisn: userId, whatsappid: item.whatsapp_phone_number, lasttime: '' }); - setMsgLoading(false); - receivedMessageList(item.sn, data); - const thisLastTime = data.length > 0 ? data[0].orgmsgtime : ''; - const loadNextPage = !(data.length === 0 || data.length < MESSAGE_PAGE_SIZE); - updateCurrentConversation({ lasttime: thisLastTime, loadNextPage }); - }; - - useEffect(() => { - const messagesList = activeConversations[`${currentConversation.sn}`] || []; - if (currentConversation.sn && messagesList.length < 20) { - getMessages(currentConversation); - } - - return () => {}; - }, [currentConversation.sn]); - const onSwitchConversation = async (item) => { setCurrentConversation(item); + const routePrefix = mobile === undefined ? `/order/chat` : `/m/chat`; if (isEmpty(item.coli_sn)) { - navigate(`/order/chat`, { replace: true }); + navigate(routePrefix, { replace: true }); } else { setSwitchToC(item); setShouldFetchCList(false); - navigate(`/order/chat/${item.coli_sn}`, { replace: true }); + navigate(`${routePrefix}/${item.coli_sn}`, { replace: routePrefix }); } // if (!isEmpty(item.coli_sn)) { // setSwitchToC(item); @@ -113,7 +94,7 @@ const Conversations = () => { await fetchConversationItemClose({ conversationid: item.sn, opisn: item.opi_sn }); delConversationitem(item); if (String(order_sn) === String(item.coli_sn)) { - navigate(`/order/chat`, { replace: true }); + navigate(`/order/chat`, { replace: routerReplace }); } }; diff --git a/src/views/Conversations/Components/Input/Emoji.jsx b/src/views/Conversations/Components/Input/Emoji.jsx index 0c6d26c..a885db3 100644 --- a/src/views/Conversations/Components/Input/Emoji.jsx +++ b/src/views/Conversations/Components/Input/Emoji.jsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import { Popover, Button } from 'antd'; import EmojiPicker from 'emoji-picker-react'; -const InputTemplate = ({ disabled = false, inputEmoji }) => { +const InputTemplate = ({ mobile, disabled = false, inputEmoji }) => { const [openPopup, setOpenPopup] = useState(false); const handlePickEmoji = (emojiData) => { @@ -13,16 +13,16 @@ const InputTemplate = ({ disabled = false, inputEmoji }) => { <> } - // title='😀' + content={} + // title='😃' trigger='click' open={openPopup} onOpenChange={setOpenPopup}> diff --git a/src/views/Conversations/Components/Input/Template.jsx b/src/views/Conversations/Components/Input/Template.jsx index ad257cb..8049cf8 100644 --- a/src/views/Conversations/Components/Input/Template.jsx +++ b/src/views/Conversations/Components/Input/Template.jsx @@ -20,7 +20,7 @@ const splitTemplate = (template) => { }, []); return obj; }; -const InputTemplate = ({ disabled = false, invokeSendMessage }) => { +const InputTemplate = ({ mobile, disabled = false, invokeSendMessage }) => { const searchInputRef = useRef(null); const { notification } = App.useApp(); const loginUser = useAuthStore((state) => state.loginUser); @@ -126,7 +126,7 @@ const InputTemplate = ({ disabled = false, invokeSendMessage }) => { return ( <> { - const userId = useAuthStore(state => state.loginUser.userId); - const websocket = useConversationStore(state => state.websocket); - const websocketOpened = useConversationStore(state => state.websocketOpened); - const currentConversation = useConversationStore(state => state.currentConversation); - const [referenceMsg, setReferenceMsg] = useConversationStore(state => [state.referenceMsg, state.setReferenceMsg]); - const [complexMsg, setComplexMsg] = useConversationStore(state => [state.complexMsg, state.setComplexMsg]); - const sentOrReceivedNewMessage = useConversationStore(state => state.sentOrReceivedNewMessage); +const InputComposer = ({ mobile }) => { + const userId = useAuthStore((state) => state.loginUser.userId); + const websocket = useConversationStore((state) => state.websocket); + const websocketOpened = useConversationStore((state) => state.websocketOpened); + const currentConversation = useConversationStore((state) => state.currentConversation); + const [referenceMsg, setReferenceMsg] = useConversationStore((state) => [state.referenceMsg, state.setReferenceMsg]); + const [complexMsg, setComplexMsg] = useConversationStore((state) => [state.complexMsg, state.setComplexMsg]); + const sentOrReceivedNewMessage = useConversationStore((state) => state.sentOrReceivedNewMessage); const talkabled = !isEmpty(currentConversation.sn) && websocketOpened; const gt24h = currentConversation.last_received_time ? dayjs().diff(dayjs(currentConversation.last_received_time), 'hour') > 24 : true; @@ -120,15 +120,14 @@ const InputComposer = () => { const contentToSend = sentMsgTypeMapped[msgObjMerge.type].contentToSend(msgObjMerge); // olog('invoke upload send +++ ', contentToSend) websocket.sendMessage({ ...contentToSend, opi_sn: userId, coli_sn: currentConversation.coli_sn }); - } - + }; const { message } = App.useApp(); const [pastedUploading, setPastedUploading] = useState(false); const readPasted = async (file, rename = false) => { // 使用 FileReader 读取文件对象 const reader = new FileReader(); - const suffix = file.name.slice(file.name.lastIndexOf('.')+1); + const suffix = file.name.slice(file.name.lastIndexOf('.') + 1); const newName = `${uuid()}.${suffix}`; // rename ? `${uuid()}.${suffix}` : file.name; const type = Object.keys(fileTypesExt).find((type) => fileTypesExt[type].includes(suffix)); const dataUri = aliOSSHost + newName; @@ -161,7 +160,7 @@ const InputComposer = () => { let isNotFile = true; for (let i = 0; i < items.length; i++) { // if (items[i].type.indexOf("image") !== -1) { - if (items[i].kind.indexOf("file") !== -1) { + if (items[i].kind.indexOf('file') !== -1) { isNotFile = false; tmpfile = items[i].getAsFile(); break; @@ -180,17 +179,17 @@ const InputComposer = () => { setComplexMsg(_tmpFile.msgData); setPastedUploading(true); const { file_url } = await postUploadFileItem(tmpfile, _tmpFile.newName); - setPastedUploading(false); - setComplexMsg({..._tmpFile.msgData, uploadStatus: file_url ? 'done' : 'error'}); + setPastedUploading(false); // todo: 更新data uri + setComplexMsg({ ..._tmpFile.msgData, uploadStatus: file_url ? 'done' : 'error' }); return; - } + }; const focusInput = () => { - textInputRef.current.focus({ cursor: 'end', preventScroll: true, }); + textInputRef.current.focus({ cursor: 'end', preventScroll: true }); }; - const addEmoji = emoji => { - setTextContent(prevValue => { + const addEmoji = (emoji) => { + setTextContent((prevValue) => { return prevValue + emoji; }); }; @@ -248,7 +247,9 @@ const InputComposer = () => { { /> - - + + {/*