Files
shanxia2.0/web-admin/src/utils/money-format.ts
T
2026-05-25 17:43:49 +08:00

74 lines
2.5 KiB
TypeScript

/**
* 金额格式化工具模块
* 提供千分位分隔、输入清洗、展示格式化、数值解析等功能
*/
/** 字符串分段拼接千分位,禁止使用前瞻正则 */
export function addThousandSeparators(intStr: string): string {
if (!intStr) return ''
const isNegative = intStr.startsWith('-')
const absStr = isNegative ? intStr.slice(1) : intStr
const parts: string[] = []
const len = absStr.length
for (let i = len; i > 0; i -= 3) {
const start = Math.max(0, i - 3)
parts.unshift(absStr.slice(start, i))
}
const result = parts.join(',')
return isNegative ? `-${result}` : result
}
/** 输入清洗:去逗号、仅保留数字与一个点、截断小数位 */
export function sanitizeMoneyInput(value: string, precision = 2): string {
if (!value) return ''
// 去逗号
let cleaned = value.replace(/,/g, '')
// 去非数字非点字符
cleaned = cleaned.replace(/[^0-9.]/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
}
// 截断小数到 precision 位
if (dotIndex !== -1) {
const dotIdx = cleaned.indexOf('.')
const intPart = cleaned.slice(0, dotIdx + 1)
let decPart = cleaned.slice(dotIdx + 1)
if (decPart.length > precision) {
decPart = decPart.slice(0, precision)
}
cleaned = intPart + decPart
}
return cleaned
}
/** 展示:整数部分千分位 + 最多 precision 位小数 */
export function formatMoneyDisplay(
value: string | number | null | undefined,
precision = 2
): string {
if (value === null || value === undefined || value === '') return '0.00'
const num = typeof value === 'string' ? parseFloat(value) : value
if (isNaN(num)) return '0.00'
const isNegative = num < 0
const absNum = Math.abs(num)
const fixed = absNum.toFixed(precision)
const [intStr, decStr] = fixed.split('.')
const formatted = addThousandSeparators(intStr)
const result = `${formatted}.${decStr}`
return isNegative ? `-${result}` : result
}
/** 提交:number | null;空串 / 仅 '.' → null */
export function parseMoneyToNumber(value: string, precision = 2): number | null {
const sanitized = sanitizeMoneyInput(value, precision)
if (!sanitized || sanitized === '.') return null
const num = Number(sanitized)
if (isNaN(num)) return null
const factor = Math.pow(10, precision)
return Math.round(num * factor) / factor
}