vue项目实战-脑图编辑管理系统kitymind百度脑图
前言
项目为前端vue项目,把kitymind百度脑图整合到前端vue项目中,显示了脑图的绘制,编辑,到处为json,png,text等格式的功能
文章末尾有相关的代码链接,代码只包含前端项目,在原始的项目中也编写了相关的接口,但是原先的后端项目是公司的,不方便公开出来,这里只提供我新写的前端项目,刚兴趣的同学可以把后端实现。
项目目录

项目的核心逻辑在public包下的local-kitymind文。件夹中,vue页面只是做了简单的引用,核心逻辑写在了diy.js与index.html两个文件当中
下面是功能介绍以及相关实现。
脑图编辑页面
主页面展示
用户可以在编辑页编辑脑图文件,支持导出为各种格式,也可导入json文件,到处test,png,md,json等格式的文件,我个人新增了 “保存” 和 “内存为” 的按钮,在原系统中可以同后端进行交互,实现json信息的入库。

保存:
自动显示当前脑图所属版本,要求用户输入脑图名称和脑图描述,脑图名称为必填项

另存为:
用户点击另存为按钮,出现弹窗,要求用户输入脑图名称,描述,新建版本名称,新建版本描述,

功能实现
diy.js
在diy.js文件中我们定义了最上层若干按钮的样式以及对应的函数。
若干个导出按钮与导入导入按钮没有与后端交互,调用了百度脑图的api,另存为和保存按钮调用了在index.html中定义的vue函数,使得页面出现弹窗,同时将脑图的json转化为字符串保存在浏览器的localStorage中。下面是代码
(function () {var oldData;var baseURL = 'http://localhost:12222';// var baseURL = 'http://10.20.26.231:12222';var html = '';html += '<a href="" class="diy export" data-type="json">导出json</a>',html += '<a href="" class="diy export" data-type="md">导出md</a>',html += '<a href="" class="diy export" data-type="km">导出km</a>',html += '<a href="" class="diy export" data-type="svg">导出svg</a>',html += '<a href="" class="diy export" data-type="txt">导出text</a>',html += '<a href="" class="diy export" data-type="png">导出png</a>',html += '<button class="diy input">',html += '导入<input type="file" id="fileInput" accept=".km,.txt,.md,.json" >',html += '</button>'html += '<button class="diy httpinput">保存</button>',html += '<button class="diy httpinput2">另存为</button>',$('.editor-title').append(html);$('.diy').css({// 'height': '30px',// 'line-height': '30px','margin-top': '0px','float': 'right','background-color': '#fff','min-width': '60px','text-decoration': 'none',color: '#999','padding': '0 10px',border: 'none','border-right': '1px solid #ccc',});$('.input').css({'overflow': 'hidden','position': 'relative',}).find('input').css({cursor: 'pointer',position: 'absolute',top: 0,bottom: 0,left: 0,right: 0,display: 'inline-block',opacity: 0});// $('.httpinput').css({// 'overflow': 'hidden',// 'position': 'relative',// }).find('httpinput').css({// cursor: 'pointer',// position: 'absolute',// top: 0,// bottom: 0,// left: 0,// right: 0,// display: 'inline-block',// opacity: 0// });$('.httpinput2').css({'overflow': 'hidden','position': 'relative',}).find('httpinput2').css({cursor: 'pointer',position: 'absolute',top: 0,bottom: 0,left: 0,right: 0,display: 'inline-block',opacity: 0});$(document).on('click', '.export', function (event) {event.preventDefault();var $this = $(this),type = $this.data('type'),exportType;switch (type) {case 'km':exportType = 'json';break;case 'md':exportType = 'markdown';break;case 'svg':exportType = 'svg';break;case 'txt':exportType = 'text';break;case 'png':exportType = 'png';break;default:exportType = type;break;}editor.minder.exportData(exportType).then(function (content) {switch (exportType) {case 'json':console.log($.parseJSON(content));break;default:console.log(content);break;}var blob = new Blob();switch (exportType) {case 'png':blob = dataURLtoBlob(content); //将base64编码转换为blob对象break;default:blob = new Blob([content]);break;}var a = document.createElement("a"); //建立标签,模拟点击下载a.download = $('#node_text1').text() + '.' + type;a.href = URL.createObjectURL(blob);a.click();});});//保存$(document).on('click', '.httpinput', async function (event) {// ct = await editor.minder.exportData('json')// console.log('shangyi');var ct;console.log('-------insert start-----')editor.minder.exportData('json').then(function (content) {ct = content;// console.log(ct)localStorage.setItem('brainJson',ct)});// console.log(version)myApp.openDialog()});//另存为$(document).on('click', '.httpinput2', async function (event) {console.log('shangyi');var ct;console.log('-------insert start-----')editor.minder.exportData('json').then(function (content) {ct = content;// console.log(ct)localStorage.setItem('brainJson',ct)});// console.log(version)myApp.openDialog2()});// 导入window.onload = function () {var fileInput = document.getElementById('fileInput');fileInput.addEventListener('change', function (e) {var file = fileInput.files[0],// textType = /(md|km)/,fileType = file.name.substr(file.name.lastIndexOf('.') + 1);console.log(file);switch (fileType) {case 'md':fileType = 'markdown';break;case 'txt':fileType = 'text';break; case 'km':case 'json':fileType = 'json';break;default:console.log("File not supported!");alert('只支持.km、.md、、text、.json文件');return;}var reader = new FileReader();reader.onload = function (e) {var content = reader.result;editor.minder.importData(fileType, content).then(function (data) {console.log(data)$(fileInput).val('');});}reader.readAsText(file);});}})();//base64转换为图片blob
function dataURLtoBlob(dataurl) {var arr = dataurl.split(',');//注意base64的最后面中括号和引号是不转译的var _arr = arr[1].substring(0, arr[1].length - 2);var mime = arr[0].match(/:(.*?);/)[1],bstr = atob(_arr),n = bstr.length,u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n);}return new Blob([u8arr], {type: mime});
}
index.html文件
我们定义了页面标题等信息,引入kityminder-editor这个标签,同时使用elements-ui写了两个保存窗口 ,用户在“保存” 和 “另存为” 窗口可以点击“保存”按钮,则调用axios请求将json字符串发送至后端。
在发送请求的同时也会携带当前登陆者的信息,登陆者的信息是存储在cookie中,调用函数 getCookie('employeeId') 可以实现,但是用户这部分功能为公司项目,在我提供的代码中并未体现。
这里介绍一下 document.addEventListener 这个函数,在项目中他起到了初始化页面的作用,原先的项目逻辑为在 脑图管理页面 点击一条脑图信息,则讲相关信息存储到浏览器的localStorage中,然后调用脑图初始化的api,将json渲染到页面上,从而实现脑图的管理与跳转。下面是整体代码
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>KityMinder Editor</title><link href="favicon.ico" type="image/x-icon" rel="shortcut icon"><!-- bower:css --><link rel="stylesheet" href="./bower_components/bootstrap/dist/css/bootstrap.css" /><link rel="stylesheet" href="./bower_components/codemirror/lib/codemirror.css" /><link rel="stylesheet" href="./bower_components/hotbox/hotbox.css" /><link rel="stylesheet" href="./bower_components/kityminder-core/dist/kityminder.core.css" /><link rel="stylesheet" href="./bower_components/color-picker/dist/color-picker.min.css" /><!-- endbower --><link rel="stylesheet" href="kityminder.editor.min.css"><style>html, body {margin: 0;padding: 0;height: 100%;overflow: hidden;}h1.editor-title {background: #393F4F;color: white;margin: 0;height: 40px;font-size: 14px;line-height: 40px;font-family: 'Hiragino Sans GB', 'Arial', 'Microsoft Yahei';font-weight: normal;padding: 0 20px;}div.minder-editor-container {position: absolute;top: 40px;bottom: 0;left: 0;right: 0;}</style>
</head><body ng-app="kityminderDemo" ng-controller="MainController"><h1 class="editor-title"><a href="http://www.huangyebo.cn" style="color: #fff;" target="_blank">KityMinder Editor</a>
<a href="https://beian.miit.gov.cn/" target="_blank"></a>
</h1><kityminder-editor on-init="initEditor(editor, minder)" data-theme="fresh-green"></kityminder-editor>
<iframe name="frameFile" style="display:none;"></iframe><div id="app"><el-dialog :visible.sync="dialogVisible" title="脑图保存"><el-form ref="form" :model="BrainMap" label-width="80px"><el-form-item label="脑图名称"><el-input required="required" v-model="BrainMap.name"></el-input></el-form-item><el-form-item label="脑图描述"><el-input v-model="BrainMap.description"></el-input></el-form-item><el-form-item label="脑图版本"><el-col :span="8"><el-input readonly v-model="BrainMap.version"></el-input></el-col></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">保存</el-button><el-button>取消</el-button></el-form-item></el-form></el-dialog><el-dialog :visible.sync="dialogVisible" title="另存为"><el-form ref="form" :model="BrainMap" label-width="80px"><el-form-item label="脑图名称"><el-input required="required" v-model="BrainMap.name"></el-input></el-form-item><el-form-item label="脑图描述"><el-input v-model="BrainMap.description"></el-input></el-form-item><el-form-item label="版本名称"><el-col ><el-input v-model="versionName"></el-input></el-col></el-form-item><el-form-item label="版本描述"><el-col ><el-input v-model="versionDescription"></el-input></el-col></el-form-item><el-form-item><el-button type="primary" @click="saveVersion">保存</el-button><el-button>取消</el-button></el-form-item></el-form></el-dialog>
</div><div>
</div>
</body><!-- bower:js -->
<script src="./bower_components/jquery/dist/jquery.js"></script>
<script src="./bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="./bower_components/angular/angular.js"></script>
<script src="./bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="./bower_components/codemirror/lib/codemirror.js"></script>
<script src="./bower_components/codemirror/mode/xml/xml.js"></script>
<script src="./bower_components/codemirror/mode/javascript/javascript.js"></script>
<script src="./bower_components/codemirror/mode/css/css.js"></script>
<script src="./bower_components/codemirror/mode/htmlmixed/htmlmixed.js"></script>
<script src="./bower_components/codemirror/mode/markdown/markdown.js"></script>
<script src="./bower_components/codemirror/addon/mode/overlay.js"></script>
<script src="./bower_components/codemirror/mode/gfm/gfm.js"></script>
<script src="./bower_components/angular-ui-codemirror/ui-codemirror.js"></script>
<script src="./bower_components/marked/lib/marked.js"></script>
<script src="./bower_components/kity/dist/kity.min.js"></script>
<script src="./bower_components/hotbox/hotbox.js"></script>
<script src="./bower_components/json-diff/json-diff.js"></script>
<script src="./bower_components/kityminder-core/dist/kityminder.core.min.js"></script>
<script src="./bower_components/color-picker/dist/color-picker.min.js"></script>
<!-- endbower --><script src="kityminder.editor.min.js"></script>
<script src="diy.js"></script><!-- 引入 Vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 引入 Element-UI 样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入 Element-UI 组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script><script>var baseURL = 'http://localhost:12222';// var baseURL = 'http://10.20.26.231:12222';angular.module('kityminderDemo', ['kityminderEditor']).controller('MainController', function($scope) {$scope.initEditor = function(editor, minder) {window.editor = editor;window.minder = minder;};});function getCookie(name){var strcookie = document.cookie;//获取cookie字符串var arrcookie = strcookie.split("; ");//分割//遍历匹配console.log(arrcookie)for ( var i = 0; i < arrcookie.length; i++) {var arr = arrcookie[i].split("=");if (arr[0] == name){return arr[1];}}return "";}var myApp = new Vue({el: '#app',data() {return {dialogVisible: false, // 控制弹窗的显示和隐藏versionDescription:'',versionName:'',BrainMap: {name: '',version: '',description: '',Json:'',employeeId:'',},}},methods: {openDialog() { //保存到旧版本this.dialogVisible = true; // 打开弹窗this.BrainMap.version = localStorage.getItem('version')},openDialog2() { //另存为this.dialogVisible = true; // 打开弹窗// this.BrainMap.version = localStorage.getItem('version')},onSubmit() {console.log('save!');this.BrainMap.Json = localStorage.getItem('brainJson')this.BrainMap.employeeId = getCookie('employeeId')if(this.BrainMap.name===''){this.$message({message:'脑图名不为空',type:'warning'})return}axios({method: 'POST',url: baseURL+'/common/saveBrainVersion',data: {json:this.BrainMap.Json,version:this.BrainMap.version,name: this.BrainMap.name,description: this.BrainMap.description,employeeId:this.BrainMap.employeeId,}}).then(response => {console.log( response)}, error => {console.log('错误', error.message)})this.dialogVisible = false},saveVersion() {var versionId = 0axios({method: 'get',url: baseURL+'/common/versionMaxId',params: {}}).then(response => {versionId = response.data.data.idthis.BrainMap.version = versionId + 1console.log(this.BrainMap.version)this.onSubmit()}, error => {console.log('错误', error.message)})axios({method: 'get',url: baseURL+'/common/saveVersion',params: {versionName: this.versionName,description: this.versionDescription}}).then(response => {console.log( response)}, error => {console.log('错误', error.message)})this.dialogVisible = false},}});document.addEventListener("DOMContentLoaded", function() {// 在页面加载完成后执行的 JavaScript 代码// 发起请求console.log("监听页面初始化")// var content = '{"root":{"data":{"id":"ctojgfitvug0","created":1687981368534,"text":"shangyi"},"children":[]},"template":"default","theme":"fresh-blue","version":"1.4.33"} 'var content = localStorage.getItem('brainJson')editor.minder.importData('json', content).then(function (data) {// console.log(data)});});
</script></html>
项目链接:
脑图编辑管理系统前端: 基于百度脑图的二次开发,将百度脑图整合到vue中去,可以直接引入自己的项目
相关文章:
vue项目实战-脑图编辑管理系统kitymind百度脑图
前言 项目为前端vue项目,把kitymind百度脑图整合到前端vue项目中,显示了脑图的绘制,编辑,到处为json,png,text等格式的功能 文章末尾有相关的代码链接,代码只包含前端项目,在原始的…...
c++调用ffmpeg api录屏 并进行rtmp推流
代码及工程见https://download.csdn.net/download/daqinzl/88156528 开发工具:visual studio 2019 记得启动rtmp流媒体服务 nginx的rtmp服务见https://download.csdn.net/download/daqinzl/20478812 播放,采用ffmpeg工具集里的ffplay.exe, 执行命令 f…...
SQL分类及通用语法数据类型(超详细版)
一、SQL分类 SQL是结构化查询语言(Structured Query Language)的缩写。它是一种用于管理和操作关系型数据库系统的标准化语言。SQL分类如下: DDL: 数据定义语言,用来定义数据库对象(数据库、表、字段)DML:…...
配置Hive远程服务详细步骤
HiveServer2支持多客户端的并发和认证,为开放API客户端如JDBC、ODBC提供了更好的支持。 (1)修改hive-site.xml,在文件中添加以下内容: <property><name>hive.metastore.event.db.notification.api.auth&l…...
Java中实现图片和Base64的互相转化
文章目录 前言一、代码二、测试三、结果 前言 公司项目中用到了实名认证此,采用的第三方平台。后端中用到的单项功能为身份证信息人像对比功能,在写demo的过程中发现,它们所要求的图片信息为base64编码格式。 一、代码 package com.bajiao…...
视频添加字幕
1、依靠ffmpeg 命令 package zimu;import java.io.IOException;public class TestSrt {public static void main(String[] args) {String videoFile "/test/test1.mp4";String subtitleFile "/test/test1.SRT";String outputFile "/test/testout13…...
Vue VS React:两大前端框架的对比与分析
Vue和React是当前最流行的前端框架之一,它们都有着广泛的应用和开发者社区。下面是Vue和React之间的深度对比与分析: 学习曲线: Vue:Vue拥有简单直观的API和文档,对初学者友好。Vue的设计初衷是逐步增强的,…...
【机密计算标准解读】 基于TEE的安全计算(IEEE 2952)
目录 1.概述2.定义、术语、缩略语3.技术框架3.1 架构框架3.2 分层功能4.基础组件4.1 基础层4.2 平台层4.3 应用层4.4 服务层4.5 交叉层5.安全计算参考过程6.技术和安全要求6.1 隔离要求6.2 互操作要求6.3 性能要求6.4 可用性要求6.5 数据安全要求6.6 密码学要求 1. 概述 随着…...
程序员编写文档的 10 个技巧
编写好的文档在软件开发领域具有重大意义。文档是概述特定问题陈述、方法、功能、工作流程、架构、挑战和开发过程的书面数据或指令。文档可以让你全面了解解决方案的功能、安装和配置。 文档不仅是为其他人编写的,也是为自己编写的。它让我们自己知道我们以前做过什…...
【ES问题总结】
文章目录 1、什么是ElasticSearch;2、ElasticSearch的基本概念;3、什么是倒排索引;4、DocValue的作用;5、text和keyword类型的区别;7、query和filter的区别;8、es写数据的过程;9、es的更新和删除流程&#…...
数据结构----结构--线性结构--顺序存储--数组
数据结构----结构–线性结构–顺序存储–数组 数组:类型相同,空间连续,长度固定 搜索: (1)基于索引搜索,时间复杂度O(1) (2)基于数值搜索: 1.有序的&…...
docker 启动kitex 的opentelemetry
https://github.com/cloudwego/kitex-examples/blob/main/opentelemetry/docker-compose.yaml 下载两个yaml文件:docker-compose.yaml otel-collector-config.yaml 在该目录下执行 docker-compose up -d...
Excel中——日期列后添加星期
需求:在日期列中添加星期几? 第一步:打开需要添加星期的Excel文件,在日期后面添加日期 第二步:选择日期列,点击鼠标右键,在下拉列表中,选择“设置单元格格式” 第三步: 在…...
谈谈DNS是什么?它的作用以及工作流程
作者:Insist-- 个人主页:insist--个人主页 作者会持续更新网络知识和python基础知识,期待你的关注 目录 一、DNS是什么? 二、DNS的作用 三、DNS查询流程 1、查看浏览器缓存 2、查看系统缓存 3、查看路由器缓存 4、查看ISP …...
Qt小项目贪吃蛇实线,主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等
Qt小项目贪吃蛇实线,主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等 Qt 贪吃蛇演示QWidget 绘制界面项目源文件 注释清晰widget.hwidget.cpp 拓展QTimerQKeyEventQRectFQPointFQPainterQIcon Qt 贪吃蛇演示 QWidget 绘制界面 项目源文件 注…...
使用HTTP隧道时如何应对目标网站的反爬虫监测?
在进行网络抓取时,我们常常会遇到目标网站对反爬虫的监测和封禁。为了规避这些风险,使用代理IP成为一种常见的方法。然而,如何应对目标网站的反爬虫监测,既能保证数据的稳定性,又能确保抓取过程的安全性呢?…...
怎么样通过Bootstrap已经编译好(压缩好)的源码去查看符合阅读习惯的源码【通过Source Map(源映射)文件实现】
阅读本篇博文前,建议大家先看看下面这篇博文: https://blog.csdn.net/wenhao_ir/article/details/132089650 Bootstrap经编译(压缩)后的源码百度网盘下载地址: https://pan.baidu.com/s/14BM9gpC3K-LKxhyLGh4J9Q?pwdm02m Bootstrap未经编译…...
【排序算法】python之冒泡,选择,插入,快速,归并
参考资料: 《Python实现5大排序算法》《六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序》 --代码似乎是C语言 ———————— 本文介绍5种常见的排序算法和基于Python实现: 冒泡排序(Bubble Sort&am…...
UML—用例图的那些事
目录 背景: 1.用例图的发展史 过程: 1.用例图中的元素和关系 2.应用中的例子 总结: 背景: 1.用例图的发展史 用例图是一种常用的软件工程工具,用于描述系统的功能需求和用户与系统的交互。它在软件开发过程中起到了重要的作用,并且经历了…...
迷宫出口问题求解(DFS)
题面 一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由 nn 的格点组成,每个格点只有 22 种状态, 00 和 11,前者表示可以通行后者表示不能通行。 同时当Extense处在某个格点时,他只能移动到东南西北…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
