利用hutool树结构工具-TreeUtil显示多级菜单树状结构

树状结构中最大的问题就是关系问题,在数据库中,每条数据通过某个字段关联自己的父节点,每个业务中这个字段的名字都不同,如何解决这个问题呢?
使用
定义结构
我们假设要构建一个菜单,可以实现系统管理和店铺管理,菜单的样子如下:

系统管理
|- 用户管理
|- 添加用户

店铺管理
|- 商品管理
|- 添加商品
那这种结构如何保存在数据库中呢?一般是这样的:
利用hutool树结构工具-TreeUtil显示多级菜单树状结构_第1张图片
我们看到,每条数据根据parentId相互关联并表示层级关系,parentId在这里也叫外键。
树结构工具-TreeUtil
实际使用后端代码

  /*查询结果*/
        List<Category> categoryLst = categoryService.select(query);

        //配置树形结构
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 最大递归深度
        treeNodeConfig.setDeep(categoryQueryDto.getDeep());
        //转换器
        String parentId = categoryQueryDto.getParentId() == null ? "0" : categoryQueryDto.getParentId().toString();
        List<Tree<String>> treeNodes = TreeUtil.build(categoryLst, parentId, treeNodeConfig,
                (category, tree) -> {
                    tree.setId(category.getId().toString());
                    tree.setParentId(category.getParentId().toString());
                    tree.setWeight(category.getSeq());
                    tree.setName(category.getName());

                    // 扩展属性为了和前端vue属性保持一致
                    tree.putExtra("value", category.getId().toString());
                    tree.putExtra("label", category.getName());
                    tree.putExtra("img", category.getImg());
                    tree.putExtra("status", category.getStatus());
                    tree.putExtra("lastUpdateBy", category.getLastUpdateBy());
                    tree.putExtra("lastUpdateTime", category.getLastUpdateTime());
                    tree.putExtra("statusX", CategoryStatus.findByStatus(category.getStatus()).getName());

                });
        return treeNodes;

前端vue页面

<template>
  <el-form :model="form" label-width="120px">
    <el-form-item label="品类名称">
      <el-input v-model="form.name" />
    </el-form-item>
    <el-form-item label="图片">
      
      <el-upload
        class="avatar-uploader"
        ref="uploadRef"
        :auto-upload="false"
        :show-file-list="false"
        :on-change="onchange"
      >
        <img v-if="form.img" :src="form.img" class="avatar" />
        <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
      </el-upload>

    </el-form-item>

    <el-form-item label="父类">
      <el-tree-select v-model="form.parentId" :data="categoryData" />
    </el-form-item>
    <el-form-item label="排序号">
      <el-input v-model="form.seq" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">保存</el-button>
      <el-button>重置</el-button>
    </el-form-item>
  </el-form>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from "vue";
import http from "@/http/index";
import { useRoute, useRouter } from "vue-router";
import type { UploadInstance } from "element-plus";

const uploadRef = ref<UploadInstance>();
const route = useRoute();
const router = useRouter();
const form = reactive({
  name: "",
  seq: 0,
  img: "",
  parentId:"0",
  imgName:"",
});
const categoryData = ref([
  { value: "0", label: "根节点" }]);
onMounted(()=>{
  http
    .post("/api/category/select", {
        // parentId: 0,
        // status:1
        // deep:3
    })
    .then((data: any) => {
     categoryData.value=categoryData.value.concat(data);
  
    })
    .catch((err: any) => {
          console.log(err);
    });
})

// 上传文件
const onchange = (file: any, fileList: any  ) => {
  var reader = new FileReader();
  reader.readAsDataURL(file.raw);
  reader.onload = () => {
    form.img = reader.result;
    form.imgName=file.raw.name;
   
   console.log(reader.result)
    console.log(file.raw.name)


  };
};

const onSubmit = () => {
  http
    .post("/api/category/insert", {
      name: form.name,
      img: form.img,
      seq:form.seq,
      parentId:form.parentId,
      imgName:form.imgName,
    })
    .then((res: any) => {
       console.log(res);
    })
    .catch((err: any) => {
          console.log(err);
    });
};
</script>
<style scoped>
.avatar-uploader .avatar {
  width: 80px;
  height: 80px;
  display: block;
}
</style>
<style>
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 80px;
  height: 80px;
  text-align: center;
}
</style>

你可能感兴趣的:(vue3,javascript,开发语言,ecmascript)