mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-21 10:27:44 +08:00
Demo:顶部工具栏支持根据窗口宽度自动收起到更多中
This commit is contained in:
parent
20157fcc8d
commit
83b916d3c9
@ -197,8 +197,8 @@ export default {
|
||||
toolbar: {
|
||||
undo: 'Undo',
|
||||
redo: 'Redo',
|
||||
insertSiblingNode: 'Insert sibling node',
|
||||
insertChildNode: 'Insert child node',
|
||||
insertSiblingNode: 'Sibling node',
|
||||
insertChildNode: 'Child node',
|
||||
deleteNode: 'Delete node',
|
||||
image: 'Image',
|
||||
icon: 'Icon',
|
||||
@ -218,7 +218,8 @@ export default {
|
||||
shortcutKey: 'Shortcut key',
|
||||
associativeLine: 'Associative line',
|
||||
painter: 'Painter',
|
||||
formula: 'Formula'
|
||||
formula: 'Formula',
|
||||
more: 'More'
|
||||
},
|
||||
edit: {
|
||||
newFeatureNoticeTitle: 'New feature reminder',
|
||||
|
||||
@ -195,8 +195,8 @@ export default {
|
||||
toolbar: {
|
||||
undo: '回退',
|
||||
redo: '前进',
|
||||
insertSiblingNode: '插入同级节点',
|
||||
insertChildNode: '插入子节点',
|
||||
insertSiblingNode: '同级节点',
|
||||
insertChildNode: '子节点',
|
||||
deleteNode: '删除节点',
|
||||
image: '图片',
|
||||
icon: '图标',
|
||||
@ -216,7 +216,8 @@ export default {
|
||||
shortcutKey: '快捷键',
|
||||
associativeLine: '关联线',
|
||||
painter: '格式刷',
|
||||
formula: '公式'
|
||||
formula: '公式',
|
||||
more: '更多'
|
||||
},
|
||||
edit: {
|
||||
newFeatureNoticeTitle: '新特性提醒',
|
||||
|
||||
@ -145,6 +145,7 @@ export default {
|
||||
onLangChange(lang) {
|
||||
i18n.locale = lang
|
||||
storeLang(lang)
|
||||
this.$bus.$emit('lang_change')
|
||||
},
|
||||
|
||||
showSearch() {
|
||||
|
||||
@ -1,149 +1,28 @@
|
||||
<template>
|
||||
<div class="toolbarContainer" :class="{ isDark: isDark }">
|
||||
<div class="toolbar">
|
||||
<div class="toolbar" ref="toolbarRef">
|
||||
<!-- 节点操作 -->
|
||||
<div class="toolbarBlock">
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: readonly || backEnd
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'BACK')"
|
||||
<ToolbarNodeBtnList :list="horizontalList"></ToolbarNodeBtnList>
|
||||
<!-- 更多 -->
|
||||
<el-popover
|
||||
v-model="popoverShow"
|
||||
placement="bottom-end"
|
||||
width="120"
|
||||
trigger="hover"
|
||||
v-if="showMoreBtn"
|
||||
style="margin-left: 20px;"
|
||||
>
|
||||
<span class="icon iconfont iconhoutui-shi"></span>
|
||||
<span class="text">{{ $t('toolbar.undo') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: readonly || forwardEnd
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'FORWARD')"
|
||||
>
|
||||
<span class="icon iconfont iconqianjin1"></span>
|
||||
<span class="text">{{ $t('toolbar.redo') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization,
|
||||
active: isInPainter
|
||||
}"
|
||||
@click="$bus.$emit('startPainter')"
|
||||
>
|
||||
<span class="icon iconfont iconjiedian"></span>
|
||||
<span class="text">{{ $t('toolbar.painter') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasRoot || hasGeneralization
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_NODE')"
|
||||
>
|
||||
<span class="icon iconfont iconjiedian"></span>
|
||||
<span class="text">{{ $t('toolbar.insertSiblingNode') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_CHILD_NODE')"
|
||||
>
|
||||
<span class="icon iconfont icontianjiazijiedian"></span>
|
||||
<span class="text">{{ $t('toolbar.insertChildNode') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'REMOVE_NODE')"
|
||||
>
|
||||
<span class="icon iconfont iconshanchu"></span>
|
||||
<span class="text">{{ $t('toolbar.deleteNode') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('showNodeImage')"
|
||||
>
|
||||
<span class="icon iconfont iconimage"></span>
|
||||
<span class="text">{{ $t('toolbar.image') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="showNodeIcon"
|
||||
>
|
||||
<span class="icon iconfont iconxiaolian"></span>
|
||||
<span class="text">{{ $t('toolbar.icon') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('showNodeLink')"
|
||||
>
|
||||
<span class="icon iconfont iconchaolianjie"></span>
|
||||
<span class="text">{{ $t('toolbar.link') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('showNodeNote')"
|
||||
>
|
||||
<span class="icon iconfont iconflow-Mark"></span>
|
||||
<span class="text">{{ $t('toolbar.note') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('showNodeTag')"
|
||||
>
|
||||
<span class="icon iconfont iconbiaoqian"></span>
|
||||
<span class="text">{{ $t('toolbar.tag') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasRoot || hasGeneralization
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'ADD_GENERALIZATION')"
|
||||
>
|
||||
<span class="icon iconfont icongaikuozonglan"></span>
|
||||
<span class="text">{{ $t('toolbar.summary') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization
|
||||
}"
|
||||
@click="$bus.$emit('createAssociativeLine')"
|
||||
>
|
||||
<span class="icon iconfont iconlianjiexian"></span>
|
||||
<span class="text">{{ $t('toolbar.associativeLine') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization
|
||||
}"
|
||||
@click="showFormula"
|
||||
>
|
||||
<span class="icon iconfont icongongshi"></span>
|
||||
<span class="text">{{ $t('toolbar.formula') }}</span>
|
||||
</div>
|
||||
<ToolbarNodeBtnList
|
||||
dir="v"
|
||||
:list="verticalList"
|
||||
@click.native="popoverShow = false"
|
||||
></ToolbarNodeBtnList>
|
||||
<div slot="reference" class="toolbarBtn">
|
||||
<span class="icon iconfont icongongshi"></span>
|
||||
<span class="text">{{ $t('toolbar.more') }}</span>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
<!-- 导出 -->
|
||||
<div class="toolbarBlock">
|
||||
@ -187,10 +66,12 @@ import NodeNote from './NodeNote'
|
||||
import NodeTag from './NodeTag'
|
||||
import Export from './Export'
|
||||
import Import from './Import'
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
import { mapState } from 'vuex'
|
||||
import { Notification } from 'element-ui'
|
||||
import exampleData from 'simple-mind-map/example/exampleData'
|
||||
import { getData } from '../../../api'
|
||||
import ToolbarNodeBtnList from './ToolbarNodeBtnList.vue'
|
||||
import { throttle } from 'simple-mind-map/src/utils/index'
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
@ -207,35 +88,35 @@ export default {
|
||||
NodeNote,
|
||||
NodeTag,
|
||||
Export,
|
||||
Import
|
||||
Import,
|
||||
ToolbarNodeBtnList
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeNodes: [],
|
||||
backEnd: false,
|
||||
forwardEnd: true,
|
||||
readonly: false,
|
||||
isFullDataFile: false,
|
||||
timer: null,
|
||||
isInPainter: false
|
||||
list: [
|
||||
'back',
|
||||
'forward',
|
||||
'painter',
|
||||
'siblingNode',
|
||||
'childNode',
|
||||
'deleteNode',
|
||||
'image',
|
||||
'icon',
|
||||
'link',
|
||||
'note',
|
||||
'tag',
|
||||
'summary',
|
||||
'associativeLine',
|
||||
'formula'
|
||||
],
|
||||
horizontalList: [],
|
||||
verticalList: [],
|
||||
showMoreBtn: true,
|
||||
popoverShow: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['isHandleLocalFile', 'isDark']),
|
||||
hasRoot() {
|
||||
return (
|
||||
this.activeNodes.findIndex(node => {
|
||||
return node.isRoot
|
||||
}) !== -1
|
||||
)
|
||||
},
|
||||
hasGeneralization() {
|
||||
return (
|
||||
this.activeNodes.findIndex(node => {
|
||||
return node.isGeneralization
|
||||
}) !== -1
|
||||
)
|
||||
}
|
||||
...mapState(['isHandleLocalFile', 'isDark'])
|
||||
},
|
||||
watch: {
|
||||
isHandleLocalFile(val) {
|
||||
@ -245,68 +126,48 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on('mode_change', this.onModeChange)
|
||||
this.$bus.$on('node_active', this.onNodeActive)
|
||||
this.$bus.$on('back_forward', this.onBackForward)
|
||||
this.$bus.$on('write_local_file', this.onWriteLocalFile)
|
||||
this.$bus.$on('painter_start', this.onPainterStart)
|
||||
this.$bus.$on('painter_end', this.onPainterEnd)
|
||||
},
|
||||
mounted() {
|
||||
this.computeToolbarShow()
|
||||
this.computeToolbarShowThrottle = throttle(this.computeToolbarShow, 300)
|
||||
window.addEventListener('resize', this.computeToolbarShowThrottle)
|
||||
this.$bus.$on('lang_change', this.computeToolbarShowThrottle)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.$off('mode_change', this.onModeChange)
|
||||
this.$bus.$off('node_active', this.onNodeActive)
|
||||
this.$bus.$off('back_forward', this.onBackForward)
|
||||
this.$bus.$off('write_local_file', this.onWriteLocalFile)
|
||||
this.$bus.$off('painter_start', this.onPainterStart)
|
||||
this.$bus.$off('painter_end', this.onPainterEnd)
|
||||
window.removeEventListener('resize', this.computeToolbarShowThrottle)
|
||||
this.$bus.$off('lang_change', this.computeToolbarShowThrottle)
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setActiveSidebar']),
|
||||
|
||||
showNodeIcon() {
|
||||
// this.$bus.$emit('showNodeIcon')
|
||||
this.$bus.$emit('close_node_icon_toolbar')
|
||||
this.setActiveSidebar('nodeIconSidebar')
|
||||
// 计算工具按钮如何显示
|
||||
computeToolbarShow() {
|
||||
const windowWidth = window.innerWidth - 40
|
||||
const all = [...this.list]
|
||||
let index = 1
|
||||
const loopCheck = () => {
|
||||
if (index > all.length) return done()
|
||||
this.horizontalList = all.slice(0, index)
|
||||
this.$nextTick(() => {
|
||||
const width = this.$refs.toolbarRef.getBoundingClientRect().width
|
||||
if (width < windowWidth) {
|
||||
index++
|
||||
loopCheck()
|
||||
} else if (index > 0 && width > windowWidth) {
|
||||
index--
|
||||
this.horizontalList = all.slice(0, index)
|
||||
done()
|
||||
}
|
||||
})
|
||||
}
|
||||
const done = () => {
|
||||
this.verticalList = all.slice(index)
|
||||
this.showMoreBtn = this.verticalList.length > 0
|
||||
}
|
||||
loopCheck()
|
||||
},
|
||||
|
||||
// 打开公式侧边栏
|
||||
showFormula() {
|
||||
this.setActiveSidebar('formulaSidebar')
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-11-14 19:17:40
|
||||
* @Desc: 监听模式切换
|
||||
*/
|
||||
onModeChange(mode) {
|
||||
this.readonly = mode === 'readonly'
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-11-14 19:18:06
|
||||
* @Desc: 监听节点激活
|
||||
*/
|
||||
onNodeActive(...args) {
|
||||
this.activeNodes = [...args[1]]
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-11-14 19:18:31
|
||||
* @Desc: 监听前进后退
|
||||
*/
|
||||
onBackForward(index, len) {
|
||||
this.backEnd = index <= 0
|
||||
this.forwardEnd = index >= len - 1
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-11-14 19:19:14
|
||||
* @Desc: 监听本地文件读写
|
||||
*/
|
||||
// 监听本地文件读写
|
||||
onWriteLocalFile(content) {
|
||||
clearTimeout(this.timer)
|
||||
this.timer = setTimeout(() => {
|
||||
@ -314,11 +175,7 @@ export default {
|
||||
}, 1000)
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-09-24 15:40:09
|
||||
* @Desc: 打开本地文件
|
||||
*/
|
||||
// 打开本地文件
|
||||
async openLocalFile() {
|
||||
try {
|
||||
let [_fileHandle] = await window.showOpenFilePicker({
|
||||
@ -353,11 +210,7 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-09-24 15:40:18
|
||||
* @Desc: 读取本地文件
|
||||
*/
|
||||
// 读取本地文件
|
||||
async readFile() {
|
||||
let file = await fileHandle.getFile()
|
||||
let fileReader = new FileReader()
|
||||
@ -375,11 +228,7 @@ export default {
|
||||
fileReader.readAsText(file)
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-09-24 15:40:26
|
||||
* @Desc: 渲染读取的数据
|
||||
*/
|
||||
// 渲染读取的数据
|
||||
setData(str) {
|
||||
try {
|
||||
let data = JSON.parse(str)
|
||||
@ -402,11 +251,7 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-09-24 15:40:42
|
||||
* @Desc: 写入本地文件
|
||||
*/
|
||||
// 写入本地文件
|
||||
async writeLocalFile(content) {
|
||||
if (!fileHandle || !this.isHandleLocalFile) {
|
||||
return
|
||||
@ -420,30 +265,18 @@ export default {
|
||||
await writable.close()
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-09-24 15:40:48
|
||||
* @Desc: 创建本地文件
|
||||
*/
|
||||
// 创建本地文件
|
||||
async createNewLocalFile() {
|
||||
await this.createLocalFile(exampleData)
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-09-24 15:49:17
|
||||
* @Desc: 另存为
|
||||
*/
|
||||
// 另存为
|
||||
async saveLocalFile() {
|
||||
let data = getData()
|
||||
await this.createLocalFile(data)
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-09-24 15:50:22
|
||||
* @Desc: 创建本地文件
|
||||
*/
|
||||
// 创建本地文件
|
||||
async createLocalFile(content) {
|
||||
try {
|
||||
let _fileHandle = await window.showSaveFilePicker({
|
||||
@ -479,14 +312,6 @@ export default {
|
||||
'你的浏览器可能不支持,建议使用最新版本的Chrome浏览器'
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
onPainterStart() {
|
||||
this.isInPainter = true
|
||||
},
|
||||
|
||||
onPainterEnd() {
|
||||
this.isInPainter = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,7 +321,7 @@ export default {
|
||||
.toolbarContainer {
|
||||
&.isDark {
|
||||
.toolbar {
|
||||
color: hsla(0,0%,100%,.9);
|
||||
color: hsla(0, 0%, 100%, 0.9);
|
||||
.toolbarBlock {
|
||||
background-color: #262a2e;
|
||||
}
|
||||
@ -510,7 +335,7 @@ export default {
|
||||
&:hover {
|
||||
&:not(.disabled) {
|
||||
.icon {
|
||||
background: hsla(0,0%,100%,.05);
|
||||
background: hsla(0, 0%, 100%, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -527,14 +352,12 @@ export default {
|
||||
transform: translateX(-50%);
|
||||
top: 20px;
|
||||
width: max-content;
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: rgba(26, 26, 26, 0.8);
|
||||
z-index: 2;
|
||||
overflow-x: auto;
|
||||
|
||||
.toolbarBlock {
|
||||
display: flex;
|
||||
@ -600,16 +423,4 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1040px) {
|
||||
.toolbarContainer {
|
||||
.toolbar {
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
transform: translateX(0);
|
||||
width: auto;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
367
web/src/pages/Edit/components/ToolbarNodeBtnList.vue
Normal file
367
web/src/pages/Edit/components/ToolbarNodeBtnList.vue
Normal file
@ -0,0 +1,367 @@
|
||||
<template>
|
||||
<div class="toolbarNodeBtnList" :class="[dir, { isDark: isDark }]">
|
||||
<template v-for="item in list">
|
||||
<div
|
||||
v-if="item === 'back'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: readonly || backEnd
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'BACK')"
|
||||
>
|
||||
<span class="icon iconfont iconhoutui-shi"></span>
|
||||
<span class="text">{{ $t('toolbar.undo') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'forward'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: readonly || forwardEnd
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'FORWARD')"
|
||||
>
|
||||
<span class="icon iconfont iconqianjin1"></span>
|
||||
<span class="text">{{ $t('toolbar.redo') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'painter'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization,
|
||||
active: isInPainter
|
||||
}"
|
||||
@click="$bus.$emit('startPainter')"
|
||||
>
|
||||
<span class="icon iconfont iconjiedian"></span>
|
||||
<span class="text">{{ $t('toolbar.painter') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'siblingNode'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasRoot || hasGeneralization
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_NODE')"
|
||||
>
|
||||
<span class="icon iconfont iconjiedian"></span>
|
||||
<span class="text">{{ $t('toolbar.insertSiblingNode') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'childNode'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_CHILD_NODE')"
|
||||
>
|
||||
<span class="icon iconfont icontianjiazijiedian"></span>
|
||||
<span class="text">{{ $t('toolbar.insertChildNode') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'deleteNode'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'REMOVE_NODE')"
|
||||
>
|
||||
<span class="icon iconfont iconshanchu"></span>
|
||||
<span class="text">{{ $t('toolbar.deleteNode') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'image'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('showNodeImage')"
|
||||
>
|
||||
<span class="icon iconfont iconimage"></span>
|
||||
<span class="text">{{ $t('toolbar.image') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'icon'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="showNodeIcon"
|
||||
>
|
||||
<span class="icon iconfont iconxiaolian"></span>
|
||||
<span class="text">{{ $t('toolbar.icon') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'link'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('showNodeLink')"
|
||||
>
|
||||
<span class="icon iconfont iconchaolianjie"></span>
|
||||
<span class="text">{{ $t('toolbar.link') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'note'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('showNodeNote')"
|
||||
>
|
||||
<span class="icon iconfont iconflow-Mark"></span>
|
||||
<span class="text">{{ $t('toolbar.note') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'tag'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0
|
||||
}"
|
||||
@click="$bus.$emit('showNodeTag')"
|
||||
>
|
||||
<span class="icon iconfont iconbiaoqian"></span>
|
||||
<span class="text">{{ $t('toolbar.tag') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'summary'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasRoot || hasGeneralization
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'ADD_GENERALIZATION')"
|
||||
>
|
||||
<span class="icon iconfont icongaikuozonglan"></span>
|
||||
<span class="text">{{ $t('toolbar.summary') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'associativeLine'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization
|
||||
}"
|
||||
@click="$bus.$emit('createAssociativeLine')"
|
||||
>
|
||||
<span class="icon iconfont iconlianjiexian"></span>
|
||||
<span class="text">{{ $t('toolbar.associativeLine') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="item === 'formula'"
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization
|
||||
}"
|
||||
@click="showFormula"
|
||||
>
|
||||
<span class="icon iconfont icongongshi"></span>
|
||||
<span class="text">{{ $t('toolbar.formula') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
dir: {
|
||||
type: String,
|
||||
default: 'h' // h(水平排列)、v(垂直排列)
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeNodes: [],
|
||||
backEnd: false,
|
||||
forwardEnd: true,
|
||||
readonly: false,
|
||||
isFullDataFile: false,
|
||||
timer: null,
|
||||
isInPainter: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['isDark']),
|
||||
hasRoot() {
|
||||
return (
|
||||
this.activeNodes.findIndex(node => {
|
||||
return node.isRoot
|
||||
}) !== -1
|
||||
)
|
||||
},
|
||||
hasGeneralization() {
|
||||
return (
|
||||
this.activeNodes.findIndex(node => {
|
||||
return node.isGeneralization
|
||||
}) !== -1
|
||||
)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on('mode_change', this.onModeChange)
|
||||
this.$bus.$on('node_active', this.onNodeActive)
|
||||
this.$bus.$on('back_forward', this.onBackForward)
|
||||
this.$bus.$on('painter_start', this.onPainterStart)
|
||||
this.$bus.$on('painter_end', this.onPainterEnd)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.$off('mode_change', this.onModeChange)
|
||||
this.$bus.$off('node_active', this.onNodeActive)
|
||||
this.$bus.$off('back_forward', this.onBackForward)
|
||||
this.$bus.$off('painter_start', this.onPainterStart)
|
||||
this.$bus.$off('painter_end', this.onPainterEnd)
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setActiveSidebar']),
|
||||
|
||||
// 监听模式切换
|
||||
onModeChange(mode) {
|
||||
this.readonly = mode === 'readonly'
|
||||
},
|
||||
|
||||
// 监听节点激活
|
||||
onNodeActive(...args) {
|
||||
this.activeNodes = [...args[1]]
|
||||
},
|
||||
|
||||
// 监听前进后退
|
||||
onBackForward(index, len) {
|
||||
this.backEnd = index <= 0
|
||||
this.forwardEnd = index >= len - 1
|
||||
},
|
||||
|
||||
// 开始格式刷
|
||||
onPainterStart() {
|
||||
this.isInPainter = true
|
||||
},
|
||||
|
||||
// 格式刷结束
|
||||
onPainterEnd() {
|
||||
this.isInPainter = false
|
||||
},
|
||||
|
||||
// 显示节点图标侧边栏
|
||||
showNodeIcon() {
|
||||
this.$bus.$emit('close_node_icon_toolbar')
|
||||
this.setActiveSidebar('nodeIconSidebar')
|
||||
},
|
||||
|
||||
// 打开公式侧边栏
|
||||
showFormula() {
|
||||
this.setActiveSidebar('formulaSidebar')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.toolbarNodeBtnList {
|
||||
display: flex;
|
||||
|
||||
&.isDark {
|
||||
.toolbarBtn {
|
||||
color: hsla(0, 0%, 100%, 0.9);
|
||||
|
||||
.icon {
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:not(.disabled) {
|
||||
.icon {
|
||||
background: hsla(0, 0%, 100%, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
color: #54595f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toolbarBtn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
cursor: pointer;
|
||||
margin-right: 20px;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:not(.disabled) {
|
||||
.icon {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
.icon {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
color: #bcbcbc;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: flex;
|
||||
height: 26px;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #e9e9e9;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&.v {
|
||||
display: block;
|
||||
width: 120px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.toolbarBtn {
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
margin-right: 0;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.text {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user