Files
as-partner-frontend/src/components/table-tree-column/index.vue
2026-07-26 12:54:46 +08:00

88 lines
2.9 KiB
Vue
Executable File

<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>