<template>
<div>
<el-radio-group v-model="isEdit" @change='handleChangeIsEdit'>
</el-radio-group>
<el-table style=" 100%;" :data="tableData" v-if='tableData.length' show-summary :summary-method="getSummaries">
<el-table-column fixed prop="org_name" label="研究所名称" width="150">
</el-table-column>
<el-table-column v-for='(item,index) in timeList' :key='item' :label="`${item}年度`" header-align="center">
<el-table-column label="费用化预算(万元)" width='250'>
<template slot-scope="scope">
<el-input-number :min="0" :controls='false' placeholder="请输入费用化预算(万元" v-model="scope.row[item].funds" @change='handleChangeMoney(scope.row, index, scope.$index)'></el-input-number>
</template>
</el-table-column>
<el-table-column label="资本化预算(万元)" width='250'>
<template slot-scope="scope">
<el-input-number :disabled='scope.row.isEdit' :min="0" :controls='false' placeholder="请输入资本化预算(万元" v-model="scope.row[item].captialized_budget" @change='handleChangeMoney(scope.row, index, scope.$index)'></el-input-number>
</template>
</el-table-column>
</el-table-column>
<el-table-column fixed='right' prop="row_money" label="小计" width="150">
</el-table-column>
</el-table>
</div>
</template>
<script>
/**
* 判断是不是整数
*/
const isInteger = (obj) => {
return Math.floor(obj) === obj;
};
/*
* 将一个浮点数转成整数,返回整数和倍数。如 3.14 >> 314,倍数是 100
* @param floatNum {number} 小数
* @return {object}
* {times:100, num: 314}
*/
const toInteger = (floatNum) => {
const ret = { times: 1, num: 0 };
if (isInteger(floatNum)) {
ret.num = floatNum;
return ret;
}
const strfi = floatNum + '';
const dotPos = strfi.indexOf('.');
const len = strfi.substr(dotPos + 1).length;
const times = Math.pow(10, len);
const intNum = parseInt(floatNum * times + 0.5, 10);
ret.times = times;
ret.num = intNum;
return ret;
};
/*
* 核心方法,实现加减乘除运算,确保不丢失精度
* 思路:把小数放大为整数(乘),进行算术运算,再缩小为小数(除)
*
* @param a {number} 运算数1
* @param b {number} 运算数2
* @param op {string} 运算类型,有加减乘除(add/subtract/multiply/divide)
*
*/
export const operation = (a, b, op) => {
const o1 = toInteger(a);
const o2 = toInteger(b);
const n1 = o1.num;
const n2 = o2.num;
const t1 = o1.times;
const t2 = o2.times;
const max = t1 > t2 ? t1 : t2;
let result = null;
switch (op) {
case 'add':
if (t1 === t2) {
// 两个小数位数相同
result = n1 + n2;
} else if (t1 > t2) {
// o1 小数位 大于 o2
result = n1 + n2 * (t1 / t2);
} else {
// o1 小数位 小于 o2
result = n1 * (t2 / t1) + n2;
}
return result / max;
case 'subtract':
if (t1 === t2) {
result = n1 - n2;
} else if (t1 > t2) {
result = n1 - n2 * (t1 / t2);
} else {
result = n1 * (t2 / t1) - n2;
}
return result / max;
case 'multiply':
result = (n1 * n2) / (t1 * t2);
return result;
case 'divide':
result = (n1 / n2) * (t2 / t1);
return result;
}
};
// 加减乘除的四个接口
export const add = (a, b) => {
return operation(a, b, 'add');
};
export const subtract = (a, b) => {
return operation(a, b, 'subtract');
};
export const multiply = (a, b) => {
return operation(a, b, 'multiply');
};
export const divide = (a, b) => {
return operation(a, b, 'divide');
};
export default {
data() {
return {
startTime: '2020',
endTime: '2023',
isEdit: false, // 这个是切换时修改的值
timeList: [],
tableData: [],
companyList: [
{
org_id: '11',
org_name: '奥利给研究所1',
org_code: 11,
force_project_id: 11,
org_total_fund: '',
},
{
org_id: '12',
org_name: '奥利给研究所2',
org_code: 12,
force_project_id: 12,
org_total_fund: '',
},
{
org_id: '13',
org_name: '奥利给研究所3',
org_code: 13,
force_project_id: 13,
org_total_fund: '',
},
{
org_id: '14',
org_name: '奥利给研究所3',
org_code: 14,
force_project_id: 14,
org_total_fund: '',
},
],
};
},
methods: {
initTableData() {
let timeList = (this.timeList = Array.from(
{
length: Number(this.endTime) - Number(this.startTime) + 1,
},
(item, index) => {
return Number(this.startTime) + index;
}
));
let tableData = this.companyList.map((tableItem, tableIndex) => {
timeList.forEach((timeItem, timeIndex) => {
this.$set(tableItem, 'row_money', 0);
this.$set(tableItem, 'column_money', 0);
this.$set(tableItem, 'column1_money', 0);
this.$set(tableItem, 'isEdit', this.isEdit);
this.$set(tableItem, timeItem, {
funds: '',
captialized_budget: '',
});
});
return tableItem;
});
this.tableData = tableData;
},
handleChangeMoney(row, index, oldIndex) {
let handleReckonMoney = (row) => {
let row_money = 0;
let column_money = 0;
let column1_money = 0;
this.timeList.forEach((item) => {
row_money = add(
Number(row_money),
add(Number(row[item].captialized_budget), Number(row[item].funds))
);
this.$set(row, 'row_money', row_money);
});
};
handleReckonMoney(row);
},
getSummaries(param) {
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '合计(万元)';
return;
} else if (index < columns.length - 1) {
let ret = 0;
if (index % 2 === 1) {
data.forEach((itemData) => {
ret = add(
Number(ret),
Number(itemData[this.timeList[Math.ceil(index / 2) - 1]].funds)
);
});
sums[index] = ret;
} else {
data.forEach((itemData) => {
ret = add(
Number(ret),
Number(
itemData[this.timeList[Math.ceil(index / 2) - 1]]
.captialized_budget
)
);
});
sums[index] = ret;
}
} else {
let ret = 0;
for (let i = 1; i < columns.length - 1; i++) {
ret = add(Number(ret), Number(sums[i]));
}
sums[index] = ret;
}
});
return sums;
},
handleChangeIsEdit(e) {
this.tableData.forEach((item) => {
this.$set(item, 'isEdit', this.isEdit);
});
},
},
created() {
this.initTableData();
},
};
</script>
发送给后端的数据格式
tableData: [
{
org_id: '11',
org_name: '奥利给研究所1',
org_code: 11,
force_project_id: 11,
org_total_fund: '',
'2020': {},
'2021': {},
'2022': {},
'2023': {},
'2024': {}
}
]