feat(dealer): 添加客户列表功能并优化邀请流程

- 新增客户列表页面,实现客户数据获取和筛选功能
- 添加客户状态管理工具函数
- 优化邀请流程,支持绑定推荐关系
- 调整提现功能,增加调试组件
- 修复申请经销商功能中的推荐人ID逻辑
This commit is contained in:
2025-09-03 10:41:06 +08:00
parent 7834124095
commit 0b43a3bc92
18 changed files with 1286 additions and 934 deletions

View File

@@ -0,0 +1,184 @@
import React, {useState, useEffect, useCallback} from 'react'
import {View, Text} from '@tarojs/components'
import {Loading, Tabs, TabPane, Tag} from '@nutui/nutui-react-taro'
import {Phone} from '@nutui/icons-react-taro'
import {pageUsers} from "@/api/system/user";
import type {User as UserType} from "@/api/system/user/model";
import {
CustomerStatus,
getStatusText,
getStatusTagType,
getRandomStatus,
getStatusOptions
} from '@/utils/customerStatus';
// 扩展User类型添加客户状态
interface CustomerUser extends UserType {
customerStatus?: CustomerStatus;
}
const CustomerManagement: React.FC = () => {
const [list, setList] = useState<CustomerUser[]>([])
const [loading, setLoading] = useState<boolean>(false)
const [activeTab, setActiveTab] = useState<CustomerStatus>('all')
const [searchValue, setSearchValue] = useState<string>('')
// Tab配置
const tabList = getStatusOptions();
// 获取客户数据
const fetchCustomerData = useCallback(async () => {
setLoading(true);
try {
// 获取用户列表status: 0 表示正常状态
const res = await pageUsers({ status: 0 });
if (res?.list) {
// 为每个用户添加随机的客户状态(实际项目中应该从后端获取真实状态)
const customersWithStatus: CustomerUser[] = res.list.map(user => ({
...user,
customerStatus: getRandomStatus() // 临时使用随机状态,实际应该从数据库获取
}));
setList(customersWithStatus);
}
} catch (error) {
console.error('获取客户数据失败:', error);
} finally {
setLoading(false);
}
}, []);
// 根据当前Tab和搜索条件筛选数据
const getFilteredList = () => {
let filteredList = list;
// 按状态筛选
if (activeTab !== 'all') {
filteredList = filteredList.filter(customer => customer.customerStatus === activeTab);
}
// 按搜索关键词筛选
if (searchValue.trim()) {
const keyword = searchValue.trim().toLowerCase();
filteredList = filteredList.filter(customer =>
(customer.realName && customer.realName.toLowerCase().includes(keyword)) ||
(customer.nickname && customer.nickname.toLowerCase().includes(keyword)) ||
(customer.username && customer.username.toLowerCase().includes(keyword)) ||
(customer.phone && customer.phone.includes(keyword)) ||
(customer.userId && customer.userId.toString().includes(keyword))
);
}
return filteredList;
};
// 获取各状态的统计数量
const getStatusCounts = () => {
const counts = {
all: list.length,
pending: 0,
signed: 0,
cancelled: 0
};
list.forEach(customer => {
if (customer.customerStatus && counts.hasOwnProperty(customer.customerStatus)) {
counts[customer.customerStatus]++;
}
});
return counts;
};
// 初始化数据
useEffect(() => {
fetchCustomerData();
}, [fetchCustomerData]);
// 渲染客户项
const renderCustomerItem = (customer: CustomerUser) => (
<View key={customer.userId} className="bg-white rounded-lg p-4 mb-3 shadow-sm">
<View className="flex items-center mb-3">
<View className="flex-1">
<View className="flex items-center justify-between mb-1">
<Text className="font-semibold text-gray-800 mr-2">
{customer.realName || customer.nickname || customer.username}
</Text>
{customer.customerStatus && (
<Tag type={getStatusTagType(customer.customerStatus)}>
{getStatusText(customer.customerStatus)}
</Tag>
)}
</View>
<View className="flex items-center mb-1">
<Phone size={12} className="mr-1" />
<Text className="text-xs text-gray-500">
{customer.phone || '未填写'}
</Text>
</View>
<Text className="text-xs text-gray-500">
{customer.createTime}
</Text>
</View>
</View>
</View>
);
// 渲染客户列表
const renderCustomerList = () => {
const filteredList = getFilteredList();
if (loading) {
return (
<View className="flex items-center justify-center py-8">
<Loading />
<Text className="text-gray-500 mt-2">...</Text>
</View>
);
}
if (filteredList.length === 0) {
return (
<View className="flex items-center justify-center py-8">
<Text className="text-gray-500"></Text>
</View>
);
}
return (
<View className="p-4">
{filteredList.map(renderCustomerItem)}
</View>
);
};
return (
<View className="min-h-screen bg-gray-50">
{/* 顶部Tabs */}
<View className="bg-white">
<Tabs
value={activeTab}
onChange={(value) => setActiveTab(value as CustomerStatus)}
>
{tabList.map(tab => {
const counts = getStatusCounts();
const count = counts[tab.value as keyof typeof counts] || 0;
return (
<TabPane
key={tab.value}
title={`${tab.label}${count > 0 ? `(${count})` : ''}`}
value={tab.value}
/>
);
})}
</Tabs>
</View>
{/* 客户列表 */}
{renderCustomerList()}
</View>
);
};
export default CustomerManagement;