mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-17 22:08:25 +08:00
完成节点内容设置及主题
This commit is contained in:
BIN
web/src/.DS_Store
vendored
BIN
web/src/.DS_Store
vendored
Binary file not shown.
BIN
web/src/assets/.DS_Store
vendored
BIN
web/src/assets/.DS_Store
vendored
Binary file not shown.
BIN
web/src/assets/icon-font/.DS_Store
vendored
BIN
web/src/assets/icon-font/.DS_Store
vendored
Binary file not shown.
@@ -54,6 +54,24 @@
|
||||
<div class="content unicode" style="display: block;">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">导出</div>
|
||||
<div class="code-name">&#xe63d;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">标签</div>
|
||||
<div class="code-name">&#xe63c;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">流程-备注</div>
|
||||
<div class="code-name">&#xe65b;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">超链接</div>
|
||||
@@ -144,9 +162,9 @@
|
||||
<pre><code class="language-css"
|
||||
>@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('iconfont.woff2?t=1622956585729') format('woff2'),
|
||||
url('iconfont.woff?t=1622956585729') format('woff'),
|
||||
url('iconfont.ttf?t=1622956585729') format('truetype');
|
||||
src: url('iconfont.woff2?t=1624540474886') format('woff2'),
|
||||
url('iconfont.woff?t=1624540474886') format('woff'),
|
||||
url('iconfont.ttf?t=1624540474886') format('truetype');
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||
@@ -172,6 +190,33 @@
|
||||
<div class="content font-class">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icondaochu"></span>
|
||||
<div class="name">
|
||||
导出
|
||||
</div>
|
||||
<div class="code-name">.icondaochu
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconbiaoqian"></span>
|
||||
<div class="name">
|
||||
标签
|
||||
</div>
|
||||
<div class="code-name">.iconbiaoqian
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconflow-Mark"></span>
|
||||
<div class="name">
|
||||
流程-备注
|
||||
</div>
|
||||
<div class="code-name">.iconflow-Mark
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconchaolianjie"></span>
|
||||
<div class="name">
|
||||
@@ -307,6 +352,30 @@
|
||||
<div class="content symbol">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icondaochu"></use>
|
||||
</svg>
|
||||
<div class="name">导出</div>
|
||||
<div class="code-name">#icondaochu</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconbiaoqian"></use>
|
||||
</svg>
|
||||
<div class="name">标签</div>
|
||||
<div class="code-name">#iconbiaoqian</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconflow-Mark"></use>
|
||||
</svg>
|
||||
<div class="name">流程-备注</div>
|
||||
<div class="code-name">#iconflow-Mark</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconchaolianjie"></use>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2479351 */
|
||||
src: url('iconfont.woff2?t=1622956585729') format('woff2'),
|
||||
url('iconfont.woff?t=1622956585729') format('woff'),
|
||||
url('iconfont.ttf?t=1622956585729') format('truetype');
|
||||
src: url('iconfont.woff2?t=1624540474886') format('woff2'),
|
||||
url('iconfont.woff?t=1624540474886') format('woff'),
|
||||
url('iconfont.ttf?t=1624540474886') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@@ -13,6 +13,18 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icondaochu:before {
|
||||
content: "\e63d";
|
||||
}
|
||||
|
||||
.iconbiaoqian:before {
|
||||
content: "\e63c";
|
||||
}
|
||||
|
||||
.iconflow-Mark:before {
|
||||
content: "\e65b";
|
||||
}
|
||||
|
||||
.iconchaolianjie:before {
|
||||
content: "\e6f4";
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,27 @@
|
||||
"css_prefix_text": "icon",
|
||||
"description": "思维导图",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "788015",
|
||||
"name": "导出",
|
||||
"font_class": "daochu",
|
||||
"unicode": "e63d",
|
||||
"unicode_decimal": 58941
|
||||
},
|
||||
{
|
||||
"icon_id": "2678575",
|
||||
"name": "标签",
|
||||
"font_class": "biaoqian",
|
||||
"unicode": "e63c",
|
||||
"unicode_decimal": 58940
|
||||
},
|
||||
{
|
||||
"icon_id": "6265396",
|
||||
"name": "流程-备注",
|
||||
"font_class": "flow-Mark",
|
||||
"unicode": "e65b",
|
||||
"unicode_decimal": 58971
|
||||
},
|
||||
{
|
||||
"icon_id": "1790486",
|
||||
"name": "超链接",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,16 +1,14 @@
|
||||
<template>
|
||||
<div class="imgUploadContainer">
|
||||
<div class="imgUploadPanel">
|
||||
<div class="upBtn" v-if="!previewSrc">
|
||||
<div class="upBtn" v-if="!value">
|
||||
<label
|
||||
for="imgUploadInput"
|
||||
class="imgUploadInputArea"
|
||||
@dragenter.stop.prevent
|
||||
@dragover.stop.prevent
|
||||
@drop.stop.prevent="onDrop"
|
||||
v-loading="loading"
|
||||
element-loading-text="上传中..."
|
||||
>点击此处添加图片、或拖动图片到此</label
|
||||
>点击此处选择图片、或拖动图片到此</label
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
@@ -19,10 +17,10 @@
|
||||
@change="onImgUploadInputChange"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="previewSrc" class="uploadInfoBox">
|
||||
<div v-if="value" class="uploadInfoBox">
|
||||
<div
|
||||
class="previewBox"
|
||||
:style="{ backgroundImage: `url('${previewSrc}')` }"
|
||||
:style="{ backgroundImage: `url('${value}')` }"
|
||||
></div>
|
||||
<span class="delBtn el-icon-close" @click="deleteImg"></span>
|
||||
</div>
|
||||
@@ -33,11 +31,19 @@
|
||||
<script>
|
||||
export default {
|
||||
name: "ImgUpload",
|
||||
model: {
|
||||
prop: "value",
|
||||
event: "change",
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
file: null,
|
||||
previewSrc: "",
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -48,7 +54,7 @@ export default {
|
||||
*/
|
||||
onImgUploadInputChange(e) {
|
||||
let file = e.target.files[0];
|
||||
this.uploadImg(file);
|
||||
this.selectImg(file);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -59,40 +65,42 @@ export default {
|
||||
onDrop(e) {
|
||||
let dt = e.dataTransfer;
|
||||
let file = dt.files && dt.files[0];
|
||||
this.uploadImg(file);
|
||||
this.selectImg(file);
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 16:56:14
|
||||
* @Desc: 显示图片
|
||||
* @Desc: 选择图片
|
||||
*/
|
||||
showImg(file) {
|
||||
selectImg(file) {
|
||||
this.file = file;
|
||||
let fr = new FileReader();
|
||||
fr.readAsDataURL(file);
|
||||
fr.onload = (e) => {
|
||||
this.previewSrc = e.target.result;
|
||||
this.$emit("change", e.target.result);
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2019-12-22 19:51:13
|
||||
* @Desc: 上传图片
|
||||
* @Date: 2021-06-22 23:03:46
|
||||
* @Desc: 获取图片大小
|
||||
*/
|
||||
async uploadImg(file) {
|
||||
this.loading = true;
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 22:33:28
|
||||
* @Desc: 获取图片url
|
||||
*/
|
||||
getUrl() {
|
||||
return this.this.previewSrc;
|
||||
getSize() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let img = new Image();
|
||||
img.src = this.value;
|
||||
img.onload = () => {
|
||||
resolve({
|
||||
width: img.width,
|
||||
height: img.height,
|
||||
});
|
||||
};
|
||||
img.onerror = (e) => {
|
||||
reject(e);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -101,7 +109,7 @@ export default {
|
||||
* @Desc: 删除图片
|
||||
*/
|
||||
deleteImg() {
|
||||
this.previewSrc = "";
|
||||
this.$emit("change", "none");
|
||||
this.file = null;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -125,4 +125,84 @@ export const borderDasharrayList = [
|
||||
export const borderRadiusList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
|
||||
// 线宽
|
||||
export const lineWidthList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
export const lineWidthList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
|
||||
// 图片重复方式
|
||||
export const backgroundRepeatList = [
|
||||
{
|
||||
name: '不重复',
|
||||
value: 'no-repeat'
|
||||
},
|
||||
{
|
||||
name: '重复',
|
||||
value: 'repeat'
|
||||
},
|
||||
{
|
||||
name: '水平方向重复',
|
||||
value: 'repeat-x'
|
||||
},
|
||||
{
|
||||
name: '垂直方向重复',
|
||||
value: 'repeat-y'
|
||||
}
|
||||
]
|
||||
|
||||
// 背景图片大小
|
||||
export const backgroundSizeList = [
|
||||
{
|
||||
name: '自动',
|
||||
value: 'auto'
|
||||
},
|
||||
{
|
||||
name: '完全覆盖',
|
||||
value: 'cover'
|
||||
},
|
||||
{
|
||||
name: '最合适',
|
||||
value: 'contain'
|
||||
}
|
||||
]
|
||||
|
||||
// 背景图片定位
|
||||
export const backgroundPositionList = [
|
||||
{
|
||||
name: '默认',
|
||||
value: '0% 0%'
|
||||
},
|
||||
{
|
||||
name: '左上',
|
||||
value: 'left top'
|
||||
},
|
||||
{
|
||||
name: '左中',
|
||||
value: 'left center'
|
||||
},
|
||||
{
|
||||
name: '左下',
|
||||
value: 'left bottom'
|
||||
},
|
||||
{
|
||||
name: '右上',
|
||||
value: 'right top'
|
||||
},
|
||||
{
|
||||
name: '右中',
|
||||
value: 'right center'
|
||||
},
|
||||
{
|
||||
name: '右下',
|
||||
value: 'right bottom'
|
||||
},
|
||||
{
|
||||
name: '中上',
|
||||
value: 'center top'
|
||||
},
|
||||
{
|
||||
name: '居中',
|
||||
value: 'center center'
|
||||
},
|
||||
{
|
||||
name: '中下',
|
||||
value: 'center bottom'
|
||||
}
|
||||
]
|
||||
@@ -1,17 +1,100 @@
|
||||
<template>
|
||||
<Sidebar ref="sidebar" title="基础样式">
|
||||
<div class="sidebarContent" v-if="data">
|
||||
<!-- 背景 -->
|
||||
<div class="title noTop">背景</div>
|
||||
<div class="row">
|
||||
<Color
|
||||
:color="style.backgroundColor"
|
||||
@change="
|
||||
(color) => {
|
||||
update('backgroundColor', color);
|
||||
}
|
||||
"
|
||||
></Color>
|
||||
<el-tabs class="tab" v-model="activeTab">
|
||||
<el-tab-pane label="颜色" name="color">
|
||||
<Color
|
||||
:color="style.backgroundColor"
|
||||
@change="
|
||||
(color) => {
|
||||
update('backgroundColor', color);
|
||||
}
|
||||
"
|
||||
></Color>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="图片" name="image">
|
||||
<ImgUpload
|
||||
class="imgUpload"
|
||||
v-model="style.backgroundImage"
|
||||
@change="
|
||||
(img) => {
|
||||
update('backgroundImage', img);
|
||||
}
|
||||
"
|
||||
></ImgUpload>
|
||||
<div class="rowItem">
|
||||
<span class="name">图片重复</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.backgroundRepeat"
|
||||
placeholder=""
|
||||
@change="
|
||||
(value) => {
|
||||
update('backgroundRepeat', value);
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in backgroundRepeatList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="rowItem">
|
||||
<span class="name">图片大小</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.backgroundSize"
|
||||
placeholder=""
|
||||
@change="
|
||||
(value) => {
|
||||
update('backgroundSize', value);
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in backgroundSizeList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="rowItem">
|
||||
<span class="name">图片定位</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.backgroundPosition"
|
||||
placeholder=""
|
||||
@change="
|
||||
(value) => {
|
||||
update('backgroundPosition', value);
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in backgroundPositionList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<!-- 连线 -->
|
||||
<div class="title noTop">连线</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
@@ -55,12 +138,13 @@
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 内边距 -->
|
||||
<div class="title noTop">节点内边距</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">水平</span>
|
||||
<el-slider
|
||||
style="width: 230px"
|
||||
style="width: 210px"
|
||||
v-model="style.paddingX"
|
||||
@change="
|
||||
(value) => {
|
||||
@@ -74,7 +158,7 @@
|
||||
<div class="rowItem">
|
||||
<span class="name">垂直</span>
|
||||
<el-slider
|
||||
style="width: 230px"
|
||||
style="width: 210px"
|
||||
v-model="style.paddingY"
|
||||
@change="
|
||||
(value) => {
|
||||
@@ -84,6 +168,58 @@
|
||||
></el-slider>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 图片 -->
|
||||
<div class="title noTop">图片</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">显示的最大宽度</span>
|
||||
<el-slider
|
||||
style="width: 150px"
|
||||
v-model="style.imgMaxWidth"
|
||||
:min="10"
|
||||
:max="300"
|
||||
@change="
|
||||
(value) => {
|
||||
update('imgMaxWidth', value);
|
||||
}
|
||||
"
|
||||
></el-slider>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">显示的最大高度</span>
|
||||
<el-slider
|
||||
style="width: 150px"
|
||||
v-model="style.imgMaxHeight"
|
||||
:min="10"
|
||||
:max="300"
|
||||
@change="
|
||||
(value) => {
|
||||
update('imgMaxHeight', value);
|
||||
}
|
||||
"
|
||||
></el-slider>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 图标 -->
|
||||
<div class="title noTop">图标</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">大小</span>
|
||||
<el-slider
|
||||
style="width: 210px"
|
||||
v-model="style.iconSize"
|
||||
:min="12"
|
||||
:max="50"
|
||||
@change="
|
||||
(value) => {
|
||||
update('iconSize', value);
|
||||
}
|
||||
"
|
||||
></el-slider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Sidebar>
|
||||
</template>
|
||||
@@ -91,13 +227,20 @@
|
||||
<script>
|
||||
import Sidebar from "./Sidebar";
|
||||
import Color from "./Color";
|
||||
import { lineWidthList } from "@/config";
|
||||
import { lineWidthList, backgroundRepeatList, backgroundSizeList, backgroundPositionList } from "@/config";
|
||||
import ImgUpload from "@/components/ImgUpload";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:52:56
|
||||
* @Desc: 基础样式
|
||||
*/
|
||||
export default {
|
||||
name: "BaseStyle",
|
||||
components: {
|
||||
Sidebar,
|
||||
Color,
|
||||
ImgUpload,
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
@@ -111,17 +254,28 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
lineWidthList,
|
||||
backgroundRepeatList,
|
||||
backgroundSizeList,
|
||||
backgroundPositionList,
|
||||
activeTab: "color",
|
||||
style: {
|
||||
backgroundColor: "",
|
||||
lineColor: "",
|
||||
lineWidth: "",
|
||||
paddingX: 0,
|
||||
paddingY: 0,
|
||||
imgMaxWidth: 0,
|
||||
imgMaxHeight: 0,
|
||||
iconSize: 0,
|
||||
backgroundImage: "",
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundSize: 'auto',
|
||||
backgroundPosition: '0% 0%'
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("showTheme", () => {
|
||||
this.$bus.$on("showBaseStyle", () => {
|
||||
this.$refs.sidebar.show = true;
|
||||
this.initStyle();
|
||||
});
|
||||
@@ -139,6 +293,13 @@ export default {
|
||||
"lineColor",
|
||||
"paddingX",
|
||||
"paddingY",
|
||||
"imgMaxWidth",
|
||||
"imgMaxHeight",
|
||||
"iconSize",
|
||||
"backgroundImage",
|
||||
"backgroundRepeat",
|
||||
"backgroundSize",
|
||||
"backgroundPosition"
|
||||
].forEach((key) => {
|
||||
this.style[key] = this.mindMap.getThemeConfig(key);
|
||||
});
|
||||
@@ -181,6 +342,14 @@ export default {
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.tab {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.imgUpload {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.btnGroup {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@@ -190,6 +359,7 @@ export default {
|
||||
.rowItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.name {
|
||||
font-size: 12px;
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
<script>
|
||||
import { colorList } from "@/config";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:53:10
|
||||
* @Desc: 颜色选择器
|
||||
*/
|
||||
export default {
|
||||
name: "Color",
|
||||
props: {
|
||||
|
||||
@@ -8,33 +8,41 @@
|
||||
:mindMap="mindMap"
|
||||
@change="changeThemeConfig"
|
||||
></BaseStyle>
|
||||
<Theme :mindMap="mindMap"></Theme>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Outline from './Outline'
|
||||
import Style from './Style'
|
||||
import BaseStyle from './BaseStyle'
|
||||
import exampleData from 'simple-mind-map/example/exampleData'
|
||||
import MindMap from "simple-mind-map";
|
||||
import Outline from "./Outline";
|
||||
import Style from "./Style";
|
||||
import BaseStyle from "./BaseStyle";
|
||||
import exampleData from "simple-mind-map/example/exampleData";
|
||||
import Theme from "./Theme";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:56:17
|
||||
* @Desc: 编辑区域
|
||||
*/
|
||||
export default {
|
||||
name: 'Edit',
|
||||
name: "Edit",
|
||||
components: {
|
||||
Outline,
|
||||
Style,
|
||||
BaseStyle,
|
||||
Theme,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mindMap: null,
|
||||
mindMapData: exampleData,
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
mounted() {
|
||||
this.init()
|
||||
this.$bus.$on('execCommand', this.execCommand)
|
||||
this.init();
|
||||
this.$bus.$on("execCommand", this.execCommand);
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
@@ -43,20 +51,20 @@ export default {
|
||||
* @Desc: 初始化
|
||||
*/
|
||||
init() {
|
||||
let { root, layout, theme } = this.mindMapData
|
||||
let { root, layout, theme } = this.mindMapData;
|
||||
this.mindMap = new MindMap({
|
||||
el: this.$refs.mindMapContainer,
|
||||
data: root,
|
||||
layout: layout,
|
||||
theme: theme.template,
|
||||
themeConfig: theme.config,
|
||||
})
|
||||
this.mindMap.on('node_active', (...args) => {
|
||||
this.$bus.$emit('node_active', ...args)
|
||||
})
|
||||
this.mindMap.on('data_change', (...args) => {
|
||||
this.$bus.$emit('data_change', ...args)
|
||||
})
|
||||
});
|
||||
this.mindMap.on("node_active", (...args) => {
|
||||
this.$bus.$emit("node_active", ...args);
|
||||
});
|
||||
this.mindMap.on("data_change", (...args) => {
|
||||
this.$bus.$emit("data_change", ...args);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -65,7 +73,7 @@ export default {
|
||||
* @Desc: 修改主题配置
|
||||
*/
|
||||
changeThemeConfig() {
|
||||
this.mindMap.setThemeConfig(this.mindMapData.theme.config)
|
||||
this.mindMap.setThemeConfig(this.mindMapData.theme.config);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -74,7 +82,7 @@ export default {
|
||||
* @Desc: 重新渲染
|
||||
*/
|
||||
reRender() {
|
||||
this.mindMap.render()
|
||||
this.mindMap.render();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -83,10 +91,10 @@ export default {
|
||||
* @Desc: 执行命令
|
||||
*/
|
||||
execCommand(...args) {
|
||||
this.mindMap.execCommand(...args)
|
||||
this.mindMap.execCommand(...args);
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -94,7 +102,7 @@ export default {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 62px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
.mindMapContainer {
|
||||
|
||||
94
web/src/pages/Edit/components/NodeHyperlink.vue
Normal file
94
web/src/pages/Edit/components/NodeHyperlink.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="nodeDialog"
|
||||
title="超链接"
|
||||
:visible.sync="dialogVisible"
|
||||
width="500"
|
||||
>
|
||||
<div class="item">
|
||||
<span class="name">链接</span>
|
||||
<el-input v-model="link" size="mini" placeholder="http://xxxx.com/"></el-input>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="name">名称</span>
|
||||
<el-input v-model="linkTitle" size="mini"></el-input>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="primary" @click="confirm">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:53:17
|
||||
* @Desc: 节点超链接内容设置
|
||||
*/
|
||||
export default {
|
||||
name: "NodeHyperlink",
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
link: "",
|
||||
linkTitle: "",
|
||||
activeNode: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
let activeNodes = args[1];
|
||||
if (activeNodes.length > 0) {
|
||||
this.activeNode = activeNodes[0];
|
||||
this.link = this.activeNode.getData("hyperlink");
|
||||
this.linkTitle = this.activeNode.getData("hyperlinkTitle");
|
||||
} else {
|
||||
this.link = "";
|
||||
this.linkTitle = "";
|
||||
}
|
||||
});
|
||||
this.$bus.$on("showNodeLink", () => {
|
||||
this.dialogVisible = true;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-22 22:08:11
|
||||
* @Desc: 取消
|
||||
*/
|
||||
cancel() {
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 22:28:20
|
||||
* @Desc: 确定
|
||||
*/
|
||||
confirm() {
|
||||
this.activeNode.setData({
|
||||
hyperlink: this.link,
|
||||
hyperlinkTitle: this.linkTitle,
|
||||
});
|
||||
this.cancel();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.nodeDialog {
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.name {
|
||||
display: block;
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="nodeDialog"
|
||||
title="图标"
|
||||
:visible.sync="dialogVisible"
|
||||
width="500"
|
||||
>
|
||||
<div class="item" v-for="item in nodeIconList" :key="item.name">
|
||||
<div class="title">{{ item.name }}</div>
|
||||
<div class="list">
|
||||
<div
|
||||
class="icon"
|
||||
v-for="icon in item.list"
|
||||
:key="icon.name"
|
||||
v-html="icon.icon"
|
||||
@click="setIcon(item.type, icon.name)"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { nodeIconList } from "simple-mind-map/src/svg/icons";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:53:33
|
||||
* @Desc: 节点图标内容设置
|
||||
*/
|
||||
export default {
|
||||
name: "NodeIcon",
|
||||
data() {
|
||||
return {
|
||||
nodeIconList,
|
||||
dialogVisible: false,
|
||||
icon: [],
|
||||
activeNode: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
let activeNodes = args[1];
|
||||
if (activeNodes.length > 0) {
|
||||
this.activeNode = activeNodes[0];
|
||||
this.icon = this.activeNode.getData("icon") || [];
|
||||
} else {
|
||||
this.icon = [];
|
||||
}
|
||||
});
|
||||
this.$bus.$on("showNodeIcon", () => {
|
||||
this.dialogVisible = true;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-23 23:16:56
|
||||
* @Desc: 设置icon
|
||||
*/
|
||||
setIcon(type, name) {
|
||||
let index = this.icon.findIndex((item) => {
|
||||
return item.split('_')[0] === type;
|
||||
})
|
||||
if (index !== -1) {
|
||||
this.icon.splice(index, 1, type + '_' + name)
|
||||
} else {
|
||||
this.icon.push(type + '_' + name)
|
||||
}
|
||||
this.activeNode.setData({
|
||||
icon: [...this.icon]
|
||||
})
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.nodeDialog {
|
||||
/deep/ .el-dialog__body {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-bottom: 20px;
|
||||
font-weight: bold;
|
||||
|
||||
.title {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,15 @@
|
||||
<template>
|
||||
<el-dialog class="nodeImageDialog" title="图片" :visible.sync="dialogVisible" width="500">
|
||||
<ImgUpload ref="imgUpload"></ImgUpload>
|
||||
<el-dialog
|
||||
class="nodeDialog"
|
||||
title="图片"
|
||||
:visible.sync="dialogVisible"
|
||||
width="500"
|
||||
>
|
||||
<ImgUpload ref="ImgUpload" v-model="img"></ImgUpload>
|
||||
<div class="imgTitleBox">
|
||||
<span class="title">图片标题</span>
|
||||
<el-input v-model="imgTitle" size="mini"></el-input>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="primary" @click="confirm">确 定</el-button>
|
||||
@@ -9,42 +18,86 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ImgUpload from '@/components/ImgUpload';
|
||||
import ImgUpload from "@/components/ImgUpload";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:53:45
|
||||
* @Desc: 节点图片内容设置
|
||||
*/
|
||||
export default {
|
||||
name: 'NodeImage',
|
||||
components: {
|
||||
ImgUpload
|
||||
},
|
||||
name: "NodeImage",
|
||||
components: {
|
||||
ImgUpload,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
img: "",
|
||||
imgTitle: "",
|
||||
activeNode: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
let activeNodes = args[1];
|
||||
this.activeNode = activeNodes[0];
|
||||
if (activeNodes.length > 0) {
|
||||
this.activeNode = activeNodes[0];
|
||||
this.img = this.activeNode.getData("image");
|
||||
this.imgTitle = this.activeNode.getData("imageTitle");
|
||||
} else {
|
||||
this.img = "";
|
||||
this.imgTitle = "";
|
||||
this.activeNode = null;
|
||||
}
|
||||
});
|
||||
this.$bus.$on("showNodeImage", () => {
|
||||
this.dialogVisible = true;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
cancel() {},
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-22 22:08:11
|
||||
* @Desc: 取消
|
||||
*/
|
||||
cancel() {
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 22:28:20
|
||||
* @Desc: 确定
|
||||
*/
|
||||
confirm() {},
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 22:28:20
|
||||
* @Desc: 确定
|
||||
*/
|
||||
async confirm() {
|
||||
try {
|
||||
let { width, height } = await this.$refs.ImgUpload.getSize();
|
||||
this.activeNode.setData({
|
||||
image: this.img,
|
||||
imageTitle: this.imgTitle,
|
||||
imageSize: {
|
||||
width,
|
||||
height,
|
||||
},
|
||||
});
|
||||
this.cancel();
|
||||
} catch (error) {}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.nodeImageDialog {
|
||||
.nodeDialog {
|
||||
.imgTitleBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
|
||||
.title {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
84
web/src/pages/Edit/components/NodeNote.vue
Normal file
84
web/src/pages/Edit/components/NodeNote.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="nodeDialog"
|
||||
title="备注"
|
||||
:visible.sync="dialogVisible"
|
||||
width="500"
|
||||
>
|
||||
<el-input
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 3, maxRows: 5 }"
|
||||
placeholder="请输入内容"
|
||||
v-model="note"
|
||||
>
|
||||
</el-input>
|
||||
<div class="tip">换行请使用:Enter+Shift</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="primary" @click="confirm">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:53:54
|
||||
* @Desc: 节点备注内容设置
|
||||
*/
|
||||
export default {
|
||||
name: "NodeNote",
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
note: "",
|
||||
activeNode: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
let activeNodes = args[1];
|
||||
if (activeNodes.length > 0) {
|
||||
this.activeNode = activeNodes[0];
|
||||
this.note = this.activeNode.getData("note");
|
||||
} else {
|
||||
this.note = "";
|
||||
}
|
||||
});
|
||||
this.$bus.$on("showNodeNote", () => {
|
||||
this.dialogVisible = true;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-22 22:08:11
|
||||
* @Desc: 取消
|
||||
*/
|
||||
cancel() {
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 22:28:20
|
||||
* @Desc: 确定
|
||||
*/
|
||||
confirm() {
|
||||
this.activeNode.setData({
|
||||
note: this.note,
|
||||
});
|
||||
this.cancel();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.nodeDialog {
|
||||
.tip {
|
||||
margin-top: 5px;
|
||||
color: #DCDFE6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
152
web/src/pages/Edit/components/NodeTag.vue
Normal file
152
web/src/pages/Edit/components/NodeTag.vue
Normal file
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="nodeDialog"
|
||||
title="标签"
|
||||
:visible.sync="dialogVisible"
|
||||
width="500"
|
||||
>
|
||||
<el-input
|
||||
v-model="tag"
|
||||
@keyup.native.enter="add"
|
||||
:disabled="tagArr.length >= max"
|
||||
>
|
||||
</el-input>
|
||||
<div class="tagList">
|
||||
<div
|
||||
class="tagItem"
|
||||
v-for="(item, index) in tagArr"
|
||||
:key="index"
|
||||
:style="{
|
||||
backgroundColor: tagColorList[index].background,
|
||||
color: tagColorList[index].color,
|
||||
}"
|
||||
>
|
||||
{{ item }}
|
||||
<div class="delBtn" @click="del(index)">
|
||||
<span class="iconfont iconshanchu"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="primary" @click="confirm">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { tagColorList } from "simple-mind-map/src/utils/constant";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:54:03
|
||||
* @Desc: 节点标签内容设置
|
||||
*/
|
||||
export default {
|
||||
name: "NodeTag",
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
tagColorList,
|
||||
tagArr: [],
|
||||
tag: "",
|
||||
activeNode: null,
|
||||
max: 5,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
let activeNodes = args[1];
|
||||
if (activeNodes.length > 0) {
|
||||
this.activeNode = activeNodes[0];
|
||||
this.tagArr = this.activeNode.getData("tag") || [];
|
||||
} else {
|
||||
this.tagArr = [];
|
||||
this.tag = "";
|
||||
}
|
||||
});
|
||||
this.$bus.$on("showNodeTag", () => {
|
||||
this.dialogVisible = true;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 21:48:14
|
||||
* @Desc: 添加
|
||||
*/
|
||||
add() {
|
||||
this.tagArr.push(this.tag);
|
||||
this.tag = "";
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 21:57:53
|
||||
* @Desc: 删除
|
||||
*/
|
||||
del(index) {
|
||||
this.tagArr.splice(index, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-22 22:08:11
|
||||
* @Desc: 取消
|
||||
*/
|
||||
cancel() {
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 22:28:20
|
||||
* @Desc: 确定
|
||||
*/
|
||||
confirm() {
|
||||
this.activeNode.setData({
|
||||
tag: this.tagArr,
|
||||
});
|
||||
this.cancel();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.nodeDialog {
|
||||
.tagList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 5px;
|
||||
|
||||
.tagItem {
|
||||
position: relative;
|
||||
padding: 3px 5px;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.delBtn {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.delBtn {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -7,6 +7,11 @@
|
||||
<script>
|
||||
import Sidebar from "./Sidebar";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:54:14
|
||||
* @Desc: 大纲内容
|
||||
*/
|
||||
export default {
|
||||
name: "Outline",
|
||||
components: {
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:54:25
|
||||
* @Desc: 侧边栏容器
|
||||
*/
|
||||
export default {
|
||||
name: "Sidebar",
|
||||
props: {
|
||||
@@ -31,7 +36,7 @@ export default {
|
||||
.sidebarContainer {
|
||||
position: fixed;
|
||||
right: -300px;
|
||||
top: 62px;
|
||||
top: 100px;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
background-color: #fff;
|
||||
|
||||
@@ -222,6 +222,11 @@ import {
|
||||
borderRadiusList,
|
||||
} from "@/config";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:54:47
|
||||
* @Desc: 节点样式设置
|
||||
*/
|
||||
export default {
|
||||
name: "Style",
|
||||
components: {
|
||||
|
||||
104
web/src/pages/Edit/components/Theme.vue
Normal file
104
web/src/pages/Edit/components/Theme.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<Sidebar ref="sidebar" title="主题">
|
||||
<div class="themeList">
|
||||
<div
|
||||
class="themeItem"
|
||||
v-for="item in themeList"
|
||||
:key="item.value"
|
||||
@click="useTheme(item)"
|
||||
:class="{ active: item.value === theme }"
|
||||
>
|
||||
<div class="imgBox">
|
||||
<img :src="item.img" alt="" />
|
||||
</div>
|
||||
<div class="name">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Sidebar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Sidebar from "./Sidebar";
|
||||
import { themeList } from "simple-mind-map/src/utils/constant";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:53:04
|
||||
* @Desc: 主题
|
||||
*/
|
||||
export default {
|
||||
name: "Theme",
|
||||
components: {
|
||||
Sidebar,
|
||||
},
|
||||
props: {
|
||||
mindMap: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
themeList,
|
||||
theme: "",
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("showTheme", () => {
|
||||
this.theme = this.mindMap.getTheme();
|
||||
this.$refs.sidebar.show = true;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 23:04:38
|
||||
* @Desc: 使用主题
|
||||
*/
|
||||
useTheme(theme) {
|
||||
this.theme = theme.value;
|
||||
this.mindMap.setTheme(theme.value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.themeList {
|
||||
padding: 20px;
|
||||
|
||||
.themeItem {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 20px;
|
||||
transition: all 0.2s;
|
||||
border: 1px solid transparent;
|
||||
|
||||
&:last-of-type {
|
||||
border: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16),
|
||||
0 3px 6px 0 rgba(0, 0, 0, 0.12), 0 5px 12px 4px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
|
||||
&.active {
|
||||
border: 1px solid #67c23a;
|
||||
}
|
||||
|
||||
.imgBox {
|
||||
width: 100%;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,92 +1,146 @@
|
||||
<template>
|
||||
<div class="toolbarContainer">
|
||||
<div class="toolbar">
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_NODE')"
|
||||
>
|
||||
<span class="icon iconfont iconjiedian"></span>
|
||||
<span class="text">插入同级节点</span>
|
||||
<!-- 节点操作 -->
|
||||
<div class="left">
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasRoot,
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_NODE')"
|
||||
>
|
||||
<span class="icon iconfont iconjiedian"></span>
|
||||
<span class="text">插入同级节点</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_CHILD_NODE')"
|
||||
>
|
||||
<span class="icon iconfont icontianjiazijiedian"></span>
|
||||
<span class="text">插入子节点</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">删除节点</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('showNodeImage')"
|
||||
>
|
||||
<span class="icon iconfont iconimage"></span>
|
||||
<span class="text">图片</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('showNodeIcon')"
|
||||
>
|
||||
<span class="icon iconfont iconxiaolian"></span>
|
||||
<span class="text">图标</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('showNodeLink')"
|
||||
>
|
||||
<span class="icon iconfont iconchaolianjie"></span>
|
||||
<span class="text">超链接</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('showNodeNote')"
|
||||
>
|
||||
<span class="icon iconfont iconflow-Mark"></span>
|
||||
<span class="text">备注</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('showNodeTag')"
|
||||
>
|
||||
<span class="icon iconfont iconbiaoqian"></span>
|
||||
<span class="text">标签</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_CHILD_NODE')"
|
||||
>
|
||||
<span class="icon iconfont icontianjiazijiedian"></span>
|
||||
<span class="text">插入子节点</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">删除节点</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('showNodeImage')"
|
||||
>
|
||||
<span class="icon iconfont iconimage"></span>
|
||||
<span class="text">图片</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('showNodeIcon')"
|
||||
>
|
||||
<span class="icon iconfont iconxiaolian"></span>
|
||||
<span class="text">图标</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
}"
|
||||
@click="$bus.$emit('showNodeLink')"
|
||||
>
|
||||
<span class="icon iconfont iconchaolianjie"></span>
|
||||
<span class="text">超链接</span>
|
||||
</div>
|
||||
<div class="toolbarBtn" @click="$bus.$emit('showOutline')">
|
||||
<span class="icon iconfont iconfuhao-dagangshu"></span>
|
||||
<span class="text">显示大纲</span>
|
||||
</div>
|
||||
<div class="toolbarBtn" @click="$bus.$emit('showTheme')">
|
||||
<span class="icon iconfont iconyangshi"></span>
|
||||
<span class="text">基础样式</span>
|
||||
<!-- 通用操作 -->
|
||||
<div class="center">
|
||||
<div class="toolbarBtn" @click="$bus.$emit('showOutline')">
|
||||
<span class="icon iconfont iconfuhao-dagangshu"></span>
|
||||
<span class="text">显示大纲</span>
|
||||
</div>
|
||||
<div class="toolbarBtn" @click="$bus.$emit('showBaseStyle')">
|
||||
<span class="icon iconfont iconyangshi"></span>
|
||||
<span class="text">基础样式</span>
|
||||
</div>
|
||||
<div class="toolbarBtn" @click="$bus.$emit('showTheme')">
|
||||
<span class="icon iconfont iconjingzi"></span>
|
||||
<span class="text">主题</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<NodeImage></NodeImage>
|
||||
<NodeHyperlink></NodeHyperlink>
|
||||
<NodeIcon></NodeIcon>
|
||||
<NodeNote></NodeNote>
|
||||
<NodeTag></NodeTag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NodeImage from "./NodeImage";
|
||||
import NodeHyperlink from "./NodeHyperlink";
|
||||
import NodeIcon from "./NodeIcon";
|
||||
import NodeNote from "./NodeNote";
|
||||
import NodeTag from "./NodeTag";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:54:58
|
||||
* @Desc: 工具栏
|
||||
*/
|
||||
export default {
|
||||
name: "Toolbar",
|
||||
components: {
|
||||
NodeImage,
|
||||
NodeHyperlink,
|
||||
NodeIcon,
|
||||
NodeNote,
|
||||
NodeTag,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeNodes: [],
|
||||
activeNodes: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasRoot() {
|
||||
return this.activeNodes.find((node) => {
|
||||
return node.isRoot;
|
||||
});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
this.activeNodes = args[1];
|
||||
@@ -97,22 +151,30 @@ export default {
|
||||
|
||||
<style lang="less" scoped>
|
||||
.toolbarContainer {
|
||||
height: 62px;
|
||||
background: #fafafa;
|
||||
padding-left: 40px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
font-size: 12px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: rgba(26, 26, 26, 0.8);
|
||||
|
||||
.toolbar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
padding-top: 20px;
|
||||
font-size: 12px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: rgba(26, 26, 26, 0.8);
|
||||
z-index: 2;
|
||||
|
||||
.left,
|
||||
.center {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
padding: 10px 20px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 16px 0 rgb(0 0 0 / 6%);
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.toolbarBtn {
|
||||
display: flex;
|
||||
@@ -121,6 +183,10 @@ export default {
|
||||
cursor: pointer;
|
||||
margin-right: 20px;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:not(.disabled) {
|
||||
.icon {
|
||||
|
||||
Reference in New Issue
Block a user