高精度金额(currency.js)
灵感:能力工具箱 currency-money(pkg: currency.js)。
CRM 报价、回款、佣金本地加减时,用 currency.js 代替裸 number 运算,避免 0.1 + 0.2 类误差展示到分位。
何时使用
- 报价行合计、含税/未税累加
- 回款流水合计、已收/未收
- 需要「分」为单位的稳定展示(默认 2 位小数)
硬约束
- 依赖
currency.js;金额字符串/数字经currency()包装后再运算。 - 展示用
.format()或固定toFixed(2)等价输出;禁止直接a + b裸浮点累加业务金额。 - 币种符号可配置(默认
¥或空,按项目 UI);不发起汇率网络请求。 - 输入非法时返回可读错误,不抛未捕获异常到 UI。
- 与「安全公式求值」分工:复杂表达式可用 mathjs;金额累加优先 currency.js。
推荐实现要点
import currency from 'currency.js'
const cny = (v: currency.Any) =>
currency(v, { symbol: '¥', precision: 2, separator: ',', decimal: '.' })
export function sumAmounts(values: Array<string | number>): string {
const total = values.reduce((acc, v) => acc.add(v), cny(0))
return total.format()
}
export function quoteTotal(lines: { price: number; qty: number }[]) {
const total = lines.reduce(
(acc, line) => acc.add(cny(line.price).multiply(line.qty)),
cny(0),
)
return {
value: total.value,
display: total.format(),
}
}
export function remaining(receivable: number, receivedList: number[]) {
const left = receivedList.reduce((acc, v) => acc.subtract(v), cny(receivable))
return { value: left.value, display: left.format() }
}
Agent 步骤
- 安装
currency.js,封装cny与sumAmounts/quoteTotal。 - 自测:
0.1+0.2经封装后展示为¥0.30;多行报价合计与手工一致。 - 列表/表单金额字段统一走封装,避免混用裸 number 加法。
附加
- README.md · reference.md · templates/usage.md