From 9470027157113c45aacd812e113cb7ac17949f9b Mon Sep 17 00:00:00 2001 From: Lei OT Date: Tue, 12 Mar 2024 11:16:17 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=9C=A8=E7=BA=BF=E7=AA=97=E5=8F=A3:=20?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E6=9B=B4=E5=A4=9A=E6=B6=88=E6=81=AF=0Bstyle:?= =?UTF-8?q?=20=E8=AE=A2=E5=8D=95=E8=B7=9F=E8=B8=AA:=20=E6=98=BE=E7=A4=BAWh?= =?UTF-8?q?atsApp=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新投递成功的时间到会话列表 粘贴上传 style: font fix: 模板填充 --- src/actions/CommonActions.js | 13 +- src/actions/ConversationActions.js | 13 +- src/stores/ConversationStore.js | 33 +++-- src/views/ChatHistory.jsx | 9 +- .../Components/ConversationsList.jsx | 7 +- .../Components/Input/Template.jsx | 10 +- .../Components/InputComposer.jsx | 118 ++++++++++++++++-- .../Conversations/Components/MessagesList.jsx | 51 +++----- .../Components/MessagesWrapper.jsx | 24 +++- src/views/Conversations/Conversations.css | 4 +- src/views/OrderFollow.jsx | 8 +- 11 files changed, 202 insertions(+), 88 deletions(-) diff --git a/src/actions/CommonActions.js b/src/actions/CommonActions.js index 3ec4543..3773d0d 100644 --- a/src/actions/CommonActions.js +++ b/src/actions/CommonActions.js @@ -1,4 +1,4 @@ -import { fetchJSON } from '@/utils/request'; +import { fetchJSON, postForm, } from '@/utils/request'; import { API_HOST } from '@/config'; /** @@ -8,3 +8,14 @@ export const fetchSalesAgent = async (q) => { const { errcode, result } = await fetchJSON(`https://p9axztuwd7x8a7.mycht.cn/service-Analyse2/GetOperatorInfo`, { q }); return errcode !== 0 ? [] : result.map((ele) => ({ ...ele, label: ele.cn_name, value: ele.op_id })); }; + +/** + * 上传单个文件 + * @returns {object} { errcode, result: { file_url } } + */ +export const postUploadFileItem = async (fileObj, rename) => { + const formData = new FormData(); + formData.append('file', fileObj, rename); + const { errcode, result } = await postForm(`${API_HOST}/WAFileUpload`, formData); + return errcode !== 0 ? {} : result; +}; diff --git a/src/actions/ConversationActions.js b/src/actions/ConversationActions.js index 5a56494..b5d0469 100644 --- a/src/actions/ConversationActions.js +++ b/src/actions/ConversationActions.js @@ -36,15 +36,9 @@ export const fetchMessages = async (params) => { pagesize: MESSAGE_PAGE_SIZE, }; const { errcode, result } = await fetchJSON(`${API_HOST}/getcusmessages`, {...defaultParams, ...params}); - return errcode !== 0 ? [] : parseRenderMessageList(result || []); + return errcode !== 0 ? [] : parseRenderMessageList(result.reverse() || []); } -export const fetchCustomerProfile = async (colisn) => { - const { result } = await fetchJSON(`${API_HOST}/getorderinfo`, { colisn }); - const data = result?.[0] || {}; - return data; -}; - /** * * @param {object} params { opisn, whatsappid, colisn } @@ -72,3 +66,8 @@ export const fetchCleanUnreadMsgCount = async (params) => { const { errcode, result } = await fetchJSON(`${API_HOST}/clean_unread_msg_count`, params); return errcode !== 0 ? {} : result; }; + +/** + * ------------------------------------------------------------------------------------------------ + * 历史记录 + */ diff --git a/src/stores/ConversationStore.js b/src/stores/ConversationStore.js index d780c9e..7a8de32 100644 --- a/src/stores/ConversationStore.js +++ b/src/stores/ConversationStore.js @@ -149,7 +149,7 @@ const conversationSlice = (set, get) => ({ const newConversationsMapped = newConversations.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {}); const newListIds = newList.map((chatItem) => `${chatItem.sn}`); - const withoutNew = conversationsList.filter(item => !newListIds.includes(`${item.sn}`)); + const withoutNew = conversationsList.filter((item) => !newListIds.includes(`${item.sn}`)); return set((state) => ({ conversationsList: [...newList, ...withoutNew], @@ -188,6 +188,19 @@ const conversationSlice = (set, get) => ({ conversationsList: [...conversationsList], })); }, + updateCurrentConversation: (conversation) => set((state) => ({ currentConversation: { ...state.currentConversation, ...conversation } })), + updateConversationItem: (conversation) => { + const { conversationsList } = get(); + const targetId = conversation.sn; + const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId)); + targetIndex !== -1 + ? conversationsList.splice(targetIndex, 1, { + ...conversationsList[targetIndex], + ...conversation, + }) + : null; + return set({ conversationsList: [...conversationsList] }); + }, }); const messageSlice = (set, get) => ({ @@ -204,7 +217,7 @@ const messageSlice = (set, get) => ({ // msgUpdate console.log('UPDATE_SENT_MESSAGE_ITEM-----------------------------------------------------------------'); // 更新会话中的消息 - const { activeConversations } = get(); + const { activeConversations, conversationsList } = get(); const targetId = message.conversationid; const targetMsgs = (activeConversations[String(targetId)] || []).map((ele) => { // 更新状态 @@ -224,17 +237,17 @@ const messageSlice = (set, get) => ({ } // 更新列表的时间 - // 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, - // }); - // } + if (message.status === 'received') { // 'delivered' + const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId)); + conversationsList.splice(targetIndex, 1, { + ...conversationsList[targetIndex], + last_received_time: message.deliverTime, // todo: 需要+8 hours + }); + } return set({ activeConversations: { ...activeConversations, [String(targetId)]: targetMsgs }, - // conversationsList: [...conversationsList], + conversationsList: [...conversationsList], }); }, sentOrReceivedNewMessage: (targetId, message) => { diff --git a/src/views/ChatHistory.jsx b/src/views/ChatHistory.jsx index a7e464e..edf0f63 100644 --- a/src/views/ChatHistory.jsx +++ b/src/views/ChatHistory.jsx @@ -1,15 +1,12 @@ -import { useNavigate } from 'react-router-dom'; import { memo, useCallback, useEffect, useRef, useState, forwardRef } from 'react'; -import { Row, Col, Divider, Table, Card, Button, Input, Flex, Layout, Space, Empty, Radio, Select, DatePicker, Form, List, Avatar, Spin, Image } from 'antd'; -import { StarFilled, ZoomInOutlined, StarOutlined, SearchOutlined } from '@ant-design/icons'; -import { ChatList, ChatItem, MessageBox } from 'react-chat-elements'; +import { Divider, Button, Input, Layout, Select, DatePicker, Form, List, Spin } from 'antd'; +import { ChatItem, MessageBox } from 'react-chat-elements'; import { fetchConversationsList, fetchMessages, MESSAGE_PAGE_SIZE } from '@/actions/ConversationActions'; import { isEmpty } from '@/utils/utils'; import useFormStore from '@/stores/FormStore'; import { useShallow } from 'zustand/react/shallow'; import { fetchSalesAgent } from '@/actions/CommonActions'; -// import SearchInput from '@/components/SearchInput2'; import SearchInput from '@/components/SearchInput'; const { Sider, Content, Header, Footer } = Layout; @@ -197,7 +194,7 @@ function ChatHistory() { const onLoadMore = () => { getMessages(selectedConversation); - window.dispatchEvent(new Event('resize')); + // window.dispatchEvent(new Event('resize')); }; const loadMore = !loading && selectedConversation.loadNextPage ? (
diff --git a/src/views/Conversations/Components/ConversationsList.jsx b/src/views/Conversations/Components/ConversationsList.jsx index c7f4665..56a91cd 100644 --- a/src/views/Conversations/Components/ConversationsList.jsx +++ b/src/views/Conversations/Components/ConversationsList.jsx @@ -2,7 +2,7 @@ import { useEffect, useState, useRef } from 'react'; import { useParams, useNavigate, useLocation } from 'react-router-dom'; import { Button, Dropdown, Input } from 'antd'; import { MoreOutlined } from '@ant-design/icons'; -import { fetchOrderConversationsList, fetchConversationItemClose, fetchMessages, fetchCleanUnreadMsgCount } from '@/actions/ConversationActions'; +import { fetchOrderConversationsList, fetchConversationItemClose, fetchMessages, MESSAGE_PAGE_SIZE, fetchCleanUnreadMsgCount } from '@/actions/ConversationActions'; import { ChatList, ChatItem } from 'react-chat-elements'; import { isEmpty } from '@/utils/utils'; import useConversationStore from '@/stores/ConversationStore'; @@ -19,7 +19,7 @@ const Conversations = () => { const userId = useAuthStore((state) => state.loginUser.userId); const initialState = useConversationStore((state) => state.initialState); const activeConversations = useConversationStore((state) => state.activeConversations); - const [currentConversation, setCurrentConversation] = useConversationStore((state) => [state.currentConversation, state.setCurrentConversation]); + const [currentConversation, setCurrentConversation, updateCurrentConversation] = useConversationStore((state) => [state.currentConversation, state.setCurrentConversation, state.updateCurrentConversation]); const conversationsList = useConversationStore((state) => state.conversationsList); const addToConversationList = useConversationStore((state) => state.addToConversationList); const delConversationitem = useConversationStore((state) => state.delConversationitem); @@ -76,6 +76,9 @@ const Conversations = () => { const data = await fetchMessages({ opisn: userId, whatsappid: item.whatsapp_phone_number, lasttime: '2024-01-01T00:25:30' }); setMsgLoading(false); receivedMessageList(item.sn, data); + const thisLastTime = data.length > 0 ? data[data.length - 1].orgmsgtime : ''; + const loadNextPage = !(data.length === 0 || data.length < MESSAGE_PAGE_SIZE); + updateCurrentConversation({ lasttime: thisLastTime, loadNextPage }); }; const switchConversation = async (item) => { setCurrentConversation(item); diff --git a/src/views/Conversations/Components/Input/Template.jsx b/src/views/Conversations/Components/Input/Template.jsx index 86bcf67..b1d7e46 100644 --- a/src/views/Conversations/Components/Input/Template.jsx +++ b/src/views/Conversations/Components/Input/Template.jsx @@ -1,4 +1,4 @@ -import { useState, useRef, useEffect } from 'react'; +import { useState, useRef, useEffect, memo } from 'react'; import { App, Popover, Flex, Button, List, Input } from 'antd'; import { MessageOutlined, SendOutlined } from '@ant-design/icons'; import useAuthStore from '@/stores/AuthStore' @@ -92,7 +92,7 @@ const InputTemplate = ({ disabled = false, invokeSendMessage }) => { }); }; - const renderForm = (tempItem) => { + const RenderForm = memo(function renderForm({tempItem}) { const templateText = tempItem.components.body?.[0]?.text || ''; const tempArr = splitTemplate(templateText); const keys = (templateText.match(/{{(.*?)}}/g) || []).map((key) => key.replace(/{{|}}/g, '')); @@ -116,11 +116,11 @@ const InputTemplate = ({ disabled = false, invokeSendMessage }) => { /> ) ); - }; + }); return ( <> { description={ <>
-
{renderForm(item)}
+
{item.components?.footer?.[0] ?
{item.components.footer[0].text || ''}
: null}
{/*
diff --git a/src/views/Conversations/Components/InputComposer.jsx b/src/views/Conversations/Components/InputComposer.jsx index 390eb17..1da686f 100644 --- a/src/views/Conversations/Components/InputComposer.jsx +++ b/src/views/Conversations/Components/InputComposer.jsx @@ -1,5 +1,5 @@ import React, { useState, useRef, useEffect } from 'react'; -import { Input, Flex, Button, Image } from 'antd'; +import { App, Input, Flex, Button, Image, } from 'antd'; // import { Input } from 'react-chat-elements'; import useAuthStore from '@/stores/AuthStore'; import useConversationStore from '@/stores/ConversationStore'; @@ -23,17 +23,36 @@ import { sentMsgTypeMapped } from '@/lib/msgUtils'; import InputTemplate from './Input/Template'; import InputEmoji from './Input/Emoji'; import InputMediaUpload from './Input/MediaUpload'; +import { postUploadFileItem } from '@/actions/CommonActions'; import dayjs from 'dayjs'; +const aliOSSHost = `https://haina-sale-system.oss-cn-shenzhen.aliyuncs.com/WAMedia/`; +/** + * image + * ext: ani;bmp;gif;ico;jpe;jpeg;jpg;pcx;png;psd;tga;tif;tiff;wmf + * + * audio + * ext: aac;ac3;aif;aifc;aiff;au;cda;dts;fla;flac;it;m1a;m2a;m3u;m4a;mid;midi;mka;mod;mp2;mp3;mpa;ogg;ra;rmi;spc;rmi;snd;umx;voc;wav;wma;xm + * + * video + * ext: 3g2;3gp;3gp2;3gpp;amr;amv;asf;avi;bdmv;bik;d2v;divx;drc;dsa;dsm;dss;dsv;evo;f4v;flc;fli;flic;flv;hdmov;ifo;ivf;m1v;m2p;m2t;m2ts;m2v;m4b;m4p;m4v;mkv;mp2v;mp4;mp4v;mpe;mpeg;mpg;mpls;mpv2;mpv4;mov;mts;ogm;ogv;pss;pva;qt;ram;ratdvd;rm;rmm;rmvb;roq;rpm;smil;smk;swf;tp;tpr;ts;vob;vp6;webm;wm;wmp;wmv + * + */ +const fileTypesExt = { + sticker: ['webp'], + photo: ['jpeg', 'jpg', 'png'], + video: ['gif', 'mp4', '3gp'], + document: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv'], + audio: ['aac', 'mp4', 'm4a', 'mp3', 'amr', 'ogg'], +}; + const InputComposer = () => { 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 = useConversationStore(state => state.referenceMsg); - const setReferenceMsg = useConversationStore(state => state.setReferenceMsg); - const complexMsg = useConversationStore(state => state.complexMsg); - const setComplexMsg = useConversationStore(state => state.setComplexMsg); + 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; @@ -103,6 +122,69 @@ const InputComposer = () => { 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 newName = rename ? `${uuid()}.${suffix}` : file.name; + const type = Object.keys(fileTypesExt).find((type) => fileTypesExt[type].includes(suffix)); + const dataUri = aliOSSHost + newName; + const msgObj = { + type: type, + name: newName, + uploadStatus: 'loading', + data: { dataUri: dataUri, link: dataUri, width: '100%', height: 150, loading: 0.01 }, + id: uuid(), + }; + // 读取完毕后获取结果 + reader.onload = (event) => { + const previewSrc = event.target.result; + msgObj.data.uri = previewSrc; + }; + file.newName = newName; + file.msgData = msgObj; + // 把文件对象作为一个 dataURL 读入 + reader.readAsDataURL(file); + return file; + }; + const handlePaste = async (event) => { + const items = (event.clipboardData || window.clipboardData).items; + let tmpfile = null; + if (!items || items.length === 0) { + // 当前浏览器不支持本地 + message.warning('当前浏览器不支持本地'); + return; + } + 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) { + isNotFile = false; + tmpfile = items[i].getAsFile(); + break; + } + } + if (isNotFile) { + // 普通的粘贴 + return; + } + if (!tmpfile) { + message.warning('没有读取到粘贴内容'); + return; + } + const shouldRename = tmpfile.type.indexOf('image') !== -1; + const _tmpFile = await readPasted(tmpfile, shouldRename); + setComplexMsg(_tmpFile.msgData); + setPastedUploading(true); + const { file_url } = await postUploadFileItem(tmpfile, _tmpFile.newName); + setPastedUploading(false); + setComplexMsg({..._tmpFile.msgData, uploadStatus: file_url ? 'done' : 'error'}); + return; + } + const focusInput = () => { textInputRef.current.focus({ cursor: 'end', preventScroll: true, }); }; @@ -144,17 +226,27 @@ const InputComposer = () => { {complexMsg.id && (
- {(complexMsg.type === 'photo' && complexMsg.data.uri) && } - {complexMsg.type === 'video' && } - {complexMsg.type !== 'photo' && {complexMsg.name}} - {complexMsg.status === 'loading' && } - {complexMsg.status === 'done' && } - {complexMsg.status === 'error' && <> 添加失败 } + {['photo', 'sticker'].includes(complexMsg.type) && complexMsg.data.uri ? ( + + ) : ( + <> + + {complexMsg.name} + + )} + {complexMsg.uploadStatus === 'loading' && } + {/* {complexMsg.uploadStatus === 'done' && } */} + {complexMsg.uploadStatus === 'error' && ( + <> + 添加失败{' '} + + )}
diff --git a/src/views/Conversations/Components/MessagesList.jsx b/src/views/Conversations/Components/MessagesList.jsx index 8435a0b..6e46393 100644 --- a/src/views/Conversations/Components/MessagesList.jsx +++ b/src/views/Conversations/Components/MessagesList.jsx @@ -1,37 +1,20 @@ import { useEffect, useRef, useState, forwardRef, memo } from 'react'; import { MessageBox } from 'react-chat-elements'; import { Button } from 'antd'; -import { DownOutlined } from '@ant-design/icons'; +import { DownOutlined, LoadingOutlined } from '@ant-design/icons'; import { useShallow } from 'zustand/react/shallow'; import useConversationStore from '@/stores/ConversationStore'; -import { isEmpty, olog } from '@/utils/utils'; +import { isEmpty, } from '@/utils/utils'; -const MessagesList = ({ messages, handlePreview, reference }) => { +const MessagesList = ({ messages, handlePreview, reference, longListLoading, getMoreMessages, shouldScrollBottom, loadNextPage, ...props }) => { const setReferenceMsg = useConversationStore(useShallow((state) => state.setReferenceMsg)); // const messagesEndRef = useRef(null); const messageRefs = useRef([]); - const [page, setPage] = useState(1); - let timeout = null; + const prevProps = useRef(props) - const fetchNextPage = async () => { - olog('fetchNextPage') - setPage(page + 1); - // Fetch next page of messages here - }; - - const handleScroll = (e) => { - const { scrollTop } = e.target; - const delay = 1000; // 1 second - - if (scrollTop === 0) { - if (timeout) clearTimeout(timeout); - timeout = setTimeout(fetchNextPage, delay); - } - }; - - const scrollToBottom = () => { - if (reference.current) { + const scrollToBottom = (force = false) => { + if (reference.current && (shouldScrollBottom || force)) { reference.current.scrollTop = reference.current.scrollHeight; } }; @@ -45,18 +28,6 @@ const MessagesList = ({ messages, handlePreview, reference }) => { useEffect(scrollToBottom, [messages]); - useEffect(() => { - const messageList = reference.current; - if (messageList) { - messageList.addEventListener('scroll', handleScroll); - } - return () => { - if (messageList) { - messageList.removeEventListener('scroll', handleScroll); - } - }; - }, []); - const RenderText = memo(function renderText({ str }) { const parts = str.split(/(https?:\/\/[^\s]+|\p{Emoji_Presentation})/gmu).filter((s) => s !== ''); const links = str.match(/https?:\/\/[\S]+/gi) || []; @@ -90,6 +61,9 @@ const MessagesList = ({ messages, handlePreview, reference }) => { ); }); + const onLoadMore = async () => { + const newLen = await getMoreMessages(); + }; // eslint-disable-next-line react/display-name const MessageBoxWithRef = forwardRef((props, ref) => (
@@ -100,6 +74,11 @@ const MessagesList = ({ messages, handlePreview, reference }) => { return (
+ {loadNextPage && ( +
+ {!longListLoading ? : } +
+ )} {messages.map((message, index) => ( (messageRefs.current[index] = el)} @@ -137,7 +116,7 @@ const MessagesList = ({ messages, handlePreview, reference }) => { /> ))}
-
); }; diff --git a/src/views/Conversations/Components/MessagesWrapper.jsx b/src/views/Conversations/Components/MessagesWrapper.jsx index e99265b..7f3d627 100644 --- a/src/views/Conversations/Components/MessagesWrapper.jsx +++ b/src/views/Conversations/Components/MessagesWrapper.jsx @@ -3,20 +3,36 @@ import useConversationStore from '@/stores/ConversationStore'; import { useShallow } from 'zustand/react/shallow'; import { Image, } from 'antd'; import MessagesList from './MessagesList'; -import { fetchCleanUnreadMsgCount } from '@/actions/ConversationActions'; +import { fetchCleanUnreadMsgCount, fetchMessages, MESSAGE_PAGE_SIZE } from '@/actions/ConversationActions'; const MessagesWrapper = () => { - const currentConversation = useConversationStore(useShallow((state) => state.currentConversation)); + const [currentConversation, updateCurrentConversation] = useConversationStore(useShallow((state) => [state.currentConversation, state.updateCurrentConversation])); const activeMessages = useConversationStore(useShallow((state) => (state.currentConversation.sn && state.activeConversations[state.currentConversation.sn] ? state.activeConversations[state.currentConversation.sn]: []))); + const [longList, setLongList] = useState([]); + const [longListLoading, setLongListLoading] = useState(false); + const [shouldScrollBottom, setShouldScrollBottom] = useState(true); useEffect(() => { + setLongList(activeMessages); + setShouldScrollBottom(true); if (currentConversation.opi_sn && currentConversation.whatsapp_phone_number && activeMessages.length > 0) { fetchCleanUnreadMsgCount({ opisn: currentConversation.opi_sn, whatsappid: currentConversation.whatsapp_phone_number }); } return () => {}; - }, [activeMessages]); + }, [activeMessages, currentConversation.sn]); + const getMoreMessages = async () => { + setShouldScrollBottom(false); + setLongListLoading(true); + const data = await fetchMessages({ opisn: currentConversation.opi_sn, whatsappid: currentConversation.whatsapp_phone_number, lasttime: currentConversation?.lasttime || '2024-01-01T00:00:00' }); + setLongListLoading(false); + setLongList(prevValue => data.concat(prevValue)); + const thisLastTime = data.length > 0 ? data[data.length - 1].orgmsgtime : ''; + const loadNextPage = !(data.length === 0 || data.length < MESSAGE_PAGE_SIZE); + updateCurrentConversation({ lasttime: thisLastTime, loadNextPage }); + return data.length; + }; const reference = useRef(null); @@ -43,7 +59,7 @@ const MessagesWrapper = () => { }; return ( <> - + ); diff --git a/src/views/Conversations/Conversations.css b/src/views/Conversations/Conversations.css index 64bd1c5..d126433 100644 --- a/src/views/Conversations/Conversations.css +++ b/src/views/Conversations/Conversations.css @@ -120,8 +120,8 @@ .chatwindow-wrapper .rce-mbox-reply-message, .chatwindow-wrapper .emoji { - font-family: 'Noto Sans',"Noto Color Emoji", 'Apple Color Emoji', 'Twemoji Mozilla', 'Segoe UI Emoji', 'Segoe UI Symbol', 'EmojiOne Color', 'Android Emoji', Arial, sans-serif; - font-weight: 500; + font-family: 'Open Sans', 'Noto Sans',"Noto Color Emoji", 'Apple Color Emoji', 'Twemoji Mozilla', 'Segoe UI Emoji', 'Segoe UI Symbol', 'EmojiOne Color', 'Android Emoji', Arial, sans-serif; + font-weight: 400; } .chatwindow-wrapper .rce-mbox-text a{ color: #4f81a1; diff --git a/src/views/OrderFollow.jsx b/src/views/OrderFollow.jsx index 755c7b3..abeb16b 100644 --- a/src/views/OrderFollow.jsx +++ b/src/views/OrderFollow.jsx @@ -11,6 +11,7 @@ import useAuthStore from '@/stores/AuthStore' import { copy } from '@/utils/commons' import useFormStore from '@/stores/FormStore'; import { useShallow } from 'zustand/react/shallow'; +import { WhatsAppOutlined } from '@ant-design/icons'; const { RangePicker } = DatePicker @@ -167,7 +168,10 @@ function OrderGroupTable({ formValues }) { if (record.buytime > 0) regularText = '(R' + record.buytime + ')' return ( - {text + regularText} + + {text + regularText} + {record.coli_guest_WhatsApp && } + - ) + ); } }, { From b8ee24a413b4ae9dad643e82375d8a1a103d6601 Mon Sep 17 00:00:00 2001 From: Lei OT Date: Tue, 12 Mar 2024 11:18:46 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=8E=86=E5=8F=B2=E8=AE=B0=E5=BD=95:=20?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E5=AE=A2=E4=BA=BA=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/actions/CommonActions.js | 8 +++++ src/views/ChatHistory.jsx | 60 ++++++++---------------------------- 2 files changed, 21 insertions(+), 47 deletions(-) diff --git a/src/actions/CommonActions.js b/src/actions/CommonActions.js index 3773d0d..6e10b26 100644 --- a/src/actions/CommonActions.js +++ b/src/actions/CommonActions.js @@ -9,6 +9,14 @@ export const fetchSalesAgent = async (q) => { return errcode !== 0 ? [] : result.map((ele) => ({ ...ele, label: ele.cn_name, value: ele.op_id })); }; +/** + * 客人列表 + */ +export const fetchCustomerList = async (q) => { + const { errcode, result } = await fetchJSON(`${API_HOST}/GetWhatsappidList`, { search: q }); + return errcode !== 0 ? [] : result.map((ele) => ({ ...ele, label: ele.whatsapp_name, value: ele.whatsapp_phone_number })); +}; + /** * 上传单个文件 * @returns {object} { errcode, result: { file_url } } diff --git a/src/views/ChatHistory.jsx b/src/views/ChatHistory.jsx index edf0f63..649e182 100644 --- a/src/views/ChatHistory.jsx +++ b/src/views/ChatHistory.jsx @@ -6,7 +6,7 @@ import { isEmpty } from '@/utils/utils'; import useFormStore from '@/stores/FormStore'; import { useShallow } from 'zustand/react/shallow'; -import { fetchSalesAgent } from '@/actions/CommonActions'; +import { fetchSalesAgent, fetchCustomerList } from '@/actions/CommonActions'; import SearchInput from '@/components/SearchInput'; const { Sider, Content, Header, Footer } = Layout; @@ -19,7 +19,11 @@ const { RangePicker } = DatePicker; const SearchForm = memo(function ({ initialValues, onSubmit }) { const [form] = Form.useForm(); function handleSubmit(values) { - onSubmit?.({...values, travel: values?.agent?.value || -1}); + onSubmit?.({ + ...values, + travel: values?.agent?.value || '', + customer_name: values?.customer?.label || '', + }); } return (
- + + + + {/*