update
26
README.md
@ -94,6 +94,12 @@ const mindMap = new MindMap({
|
||||
|
||||
群聊人数较多,无法通过二维码入群,可以微信添加`wanglinguanfang`拉你入群。
|
||||
|
||||
# star
|
||||
|
||||
如果喜欢本项目,欢迎点个star,这对我们很重要。
|
||||
|
||||
[](https://star-history.com/#wanglin2/mind-map&Date)
|
||||
|
||||
# 请作者喝杯咖啡
|
||||
|
||||
开源不易,如果本项目有帮助到你的话,可以考虑请作者喝杯咖啡~
|
||||
@ -272,4 +278,24 @@ const mindMap = new MindMap({
|
||||
<img src="./web/src/assets/avatar/慕智打印-兰兰.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>慕智打印-兰兰</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/default.png" style="width: 50px;height: 50px;" />
|
||||
<span>锦冰</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/旭东.png" style="width: 50px;height: 50px;" />
|
||||
<span>旭东</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/俊奇.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>俊奇</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/橘半.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>橘半</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/pluvet.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>pluvet</span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
1
copy.js
@ -13,3 +13,4 @@ if (fs.existsSync(src)) {
|
||||
fs.unlinkSync(src)
|
||||
}
|
||||
|
||||
console.warn('请检查手绘风格选项是否开启!!!')
|
||||
2
dist/css/app.css
vendored
BIN
dist/fonts/iconfont.ttf
vendored
BIN
dist/fonts/iconfont.woff
vendored
BIN
dist/fonts/iconfont.woff2
vendored
BIN
dist/img/pluvet.jpg
vendored
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
dist/img/俊奇.jpg
vendored
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
dist/img/橘半.jpg
vendored
Normal file
|
After Width: | Height: | Size: 34 KiB |
2
dist/js/app.js
vendored
1
dist/js/chunk-02258ed0.js
vendored
1
dist/js/chunk-2bf818d4.js
vendored
Normal file
2
dist/js/chunk-2d0aa978.js
vendored
2
dist/js/chunk-2d0c09f6.js
vendored
2
dist/js/chunk-2d0c0a44.js
vendored
2
dist/js/chunk-2d0d9fbc.js
vendored
2
dist/js/chunk-2d0dad5f.js
vendored
2
dist/js/chunk-2d0f026c.js
vendored
2
dist/js/chunk-2d0f0784.js
vendored
@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0f0784"],{"9d03":function(e,t,n){"use strict";n.r(t);var i=function(){var e=this;e._self._c;return e._m(0)},d=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("TextEdit instance")]),t("p",[e._v("Node text editing instance. It can be obtained through "),t("code",[e._v("mindMap.renderer.textEdit")]),e._v(".")]),t("h2",[e._v("Methods")]),t("h3",[e._v("isShowTextEdit()")]),t("p",[e._v("Get whether the current text editing box is in a display state, that is, whether it is in a text editing state.")]),t("h3",[e._v("hideEditTextBox()")]),t("p",[e._v("Hiding the text editing box will set the content of the current text editing box as node text.")]),t("h3",[e._v("registerTmpShortcut()")]),t("p",[e._v("Register temporary shortcut keys, which means editing can be completed through the Enter and Tab keys.")]),t("h3",[e._v("show({ node})")]),t("ul",[t("li",[t("code",[e._v("node")]),e._v(":Node instance to enter for editing")])]),t("p",[e._v("Manually enable node editing. By default, it will enter node editing when double clicking or pressing F2 on the node.")])])}],o={},h=o,r=n("2877"),s=Object(r["a"])(h,i,d,!1,null,null,null);t["default"]=s.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0f0784"],{"9d03":function(e,t,n){"use strict";n.r(t);var i=function(){var e=this;e._self._c;return e._m(0)},d=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("TextEdit instance")]),t("p",[e._v("Node text editing instance. It can be obtained through "),t("code",[e._v("mindMap.renderer.textEdit")]),e._v(".")]),t("h2",[e._v("Methods")]),t("h3",[e._v("isShowTextEdit()")]),t("p",[e._v("Get whether the current text editing box is in a display state, that is, whether it is in a text editing state.")]),t("h3",[e._v("hideEditTextBox()")]),t("p",[e._v("Hiding the text editing box will set the content of the current text editing box as node text.")]),t("h3",[e._v("registerTmpShortcut()")]),t("p",[e._v("Register temporary shortcut keys, which means editing can be completed through the Enter and Tab keys.")]),t("h3",[e._v("show({ node})")]),t("ul",[t("li",[t("code",[e._v("node")]),e._v(":Node instance to enter for editing")])]),t("p",[e._v("Manually enable node editing. By default, it will enter node editing when double clicking or pressing F2 on the node.")]),t("h3",[e._v("getCurrentEditNode()")]),t("blockquote",[t("p",[e._v("v0.9.8+")])]),t("p",[e._v("Get the node instance currently being edited.")])])}],o={},r=o,h=n("2877"),s=Object(h["a"])(r,i,d,!1,null,null,null);t["default"]=s.exports}}]);
|
||||
2
dist/js/chunk-2d208ffa.js
vendored
2
dist/js/chunk-2d216004.js
vendored
2
dist/js/chunk-2d216f87.js
vendored
@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d216f87"],{c576:function(e,t,n){"use strict";n.r(t);var _=function(){var e=this;e._self._c;return e._m(0)},v=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("TextEdit 实例")]),t("p",[e._v("节点文本编辑实例。可以通过"),t("code",[e._v("mindMap.renderer.textEdit")]),e._v("获取到。")]),t("h2",[e._v("方法")]),t("h3",[e._v("isShowTextEdit()")]),t("p",[e._v("获取当前文本编辑框是否处于显示状态,也就是是否处在文本编辑状态。")]),t("h3",[e._v("hideEditTextBox()")]),t("p",[e._v("隐藏文本编辑框,会将当前文本编辑框中的内容设置为节点文本。")]),t("h3",[e._v("registerTmpShortcut()")]),t("p",[e._v("注册临时快捷键,也就是可以通过 Enter 键和 Tab 键完成编辑。")]),t("h3",[e._v("show({ node})")]),t("ul",[t("li",[t("code",[e._v("node")]),e._v(":要进入编辑的节点实例")])]),t("p",[e._v("手动开启节点编辑。默认会在节点双击、按 F2 时进入节点编辑。")])])}],i={},r=i,d=n("2877"),o=Object(d["a"])(r,_,v,!1,null,null,null);t["default"]=o.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d216f87"],{c576:function(e,t,v){"use strict";v.r(t);var _=function(){var e=this;e._self._c;return e._m(0)},n=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("TextEdit 实例")]),t("p",[e._v("节点文本编辑实例。可以通过"),t("code",[e._v("mindMap.renderer.textEdit")]),e._v("获取到。")]),t("h2",[e._v("方法")]),t("h3",[e._v("isShowTextEdit()")]),t("p",[e._v("获取当前文本编辑框是否处于显示状态,也就是是否处在文本编辑状态。")]),t("h3",[e._v("hideEditTextBox()")]),t("p",[e._v("隐藏文本编辑框,会将当前文本编辑框中的内容设置为节点文本。")]),t("h3",[e._v("registerTmpShortcut()")]),t("p",[e._v("注册临时快捷键,也就是可以通过 Enter 键和 Tab 键完成编辑。")]),t("h3",[e._v("show({ node})")]),t("ul",[t("li",[t("code",[e._v("node")]),e._v(":要进入编辑的节点实例")])]),t("p",[e._v("手动开启节点编辑。默认会在节点双击、按 F2 时进入节点编辑。")]),t("h3",[e._v("getCurrentEditNode()")]),t("blockquote",[t("p",[e._v("v0.9.8+")])]),t("p",[e._v("获取当前正在编辑中的节点实例。")])])}],i={},o=i,r=v("2877"),d=Object(r["a"])(o,_,n,!1,null,null,null);t["default"]=d.exports}}]);
|
||||
2
dist/js/chunk-2d217907.js
vendored
1
dist/js/chunk-554d686c.js
vendored
Normal file
1
dist/js/chunk-792bedf8.js
vendored
@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link rel="icon" href="dist/logo.ico"><title>思绪思维导图</title><script>// 自定义静态资源的路径
|
||||
window.externalPublicPath = './dist/'
|
||||
// 接管应用
|
||||
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?c19e442932d6fe6a3e37" rel="stylesheet"><link href="dist/css/app.css?c19e442932d6fe6a3e37" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?97072371e55f8bd6a3b4" rel="stylesheet"><link href="dist/css/app.css?97072371e55f8bd6a3b4" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
@ -66,4 +66,4 @@
|
||||
// 可以通过window.$bus.$on()来监听应用的一些事件
|
||||
// 实例化页面
|
||||
window.initApp()
|
||||
}</script><script src="dist/js/chunk-vendors.js?c19e442932d6fe6a3e37"></script><script src="dist/js/app.js?c19e442932d6fe6a3e37"></script></body></html>
|
||||
}</script><script src="dist/js/chunk-vendors.js?97072371e55f8bd6a3b4"></script><script src="dist/js/app.js?97072371e55f8bd6a3b4"></script></body></html>
|
||||
|
||||
@ -28,7 +28,7 @@ MindMap.iconList = icons.nodeIconList
|
||||
MindMap.constants = constants
|
||||
MindMap.themes = themes
|
||||
MindMap.defaultTheme = defaultTheme
|
||||
MindMap.version = '0.9.6'
|
||||
MindMap.version = '0.9.8'
|
||||
|
||||
MindMap.usePlugin(MiniMap)
|
||||
.usePlugin(Watermark)
|
||||
|
||||
@ -31,6 +31,8 @@ class MindMap {
|
||||
constructor(opt = {}) {
|
||||
// 合并选项
|
||||
this.opt = this.handleOpt(merge(defaultOpt, opt))
|
||||
// 预处理节点数据
|
||||
this.opt.data = this.handleData(this.opt.data)
|
||||
|
||||
// 容器元素
|
||||
this.el = this.opt.el
|
||||
@ -39,6 +41,10 @@ class MindMap {
|
||||
// 获取容器尺寸位置信息
|
||||
this.getElRectInfo()
|
||||
|
||||
// 画布初始大小
|
||||
this.initWidth = this.width
|
||||
this.initHeight = this.height
|
||||
|
||||
// 添加css
|
||||
this.cssEl = null
|
||||
this.addCss()
|
||||
@ -94,8 +100,6 @@ class MindMap {
|
||||
|
||||
// 配置参数处理
|
||||
handleOpt(opt) {
|
||||
// 深拷贝一份节点数据
|
||||
opt.data = simpleDeepClone(opt.data || {})
|
||||
// 检查布局配置
|
||||
if (!layoutValueList.includes(opt.layout)) {
|
||||
opt.layout = CONSTANTS.LAYOUT.LOGICAL_STRUCTURE
|
||||
@ -105,6 +109,16 @@ class MindMap {
|
||||
return opt
|
||||
}
|
||||
|
||||
// 预处理节点数据
|
||||
handleData(data) {
|
||||
data = simpleDeepClone(data || {})
|
||||
// 根节点不能收起
|
||||
if (data.data && !data.data.expand) {
|
||||
data.data.expand = true
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// 创建容器元素
|
||||
initContainer() {
|
||||
const { associativeLineIsAlwaysAboveNode } = this.opt
|
||||
@ -304,7 +318,8 @@ class MindMap {
|
||||
|
||||
// 动态设置思维导图数据,纯节点数据
|
||||
setData(data) {
|
||||
data = simpleDeepClone(data || {})
|
||||
data = this.handleData(data)
|
||||
this.opt.data = data
|
||||
this.execCommand('CLEAR_ACTIVE_NODE')
|
||||
this.command.clearHistory()
|
||||
this.command.addHistory()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.9.6",
|
||||
"version": "0.9.8",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@ -346,7 +346,7 @@ export const cssContent = `
|
||||
display: block;
|
||||
}
|
||||
|
||||
.smm-node.active .smm-hover-node{
|
||||
.smm-node.active .smm-hover-node, .smm-node-highlight .smm-hover-node{
|
||||
display: block;
|
||||
opacity: 1;
|
||||
stroke-width: 2;
|
||||
|
||||
@ -275,5 +275,18 @@ export const defaultOpt = {
|
||||
customCreateNodePolygon: null,
|
||||
// 自定义转换节点连线路径的方法
|
||||
// 接收svg path字符串,返回转换后的svg path字符串
|
||||
customTransformNodeLinePath: null
|
||||
customTransformNodeLinePath: null,
|
||||
// 是否仅搜索当前渲染的节点,被收起的节点不会被搜索到
|
||||
isOnlySearchCurrentRenderNodes: false,
|
||||
// 协同编辑时,同一个节点不能同时被多人选中
|
||||
onlyOneEnableActiveNodeOnCooperate: false,
|
||||
// 协同编辑时,节点操作即将更新到其他客户端前的生命周期函数
|
||||
// 函数接收一个对象作为参数:
|
||||
/*
|
||||
{
|
||||
type: createOrUpdate(创建节点或更新节点)、delete(删除节点)
|
||||
data: 1.当type=createOrUpdate时,代表被创建或被更新的节点数据,即将同步到其他客户端,所以你可以修改该数据;2.当type=delete时,代表被删除的节点数据
|
||||
}
|
||||
*/
|
||||
beforeCooperateUpdate: null
|
||||
}
|
||||
|
||||
@ -28,7 +28,9 @@ import {
|
||||
parseAddGeneralizationNodeList,
|
||||
checkNodeListIsEqual,
|
||||
createSmmFormatData,
|
||||
checkSmmFormatData
|
||||
checkSmmFormatData,
|
||||
checkIsNodeStyleDataKey,
|
||||
removeRichTextStyes
|
||||
} from '../../utils'
|
||||
import { shapeList } from './node/Shape'
|
||||
import { lineStyleProps } from '../../themes/default'
|
||||
@ -271,6 +273,15 @@ class Render {
|
||||
// 定位节点
|
||||
this.goTargetNode = this.goTargetNode.bind(this)
|
||||
this.mindMap.command.add('GO_TARGET_NODE', this.goTargetNode)
|
||||
// 一键去除节点自定义样式
|
||||
this.removeCustomStyles = this.removeCustomStyles.bind(this)
|
||||
this.mindMap.command.add('REMOVE_CUSTOM_STYLES', this.removeCustomStyles)
|
||||
// 一键去除所有节点自定义样式
|
||||
this.removeAllNodeCustomStyles = this.removeAllNodeCustomStyles.bind(this)
|
||||
this.mindMap.command.add(
|
||||
'REMOVE_ALL_NODE_CUSTOM_STYLES',
|
||||
this.removeAllNodeCustomStyles
|
||||
)
|
||||
}
|
||||
|
||||
// 注册快捷键
|
||||
@ -494,6 +505,11 @@ class Render {
|
||||
|
||||
// 添加节点到激活列表里
|
||||
addNodeToActiveList(node) {
|
||||
if (
|
||||
this.mindMap.opt.onlyOneEnableActiveNodeOnCooperate &&
|
||||
node.userList.length > 0
|
||||
)
|
||||
return
|
||||
const index = this.findActiveNodeIndex(node)
|
||||
if (index === -1) {
|
||||
this.mindMap.execCommand('SET_NODE_ACTIVE', node, true)
|
||||
@ -638,7 +654,7 @@ class Render {
|
||||
uid: createUid(),
|
||||
...(appointData || {})
|
||||
},
|
||||
children: [...createUidForAppointNodes(appointChildren, true)]
|
||||
children: [...createUidForAppointNodes(appointChildren)]
|
||||
}
|
||||
parent.nodeData.children.splice(index + 1, 0, newNodeData)
|
||||
})
|
||||
@ -674,10 +690,7 @@ class Render {
|
||||
const parent = node.parent
|
||||
// 计算插入位置
|
||||
const index = getNodeDataIndex(node)
|
||||
const newNodeList = createUidForAppointNodes(
|
||||
simpleDeepClone(nodeList),
|
||||
true
|
||||
)
|
||||
const newNodeList = createUidForAppointNodes(simpleDeepClone(nodeList))
|
||||
parent.nodeData.children.splice(index + 1, 0, ...newNodeList)
|
||||
})
|
||||
if (focusNewNode) {
|
||||
@ -737,7 +750,7 @@ class Render {
|
||||
...params,
|
||||
...(appointData || {})
|
||||
},
|
||||
children: [...createUidForAppointNodes(appointChildren, true)]
|
||||
children: [...createUidForAppointNodes(appointChildren)]
|
||||
}
|
||||
node.nodeData.children.push(newNode)
|
||||
// 插入子节点时自动展开子节点
|
||||
@ -777,7 +790,7 @@ class Render {
|
||||
if (!node.nodeData.children) {
|
||||
node.nodeData.children = []
|
||||
}
|
||||
childList = createUidForAppointNodes(childList, true)
|
||||
childList = createUidForAppointNodes(childList)
|
||||
node.nodeData.children.push(...childList)
|
||||
// 插入子节点时自动展开子节点
|
||||
node.setData({
|
||||
@ -911,6 +924,65 @@ class Render {
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
// 移除节点数据的自定义样式的内部方法
|
||||
_handleRemoveCustomStyles(nodeData) {
|
||||
let hasCustomStyles = false
|
||||
Object.keys(nodeData).forEach(key => {
|
||||
if (checkIsNodeStyleDataKey(key)) {
|
||||
hasCustomStyles = true
|
||||
delete nodeData[key]
|
||||
}
|
||||
})
|
||||
// 如果是富文本,那么还要处理富文本内容
|
||||
if (hasCustomStyles && this.mindMap.richText) {
|
||||
nodeData.resetRichText = true
|
||||
nodeData.text = removeRichTextStyes(nodeData.text)
|
||||
}
|
||||
return hasCustomStyles
|
||||
}
|
||||
|
||||
// 一键去除自定义样式
|
||||
removeCustomStyles(node) {
|
||||
node = node || this.activeNodeList[0]
|
||||
if (!node) {
|
||||
return
|
||||
}
|
||||
const hasCustomStyles = this._handleRemoveCustomStyles(node.getData())
|
||||
if (hasCustomStyles) {
|
||||
this.reRenderNodeCheckChange(node)
|
||||
}
|
||||
}
|
||||
|
||||
// 一键去除所有节点自定义样式
|
||||
removeAllNodeCustomStyles(appointNodes) {
|
||||
appointNodes = formatDataToArray(appointNodes)
|
||||
let hasCustomStyles = false
|
||||
// 指定了节点列表,那么遍历该节点列表
|
||||
if (appointNodes.length > 0) {
|
||||
appointNodes.forEach(node => {
|
||||
const _hasCustomStyles = this._handleRemoveCustomStyles(node.getData())
|
||||
if (_hasCustomStyles) hasCustomStyles = true
|
||||
})
|
||||
} else {
|
||||
// 否则遍历整棵树
|
||||
walk(this.renderTree, null, node => {
|
||||
const _hasCustomStyles = this._handleRemoveCustomStyles(node.data)
|
||||
if (_hasCustomStyles) hasCustomStyles = true
|
||||
// 不要忘记概要节点
|
||||
if (node.data.generalization && node.data.generalization.length > 0) {
|
||||
node.data.generalization.forEach(generalizationData => {
|
||||
const _hasCustomStyles =
|
||||
this._handleRemoveCustomStyles(generalizationData)
|
||||
if (_hasCustomStyles) hasCustomStyles = true
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
if (hasCustomStyles) {
|
||||
this.mindMap.reRender()
|
||||
}
|
||||
}
|
||||
|
||||
// 复制节点
|
||||
copy() {
|
||||
this.beingCopyData = this.copyNode()
|
||||
@ -1146,7 +1218,15 @@ class Render {
|
||||
// 如果只选中了一个节点,删除后激活其兄弟节点或者父节点
|
||||
needActiveNode = this.getNextActiveNode()
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
let node = list[i]
|
||||
const node = list[i]
|
||||
const currentEditNode = this.textEdit.getCurrentEditNode()
|
||||
if (
|
||||
currentEditNode &&
|
||||
currentEditNode.getData('uid') === node.getData('uid')
|
||||
) {
|
||||
// 如果当前节点正在编辑中,那么先完成编辑
|
||||
this.textEdit.hideEditTextBox()
|
||||
}
|
||||
if (isAppointNodes) list.splice(i, 1)
|
||||
if (node.isGeneralization) {
|
||||
this.deleteNodeGeneralization(node)
|
||||
@ -1538,7 +1618,8 @@ class Render {
|
||||
...(data || {
|
||||
text: this.mindMap.opt.defaultGeneralizationText
|
||||
}),
|
||||
range: item.range || null
|
||||
range: item.range || null,
|
||||
uid: createUid()
|
||||
}
|
||||
let generalization = item.node.getData('generalization')
|
||||
if (generalization) {
|
||||
@ -1634,7 +1715,7 @@ class Render {
|
||||
if (targetNode) {
|
||||
targetNode.active()
|
||||
this.moveNodeToCenter(targetNode)
|
||||
callback()
|
||||
callback(targetNode)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1649,6 +1730,11 @@ class Render {
|
||||
// 设置节点数据,并判断是否渲染
|
||||
setNodeDataRender(node, data, notRender = false) {
|
||||
this.mindMap.execCommand('SET_NODE_DATA', node, data)
|
||||
this.reRenderNodeCheckChange(node, notRender)
|
||||
}
|
||||
|
||||
// 重新节点某个节点,判断节点大小是否发生了改变,是的话触发重绘
|
||||
reRenderNodeCheckChange(node, notRender) {
|
||||
let changed = node.reRender()
|
||||
if (changed) {
|
||||
if (!notRender) this.mindMap.render()
|
||||
|
||||
@ -315,4 +315,12 @@ export default class TextEdit {
|
||||
this.textEditNode.style.transform = 'translateY(0)'
|
||||
this.showTextEdit = false
|
||||
}
|
||||
|
||||
// 获取当前正在编辑中的节点实例
|
||||
getCurrentEditNode() {
|
||||
if (this.mindMap.richText) {
|
||||
return this.mindMap.richText.node
|
||||
}
|
||||
return this.currentNode
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,6 +203,8 @@ class Node {
|
||||
|
||||
// 计算节点的宽高
|
||||
getSize() {
|
||||
this.customLeft = this.getData('customLeft') || undefined
|
||||
this.customTop = this.getData('customTop') || undefined
|
||||
this.updateGeneralization()
|
||||
this.createNodeData()
|
||||
let { width, height } = this.getNodeRect()
|
||||
@ -420,6 +422,12 @@ class Node {
|
||||
this.isMultipleChoice = false
|
||||
return
|
||||
}
|
||||
if (
|
||||
this.mindMap.opt.onlyOneEnableActiveNodeOnCooperate &&
|
||||
this.userList.length > 0
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.active(e)
|
||||
})
|
||||
this.group.on('mousedown', e => {
|
||||
@ -486,10 +494,14 @@ class Node {
|
||||
})
|
||||
// 双击事件
|
||||
this.group.on('dblclick', e => {
|
||||
if (this.mindMap.opt.readonly || e.ctrlKey) {
|
||||
const { readonly, onlyOneEnableActiveNodeOnCooperate } = this.mindMap.opt
|
||||
if (readonly || e.ctrlKey) {
|
||||
return
|
||||
}
|
||||
e.stopPropagation()
|
||||
if (onlyOneEnableActiveNodeOnCooperate && this.userList.length > 0) {
|
||||
return
|
||||
}
|
||||
this.mindMap.emit('node_dblclick', this, e)
|
||||
})
|
||||
// 右键菜单事件
|
||||
@ -705,6 +717,9 @@ class Node {
|
||||
// 销毁节点,不但会从画布删除,而且原节点直接置空,后续无法再插回画布
|
||||
destroy() {
|
||||
if (!this.group) return
|
||||
if (this.emptyUser) {
|
||||
this.emptyUser()
|
||||
}
|
||||
this.resetWhenDelete()
|
||||
this.group.remove()
|
||||
this.removeGeneralization()
|
||||
@ -1052,6 +1067,16 @@ class Node {
|
||||
height: height * scaleY
|
||||
}
|
||||
}
|
||||
|
||||
// 高亮节点
|
||||
highlight() {
|
||||
if (this.group) this.group.addClass('smm-node-highlight')
|
||||
}
|
||||
|
||||
// 取消高亮节点
|
||||
closeHighlight() {
|
||||
if (this.group) this.group.removeClass('smm-node-highlight')
|
||||
}
|
||||
}
|
||||
|
||||
export default Node
|
||||
|
||||
@ -94,11 +94,18 @@ function removeUser(userInfo) {
|
||||
this.updateUserListNode()
|
||||
}
|
||||
|
||||
// 清空用户
|
||||
function emptyUser() {
|
||||
this.userList = []
|
||||
this.updateUserListNode()
|
||||
}
|
||||
|
||||
export default {
|
||||
createUserListNode,
|
||||
updateUserListNode,
|
||||
createTextAvatar,
|
||||
createImageAvatar,
|
||||
addUser,
|
||||
removeUser
|
||||
removeUser,
|
||||
emptyUser
|
||||
}
|
||||
|
||||
@ -128,6 +128,10 @@ class View {
|
||||
this.translateXY(mx, my)
|
||||
}
|
||||
})
|
||||
this.mindMap.on('resize', () => {
|
||||
if (!this.checkNeedMindMapInCanvas()) return
|
||||
this.transform()
|
||||
})
|
||||
}
|
||||
|
||||
// 获取当前变换状态数据
|
||||
@ -313,20 +317,31 @@ class View {
|
||||
this.translateXY(newX, newY)
|
||||
}
|
||||
|
||||
// 将思维导图限制在画布内
|
||||
limitMindMapInCanvas() {
|
||||
// 判断是否需要将思维导图限制在画布内
|
||||
checkNeedMindMapInCanvas() {
|
||||
const { isLimitMindMapInCanvasWhenHasScrollbar, isLimitMindMapInCanvas } =
|
||||
this.mindMap.opt
|
||||
// 如果注册了滚动条插件,那么使用isLimitMindMapInCanvasWhenHasScrollbar配置
|
||||
if (this.mindMap.scrollbar) {
|
||||
if (!isLimitMindMapInCanvasWhenHasScrollbar) return
|
||||
return isLimitMindMapInCanvasWhenHasScrollbar
|
||||
} else {
|
||||
// 否则使用isLimitMindMapInCanvas配置
|
||||
if (!isLimitMindMapInCanvas) return
|
||||
return isLimitMindMapInCanvas
|
||||
}
|
||||
}
|
||||
|
||||
// 将思维导图限制在画布内
|
||||
limitMindMapInCanvas() {
|
||||
if (!this.checkNeedMindMapInCanvas()) return
|
||||
|
||||
let { scale, left, top, right, bottom } = this.getPositionLimit()
|
||||
|
||||
// 画布宽高改变了,但是思维导图元素变换的中心点依旧是原有位置,所以需要加上中心点变化量
|
||||
const centerXChange =
|
||||
((this.mindMap.width - this.mindMap.initWidth) / 2) * scale
|
||||
const centerYChange =
|
||||
((this.mindMap.height - this.mindMap.initHeight) / 2) * scale
|
||||
|
||||
// 如果缩放值改变了
|
||||
const scaleRatio = this.scale / scale
|
||||
left *= scaleRatio
|
||||
@ -338,10 +353,10 @@ class View {
|
||||
const centerX = this.mindMap.width / 2
|
||||
const centerY = this.mindMap.height / 2
|
||||
const scaleOffset = this.scale - 1
|
||||
left -= scaleOffset * centerX
|
||||
right -= scaleOffset * centerX
|
||||
top -= scaleOffset * centerY
|
||||
bottom -= scaleOffset * centerY
|
||||
left -= scaleOffset * centerX - centerXChange
|
||||
right -= scaleOffset * centerX - centerXChange
|
||||
top -= scaleOffset * centerY - centerYChange
|
||||
bottom -= scaleOffset * centerY - centerYChange
|
||||
|
||||
// 判断是否超出边界
|
||||
if (this.x > left) {
|
||||
|
||||
@ -1,12 +1,7 @@
|
||||
import { walk } from '../utils'
|
||||
import { walk, nodeRichTextToTextWithWrap } from '../utils'
|
||||
|
||||
let el = null
|
||||
const getText = str => {
|
||||
if (!el) {
|
||||
el = document.createElement('div')
|
||||
}
|
||||
el.innerHTML = str
|
||||
return el.textContent
|
||||
const getNodeText = data => {
|
||||
return data.richText ? nodeRichTextToTextWithWrap(data.text) : data.text
|
||||
}
|
||||
|
||||
const getTitleMark = level => {
|
||||
@ -24,21 +19,22 @@ export const transformToMarkdown = root => {
|
||||
root,
|
||||
null,
|
||||
(node, parent, isRoot, layerIndex) => {
|
||||
let level = layerIndex + 1
|
||||
let text = node.data.richText ? getText(node.data.text) : node.data.text
|
||||
const level = layerIndex + 1
|
||||
if (level <= 6) {
|
||||
content += getTitleMark(level)
|
||||
} else {
|
||||
content += getIndentMark(level)
|
||||
}
|
||||
content += ' ' + text
|
||||
content += ' ' + getNodeText(node.data)
|
||||
// 概要
|
||||
let generalization = node.data.generalization
|
||||
if (generalization && generalization.text) {
|
||||
let generalizationText = generalization.richText
|
||||
? getText(generalization.text)
|
||||
: generalization.text
|
||||
content += `[${generalizationText}]`
|
||||
const generalization = node.data.generalization
|
||||
if (Array.isArray(generalization)) {
|
||||
content += generalization.map(item => {
|
||||
return ` [${getNodeText(item)}]`
|
||||
})
|
||||
} else if (generalization && generalization.text) {
|
||||
const generalizationText = getNodeText(generalization)
|
||||
content += ` [${generalizationText}]`
|
||||
}
|
||||
content += '\n\n'
|
||||
// 备注
|
||||
|
||||
35
simple-mind-map/src/parse/toTxt.js
Normal file
@ -0,0 +1,35 @@
|
||||
import { walk, nodeRichTextToTextWithWrap } from '../utils'
|
||||
|
||||
const getNodeText = data => {
|
||||
return data.richText ? nodeRichTextToTextWithWrap(data.text) : data.text
|
||||
}
|
||||
|
||||
const getIndent = level => {
|
||||
return new Array(level).fill(' ').join('')
|
||||
}
|
||||
|
||||
// 转换成txt格式
|
||||
export const transformToTxt = root => {
|
||||
let content = ''
|
||||
walk(
|
||||
root,
|
||||
null,
|
||||
(node, parent, isRoot, layerIndex) => {
|
||||
content += getIndent(layerIndex)
|
||||
content += ' ' + getNodeText(node.data)
|
||||
// 概要
|
||||
const generalization = node.data.generalization
|
||||
if (Array.isArray(generalization)) {
|
||||
content += generalization.map(item => {
|
||||
return ` [${getNodeText(item)}]`
|
||||
})
|
||||
} else if (generalization && generalization.text) {
|
||||
content += ` [${getNodeText(generalization)}]`
|
||||
}
|
||||
content += '\n\n'
|
||||
},
|
||||
() => {},
|
||||
true
|
||||
)
|
||||
return content
|
||||
}
|
||||
@ -198,7 +198,7 @@ const transformOldXmind = content => {
|
||||
childrenItem.elements.length > 0
|
||||
) {
|
||||
const children = getElementsByType(childrenItem.elements, 'attached')
|
||||
children.forEach((item, index) => {
|
||||
;(children || []).forEach((item, index) => {
|
||||
const newChild = {}
|
||||
newNode.children.push(newChild)
|
||||
if (childrenSummary[index]) {
|
||||
|
||||
@ -28,6 +28,8 @@ class Cooperate {
|
||||
this.currentData = null
|
||||
// 用户信息
|
||||
this.userInfo = null
|
||||
// 是否正在重新设置思维导图数据
|
||||
this.isSetData = false
|
||||
// 绑定事件
|
||||
this.bindEvent()
|
||||
// 处理实例化时传入的思维导图数据
|
||||
@ -92,8 +94,8 @@ class Cooperate {
|
||||
this.mindMap.on('node_tree_render_end', this.onNodeTreeRenderEnd)
|
||||
|
||||
// 监听设置思维导图数据事件
|
||||
this.initData = this.initData.bind(this)
|
||||
this.mindMap.on('set_data', this.initData)
|
||||
this.onSetData = this.onSetData.bind(this)
|
||||
this.mindMap.on('set_data', this.onSetData)
|
||||
}
|
||||
|
||||
// 解绑事件
|
||||
@ -104,7 +106,7 @@ class Cooperate {
|
||||
this.mindMap.off('data_change', this.onDataChange)
|
||||
this.mindMap.off('node_active', this.onNodeActive)
|
||||
this.mindMap.off('node_tree_render_end', this.onNodeTreeRenderEnd)
|
||||
this.mindMap.off('set_data', this.initData)
|
||||
this.mindMap.off('set_data', this.onSetData)
|
||||
this.ydoc.destroy()
|
||||
}
|
||||
|
||||
@ -125,28 +127,58 @@ class Cooperate {
|
||||
|
||||
// 当前思维导图改变后的处理,触发同步
|
||||
onDataChange(data) {
|
||||
if (this.isSetData) {
|
||||
this.isSetData = false
|
||||
return
|
||||
}
|
||||
const res = transformTreeDataToObject(data)
|
||||
this.updateChanges(res)
|
||||
}
|
||||
|
||||
// 找出更新点
|
||||
updateChanges(data) {
|
||||
const { beforeCooperateUpdate } = this.mindMap.opt
|
||||
const oldData = this.currentData
|
||||
this.currentData = data
|
||||
this.ydoc.transact(() => {
|
||||
// 找出新增的或修改的
|
||||
const createOrUpdateList = []
|
||||
Object.keys(data).forEach(uid => {
|
||||
// 新增的或已经存在的,如果数据发生了改变
|
||||
if (!oldData[uid] || !isSameObject(oldData[uid], data[uid])) {
|
||||
this.ymap.set(uid, data[uid])
|
||||
createOrUpdateList.push({
|
||||
uid,
|
||||
data: data[uid],
|
||||
oldData: oldData[uid]
|
||||
})
|
||||
}
|
||||
})
|
||||
if (beforeCooperateUpdate && createOrUpdateList.length > 0) {
|
||||
beforeCooperateUpdate({
|
||||
type: 'createOrUpdate',
|
||||
list: createOrUpdateList,
|
||||
data
|
||||
})
|
||||
}
|
||||
createOrUpdateList.forEach(item => {
|
||||
this.ymap.set(item.uid, item.data)
|
||||
})
|
||||
// 找出删除的
|
||||
const deleteList = []
|
||||
Object.keys(oldData).forEach(uid => {
|
||||
if (!data[uid]) {
|
||||
this.ymap.delete(uid)
|
||||
deleteList.push({ uid, data: oldData[uid] })
|
||||
}
|
||||
})
|
||||
if (beforeCooperateUpdate && deleteList.length > 0) {
|
||||
beforeCooperateUpdate({
|
||||
type: 'delete',
|
||||
list: deleteList
|
||||
})
|
||||
}
|
||||
deleteList.forEach(item => {
|
||||
this.ymap.delete(item.uid)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -177,6 +209,12 @@ class Cooperate {
|
||||
this.waitNodeUidMap = {}
|
||||
}
|
||||
|
||||
// 监听思维导图数据的重新设置事件
|
||||
onSetData(data) {
|
||||
this.isSetData = true
|
||||
this.initData(data)
|
||||
}
|
||||
|
||||
// 设置用户信息
|
||||
/**
|
||||
* {
|
||||
@ -220,6 +258,7 @@ class Cooperate {
|
||||
// 设置当前数据
|
||||
const data = Array.from(this.awareness.getStates().values())
|
||||
this.currentAwarenessData = data
|
||||
this.waitNodeUidMap = {}
|
||||
walk(data, (uid, node, userInfo) => {
|
||||
// 不显示自己
|
||||
if (userInfo.id === this.userInfo.id) return
|
||||
|
||||
@ -10,6 +10,7 @@ import { SVG } from '@svgdotjs/svg.js'
|
||||
import drawBackgroundImageToCanvas from '../utils/simulateCSSBackgroundInCanvas'
|
||||
import { transformToMarkdown } from '../parse/toMarkdown'
|
||||
import { ERROR_TYPES } from '../constants/constant'
|
||||
import { transformToTxt } from '../parse/toTxt'
|
||||
|
||||
// 导出插件
|
||||
class Export {
|
||||
@ -294,6 +295,15 @@ class Export {
|
||||
const res = await readBlob(blob)
|
||||
return res
|
||||
}
|
||||
|
||||
// txt文件
|
||||
async txt() {
|
||||
const data = this.mindMap.getData()
|
||||
const content = transformToTxt(data)
|
||||
const blob = new Blob([content])
|
||||
const res = await readBlob(blob)
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
Export.instanceName = 'doExport'
|
||||
|
||||
@ -326,10 +326,10 @@ class RichText {
|
||||
nodes && nodes.length > 0 ? nodes : this.mindMap.renderer.activeNodeList
|
||||
list.forEach(node => {
|
||||
this.mindMap.execCommand('SET_NODE_TEXT', node, html, true)
|
||||
if (node.isGeneralization) {
|
||||
// if (node.isGeneralization) {
|
||||
// 概要节点
|
||||
node.generalizationBelongNode.updateGeneralization()
|
||||
}
|
||||
// node.generalizationBelongNode.updateGeneralization()
|
||||
// }
|
||||
this.mindMap.render()
|
||||
})
|
||||
this.mindMap.emit('hide_text_edit', this.textEditNode, list)
|
||||
|
||||
@ -40,6 +40,7 @@ class Scrollbar {
|
||||
this.mindMap.on('mouseup', this.onMouseup)
|
||||
this.mindMap.on('node_tree_render_end', this.updateScrollbar)
|
||||
this.mindMap.on('view_data_change', this.updateScrollbar)
|
||||
this.mindMap.on('resize', this.updateScrollbar)
|
||||
}
|
||||
|
||||
// 解绑事件
|
||||
@ -48,6 +49,7 @@ class Scrollbar {
|
||||
this.mindMap.off('mouseup', this.onMouseup)
|
||||
this.mindMap.off('node_tree_render_end', this.updateScrollbar)
|
||||
this.mindMap.off('view_data_change', this.updateScrollbar)
|
||||
this.mindMap.off('resize', this.updateScrollbar)
|
||||
}
|
||||
|
||||
// 渲染后、数据改变需要更新滚动条
|
||||
@ -202,7 +204,8 @@ class Scrollbar {
|
||||
yOffset -
|
||||
paddingY * t.scaleY +
|
||||
paddingY -
|
||||
rootCenterOffset.y * t.scaleY
|
||||
rootCenterOffset.y * t.scaleY +
|
||||
((this.mindMap.height - this.mindMap.initHeight) / 2) * t.scaleY // 画布宽高改变了,但是思维导图元素变换的中心点依旧是原有位置,所以需要加上中心点变化量
|
||||
this.mindMap.view.translateYTo(chartTop)
|
||||
this.emitEvent({
|
||||
horizontal: scrollbarData.horizontal,
|
||||
@ -238,7 +241,8 @@ class Scrollbar {
|
||||
xOffset -
|
||||
paddingX * t.scaleX +
|
||||
paddingX -
|
||||
rootCenterOffset.x * t.scaleX
|
||||
rootCenterOffset.x * t.scaleX +
|
||||
((this.mindMap.width - this.mindMap.initWidth) / 2) * t.scaleX // 画布宽高改变了,但是思维导图元素变换的中心点依旧是原有位置,所以需要加上中心点变化量
|
||||
this.mindMap.view.translateXTo(chartLeft)
|
||||
this.emitEvent({
|
||||
vertical: scrollbarData.vertical,
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
isUndef,
|
||||
replaceHtmlText
|
||||
} from '../utils/index'
|
||||
import Node from '../core/render/node/Node'
|
||||
|
||||
// 搜索插件
|
||||
class Search {
|
||||
@ -69,14 +70,14 @@ class Search {
|
||||
// 结束搜索
|
||||
endSearch() {
|
||||
if (!this.isSearching) return
|
||||
if (this.mindMap.opt.readonly && this.matchNodeList[this.currentIndex]) {
|
||||
this.matchNodeList[this.currentIndex].closeHighlight()
|
||||
}
|
||||
this.searchText = ''
|
||||
this.matchNodeList = []
|
||||
this.currentIndex = -1
|
||||
this.notResetSearchText = false
|
||||
this.isSearching = false
|
||||
if (this.mindMap.opt.readonly) {
|
||||
this.mindMap.renderer.closeHighlightNode()
|
||||
}
|
||||
this.emitEvent()
|
||||
}
|
||||
|
||||
@ -84,8 +85,14 @@ class Search {
|
||||
doSearch() {
|
||||
this.matchNodeList = []
|
||||
this.currentIndex = -1
|
||||
bfsWalk(this.mindMap.renderer.root, node => {
|
||||
let { richText, text } = node.getData()
|
||||
const { isOnlySearchCurrentRenderNodes } = this.mindMap.opt
|
||||
const tree = isOnlySearchCurrentRenderNodes
|
||||
? this.mindMap.renderer.root
|
||||
: this.mindMap.renderer.renderTree
|
||||
bfsWalk(tree, node => {
|
||||
let { richText, text } = isOnlySearchCurrentRenderNodes
|
||||
? node.getData()
|
||||
: node.data
|
||||
if (richText) {
|
||||
text = getTextFromHtml(text)
|
||||
}
|
||||
@ -103,14 +110,25 @@ class Search {
|
||||
} else {
|
||||
this.currentIndex = 0
|
||||
}
|
||||
let currentNode = this.matchNodeList[this.currentIndex]
|
||||
const currentNode = this.matchNodeList[this.currentIndex]
|
||||
this.notResetSearchText = true
|
||||
this.mindMap.execCommand('GO_TARGET_NODE', currentNode, () => {
|
||||
this.notResetSearchText = false
|
||||
const uid =
|
||||
currentNode instanceof Node
|
||||
? currentNode.getData('uid')
|
||||
: currentNode.data.uid
|
||||
const targetNode = this.mindMap.renderer.findNodeByUid(uid)
|
||||
this.mindMap.execCommand('GO_TARGET_NODE', uid, node => {
|
||||
if (!(currentNode instanceof Node)) {
|
||||
this.matchNodeList[this.currentIndex] = node
|
||||
}
|
||||
callback()
|
||||
// 只读模式下节点无法激活,所以通过高亮的方式
|
||||
if (this.mindMap.opt.readonly) {
|
||||
this.mindMap.renderer.highlightNode(currentNode)
|
||||
node.highlight()
|
||||
}
|
||||
// 如果当前节点实例已经存在,则不会触发data_change事件,那么需要手动把标志复位
|
||||
if (targetNode) {
|
||||
this.notResetSearchText = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
selfCloseTagList
|
||||
} from '../constants/constant'
|
||||
import MersenneTwister from './mersenneTwister'
|
||||
|
||||
// 深度优先遍历树
|
||||
export const walk = (
|
||||
root,
|
||||
@ -688,6 +689,52 @@ export const textToNodeRichTextWithWrap = html => {
|
||||
.join('')
|
||||
}
|
||||
|
||||
// 去除富文本内容的样式,包括样式标签,比如strong、em、s等
|
||||
// 但要保留数学公式内容
|
||||
let removeRichTextStyesEl = null
|
||||
export const removeRichTextStyes = html => {
|
||||
if (!removeRichTextStyesEl) {
|
||||
removeRichTextStyesEl = document.createElement('div')
|
||||
}
|
||||
removeRichTextStyesEl.innerHTML = html
|
||||
// 首先用占位文本替换掉所有的公式
|
||||
const formulaList = removeRichTextStyesEl.querySelectorAll('.ql-formula')
|
||||
Array.from(formulaList).forEach(el => {
|
||||
const placeholder = document.createTextNode('$smmformula$')
|
||||
el.parentNode.replaceChild(placeholder, el)
|
||||
})
|
||||
// 然后遍历每行节点,去掉内部的所有标签,转为文本
|
||||
const childNodes = removeRichTextStyesEl.childNodes
|
||||
let list = []
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const node = childNodes[i]
|
||||
if (node.nodeType === 1) {
|
||||
// 元素节点
|
||||
list.push(node.textContent)
|
||||
} else if (node.nodeType === 3) {
|
||||
// 文本节点
|
||||
list.push(node.nodeValue)
|
||||
}
|
||||
}
|
||||
// 拼接文本
|
||||
html = list
|
||||
.map(item => {
|
||||
return `<p><span>${htmlEscape(item)}</span></p>`
|
||||
})
|
||||
.join('')
|
||||
// 将公式添加回去
|
||||
if (formulaList.length > 0) {
|
||||
html = html.replace(/\$smmformula\$/g, '<span class="smmformula"></span>')
|
||||
removeRichTextStyesEl.innerHTML = html
|
||||
const els = removeRichTextStyesEl.querySelectorAll('.smmformula')
|
||||
Array.from(els).forEach((el, index) => {
|
||||
el.parentNode.replaceChild(formulaList[index], el)
|
||||
})
|
||||
html = removeRichTextStyesEl.innerHTML
|
||||
}
|
||||
return html
|
||||
}
|
||||
|
||||
// 判断是否是移动端环境
|
||||
export const isMobile = () => {
|
||||
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
||||
|
||||
@ -8,4 +8,4 @@ content = content.replace(
|
||||
/(MindMap.version\s*=\s*)[^\n]+(\n)/,
|
||||
`$1'${pkg.version}'$2`
|
||||
)
|
||||
fs.writeFileSync(file, content)
|
||||
fs.writeFileSync(file, content)
|
||||
BIN
web/src/assets/avatar/pluvet.jpg
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
web/src/assets/avatar/俊奇.jpg
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
web/src/assets/avatar/旭东.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
web/src/assets/avatar/橘半.jpg
Normal file
|
After Width: | Height: | Size: 34 KiB |
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2479351 */
|
||||
src: url('iconfont.woff2?t=1697073602349') format('woff2'),
|
||||
url('iconfont.woff?t=1697073602349') format('woff'),
|
||||
url('iconfont.ttf?t=1697073602349') format('truetype');
|
||||
src: url('iconfont.woff2?t=1709781789605') format('woff2'),
|
||||
url('iconfont.woff?t=1709781789605') format('woff'),
|
||||
url('iconfont.ttf?t=1709781789605') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,14 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconTXT:before {
|
||||
content: "\e6e1";
|
||||
}
|
||||
|
||||
.iconwenjian1:before {
|
||||
content: "\e69f";
|
||||
}
|
||||
|
||||
.icondodeparent:before {
|
||||
content: "\e70f";
|
||||
}
|
||||
|
||||
@ -480,5 +480,11 @@ export const downTypeList = [
|
||||
type: 'xmind',
|
||||
icon: 'iconxmind',
|
||||
desc: 'XMind file'
|
||||
},
|
||||
{
|
||||
name: 'Txt',
|
||||
type: 'txt',
|
||||
icon: 'iconTXT',
|
||||
desc: 'Plain text file'
|
||||
}
|
||||
]
|
||||
@ -575,5 +575,11 @@ export const downTypeList = [
|
||||
type: 'xmind',
|
||||
icon: 'iconxmind',
|
||||
desc: 'XMind格式'
|
||||
},
|
||||
{
|
||||
name: 'Txt',
|
||||
type: 'txt',
|
||||
icon: 'iconTXT',
|
||||
desc: '纯文本文件'
|
||||
}
|
||||
]
|
||||
|
||||
@ -84,6 +84,14 @@ export const bindFileHandleEvent = ({ mainWindow, initOpenFileQueue }) => {
|
||||
|
||||
// 打开文件
|
||||
const openFile = (event, file) => {
|
||||
// 检查文件是否存在
|
||||
const exist = fs.existsSync(file)
|
||||
if (!exist) {
|
||||
removeFileInRecent(file).then(() => {
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
})
|
||||
return '文件不存在'
|
||||
}
|
||||
let id = uuid()
|
||||
idToFilePath[id] = file
|
||||
saveToRecent(file).then(() => {
|
||||
@ -91,7 +99,7 @@ export const bindFileHandleEvent = ({ mainWindow, initOpenFileQueue }) => {
|
||||
})
|
||||
createEditWindow(null, id)
|
||||
}
|
||||
ipcMain.on('openFile', openFile)
|
||||
ipcMain.handle('openFile', openFile)
|
||||
|
||||
// 选择打开本地文件
|
||||
ipcMain.on('selectOpenFile', event => {
|
||||
@ -171,15 +179,22 @@ export const bindFileHandleEvent = ({ mainWindow, initOpenFileQueue }) => {
|
||||
// 添加到最近文件列表
|
||||
ipcMain.handle('addRecentFileList', async (event, fileList) => {
|
||||
try {
|
||||
await saveFileListToRecent(fileList)
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
await saveFileListToRecent(fileList)
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
} catch (error) {
|
||||
return error
|
||||
}
|
||||
return error
|
||||
}
|
||||
})
|
||||
|
||||
// 打开指定目录
|
||||
ipcMain.on('openFileInDir', (event, file) => {
|
||||
ipcMain.handle('openFileInDir', (event, file) => {
|
||||
const exist = fs.existsSync(file)
|
||||
if (!exist) {
|
||||
removeFileInRecent(file).then(() => {
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
})
|
||||
return '文件不存在'
|
||||
}
|
||||
shell.showItemInFolder(file)
|
||||
})
|
||||
|
||||
@ -211,7 +226,10 @@ export const bindFileHandleEvent = ({ mainWindow, initOpenFileQueue }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.pathExists(file, (err, exists) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
removeFileInRecent(file).then(() => {
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
})
|
||||
resolve('文件不存在')
|
||||
} else {
|
||||
if (exists) {
|
||||
let { base, ...oldPathData } = path.parse(file)
|
||||
@ -227,7 +245,7 @@ export const bindFileHandleEvent = ({ mainWindow, initOpenFileQueue }) => {
|
||||
}
|
||||
fs.copy(file, newPath, err => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
resolve('复制出错')
|
||||
} else {
|
||||
saveToRecent(newPath).then(() => {
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
@ -236,7 +254,10 @@ export const bindFileHandleEvent = ({ mainWindow, initOpenFileQueue }) => {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
reject('文件不存在')
|
||||
removeFileInRecent(file).then(() => {
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
})
|
||||
resolve('文件不存在')
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -244,7 +265,7 @@ export const bindFileHandleEvent = ({ mainWindow, initOpenFileQueue }) => {
|
||||
})
|
||||
|
||||
// 直接双击文件打开应用时,需要直接打开该文件编辑
|
||||
initOpenFileQueue.forEach((file) => {
|
||||
initOpenFileQueue.forEach(file => {
|
||||
openFile(null, file)
|
||||
})
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
addRecentFileList: (fileList) => ipcRenderer.invoke('addRecentFileList', fileList),
|
||||
getRecentFileList: () => ipcRenderer.invoke('getRecentFileList'),
|
||||
clearRecentFileList: () => ipcRenderer.invoke('clearRecentFileList'),
|
||||
openFileInDir: file => ipcRenderer.send('openFileInDir', file),
|
||||
openFileInDir: file => ipcRenderer.invoke('openFileInDir', file),
|
||||
deleteFile: file => ipcRenderer.invoke('deleteFile', file),
|
||||
onRefreshRecentFileList: callback =>
|
||||
ipcRenderer.on('refreshRecentFileList', callback),
|
||||
openFile: file => ipcRenderer.send('openFile', file),
|
||||
openFile: file => ipcRenderer.invoke('openFile', file),
|
||||
selectOpenFile: () => ipcRenderer.send('selectOpenFile'),
|
||||
copyFile: file => ipcRenderer.invoke('copyFile', file)
|
||||
})
|
||||
|
||||
@ -95,7 +95,9 @@ export default {
|
||||
create: 'Create new file',
|
||||
removeImage: 'Remove image',
|
||||
removeHyperlink: 'Remove hyperlink',
|
||||
removeNote: 'Remove note'
|
||||
removeNote: 'Remove note',
|
||||
removeCustomStyles: 'Remove custom styles',
|
||||
removeAllNodeCustomStyles: 'Remove all node custom styles'
|
||||
},
|
||||
count: {
|
||||
words: 'Words',
|
||||
@ -264,7 +266,8 @@ export default {
|
||||
fileContentError: 'File content error',
|
||||
fileOpenFailed: 'File open failed',
|
||||
defaultFileName: 'Mind map',
|
||||
creatingTip: 'Creating file'
|
||||
creatingTip: 'Creating file',
|
||||
directory: 'Directory'
|
||||
},
|
||||
edit: {
|
||||
newFeatureNoticeTitle: 'New feature reminder',
|
||||
|
||||
@ -95,7 +95,9 @@ export default {
|
||||
create: '新建文件',
|
||||
removeImage: '移除图片',
|
||||
removeHyperlink: '移除超链接',
|
||||
removeNote: '移除备注'
|
||||
removeNote: '移除备注',
|
||||
removeCustomStyles: '一键去除自定义样式',
|
||||
removeAllNodeCustomStyles: '一键去除所有节点自定义样式'
|
||||
},
|
||||
count: {
|
||||
words: '字数',
|
||||
@ -260,7 +262,8 @@ export default {
|
||||
fileContentError: '文件内容有误',
|
||||
fileOpenFailed: '文件打开失败',
|
||||
defaultFileName: '思维导图',
|
||||
creatingTip: '正在创建文件'
|
||||
creatingTip: '正在创建文件',
|
||||
directory: '目录'
|
||||
},
|
||||
edit: {
|
||||
newFeatureNoticeTitle: '新特性提醒',
|
||||
|
||||
@ -1,5 +1,71 @@
|
||||
# Changelog
|
||||
|
||||
## 0.9.8
|
||||
|
||||
Fix:
|
||||
|
||||
> 1.Fix the issue of incorrect calculation function of mind maps within the canvas and scroll bar positions when the canvas size changes;
|
||||
>
|
||||
> 2.Fix the issue of errors when importing some old version xmind files;
|
||||
>
|
||||
> 3.Fix the issue where the highlight box of the collapsed node does not disappear when searching for highlighted nodes in read-only mode;
|
||||
>
|
||||
> 4.Fix the issue where data changes during search and search results are not updated in certain situations;
|
||||
>
|
||||
> 5.Fix the issue of deleting adjacent nodes when deleting nodes that are currently being edited;
|
||||
>
|
||||
> 6.Fix the issue of rendering only the root node when expand: false is set to the root node in the node data;
|
||||
>
|
||||
> 7.Fix the collaborative editing plugin: When a node is selected and then folded, the activation status of the node disappears, but the selected status of the node still exists in other clients;
|
||||
>
|
||||
> 8.Optimize the export of markdowns and fix the issue of missing summaries;
|
||||
>
|
||||
> 9.Fix the issue of ineffective forward and backward operations on node positions during free drag and drop;
|
||||
|
||||
New:
|
||||
|
||||
> 1.The commands such as INSERTNODE will not overwrite custom UIDs;
|
||||
>
|
||||
> 2.Methods for adding and removing highlighting for node instances; Adjust the way read-only mode searches for highlighted nodes;
|
||||
>
|
||||
> 3.Add configuration for searching all nodes (including those that have been folded); Search defaults to searching all nodes;
|
||||
>
|
||||
> 4.Add configuration options that cannot be selected by multiple people on the same node during collaborative editing;
|
||||
>
|
||||
> 5.Add lifecycle function configuration options before synchronizing collaborative editing node operations;
|
||||
>
|
||||
> 6.Add UID field to the summary node;
|
||||
>
|
||||
> 7.Added support for exporting txt files;
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.Fix the issue where shortcut keys become invalid after opening label pop ups and note pop ups and clicking on the mask to close them;
|
||||
>
|
||||
> 2.Modify the association logic between themes and dark colors;
|
||||
>
|
||||
> 3.Support reading local directories;
|
||||
>
|
||||
> 4.Fix the issue of selecting a file in the import pop-up window and then deleting it without actually deleting it;
|
||||
>
|
||||
> 5.Export new txt files;
|
||||
|
||||
## 0.9.7
|
||||
|
||||
Fix:
|
||||
|
||||
> 1.Fix the issue where the style is not updated when dragging nodes below level 2 to the root node to become level 2 nodes; Fix the issue where the style is not updated when moving nodes with the command to move up one level;
|
||||
>
|
||||
> 2.Fix the issue of losing focus when activating summary nodes and then setting text styles for them;
|
||||
|
||||
New:
|
||||
|
||||
> 1.Add two commands to remove custom styles from nodes;
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.Add a right-click menu button to remove custom styles from nodes.
|
||||
|
||||
## 0.9.6
|
||||
|
||||
Fix:
|
||||
|
||||
@ -1,6 +1,51 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.9.8</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
<p>1.Fix the issue of incorrect calculation function of mind maps within the canvas and scroll bar positions when the canvas size changes;</p>
|
||||
<p>2.Fix the issue of errors when importing some old version xmind files;</p>
|
||||
<p>3.Fix the issue where the highlight box of the collapsed node does not disappear when searching for highlighted nodes in read-only mode;</p>
|
||||
<p>4.Fix the issue where data changes during search and search results are not updated in certain situations;</p>
|
||||
<p>5.Fix the issue of deleting adjacent nodes when deleting nodes that are currently being edited;</p>
|
||||
<p>6.Fix the issue of rendering only the root node when expand: false is set to the root node in the node data;</p>
|
||||
<p>7.Fix the collaborative editing plugin: When a node is selected and then folded, the activation status of the node disappears, but the selected status of the node still exists in other clients;</p>
|
||||
<p>8.Optimize the export of markdowns and fix the issue of missing summaries;</p>
|
||||
<p>9.Fix the issue of ineffective forward and backward operations on node positions during free drag and drop;</p>
|
||||
</blockquote>
|
||||
<p>New:</p>
|
||||
<blockquote>
|
||||
<p>1.The commands such as INSERTNODE will not overwrite custom UIDs;</p>
|
||||
<p>2.Methods for adding and removing highlighting for node instances; Adjust the way read-only mode searches for highlighted nodes;</p>
|
||||
<p>3.Add configuration for searching all nodes (including those that have been folded); Search defaults to searching all nodes;</p>
|
||||
<p>4.Add configuration options that cannot be selected by multiple people on the same node during collaborative editing;</p>
|
||||
<p>5.Add lifecycle function configuration options before synchronizing collaborative editing node operations;</p>
|
||||
<p>6.Add UID field to the summary node;</p>
|
||||
<p>7.Added support for exporting txt files;</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.Fix the issue where shortcut keys become invalid after opening label pop ups and note pop ups and clicking on the mask to close them;</p>
|
||||
<p>2.Modify the association logic between themes and dark colors;</p>
|
||||
<p>3.Support reading local directories;</p>
|
||||
<p>4.Fix the issue of selecting a file in the import pop-up window and then deleting it without actually deleting it;</p>
|
||||
<p>5.Export new txt files;</p>
|
||||
</blockquote>
|
||||
<h2>0.9.7</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
<p>1.Fix the issue where the style is not updated when dragging nodes below level 2 to the root node to become level 2 nodes; Fix the issue where the style is not updated when moving nodes with the command to move up one level;</p>
|
||||
<p>2.Fix the issue of losing focus when activating summary nodes and then setting text styles for them;</p>
|
||||
</blockquote>
|
||||
<p>New:</p>
|
||||
<blockquote>
|
||||
<p>1.Add two commands to remove custom styles from nodes;</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.Add a right-click menu button to remove custom styles from nodes.</p>
|
||||
</blockquote>
|
||||
<h2>0.9.6</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
|
||||
@ -110,7 +110,10 @@ const mindMap = new MindMap({
|
||||
| isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+) | Boolean | true | When registering the Scrollbar plugin, will the mind map be limited to the canvas and the isLimitMindMapInCanvas configuration no longer work | |
|
||||
| associativeLineInitPointsPosition(v0.9.5+) | null / { from, to } | { from: '', to: '' } | By default, the position of the two endpoints of a newly created association line is calculated based on the relative position of the center points of the two nodes. If you want to fix the position, you can configure it through this option. If neither from nor to is transmitted, they will be automatically calculated. If only one is transmitted, the other will be automatically calculated. from and to optional values
|
||||
:left、top、bottom、right | |
|
||||
| enableAdjustAssociativeLinePoints(v0.9.5+) | Boolean | true | Is it allowed to adjust the position of the two endpoints of the associated line |
|
||||
| enableAdjustAssociativeLinePoints(v0.9.5+) | Boolean | true | Is it allowed to adjust the position of the two endpoints of the associated line | |
|
||||
| isOnlySearchCurrentRenderNodes(v0.9.8+) | Boolean | false | Is it necessary to only search for the current rendered node, and nodes that have been collapsed will not be searched for | |
|
||||
| onlyOneEnableActiveNodeOnCooperate(v0.9.8+) | Boolean | false | During collaborative editing, the same node cannot be selected by multiple people at the same time | |
|
||||
| beforeCooperateUpdate(v0.9.8+) | Function、null | null | During collaborative editing, node operations are about to be updated to the lifecycle functions of other clients. The function takes an object as a parameter:{ type: 【createOrUpdate(Create or update nodes)、delete(Delete node)】, list: 【Array type, 1.When type=createOrUpdate, it represents the node data that has been created or updated, which will be synchronized to other clients, so you can modify the data; 2.When type=delete, represents the deleted node data】 } | |
|
||||
|
||||
### Data structure
|
||||
|
||||
@ -533,13 +536,15 @@ redo. All commands are as follows:
|
||||
| SET_NODE_CUSTOM_POSITION (v0.2.0+) | Set a custom position for a node | node (the node to set), left (custom x coordinate, default is undefined), top (custom y coordinate, default is undefined) |
|
||||
| RESET_LAYOUT (v0.2.0+) | Arrange layout with one click | |
|
||||
| SET_NODE_SHAPE (v0.2.4+) | Set the shape of a node | node (the node to set), shape (the shape, all shapes: [Shape.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/core/render/node/Shape.js)) |
|
||||
| GO_TARGET_NODE(v0.6.7+) | Navigate to a node, and if the node is collapsed, it will automatically expand to that node | node(Node instance or node uid to locate)、callback(v0.6.9+, Callback function after positioning completion) |
|
||||
| GO_TARGET_NODE(v0.6.7+) | Navigate to a node, and if the node is collapsed, it will automatically expand to that node | node(Node instance or node uid to locate)、callback(v0.6.9+, Callback function after positioning completion, v0.9.8+receives a parameter representing the target node instance) |
|
||||
| INSERT_MULTI_NODE(v0.7.2+) | Insert multiple sibling nodes into the specified node at the same time, with the operating node being the currently active node or the specified node | appointNodes(Optional, specify nodes, specify multiple nodes to pass an array), nodeList(Data list of newly inserted nodes, array type) |
|
||||
| INSERT_MULTI_CHILD_NODE(v0.7.2+) | Insert multiple child nodes into the specified node simultaneously, with the operation node being the currently active node or the specified node | appointNodes(Optional, specify nodes, specify multiple nodes to pass an array), childList(Data list of newly inserted nodes, array type) |
|
||||
| INSERT_FORMULA(v0.7.2+) | Insert mathematical formulas into nodes, operate on the currently active node or specified node | formula(Mathematical formula to insert, LaTeX syntax), appointNodes(Optional, specify the node to insert the formula into. Multiple nodes can be passed as arrays, otherwise it defaults to the currently active node) |
|
||||
| INSERT_PARENT_NODE(v0.8.0+) | Insert a parent node into the specified node, with the operation node being the currently active node or the specified node | openEdit(Activate the newly inserted node and enter editing mode, default to 'true'`)、 appointNodes(Optional, specify the node to insert into the parent node, and specify that multiple nodes can pass an array)、 appointData(Optional, specify the data for the newly created node, such as {text: 'xxx', ...}, Detailed structure can be referenced [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js)) |
|
||||
| REMOVE_CURRENT_NODE(v0.8.0+) | Delete only the current node, operate on the currently active node or specified node | appointNodes(Optional, specify the nodes to be deleted, and multiple nodes can be passed as an array) |
|
||||
| MOVE_UP_ONE_LEVEL(v0.9.6+) | Move the specified node up one level | node(Optional, specify the node to move up the hierarchy, if not passed, it will be the first node in the current active node) |
|
||||
| REMOVE_CUSTOM_STYLES(v0.9.7+) | One click removal of custom styles for a node | node(Optional, specify the node to clear the custom style, otherwise it will be the first one in the current active node) |
|
||||
| REMOVE_ALL_NODE_CUSTOM_STYLES(v0.9.7+) | One click removal of multiple nodes or custom styles for all nodes | appointNodes(Optional, node instance array, specifying multiple nodes to remove custom styles from. If not passed, the custom styles of all nodes on the current canvas will be removed) |
|
||||
|
||||
### setData(data)
|
||||
|
||||
|
||||
@ -637,6 +637,27 @@
|
||||
<td>Is it allowed to adjust the position of the two endpoints of the associated line</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isOnlySearchCurrentRenderNodes(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Is it necessary to only search for the current rendered node, and nodes that have been collapsed will not be searched for</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>onlyOneEnableActiveNodeOnCooperate(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>During collaborative editing, the same node cannot be selected by multiple people at the same time</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>beforeCooperateUpdate(v0.9.8+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>During collaborative editing, node operations are about to be updated to the lifecycle functions of other clients. The function takes an object as a parameter:{ type: 【createOrUpdate(Create or update nodes)、delete(Delete node)】, list: 【Array type, 1.When type=createOrUpdate, it represents the node data that has been created or updated, which will be synchronized to other clients, so you can modify the data; 2.When type=delete, represents the deleted node data】 }</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Data structure</h3>
|
||||
@ -1363,7 +1384,7 @@ redo. All commands are as follows:</p>
|
||||
<tr>
|
||||
<td>GO_TARGET_NODE(v0.6.7+)</td>
|
||||
<td>Navigate to a node, and if the node is collapsed, it will automatically expand to that node</td>
|
||||
<td>node(Node instance or node uid to locate)、callback(v0.6.9+, Callback function after positioning completion)</td>
|
||||
<td>node(Node instance or node uid to locate)、callback(v0.6.9+, Callback function after positioning completion, v0.9.8+receives a parameter representing the target node instance)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>INSERT_MULTI_NODE(v0.7.2+)</td>
|
||||
@ -1395,6 +1416,16 @@ redo. All commands are as follows:</p>
|
||||
<td>Move the specified node up one level</td>
|
||||
<td>node(Optional, specify the node to move up the hierarchy, if not passed, it will be the first node in the current active node)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>REMOVE_CUSTOM_STYLES(v0.9.7+)</td>
|
||||
<td>One click removal of custom styles for a node</td>
|
||||
<td>node(Optional, specify the node to clear the custom style, otherwise it will be the first one in the current active node)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>REMOVE_ALL_NODE_CUSTOM_STYLES(v0.9.7+)</td>
|
||||
<td>One click removal of multiple nodes or custom styles for all nodes</td>
|
||||
<td>appointNodes(Optional, node instance array, specifying multiple nodes to remove custom styles from. If not passed, the custom styles of all nodes on the current canvas will be removed)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>setData(data)</h3>
|
||||
|
||||
@ -135,4 +135,10 @@ import ExportXMind from 'simple-mind-map/src/plugins/ExportXMind.js'
|
||||
MindMap.usePlugin(ExportXMind)
|
||||
```
|
||||
|
||||
Export as an `xmind` file type, asynchronous method, returns a `Promise` instance, and the returned data is the `data:url` data of a `zip` compressed package, which can be directly downloaded.
|
||||
Export as an `xmind` file type, asynchronous method, returns a `Promise` instance, and the returned data is the `data:url` data of a `zip` compressed package, which can be directly downloaded.
|
||||
|
||||
### txt()
|
||||
|
||||
> v0.9.8+
|
||||
|
||||
Export as `txt` file.
|
||||
@ -127,6 +127,11 @@ MindMap.usePlugin(ExportPDF)
|
||||
MindMap.usePlugin(ExportXMind)
|
||||
</code></pre>
|
||||
<p>Export as an <code>xmind</code> file type, asynchronous method, returns a <code>Promise</code> instance, and the returned data is the <code>data:url</code> data of a <code>zip</code> compressed package, which can be directly downloaded.</p>
|
||||
<h3>txt()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.8+</p>
|
||||
</blockquote>
|
||||
<p>Export as <code>txt</code> file.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -20,6 +20,14 @@
|
||||
- [x] Provide rich configurations to meet various scenarios and usage habits
|
||||
- [x] Support collaborative editing
|
||||
|
||||
> Features that will not be implemented:
|
||||
>
|
||||
> 1.Free nodes, i.e. multiple root nodes;
|
||||
>
|
||||
> 2.Continue adding nodes after the summary node;
|
||||
>
|
||||
> If you need the above features, this library may not meet your needs.
|
||||
|
||||
## Repository Catalog Introduction
|
||||
|
||||
1.`simple-mind-map`
|
||||
@ -299,4 +307,24 @@ Open source is not easy. If this project is helpful to you, you can invite the a
|
||||
<img src="../../../../assets/avatar/慕智打印-兰兰.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>慕智打印-兰兰</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>锦冰</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/旭东.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>旭东</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/俊奇.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>俊奇</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/橘半.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>橘半</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/pluvet.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>pluvet</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -8,18 +8,24 @@
|
||||
</blockquote>
|
||||
<h2>Features</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox16" checked="true" /><label for="checkbox16">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
|
||||
<li><input type="checkbox" id="checkbox17" checked="true" /><label for="checkbox17">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
|
||||
<li><input type="checkbox" id="checkbox18" checked="true" /><label for="checkbox18">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox19" checked="true" /><label for="checkbox19">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
|
||||
<li><input type="checkbox" id="checkbox20" checked="true" /><label for="checkbox20">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
|
||||
<li><input type="checkbox" id="checkbox21" checked="true" /><label for="checkbox21">Support canvas dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox22" checked="true" /><label for="checkbox22">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
|
||||
<li><input type="checkbox" id="checkbox23" checked="true" /><label for="checkbox23">Supoorts to export as </label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>, support import from <code>json</code>、<code>xmind</code>、<code>markdown</code></li>
|
||||
<li><input type="checkbox" id="checkbox24" checked="true" /><label for="checkbox24">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar</label></li>
|
||||
<li><input type="checkbox" id="checkbox25" checked="true" /><label for="checkbox25">Provide rich configurations to meet various scenarios and usage habits</label></li>
|
||||
<li><input type="checkbox" id="checkbox26" checked="true" /><label for="checkbox26">Support collaborative editing</label></li>
|
||||
<li><input type="checkbox" id="checkbox80" checked="true" /><label for="checkbox80">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
|
||||
<li><input type="checkbox" id="checkbox81" checked="true" /><label for="checkbox81">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
|
||||
<li><input type="checkbox" id="checkbox82" checked="true" /><label for="checkbox82">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox83" checked="true" /><label for="checkbox83">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
|
||||
<li><input type="checkbox" id="checkbox84" checked="true" /><label for="checkbox84">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
|
||||
<li><input type="checkbox" id="checkbox85" checked="true" /><label for="checkbox85">Support canvas dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox86" checked="true" /><label for="checkbox86">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
|
||||
<li><input type="checkbox" id="checkbox87" checked="true" /><label for="checkbox87">Supoorts to export as </label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>, support import from <code>json</code>、<code>xmind</code>、<code>markdown</code></li>
|
||||
<li><input type="checkbox" id="checkbox88" checked="true" /><label for="checkbox88">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar</label></li>
|
||||
<li><input type="checkbox" id="checkbox89" checked="true" /><label for="checkbox89">Provide rich configurations to meet various scenarios and usage habits</label></li>
|
||||
<li><input type="checkbox" id="checkbox90" checked="true" /><label for="checkbox90">Support collaborative editing</label></li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p>Features that will not be implemented:</p>
|
||||
<p>1.Free nodes, i.e. multiple root nodes;</p>
|
||||
<p>2.Continue adding nodes after the summary node;</p>
|
||||
<p>If you need the above features, this library may not meet your needs.</p>
|
||||
</blockquote>
|
||||
<h2>Repository Catalog Introduction</h2>
|
||||
<p>1.<code>simple-mind-map</code></p>
|
||||
<p>This is a mind map library that is framework-agnostic and can be used with
|
||||
@ -28,16 +34,16 @@ frameworks such as Vue and React, or without a framework.</p>
|
||||
<p>This is an online mind map built using the <code>simple-mind-map</code> library and based
|
||||
on <code>Vue2.x</code> and <code>ElementUI</code>. Features include:</p>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox27" checked="true" /><label for="checkbox27">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
<li><input type="checkbox" id="checkbox91" checked="true" /><label for="checkbox91">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
images, icons, hyperlinks, notes, tags, and summaries</li>
|
||||
<li><input type="checkbox" id="checkbox28" checked="true" /><label for="checkbox28">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
<li><input type="checkbox" id="checkbox92" checked="true" /><label for="checkbox92">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
outline, theme selection, and structure selection</li>
|
||||
<li><input type="checkbox" id="checkbox29" checked="true" /><label for="checkbox29">Import and export functionality; data is saved in the browser's local</label>
|
||||
<li><input type="checkbox" id="checkbox93" checked="true" /><label for="checkbox93">Import and export functionality; data is saved in the browser's local</label>
|
||||
storage by default, but it also supports creating, opening, and editing
|
||||
local files on the computer directly</li>
|
||||
<li><input type="checkbox" id="checkbox30" checked="true" /><label for="checkbox30">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
<li><input type="checkbox" id="checkbox94" checked="true" /><label for="checkbox94">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
and organizing layout</li>
|
||||
<li><input type="checkbox" id="checkbox31" checked="true" /><label for="checkbox31">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
<li><input type="checkbox" id="checkbox95" checked="true" /><label for="checkbox95">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
between edit and read-only modes, zooming in and out, and switching to
|
||||
full screen, support mini map</li>
|
||||
</ul>
|
||||
@ -255,6 +261,26 @@ full screen, support mini map</li>
|
||||
<img src="../../../../assets/avatar/慕智打印-兰兰.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>慕智打印-兰兰</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>锦冰</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/旭东.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>旭东</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/俊奇.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>俊奇</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/橘半.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>橘半</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/pluvet.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>pluvet</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -56,6 +56,18 @@ Whether the node is currently being dragged
|
||||
|
||||
## Methods
|
||||
|
||||
### highlight()
|
||||
|
||||
> v0.9.8+
|
||||
|
||||
Highlight node.
|
||||
|
||||
### closeHighlight()
|
||||
|
||||
> v0.9.8+
|
||||
|
||||
Unhighlight node.
|
||||
|
||||
### getPureData(removeActiveState = true, removeId = false)
|
||||
|
||||
> v0.9.0+
|
||||
|
||||
@ -31,6 +31,16 @@
|
||||
</blockquote>
|
||||
<p>Whether the node is currently being dragged</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>highlight()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.8+</p>
|
||||
</blockquote>
|
||||
<p>Highlight node.</p>
|
||||
<h3>closeHighlight()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.8+</p>
|
||||
</blockquote>
|
||||
<p>Unhighlight node.</p>
|
||||
<h3>getPureData(removeActiveState = true, removeId = false)</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.0+</p>
|
||||
|
||||
@ -21,3 +21,9 @@ Register temporary shortcut keys, which means editing can be completed through t
|
||||
- `node`:Node instance to enter for editing
|
||||
|
||||
Manually enable node editing. By default, it will enter node editing when double clicking or pressing F2 on the node.
|
||||
|
||||
### getCurrentEditNode()
|
||||
|
||||
> v0.9.8+
|
||||
|
||||
Get the node instance currently being edited.
|
||||
@ -14,6 +14,11 @@
|
||||
<li><code>node</code>:Node instance to enter for editing</li>
|
||||
</ul>
|
||||
<p>Manually enable node editing. By default, it will enter node editing when double clicking or pressing F2 on the node.</p>
|
||||
<h3>getCurrentEditNode()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.8+</p>
|
||||
</blockquote>
|
||||
<p>Get the node instance currently being edited.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,5 +1,71 @@
|
||||
# Changelog
|
||||
|
||||
## 0.9.8
|
||||
|
||||
修复:
|
||||
|
||||
> 1.修复当画布大小改变后,限制思维导图在画布内和滚动条位置计算功能不正确的问题;
|
||||
>
|
||||
> 2.修复导入某些旧版xmind文件时报错的问题;
|
||||
>
|
||||
> 3.修复只读模式搜索高亮节点时收起节点高亮框未消失的问题;
|
||||
>
|
||||
> 4.修复某些情况下搜索时数据改变,搜索结果没有更新的问题;
|
||||
>
|
||||
> 5.修复删除正在编辑中的节点时实际上删除的是相邻节点的问题;
|
||||
>
|
||||
> 6.修复节点数据中根节点设置了expand:false时只渲染根节点的问题;
|
||||
>
|
||||
> 7.修复协同编辑插件:当选中一个节点时,再将该节点收起,该节点激活状态已消失,但其他客户端该节点的选中状态依旧存在的问题;
|
||||
>
|
||||
> 8.优化markdown的导出,修复概要丢失的问题;
|
||||
>
|
||||
> 9.修复自由拖拽时,前进后退操作对节点位置不生效的问题;
|
||||
|
||||
新增:
|
||||
|
||||
> 1.INSERT_NODE等命令不会覆盖自定义的uid;
|
||||
>
|
||||
> 2.节点实例新增高亮和取消高亮的方法;调整只读模式搜索高亮节点的方式;
|
||||
>
|
||||
> 3.新增搜索所有节点(包含被收起的节点)的配置;搜索默认改为搜索所有节点;
|
||||
>
|
||||
> 4.增加协同编辑时同一节点不能多人选中的配置选项;
|
||||
>
|
||||
> 5.增加协同编辑节点操作同步前的生命周期函数配置选项;
|
||||
>
|
||||
> 6.概要节点增加uid字段;
|
||||
>
|
||||
> 7.新增支持txt文件的导出;
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.修复打开标签弹窗、备注弹窗后点击遮罩关闭弹窗后快捷键会失效的问题;
|
||||
>
|
||||
> 2.修改主题和暗色的关联逻辑;
|
||||
>
|
||||
> 3.支持读取本地目录;
|
||||
>
|
||||
> 4.修复导入弹窗选择了一个文件后再把它删除实际上并没有删掉的问题;
|
||||
>
|
||||
> 5.新增txt文件的导出;
|
||||
|
||||
## 0.9.7
|
||||
|
||||
修复:
|
||||
|
||||
> 1.修复二级以下节点拖拽到根节点变成二级节点时样式没有更新的问题;修复上移一个层级命令移动节点时样式没有更新的问题;
|
||||
>
|
||||
> 2.修复激活概要节点,然后给其设置文本样式时概要节点会失去焦点的问题;
|
||||
|
||||
新增:
|
||||
|
||||
> 1.新增两个去除节点自定义样式的命令;
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.新增去除节点自定义样式的右键菜单按钮。
|
||||
|
||||
## 0.9.6
|
||||
|
||||
修复:
|
||||
|
||||
@ -1,6 +1,51 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.9.8</h2>
|
||||
<p>修复:</p>
|
||||
<blockquote>
|
||||
<p>1.修复当画布大小改变后,限制思维导图在画布内和滚动条位置计算功能不正确的问题;</p>
|
||||
<p>2.修复导入某些旧版xmind文件时报错的问题;</p>
|
||||
<p>3.修复只读模式搜索高亮节点时收起节点高亮框未消失的问题;</p>
|
||||
<p>4.修复某些情况下搜索时数据改变,搜索结果没有更新的问题;</p>
|
||||
<p>5.修复删除正在编辑中的节点时实际上删除的是相邻节点的问题;</p>
|
||||
<p>6.修复节点数据中根节点设置了expand:false时只渲染根节点的问题;</p>
|
||||
<p>7.修复协同编辑插件:当选中一个节点时,再将该节点收起,该节点激活状态已消失,但其他客户端该节点的选中状态依旧存在的问题;</p>
|
||||
<p>8.优化markdown的导出,修复概要丢失的问题;</p>
|
||||
<p>9.修复自由拖拽时,前进后退操作对节点位置不生效的问题;</p>
|
||||
</blockquote>
|
||||
<p>新增:</p>
|
||||
<blockquote>
|
||||
<p>1.INSERT_NODE等命令不会覆盖自定义的uid;</p>
|
||||
<p>2.节点实例新增高亮和取消高亮的方法;调整只读模式搜索高亮节点的方式;</p>
|
||||
<p>3.新增搜索所有节点(包含被收起的节点)的配置;搜索默认改为搜索所有节点;</p>
|
||||
<p>4.增加协同编辑时同一节点不能多人选中的配置选项;</p>
|
||||
<p>5.增加协同编辑节点操作同步前的生命周期函数配置选项;</p>
|
||||
<p>6.概要节点增加uid字段;</p>
|
||||
<p>7.新增支持txt文件的导出;</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.修复打开标签弹窗、备注弹窗后点击遮罩关闭弹窗后快捷键会失效的问题;</p>
|
||||
<p>2.修改主题和暗色的关联逻辑;</p>
|
||||
<p>3.支持读取本地目录;</p>
|
||||
<p>4.修复导入弹窗选择了一个文件后再把它删除实际上并没有删掉的问题;</p>
|
||||
<p>5.新增txt文件的导出;</p>
|
||||
</blockquote>
|
||||
<h2>0.9.7</h2>
|
||||
<p>修复:</p>
|
||||
<blockquote>
|
||||
<p>1.修复二级以下节点拖拽到根节点变成二级节点时样式没有更新的问题;修复上移一个层级命令移动节点时样式没有更新的问题;</p>
|
||||
<p>2.修复激活概要节点,然后给其设置文本样式时概要节点会失去焦点的问题;</p>
|
||||
</blockquote>
|
||||
<p>新增:</p>
|
||||
<blockquote>
|
||||
<p>1.新增两个去除节点自定义样式的命令;</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.新增去除节点自定义样式的右键菜单按钮。</p>
|
||||
</blockquote>
|
||||
<h2>0.9.6</h2>
|
||||
<p>修复:</p>
|
||||
<blockquote>
|
||||
|
||||
@ -110,6 +110,9 @@ const mindMap = new MindMap({
|
||||
| isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+) | Boolean | true | 当注册了滚动条插件(Scrollbar)时,是否将思维导图限制在画布内,isLimitMindMapInCanvas配置不再起作用 |
|
||||
| associativeLineInitPointsPosition(v0.9.5+) | null / { from, to } | { from: '', to: '' } | 默认情况下,新创建的关联线两个端点的位置是根据两个节点中心点的相对位置来计算的,如果你想固定位置,可以通过这个选项来配置。from和to都不传,则都自动计算,如果只传一个,另一个则会自动计算。from和to可选值:left、top、bottom、right |
|
||||
| enableAdjustAssociativeLinePoints(v0.9.5+) | Boolean | true | 是否允许调整关联线两个端点的位置 |
|
||||
| isOnlySearchCurrentRenderNodes(v0.9.8+) | Boolean | false | 是否仅搜索当前渲染的节点,被收起的节点不会被搜索到 |
|
||||
| onlyOneEnableActiveNodeOnCooperate(v0.9.8+) | Boolean | false | 协同编辑时,同一个节点不能同时被多人选中 |
|
||||
| beforeCooperateUpdate(v0.9.8+) | Function、null | null | 协同编辑时,节点操作即将更新到其他客户端前的生命周期函数。函数接收一个对象作为参数:{ type: 【createOrUpdate(创建节点或更新节点)、delete(删除节点)】, list: 【数组类型,1.当type=createOrUpdate时,代表被创建或被更新的节点数据,即将同步到其他客户端,所以你可以修改该数据;2.当type=delete时,代表被删除的节点数据】 } |
|
||||
|
||||
### 数据结构
|
||||
|
||||
@ -527,13 +530,15 @@ mindMap.updateConfig({
|
||||
| SET_NODE_CUSTOM_POSITION(v0.2.0+) | 设置节点自定义位置 | node(要设置的节点)、 left(自定义的x坐标,默认为undefined)、 top(自定义的y坐标,默认为undefined) |
|
||||
| RESET_LAYOUT(v0.2.0+) | 一键整理布局 | |
|
||||
| SET_NODE_SHAPE(v0.2.4+) | 设置节点形状 | node(要设置的节点)、shape(形状,全部形状:[Shape.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/core/render/node/Shape.js)) |
|
||||
| GO_TARGET_NODE(v0.6.7+) | 定位到某个节点,如果该节点被收起,那么会自动展开到该节点 | node(要定位到的节点实例或节点uid)、callback(v0.6.9+,定位完成后的回调函数) |
|
||||
| GO_TARGET_NODE(v0.6.7+) | 定位到某个节点,如果该节点被收起,那么会自动展开到该节点 | node(要定位到的节点实例或节点uid)、callback(v0.6.9+,定位完成后的回调函数,v0.9.8+接收一个参数,代表目标节点实例) |
|
||||
| INSERT_MULTI_NODE(v0.7.2+) | 给指定的节点同时插入多个同级节点,操作节点为当前激活的节点或指定节点 | appointNodes(可选,指定节点,指定多个节点可以传一个数组), nodeList(新插入节点的数据列表,数组类型) |
|
||||
| INSERT_MULTI_CHILD_NODE(v0.7.2+) | 给指定的节点同时插入多个子节点,操作节点为当前激活的节点或指定节点 | appointNodes(可选,指定节点,指定多个节点可以传一个数组), childList(新插入节点的数据列表,数组类型) |
|
||||
| INSERT_FORMULA(v0.7.2+) | 给节点插入数学公式,操作节点为当前激活的节点或指定节点 | formula(要插入的数学公式,LaTeX 语法), appointNodes(可选,指定要插入公式的节点,多个节点可以传数组,否则默认为当前激活的节点) |
|
||||
| INSERT_PARENT_NODE(v0.8.0+) | 给指定的节点插入父节点,操作节点为当前激活的节点或指定节点 | openEdit(是否激活新插入的节点并进入编辑模式,默认为`true`)、 appointNodes(可选,指定要插入父节点的节点,指定多个节点可以传一个数组)、 appointData(可选,指定新创建节点的数据,比如{text: 'xxx', ...},详细结构可以参考[exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js)) |
|
||||
| REMOVE_CURRENT_NODE(v0.8.0+) | 仅删除当前节点,操作节点为当前激活的节点或指定节点 | appointNodes(可选,指定要删除的节点,指定多个节点可以传一个数组) |
|
||||
| MOVE_UP_ONE_LEVEL(v0.9.6+) | 将指定节点上移一个层级 | node(可选,指定要上移层级的节点,不传则为当前激活节点中的第一个) |
|
||||
| REMOVE_CUSTOM_STYLES(v0.9.7+) | 一键去除某个节点的自定义样式 | node(可选,指定要清除自定义样式的节点,不传则为当前激活节点中的第一个) |
|
||||
| REMOVE_ALL_NODE_CUSTOM_STYLES(v0.9.7+) | 一键去除多个节点或所有节点的自定义样式 | appointNodes(可选,节点实例数组,指定要去除自定义样式的多个节点,如果不传则会去除当前画布所有节点的自定义样式) |
|
||||
|
||||
### setData(data)
|
||||
|
||||
|
||||
@ -543,6 +543,24 @@
|
||||
<td>true</td>
|
||||
<td>是否允许调整关联线两个端点的位置</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isOnlySearchCurrentRenderNodes(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>是否仅搜索当前渲染的节点,被收起的节点不会被搜索到</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>onlyOneEnableActiveNodeOnCooperate(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>协同编辑时,同一个节点不能同时被多人选中</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>beforeCooperateUpdate(v0.9.8+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>协同编辑时,节点操作即将更新到其他客户端前的生命周期函数。函数接收一个对象作为参数:{ type: 【createOrUpdate(创建节点或更新节点)、delete(删除节点)】, list: 【数组类型,1.当type=createOrUpdate时,代表被创建或被更新的节点数据,即将同步到其他客户端,所以你可以修改该数据;2.当type=delete时,代表被删除的节点数据】 }</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>数据结构</h3>
|
||||
@ -1264,7 +1282,7 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
<tr>
|
||||
<td>GO_TARGET_NODE(v0.6.7+)</td>
|
||||
<td>定位到某个节点,如果该节点被收起,那么会自动展开到该节点</td>
|
||||
<td>node(要定位到的节点实例或节点uid)、callback(v0.6.9+,定位完成后的回调函数)</td>
|
||||
<td>node(要定位到的节点实例或节点uid)、callback(v0.6.9+,定位完成后的回调函数,v0.9.8+接收一个参数,代表目标节点实例)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>INSERT_MULTI_NODE(v0.7.2+)</td>
|
||||
@ -1296,6 +1314,16 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
<td>将指定节点上移一个层级</td>
|
||||
<td>node(可选,指定要上移层级的节点,不传则为当前激活节点中的第一个)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>REMOVE_CUSTOM_STYLES(v0.9.7+)</td>
|
||||
<td>一键去除某个节点的自定义样式</td>
|
||||
<td>node(可选,指定要清除自定义样式的节点,不传则为当前激活节点中的第一个)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>REMOVE_ALL_NODE_CUSTOM_STYLES(v0.9.7+)</td>
|
||||
<td>一键去除多个节点或所有节点的自定义样式</td>
|
||||
<td>appointNodes(可选,节点实例数组,指定要去除自定义样式的多个节点,如果不传则会去除当前画布所有节点的自定义样式)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>setData(data)</h3>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
> 要使用导出功能需要使用导出插件。
|
||||
|
||||
目前支持导出为`.smm`、`.json`、`.svg`、`.png`、`.pdf`、`.md`、`.xmind`文件。
|
||||
目前支持导出为`.smm`、`.json`、`.svg`、`.png`、`.pdf`、`.md`、`.xmind`、`.txt`文件。
|
||||
|
||||
`.smm`是`simple-mind-map`自己定义的一种文件,其实就是`json`文件,换了一个扩展名而已。
|
||||
|
||||
@ -108,6 +108,16 @@ mindMap.export('md', true, '文件名')
|
||||
mindMap.export('xmind', '文件名')
|
||||
```
|
||||
|
||||
### 导出为txt
|
||||
|
||||
> v0.9.8+
|
||||
|
||||
导出为`txt`文件只要传递默认的三个参数即可:
|
||||
|
||||
```js
|
||||
mindMap.export('txt', true, '文件名')
|
||||
```
|
||||
|
||||
## 导入
|
||||
|
||||
目前支持从`.smm`、`.json`、`.xmind`、`.xlsx`、`.md`格式的文件导入。
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<blockquote>
|
||||
<p>要使用导出功能需要使用导出插件。</p>
|
||||
</blockquote>
|
||||
<p>目前支持导出为<code>.smm</code>、<code>.json</code>、<code>.svg</code>、<code>.png</code>、<code>.pdf</code>、<code>.md</code>、<code>.xmind</code>文件。</p>
|
||||
<p>目前支持导出为<code>.smm</code>、<code>.json</code>、<code>.svg</code>、<code>.png</code>、<code>.pdf</code>、<code>.md</code>、<code>.xmind</code>、<code>.txt</code>文件。</p>
|
||||
<p><code>.smm</code>是<code>simple-mind-map</code>自己定义的一种文件,其实就是<code>json</code>文件,换了一个扩展名而已。</p>
|
||||
<p>导出直接调用<code>export</code>方法即可:</p>
|
||||
<pre class="hljs"><code>mindMap.export(type, isDownload, fileName, ...)
|
||||
@ -75,6 +75,13 @@ mindMap.export(<span class="hljs-string">'pdf'</span>, <span class="hl
|
||||
<p>导出为<code>Xmind</code>新版文件。</p>
|
||||
<pre class="hljs"><code>mindMap.export(<span class="hljs-string">'xmind'</span>, <span class="hljs-string">'文件名'</span>)
|
||||
</code></pre>
|
||||
<h3>导出为txt</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.8+</p>
|
||||
</blockquote>
|
||||
<p>导出为<code>txt</code>文件只要传递默认的三个参数即可:</p>
|
||||
<pre class="hljs"><code>mindMap.export(<span class="hljs-string">'txt'</span>, <span class="hljs-literal">true</span>, <span class="hljs-string">'文件名'</span>)
|
||||
</code></pre>
|
||||
<h2>导入</h2>
|
||||
<p>目前支持从<code>.smm</code>、<code>.json</code>、<code>.xmind</code>、<code>.xlsx</code>、<code>.md</code>格式的文件导入。</p>
|
||||
<h3>导入smm、json</h3>
|
||||
|
||||
@ -139,4 +139,10 @@ import ExportXMind from 'simple-mind-map/src/plugins/ExportXMind.js'
|
||||
MindMap.usePlugin(ExportXMind)
|
||||
```
|
||||
|
||||
导出为`xmind`文件类型,异步方法,返回一个`Promise`实例,返回的数据为一个`zip`压缩包的`data:url`数据,可以直接下载。
|
||||
导出为`xmind`文件类型,异步方法,返回一个`Promise`实例,返回的数据为一个`zip`压缩包的`data:url`数据,可以直接下载。
|
||||
|
||||
### txt()
|
||||
|
||||
> v0.9.8+
|
||||
|
||||
导出`txt`文件。
|
||||
@ -129,6 +129,11 @@ MindMap.usePlugin(ExportPDF)
|
||||
MindMap.usePlugin(ExportXMind)
|
||||
</code></pre>
|
||||
<p>导出为<code>xmind</code>文件类型,异步方法,返回一个<code>Promise</code>实例,返回的数据为一个<code>zip</code>压缩包的<code>data:url</code>数据,可以直接下载。</p>
|
||||
<h3>txt()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.8+</p>
|
||||
</blockquote>
|
||||
<p>导出<code>txt</code>文件。</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -20,6 +20,14 @@
|
||||
- [x] 提供丰富的配置,满足各种场景各种使用习惯
|
||||
- [x] 支持协同编辑
|
||||
|
||||
> 不会实现的特性:
|
||||
>
|
||||
> 1.自由节点,即多个根节点;
|
||||
>
|
||||
> 2.概要节点后面继续添加节点;
|
||||
>
|
||||
> 如果你需要以上特性,那么本库可能无法满足你的需求。
|
||||
|
||||
## 仓库目录介绍
|
||||
|
||||
1.`simple-mind-map`
|
||||
@ -292,4 +300,24 @@
|
||||
<img src="../../../../assets/avatar/慕智打印-兰兰.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>慕智打印-兰兰</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>锦冰</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/旭东.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>旭东</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/俊奇.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>俊奇</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/橘半.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>橘半</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/pluvet.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>pluvet</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -8,29 +8,35 @@
|
||||
</blockquote>
|
||||
<h2>特性</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox0" checked="true" /><label for="checkbox0">插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小打包体积</label></li>
|
||||
<li><input type="checkbox" id="checkbox1" checked="true" /><label for="checkbox1">支持逻辑结构图、思维导图、组织结构图、目录组织图、时间轴(横向、竖向)、鱼骨图等结构</label></li>
|
||||
<li><input type="checkbox" id="checkbox2" checked="true" /><label for="checkbox2">内置多种主题,允许高度自定义样式,支持注册新主题</label></li>
|
||||
<li><input type="checkbox" id="checkbox3" checked="true" /><label for="checkbox3">节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要、数学公式</label></li>
|
||||
<li><input type="checkbox" id="checkbox4" checked="true" /><label for="checkbox4">节点支持拖拽(拖拽移动、自由调整)、多种节点形状,支持使用 DDM 完全自定义节点内容</label></li>
|
||||
<li><input type="checkbox" id="checkbox5" checked="true" /><label for="checkbox5">支持画布拖动、缩放</label></li>
|
||||
<li><input type="checkbox" id="checkbox6" checked="true" /><label for="checkbox6">支持鼠标按键拖动选择和Ctrl+左键两种多选节点方式</label></li>
|
||||
<li><input type="checkbox" id="checkbox7" checked="true" /><label for="checkbox7">支持导出为</label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>,支持从<code>json</code>、<code>xmind</code>、<code>markdown</code>导入</li>
|
||||
<li><input type="checkbox" id="checkbox8" checked="true" /><label for="checkbox8">支持快捷键、前进后退、关联线、搜索替换、小地图、水印、滚动条</label></li>
|
||||
<li><input type="checkbox" id="checkbox9" checked="true" /><label for="checkbox9">提供丰富的配置,满足各种场景各种使用习惯</label></li>
|
||||
<li><input type="checkbox" id="checkbox10" checked="true" /><label for="checkbox10">支持协同编辑</label></li>
|
||||
<li><input type="checkbox" id="checkbox64" checked="true" /><label for="checkbox64">插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小打包体积</label></li>
|
||||
<li><input type="checkbox" id="checkbox65" checked="true" /><label for="checkbox65">支持逻辑结构图、思维导图、组织结构图、目录组织图、时间轴(横向、竖向)、鱼骨图等结构</label></li>
|
||||
<li><input type="checkbox" id="checkbox66" checked="true" /><label for="checkbox66">内置多种主题,允许高度自定义样式,支持注册新主题</label></li>
|
||||
<li><input type="checkbox" id="checkbox67" checked="true" /><label for="checkbox67">节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要、数学公式</label></li>
|
||||
<li><input type="checkbox" id="checkbox68" checked="true" /><label for="checkbox68">节点支持拖拽(拖拽移动、自由调整)、多种节点形状,支持使用 DDM 完全自定义节点内容</label></li>
|
||||
<li><input type="checkbox" id="checkbox69" checked="true" /><label for="checkbox69">支持画布拖动、缩放</label></li>
|
||||
<li><input type="checkbox" id="checkbox70" checked="true" /><label for="checkbox70">支持鼠标按键拖动选择和Ctrl+左键两种多选节点方式</label></li>
|
||||
<li><input type="checkbox" id="checkbox71" checked="true" /><label for="checkbox71">支持导出为</label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>,支持从<code>json</code>、<code>xmind</code>、<code>markdown</code>导入</li>
|
||||
<li><input type="checkbox" id="checkbox72" checked="true" /><label for="checkbox72">支持快捷键、前进后退、关联线、搜索替换、小地图、水印、滚动条</label></li>
|
||||
<li><input type="checkbox" id="checkbox73" checked="true" /><label for="checkbox73">提供丰富的配置,满足各种场景各种使用习惯</label></li>
|
||||
<li><input type="checkbox" id="checkbox74" checked="true" /><label for="checkbox74">支持协同编辑</label></li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p>不会实现的特性:</p>
|
||||
<p>1.自由节点,即多个根节点;</p>
|
||||
<p>2.概要节点后面继续添加节点;</p>
|
||||
<p>如果你需要以上特性,那么本库可能无法满足你的需求。</p>
|
||||
</blockquote>
|
||||
<h2>仓库目录介绍</h2>
|
||||
<p>1.<code>simple-mind-map</code></p>
|
||||
<p>思维导图库,框架无关,<code>Vue</code>、<code>React</code>等框架或无框架都可以使用。</p>
|
||||
<p>2.<code>web</code></p>
|
||||
<p>使用<code>simple-mind-map</code>库,基于<code>vue2.x</code>、<code>ElementUI</code>搭建的在线思维导图。特性:</p>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox11" checked="true" /><label for="checkbox11">工具栏,支持插入节点、删除节点;编辑节点图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox12" checked="true" /><label for="checkbox12">侧边栏,基础样式设置面板、节点样式设置面板、大纲面板、主题选择面板、结构选择面板</label></li>
|
||||
<li><input type="checkbox" id="checkbox13" checked="true" /><label for="checkbox13">导入导出功能;数据默认保存在浏览器本地存储,也支持直接创建、打开、编辑电脑本地文件</label></li>
|
||||
<li><input type="checkbox" id="checkbox14" checked="true" /><label for="checkbox14">右键菜单,支持展开、收起、整理布局等操作</label></li>
|
||||
<li><input type="checkbox" id="checkbox15" checked="true" /><label for="checkbox15">底部栏,支持节点数量、字数统计;支持切换编辑和只读模式;支持放大缩小;支持全屏切换;支持小地图</label></li>
|
||||
<li><input type="checkbox" id="checkbox75" checked="true" /><label for="checkbox75">工具栏,支持插入节点、删除节点;编辑节点图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox76" checked="true" /><label for="checkbox76">侧边栏,基础样式设置面板、节点样式设置面板、大纲面板、主题选择面板、结构选择面板</label></li>
|
||||
<li><input type="checkbox" id="checkbox77" checked="true" /><label for="checkbox77">导入导出功能;数据默认保存在浏览器本地存储,也支持直接创建、打开、编辑电脑本地文件</label></li>
|
||||
<li><input type="checkbox" id="checkbox78" checked="true" /><label for="checkbox78">右键菜单,支持展开、收起、整理布局等操作</label></li>
|
||||
<li><input type="checkbox" id="checkbox79" checked="true" /><label for="checkbox79">底部栏,支持节点数量、字数统计;支持切换编辑和只读模式;支持放大缩小;支持全屏切换;支持小地图</label></li>
|
||||
</ul>
|
||||
<p>提供文档页面服务。</p>
|
||||
<p>3.<code>dist</code></p>
|
||||
@ -249,6 +255,26 @@
|
||||
<img src="../../../../assets/avatar/慕智打印-兰兰.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>慕智打印-兰兰</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>锦冰</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/旭东.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>旭东</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/俊奇.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>俊奇</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/橘半.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>橘半</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/pluvet.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>pluvet</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -56,6 +56,18 @@
|
||||
|
||||
## 方法
|
||||
|
||||
### highlight()
|
||||
|
||||
> v0.9.8+
|
||||
|
||||
高亮节点。
|
||||
|
||||
### closeHighlight()
|
||||
|
||||
> v0.9.8+
|
||||
|
||||
取消高亮节点。
|
||||
|
||||
### getPureData(removeActiveState = true, removeId = false)
|
||||
|
||||
> v0.9.0+
|
||||
|
||||
@ -31,6 +31,16 @@
|
||||
</blockquote>
|
||||
<p>节点是否正在拖拽中</p>
|
||||
<h2>方法</h2>
|
||||
<h3>highlight()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.8+</p>
|
||||
</blockquote>
|
||||
<p>高亮节点。</p>
|
||||
<h3>closeHighlight()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.8+</p>
|
||||
</blockquote>
|
||||
<p>取消高亮节点。</p>
|
||||
<h3>getPureData(removeActiveState = true, removeId = false)</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.0+</p>
|
||||
|
||||
@ -21,3 +21,9 @@
|
||||
- `node`:要进入编辑的节点实例
|
||||
|
||||
手动开启节点编辑。默认会在节点双击、按 F2 时进入节点编辑。
|
||||
|
||||
### getCurrentEditNode()
|
||||
|
||||
> v0.9.8+
|
||||
|
||||
获取当前正在编辑中的节点实例。
|
||||
@ -14,6 +14,11 @@
|
||||
<li><code>node</code>:要进入编辑的节点实例</li>
|
||||
</ul>
|
||||
<p>手动开启节点编辑。默认会在节点双击、按 F2 时进入节点编辑。</p>
|
||||
<h3>getCurrentEditNode()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.8+</p>
|
||||
</blockquote>
|
||||
<p>获取当前正在编辑中的节点实例。</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -30,7 +30,7 @@ export default {
|
||||
computed: {
|
||||
...mapState({
|
||||
isZenMode: state => state.localConfig.isZenMode,
|
||||
isDark: state => state.isDark,
|
||||
isDark: state => state.localConfig.isDark,
|
||||
activeSidebar: state => state.activeSidebar
|
||||
})
|
||||
},
|
||||
|
||||
@ -1004,7 +1004,11 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['activeSidebar', 'localConfig', 'isDark']),
|
||||
...mapState({
|
||||
activeSidebar: state => state.activeSidebar,
|
||||
localConfig: state => state.localConfig,
|
||||
isDark: state => state.localConfig.isDark
|
||||
}),
|
||||
lineStyleList() {
|
||||
return lineStyleList[this.$i18n.locale] || lineStyleList.zh
|
||||
},
|
||||
|
||||
@ -45,7 +45,9 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['isDark']),
|
||||
...mapState({
|
||||
isDark: state => state.localConfig.isDark
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
color() {
|
||||
|
||||
@ -88,6 +88,9 @@
|
||||
<div class="item" @click="exec('REMOVE_NOTE')" v-if="hasNote">
|
||||
<span class="name">{{ $t('contextmenu.removeNote') }}</span>
|
||||
</div>
|
||||
<div class="item" @click="exec('REMOVE_CUSTOM_STYLES')">
|
||||
<span class="name">{{ $t('contextmenu.removeCustomStyles') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="type === 'svg'">
|
||||
<div class="item" @click="exec('RETURN_CENTER')">
|
||||
@ -125,6 +128,11 @@
|
||||
<span class="name">{{ $t('contextmenu.zenMode') }}</span>
|
||||
{{ isZenMode ? '√' : '' }}
|
||||
</div>
|
||||
<div class="item" @click="exec('REMOVE_ALL_NODE_CUSTOM_STYLES')">
|
||||
<span class="name">{{
|
||||
$t('contextmenu.removeAllNodeCustomStyles')
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="item" @click="createNewFile" v-if="IS_ELECTRON">
|
||||
{{ $t('contextmenu.create') }}
|
||||
</div>
|
||||
@ -163,7 +171,7 @@ export default {
|
||||
computed: {
|
||||
...mapState({
|
||||
isZenMode: state => state.localConfig.isZenMode,
|
||||
isDark: state => state.isDark
|
||||
isDark: state => state.localConfig.isDark
|
||||
}),
|
||||
expandList() {
|
||||
return [
|
||||
|
||||
@ -36,7 +36,9 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['isDark']),
|
||||
...mapState({
|
||||
isDark: state => state.localConfig.isDark
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on('data_change', this.onDataChange)
|
||||
|
||||
@ -98,7 +98,7 @@ MindMap.usePlugin(MiniMap)
|
||||
.usePlugin(SearchPlugin)
|
||||
.usePlugin(Painter)
|
||||
.usePlugin(Formula)
|
||||
// .usePlugin(Cooperate)// 协同插件
|
||||
// .usePlugin(Cooperate) // 协同插件
|
||||
|
||||
// 注册自定义主题
|
||||
customThemeList.forEach(item => {
|
||||
@ -766,7 +766,7 @@ export default {
|
||||
if (this.mindMap.cooperate && this.$route.query.userName) {
|
||||
this.mindMap.cooperate.setProvider(null, {
|
||||
roomName: 'demo-room',
|
||||
signalingList: ['ws://192.168.3.125:4444']
|
||||
signalingList: ['ws://10.16.83.11:4444']
|
||||
})
|
||||
this.mindMap.cooperate.setUserInfo({
|
||||
id: Math.random(),
|
||||
|
||||
@ -113,8 +113,8 @@ export default {
|
||||
computed: {
|
||||
...mapState({
|
||||
openNodeRichText: state => state.localConfig.openNodeRichText,
|
||||
isDark: state => state.isDark,
|
||||
localFileName: state => state.fileName
|
||||
localFileName: state => state.fileName,
|
||||
isDark: state => state.localConfig.isDark
|
||||
}),
|
||||
|
||||
downTypeList() {
|
||||
@ -310,6 +310,14 @@ export default {
|
||||
&.smm {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
&.xmind {
|
||||
color: #f55e5e;
|
||||
}
|
||||
|
||||
&.txt {
|
||||
color: #70798e;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
|
||||
@ -53,7 +53,11 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['activeSidebar', 'isDark', 'localConfig'])
|
||||
...mapState({
|
||||
activeSidebar: state => state.activeSidebar,
|
||||
isDark: state => state.localConfig.isDark,
|
||||
localConfig: state => state.localConfig
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
activeSidebar(val) {
|
||||
|
||||
@ -8,10 +8,12 @@
|
||||
<el-upload
|
||||
ref="upload"
|
||||
action="x"
|
||||
accept=".smm,.json,.xmind,.xlsx,.md"
|
||||
:file-list="fileList"
|
||||
:auto-upload="false"
|
||||
:multiple="false"
|
||||
:on-change="onChange"
|
||||
:on-remove="onRemove"
|
||||
:limit="1"
|
||||
:on-exceed="onExceed"
|
||||
>
|
||||
@ -117,6 +119,11 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 移除文件
|
||||
onRemove(file, fileList) {
|
||||
this.fileList = fileList
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-08-03 22:48:47
|
||||
|
||||
@ -54,7 +54,9 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['isDark'])
|
||||
...mapState({
|
||||
isDark: state => state.localConfig.isDark
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
this.setSize()
|
||||
|
||||
@ -132,13 +132,16 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['isDark', 'isReadonly'])
|
||||
...mapState({
|
||||
isReadonly: state => state.isReadonly,
|
||||
isDark: state => state.localConfig.isDark
|
||||
})
|
||||
},
|
||||
created() {
|
||||
this.lang = getLang()
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setIsDark', 'setIsReadonly']),
|
||||
...mapMutations(['setLocalConfig', 'setIsReadonly']),
|
||||
|
||||
readonlyChange() {
|
||||
this.setIsReadonly(!this.isReadonly)
|
||||
@ -165,7 +168,9 @@ export default {
|
||||
},
|
||||
|
||||
toggleDark() {
|
||||
this.setIsDark(!this.isDark)
|
||||
this.setLocalConfig({
|
||||
isDark: !this.isDark
|
||||
})
|
||||
},
|
||||
|
||||
handleCommand(command) {
|
||||
|
||||
@ -100,8 +100,6 @@ export default {
|
||||
},
|
||||
|
||||
handleShowNodeLink() {
|
||||
this.activeNodes[0].mindMap.keyCommand.pause()
|
||||
this.$bus.$emit('startTextEdit')
|
||||
this.dialogVisible = true
|
||||
},
|
||||
|
||||
@ -112,8 +110,6 @@ export default {
|
||||
*/
|
||||
cancel() {
|
||||
this.dialogVisible = false
|
||||
this.activeNodes[0].mindMap.keyCommand.recovery()
|
||||
this.$bus.$emit('endTextEdit')
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||