/** * 小数输入:保留用户输入形态,不强制补尾零;precision 表示最多小数位数。 */ /** 输入清洗:仅保留数字与小数点,截断到 maxPrecision 位小数 */ export function sanitizeDecimalInput(value: string, maxPrecision = 4): string { if (!value) return '' let cleaned = value.replace(/,/g, '').replace(/[^0-9.-]/g, '') const isNegative = cleaned.startsWith('-') if (isNegative) cleaned = cleaned.slice(1).replace(/-/g, '') cleaned = cleaned.replace(/[^0-9.]/g, '') if (maxPrecision <= 0) { return (isNegative ? '-' : '') + cleaned.replace(/\./g, '') } const dotIndex = cleaned.indexOf('.') if (dotIndex !== -1) { const intPart = cleaned.slice(0, dotIndex + 1) const decPart = cleaned.slice(dotIndex + 1).replace(/\./g, '') cleaned = intPart + decPart.slice(0, maxPrecision) } return (isNegative ? '-' : '') + cleaned } /** 外部数值同步到输入框:去掉无意义的尾零,不补零 */ export function formatDecimalDisplayNatural( value: number | null | undefined, maxPrecision = 4 ): string { if (value === null || value === undefined) return '' if (Number.isNaN(value)) return '' if (maxPrecision <= 0) return String(Math.trunc(value)) const factor = Math.pow(10, maxPrecision) const rounded = Math.round(value * factor) / factor return String(rounded) } /** 解析为 number;空串 / 仅符号或点 → undefined */ export function parseDecimalToNumber( value: string, maxPrecision = 4 ): number | undefined { const sanitized = sanitizeDecimalInput(value, maxPrecision) if (!sanitized || sanitized === '.' || sanitized === '-' || sanitized === '-.') { return undefined } const num = Number(sanitized) if (Number.isNaN(num)) return undefined if (maxPrecision <= 0) return Math.trunc(num) const factor = Math.pow(10, maxPrecision) return Math.round(num * factor) / factor }