import { roundHalfUp } from "@/lib/math"; export type MarkupType = "percent" | "fixed"; export const MARKUP_PERCENT_MIN = 0; export const MARKUP_PERCENT_MAX = 30; export const MARKUP_PERCENT_DECIMALS = 2; export const MARKUP_FIXED_MAX = 99_999.99; export type ParsedMarkupInput = { markupType: MarkupType; markupPercent: number; markupFixedAmount: number | null; }; export type MarkupValidationError = | { code: "INVALID_BODY"; message: string } | { code: "PERCENT_TOO_HIGH"; message: string } | { code: "INVALID_PERCENT"; message: string } | { code: "INVALID_FIXED"; message: string }; function parseMarkupType(value: unknown): MarkupType | null { if (value === undefined || value === null || value === "") { return "percent"; } if (value === "percent" || value === "fixed") { return value; } return null; } function parsePercentValue(value: unknown): number | null { if (typeof value !== "number" || Number.isNaN(value)) { return null; } return roundHalfUp(value, MARKUP_PERCENT_DECIMALS); } function parseFixedAmount(value: unknown): number | null { if (typeof value !== "number" || Number.isNaN(value)) { return null; } if (value < 0 || value > MARKUP_FIXED_MAX) { return null; } return roundHalfUp(value, 2); } /** 解析并校验加价配置入参(宿主 API / 管理端共用) */ export function parseMarkupInput(body: { markup_type?: unknown; markup_percent?: unknown; markup_fixed_amount?: unknown; }): ParsedMarkupInput | MarkupValidationError { const markupType = parseMarkupType(body.markup_type); if (!markupType) { return { code: "INVALID_BODY", message: "加价方式无效,请使用 percent 或 fixed" }; } if (markupType === "fixed") { const fixed = parseFixedAmount(body.markup_fixed_amount); if (fixed === null) { if ( typeof body.markup_fixed_amount === "number" && body.markup_fixed_amount > MARKUP_FIXED_MAX ) { return { code: "INVALID_FIXED", message: `固定加价金额不能超过 $${MARKUP_FIXED_MAX.toFixed(2)}`, }; } return { code: "INVALID_FIXED", message: "请提供有效的固定加价金额(≥ 0)", }; } return { markupType: "fixed", markupPercent: 0, markupFixedAmount: fixed, }; } const percent = parsePercentValue(body.markup_percent); if (percent === null) { return { code: "INVALID_PERCENT", message: "请提供有效的加价比例(0~30%,步长 0.01%)" }; } if (percent > MARKUP_PERCENT_MAX) { return { code: "PERCENT_TOO_HIGH", message: "加价比例不能超过 30%" }; } if (percent < MARKUP_PERCENT_MIN) { return { code: "INVALID_PERCENT", message: "请提供有效的加价比例(0~30%,步长 0.01%)" }; } return { markupType: "percent", markupPercent: percent, markupFixedAmount: null, }; }