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

@@ -1,18 +1,14 @@
{ {
"_charts-DKSCc2_C.js": { "_charts-Cbn6yFil.js": {
"file": "assets/charts-DKSCc2_C.js", "file": "assets/charts-Cbn6yFil.js",
"name": "charts", "name": "charts",
"imports": [ "imports": [
"_ui-DhAz00L0.js", "_ui-Cytu8vuP.js",
"_vendor-2vc8h_ct.js" "_vendor-2vc8h_ct.js"
] ]
}, },
"_ui-D0C0OGrH.css": { "_ui-Cytu8vuP.js": {
"file": "assets/ui-D0C0OGrH.css", "file": "assets/ui-Cytu8vuP.js",
"src": "_ui-D0C0OGrH.css"
},
"_ui-DhAz00L0.js": {
"file": "assets/ui-DhAz00L0.js",
"name": "ui", "name": "ui",
"imports": [ "imports": [
"_vendor-2vc8h_ct.js" "_vendor-2vc8h_ct.js"
@@ -21,6 +17,10 @@
"assets/ui-D0C0OGrH.css" "assets/ui-D0C0OGrH.css"
] ]
}, },
"_ui-D0C0OGrH.css": {
"file": "assets/ui-D0C0OGrH.css",
"src": "_ui-D0C0OGrH.css"
},
"_utils-6WF66_dS.js": { "_utils-6WF66_dS.js": {
"file": "assets/utils-6WF66_dS.js", "file": "assets/utils-6WF66_dS.js",
"name": "utils", "name": "utils",
@@ -33,18 +33,18 @@
"name": "vendor" "name": "vendor"
}, },
"index.html": { "index.html": {
"file": "assets/index-BdCPAYQ7.js", "file": "assets/index-QManA_e5.js",
"name": "index", "name": "index",
"src": "index.html", "src": "index.html",
"isEntry": true, "isEntry": true,
"imports": [ "imports": [
"_vendor-2vc8h_ct.js", "_vendor-2vc8h_ct.js",
"_utils-6WF66_dS.js", "_utils-6WF66_dS.js",
"_ui-DhAz00L0.js", "_ui-Cytu8vuP.js",
"_charts-DKSCc2_C.js" "_charts-Cbn6yFil.js"
], ],
"css": [ "css": [
"assets/index-ChiFk16x.css" "assets/index-BkBrwKGe.css"
] ]
} }
} }

View File

@@ -11,13 +11,13 @@
</style> </style>
<!-- 引入 uni-app web-view SDK必须 --> <!-- 引入 uni-app web-view SDK必须 -->
<script type="text/javascript" src="/websdk.js"></script> <script type="text/javascript" src="/websdk.js"></script>
<script type="module" crossorigin src="/assets/index-BdCPAYQ7.js"></script> <script type="module" crossorigin src="/assets/index-QManA_e5.js"></script>
<link rel="modulepreload" crossorigin href="/assets/vendor-2vc8h_ct.js"> <link rel="modulepreload" crossorigin href="/assets/vendor-2vc8h_ct.js">
<link rel="modulepreload" crossorigin href="/assets/utils-6WF66_dS.js"> <link rel="modulepreload" crossorigin href="/assets/utils-6WF66_dS.js">
<link rel="modulepreload" crossorigin href="/assets/ui-DhAz00L0.js"> <link rel="modulepreload" crossorigin href="/assets/ui-Cytu8vuP.js">
<link rel="modulepreload" crossorigin href="/assets/charts-DKSCc2_C.js"> <link rel="modulepreload" crossorigin href="/assets/charts-Cbn6yFil.js">
<link rel="stylesheet" crossorigin href="/assets/ui-D0C0OGrH.css"> <link rel="stylesheet" crossorigin href="/assets/ui-D0C0OGrH.css">
<link rel="stylesheet" crossorigin href="/assets/index-ChiFk16x.css"> <link rel="stylesheet" crossorigin href="/assets/index-BkBrwKGe.css">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View File

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

View File

