<template>
<el-table
ref="tableRef"
:data="tableData.length>0?tableData.slice(1,tableData.length):[]"
tooltip-effect="dark"
:span-method="objectSpanMethod"
:header-cell-style="handerMethod"
style="width: 100%; margin-top: 16px"
:row-class-name="tableRowClassName"
:cell-class-name="columnStyle"
>
<template v-for="item in tableHeader">
<el-table-column :label="item.label" :prop="item.label" :key="item.id" v-if="item.children && item.children.length">
<template v-for="i in item.children">
<el-table-column
:key="i.id"
:label="i.label"
:prop="i.prop?i.prop:'/'"
align="center"
label-class-name="orange"
>
</el-table-column>
</template>
</el-table-column>
<el-table-column
v-else
:key="item.id"
:label="item.label"
:prop="item.prop?item.prop:'/'"
align="center"
>
</el-table-column>
</template>
</el-table>
</template>
<script>
//引入封装的js
import { dataMethod } from "@/components/element/tableObjectSpanMethod.js";
export default {
data() {
return {
tableData: [],
spanObj: {},
tableHeader:[
{
label:'执行日期',
id:1,
prop:'data',
children:[
{
id:11,
label:'总分1',
prop:'data'
},
{
id:12,
label:'总分',
prop:'time'
}
]
},
{
label:'指标',
id:2,
prop:'time',
children:[
{
id:12,
label:'总分',
prop:'time'
}
]
},
{
label:'任务名称',
id:3,
prop:'taskName',
children:[
{
id:13,
label:'/',
prop:'taskName'
}
]
},
{
label:'任务进度状态',
id:4,
prop:'progressStatus',
children:[
{
id:14,
label:'/',
prop:'progressStatus'
}
]
},
{
label:'任务结果状态',
id:5,
prop:'resultStatue',
children:[
{
id:15,
label:'/',
prop:'resultStatue'
}
]
},
{
label:'操作',
id:6,
prop:'/',
children:[
{
id:15,
label:'/',
prop:'/'
}
]
},
]
};
},
created() {
(this.tableData = [
{
data: "总分1",
time: "总分2",
taskName: "任务20210903",
progressStatus: "0",
resultStatue: "0",
},
{
data: "收入贡献(万元)",
time: "收入贡献(万元)",
taskName: "任务",
progressStatus: "0",
resultStatue: "0",
teachingAffairsProjectId:1
},
{
data: "2022-01-07",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "1",
resultStatue: "0",
},
{
data: "2022-01-07",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "2",
resultStatue: "1",
},
{
data: "2022-01-07",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "3",
resultStatue: "1",
},
{
data: "2022-01-08",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "4",
resultStatue: "0",
},
{
data: "2022-01-09",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "5",
resultStatue: "1",
},
{
data: "2022-01-09",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "5",
resultStatue: "1",
},
{
data: "2022-01-09",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "5",
resultStatue: "1",
},
{
data: "2022-11-09",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "5",
resultStatue: "1",
},
]),
//动态渲染 请渲染数剧结束后在执行此方法
(this.spanObj = dataMethod(this.tableData));
},
methods: {
/**表格合并单元格 */
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
// 判断哪一列 如果需要处理多了 使用 || 进行处理即可
let addArr = ["总分1"];
let delArr = ["总分"];
if (row.teachingAffairsProjectId&&rowIndex==0) {
// label匹配则开始合并
if (addArr.includes(column.label)) {
return {
// 占位(合并单元格)
rowspan: 1, // 行
colspan: 2, // 列
};
}
else if (delArr.includes(column.label)) {
return [0, 0]; // 清除单元格(一定要做)
}
}
if (columnIndex === 0&&rowIndex!==0) {
const _row = this.flitterData(this.tableData.slice(1,this.tableData.length)).one[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
},
//合并单位表头
handerMethod ({ row, column, rowIndex, columnIndex }) {
// if (row[0].level == 1) {
//这里有个非常坑的bug 必须是row[0]=0 row[1]=2才会生效
row[0].colSpan = 0
// row[2].colSpan = 0
row[1].colSpan = 2
if (columnIndex === 0) {
return { display: 'none' }
}
// if (columnIndex === 3) {
// return { display: 'none' }
// }
},
/**合并表格的第一列,处理表格数据 */
flitterData(arr) {
let spanOneArr = [];
let concatOne = 0;
arr.forEach((item, index) => {
if (index === 0) {
spanOneArr.push(1);
} else {
//注意这里的data是表格绑定的字段,根据自己的需求来改
if (item.data === arr[index - 1].data) {
//第一列需合并相同内容的判断条件
spanOneArr[concatOne] += 1;
spanOneArr.push(0);
} else {
spanOneArr.push(1);
concatOne = index;
}
}
});
return {
one: spanOneArr,
};
},
// 表格斑马纹
tableRowClassName({ row, rowIndex }) {
// if(rowIndex===0){
// return "orange"
// }
if (rowIndex % 2 === 0) {
return "marginL";
} else {
return "blueRow marginL";
}
},
columnStyle({ row, column, rowIndex, columnIndex }) {
if (columnIndex == 0 &&rowIndex!=0) {
return "firstColumn";
}
},
},
};
</script>
<style >
/* ::v-deep { */
.el-table {
/* background-color: #000; */
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
border: 1px solid #ebeef5;
}
.blueRow {
background: #f6f9ff !important;
}
.orange {
background: rgb(252, 216, 149) !important;
}
.orange>td {
background: rgb(252, 216, 149) !important;
}
.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell {
background-color: #E7EFFF !important;
color: #292929 !important;
font-weight: 600 !important;
}
.firstColumn{
background: #f6f9ff !important;
border:none;
}
.el-table--enable-row-hover .el-table__body tr:hover>.firstColumn.el-table__cell{
background: #f6f9ff !important;
color: #606266 !important;
font-weight: 500 !important;
border: 1px solid #ebeef5;
}
/* } */
</style>
```// 表格单元格合并多列
let [spanObj, pos] = [{}, {}];
//spanObj 存储每个key 对应的合并值
//pos 存储的是 key合并值得索引 大概吧
const dataMethod = (data, isH = []) => {
//循环数据
for (let i in data) {
let dataI = data[i];
//循环数据内对象,查看有多少key
for (let j in dataI) {
//如果只有一条数据时默认为1即可,无需合并
if (~~i === 0) {
spanObj[j] = [1];
pos[j] = 0;
} else {
let [e, k] = [dataI, data[i - 1]];
//判断上一级别是否存在 ,
//存在当前的key是否和上级别的key是否一样
//判断是否有数组规定只允许那几列需要合并单元格的
if (k && e?.[j] === k?.[j] && (!isH?.length || isH?.includes(j))) {
//如果上一级和当前一级相当,数组就加1 数组后面就添加一个0
spanObj[j][pos[j]] += 1;
spanObj?.[j]?.push(0);
} else {
spanObj?.[j]?.push(1);
pos[j] = i;
}
console.log(e, k);
}
}
}
return spanObj;
};
export { dataMethod };
以下以指标明细表格作为参考,整体区别不大,我只合并单元格及第一列值相同自动合并的内容,有其他修改需要自己处理一下
<template>
<el-table
ref="tableRef"
:data="tableData"
tooltip-effect="dark"
:span-method="objectSpanMethod"
:header-cell-style="handerMethod"
style="width: 100%; margin-top: 16px"
:row-class-name="tableRowClassName"
:cell-class-name="columnStyle"
>
<template v-for="item in tableHeader">
<el-table-column :label="item.label" :prop="item.label" :key="item.id" v-if="item.children && item.children.length">
<template v-for="i in item.children">
<el-table-column
:key="i.id"
:label="i.label"
:prop="i.prop?i.prop:'/'"
align="center"
>
</el-table-column>
</template>
</el-table-column>
<el-table-column
v-else
:key="item.id"
:label="item.label"
:prop="item.prop?item.prop:'/'"
align="center"
>
</el-table-column>
</template>
</el-table>
</template>
<script>
//引入封装的js
import { dataMethod } from "@/components/element/tableObjectSpanMethod.js";
export default {
data() {
return {
tableData: [],
spanObj: {},
tableHeader:[
{
label:'项目',
id:1,
prop:'data',
},
{
label:'项目',
id:122,
prop:'data2',
},
{
label:'收入指标',
id:2,
prop:'time',
children:[
{
id:12,
label:'全收入-净(万元)',
prop:'time'
},
{
id:121,
label:'地区收入份额',
prop:'taskName'
}
]
},
{
label:'业务指标',
id:3,
prop:'taskName',
children:[
{
id:13,
label:'有效地区股基份额',
prop:'taskName'
},
{
id:131,
label:'有效地区股基份额',
prop:'progressStatus'
},
{
id:132,
label:'金融产品销售规模(亿元)',
prop:'taskName'
},
{
id:133,
label:'金融产品年均保有净值规模(亿元)',
prop:'time'
},
{
id:134,
label:'日均两融余额(亿元)',
prop:'taskName'
},
]
},
{
label:'任务进度状态',
id:4,
prop:'progressStatus',
children:[
{
id:14,
label:'/',
prop:'progressStatus'
}
]
},
{
label:'任务结果状态',
id:5,
prop:'resultStatue',
children:[
{
id:15,
label:'/',
prop:'resultStatue'
}
]
},
{
label:'操作',
id:6,
prop:'/',
children:[
{
id:65,
label:'/',
prop:'resultStatue'
}
]
},
{
label:'操作',
id:7,
prop:'/',
children:[
{
id:75,
label:'/',
prop:'resultStatue'
}
]
},
{
label:'操作',
id:8,
prop:'/',
children:[
{
id:85,
label:'/',
prop:'resultStatue'
}
]
},
]
};
},
created() {
(this.tableData = [
{
data: "2022-01-07",
data2: "33",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "1",
resultStatue: "0",
},
{
data: "2022-01-07",
time: "15:56:08",
data2: "44",
taskName: "任务20210903",
progressStatus: "2",
resultStatue: "1",
},
{
data: "2022-01-07",
time: "15:56:08",
data2: "55",
taskName: "任务20210903",
progressStatus: "3",
resultStatue: "1",
},
{
data: "2022-01-08",
time: "15:56:08",
data2: "66",
taskName: "任务20210903",
progressStatus: "4",
resultStatue: "0",
},
{
data: "2022-01-09",
time: "15:56:08",
taskName: "任务20210903",
progressStatus: "5",
data2: "77",
resultStatue: "1",
},
{
data: "2022-01-09",
time: "15:56:08",
data2: "88",
taskName: "任务20210903",
progressStatus: "5",
resultStatue: "1",
},
{
data: "2022-01-09",
time: "15:56:08",
data2: "99",
taskName: "任务20210903",
progressStatus: "5",
resultStatue: "1",
},
{
data: "2022-11-09",
time: "15:56:08",
data2: "10",
taskName: "任务20210903",
progressStatus: "5",
resultStatue: "1",
},
]),
//动态渲染 请渲染数剧结束后在执行此方法
this.spanObj = dataMethod(this.tableData);
},
methods: {
/**表格合并单元格 */
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
const _row = this.flitterData(this.tableData).one[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
},
//合并单位表头,第一列和第二列第一行的表头,如不需要合并把这个方法注释即可
handerMethod ({ row, column, rowIndex, columnIndex }) {
if (row[0].level == 1) {
row[0].colSpan = 0
row[1].colSpan = 2
if (columnIndex === 0) {
return { display: 'none' }
}
}
},
/**合并表格的第一列,处理表格数据 */
flitterData(arr) {
let spanOneArr = [];
let concatOne = 0;
arr.forEach((item, index) => {
if (index === 0) {
spanOneArr.push(1);
} else {
//注意这里的data是表格绑定的字段,根据自己的需求来改
if (item.data === arr[index - 1].data) {
//第一列需合并相同内容的判断条件
spanOneArr[concatOne] += 1;
spanOneArr.push(0);
} else {
spanOneArr.push(1);
concatOne = index;
}
}
});
return {
one: spanOneArr,
};
},
// 表格斑马纹
tableRowClassName({ row, rowIndex }) {
if (rowIndex % 2 === 0) {
return "marginL";
} else {
return "blueRow marginL";
}
},
columnStyle({ row, column, rowIndex, columnIndex }) {
if (columnIndex == 0 ) {
return "firstColumn";
}
},
},
};
</script>
<style >
/* ::v-deep { */
.el-table {
/* background-color: #000; */
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
border: 1px solid #ebeef5;
}
.blueRow {
background: #f6f9ff !important;
}
.orange {
background: rgb(252, 216, 149) !important;
}
.orange>td {
background: rgb(252, 216, 149) !important;
}
.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell {
background-color: #E7EFFF !important;
color: #292929 !important;
font-weight: 600 !important;
}
.firstColumn{
background: #f6f9ff !important;
border:none;
}
.el-table--enable-row-hover .el-table__body tr:hover>.firstColumn.el-table__cell{
background: #f6f9ff !important;
color: #606266 !important;
font-weight: 500 !important;
border: 1px solid #ebeef5;
}
.el-table thead.is-group th.el-table__cell{
text-align: center;
}
/* } */
</style>
<template>
<el-table
ref="tableRef"
:data="tableData"
tooltip-effect="dark"
:span-method="objectSpanMethod"
:header-cell-style="handerMethod"
style="width: 100%; margin-top: 16px"
:row-class-name="tableRowClassName"
:cell-class-name="columnStyle"
>
<template v-for="item in tableHeader">
<el-table-column :label="item.label" :prop="item.label" :key="item.id" v-if="item.children && item.children.length">
<template v-for="i in item.children">
<el-table-column
:key="i.id"
:label="i.label"
:prop="i.prop?i.prop:'/'"
align="center"
label-class-name="orange"
>
</el-table-column>
</template>
</el-table-column>
<el-table-column
v-else
:key="item.id"
:label="item.label"
:prop="item.prop?item.prop:'/'"
align="center"
>
</el-table-column>
</template>
</el-table>
</template>
<script>
//引入封装的js
import { dataMethod } from "@/components/element/tableObjectSpanMethod.js";
export default {
data() {
return {
tableData: [],
spanObj: {},
tableHeader:[
{
label:'项目',
id:1,
prop:'data',
children:[
{
id:111,
label:'全净',
prop:'data'
},
]
},
{
label:'项目',
id:122,
prop:'data2',
children:[
{
id:1222,
label:'全收入',
prop:'data2'
},
]
},
{
label:'收入指标',
id:2,
prop:'time',
children:[
{
id:12,
label:'全收入-净',
prop:'time'
},
]
},
{
label:'业务指标',
id:3,
prop:'taskName',
children:[
{
id:13,
label:'有效地区',
prop:'taskName'
},
]
},
{
label:'任务进度状态',
id:4,
prop:'progressStatus',
children:[
{
id:14,
label:'/',
prop:'progressStatus'
}
]
},
{
label:'任务结果状态',
id:5,
prop:'resultStatue',
children:[
{
id:15,
label:'/',
prop:'resultStatue'
}
]
},
{
label:'操作',
id:6,
prop:'/',
children:[
{
id:65,
label:'/',
prop:'resultStatue'
}
]
},
{
label:'操作',
id:7,
prop:'/',
children:[
{
id:75,
label:'/',
prop:'resultStatue'
}
]
},
{
label:'操作',
id:8,
prop:'/',
children:[
{
id:85,
label:'/',
prop:'resultStatue'
}
]
},
]
};
},
created() {
(this.tableData = [
{
data: "2022-01-07",
time: "15:56:08",
data2: "55",
taskName: "任务2021",
progressStatus: "3",
resultStatue: "1",
},
{
data: "2022-01-08",
time: "15:56:08",
data2: "66",
taskName: "任务2",
progressStatus: "4",
resultStatue: "0",
},
{
data: "2022-01-09",
time: "15:56:08",
taskName: "任务202",
progressStatus: "5",
data2: "77",
resultStatue: "1",
},
{
data: "2022-01-09",
time: "15:56:08",
data2: "88",
taskName: "任务903",
progressStatus: "5",
resultStatue: "1",
},
{
data: "2022-01-09",
time: "15:56:08",
data2: "99",
taskName: "任务3",
progressStatus: "5",
resultStatue: "1",
},
{
data: "2022-11-09",
time: "15:56:08",
data2: "10",
taskName: "任务03",
progressStatus: "5",
resultStatue: "1",
},
]),
//动态渲染 请渲染数剧结束后在执行此方法
this.spanObj = dataMethod(this.tableData);
},
methods: {
/**表格合并单元格 */
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
const _row = this.flitterData(this.tableData).one[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
},
//合并单位表头
handerMethod ({ row, column, rowIndex, columnIndex }) {
// if (row[0].level == 1) {
// row[0].colSpan = 0
// row[1].colSpan = 2
// if (columnIndex === 0) {
// return { display: 'none' }
// }
// }
},
/**合并表格的第一列,处理表格数据 */
flitterData(arr) {
let spanOneArr = [];
let concatOne = 0;
arr.forEach((item, index) => {
if (index === 0) {
spanOneArr.push(1);
} else {
//注意这里的data是表格绑定的字段,根据自己的需求来改
if (item.data === arr[index - 1].data) {
//第一列需合并相同内容的判断条件
spanOneArr[concatOne] += 1;
spanOneArr.push(0);
} else {
spanOneArr.push(1);
concatOne = index;
}
}
});
return {
one: spanOneArr,
};
},
// 表格斑马纹
tableRowClassName({ row, rowIndex }) {
if (rowIndex % 2 === 0) {
return "marginL";
} else {
return "blueRow marginL";
}
},
columnStyle({ row, column, rowIndex, columnIndex }) {
if (columnIndex == 0 ) {
return "firstColumn";
}
},
},
};
</script>
<style >
/* ::v-deep { */
.el-table {
/* background-color: #000; */
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
border: 1px solid #ebeef5;
}
.blueRow {
background: #f6f9ff !important;
}
.orange {
background: rgb(252, 216, 149) !important;
}
.orange>td {
background: rgb(252, 216, 149) !important;
}
.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell {
background-color: #E7EFFF !important;
color: #292929 !important;
font-weight: 600 !important;
}
.firstColumn{
background: #f6f9ff !important;
border:none;
}
.el-table--enable-row-hover .el-table__body tr:hover>.firstColumn.el-table__cell{
background: #f6f9ff !important;
color: #606266 !important;
font-weight: 500 !important;
border: 1px solid #ebeef5;
}
.el-table thead.is-group th.el-table__cell{
text-align: center;
}
/* } */
</style>