优化客户管理模块:更新标签页样式,调整按钮组件,重构联系人展示为表格形式,提升用户体验和代码可读性。
This commit is contained in:
@@ -114,9 +114,9 @@
|
||||
|
||||
// 标签页
|
||||
.tabs {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
gap: 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
gap: 10px;
|
||||
|
||||
.tab {
|
||||
padding: 12px 24px;
|
||||
@@ -127,15 +127,6 @@
|
||||
color: #8c8c8c;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
&.activeTab {
|
||||
color: #1890ff;
|
||||
border-bottom-color: #1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import PowerNavigation from "@/components/PowerNavtion";
|
||||
import {
|
||||
SearchOutlined,
|
||||
FilterOutlined,
|
||||
MessageOutlined,
|
||||
PhoneOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { SearchOutlined, FilterOutlined } from "@ant-design/icons";
|
||||
import styles from "./index.module.scss";
|
||||
import { Button, Input, Row, Col, Pagination, Spin, message } from "antd";
|
||||
import { Button, Input, Table, message } from "antd";
|
||||
import { getContactList } from "@/pages/pc/ckbox/weChat/api";
|
||||
import { ContractData } from "@/pages/pc/ckbox/data";
|
||||
import Layout from "@/components/Layout/LayoutFiexd";
|
||||
@@ -196,132 +191,129 @@ const CustomerManagement: React.FC = () => {
|
||||
刷新
|
||||
</Button>
|
||||
</div>
|
||||
{/* 标签页 */}
|
||||
{/* 标签按钮组 */}
|
||||
<div className={styles.tabs}>
|
||||
{tabs.map(tab => (
|
||||
<button
|
||||
<Button
|
||||
key={tab.key}
|
||||
className={`${styles.tab} ${activeTab === tab.key ? styles.activeTab : ""}`}
|
||||
type={activeTab === tab.key ? "primary" : "default"}
|
||||
onClick={() => setActiveTab(tab.key)}
|
||||
>
|
||||
{tab.label} ({tab.count})
|
||||
</button>
|
||||
{tab.label}
|
||||
<span style={{ marginLeft: 6, opacity: 0.85 }}>
|
||||
{tab.count}
|
||||
</span>
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
footer={
|
||||
<div className="pagination-wrapper">
|
||||
<Pagination
|
||||
current={pagination.current}
|
||||
pageSize={pagination.pageSize}
|
||||
total={pagination.total}
|
||||
showSizeChanger
|
||||
showQuickJumper
|
||||
showTotal={(total, range) =>
|
||||
`第 ${range[0]}-${range[1]} 条,共 ${total} 条`
|
||||
}
|
||||
onChange={(page, pageSize) => {
|
||||
loadContacts(page, pageSize || pagination.pageSize);
|
||||
}}
|
||||
onShowSizeChange={(current, size) => {
|
||||
loadContacts(1, size);
|
||||
}}
|
||||
pageSizeOptions={["6", "12", "24", "48"]}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
footer={null}
|
||||
>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
{/* 联系人卡片列表 */}
|
||||
<div className={styles.contactsList}>
|
||||
{loading ? (
|
||||
<div style={{ textAlign: "center", padding: "50px" }}>
|
||||
<Spin size="large" />
|
||||
<p style={{ marginTop: "16px", color: "#666" }}>
|
||||
正在加载联系人数据...
|
||||
</p>
|
||||
</div>
|
||||
) : filteredContacts.length === 0 ? (
|
||||
<div style={{ textAlign: "center", padding: "50px" }}>
|
||||
<p style={{ color: "#999" }}>暂无联系人数据</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Row gutter={[16, 16]}>
|
||||
{filteredContacts.map(contact => (
|
||||
<Col span={8} key={contact.id || contact.serverId}>
|
||||
<div className={styles.contactCard}>
|
||||
<div className={styles.cardHeader}>
|
||||
<div className={styles.contactInfo}>
|
||||
<Avatar
|
||||
name={
|
||||
contact.conRemark ||
|
||||
contact.nickname ||
|
||||
contact.alias ||
|
||||
"未知用户"
|
||||
}
|
||||
avatar={contact.avatar}
|
||||
size={48}
|
||||
/>
|
||||
<div className={styles.nameSection}>
|
||||
<h3 className={styles.contactName}>
|
||||
{contact.conRemark ||
|
||||
contact.nickname ||
|
||||
contact.alias ||
|
||||
"未知用户"}
|
||||
</h3>
|
||||
<p className={styles.roleCompany}>
|
||||
客户 {"·"} {contact.desc || "未设置公司"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.contactDetails}>
|
||||
<div className={styles.contactInfo}>
|
||||
<p className={styles.contactItem}>
|
||||
<span className={styles.label}>电话:</span>{" "}
|
||||
{contact.phone || "未设置电话"}
|
||||
</p>
|
||||
<p className={styles.contactItem}>
|
||||
<span className={styles.label}>地区:</span>{" "}
|
||||
{contact.region || contact.city || "未设置地区"}
|
||||
</p>
|
||||
<p className={styles.contactItem}>
|
||||
<span className={styles.label}>微信ID:</span>{" "}
|
||||
{contact.wechatId}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.tagsSection}>
|
||||
<div className={styles.tags}>
|
||||
{contact?.labels?.map(
|
||||
(tag: string, index: number) => (
|
||||
<span key={index} className={styles.tag}>
|
||||
{tag}
|
||||
</span>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.actions}>
|
||||
<Button type="primary" block>
|
||||
<MessageOutlined />
|
||||
聊天
|
||||
</Button>
|
||||
</div>
|
||||
{/* 联系人表格 */}
|
||||
<Table
|
||||
rowKey={(record: any) => record.id || record.serverId}
|
||||
loading={loading}
|
||||
dataSource={filteredContacts as any}
|
||||
columns={[
|
||||
{
|
||||
title: "客户姓名",
|
||||
key: "name",
|
||||
render: (_: any, record: any) => {
|
||||
const displayName =
|
||||
record.conRemark ||
|
||||
record.nickname ||
|
||||
record.alias ||
|
||||
"未知用户";
|
||||
return (
|
||||
<div className={styles.contactInfo}>
|
||||
<Avatar
|
||||
name={displayName}
|
||||
avatar={record.avatar}
|
||||
size={40}
|
||||
/>
|
||||
<div className={styles.nameSection}>
|
||||
<h3 className={styles.contactName}>{displayName}</h3>
|
||||
<p className={styles.roleCompany}>
|
||||
客户 · {record.desc || "未设置公司"}
|
||||
</p>
|
||||
</div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "RFM评分",
|
||||
dataIndex: "rfmScore",
|
||||
key: "rfmScore",
|
||||
width: 100,
|
||||
render: (val: any) => val ?? "-",
|
||||
},
|
||||
{
|
||||
title: "电话",
|
||||
dataIndex: "phone",
|
||||
key: "phone",
|
||||
width: 180,
|
||||
render: (val: string) => val || "未设置电话",
|
||||
},
|
||||
{
|
||||
title: "微信号",
|
||||
dataIndex: "wechatId",
|
||||
key: "wechatId",
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: "地址",
|
||||
key: "address",
|
||||
ellipsis: true,
|
||||
render: (_: any, record: any) =>
|
||||
record.region || record.city || "未设置地区",
|
||||
},
|
||||
{
|
||||
title: "标签",
|
||||
key: "labels",
|
||||
render: (_: any, record: any) => (
|
||||
<div className={styles.tags}>
|
||||
{(record?.labels || []).map(
|
||||
(tag: string, index: number) => (
|
||||
<span key={index} className={styles.tag}>
|
||||
{tag}
|
||||
</span>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
width: 120,
|
||||
render: () => (
|
||||
<Button type="primary" size="small">
|
||||
聊天
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
]}
|
||||
pagination={{
|
||||
current: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
total: pagination.total,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: (total: number, range: [number, number]) =>
|
||||
`第 ${range[0]}-${range[1]} 条,共 ${total} 条`,
|
||||
pageSizeOptions: ["6", "12", "24", "48"],
|
||||
}}
|
||||
onChange={(pager: any) => {
|
||||
const nextCurrent = pager.current || 1;
|
||||
const nextSize = pager.pageSize || pagination.pageSize;
|
||||
loadContacts(nextCurrent, nextSize);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -5,6 +5,7 @@ import AudioMessage from "./components/AudioMessage/AudioMessage";
|
||||
import SmallProgramMessage from "./components/SmallProgramMessage";
|
||||
import VideoMessage from "./components/VideoMessage";
|
||||
import ClickMenu from "./components/ClickMeau";
|
||||
import LocationMessage from "./components/LocationMessage";
|
||||
import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
|
||||
import { formatWechatTime } from "@/utils/common";
|
||||
import { getEmojiPath } from "@/components/EmojiSeclection/wechatEmoji";
|
||||
@@ -270,6 +271,9 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
|
||||
}
|
||||
return renderErrorMessage("[表情包]");
|
||||
|
||||
case 48: // 定位消息
|
||||
return <LocationMessage content={content || ""} />;
|
||||
|
||||
case 49: // 小程序/文章/其他:图文、文件
|
||||
return <SmallProgramMessage content={content || ""} />;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user