feat: tree 展开

This commit is contained in:
JiangSheng
2026-01-22 19:11:30 +08:00
parent a41c2f9753
commit 5b97a0cb31
5 changed files with 128 additions and 5 deletions

View File

@@ -22,6 +22,21 @@
<div class="item">
<div class="btns">
<slot name="leftOptions" />
<el-select
v-if="showExpandSelect"
v-model="expandLevel"
class="expand-select"
@visible-change="expandVisibleChangeFun"
@change="expandLevelFun"
>
<el-option
v-for="item in expandOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<slot name="iconOptions" />
<el-tooltip v-if="exportApi" :content="$t('表格.导出')" placement="top">
<div v-if="exportApi" class="icon-btn" @click="exportFun">
<el-icon :size="18">
@@ -214,7 +229,7 @@
</template>
<script setup lang="ts">
import { ref, onMounted, watch, nextTick, inject } from 'vue';
import { ref, onMounted, watch, nextTick, inject, computed } from 'vue';
import { ElMessageBox } from 'element-plus';
import { Download, Upload, MoreFilled } from '@element-plus/icons-vue';
import type { TableHead } from './types';
@@ -225,6 +240,8 @@ import { formOptionsFormat } from './lib';
import { uniqBy, cloneDeep } from 'lodash-es';
import { exportFile } from '@/utils/file';
import HeadSearch from './treeHeadSearch.vue';
import { traverseTree } from '@/utils/node';
import { useI18n } from 'vue-i18n';
const emit = defineEmits([
'searchChange',
@@ -252,6 +269,7 @@ interface Props {
editMode?: boolean;
listTitle?: string;
actionList?: any;
showExpandSelect?: boolean; // 是否显示展开级别下拉框
}
const props = withDefaults(defineProps<Props>(), {
@@ -272,8 +290,9 @@ const props = withDefaults(defineProps<Props>(), {
editMode: false,
listTitle: '',
actionList: [],
showExpandSelect: false, // 默认显示展开级别下拉框
});
const { t } = useI18n();
const checkMethod: any = inject('checkMethod', () => {
return true;
});
@@ -297,6 +316,20 @@ const filterData = ref<any>({});
let originData: any = [];
const actionAutoWidth = ref(95);
const expandLevel = ref<string>('all');
const maxTreeLevel = ref(1);
const expandOptions = computed(() => {
const options: { label: string; value: string }[] = [
{ label: t('表格.全部展开'), value: 'all' },
{ label: t('表格.全部折叠'), value: 'collapse' },
];
for (let i = 1; i <= maxTreeLevel.value; i++) {
options.push({ label: t('表格.显示级', { level: i }), value: String(i) });
}
options.push();
return options;
});
const findVisibleIndex = (row: any, action: any) => {
let index = 0;
props.actionList.some((item: any) => {
@@ -349,10 +382,89 @@ watch(
});
formatData.value = data;
originData = cloneDeep(props.data);
nextTick(() => {
calcMaxLevelFun();
});
},
{ immediate: true }
);
const calcMaxLevelFun = () => {
if (!vxeTableRef.value) {
return;
}
const treeData = vxeTableRef.value.getTableData().fullData;
if (!treeData || treeData.length === 0) {
maxTreeLevel.value = 1;
return;
}
let maxLevel = 1;
const levelMap = new Map<any, number>();
traverseTree(
treeData,
(node: any, parent: any) => {
const level = parent ? (levelMap.get(parent) || 1) + 1 : 1;
levelMap.set(node, level);
if (level > maxLevel) {
maxLevel = level;
}
if (!node.parentId) {
node.parentId = parent ? parent.fakeId : null;
}
},
null
);
maxTreeLevel.value = maxLevel;
};
const expandVisibleChangeFun = (visible: boolean) => {
if (visible) {
calcMaxLevelFun();
}
};
const expandLevelFun = (level: string) => {
if (!vxeTableRef.value) {
return;
}
expandLevel.value = level;
if (level === 'all') {
vxeTableRef.value.setAllTreeExpand(true);
} else if (level === 'collapse') {
vxeTableRef.value.setAllTreeExpand(false);
} else {
const targetLevel = parseInt(level, 10);
const treeData = vxeTableRef.value.getTableData().fullData;
const levelMap = new Map<any, number>();
const rowsToExpand: any[] = [];
traverseTree(
treeData,
(node: any, parent: any) => {
const nodeLevel = parent ? (levelMap.get(parent) || 1) + 1 : 1;
levelMap.set(node, nodeLevel);
if (nodeLevel < targetLevel) {
rowsToExpand.push(node);
}
},
null
);
vxeTableRef.value.setAllTreeExpand(false);
nextTick(() => {
vxeTableRef.value.setTreeExpand(rowsToExpand, true);
});
}
};
const checkDataChangeFun = () => {
if (!vxeTableRef.value) {
return;
}
calcMaxLevelFun();
nextTick(() => {
expandLevelFun(expandLevel.value);
});
};
watch(
() => props.params,
(val: any) => {
@@ -653,6 +765,11 @@ defineExpose({
.btns {
display: flex;
align-items: center;
padding: 0 var(--margin-small);
.expand-select {
width: 110px;
margin-left: var(--margin-small);
}
.icon-btn {
display: flex;
align-items: center;

View File

@@ -31,6 +31,8 @@
>{{ $t('工况库.指标') }}</el-button
>
</div>
</template>
<template #iconOptions>
<slot name="otherOptions"></slot>
</template>
<!-- <template #eMemberList="{row}">
@@ -406,7 +408,10 @@ const onNodeDetailConfirmFun = (formData: any) => {
}
nextTick(async () => {
await getVxeRef()?.insertAt(addRow, insertPosition);
await getVxeRef()?.setTreeExpand(checkRowData[0], true);
await nextTick();
if (checkRowData[0]) {
getVxeRef()?.setTreeExpand(checkRowData[0], true);
}
// emits('updateCallback', 'add');
});
} else {

View File

@@ -107,7 +107,7 @@ const lang = {
: 'Collapse',
: 'Expand All',
: 'Collapse All',
: 'Expand Level {level}',
: 'Show Level {level}',
},
: {
: 'Top',

View File

@@ -106,7 +106,7 @@ const lang = {
: '收起',
: '全部展开',
: '全部折叠',
: '展开{level}级',
: '显示 {level} 级',
},
: {
: '根节点',

View File

@@ -189,6 +189,7 @@
poolName: currentPoolBriefVersion ? currentPoolBriefVersion.poolName : '',
version: currentPoolBriefVersion ? currentPoolBriefVersion.poolVersion : '',
}"
:showExpandSelect="false"
>
</loadCaseTable>
</div>