基于BALKANFamilyTreeJS插件的家谱可视化项目功能Demo

0、演示视频:

家谱可视化demo演示_演示 (bilibili.com)

1、思路分析视频:

202206151735_哔哩哔哩bilibili_演示

2、项目基本构成:

        后端:go语言+gin+gorm框架

        前端:vue+element-plus

        数据库:postgresSQL

        所使用的插件官网:

Royal Family Tree - Family Tree JS (balkan.app)

3、数据表设计:

 sql语句:


DROP TABLE IF EXISTS "public"."visualization";
CREATE TABLE "public"."visualization" (
  "id" int primary key,
  "pids" int,
  "mid" int,
  "fid" int,
  "name" varchar(255),
  "gender" varchar(255),
  "birthday" varchar(255),
  "familytree" varchar(255),
  "img" varchar(255),
  "tel" varchar(255),
  "email" varchar(255),
  "resume" varchar(255),
  "is_del" bool NOT NULL DEFAULT false,
  "update_time" timestamptz(6) NOT NULL
);
/*
INSERT INTO "public"."visualization" (id,pids,mid,fid,name,gender,birthday,familytree,img,tel,email,resume,is_del,update_time)
VALUES('1','0','0','0','蒋介石','男','1887年10月31日-1975年4月5日','蒋介石家族','1.jpg','123456','[email protected]','原名瑞元,学名志清、中正,字介石。', 'f', '2022-06-08 08:00:00+08');
*/

4、后端业务逻辑实现+接口

model层:数据表的结构体设计:

package models

import "time"

type Visualization struct {
	Id         int       `gorm:"column:id"`
	Pids       int       `gorm:"column:pids"`
	Mid        int       `gorm:"column:mid"`
	Fid        int       `gorm:"column:fid"`
	Name       string    `gorm:"column:name"`
	Gender     string    `gorm:"column:gender"`
	Birth      string    `gorm:"column:birthday"`
	Familytree string    `gorm:"column:familytree"`
	Img        string    `gorm:"column:img"`
	Tel        string    `gorm:"column:tel"`
	Email      string    `gorm:"column:email"`
	Resume     string    `gorm:"column:resume"`
	Isdel      bool      `gorm:"column:is_del"`
	UpdateTime time.Time `gorm:"column:update_time"`
}

dao层:主要负责对数据的基本操作。

        familytree.go 获取显示内容:

package dao

import "familytree/models"

func GetFamilytree() (error, []models.Visualization, int64) {
	var familytreeData []models.Visualization

	var total int64

	err := db.Table("visualization").Select("id,pids,mid,fid,name,gender,img").Order("id ASC").Count(&total).Find(&familytreeData).Error

	return err, familytreeData, total
}

        visualization.go 对数据表进行增删改查: 

package dao

import "familytree/models"

func GetAllVisual(visual map[string]interface{}) (error, []models.Visualization, int64) {
	var visualData []models.Visualization
	page := visual["page"].(int)
	pageSize := visual["limit"].(int)
	searchName := visual["searchName"].(string)
	var total int64
	err := db.Table("visualization").Select("*").Where("name like ? And is_del = false", searchName+"%").Order("id ASC").Count(&total).Offset((page - 1) * pageSize).Limit(pageSize).Find(&visualData).Error
	return err, visualData, total
}

func DelVisual(id string) error {
	err := db.Table("visualization").Where("id = ?", id).Update("is_del", true).Error
	return err
}

func UpdateVisual(visual models.Visualization) error {
	err := db.Table("visualization").Where("id = ?", visual.Id).Updates(&visual).Error
	return err
}

func Addvisual(visual models.Visualization) error {
	err := db.Table("visualization").Select("id", "pids", "mid", "fid", "name", "gender", "birthday", "familytree", "img", "tel", "email", "resume", "update_time", "is_del").Create(&visual).Error
	return err
}

