import type { Priority1DemoInput } from "@/workers/rpa/priority1/demo-input"; import { validatePriority1FormConstraints } from "@/workers/rpa/priority1/form-constraints"; import { findPhoneCountry } from "@/lib/priority1/phone-countries"; import { pickupDateValidationMessage } from "@/lib/priority1/pickup-date"; import { ValidationError } from "@/modules/quote/types"; const ZIP_RE = /^\d{5}$/; const DATE_RE = /^\d{2}\/\d{2}\/\d{4}$/; function req(value: string | undefined, label: string): string { const v = value?.trim(); if (!v) throw new ValidationError(`请填写${label}`); return v; } /** 校验 Priority1 模拟表单提交 */ export function validatePriority1QuoteInput( body: unknown, ): Priority1DemoInput & { request_id: string; customer_id: string } { if (!body || typeof body !== "object") { throw new ValidationError("请求体格式无效"); } const o = body as Record; const requestId = req(o.request_id as string | undefined, "请求标识"); const customerId = req(o.customer_id as string | undefined, "客户标识"); const input = o.priority1_input; if (!input || typeof input !== "object") { throw new ValidationError("请填写 Priority1 表单参数"); } const p = input as Priority1DemoInput; if (!["ltl", "ftl", "expedited"].includes(p.shipmentType)) { throw new ValidationError("请选择运输类型"); } if (!ZIP_RE.test(req(p.originZip, "起运邮编"))) { throw new ValidationError("起运邮编须为 5 位数字"); } if (!ZIP_RE.test(req(p.destinationZip, "目的邮编"))) { throw new ValidationError("目的邮编须为 5 位数字"); } if (p.originZip === p.destinationZip) { throw new ValidationError("起运与目的邮编不能相同"); } if (!DATE_RE.test(req(p.pickupDate, "提货日"))) { throw new ValidationError("提货日格式须为 MM/DD/YYYY"); } const pickupDateError = pickupDateValidationMessage(p.pickupDate); if (pickupDateError) { throw new ValidationError(pickupDateError); } const phoneDigits = req(p.phone, "电话").replace(/\D/g, ""); const country = findPhoneCountry(p.phoneCountry ?? "US"); if (country.code === "US" || country.code === "CA") { if (phoneDigits.length !== 10) { throw new ValidationError("美国/加拿大电话须为 10 位数字"); } } else if (phoneDigits.length < 6 || phoneDigits.length > 15) { throw new ValidationError("请填写有效电话号码"); } req(p.email, "商务邮箱"); if (p.shipmentType === "ltl") { req(p.lengthIn, "长度"); req(p.widthIn, "宽度"); req(p.heightIn, "高度"); req(p.weightLb, "总重量"); req(p.packaging, "包装类型"); req(p.palletCount, "托盘数"); req(p.freightClass, "货运等级"); req(p.pickupLocation, "提货地点类型"); req(p.deliveryLocation, "派送地点类型"); } if (p.shipmentType === "ftl") { req(p.commodity, "货描"); req(p.weightLb, "总重量"); if (p.ftlTrailer !== "ftl_expedited") { req(p.palletCount, "托盘数"); } if (p.ftlTrailer === "open_deck") req(p.openDeckSubtype, "Open Deck 子类型"); if (p.ftlTrailer === "temperature_controlled") { req(p.tempMinF, "最低温度"); req(p.tempMaxF, "最高温度"); } } if (p.shipmentType === "expedited") { req(p.commodity, "货描"); req(p.weightLb, "总重量"); } const constraintErrors = validatePriority1FormConstraints(p).filter( (v) => v.severity === "error", ); if (constraintErrors.length > 0) { throw new ValidationError(constraintErrors[0]!.message); } return { ...p, phone: p.phone.replace(/\D/g, "").slice(-10), request_id: requestId, customer_id: customerId, }; }