最近写项目的时候,有个需求是这样的:
购买项目的时候勾选了两个以上的员工(这里假设张三和李四两个员工),那么在统计业绩或者提成的时候,张三和李四就需要均分该项目的业绩和提成金额,显示的时候需要将张三和李四统计在一起,方便修改其中一个员工的业绩的时候另外一个也跟着变。设计图如下:
从设计图可见修改mb006员工的销售业绩或提成金额的时候是需要变动同个项目下其他员工(gt_test和mb005)的销售业绩或提成总额的。并且这里是根据项目名称(轮胎修补与打蜡2223)来合并员工数据的。而后台返回的数据是这样的:
可以看到实际上后台返回的数据是5条,迫于后台数据表存放的限制,后台开发人员无法将同一项目的员工的业绩整合在一块,为此我只能将这5条数据转化为上面显示的类似2条数据的情况。
本项目是PC端,使用的前端框架是vue,所以直接使用ElementUI的el-table组件来实现布局。但是el-table组件的合并只能根据行号来合并。先来看看官方案例:
可以看到官方案例是每隔两行就合并两行的数据,并不完全符合我们想要根据某个属性来合并不知道是几条数据的需求。先来看看这个怎么用法:
官方介绍:
通过给table传入span-method方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性。该函数可以返回一个包含两个元素的数组,第一个元素代表rowspan,第二个元素代表colspan。
也可以返回一个键名为rowspan和colspan的对象。
有点绕口的话请看以下栗子:
if (columnIndex === 0) {
if (rowIndex === 0) { // 合并第一行到第四行,从第一行开始,共4行 return {
rowspan: 4,
colspan: 1
}
} else if (rowIndex === 4) { // 合并第五行到第九行,从第五行开始,共5行 return {
rowspan: 5,
colspan: 1
}
} else if (rowIndex === 9) { // 合并第10行到第14行,从第10行开始,共5行 return {
rowspan: 5,
colspan: 1
}
} else { // 其余被合并的行,诸如1、2、3、5、6、7、8、10、11、12、13全都设为0 return {
rowspan: 0,
colspan: 0
}
}
}
可以看到rowspan就代表合并多少行数据的意思。
下面开始借助:span-method来实现需求,合并数据之前需要先处理数据,直接上代码:
// 核算业绩提成合并员工
// 生成一个与行数相同的数组,记录每一行设置的合并数
setMergeArr(data) {
for (var i = 0; i < data.length; i++) {
if (i === 0) {
this.mergeSpanArr.push(1)
this.mergeSpanArrIndex = 0
} else {
// 判断当前元素与上一个元素是否相同
if (data[i].itemInfo === data[i - 1].itemInfo) {//itemInfo代表根据哪个相同的属性去合并
this.mergeSpanArr[this.mergeSpanArrIndex] += 1
this.mergeSpanArr.push(0)
} else {
this.mergeSpanArr.push(1)
this.mergeSpanArrIndex = i
}
}
}
// 如果第一条记录索引为0,向数组中push 1,设置索引值
// 如果不是第一条记录,判断与前一条记录是否相等,相等则向mergeSpanArr添加元素0
// 且将前一条记录+1,即需要合并的行数+1,直到得到所有需要合并的行数
}
最终使用:
<el-table :data="recordList" :span-method="activementTable" border></tl-table>
//核算业绩表合并
activementTable({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0 || columnIndex === 1) {
const _row = this.mergeSpanArr[rowIndex]
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
}
这样合并数据的时候就能够根据数据的某个属性来合并,而不是跟官方一样只能根据行号来合并。
下面说一下修改其中一个员工 其他同项目的员工的金额跟着改变应该怎么实现,先看设计图:
输入框:
<el-input v-model.trim="scope.row.performance" @keyup.native="totalPayTypeMoney(scope.row,1)"></el-input> 元
这里的需求是修改mb006的销售金额或提成金额,即时变动mb005和gt_test的销售业绩和提成业绩(数值是(项目销售金额-mb006的销售业绩)/(员工数-1)就是剩下员工均分剩下的金额)。直接上代码:
//销售业绩-自动计算
totalPayTypeMoney(item, type) {
let singePrice //单个员工的业绩|提成
let totalPrice //总业绩|总提成
if (type == 1) {//业绩
totalPrice = item.itemTotal
singePrice = item.performance
} else {//提成
totalPrice = item.totalAmount
singePrice = item.commission
}
if (
isNaN(singePrice) ||
parseFloat(singePrice) > parseFloat(totalPrice)
) {
this.$message({
message: "请输入小于" + totalPrice + "的数字!",
type: "error"
})
//将当前修改的员工业绩|提成置为总业绩|总提成
if (type == 1) {
item.performance = totalPrice
} else {
item.commission = totalPrice
}
}
//算出剩下的业绩金额|提成金额并根据几个员工均分
let surplusTotal = (parseFloat(totalPrice) - parseFloat(type == 1 ? item.performance || 0 : item.commission || 0)) / (this.getRealNum(item.index) - 1) //分配剩余的业绩或提成
this.recordList.forEach(val => {
if (val != item && val.itemInfo == item.itemInfo) {//除去本身编辑的员工 val.itemInfo == item.itemInfo控制是均分金额的是同个项目的员工
if (type == 1) {
val.performance = parseFloat(surplusTotal).toFixed(2)
} else {
val.commission = parseFloat(surplusTotal).toFixed(2)
}
}
})
}
这个方法是找到修改员工业绩的时候,需要知道剩余的金额均分几份:
//如果得到的是0 就一直往上找 直到找到有合并数
getRealNum(index) {
let num
if (this.mergeSpanArr[index] < 1) {
for (let i = index; i < this.mergeSpanArr.length; i--) {
if (i > -1 && this.mergeSpanArr[i] > 0) {
num = i
return this.mergeSpanArr[num]
}
}
} else {
return this.mergeSpanArr[index]
}
}
好了 本次分享到此结束,如果你看到此文章只好解决了你想解决的问题的话麻烦给个小星星支持一下,如有不懂或者解决不了你的问题也随时欢迎你找到共同探讨!
本人微信:huang009516