vue项目如何解决金额计算超过15出现精度丢失问题
vue项目如何解决金额计算超过15出现精度丢失问题
(1)使用big.js解决
npm i big.js
示例
应收金额 + 收款金额 不能大于累计实收金额
金额15位 + 小数点2位,出现精度丢失
500000000000000 + 0.02 !=500000000000000.02
使用big.js的几个方法来转换解决
<template>
<h-bill-container
:content="content"
:router="backUrl"
:billHead="billHead"
v-loading="mainLoading"
>
<el-collapse v-model="collapseName" class="collase-box" id="collse">
<el-form
:model="model"
ref="contractRef"
label-width="150px"
:rules="rules"
class="inspect-form"
>
<el-collapse-item name="3" title="收款信息" id="3">
<el-row :gutter="20">
<el-col :lg="8" :md="8">
<el-form-item label="应收金额:" :prop="model.receiveType == 0 ? '' : 'receivableAmount'">
<el-input
clearable
:disabled="model.receiveType && model.receiveType == 1 ? false : true"
v-model="model.receivableAmount"
placeholder="自动带出"
>
<span slot="append">元</span>
</el-input>
</el-form-item>
</el-col>
<el-col :lg="8" :md="8">
<el-form-item label="累计实收金额:">
<el-input
v-model="model.receiveAmountHis"
disabled
placeholder="自动带出"
>
<span slot="append">元</span>
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-collapse-item>
<el-collapse-item name="4" title="收款流水信息" id="4">
<el-row :gutter="20">
<div class="inspect-table">
<el-table class="table-supplier" :data="model.detailList" border
:header-cell-style="{background:'#F5F7FA',color:'#333333', height: '45px',textAlign: 'center'}"
>
<el-table-column label="收款金额(元)" min-width="40">
<template slot="header">
<span class="star">*</span>
<span>收款金额(元)</span>
</template>
<template slot-scope="scope">
<el-form-item
label-width="0px"
class="isError"
:prop="'detailList.' + scope.$index + '.receiveAmount'"
:rules="rules.receiveAmount"
>
<el-input
v-model="scope.row.receiveAmount"
placeholder="请输入金额"
class="select-width"
maxlength="15"
clearable
>
</el-input>
</el-form-item>
</template>
</el-table-column>
</el-table>
</div>
</el-row>
</el-collapse-item>
</el-form>
</el-collapse>
</h-bill-container>
</template>
import Big from 'big.js';
export default {
components: {
AnchorPoint,
proSelect,
projectSelect,
},
data() {
return {
model: {
approvalAmount:'',//批复金额
receivableAmount: null, //应收金额
receiveAmountHis: "", //累计实收金额
},
oldModel: {},
rules: {
receivableAmount: [
{ required: true, validator: this.checkReceivableAmount}
],
receiveAmount: [
{ required: true, validator: this.checkReceiveMoney, trigger: ['blur','change'] }
],
},
};
},
methods: {
//校验应收金额
checkReceivableAmount(rule, value, callback) {
var reg = /^-?[0-9]+(\.[0-9]{1,2})?$/;
const num1 = Big(Number(this.model.receiveAmountHis))
const num2 = isNaN(Number(this.model.detailList[0].receiveAmount)) ? undefined : Big(Number(this.model.detailList[0].receiveAmount))
const result = isNaN(Number(num2)) ? undefined : num1.plus(Number(num2)).toString();
// const num2 = Big(Number(this.model.detailList[0].receiveAmount))
// const result = num1.plus(num2).toString();
if (value === "" || value == undefined || value == null) {
callback(new Error(`请输入应收金额`));
return;
} else if (!reg.test(value)) {
callback(new Error(`只能输入正数,负数或0,且最多保留两位小数`));
return;
} else if(this.model.detailList[0].receiveAmount) {
if(new Big(value).lt(new Big(result))) {
callback(new Error(`收款金额与累计实收金额的总和不能大于应收金额`));
return;
}else {
callback();
return;
}
}else {
callback();
}
},
//校验收款金额
checkReceiveMoney(rule, value, callback) {
var reg = /^-?[0-9]+(\.[0-9]{1,2})?$/;
const num1 = Big(Number(this.model.receiveAmountHis))//累计实收金额
const num2 = Big(Number(this.model.receivableAmount))//应收金额
if(isNaN(Number(value))) {
this.resultStatus = false
}else {
this.result = num1.plus(Number(value)).toString();
this.resultStatus = true
}
var reg = /^-?[0-9]+(\.[0-9]{1,2})?$/;
if (value === "" || value == undefined || value == null) {
callback(new Error(`请输入收款金额`));
return;
} else if (!reg.test(value)) {
callback(
new Error(
`收款金额只能输入正数,负数及0,且最多保留两位小数`
)
);
return;
}else if(this.resultStatus){
if(num2 > 0 && new Big(num2).lt(new Big(this.result))) {
callback(new Error(`收款金额与累计实收金额的总和不能大于应收金额`));
return;
}else if(num2 < 0 && new Big(this.result).lt(new Big(num2))) {
callback(new Error(`收款金额与累计实收金额的总和不能小于应收金额`));
return;
}else {
callback();
return;
}
} else {
callback();
return;
}
},
},
};
</script>