ERPTurbo_Client/packages/app-client/src/components/order/module/StallInfo.tsx
2025-12-29 23:52:15 +08:00

1237 lines
40 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 { Image, Text, View } from "@tarojs/components";
import { Button, Dialog, Input, Radio, Toast } from "@nutui/nutui-react-taro";
import { Icon, SupplierPicker } from "@/components";
import Taro from "@tarojs/taro";
import { forwardRef, useImperativeHandle, useState } from "react";
import { buildUrl, generateShortId, uploadFile } from "@/utils";
import { globalStore } from "@/store/global-store";
// 定义ref暴露的方法接口
export interface StallInfoRef {
validate: () => boolean;
}
interface IStallInfoProps {
index: number;
value: BusinessAPI.OrderVO;
onChange: (orderVO: BusinessAPI.OrderVO) => void;
}
export default forwardRef<StallInfoRef, IStallInfoProps>(
function StallInfo(props, ref) {
const [showSupplierPicker, setShowSupplierPicker] = useState(false);
const onRemove = (supplierVO: BusinessAPI.OrderSupplier) => {
if (orderSupplierList.length <= 1) {
setOrderSupplierList([
{
orderSupplierId: generateShortId(),
supplierId: "", // 空的supplierId表示其他家档口
name: "",
payeeName: "",
bankName: "",
bankCard: "",
phone: "",
type: "",
selected: true,
isPaper: false,
orderPackageList: [],
packageUsage: [
{
boxType: "USED",
isUsed: 0,
},
],
} as any,
]);
return;
} else {
let temp = orderSupplierList.filter(
(item: BusinessAPI.OrderSupplier) =>
item.orderSupplierId !== supplierVO.orderSupplierId,
) as BusinessAPI.OrderSupplier[];
temp[0].selected = true;
setOrderSupplierList(temp);
}
};
const { value, onChange, index } = props;
const { orderSupplierList } = value;
const supplierVO = orderSupplierList[index] as BusinessAPI.OrderSupplier;
const supplierCount = orderSupplierList.length;
const isLast = index === supplierCount - 1;
const { setLoading } = globalStore((state: any) => state);
// 获取已选择的供应商ID列表排除当前项
const selectedSupplierIds = orderSupplierList
.filter((supplier, idx) => idx !== index && supplier.supplierId)
.map((supplier) => supplier.supplierId!);
// 获取已选择的供应商ID列表排除当前项
const selectedSupplierNames = orderSupplierList
.filter((supplier, idx) => idx !== index && supplier.supplierId)
.map((supplier) => supplier.name!);
const setOrderSupplierList = (
newOrderSupplierList: BusinessAPI.OrderSupplier[],
) => {
onChange({
...value,
orderSupplierList: newOrderSupplierList,
});
};
const setSupplierVO = (newSupplierVO: BusinessAPI.OrderSupplier) => {
console.log("setSupplierVO", newSupplierVO);
setOrderSupplierList([
...orderSupplierList.map((item: BusinessAPI.OrderSupplier) => {
if (item.orderSupplierId == newSupplierVO.orderSupplierId) {
return {
...item,
...newSupplierVO,
};
}
return item;
}),
]);
};
// 微信收款码上传处理函数
const handleWechatQrUpload = async () => {
await Taro.chooseImage({
count: 1,
sourceType: ["album", "camera"],
success: (res) => {
setLoading(true);
const file = res.tempFiles[0];
uploadFile(file.path)
.then(({ url }) => {
setSupplierVO({
...supplierVO,
wechatQr: url,
});
setLoading(false);
Toast.show("toast", {
title: "上传成功",
icon: "success",
content: "微信收款码已上传",
});
})
.catch((err) => {
Toast.show("toast", {
title: "上传失败",
icon: "fail",
content: err.message || "上传过程中发生错误",
});
setLoading(false);
});
},
fail: (err) => {
Toast.show("toast", {
title: "选择图片失败",
icon: "fail",
content: err.errMsg,
});
},
});
};
// 校验状态
const [nameError, setNameError] = useState<{ [key: string]: boolean }>({});
const [payeeNameError, setPayeeNameError] = useState<{
[key: string]: boolean;
}>({});
const [bankCardError, setBankCardError] = useState<{
[key: string]: boolean;
}>({});
const [bankNameError, setBankNameError] = useState<{
[key: string]: boolean;
}>({});
const [phoneError, setPhoneError] = useState<{
[key: string]: boolean;
}>({});
const [isLastFarmerError, setIsLastFarmerError] = useState<{
[key: string]: boolean;
}>({}); // 添加是否要拼车的错误状态
// 校验姓名函数
const validateName = (name: string) => {
if (!name) {
return false;
}
// 姓名至少2个字符
return name.length >= 2;
};
// 校验身份证号函数
const validatePayeeName = (payeeName: string) => {
if (!payeeName) {
return false;
}
// 收款人姓名至少2个字符
return payeeName.length >= 2;
};
// 校验银行卡号函数
const validateBankCard = (bankCard: string) => {
if (!bankCard) {
return false;
}
// 银行卡号一般为16-19位数字
const bankCardRegex = /^\d{16,19}$/;
return bankCardRegex.test(bankCard);
};
// 校验银行名称函数
const validateBankName = (bankName: string) => {
if (!bankName) {
return false;
}
// 银行名称至少2个字符
return bankName.length >= 2;
};
// 校验手机号函数
const validatePhone = (phone: string) => {
if (!phone) {
return false;
}
// 使用项目规范的手机号正则表达式
const phoneRegex = /^1[3456789]\d{9}$/;
return phoneRegex.test(phone);
};
// 校验是否要拼车函数
const validateIsLastFarmer = (isLast?: boolean) => {
// 必须选择要不要
return isLast !== undefined;
};
// 对外暴露的校验方法
const validate = () => {
const id = supplierVO?.orderSupplierId;
if (!id) return false;
const isNameValid = validateName(supplierVO.name || "");
if (
selectedSupplierNames &&
selectedSupplierNames.includes(supplierVO.name || "")
) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "该档口已被选择,请输入其他名称",
});
return false;
}
// 根据档口类型决定是否校验收款信息
const isPayeeNameValid =
supplierVO.type === "STALL"
? true // 自家档口不需要校验收款人姓名
: validatePayeeName(supplierVO.payeeName || "");
const isBankNameValid =
supplierVO.type === "STALL"
? true // 自家档口不需要校验银行名称
: validateBankName(supplierVO.bankName || "");
const isBankCardValid =
supplierVO.type === "STALL"
? true // 自家档口不需要校验银行卡号
: validateBankCard(supplierVO.bankCard || "");
const isPhoneValid =
supplierVO.type === "STALL"
? true // 自家档口不需要校验手机号
: validatePhone(supplierVO.phone || "");
const isLastFarmerValid = validateIsLastFarmer(supplierVO?.isLast); // 校验是否需要拼车
// 更新错误状态
setNameError((prev) => ({
...prev,
[id]: !isNameValid,
}));
setPayeeNameError((prev) => ({
...prev,
[id]: supplierVO.type === "STALL" ? false : !isPayeeNameValid,
}));
setBankNameError((prev) => ({
...prev,
[id]: supplierVO.type === "STALL" ? false : !isBankNameValid,
}));
setBankCardError((prev) => ({
...prev,
[id]: supplierVO.type === "STALL" ? false : !isBankCardValid,
}));
setPhoneError((prev) => ({
...prev,
[id]: supplierVO.type === "STALL" ? false : !isPhoneValid,
}));
// 更新是否为最后一个档口的错误状态
setIsLastFarmerError((prev) => ({
...prev,
[id]: !isLastFarmerValid,
}));
const isValid =
isNameValid &&
isPayeeNameValid &&
isBankNameValid &&
isBankCardValid &&
isPhoneValid &&
isLastFarmerValid;
if (!isValid) {
const errorMsg =
supplierVO.type === "STALL"
? "请选择自家档口"
: "请完善其他家档口信息";
Toast.show("toast", {
icon: "fail",
title: "提示",
content: errorMsg,
});
}
return isValid;
};
// 将校验方法暴露给父组件
useImperativeHandle(ref, () => ({
validate,
}));
// 处理姓名变化
const handleNameChange = (
value: string,
supplierVO: BusinessAPI.OrderSupplier,
) => {
setSupplierVO({
...supplierVO!,
name: value,
});
const id = supplierVO.orderSupplierId;
// 校验并更新错误状态
const isValid = validateName(value);
setNameError((prev) => ({
...prev,
[id]: !isValid && value !== "",
}));
if (isValid) {
setNameError((prev) => ({
...prev,
[id]: false,
}));
}
if (selectedSupplierNames && selectedSupplierNames.includes(value)) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "该档口已被选择,请输入其他名称",
});
}
};
// 处理姓名失焦
const handleNameBlur = async (value: string, id: any) => {
if (value && !validateName(value)) {
setNameError((prev) => ({
...prev,
[id]: true,
}));
return;
} else {
setNameError((prev) => ({
...prev,
[id]: false,
}));
}
};
// 处理收款人姓名变化
const handlePayeeNameChange = (
value: string,
supplierVO: BusinessAPI.OrderSupplier,
) => {
setSupplierVO({
...supplierVO,
payeeName: value,
});
const id = supplierVO.orderSupplierId;
// 校验并更新错误状态
const isValid = validatePayeeName(value);
setPayeeNameError((prev) => ({
...prev,
[id]: !isValid && value !== "",
}));
if (isValid) {
setPayeeNameError((prev) => ({
...prev,
[id]: false,
}));
}
};
// 处理收款人姓名失焦
const handlePayeeNameBlur = (value: string, id: any) => {
if (value && !validatePayeeName(value)) {
setPayeeNameError((prev) => ({
...prev,
[id]: true,
}));
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "请输入正确的收款人姓名",
});
} else {
setPayeeNameError((prev) => ({
...prev,
[id]: false,
}));
}
};
// 处理银行卡号变化
const handleBankCardChange = (
value: string,
supplierVO: BusinessAPI.OrderSupplier,
) => {
setSupplierVO({
...supplierVO,
bankCard: value,
});
const id = supplierVO.orderSupplierId;
// 校验并更新错误状态
const isValid = validateBankCard(value);
setBankCardError((prev) => ({
...prev,
[id]: !isValid && value !== "",
}));
if (isValid) {
setBankCardError((prev) => ({
...prev,
[id]: false,
}));
}
};
// 处理银行卡号失焦
const handleBankCardBlur = (value: string, id: any) => {
if (value && !validateBankCard(value)) {
setBankCardError((prev) => ({
...prev,
[id]: true,
}));
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "请输入正确的银行卡号",
});
} else {
setBankCardError((prev) => ({
...prev,
[id]: false,
}));
}
};
// 处理银行名称变化
const handleBankNameChange = (
value: string,
supplierVO: BusinessAPI.OrderSupplier,
) => {
setSupplierVO({
...supplierVO,
bankName: value,
});
const id = supplierVO.orderSupplierId;
// 校验并更新错误状态
const isValid = validateBankName(value);
setBankNameError((prev) => ({
...prev,
[id]: !isValid && value !== "",
}));
if (isValid) {
setBankNameError((prev) => ({
...prev,
[id]: false,
}));
}
};
// 处理银行名称失焦
const handleBankNameBlur = (value: string, id: any) => {
if (value && !validateBankName(value)) {
setBankNameError((prev) => ({
...prev,
[id]: true,
}));
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "请输入正确的银行名称",
});
} else {
setBankNameError((prev) => ({
...prev,
[id]: false,
}));
}
};
// 处理手机号变化
const handlePhoneChange = (
value: string,
supplierVO: BusinessAPI.OrderSupplier,
) => {
setSupplierVO({
...supplierVO,
phone: value,
});
const id = supplierVO.orderSupplierId;
// 校验并更新错误状态
const isValid = validatePhone(value);
setPhoneError((prev) => ({
...prev,
[id]: !isValid && value !== "",
}));
if (isValid) {
setPhoneError((prev) => ({
...prev,
[id]: false,
}));
}
};
// 处理手机号失焦
const handlePhoneBlur = (value: string, id: any) => {
if (value && !validatePhone(value)) {
setPhoneError((prev) => ({
...prev,
[id]: true,
}));
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "请输入正确的手机号",
});
} else {
setPhoneError((prev) => ({
...prev,
[id]: false,
}));
}
};
// 处理删除档口确认
const handleRemoveConfirm = (supplierVO: BusinessAPI.OrderSupplier) => {
Dialog.open("dialog", {
title: "移除档口",
content: `确定要移除"${supplierVO.name || "这个档口"}"吗?移除后如果需要可以重新添加。`,
onConfirm: () => {
onRemove(supplierVO);
Dialog.close("dialog");
},
onCancel: () => {
Dialog.close("dialog");
},
});
};
console.log("supplierVO", supplierVO);
if (!supplierVO) {
return;
}
return (
<View
className="flex flex-1 flex-col gap-2.5 p-2.5"
style={{
//@ts-ignore
"--nutui-input-padding": 0,
}}
>
{/* 功能提醒 */}
<View className="flex items-center rounded-lg border border-blue-200 bg-blue-50 p-2.5">
<Icon
className={"mr-1"}
name="circle-info"
color={"var(--color-blue-700)"}
size={18}
/>
<View className={"text-sm text-blue-700"}>
</View>
</View>
{/* 只有最后一个档口才显示是否为最后一个档口的选项和添加按钮 */}
{isLast && (
<View className="border-primary rounded-lg border-4 bg-white p-2.5 shadow-sm">
<View className="flex items-center justify-between">
{supplierCount > 1 ? (
<View className="text-sm"></View>
) : (
<View className="text-sm"></View>
)}
<View className="text-neutral-darkest text-sm font-medium">
<Radio.Group
direction="horizontal"
value={
supplierVO.isLast === true
? "true"
: supplierVO.isLast === false
? "false"
: undefined
}
onChange={(value) => {
// 清除错误状态
setIsLastFarmerError((prev) => ({
...prev,
[supplierVO.orderSupplierId]: false,
}));
// 根据用户选择设置是否为最后一个档口
const isLastValue =
value === "true"
? true
: value === "false"
? false
: undefined;
setSupplierVO({
...supplierVO,
// @ts-ignore
isLast: isLastValue,
});
}}
>
<Radio value="false"></Radio>
<Radio value="true"></Radio>
</Radio.Group>
</View>
</View>
{isLastFarmerError[supplierVO.orderSupplierId] && (
<View className="mt-1 text-xs text-red-500">
</View>
)}
</View>
)}
{/* 档口类型选择卡片 */}
<View className="border-primary rounded-lg border-4 bg-white p-2.5 shadow-sm">
<View className="text-primary mb-2.5 text-base font-bold">
</View>
{/* 自家档口选项 */}
<View
className={`mb-2.5 flex cursor-pointer items-center rounded-lg border-2 p-2.5 transition-colors ${
supplierVO.type === "STALL"
? "border-blue-500 bg-blue-50"
: "border-gray-200 hover:border-gray-300 hover:bg-gray-50"
}`}
onClick={() => {
// 自家档口需要选择供应商
setSupplierVO({
...supplierVO,
supplierId: "",
name: "",
payeeName: "",
bankName: "",
bankCard: "",
phone: "",
wechatQr: undefined,
type: "STALL",
});
setShowSupplierPicker(true);
}}
>
<Radio
value="OWN"
className="mr-2.5"
checked={supplierVO.type === "STALL"}
onChange={() => {
// 自家档口需要选择供应商
setSupplierVO({
...supplierVO,
supplierId: "",
name: "",
payeeName: "",
bankName: "",
bankCard: "",
phone: "",
wechatQr: undefined,
type: "STALL",
});
setShowSupplierPicker(true);
}}
/>
<View className="flex-1">
<View className="font-medium text-gray-900"></View>
<View className="text-sm text-gray-600">
</View>
</View>
</View>
{/* 其他家档口选项 */}
<View
className={`flex cursor-pointer items-center rounded-lg border-2 p-2.5 transition-colors ${
supplierVO.type === "OTHER_STALL"
? "border-blue-500 bg-blue-50"
: "border-gray-200 hover:border-gray-300 hover:bg-gray-50"
}`}
onClick={() => {
// 其他家档口需要清空供应商ID
setSupplierVO({
...supplierVO,
supplierId: "",
name: "",
payeeName: "",
bankName: "",
bankCard: "",
phone: "",
wechatQr: undefined,
type: "OTHER_STALL",
});
}}
>
<Radio
value="EXTERNAL"
className="mr-2.5"
checked={supplierVO.type === "OTHER_STALL"}
onChange={() => {
// 其他家档口需要清空供应商ID
setSupplierVO({
...supplierVO,
supplierId: "",
name: "",
payeeName: "",
bankName: "",
bankCard: "",
phone: "",
wechatQr: undefined,
type: "OTHER_STALL",
});
}}
/>
<View className="flex-1">
<View className="font-medium text-gray-900"></View>
<View className="text-sm text-gray-600">
</View>
</View>
</View>
</View>
{/* 快捷工具 */}
{supplierVO.type === "OTHER_STALL" && (
<View className="flex gap-2">
<View className={"flex-1"}>
<Button
block
icon={<Icon name={"credit-card"} size={28} color={"white"} />}
type={"primary"}
size={"large"}
className="bg-primary flex flex-1 items-center justify-center text-white"
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/public/camera/ocr", {
type: "bankcard",
}),
complete: () => {
Taro.eventCenter.on("ocr", (res) => {
console.log("识别结果为:", res.result);
setSupplierVO({
...supplierVO,
bankCard: res.result.number,
});
Taro.eventCenter.off("ocr");
});
},
});
}}
>
<View></View>
</Button>
</View>
</View>
)}
{/* 档口信息 */}
<View className="border-primary rounded-lg border-4 bg-white p-2.5 shadow-sm">
<View className="flex flex-col gap-2.5">
<View className="flex items-center justify-between">
<View className="text-primary text-base font-bold">
{supplierVO.name || "档口"}
</View>
{supplierCount > 1 && isLast && (
<View
className="cursor-pointer text-sm text-red-500"
onClick={() => handleRemoveConfirm(supplierVO)}
>
</View>
)}
</View>
{/* 根据档口类型显示不同的表单内容 */}
{supplierVO.type === "STALL" && (
// 自家档口:显示档口选择器
<>
<View className="flex flex-row justify-between">
<View className={"block text-sm font-normal text-[#000000]"}>
</View>
<SupplierPicker
type={"STALL"}
trigger={
<View className="flex items-center">
<Icon
className={"mr-1 leading-4"}
name="address-book"
size={16}
color="var(--color-primary)"
/>
<Text className={"text-primary ml-1 text-sm font-bold"}>
</Text>
</View>
}
onFinish={(supplierVO1) => {
// 检查是否已经选择了该档口
if (
selectedSupplierIds &&
selectedSupplierIds.includes(supplierVO1.supplierId!)
) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "该档口已被选择,请选择其他档口",
});
return;
}
setSupplierVO({
...supplierVO,
...supplierVO1,
// 自家档口时清空收款信息
payeeName: "",
bankName: "",
bankCard: "",
phone: "",
wechatQr: undefined,
});
// 清除所有错误状态
setNameError((prev) => ({
...prev,
[supplierVO.orderSupplierId]: false,
}));
}}
/>
</View>
{supplierVO.name ? (
<View className="rounded-lg bg-green-50 p-2.5">
<View className="flex items-center">
<Icon
name="circle-check"
size={16}
color="var(--color-green-600)"
className="mr-2"
/>
<View>
<View className="font-medium text-green-700">
{supplierVO.name}
</View>
<View className="text-sm text-green-600">
</View>
</View>
</View>
</View>
) : (
<View className="rounded-lg bg-yellow-50 p-2.5">
<View className="flex items-center">
<Icon
name="exclamation"
size={16}
color="var(--color-yellow-600)"
className="mr-2"
/>
<View className="text-sm text-yellow-700">
</View>
</View>
</View>
)}
</>
)}
{supplierVO.type === "OTHER_STALL" && (
// 其他家档口:显示完整的表单
<>
<View className="flex flex-row justify-between">
<View className={"block text-sm font-normal text-[#000000]"}>
</View>
<SupplierPicker
type={"OTHER_STALL"}
trigger={
<View className="flex items-center">
<Icon
className={"mr-1 leading-4"}
name="address-book"
size={16}
color="var(--color-primary)"
/>
<Text className={"text-primary ml-1 text-sm font-bold"}>
</Text>
</View>
}
onFinish={(supplierVO1) => {
// 检查是否已经选择了该档口
if (
selectedSupplierIds &&
selectedSupplierIds.includes(supplierVO1.supplierId!)
) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "该档口已被选择,请选择其他档口",
});
return;
}
setSupplierVO({
...supplierVO,
...supplierVO1,
});
// 清除所有错误状态
setNameError((prev) => ({
...prev,
[supplierVO.orderSupplierId]: false,
}));
}}
/>
</View>
<View
className={`flex h-10 w-full items-center rounded-md ${nameError[supplierVO.orderSupplierId] ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
>
<Icon name="user" size={16} color="#999" className="mx-2" />
<Input
clearable
type="text"
placeholder="请输入档口名称"
value={supplierVO.name}
onChange={(value) => handleNameChange(value, supplierVO)}
onBlur={() =>
handleNameBlur(
supplierVO?.name || "",
supplierVO.orderSupplierId,
)
}
className="flex-1"
/>
</View>
{nameError[supplierVO.orderSupplierId] && (
<View className="mt-1 text-xs text-red-500">
{`档口名称"${supplierVO.name}"至少2个字符`}
</View>
)}
<View className="block text-sm font-normal text-[#000000]">
</View>
<View
className={`flex h-10 w-full items-center rounded-md ${payeeNameError[supplierVO.orderSupplierId] ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
>
<Icon name="user" size={16} color="#999" className="mx-2" />
<Input
clearable
type="text"
placeholder="请输入收款人姓名"
value={supplierVO.payeeName}
onChange={(value) =>
handlePayeeNameChange(value, supplierVO)
}
onBlur={() =>
handlePayeeNameBlur(
supplierVO?.payeeName || "",
supplierVO.orderSupplierId,
)
}
className="flex-1"
/>
</View>
{payeeNameError[supplierVO.orderSupplierId] && (
<View className="mt-1 text-xs text-red-500">
{`收款人姓名至少2个字符`}
</View>
)}
<View className="block text-sm font-normal text-[#000000]">
</View>
<View
className={`flex h-10 w-full items-center rounded-md ${bankNameError[supplierVO.orderSupplierId] ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
>
<Icon
name="building"
size={16}
color="#999"
className="mx-2"
/>
<Input
clearable
type="text"
placeholder="请输入银行名称"
value={supplierVO.bankName}
onChange={(value) =>
handleBankNameChange(value, supplierVO)
}
onBlur={() =>
handleBankNameBlur(
supplierVO?.bankName || "",
supplierVO.orderSupplierId,
)
}
className="flex-1"
/>
</View>
{bankNameError[supplierVO.orderSupplierId] && (
<View className="text-xs text-red-500">
{`银行名称"${supplierVO.bankName}"至少2个字符`}
</View>
)}
<View className="block text-sm font-normal text-[#000000]">
</View>
<View
className={`flex h-10 w-full items-center rounded-md ${bankCardError[supplierVO.orderSupplierId] ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
>
<Icon
name="credit-card"
size={16}
color="#999"
className="mx-2"
/>
<Input
clearable
type="digit"
placeholder="请输入银行卡号"
value={supplierVO.bankCard}
onChange={(value) =>
handleBankCardChange(value, supplierVO)
}
onBlur={() =>
handleBankCardBlur(
supplierVO?.bankCard || "",
supplierVO.orderSupplierId,
)
}
className="flex-1"
/>
</View>
{bankCardError[supplierVO.orderSupplierId] && (
<View className="text-xs text-red-500">
</View>
)}
<View className="block text-sm font-normal text-[#000000]">
</View>
<View
className={`flex h-10 w-full items-center rounded-md ${phoneError[supplierVO.orderSupplierId] ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
>
<Icon name="phone" size={16} color="#999" className="mx-2" />
<Input
clearable
type="tel"
placeholder="请输入手机号码"
value={supplierVO.phone}
onChange={(value) => handlePhoneChange(value, supplierVO)}
onBlur={() =>
handlePhoneBlur(
supplierVO?.phone || "",
supplierVO.orderSupplierId,
)
}
className="flex-1"
/>
</View>
{phoneError[supplierVO.orderSupplierId] && (
<View className="text-xs text-red-500">
</View>
)}
</>
)}
</View>
</View>
{/* 只有其他家档口才显示微信收款码部分 */}
{supplierVO.type === "OTHER_STALL" && (
<View className="border-primary rounded-lg border-4 bg-white p-2.5 shadow-sm">
<View className="flex flex-col gap-2.5">
<View className="text-primary text-base font-bold">
{supplierVO.name || "档口"}
</View>
{supplierVO.wechatQr ? (
<View className="flex flex-col gap-2.5 rounded-lg bg-green-50 p-2.5">
<View className="flex items-center">
<View className="relative mr-3 h-20 w-20 overflow-hidden rounded-lg">
<Image
className="h-full w-full object-cover"
src={supplierVO.wechatQr}
/>
</View>
<View className="flex-1">
<View className="font-medium text-green-700">
</View>
<View className="text-sm text-green-600"></View>
<View className="text-neutral-darker mt-1 text-xs">
</View>
</View>
</View>
<View className="flex flex-row gap-2.5">
<View className={"flex-1"}>
<Button
type={"primary"}
size={"large"}
fill={"outline"}
block
onClick={handleWechatQrUpload}
>
<View></View>
</Button>
</View>
<View className={"flex-1"}>
<Button
type={"warning"}
size={"large"}
fill={"outline"}
block
onClick={(e) => {
setSupplierVO({
...supplierVO,
wechatQr: undefined,
});
Toast.show("toast", {
title: "删除成功",
icon: "success",
content: "微信收款码已删除",
});
e.stopPropagation();
}}
>
<View></View>
</Button>
</View>
</View>
</View>
) : (
<View
className={
"flex h-40 flex-1 flex-col items-center justify-center rounded-md border-2 border-dashed border-green-300 bg-green-50 p-2.5"
}
onClick={handleWechatQrUpload}
>
<Icon name={"camera"} size={24} />
<View className="text-sm font-medium text-green-700">
</View>
<View className="text-neutral-darker mt-1 text-xs">
</View>
<View className="mt-2 text-center text-xs text-gray-400">
</View>
</View>
)}
</View>
</View>
)}
{/* 隐藏的供应商选择器,用于自家档口选择 */}
{showSupplierPicker && (
<SupplierPicker
type={"STALL"}
trigger={
<View
style={{ display: "none" }}
onClick={() => setShowSupplierPicker(true)}
/>
}
onFinish={(supplierVO1) => {
setShowSupplierPicker(false);
// 检查是否已经选择了该档口
if (
selectedSupplierIds &&
selectedSupplierIds.includes(supplierVO1.supplierId!)
) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "该档口已被选择,请选择其他档口",
});
return;
}
setSupplierVO({
...supplierVO,
...supplierVO1,
// 自家档口时清空收款信息
payeeName: "",
bankName: "",
bankCard: "",
phone: "",
wechatQr: undefined,
});
// 清除所有错误状态
setNameError((prev) => ({
...prev,
[supplierVO.orderSupplierId]: false,
}));
}}
/>
)}
</View>
);
},
);