优化客户管理模块:更新标签页样式,调整按钮组件,重构联系人展示为表格形式,提升用户体验和代码可读性。
This commit is contained in:
@@ -114,9 +114,9 @@
|
|||||||
|
|
||||||
// 标签页
|
// 标签页
|
||||||
.tabs {
|
.tabs {
|
||||||
|
padding: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0;
|
gap: 10px;
|
||||||
border-bottom: 1px solid #f0f0f0;
|
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
@@ -127,15 +127,6 @@
|
|||||||
color: #8c8c8c;
|
color: #8c8c8c;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
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 React, { useState, useEffect } from "react";
|
||||||
import PowerNavigation from "@/components/PowerNavtion";
|
import PowerNavigation from "@/components/PowerNavtion";
|
||||||
import {
|
import { SearchOutlined, FilterOutlined } from "@ant-design/icons";
|
||||||
SearchOutlined,
|
|
||||||
FilterOutlined,
|
|
||||||
MessageOutlined,
|
|
||||||
PhoneOutlined,
|
|
||||||
} from "@ant-design/icons";
|
|
||||||
import styles from "./index.module.scss";
|
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 { getContactList } from "@/pages/pc/ckbox/weChat/api";
|
||||||
import { ContractData } from "@/pages/pc/ckbox/data";
|
import { ContractData } from "@/pages/pc/ckbox/data";
|
||||||
import Layout from "@/components/Layout/LayoutFiexd";
|
import Layout from "@/components/Layout/LayoutFiexd";
|
||||||
@@ -196,132 +191,129 @@ const CustomerManagement: React.FC = () => {
|
|||||||
刷新
|
刷新
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{/* 标签页 */}
|
{/* 标签按钮组 */}
|
||||||
<div className={styles.tabs}>
|
<div className={styles.tabs}>
|
||||||
{tabs.map(tab => (
|
{tabs.map(tab => (
|
||||||
<button
|
<Button
|
||||||
key={tab.key}
|
key={tab.key}
|
||||||
className={`${styles.tab} ${activeTab === tab.key ? styles.activeTab : ""}`}
|
type={activeTab === tab.key ? "primary" : "default"}
|
||||||
onClick={() => setActiveTab(tab.key)}
|
onClick={() => setActiveTab(tab.key)}
|
||||||
>
|
>
|
||||||
{tab.label} ({tab.count})
|
{tab.label}
|
||||||
</button>
|
<span style={{ marginLeft: 6, opacity: 0.85 }}>
|
||||||
|
{tab.count}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
footer={
|
footer={null}
|
||||||
<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>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
{/* 联系人卡片列表 */}
|
{/* 联系人表格 */}
|
||||||
<div className={styles.contactsList}>
|
<Table
|
||||||
{loading ? (
|
rowKey={(record: any) => record.id || record.serverId}
|
||||||
<div style={{ textAlign: "center", padding: "50px" }}>
|
loading={loading}
|
||||||
<Spin size="large" />
|
dataSource={filteredContacts as any}
|
||||||
<p style={{ marginTop: "16px", color: "#666" }}>
|
columns={[
|
||||||
正在加载联系人数据...
|
{
|
||||||
</p>
|
title: "客户姓名",
|
||||||
</div>
|
key: "name",
|
||||||
) : filteredContacts.length === 0 ? (
|
render: (_: any, record: any) => {
|
||||||
<div style={{ textAlign: "center", padding: "50px" }}>
|
const displayName =
|
||||||
<p style={{ color: "#999" }}>暂无联系人数据</p>
|
record.conRemark ||
|
||||||
</div>
|
record.nickname ||
|
||||||
) : (
|
record.alias ||
|
||||||
<>
|
"未知用户";
|
||||||
<Row gutter={[16, 16]}>
|
return (
|
||||||
{filteredContacts.map(contact => (
|
<div className={styles.contactInfo}>
|
||||||
<Col span={8} key={contact.id || contact.serverId}>
|
<Avatar
|
||||||
<div className={styles.contactCard}>
|
name={displayName}
|
||||||
<div className={styles.cardHeader}>
|
avatar={record.avatar}
|
||||||
<div className={styles.contactInfo}>
|
size={40}
|
||||||
<Avatar
|
/>
|
||||||
name={
|
<div className={styles.nameSection}>
|
||||||
contact.conRemark ||
|
<h3 className={styles.contactName}>{displayName}</h3>
|
||||||
contact.nickname ||
|
<p className={styles.roleCompany}>
|
||||||
contact.alias ||
|
客户 · {record.desc || "未设置公司"}
|
||||||
"未知用户"
|
</p>
|
||||||
}
|
|
||||||
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>
|
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</div>
|
||||||
))}
|
);
|
||||||
</Row>
|
},
|
||||||
</>
|
},
|
||||||
)}
|
{
|
||||||
</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>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import AudioMessage from "./components/AudioMessage/AudioMessage";
|
|||||||
import SmallProgramMessage from "./components/SmallProgramMessage";
|
import SmallProgramMessage from "./components/SmallProgramMessage";
|
||||||
import VideoMessage from "./components/VideoMessage";
|
import VideoMessage from "./components/VideoMessage";
|
||||||
import ClickMenu from "./components/ClickMeau";
|
import ClickMenu from "./components/ClickMeau";
|
||||||
|
import LocationMessage from "./components/LocationMessage";
|
||||||
import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
|
import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
|
||||||
import { formatWechatTime } from "@/utils/common";
|
import { formatWechatTime } from "@/utils/common";
|
||||||
import { getEmojiPath } from "@/components/EmojiSeclection/wechatEmoji";
|
import { getEmojiPath } from "@/components/EmojiSeclection/wechatEmoji";
|
||||||
@@ -270,6 +271,9 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
|
|||||||
}
|
}
|
||||||
return renderErrorMessage("[表情包]");
|
return renderErrorMessage("[表情包]");
|
||||||
|
|
||||||
|
case 48: // 定位消息
|
||||||
|
return <LocationMessage content={content || ""} />;
|
||||||
|
|
||||||
case 49: // 小程序/文章/其他:图文、文件
|
case 49: // 小程序/文章/其他:图文、文件
|
||||||
return <SmallProgramMessage content={content || ""} />;
|
return <SmallProgramMessage content={content || ""} />;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user