<template>
<div>
<el-table
ref="multipleDevCreateRef"
v-model:selected-row-keys="multipleDevCreateList"
:data="tableData"
style="width: 100%"
row-key="Path"
default-expand-all
@select="select"
@select-all="selectAll"
@selection-change="handleSelectionChange"
:tree-props="{ children: 'Children' }"
:row-class-name="tableRowClassName"
>
<el-table-column type="selection" width="55" :selectable="selectable" />
<el-table-column property="Path" label="设备名" width="240" />
<el-table-column property="TypStr" label="类型" />
<el-table-column property="Mount" label="挂载点" />
<el-table-column property="Capacity" label="容量" />
</el-table>
</div>
</template>
<script setup lang="ts">
interface nodeItem {
Path: string // 路径
Capacity: string // 空间
Parent: string // 父节点(如果空就是根节点)
Mount: string // 挂载点
Typstr: string // 类型
IsUsed: boolean // 是否使用
Children?: nodeItem[]
}
const multipleDevCreateRef = ref<InstanceType<typeof ElTable>>()
const multipleDevCreateList = ref<nodeItem[]>([])
const handleSelectionChange = (value: nodeItem[]) => {
multipleDevCreateList.value = multipleDevCreateRef.value?.getSelectionRows()
}
// 转化前数据:
/* [
{
"Capacity": "20.0GB",
"IsUsed": false,
"Mount": "",
"Parent": "",
"Path": "/dev/sdb",
"TypStr": "disk"
},
{
"Capacity": "19.9GB",
"IsUsed": false,
"Mount": "",
"Parent": "/dev/sdb",
"Path": "/dev/sdb1",
"TypStr": "part"
},
{
"Capacity": "200.0GB",
"IsUsed": false,
"Mount": "",
"Parent": "",
"Path": "/dev/sdc",
"TypStr": "disk"
},
{
"Capacity": "190.0GB",
"IsUsed": false,
"Mount": "",
"Parent": "/dev/sdc",
"Path": "/dev/sdc1",
"TypStr": "part"
},
{
"Capacity": "9.9GB",
"IsUsed": false,
"Mount": "",
"Parent": "/dev/sdc",
"Path": "/dev/sdc2",
"TypStr": "part"
},
{
"Capacity": "20.0GB",
"IsUsed": false,
"Mount": "",
"Parent": "",
"Path": "/dev/sdd",
"TypStr": "disk"
},
{
"Capacity": "19.9GB",
"IsUsed": false,
"Mount": "",
"Parent": "/dev/sdd",
"Path": "/dev/sdd1",
"TypStr": "part"
}
] */
// 转化后的数据
const tableData = ref<any[]>([
{
Capacity: '200.0GB',
IsUsed: false,
Mount: '',
Parent: '',
Path: '/dev/sdc',
TypStr: 'disk',
Children: [
{
Capacity: '190.GB',
IsUsed: false,
Mount: '',
Parent: '/dev/sdc',
Path: '/dev/sdc1',
TypStr: 'part',
},
{
Capacity: '9.9GB',
IsUsed: false,
Mount: '',
Parent: '/dev/sdc',
Path: '/dev/sdc2z',
TypStr: 'part',
},
],
},
{
Capacity: '20.0GB',
IsUsed: false,
Mount: '',
Parent: '',
Path: '/dev/sdd',
TypStr: 'disk',
Children: [
{
Capacity: '19.9GB',
IsUsed: false,
Mount: '',
Parent: '/dev/sdd',
Path: '/dev/sdd1',
TypStr: 'part',
},
],
},
{
Capacity: '20.0GB',
IsUsed: false,
Mount: '',
Parent: '',
Path: '/dev/sdb',
TypStr: 'disk',
Children: [
{
Capacity: '19.9GB',
IsUsed: false,
Mount: '',
Parent: '/dev/sdb',
Path: '/dev/sdb1',
TypStr: 'part',
},
],
},
])
const tableRowClassName = ({ row }: { row: nodeItem }) => {
// 被使用了的设备 颜色加深 原生UI 不太明显
if (row.IsUsed === true) {
return 'disabled-row'
} else {
return ''
}
}
const selectable = (row: nodeItem) => {
return row.IsUsed === false
}
const setChildren = (children: nodeItem[], type: boolean) => {
// 编辑多个子层级
children.map((j: nodeItem) => {
toggleSelection(j, type)
if (j.Children) {
setChildren(j.Children, type)
}
})
}
// 设置父级选中/取消
const setParent = (
currentRow: any,
type: boolean,
parent: nodeItem[],
selectionLists: nodeItem[]
) => {
if (!parent.length) {
parent = tableData.value
}
let allSelect: any[] = []
parent.forEach((item: nodeItem) => {
if (item.Children) {
// 注:Parent 是当前选中节点的所有父节点的一个字符串形式的数据,这个很关键
if (currentRow.Parent === item.Path) {
// 选中
if (type) {
selectionLists.forEach((k: nodeItem) => {
item.Children?.forEach((j: nodeItem) => {
if (k.Path == j.Path) {
allSelect.push(j)
}
})
})
if (allSelect.length == item.Children.length) {
toggleSelection(item, type)
selectionLists.push(item)
select(selectionLists, item)
} else {
setParent(currentRow, type, item.Children, selectionLists)
}
} else {
// 取消选中
toggleSelection(item, type)
setParent(currentRow, type, item.Children, [])
}
}
}
})
}
const toggleSelection = (row: nodeItem, select: boolean) => {
// 编辑多个子层级
if (row) {
multipleDevCreateRef.value?.toggleRowSelection(row, select)
}
}
// 选中父节点时,子节点一起选中/取消
const select = (selection: nodeItem[], row: nodeItem) => {
const hasSelect = selection.some((el: nodeItem) => {
return row.Path === el.Path
})
if (hasSelect) {
if (row.Children) {
// 解决子组件没有被勾选到
setChildren(row.Children, true)
}
// 子节点被全勾选,父节点也勾上
setParent(row, true, [], selection)
} else {
if (row.Children) {
setChildren(row.Children, false)
}
// 子级取消选中, 传入当前选中节点, 所有父级取消选中
setParent(row, false, [], [])
}
}
// 选择全部
const selectAll = (selection: nodeItem[]) => {
// tabledata第一层只要有在selection里面就是全选
const isSelect = selection.some((el: nodeItem) => {
const tableDataPaths = tableData.value.map((j: nodeItem) => j.Path)
return tableDataPaths.includes(el.Path)
})
// tableDate第一层只要有不在selection里面就是全不选
const isCancel = !tableData.value.every((el: nodeItem) => {
const selectPaths = selection.map((j) => j.Path)
return selectPaths.includes(el.Path)
})
if (isCancel) {
tableData.value.map((el: nodeItem) => {
if (el.Children) {
// 解决子组件没有被勾选到
setChildren(el.Children, false)
}
})
}
if (isSelect) {
selection.map((el) => {
if (el.Children) {
// 解决子组件没有被勾选到
setChildren(el.Children, true)
}
})
}
}
</script>
<style scoped></style>
Element Plus 树形表格全选多选以及子节点勾选
最新推荐文章于 2024-05-24 11:24:33 发布