import { useEffect, useMemo, useState } from 'react';
|
import { Button, Descriptions, Drawer, Empty, Spin, Tag } from 'antd';
|
import type { DescriptionsProps } from 'antd';
|
import { customerTypeMeta, levelMeta, renderTags, sourceMeta, stageMeta } from '../columns';
|
import { getCustomerDetail } from '../server';
|
import type { CustomerVO } from '../types';
|
import { formatDateTime } from '../utils';
|
|
interface CustomerDetailDrawerProps {
|
open: boolean;
|
/** 待展示的客户 ID,关闭时为 null。 */
|
customerId: number | null;
|
onClose: () => void;
|
}
|
|
const renderTag = (meta?: { text: string; color: string }) =>
|
meta ? (
|
<Tag color={meta.color} bordered={false}>
|
{meta.text}
|
</Tag>
|
) : (
|
'-'
|
);
|
|
const CustomerDetailDrawer = ({ open, customerId, onClose }: CustomerDetailDrawerProps) => {
|
const [customer, setCustomer] = useState<CustomerVO | null>(null);
|
const [loading, setLoading] = useState(false);
|
|
useEffect(() => {
|
if (!open || !customerId) return;
|
|
let active = true;
|
setCustomer(null);
|
setLoading(true);
|
|
getCustomerDetail({ id: customerId })
|
.then((data) => {
|
if (active) setCustomer(data);
|
})
|
.catch(() => {
|
// 错误已由 request 统一提示
|
if (active) setCustomer(null);
|
})
|
.finally(() => {
|
if (active) setLoading(false);
|
});
|
|
return () => {
|
active = false;
|
};
|
}, [customerId, open]);
|
|
const items = useMemo<DescriptionsProps['items']>(() => {
|
if (!customer) return [];
|
|
return [
|
{ key: 'name', label: '客户名称', children: customer.name || '-' },
|
{
|
key: 'customerType',
|
label: '客户类型',
|
children: renderTag(customer.customerType ? customerTypeMeta[customer.customerType] : undefined),
|
},
|
{
|
key: 'level',
|
label: '客户等级',
|
children: renderTag(customer.level ? levelMeta[customer.level] : undefined),
|
},
|
{
|
key: 'stage',
|
label: '客户阶段',
|
children: renderTag(customer.stage ? stageMeta[customer.stage] : undefined),
|
},
|
{ key: 'industry', label: '所属行业', children: customer.industry || '-' },
|
{ key: 'region', label: '所在地区', children: customer.region || '-' },
|
{
|
key: 'source',
|
label: '客户来源',
|
children: customer.source ? sourceMeta[customer.source] ?? customer.source : '-',
|
},
|
{ key: 'contactName', label: '联系人', children: customer.contactName || '-' },
|
{ key: 'contactPhone', label: '联系电话', children: customer.contactPhone || '-' },
|
{ key: 'contactPosition', label: '职位', children: customer.contactPosition || '-' },
|
{ key: 'contactTel', label: '备用电话', children: customer.contactTel || '-' },
|
{ key: 'email', label: '邮箱', children: customer.email || '-' },
|
{ key: 'address', label: '地址', children: customer.address || '-' },
|
{ key: 'demand', label: '需求描述', children: customer.demand || '-' },
|
{ key: 'tags', label: '标签', children: renderTags(customer.tags) },
|
{ key: 'owner', label: '归属销售员', children: customer.ownerName || '-' },
|
{ key: 'lastFollowAt', label: '最近跟进', children: formatDateTime(customer.lastFollowAt) },
|
{ key: 'nextFollowAt', label: '下次跟进', children: formatDateTime(customer.nextFollowAt) },
|
{ key: 'dealAt', label: '成交时间', children: formatDateTime(customer.dealAt) },
|
{ key: 'lostAt', label: '流失时间', children: formatDateTime(customer.lostAt) },
|
{ key: 'lostReason', label: '流失原因', children: customer.lostReason || '-' },
|
];
|
}, [customer]);
|
|
return (
|
<Drawer
|
title="客户详情"
|
width={520}
|
open={open}
|
onClose={onClose}
|
footer={
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
<Button onClick={onClose}>关闭</Button>
|
</div>
|
}
|
>
|
<Spin spinning={loading}>
|
{customer ? (
|
<Descriptions column={1} bordered size="small" items={items} />
|
) : (
|
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无客户信息" />
|
)}
|
</Spin>
|
</Drawer>
|
);
|
};
|
|
export default CustomerDetailDrawer;
|