概要开发中

This commit is contained in:
wanglin
2022-07-31 10:28:13 +08:00
parent 30f7713af1
commit 2d8643015f
25 changed files with 483 additions and 16 deletions

View File

@@ -864,6 +864,70 @@ const data4 = {
}
}
// 带概要
const data5 = {
"root": {
"data": {
"text": "根节点"
},
"children": [
{
"data": {
"text": "二级节点",
"generalization": {
"text": "概要",
}
},
"children": [
{
"data": {
"text": "子节点"
},
"children": []
},
{
"data": {
"text": "子节点"
},
"children": []
},
{
"data": {
"text": "子节点"
},
"children": []
},
{
"data": {
"text": "子节点"
},
"children": []
}
]
},
{
"data": {
"text": "二级节点2"
},
"children": [
{
"data": {
"text": "子节点"
},
"children": []
},
{
"data": {
"text": "子节点"
},
"children": []
}
]
}
]
}
}
const rootData = {
"root": {
"data": {
@@ -876,8 +940,9 @@ const rootData = {
export default {
// ...data1,
// ...data2,
...data3,
// ...data3,
// ...data4,
...data5,
// ...rootData,
"theme": {
"template": "minions",

View File

@@ -71,7 +71,7 @@ class Drag extends Base {
bindEvent() {
this.checkOverlapNode = throttle(this.checkOverlapNode, 300, this)
this.mindMap.on('node_mousedown', (node, e) => {
if (this.mindMap.opt.readonly) {
if (this.mindMap.opt.readonly || node.isGeneralization) {
return
}
if (e.which !== 1 || node.isRoot) {

View File

@@ -45,6 +45,9 @@ class Node {
this.style = new Style(this, this.themeConfig)
// 是否是根节点
this.isRoot = opt.isRoot === undefined ? false : opt.isRoot
// 是否是概要节点
this.isGeneralization = opt.isGeneralization === undefined ? false : opt.isGeneralization
this.generalizationBelongNode = null
// 节点层级
this.layerIndex = opt.layerIndex === undefined ? 0 : opt.layerIndex
// 节点宽
@@ -73,6 +76,8 @@ class Node {
this.noteEl = null
this._expandBtn = null
this._lines = []
this._generalizationLine = null
this._generalizationNode = null
// 尺寸信息
this._rectInfo = {
imgContentWidth: 0,
@@ -153,6 +158,7 @@ class Node {
this._hyperlinkData = this.createHyperlinkNode()
this._tagData = this.createTagNode()
this._noteData = this.createNoteNode()
this.createGeneralizationNode()
}
/**
@@ -584,7 +590,7 @@ class Node {
})
// 右键菜单事件
this.group.on('contextmenu', (e) => {
if (this.mindMap.opt.readonly) {
if (this.mindMap.opt.readonly || this.isGeneralization) {
return
}
e.stopPropagation()
@@ -646,6 +652,7 @@ class Node {
} else {
this.updateExpandBtnPos()
}
this.renderGeneralization()
let t = this.group.transform()
if (!layout) {
this.group.animate(300).translate(this.left - t.translateX, this.top - t.translateY)
@@ -690,6 +697,7 @@ class Node {
this.removeAllEvent()
this.removeAllNode()
this.removeLine()
this.removeGeneralization()
// 子节点
if (this.children && this.children.length) {
asyncRun(this.children.map((item) => {
@@ -728,7 +736,10 @@ class Node {
* @Date: 2021-11-23 18:39:14
* @Desc: 显示节点
*/
show() {
show() {
if (!this.group) {
return;
}
this.group.show()
if (this.parent) {
let index = this.parent.children.indexOf(this)
@@ -786,6 +797,71 @@ class Node {
this._lines = []
}
/**
* @Author: 王林
* @Date: 2022-07-31 09:41:28
* @Desc: 创建概要节点
*/
createGeneralizationNode() {
if (this.isGeneralization || !this.nodeData.data.generalization) {
return
}
if (!this._generalizationLine) {
this._generalizationLine = this.draw.path()
}
if (!this._generalizationNode) {
this._generalizationNode = new Node({
data: {
data: this.nodeData.data.generalization
},
uid: this.mindMap.uid++,
renderer: this.renderer,
mindMap: this.mindMap,
draw: this.draw,
isGeneralization: true
})
this._generalizationNode.generalizationBelongNode = this
if (this.nodeData.data.generalization.isActive) {
this.renderer.addActiveNode(this._generalizationNode)
}
}
}
/**
* @Author: 王林
* @Date: 2022-07-30 08:35:51
* @Desc: 创建概要节点
*/
renderGeneralization() {
if (this.isGeneralization) {
return
}
if (this.nodeData.data.expand === false || !this.nodeData.data.generalization) {
this.removeGeneralization()
return
}
this.createGeneralizationNode()
this.renderer.layout.renderGeneralization(this, this._generalizationLine, this._generalizationNode)
this.style.generalizationLine(this._generalizationLine)
this._generalizationNode.render()
}
/**
* @Author: 王林
* @Date: 2022-07-30 13:11:27
* @Desc: 删除概要节点
*/
removeGeneralization() {
if (this._generalizationLine) {
this._generalizationLine.remove()
this._generalizationLine = null
}
if (this._generalizationNode) {
this._generalizationNode.remove()
this._generalizationNode = null
}
}
/**
* @Author: 王林
* @Date: 2021-07-10 17:59:14

View File

@@ -163,6 +163,12 @@ class Render {
// 设置节点标签
this.setNodeTag = this.setNodeTag.bind(this)
this.mindMap.command.add('SET_NODE_TAG', this.setNodeTag)
// 添加节点概要
this.addGeneralization = this.addGeneralization.bind(this)
this.mindMap.command.add('ADD_GENERALIZATION', this.addGeneralization)
// 删除节点概要
this.removeGeneralization = this.removeGeneralization.bind(this)
this.mindMap.command.add('REMOVE_GENERALIZATION', this.removeGeneralization)
}
/**
@@ -579,7 +585,14 @@ class Render {
}
for (let i = 0; i < this.activeNodeList.length; i++) {
let node = this.activeNodeList[i]
if (node.isRoot) {
if (node.isGeneralization) {
// 删除概要节点
this.setNodeData(node.generalizationBelongNode, {
generalization: null
})
this.removeActiveNode(node)
i--
} else if (node.isRoot) {
node.children.forEach((child) => {
child.remove()
})
@@ -855,6 +868,48 @@ class Render {
})
}
/**
* @Author: 王林
* @Date: 2022-07-30 20:52:42
* @Desc: 添加节点概要
*/
addGeneralization(data) {
if (this.activeNodeList.length <= 0) {
return
}
this.activeNodeList.forEach((node) => {
if (node.nodeData.data.generalization) {
return
}
this.setNodeData(node, {
generalization: data || {
text: '概要'
}
})
})
this.mindMap.render()
}
/**
* @Author: 王林
* @Date: 2022-07-30 21:16:33
* @Desc: 删除节点概要
*/
removeGeneralization() {
if (this.activeNodeList.length <= 0) {
return
}
this.activeNodeList.forEach((node) => {
if (!node.nodeData.data.generalization) {
return
}
this.setNodeData(node, {
generalization: null
})
})
this.mindMap.render()
}
/**
* @Author: 王林
* @Date: 2021-05-04 14:19:48

View File

@@ -50,6 +50,8 @@ class Style {
let defaultConfig = this.themeConfig.node
if (root || rootProp.includes(prop)) {// 直接使用最外层样式
defaultConfig = this.themeConfig
} else if (this.ctx.isGeneralization) {// 概要节点
defaultConfig = this.themeConfig.generalization
} else if (this.ctx.layerIndex === 0) {// 根节点
defaultConfig = this.themeConfig.root
} else if (this.ctx.layerIndex === 1) {// 二级节点
@@ -154,6 +156,15 @@ class Style {
node.stroke({ width: this.merge('lineWidth', true), color: this.merge('lineColor', true) }).fill({ color: 'none' })
}
/**
* @Author: 王林
* @Date: 2022-07-30 16:19:03
* @Desc: 概要连线
*/
generalizationLine(node) {
node.stroke({ width: this.merge('generalizationLineWidth', true), color: this.merge('generalizationLineColor', true) }).fill({ color: 'none' })
}
/**
* @Author: 王林
* @Date: 2021-04-11 20:03:59

View File

@@ -1,4 +1,7 @@
import Node from '../Node'
import {
walk,
} from '../utils'
/**
* @Author: 王林
@@ -49,6 +52,13 @@ class Base {
throw new Error('【renderExpandBtn】方法为必要方法需要子类进行重写')
}
/**
* @Author: 王林
* @Date: 2022-07-30 22:49:28
* @Desc: 概要节点
*/
renderGeneralization() {}
/**
* @Author: 王林
* @Date: 2021-07-10 21:30:54
@@ -156,6 +166,38 @@ class Base {
getMarginY(layerIndex) {
return layerIndex === 1 ? this.mindMap.themeConfig.second.marginY : this.mindMap.themeConfig.node.marginY;
}
/**
* @Author: 王林
* @Date: 2022-07-31 09:14:03
* @Desc: 获取节点的边界值
*/
getNodeBoundaries(node) {
let top = Infinity
let bottom = -Infinity
let left = Infinity
let right = -Infinity
walk(node, null, (root) => {
if (root.top < top) {
top = root.top
}
if (root.top + root.height > bottom) {
bottom = root.top + root.height
}
if (root.left < left) {
left = root.left
}
if (root.left + root.width > right) {
right = root.left + root.width
}
}, null, true)
return {
left,
right,
top,
bottom
};
}
}
export default Base

View File

@@ -310,6 +310,26 @@ class CatalogOrganization extends Base {
btn.translate(width * 0.3 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY)
}
}
/**
* @Author: 王林
* @Date: 2022-07-30 08:30:35
* @Desc: 创建概要节点
*/
renderGeneralization(node, gLine, gNode) {
let { top, bottom, right } = this.getNodeBoundaries(node)
let space = 20
let x1 = right
let y1 = top
let x2 = right
let y2 = bottom
let cx = x1 + space
let cy = y1 + (y2 - y1) / 2
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
gLine.plot(path)
gNode.left = right + space
gNode.top = top + (bottom - top - gNode.height) / 2
}
}
export default CatalogOrganization

View File

@@ -188,6 +188,26 @@ class LogicalStructure extends Base {
} = btn.transform()
btn.translate(width - translateX, height / 2 - translateY)
}
/**
* @Author: 王林
* @Date: 2022-07-30 08:30:35
* @Desc: 创建概要节点
*/
renderGeneralization(node, gLine, gNode) {
let { top, bottom, right } = this.getNodeBoundaries(node)
let space = 20
let x1 = right
let y1 = top
let x2 = right
let y2 = bottom
let cx = x1 + space
let cy = y1 + (y2 - y1) / 2
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
gLine.plot(path)
gNode.left = right + space
gNode.top = top + (bottom - top - gNode.height) / 2
}
}
export default LogicalStructure

View File

@@ -224,6 +224,29 @@ class MindMap extends Base {
let y = height / 2 - translateY
btn.translate(x, y)
}
/**
* @Author: 王林
* @Date: 2022-07-30 08:30:35
* @Desc: 创建概要节点
*/
renderGeneralization(node, gLine, gNode) {
let { top, bottom, left, right } = this.getNodeBoundaries(node)
let isLeft = node.dir === 'left'
let space = 20
let x = isLeft ? left : right
space = (isLeft ? -space : space)
let x1 = x
let y1 = top
let x2 = x
let y2 = bottom
let cx = x1 + space
let cy = y1 + (y2 - y1) / 2
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
gLine.plot(path)
gNode.left = x + space - (isLeft ? gNode.width : 0)
gNode.top = top + (bottom - top - gNode.height) / 2
}
}
export default MindMap

View File

@@ -206,6 +206,26 @@ class OrganizationStructure extends Base {
} = btn.transform()
btn.translate(width / 2 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY)
}
/**
* @Author: 王林
* @Date: 2022-07-30 08:30:35
* @Desc: 创建概要节点
*/
renderGeneralization(node, gLine, gNode) {
let { bottom, left, right } = this.getNodeBoundaries(node)
let space = 20
let x1 = left
let y1 = bottom
let x2 = right
let y2 = bottom
let cx = left + (right - left) / 2
let cy = bottom + space
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
gLine.plot(path)
gNode.top = bottom + space
gNode.left = left + (right - left - gNode.width) / 2
}
}
export default OrganizationStructure

View File

@@ -17,6 +17,10 @@ export default {
lineWidth: 1,
// 连线的颜色
lineColor: '#549688',
// 概要连线的粗细
generalizationLineWidth: 1,
// 概要连线的颜色
generalizationLineColor: '#549688',
// 背景颜色
backgroundColor: '#fafafa',
// 背景图片
@@ -86,5 +90,27 @@ export default {
borderWidth: 3,
borderDasharray: 'none',
}
},
// 概要节点样式
generalization: {
marginX: 100,
marginY: 40,
fillColor: '#fff',
fontFamily: '微软雅黑, Microsoft YaHei',
color: '#565656',
fontSize: 16,
fontWeight: 'noraml',
fontStyle: 'normal',
lineHeight: 1.5,
borderColor: '#549688',
borderWidth: 1,
borderDasharray: 'none',
borderRadius: 5,
textDecoration: 'none',
active: {
borderColor: 'rgb(57, 80, 96)',
borderWidth: 3,
borderDasharray: 'none',
}
}
}

View File

@@ -10,6 +10,10 @@ export default merge(defaultTheme, {
// 连线的颜色
lineColor: 'rgb(51, 51, 51)',
lineWidth: 3,
// 概要连线的粗细
generalizationLineWidth: 3,
// 概要连线的颜色
generalizationLineColor: '#222',
// 背景颜色
backgroundColor: 'rgb(248, 215, 49)',
// 根节点样式
@@ -39,5 +43,14 @@ export default merge(defaultTheme, {
active: {
borderColor: 'rgb(55, 165, 255)'
}
},
// 概要节点样式
generalization: {
borderColor: '#222',
borderWidth: 3,
color: '#222',
active: {
borderColor: 'rgb(55, 165, 255)'
}
}
})

View File

@@ -229,7 +229,7 @@ export const asyncRun = (taskList, callback = () => {}) => {
let index = 0
let len = taskList.length
if (len <= 0) {
return
return callback()
}
let loop = () => {
if (index >= len) {

BIN
web/src/.DS_Store vendored

Binary file not shown.

Binary file not shown.

View File

@@ -54,6 +54,12 @@
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe609;</span>
<div class="name">概要总览</div>
<div class="code-name">&amp;#xe609;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xf199;</span>
<div class="name">全选</div>
@@ -258,9 +264,9 @@
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1628093007325') format('woff2'),
url('iconfont.woff?t=1628093007325') format('woff'),
url('iconfont.ttf?t=1628093007325') format('truetype');
src: url('iconfont.woff2?t=1659185196536') format('woff2'),
url('iconfont.woff?t=1659185196536') format('woff'),
url('iconfont.ttf?t=1659185196536') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -286,6 +292,15 @@
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icongaikuozonglan"></span>
<div class="name">
概括总览
</div>
<div class="code-name">.icongaikuozonglan
</div>
</li>
<li class="dib">
<span class="icon iconfont iconquanxuan"></span>
<div class="name">
@@ -592,6 +607,14 @@
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icongaikuozonglan"></use>
</svg>
<div class="name">概括总览</div>
<div class="code-name">#icongaikuozonglan</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#iconquanxuan"></use>

View File

@@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2479351 */
src: url('iconfont.woff2?t=1628093007325') format('woff2'),
url('iconfont.woff?t=1628093007325') format('woff'),
url('iconfont.ttf?t=1628093007325') format('truetype');
src: url('iconfont.woff2?t=1659185196536') format('woff2'),
url('iconfont.woff?t=1659185196536') format('woff'),
url('iconfont.ttf?t=1659185196536') format('truetype');
}
.iconfont {
@@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale;
}
.icongaikuozonglan:before {
content: "\e609";
}
.iconquanxuan:before {
content: "\f199";
}

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,13 @@
"css_prefix_text": "icon",
"description": "思维导图",
"glyphs": [
{
"icon_id": "14843439",
"name": "概要总览",
"font_class": "gaikuozonglan",
"unicode": "e609",
"unicode_decimal": 58889
},
{
"icon_id": "19738998",
"name": "全选",

View File

@@ -94,6 +94,50 @@
</el-select>
</div>
</div>
<!-- 概要连线 -->
<div class="title noTop">概要的连线</div>
<div class="row">
<div class="rowItem">
<span class="name">颜色</span>
<span
class="block"
v-popover:popover
:style="{ backgroundColor: style.generalizationLineColor }"
></span>
<el-popover ref="popover" placement="bottom" trigger="click">
<Color
:color="style.generalizationLineColor"
@change="
(color) => {
update('generalizationLineColor', color);
}
"
></Color>
</el-popover>
</div>
<div class="rowItem">
<span class="name">粗细</span>
<el-select
size="mini"
style="width: 80px"
v-model="style.generalizationLineWidth"
placeholder=""
@change="
(value) => {
update('generalizationLineWidth', value);
}
"
>
<el-option
v-for="item in lineWidthList"
:key="item"
:label="item"
:value="item"
>
</el-option>
</el-select>
</div>
</div>
<!-- 内边距 -->
<div class="title noTop">节点内边距</div>
<div class="row">
@@ -259,6 +303,8 @@ export default {
backgroundColor: "",
lineColor: "",
lineWidth: "",
generalizationLineWidth: "",
generalizationLineColor: "",
paddingX: 0,
paddingY: 0,
imgMaxWidth: 0,
@@ -291,6 +337,8 @@ export default {
"backgroundColor",
"lineWidth",
"lineColor",
"generalizationLineWidth",
"generalizationLineColor",
"paddingX",
"paddingY",
"imgMaxWidth",

View File

@@ -50,7 +50,6 @@ export default {
} else {
this.iconList = [];
}
console.log(this.iconList, nodeIconList);
});
this.$bus.$on("showNodeIcon", () => {
this.dialogVisible = true;

View File

@@ -26,7 +26,7 @@
<div
class="toolbarBtn"
:class="{
disabled: activeNodes.length <= 0 || hasRoot,
disabled: activeNodes.length <= 0 || hasRoot || hasGeneralization,
}"
@click="$bus.$emit('execCommand', 'INSERT_NODE')"
>
@@ -36,7 +36,7 @@
<div
class="toolbarBtn"
:class="{
disabled: activeNodes.length <= 0,
disabled: activeNodes.length <= 0 || hasGeneralization,
}"
@click="$bus.$emit('execCommand', 'INSERT_CHILD_NODE')"
>
@@ -103,6 +103,16 @@
<span class="icon iconfont iconbiaoqian"></span>
<span class="text">标签</span>
</div>
<div
class="toolbarBtn"
:class="{
disabled: activeNodes.length <= 0 || hasRoot,
}"
@click="$bus.$emit('execCommand', 'ADD_GENERALIZATION')"
>
<span class="icon iconfont icongaikuozonglan"></span>
<span class="text">概要</span>
</div>
</div>
<!-- 通用操作 -->
<div class="toolbarBlock">
@@ -188,6 +198,11 @@ export default {
return node.isRoot;
});
},
hasGeneralization() {
return this.activeNodes.find((node) => {
return node.isGeneralization;
});
}
},
created() {
this.$bus.$on("mode_change", (mode) => {