This commit is contained in:
超级老白兔
2025-09-02 17:36:53 +08:00
parent 70877c8c96
commit b08086e3f5
5 changed files with 156 additions and 49 deletions

View File

@@ -60,6 +60,13 @@
padding: 10px 0;
}
.noResults {
text-align: center;
color: #999;
padding: 20px;
font-size: 14px;
}
.list {
flex: 1;
overflow-y: auto;

View File

@@ -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}
/>
</>

View File

@@ -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();