54 lines
1.9 KiB
TypeScript
54 lines
1.9 KiB
TypeScript
/**
|
|
* 小数输入:保留用户输入形态,不强制补尾零;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
|
|
}
|