service层:实现基本业务逻辑,调用dao层封装函数。

        visualization.go调用dao层函数:

package services

import (
	"familytree/dao"
	"familytree/models"
)

func GetAllVisual(visual map[string]interface{}) (error, []models.Visualization, int64) {
	err, visualData, total := dao.GetAllVisual(visual)
	return err, visualData, total
}

func DelVisual(id string) error {
	err := dao.DelVisual(id)
	return err
}

func UpdateVisual(visual models.Visualization) error {
	err := dao.UpdateVisual(visual)
	return err
}

func AddVisual(visual models.Visualization) error {
	err := dao.Addvisual(visual)
	return err
}

       familytree.go数据可视化函数:

package services

import (
	"familytree/dao"
	"familytree/models"
)

func GetFamilytree() (error, []models.Visualization, int64) {
	err, familytreeData, total := dao.GetFamilytree()
	return err, familytreeData, total
}

controller层:调用service层函数进行前后端数据操作:

familytree,go显示数据:

package controllers

import (
	"familytree/pkg/app"
	"familytree/pkg/e"
	"familytree/services"

	"github.com/gin-gonic/gin"
)

func GetFamilytree(c *gin.Context) {

	err, info, total := services.GetFamilytree()

	if err != nil {
		app.Error(c, e.ERROR, err, err.Error())
		return
	}
	var m = map[string]interface{}{"value": info, "total": total}

	app.OK(c, m, "查询成功")
}

visualization.go表操作

package controllers

import (
	"encoding/json"
	"familytree/models"
	"familytree/pkg/app"
	"familytree/pkg/e"
	"familytree/services"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/unknwon/com"
)

func GetVisual(c *gin.Context) {
	page := -1
	if arg := c.Query("page"); arg != "" {
		page = com.StrTo(arg).MustInt()
	}
	limit := -1
	if arg := c.Query("limit"); arg != "" {
		limit = com.StrTo(arg).MustInt()
	}
	searchName := ""
	if arg := c.Query("searchName"); arg != "" {
		searchName = arg
	}
	supplierParam := map[string]interface{}{
		"page":       page,
		"limit":      limit,
		"searchName": searchName,
	}
	err, info, total := services.GetAllVisual(supplierParam)
	if err != nil {
		app.Error(c, e.ERROR, err, err.Error())
		return
	}
	app.OK(c, map[string]interface{}{"value": info, "total": total}, "查询成功")
}

func DelVisual(c *gin.Context) {
	id := ""
	if arg := c.Query("id"); arg != "" {
		id = arg
	}
	if id == "" {
		app.INFO(c, 30001, "参数错误")
		return
	}
	err := services.DelVisual(id)
	if err != nil {
		app.Error(c, e.ERROR, err, err.Error())
		return
	}
	app.OK(c, map[string]interface{}{}, "删除成功")
}

func UpdateVisual(c *gin.Context) {
	b, _ := c.GetRawData()
	var m map[string]string
	_ = json.Unmarshal(b, &m)
	if m["Id"] == "" {
		app.INFO(c, 30000, "参数非法")
		return
	}
	Id := com.StrTo(m["Id"]).MustInt()
	Pids := com.StrTo(m["Pids"]).MustInt()
	Mid := com.StrTo(m["Mid"]).MustInt()
	Fid := com.StrTo(m["Fid"]).MustInt()
	Name := m["Name"]
	Gender := m["Gender"]
	Birth := m["Birth"]
	Familytree := m["Familytree"]
	Img := m["Img"]
	Tel := m["Tel"]
	Email := m["Email"]
	Resume := m["Resume"]
	err := services.UpdateVisual(models.Visualization{Id: Id, Pids: Pids, Mid: Mid, Fid: Fid, Name: Name, Gender: Gender, Birth: Birth, Familytree: Familytree, Img: Img, Tel: Tel, Email: Email, Resume: Resume, Isdel: false, UpdateTime: time.Now()})
	if err != nil {
		app.Error(c, e.ERROR, err, err.Error())
		return
	}
	app.OK(c, map[string]interface{}{}, "更新成功")
}

