feat(pages): 添加多个页面配置和功能模块
- 新增 .editorconfig、.eslintrc、.gitignore 配置文件 - 添加管理员文章管理页面配置和功能实现 - 添加经销商申请注册页面配置和功能实现 - 添加经销商银行卡管理页面配置和功能实现 - 添加经销商客户管理页面配置和功能实现 - 添加用户地址管理页面配置和功能实现 - 添加用户聊天消息页面配置和功能实现 - 添加用户礼品管理页面配置和功能实现
This commit is contained in:
430
src/dealer/customer/add.tsx
Normal file
430
src/dealer/customer/add.tsx
Normal file
@@ -0,0 +1,430 @@
|
||||
import {useEffect, useState, useRef} from "react";
|
||||
import {Loading, CellGroup, Cell, Input, Form, Calendar} from '@nutui/nutui-react-taro'
|
||||
import {Edit, Calendar as CalendarIcon} from '@nutui/icons-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import {useRouter} from '@tarojs/taro'
|
||||
import {View, Text} from '@tarojs/components'
|
||||
import FixedButton from "@/components/FixedButton";
|
||||
import {useUser} from "@/hooks/useUser";
|
||||
import {ShopDealerApply} from "@/api/shop/shopDealerApply/model";
|
||||
import {
|
||||
addShopDealerApply, getShopDealerApply, pageShopDealerApply,
|
||||
updateShopDealerApply
|
||||
} from "@/api/shop/shopDealerApply";
|
||||
import {
|
||||
formatDateForDatabase,
|
||||
extractDateForCalendar, formatDateForDisplay
|
||||
} from "@/utils/dateUtils";
|
||||
import {ShopDealerUser} from "@/api/shop/shopDealerUser/model";
|
||||
import {getShopDealerUser, pageShopDealerUser} from "@/api/shop/shopDealerUser";
|
||||
|
||||
const AddShopDealerApply = () => {
|
||||
const {user} = useUser()
|
||||
const {params} = useRouter();
|
||||
const [loading, setLoading] = useState<boolean>(true)
|
||||
const [FormData, setFormData] = useState<ShopDealerApply>()
|
||||
const formRef = useRef<any>(null)
|
||||
const [isEditMode, setIsEditMode] = useState<boolean>(false)
|
||||
const [existingApply, setExistingApply] = useState<ShopDealerApply | null>(null)
|
||||
const [referee, setReferee] = useState<ShopDealerUser>()
|
||||
|
||||
// 日期选择器状态
|
||||
const [showApplyTimePicker, setShowApplyTimePicker] = useState<boolean>(false)
|
||||
const [showContractTimePicker, setShowContractTimePicker] = useState<boolean>(false)
|
||||
const [applyTime, setApplyTime] = useState<string>('')
|
||||
const [contractTime, setContractTime] = useState<string>('')
|
||||
|
||||
// 获取审核状态文字
|
||||
const getApplyStatusText = (status?: number) => {
|
||||
switch (status) {
|
||||
case 10:
|
||||
return '待审核'
|
||||
case 20:
|
||||
return '已签约'
|
||||
case 30:
|
||||
return '已取消'
|
||||
default:
|
||||
return '未知状态'
|
||||
}
|
||||
}
|
||||
|
||||
console.log(getApplyStatusText)
|
||||
|
||||
// 处理签约时间选择
|
||||
const handleApplyTimeConfirm = (param: string) => {
|
||||
const selectedDate = param[3] // 选中的日期字符串 (YYYY-M-D)
|
||||
const formattedDate = formatDateForDatabase(selectedDate) // 转换为数据库格式
|
||||
setApplyTime(selectedDate) // 保存原始格式用于显示
|
||||
setShowApplyTimePicker(false)
|
||||
|
||||
// 更新表单数据(使用数据库格式)
|
||||
if (formRef.current) {
|
||||
formRef.current.setFieldsValue({
|
||||
applyTime: formattedDate
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 处理合同日期选择
|
||||
const handleContractTimeConfirm = (param: string) => {
|
||||
const selectedDate = param[3] // 选中的日期字符串 (YYYY-M-D)
|
||||
const formattedDate = formatDateForDatabase(selectedDate) // 转换为数据库格式
|
||||
setContractTime(selectedDate) // 保存原始格式用于显示
|
||||
setShowContractTimePicker(false)
|
||||
|
||||
// 更新表单数据(使用数据库格式)
|
||||
if (formRef.current) {
|
||||
formRef.current.setFieldsValue({
|
||||
contractTime: formattedDate
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const reload = async () => {
|
||||
// 查询推荐人信息
|
||||
const dealerUser = await getShopDealerUser(Number(Taro.getStorageSync('UserId')))
|
||||
setReferee(dealerUser)
|
||||
|
||||
if (!params.id) {
|
||||
setLoading(false);
|
||||
return false;
|
||||
}
|
||||
// 查询当前用户ID是否已有申请记录
|
||||
try {
|
||||
const dealerApply = await getShopDealerApply(Number(params.id));
|
||||
if (dealerApply) {
|
||||
setFormData(dealerApply)
|
||||
setIsEditMode(true);
|
||||
setExistingApply(dealerApply)
|
||||
|
||||
// 初始化日期数据(从数据库格式转换为Calendar组件格式)
|
||||
if (dealerApply.applyTime) {
|
||||
setApplyTime(extractDateForCalendar(dealerApply.applyTime))
|
||||
}
|
||||
if (dealerApply.contractTime) {
|
||||
setContractTime(extractDateForCalendar(dealerApply.contractTime))
|
||||
}
|
||||
|
||||
Taro.setNavigationBarTitle({title: '签约'})
|
||||
}
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
console.error('查询申请记录失败:', error);
|
||||
setIsEditMode(false);
|
||||
setExistingApply(null);
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
// 计算保护期过期时间(7天后)
|
||||
const calculateExpirationTime = (): string => {
|
||||
const now = new Date();
|
||||
const expirationDate = new Date(now);
|
||||
expirationDate.setDate(now.getDate() + 7); // 7天后
|
||||
|
||||
// 格式化为数据库需要的格式:YYYY-MM-DD HH:mm:ss
|
||||
const year = expirationDate.getFullYear();
|
||||
const month = String(expirationDate.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(expirationDate.getDate()).padStart(2, '0');
|
||||
const hours = String(expirationDate.getHours()).padStart(2, '0');
|
||||
const minutes = String(expirationDate.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(expirationDate.getSeconds()).padStart(2, '0');
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 验证报备人是否存在
|
||||
if (values.userId > 0) {
|
||||
const isExist = await pageShopDealerUser({userId: Number(values.userId)});
|
||||
if(isExist && isExist.count == 0){
|
||||
Taro.showToast({
|
||||
title: '报备人不存在',
|
||||
icon: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查客户是否已存在
|
||||
const res = await pageShopDealerApply({dealerName: values.dealerName, type: 4, applyStatus: 10});
|
||||
|
||||
if (res && res.count > 0) {
|
||||
const existingCustomer = res.list[0];
|
||||
|
||||
// 检查是否在7天保护期内
|
||||
if (!isEditMode && existingCustomer.applyTime) {
|
||||
// 将申请时间字符串转换为时间戳进行比较
|
||||
const applyTimeStamp = new Date(existingCustomer.applyTime).getTime();
|
||||
const currentTimeStamp = new Date().getTime();
|
||||
const sevenDaysInMs = 7 * 24 * 60 * 60 * 1000; // 7天的毫秒数
|
||||
|
||||
// 如果在7天保护期内,不允许重复添加
|
||||
if (currentTimeStamp - applyTimeStamp < sevenDaysInMs) {
|
||||
const remainingDays = Math.ceil((sevenDaysInMs - (currentTimeStamp - applyTimeStamp)) / (24 * 60 * 60 * 1000));
|
||||
|
||||
Taro.showToast({
|
||||
title: `该客户还在保护期,还需等待${remainingDays}天后才能重新添加`,
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
// 超过7天保护期,可以重新添加,显示确认对话框
|
||||
const modalResult = await new Promise<boolean>((resolve) => {
|
||||
Taro.showModal({
|
||||
title: '提示',
|
||||
content: '该客户已超过7天保护期,是否重新添加跟进?',
|
||||
showCancel: true,
|
||||
cancelText: '取消',
|
||||
confirmText: '确定',
|
||||
success: (modalRes) => {
|
||||
resolve(modalRes.confirm);
|
||||
},
|
||||
fail: () => {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!modalResult) {
|
||||
return false; // 用户取消,不继续执行
|
||||
}
|
||||
// 用户确认后继续执行添加逻辑
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 计算过期时间
|
||||
const expirationTime = isEditMode ? existingApply?.expirationTime : calculateExpirationTime();
|
||||
|
||||
// 准备提交的数据
|
||||
const submitData = {
|
||||
...values,
|
||||
type: 4,
|
||||
realName: values.realName || user?.nickname,
|
||||
mobile: values.mobile,
|
||||
refereeId: referee?.refereeId,
|
||||
applyStatus: isEditMode ? 20 : 10,
|
||||
auditTime: undefined,
|
||||
// 设置保护期过期时间(7天后)
|
||||
expirationTime: expirationTime,
|
||||
// 确保日期数据正确提交(使用数据库格式)
|
||||
applyTime: values.applyTime || (applyTime ? formatDateForDatabase(applyTime) : ''),
|
||||
contractTime: values.contractTime || (contractTime ? formatDateForDatabase(contractTime) : '')
|
||||
};
|
||||
|
||||
// 调试信息
|
||||
console.log('=== 提交数据调试 ===');
|
||||
console.log('是否编辑模式:', isEditMode);
|
||||
console.log('计算的过期时间:', expirationTime);
|
||||
console.log('提交的数据:', submitData);
|
||||
console.log('==================');
|
||||
|
||||
// 如果是编辑模式,添加现有申请的id
|
||||
if (isEditMode && existingApply?.applyId) {
|
||||
submitData.applyId = existingApply.applyId;
|
||||
}
|
||||
|
||||
// 执行新增或更新操作
|
||||
if (isEditMode) {
|
||||
await updateShopDealerApply(submitData);
|
||||
} else {
|
||||
await addShopDealerApply(submitData);
|
||||
}
|
||||
|
||||
Taro.showToast({
|
||||
title: `${isEditMode ? '更新' : '提交'}成功`,
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
Taro.navigateBack();
|
||||
}, 1000);
|
||||
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error);
|
||||
Taro.showToast({
|
||||
title: '提交失败,请重试',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 处理固定按钮点击事件
|
||||
const handleFixedButtonClick = () => {
|
||||
// 触发表单提交
|
||||
formRef.current?.submit();
|
||||
};
|
||||
|
||||
const submitFailed = (error: any) => {
|
||||
console.log(error, 'err...')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload().then(() => {
|
||||
setLoading(false)
|
||||
}).catch((error) => {
|
||||
console.error('页面加载失败:', error);
|
||||
setLoading(false);
|
||||
Taro.showToast({
|
||||
title: '页面加载失败',
|
||||
icon: 'error'
|
||||
});
|
||||
})
|
||||
}, []); // 依赖用户ID,当用户变化时重新加载
|
||||
|
||||
if (loading) {
|
||||
return <Loading className={'px-2'}>加载中</Loading>
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form
|
||||
ref={formRef}
|
||||
divider
|
||||
initialValues={FormData}
|
||||
labelPosition="left"
|
||||
onFinish={(values) => submitSucceed(values)}
|
||||
onFinishFailed={(errors) => submitFailed(errors)}
|
||||
>
|
||||
<View className={'bg-gray-100 h-3'}></View>
|
||||
<CellGroup style={{padding: '4px 0'}}>
|
||||
<Form.Item name="dealerName" label="公司名称" initialValue={FormData?.dealerName} 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}/>
|
||||
</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 && (
|
||||
<>
|
||||
<Form.Item name="money" label="签约价格" initialValue={FormData?.money} required>
|
||||
<Input placeholder="(元/兆瓦时)" disabled={false}/>
|
||||
</Form.Item>
|
||||
<Form.Item name="applyTime" label="签约时间" initialValue={FormData?.applyTime}>
|
||||
<View
|
||||
className="flex items-center justify-between py-2"
|
||||
onClick={() => setShowApplyTimePicker(true)}
|
||||
>
|
||||
<View className="flex items-center">
|
||||
<CalendarIcon size={16} color="#999" className="mr-2"/>
|
||||
<Text style={{color: applyTime ? '#333' : '#999'}}>
|
||||
{applyTime ? formatDateForDisplay(applyTime) : '请选择签约时间'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Form.Item>
|
||||
<Form.Item name="contractTime" label="合同日期" initialValue={FormData?.contractTime}>
|
||||
<View
|
||||
className="flex items-center justify-between py-2"
|
||||
onClick={() => setShowContractTimePicker(true)}
|
||||
>
|
||||
<View className="flex items-center">
|
||||
<CalendarIcon size={16} color="#999" className="mr-2"/>
|
||||
<Text style={{color: contractTime ? '#333' : '#999'}}>
|
||||
{contractTime ? formatDateForDisplay(contractTime) : '请选择合同生效起止时间'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Form.Item>
|
||||
{/*<Form.Item name="refereeId" label="邀请人ID" initialValue={FormData?.refereeId} required>*/}
|
||||
{/* <Input placeholder="邀请人ID"/>*/}
|
||||
{/*</Form.Item>*/}
|
||||
</>
|
||||
)}
|
||||
<Form.Item name="userId" label="报备人(ID)" initialValue={FormData?.userId}>
|
||||
<Input
|
||||
placeholder="自己报备请留空"
|
||||
disabled={isEditMode}
|
||||
type="number"
|
||||
value={(FormData?.userId)?.toString() || ''}
|
||||
/>
|
||||
</Form.Item>
|
||||
</CellGroup>
|
||||
</Form>
|
||||
|
||||
{/* 签约时间选择器 */}
|
||||
<Calendar
|
||||
visible={showApplyTimePicker}
|
||||
defaultValue={applyTime}
|
||||
onClose={() => setShowApplyTimePicker(false)}
|
||||
onConfirm={handleApplyTimeConfirm}
|
||||
/>
|
||||
|
||||
{/* 合同日期选择器 */}
|
||||
<Calendar
|
||||
visible={showContractTimePicker}
|
||||
defaultValue={contractTime}
|
||||
onClose={() => setShowContractTimePicker(false)}
|
||||
onConfirm={handleContractTimeConfirm}
|
||||
/>
|
||||
|
||||
{/* 审核状态显示(仅在编辑模式下显示) */}
|
||||
{isEditMode && (
|
||||
<CellGroup>
|
||||
{/*<Cell*/}
|
||||
{/* title={'审核状态'}*/}
|
||||
{/* extra={*/}
|
||||
{/* <span style={{*/}
|
||||
{/* color: FormData?.applyStatus === 20 ? '#52c41a' :*/}
|
||||
{/* FormData?.applyStatus === 30 ? '#ff4d4f' : '#faad14'*/}
|
||||
{/* }}>*/}
|
||||
{/* {getApplyStatusText(FormData?.applyStatus)}*/}
|
||||
{/* </span>*/}
|
||||
{/* }*/}
|
||||
{/*/>*/}
|
||||
{FormData?.applyStatus === 20 && (
|
||||
<Cell title={'签约时间'} extra={FormData?.auditTime || '无'}/>
|
||||
)}
|
||||
{FormData?.applyStatus === 30 && (
|
||||
<Cell title={'驳回原因'} extra={FormData?.rejectReason || '无'}/>
|
||||
)}
|
||||
</CellGroup>
|
||||
)}
|
||||
|
||||
|
||||
{/* 底部浮动按钮 */}
|
||||
{(!isEditMode || FormData?.applyStatus === 10) && (
|
||||
<FixedButton
|
||||
icon={<Edit/>}
|
||||
text={'立即提交'}
|
||||
onClick={handleFixedButtonClick}
|
||||
/>
|
||||
)}
|
||||
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddShopDealerApply;
|
||||
Reference in New Issue
Block a user