1、发起群聊全选✔

This commit is contained in:
超级老白兔
2025-11-27 10:45:13 +08:00
parent 644dd8912d
commit 65da14032b
2 changed files with 175 additions and 6 deletions

View File

@@ -48,6 +48,43 @@
font-weight: 500;
font-size: 14px;
color: #262626;
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
}
.headerActions {
display: flex;
gap: 8px;
:global(.ant-btn-sm) {
padding: 0 8px;
}
}
.actionButton {
color: #fff !important;
border: none !important;
transition: background-color 0.2s ease;
&:hover,
&:focus {
color: #fff;
opacity: 0.9;
}
}
.currentPageButton {
background-color: #1677ff !important;
}
.allSelectButton {
background-color: #13c2c2 !important;
}
.deselectState {
background-color: #ff7875 !important;
}
.listContent {
@@ -57,6 +94,14 @@
min-height: 0;
}
.selectedList {
.listContent {
flex: unset;
height: 600px;
overflow-y: auto;
}
}
.contactItem,
.selectedItem {
display: flex;

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useMemo } from "react";
import React, { useState, useEffect, useMemo, useCallback } from "react";
import {
Modal,
Input,
@@ -32,6 +32,7 @@ const PopChatRoom: React.FC<PopChatRoomProps> = ({ visible, onCancel }) => {
const [showNameModal, setShowNameModal] = useState(false);
const [chatroomName, setChatroomName] = useState("");
const pageSize = 10;
const MAX_SELECT_COUNT = 50; // 最多选择联系人数量
const { sendCommand } = useWebSocketStore();
const currentUserId = useUserStore(state => state.user?.id) || 0;
const currentCustomer = useCustomerStore(state => state.currentCustomer);
@@ -91,12 +92,115 @@ const PopChatRoom: React.FC<PopChatRoomProps> = ({ visible, onCancel }) => {
return filteredContacts.slice(start, end);
}, [filteredContacts, page]);
const isContactSelected = useCallback(
(contactId: number) => {
return selectedContacts.some(contact => contact.id === contactId);
},
[selectedContacts],
);
const addContactsToSelection = (contacts: Contact[]) => {
setSelectedContacts(prev => {
const existingIds = new Set(prev.map(contact => contact.id));
const additions = contacts.filter(
contact => !existingIds.has(contact.id),
);
if (additions.length === 0) return prev;
return [...prev, ...additions];
});
};
const removeContactsFromSelection = (contacts: Contact[]) => {
if (contacts.length === 0) return;
const removalIds = new Set(contacts.map(contact => contact.id));
setSelectedContacts(prev =>
prev.filter(contact => !removalIds.has(contact.id)),
);
};
const isCurrentPageFullySelected = useMemo(() => {
return (
paginatedContacts.length > 0 &&
paginatedContacts.every(contact => isContactSelected(contact.id))
);
}, [isContactSelected, paginatedContacts]);
const isAllContactsFullySelected = useMemo(() => {
return (
filteredContacts.length > 0 &&
filteredContacts.every(contact => isContactSelected(contact.id))
);
}, [filteredContacts, isContactSelected]);
const handleToggleCurrentPageSelection = () => {
if (isCurrentPageFullySelected) {
removeContactsFromSelection(paginatedContacts);
} else {
const currentSelectedCount = selectedContacts.length;
const remainingSlots = MAX_SELECT_COUNT - currentSelectedCount;
if (remainingSlots <= 0) {
message.warning(`最多只能选择${MAX_SELECT_COUNT}个联系人`);
return;
}
// 获取当前页未选中的联系人
const unselectedContacts = paginatedContacts.filter(
contact => !isContactSelected(contact.id),
);
if (unselectedContacts.length > remainingSlots) {
// 只选择前 remainingSlots 个未选中的联系人
const contactsToAdd = unselectedContacts.slice(0, remainingSlots);
addContactsToSelection(contactsToAdd);
message.warning(
`最多只能选择${MAX_SELECT_COUNT}个联系人,已选择前${remainingSlots}`,
);
} else {
addContactsToSelection(unselectedContacts);
}
}
};
const handleToggleAllContactsSelection = () => {
if (isAllContactsFullySelected) {
removeContactsFromSelection(filteredContacts);
} else {
const currentSelectedCount = selectedContacts.length;
const remainingSlots = MAX_SELECT_COUNT - currentSelectedCount;
if (remainingSlots <= 0) {
message.warning(`最多只能选择${MAX_SELECT_COUNT}个联系人`);
return;
}
if (filteredContacts.length > remainingSlots) {
// 只选择前 remainingSlots 个未选中的联系人
const unselectedContacts = filteredContacts.filter(
contact => !isContactSelected(contact.id),
);
const contactsToAdd = unselectedContacts.slice(0, remainingSlots);
addContactsToSelection(contactsToAdd);
message.warning(
`最多只能选择${MAX_SELECT_COUNT}个联系人,已选择前${remainingSlots}`,
);
} else {
addContactsToSelection(filteredContacts);
}
}
};
// 处理联系人选择
const handleContactSelect = (contact: Contact) => {
setSelectedContacts(prev => {
if (isContactSelected(contact.id)) {
return prev.filter(item => item.id !== contact.id);
}
// 检查是否超过50个限制
if (prev.length >= MAX_SELECT_COUNT) {
message.warning(`最多只能选择${MAX_SELECT_COUNT}个联系人`);
return prev;
}
return [...prev, contact];
});
};
@@ -108,11 +212,6 @@ const PopChatRoom: React.FC<PopChatRoomProps> = ({ visible, onCancel }) => {
);
};
// 检查联系人是否已选择
const isContactSelected = (contactId: number) => {
return selectedContacts.some(contact => contact.id === contactId);
};
// 处理取消
const handleCancel = () => {
setSearchValue("");
@@ -219,6 +318,31 @@ const PopChatRoom: React.FC<PopChatRoomProps> = ({ visible, onCancel }) => {
<div className={styles.contactList}>
<div className={styles.listHeader}>
<span> ({filteredContacts.length})</span>
<div className={styles.headerActions}>
<Button
size="small"
className={`${styles.actionButton} ${styles.currentPageButton} ${
isCurrentPageFullySelected ? styles.deselectState : ""
}`}
onClick={handleToggleCurrentPageSelection}
disabled={loading || paginatedContacts.length === 0}
>
{isCurrentPageFullySelected
? "取消全选当前页"
: "全选当前页"}
</Button>
<Button
size="small"
className={`${styles.actionButton} ${styles.allSelectButton} ${
isAllContactsFullySelected ? styles.deselectState : ""
}`}
onClick={handleToggleAllContactsSelection}
disabled={loading || filteredContacts.length === 0}
>
{isAllContactsFullySelected ? "取消全选所有" : "全选所有"}
</Button>
50
</div>
</div>
<div className={styles.listContent}>
{loading ? (