From b8db2238ff6cededcb897dc48452abb8a6eb32cf Mon Sep 17 00:00:00 2001 From: Lei OT Date: Tue, 16 Apr 2024 10:40:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=86=E9=85=8D=E4=BC=9A=E8=AF=9D;?= =?UTF-8?q?=20=0Btodo:=20=E5=B7=B2=E7=BB=91=E5=AE=9A=E9=92=89=E9=92=89?= =?UTF-8?q?=E7=9A=84=E9=A1=BE=E9=97=AE=E5=88=97=E8=A1=A8=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/actions/ConversationActions.js | 30 ++++++++++ src/main.jsx | 7 +++ src/views/ChatHistory.jsx | 25 ++++++++- src/views/ChatUnassign.jsx | 52 ++++++++++++++++++ src/views/Conversations/ChatAssign.jsx | 55 +++++++++++++++++++ .../History/ConversationsList.jsx | 28 +--------- src/views/Conversations/InputAssign.jsx | 43 +++++++++++++++ .../Conversations/Online/MessagesWrapper.jsx | 8 +-- 8 files changed, 216 insertions(+), 32 deletions(-) create mode 100644 src/views/ChatUnassign.jsx create mode 100644 src/views/Conversations/ChatAssign.jsx create mode 100644 src/views/Conversations/InputAssign.jsx diff --git a/src/actions/ConversationActions.js b/src/actions/ConversationActions.js index 08ca7f9..832645e 100644 --- a/src/actions/ConversationActions.js +++ b/src/actions/ConversationActions.js @@ -97,6 +97,7 @@ export const fetchConversationsSearch = async (params) => { ? [] : (data || []).map((ele) => ({ ...ele, + sn: ele.conversationid, customer_name: `${ele.whatsapp_name || ''}`.trim(), whatsapp_name: `${ele.whatsapp_name || ''}`.trim(), opi_sn: ele.OPI_SN || ele.opi_sn || 0, @@ -127,3 +128,32 @@ export const fetchMessagesHistory = async (params) => { const data = errcode !== 0 ? [] : result; // _params.pagedir === 'next' ? result.reverse() : result; return parseRenderMessageList(data); } + +/** + * ------------------------------------------------------------------------------------------------ + * 未分配 + */ + +export const fetchConversationsUnassigned = async (params) => { + const { errcode, result: data } = await fetchJSON(`${API_HOST}/unassigned-conversation`, params); + const list = + errcode !== 0 + ? [] + : (data || []).map((ele) => ({ + ...ele, + customer_name: `${ele.whatsapp_name || ''}`.trim(), + whatsapp_name: `${ele.whatsapp_name || ''}`.trim(), + opi_sn: ele.OPI_SN || ele.opi_sn || 0, + OPI_Name: `${ele.OPI_Name || ele.opi_name || ''}`.trim(), + dateText: dayjs((ele.last_received_time)).format('MM-DD HH:mm'), + })); + return list; +}; + +/** + * @param {object} params { opi_sn, conversationid } + */ +export const postAssignConversation = async (params) => { + const { errcode, result } = await fetchJSON(`${API_HOST}/assign_conversation`, params); + return errcode !== 0 ? {} : result; +} diff --git a/src/main.jsx b/src/main.jsx index 5d36f8d..eea4b11 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -19,6 +19,9 @@ import MobileChat from '@/views/mobile/Chat' import MobileSecondHeader from '@/views/mobile/SecondHeaderWrapper'; import CustomerProfile from '@/views/Conversations/Online/order/CustomerProfile'; +import Unassign from '@/views/ChatUnassign'; +import ChatAssign from '@/views/Conversations/ChatAssign'; + import DingdingLogin from '@/views/dingding/Login' import useAuthStore from '@/stores/AuthStore' import '@/assets/index.css' @@ -39,8 +42,10 @@ const router = createBrowserRouter([ children: [ { index: true, element: }, { path: 'm/conversation', element: }, + { path: 'unassign', element: }, ], }, + { path: 'chat/unassign/:whatsappid/:conversationid', element: }, { path: 'm/chat/:order_sn', element: }, { path: 'm/chat', element: }, { @@ -61,6 +66,8 @@ const router = createBrowserRouter([ { path: 'order/chat/:order_sn', element: }, { path: 'order/chat', element: }, { path: 'account/profile', element: }, + { path: 'chat/unassign/:whatsappid/:conversationid', element: }, + { path: 'chat/unassign', element: }, ], }, ], diff --git a/src/views/ChatHistory.jsx b/src/views/ChatHistory.jsx index b2e3e0e..73488a8 100644 --- a/src/views/ChatHistory.jsx +++ b/src/views/ChatHistory.jsx @@ -1,4 +1,4 @@ -import { useCallback, useState } from 'react'; +import { useCallback, useState, useEffect } from 'react'; import { Divider, Layout, Flex, Image } from 'antd'; import useFormStore from '@/stores/FormStore'; import SearchForm from './Conversations/History/SearchForm'; @@ -6,23 +6,44 @@ import ConversationsList from './Conversations/History/ConversationsList'; import MessagesMatchList from './Conversations/History/MessagesMatchList'; import MessagesList from './Conversations/History/MessagesList'; import ImageAlbumPreview from './Conversations/History/ImageAlumPreview'; +import { flush, pick } from '@/utils/commons'; +import { fetchConversationsSearch } from '@/actions/ConversationActions'; const { Sider, Content } = Layout; const Index = (props) => { const [formValues, setFormValues] = useFormStore((state) => [state.chatHistoryForm, state.setChatHistoryForm]); + const [selectedConversation, setSelectedConversation] = useFormStore((state) => [state.chatHistorySelectChat, state.setChatHistorySelectChat]); + + const [conversationsListLoading, setConversationsListLoading] = useState(false); + const [conversationsList, setConversationsList] = useState([]); const handleSubmit = useCallback((values) => { setFormValues({ ...values }); }, []); + useEffect(() => { + getConversationsList(); + return () => {}; + }, [formValues]); + + const getConversationsList = async () => { + setConversationsListLoading(true); + 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]); + } + }; return ( <> - + diff --git a/src/views/ChatUnassign.jsx b/src/views/ChatUnassign.jsx new file mode 100644 index 0000000..4e83f2a --- /dev/null +++ b/src/views/ChatUnassign.jsx @@ -0,0 +1,52 @@ +import { useCallback, useState, useEffect } from 'react'; +import { Divider, Layout, Flex, Image } from 'antd'; +import useFormStore from '@/stores/FormStore'; +import SearchForm from './Conversations/History/SearchForm'; +import ConversationsList from './Conversations/History/ConversationsList'; +import MessagesMatchList from './Conversations/History/MessagesMatchList'; +import MessagesList from './Conversations/History/MessagesList'; +import ImageAlbumPreview from './Conversations/History/ImageAlumPreview'; +import { flush, pick } from '@/utils/commons'; +import { fetchConversationsSearch, fetchConversationsUnassigned } from '@/actions/ConversationActions'; + +const { Sider, Content } = Layout; +const Unassign = (props) => { + const [selectedConversation, setSelectedConversation] = useFormStore((state) => [state.chatHistorySelectChat, state.setChatHistorySelectChat]); + + const [conversationsListLoading, setConversationsListLoading] = useState(false); + const [conversationsList, setConversationsList] = useState([]); + + useEffect(() => { + getConversationsList(); + return () => {}; + }, []); + + const getConversationsList = async () => { + setConversationsListLoading(true); + const params = {}; + const data = await fetchConversationsSearch(params); + setConversationsListLoading(false); + setConversationsList(data); + if (data.length === 1) { + setSelectedConversation(data[0]); + } + }; + return ( + <> + + +

未分配会话

+ +
+ + {/* + + + + */} + +
+ + ); +}; +export default Unassign; diff --git a/src/views/Conversations/ChatAssign.jsx b/src/views/Conversations/ChatAssign.jsx new file mode 100644 index 0000000..6a54b16 --- /dev/null +++ b/src/views/Conversations/ChatAssign.jsx @@ -0,0 +1,55 @@ +import { useRef, useState, useEffect } from 'react'; +import { Layout, Button } from 'antd'; +import MessagesHeader from '@/views/Conversations/Online/MessagesHeader'; +import MessagesWrapper from '@/views/Conversations/Online/MessagesWrapper'; +import InputComposer from '@/views/Conversations/Online/InputComposer'; +import { UnorderedListOutlined, MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons'; +import { useNavigate, useParams } from 'react-router-dom'; +import useConversationStore from '@/stores/ConversationStore'; +import useAuthStore from '@/stores/AuthStore'; +import { useShallow } from 'zustand/react/shallow'; +import InputAssign from './InputAssign'; + +import { fetchConversationsList, fetchConversationsSearch } from '@/actions/ConversationActions'; + +const { Content, Header, Footer } = Layout; + +function ChatAssign() { + const navigate = useNavigate(); + const { whatsappid, conversationid } = useParams(); + + const [currentConversation, setCurrentConversation] = useConversationStore(useShallow((state) => [state.currentConversation, state.setCurrentConversation])); + + async function refreshConversationList() { + const _list = await fetchConversationsSearch({ whatsapp_id: whatsappid }); + if (_list.length > 0) { + setCurrentConversation(_list[0]); + } + } + + useEffect(() => { + refreshConversationList(); + + return () => {}; + }, [whatsappid]); + + + return ( + <> + +
+ + +
+ + + + {/*
+ +
*/} +
+ + ); +} + +export default ChatAssign; diff --git a/src/views/Conversations/History/ConversationsList.jsx b/src/views/Conversations/History/ConversationsList.jsx index dc63c05..c012ac9 100644 --- a/src/views/Conversations/History/ConversationsList.jsx +++ b/src/views/Conversations/History/ConversationsList.jsx @@ -1,32 +1,8 @@ -import { useEffect, useState } from 'react'; import { Spin } from 'antd'; import { ChatItem } from 'react-chat-elements'; -import useFormStore from '@/stores/FormStore'; -import { flush, pick } from '@/utils/commons'; -import { fetchConversationsSearch } from '@/actions/ConversationActions'; -const ConversationsList = ({ ...props }) => { - const [formValues,] = useFormStore(((state) => [state.chatHistoryForm,])); - const [selectedConversation, setSelectedConversation] = useFormStore((state) => [state.chatHistorySelectChat, state.setChatHistorySelectChat]); +const ConversationsList = ({ conversationsListLoading, handleChatItemClick, selectedConversation, conversationsList, ...props }) => { - const [conversationsListLoading, setConversationsListLoading] = useState(false); - const [conversationsList, setConversationsList] = useState([]); - - useEffect(() => { - getConversationsList(); - return () => {}; - }, [formValues]); - - const getConversationsList = async () => { - setConversationsListLoading(true); - 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]); - } - }; return ( <> @@ -43,7 +19,7 @@ const ConversationsList = ({ ...props }) => { // dateString={item.last_received_time} dateString={item.dateText} className={String(item.conversationid) === String(selectedConversation.conversationid) ? '__active text-primary bg-neutral-100' : ''} - onClick={() => setSelectedConversation(item)} + onClick={() => handleChatItemClick(item)} /> ))} diff --git a/src/views/Conversations/InputAssign.jsx b/src/views/Conversations/InputAssign.jsx new file mode 100644 index 0000000..a637deb --- /dev/null +++ b/src/views/Conversations/InputAssign.jsx @@ -0,0 +1,43 @@ +import { useState } from 'react'; +import { App, Button, Form, Input } from 'antd'; +import SearchInput from '@/components/SearchInput'; +import { fetchSalesAgent } from '@/actions/CommonActions'; +import { postAssignConversation } from '@/actions/ConversationActions'; + +const InputAssign = ({ initialValues, ...props }) => { + const { message } = App.useApp(); + const [form] = Form.useForm(); + + const [subLoading, setSubLoading] = useState(false); + async function handleSubmit(values) { + const valuesSub = { + ...values, + opi_sn: values.opi_sn.value, + }; + setSubLoading(true); + await postAssignConversation(valuesSub); + setSubLoading(false); + message.success('分配成功'); + } + return ( + <> +
+ + + + +
+ {/* */} + +
+
+ + ); +}; +export default InputAssign; diff --git a/src/views/Conversations/Online/MessagesWrapper.jsx b/src/views/Conversations/Online/MessagesWrapper.jsx index e276141..6f10bb0 100644 --- a/src/views/Conversations/Online/MessagesWrapper.jsx +++ b/src/views/Conversations/Online/MessagesWrapper.jsx @@ -9,7 +9,7 @@ import { isEmpty } from '@/utils/commons'; import useAuthStore from '@/stores/AuthStore'; import { useVisibilityState } from '@/hooks/useVisibilityState'; -const MessagesWrapper = () => { +const MessagesWrapper = ({ updateRead = true, forceGetMessages }) => { const userId = useAuthStore((state) => state.loginUser.userId); const [currentConversation, updateCurrentConversation, setCurrentConversation] = useConversationStore(useShallow((state) => [state.currentConversation, state.updateCurrentConversation, state.setCurrentConversation])); @@ -27,7 +27,7 @@ const MessagesWrapper = () => { const [longListLoading, setLongListLoading] = useState(false); const [shouldScrollBottom, setShouldScrollBottom] = useState(true); useEffect(() => { - if (currentConversation.sn && activeMessages.length < 20) { + if (currentConversation.sn && (activeMessages.length < 20 || forceGetMessages !== undefined)) { getFirstPageMessages(currentConversation); } setShouldScrollBottom(true); @@ -43,7 +43,7 @@ const MessagesWrapper = () => { }, [activeMessages]); useEffect(() => { - if (isVisible && currentConversation.opi_sn && currentConversation.whatsapp_phone_number && activeMessages.length > 0) { + if (updateRead === true && isVisible && currentConversation.opi_sn && currentConversation.whatsapp_phone_number && activeMessages.length > 0) { fetchCleanUnreadMsgCount({ opisn: currentConversation.opi_sn, whatsappid: currentConversation.whatsapp_phone_number }); refreshTotalNotify(); } @@ -53,7 +53,7 @@ const MessagesWrapper = () => { const getFirstPageMessages = async (item) => { setMsgLoading(true); - const data = await fetchMessages({ opisn: userId, whatsappid: item.whatsapp_phone_number, lasttime: '' }); + const data = await fetchMessages({ opisn: forceGetMessages ? '' : userId, whatsappid: item.whatsapp_phone_number, lasttime: '' }); setMsgLoading(false); receivedMessageList(item.sn, data); const thisLastTime = data.length > 0 ? data[0].orgmsgtime : '';