feat(dealer/customer): 优化客户信息展示和跟进功能

- 添加手机号验证功能(必填和格式验证)
- 增加跟进情况字段
- 实现手机号复制和拨打功能
- 显示报备人昵称
- 优化客户列表项的展示效果
This commit is contained in:
2025-09-15 23:05:20 +08:00
parent 924188568c
commit 08354c5adf
3 changed files with 86 additions and 7 deletions

View File

@@ -127,6 +127,25 @@ const AddShopDealerApply = () => {
const submitSucceed = async (values: any) => {
try {
// 验证必填字段
if (!values.mobile || values.mobile.trim() === '') {
Taro.showToast({
title: '请填写联系方式',
icon: 'error'
});
return;
}
// 验证手机号格式
const phoneRegex = /^1[3-9]\d{9}$/;
if (!phoneRegex.test(values.mobile)) {
Taro.showToast({
title: '请填写正确的手机号',
icon: 'error'
});
return;
}
// 检查客户是否已存在
const res = await pageShopDealerApply({dealerName: values.dealerName, type: 4, applyStatus: 10});
@@ -280,6 +299,9 @@ const AddShopDealerApply = () => {
<Form.Item name="dealerCode" label="户号" initialValue={FormData?.dealerCode} required>
<Input placeholder="请填写户号" disabled={isEditMode}/>
</Form.Item>
<Form.Item name="comments" label="跟进情况" initialValue={FormData?.comments}>
<Input placeholder="请填写跟进情况" disabled={isEditMode}/>
</Form.Item>
{isEditMode && (
<>
<Form.Item name="money" label="签约价格" initialValue={FormData?.money} required>

View File

@@ -33,6 +33,33 @@ const CustomerIndex = () => {
// Tab配置
const tabList = getStatusOptions();
// 复制手机号
const copyPhone = (phone: string) => {
Taro.setClipboardData({
data: phone,
success: () => {
Taro.showToast({
title: '手机号已复制',
icon: 'success',
duration: 1500
});
}
});
};
// 一键拨打
const makePhoneCall = (phone: string) => {
Taro.makePhoneCall({
phoneNumber: phone,
fail: () => {
Taro.showToast({
title: '拨打取消',
icon: 'error'
});
}
});
};
// 计算剩余保护天数(基于过期时间)
const calculateProtectDays = (expirationTime?: string, applyTime?: string): number => {
try {
@@ -272,8 +299,7 @@ const CustomerIndex = () => {
// 渲染客户项
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"
onClick={() => navTo(`/dealer/customer/add?id=${customer.applyId}`, true)}>
<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">
@@ -288,13 +314,40 @@ const CustomerIndex = () => {
<View className="flex items-center mb-1">
<Space direction="vertical">
<Text className="text-xs text-gray-500">{customer.realName}</Text>
<Text className="text-xs text-gray-500">{customer.mobile}<Phone size={12}
className="ml-1 text-green-500"/></Text>
<View className="flex items-center">
<Text className="text-xs text-gray-500" onClick={(e) => {
e.stopPropagation();
makePhoneCall(customer.mobile || '');
}}>{customer.mobile}</Text>
<View className="flex items-center ml-2">
<Phone
size={14}
className="text-green-500 mr-2"
onClick={(e) => {
e.stopPropagation();
makePhoneCall(customer.mobile || '');
}}
/>
<Text
className="text-xs text-blue-500 cursor-pointer"
onClick={(e) => {
e.stopPropagation();
copyPhone(customer.mobile || '');
}}
>
</Text>
</View>
</View>
{/* 显示 comments 字段 */}
<Space><Text className="text-xs text-gray-500">{customer.comments || '暂无'}</Text><Text className={'text-xs text-blue-500 cursor-pointer'}></Text></Space>
{customer.userId && <Text className="text-xs text-gray-500">{ customer?.nickname }</Text>}
<Text className="text-xs text-gray-500">
{customer.createTime}
</Text>
</Space>
</View>
<Text className="text-xs text-gray-500">
{customer.createTime}
</Text>
{/* 保护天数显示 */}
{customer.applyStatus === 10 && (
<View className="flex items-center mt-1">