1、一级树
应用效果:
代码:MaterialCategory.vue
<script setup lang="ts" name="MaterialCategory">
......
// 创建树(一级树)
const createTree = (dataList: IMaterialCategory[]) => {// 将原始数据转换成树节点数据let data: IMaterialCategoryTree[] = dataList.map((item) => {return {label: item.categoryName,value: item.categoryNo};});// 添加根节点treeData.value.push({label: "物资分类",value: "",children: data});
};
......
</script><template><el-container class="layout-container"><el-aside class="aside"><el-scrollbar><el-treeclass="tree-horizontal-scrollbar":data="treeData":default-expand-all="true":highlight-current="true":expand-on-click-node="false":indent="15"@node-click="onTreeNodeClick"><!-- 自定义节点内容,点击的节点字体变色加粗 --><!-- 动态样式:通过<template #default>插槽自定义节点内容,使用:style绑定根据当前选择的节点值currentNode.value动态设置color和fontWeight --><template #default="{ node, data }"><span:style="{color: currentNode?.value === data.value ? `#409EFF` : `#606266`,fontWeight: currentNode?.value === data.value ? `bold` : `normal`}">{{ node.label }}</span></template></el-tree></el-scrollbar></el-aside>......</el-container>
</template>
2、二级树
应用效果1:
代码2:MaterialInfo.vue
<script setup lang="ts" name="MaterialInfo">
......
// 创建树
const createTree = (dataList: IMaterialCategory[]) => {// 将原始数据转换成树节点数据let data: IMaterialCategoryTree[] = dataList.map((item) => {return {label: item.categoryName,value: item.categoryNo};});// 遍历物资类别列表,过滤出一级节点数据let data1 = data.filter((item) => {if (item.value.length === 2) return item;});// 遍历物资类别列表,过滤出二级节点数据let data2 = data.filter((item) => {if (item.value.length === 4) return item;});// 将一级节点数据与二级节点数据组合成树节点数据let dataChild = data1.map((item1) => {// 遍历二级节点数据,过滤出对应一级节点的数据let dataChild2 = data2.filter((item2) => {if (item2.value.substring(0, 2) === item1.value) return item2;});return {label: item1.label,value: item1.value,children: dataChild2};});// 添加根节点treeData.value.push({label: "物资分类",value: "",children: dataChild});
};
......
</script><template><el-container class="layout-container"><el-aside class="aside"><el-scrollbar><el-treeclass="tree-horizontal-scrollbar":data="treeData":default-expand-all="true":highlight-current="true":expand-on-click-node="false":indent="15"@node-click="onTreeNodeClick"><!-- 自定义节点内容,点击的节点字体变色加粗 --><!-- 动态样式:通过<template #default>插槽自定义节点内容,使用:style绑定根据当前选择的节点值currentNode.value动态设置color和fontWeight --><template #default="{ node, data }"><span:style="{color: currentNode?.value === data.value ? `#409EFF` : `#606266`,fontWeight: currentNode?.value === data.value ? `bold` : `normal`}">{{ node.label }}</span></template></el-tree></el-scrollbar></el-aside>......</el-container>
</template><style scoped lang="scss">
// 树节点
:deep(.el-tree-node__content) {height: 32px;
}
// 树节点展开图标
:deep(.el-tree-node__content > .el-tree-node__expand-icon) {padding: 0;
}
</style>
应用效果2:
代码2:LedgerDetail.vue
<script setup lang="ts" name="Ledger">
......
import { useMaterialCategoryTree } from "@/hooks/useMaterialCategoryTree";// 物资分类树 hook
const { materialCategoryTreeData, defaultProps } = useMaterialCategoryTree();
......
</script><template><el-container class="layout-container"><el-aside class="aside"><el-scrollbar><el-treeclass="tree-horizontal-scrollbar"ref="materialCategoryTreeRef":data="materialCategoryTreeData"node-key="value":show-checkbox="true":highlight-current="true":default-expand-all="true":check-on-click-node="true":expand-on-click-node="false":props="defaultProps"@check="handleCheck" /></el-scrollbar></el-aside>......</el-container>
</template><style scoped lang="scss">
// 树节点
:deep(.el-tree-node__content) {height: 32px;
}
// 树节点展开图标
:deep(.el-tree-node__content > .el-tree-node__expand-icon) {padding: 0;
}
</style>
物资分类树 hook:useMaterialCategoryTree.ts
import { onMounted, ref } from "vue";
import type { IMaterialCategory, IMaterialCategoryTree } from "@/views/warehouse/types";
import { materialCategoryService } from "@/api/warehouse";/*** 物资分类树 hook* @returns*/
export const useMaterialCategoryTree = () => {// 物资分类列表数据const materialCategoryListData = ref<IMaterialCategory[]>([]);// 物资分类树数据const materialCategoryTreeData = ref<IMaterialCategoryTree[]>([]);const defaultProps = {children: "children",label: "label"};// 获取物资分类列表数据const fetchMaterialCategoryListData = async () => {// 获取物资分类列表数据let result = await materialCategoryService();materialCategoryListData.value = result.data;};// 创建物资分类树数据const createMaterialCategoryTreeData = (dataList: IMaterialCategory[]) => {// 将原始数据转换成树节点数据let data: IMaterialCategoryTree[] = dataList.map((item) => {return {label: item.categoryName,value: item.categoryNo};});// 遍历物资分类列表数据,过滤出一级节点数据let data1 = data.filter((item) => {if (item.value.length === 2) return item;});// 遍历物资分类列表数据,过滤出二级节点数据let data2 = data.filter((item) => {if (item.value.length === 4) return item;});// 将一级节点数据与二级节点数据组合成树节点数据let dataChild = data1.map((item1) => {// 遍历二级节点数据,过滤出对应一级节点的数据let dataChild2 = data2.filter((item2) => {if (item2.value.substring(0, 2) === item1.value) return item2;});return {label: item1.label,value: item1.value,children: dataChild2};});// 添加根节点materialCategoryTreeData.value.push({label: "物资分类",value: "",children: dataChild});};onMounted(async () => {// 获取物资分类列表数据await fetchMaterialCategoryListData();// 创建物资分类树数据createMaterialCategoryTreeData(materialCategoryListData.value);});return { materialCategoryTreeData, defaultProps };
};
3、并级树
应用效果:
代码:QualityFileCategoryTree.vue
<script setup lang="ts" name="QualityFileCategoryTree">
......
// 创建树
const createTree = async (dataList: IFileCategory[]) => {// 文件小类列表(对象数组),数据可能会有重复let smallCategoryList = dataList.filter((item) => item.smallCategoryNo && item.smallCategoryName).map((item) => {return {smallCategoryNo: item.smallCategoryNo!,smallCategoryName: item.smallCategoryName!};});// 对象数组去重,通过对象所有属性值都相同去重,使用 JSON 序列化与 Set(适用扁平对象,简单高效)smallCategoryList = deduplicateObjectArray(smallCategoryList);// 遍历文件小类列表,将原始数据转换成树节点数据treeData.value = smallCategoryList.map((item1) => {// 链式调用,.filter().map().filter()return {value: item1.smallCategoryNo,label: item1.smallCategoryName,children: dataList// 过滤出对应一级节点的二级节点数据(文件细类).filter((item2) => item2.smallCategoryNo === item1.smallCategoryNo)// 将文件细类数据转换为树节点数据.map((item) => ({value: item.detailCategoryNo as string,label: item.detailCategoryName as string}))// 过滤出有效的数据(value 和 label 值不为空).filter((item) => item.value && item.label)};});
};
......
</script setup lang="ts"><template><el-scrollbar><!-- el-scrollbar 显示横向滚动条 --><div class="scroll-container"><el-treeref="treeRef":data="treeData"node-key="value":default-expand-all="true":highlight-current="true":expand-on-click-node="false":indent="15"@node-click="onTreeNodeClick"><!-- 自定义节点内容,点击的节点字体变色加粗 --><!-- 动态样式:通过<template #default>插槽自定义节点内容,使用:style绑定根据当前选择的节点值currentNode.value动态设置color和fontWeight --><template #default="{ node, data }"><span:style="{color: currentNode?.value === data.value ? `#409EFF` : `#606266`,fontWeight: currentNode?.value === data.value ? `bold` : `normal`}">{{ node.label }}</span></template></el-tree></div></el-scrollbar>
</template><style scoped lang="scss">
// el-scrollbar 显示横向滚动条
.scroll-container {display: flex;width: max-content;
}
</style>