Files
template-10582/src/dealer/customer/add.tsx
赵忠林 812df56f8c refactor(customer): 优化客户数据查询和表单字段校验
- 移除新增客户页面对手机号的必填和格式校验
- 修改手机号字段标签为“手机号/微信号”,取消必填和长度限制
- 新增判断当前用户是否为超级管理员逻辑
- 抽取并统一构建客户查询参数方法,根据权限动态设置筛选条件
- 优化客户列表数据获取逻辑,支持超级管理员查看全部客户
- 调整依赖项,更新使用了新构建的查询参数函数
- 增强状态统计接口参数构建,统一调用参数生成函数
- 优化副作用 Hook 依赖,保证数据加载时机正确
2026-06-04 15:21:56 +08:00

790 lines
29 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, useRef} from "react";
import {Loading, CellGroup, Cell, Input, Form, Calendar, Popup, SearchBar} from '@nutui/nutui-react-taro'
import {Edit, Calendar as CalendarIcon, ArrowRight, Del} from '@nutui/icons-react-taro'
import Taro from '@tarojs/taro'
import {useRouter} from '@tarojs/taro'
import {View, Text, ScrollView} from '@tarojs/components'
import FixedButton from "@/components/FixedButton";
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 {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 PROTECTION_DAYS = 15;
const DUP_CHECK_LIMIT = 200;
const DUP_CHECK_MAX_PAGES = 50;
// 房号信息:用 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 [showContractTimePicker, setShowContractTimePicker] = useState<boolean>(false)
const [applyTime, setApplyTime] = useState<string>('')
const [contractTime, setContractTime] = useState<string>('')
// 接待人员选择状态
const [showReceptionistPicker, setShowReceptionistPicker] = useState<boolean>(false)
const [receptionistSearch, setReceptionistSearch] = useState<string>('')
const [receptionistList, setReceptionistList] = useState<ShopDealerUser[]>([])
const [receptionistLoading, setReceptionistLoading] = useState<boolean>(false)
const [selectedReceptionist, setSelectedReceptionist] = useState<ShopDealerUser | null>(null)
// 获取审核状态文字
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))
}
// 回填接待人员
if (dealerApply.receptionistId) {
setSelectedReceptionist({
userId: dealerApply.receptionistId,
dealerName: dealerApply.receptionistName || '',
realName: dealerApply.receptionistName || '',
})
}
Taro.setNavigationBarTitle({title: '签约'})
}
} catch (error) {
setLoading(false)
console.error('查询申请记录失败:', error);
setIsEditMode(false);
setExistingApply(null);
}
}
// 加载接待人员列表
const loadReceptionistList = async (keyword?: string) => {
setReceptionistLoading(true)
try {
const res = await pageShopDealerUser({keywords: keyword || '', limit: 50, page: 1})
setReceptionistList(res?.list || [])
} catch (e) {
console.error('加载接待人员失败:', e)
} finally {
setReceptionistLoading(false)
}
}
// 打开接待人员选择
const openReceptionistPicker = () => {
setReceptionistSearch('')
loadReceptionistList()
setShowReceptionistPicker(true)
}
// 搜索接待人员
const handleReceptionistSearch = (val: string) => {
setReceptionistSearch(val)
loadReceptionistList(val)
}
// 选择接待人员
const handleSelectReceptionist = (user: ShopDealerUser) => {
setSelectedReceptionist(user)
setShowReceptionistPicker(false)
}
// 清除接待人员
const handleClearReceptionist = () => {
setSelectedReceptionist(null)
}
// 提交表单
// 计算保护期过期时间15天后
const calculateExpirationTime = (): string => {
const now = new Date();
const expirationDate = new Date(now);
expirationDate.setDate(now.getDate() + PROTECTION_DAYS); // 15天后
// 格式化为数据库需要的格式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 normalizeText = (v: any) => (v ?? '').toString().trim();
const toHalfWidth = (input: string) =>
(input || '').replace(/[\uFF01-\uFF5E]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 0xFEE0)).replace(/\u3000/g, ' ');
const parseChineseNumber = (s: string): number | null => {
const str = (s || '').trim();
if (!str) return null;
// 仅处理纯中文数字(含大小写)+ 单位
if (!/^[零〇一二三四五六七八九十百千万两兩俩壹贰叁肆伍陆柒捌玖拾佰仟萬]+$/.test(str)) return null;
const digitMap: Record<string, number> = {
: 0, : 0,
: 1, : 1,
: 2, : 2, : 2, : 2, : 2,
: 3, : 3,
: 4, : 4,
: 5, : 5,
: 6, : 6,
: 7, : 7,
: 8, : 8,
: 9, : 9,
};
const unitMap: Record<string, number> = {: 10, : 10, : 100, : 100, : 1000, : 1000, : 10000, : 10000};
let total = 0;
let section = 0;
let number = 0;
for (const ch of str) {
if (digitMap[ch] !== undefined) {
number = digitMap[ch];
continue;
}
const unit = unitMap[ch];
if (!unit) continue;
if (unit === 10000) {
section = (section + number) * unit;
total += section;
section = 0;
} else {
// “十/百/千”前省略“一”的情况:十=10、十二=12
const n = number === 0 ? 1 : number;
section += n * unit;
}
number = 0;
}
const result = total + section + number;
return Number.isFinite(result) ? result : null;
};
const normalizeCommunity = (community: string) => {
const s = toHalfWidth(normalizeText(community));
return s.replace(/\s+/g, '').toUpperCase();
};
const normalizeHouseNoPart = (raw: string, kind: 'building' | 'unit' | 'room') => {
let s = toHalfWidth(normalizeText(raw)).toUpperCase();
s = s.replace(/\s+/g, '');
// 去掉常见后缀/装饰词
if (kind === 'building') s = s.replace(/(号楼|栋|幢|楼)$/g, '');
if (kind === 'unit') s = s.replace(/(单元)$/g, '');
if (kind === 'room') s = s.replace(/(室|房|号)$/g, '');
// 只保留数字与字母,统一分隔符差异(如 12-01 / 12#01
s = s.replace(/[^0-9A-Z零一二三四五六七八九十百千万两兩俩壹贰叁肆伍陆柒捌玖拾佰仟萬]/g, '');
// 纯中文数字 => 阿拉伯数字(支持大小写)
const cn = parseChineseNumber(s);
if (cn !== null) return String(cn);
// 数字段去前导 0如 03A => 3A1201 不变)
s = s.replace(/\d+/g, (m) => String(parseInt(m, 10)));
return s;
};
const buildHouseKeyNormalized = (community: string, buildingNo: string, unitNo: string | undefined, roomNo: string) => {
const c = normalizeCommunity(community);
const b = normalizeHouseNoPart(buildingNo, 'building');
const u = normalizeHouseNoPart(unitNo || '', 'unit');
const r = normalizeHouseNoPart(roomNo, 'room');
return [c, b, u, r].join('|');
};
const getNormalizedHouseKeyFromApply = (apply: ShopDealerApply) => {
const parsed = parseHouseKey(apply.dealerCode);
return buildHouseKeyNormalized(
parsed.community || apply.address || '',
parsed.buildingNo || '',
parsed.unitNo || '',
parsed.roomNo || ''
);
};
const findExistingApplyByHouse = async (params: {houseKeyNormalized: string; houseKeyRaw: string; communityKeyword: string}) => {
const tryByDealerCode = async (dealerCode: string) => {
const res = await pageShopDealerApply({dealerCode, type: 4});
return res?.list?.[0] as ShopDealerApply | undefined;
};
const keys = Array.from(new Set([params.houseKeyNormalized, params.houseKeyRaw].filter(Boolean)));
for (const k of keys) {
const hit = await tryByDealerCode(k);
if (hit) return hit;
}
// 兼容历史数据:用关键词拉取附近数据,再用“规范化后的 houseKey”对比
const keyword = normalizeText(params.communityKeyword);
if (!keyword) return null;
for (let page = 1; page <= DUP_CHECK_MAX_PAGES; page++) {
const res = await pageShopDealerApply({type: 4, keywords: keyword, page, limit: DUP_CHECK_LIMIT});
const list = res?.list || [];
for (const item of list) {
if (getNormalizedHouseKeyFromApply(item) === params.houseKeyNormalized) return item;
}
if (list.length < DUP_CHECK_LIMIT) break;
}
return null;
};
const submitSucceed = async (values: any) => {
try {
const currentUserId = Number(Taro.getStorageSync('UserId')) || 0;
// 房号相关必填校验
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;
}
// 规范化报备人:留空=自己报备(当前登录用户)
const rawUserId = normalizeText(values.userId);
const submitUserId = rawUserId
? Number(rawUserId)
: (isEditMode ? (existingApply?.userId || currentUserId) : currentUserId);
if (!Number.isFinite(submitUserId) || submitUserId <= 0) {
Taro.showToast({title: '请填写正确的报备人ID', icon: 'error'});
return;
}
// 报备人存在性校验 + 获取该报备人的推荐人(用于后端展示链路)
let reporterDealerUser: ShopDealerUser | undefined = undefined;
if (submitUserId === currentUserId) {
reporterDealerUser = referee;
} else {
try {
reporterDealerUser = await getShopDealerUser(submitUserId);
} catch {
Taro.showToast({title: '报备人不存在', icon: 'error'});
return;
}
}
// 后端常用 0 表示“无推荐人”,避免传空值触发“推荐人不存在”
const submitRefereeId = (reporterDealerUser?.refereeId && reporterDealerUser.refereeId > 0)
? reporterDealerUser.refereeId
: undefined;
const houseKeyRaw = buildHouseKey(values.address, values.buildingNo, values.unitNo, values.roomNo);
const houseKeyNormalized = buildHouseKeyNormalized(values.address, values.buildingNo, values.unitNo, values.roomNo);
const houseKey = houseKeyNormalized || houseKeyRaw;
const houseDisplay = buildHouseDisplay(values.address, values.buildingNo, values.unitNo, values.roomNo);
// 新增报备:提交前检查房号是否已报备(按 小区+楼栋+单元+房号 判断,且做规范化)
if (!isEditMode) {
const existingCustomer = await findExistingApplyByHouse({
houseKeyNormalized,
houseKeyRaw,
communityKeyword: values.address
});
if (existingCustomer) {
// 报备人不同:直接拦截(避免跨报备人“抢单/续报”)
const existingReporterId = Number(existingCustomer.userId);
if (Number.isFinite(existingReporterId) && existingReporterId > 0 && existingReporterId !== submitUserId) {
Taro.showToast({
title: '请改房号,该房号信息已报备',
icon: 'none',
duration: 2500
});
return false;
}
// 已签约/已取消:直接提示已报备
if (existingCustomer.applyStatus && existingCustomer.applyStatus !== 10) {
Taro.showToast({
title: `该房号信息已报备(${getApplyStatusText(existingCustomer.applyStatus)}),本次报备未生效`,
icon: 'none',
duration: 2500
});
return false;
}
// 跟进中:保护期逻辑
if (existingCustomer.applyTime) {
const applyTimeStamp = new Date(existingCustomer.applyTime).getTime();
const currentTimeStamp = new Date().getTime();
const protectionMs = PROTECTION_DAYS * 24 * 60 * 60 * 1000;
if (currentTimeStamp - applyTimeStamp < protectionMs) {
const remainingDays = Math.ceil((protectionMs - (currentTimeStamp - applyTimeStamp)) / (24 * 60 * 60 * 1000));
Taro.showToast({
title: `该房号信息已报备(${getApplyStatusText(existingCustomer.applyStatus)}),保护期剩余${remainingDays}天,本次报备未生效`,
icon: 'none',
duration: 3000
});
return false;
}
// 超过保护期:询问是否重新报备
const modalResult = await new Promise<boolean>((resolve) => {
Taro.showModal({
title: '提示',
content: `该房号已超过${PROTECTION_DAYS}天保护期,是否重新报备跟进?`,
showCancel: true,
cancelText: '取消',
confirmText: '确定',
success: (modalRes) => resolve(modalRes.confirm),
fail: () => resolve(false)
});
});
if (!modalResult) return false;
} else {
Taro.showToast({
title: `该房号信息已报备(${getApplyStatusText(existingCustomer.applyStatus)}),本次报备未生效`,
icon: 'none',
duration: 2500
});
return false;
}
}
}
// 计算过期时间
const expirationTime = isEditMode ? existingApply?.expirationTime : calculateExpirationTime();
// 准备提交的数据
// 避免把表单里的楼栋/单元/房号等临时字段原样提交给后端
const {buildingNo, unitNo, roomNo, ...restValues} = values;
const submitData = {
...restValues,
type: 4,
// 展示用:小区+楼栋+单元+房号
dealerName: houseDisplay,
// 唯一键:用于后续重复报备提示
dealerCode: houseKey,
// 客户姓名/手机号
realName: values.realName,
mobile: values.mobile,
// 报备人(留空时用当前登录用户)
// userId: submitUserId,
// 推荐人(报备人的上级;无则传 0
refereeId: submitRefereeId,
applyStatus: isEditMode ? 20 : 10,
auditTime: undefined,
// 设置保护期过期时间15天后
expirationTime: expirationTime,
// 确保日期数据正确提交(使用数据库格式)
applyTime: values.applyTime || (applyTime ? formatDateForDatabase(applyTime) : ''),
contractTime: values.contractTime || (contractTime ? formatDateForDatabase(contractTime) : ''),
// 接待人员
receptionistId: selectedReceptionist?.userId || undefined,
receptionistName: selectedReceptionist ? (selectedReceptionist.realName || selectedReceptionist.dealerName || '') : undefined,
};
// 调试信息
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当用户变化时重新加载
// 编辑模式下,从 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
});
}, [FormData]);
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)}
>
<CellGroup style={{padding: '0'}}>
{/* 接待人员选择 */}
<Cell
title="接待人员"
extra={
<View className="flex items-center">
{selectedReceptionist ? (
<View className="flex items-center">
<Text className="text-sm text-gray-800 mr-2">
{selectedReceptionist.realName || selectedReceptionist.dealerName || '已选择'}
</Text>
<View
onClick={(e) => { e.stopPropagation(); handleClearReceptionist(); }}
className="flex items-center px-1"
>
<Del size={14} color="#999"/>
</View>
</View>
) : (
<Text className="text-sm text-gray-400"></Text>
)}
<ArrowRight size={14} color="#ccc"/>
</View>
}
onClick={openReceptionistPicker}
/>
<View className={'bg-gray-100 h-2'}></View>
<Form.Item name="address" label="小区" initialValue={FormData?.address} required>
<Input placeholder="如:幸福里小区" disabled={isEditMode}/>
</Form.Item>
<Form.Item name="buildingNo" label="楼栋号" required>
<Input placeholder="如(只填写数字)3" disabled={isEditMode}/>
</Form.Item>
<Form.Item name="unitNo" label="单元号">
<Input placeholder="如(只填写数字)1" disabled={isEditMode}/>
</Form.Item>
<Form.Item name="roomNo" label="房号" required>
<Input placeholder="如(只填写数字)1201" 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}/>
</Form.Item>
<Form.Item name="comments" label="备注" initialValue={FormData?.comments}>
<Input placeholder="请输入备注信息" />
</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"*/}
{/* />*/}
{/*</Form.Item>*/}
</CellGroup>
</Form>
{/* 签约时间选择器 */}
<Calendar
visible={showApplyTimePicker}
defaultValue={applyTime}
onClose={() => setShowApplyTimePicker(false)}
onConfirm={handleApplyTimeConfirm}
/>
{/* 合同日期选择器 */}
<Calendar
visible={showContractTimePicker}
defaultValue={contractTime}
onClose={() => setShowContractTimePicker(false)}
onConfirm={handleContractTimeConfirm}
/>
{/* 接待人员选择弹出层 */}
<Popup
visible={showReceptionistPicker}
position="bottom"
round
onClose={() => setShowReceptionistPicker(false)}
style={{height: '70vh'}}
>
<View style={{height: '100%', display: 'flex', flexDirection: 'column'}}>
{/* 标题栏 */}
<View className="flex items-center justify-between px-4 py-3 border-b border-gray-100">
<Text className="text-base font-semibold text-gray-800"></Text>
<View onClick={() => setShowReceptionistPicker(false)}>
<Text className="text-sm text-blue-500"></Text>
</View>
</View>
{/* 搜索框 */}
<View className="px-3 py-2">
<SearchBar
value={receptionistSearch}
placeholder="搜索姓名/手机号"
onChange={handleReceptionistSearch}
/>
</View>
{/* 列表 */}
<ScrollView
scrollY
style={{flex: 1, minHeight: 0, height: 'calc(70vh - 112px)'}}
>
{receptionistLoading ? (
<View className="flex justify-center items-center py-8">
<Loading></Loading>
</View>
) : receptionistList.length === 0 ? (
<View className="flex justify-center items-center py-8">
<Text className="text-sm text-gray-400"></Text>
</View>
) : (
receptionistList.map((user) => (
<Cell
key={user.userId}
title={user.realName || user.dealerName || '未知'}
description={user.mobile || user.dealerPhone || ''}
extra={
selectedReceptionist?.userId === user.userId ? (
<Text className="text-sm text-blue-500"></Text>
) : null
}
onClick={() => handleSelectReceptionist(user)}
/>
))
)}
</ScrollView>
</View>
</Popup>
{/* 审核状态显示(仅在编辑模式下显示) */}
{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;