Преглед изворни кода

fix(财务计算): 修复浮点数精度问题,使用分进行计算,优化了价格刷新逻辑,确保金额总和与优惠金额精确匹配。

liujt пре 4 месеци
родитељ
комит
5be0348c54

+ 65 - 42
src/BIZComponents/paymentCollectionPlan/Index.vue

@@ -354,7 +354,8 @@
         return this.form.datasource.reduce((acc, cur) => acc + Number(cur.ratio), 0).toFixed(2);
       },
       allPrice() {
-        return this.form.datasource.reduce((acc, cur) => acc + Number(cur.price), 0).toFixed(2);
+        // 使用分进行计算,避免浮点数精度问题
+        return (this.form.datasource.reduce((acc, cur) => acc + Math.round(Number(cur.price) * 100), 0) / 100).toFixed(2);
       },
     },
     watch: {
@@ -366,14 +367,14 @@
       info: {
         handler(newval) {
           if (newval && newval.receiptPaymentList) {
-            // this.isLoadingFromApi = true;
-            // this.form.datasource = newval.receiptPaymentList;
-            // if (newval.payAmount) {
-            //   this.discountAmount = newval.payAmount;
-            // }
-            // setTimeout(() => {
-            //   this.isLoadingFromApi = false;
-            // }, 100);
+            this.isLoadingFromApi = true;
+            this.form.datasource = newval.receiptPaymentList;
+            if (newval.payAmount) {
+              this.discountAmount = newval.payAmount;
+            }
+            setTimeout(() => {
+              this.isLoadingFromApi = false;
+            }, 100);
           }
         },
         deep: true
@@ -382,11 +383,9 @@
     methods: {
       setDiscountAmount(val) {
         console.log(val, '000000');
-        // this.isLoadingFromApi = true;
         this.discountAmount = val;
-        // setTimeout(() => {
-        //   this.isLoadingFromApi = false;
-        // }, 100);
+        // 立即更新价格,无需设置isLoadingFromApi为true
+        this.refreshprice();
       },
       typeChange(val, index = null) {
         // console.log(val, index, '55555');
@@ -449,42 +448,66 @@
         });
       },
       refreshprice() {
-        // console.log(this.form, '666666');
-        let newData = this.form.datasource;
+        // 如果正在从API加载数据,则不执行刷新操作
+        if (this.isLoadingFromApi) {
+          return;
+        }
+        
+        // 创建一个新的数组,避免直接修改原数组
+        let newData = JSON.parse(JSON.stringify(this.form.datasource));
+        console.log('newData after copy:', newData);
         
         // 先根据比例计算所有价格
-        newData.forEach(async (r, index) => {
+        for (let i = 0; i < newData.length; i++) {
+          const r = newData[i];
           if (r.ratio) {
-            console.log(this.ratioInput(Number(r.ratio)), '9999888888');
-            r.price = await this.ratioInput(Number(r.ratio));
+            // 直接计算价格,避免使用async/await的forEach
+            let val = Number(r.ratio);
+            let newval = (val / 100).toFixed(2);
+            let price = (this.discountAmount * newval).toFixed(2);
+            newData[i] = {
+              ...r,
+              price: price
+            };
+            console.log('updated item', i, 'price:', price);
           }
-        });
+        }
         
         // 验证并调整最后一行价格,确保总和等于优惠后的总金额
-        setTimeout(() => {
-          const allPriceSum = newData.reduce((acc, cur) => acc + Number(cur.price || 0), 0);
-          const discountAmount = Number(this.discountAmount);
-          // 直接计算比例总和,避免字符串转换问题
-          const allRatio = newData.reduce((acc, cur) => acc + Number(cur.ratio || 0), 0);
-          
-          // 检查是否所有数据都有price且比例合计为100%
-          const allHavePrice = newData.every(item => item.price != null && item.price !== '');
-          
-          if (allHavePrice && Math.abs(allRatio - 100) < 0.01 && Math.abs(allPriceSum - discountAmount) > 0.01) {
-            // 调整最后一行的价格
-            if (newData.length > 0) {
-              const lastIndex = newData.length - 1;
-              // 计算其他行的价格总和
-              const otherPriceSum = newData.slice(0, lastIndex).reduce((acc, cur) => acc + Number(cur.price || 0), 0);
-              // 计算最后一行应该有的价格
-              const lastPrice = discountAmount - otherPriceSum;
-              this.$set(newData, lastIndex, {
-                ...newData[lastIndex],
-                price: lastPrice.toFixed(2)
-              });
-            }
+        // 使用分进行计算,避免浮点数精度问题
+        const allPriceSum = newData.reduce((acc, cur) => acc + Math.round(Number(cur.price || 0) * 100), 0) / 100;
+        const discountAmount = Number(this.discountAmount);
+        // 直接计算比例总和,避免字符串转换问题
+        const allRatio = newData.reduce((acc, cur) => acc + Number(cur.ratio || 0), 0);
+        
+        console.log('allPriceSum:', allPriceSum, 'discountAmount:', discountAmount, 'allRatio:', allRatio);
+        
+        // 检查是否所有数据都有price且比例合计为100%
+        const allHavePrice = newData.every(item => item.price != null && item.price !== '');
+        
+        console.log('allHavePrice:', allHavePrice);
+        
+        if (allHavePrice && Math.abs(allRatio - 100) < 0.01 && Math.abs(allPriceSum - discountAmount) >= 0.01) {
+          // 调整最后一行的价格
+          if (newData.length > 0) {
+            const lastIndex = newData.length - 1;
+            // 使用分进行计算,避免浮点数精度问题
+            const otherPriceSum = newData.slice(0, lastIndex).reduce((acc, cur) => acc + Math.round(Number(cur.price || 0) * 100), 0) / 100;
+            // 计算最后一行应该有的价格
+            const lastPrice = Math.round((discountAmount - otherPriceSum) * 100) / 100;
+            newData[lastIndex] = {
+              ...newData[lastIndex],
+              price: lastPrice.toFixed(2)
+            };
+            console.log('adjusted last item price:', lastPrice);
           }
-        }, 0);
+        }
+        
+        console.log('newData before update:', newData);
+        
+        // 确保更新this.form.datasource,触发Vue的响应式更新
+        this.form.datasource = newData;
+        console.log('after update, datasource:', this.form.datasource);
       },
       // 返回列表数据
       getTableValue() {

+ 9 - 5
src/views/contractManage/contractBook/components/addDialog.vue

@@ -1962,15 +1962,19 @@
             return;
           }
 
-          let receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + +cur.price, 0);
+          // 使用分进行计算,避免浮点数精度问题
+          let receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + Math.round(+cur.price * 100), 0) / 100;
           const payAmount = +commitData.payAmount;
           
           if(+ratioSum == 100) {
-            const difference = payAmount - receiptPaymentListSum;
-            if (Math.abs(difference) > 0.01 && commitData.receiptPaymentList.length > 0) {
+            // 使用分进行计算,避免浮点数精度问题
+            const difference = Math.round((payAmount - receiptPaymentListSum) * 100) / 100;
+            if (Math.abs(difference) >= 0.01 && commitData.receiptPaymentList.length > 0) {
               const lastIndex = commitData.receiptPaymentList.length - 1;
-              commitData.receiptPaymentList[lastIndex].price = (+commitData.receiptPaymentList[lastIndex].price + difference).toFixed(2);
-              receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + +cur.price, 0);
+              // 使用分进行计算,避免浮点数精度问题
+              const newPrice = Math.round((+commitData.receiptPaymentList[lastIndex].price + difference) * 100) / 100;
+              commitData.receiptPaymentList[lastIndex].price = newPrice.toFixed(2);
+              receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + Math.round(+cur.price * 100), 0) / 100;
             }
           }
 