func Addvisual(c *gin.Context) {
	b, _ := c.GetRawData()
	var m map[string]string
	_ = json.Unmarshal(b, &m)
	Id := com.StrTo(m["Id"]).MustInt()
	Pids := com.StrTo(m["Pids"]).MustInt()
	Mid := com.StrTo(m["Mid"]).MustInt()
	Fid := com.StrTo(m["Fid"]).MustInt()
	Name := m["Name"]
	Gender := m["Gender"]
	Birth := m["Birth"]
	Familytree := m["Familytree"]
	Img := m["Img"]
	Tel := m["Tel"]
	Email := m["Email"]
	Resume := m["Resume"]
	err := services.AddVisual(models.Visualization{Id: Id, Pids: Pids, Mid: Mid, Fid: Fid, Name: Name, Gender: Gender, Birth: Birth, Familytree: Familytree, Img: Img, Tel: Tel, Email: Email, Resume: Resume, Isdel: false, UpdateTime: time.Now()})
	if err != nil {
		app.Error(c, e.ERROR, err, err.Error())
		return
	}
	app.OK(c, map[string]interface{}{}, "添加成功")
}

router层:设置路由接口

数据可视化接口:

package routers

import (
	"familytree/controllers"

	"github.com/gin-gonic/gin"
)

func FamilytreeRouter(r *gin.RouterGroup) {
	r.GET("/familytree", controllers.GetFamilytree)
}

操作表接口:

package routers

import (
	"familytree/controllers"

	"github.com/gin-gonic/gin"
)

func VisualRouter(r *gin.RouterGroup) {
	r.GET("/visualization", controllers.GetVisual)
	r.DELETE("/visualization", controllers.DelVisual)
	r.PUT("/visualization", controllers.UpdateVisual)
	r.POST("/visualization", controllers.Addvisual)
}

        

5、前端代码设计:

表操作代码实现:

