|
|
@@ -11,20 +11,22 @@
|
|
|
<!-- 表头工具栏 -->
|
|
|
<template v-slot:toolbar>
|
|
|
<div class="headbox">
|
|
|
- <el-button
|
|
|
- size="small"
|
|
|
- type="primary"
|
|
|
- icon="el-icon-plus"
|
|
|
- class="ele-btn-icon"
|
|
|
- @click="handlAdd"
|
|
|
- v-if="type!='view'"
|
|
|
- >
|
|
|
- 新增
|
|
|
- </el-button>
|
|
|
+ <div>
|
|
|
+ <el-button
|
|
|
+ size="small"
|
|
|
+ type="primary"
|
|
|
+ icon="el-icon-plus"
|
|
|
+ class="ele-btn-icon"
|
|
|
+ @click="handlAdd"
|
|
|
+ v-if="showAddBtn"
|
|
|
+ >
|
|
|
+ 新增
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
|
|
|
<div class="pricebox">
|
|
|
<span class="amount">比例合计:{{ allRatio }}%</span>
|
|
|
- <span class="amount">计划{{ menu === 'purchase' ? '收款' : '付款' }}金额合计:{{ allPrice }}元</span>
|
|
|
+ <span class="amount">计划{{ menu === 'purchase' ? '付款' : '收款' }}金额合计:{{ allPrice }}元</span>
|
|
|
|
|
|
<!-- <el-form-item
|
|
|
style="width: 300px"
|
|
|
@@ -122,7 +124,7 @@
|
|
|
placeholder="请选择"
|
|
|
style="width: 100%"
|
|
|
:disabled="type=='view'"
|
|
|
-
|
|
|
+ @change="(val) => typeChange(val, scope.$index)"
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="item in paymentTypeOp"
|
|
|
@@ -155,7 +157,7 @@
|
|
|
<el-input
|
|
|
type="number"
|
|
|
:min="0"
|
|
|
- :disabled="type=='view'"
|
|
|
+ disabled
|
|
|
v-model="scope.row.price"
|
|
|
style="width: 100%"
|
|
|
placeholder="请输入"
|
|
|
@@ -177,7 +179,7 @@
|
|
|
<el-date-picker
|
|
|
style="width: 140px"
|
|
|
v-model="scope.row.deadLine"
|
|
|
- :disabled="type=='view'"
|
|
|
+ :disabled="!showAddBtn"
|
|
|
type="date"
|
|
|
placeholder="选择日期"
|
|
|
>
|
|
|
@@ -220,6 +222,7 @@
|
|
|
<script>
|
|
|
import { emailReg, phoneReg, numberReg } from 'ele-admin';
|
|
|
import { paymentTypeOp } from '@/enum/dict';
|
|
|
+ import { formatPrice } from '@/BIZComponents/setProduct.js';
|
|
|
export default {
|
|
|
props: {
|
|
|
delDetailIds: Array,
|
|
|
@@ -231,6 +234,10 @@
|
|
|
discountTotalPrice: {
|
|
|
type: [Number, String],
|
|
|
default: 0
|
|
|
+ },
|
|
|
+ info: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {}
|
|
|
}
|
|
|
},
|
|
|
data() {
|
|
|
@@ -242,6 +249,7 @@
|
|
|
ratio: null,
|
|
|
remark: '',
|
|
|
type: '',
|
|
|
+ typeName: '',
|
|
|
issueNumber: null
|
|
|
};
|
|
|
return {
|
|
|
@@ -254,14 +262,19 @@
|
|
|
datasource: []
|
|
|
},
|
|
|
paymentTypeOp,
|
|
|
-
|
|
|
- rules: {}
|
|
|
+ rules: {},
|
|
|
+ isLoadingFromApi: false
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
canHandl() {
|
|
|
return this.form.datasource.length;
|
|
|
},
|
|
|
+ showAddBtn() {
|
|
|
+ // console.log('showAddBtn~~~~', this.type, this.info);
|
|
|
+ // console.log('showAddBtn!!!!',!['1', '2'].includes(this.info.settlementMode) || this.type != 'view');
|
|
|
+ return !(['1', '2'].includes(this.info?.settlementMode)) && this.type != 'view'
|
|
|
+ },
|
|
|
columns() {
|
|
|
return [
|
|
|
{
|
|
|
@@ -334,42 +347,68 @@
|
|
|
resizable: false,
|
|
|
slot: 'action',
|
|
|
showOverflowTooltip: true,
|
|
|
- show: this.type != 'view'
|
|
|
+ show: this.showAddBtn
|
|
|
}
|
|
|
];
|
|
|
},
|
|
|
allRatio() {
|
|
|
- return this.form.datasource.reduce((acc, cur) => acc + Number(cur.ratio), 0).toFixed(2);
|
|
|
+ return formatPrice(this.form.datasource.reduce((acc, cur) => acc + Number(cur.ratio), 0));
|
|
|
},
|
|
|
allPrice() {
|
|
|
- return this.form.datasource.reduce((acc, cur) => acc + Number(cur.price), 0).toFixed(2);
|
|
|
+ // 使用分进行计算,避免浮点数精度问题
|
|
|
+ return formatPrice(this.form.datasource.reduce((acc, cur) => acc + Math.round(Number(cur.price) * 100), 0) / 100);
|
|
|
},
|
|
|
},
|
|
|
watch: {
|
|
|
discountAmount(newval) {
|
|
|
- if (newval) {
|
|
|
+ if (newval && !this.isLoadingFromApi) {
|
|
|
this.refreshprice();
|
|
|
}
|
|
|
+ },
|
|
|
+ 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);
|
|
|
+ // }
|
|
|
+ },
|
|
|
+ deep: true
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
setDiscountAmount(val) {
|
|
|
console.log(val, '000000');
|
|
|
this.discountAmount = val;
|
|
|
+ // 立即更新价格,无需设置isLoadingFromApi为true
|
|
|
+ this.refreshprice();
|
|
|
+ },
|
|
|
+ typeChange(val, index = null) {
|
|
|
+ // console.log(val, index, '55555');
|
|
|
+ if (val) {
|
|
|
+ this.$set(this.form.datasource[index], 'typeName', this.paymentTypeOp.find(item => item.value === val).label);
|
|
|
+ }
|
|
|
},
|
|
|
//输入比例更新金额
|
|
|
async ratioInput(val, index = null) {
|
|
|
- console.log(this.discountAmount, '77777');
|
|
|
+ // console.log(this.discountAmount, '77777');
|
|
|
+ // console.log(val, '5555555');
|
|
|
val = Number(val);
|
|
|
try {
|
|
|
if (index != null) {
|
|
|
await this.checkRatio();
|
|
|
}
|
|
|
let newval = (val / 100).toFixed(2);
|
|
|
- let price = (this.discountAmount * newval).toFixed(2);
|
|
|
- console.log(newval, price, index, '88888');
|
|
|
+ // console.log('newval~~~', newval)
|
|
|
+ let price = formatPrice(this.discountAmount * newval);
|
|
|
+ // console.log(newval, price, index, '88888');
|
|
|
if (index != null) {
|
|
|
- console.log(newval, price, index, '999999');
|
|
|
+ // console.log(newval, price, index, '999999');
|
|
|
this.$set(this.form.datasource[index], 'price', price);
|
|
|
} else {
|
|
|
return price;
|
|
|
@@ -390,7 +429,7 @@
|
|
|
sum += Number(r.ratio);
|
|
|
}
|
|
|
});
|
|
|
- console.log(sum, '3333333');
|
|
|
+ // console.log(sum, '3333333');
|
|
|
if (sum > 100) {
|
|
|
this.$message.error('总共比例不能超过100');
|
|
|
this.$set(
|
|
|
@@ -403,20 +442,72 @@
|
|
|
'price',
|
|
|
0.0
|
|
|
);
|
|
|
- reject(false);
|
|
|
+ resolve(true);
|
|
|
} else {
|
|
|
resolve(true);
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
refreshprice() {
|
|
|
- let newData = this.form.datasource;
|
|
|
- newData.forEach(async (r, index) => {
|
|
|
+ // 如果正在从API加载数据,则不执行刷新操作
|
|
|
+ if (this.isLoadingFromApi) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建一个新的数组,避免直接修改原数组
|
|
|
+ let newData = JSON.parse(JSON.stringify(this.form.datasource));
|
|
|
+ console.log('newData after copy:', newData);
|
|
|
+
|
|
|
+ // 先根据比例计算所有价格
|
|
|
+ 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 = formatPrice(this.discountAmount * newval);
|
|
|
+ newData[i] = {
|
|
|
+ ...r,
|
|
|
+ price: price
|
|
|
+ };
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证并调整最后一行价格,确保总和等于优惠后的总金额
|
|
|
+ // 使用分进行计算,避免浮点数精度问题
|
|
|
+ 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: formatPrice(lastPrice)
|
|
|
+ };
|
|
|
+ console.log('adjusted last item price:', lastPrice);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('newData before update:', newData);
|
|
|
+
|
|
|
+ // 确保更新this.form.datasource,触发Vue的响应式更新
|
|
|
+ this.form.datasource = newData;
|
|
|
+ console.log('after update, datasource:', this.form.datasource);
|
|
|
},
|
|
|
// 返回列表数据
|
|
|
getTableValue() {
|
|
|
@@ -424,7 +515,7 @@
|
|
|
},
|
|
|
//修改回显
|
|
|
putTableValue(data) {
|
|
|
- console.log('data~~~~', data);
|
|
|
+ console.log('data~~~~111', data);
|
|
|
if (data) {
|
|
|
this.form.datasource = data.receiptPaymentList;
|
|
|
this.setDiscountAmount(data.payAmount);
|
|
|
@@ -438,6 +529,7 @@
|
|
|
if (row.id) {
|
|
|
this.delDetailIds.push(row.id);
|
|
|
}
|
|
|
+ this.$emit('getIssueNumber', this.form.datasource.length);
|
|
|
}
|
|
|
},
|
|
|
// 清空表格
|
|
|
@@ -451,7 +543,7 @@
|
|
|
});
|
|
|
},
|
|
|
defaultList(method, issueNumber, dateRange) {
|
|
|
- console.log('method, issueNumber', method, issueNumber);
|
|
|
+ // console.log('method, issueNumber', method, issueNumber, dateRange);
|
|
|
const tempList = []
|
|
|
if(dateRange) {
|
|
|
this.setDefaultList(dateRange, issueNumber);
|
|
|
@@ -463,6 +555,7 @@
|
|
|
let item = JSON.parse(JSON.stringify(this.defaultForm));
|
|
|
item.moneyName = i < params.length ? params[i] : '';
|
|
|
item.type = i < params.length ? this.paymentTypeOp[i].value : '';
|
|
|
+ item.typeName = i < params.length ? this.paymentTypeOp[i].label : '';
|
|
|
item.key = i + 1;
|
|
|
item.issueNumber = i + 1;
|
|
|
tempList.push(item);
|
|
|
@@ -486,15 +579,34 @@
|
|
|
// });
|
|
|
for(let i = 0; i < issueNumber; i++) {
|
|
|
let item = JSON.parse(JSON.stringify(this.defaultForm));
|
|
|
+ if(issueNumber == 1) {
|
|
|
+ item.moneyName = '';
|
|
|
+ item.type = 2;
|
|
|
+ item.typeName = '交货款';
|
|
|
+ item.ratio = 100;
|
|
|
+ item.key = i + 1;
|
|
|
+ item.issueNumber = i + 1;
|
|
|
+ } else {
|
|
|
item.moneyName = '';
|
|
|
item.type = '';
|
|
|
+ item.typeName = '';
|
|
|
+ item.ratio = '';
|
|
|
item.key = i + 1;
|
|
|
item.issueNumber = i + 1;
|
|
|
- tempList.push(item);
|
|
|
+ }
|
|
|
+ tempList.push(item);
|
|
|
}
|
|
|
}
|
|
|
console.log('tempList~~~', tempList);
|
|
|
- this.form.datasource = tempList;
|
|
|
+ // 清空原数组并逐个添加新元素,确保Vue能够检测到变化
|
|
|
+ this.form.datasource = [];
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.form.datasource = tempList;
|
|
|
+ console.log('form.datasource after update:', this.form.datasource);
|
|
|
+ // 强制组件重新渲染
|
|
|
+ this.$forceUpdate();
|
|
|
+ console.log('forceUpdate called');
|
|
|
+ });
|
|
|
},
|
|
|
|
|
|
transformDaysFun(date) {
|
|
|
@@ -559,18 +671,30 @@
|
|
|
return allMonthDates;
|
|
|
},
|
|
|
setDefaultList(dateRange, issueNumber) {
|
|
|
+ // console.log('setDefaultList-dateRange~~~', dateRange);
|
|
|
const tempPeriod = issueNumber || 0;
|
|
|
|
|
|
// 计算基本比例
|
|
|
const basicRatio = 100 / tempPeriod;
|
|
|
let totalRatio = 0;
|
|
|
|
|
|
+ // 保存原有数据
|
|
|
+ const existingData = [...this.form.datasource];
|
|
|
+
|
|
|
// 生成付款计划列表项
|
|
|
const tempList = [];
|
|
|
|
|
|
// 根据传入的period参数生成付款计划
|
|
|
for (let i = 0; i < tempPeriod; i++) {
|
|
|
let item = JSON.parse(JSON.stringify(this.defaultForm));
|
|
|
+ // let item;
|
|
|
+ // // 如果原有数据中有对应项,则保留原有数据
|
|
|
+ // if (i < existingData.length) {
|
|
|
+ // item = JSON.parse(JSON.stringify(existingData[i]));
|
|
|
+ // } else {
|
|
|
+ // item = JSON.parse(JSON.stringify(this.defaultForm));
|
|
|
+ // }
|
|
|
+
|
|
|
// 获取日期:如果i小于日期数组长度则使用对应日期,否则设为空
|
|
|
const deadLine = i < dateRange.length ? dateRange[i] : '';
|
|
|
const ratio = parseFloat(basicRatio.toFixed(2));
|
|
|
@@ -592,9 +716,16 @@
|
|
|
// }
|
|
|
|
|
|
console.log('付款计划列表:~~', tempList);
|
|
|
- this.form.datasource = tempList;
|
|
|
// this.$set(this.form, 'datasource', tempList);
|
|
|
console.log('付款计划列表:', this.form.datasource);
|
|
|
+ this.form.datasource = [];
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.form.datasource = tempList;
|
|
|
+ console.log('form.datasource after update:', this.form.datasource);
|
|
|
+ // 强制组件重新渲染
|
|
|
+ this.$forceUpdate();
|
|
|
+ console.log('forceUpdate called');
|
|
|
+ });
|
|
|
},
|
|
|
// 添加
|
|
|
handlAdd() {
|
|
|
@@ -602,6 +733,7 @@
|
|
|
item.key = this.form.datasource.length + 1;
|
|
|
item.issueNumber = this.form.datasource.length + 1;
|
|
|
this.form.datasource.push(item);
|
|
|
+ this.$emit('getIssueNumber', this.form.datasource.length);
|
|
|
},
|
|
|
|
|
|
// validateForm(callback) {
|