88 lines
2.9 KiB
Vue
88 lines
2.9 KiB
Vue
|
|
<template>
|
||
|
|
<el-table-column :prop="prop" v-bind="$attrs">
|
||
|
|
<template #default="scope">
|
||
|
|
<span @click.prevent="toggleHandle(scope.$index, scope.row)" :style="childStyles(scope.row)">
|
||
|
|
<i :class="iconClasses(scope.row)" :style="iconStyles(scope.row)"></i>
|
||
|
|
{{ scope.row[prop] }}
|
||
|
|
</span>
|
||
|
|
</template>
|
||
|
|
</el-table-column>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup lang="ts">
|
||
|
|
import { nextTick, getCurrentInstance } from 'vue'
|
||
|
|
import isArray from 'lodash/isArray'
|
||
|
|
import type { TableTreeColumnProps, TableRow } from './index.data'
|
||
|
|
|
||
|
|
const props = withDefaults(defineProps<TableTreeColumnProps>(), {
|
||
|
|
prop: '',
|
||
|
|
treeKey: 'id',
|
||
|
|
parentKey: 'parentId',
|
||
|
|
levelKey: '_level',
|
||
|
|
childKey: 'children'
|
||
|
|
})
|
||
|
|
|
||
|
|
function childStyles(row: TableRow) {
|
||
|
|
return { 'padding-left': (row[props.levelKey] > 1 ? row[props.levelKey] * 7 : 0) + 'px' }
|
||
|
|
}
|
||
|
|
|
||
|
|
function iconClasses(row: TableRow) {
|
||
|
|
return [!row._expanded ? 'el-icon-caret-right' : 'el-icon-caret-bottom']
|
||
|
|
}
|
||
|
|
|
||
|
|
function iconStyles(row: TableRow): { visibility: 'visible' | 'hidden' } {
|
||
|
|
return { visibility: hasChild(row) ? 'visible' : 'hidden' }
|
||
|
|
}
|
||
|
|
|
||
|
|
function hasChild(row: TableRow) {
|
||
|
|
return (isArray(row[props.childKey]) && row[props.childKey].length >= 1) || false
|
||
|
|
}
|
||
|
|
|
||
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
|
function toggleHandle(index: number, row: TableRow) {
|
||
|
|
if (hasChild(row)) {
|
||
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
|
const parentTable: any = (() => {
|
||
|
|
// 在setup中访问父组件需要使用getCurrentInstance
|
||
|
|
// 这里保留原有逻辑,通过$parent访问
|
||
|
|
const instance = getCurrentInstance()
|
||
|
|
return instance?.parent
|
||
|
|
})()
|
||
|
|
|
||
|
|
// 使用更兼容的方式获取table数据
|
||
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
|
const tableInstance = parentTable?.proxy?.$parent as any
|
||
|
|
if (!tableInstance?.store?.states?.data) return
|
||
|
|
|
||
|
|
const data = tableInstance.store.states.data.slice(0)
|
||
|
|
data[index]._expanded = !data[index]._expanded
|
||
|
|
if (data[index]._expanded) {
|
||
|
|
data.splice(0, index + 1).concat(row[props.childKey]).concat(data)
|
||
|
|
} else {
|
||
|
|
removeChildNode(data, row[props.treeKey])
|
||
|
|
}
|
||
|
|
tableInstance.store.commit('setData', data)
|
||
|
|
nextTick(() => {
|
||
|
|
tableInstance.doLayout()
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function removeChildNode(data: TableRow[], parentId: string | number | (string | number)[]): TableRow[] {
|
||
|
|
const parentIds = isArray(parentId) ? parentId : [parentId]
|
||
|
|
if ((parentIds as (string | number)[]).length <= 0) {
|
||
|
|
return data
|
||
|
|
}
|
||
|
|
const ids: (string | number)[] = []
|
||
|
|
for (let i = 0; i < data.length; i++) {
|
||
|
|
if ((parentIds as (string | number)[]).indexOf(data[i][props.parentKey]) !== -1 &&
|
||
|
|
(parentIds as (string | number)[]).indexOf(data[i][props.treeKey]) === -1) {
|
||
|
|
data[i]._expanded = false
|
||
|
|
ids.push(data.splice(i, 1)[0][props.treeKey])
|
||
|
|
i--
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return removeChildNode(data, ids)
|
||
|
|
}
|
||
|
|
</script>
|