Merge branch 'main' of github.com:hainatravel/global-sales

2.0/email-builder
Jimmy Liow 10 months ago
commit 4a4ceb7375

@ -14,23 +14,17 @@
"@lexical/react": "^0.20.0", "@lexical/react": "^0.20.0",
"@vonage/client-sdk": "^1.7.2", "@vonage/client-sdk": "^1.7.2",
"antd": "^5.22.2", "antd": "^5.22.2",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"dingtalk-jsapi": "^3.0.41", "dingtalk-jsapi": "^3.0.41",
"emoji-picker-react": "^4.12.0", "emoji-picker-react": "^4.12.0",
"lexical": "^0.20.0", "lexical": "^0.20.0",
"re-resizable": "^6.10.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^6.28.0", "react-router-dom": "^6.28.0",
"zustand": "^4.5.5", "zustand": "^4.5.5",
"react-chat-elements": "^12.0.17", "react-chat-elements": "^12.0.17",
"react-draggable": "^4.4.6",
"react-quill": "^2.0.0",
"react-rnd": "^10.4.13",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"uuid": "^9.0.1", "uuid": "^9.0.1"
"vite-plugin-pwa": "^0.21.0"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.3.12", "@types/react": "^18.3.12",
@ -46,6 +40,7 @@
"tailwindcss": "^3.4.15", "tailwindcss": "^3.4.15",
"vite": "^4.5.1", "vite": "^4.5.1",
"vite-plugin-css-modules": "^0.0.1", "vite-plugin-css-modules": "^0.0.1",
"vite-plugin-pwa": "^0.21.0",
"vite-plugin-svgr": "^4.3.0", "vite-plugin-svgr": "^4.3.0",
"vite-plugin-windicss": "^1.9.3", "vite-plugin-windicss": "^1.9.3",
"windicss": "^3.5.6" "windicss": "^3.5.6"

