前一段时间有一个需求,要求既要合并单元格,又要实现树状图的效果,但是展开节点tree-node 可以放在非第一列的任意位置,Vxe-table可以实现如下是效果图:
大家可以一起交流学习!
~效果图
~Template
<template>
<div>
<p>
<vxe-button @click="toggleExpandEvent">切换第一个</vxe-button>
<vxe-button @click="setExpandEvent">展开第三个</vxe-button>
<vxe-button @click="expandAllEvent">展开所有</vxe-button>
<vxe-button @click="claseExpandEvent">关闭所有</vxe-button>
</p>
<vxe-table
border
show-overflow
ref="tableRef"
:column-config="{ resizable: true }"
:tree-config="{ transform: true }"
:edit-config="{ trigger: 'click', mode: 'cell' }"
:data="tableData"
:span-method="objectSpanMethod"
header-row-class-name="headerRowClass"
>
<vxe-column
field="userName"
title="用户名"
:edit-render="{ autofocus: ' .vxe-input--inner' }"
>
<template #edit="{ row }">
<vxe-input v-model="row.userName" />
</template>
</vxe-column>
<vxe-column
field="targetNum"
title="数量"
:edit-render="{ autofocus: ' .vxe-input--inner' }"
>
<template #edit="{ row }">
<vxe-input v-model="row.targetNum" mode="text" type="number" />
</template>
</vxe-column>
<vxe-column
field="dilieverSite"
title="项目交付地"
:edit-render="{ autofocus: ' .vxe-input--inner' }"
>
<template #edit="{ row }">
<vxe-input v-model="row.dilieverSite" mode="text" />
</template>
</vxe-column>
<vxe-column
field="name"
title="名字"
:edit-render="{ autofocus: ' .vxe-input--inner' }"
tree-node
>
<template #edit="{ row }">
<vxe-input v-model="row.name" transfer />
</template>
</vxe-column>
<vxe-column
field="type"
title="类型"
:edit-render="{ autofocus: ' .vxe-input--inner' }"
>
<template #edit="{ row }">
<vxe-input v-model="row.type" transfer />
</template>
</vxe-column>
<vxe-column
field="size"
title="尺寸"
:edit-render="{ autofocus: ' .vxe-input--inner' }"
>
<template #edit="{ row }">
<vxe-input v-model="row.size" transfer />
</template>
</vxe-column>
<vxe-column title="删除小条目" width="80">
<template #default="{ row }">
<el-icon
@click="handleERPDelete(row)"
class="el-icon-delete"
color="#F56C6C"
><Delete
/></el-icon>
</template>
</vxe-column>
<vxe-column field="oper" title="操作" width="100">
<template #default="{ row }">
<el-button @click="handleAdd(row)" link size="small" type="primary"
>新增</el-button
>
<el-button @click="handleDelete(row)" link size="small" type="danger"
>删除</el-button
>
</template>
</vxe-column>
</vxe-table>
</div>
</template>
~script
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { ElMessageBox } from "element-plus";
import type {
VxeTablePropTypes,
VxeTableEvents,
VxeTableInstance
} from "vxe-table";
interface RowVO {
id: number;
userName: string;
dilieverSite: string;
targetNum: number;
parentId: number | null;
name: string;
type: string;
size: number;
date: string;
oper?: string;
}
const tableData = ref<RowVO[]>([
{
id: 10000,
parentId: null,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "test abc1",
type: "mp3",
size: 1024,
date: "2020-08-01"
},
{
id: 10050,
parentId: null,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test2",
type: "mp4",
size: 0,
date: "2021-04-01"
},
{
id: 24300,
parentId: 10050,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test3",
type: "avi",
size: 1024,
date: "2020-03-01"
},
{
id: 20045,
parentId: 24300,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "test abc4",
type: "html",
size: 600,
date: "2021-04-01"
},
{
id: 10053,
parentId: 24300,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "test abc96",
type: "avi",
size: 0,
date: "2021-04-01"
},
{
id: 24330,
parentId: 10053,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "test abc5",
type: "txt",
size: 25,
date: "2021-10-01"
},
{
id: 21011,
parentId: 10053,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test6",
type: "pdf",
size: 512,
date: "2020-01-01"
},
{
id: 22200,
parentId: 10053,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test7",
type: "js",
size: 1024,
date: "2021-06-01"
},
{
id: 23666,
parentId: null,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test8",
type: "xlsx",
size: 2048,
date: "2020-11-01"
},
{
id: 23677,
parentId: 23666,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test7",
type: "js",
size: 1024,
date: "2021-06-01"
},
{
id: 23671,
parentId: 23677,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test7",
type: "js",
size: 1024,
date: "2021-06-01"
},
{
id: 23672,
parentId: 23677,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test7",
type: "js",
size: 1024,
date: "2021-06-01"
},
{
id: 23688,
parentId: 23666,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test7",
type: "js",
size: 1024,
date: "2021-06-01"
},
{
id: 23681,
parentId: 23688,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test7",
type: "js",
size: 1024,
date: "2021-06-01"
},
{
id: 23682,
parentId: 23688,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test7",
type: "js",
size: 1024,
date: "2021-06-01"
},
{
id: 24555,
parentId: null,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "test abc9",
type: "avi",
size: 224,
date: "2020-10-01"
},
{
id: 24566,
parentId: 24555,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test7",
type: "js",
size: 1024,
date: "2021-06-01"
},
{
id: 24577,
parentId: 24555,
userName: "宁夏宝丰",
dilieverSite: "中国-灵武",
targetNum: 3,
name: "Test7",
type: "js",
size: 1024,
date: "2021-06-01"
}
]);
const setTabelRowSpan = (tableData: any, fieldArr: any, effectMerge = {}) => {
let lastItem = {};
fieldArr.forEach((field: any, index: any) => {
let judgeArr = fieldArr.slice(0, index + 1);
if (effectMerge[field]) {
judgeArr = [...effectMerge[field], field];
}
tableData.forEach((item: any) => {
item.mergeCell = fieldArr;
const rowSpan = `rowspan_${field}`;
if (
judgeArr.every((e: any) => lastItem[e] === item[e] && item[e] !== "")
) {
item[rowSpan] = 0;
lastItem[rowSpan] += 1;
} else {
item[rowSpan] = 1;
lastItem = item;
}
});
});
};
const executeMerge = (data: any) => {
// let effectRows = [0];
// let fieldArr = ["userName"]; //全部字段
let RowfieldArr = ["userName", "dilieverSite", "targetNum"];
//setTableColumnSpan(data, fieldArr, effectRows); // (表格数据,表格字段,合并列
setTabelRowSpan(data, RowfieldArr); // (表格数据,表格字段,合并的条件)
//如果要用到合并条件:参考如下
// const effectMerge = {
// dilieverSite: ['userName'],//参照userName字段合并
// targetNum: ['userName']//
// }
};
onMounted(() => {
executeMerge(tableData.value);
});
const tableRef = ref<VxeTableInstance<RowVO>>();
const colspanMethod: VxeTablePropTypes.SpanMethod<RowVO> = ({
row,
_rowIndex,
column,
columnIndex
}) => {
if (columnIndex === 1) {
console.log("row", row);
}
};
const toggleExpandEvent = () => {
const $table = tableRef.value;
if ($table) {
$table.toggleTreeExpand(tableData.value[1]);
}
};
const setExpandEvent = () => {
const $table = tableRef.value;
if ($table) {
$table.setTreeExpand(tableData.value[8], true);
}
};
const expandAllEvent = () => {
const $table = tableRef.value;
if ($table) {
$table.setAllTreeExpand(true);
}
};
const claseExpandEvent = () => {
const $table = tableRef.value;
if ($table) {
$table.clearTreeExpand();
}
};
const objectSpanMethod: VxeTablePropTypes.SpanMethod<any> = ({
row,
column,
rowIndex,
columnIndex
}) => {
// if (effectRows.includes(rowIndex)) {
// const colspan = row[`colspan_${column.property}`];
// if (colspan) {
// return { rowspan: 1, colspan: colspan };
// } else {
// return { rowspan: 0, colspan: 0 };
// }
// }
if (row.mergeCell.includes(column.property)) {
const rowspan = row[`rowspan_${column.property}`];
if (rowspan) {
return { rowspan: rowspan, colspan: 1 };
} else {
return { rowspan: 0, colspan: 0 };
}
} else if (column.property === "oper") {
const rowspan = row[`rowspan_userName`];
if (rowspan) {
return { rowspan: rowspan, colspan: 1 };
} else {
return { rowspan: 0, colspan: 0 };
}
}
};
const handleAdd = row => {
console.log(row);
};
const handleDelete = row => {
console.log(row);
};
const handleERPDelete = row => {
ElMessageBox.confirm("确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
console.log(row);
});
};
</script>