效果
- 存在两个对象数组
- 针对属性 date 对两个对象数组进行合并
- 效果如下

代码
- 利用 mockjs 模拟数据请求,通过 getList1 和 getList2 分别请求回来两个数组的数据
- 利用 Promise.all 方法等待两个接口请求完成后,进行数据处理
- 利用 concat 方法对两个数组数据进行拼接
- 利用 sort 方法对合并后的数组进行排序,排序顺序为日期升序
- 利用 reduce 方法生成新数组,针对 date 进行合并,并且根据不同的组别 group 分到不同的数组中
- 处理后的数组格式如下

getAllData() {
let promise1 = this.getList1().then((data) => {
this.data1 = data;
});
let promise2 = this.getList2().then((data) => {
this.data2 = data;
});
Promise.all([promise1, promise2]).then(() => {
console.log("两个列表都请求完了");
let concatData = this.data1.concat(this.data2);
concatData.sort((a, b) => {
return new Date(a.date).getTime() - new Date(b.date).getTime();
});
let timeReduce = concatData.reduce((arrItem, row) => {
let tempRow = arrItem.find((item) => item.date == row.date);
if (tempRow) {
if (row.group == "group1") {
tempRow.group1.push(row);
} else if (row.group == "group2") {
tempRow.group2.push(row);
}
} else {
if (row.group == "group1") {
arrItem.push({
date: row.date,
group1: [row],
group2: [],
});
} else if (row.group == "group2") {
arrItem.push({
date: row.date,
group1: [],
group2: [row],
});
}
}
return arrItem;
}, []);
console.log("timeReduce", timeReduce);
this.totalData = JSON.parse(JSON.stringify(timeReduce));
});
},
getList1() {
return new Promise((resolve, reject) => {
axios.get("/list1").then((res) => {
if (res.status == 200) {
console.log("列表1 请求", res.data);
resolve(res.data);
} else {
resolve([]);
}
});
});
},
getList2() {
return new Promise((resolve, reject) => {
axios.get("/list2").then((res) => {
if (res.status == 200) {
console.log("列表2 请求", res.data);
resolve(res.data);
} else {
resolve([]);
}
});
});
},
完整代码
<template>
<div class="validateForm">
<div class="top">
<div class="table">
<div class="title">第一组数组</div>
<el-table border :data="data1" size="mini">
<el-table-column prop="id" label="ID"> </el-table-column>
<el-table-column prop="date" label="日期"> </el-table-column>
<el-table-column prop="name" label="姓名"> </el-table-column>
<el-table-column prop="age" label="年龄"> </el-table-column>
<el-table-column prop="group" label="组别"> </el-table-column>
</el-table>
</div>
<div class="table">
<div class="title">第二组数据</div>
<el-table border :data="data2" size="mini">
<el-table-column prop="id" label="ID"> </el-table-column>
<el-table-column prop="date" label="日期"> </el-table-column>
<el-table-column prop="name" label="姓名"> </el-table-column>
<el-table-column prop="age" label="年龄"> </el-table-column>
<el-table-column prop="group" label="组别"> </el-table-column>
</el-table>
</div>
</div>
<div class="bottom">
<div class="title">按日期区分组别</div>
<div class="scrollBox">
<div class="sinData" v-for="(item, index) in totalData" :key="index">
<div class="group group1">
<div
class="sinGroup"
v-for="(item1, index1) in item.group1"
:key="index1"
>
<div>编码:{{ item1.group }}组 - {{ item1.id }}号</div>
<div>信息:{{ item1.name }} - {{ item1.age }}岁</div>
<div>日期:{{ item1.date }}</div>
</div>
</div>
<div class="date">
{{ item.date }}
</div>
<div class="group group2">
<div
class="sinGroup"
v-for="(item2, index2) in item.group2"
:key="index2"
>
<div>编码:{{ item2.group }}组 - {{ item2.id }}号</div>
<div>信息:{{ item2.name }} - {{ item2.age }}岁</div>
<div>日期:{{ item2.date }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "dataEdit",
components: {},
data() {
return {
data1: [],
data2: [],
totalData: [],
};
},
mounted() {
this.getAllData();
},
methods: {
getAllData() {
let promise1 = this.getList1().then((data) => {
this.data1 = data;
});
let promise2 = this.getList2().then((data) => {
this.data2 = data;
});
Promise.all([promise1, promise2]).then(() => {
console.log("两个列表都请求完了");
let concatData = this.data1.concat(this.data2);
concatData.sort((a, b) => {
return new Date(a.date).getTime() - new Date(b.date).getTime();
});
let timeReduce = concatData.reduce((arrItem, row) => {
let tempRow = arrItem.find((item) => item.date == row.date);
if (tempRow) {
if (row.group == "group1") {
tempRow.group1.push(row);
} else if (row.group == "group2") {
tempRow.group2.push(row);
}
} else {
if (row.group == "group1") {
arrItem.push({
date: row.date,
group1: [row],
group2: [],
});
} else if (row.group == "group2") {
arrItem.push({
date: row.date,
group1: [],
group2: [row],
});
}
}
return arrItem;
}, []);
console.log("timeReduce", timeReduce);
this.totalData = JSON.parse(JSON.stringify(timeReduce));
});
},
getList1() {
return new Promise((resolve, reject) => {
axios.get("/list1").then((res) => {
if (res.status == 200) {
console.log("列表1 请求", res.data);
resolve(res.data);
} else {
resolve([]);
}
});
});
},
getList2() {
return new Promise((resolve, reject) => {
axios.get("/list2").then((res) => {
if (res.status == 200) {
console.log("列表2 请求", res.data);
resolve(res.data);
} else {
resolve([]);
}
});
});
},
},
};
</script>
<style lang="less" scoped>
.validateForm {
padding: 20px;
background: #f7f7f7;
.top {
display: flex;
align-items: flex-start;
justify-content: space-between;
.table {
width: calc((100% - 20px) / 2);
.title {
line-height: 30px;
color: #333;
font-weight: bold;
}
}
}
.bottom {
margin-top: 20px;
overflow-x: auto;
.title {
line-height: 30px;
color: #333;
font-weight: bold;
}
.scrollBox {
display: flex;
.sinData {
.group {
display: flex;
height: 140px;
.sinGroup {
height: 140px;
width: 200px;
background: #fff;
padding: 5px 10px;
border-radius: 4px;
margin-right: 10px;
box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.1);
div {
line-height: 30px;
color: #666;
}
}
&.group1 {
.sinGroup {
position: relative;
&::after {
content: "";
position: absolute;
left: 10px;
bottom: -16px;
border-top: 8px solid #fff;
border-right: 10px solid transparent;
border-bottom: 8px solid transparent;
border-left: 10px solid transparent;
}
}
}
&.group2 {
.sinGroup {
position: relative;
&::after {
content: "";
position: absolute;
left: 10px;
top: -16px;
border-top: 8px solid transparent;
border-right: 10px solid transparent;
border-bottom: 8px solid #fff;
border-left: 10px solid transparent;
}
}
}
}
.date {
font-weight: bold;
padding: 10px 0 20px 0;
position: relative;
color: #3c8f6c;
&::before {
content: "";
width: 100%;
position: absolute;
left: 0;
top: 35px;
border-top: 2px dashed #999;
}
&::after {
content: "";
width: 10px;
height: 10px;
background: #3c8f6c;
border-radius: 50%;
position: absolute;
left: 0;
top: 32px;
}
}
}
}
}
}
</style>