主要代码展示:
1、选择父级后子级联动的效果
2、表格样式
布局
<el-table
:data="tableData"
style="width: 100%"
:tree-props="{ children: 'children_prefix' }"
row-key="pk"
ref="treeTableRef"
:default-expand-all="true"
@select="handleSelect"
@select-all="selectAll"
id="tree-table"
>
<el-table-column type="selection" width="35" />
<el-table-column v-for="item in columnsTable" :label="item.label" :key="item.label">
<template #default="scope">
<div
class="treeSpan"
:class="{ c1: scope.row._depth % 7 === 0, c2: scope.row._depth % 7 === 1, c3: scope.row._depth % 7 === 2 }"
>
<div
class="treeSpanData link-text"
v-if="item.name === 'prefix' || (item.name === '_children' && scope.row[item.name])"
@click="toDetail(scope.row, item.name)"
>
{{ scope.row[item.name] || "-" }}
</div>
<div class="treeSpanData" v-else>
{{ scope.row[item.name] || "-" }}
</div>
</div>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" width="190">
<template #default="scope">
<div
class="treeSpan"
:class="{ c1: scope.row._depth % 7 === 0, c2: scope.row._depth % 7 === 1, c3: scope.row._depth % 7 === 2 }"
>
<el-button type="primary" link :icon="Delete" @click="handleDeletePrefix(scope.row)">删除</el-button>
</div>
</template>
</el-table-column>
</el-table>
父子联动代码
const checkedData = ref<any>([]);
// 勾选变化
const handleSelect = (selection, row) => {
// 更新当前行的选中状态
const isSelected = selection.some(el => row.pk === el.pk);
isSelected ? addId(row) : deleteId(row);
if (row.children_prefix && row.children_prefix?.length) {
toggleChildrenSelection(row.children_prefix, isSelected);
}
setSelect();
};
// 递归处理子级选中状态
const toggleChildrenSelection = (children, isChecked) => {
children.forEach(child => {
isChecked ? addId(child) : deleteId(child);
if (child.children_prefix && child.children_prefix.length > 0) {
toggleChildrenSelection(child.children_prefix, isChecked);
}
});
};
// 设置显示勾选
const setSelect = () => {
nextTick(() => {
treeTableRef.value!.clearSelection();
checkedData.value.forEach(item => {
treeTableRef.value!.toggleRowSelection(item, true);
});
});
};
// 全选和取消全选
const selectAll = () => {
const isAllSelected = checkedData.value.length > 0;
tableData.value.forEach(el => {
if (isAllSelected) {
deleteId(el); // 取消选择
if (el.children_prefix && el.children_prefix.length > 0) {
toggleChildrenSelection(el.children_prefix, false);
}
} else {
addId(el); // 选择
if (el.children_prefix && el.children_prefix.length > 0) {
toggleChildrenSelection(el.children_prefix, true);
}
}
});
setSelect();
};
const addId = o => {
const idSet = new Set(checkedData.value.map(item => item.pk));
if (!idSet.has(o.pk)) {
checkedData.value.push(o);
}
};
const deleteId = o => {
checkedData.value = checkedData.value.filter(item => item.pk !== o.pk);
};
样式
// 树形结构的表格样式
#tree-table {
.link-text {
color: #1775ff;
cursor: pointer;
}
.el-table__cell {
padding: 0;
}
.tr {
background-color: #ffffff00;
}
.cell {
display: flex;
align-items: center;
padding: 0 0 0 12px;
line-height: 44px;
.el-table__expand-icon {
z-index: 100;
}
.treeSpan.c1 {
position: relative;
flex: 1;
margin-left: -32px;
background: rgb(245 248 255);
.treeSpanData {
margin-left: 32px;
}
}
.treeSpan.c1::before {
position: absolute;
left: 0;
width: 4px;
height: 100%;
content: "";
background: rgb(23 117 255);
}
.treeSpan.c2 {
position: relative;
flex: 1;
margin-left: -32px;
background: rgb(250 243 238);
.treeSpanData {
margin-left: 32px;
}
}
.treeSpan.c2::before {
position: absolute;
left: 0;
width: 4px;
height: 100%;
content: "";
background: rgb(255 117 19);
}
.treeSpan.c3 {
position: relative;
flex: 1;
margin-left: -32px;
background: rgb(243 252 249);
.treeSpanData {
margin-left: 32px;
}
}
.treeSpan.c3::before {
position: absolute;
left: 0;
width: 4px;
height: 100%;
content: "";
background: rgb(18 199 146);
}
}
}