一、需求描述:
前端要做的数据处理:拿到后台给的列表进行数据合并,每条数据都有个【合并地址】操作,
且合并完:
①姓名:姓名列聚合展示为一行,并将所有姓名去重展示,多个姓名之间用逗号隔开
②地址:展示合并项的地址
③手机号:电话列去重展示,相同电话合并为一行。 若存在包含两个电话的情况,将两个电话分开展示:(这里刚开始没想好,后来发现bug了,起初我是根据mergeId判断,因为合并完合并项和被合并项mergeId相同,我是判断相邻行的mergeId相同且手机号相同就合并,后来发现如果有三条合并数据(A/B/C)A和B的不同,A和C相同,那么因为A和C没有挨着就没有做到手机号去重并合并的效果)
思路:
要做合并单元格所以得有个相同的依据,就是根据mergeId:
1、拿到后台数据前段初始化一个mergeId,取值自身索引值,0/1/2/3
2、合并地址选择弹框:
点【合并地址】按钮会出现一个弹框,弹框下拉框数据(①排除点击项②剩下的数据相同的mergId数据只保留一个),因为会在选完合并项后把合并项和被合并项得mergeId都赋值为当前时间时间戳(now = new Date().getTime()),
拿四条数据举例,初始化的时候
list = [{
mergeId: 0,name:'A',adderss:'北京xxx',phone:'13073512485',sortIndex:1,
mergeId: 1,name:'B',adderss:'上海xxx',phone:'13173512485',sortIndex:2,
mergeId: 2,name:'B',adderss:'天津xxx',phone:'13073512485',sortIndex:3,
mergeId: 3,name:'D,adderss:'四川xxx',phone:'13073512485',sortIndex:4,
}]
2.1、第一次选择sortIndex:1合并到其他(第二条sortIndex:2):弹框下拉值是sortIndex为2 3 4的数据,此时只按filter排除非自己的还满足:
const temp = list.filter(item => row.mergeId !== item.mergeId)
合并完数据如下:
list = [{
mergeId: 1752306068107,name:'A,B',adderss:'上海xxx',phone:'13073512485',sortIndex:1,}
{mergeId: 1752306068107,name:'A,B',adderss:'上海xxx',phone:'13173512485',sortIndex:2,}
{mergeId: 2,name:'B',adderss:'天津xxx',phone:'13073512485',sortIndex:3,}
{mergeId: 3,name:'D,adderss:'四川xxx',phone:'13073512485',sortIndex:4,}
]
操作列也做了单元格合并(根据相邻mergeId相同):此时合并完后(1 2)两项共用一个【合并地址】操作
2.2、第二次选择把3合并其他(1 2),那么下拉值除了按mergeId筛选出非自己的,还需要做数据去重处理,因为(1和2)mergeId相同,此时用reduce对数组 temp
进行去重操作
const uniqueTemp = temp.reduce((accumulator, current) => {
if (!accumulator.some(a => a.mergeId === current.mergeId)) {
accumulator.push(current);
}
return accumulator;
}, []);
3、弹框选完合并项后的处理:(重点)
整体思路:
①先处理被选择的合并目标项,通过list遍历根据mergeId比对,给其mergeId赋值为now,选中目标地址selectAddressStr赋值,记录选中目标项selectRowList赋值
②处理要合并的操作项,通过list遍历根据mergeId比对,给其mergeId赋值为now,其地址赋值为目标项的地址selectAddressStr,记录操作项clickRowList赋值
③删除list中操作项,然后读取删除完操作项的剩余数据中第一个目标项的索引(目标有可能是多个,比如1合2成了(1 2),3再合到(12)组上)拿到索引位置,完事删除所有目标项,合并操作项和目标项为一个数组并根据手机号排序,最后把排好序的操作项和目标项一起插到之前读取的第一个目标项索引位置
3.1、
3.1.1、定义以下变量
const now = new Date().getTime()
let selectAddressStr = '' // 选中项地址
let selectRowIdx = 0 // 选中项下标
let selectRowList = [] // 选中项list(可能是多个)
let clickRowList = [] // 点击项(可能是多个)
let copyDataList = null // 数据备份
3.1.2、先处理被选择的合并目标项:根据选择的mergeId去list中对比,找到后给mergeId赋值,定义选中地址(selectAddressStr)为保存被选中的合并项address,selectRow赋值(需注意根据mergeId相同比对的话可能有多个,比如上面第二次合并到(1 2)只需赋值第一次的值)
// 选中项赋值
let isSameVal = false
list.forEach((v,i) => {
if (v.mergeId === id) {
v.mergeId = now
selectAddressStr = v.address
selectRowList.push(v)
}
})
3.1.3、再处理操作项
// state.clickRow 为点击的那个操作项
const mergeRowMergeId = state.clickRow.mergeId
state[state.memberInfoKey].memberOrderAddressDtoList.forEach(v => {
if (v.mergeId === mergeRowMergeId ) {
v.mergeId = now
v.address = selectAddressStr
clickRowList.push(v)
}
})
3.1.4、数据处理
// 数据备份赋值
copyDataList = copyDeep(list)
// 从copyDataList中排除操作项clickRowList
copyDataList = copyDataList.filter(item =>
!clickRowList.some(cItem => cItem.sortIndex === item.sortIndex)
);
// 选择项selectRowIdx 赋值: 取mergeId相同的第一项
selectRowIdx = copyDataList.findIndex(v => v.mergeId === selectRowList[0].mergeId)
// 从copyDataList中排除目标项
copyDataList = copyDataList.filter(item =>
!selectRowList.some(cItem => cItem.sortIndex[0] === item.sortIndex[0])
);
// 操作项和目标项合并数据后按手机号排序
const concatArrs = [...clickRowList, ...selectRowList]; // 使用扩展运算符合并数组
console.log('打印操作项和目标项合并数据:', concatArrs);
const sortDatas = concatArrs.sort((a, b) => {
const aValue = a.phonep;
const bValue = b.phoneList;
// 判断类型,如果是字符串用localeCompare,如果是数字直接做比较
if (typeof aValue === 'string' && typeof bValue === 'string') {
return aValue.localeCompare(bValue); // 字符串排序
}
return aValue - bValue; // 数字排序
});
// 把最后拍完序的操作项和合并项 默认插到 选中项前
copyDataList.splice(selectRowIdx, 0, ...sortDatas)
// list 赋值
list = copyDataList
这样就满足要求了,因为手机号合并的逻辑是mergeId相同且相邻手机号相同合并,经过排序后的手机号相同的会挨在一起。
3.2、最后姓名聚合去重处理
需要注意: 项目中后台返给我的name是数组形式,所以聚合后需要用flatMap扁平化
const mergedNames = _.uniq(
list
.filter(item => item.mergeId === now)
.flatMap(item => item.copyName)
);
state[state.memberInfoKey].memberOrderAddressDtoList.forEach(v => {
if(v.mergeId === now) {
v.receiverNameList = mergedNames;
}
})