前端百分比展示导致后端 BigDecimal 转换异常的排查与解决

在开发一个订单预算系统 时,我们需要在前端动态计算「利润率差额」,格式为百分比(带 % 符号)保留4位小数 ,但实际传给后端时必须是纯数字(浮点数) ,以便后端正常以 BigDecimal 类型接收并处理。

然而,我们在某次提交数据到后端时,系统直接抛出以下异常:

告诉我们传递的是null ,告诉我无法转换

问题分析

前端相关代码如下所示:

html 复制代码
// 利润率差额 profitRateDiff(百分比 + % 符号,保留4位小数)
const orderRevenueActual = Number(this.costData.orderRevenueActual) || 0
let profitRateDiff = '0.0000%' // 👈 注意这里是字符串!
if (orderRevenueActual !== 0) {
  const rate = (netProfitDiff / orderRevenueActual) * 100
  profitRateDiff = `${rate.toFixed(4)}%`
}
this.$set(this.costData, 'profitRateDiff', profitRateDiff)

这段代码表面上看没毛病,逻辑严谨,结果也是正确显示出"28.4212%"这样格式化的字符串。

然而,致命问题在于:

👉 profitRateDiff 被直接设置为 字符串类型(带 %)

👉 最终提交接口时 this.costData.profitRateDiff 仍是字符串 "28.4212%"

👉 后端尝试将 "28.4212%" 转换为 BigDecimal,但 % 字符不是合法数字格式

👉 报错!

正确写法

1. 存值用数字,不要包含 % 字符,如果需要可以重新写个方法转过去

html 复制代码
const orderRevenueActual = Number(this.costData.orderRevenueActual) || 0
let profitRateDiff = 0 // 👈 注意初始化为数字
if (orderRevenueActual !== 0) {
  const rate = (netProfitDiff / orderRevenueActual) * 100
  profitRateDiff = +rate.toFixed(4) // 强转为小数数字
}
this.$set(this.costData, 'profitRateDiff', profitRateDiff) // 仍是纯数字

比如:

html 复制代码
methods: {
  formatPercent(value) {
    if (value == null || isNaN(value)) return '0.0000%'
    return value.toFixed(4) + '%'
  }
}

最佳实践总结

需求 实现方式
存储 使用数字 28.4212
展示 格式化显示为 28.4212%
提交后端 保证 costData.profitRateDiff 是数字类型

写在最后

这次坑给我们的经验是:

  • 前端显示归显示,存储归存储,一定要分离

  • 在与后端协作中,要严格约定字段类型:数字就是数字、字符串就是字符串

  • 对格式化展示的字段,尽量使用计算属性、方法或者过滤器处理,而不要将格式化后的值直接赋值到数据模型中