<template>
  <!-- 卡片视图区 -->
  <el-card>
    <el-row :gutter="25">
      <el-col :span="7">
        <!-- 搜索添加 -->
        <el-input
          placeholder="请输入搜索成员的名字"
          v-model.lazy="queryInfo.searchName"
          @change="getVisualList"
        >
        </el-input>
      </el-col>

      <el-col :span="4">
      <el-button type="primary"
          >搜索</el-button
        >
        <el-button type="primary" @click="dialogAddVisible = true"
          >添加</el-button
        >
      </el-col>
    </el-row>
    <!-- 列表 -->
    <el-table
      :data="VisualList"
      border
      stripe
      v-loading="isLoading"
      element-loading-background="rgba(255, 255, 255, .5)"
      element-loading-text="加载中,请稍后..."
      element-loading-spinner="el-icon-loading"
    >
      <el-table-column label="序号" type="index" fixed="left"></el-table-column>
      <el-table-column label="成员ID" prop="Id"></el-table-column>
      <el-table-column label="伴侣ID" prop="Pids"></el-table-column>
      <el-table-column label="母亲ID" prop="Mid"></el-table-column>
      <el-table-column label="父亲ID" prop="Fid"></el-table-column>
      <el-table-column label="姓名" prop="Name"></el-table-column>
      <el-table-column label="性别" prop="Gender"></el-table-column>
      <el-table-column label="生日" prop="Birth"></el-table-column>
      <el-table-column label="家族" prop="Familytree"></el-table-column>
      <el-table-column label="头像" prop="Img"></el-table-column>
      <el-table-column label="电话" prop="Tel"></el-table-column>
      <el-table-column label="邮箱" prop="Email"></el-table-column>
      <el-table-column label="履历" prop="Resume"></el-table-column>
      <el-table-column label="更新时间" prop="UpdateTime"></el-table-column>
      <el-table-column label="操作" fixed="right">
        <template #default="scope">
          <!-- 修改 -->
          <el-button
            type="primary"
            icon="el-icon-edit"
            size="mini"
            @click="
              dialogEditOpen(
                scope.row.Id,
                scope.row.Pids,
                scope.row.Mid,
                scope.row.Fid,
                scope.row.Name,
                scope.row.Gender,
                scope.row.Birth,                
                scope.row.Familytree,
                scope.row.Img,
                scope.row.Tel,
                scope.row.Email,
                scope.row.Resume,
              )
            "
          >
          </el-button>
          <!-- 删除 -->
          <el-button
            type="danger"
            icon="el-icon-delete"
            size="mini"
            @click="deleteVisual(scope.row.Id)"
          >
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="queryInfo.page"
      :page-sizes="[1, 2, 10, 100]"
      :page-size="queryInfo.limit"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
    ></el-pagination>
  </el-card>

  <el-dialog title="添加成员" v-model="dialogAddVisible" width="50%">
    <el-form
      :model="addForm"
      :rules="addFormRules"
      ref="addFormRef"
      label-width="100px"
    >
      <el-form-item label="成员ID" prop="Id">
        <el-input v-model="addForm.Id" @blur="test()"></el-input>
      </el-form-item>
      <el-form-item label="伴侣ID" prop="Pids">
        <el-input v-model="addForm.Pids"></el-input>
      </el-form-item>
      <el-form-item label="母亲ID" prop="Mid">
        <el-input v-model="addForm.Mid"></el-input>
      </el-form-item>
      <el-form-item label="父亲ID" prop="Fid">
        <el-input v-model="addForm.Fid"></el-input>
      </el-form-item>
      <el-form-item label="姓名" prop="Name">
        <el-input v-model="addForm.Name"></el-input>
      </el-form-item>
      <el-form-item label="性别" prop="Gender">
        <el-input v-model="addForm.Gender"></el-input>
      </el-form-item>
       <el-form-item label="生日" prop="Birth">
        <el-input v-model="addForm.Birth"></el-input>
      </el-form-item>
      <el-form-item label="家族" prop="Familytree">
        <el-input v-model="addForm.Familytree"></el-input>
      </el-form-item>
      <el-form-item label="头像" prop="Img">
        <el-input v-model="addForm.Img"></el-input>
      </el-form-item>
      <el-form-item label="电话" prop="Tel">
        <el-input v-model="addForm.Tel"></el-input>
      </el-form-item>
      <el-form-item label="邮箱" prop="Email">
        <el-input v-model="addForm.Email"></el-input>
      </el-form-item>
      <el-form-item label="履历" prop="Resume">
        <el-input v-model="addForm.Resume"></el-input>
      </el-form-item>
      <el-form-item label="更新时间" prop="UpdateTime">
        <el-input v-model="addForm.UpdateTime"></el-input>
      </el-form-item>
    </el-form>
    <el-button type="primary" @click="addVisual()">确 定</el-button>
    <el-button @click="dialogAddVisible = false">取 消</el-button>
  </el-dialog>

  <!-- 编辑对话框 -->
  <el-dialog title="编辑成员" v-model="dialogEditVisible" width="50%">
    <el-form
      :model="editForm"
      :rules="editFormRules"
      ref="editFormRef"
      label-width="100px"
    >
      <el-form-item label="成员ID" prop="Id">
        <el-input v-model="editForm.Id"></el-input>
      </el-form-item>
      <el-form-item label="伴侣ID" prop="Pids">
        <el-input v-model="editForm.Pids"></el-input>
      </el-form-item>
      <el-form-item label="母亲ID" prop="Mid">
        <el-input v-model="editForm.Mid"></el-input>
      </el-form-item>
      <el-form-item label="父亲ID" prop="Fid">
        <el-input v-model="editForm.Fid"></el-input>
      </el-form-item>
       <el-form-item label="姓名" prop="Name">
        <el-input v-model="editForm.Name"></el-input>
      </el-form-item>
      <el-form-item label="性别" prop="Gender">
        <el-input v-model="editForm.Gender"></el-input>
      </el-form-item>
      <el-form-item label="生日" prop="Birth">
        <el-input v-model="editForm.Birth"></el-input>
      </el-form-item>
      <el-form-item label="家族" prop="Familytree">
        <el-input v-model="editForm.Familytree"></el-input>
      </el-form-item>
      <el-form-item label="头像" prop="Img">
        <el-input v-model="editForm.Img"></el-input>
      </el-form-item>
      <el-form-item label="电话" prop="Tel">
        <el-input v-model="editForm.Tel"></el-input>
      </el-form-item>
      <el-form-item label="邮箱" prop="Email">
        <el-input v-model="editForm.Email"></el-input>
      </el-form-item>
      <el-form-item label="履历" prop="Resume">
        <el-input v-model="editForm.Resume"></el-input>
      </el-form-item>
    </el-form>
    <el-button type="primary" @click="updateVisual">确 定</el-button>
    <el-button @click="dialogEditVisible = false">取 消</el-button>
  </el-dialog>
