mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-03-01 06:17:50 +08:00
Merge branch 'feature' into electron
This commit is contained in:
commit
ac31a26072
@ -65,7 +65,9 @@ class Render {
|
||||
this.mindMap = opt.mindMap
|
||||
this.themeConfig = this.mindMap.themeConfig
|
||||
// 渲染树,操作过程中修改的都是这里的数据
|
||||
this.renderTree = this.mindMap.opt.data ? merge({}, this.mindMap.opt.data) : null
|
||||
this.renderTree = this.mindMap.opt.data
|
||||
? merge({}, this.mindMap.opt.data)
|
||||
: null
|
||||
// 是否重新渲染
|
||||
this.reRender = false
|
||||
// 是否正在渲染中
|
||||
@ -246,6 +248,9 @@ class Render {
|
||||
// 设置节点备注
|
||||
this.setNodeNote = this.setNodeNote.bind(this)
|
||||
this.mindMap.command.add('SET_NODE_NOTE', this.setNodeNote)
|
||||
// 设置节点附件
|
||||
this.setNodeAttachment = this.setNodeAttachment.bind(this)
|
||||
this.mindMap.command.add('SET_NODE_ATTACHMENT', this.setNodeAttachment)
|
||||
// 设置节点标签
|
||||
this.setNodeTag = this.setNodeTag.bind(this)
|
||||
this.mindMap.command.add('SET_NODE_TAG', this.setNodeTag)
|
||||
@ -1600,6 +1605,14 @@ class Render {
|
||||
})
|
||||
}
|
||||
|
||||
// 设置节点附件
|
||||
setNodeAttachment(node, url, name = '') {
|
||||
this.setNodeDataRender(node, {
|
||||
attachmentUrl: url,
|
||||
attachmentName: name
|
||||
})
|
||||
}
|
||||
|
||||
// 设置节点标签
|
||||
setNodeTag(node, tag) {
|
||||
this.setNodeDataRender(node, {
|
||||
|
||||
@ -75,6 +75,7 @@ class Node {
|
||||
this._noteData = null
|
||||
this.noteEl = null
|
||||
this.noteContentIsShow = false
|
||||
this._attachmentData = null
|
||||
this._expandBtn = null
|
||||
this._lastExpandBtnType = null
|
||||
this._showExpandBtn = false
|
||||
@ -199,6 +200,7 @@ class Node {
|
||||
this._hyperlinkData = this.createHyperlinkNode()
|
||||
this._tagData = this.createTagNode()
|
||||
this._noteData = this.createNoteNode()
|
||||
this._attachmentData = this.createAttachmentNode()
|
||||
}
|
||||
|
||||
// 计算节点的宽高
|
||||
@ -267,6 +269,11 @@ class Node {
|
||||
textContentWidth += this._noteData.width
|
||||
textContentHeight = Math.max(textContentHeight, this._noteData.height)
|
||||
}
|
||||
// 附件
|
||||
if (this._attachmentData) {
|
||||
textContentWidth += this._attachmentData.width
|
||||
textContentHeight = Math.max(textContentHeight, this._attachmentData.height)
|
||||
}
|
||||
// 文字内容部分的尺寸
|
||||
this._rectInfo.textContentWidth = textContentWidth
|
||||
this._rectInfo.textContentHeight = textContentHeight
|
||||
@ -399,6 +406,14 @@ class Node {
|
||||
textContentNested.add(this._noteData.node)
|
||||
textContentOffsetX += this._noteData.width
|
||||
}
|
||||
// 附件
|
||||
if (this._attachmentData) {
|
||||
this._attachmentData.node
|
||||
.x(textContentOffsetX)
|
||||
.y((this._rectInfo.textContentHeight - this._attachmentData.height) / 2)
|
||||
textContentNested.add(this._attachmentData.node)
|
||||
textContentOffsetX += this._attachmentData.width
|
||||
}
|
||||
// 文字内容整体
|
||||
textContentNested.translate(
|
||||
width / 2 - textContentNested.bbox().width / 2,
|
||||
|
||||
@ -28,6 +28,11 @@ function setNote(note) {
|
||||
this.mindMap.execCommand('SET_NODE_NOTE', this, note)
|
||||
}
|
||||
|
||||
// 设置附件
|
||||
function setAttachment(url, name) {
|
||||
this.mindMap.execCommand('SET_NODE_ATTACHMENT', this, url, name)
|
||||
}
|
||||
|
||||
// 设置标签
|
||||
function setTag(tag) {
|
||||
this.mindMap.execCommand('SET_NODE_TAG', this, tag)
|
||||
@ -55,6 +60,7 @@ export default {
|
||||
setIcon,
|
||||
setHyperlink,
|
||||
setNote,
|
||||
setAttachment,
|
||||
setTag,
|
||||
setShape,
|
||||
setStyle,
|
||||
|
||||
@ -262,7 +262,7 @@ function createHyperlinkNode() {
|
||||
e.stopPropagation()
|
||||
})
|
||||
if (hyperlinkTitle) {
|
||||
a.attr('title', hyperlinkTitle)
|
||||
node.add(SVG(`<title>${hyperlinkTitle}</title>`))
|
||||
}
|
||||
// 添加一个透明的层,作为鼠标区域
|
||||
a.rect(iconSize, iconSize).fill({ color: 'transparent' })
|
||||
@ -368,6 +368,36 @@ function createNoteNode() {
|
||||
}
|
||||
}
|
||||
|
||||
// 创建附件节点
|
||||
function createAttachmentNode() {
|
||||
const { attachmentUrl, attachmentName } = this.getData()
|
||||
if (!attachmentUrl) {
|
||||
return
|
||||
}
|
||||
const iconSize = this.mindMap.themeConfig.iconSize
|
||||
const node = new SVG().attr('cursor', 'pointer').size(iconSize, iconSize)
|
||||
if (attachmentName) {
|
||||
node.add(SVG(`<title>${attachmentName}</title>`))
|
||||
}
|
||||
// 透明的层,用来作为鼠标区域
|
||||
node.add(new Rect().size(iconSize, iconSize).fill({ color: 'transparent' }))
|
||||
// 备注图标
|
||||
const iconNode = SVG(iconsSvg.attachment).size(iconSize, iconSize)
|
||||
this.style.iconNode(iconNode)
|
||||
node.add(iconNode)
|
||||
node.on('click', e => {
|
||||
this.mindMap.emit('node_attachmentClick', this, e, node)
|
||||
})
|
||||
node.on('contextmenu', e => {
|
||||
this.mindMap.emit('node_attachmentContextmenu', this, e, node)
|
||||
})
|
||||
return {
|
||||
node,
|
||||
width: iconSize,
|
||||
height: iconSize
|
||||
}
|
||||
}
|
||||
|
||||
// 获取节点备注显示位置
|
||||
function getNoteContentPosition() {
|
||||
const iconSize = this.mindMap.themeConfig.iconSize
|
||||
@ -415,6 +445,7 @@ export default {
|
||||
createHyperlinkNode,
|
||||
createTagNode,
|
||||
createNoteNode,
|
||||
createAttachmentNode,
|
||||
getNoteContentPosition,
|
||||
measureCustomNodeContentSize,
|
||||
isUseCustomNodeContent
|
||||
|
||||
@ -158,7 +158,8 @@ class View {
|
||||
...viewData.transform
|
||||
})
|
||||
this.mindMap.emit('view_data_change', this.getTransformData())
|
||||
this.mindMap.emit('scale', this.scale)
|
||||
this.emitEvent('scale')
|
||||
this.emitEvent('translate')
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,6 +169,7 @@ class View {
|
||||
this.x += x
|
||||
this.y += y
|
||||
this.transform()
|
||||
this.emitEvent('translate')
|
||||
}
|
||||
|
||||
// 平移x方向
|
||||
@ -175,12 +177,14 @@ class View {
|
||||
if (step === 0) return
|
||||
this.x += step
|
||||
this.transform()
|
||||
this.emitEvent('translate')
|
||||
}
|
||||
|
||||
// 平移x方式到
|
||||
translateXTo(x) {
|
||||
this.x = x
|
||||
this.transform()
|
||||
this.emitEvent('translate')
|
||||
}
|
||||
|
||||
// 平移y方向
|
||||
@ -188,12 +192,14 @@ class View {
|
||||
if (step === 0) return
|
||||
this.y += step
|
||||
this.transform()
|
||||
this.emitEvent('translate')
|
||||
}
|
||||
|
||||
// 平移y方向到
|
||||
translateYTo(y) {
|
||||
this.y = y
|
||||
this.transform()
|
||||
this.emitEvent('translate')
|
||||
}
|
||||
|
||||
// 应用变换
|
||||
@ -211,13 +217,17 @@ class View {
|
||||
|
||||
// 恢复
|
||||
reset() {
|
||||
let scaleChange = this.scale !== 1
|
||||
const scaleChange = this.scale !== 1
|
||||
const translateChange = this.x !== 0 || this.y !== 0
|
||||
this.scale = 1
|
||||
this.x = 0
|
||||
this.y = 0
|
||||
this.transform()
|
||||
if (scaleChange) {
|
||||
this.mindMap.emit('scale', this.scale)
|
||||
this.emitEvent('scale')
|
||||
}
|
||||
if (translateChange) {
|
||||
this.emitEvent('translate')
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,7 +237,7 @@ class View {
|
||||
const scale = Math.max(this.scale - scaleRatio, 0.1)
|
||||
this.scaleInCenter(scale, cx, cy)
|
||||
this.transform()
|
||||
this.mindMap.emit('scale', this.scale)
|
||||
this.emitEvent('scale')
|
||||
}
|
||||
|
||||
// 放大
|
||||
@ -236,7 +246,7 @@ class View {
|
||||
const scale = this.scale + scaleRatio
|
||||
this.scaleInCenter(scale, cx, cy)
|
||||
this.transform()
|
||||
this.mindMap.emit('scale', this.scale)
|
||||
this.emitEvent('scale')
|
||||
}
|
||||
|
||||
// 基于指定中心进行缩放,cx,cy 可不指定,此时会使用画布中心点
|
||||
@ -262,7 +272,7 @@ class View {
|
||||
this.scale = scale
|
||||
}
|
||||
this.transform()
|
||||
this.mindMap.emit('scale', this.scale)
|
||||
this.emitEvent('scale')
|
||||
}
|
||||
|
||||
// 适应画布大小
|
||||
@ -394,6 +404,16 @@ class View {
|
||||
bottom
|
||||
}
|
||||
}
|
||||
|
||||
// 派发事件
|
||||
emitEvent(type) {
|
||||
switch (type) {
|
||||
case 'scale':
|
||||
this.mindMap.emit('scale', this.scale)
|
||||
case 'translate':
|
||||
this.mindMap.emit('translate', this.x, this.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default View
|
||||
|
||||
@ -86,6 +86,7 @@ class Search {
|
||||
this.matchNodeList = []
|
||||
this.currentIndex = -1
|
||||
const { isOnlySearchCurrentRenderNodes } = this.mindMap.opt
|
||||
// 如果要搜索收起来的节点,那么要遍历渲染树而不是节点树
|
||||
const tree = isOnlySearchCurrentRenderNodes
|
||||
? this.mindMap.renderer.root
|
||||
: this.mindMap.renderer.renderTree
|
||||
@ -103,6 +104,11 @@ class Search {
|
||||
})
|
||||
}
|
||||
|
||||
// 判断对象是否是节点实例
|
||||
isNodeInstance(node) {
|
||||
return node instanceof Node
|
||||
}
|
||||
|
||||
// 搜索下一个,定位到下一个匹配节点
|
||||
searchNext(callback) {
|
||||
if (!this.isSearching || this.matchNodeList.length <= 0) return
|
||||
@ -113,13 +119,12 @@ class Search {
|
||||
}
|
||||
const currentNode = this.matchNodeList[this.currentIndex]
|
||||
this.notResetSearchText = true
|
||||
const uid =
|
||||
currentNode instanceof Node
|
||||
? currentNode.getData('uid')
|
||||
: currentNode.data.uid
|
||||
const uid = this.isNodeInstance(currentNode)
|
||||
? 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)) {
|
||||
if (!this.isNodeInstance(currentNode)) {
|
||||
this.matchNodeList[this.currentIndex] = node
|
||||
}
|
||||
callback()
|
||||
@ -173,15 +178,20 @@ class Search {
|
||||
return
|
||||
replaceText = String(replaceText)
|
||||
this.matchNodeList.forEach(node => {
|
||||
let text = this.getReplacedText(node, this.searchText, replaceText)
|
||||
this.mindMap.renderer.setNodeDataRender(
|
||||
node,
|
||||
{
|
||||
text,
|
||||
resetRichText: !!node.getData('richText')
|
||||
},
|
||||
true
|
||||
)
|
||||
const text = this.getReplacedText(node, this.searchText, replaceText)
|
||||
if (this.isNodeInstance(node)) {
|
||||
this.mindMap.renderer.setNodeDataRender(
|
||||
node,
|
||||
{
|
||||
text,
|
||||
resetRichText: !!node.getData('richText')
|
||||
},
|
||||
true
|
||||
)
|
||||
} else {
|
||||
node.data.text = text
|
||||
node.data.resetRichText = !!node.data.richText
|
||||
}
|
||||
})
|
||||
this.mindMap.render()
|
||||
this.mindMap.command.addHistory()
|
||||
@ -190,7 +200,9 @@ class Search {
|
||||
|
||||
// 获取某个节点替换后的文本
|
||||
getReplacedText(node, searchText, replaceText) {
|
||||
let { richText, text } = node.getData()
|
||||
let { richText, text } = this.isNodeInstance(node)
|
||||
? node.getData()
|
||||
: node.data
|
||||
if (richText) {
|
||||
return replaceHtmlText(text, searchText, replaceText)
|
||||
} else {
|
||||
|
||||
@ -8,6 +8,10 @@ const hyperlink =
|
||||
const note =
|
||||
'<svg t="1624195132675" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8792" ><path d="M152.768 985.984 152.768 49.856l434.56 0 66.816 0 234.048 267.392 0 66.816 0 601.92L152.768 985.984 152.768 985.984zM654.144 193.088l0 124.16 108.736 0L654.144 193.088 654.144 193.088zM821.312 384.064l-167.168 0L587.328 384.064 587.328 317.312 587.328 116.736 219.584 116.736 219.584 919.04l601.728 0L821.312 384.064 821.312 384.064zM386.688 517.888 319.808 517.888 319.808 450.944l66.816 0L386.624 517.888 386.688 517.888zM386.688 651.584 319.808 651.584 319.808 584.704l66.816 0L386.624 651.584 386.688 651.584zM386.688 785.344 319.808 785.344l0-66.88 66.816 0L386.624 785.344 386.688 785.344zM721.024 517.888 453.632 517.888 453.632 450.944l267.392 0L721.024 517.888 721.024 517.888zM654.144 651.584 453.632 651.584 453.632 584.704l200.512 0L654.144 651.584 654.144 651.584zM620.672 785.344l-167.04 0 0-66.88 167.04 0L620.672 785.344 620.672 785.344z" p-id="8793"></path></svg>'
|
||||
|
||||
// 附件图标
|
||||
const attachment =
|
||||
'<svg t="1711935375590" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3864" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M516.373333 375.978667l136.576-136.576a147.797333 147.797333 0 0 1 208.853334-0.021334 147.690667 147.690667 0 0 1-0.042667 208.832l-204.8 204.778667v0.021333l-153.621333 153.6c-85.973333 85.973333-225.28 85.973333-311.253334 0.021334-85.994667-85.973333-85.973333-225.216 0.149334-311.36L431.146667 256.362667a21.333333 21.333333 0 0 0-30.165334-30.165334L162.069333 465.066667c-102.805333 102.826667-102.826667 269.056-0.149333 371.733333 102.613333 102.613333 268.970667 102.613333 371.584 0l153.6-153.642667h0.021333l0.021334-0.021333 204.778666-204.778667c74.325333-74.325333 74.346667-194.858667 0.021334-269.184-74.24-74.24-194.88-74.24-269.162667 0.042667l-136.576 136.554667-187.626667 187.626666a117.845333 117.845333 0 0 0-0.106666 166.826667 118.037333 118.037333 0 0 0 166.826666-0.106667l255.850667-255.829333a21.333333 21.333333 0 0 0-30.165333-30.165333L435.136 669.973333a75.370667 75.370667 0 0 1-106.496 0.106667 75.178667 75.178667 0 0 1 0.128-106.496l187.605333-187.605333z" p-id="3865"></path></svg>'
|
||||
|
||||
// 节点icon
|
||||
export const nodeIconList = [
|
||||
{
|
||||
@ -303,6 +307,7 @@ const getNodeIconListIcon = (name, extendIconList = []) => {
|
||||
export default {
|
||||
hyperlink,
|
||||
note,
|
||||
attachment,
|
||||
nodeIconList,
|
||||
getNodeIconListIcon
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2479351 */
|
||||
src: url('iconfont.woff2?t=1711536835850') format('woff2'),
|
||||
url('iconfont.woff?t=1711536835850') format('woff'),
|
||||
url('iconfont.ttf?t=1711536835850') format('truetype');
|
||||
src: url('iconfont.woff2?t=1711935414521') format('woff2'),
|
||||
url('iconfont.woff?t=1711935414521') format('woff'),
|
||||
url('iconfont.ttf?t=1711935414521') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,10 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconfujian:before {
|
||||
content: "\e88a";
|
||||
}
|
||||
|
||||
.icongeshihua:before {
|
||||
content: "\e7a3";
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -261,6 +261,7 @@ export default {
|
||||
save: 'Save',
|
||||
painter: 'Painter',
|
||||
formula: 'Formula',
|
||||
attachment: 'Attachment',
|
||||
more: 'More',
|
||||
selectFileTip: 'Please select a file',
|
||||
notSupportTip:
|
||||
@ -333,5 +334,8 @@ export default {
|
||||
formatErrorTip: 'The JSON format is incorrect. Please check and try again',
|
||||
copyTip: 'Copied to clipboard',
|
||||
formatTip: 'Format complete'
|
||||
},
|
||||
attachment: {
|
||||
deleteAttachment: 'Delete attachment'
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,6 +258,7 @@ export default {
|
||||
save: '保存',
|
||||
painter: '格式刷',
|
||||
formula: '公式',
|
||||
attachment: '附件',
|
||||
more: '更多',
|
||||
selectFileTip: '请选择文件',
|
||||
notSupportTip: '你的浏览器不支持该功能,或者当前页面非https协议',
|
||||
@ -327,5 +328,8 @@ export default {
|
||||
formatErrorTip: 'JSON格式有误,请检查后再试',
|
||||
copyTip: '已复制到剪贴板',
|
||||
formatTip: '格式化完成'
|
||||
},
|
||||
attachment: {
|
||||
deleteAttachment: '删除附件'
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,6 +225,7 @@ export default {
|
||||
this.$bus.$on('expand_btn_click', this.hide)
|
||||
this.$bus.$on('svg_mousedown', this.onMousedown)
|
||||
this.$bus.$on('mouseup', this.onMouseup)
|
||||
this.$bus.$on('translate', this.hide)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.$off('node_contextmenu', this.show)
|
||||
@ -233,6 +234,7 @@ export default {
|
||||
this.$bus.$off('expand_btn_click', this.hide)
|
||||
this.$bus.$off('svg_mousedown', this.onMousedown)
|
||||
this.$bus.$off('mouseup', this.onMouseup)
|
||||
this.$bus.$off('translate', this.hide)
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setLocalConfig']),
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
v-if="mindMap"
|
||||
:mindMap="mindMap"
|
||||
></NodeNoteContentShow>
|
||||
<NodeAttachment v-if="mindMap" :mindMap="mindMap"></NodeAttachment>
|
||||
<NodeImgPreview v-if="mindMap" :mindMap="mindMap"></NodeImgPreview>
|
||||
<SidebarTrigger v-if="!isZenMode"></SidebarTrigger>
|
||||
<Search v-if="mindMap" :mindMap="mindMap"></Search>
|
||||
@ -87,6 +88,7 @@ import Scrollbar from './Scrollbar.vue'
|
||||
import exampleData from 'simple-mind-map/example/exampleData'
|
||||
import FormulaSidebar from './FormulaSidebar.vue'
|
||||
import SourceCodeEdit from './SourceCodeEdit.vue'
|
||||
import NodeAttachment from './NodeAttachment.vue'
|
||||
|
||||
// 注册插件
|
||||
MindMap.usePlugin(MiniMap)
|
||||
@ -139,7 +141,8 @@ export default {
|
||||
OutlineEdit,
|
||||
Scrollbar,
|
||||
FormulaSidebar,
|
||||
SourceCodeEdit
|
||||
SourceCodeEdit,
|
||||
NodeAttachment
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -532,7 +535,10 @@ export default {
|
||||
'painter_start',
|
||||
'painter_end',
|
||||
'scrollbar_change',
|
||||
'scale'
|
||||
'scale',
|
||||
'translate',
|
||||
'node_attachmentClick',
|
||||
'node_attachmentContextmenu'
|
||||
].forEach(event => {
|
||||
this.mindMap.on(event, (...args) => {
|
||||
this.$bus.$emit(event, ...args)
|
||||
|
||||
133
web/src/pages/Edit/components/NodeAttachment.vue
Normal file
133
web/src/pages/Edit/components/NodeAttachment.vue
Normal file
@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<div
|
||||
class="nodeAttachmentContextMenu"
|
||||
:style="{
|
||||
left: this.left + 'px',
|
||||
top: this.top + 'px',
|
||||
visibility: show ? 'visible' : 'hidden'
|
||||
}"
|
||||
@click.stop="deleteAttachment"
|
||||
>
|
||||
<div class="menuItem">{{ $t('attachment.deleteAttachment') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mindMap: {
|
||||
type: Object,
|
||||
default() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
left: 0,
|
||||
top: 0,
|
||||
node: null,
|
||||
icon: null
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on('node_attachmentClick', this.onNodeAttachmentClick)
|
||||
this.$bus.$on('selectAttachment', this.onSelectAttachment)
|
||||
this.$bus.$on(
|
||||
'node_attachmentContextmenu',
|
||||
this.onNodeAttachmentContextmenu
|
||||
)
|
||||
this.$bus.$on('hide', this.hide)
|
||||
document.body.addEventListener('click', this.hide)
|
||||
this.$bus.$on('node_active', this.hide)
|
||||
this.$bus.$on('scale', this.onScale)
|
||||
this.$bus.$on('translate', this.onScale)
|
||||
this.$bus.$on('svg_mousedown', this.hide)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.$off('node_attachmentClick', this.onNodeAttachmentClick)
|
||||
this.$bus.$off('selectAttachment', this.onSelectAttachment)
|
||||
this.$bus.$off(
|
||||
'node_attachmentContextmenu',
|
||||
this.onNodeAttachmentContextmenu
|
||||
)
|
||||
this.$bus.$off('hide', this.hide)
|
||||
document.body.removeEventListener('click', this.hide)
|
||||
this.$bus.$off('node_active', this.hide)
|
||||
this.$bus.$off('scale', this.onScale)
|
||||
this.$bus.$off('translate', this.onScale)
|
||||
this.$bus.$off('svg_mousedown', this.hide)
|
||||
},
|
||||
methods: {
|
||||
// 选择附件
|
||||
onSelectAttachment(activeNodes) {
|
||||
// activeNodes.forEach(node => {
|
||||
// node.setAttachment('/test.md', '我去')
|
||||
// })
|
||||
},
|
||||
|
||||
// 点击附件图标,一般用来打开或下载附件
|
||||
onNodeAttachmentClick(node, e, icon) {
|
||||
// console.log(node.getData('attachmentUrl'))
|
||||
},
|
||||
|
||||
// 显示删除浮层
|
||||
onNodeAttachmentContextmenu(node, e, icon) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.node = node
|
||||
this.icon = icon
|
||||
this.updatePosition()
|
||||
this.show = true
|
||||
},
|
||||
|
||||
// 更新位置
|
||||
updatePosition() {
|
||||
const iconSize = this.mindMap.themeConfig.iconSize
|
||||
const { x, y } = this.icon.rbox()
|
||||
this.left = x + iconSize
|
||||
this.top = y
|
||||
},
|
||||
|
||||
// 画布缩放事件
|
||||
onScale() {
|
||||
console.log(1)
|
||||
if (!this.node || !this.show) return
|
||||
this.updatePosition()
|
||||
},
|
||||
|
||||
// 删除附件
|
||||
deleteAttachment() {
|
||||
if (!this.node || !this.show) return
|
||||
this.node.setAttachment('', '')
|
||||
this.hide()
|
||||
},
|
||||
|
||||
// 隐藏浮层
|
||||
hide() {
|
||||
this.show = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.nodeAttachmentContextMenu {
|
||||
position: fixed;
|
||||
background-color: #fff;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.06);
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
|
||||
.menuItem {
|
||||
font-size: 14px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -37,6 +37,7 @@ export default {
|
||||
document.body.addEventListener('click', this.hideNoteContent)
|
||||
this.$bus.$on('node_active', this.hideNoteContent)
|
||||
this.$bus.$on('scale', this.onScale)
|
||||
this.$bus.$on('translate', this.onScale)
|
||||
this.$bus.$on('svg_mousedown', this.hideNoteContent)
|
||||
},
|
||||
mounted() {
|
||||
@ -48,6 +49,7 @@ export default {
|
||||
document.body.removeEventListener('click', this.hideNoteContent)
|
||||
this.$bus.$off('node_active', this.hideNoteContent)
|
||||
this.$bus.$off('scale', this.onScale)
|
||||
this.$bus.$off('translate', this.onScale)
|
||||
this.$bus.$off('svg_mousedown', this.hideNoteContent)
|
||||
},
|
||||
methods: {
|
||||
@ -97,6 +99,8 @@ export default {
|
||||
border-radius: 5px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.06);
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
|
||||
@ -184,6 +184,7 @@ export default {
|
||||
'summary',
|
||||
'associativeLine',
|
||||
'formula'
|
||||
// 'attachment'
|
||||
],
|
||||
horizontalList: [],
|
||||
verticalList: [],
|
||||
|
||||
@ -156,6 +156,17 @@
|
||||
<span class="icon iconfont icongongshi"></span>
|
||||
<span class="text">{{ $t('toolbar.formula') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'attachment'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization
|
||||
}"
|
||||
@click="selectAttachmentFile"
|
||||
>
|
||||
<span class="icon iconfont iconfujian"></span>
|
||||
<span class="text">{{ $t('toolbar.attachment') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@ -258,6 +269,11 @@ export default {
|
||||
// 打开公式侧边栏
|
||||
showFormula() {
|
||||
this.setActiveSidebar('formulaSidebar')
|
||||
},
|
||||
|
||||
// 选择附件
|
||||
selectAttachmentFile() {
|
||||
this.$bus.$emit('selectAttachment', this.activeNodes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user