原理不难,晚上找了一堆全是废话,自己造了一个:
1、模拟数据为 JSON格式;
2、需转为二维数组;
3、控制表格合并,删除合并项。
<template>
<div>
<table>
<tbody>
<tr>
<th
colspan="3"
class="th-box"
style="text-align: left; color: #ffc000"
>
三、汇总
</th>
</tr>
<tr>
<th class="big-th">物料名称</th>
<th class="big-th">阶段</th>
<th class="big-th">物料类型</th>
<th class="big-th">需求数量</th>
<th class="big-th">单位</th>
</tr>
<tr v-for="(item, index) in listTotal" :key="index">
<td v-if="item.show1" :rowspan="item.rowspan1">{{ item.data[0] }}</td>
<td v-if="item.show2" :rowspan="item.rowspan2">{{ item.data[1] }}</td>
<!-- <td>{{ item.data[1] }}</td> -->
<td>{{ item.data[2] }}</td>
<td>{{ item.data[3] }}</td>
<td>{{ item.data[4] }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
onMounted(() => {
transformListTotalFn(objJson);
});
// 模拟数据
const objJson = {
MB: {
TR4: {
PCBA: {
panel: 1,
},
},
总计: {
PCBA: {
panel: 1,
},
},
},
CPU: {
TR6: {
其他原材料: {
pcs: 3,
},
},
总计: {
其他原材料: {
pcs: 3,
},
},
},
KTV: {
TR6: {
PCBA: {
pcs: 6,
},
},
总计: {
PCBA: {
pcs: 6,
},
},
},
kfc: {
TR5: {
PCBA: {
pcs: 4,
},
},
TR6: {
PCBA: {
pcs: 3,
},
其他原材料: {
pcs: 10,
},
},
总计:{
PCBA: {
pcs: 7,
},
其他原材料: {
pcs: 10,
},
}
},
};
const listTotal = ref([]);
// const columns = ['card_name', 'stage', 'card_type', 'num', 'unit'];
function transformListTotalFn(_obj) {
let _arr = [];
for (let k in _obj) {
for (let l in _obj[k]) {
for (let m in _obj[k][l]) {
for (let n in _obj[k][l][m]) {
// let item = {
// card_name: k,
// stage: l,
// card_type: m,
// num: _obj[k][l][m][n],
// unit: n,
// };
let item = [k, l, m, _obj[k][l][m][n], n];
_arr.push(item);
}
}
}
}
console.log("表格列表:", _arr);
const _m1 = getMergeArrFn(_arr, 0);
const _m2 = getMergeArrFn(_arr, 1);
console.log("m1 m2:::::", _m1, _m2);
let _arr2 = [];
_arr.map((v, i) => {
let _obj = {
show1: true,
show2: true,
rowspan1: 1,
rowspan2: 1,
data: v,
};
_m1.map((v2) => {
if (i > v2[0] && i <= v2[1]) {
_obj.show1 = false;
}
if (i == v2[0]) {
_obj.rowspan1 = v2[1] - v2[0] + 1;
}
});
_m2.map((v2) => {
if (i > v2[0] && i <= v2[1]) {
_obj.show2 = false;
}
if (i == v2[0]) {
// console.log(i, v2)
_obj.rowspan2 = v2[1] - v2[0] + 1;
}
});
_arr2.push(_obj);
});
console.log("处理的表格列表:", _arr2);
listTotal.value = _arr2;
}
//
/**
* 生成合并项 位置
* @param { Array } _arr 二维数组
* @param { Number | String } key 对比位置
*/
function getMergeArrFn (_arr, key = 0) {
let arrDiff = [];
let idxS = 0; // 合并起始位置
let idxMerge = 0; // 合并的个数
let _len2 = _arr.length;
for (let i = 1; i < _len2; i++) {
console.log(_arr[i][key])
if (_arr[i][key] === _arr[i - 1][key]) {
idxMerge += 1;
if (i === _len2 - 1) {
arrDiff.push([idxS, i]);
}
} else {
if (idxMerge > 0) {
arrDiff.push([idxS, idxS + idxMerge]);
idxMerge = 0;
}
idxS = i;
}
}
return arrDiff
}
</script>
二、表格数据(二维数组转JSON对象)
// 模拟数据
const inputArray =[
["MB", "TR4", "PCBA", 1, "panel"],
["CPU", "TR6", "其他原材料", 3, "pcs" ],
["KTV", "TR6", "PCBA", 6, "pcs"],
["kfc", "TR5", "PCBA", 4, "pcs"],
[ "kfc", "TR6", "PCBA", 3, "pcs" ],
["kfc", "TR6", "其他原材料", 10, "pcs"]
];
/**
* 表格转 JSON对象
* @param { Array } array 二维数组
*/
const convertArrayToObject = (array) => {
return array.reduce((result, [one, two, three, num, unit]) => {
if (!result[one]) {
result[one] = {};
}
if (!result[one][two]) {
result[one][two] = {};
}
if (!result[one][two][three]) {
result[one][two][three] = {};
}
// 将数量转换为浮点数
const numFloat = Number(num);
// 设置单位的值
result[one][two][three][unit] = isNaN(numFloat) ? num : numFloat;
return result;
}, {});
};
const outputObject = convertArrayToObject(inputArray );
console.log(outputObject);
/** 增加总计 */
function transformAddTotalFn (_obj) {
for (let k in _obj) {
_obj[k]['总计'] = {}
for (let l in _obj[k]) {
if (l === '总计') continue;
for (let m in _obj[k][l]) {
if (!_obj[k]['总计'][m]) {
_obj[k]['总计'][m] = {};
}
for (let n in _obj[k][l][m]) {
// console.log(_obj[k]['总计'][m])
// 判断是否存在
if (Object.prototype.hasOwnProperty.call(_obj[k]['总计'][m], n)) {
_obj[k]['总计'][m][n] += _obj[k][l][m][n];
} else {
_obj[k]['总计'][m][n] = _obj[k][l][m][n];
}
}
}
}
}
return _obj;
}