feat: tree 展开

This commit is contained in:
JiangSheng
2026-04-14 15:28:23 +08:00
parent 0c22d2f103
commit cae80508c4
2 changed files with 109 additions and 10 deletions

View File

@@ -27,7 +27,7 @@
v-model="expandLevel"
class="expand-select"
@visible-change="expandVisibleChangeFun"
@change="expandLevelFun"
@change="expandChangeFun"
>
<el-option
v-for="item in expandOptions"
@@ -248,6 +248,7 @@ import HeadSearch from './treeHeadSearch.vue';
import { traverseTree } from '@/utils/node';
import { useI18n } from 'vue-i18n';
import { setTableColumnSize, userTableHeadData } from '@/utils/common';
import { allNodeTypeMap } from '@/utils/project';
const emit = defineEmits([
'searchChange',
@@ -277,6 +278,7 @@ interface Props {
actionList?: any;
showExpandSelect?: boolean; // 是否显示展开级别下拉框
defaultExpandAll?: boolean; // 是否默认展开所有节点
expandMode?: 'level' | 'type'; // 展开模式:按级别 | 按类型
}
const props = withDefaults(defineProps<Props>(), {
@@ -299,6 +301,7 @@ const props = withDefaults(defineProps<Props>(), {
actionList: [],
showExpandSelect: true, // 默认显示展开级别下拉框
defaultExpandAll: true, // 默认展开所有节点
expandMode: 'type',
});
const { t } = useI18n();
const checkMethod: any = inject('checkMethod', () => {
@@ -326,15 +329,53 @@ const actionAutoWidth = ref(95);
const expandLevel = ref<string>(props.defaultExpandAll ? 'all' : 'collapse');
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) });
const availableNodeTypes = ref<Set<string>>(new Set());
const collectNodeTypes = (data: any[]) => {
const types = new Set<string>();
traverseTree(
data,
(node: any) => {
if (node.nodeType) {
types.add(node.nodeType);
}
},
null
);
return types;
};
const getNodeTypeLabel = (nodeType: string) => {
if (allNodeTypeMap.value && allNodeTypeMap.value[nodeType]) {
return allNodeTypeMap.value[nodeType];
}
return nodeType;
};
const expandOptions = computed(() => {
if (props.expandMode === 'type') {
const options: { label: string; value: string }[] = [
{ label: t('表格.全部展开'), value: 'all' },
{ label: t('表格.全部折叠'), value: 'collapse' },
];
availableNodeTypes.value.forEach((type: string) => {
const label = getNodeTypeLabel(type);
options.push({
label: `展开${label}`,
value: type,
});
});
return options;
} else {
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) });
}
return options;
}
return options;
});
const visibleActionNum = ref(3); // 操作按钮展示个数
@@ -392,6 +433,9 @@ watch(
originData = cloneDeep(props.data);
nextTick(() => {
calcMaxLevelFun();
if (expandLevel.value && expandLevel.value !== 'collapse') {
expandChangeFun(expandLevel.value);
}
});
},
{ immediate: true }
@@ -404,6 +448,7 @@ const calcMaxLevelFun = () => {
const { fullData } = vxeTableRef.value.getTableData();
if (!fullData || fullData.length === 0) {
maxTreeLevel.value = 1;
availableNodeTypes.value = new Set();
return;
}
let maxLevel = 1;
@@ -423,6 +468,9 @@ const calcMaxLevelFun = () => {
null
);
maxTreeLevel.value = maxLevel;
if (props.expandMode === 'type') {
availableNodeTypes.value = collectNodeTypes(fullData);
}
};
const expandVisibleChangeFun = (visible: boolean) => {
@@ -451,6 +499,29 @@ const collectRowsToExpand = (data: any[], targetLevel: number) => {
return rowsToExpand;
};
const collectRowsToExpandByType = (data: any[], targetType: string) => {
const rowsToExpand: any[] = [];
const hasTargetType = (node: any): boolean => {
if (node.nodeType === targetType) {
return true;
}
if (node.children && node.children.length > 0) {
return node.children.some((child: any) => hasTargetType(child));
}
return false;
};
traverseTree(
data,
(node: any) => {
if (node.children && node.children.length > 0 && hasTargetType(node)) {
rowsToExpand.push(node);
}
},
null
);
return rowsToExpand;
};
const flatTreeRows = (arr: any[]) => {
const result: any[] = [];
const walk = (nodes: any[]) => {
@@ -486,6 +557,34 @@ const expandLevelFun = (level: string) => {
}
};
const expandTypeFun = (type: string) => {
if (!vxeTableRef.value) {
return;
}
expandLevel.value = type;
const { fullData = [], visibleData = [] } = vxeTableRef.value.getTableData();
const flattedVisibleData = flatTreeRows(visibleData);
if (type === 'all') {
vxeTableRef.value.setTreeExpand(flattedVisibleData, true);
} else if (type === 'collapse') {
vxeTableRef.value.setTreeExpand(flattedVisibleData, false);
} else {
const rowsToExpand = collectRowsToExpandByType(fullData, type);
vxeTableRef.value.setTreeExpand(flattedVisibleData, false);
nextTick(() => {
vxeTableRef.value.setTreeExpand(rowsToExpand, true);
});
}
};
const expandChangeFun = (value: string) => {
if (props.expandMode === 'type') {
expandTypeFun(value);
} else {
expandLevelFun(value);
}
};
watch(
() => props.params,
(val: any) => {

View File

@@ -497,7 +497,7 @@ const getNodeLevel3TreeByLevel2Uuid = async () => {
const expandTree = (treeRef: any) => {
setTimeout(() => {
treeRef.loadcaseTableRef.TreeTableRef.treeTableRef.setAllTreeExpand(true);
// treeRef.loadcaseTableRef.TreeTableRef.treeTableRef.setAllTreeExpand(true);
}, 200);
};