@@ -2,7 +2,10 @@ import React, { useState, useCallback, useEffect } from "react";
import { List, Avatar, Collapse, Button } from "antd"; import { List, Avatar, Collapse, Button } from "antd";
import type { CollapseProps } from "antd"; import type { CollapseProps } from "antd";
import styles from "./WechatFriends.module.scss"; 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"; import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
interface WechatFriendsProps { interface WechatFriendsProps {
@@ -17,6 +20,9 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
selectedContactId, selectedContactId,
}) => { }) => {
const [newContractList, setNewContractList] = useState<any[]>([]); const [newContractList, setNewContractList] = useState<any[]>([]);
const [searchResults, setSearchResults] = useState<
(ContractData | weChatGroup)[]
>([]);
const getNewContractListFn = useCkChatStore( const getNewContractListFn = useCkChatStore(
state => state.getNewContractList, state => state.getNewContractList,
); );
@@ -26,17 +32,27 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
// 使用useEffect来处理异步的getNewContractList调用 // 使用useEffect来处理异步的getNewContractList调用
useEffect(() => { useEffect(() => {
const fetchNewContractList = async () => { const fetchData = async () => {
try { try {
const result = await getNewContractListFn(); if (searchKeyword.trim()) {
setNewContractList(result || []); // 有搜索关键词时,获取搜索结果
const searchResult = await searchContactsAndGroups();
setSearchResults(searchResult || []);
setNewContractList([]);
} else {
// 无搜索关键词时,获取分组列表
const result = await getNewContractListFn();
setNewContractList(result || []);
setSearchResults([]);
}
} catch (error) { } catch (error) {
console.error("获取联系人分组列表失败:", error); console.error("获取联系人数据失败:", error);
setNewContractList([]); setNewContractList([]);
setSearchResults([]);
} }
}; };
fetchNewContractList(); fetchData();
}, [getNewContractListFn, kfSelected, countLables, searchKeyword]); }, [getNewContractListFn, kfSelected, countLables, searchKeyword]);
const [activeKey, setActiveKey] = useState<string[]>([]); // 默认展开第一个分组 const [activeKey, setActiveKey] = useState<string[]>([]); // 默认展开第一个分组
@@ -50,30 +66,32 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
const [page, setPage] = useState<{ [key: string]: number }>({}); const [page, setPage] = useState<{ [key: string]: number }>({});
// 渲染联系人项 // 渲染联系人项
const renderContactItem = (contact: ContractData) => ( const renderContactItem = (contact: ContractData | weChatGroup) => {
<List.Item // 判断是否为群组
key={contact.id} const isGroup = "chatroomId" in contact;
onClick={() => onContactClick(contact)} const avatar = contact.avatar || contact.chatroomAvatar;
className={`${styles.contractItem} ${contact.id === selectedContactId?.id ? styles.selected : ""}`} const name = contact.conRemark || contact.nickname;
>
<div className={styles.avatarContainer}> return (
<Avatar <List.Item
src={contact.avatar || contact.chatroomAvatar} key={contact.id}
icon={ onClick={() => onContactClick(contact)}
!(contact.avatar || contact.chatroomAvatar) && ( className={`${styles.contractItem} ${contact.id === selectedContactId?.id ? styles.selected : ""}`}
<span>{contact.nickname.charAt(0)}</span> >
) <div className={styles.avatarContainer}>
} <Avatar
className={styles.avatar} src={avatar}
/> icon={!avatar && <span>{contact.nickname.charAt(0)}</span>}
</div> className={styles.avatar}
<div className={styles.contractInfo}> />
<div className={styles.name}>
{contact.conRemark || contact.nickname}
</div> </div>
</div> <div className={styles.contractInfo}>
</List.Item> <div className={styles.name}>{name}</div>
); {isGroup && <div className={styles.groupInfo}></div>}
</div>
</List.Item>
);
};
// 初始化分页数据 // 初始化分页数据
useEffect(() => { useEffect(() => {
@@ -188,7 +206,21 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
return ( return (
<div className={styles.contractListSimple}> <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 <Collapse
className={styles.groupCollapse} className={styles.groupCollapse}
activeKey={activeKey} activeKey={activeKey}
@@ -196,11 +228,12 @@ const ContactListSimple: React.FC<WechatFriendsProps> = ({
items={getCollapseItems()} items={getCollapseItems()}
/> />
) : ( ) : (
// 备用模式:显示传入的联系人列表
<> <>
<div className={styles.header}></div> <div className={styles.header}></div>
<List <List
className={styles.list} className={styles.list}
dataSource={contracts as ContractData[]} dataSource={contracts}
renderItem={renderContactItem} renderItem={renderContactItem}
/> />
</> </>

View File

@@ -131,6 +131,71 @@ export const useCkChatStore = createPersistStore<CkChatState>(
return cachedResult; 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[]) => { asyncNewContractList: async (data: any[]) => {
set({ newContractList: data }); set({ newContractList: data });
@@ -472,4 +537,6 @@ export const setSearchKeyword = (keyword: string) =>
useCkChatStore.getState().setSearchKeyword(keyword); useCkChatStore.getState().setSearchKeyword(keyword);
export const clearSearchKeyword = () => export const clearSearchKeyword = () =>
useCkChatStore.getState().clearSearchKeyword(); useCkChatStore.getState().clearSearchKeyword();
export const searchContactsAndGroups = () =>
useCkChatStore.getState().searchContactsAndGroups();
useCkChatStore.getState().getKfSelectedUser(); useCkChatStore.getState().getKfSelectedUser();