feat(前端): 设为静音

dev/supplier-email-drawer
Lei OT 9 months ago
parent dd8adbf207
commit d39d5f4da0

@ -1,6 +1,6 @@
import { create } from 'zustand';
import { RealTimeAPI } from '@/channel/realTimeAPI';
import { olog, isEmpty, groupBy, sortArrayByOrder, logWebsocket, pick } from '@/utils/commons';
import { olog, isEmpty, groupBy, sortArrayByOrder, logWebsocket, pick, sortKeys, omit, sortObjectsByKeysMap } from '@/utils/commons';
import { receivedMsgTypeMapped, handleNotification } from '@/channel/bubbleMsgUtils';
import { fetchConversationsList, fetchTemplates, fetchConversationsSearch, UNREAD_MARK, fetchTags } from '@/actions/ConversationActions';
import { devtools } from 'zustand/middleware';
@ -12,6 +12,16 @@ const replaceObjectsByKey = (arr1, arr2, key) => {
return arr1.map(item => map.has(item[key]) ? map.get(item[key]) : item);
}
const sortConversationList = (list) => {
const mergedListMapped = groupBy(list, 'top_state');
const topValOrder = Object.keys(mergedListMapped).filter(ss => ss !== '1').sort((a, b) => b - a);
const pagelist = topValOrder.reduce((r, topVal) => r.concat(mergedListMapped[String(topVal)]), []);
return {
topList: mergedListMapped['1'] || [],
pageList: pagelist,
}
};
// const WS_URL = 'ws://202.103.68.144:8888/whatever/';
// const WS_URL = 'ws://120.79.9.217:10022/whatever/';
const conversationRow = {
@ -259,12 +269,12 @@ const conversationSlice = (set, get) => ({
const _len = hasCurrent ? 0 : conversationsList.unshift(currentConversation);
}
const conversationsTopStateMapped = groupBy(conversationsList, 'top_state');
const { topList, pageList } = sortConversationList(conversationsList);
return set({
topList: conversationsTopStateMapped[1] || [],
topList,
// conversationsList: conversationsTopStateMapped[0],
pageList: conversationsTopStateMapped[0] || [],
pageList,
conversationsList,
activeConversations: { ...conversationsMapped, ...activeConversations }
})
@ -296,11 +306,11 @@ const conversationSlice = (set, get) => ({
}
const refreshTotalNotify = mergedList.reduce((r, c) => r+(c.unread_msg_count === UNREAD_MARK ? 0 : c.unread_msg_count), 0);
const mergedListMapped = groupBy(mergedList, 'top_state');
const { topList, pageList } = sortConversationList(mergedList)
return set((state) => ({
topList: mergedListMapped[1] || [],
pageList: mergedListMapped[0] || [],
topList,
pageList,
conversationsList: mergedList,
activeConversations: mergedListMsgs,
totalNotify: refreshTotalNotify,
@ -312,11 +322,11 @@ const conversationSlice = (set, get) => ({
const targetId = conversation.sn;
const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId));
conversationsList.splice(targetIndex, 1);
const mergedListMapped = groupBy(conversationsList, 'top_state');
const { topList, pageList } = sortConversationList(conversationsList)
return set({
topList: mergedListMapped['1'] || [],
pageList: mergedListMapped['0'] || [],
topList,
pageList,
conversationsList: [...conversationsList],
activeConversations: { ...activeConversations, [`${targetId}`]: [] },
currentConversation: {},
@ -361,11 +371,11 @@ const conversationSlice = (set, get) => ({
...conversation,
})
: null;
const mergedListMapped = groupBy(conversationsList, 'top_state');
const { topList, pageList } = sortConversationList(conversationsList)
return set({
topList: mergedListMapped['1'] || [],
pageList: mergedListMapped['0'] || [],
topList,
pageList,
conversationsList: [...conversationsList]
});
},
@ -447,12 +457,12 @@ const messageSlice = (set, get) => ({
}];
}
const mergedList = [...newConversations, ...conversationsList]
const mergedListMapped = groupBy(mergedList, 'top_state');
setFilter({ loadNextPage: true });
const { topList, pageList } = sortConversationList(mergedList);
return set({
topList: mergedListMapped['1'] || [],
pageList: mergedListMapped['0'] || [],
topList,
pageList,
conversationsList: mergedList,
activeConversations: { ...activeConversations, [String(targetId)]: targetMsgs },
});
@ -503,7 +513,6 @@ const messageSlice = (set, get) => ({
// console.log('find in list, i:', targetIndex);
// 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));
const mergedListMapped = groupBy(conversationsList, 'top_state');
setFilter({ loadNextPage: true });
const isCurrent = Number(targetId) === Number(currentConversation.sn);
@ -515,10 +524,12 @@ const messageSlice = (set, get) => ({
last_message: message,
}
: {...currentConversation, last_message: message,};
const { topList, pageList } = sortConversationList(conversationsList);
return set({
currentConversation: updatedCurrent,
topList: mergedListMapped['1'] || [],
pageList: mergedListMapped['0'] || [],
topList,
pageList,
conversationsList: [...conversationsList],
totalNotify: totalNotify + (message.sender === 'me' ? 0 : 1),
activeConversations: { ...activeConversations, [String(targetId)]: [...targetMsgs, message] },

@ -119,6 +119,26 @@ export const sortKeys = (obj) =>
.sort()
.reduce((a, k2) => ({ ...a, [k2]: obj[k2] }), {});
export function sortObjectsByKeysMap(objects, keyOrder) {
if (!objects) return {} // Handle null/undefined input
if (!keyOrder || keyOrder.length === 0) return objects
const objectMap = new Map(Object.entries(objects))
const sortedMap = new Map()
for (const key of keyOrder) {
if (objectMap.has(key)) {
sortedMap.set(key, objectMap.get(key))
objectMap.delete(key) // Optimization: Remove from original map after adding
}
}
// Add remaining keys
for (const [key, value] of objectMap) {
sortedMap.set(key, value)
}
return Object.fromEntries(sortedMap)
}
/**
* 数组排序, 给定排序数组
* @param {array} items 需要排序的数组

@ -34,9 +34,9 @@ const ChatWindow = () => {
collapsible={true}
breakpoint='xl'
collapsedWidth={73}
collapsed={collapsedLeft}
collapsed={false}
onBreakpoint={(broken) => {
setCollapsedLeft(broken)
// setCollapsedLeft(broken)
setCollapsedRight(broken)
}}
trigger={null}>

@ -1,6 +1,6 @@
import React, { useEffect, useState, useRef } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Dropdown, Input, Button, Tag, Popover, Form, Tooltip } from 'antd';
import { Dropdown, Input, Button, Tag, Popover, Form, Tooltip, Spin } from 'antd';
import { CloseCircleOutlined, MinusCircleOutlined } from '@ant-design/icons';
import { fetchConversationItemClose, fetchConversationsSearch, fetchConversationItemUnread, fetchConversationItemTop, postConversationTags, deleteConversationTags } from '@/actions/ConversationActions';
import { ChatItem } from 'react-chat-elements';
@ -75,6 +75,8 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
const setClosedConversationList = useConversationStore((state) => state.setClosedConversationList);
const [currentHandleChat, setCurrentHandleChat] = useState({});
const itemTagsKeys = (item.tags || []).map(t => t.key);
const [tags, addTag] = useConversationStore(state => [state.tags, state.addTag]);
const handleConversationItemClose = async (item) => {
@ -85,18 +87,28 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
}
const _clist = await fetchConversationsSearch({ opisn: userId, session_enable: 0 });
setClosedConversationList(_clist);
setCurrentHandleChat({});
};
const handleConversationItemUnread = async (item) => {
await fetchConversationItemUnread({ conversationid: item.sn });
await refreshConversationList(item.lasttime);
setListUpdateFlag(Math.random());
setCurrentHandleChat({});
}
const handleConversationItemTop = async (item) => {
await fetchConversationItemTop({ conversationid: item.sn, top_state: item.top_state === 0 ? 1 : 0 });
await refreshConversationList(item.lasttime);
setListUpdateFlag(Math.random());
setCurrentHandleChat({});
}
const handleConversationItemMuted = async (item) => {
await fetchConversationItemTop({ conversationid: item.sn, top_state: item.top_state === -1 ? 0 : -1 });
await refreshConversationList(item.lasttime);
setListUpdateFlag(Math.random());
setCurrentHandleChat({});
}
const handleConversationItemTags = async (item, tagKey, tagLabel) => {
@ -117,12 +129,16 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
await refreshConversationList(item.lasttime);
setListUpdateFlag(Math.random());
setContextMenuOpen(false);
setCurrentHandleChat({});
}
const [contextMenuOpen, setContextMenuOpen] = useState(false);
const handleContextMenuOpenChange = (nextOpen, info) => {
const handleContextMenuOpenChange = (nextOpen, info, item) => {
if (info.source === 'trigger' || nextOpen) {
setContextMenuOpen(nextOpen);
setCurrentHandleChat(nextOpen ? item : {})
} else {
// setCurrentHandleChat({});
}
};
@ -152,11 +168,12 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
trigger={['contextMenu']}
overlayClassName='z-[998]'
open={contextMenuOpen}
onOpenChange={handleContextMenuOpenChange}
onOpenChange={(nextOpen, info) => handleContextMenuOpenChange(nextOpen, info, item)}
menu={{
items: [
item.top_state === 1 ? { label: '取消置顶', key: 'top' } : { label: '置顶会话', key: 'top' },
{ label: '标记为未读', key: 'unread' },
item.top_state === -1 ? { label: '取消静音', key: 'mute' } : { label: '设为静音', key: 'mute' },
{
label: '设置标签',
key: 'tags',
@ -214,14 +231,17 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
}
switch (key) {
case 'top':
setContextMenuOpen(false)
return handleConversationItemTop(item)
setContextMenuOpen(false);
return handleConversationItemTop(item);
case 'mute':
setContextMenuOpen(false);
return handleConversationItemMuted(item);
case 'unread':
setContextMenuOpen(false)
return handleConversationItemUnread(item)
setContextMenuOpen(false);
return handleConversationItemUnread(item);
case 'close':
setContextMenuOpen(false)
return handleConversationItemClose(item)
setContextMenuOpen(false);
return handleConversationItemClose(item);
case 'edit0':
setOpenTags([])
setEditingChat({ ...item, is_new: false })
@ -245,11 +265,14 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
: item.top_state === 1
? 'bg-stone-100'
: '',
'hover:bg-slate-100',
(item.sn) === (currentHandleChat?.sn) ? ' bg-slate-100 text-slate-500' : '',
// String(item.sn) === String(tabSelectedConversation?.sn) ? ' bg-neutral-200' : '',
].join(' ')}>
{/* <div className='pl-4 pt-1 text-xs text-right'>
{tags.map((tag) => <Tag color={tag.color} key={tag.value}>{tag.label}</Tag>)}
</div> */}
<Spin spinning={(item.sn) === (currentHandleChat?.sn) && props.conversationsListLoading} size='small'>
<ChatItem
{...item}
key={item.sn}
@ -289,8 +312,8 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
date={item.lasttime || item.last_received_time || item.last_send_time}
dateString='' // : , , dataString
unread={item.unread_msg_count > 99 ? 0 : item.unread_msg_count}
// muted={item.unread_msg_count>0}
// showMute={item.unread_msg_count>0}
muted={item.top_state === -1}
showMute={item.top_state === -1}
// className={[
// String(item.sn) === String(currentConversation.sn) ? '__active text-primary bg-whatsapp-bg' : '',
// String(item.sn) === String(tabSelectedConversation?.sn) ? ' bg-neutral-200' : '',
@ -313,6 +336,7 @@ const ChatListItem = (({item, refreshConversationList,setListUpdateFlag,onSwitch
// () => <span key={'tag'} className='self-end>💎💴👑💼🤝💤💔💨🕳🚫🎈🎊🎁📜</span>,
]}
/>
</Spin>
</div>
</Dropdown>
</>

@ -358,6 +358,7 @@ const Conversations = () => {
onSwitchConversation,
setNewChatModalVisible,
setEditingChat,
conversationsListLoading,
}}
/>
)}

Loading…
Cancel
Save