- 新增 VersionChecker 组件实现应用版本自动检查 - 版本检查通过 HEAD 请求比较 ETag 和 Last-Modified - 每 5 分钟自动检查一次应用版本更新 - 在 H5 生产环境自动注入版本检查组件 - 修复采购订单提交时的类型安全问题 - 优化成本项价格计算逻辑 - 更新供应商信息显示的动态文本 - 调整称重单位从公斤改为斤 - 修正角色ID数据类型从number改为string - 移除过期的业务规则代码 - 更新应用版本号至 v0.0.57
885 lines
28 KiB
TypeScript
885 lines
28 KiB
TypeScript
import { View } from "@tarojs/components";
|
||
import {
|
||
Button,
|
||
Checkbox,
|
||
DatePicker,
|
||
Input,
|
||
PickerOption,
|
||
PickerValue,
|
||
TextArea,
|
||
Toast,
|
||
} from "@nutui/nutui-react-taro";
|
||
import { DealerPicker, Icon } from "@/components";
|
||
import { forwardRef, useImperativeHandle, useState } from "react";
|
||
import dayjs from "dayjs";
|
||
import Taro from "@tarojs/taro";
|
||
import { business } from "@/services";
|
||
import { validatePrice as validatePrice1 } from "@/utils";
|
||
|
||
interface IOrderVehicleProps {
|
||
value: BusinessAPI.OrderVO;
|
||
onChange: (orderVO: BusinessAPI.OrderVO) => void;
|
||
}
|
||
|
||
export interface OrderVehicleRef {
|
||
validate: () => boolean;
|
||
}
|
||
|
||
export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
|
||
function OrderVehicle(props, ref) {
|
||
const { value, onChange } = props;
|
||
|
||
const { orderVehicle, orderDealer } = value;
|
||
|
||
const [originalData, setOriginalData] = useState<string>();
|
||
|
||
const [show, setShow] = useState(false);
|
||
|
||
// 校验状态
|
||
const [phoneError, setPhoneError] = useState(false);
|
||
const [plateError, setPlateError] = useState(false);
|
||
const [driverError, setDriverError] = useState(false);
|
||
const [originError, setOriginError] = useState(false);
|
||
const [destinationError, setDestinationError] = useState(false);
|
||
const [priceError, setPriceError] = useState(false);
|
||
const [strawCurtainPriceError, setStrawCurtainPriceError] = useState(false);
|
||
const [deliveryTimeError, setDeliveryTimeError] = useState(false);
|
||
const [dealerNameError, setDealerNameError] = useState(false);
|
||
|
||
// 获取当年的第一天和今天,用于限制日期选择范围
|
||
const currentYear = new Date().getFullYear();
|
||
const startDate = new Date(currentYear, 0, 1); // 当年第一天
|
||
const endDate = new Date(); // 今天
|
||
|
||
// 校验手机号码函数
|
||
const validatePhone = (phone: string) => {
|
||
if (!phone) {
|
||
return false;
|
||
}
|
||
const phoneRegex = /^1[3456789]\d{9}$/;
|
||
return phoneRegex.test(phone);
|
||
};
|
||
|
||
// 校验车牌号函数
|
||
const validatePlate = (plate: string) => {
|
||
if (!plate) {
|
||
return false;
|
||
}
|
||
// 车牌号正则表达式(包含普通蓝牌、黄牌、绿牌、黑牌、白牌等)
|
||
const plateRegex =
|
||
/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-Z0-9]{4,5}[A-Z0-9挂学警港澳]$/;
|
||
return plateRegex.test(plate);
|
||
};
|
||
|
||
// 校验司机姓名函数
|
||
const validateDriver = (driver: string) => {
|
||
if (!driver) {
|
||
return false;
|
||
}
|
||
// 司机姓名至少2个字符
|
||
return driver.length >= 2;
|
||
};
|
||
|
||
// 校验出发地函数
|
||
const validateOrigin = (origin: string) => {
|
||
if (!origin) {
|
||
return false;
|
||
}
|
||
// 出发地至少2个字符
|
||
return origin.length >= 2;
|
||
};
|
||
|
||
// 校验目的地函数
|
||
const validateDestination = (destination: string) => {
|
||
if (!destination) {
|
||
return false;
|
||
}
|
||
// 目的地至少2个字符
|
||
return destination.length >= 2;
|
||
};
|
||
|
||
// 校验运费函数
|
||
const validatePrice = (price: string | number) => {
|
||
if (price === "" || price === undefined) {
|
||
return false;
|
||
}
|
||
const priceNum = typeof price === "string" ? parseFloat(price) : price;
|
||
// 运费必须大于等于0
|
||
return !Number.isNaN(priceNum) && priceNum >= 0;
|
||
};
|
||
|
||
// 校验发货时间函数
|
||
const validateDeliveryTime = (deliveryTime: string) => {
|
||
return !!deliveryTime; // 发货时间必须存在
|
||
};
|
||
|
||
// 校验经销商函数
|
||
const validateDealerName = (dealerName: string) => {
|
||
return !!dealerName; // 经销商必须存在
|
||
};
|
||
|
||
// 对外暴露的校验方法
|
||
const validate = () => {
|
||
console.log("vehicle", orderVehicle);
|
||
const isPhoneValid = validatePhone(orderVehicle?.phone || "");
|
||
const isPlateValid = validatePlate(orderVehicle?.plate || "");
|
||
const isDriverValid = validateDriver(orderVehicle?.driver || "");
|
||
const isOriginValid = validateOrigin(orderVehicle?.origin || "");
|
||
const isDestinationValid = validateDestination(
|
||
orderVehicle?.destination || "",
|
||
);
|
||
const isPriceValid = validatePrice(orderVehicle?.price || 0);
|
||
const isStrawCurtainPriceValid =
|
||
!orderVehicle.openStrawCurtain ||
|
||
validatePrice(orderVehicle?.strawCurtainPrice || 0);
|
||
const isDeliveryTimeValid = validateDeliveryTime(
|
||
orderVehicle?.deliveryTime || "",
|
||
);
|
||
const isDealerValid = validateDealerName(orderVehicle?.dealerName);
|
||
|
||
setPhoneError(!isPhoneValid);
|
||
setPlateError(!isPlateValid);
|
||
setDriverError(!isDriverValid);
|
||
setOriginError(!isOriginValid);
|
||
setDestinationError(!isDestinationValid);
|
||
setPriceError(!isPriceValid);
|
||
setDeliveryTimeError(!isDeliveryTimeValid);
|
||
setDealerNameError(!isDealerValid);
|
||
|
||
if (orderVehicle.openStrawCurtain) {
|
||
setStrawCurtainPriceError(!isStrawCurtainPriceValid);
|
||
}
|
||
|
||
const isValid =
|
||
isPhoneValid &&
|
||
isPlateValid &&
|
||
isDriverValid &&
|
||
isOriginValid &&
|
||
isDestinationValid &&
|
||
isPriceValid &&
|
||
isStrawCurtainPriceValid &&
|
||
isDeliveryTimeValid &&
|
||
isDealerValid;
|
||
|
||
if (!isValid) {
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "请完善车辆信息后再进行下一步操作",
|
||
});
|
||
}
|
||
|
||
return isValid;
|
||
};
|
||
|
||
useImperativeHandle(ref, () => ({
|
||
validate,
|
||
}));
|
||
|
||
const handlePhoneChange = (phone: string) => {
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
phone: phone as any,
|
||
},
|
||
});
|
||
|
||
// 校验手机号码并更新错误状态
|
||
const isValid = validatePhone(phone);
|
||
setPhoneError(!isValid && phone !== "");
|
||
|
||
// 如果手机号有效,清除错误状态
|
||
if (isValid) {
|
||
setPhoneError(false);
|
||
}
|
||
};
|
||
|
||
const handlePhoneBlur = () => {
|
||
// 失去焦点时校验手机号码
|
||
if (orderVehicle?.phone && !validatePhone(orderVehicle.phone)) {
|
||
setPhoneError(true);
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "请输入正确的手机号码",
|
||
});
|
||
} else {
|
||
setPhoneError(false);
|
||
}
|
||
};
|
||
|
||
const handlePlateChange = (plate: string) => {
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
plate: plate as any,
|
||
},
|
||
});
|
||
|
||
// 校验车牌号并更新错误状态
|
||
const isValid = validatePlate(plate);
|
||
setPlateError(!isValid && plate !== "");
|
||
|
||
// 如果车牌号有效,清除错误状态
|
||
if (isValid) {
|
||
setPlateError(false);
|
||
}
|
||
};
|
||
|
||
const handlePlateBlur = () => {
|
||
if (orderVehicle?.plate && !validatePlate(orderVehicle.plate)) {
|
||
setPlateError(true);
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "请输入正确的车牌号",
|
||
});
|
||
} else {
|
||
setPlateError(false);
|
||
}
|
||
};
|
||
|
||
const handleDriverChange = (driver: string) => {
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
driver: driver as any,
|
||
},
|
||
});
|
||
|
||
// 校验司机姓名并更新错误状态
|
||
const isValid = validateDriver(driver);
|
||
setDriverError(!isValid && driver !== "");
|
||
|
||
// 如果司机姓名有效,清除错误状态
|
||
if (isValid) {
|
||
setDriverError(false);
|
||
}
|
||
};
|
||
|
||
const handleDriverBlur = () => {
|
||
if (orderVehicle?.driver && !validateDriver(orderVehicle.driver)) {
|
||
setDriverError(true);
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "司机姓名至少2个字符",
|
||
});
|
||
} else {
|
||
setDriverError(false);
|
||
}
|
||
};
|
||
|
||
const handleOriginChange = (origin: string) => {
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
origin: origin as any,
|
||
},
|
||
});
|
||
|
||
// 校验出发地并更新错误状态
|
||
const isValid = validateOrigin(origin);
|
||
setOriginError(!isValid && origin !== "");
|
||
|
||
// 如果出发地有效,清除错误状态
|
||
if (isValid) {
|
||
setOriginError(false);
|
||
}
|
||
};
|
||
|
||
const handleOriginBlur = () => {
|
||
if (orderVehicle?.origin && !validateOrigin(orderVehicle.origin)) {
|
||
setOriginError(true);
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "出发地至少2个字符",
|
||
});
|
||
} else {
|
||
setOriginError(false);
|
||
}
|
||
};
|
||
|
||
const handleDestinationChange = (destination: string) => {
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
destination: destination as any,
|
||
},
|
||
});
|
||
|
||
// 校验目的地并更新错误状态
|
||
const isValid = validateDestination(destination);
|
||
setDestinationError(!isValid && destination !== "");
|
||
|
||
// 如果目的地有效,清除错误状态
|
||
if (isValid) {
|
||
setDestinationError(false);
|
||
}
|
||
};
|
||
|
||
const handleDestinationBlur = () => {
|
||
if (
|
||
orderVehicle?.destination &&
|
||
!validateDestination(orderVehicle.destination)
|
||
) {
|
||
setDestinationError(true);
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "目的地至少2个字符",
|
||
});
|
||
} else {
|
||
setDestinationError(false);
|
||
}
|
||
};
|
||
|
||
const handlePriceChange = (price: string) => {
|
||
// 只允许数字和小数点,小数点后最多两位
|
||
const numValue = validatePrice1(price);
|
||
if (numValue !== undefined) {
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
price: numValue as any,
|
||
},
|
||
});
|
||
|
||
// 校验运费并更新错误状态
|
||
const isValid = validatePrice(price);
|
||
setPriceError(!isValid && price !== "");
|
||
|
||
// 如果运费有效,清除错误状态
|
||
if (isValid) {
|
||
setPriceError(false);
|
||
}
|
||
}
|
||
};
|
||
|
||
const handlePriceBlur = () => {
|
||
if (orderVehicle?.price && !validatePrice(orderVehicle.price)) {
|
||
setPriceError(true);
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "运费必须大于等于0",
|
||
});
|
||
} else {
|
||
setPriceError(false);
|
||
}
|
||
};
|
||
|
||
const handleStrawCurtainPriceChange = (strawCurtainPrice: string) => {
|
||
const numValue = validatePrice1(strawCurtainPrice);
|
||
if (numValue !== undefined) {
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
strawCurtainPrice: numValue as any,
|
||
},
|
||
});
|
||
|
||
// 校验草帘费用并更新错误状态
|
||
const isValid = validatePrice(strawCurtainPrice);
|
||
setStrawCurtainPriceError(!isValid && strawCurtainPrice !== "");
|
||
|
||
// 如果草帘费用有效,清除错误状态
|
||
if (isValid) {
|
||
setStrawCurtainPriceError(false);
|
||
}
|
||
}
|
||
};
|
||
|
||
const handleStrawCurtainPriceBlur = () => {
|
||
if (
|
||
orderVehicle?.strawCurtainPrice &&
|
||
!validatePrice(orderVehicle.strawCurtainPrice)
|
||
) {
|
||
setStrawCurtainPriceError(true);
|
||
Toast.show("toast", {
|
||
icon: "fail",
|
||
title: "提示",
|
||
content: "草帘费用必须大于等于0",
|
||
});
|
||
} else {
|
||
setStrawCurtainPriceError(false);
|
||
}
|
||
};
|
||
|
||
const confirm = (_values: PickerValue[]) => {
|
||
const selectedDate = dayjs(_values.join("-")).format("YYYY-MM-DD");
|
||
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
deliveryTime: selectedDate as any,
|
||
},
|
||
});
|
||
|
||
// 校验发货时间
|
||
const isValid = validateDeliveryTime(selectedDate);
|
||
setDeliveryTimeError(!isValid);
|
||
};
|
||
|
||
const formatter = (type: string, option: PickerOption) => {
|
||
switch (type) {
|
||
case "year":
|
||
option.label += "年";
|
||
break;
|
||
case "month":
|
||
option.label += "月";
|
||
break;
|
||
case "day":
|
||
option.label += "日";
|
||
break;
|
||
case "hour":
|
||
option.label += "时";
|
||
break;
|
||
case "minute":
|
||
option.label += "分";
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
return option;
|
||
};
|
||
|
||
const vehicleExtraction = async (originalData: string) => {
|
||
// 简单校验message,避免无效的数据抽取
|
||
if (!originalData || originalData.trim() === "") {
|
||
Toast.show("toast", {
|
||
title: "请输入有效内容",
|
||
icon: "none",
|
||
});
|
||
return;
|
||
}
|
||
|
||
Taro.showLoading({
|
||
title: "识别中,请稍后",
|
||
});
|
||
|
||
const {
|
||
data: { data: newVehicle },
|
||
} = await business.extraction.vehicleExtraction({
|
||
message: originalData,
|
||
dealerNames: "",
|
||
});
|
||
|
||
if (newVehicle) {
|
||
const dealerVO = newVehicle.dealerVO;
|
||
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...newVehicle,
|
||
// 通过 - 分割
|
||
plate: newVehicle.plate?.split("-")[0]!,
|
||
dealerId: newVehicle.dealerId || orderVehicle?.dealerId,
|
||
dealerName: newVehicle.dealerName || orderVehicle?.dealerName,
|
||
openStrawCurtain: false,
|
||
//@ts-ignore
|
||
strawCurtainPrice: "",
|
||
deliveryTime: dayjs().format("YYYY-MM-DD"),
|
||
originalData: originalData || "",
|
||
},
|
||
orderDealer: {
|
||
...orderDealer,
|
||
...dealerVO,
|
||
},
|
||
});
|
||
|
||
// 清除所有错误状态
|
||
setPlateError(false);
|
||
setDriverError(false);
|
||
setPhoneError(false);
|
||
setOriginError(false);
|
||
setDestinationError(false);
|
||
setPriceError(false);
|
||
setStrawCurtainPriceError(false);
|
||
setDeliveryTimeError(false);
|
||
setDealerNameError(false);
|
||
}
|
||
|
||
Taro.hideLoading();
|
||
};
|
||
|
||
return (
|
||
<View className="flex flex-1 flex-col gap-2.5 p-2.5">
|
||
<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 flex-1 flex-col gap-2.5"}>
|
||
<View className="text-primary text-base font-bold">智能识别</View>
|
||
<View
|
||
className={
|
||
"flex w-full items-center rounded-md border-4 border-gray-300"
|
||
}
|
||
>
|
||
<TextArea
|
||
className={"flex-1"}
|
||
value={originalData}
|
||
onChange={(value) => {
|
||
setOriginalData(value);
|
||
}}
|
||
rows={8}
|
||
maxLength={500}
|
||
showCount
|
||
placeholder="「粘贴识别」获输入文本,智能拆分车牌号、司机姓名、联系电话、出发地、目的地和运费"
|
||
/>
|
||
</View>
|
||
</View>
|
||
<View className={"flex flex-row gap-2.5"}>
|
||
{originalData ? (
|
||
<>
|
||
<View className={"flex-1"}>
|
||
<Button
|
||
size={"large"}
|
||
type={"default"}
|
||
block
|
||
className="bg-primary flex h-10 items-center justify-center px-4 text-white"
|
||
onClick={async () => {
|
||
setOriginalData("");
|
||
}}
|
||
>
|
||
清空
|
||
</Button>
|
||
</View>
|
||
<View className={"flex-1"}>
|
||
<Button
|
||
id={"target1"}
|
||
size={"large"}
|
||
type={"primary"}
|
||
block
|
||
className="bg-primary flex h-10 items-center justify-center px-4 text-white"
|
||
onClick={async () => {
|
||
await vehicleExtraction(originalData);
|
||
}}
|
||
>
|
||
识别
|
||
</Button>
|
||
</View>
|
||
</>
|
||
) : (
|
||
<View className={"flex-1"}>
|
||
<Button
|
||
id={"target1"}
|
||
size={"large"}
|
||
type={"primary"}
|
||
block
|
||
className="bg-primary flex h-10 items-center justify-center px-4 text-white"
|
||
onClick={() => {
|
||
Taro.getClipboardData({
|
||
success: async (res) => {
|
||
let originalData = res.data;
|
||
if (originalData == "") {
|
||
return;
|
||
}
|
||
|
||
await vehicleExtraction(originalData);
|
||
|
||
setOriginalData(originalData);
|
||
},
|
||
});
|
||
}}
|
||
>
|
||
粘贴并识别
|
||
</Button>
|
||
</View>
|
||
)}
|
||
</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">运输信息</View>
|
||
<View className={"flex flex-col gap-2.5"}>
|
||
<View className="block text-sm font-normal text-[#000000]">
|
||
车牌号
|
||
</View>
|
||
<View
|
||
className={`flex h-10 w-full items-center rounded-md ${plateError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<Input
|
||
type="text"
|
||
placeholder="请输入车牌号"
|
||
value={orderVehicle?.plate}
|
||
onChange={handlePlateChange}
|
||
onBlur={handlePlateBlur}
|
||
/>
|
||
</View>
|
||
{plateError && (
|
||
<View className="mt-1 text-xs text-red-500">
|
||
请输入正确的车牌号
|
||
</View>
|
||
)}
|
||
</View>
|
||
<View className={"flex flex-col gap-2.5"}>
|
||
<View className="block text-sm font-normal text-[#000000]">
|
||
司机姓名
|
||
</View>
|
||
<View
|
||
className={`flex h-10 w-full items-center rounded-md ${driverError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<Input
|
||
type="text"
|
||
placeholder="请输入司机姓名"
|
||
value={orderVehicle?.driver}
|
||
onChange={handleDriverChange}
|
||
onBlur={handleDriverBlur}
|
||
/>
|
||
</View>
|
||
{driverError && (
|
||
<View className="mt-1 text-xs text-red-500">
|
||
司机姓名至少2个字符
|
||
</View>
|
||
)}
|
||
</View>
|
||
<View className={"flex flex-col gap-2.5"}>
|
||
<View className="block text-sm font-normal text-[#000000]">
|
||
联系电话
|
||
</View>
|
||
<View
|
||
className={`flex h-10 w-full items-center rounded-md ${phoneError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<Input
|
||
type="tel"
|
||
placeholder="请输入联系电话"
|
||
value={orderVehicle?.phone}
|
||
onChange={handlePhoneChange}
|
||
onBlur={handlePhoneBlur}
|
||
/>
|
||
</View>
|
||
{phoneError && (
|
||
<View className="mt-1 text-xs text-red-500">
|
||
请输入正确的手机号码
|
||
</View>
|
||
)}
|
||
</View>
|
||
<View className={"flex flex-col gap-2.5"}>
|
||
<View className="block text-sm font-normal text-[#000000]">
|
||
出发地
|
||
</View>
|
||
<View
|
||
className={`flex h-10 w-full items-center rounded-md ${originError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<Input
|
||
type="text"
|
||
placeholder="请输入出发地"
|
||
value={orderVehicle?.origin}
|
||
onChange={handleOriginChange}
|
||
onBlur={handleOriginBlur}
|
||
/>
|
||
</View>
|
||
{originError && (
|
||
<View className="mt-1 text-xs text-red-500">
|
||
出发地至少2个字符
|
||
</View>
|
||
)}
|
||
</View>
|
||
<View className={"flex flex-col gap-2.5"}>
|
||
<View className="block text-sm font-normal text-[#000000]">
|
||
目的地
|
||
</View>
|
||
<View className={"flex flex-row gap-2.5"}>
|
||
<View className={"flex-1"}>
|
||
<View
|
||
id={"target2"}
|
||
className={`flex h-10 w-full flex-1 items-center rounded-md ${dealerNameError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<DealerPicker
|
||
onFinish={(dealerVO) => {
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
dealerId: dealerVO.dealerId,
|
||
dealerName: dealerVO.shortName!,
|
||
},
|
||
orderDealer: {
|
||
...orderDealer,
|
||
...dealerVO,
|
||
},
|
||
});
|
||
|
||
// 校验经销商信息
|
||
const isValid = validateDealerName(dealerVO.shortName!);
|
||
setDealerNameError(!isValid);
|
||
}}
|
||
enableManualInput
|
||
trigger={
|
||
<View
|
||
className={
|
||
"flex flex-1 flex-row items-center justify-between px-5"
|
||
}
|
||
>
|
||
<View className={"text-sm"}>
|
||
{orderVehicle?.dealerName || "选择经销商"}
|
||
</View>
|
||
<Icon name={"chevron-down"} />
|
||
</View>
|
||
}
|
||
/>
|
||
</View>
|
||
{dealerNameError && (
|
||
<View className="mt-1 text-xs text-red-500">
|
||
请选择经销商
|
||
</View>
|
||
)}
|
||
</View>
|
||
<View className={"flex-1"}>
|
||
<View
|
||
className={`flex h-10 w-full items-center rounded-md ${destinationError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<Input
|
||
type="text"
|
||
placeholder="请输入目的地"
|
||
value={orderVehicle?.destination}
|
||
onChange={(value) => handleDestinationChange(value)}
|
||
onBlur={handleDestinationBlur}
|
||
/>
|
||
</View>
|
||
{destinationError && (
|
||
<View className="mt-1 text-xs text-red-500">
|
||
目的地至少2个字符
|
||
</View>
|
||
)}
|
||
</View>
|
||
</View>
|
||
</View>
|
||
<View className={"flex flex-col gap-2.5"}>
|
||
<View className="block text-sm font-normal text-[#000000]">
|
||
运费
|
||
</View>
|
||
<View
|
||
className={`flex h-10 w-full items-center rounded-md ${priceError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<Input
|
||
type="digit"
|
||
placeholder="请输入运费,可填0"
|
||
value={orderVehicle?.price?.toString()}
|
||
onChange={handlePriceChange}
|
||
onBlur={handlePriceBlur}
|
||
/>
|
||
<View
|
||
className="text-gray-500"
|
||
style={{
|
||
padding: `var(--nutui-input-padding)`,
|
||
}}
|
||
>
|
||
元
|
||
</View>
|
||
</View>
|
||
{priceError && (
|
||
<View className="mt-1 text-xs text-red-500">
|
||
运费必须大于等于0
|
||
</View>
|
||
)}
|
||
</View>
|
||
<View className={"flex flex-col gap-2.5"}>
|
||
<View className={"flex flex-row justify-between"}>
|
||
<View className="block text-sm font-normal text-[#000000]">
|
||
草帘
|
||
</View>
|
||
<Checkbox
|
||
className={"flex flex-row items-center"}
|
||
checked={orderVehicle?.openStrawCurtain}
|
||
onChange={(checked) => {
|
||
onChange?.({
|
||
...value,
|
||
orderVehicle: {
|
||
...orderVehicle,
|
||
openStrawCurtain: checked,
|
||
},
|
||
});
|
||
}}
|
||
>
|
||
<View className={"text-sm font-normal text-[#000000]"}>
|
||
用了
|
||
</View>
|
||
</Checkbox>
|
||
</View>
|
||
{orderVehicle?.openStrawCurtain && (
|
||
<View
|
||
className={`flex h-10 w-full items-center rounded-md ${strawCurtainPriceError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<Input
|
||
type="digit"
|
||
placeholder="请输入草帘费用"
|
||
value={orderVehicle?.strawCurtainPrice?.toString()}
|
||
onChange={handleStrawCurtainPriceChange}
|
||
onBlur={handleStrawCurtainPriceBlur}
|
||
/>
|
||
<View
|
||
className="text-gray-500"
|
||
style={{
|
||
padding: `var(--nutui-input-padding)`,
|
||
}}
|
||
>
|
||
元
|
||
</View>
|
||
</View>
|
||
)}
|
||
{strawCurtainPriceError && orderVehicle?.openStrawCurtain && (
|
||
<View className="mt-1 text-xs text-red-500">
|
||
草帘费用必须大于等于0
|
||
</View>
|
||
)}
|
||
</View>
|
||
<View className={"flex flex-col gap-2.5"}>
|
||
<View className="block text-sm font-normal text-[#000000]">
|
||
发货时间
|
||
</View>
|
||
<View
|
||
className={`flex h-10 w-full items-center rounded-md ${deliveryTimeError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||
>
|
||
<View
|
||
className={
|
||
"flex flex-1 flex-row items-center justify-between px-5"
|
||
}
|
||
style={{
|
||
color: "var(--nutui-color-title, #1a1a1a)",
|
||
}}
|
||
onClick={() => setShow(true)}
|
||
>
|
||
<View className={"text-sm"}>
|
||
{orderVehicle?.deliveryTime
|
||
? dayjs(orderVehicle?.deliveryTime).format(
|
||
"YYYY年MM月DD日",
|
||
)
|
||
: "请选择发货时间"}
|
||
</View>
|
||
<Icon name={"chevron-down"} />
|
||
</View>
|
||
</View>
|
||
{deliveryTimeError && (
|
||
<View className="mt-1 text-xs text-red-500">
|
||
请选择发货时间
|
||
</View>
|
||
)}
|
||
<DatePicker
|
||
title="发货时间选择"
|
||
type="date"
|
||
startDate={startDate}
|
||
endDate={endDate}
|
||
visible={show}
|
||
defaultValue={new Date()}
|
||
formatter={formatter}
|
||
onClose={() => setShow(false)}
|
||
onConfirm={(_, values) => confirm(values)}
|
||
/>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
);
|
||
},
|
||
);
|