mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-22 09:10:29 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
067131f76d | ||
|
|
f689d333f9 | ||
|
|
b3059bb6a3 | ||
|
|
b135f6a61c | ||
|
|
2a8b71497f | ||
|
|
726ebc5e88 | ||
|
|
2c56cd453c | ||
|
|
bf2f9b2697 | ||
|
|
fbd061e8b3 | ||
|
|
680320ba76 | ||
|
|
0d992bd6b1 | ||
|
|
c80eacc5e7 | ||
|
|
6d202b4b7d | ||
|
|
94478fe9f3 | ||
|
|
5745e4567b | ||
|
|
c6a3f4ac7b |
@@ -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?5afd1a8b2213b3355dce" rel="stylesheet"><link href="dist/css/app.css?5afd1a8b2213b3355dce" 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?385fe6c0328bd2e58384" rel="stylesheet"><link href="dist/css/app.css?385fe6c0328bd2e58384" 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?5afd1a8b2213b3355dce"></script><script src="dist/js/app.js?5afd1a8b2213b3355dce"></script></body></html>
|
||||
}</script><script src="dist/js/chunk-vendors.js?385fe6c0328bd2e58384"></script><script src="dist/js/app.js?385fe6c0328bd2e58384"></script></body></html>
|
||||
4
simple-mind-map/package-lock.json
generated
4
simple-mind-map/package-lock.json
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.6.12",
|
||||
"version": "0.6.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "0.6.12",
|
||||
"version": "0.6.13",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@svgdotjs/svg.js": "^3.0.16",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.6.13",
|
||||
"version": "0.6.14",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@@ -127,12 +127,29 @@ export const defaultOpt = {
|
||||
customInnerElsAppendTo: null,
|
||||
// 拖拽元素时,指示元素新位置的块的最大高度
|
||||
nodeDragPlaceholderMaxSize: 20,
|
||||
// 是否允许创建一个隐藏的输入框,该输入框会在节点激活时聚焦,用于粘贴数据和自动进入文本编辑状态
|
||||
enableCreateHiddenInput: true,
|
||||
// 是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式
|
||||
// 该配置在enableCreateHiddenInput设为true时生效
|
||||
enableAutoEnterTextEditWhenKeydown: true,
|
||||
// 开启该特性后,需要给你的输入框绑定keydown事件,并禁止冒泡
|
||||
enableAutoEnterTextEditWhenKeydown: false,
|
||||
// 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果
|
||||
// 需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果
|
||||
richTextEditFakeInPlace: false
|
||||
richTextEditFakeInPlace: false,
|
||||
// 自定义对剪贴板文本的处理。当按ctrl+v粘贴时会读取用户剪贴板中的文本和图片,默认只会判断文本是否是普通文本和simple-mind-map格式的节点数据,如果你想处理其他思维导图的数据,比如processon、zhixi等,那么可以传递一个函数,接受当前剪贴板中的文本为参数,返回处理后的数据,可以返回两种类型:
|
||||
/*
|
||||
1.返回一个纯文本,那么会直接以该文本创建一个子节点
|
||||
|
||||
2.返回一个节点对象,格式如下:
|
||||
{
|
||||
// 代表是simple-mind-map格式的数据
|
||||
simpleMindMap: true,
|
||||
// 节点数据,同simple-mind-map节点数据格式
|
||||
data: {
|
||||
data: {
|
||||
text: ''
|
||||
},
|
||||
children: []
|
||||
}
|
||||
}
|
||||
*/
|
||||
// 如果你的处理逻辑存在异步逻辑,也可以返回一个promise
|
||||
customHandleClipboardText: null
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import {
|
||||
simpleDeepClone,
|
||||
walk,
|
||||
bfsWalk,
|
||||
loadImage
|
||||
loadImage,
|
||||
isUndef
|
||||
} from '../../utils'
|
||||
import { shapeList } from './node/Shape'
|
||||
import { lineStyleProps } from '../../themes/default'
|
||||
@@ -108,10 +109,6 @@ class Render {
|
||||
this.mindMap.execCommand('CLEAR_ACTIVE_NODE')
|
||||
}
|
||||
})
|
||||
// 粘贴事件
|
||||
this.mindMap.on('paste', data => {
|
||||
this.onPaste(data)
|
||||
})
|
||||
// let timer = null
|
||||
// this.mindMap.on('view_data_change', () => {
|
||||
// clearTimeout(timer)
|
||||
@@ -273,8 +270,7 @@ class Render {
|
||||
this.copy = this.copy.bind(this)
|
||||
this.mindMap.keyCommand.addShortcut('Control+c', this.copy)
|
||||
this.mindMap.keyCommand.addShortcut('Control+v', () => {
|
||||
// 隐藏输入框可能会失去焦点,所以要重新聚焦
|
||||
this.textEdit.focusHiddenInput()
|
||||
this.onPaste()
|
||||
})
|
||||
this.cut = this.cut.bind(this)
|
||||
this.mindMap.keyCommand.addShortcut('Control+x', this.cut)
|
||||
@@ -449,7 +445,12 @@ class Render {
|
||||
}
|
||||
|
||||
// 插入同级节点,多个节点只会操作第一个节点
|
||||
insertNode(openEdit = true, appointNodes = [], appointData = null) {
|
||||
insertNode(
|
||||
openEdit = true,
|
||||
appointNodes = [],
|
||||
appointData = null,
|
||||
appointChildren = []
|
||||
) {
|
||||
appointNodes = this.formatAppointNodes(appointNodes)
|
||||
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
|
||||
return
|
||||
@@ -485,14 +486,19 @@ class Render {
|
||||
resetRichText: isRichText,
|
||||
...(appointData || {})
|
||||
},
|
||||
children: []
|
||||
children: [...appointChildren]
|
||||
})
|
||||
this.mindMap.render()
|
||||
}
|
||||
}
|
||||
|
||||
// 插入子节点
|
||||
insertChildNode(openEdit = true, appointNodes = [], appointData = null) {
|
||||
insertChildNode(
|
||||
openEdit = true,
|
||||
appointNodes = [],
|
||||
appointData = null,
|
||||
appointChildren = []
|
||||
) {
|
||||
appointNodes = this.formatAppointNodes(appointNodes)
|
||||
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
|
||||
return
|
||||
@@ -523,7 +529,7 @@ class Render {
|
||||
resetRichText: isRichText,
|
||||
...(appointData || {})
|
||||
},
|
||||
children: []
|
||||
children: [...appointChildren]
|
||||
})
|
||||
// 插入子节点时自动展开子节点
|
||||
node.nodeData.data.expand = true
|
||||
@@ -591,15 +597,29 @@ class Render {
|
||||
// 复制节点
|
||||
copy() {
|
||||
this.beingCopyData = this.copyNode()
|
||||
this.setCoptyDataToClipboard(this.beingCopyData)
|
||||
}
|
||||
|
||||
// 剪切节点
|
||||
cut() {
|
||||
this.mindMap.execCommand('CUT_NODE', copyData => {
|
||||
this.beingCopyData = copyData
|
||||
this.setCoptyDataToClipboard(copyData)
|
||||
})
|
||||
}
|
||||
|
||||
// 将粘贴或剪切的数据设置到用户剪切板中
|
||||
setCoptyDataToClipboard(data) {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(
|
||||
JSON.stringify({
|
||||
simpleMindMap: true,
|
||||
data
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 粘贴节点
|
||||
paste() {
|
||||
if (this.beingCopyData) {
|
||||
@@ -608,7 +628,28 @@ class Render {
|
||||
}
|
||||
|
||||
// 粘贴事件
|
||||
async onPaste({ text, img }) {
|
||||
async onPaste() {
|
||||
// 读取剪贴板的文字和图片
|
||||
let text = null
|
||||
let img = null
|
||||
if (navigator.clipboard) {
|
||||
try {
|
||||
text = await navigator.clipboard.readText()
|
||||
const items = await navigator.clipboard.read()
|
||||
if (items && items.length > 0) {
|
||||
for (const clipboardItem of items) {
|
||||
for (const type of clipboardItem.types) {
|
||||
if (/^image\//.test(type)) {
|
||||
img = await clipboardItem.getType(type)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
// 检查剪切板数据是否有变化
|
||||
// 通过图片大小来判断图片是否发生变化,可能是不准确的,但是目前没有其他好方法
|
||||
const imgSize = img ? img.size : 0
|
||||
@@ -626,9 +667,47 @@ class Render {
|
||||
if (this.currentBeingPasteType === CONSTANTS.PASTE_TYPE.CLIP_BOARD) {
|
||||
// 存在文本,则创建子节点
|
||||
if (text) {
|
||||
this.mindMap.execCommand('INSERT_CHILD_NODE', false, [], {
|
||||
text
|
||||
})
|
||||
// 判断粘贴的是否是simple-mind-map的数据
|
||||
let smmData = null
|
||||
let useDefault = true
|
||||
// 用户自定义处理
|
||||
if (this.mindMap.opt.customHandleClipboardText) {
|
||||
try {
|
||||
const res = await this.mindMap.opt.customHandleClipboardText(text)
|
||||
if (!isUndef(res)) {
|
||||
useDefault = false
|
||||
if (typeof res === 'object' && res.simpleMindMap) {
|
||||
smmData = res.data
|
||||
} else {
|
||||
text = String(res)
|
||||
}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
// 默认处理
|
||||
if (useDefault) {
|
||||
try {
|
||||
const parsedData = JSON.parse(text)
|
||||
if (parsedData && parsedData.simpleMindMap) {
|
||||
smmData = parsedData.data
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
if (smmData) {
|
||||
this.mindMap.execCommand(
|
||||
'INSERT_CHILD_NODE',
|
||||
false,
|
||||
[],
|
||||
{
|
||||
...smmData.data
|
||||
},
|
||||
[...smmData.children]
|
||||
)
|
||||
} else {
|
||||
this.mindMap.execCommand('INSERT_CHILD_NODE', false, [], {
|
||||
text
|
||||
})
|
||||
}
|
||||
}
|
||||
// 存在图片,则添加到当前激活节点
|
||||
if (img) {
|
||||
@@ -1027,7 +1106,8 @@ class Render {
|
||||
}
|
||||
|
||||
// 设置节点图片
|
||||
setNodeImage(node, { url, title, width, height, custom = false }) {
|
||||
setNodeImage(node, data) {
|
||||
const { url, title, width, height, custom = false } = data || { url: '', title: '', width: 0, height: 0, custom: false }
|
||||
this.setNodeDataRender(node, {
|
||||
image: url,
|
||||
imageTitle: title || '',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getStrWithBrFromHtml, checkNodeOuter, isMobile } from '../../utils'
|
||||
import { getStrWithBrFromHtml, checkNodeOuter } from '../../utils'
|
||||
|
||||
// 节点文字编辑类
|
||||
export default class TextEdit {
|
||||
@@ -10,16 +10,11 @@ export default class TextEdit {
|
||||
this.currentNode = null
|
||||
// 文本编辑框
|
||||
this.textEditNode = null
|
||||
// 隐藏的文本输入框
|
||||
this.hiddenInputEl = null
|
||||
// 节点激活时默认聚焦到隐藏输入框
|
||||
this.enableFocus = true
|
||||
// 文本编辑框是否显示
|
||||
this.showTextEdit = false
|
||||
// 如果编辑过程中缩放画布了,那么缓存当前编辑的内容
|
||||
this.cacheEditingText = ''
|
||||
this.bindEvent()
|
||||
this.createHiddenInput()
|
||||
}
|
||||
|
||||
// 事件
|
||||
@@ -51,10 +46,6 @@ export default class TextEdit {
|
||||
this.mindMap.on('before_node_active', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
// 节点激活事件
|
||||
this.mindMap.on('node_active', () => {
|
||||
this.focusHiddenInput()
|
||||
})
|
||||
// 注册编辑快捷键
|
||||
this.mindMap.keyCommand.addShortcut('F2', () => {
|
||||
if (this.renderer.activeNodeList.length <= 0) {
|
||||
@@ -63,74 +54,29 @@ export default class TextEdit {
|
||||
this.show(this.renderer.activeNodeList[0])
|
||||
})
|
||||
this.mindMap.on('scale', this.onScale)
|
||||
}
|
||||
|
||||
// 创建一个隐藏的文本输入框
|
||||
createHiddenInput() {
|
||||
const { enableCreateHiddenInput, enableAutoEnterTextEditWhenKeydown } =
|
||||
this.mindMap.opt
|
||||
if (this.hiddenInputEl || isMobile() || !enableCreateHiddenInput) return
|
||||
this.hiddenInputEl = document.createElement('input')
|
||||
this.hiddenInputEl.type = 'text'
|
||||
this.hiddenInputEl.style.cssText = `
|
||||
position: fixed;
|
||||
left: -99999px;
|
||||
top: -99999px;
|
||||
`
|
||||
// 监听按键事件
|
||||
if (enableAutoEnterTextEditWhenKeydown) {
|
||||
this.hiddenInputEl.addEventListener('keydown', e => {
|
||||
// // 监听按键事件,判断是否自动进入文本编辑模式
|
||||
if (this.mindMap.opt.enableAutoEnterTextEditWhenKeydown) {
|
||||
window.addEventListener('keydown', e => {
|
||||
const activeNodeList = this.mindMap.renderer.activeNodeList
|
||||
if (activeNodeList.length <= 0 || activeNodeList.length > 1) return
|
||||
const node = activeNodeList[0]
|
||||
// 当正在输入中文或英文或数字时,如果没有按下组合键,那么自动进入文本编辑模式
|
||||
const keyCode = e.keyCode
|
||||
if (
|
||||
node &&
|
||||
(keyCode === 229 ||
|
||||
(keyCode >= 65 && keyCode <= 90) ||
|
||||
(keyCode >= 48 && keyCode <= 57)) &&
|
||||
!this.mindMap.keyCommand.hasCombinationKey(e)
|
||||
) {
|
||||
if (node && this.checkIsAutoEnterTextEditKey(e)) {
|
||||
this.show(node)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 监听粘贴事件
|
||||
this.hiddenInputEl.addEventListener('paste', async event => {
|
||||
event.preventDefault()
|
||||
const text = (event.clipboardData || window.clipboardData).getData('text')
|
||||
const files = event.clipboardData.files
|
||||
let img = null
|
||||
if (files.length > 0) {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
if (/^image\//.test(files[i].type)) {
|
||||
img = files[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this.mindMap.emit('paste', {
|
||||
text,
|
||||
img
|
||||
})
|
||||
})
|
||||
document.body.appendChild(this.hiddenInputEl)
|
||||
}
|
||||
|
||||
// 让隐藏的文本输入框聚焦
|
||||
focusHiddenInput() {
|
||||
if (this.hiddenInputEl && this.enableFocus) this.hiddenInputEl.focus()
|
||||
}
|
||||
|
||||
// 关闭默认聚焦
|
||||
stopFocusOnNodeActive() {
|
||||
this.enableFocus = false
|
||||
}
|
||||
|
||||
// 开启默认聚焦
|
||||
openFocusOnNodeActive() {
|
||||
this.enableFocus = true
|
||||
// 判断是否是自动进入文本编模式的按钮
|
||||
checkIsAutoEnterTextEditKey(e) {
|
||||
const keyCode = e.keyCode
|
||||
return (
|
||||
(keyCode === 229 ||
|
||||
(keyCode >= 65 && keyCode <= 90) ||
|
||||
(keyCode >= 48 && keyCode <= 57)) &&
|
||||
!this.mindMap.keyCommand.hasCombinationKey(e)
|
||||
)
|
||||
}
|
||||
|
||||
// 注册临时快捷键
|
||||
@@ -188,6 +134,7 @@ export default class TextEdit {
|
||||
|
||||
// 显示文本编辑框
|
||||
showEditTextBox(node, rect, isInserting) {
|
||||
if (this.showTextEdit) return
|
||||
this.mindMap.emit('before_show_text_edit')
|
||||
this.registerTmpShortcut()
|
||||
if (!this.textEditNode) {
|
||||
@@ -203,6 +150,11 @@ export default class TextEdit {
|
||||
this.textEditNode.addEventListener('mousedown', e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
this.textEditNode.addEventListener('keydown', e => {
|
||||
if (this.checkIsAutoEnterTextEditKey(e)) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
})
|
||||
const targetNode =
|
||||
this.mindMap.opt.customInnerElsAppendTo || document.body
|
||||
targetNode.appendChild(this.textEditNode)
|
||||
|
||||
@@ -64,13 +64,13 @@ const transformXmind = async (content, files) => {
|
||||
}
|
||||
// 图片
|
||||
if (node.image && /\.(jpg|jpeg|png|gif|webp)$/.test(node.image.src)) {
|
||||
// 处理异步逻辑
|
||||
let resolve = null
|
||||
let promise = new Promise(_resolve => {
|
||||
resolve = _resolve
|
||||
})
|
||||
waitLoadImageList.push(promise)
|
||||
try {
|
||||
// 处理异步逻辑
|
||||
let resolve = null
|
||||
let promise = new Promise(_resolve => {
|
||||
resolve = _resolve
|
||||
})
|
||||
waitLoadImageList.push(promise)
|
||||
// 读取图片
|
||||
let imageType = /\.([^.]+)$/.exec(node.image.src)[1]
|
||||
let imageBase64 =
|
||||
|
||||
@@ -198,6 +198,11 @@ class RichText {
|
||||
this.textEditNode.addEventListener('mousedown', e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
this.textEditNode.addEventListener('keydown', e => {
|
||||
if (this.mindMap.renderer.textEdit.checkIsAutoEnterTextEditKey(e)) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
})
|
||||
const targetNode = customInnerElsAppendTo || document.body
|
||||
targetNode.appendChild(this.textEditNode)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2479351 */
|
||||
src: url('iconfont.woff2?t=1690537337895') format('woff2'),
|
||||
url('iconfont.woff?t=1690537337895') format('woff'),
|
||||
url('iconfont.ttf?t=1690537337895') format('truetype');
|
||||
src: url('iconfont.woff2?t=1691822758372') format('woff2'),
|
||||
url('iconfont.woff?t=1691822758372') format('woff'),
|
||||
url('iconfont.ttf?t=1691822758372') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@@ -13,6 +13,10 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icontouming:before {
|
||||
content: "\e60c";
|
||||
}
|
||||
|
||||
.iconlieri:before {
|
||||
content: "\e60b";
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -97,7 +97,8 @@ export const colorList = [
|
||||
'#0C797D',
|
||||
'#0062B1',
|
||||
'#653294',
|
||||
'#AB149E'
|
||||
'#AB149E',
|
||||
'transparent'
|
||||
]
|
||||
|
||||
// 边框宽度
|
||||
|
||||
@@ -77,7 +77,10 @@ export default {
|
||||
level5: 'Level5',
|
||||
level6: 'Level6',
|
||||
zenMode: 'Zen mode',
|
||||
fitCanvas: 'Fit canvas'
|
||||
fitCanvas: 'Fit canvas',
|
||||
removeImage: 'Remove image',
|
||||
removeHyperlink: 'Remove hyperlink',
|
||||
removeNote: 'Remove note'
|
||||
},
|
||||
count: {
|
||||
words: 'Words',
|
||||
@@ -167,6 +170,7 @@ export default {
|
||||
italic: 'Italic',
|
||||
textDecoration: 'Text decoration',
|
||||
underline: 'Underline',
|
||||
none: 'None',
|
||||
lineThrough: 'Line through',
|
||||
overline: 'Overline',
|
||||
border: 'Border',
|
||||
|
||||
@@ -77,7 +77,10 @@ export default {
|
||||
level5: '五级主题',
|
||||
level6: '六级主题',
|
||||
zenMode: '禅模式',
|
||||
fitCanvas: '适应画布'
|
||||
fitCanvas: '适应画布',
|
||||
removeImage: '移除图片',
|
||||
removeHyperlink: '移除超链接',
|
||||
removeNote: '移除备注'
|
||||
},
|
||||
count: {
|
||||
words: '字数',
|
||||
@@ -166,6 +169,7 @@ export default {
|
||||
addFontWeight: '加粗',
|
||||
italic: '斜体',
|
||||
textDecoration: '划线',
|
||||
none: '无',
|
||||
underline: '下划线',
|
||||
lineThrough: '中划线',
|
||||
overline: '上划线',
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# Changelog
|
||||
|
||||
## 0.6.14
|
||||
|
||||
New:
|
||||
|
||||
> 1.Remove and create hidden input boxes, and copy and paste them through navigator. clipboard; Support cross browser pasting of mind map node data; Support custom processing of text data in the clipboard.
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.Fix the issue of enabling input to automatically enter text editing mode and conflicting with other input boxes.
|
||||
>
|
||||
> 2.Fix the issue of not being able to delete node images in the node image pop-up window.
|
||||
>
|
||||
> 3.Fixed an issue where the text decoration line style of nodes cannot be removed in the node style sidebar.
|
||||
>
|
||||
> 4.The color selector supports selecting transparent colors.
|
||||
>
|
||||
> 5.Fix the issue of importing mind map data without updating the sidebar data when the basic style sidebar is open.
|
||||
>
|
||||
> 6.Fixed the issue of not focusing when modifying the text of one node in the outline and then clicking on other nodes.
|
||||
>
|
||||
> 7.Fixed an issue where the node and word count statistics in the bottom left corner were not updated after exiting Zen mode.
|
||||
>
|
||||
> 8.Support deleting hyperlinks and notes of nodes from the right-click menu.
|
||||
>
|
||||
> 9.Support pasting node data of Zhixi Mind Map.
|
||||
|
||||
## 0.6.13
|
||||
|
||||
Fix:
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.6.14</h2>
|
||||
<p>New:</p>
|
||||
<blockquote>
|
||||
<p>1.Remove and create hidden input boxes, and copy and paste them through navigator. clipboard; Support cross browser pasting of mind map node data; Support custom processing of text data in the clipboard.</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.Fix the issue of enabling input to automatically enter text editing mode and conflicting with other input boxes.</p>
|
||||
<p>2.Fix the issue of not being able to delete node images in the node image pop-up window.</p>
|
||||
<p>3.Fixed an issue where the text decoration line style of nodes cannot be removed in the node style sidebar.</p>
|
||||
<p>4.The color selector supports selecting transparent colors.</p>
|
||||
<p>5.Fix the issue of importing mind map data without updating the sidebar data when the basic style sidebar is open.</p>
|
||||
<p>6.Fixed the issue of not focusing when modifying the text of one node in the outline and then clicking on other nodes.</p>
|
||||
<p>7.Fixed an issue where the node and word count statistics in the bottom left corner were not updated after exiting Zen mode.</p>
|
||||
<p>8.Support deleting hyperlinks and notes of nodes from the right-click menu.</p>
|
||||
<p>9.Support pasting node data of Zhixi Mind Map.</p>
|
||||
</blockquote>
|
||||
<h2>0.6.13</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
|
||||
@@ -73,9 +73,10 @@ const mindMap = new MindMap({
|
||||
| mouseScaleCenterUseMousePosition(v0.6.4-fix.1+) | Boolean | true | Is the mouse zoom centered around the current position of the mouse, otherwise centered around the canvas | |
|
||||
| customInnerElsAppendTo(v0.6.12+) | null/HTMLElement | null | Specify the location where some internal elements (node text editing element, node note display element, associated line text editing element, node image adjustment button element) are added, and default to document.body | |
|
||||
| nodeDragPlaceholderMaxSize(v0.6.12+) | Number | 20 | When dragging an element, the maximum height of the block indicating the new position of the element | |
|
||||
| enableCreateHiddenInput(v0.6.13+) | Boolean | true | Is it allowed to create a hidden input box that will be focused when the node is activated for pasting data and automatically entering the text editing state | |
|
||||
| enableAutoEnterTextEditWhenKeydown(v0.6.13+) | Boolean | true | Does it automatically enter text editing mode when pressing the Chinese, English, or numeric buttons when there is an activation node? This configuration takes effect when enableCreateHiddenInput is set to true | |
|
||||
| enableCreateHiddenInput(v0.6.13+)(v0.6.14+ remove this feature) | Boolean | true | Is it allowed to create a hidden input box that will be focused when the node is activated for pasting data and automatically entering the text editing state | |
|
||||
| enableAutoEnterTextEditWhenKeydown(v0.6.13+) | Boolean | true | Does it automatically enter text editing mode when pressing the Chinese, English, or numeric buttons when there is an activation node?| |
|
||||
| richTextEditFakeInPlace(v0.6.13+) | Boolean | false | Set the rich text node edit box to match the size of the node, creating a pseudo in place editing effect. It should be noted that only when there is only text within the node and the shape is rectangular, can the effect be better | |
|
||||
| customHandleClipboardText(v0.6.14+) | Function | null | Customize the processing of clipboard text. When pressing ctrl+v to paste, it will read the text and images from the user's clipboard. By default, it will only determine whether the text is regular text and node data in simple mind map format. If you want to process data from other mind maps, such as process, zhixi, etc., you can pass a function that takes the text from the current clipboard as a parameter and returns the processed data, which can be of two types: 1.If a pure text is returned, a child node will be directly created with that text; 2.Returns a node object in the following format: { simpleMindMap: true, data: { data: { text: '' }, children: [] } }, The representative is data in simple bind map format, and the node data is in the same format as the simple bind map node data. If your processing logic has asynchronous logic, you can also return a promise | |
|
||||
|
||||
### Watermark config
|
||||
|
||||
@@ -326,8 +327,8 @@ redo. All commands are as follows:
|
||||
| SELECT_ALL | Select all | |
|
||||
| BACK | Go back a specified number of steps | step (the number of steps to go back, default is 1) |
|
||||
| FORWARD | Go forward a specified number of steps | step (the number of steps to go forward, default is 1) |
|
||||
| INSERT_NODE | Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effective | openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true`) 、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) ) |
|
||||
| INSERT_CHILD_NODE | Insert a child node, the active node or appoint node will be the operation node | openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true`)、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) ) |
|
||||
| INSERT_NODE | Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effective | openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true`) 、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) )、 appointChildren(v0.6.14+, Optional, Specify the child nodes of the newly created node, array type) |
|
||||
| INSERT_CHILD_NODE | Insert a child node, the active node or appoint node will be the operation node | openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true`)、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) )、 appointChildren(v0.6.14+, Optional, Specify the child nodes of the newly created node, array type) |
|
||||
| UP_NODE | Move node up, the active node will be the operation node. If there are multiple active nodes, only the first one will be effective. Using this command on the root node or the first node in the list will be invalid | |
|
||||
| DOWN_NODE | Move node down, the active node will be the operation node. If there are multiple active nodes, only the first one will be effective. Using this command on the root node or the last node in the list will be invalid | |
|
||||
| REMOVE_NODE | Remove node, the active node or appoint node will be the operation node | appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array) |
|
||||
|
||||
@@ -372,7 +372,7 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableCreateHiddenInput(v0.6.13+)</td>
|
||||
<td>enableCreateHiddenInput(v0.6.13+)(v0.6.14+ remove this feature)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>Is it allowed to create a hidden input box that will be focused when the node is activated for pasting data and automatically entering the text editing state</td>
|
||||
@@ -382,7 +382,7 @@
|
||||
<td>enableAutoEnterTextEditWhenKeydown(v0.6.13+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>Does it automatically enter text editing mode when pressing the Chinese, English, or numeric buttons when there is an activation node? This configuration takes effect when enableCreateHiddenInput is set to true</td>
|
||||
<td>Does it automatically enter text editing mode when pressing the Chinese, English, or numeric buttons when there is an activation node?</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -392,6 +392,13 @@
|
||||
<td>Set the rich text node edit box to match the size of the node, creating a pseudo in place editing effect. It should be noted that only when there is only text within the node and the shape is rectangular, can the effect be better</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>customHandleClipboardText(v0.6.14+)</td>
|
||||
<td>Function</td>
|
||||
<td>null</td>
|
||||
<td>Customize the processing of clipboard text. When pressing ctrl+v to paste, it will read the text and images from the user's clipboard. By default, it will only determine whether the text is regular text and node data in simple mind map format. If you want to process data from other mind maps, such as process, zhixi, etc., you can pass a function that takes the text from the current clipboard as a parameter and returns the processed data, which can be of two types: 1.If a pure text is returned, a child node will be directly created with that text; 2.Returns a node object in the following format: { simpleMindMap: true, data: { data: { text: '' }, children: [] } }, The representative is data in simple bind map format, and the node data is in the same format as the simple bind map node data. If your processing logic has asynchronous logic, you can also return a promise</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Watermark config</h3>
|
||||
@@ -828,12 +835,12 @@ redo. All commands are as follows:</p>
|
||||
<tr>
|
||||
<td>INSERT_NODE</td>
|
||||
<td>Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effective</td>
|
||||
<td>openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is <code>true</code>) 、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a> )</td>
|
||||
<td>openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is <code>true</code>) 、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a> )、 appointChildren(v0.6.14+, Optional, Specify the child nodes of the newly created node, array type)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>INSERT_CHILD_NODE</td>
|
||||
<td>Insert a child node, the active node or appoint node will be the operation node</td>
|
||||
<td>openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is <code>true</code>)、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a> )</td>
|
||||
<td>openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is <code>true</code>)、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a> )、 appointChildren(v0.6.14+, Optional, Specify the child nodes of the newly created node, array type)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UP_NODE</td>
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# Changelog
|
||||
|
||||
## 0.6.14
|
||||
|
||||
新增:
|
||||
|
||||
> 1.去除创建隐藏输入框,通过navigator.clipboard实现复制粘贴;支持跨浏览器粘贴思维导图节点数据;支持自定义处理剪贴板中的文本数据。
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.修复开启输入自动进入文本编辑模式和其他输入框冲突的问题。
|
||||
>
|
||||
> 2.修复无法在节点图片弹窗里删除节点图片的问题。
|
||||
>
|
||||
> 3.修复在节点样式侧边栏里无法去除节点的文本修饰线样式的问题。
|
||||
>
|
||||
> 4.颜色选择器支持选择透明颜色。
|
||||
>
|
||||
> 5.修复基础样式侧边栏打开状态下,导入思维导图数据后侧边栏数据未更新的问题。
|
||||
>
|
||||
> 6.修复大纲修改一个节点的文本后再点击其他节点时不聚焦的问题。
|
||||
>
|
||||
> 7.修复退出禅模式后左下角的节点和字数统计未更新的问题。
|
||||
>
|
||||
> 8.支持从右键菜单删除节点的超链接、备注。
|
||||
>
|
||||
> 9.支持粘贴知犀思维导图的节点数据。
|
||||
|
||||
## 0.6.13
|
||||
|
||||
修复:
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.6.14</h2>
|
||||
<p>新增:</p>
|
||||
<blockquote>
|
||||
<p>1.去除创建隐藏输入框,通过navigator.clipboard实现复制粘贴;支持跨浏览器粘贴思维导图节点数据;支持自定义处理剪贴板中的文本数据。</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.修复开启输入自动进入文本编辑模式和其他输入框冲突的问题。</p>
|
||||
<p>2.修复无法在节点图片弹窗里删除节点图片的问题。</p>
|
||||
<p>3.修复在节点样式侧边栏里无法去除节点的文本修饰线样式的问题。</p>
|
||||
<p>4.颜色选择器支持选择透明颜色。</p>
|
||||
<p>5.修复基础样式侧边栏打开状态下,导入思维导图数据后侧边栏数据未更新的问题。</p>
|
||||
<p>6.修复大纲修改一个节点的文本后再点击其他节点时不聚焦的问题。</p>
|
||||
<p>7.修复退出禅模式后左下角的节点和字数统计未更新的问题。</p>
|
||||
<p>8.支持从右键菜单删除节点的超链接、备注。</p>
|
||||
<p>9.支持粘贴知犀思维导图的节点数据。</p>
|
||||
</blockquote>
|
||||
<h2>0.6.13</h2>
|
||||
<p>修复:</p>
|
||||
<blockquote>
|
||||
|
||||
@@ -73,9 +73,10 @@ const mindMap = new MindMap({
|
||||
| mouseScaleCenterUseMousePosition(v0.6.4-fix.1+) | Boolean | true | 鼠标缩放是否以鼠标当前位置为中心点,否则以画布中心点 | |
|
||||
| customInnerElsAppendTo(v0.6.12+) | null/HTMLElement | null | 指定内部一些元素(节点文本编辑元素、节点备注显示元素、关联线文本编辑元素、节点图片调整按钮元素)添加到的位置,默认添加到document.body下 | |
|
||||
| nodeDragPlaceholderMaxSize(v0.6.12+) | Number | 20 | 拖拽元素时,指示元素新位置的块的最大高度 | |
|
||||
| enableCreateHiddenInput(v0.6.13+) | Boolean | true | 是否允许创建一个隐藏的输入框,该输入框会在节点激活时聚焦,用于粘贴数据和自动进入文本编辑状态 | |
|
||||
| enableAutoEnterTextEditWhenKeydown(v0.6.13+) | Boolean | true | 是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式,该配置在enableCreateHiddenInput设为true时生效 | |
|
||||
| enableCreateHiddenInput(v0.6.13+)(v0.6.14+版本已去除该特性) | Boolean | true | 是否允许创建一个隐藏的输入框,该输入框会在节点激活时聚焦,用于粘贴数据和自动进入文本编辑状态 | |
|
||||
| enableAutoEnterTextEditWhenKeydown(v0.6.13+) | Boolean | true | 是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式 | |
|
||||
| richTextEditFakeInPlace(v0.6.13+) | Boolean | false | 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果,需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果 | |
|
||||
| customHandleClipboardText(v0.6.14+) | Function | null | 自定义对剪贴板文本的处理。当按ctrl+v粘贴时会读取用户剪贴板中的文本和图片,默认只会判断文本是否是普通文本和simple-mind-map格式的节点数据,如果你想处理其他思维导图的数据,比如processon、zhixi等,那么可以传递一个函数,接受当前剪贴板中的文本为参数,返回处理后的数据,可以返回两种类型:1.返回一个纯文本,那么会直接以该文本创建一个子节点;2.返回一个节点对象,格式如下:{ simpleMindMap: true, data: { data: { text: '' }, children: [] } },代表是simple-mind-map格式的数据,节点数据同simple-mind-map节点数据格式,如果你的处理逻辑存在异步逻辑,也可以返回一个promise | |
|
||||
|
||||
### 水印配置
|
||||
|
||||
@@ -318,8 +319,8 @@ mindMap.updateConfig({
|
||||
| SELECT_ALL | 全选 | |
|
||||
| BACK | 回退指定的步数 | step(要回退的步数,默认为1) |
|
||||
| FORWARD | 前进指定的步数 | step(要前进的步数,默认为1) |
|
||||
| INSERT_NODE | 插入同级节点,操作节点为当前激活的节点或指定节点,如果有多个激活节点,只会对第一个有效 | openEdit(v0.4.6+,是否激活新插入的节点并进入编辑模式,默认为`true`)、 appointNodes(v0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData(可选,指定新创建节点的数据,比如{text: 'xxx', ...},详细结构可以参考[exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js)) |
|
||||
| INSERT_CHILD_NODE | 插入子节点,操作节点为当前激活的节点或指定节点 | openEdit(v0.4.6+,是否激活新插入的节点并进入编辑模式,默认为`true`)、 appointNodes(v0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData(可选,指定新创建节点的数据,比如{text: 'xxx', ...},详细结构可以参考[exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js)) |
|
||||
| INSERT_NODE | 插入同级节点,操作节点为当前激活的节点或指定节点,如果有多个激活节点,只会对第一个有效 | openEdit(v0.4.6+,是否激活新插入的节点并进入编辑模式,默认为`true`)、 appointNodes(v0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData(可选,指定新创建节点的数据,比如{text: 'xxx', ...},详细结构可以参考[exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js))、 appointChildren(v0.6.14+,可选,指定新创建节点的子节点,数组类型) |
|
||||
| INSERT_CHILD_NODE | 插入子节点,操作节点为当前激活的节点或指定节点 | openEdit(v0.4.6+,是否激活新插入的节点并进入编辑模式,默认为`true`)、 appointNodes(v0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData(可选,指定新创建节点的数据,比如{text: 'xxx', ...},详细结构可以参考[exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js))、 appointChildren(v0.6.14+,可选,指定新创建节点的子节点,数组类型) |
|
||||
| UP_NODE | 上移节点,操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点或在列表里的第一个节点使用无效 | |
|
||||
| DOWN_NODE | 操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点或在列表里的最后一个节点使用无效 | |
|
||||
| REMOVE_NODE | 删除节点,操作节点为当前激活的节点或指定节点 | appointNodes(v0.4.7+,可选,指定节点,指定多个节点可以传一个数组) |
|
||||
|
||||
@@ -372,7 +372,7 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableCreateHiddenInput(v0.6.13+)</td>
|
||||
<td>enableCreateHiddenInput(v0.6.13+)(v0.6.14+版本已去除该特性)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>是否允许创建一个隐藏的输入框,该输入框会在节点激活时聚焦,用于粘贴数据和自动进入文本编辑状态</td>
|
||||
@@ -382,7 +382,7 @@
|
||||
<td>enableAutoEnterTextEditWhenKeydown(v0.6.13+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式,该配置在enableCreateHiddenInput设为true时生效</td>
|
||||
<td>是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -392,6 +392,13 @@
|
||||
<td>设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果,需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>customHandleClipboardText(v0.6.14+)</td>
|
||||
<td>Function</td>
|
||||
<td>null</td>
|
||||
<td>自定义对剪贴板文本的处理。当按ctrl+v粘贴时会读取用户剪贴板中的文本和图片,默认只会判断文本是否是普通文本和simple-mind-map格式的节点数据,如果你想处理其他思维导图的数据,比如processon、zhixi等,那么可以传递一个函数,接受当前剪贴板中的文本为参数,返回处理后的数据,可以返回两种类型:1.返回一个纯文本,那么会直接以该文本创建一个子节点;2.返回一个节点对象,格式如下:{ simpleMindMap: true, data: { data: { text: '' }, children: [] } },代表是simple-mind-map格式的数据,节点数据同simple-mind-map节点数据格式,如果你的处理逻辑存在异步逻辑,也可以返回一个promise</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>水印配置</h3>
|
||||
@@ -818,12 +825,12 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
<tr>
|
||||
<td>INSERT_NODE</td>
|
||||
<td>插入同级节点,操作节点为当前激活的节点或指定节点,如果有多个激活节点,只会对第一个有效</td>
|
||||
<td>openEdit(v0.4.6+,是否激活新插入的节点并进入编辑模式,默认为<code>true</code>)、 appointNodes(v0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData(可选,指定新创建节点的数据,比如{text: 'xxx', ...},详细结构可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a>)</td>
|
||||
<td>openEdit(v0.4.6+,是否激活新插入的节点并进入编辑模式,默认为<code>true</code>)、 appointNodes(v0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData(可选,指定新创建节点的数据,比如{text: 'xxx', ...},详细结构可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a>)、 appointChildren(v0.6.14+,可选,指定新创建节点的子节点,数组类型)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>INSERT_CHILD_NODE</td>
|
||||
<td>插入子节点,操作节点为当前激活的节点或指定节点</td>
|
||||
<td>openEdit(v0.4.6+,是否激活新插入的节点并进入编辑模式,默认为<code>true</code>)、 appointNodes(v0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData(可选,指定新创建节点的数据,比如{text: 'xxx', ...},详细结构可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a>)</td>
|
||||
<td>openEdit(v0.4.6+,是否激活新插入的节点并进入编辑模式,默认为<code>true</code>)、 appointNodes(v0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData(可选,指定新创建节点的数据,比如{text: 'xxx', ...},详细结构可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a>)、 appointChildren(v0.6.14+,可选,指定新创建节点的子节点,数组类型)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UP_NODE</td>
|
||||
|
||||
@@ -277,7 +277,9 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.associativeLineActiveColor') }}</span>
|
||||
<span class="name">{{
|
||||
$t('baseStyle.associativeLineActiveColor')
|
||||
}}</span>
|
||||
<span
|
||||
class="block"
|
||||
v-popover:popover5
|
||||
@@ -295,7 +297,9 @@
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.associativeLineActiveWidth') }}</span>
|
||||
<span class="name">{{
|
||||
$t('baseStyle.associativeLineActiveWidth')
|
||||
}}</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
@@ -382,11 +386,15 @@
|
||||
<div class="title noTop">{{ $t('baseStyle.nodeBorderType') }}</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<el-checkbox v-model="style.nodeUseLineStyle" @change="
|
||||
<el-checkbox
|
||||
v-model="style.nodeUseLineStyle"
|
||||
@change="
|
||||
value => {
|
||||
update('nodeUseLineStyle', value)
|
||||
}
|
||||
">{{ $t('baseStyle.nodeUseLineStyle') }}</el-checkbox>
|
||||
"
|
||||
>{{ $t('baseStyle.nodeUseLineStyle') }}</el-checkbox
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 内边距 -->
|
||||
@@ -520,7 +528,11 @@
|
||||
<div class="row">
|
||||
<!-- 是否显示水印 -->
|
||||
<div class="rowItem">
|
||||
<el-checkbox v-model="watermarkConfig.show" @change="watermarkShowChange">{{ $t('baseStyle.showWatermark') }}</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="watermarkConfig.show"
|
||||
@change="watermarkShowChange"
|
||||
>{{ $t('baseStyle.showWatermark') }}</el-checkbox
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="watermarkConfig.show">
|
||||
@@ -528,7 +540,12 @@
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.watermarkText') }}</span>
|
||||
<el-input v-model="watermarkConfig.text" size="small" @change="updateWatermarkConfig"></el-input>
|
||||
<el-input
|
||||
v-model="watermarkConfig.text"
|
||||
size="small"
|
||||
@change="updateWatermarkConfig"
|
||||
@keydown.native.stop
|
||||
></el-input>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 水印文字颜色 -->
|
||||
@@ -543,10 +560,12 @@
|
||||
<el-popover ref="popover3" placement="bottom" trigger="click">
|
||||
<Color
|
||||
:color="watermarkConfig.textStyle.color"
|
||||
@change="(value) => {
|
||||
watermarkConfig.textStyle.color = value
|
||||
updateWatermarkConfig()
|
||||
}"
|
||||
@change="
|
||||
value => {
|
||||
watermarkConfig.textStyle.color = value
|
||||
updateWatermarkConfig()
|
||||
}
|
||||
"
|
||||
></Color>
|
||||
</el-popover>
|
||||
</div>
|
||||
@@ -555,35 +574,72 @@
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.watermarkTextOpacity') }}</span>
|
||||
<el-slider v-model="watermarkConfig.textStyle.opacity" style="width: 170px" :min="0" :max="1" :step="0.1" @change="updateWatermarkConfig"></el-slider>
|
||||
<el-slider
|
||||
v-model="watermarkConfig.textStyle.opacity"
|
||||
style="width: 170px"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:step="0.1"
|
||||
@change="updateWatermarkConfig"
|
||||
></el-slider>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 水印文字字号 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.watermarkTextFontSize') }}</span>
|
||||
<el-input-number v-model="watermarkConfig.textStyle.fontSize" size="small" :min="0" :max="50" :step="1" @change="updateWatermarkConfig"></el-input-number>
|
||||
<span class="name">{{
|
||||
$t('baseStyle.watermarkTextFontSize')
|
||||
}}</span>
|
||||
<el-input-number
|
||||
v-model="watermarkConfig.textStyle.fontSize"
|
||||
size="small"
|
||||
:min="0"
|
||||
:max="50"
|
||||
:step="1"
|
||||
@change="updateWatermarkConfig"
|
||||
@keydown.native.stop
|
||||
></el-input-number>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 旋转角度 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.watermarkAngle') }}</span>
|
||||
<el-input-number v-model="watermarkConfig.angle" size="small" :min="0" :max="90" :step="10" @change="updateWatermarkConfig"></el-input-number>
|
||||
<el-input-number
|
||||
v-model="watermarkConfig.angle"
|
||||
size="small"
|
||||
:min="0"
|
||||
:max="90"
|
||||
:step="10"
|
||||
@change="updateWatermarkConfig"
|
||||
@keydown.native.stop
|
||||
></el-input-number>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 水印行间距 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.watermarkLineSpacing') }}</span>
|
||||
<el-input-number v-model="watermarkConfig.lineSpacing" size="small" :step="10" @change="updateWatermarkConfig"></el-input-number>
|
||||
<el-input-number
|
||||
v-model="watermarkConfig.lineSpacing"
|
||||
size="small"
|
||||
:step="10"
|
||||
@change="updateWatermarkConfig"
|
||||
@keydown.native.stop
|
||||
></el-input-number>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 水印文字间距 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.watermarkTextSpacing') }}</span>
|
||||
<el-input-number v-model="watermarkConfig.textSpacing" size="small" :step="10" @change="updateWatermarkConfig"></el-input-number>
|
||||
<el-input-number
|
||||
v-model="watermarkConfig.textSpacing"
|
||||
size="small"
|
||||
:step="10"
|
||||
@change="updateWatermarkConfig"
|
||||
@keydown.native.stop
|
||||
></el-input-number>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -592,17 +648,25 @@
|
||||
<!-- 配置开启自由拖拽 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<el-checkbox v-model="config.enableFreeDrag" @change="
|
||||
<el-checkbox
|
||||
v-model="config.enableFreeDrag"
|
||||
@change="
|
||||
value => {
|
||||
updateOtherConfig('enableFreeDrag', value)
|
||||
}
|
||||
">{{ $t('baseStyle.enableFreeDrag') }}</el-checkbox>
|
||||
"
|
||||
>{{ $t('baseStyle.enableFreeDrag') }}</el-checkbox
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 配置是否启用富文本编辑 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<el-checkbox v-model="enableNodeRichText" @change="enableNodeRichTextChange">{{ $t('baseStyle.isEnableNodeRichText') }}</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="enableNodeRichText"
|
||||
@change="enableNodeRichTextChange"
|
||||
>{{ $t('baseStyle.isEnableNodeRichText') }}</el-checkbox
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 配置鼠标滚轮行为 -->
|
||||
@@ -620,15 +684,23 @@
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option :label="$t('baseStyle.zoomView') " value="zoom"></el-option>
|
||||
<el-option :label="$t('baseStyle.moveViewUpDown') " value="move"></el-option>
|
||||
<el-option
|
||||
:label="$t('baseStyle.zoomView')"
|
||||
value="zoom"
|
||||
></el-option>
|
||||
<el-option
|
||||
:label="$t('baseStyle.moveViewUpDown')"
|
||||
value="move"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 配置鼠标缩放行为 -->
|
||||
<div class="row" v-if="config.mousewheelAction === 'zoom'">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.mousewheelZoomActionReverse') }}</span>
|
||||
<span class="name">{{
|
||||
$t('baseStyle.mousewheelZoomActionReverse')
|
||||
}}</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 120px"
|
||||
@@ -640,8 +712,14 @@
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option :label="$t('baseStyle.mousewheelZoomActionReverse1') " :value="false"></el-option>
|
||||
<el-option :label="$t('baseStyle.mousewheelZoomActionReverse2') " :value="true"></el-option>
|
||||
<el-option
|
||||
:label="$t('baseStyle.mousewheelZoomActionReverse1')"
|
||||
:value="false"
|
||||
></el-option>
|
||||
<el-option
|
||||
:label="$t('baseStyle.mousewheelZoomActionReverse2')"
|
||||
:value="true"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -652,7 +730,16 @@
|
||||
<script>
|
||||
import Sidebar from './Sidebar'
|
||||
import Color from './Color'
|
||||
import { lineWidthList, lineStyleList, backgroundRepeatList, backgroundPositionList, backgroundSizeList, fontFamilyList, fontSizeList, rootLineKeepSameInCurveList } from '@/config'
|
||||
import {
|
||||
lineWidthList,
|
||||
lineStyleList,
|
||||
backgroundRepeatList,
|
||||
backgroundPositionList,
|
||||
backgroundSizeList,
|
||||
fontFamilyList,
|
||||
fontSizeList,
|
||||
rootLineKeepSameInCurveList
|
||||
} from '@/config'
|
||||
import ImgUpload from '@/components/ImgUpload'
|
||||
import { storeConfig } from '@/api'
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
@@ -740,20 +827,25 @@ export default {
|
||||
return lineStyleList[this.$i18n.locale] || lineStyleList.zh
|
||||
},
|
||||
rootLineKeepSameInCurveList() {
|
||||
return rootLineKeepSameInCurveList[this.$i18n.locale] || rootLineKeepSameInCurveList.zh
|
||||
return (
|
||||
rootLineKeepSameInCurveList[this.$i18n.locale] ||
|
||||
rootLineKeepSameInCurveList.zh
|
||||
)
|
||||
},
|
||||
backgroundRepeatList() {
|
||||
return backgroundRepeatList[this.$i18n.locale] || backgroundRepeatList.zh
|
||||
},
|
||||
backgroundPositionList() {
|
||||
return backgroundPositionList[this.$i18n.locale] || backgroundPositionList.zh
|
||||
return (
|
||||
backgroundPositionList[this.$i18n.locale] || backgroundPositionList.zh
|
||||
)
|
||||
},
|
||||
backgroundSizeList() {
|
||||
return backgroundSizeList[this.$i18n.locale] || backgroundSizeList.zh
|
||||
},
|
||||
fontFamilyList() {
|
||||
return fontFamilyList[this.$i18n.locale] || fontFamilyList.zh
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeSidebar(val) {
|
||||
@@ -767,14 +859,25 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
created() {
|
||||
this.enableNodeRichText = this.localConfig.openNodeRichText
|
||||
this.mousewheelAction = this.localConfig.mousewheelAction
|
||||
this.mousewheelZoomActionReverse = this.localConfig.mousewheelZoomActionReverse
|
||||
this.$bus.$on('setData', this.onSetData)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.$off('setData', this.onSetData)
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setLocalConfig']),
|
||||
|
||||
onSetData() {
|
||||
if (this.activeSidebar !== 'baseStyle') return
|
||||
setTimeout(() => {
|
||||
this.initStyle()
|
||||
}, 0)
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 14:02:12
|
||||
@@ -817,7 +920,11 @@ export default {
|
||||
|
||||
// 初始化其他配置
|
||||
initConfig() {
|
||||
;['enableFreeDrag', 'mousewheelAction', 'mousewheelZoomActionReverse'].forEach(key => {
|
||||
;[
|
||||
'enableFreeDrag',
|
||||
'mousewheelAction',
|
||||
'mousewheelZoomActionReverse'
|
||||
].forEach(key => {
|
||||
this.config[key] = this.mindMap.getConfig(key)
|
||||
})
|
||||
},
|
||||
@@ -825,7 +932,7 @@ export default {
|
||||
// 初始化水印配置
|
||||
initWatermark() {
|
||||
let config = this.mindMap.getConfig('watermarkConfig')
|
||||
;['text', 'lineSpacing', 'textSpacing', 'angle'].forEach((key) => {
|
||||
;['text', 'lineSpacing', 'textSpacing', 'angle'].forEach(key => {
|
||||
this.watermarkConfig[key] = config[key]
|
||||
})
|
||||
this.watermarkConfig.show = !!config.text
|
||||
@@ -883,16 +990,18 @@ export default {
|
||||
updateWatermarkConfig() {
|
||||
clearTimeout(this.updateWatermarkTimer)
|
||||
this.updateWatermarkTimer = setTimeout(() => {
|
||||
let {show, ...config} = this.watermarkConfig
|
||||
let { show, ...config } = this.watermarkConfig
|
||||
this.mindMap.watermark.updateWatermark({
|
||||
...config
|
||||
})
|
||||
this.data.config = this.data.config || {}
|
||||
this.data.config.watermarkConfig = this.mindMap.getConfig('watermarkConfig')
|
||||
this.data.config.watermarkConfig = this.mindMap.getConfig(
|
||||
'watermarkConfig'
|
||||
)
|
||||
storeConfig({
|
||||
config: this.data.config
|
||||
})
|
||||
}, 300);
|
||||
}, 300)
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -918,7 +1027,8 @@ export default {
|
||||
// 切换显示水印与否
|
||||
watermarkShowChange(value) {
|
||||
if (value) {
|
||||
let text = this.watermarkConfig.text || this.$t('baseStyle.watermarkDefaultText')
|
||||
let text =
|
||||
this.watermarkConfig.text || this.$t('baseStyle.watermarkDefaultText')
|
||||
this.watermarkConfig.text = text
|
||||
} else {
|
||||
this.watermarkConfig.text = ''
|
||||
@@ -940,7 +1050,7 @@ export default {
|
||||
mousewheelAction: e
|
||||
})
|
||||
this.mindMap.updateConfig
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -958,7 +1068,7 @@ export default {
|
||||
.row {
|
||||
.rowItem {
|
||||
.name {
|
||||
color: hsla(0,0%,100%,.6);
|
||||
color: hsla(0, 0%, 100%, 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
<div class="colorContainer" :class="{ isDark: isDark }">
|
||||
<div class="colorList">
|
||||
<span
|
||||
class="colorItem"
|
||||
class="colorItem iconfont"
|
||||
v-for="item in colorList"
|
||||
:style="{ backgroundColor: item }"
|
||||
:class="{ icontouming: item === 'transparent' }"
|
||||
:key="item"
|
||||
@click="clickColorItem(item)"
|
||||
></span>
|
||||
@@ -87,9 +88,13 @@ export default {
|
||||
|
||||
.colorList {
|
||||
width: 240px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.colorItem {
|
||||
display: inline-block;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
|
||||
@@ -70,6 +70,12 @@
|
||||
{{ $t('contextmenu.pasteNode') }}
|
||||
<span class="desc">Ctrl + V</span>
|
||||
</div>
|
||||
<div class="item" @click="exec('REMOVE_HYPERLINK')" v-if="hasHyperlink">
|
||||
{{ $t('contextmenu.removeHyperlink') }}
|
||||
</div>
|
||||
<div class="item" @click="exec('REMOVE_NOTE')" v-if="hasNote">
|
||||
{{ $t('contextmenu.removeNote') }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="type === 'svg'">
|
||||
<div class="item" @click="exec('RETURN_CENTER')">
|
||||
@@ -180,6 +186,12 @@ export default {
|
||||
},
|
||||
isGeneralization() {
|
||||
return this.node.isGeneralization
|
||||
},
|
||||
hasHyperlink() {
|
||||
return !!this.node.getData('hyperlink')
|
||||
},
|
||||
hasNote() {
|
||||
return !!this.node.getData('note')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -302,6 +314,12 @@ export default {
|
||||
case 'FIT_CANVAS':
|
||||
this.mindMap.view.fit()
|
||||
break
|
||||
case 'REMOVE_HYPERLINK':
|
||||
this.node.setHyperlink('', '')
|
||||
break
|
||||
case 'REMOVE_NOTE':
|
||||
this.node.setNote('')
|
||||
break
|
||||
default:
|
||||
this.$bus.$emit('execCommand', key, ...args)
|
||||
break
|
||||
|
||||
@@ -23,7 +23,11 @@ import { mapState } from 'vuex'
|
||||
let countEl = document.createElement('div')
|
||||
export default {
|
||||
name: 'Count',
|
||||
props: {},
|
||||
props: {
|
||||
mindMap: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
textStr: '',
|
||||
@@ -36,6 +40,9 @@ export default {
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on('data_change', this.onDataChange)
|
||||
if (this.mindMap) {
|
||||
this.onDataChange(this.mindMap.getData())
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.$off('data_change', this.onDataChange)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="editContainer">
|
||||
<div class="mindMapContainer" ref="mindMapContainer"></div>
|
||||
<Count v-if="!isZenMode"></Count>
|
||||
<Count :mindMap="mindMap" v-if="!isZenMode"></Count>
|
||||
<Navigator :mindMap="mindMap"></Navigator>
|
||||
<NavigatorToolbar :mindMap="mindMap" v-if="!isZenMode"></NavigatorToolbar>
|
||||
<OutlineSidebar :mindMap="mindMap"></OutlineSidebar>
|
||||
@@ -70,6 +70,7 @@ import NodeIconSidebar from './NodeIconSidebar.vue'
|
||||
import NodeIconToolbar from './NodeIconToolbar.vue'
|
||||
import OutlineEdit from './OutlineEdit.vue'
|
||||
import { showLoading, hideLoading } from '@/utils/loading'
|
||||
import handleClipboardText from '@/utils/handleClipboardText'
|
||||
|
||||
// 注册插件
|
||||
MindMap.usePlugin(MiniMap)
|
||||
@@ -275,7 +276,9 @@ export default {
|
||||
...(config || {}),
|
||||
iconList: icon,
|
||||
useLeftKeySelectionRightKeyDrag: this.useLeftKeySelectionRightKeyDrag,
|
||||
customInnerElsAppendTo: null
|
||||
customInnerElsAppendTo: null,
|
||||
enableAutoEnterTextEditWhenKeydown: true,
|
||||
customHandleClipboardText: handleClipboardText,
|
||||
// isUseCustomNodeContent: true,
|
||||
// 示例1:组件里用到了router、store、i18n等实例化vue组件时需要用到的东西
|
||||
// customCreateNodeContent: (node) => {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
style="width: 300px"
|
||||
v-model="fileName"
|
||||
size="mini"
|
||||
@keydown.native.stop
|
||||
></el-input>
|
||||
<el-checkbox
|
||||
v-show="['smm', 'json'].includes(exportType)"
|
||||
@@ -34,6 +35,7 @@
|
||||
v-model="paddingX"
|
||||
size="mini"
|
||||
@change="onPaddingChange"
|
||||
@keydown.native.stop
|
||||
></el-input>
|
||||
<span class="name" style="margin-left: 10px;">{{
|
||||
$t('export.paddingY')
|
||||
@@ -43,6 +45,7 @@
|
||||
v-model="paddingY"
|
||||
size="mini"
|
||||
@change="onPaddingChange"
|
||||
@keydown.native.stop
|
||||
></el-input>
|
||||
<el-checkbox
|
||||
v-show="['png'].includes(exportType)"
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
size="mini"
|
||||
placeholder="http://xxxx.com/"
|
||||
@keyup.native.stop
|
||||
@keydown.native.stop
|
||||
></el-input>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="name">{{ $t('nodeHyperlink.name') }}</span>
|
||||
<el-input v-model="linkTitle" size="mini" @keyup.native.stop></el-input>
|
||||
<el-input
|
||||
v-model="linkTitle"
|
||||
size="mini"
|
||||
@keyup.native.stop
|
||||
@keydown.native.stop
|
||||
></el-input>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
|
||||
|
||||
@@ -18,12 +18,13 @@
|
||||
v-model="imgUrl"
|
||||
size="mini"
|
||||
placeholder="http://xxx.com/xx.jpg"
|
||||
@keydown.native.stop
|
||||
></el-input>
|
||||
</div>
|
||||
<div class="title">可选</div>
|
||||
<div class="inputBox">
|
||||
<span class="label">{{ $t('nodeImage.imgTitle') }}</span>
|
||||
<el-input v-model="imgTitle" size="mini"></el-input>
|
||||
<el-input v-model="imgTitle" size="mini" @keydown.native.stop></el-input>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
|
||||
@@ -100,7 +101,14 @@ export default {
|
||||
|
||||
async confirm() {
|
||||
try {
|
||||
if (!this.img && !this.imgUrl) return
|
||||
// 删除图片
|
||||
if (!this.img && !this.imgUrl) {
|
||||
this.cancel()
|
||||
this.activeNodes.forEach(node => {
|
||||
node.setImage(null)
|
||||
})
|
||||
return
|
||||
}
|
||||
let res = null
|
||||
let img = ''
|
||||
if (this.img) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
v-model="note"
|
||||
>
|
||||
</el-input> -->
|
||||
<div class="noteEditor" ref="noteEditor" @keyup.stop></div>
|
||||
<div class="noteEditor" ref="noteEditor" @keyup.stop @keydown.stop></div>
|
||||
<!-- <div class="tip">换行请使用:Enter+Shift</div> -->
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
v-model="tag"
|
||||
@keyup.native.enter="add"
|
||||
@keyup.native.stop
|
||||
@keydown.native.stop
|
||||
:disabled="tagArr.length >= max"
|
||||
:placeholder="$t('nodeTag.addTip')"
|
||||
>
|
||||
|
||||
@@ -75,6 +75,7 @@ export default {
|
||||
window.addEventListener('keydown', this.onKeyDown)
|
||||
this.$bus.$on('data_change', this.handleDataChange)
|
||||
this.$bus.$on('node_tree_render_end', this.handleNodeTreeRenderEnd)
|
||||
this.$bus.$on('hide_text_edit', this.handleHideTextEdit)
|
||||
},
|
||||
mounted() {
|
||||
this.refresh()
|
||||
@@ -83,8 +84,16 @@ export default {
|
||||
window.removeEventListener('keydown', this.onKeyDown)
|
||||
this.$bus.$off('data_change', this.handleDataChange)
|
||||
this.$bus.$off('node_tree_render_end', this.handleNodeTreeRenderEnd)
|
||||
this.$bus.$off('hide_text_edit', this.handleHideTextEdit)
|
||||
},
|
||||
methods: {
|
||||
handleHideTextEdit() {
|
||||
if (this.notHandleDataChange) {
|
||||
this.notHandleDataChange = false
|
||||
this.refresh()
|
||||
}
|
||||
},
|
||||
|
||||
handleDataChange() {
|
||||
// 在大纲里操作节点时不要响应该事件,否则会重新刷新树
|
||||
if (this.notHandleDataChange) {
|
||||
@@ -191,6 +200,7 @@ export default {
|
||||
const text = richText ? e.target.innerHTML : e.target.innerText
|
||||
const targetNode = this.mindMap.renderer.findNodeByUid(node.data.uid)
|
||||
if (!targetNode) return
|
||||
this.notHandleDataChange = true
|
||||
if (richText) {
|
||||
targetNode.setText(textToNodeRichTextWithWrap(text), true, true)
|
||||
} else {
|
||||
@@ -258,9 +268,7 @@ export default {
|
||||
this.notHandleDataChange = true
|
||||
const targetNode = this.mindMap.renderer.findNodeByUid(data.uid)
|
||||
if (targetNode && targetNode.nodeData.data.isActive) return
|
||||
this.mindMap.renderer.textEdit.stopFocusOnNodeActive()
|
||||
this.mindMap.execCommand('GO_TARGET_NODE', data.uid, () => {
|
||||
this.mindMap.renderer.textEdit.openFocusOnNodeActive()
|
||||
this.notHandleDataChange = false
|
||||
})
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
size="small"
|
||||
v-model="searchText"
|
||||
@keyup.native.enter.stop="onSearchNext"
|
||||
@keydown.native.stop
|
||||
>
|
||||
<i slot="prefix" class="el-input__icon el-icon-search"></i>
|
||||
<el-button
|
||||
@@ -35,6 +36,7 @@
|
||||
size="small"
|
||||
v-model="replaceText"
|
||||
style="margin: 12px 0;"
|
||||
@keydown.native.stop
|
||||
>
|
||||
<i slot="prefix" class="el-input__icon el-icon-edit"></i>
|
||||
<el-button size="small" slot="append" @click="hideReplaceInput">{{
|
||||
|
||||
@@ -142,6 +142,9 @@
|
||||
v-model="style.textDecoration"
|
||||
@change="update('textDecoration')"
|
||||
>
|
||||
<el-radio-button label="none">{{
|
||||
$t('style.none')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="underline">{{
|
||||
$t('style.underline')
|
||||
}}</el-radio-button>
|
||||
|
||||
70
web/src/utils/handleClipboardText.js
Normal file
70
web/src/utils/handleClipboardText.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import { imgToDataUrl } from 'simple-mind-map/src/utils/index'
|
||||
|
||||
// 处理知犀
|
||||
const handleZHIXI = async text => {
|
||||
text = text.replace('', '')
|
||||
try {
|
||||
// 只处理一项
|
||||
const node = JSON.parse(text)[0]
|
||||
const newNode = {}
|
||||
const waitLoadImageList = []
|
||||
const walk = async (root, newRoot) => {
|
||||
newRoot.data = {
|
||||
text: root.data.text,
|
||||
hyperlink: root.data.hyperlink,
|
||||
hyperlinkTitle: root.data.hyperlinkTitle,
|
||||
note: root.data.note
|
||||
}
|
||||
// 图片
|
||||
if (root.data.image) {
|
||||
let resolve = null
|
||||
let promise = new Promise(_resolve => {
|
||||
resolve = _resolve
|
||||
})
|
||||
waitLoadImageList.push(promise)
|
||||
try {
|
||||
newRoot.data.image = await imgToDataUrl(root.data.image)
|
||||
newRoot.data.imageSize = root.data.imageSize
|
||||
resolve()
|
||||
} catch (error) {
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
// 子节点
|
||||
newRoot.children = []
|
||||
if (root.children && root.children.length > 0) {
|
||||
root.children.forEach(item => {
|
||||
// 概要
|
||||
if (item.data.type === 'generalize') {
|
||||
newRoot.data.generalization = {
|
||||
text: item.data.text
|
||||
}
|
||||
return
|
||||
}
|
||||
let newChild = {}
|
||||
newRoot.children.push(newChild)
|
||||
walk(item, newChild)
|
||||
})
|
||||
}
|
||||
}
|
||||
walk(node, newNode)
|
||||
await Promise.all(waitLoadImageList)
|
||||
return {
|
||||
simpleMindMap: true,
|
||||
data: newNode
|
||||
}
|
||||
} catch (error) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const handleClipboardText = async text => {
|
||||
// 处理知犀数据
|
||||
if (text.includes('')) {
|
||||
const res = await handleZHIXI(text)
|
||||
return res
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
export default handleClipboardText
|
||||
Reference in New Issue
Block a user