You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chajia/lib/mothership/ms-checkout-selection.ts

59 lines
1.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* MotherShip 结账选价 / FreightProtect 货值校验
*/
export type MsCoverageKind = "basic" | "freight_protect";
export type MsCheckoutSelection = {
preferredCarrier: string;
coverage: MsCoverageKind;
cargoValueUsd?: number;
};
/** 返回中文错误;null = 通过 */
export function validateMsCheckoutSelection(
input: MsCheckoutSelection,
): string | null {
const carrier = input.preferredCarrier?.trim();
if (!carrier) return "请选择承运商";
if (carrier.length > 128) return "承运商名称过长";
if (input.coverage !== "basic" && input.coverage !== "freight_protect") {
return "保障方案无效";
}
if (input.coverage === "freight_protect") {
const v = Number(input.cargoValueUsd);
if (!Number.isFinite(v) || v <= 0) {
return "选择 FreightProtect 时请填写大于 0 的货物价值(美元)";
}
if (v > 1_000_000) {
return "货物价值超出允许范围";
}
}
return null;
}
/** 输入框清洗:允许美元小数(最多两位),并兼容输入过程中的尾随小数点 */
export function sanitizeCargoValueUsdInput(raw: string): string {
let cleaned = raw.replace(/[$,\s]/g, "").replace(/[^\d.]/g, "");
const firstDot = cleaned.indexOf(".");
if (firstDot >= 0) {
cleaned =
cleaned.slice(0, firstDot + 1) +
cleaned.slice(firstDot + 1).replace(/\./g, "");
}
const m = cleaned.match(/^(\d*)(\.?)(\d{0,2})/);
if (!m) return "";
return `${m[1] ?? ""}${m[2] ?? ""}${m[3] ?? ""}`;
}
/** 解析货值(美元);支持小数,四舍五入到分 */
export function parseCargoValueUsd(raw: string): number | null {
const cleaned = raw.replace(/[$,\s]/g, "").trim();
if (!cleaned || cleaned === ".") return null;
const n = Number(cleaned);
if (!Number.isFinite(n) || n <= 0) return null;
const cents = Math.round(n * 100) / 100;
if (!Number.isFinite(cents) || cents <= 0) return null;
return cents;
}