Files
template-10560/src/pages/customer/list.tsx
赵忠林 0b43a3bc92 feat(dealer): 添加客户列表功能并优化邀请流程
- 新增客户列表页面,实现客户数据获取和筛选功能
- 添加客户状态管理工具函数
- 优化邀请流程,支持绑定推荐关系
- 调整提现功能,增加调试组件
- 修复申请经销商功能中的推荐人ID逻辑
2025-09-03 10:41:06 +08:00

236 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {useEffect, useState} from "react";
import Taro from '@tarojs/taro';
import {View, Text} from '@tarojs/components';
import {Space, Tabs, Button, Empty} from '@nutui/nutui-react-taro';
import {Phone} from '@nutui/icons-react-taro';
import './list.scss';
import {pageUsers} from "@/api/system/user";
import {ShopDealerUser} from "@/api/shop/shopDealerUser/model";
const CustomerList = () => {
const [activeTab, setActiveTab] = useState<string>('all');
const [loading, setLoading] = useState<boolean>(false);
const [list, setList] = useState<ShopDealerUser[]>([]);
const tabList = [
{title: '全部', value: 'all'},
{title: '跟进中', value: 'pending'},
{title: '已签约', value: 'confirmed'},
{title: '已取消', value: 'cancelled'}
];
const reload = async () => {
setLoading(true);
try {
const res = await pageUsers({status: 0});
console.log(res, '客户列表');
if(res?.list){
// 为每个用户添加默认状态
const customersWithStatus: ShopDealerUser[] = res.list.map(user => ({
...user,
status: 'pending' // 默认状态为跟进中
}));
setList(customersWithStatus);
}
} catch (error) {
console.error('获取客户列表失败:', error);
Taro.showToast({
title: '获取客户列表失败',
icon: 'error'
});
} finally {
setLoading(false);
}
};
const getStatusText = (status: string) => {
switch (status) {
case 'pending':
return '跟进中';
case 'confirmed':
return '已签约';
case 'cancelled':
return '已取消';
default:
return '';
}
};
const getStatusColor = (status: string) => {
switch (status) {
case 'pending':
return '#ff6b35';
case 'confirmed':
return '#52c41a';
case 'cancelled':
return '#999';
default:
return '#999';
}
};
const handleCall = (phone: string) => {
Taro.makePhoneCall({
phoneNumber: phone
});
};
const handleAction = (customer: ShopDealerUser, action: 'sign' | 'cancel' | 'detail') => {
switch (action) {
case 'sign':
// 跳转到签约页面
Taro.navigateTo({
url: `/pages/customer/sign?customerId=${customer.userId}`
});
break;
case 'cancel':
Taro.showModal({
title: '确认取消',
content: '确定要取消该客户吗?',
success: (res) => {
if (res.confirm) {
// 这里应该调用取消客户的API
Taro.showToast({
title: '已取消',
icon: 'success'
});
// 刷新列表
reload().then();
}
}
});
break;
case 'detail':
// 跳转到客户详情页面
Taro.navigateTo({
url: `/pages/customer/detail?customerId=${customer.userId}`
});
break;
}
};
const handleReport = () => {
// 跳转到邀请页面
Taro.navigateTo({
url: '/pages/customer/invite'
});
};
useEffect(() => {
reload().then();
}, []);
return (
<View className="customer-list-page">
{/* 头部背景 */}
<View className="header-bg" style={{
height: '180px'
}} />
{/* 标签页 */}
<View className="tabs-container">
<Tabs
value={activeTab}
onChange={(value) => setActiveTab(value as string)}
>
{tabList.map(tab => (
<Tabs.TabPane key={tab.value} title={tab.title} value={tab.value} />
))}
</Tabs>
</View>
{/* 客户列表 */}
<View className="customer-list">
{loading ? (
<View className="loading-container">
<Text>...</Text>
</View>
) : list.length > 0 ? (
list.map((record) => (
<View key={record.userId} className="customer-item">
<View className="customer-header">
<Text className="company-name">{record.realName || '未知客户'}</Text>
<Text
className="status-tag"
style={{color: getStatusColor('pending')}}
>
{getStatusText('pending')}
</Text>
</View>
<View className="customer-info">
<View className="info-row">
<Text className="label"></Text>
<Text className="value">{record.realName || '未知'}</Text>
<Text className="label contact-label"></Text>
<Text className="value">{record.mobile || '未提供'}</Text>
<Phone
size={14}
className={'text-green-500'}
onClick={() => handleCall(`${record?.mobile}`)}
/>
</View>
<View className="address-row">
<Text className="label"></Text>
<Text className="address">{'地址未提供'}</Text>
</View>
<View className="time-row">
<Text className="time">{record.createTime || '未知'}</Text>
</View>
</View>
{/* 操作按钮 */}
<View className="action-buttons">
{record.payPassword === 'pending' && (
<Space>
<Button
className="action-btn sign-btn"
size="small"
onClick={() => handleAction(record, 'sign')}
>
</Button>
<Button
className="action-btn cancel-btn"
size="small"
onClick={() => handleAction(record, 'cancel')}
>
</Button>
</Space>
)}
{record.payPassword === 'confirmed' && (
<Button
className="action-btn detail-btn"
size="small"
onClick={() => handleAction(record, 'detail')}
>
</Button>
)}
</View>
</View>
))
) : (
<Empty description="暂无客户数据" />
)}
</View>
{/* 底部邀请好友按钮 */}
<View className="fixed-bottom">
<Button
className="report-btn"
onClick={handleReport}
>
</Button>
</View>
</View>
);
};
export default CustomerList;