</template>

<script>
export default {
  data() {
    return {
      isLoading: false,
      dialogAddVisible: false,
      dialogEditVisible: false,
      queryInfo: {
        searchName: "",
        page: 1,
        limit: 10,
      },
      VisualList: [], // 成员列表
      total: 0, // 最大数据记录
      addForm: {
        Id: "",
        Pids: "",
        Mid: "",
        Fid: "",
        Name: "",
        Gender: "",
        Birth: "",
        Familytree: "",
        Img: "",
        Tel: "",
        Email: "",
        Resume: "",
        UpdateTime: "",
      },
      editForm: {
        Id: "",
        Pids: "",
        Mid: "",
        Fid: "",
        Name: "",
        Gender: "",
        Birth: "",
        Familytree: "",
        Img: "",
        Tel: "",
        Email: "",
        Resume: "",
        UpdateTime: "",
      },
      addFormRules: {
        Id: [
          {
            required: true,
            message: "请输入成员ID",
            trigger: "blur",
          },
        ],
        Pids: [
          {
            required: true,
            message: "请输入伴侣ID",
            trigger: "blur",
          },
        ],
        Mid: [
          {
            required: true,
            message: "请输入母亲ID",
            trigger: "blur",
          },
        ],
        Fid: [
          {
            required: true,
            message: "请输入父亲ID",
            trigger: "blur",
          },
        ],
        Name: [
          {
            required: true,
            message: "请输入姓名姓名",
            trigger: "blur",
          },
        ],
        Gender: [
          {
            required: true,
            message: "请输入母亲姓名",
            trigger: "blur",
          },
        ],
        Birth: [
          {
            required: true,
            message: "请输入成员生日",
            trigger: "blur",
          },
        ],
        Familytree: [
          {
            required: true,
            message: "请输入成员家族",
            trigger: "blur",
          },
        ],
        Img: [
          {
            required: true,
            message: "请输入头像",
            trigger: "blur",
          },
        ],
        Tel: [
          {
            required: true,
            message: "请输入电话",
            trigger: "blur",
          },
        ],
        Email: [
          {
            required: true,
            message: "请输入成员邮箱",
            trigger: "blur",
          },
        ],
        Resume:[
          {
            required: true,
            message: "请输入成员履历",
            trigger: "blur",
          },
        ],
      },
      editFormRules: {
        Id: [
          {
            required: false,
            message: "请输入成员ID",
            trigger: "blur",
          },
        ],
        Pids: [
          {
            required: false,
            message: "请输入伴侣ID",
            trigger: "blur",
          },
        ],
        Mid: [
          {
            required: false,
            message: "请输入母亲ID",
            trigger: "blur",
          },
        ],
        Fid: [
          {
            required: false,
            message: "请输入父亲ID",
            trigger: "blur",
          },
        ],
        Name: [
          {
            required: false,
            message: "请输入姓名",
            trigger: "blur",
          },
        ],
        Gender: [
          {
            required: false,
            message: "请输入性别",
            trigger: "blur",
          },
        ],
         Birth: [
          {
            required: false,
            message: "请输入成员生日",
            trigger: "blur",
          },
        ],
        Familytree: [
          {
            required: false,
            message: "请输入成员家族",
            trigger: "blur",
          },
        ],
        Img: [
          {
            required: false,
            message: "请输入头像",
            trigger: "blur",
          },
        ],
        Tel: [
          {
            required: false,
            message: "请输入电话",
            trigger: "blur",
          },
        ],
        Email: [
          {
            required: false,
            message: "请输入成员邮箱",
            trigger: "blur",
          },
        ],
        Resume:[
          {
            required: true,
            message: "请输入成员履历",
            trigger: "blur",
          },
        ],
      },
    };
  },
  created() {
    this.getVisualList();
  },
  methods: {
    async getVisualList() {
      this.isLoading = true;
      // 调用post请求
      console.log(this.VisualList)
      const { data: res } = await this.$http.get("system/apis/visualization", {
        params: this.queryInfo,
      });
      if (res.code != 20000) {
        this.$message.error("加载用户列表失败");
        this.isLoading = false;
      }
      this.VisualList = res.data.value; // 将返回数据赋值
      this.total = res.data.total; // 总个数
      this.isLoading = false;
    },
    // 监听pageSize改变的事件
    handleSizeChange(newLimit) {
      this.queryInfo.limit = newLimit;
      this.getVisualList(); // 数据发生改变重新申请数据
    },
    // 监听pageNum改变的事件
    handleCurrentChange(newPage) {
      this.queryInfo.page = newPage;
      this.getVisualList(); // 数据发生改变重新申请数据
    },
    test(){
      console.log(this.addForm.Id);
    },
    async deleteVisual(Id) {
      // 弹框
      const confirmResult = await this.$confirm(
        "此操作将永久删除该成员, 是否继续?",
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      ).catch((err) => err);
      // 成功删除为confirm 取消为 cancel
      if (confirmResult != "confirm") {
        return this.$message.info("已取消删除");
      }
      const { data: res } = await this.$http.delete(
        "system/apis/visualization?id=" + Id
      );
      if (res.code != 20000) {
        return this.$message.error("删除失败");
      }
      this.$message.success("删除成功");
      this.getVisualList();
    },
    // 添加成员
    addVisual() {
      this.$refs.addFormRef.validate(async (valid) => {
        if (!valid) return;
        // 发起请求
        const { data: res } = await this.$http.post(
          "/system/apis/visualization",
          this.addForm
        );
        if (res.code == 20000) {
          this.getVisualList();
          this.dialogAddVisible = false;
          return this.$message.success("添加成功");
        }
        this.$message.error("添加失败");
      });
    },
    // 编辑
    updateVisual() {
      this.$refs.editFormRef.validate(async (valid) => {
        if (!valid) return;
        // 发起请求
        console.log(this.Id)
        const { data: res } = await this.$http.put(
          "/system/apis/visualization",
          this.editForm
        );
        if (res.code == 20000) {
          this.getVisualList();
          this.dialogEditVisible = false;
          return this.$message.success("编辑成功");
        }
        this.$message.error("编辑失败");
      });
    },
    dialogEditOpen(
      Id,
      Pids,
      Mid,
      Fid,
      Name,
      Gender,
      Birth,
      Familytree,
      Img,
      Tel,
      Email,
      Resume
    ) {
      this.editForm.Id = String(Id);
      this.editForm.Pids = String(Pids);
      this.editForm.Mid = String(Mid);
      this.editForm.Fid = String(Fid);
      this.editForm.Name = String(Name);
      this.editForm.Gender = String(Gender);
      this.editForm.Birth = String(Birth);
      this.editForm.Familytree = String(Familytree);
      this.editForm.Img = String(Img);
      this.editForm.Tel = String(Tel);
      this.editForm.Email = String(Email);
      this.editForm.Resume = String(Resume);
      this.dialogEditVisible = true;
    },
  },
};
</script>

