当前位置: 首页 > news >正文

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>

相关文章:

  • 自然语言处理(NLP)技术
  • 前端按钮动画
  • npm install的-S和-D的区别
  • iOS中卡顿产生的主要原因及优化思路
  • Apache Paimon Append Queue表解析
  • 【语音识别】- 几个主流模型
  • 数据库的介绍、分类、作用和特点
  • 【C++精简版回顾】14.(重载2)流重载
  • 【Python】python离线安装依赖
  • 3D工业相机及品牌集合
  • 蓝月亮,蓝禾,三七互娱,顺丰,康冠科技,金证科技24春招内推
  • git入门
  • PCIE Order Set
  • java spring cloud 企业电子招标采购系统源码:营造全面规范安全的电子招投标环境,促进招投标市场健康可持续发展
  • 大宇、固特、希亦超声波清洗机实测,哪款清洗效果好?一篇掌握
  • Laravel Octane 和 Swoole 协程的使用分析二
  • Unity 向量计算、欧拉角与四元数转换、输出文本、告警、错误、修改时间、定时器、路径、
  • SQL server创建数据库
  • leetcode--接雨水(双指针法,动态规划,单调栈)
  • 【AI Agent系列】【MetaGPT多智能体学习】3. 开发一个简单的多智能体系统,兼看MetaGPT多智能体运行机制
  • 俄联邦安全局:俄军高级官员汽车爆炸案嫌疑人已被捕
  • 我驻阿巴斯总领馆:将持续跟踪港口爆炸事件进展,全力确保中方人员安全
  • 《深化养老服务改革发展的大湾区探索》新书将于今年6月出版
  • 政治局会议:持续稳定和活跃资本市场
  • “80后”李岩已任安徽安庆市领导
  • 从息屏24小时到息屏1小时,姚明在深圳开启落地试点