- 修复经销商信息显示逻辑,正确处理名称和瓜品等级的显示 - 移除PDF自动保存功能,仅保留下载成功提示 - 更新按钮样式为外框样式,改善视觉效果 - 优化箱重计算精度,添加小数位处理 - 移除货币格式化,直接显示数值 - 添加供应商银行名称字段并优化验证逻辑 - 改进供应商信息表单的空值处理 - 优化车次号获取逻辑,支持强制重新获取 - 实现包装信息表格的可编辑功能,支持销售单价修改 - 修复表格渲染逻辑,正确处理合计行显示 - 更新应用版本号至v0.0.61 - 优化PDF模板中经销商和目的地信息的显示逻辑 - 修复订单转换器中的价格计算逻辑 - 调整发货单转换器中的包装分组逻辑
1084 lines
34 KiB
TypeScript
1084 lines
34 KiB
TypeScript
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 { business } from "@/services";
|
||
import { globalStore } from "@/store/global-store";
|
||
|
||
// 定义ref暴露的方法接口
|
||
export interface SupplierInfoRef {
|
||
validate: () => boolean;
|
||
}
|
||
|
||
interface ISupplierInfoProps {
|
||
index: number;
|
||
value: BusinessAPI.OrderVO;
|
||
onChange: (orderVO: BusinessAPI.OrderVO) => void;
|
||
}
|
||
|
||
export default forwardRef<SupplierInfoRef, ISupplierInfoProps>(
|
||
function MelonFarmer(props, ref) {
|
||
const onRemove = (supplierVO: BusinessAPI.OrderSupplier) => {
|
||
if (orderSupplierList.length <= 1) {
|
||
setOrderSupplierList([
|
||
{
|
||
orderSupplierId: generateShortId(),
|
||
supplierId: "",
|
||
name: "瓜农1",
|
||
payeeName: "",
|
||
idCard: "",
|
||
bankName: "",
|
||
bankCard: "",
|
||
phone: "",
|
||
selected: true,
|
||
orderPackageList: [],
|
||
packageUsage: [
|
||
{
|
||
boxType: "USED",
|
||
isUsed: 0,
|
||
},
|
||
{
|
||
boxType: "EXTRA_USED",
|
||
isUsed: 0,
|
||
},
|
||
{
|
||
boxType: "EXTRA",
|
||
isUsed: 0,
|
||
},
|
||
{
|
||
boxType: "REMAIN",
|
||
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 [idCardError, setIdCardError] = 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 validateIdCard = (idCard: string) => {
|
||
if (!idCard) {
|
||
return false;
|
||
}
|
||
// 18位身份证号正则表达式
|
||
const idCardRegex =
|
||
/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
|
||
return idCardRegex.test(idCard);
|
||
};
|
||
|
||
// 校验银行卡号函数
|
||
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 isIdCardValid = validateIdCard(supplierVO.idCard || "");
|
||
const isBankNameValid = validateBankName(supplierVO.bankName || "");
|
||
const isBankCardValid = validateBankCard(supplierVO.bankCard || "");
|
||
const isPhoneValid = validatePhone(supplierVO.phone || "");
|
||
const isLastFarmerValid = validateIsLastFarmer(supplierVO?.isLast); // 校验是否需要拼车
|
||
|
||
// 更新错误状态
|
||
setNameError((prev) => ({
|
||
...prev,
|
||
[id]: !isNameValid,
|
||
}));
|
||
|
||
setIdCardError((prev) => ({
|
||
...prev,
|
||
[id]: !isIdCardValid,
|
||
}));
|
||
|
||
setBankNameError((prev) => ({
|
||
...prev,
|
||
[id]: !isBankNameValid,
|
||
}));
|
||
|
||
setBankCardError((prev) => ({
|
||
...prev,
|
||
[id]: !isBankCardValid,
|
||
}));
|
||
|
||
setPhoneError((prev) => ({
|
||
...prev,
|
||
[id]: !isPhoneValid,
|
||
}));
|
||
|
||
// 更新是否为最后一个瓜农的错误状态
|
||
setIsLastFarmerError((prev) => ({
|
||
...prev,
|
||
[id]: !isLastFarmerValid,
|
||
}));
|
||
|
||
const isValid =
|
||
isNameValid &&
|
||
isIdCardValid &&
|
||
isBankNameValid &&
|
||
isBankCardValid &&
|
||
isPhoneValid &&
|
||
isLastFarmerValid;
|
||
|
||
if (!isValid) {
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "请完善瓜农信息后再进行下一步操作",
|
||
});
|
||
}
|
||
|
||
return isValid;
|
||
};
|
||
|
||
// 将校验方法暴露给父组件
|
||
useImperativeHandle(ref, () => ({
|
||
validate,
|
||
}));
|
||
|
||
// 处理姓名变化
|
||
const handleNameChange = (
|
||
value: string,
|
||
supplierVO: BusinessAPI.OrderSupplier,
|
||
) => {
|
||
setSupplierVO({
|
||
...supplierVO!,
|
||
name: value,
|
||
payeeName: 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,
|
||
}));
|
||
}
|
||
|
||
// 检查瓜农姓名是否在系统中存在
|
||
console.log("checkSupplier", value);
|
||
if (value) {
|
||
if (selectedSupplierNames && selectedSupplierNames.includes(value)) {
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "该瓜农已被选择,请输入其他名称",
|
||
});
|
||
return;
|
||
}
|
||
try {
|
||
const {
|
||
data: { data: newSupplierVO, success },
|
||
} = await business.supplier.checkSupplier({
|
||
supplierCheckQry: {
|
||
name: value,
|
||
},
|
||
});
|
||
|
||
if (success && newSupplierVO) {
|
||
// 系统中已存在该瓜农信息,检查是否需要提示用户快速填入
|
||
// 条件1: 当前没有选择瓜农 (没有supplierId)
|
||
// 条件2: 当前选择的瓜农与系统中找到的瓜农不一致
|
||
const shouldPrompt =
|
||
!supplierVO?.supplierId ||
|
||
(supplierVO?.supplierId &&
|
||
supplierVO?.supplierId !== newSupplierVO.supplierId);
|
||
|
||
if (shouldPrompt) {
|
||
// 判断是首次填入还是冲突替换
|
||
const isConflict =
|
||
supplierVO?.supplierId &&
|
||
supplierVO?.supplierId !== newSupplierVO.supplierId;
|
||
|
||
Dialog.open("dialog", {
|
||
title: "提示",
|
||
content: isConflict
|
||
? `系统中存在瓜农"${value}"的信息与当前瓜农不同,是否替换为系统中的信息?`
|
||
: `系统中已存在瓜农"${value}"的信息,是否快速填入?`,
|
||
onConfirm: () => {
|
||
// 用户确认,填入信息
|
||
setSupplierVO({
|
||
...supplierVO!,
|
||
...newSupplierVO,
|
||
});
|
||
|
||
// 清除所有错误状态
|
||
setNameError((prev) => ({
|
||
...prev,
|
||
[id]: false,
|
||
}));
|
||
setPhoneError((prev) => ({
|
||
...prev,
|
||
[id]: false,
|
||
}));
|
||
setBankCardError((prev) => ({
|
||
...prev,
|
||
[id]: false,
|
||
}));
|
||
setBankNameError((prev) => ({
|
||
...prev,
|
||
[id]: false,
|
||
}));
|
||
setIdCardError((prev) => ({
|
||
...prev,
|
||
[id]: false,
|
||
}));
|
||
|
||
Dialog.close("dialog");
|
||
},
|
||
onCancel: () => {
|
||
Dialog.close("dialog");
|
||
},
|
||
});
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error("检查瓜农信息失败", error);
|
||
}
|
||
}
|
||
};
|
||
|
||
// 处理身份证号变化
|
||
const handleIdCardChange = (
|
||
value: string,
|
||
supplierVO: BusinessAPI.OrderSupplier,
|
||
) => {
|
||
setSupplierVO({
|
||
...supplierVO,
|
||
idCard: value,
|
||
});
|
||
|
||
const id = supplierVO.orderSupplierId;
|
||
|
||
// 校验并更新错误状态
|
||
const isValid = validateIdCard(value);
|
||
setIdCardError((prev) => ({
|
||
...prev,
|
||
[id]: !isValid && value !== "",
|
||
}));
|
||
|
||
if (isValid) {
|
||
setIdCardError((prev) => ({
|
||
...prev,
|
||
[id]: false,
|
||
}));
|
||
}
|
||
};
|
||
|
||
// 处理身份证号失焦
|
||
const handleIdCardBlur = (value: string, id: any) => {
|
||
if (value && !validateIdCard(value)) {
|
||
setIdCardError((prev) => ({
|
||
...prev,
|
||
[id]: true,
|
||
}));
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "请输入正确的身份证号",
|
||
});
|
||
} else {
|
||
setIdCardError((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="flex gap-2">
|
||
<View className={"flex-1"}>
|
||
<Button
|
||
block
|
||
icon={<Icon name={"id-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: "idcard",
|
||
}),
|
||
complete: () => {
|
||
Taro.eventCenter.on("ocr", (res) => {
|
||
console.log("识别结果为:", res.result);
|
||
setSupplierVO({
|
||
...supplierVO,
|
||
name: res.result.name,
|
||
idCard: res.result.idCard,
|
||
});
|
||
|
||
Taro.eventCenter.off("ocr");
|
||
});
|
||
},
|
||
});
|
||
}}
|
||
>
|
||
<View>扫描身份证</View>
|
||
</Button>
|
||
</View>
|
||
<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>
|
||
<View className="flex flex-row justify-between">
|
||
<View className={"block text-sm font-normal text-[#000000]"}>
|
||
姓名
|
||
</View>
|
||
<SupplierPicker
|
||
type={"FARMER"}
|
||
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,
|
||
}));
|
||
setPhoneError((prev) => ({
|
||
...prev,
|
||
[supplierVO.orderSupplierId]: false,
|
||
}));
|
||
setBankCardError((prev) => ({
|
||
...prev,
|
||
[supplierVO.orderSupplierId]: false,
|
||
}));
|
||
setBankNameError((prev) => ({
|
||
...prev,
|
||
[supplierVO.orderSupplierId]: false,
|
||
}));
|
||
setIdCardError((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 ${idCardError[supplierVO.orderSupplierId] ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<Icon name="id-card" size={16} color="#999" className="mx-2" />
|
||
<Input
|
||
clearable
|
||
type="idcard"
|
||
placeholder="请输入身份证号"
|
||
value={supplierVO.idCard || ""}
|
||
onChange={(value) => handleIdCardChange(value, supplierVO)}
|
||
onBlur={() =>
|
||
handleIdCardBlur(
|
||
supplierVO?.idCard || "",
|
||
supplierVO.orderSupplierId,
|
||
)
|
||
}
|
||
className="flex-1"
|
||
/>
|
||
</View>
|
||
{idCardError[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 ${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>
|
||
|
||
{/* 若瓜农无法开发票,则可打款到微信 */}
|
||
<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>
|
||
</View>
|
||
);
|
||
},
|
||
);
|