<style>
</style>

可视化代码实现:

<template>
    <div>{
   
   {total}},{
   
   {v}},{
   
   {nodes}}</div>
     <div id="tree" ref="tree"></div>
  </template>
  
<script>
     import FamilyTree from '@balkangraph/familytree.js'
     export default {
        name: 'tree',
        data() {
           return {
            /*
            queryInfo: {
                page: 1,
                limit: 10,
            },*/
            nodes:[],
            temp:[],
            map:{"id":0,"pids":0,"name":""},
            //map:{"id":0,"pids":0,"mid":0,"fid":0,"name":""},
            total:0,  
            v:"",
           }},
        created(){
            this.getNodeList();
        },
        methods: {
            mytree: function(domEl, x) {
                this.family = new FamilyTree (domEl, {
                   nodes: x,
                      nodeBinding: {
                         field_0: "name",
                         img_0: "img"
                       }
                   });
               },
            async getNodeList(){
            const { data: res } = await this.$http.get("system/apis/familytree");
            if (res.code != 20000) {
                this.$message.error("加载家族族谱失败");
            }
            this.total=res.data["total"];
            this.v=res.data.value;
            var count=0;
            for(var i in res.data.value)
            //for(var i =0;i<this.total;i++)
            {
                count++;
                if(count==1)
                {
                   
                        var map={"id":0,"pids":[],"name":"","gender":"","img":""};
                        map["id"]=res.data.value[i]["Id"];
                        map["pids"][0]=res.data.value[i]["Pids"];
                        //this.map["mid"]=res.data.value[i]["Mid"];
                        //this.map["fid"]=res.data.value[i]["Fid"];
                        map["name"]=res.data.value[i]["Name"];
                        map["gender"]=res.data.value[i]["Gender"];
                        map["img"]=res.data.value[i]["Img"];
                        this.temp[i]=map; 
                    
                }
               else{
                   
                        var map={"id":0,"pids":[],"mid":0,"fid":0,"name":"","gender":"","img":""};
                        map["id"]=res.data.value[i]["Id"];
                        map["pids"][0]=res.data.value[i]["Pids"];
                        map["mid"]=res.data.value[i]["Mid"];
                        map["fid"]=res.data.value[i]["Fid"];
                        map["name"]=res.data.value[i]["Name"];
                        map["gender"]=res.data.value[i]["Gender"];
                        map["img"]=res.data.value[i]["Img"];
                        this.temp[i]=map;     
                   
               }
            }
            
            //this.nodes[0] = this.temp[0]; // 将返回数据赋值
            //this.nodes[1] = this.temp[1]; // 将返回数据赋值
            for(var i =this.total-1;i>=0;i--)
            {
                this.nodes[i] = this.temp[i]; // 将返回数据赋值
            }
        }
     },
     mounted(){
          this.mytree(this.$refs.tree, this.nodes)
          }
      }
  </script>
  <style scoped>
  </style>

6、在前端项目导入familytree插件方法:

cnpm install
  cnpm i @balkangraph/familytree.js

然后复制粘贴代码使用即可。

7、演示:

插入表:

 可视化:

示例2: 

8、如果发生这种报错暂可不用理会,再次运行即可。

优点:完成了数据库连接的可视化界面

缺点:目前不支持多父母和多前任夫妻关系,可以将pids和mid、fid的值改为列表即可。

猜你喜欢

转载自blog.csdn.net/qq_51701007/article/details/125299575