import type { EventItem } from "@/types/EventItem"; /** * 返回事件数值单位的前端文案。 * 后端仍使用 CENT 表示金额分,前端统一按元展示和录入。 */ export function getEventValueUnitText(valueUnit?: EventItem["valueUnit"]): string { if (valueUnit === "CENT") { return "元"; } if (valueUnit === "COUNT") { return "次"; } return "未配置单位"; } /** * 获取事件数值输入提示。 */ export function getEventNumberValuePlaceholder(event: EventItem): string { if (event.valueUnit === "CENT") { return event.requireValue ? "金额(元),最多两位小数" : "金额(元),可留空,最多两位小数"; } return event.requireValue ? "次数,必须是大于等于 0 的整数" : "次数,可留空,必须是大于等于 0 的整数"; } /** * 将前端输入的事件数值转换为后端要求的整数。 * 金额使用字符串拆分后转换为分,避免直接使用浮点数放大导致精度误差。 */ export function resolveEventNumberValue(event: EventItem, valueText: string): number | undefined { const normalizedValue = valueText.trim(); if (!normalizedValue) { return undefined; } if (event.valueUnit === "CENT") { return resolveCentValue(normalizedValue); } if (!/^\d+$/.test(normalizedValue)) { return undefined; } const value = Number(normalizedValue); return Number.isSafeInteger(value) ? value : undefined; } /** * 将后端返回的整数分转换为前端金额文案。 */ export function formatEventNumberValue(event: EventItem | undefined, value?: number | null): string { if (value === undefined || value === null) { return "-"; } if (event?.valueUnit !== "CENT") { return `${value}${event?.valueUnit === "COUNT" ? " 次" : ""}`; } return `${formatCentValue(value)} 元`; } /** * 将金额字符串转换为分,最多保留两位小数。 */ export function resolveCentValue(valueText: string): number | undefined { const match = /^(\d+)(?:\.(\d{0,2}))?$/.exec(valueText); if (!match) { return undefined; } const integerText = match[1]; const decimalText = (match[2] || "").padEnd(2, "0"); const centValue = BigInt(integerText) * 100n + BigInt(decimalText || "0"); if (centValue > BigInt(Number.MAX_SAFE_INTEGER)) { return undefined; } return Number(centValue); } /** * 将整数分格式化为不带单位的元字符串。 */ export function formatCentValue(value: number): string { if (!Number.isSafeInteger(value) || value < 0) { return ""; } const centText = String(value); const yuanText = centText.length < 3 ? "0" : centText.slice(0, -2); const decimalText = centText.slice(-2).padStart(2, "0").replace(/0+$/, ""); return `${yuanText}${decimalText ? `.${decimalText}` : ""}`; }