From 5acdd13966a00a1befb16144f8b9ccbac7e464d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E7=BA=A7=E8=80=81=E7=99=BD=E5=85=94?= Date: Thu, 25 Sep 2025 15:39:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AE=A2=E6=88=B6=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E9=A0=81=E9=9D=A2=E5=84=AA=E5=8C=96):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=AE=A2=E6=88=B6=E7=AE=A1=E7=90=86=E9=A0=81=E9=9D=A2=EF=BC=8C?= =?UTF-8?q?=E8=AA=BF=E6=95=B4=E8=81=AF=E7=B5=A1=E4=BA=BA=E5=8D=A1=E7=89=87?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E5=B0=8F=E9=AB=98=E5=BA=A6=EF=BC=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E6=A8=A3=E5=BC=8F?= =?UTF-8?q?=EF=BC=8C=E4=B8=A6=E6=95=B4=E5=90=88=E8=81=AF=E7=B5=A1=E4=BA=BA?= =?UTF-8?q?=E6=95=B8=E6=93=9A=E5=8A=A0=E8=BC=89=E9=82=8F=E8=BC=AF=EF=BC=8C?= =?UTF-8?q?=E6=8F=90=E5=8D=87=E9=A0=81=E9=9D=A2=E6=80=A7=E8=83=BD=E8=88=87?= =?UTF-8?q?=E7=94=A8=E6=88=B6=E9=AB=94=E9=A9=97=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../customer-management/index.module.scss | 4 +- .../powerCenter/customer-management/index.tsx | 432 +++++++++++------- Touchkebao/src/styles/global.scss | 8 + 3 files changed, 275 insertions(+), 169 deletions(-) diff --git a/Touchkebao/src/pages/pc/ckbox/powerCenter/customer-management/index.module.scss b/Touchkebao/src/pages/pc/ckbox/powerCenter/customer-management/index.module.scss index a290c73b..2eb4278c 100644 --- a/Touchkebao/src/pages/pc/ckbox/powerCenter/customer-management/index.module.scss +++ b/Touchkebao/src/pages/pc/ckbox/powerCenter/customer-management/index.module.scss @@ -116,7 +116,6 @@ .tabs { display: flex; gap: 0; - margin-bottom: 24px; border-bottom: 1px solid #f0f0f0; .tab { @@ -155,7 +154,6 @@ padding: 20px; transition: all 0.3s; height: 100%; - min-height: 380px; display: flex; flex-direction: column; @@ -320,7 +318,7 @@ } .contactCard { - min-height: 350px; + min-height: 175px; } .header { diff --git a/Touchkebao/src/pages/pc/ckbox/powerCenter/customer-management/index.tsx b/Touchkebao/src/pages/pc/ckbox/powerCenter/customer-management/index.tsx index 733332b3..53914ab0 100644 --- a/Touchkebao/src/pages/pc/ckbox/powerCenter/customer-management/index.tsx +++ b/Touchkebao/src/pages/pc/ckbox/powerCenter/customer-management/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useMemo } from "react"; +import React, { useState, useEffect } from "react"; import PowerNavigation from "@/components/PowerNavtion"; import { SearchOutlined, @@ -7,11 +7,10 @@ import { PhoneOutlined, } from "@ant-design/icons"; import styles from "./index.module.scss"; -import { Button, Input, Row, Col } from "antd"; -import { useCkChatStore } from "@/store/module/ckchat/ckchat"; +import { Button, Input, Row, Col, Pagination, Spin, message } from "antd"; +import { getContactList } from "@/pages/pc/ckbox/weChat/api"; import { ContractData } from "@/pages/pc/ckbox/data"; -// 直接使用 ContractData 类型 - +import Layout from "@/components/Layout/LayoutFiexd"; // 头像组件 const Avatar: React.FC<{ name: string; avatar?: string; size?: number }> = ({ name, @@ -64,187 +63,288 @@ const Avatar: React.FC<{ name: string; avatar?: string; size?: number }> = ({ }; const CustomerManagement: React.FC = () => { - const [activeTab, setActiveTab] = useState("customer"); + const [activeTab, setActiveTab] = useState("all"); const [searchValue, setSearchValue] = useState(""); + const [contacts, setContacts] = useState([]); + const [loading, setLoading] = useState(false); + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 12, + total: 0, + }); - // 获取联系人数据 - const getContractList = useCkChatStore(state => state.getContractList); - const contacts: ContractData[] = getContractList(); - console.log(contacts, "contacts"); - - // 动态计算各分类的联系人数量 - const tabCounts = useMemo(() => { - return { - customer: contacts.filter(c => c.isPassed).length, - potential: contacts.filter(c => !c.isPassed).length, - partner: 0, // 可以根据业务逻辑调整 - friend: 0, // 可以根据业务逻辑调整 - }; - }, [contacts]); + // 获取各分类的总数 + const [tabCounts, setTabCounts] = useState({ + all: 0, + customer: 0, + potential: 0, + partner: 0, + friend: 0, + }); const tabs = [ + { key: "all", label: "全部", count: tabCounts.all }, { key: "customer", label: "客户", count: tabCounts.customer }, { key: "potential", label: "潜在客户", count: tabCounts.potential }, { key: "partner", label: "合作伙伴", count: tabCounts.partner }, { key: "friend", label: "朋友", count: tabCounts.friend }, ]; - // const filteredContacts = contacts.filter(contact => { - // const isCategoryMatch = - // (activeTab === "customer" && contact.isPassed) || - // (activeTab === "potential" && !contact.isPassed) || - // activeTab === "partner" || - // activeTab === "friend"; + // 加载联系人数据 + const loadContacts = async (page: number = 1, pageSize: number = 12) => { + try { + setLoading(true); - // const isSearchMatch = - // searchValue === "" || - // contact.nickname?.includes(searchValue) || - // contact.conRemark?.includes(searchValue) || - // contact.alias?.includes(searchValue) || - // contact.desc?.includes(searchValue) || - // contact.labels?.some(tag => tag.includes(searchValue)); + // 构建请求参数 + const params: any = { + page, + limit: pageSize, + }; + + // 添加搜索条件 + if (searchValue.trim()) { + params.keyword = searchValue; + } + + // 添加分类筛选 + if (activeTab === "customer") { + params.isPassed = true; + } else if (activeTab === "potential") { + params.isPassed = false; + } + // "全部"、"partner" 和 "friend" 不添加额外筛选条件 + + const response = await getContactList(params); + + // 假设接口返回格式为 { data: Contact[], total: number, page: number, limit: number } + setContacts(response.data || response.list || []); + setPagination(prev => ({ + ...prev, + current: response.page || page, + pageSize: response.limit || pageSize, + total: response.total || 0, + })); + + // 更新分类统计 + if (page === 1) { + // 只在第一页时更新统计,避免重复请求 + const allResponse = await getContactList({ page: 1, limit: 1 }); + const customerResponse = await getContactList({ + page: 1, + limit: 1, + isPassed: true, + }); + const potentialResponse = await getContactList({ + page: 1, + limit: 1, + isPassed: false, + }); + + setTabCounts({ + all: allResponse.total || 0, + customer: customerResponse.total || 0, + potential: potentialResponse.total || 0, + partner: 0, // 可以根据业务逻辑调整 + friend: 0, // 可以根据业务逻辑调整 + }); + } + } catch (error) { + console.error("加载联系人数据失败:", error); + message.error("加载联系人数据失败,请稍后重试"); + } finally { + setLoading(false); + } + }; + + // 当分类或搜索条件改变时重新加载数据 + useEffect(() => { + loadContacts(1, pagination.pageSize); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [activeTab, searchValue, pagination.pageSize]); - // return isCategoryMatch && isSearchMatch; - // }); const filteredContacts = contacts; return ( -
- 添加好友} - /> - -
- {/* 搜索和筛选 */} -
- setSearchValue(e.target.value)} - prefix={} - allowClear - size="large" - /> - -
- {/* 标签页 */} -
- {tabs.map(tab => ( - - ))} -
- - {/* 联系人卡片列表 */} -
- {filteredContacts.length === 0 ? ( -
-

暂无联系人数据

+ +
+ 添加好友} + /> + {/* 搜索和筛选 */} +
+ setSearchValue(e.target.value)} + prefix={} + allowClear + size="large" + /> +
- ) : ( - - {filteredContacts.map(contact => ( - -
-
-
- -
-

- {contact.conRemark || - contact.nickname || - contact.alias || - "未知用户"} -

-

- 客户 {"·"} {contact.desc || "未设置公司"} -

+ {/* 标签页 */} +
+ {tabs.map(tab => ( + + ))} +
+
+ + } + footer={ +
+ + `第 ${range[0]}-${range[1]} 条,共 ${total} 条` + } + onChange={(page, pageSize) => { + loadContacts(page, pageSize || pagination.pageSize); + }} + onShowSizeChange={(current, size) => { + loadContacts(1, size); + }} + pageSizeOptions={["6", "12", "24", "48"]} + /> +
+ } + > +
+
+ {/* 联系人卡片列表 */} +
+ {loading ? ( +
+ +

+ 正在加载联系人数据... +

+
+ ) : filteredContacts.length === 0 ? ( +
+

暂无联系人数据

+
+ ) : ( + <> + + {filteredContacts.map(contact => ( + +
+
+
+ +
+

+ {contact.conRemark || + contact.nickname || + contact.alias || + "未知用户"} +

+

+ 客户 {"·"} {contact.desc || "未设置公司"} +

+
+
+
+ +
+
+

+ 电话:{" "} + {contact.phone || "未设置电话"} +

+

+ 地区:{" "} + {contact.region || contact.city || "未设置地区"} +

+

+ 微信ID:{" "} + {contact.wechatId} +

+
+
+ +
+
+ {contact?.labels?.map( + (tag: string, index: number) => ( + + {tag} + + ), + )} +
+ 微信好友 +
+ +
+ 最后联系:{" "} + {contact.lastMessageTime + ? new Date( + contact.lastMessageTime, + ).toLocaleDateString() + : "未联系"} +
+ + {contact.signature && ( +
+ {contact.signature} +
+ )} + +
+ +
-
- -
-
-

- 电话:{" "} - {contact.phone || "未设置电话"} -

-

- 地区:{" "} - {contact.region || contact.city || "未设置地区"} -

-

- 微信ID:{" "} - {contact.wechatId} -

-
-
- -
-
- {contact?.labels?.map((tag: string, index: number) => ( - - {tag} - - ))} -
- 微信好友 -
- -
- 最后联系:{" "} - {contact.lastMessageTime - ? new Date(contact.lastMessageTime).toLocaleDateString() - : "未联系"} -
- - {contact.signature && ( -
{contact.signature}
- )} - -
- - -
-
- - ))} - - )} + + ))} + + + )} +
-
+ ); }; diff --git a/Touchkebao/src/styles/global.scss b/Touchkebao/src/styles/global.scss index 0b681cc6..16c25c87 100644 --- a/Touchkebao/src/styles/global.scss +++ b/Touchkebao/src/styles/global.scss @@ -315,3 +315,11 @@ button { flex: 1; } } +.pagination-wrapper { + display: flex; + justify-content: center; + align-items: center; + padding: 16px; + background: white; + border-top: 1px solid #f0f0f0; +}