feat
This commit is contained in:
@@ -60,6 +60,13 @@
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.noResults {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
|
||||
@@ -2,7 +2,10 @@ import React, { useState, useCallback, useEffect } from "react";
|
||||
import { List, Avatar, Collapse, Button } from "antd";
|
||||
import type { CollapseProps } from "antd";
|
||||
import styles from "./WechatFriends.module.scss";
|
||||
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
|
||||
import {
|
||||
useCkChatStore,
|
||||
searchContactsAndGroups,
|
||||
} from "@/store/module/ckchat/ckchat";
|
||||
import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
|
||||
|
||||
interface WechatFriendsProps {
|
||||
@@ -17,6 +20,9 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
|
||||
selectedContactId,
|
||||
}) => {
|
||||
const [newContractList, setNewContractList] = useState<any[]>([]);
|
||||
const [searchResults, setSearchResults] = useState<
|
||||
(ContractData | weChatGroup)[]
|
||||
>([]);
|
||||
const getNewContractListFn = useCkChatStore(
|
||||
state => state.getNewContractList,
|
||||
);
|
||||
@@ -26,17 +32,27 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
|
||||
|
||||
// 使用useEffect来处理异步的getNewContractList调用
|
||||
useEffect(() => {
|
||||
const fetchNewContractList = async () => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const result = await getNewContractListFn();
|
||||
setNewContractList(result || []);
|
||||
if (searchKeyword.trim()) {
|
||||
// 有搜索关键词时,获取搜索结果
|
||||
const searchResult = await searchContactsAndGroups();
|
||||
setSearchResults(searchResult || []);
|
||||
setNewContractList([]);
|
||||
} else {
|
||||
// 无搜索关键词时,获取分组列表
|
||||
const result = await getNewContractListFn();
|
||||
setNewContractList(result || []);
|
||||
setSearchResults([]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取联系人分组列表失败:", error);
|
||||
console.error("获取联系人数据失败:", error);
|
||||
setNewContractList([]);
|
||||
setSearchResults([]);
|
||||
}
|
||||
};
|
||||
|
||||
fetchNewContractList();
|
||||
fetchData();
|
||||
}, [getNewContractListFn, kfSelected, countLables, searchKeyword]);
|
||||
|
||||
const [activeKey, setActiveKey] = useState<string[]>([]); // 默认展开第一个分组
|
||||
@@ -50,30 +66,32 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
|
||||
const [page, setPage] = useState<{ [key: string]: number }>({});
|
||||
|
||||
// 渲染联系人项
|
||||
const renderContactItem = (contact: ContractData) => (
|
||||
<List.Item
|
||||
key={contact.id}
|
||||
onClick={() => onContactClick(contact)}
|
||||
className={`${styles.contractItem} ${contact.id === selectedContactId?.id ? styles.selected : ""}`}
|
||||
>
|
||||
<div className={styles.avatarContainer}>
|
||||
<Avatar
|
||||
src={contact.avatar || contact.chatroomAvatar}
|
||||
icon={
|
||||
!(contact.avatar || contact.chatroomAvatar) && (
|
||||
<span>{contact.nickname.charAt(0)}</span>
|
||||
)
|
||||
}
|
||||
className={styles.avatar}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.contractInfo}>
|
||||
<div className={styles.name}>
|
||||
{contact.conRemark || contact.nickname}
|
||||
const renderContactItem = (contact: ContractData | weChatGroup) => {
|
||||
// 判断是否为群组
|
||||
const isGroup = "chatroomId" in contact;
|
||||
const avatar = contact.avatar || contact.chatroomAvatar;
|
||||
const name = contact.conRemark || contact.nickname;
|
||||
|
||||
return (
|
||||
<List.Item
|
||||
key={contact.id}
|
||||
onClick={() => onContactClick(contact)}
|
||||
className={`${styles.contractItem} ${contact.id === selectedContactId?.id ? styles.selected : ""}`}
|
||||
>
|
||||
<div className={styles.avatarContainer}>
|
||||
<Avatar
|
||||
src={avatar}
|
||||
icon={!avatar && <span>{contact.nickname.charAt(0)}</span>}
|
||||
className={styles.avatar}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</List.Item>
|
||||
);
|
||||
<div className={styles.contractInfo}>
|
||||
<div className={styles.name}>{name}</div>
|
||||
{isGroup && <div className={styles.groupInfo}>群聊</div>}
|
||||
</div>
|
||||
</List.Item>
|
||||
);
|
||||
};
|
||||
|
||||
// 初始化分页数据
|
||||
useEffect(() => {
|
||||
@@ -188,7 +206,21 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
|
||||
|
||||
return (
|
||||
<div className={styles.contractListSimple}>
|
||||
{newContractList && newContractList.length > 0 ? (
|
||||
{searchKeyword.trim() ? (
|
||||
// 搜索模式:直接显示搜索结果列表
|
||||
<>
|
||||
<div className={styles.header}>搜索结果</div>
|
||||
<List
|
||||
className={styles.list}
|
||||
dataSource={searchResults}
|
||||
renderItem={renderContactItem}
|
||||
/>
|
||||
{searchResults.length === 0 && (
|
||||
<div className={styles.noResults}>未找到匹配的联系人</div>
|
||||
)}
|
||||
</>
|
||||
) : newContractList && newContractList.length > 0 ? (
|
||||
// 正常模式:显示分组
|
||||
<Collapse
|
||||
className={styles.groupCollapse}
|
||||
activeKey={activeKey}
|
||||
@@ -196,11 +228,12 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
|
||||
items={getCollapseItems()}
|
||||
/>
|
||||
) : (
|
||||
// 备用模式:显示传入的联系人列表
|
||||
<>
|
||||
<div className={styles.header}>全部好友</div>
|
||||
<div className={styles.header}>全部联系人</div>
|
||||
<List
|
||||
className={styles.list}
|
||||
dataSource={contracts as ContractData[]}
|
||||
dataSource={contracts}
|
||||
renderItem={renderContactItem}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -131,6 +131,71 @@ export const useCkChatStore = createPersistStore<CkChatState>(
|
||||
return cachedResult;
|
||||
};
|
||||
})(),
|
||||
// 搜索好友和群组的新方法 - 从本地数据库查询并返回扁平化的搜索结果
|
||||
searchContactsAndGroups: (() => {
|
||||
let cachedResult: (ContractData | weChatGroup)[] = [];
|
||||
let lastKfSelected: number | null = null;
|
||||
let lastSearchKeyword: string = "";
|
||||
|
||||
return async () => {
|
||||
const state = useCkChatStore.getState();
|
||||
|
||||
// 检查是否需要重新计算缓存
|
||||
const shouldRecalculate =
|
||||
lastKfSelected !== state.kfSelected ||
|
||||
lastSearchKeyword !== state.searchKeyword;
|
||||
|
||||
if (shouldRecalculate) {
|
||||
if (state.searchKeyword.trim()) {
|
||||
const keyword = state.searchKeyword.toLowerCase();
|
||||
|
||||
// 从本地数据库查询联系人数据
|
||||
let allContacts: ContractData[] = await contractService.findAll();
|
||||
|
||||
// 根据选中的客服筛选联系人
|
||||
if (state.kfSelected !== 0) {
|
||||
allContacts = allContacts.filter(
|
||||
item => item.wechatAccountId === state.kfSelected,
|
||||
);
|
||||
}
|
||||
|
||||
// 从本地数据库查询群组数据
|
||||
let allGroups: weChatGroup[] = await weChatGroupService.findAll();
|
||||
|
||||
// 根据选中的客服筛选群组
|
||||
if (state.kfSelected !== 0) {
|
||||
allGroups = allGroups.filter(
|
||||
item => item.wechatAccountId === state.kfSelected,
|
||||
);
|
||||
}
|
||||
|
||||
// 搜索匹配的联系人
|
||||
const matchedContacts = allContacts.filter(item => {
|
||||
const nickname = (item.nickname || "").toLowerCase();
|
||||
const conRemark = (item.conRemark || "").toLowerCase();
|
||||
return nickname.includes(keyword) || conRemark.includes(keyword);
|
||||
});
|
||||
|
||||
// 搜索匹配的群组
|
||||
const matchedGroups = allGroups.filter(item => {
|
||||
const nickname = (item.nickname || "").toLowerCase();
|
||||
const conRemark = (item.conRemark || "").toLowerCase();
|
||||
return nickname.includes(keyword) || conRemark.includes(keyword);
|
||||
});
|
||||
|
||||
// 合并搜索结果
|
||||
cachedResult = [...matchedContacts, ...matchedGroups];
|
||||
} else {
|
||||
cachedResult = [];
|
||||
}
|
||||
|
||||
lastKfSelected = state.kfSelected;
|
||||
lastSearchKeyword = state.searchKeyword;
|
||||
}
|
||||
|
||||
return cachedResult;
|
||||
};
|
||||
})(),
|
||||
// 异步设置联系人分组列表
|
||||
asyncNewContractList: async (data: any[]) => {
|
||||
set({ newContractList: data });
|
||||
@@ -472,4 +537,6 @@ export const setSearchKeyword = (keyword: string) =>
|
||||
useCkChatStore.getState().setSearchKeyword(keyword);
|
||||
export const clearSearchKeyword = () =>
|
||||
useCkChatStore.getState().clearSearchKeyword();
|
||||
export const searchContactsAndGroups = () =>
|
||||
useCkChatStore.getState().searchContactsAndGroups();
|
||||
useCkChatStore.getState().getKfSelectedUser();
|
||||
|
||||
Reference in New Issue
Block a user