Demo:顶部工具栏支持根据窗口宽度自动收起到更多中
This commit is contained in:
parent
20157fcc8d
commit
83b916d3c9
@ -197,8 +197,8 @@ export default {
|
|||||||
toolbar: {
|
toolbar: {
|
||||||
undo: 'Undo',
|
undo: 'Undo',
|
||||||
redo: 'Redo',
|
redo: 'Redo',
|
||||||
insertSiblingNode: 'Insert sibling node',
|
insertSiblingNode: 'Sibling node',
|
||||||
insertChildNode: 'Insert child node',
|
insertChildNode: 'Child node',
|
||||||
deleteNode: 'Delete node',
|
deleteNode: 'Delete node',
|
||||||
image: 'Image',
|
image: 'Image',
|
||||||
icon: 'Icon',
|
icon: 'Icon',
|
||||||
@ -218,7 +218,8 @@ export default {
|
|||||||
shortcutKey: 'Shortcut key',
|
shortcutKey: 'Shortcut key',
|
||||||
associativeLine: 'Associative line',
|
associativeLine: 'Associative line',
|
||||||
painter: 'Painter',
|
painter: 'Painter',
|
||||||
formula: 'Formula'
|
formula: 'Formula',
|
||||||
|
more: 'More'
|
||||||
},
|
},
|
||||||
edit: {
|
edit: {
|
||||||
newFeatureNoticeTitle: 'New feature reminder',
|
newFeatureNoticeTitle: 'New feature reminder',
|
||||||
|
|||||||
@ -195,8 +195,8 @@ export default {
|
|||||||
toolbar: {
|
toolbar: {
|
||||||
undo: '回退',
|
undo: '回退',
|
||||||
redo: '前进',
|
redo: '前进',
|
||||||
insertSiblingNode: '插入同级节点',
|
insertSiblingNode: '同级节点',
|
||||||
insertChildNode: '插入子节点',
|
insertChildNode: '子节点',
|
||||||
deleteNode: '删除节点',
|
deleteNode: '删除节点',
|
||||||
image: '图片',
|
image: '图片',
|
||||||
icon: '图标',
|
icon: '图标',
|
||||||
@ -216,7 +216,8 @@ export default {
|
|||||||
shortcutKey: '快捷键',
|
shortcutKey: '快捷键',
|
||||||
associativeLine: '关联线',
|
associativeLine: '关联线',
|
||||||
painter: '格式刷',
|
painter: '格式刷',
|
||||||
formula: '公式'
|
formula: '公式',
|
||||||
|
more: '更多'
|
||||||
},
|
},
|
||||||
edit: {
|
edit: {
|
||||||
newFeatureNoticeTitle: '新特性提醒',
|
newFeatureNoticeTitle: '新特性提醒',
|
||||||
|
|||||||
@ -145,6 +145,7 @@ export default {
|
|||||||
onLangChange(lang) {
|
onLangChange(lang) {
|
||||||
i18n.locale = lang
|
i18n.locale = lang
|
||||||
storeLang(lang)
|
storeLang(lang)
|
||||||
|
this.$bus.$emit('lang_change')
|
||||||
},
|
},
|
||||||
|
|
||||||
showSearch() {
|
showSearch() {
|
||||||
|
|||||||
@ -1,149 +1,28 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="toolbarContainer" :class="{ isDark: isDark }">
|
<div class="toolbarContainer" :class="{ isDark: isDark }">
|
||||||
<div class="toolbar">
|
<div class="toolbar" ref="toolbarRef">
|
||||||
<!-- 节点操作 -->
|
<!-- 节点操作 -->
|
||||||
<div class="toolbarBlock">
|
<div class="toolbarBlock">
|
||||||
<div
|
<ToolbarNodeBtnList :list="horizontalList"></ToolbarNodeBtnList>
|
||||||
class="toolbarBtn"
|
<!-- 更多 -->
|
||||||
:class="{
|
<el-popover
|
||||||
disabled: readonly || backEnd
|
v-model="popoverShow"
|
||||||
}"
|
placement="bottom-end"
|
||||||
@click="$bus.$emit('execCommand', 'BACK')"
|
width="120"
|
||||||
|
trigger="hover"
|
||||||
|
v-if="showMoreBtn"
|
||||||
|
style="margin-left: 20px;"
|
||||||
>
|
>
|
||||||
<span class="icon iconfont iconhoutui-shi"></span>
|
<ToolbarNodeBtnList
|
||||||
<span class="text">{{ $t('toolbar.undo') }}</span>
|
dir="v"
|
||||||
</div>
|
:list="verticalList"
|
||||||
<div
|
@click.native="popoverShow = false"
|
||||||
class="toolbarBtn"
|
></ToolbarNodeBtnList>
|
||||||
:class="{
|
<div slot="reference" class="toolbarBtn">
|
||||||
disabled: readonly || forwardEnd
|
<span class="icon iconfont icongongshi"></span>
|
||||||
}"
|
<span class="text">{{ $t('toolbar.more') }}</span>
|
||||||
@click="$bus.$emit('execCommand', 'FORWARD')"
|
</div>
|
||||||
>
|
</el-popover>
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- 导出 -->
|
<!-- 导出 -->
|
||||||
<div class="toolbarBlock">
|
<div class="toolbarBlock">
|
||||||
@ -187,10 +66,12 @@ import NodeNote from './NodeNote'
|
|||||||
import NodeTag from './NodeTag'
|
import NodeTag from './NodeTag'
|
||||||
import Export from './Export'
|
import Export from './Export'
|
||||||
import Import from './Import'
|
import Import from './Import'
|
||||||
import { mapState, mapMutations } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import { Notification } from 'element-ui'
|
import { Notification } from 'element-ui'
|
||||||
import exampleData from 'simple-mind-map/example/exampleData'
|
import exampleData from 'simple-mind-map/example/exampleData'
|
||||||
import { getData } from '../../../api'
|
import { getData } from '../../../api'
|
||||||
|
import ToolbarNodeBtnList from './ToolbarNodeBtnList.vue'
|
||||||
|
import { throttle } from 'simple-mind-map/src/utils/index'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: 王林
|
* @Author: 王林
|
||||||
@ -207,35 +88,35 @@ export default {
|
|||||||
NodeNote,
|
NodeNote,
|
||||||
NodeTag,
|
NodeTag,
|
||||||
Export,
|
Export,
|
||||||
Import
|
Import,
|
||||||
|
ToolbarNodeBtnList
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeNodes: [],
|
list: [
|
||||||
backEnd: false,
|
'back',
|
||||||
forwardEnd: true,
|
'forward',
|
||||||
readonly: false,
|
'painter',
|
||||||
isFullDataFile: false,
|
'siblingNode',
|
||||||
timer: null,
|
'childNode',
|
||||||
isInPainter: false
|
'deleteNode',
|
||||||
|
'image',
|
||||||
|
'icon',
|
||||||
|
'link',
|
||||||
|
'note',
|
||||||
|
'tag',
|
||||||
|
'summary',
|
||||||
|
'associativeLine',
|
||||||
|
'formula'
|
||||||
|
],
|
||||||
|
horizontalList: [],
|
||||||
|
verticalList: [],
|
||||||
|
showMoreBtn: true,
|
||||||
|
popoverShow: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['isHandleLocalFile', 'isDark']),
|
...mapState(['isHandleLocalFile', 'isDark'])
|
||||||
hasRoot() {
|
|
||||||
return (
|
|
||||||
this.activeNodes.findIndex(node => {
|
|
||||||
return node.isRoot
|
|
||||||
}) !== -1
|
|
||||||
)
|
|
||||||
},
|
|
||||||
hasGeneralization() {
|
|
||||||
return (
|
|
||||||
this.activeNodes.findIndex(node => {
|
|
||||||
return node.isGeneralization
|
|
||||||
}) !== -1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
isHandleLocalFile(val) {
|
isHandleLocalFile(val) {
|
||||||
@ -245,68 +126,48 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
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('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() {
|
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('write_local_file', this.onWriteLocalFile)
|
||||||
this.$bus.$off('painter_start', this.onPainterStart)
|
window.removeEventListener('resize', this.computeToolbarShowThrottle)
|
||||||
this.$bus.$off('painter_end', this.onPainterEnd)
|
this.$bus.$off('lang_change', this.computeToolbarShowThrottle)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations(['setActiveSidebar']),
|
// 计算工具按钮如何显示
|
||||||
|
computeToolbarShow() {
|
||||||
showNodeIcon() {
|
const windowWidth = window.innerWidth - 40
|
||||||
// this.$bus.$emit('showNodeIcon')
|
const all = [...this.list]
|
||||||
this.$bus.$emit('close_node_icon_toolbar')
|
let index = 1
|
||||||
this.setActiveSidebar('nodeIconSidebar')
|
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) {
|
onWriteLocalFile(content) {
|
||||||
clearTimeout(this.timer)
|
clearTimeout(this.timer)
|
||||||
this.timer = setTimeout(() => {
|
this.timer = setTimeout(() => {
|
||||||
@ -314,11 +175,7 @@ export default {
|
|||||||
}, 1000)
|
}, 1000)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// 打开本地文件
|
||||||
* @Author: 王林
|
|
||||||
* @Date: 2022-09-24 15:40:09
|
|
||||||
* @Desc: 打开本地文件
|
|
||||||
*/
|
|
||||||
async openLocalFile() {
|
async openLocalFile() {
|
||||||
try {
|
try {
|
||||||
let [_fileHandle] = await window.showOpenFilePicker({
|
let [_fileHandle] = await window.showOpenFilePicker({
|
||||||
@ -353,11 +210,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// 读取本地文件
|
||||||
* @Author: 王林
|
|
||||||
* @Date: 2022-09-24 15:40:18
|
|
||||||
* @Desc: 读取本地文件
|
|
||||||
*/
|
|
||||||
async readFile() {
|
async readFile() {
|
||||||
let file = await fileHandle.getFile()
|
let file = await fileHandle.getFile()
|
||||||
let fileReader = new FileReader()
|
let fileReader = new FileReader()
|
||||||
@ -375,11 +228,7 @@ export default {
|
|||||||
fileReader.readAsText(file)
|
fileReader.readAsText(file)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// 渲染读取的数据
|
||||||
* @Author: 王林
|
|
||||||
* @Date: 2022-09-24 15:40:26
|
|
||||||
* @Desc: 渲染读取的数据
|
|
||||||
*/
|
|
||||||
setData(str) {
|
setData(str) {
|
||||||
try {
|
try {
|
||||||
let data = JSON.parse(str)
|
let data = JSON.parse(str)
|
||||||
@ -402,11 +251,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// 写入本地文件
|
||||||
* @Author: 王林
|
|
||||||
* @Date: 2022-09-24 15:40:42
|
|
||||||
* @Desc: 写入本地文件
|
|
||||||
*/
|
|
||||||
async writeLocalFile(content) {
|
async writeLocalFile(content) {
|
||||||
if (!fileHandle || !this.isHandleLocalFile) {
|
if (!fileHandle || !this.isHandleLocalFile) {
|
||||||
return
|
return
|
||||||
@ -420,30 +265,18 @@ export default {
|
|||||||
await writable.close()
|
await writable.close()
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// 创建本地文件
|
||||||
* @Author: 王林
|
|
||||||
* @Date: 2022-09-24 15:40:48
|
|
||||||
* @Desc: 创建本地文件
|
|
||||||
*/
|
|
||||||
async createNewLocalFile() {
|
async createNewLocalFile() {
|
||||||
await this.createLocalFile(exampleData)
|
await this.createLocalFile(exampleData)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// 另存为
|
||||||
* @Author: 王林
|
|
||||||
* @Date: 2022-09-24 15:49:17
|
|
||||||
* @Desc: 另存为
|
|
||||||
*/
|
|
||||||
async saveLocalFile() {
|
async saveLocalFile() {
|
||||||
let data = getData()
|
let data = getData()
|
||||||
await this.createLocalFile(data)
|
await this.createLocalFile(data)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// 创建本地文件
|
||||||
* @Author: 王林
|
|
||||||
* @Date: 2022-09-24 15:50:22
|
|
||||||
* @Desc: 创建本地文件
|
|
||||||
*/
|
|
||||||
async createLocalFile(content) {
|
async createLocalFile(content) {
|
||||||
try {
|
try {
|
||||||
let _fileHandle = await window.showSaveFilePicker({
|
let _fileHandle = await window.showSaveFilePicker({
|
||||||
@ -479,14 +312,6 @@ export default {
|
|||||||
'你的浏览器可能不支持,建议使用最新版本的Chrome浏览器'
|
'你的浏览器可能不支持,建议使用最新版本的Chrome浏览器'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
onPainterStart() {
|
|
||||||
this.isInPainter = true
|
|
||||||
},
|
|
||||||
|
|
||||||
onPainterEnd() {
|
|
||||||
this.isInPainter = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,7 +321,7 @@ export default {
|
|||||||
.toolbarContainer {
|
.toolbarContainer {
|
||||||
&.isDark {
|
&.isDark {
|
||||||
.toolbar {
|
.toolbar {
|
||||||
color: hsla(0,0%,100%,.9);
|
color: hsla(0, 0%, 100%, 0.9);
|
||||||
.toolbarBlock {
|
.toolbarBlock {
|
||||||
background-color: #262a2e;
|
background-color: #262a2e;
|
||||||
}
|
}
|
||||||
@ -510,7 +335,7 @@ export default {
|
|||||||
&:hover {
|
&:hover {
|
||||||
&:not(.disabled) {
|
&:not(.disabled) {
|
||||||
.icon {
|
.icon {
|
||||||
background: hsla(0,0%,100%,.05);
|
background: hsla(0, 0%, 100%, 0.05);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -527,14 +352,12 @@ export default {
|
|||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
top: 20px;
|
top: 20px;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
max-width: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-family: PingFangSC-Regular, PingFang SC;
|
font-family: PingFangSC-Regular, PingFang SC;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: rgba(26, 26, 26, 0.8);
|
color: rgba(26, 26, 26, 0.8);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
overflow-x: auto;
|
|
||||||
|
|
||||||
.toolbarBlock {
|
.toolbarBlock {
|
||||||
display: flex;
|
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>
|
</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…
x
Reference in New Issue
Block a user