@ -37,6 +37,7 @@ export const fetchConversationsList = async (params) => {
intour: '', intour: '',
session_enable: 1, session_enable: 1,
lastactivetime: '', lastactivetime: '',
top_state: '',
} }
const combinedFilterStr = Object.values(pick(params, ['keyword', 'tags', 'olabel', 'intour', 'ostate'])).join('') const combinedFilterStr = Object.values(pick(params, ['keyword', 'tags', 'olabel', 'intour', 'ostate'])).join('')
if (isNotEmpty(combinedFilterStr) || params.session_enable === 0) { if (isNotEmpty(combinedFilterStr) || params.session_enable === 0) {

@ -599,6 +599,7 @@ export const parseRenderMessageItem = (msg) => {
...(typeof whatsappMsgTypeMapped[thisMsgType].type === 'function' ? whatsappMsgTypeMapped[thisMsgType].type(msg) : { type: whatsappMsgTypeMapped[thisMsgType].type || 'text' }), ...(typeof whatsappMsgTypeMapped[thisMsgType].type === 'function' ? whatsappMsgTypeMapped[thisMsgType].type(msg) : { type: whatsappMsgTypeMapped[thisMsgType].type || 'text' }),
// type: whatsappMsgTypeMapped?.[thisMsgType]?.type || 'text', // type: whatsappMsgTypeMapped?.[thisMsgType]?.type || 'text',
localDate: (msg?.sendTime || msg?.createTime || '').replace('T', ' '), localDate: (msg?.sendTime || msg?.createTime || '').replace('T', ' '),
dateString: dayjs(msg?.sendTime || msg.createTime).format('MM-DD HH:mm'),
from: msg.from, from: msg.from,
sender: msg.from, sender: msg.from,
senderName: msg?.customerProfile?.name || msg?.fromName || msg?.from || 'me', // msg.from, senderName: msg?.customerProfile?.name || msg?.fromName || msg?.from || 'me', // msg.from,
@ -670,6 +671,7 @@ export const parseRenderMessageList = (messages) => {
...(typeof whatsappMsgTypeMapped[msgType].type === 'function' ? whatsappMsgTypeMapped[msgType].type(msg) : { type: whatsappMsgTypeMapped[msgType].type || 'text' }), ...(typeof whatsappMsgTypeMapped[msgType].type === 'function' ? whatsappMsgTypeMapped[msgType].type(msg) : { type: whatsappMsgTypeMapped[msgType].type || 'text' }),
date: msgContent?.sendTime || msg.msgtime || '', date: msgContent?.sendTime || msg.msgtime || '',
dateText: dayjs(msgContent?.sendTime || msg.msgtime).format('MM-DD HH:mm'), dateText: dayjs(msgContent?.sendTime || msg.msgtime).format('MM-DD HH:mm'),
dateString: dayjs(msgContent?.sendTime || msg.msgtime).format('MM-DD HH:mm'),
localDate: (msg.msgtime || '').replace('T', ' '), localDate: (msg.msgtime || '').replace('T', ' '),
from: msgContent.from, from: msgContent.from,
sender: msgContent.from, sender: msgContent.from,

@ -74,6 +74,7 @@ const tagsSlice = (set) => ({
// 会话筛选 // 会话筛选
const filterObj = { const filterObj = {
pagesize: '',
search: '', search: '',
otype: '', otype: '',
tags: [], tags: [],
@ -268,8 +269,11 @@ const conversationSlice = (set, get) => ({
const targetId = conversation.sn; const targetId = conversation.sn;
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId)); const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
conversationsList.splice(targetIndex, 1); conversationsList.splice(targetIndex, 1);
const mergedListMapped = groupBy(conversationsList, 'top_state');
return set({ return set({
topList: mergedListMapped['1'] || [],
pageList: mergedListMapped['0'] || [],
conversationsList: [...conversationsList], conversationsList: [...conversationsList],
activeConversations: { ...activeConversations, [`${targetId}`]: [] }, activeConversations: { ...activeConversations, [`${targetId}`]: [] },
currentConversation: {}, currentConversation: {},
@ -287,11 +291,14 @@ const conversationSlice = (set, get) => ({
unread_msg_count: 0, unread_msg_count: 0,
}) })
: null; : null;
const mergedListMapped = groupBy(conversationsList, 'top_state');
return set((state) => ({ return set((state) => ({
totalNotify: state.totalNotify - (conversation.unread_msg_count || 0), totalNotify: state.totalNotify - (conversation.unread_msg_count || 0),
currentConversation: Object.assign({}, conversation, targetItemFromList), currentConversation: Object.assign({}, conversation, targetItemFromList),
referenceMsg: {}, referenceMsg: {},
topList: mergedListMapped['1'] || [],
pageList: mergedListMapped['0'] || [],
conversationsList: [...conversationsList], conversationsList: [...conversationsList],
})); }));
}, },
@ -306,7 +313,13 @@ const conversationSlice = (set, get) => ({
...conversation, ...conversation,
}) })
: null; : null;
return set({ conversationsList: [...conversationsList] }); const mergedListMapped = groupBy(conversationsList, 'top_state');
return set({
topList: mergedListMapped['1'] || [],
pageList: mergedListMapped['0'] || [],
conversationsList: [...conversationsList]
});
}, },
}); });
@ -379,10 +392,14 @@ const messageSlice = (set, get) => ({
}, },
}]; }];
} }
const mergedList = [...newConversations, ...conversationsList]
const mergedListMapped = groupBy(mergedList, 'top_state');
return set({ return set({
topList: mergedListMapped['1'] || [],
pageList: mergedListMapped['0'] || [],
conversationsList: mergedList,
activeConversations: { ...activeConversations, [String(targetId)]: targetMsgs }, activeConversations: { ...activeConversations, [String(targetId)]: targetMsgs },
conversationsList: [...newConversations, ...conversationsList],
}); });
}, },
sentOrReceivedNewMessage: (targetId, message) => { sentOrReceivedNewMessage: (targetId, message) => {
@ -425,6 +442,8 @@ const messageSlice = (set, get) => ({
// console.log('find in list, i:', targetIndex); // console.log('find in list, i:', targetIndex);
// console.log('find in list, chat updated and Top: \n', JSON.stringify(newConversation, null, 2)); // console.log('find in list, chat updated and Top: \n', JSON.stringify(newConversation, null, 2));
// console.log('list updated : \n', JSON.stringify(conversationsList, null, 2)); // console.log('list updated : \n', JSON.stringify(conversationsList, null, 2));
const mergedListMapped = groupBy(conversationsList, 'top_state');
const isCurrent = Number(targetId) === Number(currentConversation.sn); const isCurrent = Number(targetId) === Number(currentConversation.sn);
const updatedCurrent = isCurrent const updatedCurrent = isCurrent
? { ? {
@ -436,6 +455,8 @@ const messageSlice = (set, get) => ({
: {...currentConversation, last_message: message,}; : {...currentConversation, last_message: message,};
return set({ return set({
currentConversation: updatedCurrent, currentConversation: updatedCurrent,
topList: mergedListMapped['1'] || [],
pageList: mergedListMapped['0'] || [],
conversationsList: [...conversationsList], conversationsList: [...conversationsList],
totalNotify: totalNotify + (message.sender === 'me' ? 0 : 1), totalNotify: totalNotify + (message.sender === 'me' ? 0 : 1),
activeConversations: { ...activeConversations, [String(targetId)]: [...targetMsgs, message] }, activeConversations: { ...activeConversations, [String(targetId)]: [...targetMsgs, message] },

@ -11,12 +11,13 @@ const BubbleEmail = ({ onOpenEditor, onOpenEmail, ...message }) => {
const RenderText = memo(function renderText({ className, email, sender }) { const RenderText = memo(function renderText({ className, email, sender }) {
return ( return (
<div onClick={() => handlePreview(message)} className={`text-sm leading-5 emoji-text whitespace-pre-wrap cursor-pointer ${className}`} key={'msg-text'}> <div onClick={() => handlePreview(message)} className={`text-sm leading-5 emoji-text whitespace-pre-wrap cursor-pointer ${className}`} key={'msg-text'}>
{sender === 'me' && <div><b>From: </b>{email.from}</div>} {/* {sender === 'me' && <div><b>From: </b>{email.from}</div>} */}
<div><b>To: </b>{email.to}</div> {/* <div><b>To: </b>{email.to}</div> */}
<div ><b>Subject: </b>{email.subject}</div> <div ><b>Subject: </b>{email.subject}</div>
<hr className='border-0 border-solid border-b border-neutral-400'/> <hr className='border-0 border-solid border-b border-neutral-400'/>
<div className='line-clamp-2 text-neutral-600'>{email.abstract}</div> <div className='line-clamp-2 text-neutral-600'>{email.abstract}</div>
</div> <div className=' text-neutral-500 text-xs italic'>{email.coli_id ? `订单: ${email.coli_id}` : '未绑定订单'}</div>
</div>
); );
}); });
const handlePreview = (message) => { const handlePreview = (message) => {
@ -47,15 +48,19 @@ const BubbleEmail = ({ onOpenEditor, onOpenEmail, ...message }) => {
{...message} {...message}
key={`${message.from}.${message.id}`} key={`${message.from}.${message.id}`}
type='text' type='text'
title={ message.sender !== 'me' && title={
<> <>
<MailOutlined className='text-indigo-600' /> <MailOutlined className='text-indigo-600' />
<span className={`pl-2 ${message.sender === 'me' ? '' : 'text-indigo-600'}`}> <span className={`pl-2 ${message.sender === 'me' ? '' : 'text-indigo-600'}`}>
{message.sender !== 'me' ?
<>
<b>From: </b> <b>From: </b>
<span> <span>
{/* {message?.emailOrigin?.fromName}&nbsp;&lt;{message?.emailOrigin.fromEmail}&gt; */} {/* {message?.emailOrigin?.fromName}&nbsp;&lt;{message?.emailOrigin.fromEmail}&gt; */}
{message.msgOrigin?.from} {message.msgOrigin?.from}
</span> </span>
</> : <><b>To: </b>{message.msgOrigin?.to}</>
}
</span> </span>
</> </>
} }

@ -6,6 +6,7 @@ import { groupBy, isEmpty } from '@/utils/commons';
import useConversationStore from '@/stores/ConversationStore'; import useConversationStore from '@/stores/ConversationStore';
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
import { WABIcon } from '@/components/Icons'; import { WABIcon } from '@/components/Icons';
import ChannelLogo from './ChannelLogo';
const BubbleIM = ({ handlePreview, handleContactClick, setNewChatModalVisible, setNewChatFormValues, scrollToMessage, focusMsg, ...message }) => { const BubbleIM = ({ handlePreview, handleContactClick, setNewChatModalVisible, setNewChatFormValues, scrollToMessage, focusMsg, ...message }) => {
const { message: appMessage } = App.useApp(); const { message: appMessage } = App.useApp();
@ -112,9 +113,12 @@ const BubbleIM = ({ handlePreview, handleContactClick, setNewChatModalVisible, s
// styles: { backgroundColor: '#ccd4ae' }, // styles: { backgroundColor: '#ccd4ae' },
notchStyle: { fill: '#ccd4ae' }, // todo: channel[WhatsApp] color '#d9fdd3' notchStyle: { fill: '#ccd4ae' }, // todo: channel[WhatsApp] color '#d9fdd3'
replyButton: ['text', 'document', 'image'].includes(message.whatsapp_msg_type) && message.status !== 'failed' ? true : false, replyButton: ['text', 'document', 'image'].includes(message.whatsapp_msg_type) && message.status !== 'failed' ? true : false,
// title: <><WABIcon/>&nbsp;Global Highlights</>, // test: 0
title: <><ChannelLogo channel={message.msg_source} />&nbsp;Global Highlights</>,
} }
: {})} : {
// notch={false} title: <><ChannelLogo channel={message.msg_source} />{message.title}</>,
})}
className={[ className={[
'whitespace-pre-wrap', 'whitespace-pre-wrap',
message.whatsapp_msg_type === 'sticker' ? 'bg-transparent' : '', message.whatsapp_msg_type === 'sticker' ? 'bg-transparent' : '',

@ -7,7 +7,8 @@ const ChannelLogo = ({channel}) => {
if (Array.isArray(channel)) { if (Array.isArray(channel)) {
channel = channel[channel.length - 1]; channel = channel[channel.length - 1];
} }
switch (channel) { const _channel = channel.toLowerCase();
switch (_channel) {
case 'waba': case 'waba':
return <WABIcon key={channel} className='text-whatsapp' />; return <WABIcon key={channel} className='text-whatsapp' />;
case 'wa': case 'wa':

@ -169,6 +169,9 @@ export default defineConfig({
output: { output: {
entryFileNames: '[name]/build.[hash].js', entryFileNames: '[name]/build.[hash].js',
manualChunks(id) { manualChunks(id) {
if (id.toLowerCase().includes('lexical')) {
return 'lexical';
}
if (id.includes('node_modules')) { if (id.includes('node_modules')) {
return 'vendor'; return 'vendor';
// return id.toString().split('node_modules/')[1].split('/')[0].toString(); // return id.toString().split('node_modules/')[1].split('/')[0].toString();

Loading…
Cancel
Save