+ 9 - 5
src/views/purchasingManage/purchaseOrder/components/addDialogNew.vue

@@ -2166,15 +2166,19 @@
             return;
           }
 
-          let receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + +cur.price, 0);
+          // 使用分进行计算,避免浮点数精度问题
+          let receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + Math.round(+cur.price * 100), 0) / 100;
           const payAmount = +commitData.payAmount;
           
           if(+ratioSum == 100) {
-            const difference = payAmount - receiptPaymentListSum;
-            if (Math.abs(difference) > 0.01 && commitData.receiptPaymentList.length > 0) {
+            // 使用分进行计算,避免浮点数精度问题
+            const difference = Math.round((payAmount - receiptPaymentListSum) * 100) / 100;
+            if (Math.abs(difference) >= 0.01 && commitData.receiptPaymentList.length > 0) {
               const lastIndex = commitData.receiptPaymentList.length - 1;
-              commitData.receiptPaymentList[lastIndex].price = (+commitData.receiptPaymentList[lastIndex].price + difference).toFixed(2);
-              receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + +cur.price, 0);
+              // 使用分进行计算,避免浮点数精度问题
+              const newPrice = Math.round((+commitData.receiptPaymentList[lastIndex].price + difference) * 100) / 100;
+              commitData.receiptPaymentList[lastIndex].price = newPrice.toFixed(2);
+              receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + Math.round(+cur.price * 100), 0) / 100;
             }
           }
 

+ 10 - 5
src/views/saleManage/saleOrder/components/addDialogNew.vue

@@ -1934,15 +1934,20 @@
               return;
             }
 
-            let receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + +cur.price, 0);
+            // 使用分进行计算,避免浮点数精度问题
+            let receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + Math.round(+cur.price * 100), 0) / 100;
             const payAmount = +commitData.payAmount;
             
             if(+ratioSum == 100) {
-              const difference = payAmount - receiptPaymentListSum;
-              if (Math.abs(difference) > 0.01 && commitData.receiptPaymentList.length > 0) {
+              // 使用分进行计算,避免浮点数精度问题
+              const difference = Math.round((payAmount - receiptPaymentListSum) * 100) / 100;
+              console.log('difference~~~', difference);
+              if (Math.abs(difference) >= 0.01 && commitData.receiptPaymentList.length > 0) {
                 const lastIndex = commitData.receiptPaymentList.length - 1;
-                commitData.receiptPaymentList[lastIndex].price = (+commitData.receiptPaymentList[lastIndex].price + difference).toFixed(2);
-                receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + +cur.price, 0);
+                // 使用分进行计算,避免浮点数精度问题
+                const newPrice = Math.round((+commitData.receiptPaymentList[lastIndex].price + difference) * 100) / 100;
+                commitData.receiptPaymentList[lastIndex].price = newPrice.toFixed(2);
+                receiptPaymentListSum = commitData.receiptPaymentList.reduce((acc, cur) => acc + Math.round(+cur.price * 100), 0) / 100;
               }
             }