feat(dealer): 调整客户报备功能以支持房号信息管理
- 移除 useUser hook 的使用,不再依赖用户信息 - 新增房号信息处理函数:buildHouseKey、buildHouseDisplay 和 parseHouseKey - 添加房号相关必填字段校验(小区、楼栋号、房号、姓名) - 修改报备逻辑:使用房号作为唯一键进行重复检查 - 优化报备保护期逻辑:区分已签约/已取消和跟进中的状态 - 调整表单字段:将公司信息改为小区楼栋房号信息 - 更新数据提交格式:dealerName 存储展示文案,dealerCode 存储唯一键 - 添加编辑模式下房号信息的回填功能 - 移除对用户ID的依赖,简化报备流程
This commit is contained in:
@@ -57,6 +57,7 @@ export interface ShopDealerApplyParam extends PageParam {
|
|||||||
applyId?: number;
|
applyId?: number;
|
||||||
type?: number;
|
type?: number;
|
||||||
dealerName?: string;
|
dealerName?: string;
|
||||||
|
dealerCode?: string;
|
||||||
mobile?: string;
|
mobile?: string;
|
||||||
userId?: number;
|
userId?: number;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import Taro from '@tarojs/taro'
|
|||||||
import {useRouter} from '@tarojs/taro'
|
import {useRouter} from '@tarojs/taro'
|
||||||
import {View, Text} from '@tarojs/components'
|
import {View, Text} from '@tarojs/components'
|
||||||
import FixedButton from "@/components/FixedButton";
|
import FixedButton from "@/components/FixedButton";
|
||||||
import {useUser} from "@/hooks/useUser";
|
|
||||||
import {ShopDealerApply} from "@/api/shop/shopDealerApply/model";
|
import {ShopDealerApply} from "@/api/shop/shopDealerApply/model";
|
||||||
import {
|
import {
|
||||||
addShopDealerApply, getShopDealerApply, pageShopDealerApply,
|
addShopDealerApply, getShopDealerApply, pageShopDealerApply,
|
||||||
@@ -19,7 +18,6 @@ import {ShopDealerUser} from "@/api/shop/shopDealerUser/model";
|
|||||||
import {getShopDealerUser, pageShopDealerUser} from "@/api/shop/shopDealerUser";
|
import {getShopDealerUser, pageShopDealerUser} from "@/api/shop/shopDealerUser";
|
||||||
|
|
||||||
const AddShopDealerApply = () => {
|
const AddShopDealerApply = () => {
|
||||||
const {user} = useUser()
|
|
||||||
const {params} = useRouter();
|
const {params} = useRouter();
|
||||||
const [loading, setLoading] = useState<boolean>(true)
|
const [loading, setLoading] = useState<boolean>(true)
|
||||||
const [FormData, setFormData] = useState<ShopDealerApply>()
|
const [FormData, setFormData] = useState<ShopDealerApply>()
|
||||||
@@ -28,6 +26,33 @@ const AddShopDealerApply = () => {
|
|||||||
const [existingApply, setExistingApply] = useState<ShopDealerApply | null>(null)
|
const [existingApply, setExistingApply] = useState<ShopDealerApply | null>(null)
|
||||||
const [referee, setReferee] = useState<ShopDealerUser>()
|
const [referee, setReferee] = useState<ShopDealerUser>()
|
||||||
|
|
||||||
|
// 房号信息:用 dealerCode 存储唯一键,dealerName 存储展示文案
|
||||||
|
const buildHouseKey = (community: string, buildingNo: string, unitNo: string | undefined, roomNo: string) => {
|
||||||
|
const c = (community || '').trim();
|
||||||
|
const b = (buildingNo || '').trim();
|
||||||
|
const u = (unitNo || '').trim();
|
||||||
|
const r = (roomNo || '').trim();
|
||||||
|
return [c, b, u, r].join('|');
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildHouseDisplay = (community: string, buildingNo: string, unitNo: string | undefined, roomNo: string) => {
|
||||||
|
const c = (community || '').trim();
|
||||||
|
const b = (buildingNo || '').trim();
|
||||||
|
const u = (unitNo || '').trim();
|
||||||
|
const r = (roomNo || '').trim();
|
||||||
|
return `${c}${b ? `${b}栋` : ''}${u ? `${u}单元` : ''}${r ? `${r}号` : ''}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseHouseKey = (key?: string) => {
|
||||||
|
const parts = (key || '').split('|');
|
||||||
|
return {
|
||||||
|
community: parts[0] || '',
|
||||||
|
buildingNo: parts[1] || '',
|
||||||
|
unitNo: parts[2] || '',
|
||||||
|
roomNo: parts[3] || '',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// 日期选择器状态
|
// 日期选择器状态
|
||||||
const [showApplyTimePicker, setShowApplyTimePicker] = useState<boolean>(false)
|
const [showApplyTimePicker, setShowApplyTimePicker] = useState<boolean>(false)
|
||||||
const [showContractTimePicker, setShowContractTimePicker] = useState<boolean>(false)
|
const [showContractTimePicker, setShowContractTimePicker] = useState<boolean>(false)
|
||||||
@@ -136,6 +161,24 @@ const AddShopDealerApply = () => {
|
|||||||
const submitSucceed = async (values: any) => {
|
const submitSucceed = async (values: any) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// 房号相关必填校验
|
||||||
|
if (!values.address || values.address.trim() === '') {
|
||||||
|
Taro.showToast({title: '请选择/填写小区', icon: 'error'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!values.buildingNo || values.buildingNo.trim() === '') {
|
||||||
|
Taro.showToast({title: '请填写楼栋号', icon: 'error'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!values.roomNo || values.roomNo.trim() === '') {
|
||||||
|
Taro.showToast({title: '请填写房号', icon: 'error'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!values.realName || values.realName.trim() === '') {
|
||||||
|
Taro.showToast({title: '请填写姓名', icon: 'error'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 验证必填字段
|
// 验证必填字段
|
||||||
if (!values.mobile || values.mobile.trim() === '') {
|
if (!values.mobile || values.mobile.trim() === '') {
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
@@ -167,51 +210,63 @@ const AddShopDealerApply = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查客户是否已存在
|
const houseKey = buildHouseKey(values.address, values.buildingNo, values.unitNo, values.roomNo);
|
||||||
const res = await pageShopDealerApply({dealerName: values.dealerName, type: 4, applyStatus: 10});
|
const houseDisplay = buildHouseDisplay(values.address, values.buildingNo, values.unitNo, values.roomNo);
|
||||||
|
|
||||||
|
// 检查房号是否已报备
|
||||||
|
const res = await pageShopDealerApply({dealerCode: houseKey, type: 4});
|
||||||
|
|
||||||
if (res && res.count > 0) {
|
if (res && res.count > 0) {
|
||||||
const existingCustomer = res.list[0];
|
const existingCustomer = res.list[0];
|
||||||
|
|
||||||
// 检查是否在7天保护期内
|
if (!isEditMode) {
|
||||||
if (!isEditMode && existingCustomer.applyTime) {
|
// 已签约/已取消:直接提示已报备
|
||||||
// 将申请时间字符串转换为时间戳进行比较
|
if (existingCustomer.applyStatus && existingCustomer.applyStatus !== 10) {
|
||||||
|
Taro.showToast({
|
||||||
|
title: `该房号信息已报备(${getApplyStatusText(existingCustomer.applyStatus)})`,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2500
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跟进中:保留 7 天保护期逻辑
|
||||||
|
if (existingCustomer.applyTime) {
|
||||||
const applyTimeStamp = new Date(existingCustomer.applyTime).getTime();
|
const applyTimeStamp = new Date(existingCustomer.applyTime).getTime();
|
||||||
const currentTimeStamp = new Date().getTime();
|
const currentTimeStamp = new Date().getTime();
|
||||||
const sevenDaysInMs = 7 * 24 * 60 * 60 * 1000; // 7天的毫秒数
|
const sevenDaysInMs = 7 * 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
// 如果在7天保护期内,不允许重复添加
|
|
||||||
if (currentTimeStamp - applyTimeStamp < sevenDaysInMs) {
|
if (currentTimeStamp - applyTimeStamp < sevenDaysInMs) {
|
||||||
const remainingDays = Math.ceil((sevenDaysInMs - (currentTimeStamp - applyTimeStamp)) / (24 * 60 * 60 * 1000));
|
const remainingDays = Math.ceil((sevenDaysInMs - (currentTimeStamp - applyTimeStamp)) / (24 * 60 * 60 * 1000));
|
||||||
|
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
title: `该客户还在保护期,还需等待${remainingDays}天后才能重新添加`,
|
title: `该房号信息已报备,保护期剩余${remainingDays}天`,
|
||||||
icon: 'none',
|
icon: 'none',
|
||||||
duration: 3000
|
duration: 3000
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
// 超过7天保护期,可以重新添加,显示确认对话框
|
|
||||||
|
// 超过保护期:询问是否重新报备
|
||||||
const modalResult = await new Promise<boolean>((resolve) => {
|
const modalResult = await new Promise<boolean>((resolve) => {
|
||||||
Taro.showModal({
|
Taro.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: '该客户已超过7天保护期,是否重新添加跟进?',
|
content: '该房号已超过7天保护期,是否重新报备跟进?',
|
||||||
showCancel: true,
|
showCancel: true,
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
confirmText: '确定',
|
confirmText: '确定',
|
||||||
success: (modalRes) => {
|
success: (modalRes) => resolve(modalRes.confirm),
|
||||||
resolve(modalRes.confirm);
|
fail: () => resolve(false)
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
resolve(false);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!modalResult) {
|
if (!modalResult) return false;
|
||||||
return false; // 用户取消,不继续执行
|
} else {
|
||||||
}
|
Taro.showToast({
|
||||||
// 用户确认后继续执行添加逻辑
|
title: '该房号信息已报备',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2500
|
||||||
|
});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,10 +276,17 @@ const AddShopDealerApply = () => {
|
|||||||
const expirationTime = isEditMode ? existingApply?.expirationTime : calculateExpirationTime();
|
const expirationTime = isEditMode ? existingApply?.expirationTime : calculateExpirationTime();
|
||||||
|
|
||||||
// 准备提交的数据
|
// 准备提交的数据
|
||||||
|
// 避免把表单里的楼栋/单元/房号等临时字段原样提交给后端
|
||||||
|
const {buildingNo, unitNo, roomNo, ...restValues} = values;
|
||||||
const submitData = {
|
const submitData = {
|
||||||
...values,
|
...restValues,
|
||||||
type: 4,
|
type: 4,
|
||||||
realName: values.realName || user?.nickname,
|
// 展示用:小区+楼栋+单元+房号
|
||||||
|
dealerName: houseDisplay,
|
||||||
|
// 唯一键:用于后续重复报备提示
|
||||||
|
dealerCode: houseKey,
|
||||||
|
// 客户姓名/手机号
|
||||||
|
realName: values.realName,
|
||||||
mobile: values.mobile,
|
mobile: values.mobile,
|
||||||
refereeId: referee?.refereeId,
|
refereeId: referee?.refereeId,
|
||||||
applyStatus: isEditMode ? 20 : 10,
|
applyStatus: isEditMode ? 20 : 10,
|
||||||
@@ -296,6 +358,21 @@ const AddShopDealerApply = () => {
|
|||||||
})
|
})
|
||||||
}, []); // 依赖用户ID,当用户变化时重新加载
|
}, []); // 依赖用户ID,当用户变化时重新加载
|
||||||
|
|
||||||
|
// 编辑模式下,从 dealerCode 反解出楼栋/单元/房号,回填表单(只读展示)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!formRef.current || !FormData) return;
|
||||||
|
const parsed = parseHouseKey(FormData.dealerCode);
|
||||||
|
formRef.current.setFieldsValue({
|
||||||
|
address: parsed.community || FormData.address,
|
||||||
|
buildingNo: parsed.buildingNo,
|
||||||
|
unitNo: parsed.unitNo,
|
||||||
|
roomNo: parsed.roomNo,
|
||||||
|
realName: FormData.realName,
|
||||||
|
mobile: FormData.mobile,
|
||||||
|
userId: FormData.userId
|
||||||
|
});
|
||||||
|
}, [FormData]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Loading className={'px-2'}>加载中</Loading>
|
return <Loading className={'px-2'}>加载中</Loading>
|
||||||
}
|
}
|
||||||
@@ -312,21 +389,24 @@ const AddShopDealerApply = () => {
|
|||||||
>
|
>
|
||||||
<View className={'bg-gray-100 h-3'}></View>
|
<View className={'bg-gray-100 h-3'}></View>
|
||||||
<CellGroup style={{padding: '4px 0'}}>
|
<CellGroup style={{padding: '4px 0'}}>
|
||||||
<Form.Item name="dealerName" label="公司名称" initialValue={FormData?.dealerName} required>
|
<Form.Item name="address" label="小区" initialValue={FormData?.address} required>
|
||||||
<Input placeholder="公司名称" disabled={isEditMode}/>
|
<Input placeholder="请选择/填写小区" disabled={isEditMode}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="realName" label="联系人" initialValue={FormData?.realName} required>
|
<Form.Item name="buildingNo" label="楼栋号" required>
|
||||||
<Input placeholder="请输入联系人" disabled={isEditMode}/>
|
<Input placeholder="请输入楼栋号" disabled={isEditMode}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="mobile" label="联系方式" initialValue={FormData?.mobile} required>
|
<Form.Item name="unitNo" label="单元号">
|
||||||
|
<Input placeholder="选填" disabled={isEditMode}/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="roomNo" label="房号" required>
|
||||||
|
<Input placeholder="请输入房号" disabled={isEditMode}/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="realName" label="姓名" initialValue={FormData?.realName} required>
|
||||||
|
<Input placeholder="请输入客户姓名" disabled={isEditMode}/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name="mobile" label="手机号" initialValue={FormData?.mobile} required>
|
||||||
<Input placeholder="请输入手机号" disabled={isEditMode} maxLength={11}/>
|
<Input placeholder="请输入手机号" disabled={isEditMode} maxLength={11}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="address" label="公司地址" initialValue={FormData?.address} required>
|
|
||||||
<Input placeholder="请输入详细地址" disabled={isEditMode}/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="dealerCode" label="户号" initialValue={FormData?.dealerCode} required>
|
|
||||||
<Input placeholder="请填写户号" disabled={isEditMode}/>
|
|
||||||
</Form.Item>
|
|
||||||
{isEditMode && (
|
{isEditMode && (
|
||||||
<>
|
<>
|
||||||
<Form.Item name="money" label="签约价格" initialValue={FormData?.money} required>
|
<Form.Item name="money" label="签约价格" initialValue={FormData?.money} required>
|
||||||
@@ -368,7 +448,6 @@ const AddShopDealerApply = () => {
|
|||||||
placeholder="自己报备请留空"
|
placeholder="自己报备请留空"
|
||||||
disabled={isEditMode}
|
disabled={isEditMode}
|
||||||
type="number"
|
type="number"
|
||||||
value={(FormData?.userId)?.toString() || ''}
|
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</CellGroup>
|
</CellGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user