JSMInd实现动态思维导图的保存和展示

前言:最近公司要求java微服务架构中某一个页面做成动态表格的形式,可以手动增加列这种,但是领导希望能够做成思维导图更好,也是能够实时的动态添加数据,保存数据,查看数据。其他同事做列转行,我进行调研,最终选择JSMind插件实现。

第一步:

 新建springboot项目,引入对应的js文件jsmind.js、jsmind.draggable.js、jsmind.css、jquery-3.5.1.min.js。引入依赖(根据自己需求取舍,我这将项目里的都拿过来了)
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--由于feign整合了ribbon的负载均衡,所以需要引入ribbon的依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>0.2.2.RELEASE</version><!--排除nacos-client需要注掉--><!-- <exclusions><exclusion><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId></exclusion></exclusions>--></dependency><dependency><groupId>com.hf.example</groupId><artifactId>order-service-api</artifactId><version>0.0.2-SNAPSHOT</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.10.6</version></dependency><dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><!-- <version>2.1.0.Final</version> --></dependency><dependency><groupId>jakarta.xml.bind</groupId><artifactId>jakarta.xml.bind-api</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.13</version><scope>runtime</scope></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
</dependencies>

第二步:

 新建index.html,代码如下:
<!DOCTYPE html>
<html>
<head><title>jsmindd</title>
</head>
<link rel="stylesheet" href="css/jsmind.css">
<script type="text/javascript" src="js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="js/jsmind.js"></script>
<script type="text/javascript" src="js/jsmind.draggable.js"></script>
<body>
<div id="jsmind_container" style="width: 1000px;height: 1000px;"></div>
<button type="button" onclick="save()">保存</button>
<input type="hidden"  th:value='${queryId}' id="queryId">
<!--<button type="button" onclick="initializeNode(1)">查询</button>-->
</body>
</html>
<script>var json={"id":"root", "topic":"jsMind"};var queryId=$("#queryId").val();if(queryId!=null && queryId!=""&&queryId!="undefined"){initializeNode(parseInt(queryId));}// var json={"children":[{"children":[{"expanded":true,"id":"5ac0879039b39d07","topic":"测试1-1"},{"expanded":true,"id":"5ac088c8337ea5ec","topic":"测试1-2"}],"expanded":true,"id":"5ac0861536b973f9","topic":"测试1"},{"children":[{"expanded":true,"id":"5ac089d5d3d25fd2","topic":"测试2-1"},{"expanded":true,"id":"5ac08ae33fd3213e","topic":"测试2-2"}],"expanded":true,"id":"5ac086e73ce21e88","topic":"测试2"}],"expanded":true,"id":"root","topic":"jsMind"};var mind = {"meta":{"name":"jsMind remote","author":"hizzgdev@163.com","version":"0.2"},"format":"node_tree","data":json}// jsMind的选项,更多参数参见jsMind的文档// https://github.com/hizzgdev/jsmind/blob/master/docs/zh/index.mdvar options = {container:'jsmind_container',//容器的IDtheme:'primary',             //主题//options的属性//container : '',         // [必选] 容器的IDeditable : true,       // 是否启用编辑// theme : null,           // 主题// mode :'full',           // 显示模式========full - 子节点动态分布在根节点两侧 [默认值] side - 子节点只分布在根节点右侧// support_html : true,    // 是否支持节点里的HTML元素// view:{//     hmargin:100,        // 思维导图距容器外框的最小水平距离//     vmargin:50,         // 思维导图距容器外框的最小垂直距离//     line_width:2,       // 思维导图线条的粗细//     line_color:'#555'   // 思维导图线条的颜色// },// layout:{//     hspace:30,          // 节点之间的水平间距//     vspace:20,          // 节点之间的垂直间距//     pspace:13           // 节点与连接线之间的水平间距(用于容纳节点收缩/展开控制器)// },shortcut:{enable:true,        // 是否启用快捷键//     handles:{},         // 命名的快捷键事件处理器mapping:{           // 快捷键映射addchild   : 45,    // <Insert>addbrother : 13,    // <Enter>editnode   : 113,   // <F2>delnode    : 46,    // <Delete>toggle     : 32,    // <Space>left       : 37,    // <Left>up         : 38,    // <Up>right      : 39,    // <Right>down       : 40,    // <Down>}},}var jm = new jsMind(options);jm.show(mind);//jm.disable_edit();//禁止编制jm.expand_all();//展开全部节点var savejson;
//将思维导图拼成一个json传递到后台进行保存
function save() {var node=jm.get_root();var id=node.id;var topic = node.topic;var expanded = node.expanded;var children = node.children;savejson='{"queryId":"'+queryId+'","id":"'+id+'","topic":"'+topic+'","expanded":"'+expanded+'"';generateChild(children);var jsonend= savejson+'}';$.ajax({url:"/save",        //请求地址type:"post",             //请求方式data:jsonend,             //这里的data:发送给服务器的请求数据datatype:"json",contentType: 'application/json;charset=utf-8',success:function(str){  //回调函数:数据请求成功之后调用if(str=='true'){alert("保存成功");}else{alert("保存失败");}                 //这里的data:从服务器发送回来的数据},});
}
//递归实现思维导图各个子节点的拼接
function generateChild(children) {if(children.length>0){savejson=savejson +',"children":[';for (var i = 0 ; i< children.length ; i++){var zid=children[i].id;var ztopic=children[i].topic;var zexpanded=children[i].expanded;var parentId=children[i].parent.id;savejson=savejson +'{"id":"'+zid+'","topic":"'+ztopic+'","expanded":"'+zexpanded+'","parentId":"'+parentId+'"';if(children[i].children.length>0){generateChild(children[i].children,savejson);}savejson=savejson+"},";}savejson=savejson.substring(0, savejson.length-1)+"]";}
}
/*** 根据id初始化节点信息*/
function initializeNode(i) {var queryjson={"queryId":i};$.ajax({url:"/query",      //请求地址type:"get",          //请求方式data:queryjson,           //这里的data:发送给服务器的请求数据async: false,datatype:"json",//contentType: 'application/json;charset=UTF-8"',success:function(msg){  //回调函数:数据请求成功之后调用json=JSON.parse(msg);},});}
</script>

第三步:

 application.properties添加数据库配置如下:
server.port=8091
##单机操作解注(没有使用nacos或者eureka)
##order-service.ribbon.listOfServers=\localhost:8082
spring.application.name =user-service
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848#数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/hf-test?useUnicode=true&characterEncoding=utf8&useOldAliasMetadataBehavior=true&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Drivermybatis.mapper-locations= classpath:com/example/mapper/persistence/*.xml

第四步:

 controller层代码编写:
import com.alibaba.fastjson.JSONObject;
import com.example.dto.FileNodePojo;
import com.example.mapper.entitys.FileNode;
import com.example.mapper.persistence.FileNodeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;@Controller
public class WebController {@AutowiredFileNodeMapper fileNodeMapper;@RequestMapping(value="/index")@ResponseBodypublic ModelAndView index(int i){ModelAndView mv = new ModelAndView("index.html");mv.addObject("queryId", i);// mv.setViewName("index.html");return mv;}@PostMapping(value = "/save",consumes="application/json;charset=UTF-8")@ResponseBodypublic String save(@RequestBody FileNodePojo fileNodePojo){String saveflag="false";try {// String[] excludeProperties = {"queryId"};String jsonString = JSONObject.toJSONString(fileNodePojo);FileNode fileNode = new FileNode();fileNode.setId(Integer.valueOf(fileNodePojo.getQueryId()));fileNode.setFilenodejsonstr(jsonString);FileNode node = fileNodeMapper.selectByPrimaryKey(Integer.valueOf(fileNodePojo.getQueryId()));if (node!=null){fileNodeMapper.updateByPrimaryKey(fileNode);}else{fileNodeMapper.insert(fileNode);}saveflag="true";}catch (Exception e){throw e;}return saveflag;}@GetMapping(value = "/query")@ResponseBodypublic String query(String queryId){FileNode fileNode = fileNodeMapper.selectByPrimaryKey(Integer.valueOf(queryId));return fileNode.getFilenodejsonstr();}
}

第五步:

 实体类代码:
import lombok.Data;import java.io.Serializable;
import java.util.List;
@Data
public class FileNodePojo implements Serializable {public String queryId;//对应jsmind唯一idpublic String id;//对应jsmind唯一idpublic String topic;//对应jsmind显示的名称public String direction;//对应jsmind思维导图的朝向 left/rightpublic boolean expanded; //对应jsmind该节点是否展开true/falsepublic String background; //jsmind只识别background-color属性,此处定义“-”会编译不通过,待前台js批量替换处理public String foreground; //jsmind只识别foreground-color属性,此处定义“-”会编译不通过,待前台js批量替换处理public String parentd; //jsmind没有此属性,此处定义为了与数据库所属父节点字段对应,递归关联查询时会用到public List<FileNodePojo> children;//对应jsmind当前节点的子节点集合}

第六步:

 数据库底层代码FileNode、FileNodeMapper和FileNodeMapper.xml:
public class FileNode {private Integer id;private String filenodejsonstr;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getFilenodejsonstr() {return filenodejsonstr;}public void setFilenodejsonstr(String filenodejsonstr) {this.filenodejsonstr = filenodejsonstr == null ? null : filenodejsonstr.trim();}
}
import com.example.mapper.entitys.FileNode;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;@Mapper
@Repository
public interface FileNodeMapper {int deleteByPrimaryKey(Integer id);int insert(FileNode record);int insertSelective(FileNode record);FileNode selectByPrimaryKey(Integer id);int updateByPrimaryKeySelective(FileNode record);int updateByPrimaryKey(FileNode record);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.mapper.persistence.FileNodeMapper" ><resultMap id="BaseResultMap" type="com.example.mapper.entitys.FileNode" ><id column="id" property="id" jdbcType="INTEGER" /><result column="fileNodeJsonStr" property="filenodejsonstr" jdbcType="VARCHAR" /></resultMap><sql id="Base_Column_List" >id, fileNodeJsonStr</sql><select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >select <include refid="Base_Column_List" />from filenodewhere id = #{id,jdbcType=INTEGER}</select><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >delete from filenodewhere id = #{id,jdbcType=INTEGER}</delete><insert id="insert" parameterType="com.example.mapper.entitys.FileNode" >insert into filenode (id, fileNodeJsonStr)values (#{id,jdbcType=INTEGER}, #{filenodejsonstr,jdbcType=VARCHAR})</insert><insert id="insertSelective" parameterType="com.example.mapper.entitys.FileNode" >insert into filenode<trim prefix="(" suffix=")" suffixOverrides="," ><if test="id != null" >id,</if><if test="filenodejsonstr != null" >fileNodeJsonStr,</if></trim><trim prefix="values (" suffix=")" suffixOverrides="," ><if test="id != null" >#{id,jdbcType=INTEGER},</if><if test="filenodejsonstr != null" >#{filenodejsonstr,jdbcType=VARCHAR},</if></trim></insert><update id="updateByPrimaryKeySelective" parameterType="com.example.mapper.entitys.FileNode" >update filenode<set ><if test="filenodejsonstr != null" >fileNodeJsonStr = #{filenodejsonstr,jdbcType=VARCHAR},</if></set>where id = #{id,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="com.example.mapper.entitys.FileNode" >update filenodeset fileNodeJsonStr = #{filenodejsonstr,jdbcType=VARCHAR}where id = #{id,jdbcType=INTEGER}</update>
</mapper>

第七步:进行测试

刚开始访问界面如下:

添加对应属性后:

点击保存数据库存储为:

再次刷新页面仍保持不变,更新之后,再次刷新为最新数据。完成任务。

源码下载地址
链接:https://pan.baidu.com/s/1jBkyu6fi1OvoEDEP-JWi-A
提取码:myfx
分享请注明出处。

JSMInd实现动态思维导图的保存和展示相关推荐

  1. SaaSBase:免费的思维导图软件:2022年9种最好的工具

    很有可能的是,现在你的盘子里有很多东西. 这篇文章可能不是你的网络浏览器上唯一打开的标签,找到正确的思维导图软件并不是你清单上的唯一任务. 这就是为什么思维导图软件如此重要.思维导图是一个可视化图表, ...

  2. 思维导图使用技巧:手把手教你怎么画思维导图 #CSDN博文精选# #系统化学习# #IT技术# #知识图谱#

    大家好~我是小C,又见面啦!"文章过滤器"精选大咖干货.助力学习之路. <5天20篇CSDN精选博文带你掌握系统化学习方法>专栏将挑选有关"系统化学习方法&q ...

  3. 地理思维导图怎么画?五步教你思维导图画法

    对于思维导图的使用很多人就说上班的时候用处确实挺大的,但也仅限于上班,其余的时候没什么用.能说出这样话的人必定是对思维导图不熟悉的人.对于思维导图来说,学习,工作,生活没有什么场合是不能使用的.地理思 ...

  4. 基于网络的思维导图工具的八个独特优点

    概述:新兴的基于网络的思维导图工具比起传统的桌面软件有着太多的优点,以下是笔者总结的八个独特优点. 如果你正在寻找一种低成本的用于商业的思维导图工具,那么那些基于网络的思维导图软件会是一个不错的选择. ...

  5. 17张思维导图,2021年作为一名前端开发者需要掌握这些,前端面试复习资料参考大纲

    本文首发于17张思维导图,2021年作为一名前端开发者需要掌握这些,前端面试复习资料参考大纲,转载请联系作者 前言 2020年最后一个月了,熬夜多天整理出17张思维导图,对前端面试复习知识点进行了最全 ...

  6. SimpleMind Pro for Mac(思维导图)中文完整版

    SimpleMind for Mac是Mac平台上非常好用的一款思维导图软件,可将您的Mac变成头脑风暴,创意收集和思维结构设备,simplemind完整版无缝地图同步,可以选择多种思维导图样式,还可 ...

  7. 多平台的思维导图软件

    说到思维导图,可能很多人只听过,却不清楚它到底是什么,是用来做什么的.思维导图,其实也叫作脑图,是一种实用的思维整理工具,可以让你大脑的思路更清晰,让凌乱的知识点架构更明确,对日常工作.学习.生活都有 ...

  8. 绘制思维导图用什么软件?告诉你三个实用的软件

    思维导图是一种有效的思维模式,应用于记忆.学习.思考等的思维"地图",有利于人脑思维的扩散.如今市面上能够辅助我们更好地锻炼大脑,产出思维导图的工具数不胜数,但不同人群的使用不同, ...

  9. 没用过TheBrain,请别叫它“思维导图” | TheBrain深度解析

    TheBrain是一块国内外非常火爆的软件,它是各种思维过程记录工具中独树一帜的精品--其思维网络呈现方式非常独特,节点/关联关系表达能力极强,交互界面比较符合人类直觉,对思维网络的编辑操作也相当灵活 ...

  10. 计算机信息技术知识点思维导图,初中信息技术《计算机系统》单元教学设计以及思维导图.doc...

    初中信息技术<计算机系统>单元教学设计以及思维导图.doc 初中信息技术计算机系统单元教学设计以及思维导图主题单元标题计算机系统适用年级初中一年级所需时间6课时主题学习概述(对主题内容进行 ...

最新文章

  1. 常用python工具类代码总结
  2. GIS+=地理信息+云计算技术——Spark集群部署
  3. 算法设计与分析之循环与递归
  4. Python 技术篇-使用time库获取秒级时间戳、毫秒级时间戳实例演示
  5. DMURLConnection
  6. SDNU 1330.Max Sum(最大子序列和)
  7. 18年5年制计算机辅助考试题,2018年自考《计算机辅助教育》试题二
  8. 用自己数据集训练Mask_RCNN代码
  9. ios tableview_iOS简单TableView示例教程
  10. linux opendir路径_Linux C - opendir 和 readdir 和 closedir - 目录文件打开
  11. RC有源滤波器之低通滤波器(一)
  12. 弹性系数和线径的计算公式_弹簧力的计算公式
  13. 无电流时二极管压降问题
  14. EPUB电子书阅读与制作
  15. kdj超卖_最全的KDJ(超买超卖)指标实用技巧(图解)
  16. 计算机函数公式 加法,Excel中如何计算加减乘除法/表格加法公式
  17. JavaScript 10进制转换为类似‘0x00d5’格式的16进制
  18. SparkSQL 自定义UDF提取json中的字段
  19. dialog出现Uncaught RangeError: Maximum call stack size exceeded错误
  20. Winodows subsystem for Linux(WSL)的安装及GUI图形界面启用

热门文章

  1. Android 补间动画之平移动画TranslateAnimation
  2. 内部审计具体准则第28号—信息系统审计
  3. 屏幕录像专家v2016破解版
  4. 卡巴斯基正式版 送一年
  5. 为什么计算机软件是无形资产,购买软件是否属于无形资产
  6. 迅雷:游移的4亿用户帝国
  7. PXE网刻教程 教如何制作自己的DOS网卡驱动
  8. VB6.0视频教程78集,入门视频教程,基础够了(基础篇)
  9. Eclipse之各个版本的区别
  10. 机器学习教程 二.在股票上的回归预测