mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-17 22:08:25 +08:00
初始化仓库
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
oss.js
|
||||
5
babel.config.js
Normal file
5
babel.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
||||
50
package.json
Normal file
50
package.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "thoughts",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@svgdotjs/svg.js": "^3.0.16",
|
||||
"core-js": "^3.6.5",
|
||||
"deepmerge": "^1.5.2",
|
||||
"element-ui": "^2.15.1",
|
||||
"vue": "^2.6.11",
|
||||
"vue-router": "^3.5.1",
|
||||
"vuex": "^3.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.5.0",
|
||||
"@vue/cli-plugin-eslint": "^4.5.0",
|
||||
"@vue/cli-service": "^4.5.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"less": "^3.12.2",
|
||||
"less-loader": "^7.1.0",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack": "^4.44.2"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
},
|
||||
"rules": {}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead"
|
||||
]
|
||||
}
|
||||
18
public/index.html
Normal file
18
public/index.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>思绪_一个极简的在线思维导图</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<script src="http://lxqnsys.com/js/polyfillB.js"></script>
|
||||
<script src="http://lxqnsys.com/js/aliyun-oss-sdk-6.0.1.min.js"></script>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
BIN
src/.DS_Store
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
Binary file not shown.
26
src/App.vue
Normal file
26
src/App.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "App",
|
||||
components: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #2c3e50;
|
||||
}
|
||||
</style>
|
||||
BIN
src/assets/.DS_Store
vendored
Normal file
BIN
src/assets/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/assets/icon-font/.DS_Store
vendored
Normal file
BIN
src/assets/icon-font/.DS_Store
vendored
Normal file
Binary file not shown.
539
src/assets/icon-font/demo.css
Normal file
539
src/assets/icon-font/demo.css
Normal file
@@ -0,0 +1,539 @@
|
||||
/* Logo 字体 */
|
||||
@font-face {
|
||||
font-family: "iconfont logo";
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "iconfont logo";
|
||||
font-size: 160px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* tabs */
|
||||
.nav-tabs {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-more {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#tabs {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#tabs li {
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
border-bottom: 2px solid transparent;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: -1px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
||||
#tabs .active {
|
||||
border-bottom-color: #f00;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.tab-container .content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 页面布局 */
|
||||
.main {
|
||||
padding: 30px 100px;
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.main .logo {
|
||||
color: #333;
|
||||
text-align: left;
|
||||
margin-bottom: 30px;
|
||||
line-height: 1;
|
||||
height: 110px;
|
||||
margin-top: -50px;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.main .logo a {
|
||||
font-size: 160px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.helps {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.helps pre {
|
||||
padding: 20px;
|
||||
margin: 10px 0;
|
||||
border: solid 1px #e7e1cd;
|
||||
background-color: #fffdef;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.icon_lists {
|
||||
width: 100% !important;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.icon_lists li {
|
||||
width: 100px;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
list-style: none !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.icon_lists li .code-name {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.icon_lists .icon {
|
||||
display: block;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
font-size: 42px;
|
||||
margin: 10px auto;
|
||||
color: #333;
|
||||
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
-moz-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
transition: font-size 0.25s linear, width 0.25s linear;
|
||||
}
|
||||
|
||||
.icon_lists .icon:hover {
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
.icon_lists .svg-icon {
|
||||
/* 通过设置 font-size 来改变图标大小 */
|
||||
width: 1em;
|
||||
/* 图标和文字相邻时,垂直对齐 */
|
||||
vertical-align: -0.15em;
|
||||
/* 通过设置 color 来改变 SVG 的颜色/fill */
|
||||
fill: currentColor;
|
||||
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
|
||||
normalize.css 中也包含这行 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.icon_lists li .name,
|
||||
.icon_lists li .code-name {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* markdown 样式 */
|
||||
.markdown {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown img {
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
color: #404040;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown h2,
|
||||
.markdown h3,
|
||||
.markdown h4,
|
||||
.markdown h5,
|
||||
.markdown h6 {
|
||||
color: #404040;
|
||||
margin: 1.6em 0 0.6em 0;
|
||||
font-weight: 500;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.markdown h2 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.markdown h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.markdown h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.markdown h5 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown h6 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown hr {
|
||||
height: 1px;
|
||||
border: 0;
|
||||
background: #e9e9e9;
|
||||
margin: 16px 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown>p,
|
||||
.markdown>blockquote,
|
||||
.markdown>.highlight,
|
||||
.markdown>ol,
|
||||
.markdown>ul {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.markdown ul>li {
|
||||
list-style: circle;
|
||||
}
|
||||
|
||||
.markdown>ul li,
|
||||
.markdown blockquote ul>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown>ul li p,
|
||||
.markdown>ol li p {
|
||||
margin: 0.6em 0;
|
||||
}
|
||||
|
||||
.markdown ol>li {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.markdown>ol li,
|
||||
.markdown blockquote ol>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown code {
|
||||
margin: 0 3px;
|
||||
padding: 0 5px;
|
||||
background: #eee;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown strong,
|
||||
.markdown b {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
empty-cells: show;
|
||||
border: 1px solid #e9e9e9;
|
||||
width: 95%;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
white-space: nowrap;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table th,
|
||||
.markdown>table td {
|
||||
border: 1px solid #e9e9e9;
|
||||
padding: 8px 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
background: #F7F7F7;
|
||||
}
|
||||
|
||||
.markdown blockquote {
|
||||
font-size: 90%;
|
||||
color: #999;
|
||||
border-left: 4px solid #e9e9e9;
|
||||
padding-left: 0.8em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown blockquote p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown .anchor {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.markdown .waiting {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.markdown h1:hover .anchor,
|
||||
.markdown h2:hover .anchor,
|
||||
.markdown h3:hover .anchor,
|
||||
.markdown h4:hover .anchor,
|
||||
.markdown h5:hover .anchor,
|
||||
.markdown h6:hover .anchor {
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.markdown>br,
|
||||
.markdown>p>br {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
background: white;
|
||||
padding: 0.5em;
|
||||
color: #333333;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-meta {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-strong,
|
||||
.hljs-emphasis,
|
||||
.hljs-quote {
|
||||
color: #df5000;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-type {
|
||||
color: #a71d5d;
|
||||
}
|
||||
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-attribute {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-attr,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
color: #55a532;
|
||||
background-color: #eaffea;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
color: #bd2c00;
|
||||
background-color: #ffecec;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 代码高亮 */
|
||||
/* PrismJS 1.15.0
|
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection,
|
||||
pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre)>code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre)>code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #9a6e3a;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
464
src/assets/icon-font/demo_index.html
Normal file
464
src/assets/icon-font/demo_index.html
Normal file
@@ -0,0 +1,464 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>iconfont Demo</title>
|
||||
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico" type="image/x-icon"/>
|
||||
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg"/>
|
||||
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<link rel="stylesheet" href="iconfont.css">
|
||||
<script src="iconfont.js"></script>
|
||||
<!-- jQuery -->
|
||||
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
|
||||
<!-- 代码高亮 -->
|
||||
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
|
||||
<style>
|
||||
.main .logo {
|
||||
margin-top: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.main .logo a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main .logo .sub-title {
|
||||
margin-left: 0.5em;
|
||||
font-size: 22px;
|
||||
color: #fff;
|
||||
background: linear-gradient(-45deg, #3967FF, #B500FE);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main">
|
||||
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
|
||||
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
|
||||
|
||||
</a></h1>
|
||||
<div class="nav-tabs">
|
||||
<ul id="tabs" class="dib-box">
|
||||
<li class="dib active"><span>Unicode</span></li>
|
||||
<li class="dib"><span>Font class</span></li>
|
||||
<li class="dib"><span>Symbol</span></li>
|
||||
</ul>
|
||||
|
||||
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2479351" target="_blank" class="nav-more">查看项目</a>
|
||||
|
||||
</div>
|
||||
<div class="tab-container">
|
||||
<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">&#xe6f4;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">主题</div>
|
||||
<div class="code-name">&#xe610;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">笑脸</div>
|
||||
<div class="code-name">&#xe60f;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">图 片</div>
|
||||
<div class="code-name">&#xe629;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">结构</div>
|
||||
<div class="code-name">&#xe61d;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">样式</div>
|
||||
<div class="code-name">&#xe631;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">符号-大纲树</div>
|
||||
<div class="code-name">&#xe71f;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">添加子节点</div>
|
||||
<div class="code-name">&#xe622;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">节点</div>
|
||||
<div class="code-name">&#xe655;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">删 除</div>
|
||||
<div class="code-name">&#xe696;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">HTSCIT_展开</div>
|
||||
<div class="code-name">&#xe64c;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">HTSCIT_展开2</div>
|
||||
<div class="code-name">&#xe673;</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="article markdown">
|
||||
<h2 id="unicode-">Unicode 引用</h2>
|
||||
<hr>
|
||||
|
||||
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
|
||||
<ul>
|
||||
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
|
||||
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
|
||||
</blockquote>
|
||||
<p>Unicode 使用步骤如下:</p>
|
||||
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
|
||||
<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');
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||
<pre><code class="language-css"
|
||||
>.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
|
||||
<pre>
|
||||
<code class="language-html"
|
||||
><span class="iconfont">&#x33;</span>
|
||||
</code></pre>
|
||||
<blockquote>
|
||||
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content font-class">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconchaolianjie"></span>
|
||||
<div class="name">
|
||||
超链接
|
||||
</div>
|
||||
<div class="code-name">.iconchaolianjie
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconjingzi"></span>
|
||||
<div class="name">
|
||||
主题
|
||||
</div>
|
||||
<div class="code-name">.iconjingzi
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconxiaolian"></span>
|
||||
<div class="name">
|
||||
笑脸
|
||||
</div>
|
||||
<div class="code-name">.iconxiaolian
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconimage"></span>
|
||||
<div class="name">
|
||||
图 片
|
||||
</div>
|
||||
<div class="code-name">.iconimage
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconjiegou"></span>
|
||||
<div class="name">
|
||||
结构
|
||||
</div>
|
||||
<div class="code-name">.iconjiegou
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconyangshi"></span>
|
||||
<div class="name">
|
||||
样式
|
||||
</div>
|
||||
<div class="code-name">.iconyangshi
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconfuhao-dagangshu"></span>
|
||||
<div class="name">
|
||||
符号-大纲树
|
||||
</div>
|
||||
<div class="code-name">.iconfuhao-dagangshu
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icontianjiazijiedian"></span>
|
||||
<div class="name">
|
||||
添加子节点
|
||||
</div>
|
||||
<div class="code-name">.icontianjiazijiedian
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconjiedian"></span>
|
||||
<div class="name">
|
||||
节点
|
||||
</div>
|
||||
<div class="code-name">.iconjiedian
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconshanchu"></span>
|
||||
<div class="name">
|
||||
删 除
|
||||
</div>
|
||||
<div class="code-name">.iconshanchu
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconzhankai"></span>
|
||||
<div class="name">
|
||||
HTSCIT_展开
|
||||
</div>
|
||||
<div class="code-name">.iconzhankai
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconzhankai1"></span>
|
||||
<div class="name">
|
||||
HTSCIT_展开2
|
||||
</div>
|
||||
<div class="code-name">.iconzhankai1
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="article markdown">
|
||||
<h2 id="font-class-">font-class 引用</h2>
|
||||
<hr>
|
||||
|
||||
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
|
||||
<p>与 Unicode 使用方式相比,具有如下特点:</p>
|
||||
<ul>
|
||||
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
|
||||
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
|
||||
</ul>
|
||||
<p>使用步骤如下:</p>
|
||||
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
|
||||
<pre><code class="language-html"><link rel="stylesheet" href="./iconfont.css">
|
||||
</code></pre>
|
||||
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||
<pre><code class="language-html"><span class="iconfont iconxxx"></span>
|
||||
</code></pre>
|
||||
<blockquote>
|
||||
<p>"
|
||||
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content symbol">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconchaolianjie"></use>
|
||||
</svg>
|
||||
<div class="name">超链接</div>
|
||||
<div class="code-name">#iconchaolianjie</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconjingzi"></use>
|
||||
</svg>
|
||||
<div class="name">主题</div>
|
||||
<div class="code-name">#iconjingzi</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconxiaolian"></use>
|
||||
</svg>
|
||||
<div class="name">笑脸</div>
|
||||
<div class="code-name">#iconxiaolian</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconimage"></use>
|
||||
</svg>
|
||||
<div class="name">图 片</div>
|
||||
<div class="code-name">#iconimage</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconjiegou"></use>
|
||||
</svg>
|
||||
<div class="name">结构</div>
|
||||
<div class="code-name">#iconjiegou</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconyangshi"></use>
|
||||
</svg>
|
||||
<div class="name">样式</div>
|
||||
<div class="code-name">#iconyangshi</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconfuhao-dagangshu"></use>
|
||||
</svg>
|
||||
<div class="name">符号-大纲树</div>
|
||||
<div class="code-name">#iconfuhao-dagangshu</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icontianjiazijiedian"></use>
|
||||
</svg>
|
||||
<div class="name">添加子节点</div>
|
||||
<div class="code-name">#icontianjiazijiedian</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconjiedian"></use>
|
||||
</svg>
|
||||
<div class="name">节点</div>
|
||||
<div class="code-name">#iconjiedian</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconshanchu"></use>
|
||||
</svg>
|
||||
<div class="name">删 除</div>
|
||||
<div class="code-name">#iconshanchu</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconzhankai"></use>
|
||||
</svg>
|
||||
<div class="name">HTSCIT_展开</div>
|
||||
<div class="code-name">#iconzhankai</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconzhankai1"></use>
|
||||
</svg>
|
||||
<div class="name">HTSCIT_展开2</div>
|
||||
<div class="code-name">#iconzhankai1</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="article markdown">
|
||||
<h2 id="symbol-">Symbol 引用</h2>
|
||||
<hr>
|
||||
|
||||
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
|
||||
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
|
||||
<ul>
|
||||
<li>支持多色图标了,不再受单色限制。</li>
|
||||
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
|
||||
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
|
||||
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
|
||||
</ul>
|
||||
<p>使用步骤如下:</p>
|
||||
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
|
||||
<pre><code class="language-html"><script src="./iconfont.js"></script>
|
||||
</code></pre>
|
||||
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
|
||||
<pre><code class="language-html"><style>
|
||||
.icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</code></pre>
|
||||
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||
<pre><code class="language-html"><svg class="icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xxx"></use>
|
||||
</svg>
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.tab-container .content:first').show()
|
||||
|
||||
$('#tabs li').click(function (e) {
|
||||
var tabContent = $('.tab-container .content')
|
||||
var index = $(this).index()
|
||||
|
||||
if ($(this).hasClass('active')) {
|
||||
return
|
||||
} else {
|
||||
$('#tabs li').removeClass('active')
|
||||
$(this).addClass('active')
|
||||
|
||||
tabContent.hide().eq(index).fadeIn()
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
63
src/assets/icon-font/iconfont.css
Normal file
63
src/assets/icon-font/iconfont.css
Normal file
@@ -0,0 +1,63 @@
|
||||
@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');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconchaolianjie:before {
|
||||
content: "\e6f4";
|
||||
}
|
||||
|
||||
.iconjingzi:before {
|
||||
content: "\e610";
|
||||
}
|
||||
|
||||
.iconxiaolian:before {
|
||||
content: "\e60f";
|
||||
}
|
||||
|
||||
.iconimage:before {
|
||||
content: "\e629";
|
||||
}
|
||||
|
||||
.iconjiegou:before {
|
||||
content: "\e61d";
|
||||
}
|
||||
|
||||
.iconyangshi:before {
|
||||
content: "\e631";
|
||||
}
|
||||
|
||||
.iconfuhao-dagangshu:before {
|
||||
content: "\e71f";
|
||||
}
|
||||
|
||||
.icontianjiazijiedian:before {
|
||||
content: "\e622";
|
||||
}
|
||||
|
||||
.iconjiedian:before {
|
||||
content: "\e655";
|
||||
}
|
||||
|
||||
.iconshanchu:before {
|
||||
content: "\e696";
|
||||
}
|
||||
|
||||
.iconzhankai:before {
|
||||
content: "\e64c";
|
||||
}
|
||||
|
||||
.iconzhankai1:before {
|
||||
content: "\e673";
|
||||
}
|
||||
|
||||
1
src/assets/icon-font/iconfont.js
Normal file
1
src/assets/icon-font/iconfont.js
Normal file
File diff suppressed because one or more lines are too long
93
src/assets/icon-font/iconfont.json
Normal file
93
src/assets/icon-font/iconfont.json
Normal file
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"id": "2479351",
|
||||
"name": "思绪",
|
||||
"font_family": "iconfont",
|
||||
"css_prefix_text": "icon",
|
||||
"description": "思维导图",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "1790486",
|
||||
"name": "超链接",
|
||||
"font_class": "chaolianjie",
|
||||
"unicode": "e6f4",
|
||||
"unicode_decimal": 59124
|
||||
},
|
||||
{
|
||||
"icon_id": "4608986",
|
||||
"name": "主题",
|
||||
"font_class": "jingzi",
|
||||
"unicode": "e610",
|
||||
"unicode_decimal": 58896
|
||||
},
|
||||
{
|
||||
"icon_id": "11903017",
|
||||
"name": "笑脸",
|
||||
"font_class": "xiaolian",
|
||||
"unicode": "e60f",
|
||||
"unicode_decimal": 58895
|
||||
},
|
||||
{
|
||||
"icon_id": "19657962",
|
||||
"name": "图 片",
|
||||
"font_class": "image",
|
||||
"unicode": "e629",
|
||||
"unicode_decimal": 58921
|
||||
},
|
||||
{
|
||||
"icon_id": "20784489",
|
||||
"name": "结构",
|
||||
"font_class": "jiegou",
|
||||
"unicode": "e61d",
|
||||
"unicode_decimal": 58909
|
||||
},
|
||||
{
|
||||
"icon_id": "15969341",
|
||||
"name": "样式",
|
||||
"font_class": "yangshi",
|
||||
"unicode": "e631",
|
||||
"unicode_decimal": 58929
|
||||
},
|
||||
{
|
||||
"icon_id": "2967176",
|
||||
"name": "符号-大纲树",
|
||||
"font_class": "fuhao-dagangshu",
|
||||
"unicode": "e71f",
|
||||
"unicode_decimal": 59167
|
||||
},
|
||||
{
|
||||
"icon_id": "12316668",
|
||||
"name": "添加子节点",
|
||||
"font_class": "tianjiazijiedian",
|
||||
"unicode": "e622",
|
||||
"unicode_decimal": 58914
|
||||
},
|
||||
{
|
||||
"icon_id": "14435368",
|
||||
"name": "节点",
|
||||
"font_class": "jiedian",
|
||||
"unicode": "e655",
|
||||
"unicode_decimal": 58965
|
||||
},
|
||||
{
|
||||
"icon_id": "15765352",
|
||||
"name": "删 除",
|
||||
"font_class": "shanchu",
|
||||
"unicode": "e696",
|
||||
"unicode_decimal": 59030
|
||||
},
|
||||
{
|
||||
"icon_id": "9592600",
|
||||
"name": "HTSCIT_展开",
|
||||
"font_class": "zhankai",
|
||||
"unicode": "e64c",
|
||||
"unicode_decimal": 58956
|
||||
},
|
||||
{
|
||||
"icon_id": "9900009",
|
||||
"name": "HTSCIT_展开2",
|
||||
"font_class": "zhankai1",
|
||||
"unicode": "e673",
|
||||
"unicode_decimal": 58995
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
src/assets/icon-font/iconfont.ttf
Normal file
BIN
src/assets/icon-font/iconfont.ttf
Normal file
Binary file not shown.
BIN
src/assets/icon-font/iconfont.woff
Normal file
BIN
src/assets/icon-font/iconfont.woff
Normal file
Binary file not shown.
BIN
src/assets/icon-font/iconfont.woff2
Normal file
BIN
src/assets/icon-font/iconfont.woff2
Normal file
Binary file not shown.
131
src/components/ImgUpload/index.vue
Normal file
131
src/components/ImgUpload/index.vue
Normal file
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<div class="imgUploadContainer">
|
||||
<div class="imgUploadPanel">
|
||||
<div class="upBtn" v-if="!previewSrc">
|
||||
<label
|
||||
for="imgUploadInput"
|
||||
class="imgUploadInputArea"
|
||||
@dragenter.stop.prevent
|
||||
@dragover.stop.prevent
|
||||
@drop.stop.prevent="onDrop"
|
||||
v-loading="loading"
|
||||
element-loading-text="上传中..."
|
||||
>点击此处添加图片、或拖动图片到此</label
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
id="imgUploadInput"
|
||||
@change="onImgUploadInputChange"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="previewSrc" class="uploadInfoBox">
|
||||
<div
|
||||
class="previewBox"
|
||||
:style="{ backgroundImage: `url('${previewSrc}')` }"
|
||||
></div>
|
||||
<span class="delBtn el-icon-close" @click="deleteImg"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ossUpLoader from "@/utils/oss";
|
||||
|
||||
export default {
|
||||
name: "ImgUpload",
|
||||
data() {
|
||||
return {
|
||||
file: null,
|
||||
previewSrc: "",
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2019-12-22 19:47:19
|
||||
* @Desc: 图片选择事件
|
||||
*/
|
||||
onImgUploadInputChange(e) {
|
||||
let file = e.target.files[0];
|
||||
this.uploadImg(file);
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2019-12-22 20:32:31
|
||||
* @Desc: 拖动上传图片
|
||||
*/
|
||||
onDrop(e) {
|
||||
let dt = e.dataTransfer;
|
||||
let file = dt.files && dt.files[0];
|
||||
this.uploadImg(file);
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 16:56:14
|
||||
* @Desc: 显示图片
|
||||
*/
|
||||
showImg(file) {
|
||||
this.file = file;
|
||||
let fr = new FileReader();
|
||||
fr.readAsDataURL(file);
|
||||
fr.onload = (e) => {
|
||||
this.previewSrc = e.target.result;
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2019-12-22 19:51:13
|
||||
* @Desc: 上传图片
|
||||
*/
|
||||
async uploadImg(file) {
|
||||
this.loading = true;
|
||||
ossUpLoader.uploadFile(
|
||||
file,
|
||||
() => {},
|
||||
(e) => {
|
||||
this.previewSrc = e[0].res.requestUrls[0]
|
||||
this.loading = false;
|
||||
},
|
||||
(e) => {
|
||||
if (e.length > 0) {
|
||||
this.loading = false;
|
||||
this.$message({
|
||||
message: "上传失败",
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 22:33:28
|
||||
* @Desc: 获取图片url
|
||||
*/
|
||||
getUrl() {
|
||||
return this.this.previewSrc;
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 21:59:57
|
||||
* @Desc: 删除图片
|
||||
*/
|
||||
deleteImg() {
|
||||
this.previewSrc = "";
|
||||
this.file = null;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import "./style.less";
|
||||
</style>
|
||||
80
src/components/ImgUpload/style.less
Normal file
80
src/components/ImgUpload/style.less
Normal file
@@ -0,0 +1,80 @@
|
||||
.imgUploadContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: rgba(255,255,255,.9);
|
||||
z-index: 1000;
|
||||
|
||||
.imgUploadPanel {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
font-size: 22px;
|
||||
white-space: nowrap;
|
||||
color: #909090;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
|
||||
.title {
|
||||
margin-bottom: 15px;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: hsla(218,9%,51%,.8);
|
||||
}
|
||||
|
||||
.closeBtn {
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
top: 32px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.imgUploadInputArea {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
font-size: 20px;
|
||||
color: rgba(51,51,51,.4);
|
||||
background-color: hsla(0,0%,87%,.6);
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
white-space: normal;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#imgUploadInput {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.uploadInfoBox {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background-color: hsla(0,0%,87%,.6);
|
||||
|
||||
.previewBox {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.delBtn {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
128
src/config/index.js
Normal file
128
src/config/index.js
Normal file
@@ -0,0 +1,128 @@
|
||||
// 字体列表
|
||||
export const fontFamilyList = [
|
||||
{
|
||||
name: '宋体',
|
||||
value: '宋体, SimSun, Songti SC'
|
||||
}, {
|
||||
name: '微软雅黑',
|
||||
value: '微软雅黑, Microsoft YaHei'
|
||||
}, {
|
||||
name: '楷体',
|
||||
value: '楷体, 楷体_GB2312, SimKai, STKaiti'
|
||||
}, {
|
||||
name: '黑体',
|
||||
value: '黑体, SimHei, Heiti SC'
|
||||
}, {
|
||||
name: '隶书',
|
||||
value: '隶书, SimLi'
|
||||
}, {
|
||||
name: 'Andale Mono',
|
||||
value: 'andale mono'
|
||||
}, {
|
||||
name: 'Arial',
|
||||
value: 'arial, helvetica, sans-serif'
|
||||
}, {
|
||||
name: 'arialBlack',
|
||||
value: 'arial black, avant garde'
|
||||
}, {
|
||||
name: 'Comic Sans Ms',
|
||||
value: 'comic sans ms'
|
||||
}, {
|
||||
name: 'Impact',
|
||||
value: 'impact, chicago'
|
||||
}, {
|
||||
name: 'Times New Roman',
|
||||
value: 'times new roman'
|
||||
}, {
|
||||
name: 'Sans-Serif',
|
||||
value: 'sans-serif'
|
||||
},
|
||||
{
|
||||
name: 'serif',
|
||||
value: 'serif'
|
||||
}
|
||||
]
|
||||
|
||||
// 字号
|
||||
export const fontSizeList = [10, 12, 16, 18, 24, 32, 48]
|
||||
|
||||
// 颜色
|
||||
export const colorList = [
|
||||
'#4D4D4D',
|
||||
'#999999',
|
||||
'#FFFFFF',
|
||||
'#F44E3B',
|
||||
'#FE9200',
|
||||
'#FCDC00',
|
||||
'#DBDF00',
|
||||
'#A4DD00',
|
||||
'#68CCCA',
|
||||
'#73D8FF',
|
||||
'#AEA1FF',
|
||||
'#FDA1FF',
|
||||
'#333333',
|
||||
'#808080',
|
||||
'#cccccc',
|
||||
'#D33115',
|
||||
'#E27300',
|
||||
'#FCC400',
|
||||
'#B0BC00',
|
||||
'#68BC00',
|
||||
'#16A5A5',
|
||||
'#009CE0',
|
||||
'#7B64FF',
|
||||
'#FA28FF',
|
||||
'#000000',
|
||||
'#666666',
|
||||
'#B3B3B3',
|
||||
'#9F0500',
|
||||
'#C45100',
|
||||
'#FB9E00',
|
||||
'#808900',
|
||||
'#194D33',
|
||||
'#0C797D',
|
||||
'#0062B1',
|
||||
'#653294',
|
||||
'#AB149E'
|
||||
]
|
||||
|
||||
// 边框宽度
|
||||
export const borderWidthList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
|
||||
// 边框样式
|
||||
export const borderDasharrayList = [
|
||||
{
|
||||
name: '实线',
|
||||
value: 'none'
|
||||
},
|
||||
{
|
||||
name: '虚线1',
|
||||
value: '5,5'
|
||||
},
|
||||
{
|
||||
name: '虚线2',
|
||||
value: '10,10'
|
||||
},
|
||||
{
|
||||
name: '虚线3',
|
||||
value: '20,10,5,5,5,10'
|
||||
},
|
||||
{
|
||||
name: '虚线4',
|
||||
value: '5, 5, 1, 5'
|
||||
},
|
||||
{
|
||||
name: '虚线5',
|
||||
value: '15, 10, 5, 10, 15'
|
||||
},
|
||||
{
|
||||
name: '虚线6',
|
||||
value: '1, 5'
|
||||
}
|
||||
]
|
||||
|
||||
// 圆角
|
||||
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]
|
||||
17
src/main.js
Normal file
17
src/main.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import '@/assets/icon-font/iconfont.css';
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.prototype.$bus = new Vue()
|
||||
Vue.use(ElementUI)
|
||||
|
||||
new Vue({
|
||||
render: h => h(App),
|
||||
router,
|
||||
store
|
||||
}).$mount('#app')
|
||||
BIN
src/package/.DS_Store
vendored
Normal file
BIN
src/package/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/package/mind-map/.DS_Store
vendored
Normal file
BIN
src/package/mind-map/.DS_Store
vendored
Normal file
Binary file not shown.
44
src/package/mind-map/example/exampleData.js
Normal file
44
src/package/mind-map/example/exampleData.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-15 22:23:24
|
||||
* @Desc: 完整示例数据
|
||||
*/
|
||||
export default {
|
||||
"root": {
|
||||
"data": {
|
||||
"text": "鱼骨头图",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "分支主题",
|
||||
"expand": true
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "分支主题",
|
||||
"hyperlink": "https://naotu.baidu.com/",
|
||||
"hyperlinkTitle": "百度脑图",
|
||||
"image": "https://kityminder-img.gz.bcebos.com/865551aedebd1e02ac6e76d24c093231df9aafda",
|
||||
"imageTitle": "图片名称",
|
||||
"imageSize": {
|
||||
"width": 200,
|
||||
"height": 112
|
||||
},
|
||||
"note": "我是备注",
|
||||
"resource": ["标签1", "标签2"],
|
||||
"priority": 5,
|
||||
"progress": 7,
|
||||
// ... 其他类型的图标
|
||||
},
|
||||
"children": []
|
||||
}]
|
||||
}]
|
||||
},
|
||||
"theme": {
|
||||
"template": "default",
|
||||
"config": {
|
||||
// 自定义配置...
|
||||
}
|
||||
},
|
||||
"layout": "logicalStructure"
|
||||
}
|
||||
174
src/package/mind-map/index.js
Normal file
174
src/package/mind-map/index.js
Normal file
@@ -0,0 +1,174 @@
|
||||
import View from './src/View'
|
||||
import Event from './src/Event'
|
||||
import Render from './src/Render'
|
||||
import merge from 'deepmerge'
|
||||
import theme from './src/themes'
|
||||
import Style from './src/Style'
|
||||
import KeyCommand from './src/KeyCommand'
|
||||
import Command from './src/Command';
|
||||
import { SVG } from '@svgdotjs/svg.js'
|
||||
|
||||
const defaultOpt = {
|
||||
// 布局
|
||||
layout: 'logicalStructure',
|
||||
// 放大缩小的增量比例,即step = scaleRatio * width|height
|
||||
scaleRatio: 0.1,
|
||||
// 主题
|
||||
theme: 'default',// 内置主题:default(默认主题)
|
||||
// 主题配置,会和所选择的主题进行合并
|
||||
themeConfig: {}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 11:18:47
|
||||
* @Desc: 思维导图
|
||||
*/
|
||||
class MindMap {
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 11:19:01
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt = {}) {
|
||||
this.opt = merge(defaultOpt, opt)
|
||||
// 容器元素
|
||||
this.el = this.opt.el
|
||||
let {
|
||||
width,
|
||||
height
|
||||
} = this.el.getBoundingClientRect()
|
||||
// 画布宽高
|
||||
this.width = width
|
||||
this.height = height
|
||||
// 画笔
|
||||
this.draw = SVG().addTo(this.el).size(width, height)
|
||||
// 节点id
|
||||
this.uid = 0
|
||||
|
||||
// 主题
|
||||
this.initTheme()
|
||||
|
||||
// 事件类
|
||||
this.event = new Event({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 按键类
|
||||
this.keyCommand = new KeyCommand({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 命令类
|
||||
this.command = new Command({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 渲染类
|
||||
this.renderer = new Render({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 视图操作类
|
||||
this.view = new View({
|
||||
mindMap: this,
|
||||
draw: this.draw
|
||||
})
|
||||
|
||||
this.render()
|
||||
setTimeout(() => {
|
||||
this.command.addHistory()
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 13:25:50
|
||||
* @Desc: 监听事件
|
||||
*/
|
||||
on(event, fn) {
|
||||
this.event.on(event, fn)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 13:51:35
|
||||
* @Desc: 触发事件
|
||||
*/
|
||||
emit(event, ...args) {
|
||||
this.event.emit(event, ...args)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 13:53:54
|
||||
* @Desc: 解绑事件
|
||||
*/
|
||||
off(event, fn) {
|
||||
this.event.off(event, fn)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 13:32:43
|
||||
* @Desc: 设置主题
|
||||
*/
|
||||
initTheme() {
|
||||
this.themeConfig = merge(this.opt.theme && theme[this.opt.theme] ? theme[this.opt.theme] : theme.default, this.opt.themeConfig)
|
||||
Style.setBackgroundStyle(this.el, this.themeConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 13:52:08
|
||||
* @Desc: 设置主题
|
||||
*/
|
||||
setTheme(theme) {
|
||||
this.opt.theme = theme
|
||||
this.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 13:50:17
|
||||
* @Desc: 设置主题配置
|
||||
*/
|
||||
setThemeConfig(config) {
|
||||
this.opt.themeConfig = config
|
||||
this.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 14:01:29
|
||||
* @Desc: 获取某个主题配置值
|
||||
*/
|
||||
getThemeConfig(prop) {
|
||||
return prop === undefined ? this.themeConfig : this.themeConfig[prop]
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 18:47:29
|
||||
* @Desc: 渲染节点
|
||||
*/
|
||||
render() {
|
||||
this.draw.clear()
|
||||
this.initTheme()
|
||||
this.renderer.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:01:00
|
||||
* @Desc: 执行命令
|
||||
*/
|
||||
execCommand(...args) {
|
||||
this.command.exec(...args)
|
||||
}
|
||||
}
|
||||
|
||||
export default MindMap
|
||||
71
src/package/mind-map/src/Command.js
Normal file
71
src/package/mind-map/src/Command.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import { copyRenderTree, simpleDeepClone } from './Utils';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:10:06
|
||||
* @Desc: 命令类
|
||||
*/
|
||||
class Command {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:10:24
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt = {}) {
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
this.commands = {}
|
||||
this.history = []
|
||||
this.activeHistoryIndex = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:12:30
|
||||
* @Desc: 执行命令
|
||||
*/
|
||||
exec(name, ...args) {
|
||||
if (this.commands[name]) {
|
||||
this.commands[name].forEach((fn) => {
|
||||
fn(...args)
|
||||
})
|
||||
this.addHistory()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:13:01
|
||||
* @Desc: 添加命令
|
||||
*/
|
||||
add(name, fn) {
|
||||
if (this.commands[name]) {
|
||||
this.commands[name].push(fn)
|
||||
} else[
|
||||
this.commands[name] = [fn]
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 14:35:43
|
||||
* @Desc: 添加回退数据
|
||||
*/
|
||||
addHistory() {
|
||||
let data = this.getCopyData()
|
||||
this.history.push(simpleDeepClone(data))
|
||||
this.activeHistoryIndex++
|
||||
this.mindMap.emit('data_change', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 15:02:58
|
||||
* @Desc: 获取渲染树数据副本
|
||||
*/
|
||||
getCopyData() {
|
||||
return copyRenderTree({}, this.mindMap.renderer.renderTree)
|
||||
}
|
||||
}
|
||||
|
||||
export default Command
|
||||
149
src/package/mind-map/src/Event.js
Normal file
149
src/package/mind-map/src/Event.js
Normal file
@@ -0,0 +1,149 @@
|
||||
import EventEmitter from 'eventemitter3'
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 14:53:09
|
||||
* @Desc: 事件类
|
||||
*/
|
||||
class Event extends EventEmitter {
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 14:53:25
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt = {}) {
|
||||
super()
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
this.isMousedown = false
|
||||
this.mousedownPos = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
this.mousemovePos = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
this.mousemoveOffset = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
this.bindFn()
|
||||
this.bind()
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 15:52:24
|
||||
* @Desc: 绑定函数上下文
|
||||
*/
|
||||
bindFn() {
|
||||
this.onDrawClick = this.onDrawClick.bind(this)
|
||||
this.onMousedown = this.onMousedown.bind(this)
|
||||
this.onMousemove = this.onMousemove.bind(this)
|
||||
this.onMouseup = this.onMouseup.bind(this)
|
||||
this.onMousewheel = this.onMousewheel.bind(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 14:53:43
|
||||
* @Desc: 绑定事件
|
||||
*/
|
||||
bind() {
|
||||
this.mindMap.draw.on('click', this.onDrawClick)
|
||||
this.mindMap.el.addEventListener('mousedown', this.onMousedown)
|
||||
window.addEventListener('mousemove', this.onMousemove)
|
||||
window.addEventListener('mouseup', this.onMouseup)
|
||||
this.mindMap.el.addEventListener('mousewheel', this.onMousewheel)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 15:40:51
|
||||
* @Desc: 解绑事件
|
||||
*/
|
||||
unbind() {
|
||||
this.mindMap.el.removeEventListener('mousedown', this.onMousedown)
|
||||
window.removeEventListener('mousemove', this.onMousemove)
|
||||
window.removeEventListener('mouseup', this.onMouseup)
|
||||
this.mindMap.el.removeEventListener('mousewheel', this.onMousewheel)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 13:19:39
|
||||
* @Desc: 画布的单击事件
|
||||
*/
|
||||
onDrawClick(e) {
|
||||
this.emit('draw_click', e)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 15:17:35
|
||||
* @Desc: 鼠标按下事件
|
||||
*/
|
||||
onMousedown(e) {
|
||||
e.preventDefault()
|
||||
this.isMousedown = true
|
||||
this.mousedownPos.x = e.clientX
|
||||
this.mousedownPos.y = e.clientY
|
||||
this.emit('mousedown', e, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 15:18:32
|
||||
* @Desc: 鼠标移动事件
|
||||
*/
|
||||
onMousemove(e) {
|
||||
e.preventDefault()
|
||||
this.mousemovePos.x = e.clientX
|
||||
this.mousemovePos.y = e.clientY
|
||||
this.mousemoveOffset.x = e.clientX - this.mousedownPos.x
|
||||
this.mousemoveOffset.y = e.clientY - this.mousedownPos.y
|
||||
this.emit('mousemove', e, this)
|
||||
if (this.isMousedown) {
|
||||
this.emit('drag', e, this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 15:18:57
|
||||
* @Desc: 鼠标松开事件
|
||||
*/
|
||||
onMouseup(e) {
|
||||
this.isMousedown = false
|
||||
this.emit('mouseup', e, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 15:46:27
|
||||
* @Desc: 鼠标滚动
|
||||
*/
|
||||
onMousewheel(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
let dir
|
||||
if (e.wheelDeltaY > 0) {
|
||||
dir = 'up'
|
||||
} else {
|
||||
dir = 'down'
|
||||
}
|
||||
this.emit('mousewheel', e, dir, this)
|
||||
}
|
||||
}
|
||||
|
||||
export default Event
|
||||
116
src/package/mind-map/src/KeyCommand.js
Normal file
116
src/package/mind-map/src/KeyCommand.js
Normal file
@@ -0,0 +1,116 @@
|
||||
import { keyMap } from './utils/keyMap';
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 15:20:46
|
||||
* @Desc: 快捷按键、命令处理类
|
||||
*/
|
||||
export default class KeyCommand {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 15:21:32
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt) {
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
this.shortcutMap = {
|
||||
//Enter: [fn]
|
||||
}
|
||||
this.bindEvent()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 15:23:22
|
||||
* @Desc: 绑定事件
|
||||
*/
|
||||
bindEvent() {
|
||||
window.addEventListener('keydown', (e) => {
|
||||
Object.keys(this.shortcutMap).forEach((key) => {
|
||||
if (this.checkKey(e, key)) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.shortcutMap[key].forEach((fn) => {
|
||||
fn()
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 19:24:53
|
||||
* @Desc: 检查键值是否符合
|
||||
*/
|
||||
checkKey(e, key) {
|
||||
let o = this.getOriginEventCodeArr(e)
|
||||
let k = this.getKeyCodeArr(key)
|
||||
if (o.length !== k.length) {
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < o.length; i++) {
|
||||
let index = k.findIndex((item) => {
|
||||
return item === o[i];
|
||||
})
|
||||
if (index === -1) {
|
||||
return false
|
||||
} else {
|
||||
k.splice(index, 1)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 19:15:19
|
||||
* @Desc: 获取事件对象里的键值数组
|
||||
*/
|
||||
getOriginEventCodeArr(e) {
|
||||
let arr = []
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
arr.push(keyMap['Control'])
|
||||
}
|
||||
if (e.altKey) {
|
||||
arr.push(keyMap['Alt'])
|
||||
}
|
||||
if (e.shiftKey) {
|
||||
arr.push(keyMap['Shift'])
|
||||
}
|
||||
arr.push(e.keyCode)
|
||||
return arr
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 19:40:11
|
||||
* @Desc: 获取快捷键对应的键值数组
|
||||
*/
|
||||
getKeyCodeArr(key) {
|
||||
let keyArr = key.split(/\s*\+\s*/)
|
||||
let arr = []
|
||||
keyArr.forEach((item) => {
|
||||
arr.push(keyMap[item])
|
||||
})
|
||||
return arr
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 15:23:00
|
||||
* @Desc: 添加快捷键命令
|
||||
* Enter
|
||||
* Tab | Insert
|
||||
* Shift + a
|
||||
*/
|
||||
addShortcut(key, fn) {
|
||||
key.split(/\s*\|\s*/).forEach((item) => {
|
||||
if (this.shortcutMap[item]) {
|
||||
this.shortcutMap[item].push(fn)
|
||||
} else {
|
||||
this.shortcutMap[item] = [fn]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
397
src/package/mind-map/src/Node.js
Normal file
397
src/package/mind-map/src/Node.js
Normal file
@@ -0,0 +1,397 @@
|
||||
import Style from './Style';
|
||||
import {
|
||||
resizeImgSize
|
||||
} from './Utils'
|
||||
import {
|
||||
Image,
|
||||
Text,
|
||||
SVG,
|
||||
Circle,
|
||||
Element
|
||||
} from '@svgdotjs/svg.js'
|
||||
import btnsSvg from './svg/btns';
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 11:26:00
|
||||
* @Desc: 节点类
|
||||
*/
|
||||
class Node {
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 11:26:17
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt = {}) {
|
||||
// 原始数据
|
||||
this.originData = opt.originData
|
||||
// 原始数据里的数据部分
|
||||
this.data = opt.data
|
||||
// id
|
||||
this.uid = opt.uid
|
||||
// 控制实例
|
||||
this.mindMap = opt.mindMap
|
||||
// 渲染实例
|
||||
this.renderer = opt.renderer
|
||||
// 主题配置
|
||||
this.themeConfig = this.mindMap.themeConfig
|
||||
// 样式实例
|
||||
this.style = new Style(this, this.themeConfig)
|
||||
// 渲染器
|
||||
this.draw = opt.draw || null
|
||||
// 是否是根节点
|
||||
this.isRoot = opt.isRoot === undefined ? false : opt.isRoot
|
||||
// 是否激活
|
||||
this.isActive = opt.isActive === undefined ? false : opt.isActive
|
||||
// 是否展开
|
||||
this.expand = opt.expand === undefined ? true : opt.expand
|
||||
// 节点层级
|
||||
this.layerIndex = opt.layerIndex === undefined ? 0 : opt.layerIndex
|
||||
// 节点宽
|
||||
this.width = opt.width || 0
|
||||
// 节点高
|
||||
this.height = opt.height || 0
|
||||
// left
|
||||
this.left = opt.left || 0
|
||||
// top
|
||||
this.top = opt.top || 0
|
||||
// 父节点
|
||||
this.parent = opt.parent || null
|
||||
// 子节点
|
||||
this.children = opt.children || []
|
||||
// 全部子节点所占的高度之和
|
||||
this.childrenAreaHeight = opt.childrenAreaHeight || 0
|
||||
// 文本节点
|
||||
this.textNode = null
|
||||
// 其他数据
|
||||
Object.keys(opt.data).forEach((key) => {
|
||||
this[key] = opt.data[key]
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 15:55:04
|
||||
* @Desc: 添加子节点
|
||||
*/
|
||||
addChildren(node) {
|
||||
this.children.push(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-09 09:46:23
|
||||
* @Desc: 刷新节点的宽高
|
||||
*/
|
||||
refreshSize() {
|
||||
let {
|
||||
width,
|
||||
height
|
||||
} = this.getNodeRect()
|
||||
this.width = width
|
||||
this.height = height
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 14:52:17
|
||||
* @Desc: 计算节点尺寸信息
|
||||
*/
|
||||
getNodeRect() {
|
||||
let width = this.themeConfig.paddingX * 2
|
||||
let height = this.themeConfig.paddingY * 2
|
||||
let maxWidth = 0
|
||||
if (this.img) {
|
||||
let img = this.createImgNode()
|
||||
if (img.width > maxWidth) {
|
||||
maxWidth = img.width
|
||||
}
|
||||
height += img.height
|
||||
}
|
||||
if (this.icon && this.text) {
|
||||
let icon = this.createIconNode()
|
||||
let text = this.createTextNode()
|
||||
if (icon.width + text.width > maxWidth) {
|
||||
maxWidth = icon.width + text.width
|
||||
}
|
||||
height += Math.max(text.height, icon.height)
|
||||
} else if (this.text) {
|
||||
let text = this.createTextNode()
|
||||
if (text.width > maxWidth) {
|
||||
maxWidth = text.width
|
||||
}
|
||||
height += text.height
|
||||
} else if (this.icon) {
|
||||
let icon = this.createIconNode()
|
||||
if (icon.width > maxWidth) {
|
||||
maxWidth = icon.width
|
||||
}
|
||||
height += icon.height
|
||||
}
|
||||
return {
|
||||
width: width + maxWidth,
|
||||
height
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-09 14:06:17
|
||||
* @Desc: 创建图片节点
|
||||
*/
|
||||
createImgNode() {
|
||||
if (!this.img) {
|
||||
return
|
||||
}
|
||||
let imgSize = this.getImgShowSize()
|
||||
return {
|
||||
node: new Image().load(this.img).size(...imgSize),
|
||||
width: imgSize[0],
|
||||
height: imgSize[1]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-09 14:08:56
|
||||
* @Desc: 创建文本节点
|
||||
*/
|
||||
createTextNode() {
|
||||
if (!this.text) {
|
||||
return
|
||||
}
|
||||
let node = this.draw.text(this.text)
|
||||
this.style.text(node)
|
||||
let {
|
||||
width,
|
||||
height
|
||||
} = node.bbox()
|
||||
let cloneNode = node.clone()
|
||||
node.remove()
|
||||
return {
|
||||
node: cloneNode,
|
||||
width,
|
||||
height
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-09 14:10:48
|
||||
* @Desc: 创建icon节点
|
||||
*/
|
||||
createIconNode() {
|
||||
if (!this.icon) {
|
||||
return
|
||||
}
|
||||
let node = SVG('<svg t="1617947697619" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="999" width="200" height="200"><path d="M512 899.5c-213.668 0-387.5-173.832-387.5-387.5S298.332 124.5 512 124.5 899.5 298.332 899.5 512 725.668 899.5 512 899.5z" fill="#4472C4" p-id="1000"></path><path d="M512 137c-206.776 0-375 168.224-375 375s168.224 375 375 375 375-168.224 375-375-168.224-375-375-375m0-25c220.914 0 400 179.086 400 400S732.914 912 512 912 112 732.914 112 512s179.086-400 400-400z" fill="#4472C4" p-id="1001"></path><path d="M597.681 335.009c0-7.67-2.36-13.569-7.08-17.109a35.115 35.115 0 0 0-20.061-5.9c-3.54 0-6.49 1.77-10.029 4.13-3.54 2.95-6.49 5.31-8.26 7.08a75.758 75.758 0 0 0-11.211 13.569c-3.54 4.72-7.67 9.44-11.209 13.569-11.209 12.979-23.009 27.139-35.988 41.3-13.569 14.749-26.549 27.729-38.938 39.528-1.18 1.18-2.95 2.36-4.13 3.54l-4.72 2.36c-1.77 1.18-3.54 1.77-4.72 2.95l-5.31 3.54c-2.95 2.36-5.31 4.13-7.08 5.9-2.36 2.36-2.95 4.13-2.95 5.9 0 7.08 2.95 12.389 10.03 16.519 5.9 4.72 12.979 6.49 20.059 6.49a31.985 31.985 0 0 0 14.756-3.543c4.13-2.36 8.26-5.9 12.979-10.619 2.95-3.54 6.49-7.67 11.209-12.979l11.8-12.979c2.95-2.95 7.67-7.67 13.569-14.159s12.389-14.159 20.649-23.009c-1.77 9.44-3.54 20.649-4.72 33.628-2.36 12.979-4.13 25.959-5.9 40.118l-4.72 41.888c-1.18 14.159-2.36 27.729-2.95 39.528-1.18 22.419-2.36 44.838-2.95 67.257q-1.77 33.628-1.77 58.407c0 9.44 2.36 16.519 7.67 21.829 5.31 5.9 12.389 8.26 21.829 8.26a43.479 43.479 0 0 0 15.929-3.54c4.72-2.36 7.67-5.31 7.67-8.85 0-1.77-0.59-5.31-0.59-11.209a149.392 149.392 0 0 1-2.36-18.879 116.91 116.91 0 0 1-2.36-21.239 132.008 132.008 0 0 1-1.18-20.649c0-41.3 1.18-82.6 4.72-124.484 3.54-41.3 10.03-82.6 20.649-123.3a106.366 106.366 0 0 1 2.95-11.209l2.36-11.209 1.77-11.209c-0.002-3.547 0.588-7.086 0.588-11.216z" fill="#FFFFFF" p-id="1002"></path></svg>').size(this.themeConfig.iconSize, this.themeConfig.iconSize)
|
||||
return {
|
||||
node,
|
||||
width: this.themeConfig.iconSize,
|
||||
height: this.themeConfig.iconSize
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-09 11:10:11
|
||||
* @Desc: 创建内容节点
|
||||
*/
|
||||
createNode() {
|
||||
let {
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height
|
||||
} = this
|
||||
let paddingY = this.themeConfig.paddingY
|
||||
// 创建组
|
||||
let group = this.draw.group()
|
||||
// 节点矩形
|
||||
let _rectNode = group.rect(width, height).x(left).y(top)
|
||||
this.style.rect(_rectNode)
|
||||
// 内容节点
|
||||
let imgNode = this.createImgNode()
|
||||
let iconNode = this.createIconNode()
|
||||
let textNode = this.createTextNode()
|
||||
let imgHeight = imgNode ? imgNode.height : 0
|
||||
// 图片
|
||||
if (imgNode) {
|
||||
group.add(imgNode.node)
|
||||
imgNode.node.cx(left + width / 2).y(top + paddingY)
|
||||
}
|
||||
// icon
|
||||
if (iconNode) {
|
||||
group.add(iconNode.node)
|
||||
iconNode.node.x(left + width / 2).y(top + paddingY + imgHeight + (textNode && textNode.height > iconNode.height ? (textNode.height - iconNode.height) / 2 : 0)).dx(textNode ? -textNode.width / 2 - iconNode.width / 2 : 0)
|
||||
}
|
||||
// 文字
|
||||
if (textNode) {
|
||||
this.textNode = textNode
|
||||
group.add(textNode.node)
|
||||
textNode.node.cx(left + width / 2).y(top + paddingY + imgHeight).dx(iconNode ? iconNode.width / 2 : 0)
|
||||
}
|
||||
// 单击事件
|
||||
group.click((e) => {
|
||||
e.stopPropagation()
|
||||
if (this.isActive) {
|
||||
return;
|
||||
}
|
||||
this.mindMap.emit('before_node_active', this, this.renderer.activeNodeList)
|
||||
this.renderer.clearActive()
|
||||
this.isActive = true
|
||||
this.mindMap.execCommand('UPDATE_NODE_DATA', this, {
|
||||
isActive: this.isActive
|
||||
})
|
||||
this.renderer.activeNodeList.push(this)
|
||||
this.mindMap.render()
|
||||
this.mindMap.emit('node_active', this, this.renderer.activeNodeList)
|
||||
})
|
||||
// 双击事件
|
||||
group.dblclick(() => {
|
||||
this.showTextEditBox()
|
||||
})
|
||||
return group
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-13 22:15:56
|
||||
* @Desc: 显示文本编辑框
|
||||
*/
|
||||
showTextEditBox() {
|
||||
if (!this.text) {
|
||||
return;
|
||||
}
|
||||
this.renderer.showEditTextBox(this, this.textNode.node.node.getBoundingClientRect())
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 13:55:58
|
||||
* @Desc: 渲染
|
||||
*/
|
||||
render() {
|
||||
// 连线
|
||||
this.drawLine()
|
||||
// 按钮
|
||||
this.drawBtn()
|
||||
// 节点
|
||||
this.draw.add(this.createNode())
|
||||
// 子节点
|
||||
if (this.children && this.children.length && this.expand) {
|
||||
this.children.forEach((child) => {
|
||||
child.render()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-10 22:01:53
|
||||
* @Desc: 连线
|
||||
*/
|
||||
drawLine() {
|
||||
if (!this.expand) {
|
||||
return;
|
||||
}
|
||||
let lines = this.renderer.layout.drawLine(this)
|
||||
lines.forEach((line) => {
|
||||
this.style.line(line)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 19:47:01
|
||||
* @Desc: 展开收缩按钮
|
||||
*/
|
||||
drawBtn() {
|
||||
if (this.children.length <= 0 || this.isRoot) {
|
||||
return;
|
||||
}
|
||||
let g = this.draw.group()
|
||||
let iconSvg
|
||||
if (this.expand) {
|
||||
iconSvg = btnsSvg.close
|
||||
} else {
|
||||
iconSvg = btnsSvg.open
|
||||
}
|
||||
let node = SVG(iconSvg).size(20, 20)
|
||||
let fillNode = new Circle().size(20)
|
||||
this.renderer.layout.drawIcon(this, [node, fillNode])
|
||||
node.dx(0).dy(-10)
|
||||
fillNode.dx(0).dy(-10)
|
||||
this.style.iconBtn(node, fillNode)
|
||||
g.mouseover(() => {
|
||||
g.css({ cursor: 'pointer' })
|
||||
})
|
||||
g.mouseout(() => {
|
||||
g.css({ cursor: 'auto' })
|
||||
})
|
||||
g.click(() => {
|
||||
this.expand = !this.expand
|
||||
// 需要反映到实际数据上
|
||||
this.mindMap.execCommand('UPDATE_NODE_DATA', this, {
|
||||
expand: this.expand
|
||||
})
|
||||
this.mindMap.render()
|
||||
this.mindMap.emit('expand_btn_click', this)
|
||||
})
|
||||
g.add(fillNode)
|
||||
g.add(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-09 10:12:51
|
||||
* @Desc: 获取图片显示宽高
|
||||
*/
|
||||
getImgShowSize() {
|
||||
return resizeImgSize(this.imgWidth, this.imgHeight, this.themeConfig.imgMaxWidth, this.themeConfig.imgMaxHeight)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 21:48:49
|
||||
* @Desc: 获取某个样式
|
||||
*/
|
||||
getStyle(prop, root, isActive) {
|
||||
let v = this.style.merge(prop, root, isActive)
|
||||
return v === undefined ? '' : v
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 22:18:07
|
||||
* @Desc: 修改某个样式
|
||||
*/
|
||||
setStyle(prop, value, isActive) {
|
||||
if (isActive) {
|
||||
this.mindMap.execCommand('UPDATE_NODE_DATA', this, {
|
||||
activeStyle: {
|
||||
...(this.data.activeStyle || {}),
|
||||
[prop]: value
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.mindMap.execCommand('UPDATE_NODE_DATA', this, {
|
||||
[prop]: value
|
||||
})
|
||||
}
|
||||
this.mindMap.render()
|
||||
}
|
||||
}
|
||||
|
||||
export default Node
|
||||
256
src/package/mind-map/src/Render.js
Normal file
256
src/package/mind-map/src/Render.js
Normal file
@@ -0,0 +1,256 @@
|
||||
import merge from 'deepmerge'
|
||||
import LogicalStructure from './layouts/LogicalStructure'
|
||||
import { getStrWithBrFromHtml } from './Utils'
|
||||
|
||||
// 布局列表
|
||||
const layouts = {
|
||||
logicalStructure: LogicalStructure
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 16:25:07
|
||||
* @Desc: 渲染
|
||||
*/
|
||||
class Render {
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 16:25:32
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt = {}) {
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
this.themeConfig = this.mindMap.themeConfig
|
||||
this.draw = this.mindMap.draw
|
||||
// 渲染树,操作过程中修改的都是这里的数据
|
||||
this.renderTree = merge({}, this.mindMap.opt.data || {})
|
||||
// 当前激活的节点列表
|
||||
this.activeNodeList = []
|
||||
// 根节点
|
||||
this.root = null
|
||||
// 文本编辑框
|
||||
this.textEditNode = null
|
||||
// 文本编辑框是否显示
|
||||
this.showTextEdit = false
|
||||
// 布局
|
||||
this.layout = new (layouts[this.mindMap.opt.layout] ? layouts[this.mindMap.opt.layout] : layouts.logicalStructure)({
|
||||
mindMap: this.mindMap,
|
||||
renderer: this,
|
||||
renderTree: this.renderTree,
|
||||
themeConfig: this.mindMap.themeConfig,
|
||||
draw: this.mindMap.draw
|
||||
})
|
||||
// 绑定事件
|
||||
this.bindEvent()
|
||||
// 注册命令
|
||||
this.registerCommands()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 13:27:04
|
||||
* @Desc: 事件
|
||||
*/
|
||||
bindEvent() {
|
||||
this.mindMap.on('draw_click', () => {
|
||||
// 隐藏文本编辑框
|
||||
this.hideEditTextBox()
|
||||
// 清除激活状态
|
||||
if (this.activeNodeList.length > 0) {
|
||||
this.clearActive()
|
||||
this.mindMap.render()
|
||||
this.mindMap.emit('node_active', null, [])
|
||||
}
|
||||
})
|
||||
this.mindMap.on('expand_btn_click', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
this.mindMap.on('before_node_active', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
this.mindMap.keyCommand.addShortcut('Enter', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:19:06
|
||||
* @Desc: 注册命令
|
||||
*/
|
||||
registerCommands() {
|
||||
this.insertNode = this.insertNode.bind(this)
|
||||
this.mindMap.command.add('INSERT_NODE', this.insertNode)
|
||||
this.insertChildNode = this.insertChildNode.bind(this)
|
||||
this.mindMap.command.add('INSERT_CHILD_NODE', this.insertChildNode)
|
||||
this.removeNode = this.removeNode.bind(this)
|
||||
this.mindMap.command.add('REMOVE_NODE', this.removeNode)
|
||||
this.updateNodeData = this.updateNodeData.bind(this)
|
||||
this.mindMap.command.add('UPDATE_NODE_DATA', this.updateNodeData)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 16:27:55
|
||||
* @Desc: 渲染
|
||||
*/
|
||||
render() {
|
||||
this.root = this.layout.doLayout()
|
||||
this.root.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-12 22:45:01
|
||||
* @Desc: 清楚当前激活的节点
|
||||
*/
|
||||
clearActive() {
|
||||
this.activeNodeList.forEach((item) => {
|
||||
this.mindMap.execCommand('UPDATE_NODE_DATA', item, {
|
||||
isActive: false
|
||||
})
|
||||
})
|
||||
this.activeNodeList = []
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:46:08
|
||||
* @Desc: 获取节点在同级里的索引位置
|
||||
*/
|
||||
getNodeIndex(node) {
|
||||
return node.parent ? node.parent.children.findIndex((item) => {
|
||||
return item === node
|
||||
}) : 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:19:54
|
||||
* @Desc: 插入同级节点
|
||||
*/
|
||||
insertNode() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return;
|
||||
}
|
||||
let first = this.activeNodeList[0]
|
||||
if (first.isRoot) {
|
||||
this.insertChildNode()
|
||||
} else {
|
||||
let index = this.getNodeIndex(first)
|
||||
first.parent.originData.children.splice(index + 1, 0, {
|
||||
"data": {
|
||||
"text": "分支主题",
|
||||
"expand": true
|
||||
},
|
||||
"children": []
|
||||
})
|
||||
this.mindMap.render()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:31:02
|
||||
* @Desc: 插入子节点
|
||||
*/
|
||||
insertChildNode() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return;
|
||||
}
|
||||
let first = this.activeNodeList[0]
|
||||
first.originData.children.push({
|
||||
"data": {
|
||||
"text": "分支主题",
|
||||
"expand": true
|
||||
},
|
||||
"children": []
|
||||
})
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:40:39
|
||||
* @Desc: 移除节点
|
||||
*/
|
||||
removeNode() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return;
|
||||
}
|
||||
this.activeNodeList.forEach((item) => {
|
||||
if (item.isRoot) {
|
||||
item.children = []
|
||||
item.originData.children = []
|
||||
} else {
|
||||
let index = this.getNodeIndex(item)
|
||||
item.parent.children.splice(index, 1)
|
||||
item.parent.originData.children.splice(index, 1)
|
||||
}
|
||||
})
|
||||
this.clearActive()
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 14:19:48
|
||||
* @Desc: 更新节点数据
|
||||
*/
|
||||
updateNodeData(node, data) {
|
||||
Object.keys(data).forEach((key) => {
|
||||
node.data[key] = data[key]
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-13 22:13:02
|
||||
* @Desc: 显示文本编辑框
|
||||
*/
|
||||
showEditTextBox(node, rect) {
|
||||
if (!this.textEditNode) {
|
||||
this.textEditNode = document.createElement('div')
|
||||
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;background-color:#fff;box-shadow: 0 0 20px rgba(0,0,0,.5);padding: 3px 5px;margin-left: -5px;margin-top: -3px;outline: none;`
|
||||
this.textEditNode.setAttribute('contenteditable', true)
|
||||
document.body.appendChild(this.textEditNode)
|
||||
}
|
||||
node.style.domText(this.textEditNode)
|
||||
this.textEditNode.innerHTML = node.data.text.split(/\n/img).join('<br>')
|
||||
this.textEditNode.style.minWidth = rect.width + 10 + 'px'
|
||||
this.textEditNode.style.minHeight = rect.height + 6 + 'px'
|
||||
this.textEditNode.style.left = rect.left + 'px'
|
||||
this.textEditNode.style.top = rect.top + 'px'
|
||||
this.textEditNode.style.display = 'block'
|
||||
this.showTextEdit = true
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 13:48:16
|
||||
* @Desc: 隐藏文本编辑框
|
||||
*/
|
||||
hideEditTextBox() {
|
||||
if (!this.showTextEdit) {
|
||||
return
|
||||
}
|
||||
this.activeNodeList.forEach((node) => {
|
||||
let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
|
||||
node.data.text = str
|
||||
this.mindMap.render()
|
||||
})
|
||||
this.mindMap.emit('hide_text_edit', this.textEditNode, this.activeNodeList)
|
||||
this.textEditNode.style.display = 'none'
|
||||
this.textEditNode.innerHTML = ''
|
||||
this.textEditNode.style.fontFamily = 'inherit'
|
||||
this.textEditNode.style.fontSize = 'inherit'
|
||||
this.textEditNode.style.fontWeight = 'normal'
|
||||
this.showTextEdit = false
|
||||
}
|
||||
}
|
||||
|
||||
export default Render
|
||||
122
src/package/mind-map/src/Style.js
Normal file
122
src/package/mind-map/src/Style.js
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 10:09:08
|
||||
* @Desc: 样式类
|
||||
*/
|
||||
class Style {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 16:01:53
|
||||
* @Desc: 设置背景样式
|
||||
*/
|
||||
static setBackgroundStyle(el, themeConfig) {
|
||||
let { backgroundColor, backgroundImage, backgroundRepeat } = themeConfig
|
||||
el.style.backgroundColor = backgroundColor
|
||||
if (backgroundImage) {
|
||||
el.style.backgroundImage = `url(${backgroundImage})`
|
||||
el.style.backgroundRepeat = backgroundRepeat
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 10:10:11
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(ctx, themeConfig) {
|
||||
this.ctx = ctx
|
||||
this.themeConfig = themeConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 12:02:55
|
||||
* @Desc: 合并样式
|
||||
*/
|
||||
merge(prop, root, isActive) {
|
||||
// 三级及以下节点
|
||||
let defaultConfig = this.themeConfig.node
|
||||
if (root) {// 直接使用最外层样式
|
||||
defaultConfig = this.themeConfig
|
||||
} else if (this.ctx.layerIndex === 0) {// 根节点
|
||||
defaultConfig = this.themeConfig.root
|
||||
} else if (this.ctx.layerIndex === 1) {// 二级节点
|
||||
defaultConfig = this.themeConfig.secondLevel
|
||||
}
|
||||
// 激活状态
|
||||
if (isActive !== undefined ? isActive : this.ctx.isActive) {
|
||||
if (this.ctx.activeStyle && this.ctx.activeStyle[prop] !== undefined) {
|
||||
return this.ctx.activeStyle[prop];
|
||||
} else if (defaultConfig.active && defaultConfig.active[prop]) {
|
||||
return defaultConfig.active[prop]
|
||||
}
|
||||
}
|
||||
// 优先使用节点本身的样式
|
||||
return this.ctx[prop] !== undefined ? this.ctx[prop] : defaultConfig[prop]
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 10:12:56
|
||||
* @Desc: 矩形
|
||||
*/
|
||||
rect(node) {
|
||||
node.fill({
|
||||
color: this.merge('fillColor')
|
||||
}).stroke({
|
||||
color: this.merge('borderColor'),
|
||||
width: this.merge('borderWidth'),
|
||||
dasharray: this.merge('borderDasharray')
|
||||
}).radius(this.merge('borderRadius'))
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 12:07:59
|
||||
* @Desc: 文字
|
||||
*/
|
||||
text(node) {
|
||||
node.fill({
|
||||
color: this.merge('color')
|
||||
}).css({
|
||||
'font-family': this.merge('fontFamily'),
|
||||
'font-size': this.merge('fontSize'),
|
||||
'font-weight': this.merge('fontWeight'),
|
||||
'font-style': this.merge('fontStyle'),
|
||||
'text-decoration': this.merge('textDecoration')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-13 08:14:34
|
||||
* @Desc: html文字节点
|
||||
*/
|
||||
domText(node) {
|
||||
node.style.fontFamily = this.merge('fontFamily')
|
||||
node.style.fontSize = this.merge('fontSize') + 'px'
|
||||
node.style.fontWeight = this.merge('fontWeight') || 'normal'
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 14:50:49
|
||||
* @Desc: 连线
|
||||
*/
|
||||
line(node) {
|
||||
node.stroke({ width: this.merge('lineWidth', true), color: this.merge('lineColor', true) }).fill({ color: 'none' })
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 20:03:59
|
||||
* @Desc: 按钮
|
||||
*/
|
||||
iconBtn(node, fillNode) {
|
||||
node.fill({ color: '#808080' })
|
||||
fillNode.fill({ color: '#fff' })
|
||||
}
|
||||
}
|
||||
|
||||
export default Style
|
||||
134
src/package/mind-map/src/Utils.js
Normal file
134
src/package/mind-map/src/Utils.js
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 14:13:17
|
||||
* @Desc: 深度优先遍历树
|
||||
*/
|
||||
export const walk = (root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0) => {
|
||||
beforeCallback && beforeCallback(root, parent, isRoot, layerIndex)
|
||||
if (root.children && root.children.length > 0) {
|
||||
let _layerIndex = layerIndex + 1
|
||||
root.children.forEach((node) => {
|
||||
walk(node, root, beforeCallback, afterCallback, false, _layerIndex)
|
||||
})
|
||||
}
|
||||
afterCallback && afterCallback(root, parent, isRoot, layerIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 18:47:20
|
||||
* @Desc: 广度优先遍历树
|
||||
*/
|
||||
export const bfsWalk = (root, callback) => {
|
||||
callback(root)
|
||||
let stack = [root]
|
||||
while (stack.length) {
|
||||
let cur = stack.shift()
|
||||
if (cur.children && cur.children.length) {
|
||||
cur.children.forEach((item) => {
|
||||
stack.push(item)
|
||||
callback(item)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-09 10:44:54
|
||||
* @Desc: 缩放图片尺寸
|
||||
*/
|
||||
export const resizeImgSize = (width, height, maxWidth, maxHeight) => {
|
||||
let nRatio = width / height
|
||||
let arr = []
|
||||
if (maxWidth && maxHeight) {
|
||||
if (width <= maxWidth && height <= maxHeight) {
|
||||
arr = [width, height]
|
||||
} else {
|
||||
let mRatio = maxWidth / maxHeight
|
||||
if (nRatio > mRatio) { // 固定高度
|
||||
arr = [nRatio * maxHeight, maxHeight]
|
||||
} else { // 固定宽度
|
||||
arr = [maxWidth, maxWidth / nRatio]
|
||||
}
|
||||
}
|
||||
} else if (maxWidth) {
|
||||
if (width <= maxWidth) {
|
||||
arr = [width, height]
|
||||
} else {
|
||||
arr = [maxWidth, maxWidth / nRatio]
|
||||
}
|
||||
} else if (maxHeight) {
|
||||
if (height <= maxHeight) {
|
||||
arr = [width, height]
|
||||
} else {
|
||||
arr = [nRatio * maxHeight, maxHeight]
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-09 10:18:42
|
||||
* @Desc: 缩放图片
|
||||
*/
|
||||
export const resizeImg = (imgUrl, maxWidth, maxHeight) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let img = new Image()
|
||||
img.src = imgUrl
|
||||
img.onload = () => {
|
||||
let arr = resizeImgSize(img.naturalWidth, img.naturalHeight, maxWidth, maxHeight)
|
||||
resolve(arr)
|
||||
}
|
||||
img.onerror = (e) => {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 12:26:56
|
||||
* @Desc: 从头html结构字符串里获取带换行符的字符串
|
||||
*/
|
||||
export const getStrWithBrFromHtml = (str) => {
|
||||
str = str.replace(/<br>/img, '\n')
|
||||
let el = document.createElement('div')
|
||||
el.innerHTML = str
|
||||
str = el.textContent
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 14:45:39
|
||||
* @Desc: 极简的深拷贝
|
||||
*/
|
||||
export const simpleDeepClone = (data) => {
|
||||
try {
|
||||
return JSON.parse(JSON.stringify(data))
|
||||
} catch (error) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 14:40:11
|
||||
* @Desc: 复制渲染树数据
|
||||
*/
|
||||
export const copyRenderTree = (tree, root) => {
|
||||
tree.data = simpleDeepClone(root.data)
|
||||
tree.children = []
|
||||
if (root.children.length > 0) {
|
||||
root.children.forEach((item, index) => {
|
||||
tree.children[index] = copyRenderTree({}, item)
|
||||
})
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
87
src/package/mind-map/src/View.js
Normal file
87
src/package/mind-map/src/View.js
Normal file
@@ -0,0 +1,87 @@
|
||||
import merge from 'deepmerge'
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 14:45:24
|
||||
* @Desc: 视图操作类
|
||||
*/
|
||||
class View {
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 14:45:40
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt = {}) {
|
||||
this.opt = opt
|
||||
this.mindMap = this.opt.mindMap
|
||||
this.viewBox = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.mindMap.width,
|
||||
height: this.mindMap.height
|
||||
}
|
||||
this.cacheViewBox = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.mindMap.width,
|
||||
height: this.mindMap.height
|
||||
}
|
||||
this.scale = 1
|
||||
this.bind()
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 15:38:51
|
||||
* @Desc: 绑定
|
||||
*/
|
||||
bind() {
|
||||
// 拖动视图
|
||||
this.mindMap.event.on('mousedown', () => {
|
||||
this.cacheViewBox = merge({}, this.viewBox)
|
||||
})
|
||||
this.mindMap.event.on('drag', (e, event) => {
|
||||
// 视图放大缩小后拖动的距离也要相应变化
|
||||
this.viewBox.x = this.cacheViewBox.x - event.mousemoveOffset.x * this.scale
|
||||
this.viewBox.y = this.cacheViewBox.y - event.mousemoveOffset.y * this.scale
|
||||
this.setViewBox()
|
||||
})
|
||||
// 放大缩小视图
|
||||
this.mindMap.event.on('mousewheel', (e, dir) => {
|
||||
let stepWidth = this.viewBox.width * this.mindMap.opt.scaleRatio
|
||||
let stepHeight = this.viewBox.height * this.mindMap.opt.scaleRatio
|
||||
// 放大
|
||||
if (dir === 'down') {
|
||||
this.scale += this.mindMap.opt.scaleRatio
|
||||
this.viewBox.width += stepWidth
|
||||
this.viewBox.height += stepHeight
|
||||
} else { // 缩小
|
||||
this.scale -= this.mindMap.opt.scaleRatio
|
||||
this.viewBox.width -= stepWidth
|
||||
this.viewBox.height -= stepHeight
|
||||
}
|
||||
this.setViewBox()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 15:43:26
|
||||
* @Desc: 设置视图
|
||||
*/
|
||||
setViewBox() {
|
||||
let {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
} = this.viewBox
|
||||
this.opt.draw.viewbox(x, y, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
export default View
|
||||
70
src/package/mind-map/src/layouts/Base.js
Normal file
70
src/package/mind-map/src/layouts/Base.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-12 22:24:30
|
||||
* @Desc: 布局基类
|
||||
*/
|
||||
class Base {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-12 22:25:16
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt) {
|
||||
// 控制实例
|
||||
this.mindMap = opt.mindMap
|
||||
// 渲染实例
|
||||
this.renderer = opt.renderer
|
||||
// 渲染树
|
||||
this.renderTree = opt.renderTree
|
||||
// 主题配置
|
||||
this.themeConfig = opt.themeConfig
|
||||
// 绘图对象
|
||||
this.draw = opt.draw
|
||||
// 根节点
|
||||
this.root = null
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-12 22:39:50
|
||||
* @Desc: 计算节点位置
|
||||
*/
|
||||
doLayout() {
|
||||
throw new Error('【computed】方法为必要方法,需要子类进行重写!')
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-12 22:41:04
|
||||
* @Desc: 连线
|
||||
*/
|
||||
drawLine() {
|
||||
throw new Error('【drawLine】方法为必要方法,需要子类进行重写!')
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-12 22:42:08
|
||||
* @Desc: 定位显示展开收缩按钮
|
||||
*/
|
||||
drawIcon() {
|
||||
throw new Error('【drawIcon】方法为必要方法,需要子类进行重写!')
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 11:25:52
|
||||
* @Desc: 更新子节点属性
|
||||
*/
|
||||
updateChildren(children, prop, offset) {
|
||||
children.forEach((item) => {
|
||||
item[prop] += offset
|
||||
if (item.children && item.children.length) {
|
||||
this.updateChildren(item.children, prop, offset)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Base
|
||||
240
src/package/mind-map/src/layouts/LogicalStructure.js
Normal file
240
src/package/mind-map/src/layouts/LogicalStructure.js
Normal file
@@ -0,0 +1,240 @@
|
||||
import Base from './Base';
|
||||
import {
|
||||
walk
|
||||
} from '../Utils'
|
||||
import Node from '../Node'
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-12 22:25:58
|
||||
* @Desc: 逻辑结构图
|
||||
*/
|
||||
class LogicalStructure extends Base {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-12 22:26:31
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt = {}) {
|
||||
super(opt)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 14:04:20
|
||||
* @Desc: 布局
|
||||
*/
|
||||
doLayout() {
|
||||
// 计算节点的left、width、height
|
||||
this.computedBaseValue()
|
||||
// 计算节点的top
|
||||
this.computedTopValue()
|
||||
// 调整节点top
|
||||
this.adjustTopValue()
|
||||
|
||||
return this.root;
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 09:49:32
|
||||
* @Desc: 计算节点的left、width、height
|
||||
*/
|
||||
computedBaseValue() {
|
||||
walk(this.renderTree, null, (node, parent, isRoot, layerIndex) => {
|
||||
// 遍历子节点前设置left、width、height
|
||||
if (!node.data) {
|
||||
node.data = {}
|
||||
}
|
||||
// 创建节点
|
||||
let newNode = new Node({
|
||||
uid: this.mindMap.uid++,
|
||||
originData: node,
|
||||
data: node.data,
|
||||
renderer: this.renderer,
|
||||
mindMap: this.mindMap,
|
||||
draw: this.draw,
|
||||
layerIndex
|
||||
})
|
||||
// 计算节点的宽高
|
||||
newNode.refreshSize()
|
||||
if (isRoot) {
|
||||
newNode.isRoot = true
|
||||
newNode.left = (this.mindMap.width - newNode.width) / 2
|
||||
newNode.top = (this.mindMap.height - newNode.height) / 2
|
||||
this.root = newNode
|
||||
} else {
|
||||
let marginX = layerIndex === 1 ? this.themeConfig.secondLevel.marginX : this.themeConfig.node.marginX
|
||||
newNode.left = parent._node.left + parent._node.width + marginX,
|
||||
newNode.parent = parent._node
|
||||
parent._node.addChildren(newNode)
|
||||
}
|
||||
node._node = newNode
|
||||
}, (node, parent, isRoot, layerIndex) => {
|
||||
// 返回时计算节点的areaHeight,也就是子节点所占的高度之和,包括外边距
|
||||
let len = node.expand === false ? 0 : node._node.children.length
|
||||
node._node.childrenAreaHeight = len ? node._node.children.reduce((h, cur) => {
|
||||
return h + cur.height
|
||||
}, 0) + (len + 1) * this.getMarginY(layerIndex) : 0
|
||||
}, true, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 09:59:25
|
||||
* @Desc: 计算节点的top
|
||||
*/
|
||||
computedTopValue() {
|
||||
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
|
||||
if (node.children && node.children.length) {
|
||||
let marginY = this.getMarginY(layerIndex)
|
||||
// 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半
|
||||
let top = node.top + node.height / 2 - node.childrenAreaHeight / 2
|
||||
let totalTop = top + marginY
|
||||
node.children.forEach((cur) => {
|
||||
cur.top = totalTop
|
||||
totalTop += cur.height + marginY
|
||||
})
|
||||
}
|
||||
}, null, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 10:04:05
|
||||
* @Desc: 调整节点top
|
||||
*/
|
||||
adjustTopValue() {
|
||||
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
|
||||
// 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置
|
||||
let difference = node.childrenAreaHeight - this.getMarginY(layerIndex) - node.height
|
||||
if (difference > 0) {
|
||||
this.updateBrothers(node, difference / 2)
|
||||
}
|
||||
}, null, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 14:26:03
|
||||
* @Desc: 更新兄弟节点的top
|
||||
*/
|
||||
updateBrothers(node, addHeight) {
|
||||
if (node.parent) {
|
||||
let childrenList = node.parent.children
|
||||
let index = childrenList.findIndex((item) => {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
let _offset = 0
|
||||
// 上面的节点往上移
|
||||
if (_index < index) {
|
||||
_offset = -addHeight
|
||||
} else if (_index > index) {// 下面的节点往下移
|
||||
_offset = addHeight
|
||||
}
|
||||
item.top += _offset
|
||||
// 同步更新子节点的位置
|
||||
if (item.children && item.children.length) {
|
||||
this.updateChildren(item.children, 'top', _offset)
|
||||
}
|
||||
})
|
||||
// 更新父节点的位置
|
||||
this.updateBrothers(node.parent, addHeight)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:34:20
|
||||
* @Desc: 获取节点的marginY
|
||||
*/
|
||||
getMarginY(layerIndex) {
|
||||
return layerIndex === 1 ? this.themeConfig.secondLevel.marginY : this.themeConfig.node.marginY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:05:01
|
||||
* @Desc: 二次贝塞尔曲线
|
||||
*/
|
||||
quadraticCurvePath(x1, y1, x2, y2) {
|
||||
let cx = x1 + (x2 - x1) * 0.2
|
||||
let cy = y1 + (y2 - y1) * 0.8
|
||||
return `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:05:18
|
||||
* @Desc: 三次贝塞尔曲线
|
||||
*/
|
||||
cubicBezierPath(x1, y1, x2, y2) {
|
||||
let cx1 = x1 + (x2 - x1) / 2
|
||||
let cy1 = y1
|
||||
let cx2 = x2 - (x2 - x1) / 2
|
||||
let cy2 = y2
|
||||
return `M ${x1},${y1} C ${cx1},${cy1} ${cx2},${cy2} ${x2},${y2}`
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 14:42:48
|
||||
* @Desc: 绘制连线,连接该节点到其子节点
|
||||
*/
|
||||
drawLine(node) {
|
||||
if (node.children.length <= 0) {
|
||||
return [];
|
||||
}
|
||||
let {
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height
|
||||
} = node
|
||||
let lines = []
|
||||
if (!node.isRoot) {
|
||||
let line = this.draw.line(left + width, top + height / 2, left + width + 20, top + height / 2)
|
||||
lines.push(line)
|
||||
}
|
||||
node.children.forEach((item) => {
|
||||
let x1 = node.layerIndex === 0 ? left + width / 2 : left + width + 20
|
||||
let y1 = node.layerIndex === 0 ? top + height / 2 : top + height / 2
|
||||
let x2 = item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
let path = ''
|
||||
if (node.isRoot) {
|
||||
path = this.quadraticCurvePath(x1, y1, x2, y2)
|
||||
} else {
|
||||
path = this.cubicBezierPath(x1, y1, x2, y2)
|
||||
}
|
||||
let line = this.draw.path(path)
|
||||
lines.push(line)
|
||||
})
|
||||
return lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 19:54:26
|
||||
* @Desc: 渲染按钮
|
||||
*/
|
||||
drawIcon(node, icons) {
|
||||
let {
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height
|
||||
} = node
|
||||
icons.forEach((icon) => {
|
||||
icon.x(left + width).y(top + height / 2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default LogicalStructure
|
||||
18
src/package/mind-map/src/svg/btns.js
Normal file
18
src/package/mind-map/src/svg/btns.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 19:46:10
|
||||
* @Desc: 展开按钮
|
||||
*/
|
||||
const open = `<svg t="1618141562310" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13476" width="200" height="200"><path d="M475.136 327.168v147.968h-147.968v74.24h147.968v147.968h74.24v-147.968h147.968v-74.24h-147.968v-147.968h-74.24z m36.864-222.208c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z" p-id="13477"></path></svg>`
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 19:46:23
|
||||
* @Desc: 收缩按钮
|
||||
*/
|
||||
const close = `<svg t="1618141589243" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13611" width="200" height="200"><path d="M512 105.472c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z" p-id="13612"></path><path d="M252.928 474.624h518.144v74.24h-518.144z" p-id="13613"></path></svg>`
|
||||
|
||||
export default {
|
||||
open,
|
||||
close
|
||||
}
|
||||
40
src/package/mind-map/src/themes/blueSky.js
Normal file
40
src/package/mind-map/src/themes/blueSky.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 天空蓝
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(115, 161, 191)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(115, 161, 191)',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: 'rgb(238, 243, 246)',
|
||||
color: '#333',
|
||||
borderColor: 'rgb(115, 161, 191)',
|
||||
borderWidth: 1,
|
||||
fontSize: 14,
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 12,
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)'
|
||||
}
|
||||
},
|
||||
})
|
||||
40
src/package/mind-map/src/themes/brainImpairedPink.js
Normal file
40
src/package/mind-map/src/themes/brainImpairedPink.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 脑残粉
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(191, 115, 148)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(191, 115, 148)',
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 74)'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: 'rgb(246, 238, 242)',
|
||||
color: '#333',
|
||||
borderColor: 'rgb(191, 115, 148)',
|
||||
borderWidth: 1,
|
||||
fontSize: 14,
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 74)'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 12,
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 74)'
|
||||
}
|
||||
}
|
||||
})
|
||||
53
src/package/mind-map/src/themes/classic.js
Normal file
53
src/package/mind-map/src/themes/classic.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 脑图经典
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: '#fff',
|
||||
// 连线的粗细
|
||||
lineWidth: 3,
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(58, 65, 68)',
|
||||
// 背景图片
|
||||
backgroundImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQzg5QTQ0NDhENzgxMUUzOENGREE4QTg0RDgzRTZDNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQzg5QTQ0NThENzgxMUUzOENGREE4QTg0RDgzRTZDNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkMwOEQ1NDRGOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkMwOEQ1NDUwOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+e9P33AAAACVJREFUeNpisXJ0YUACTAyoAMr/+eM7EGGRZ4FQ7BycEAZAgAEAHbEGtkoQm/wAAAAASUVORK5CYII=',
|
||||
// 背景重复
|
||||
backgroundRepeat: 'repeat',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(233, 223, 152)',
|
||||
color: '#333',
|
||||
fontSize: 24,
|
||||
borderRadius: 21,
|
||||
active: {
|
||||
fillColor: 'rgb(254, 219, 0)',
|
||||
borderColor: 'transparent'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: 'rgb(164, 197, 192)',
|
||||
borderColor: 'transparent',
|
||||
color: '#333',
|
||||
fontSize: 16,
|
||||
borderRadius: 10,
|
||||
active: {
|
||||
fillColor: 'rgb(254, 219, 0)',
|
||||
borderColor: 'transparent'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 12,
|
||||
color: '#fff',
|
||||
fontWeight: 'bold',
|
||||
active: {
|
||||
fillColor: 'rgb(254, 219, 0)',
|
||||
borderColor: 'transparent'
|
||||
}
|
||||
}
|
||||
})
|
||||
45
src/package/mind-map/src/themes/classic2.js
Normal file
45
src/package/mind-map/src/themes/classic2.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 经典2
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(51, 51, 51)',
|
||||
// 连线的粗细
|
||||
lineWidth: 2,
|
||||
// 背景颜色
|
||||
backgroundColor: '#fff',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(18, 187, 55)',
|
||||
color: '#fff',
|
||||
fontSize: 24,
|
||||
borderRadius: 10,
|
||||
active: {
|
||||
borderColor: 'rgb(51, 51, 51)'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: 'rgb(241, 242, 241)',
|
||||
borderColor: 'transparent',
|
||||
color: '#1a1a1a',
|
||||
fontSize: 18,
|
||||
borderRadius: 10,
|
||||
active: {
|
||||
borderColor: 'rgb(51, 51, 51)'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 14,
|
||||
color: '#1a1a1a',
|
||||
active: {
|
||||
borderColor: 'rgb(51, 51, 51)'
|
||||
}
|
||||
}
|
||||
})
|
||||
48
src/package/mind-map/src/themes/classic3.js
Normal file
48
src/package/mind-map/src/themes/classic3.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 经典3
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(94, 202, 110)',
|
||||
// 连线的粗细
|
||||
lineWidth: 2,
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(241, 241, 241)',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(255, 245, 214)',
|
||||
color: '#1a1a1a',
|
||||
fontSize: 24,
|
||||
borderRadius: 10,
|
||||
borderColor: 'rgb(249, 199, 84)',
|
||||
borderWidth: 1,
|
||||
active: {
|
||||
borderColor: 'rgb(94, 202, 110)'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: 'rgb(255, 245, 214)',
|
||||
borderColor: 'rgb(249, 199, 84)',
|
||||
borderWidth: 1,
|
||||
color: '#1a1a1a',
|
||||
fontSize: 18,
|
||||
borderRadius: 10,
|
||||
active: {
|
||||
borderColor: 'rgb(94, 202, 110)'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 14,
|
||||
color: '#1a1a1a',
|
||||
active: {
|
||||
borderColor: 'rgb(94, 202, 110)'
|
||||
}
|
||||
}
|
||||
})
|
||||
45
src/package/mind-map/src/themes/dark.js
Normal file
45
src/package/mind-map/src/themes/dark.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 暗色
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(17, 68, 23)',
|
||||
// 连线的粗细
|
||||
lineWidth: 2,
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(15, 16, 17)',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(28, 178, 43)',
|
||||
color: '#fff',
|
||||
fontSize: 24,
|
||||
borderRadius: 10,
|
||||
active: {
|
||||
borderColor: 'rgb(17, 68, 23)'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: 'rgb(55, 56, 58)',
|
||||
color: 'rgb(147,148,149)',
|
||||
fontSize: 18,
|
||||
borderRadius: 10,
|
||||
borderWidth: 0,
|
||||
active: {
|
||||
borderColor: 'rgb(17, 68, 23)'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 14,
|
||||
color: 'rgb(147, 148, 149)',
|
||||
active: {
|
||||
borderColor: 'rgb(17, 68, 23)'
|
||||
}
|
||||
}
|
||||
})
|
||||
87
src/package/mind-map/src/themes/default.js
Normal file
87
src/package/mind-map/src/themes/default.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 10:19:55
|
||||
* @Desc: 默认主题
|
||||
*/
|
||||
export default {
|
||||
// 节点内边距
|
||||
paddingX: 20,
|
||||
paddingY: 10,
|
||||
// 图片显示的最大宽度
|
||||
imgMaxWidth: 200,
|
||||
// 图片显示的最大高度
|
||||
imgMaxHeight: 200,
|
||||
// icon的大小
|
||||
iconSize: 20,
|
||||
// 连线的粗细
|
||||
lineWidth: 1,
|
||||
// 连线的颜色
|
||||
lineColor: '#549688',
|
||||
// 背景颜色
|
||||
backgroundColor: '#fafafa',
|
||||
// 背景图片
|
||||
backgroundImage: '',
|
||||
// 背景重复
|
||||
backgroundRepeat: 'none',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: '#549688',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#fff',
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
fontStyle: 'normal',
|
||||
borderColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
borderDasharray: 'none',
|
||||
borderRadius: 5,
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none',
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
marginX: 100,
|
||||
marginY: 40,
|
||||
fillColor: '#fff',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#565656',
|
||||
fontSize: 16,
|
||||
fontWeight: 'noraml',
|
||||
fontStyle: 'normal',
|
||||
borderColor: '#549688',
|
||||
borderWidth: 1,
|
||||
borderDasharray: 'none',
|
||||
borderRadius: 5,
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none',
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
marginX: 60,
|
||||
marginY: 40,
|
||||
fillColor: 'transparent',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#6a6d6c',
|
||||
fontSize: 14,
|
||||
fontWeight: 'noraml',
|
||||
fontStyle: 'normal',
|
||||
borderColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
borderRadius: 5,
|
||||
borderDasharray: 'none',
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none',
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/package/mind-map/src/themes/earthYellow.js
Normal file
40
src/package/mind-map/src/themes/earthYellow.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 泥土黄
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(191, 147, 115)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(191, 147, 115)',
|
||||
active: {
|
||||
borderColor: 'rgb(96, 73, 57)'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: 'rgb(246, 242, 238)',
|
||||
color: '#333',
|
||||
borderColor: 'rgb(191, 147, 115)',
|
||||
borderWidth: 1,
|
||||
fontSize: 14,
|
||||
active: {
|
||||
borderColor: 'rgb(96, 73, 57)'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 12,
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(96, 73, 57)'
|
||||
}
|
||||
}
|
||||
})
|
||||
25
src/package/mind-map/src/themes/freshGreen.js
Normal file
25
src/package/mind-map/src/themes/freshGreen.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 清新绿
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: '#333',
|
||||
// 背景颜色
|
||||
backgroundColor: '#d1f6ec',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: '#1fb27d'
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: '#fff',
|
||||
color: '#565656',
|
||||
borderColor: 'transparent',
|
||||
borderWidth: 0
|
||||
},
|
||||
})
|
||||
40
src/package/mind-map/src/themes/freshRed.js
Normal file
40
src/package/mind-map/src/themes/freshRed.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 清新红
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(191, 115, 115)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(191, 115, 115)',
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 57)'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: 'rgb(246, 238, 238)',
|
||||
color: '#333',
|
||||
borderColor: 'rgb(191, 115, 115)',
|
||||
borderWidth: 1,
|
||||
fontSize: 14,
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 57)'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 12,
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 57)'
|
||||
}
|
||||
}
|
||||
})
|
||||
25
src/package/mind-map/src/themes/index.js
Normal file
25
src/package/mind-map/src/themes/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import defaultTheme from './default';
|
||||
import freshGreen from './freshGreen';
|
||||
import blueSky from './blueSky';
|
||||
import brainImpairedPink from './brainImpairedPink';
|
||||
import romanticPurple from './romanticPurple';
|
||||
import freshRed from './freshRed';
|
||||
import earthYellow from './earthYellow';
|
||||
import classic from './classic';
|
||||
import classic2 from './classic2';
|
||||
import classic3 from './classic3';
|
||||
import dark from './dark';
|
||||
|
||||
export default {
|
||||
default: defaultTheme,
|
||||
freshGreen,
|
||||
blueSky,
|
||||
brainImpairedPink,
|
||||
romanticPurple,
|
||||
freshRed,
|
||||
earthYellow,
|
||||
classic,
|
||||
classic2,
|
||||
classic3,
|
||||
dark
|
||||
}
|
||||
40
src/package/mind-map/src/themes/romanticPurple.js
Normal file
40
src/package/mind-map/src/themes/romanticPurple.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 浪漫紫
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(123, 115, 191)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(123, 115, 191)',
|
||||
active: {
|
||||
borderColor: 'rgb(61, 57, 96)'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
secondLevel: {
|
||||
fillColor: 'rgb(239, 238, 246)',
|
||||
color: '#333',
|
||||
borderColor: 'rgb(123, 115, 191)',
|
||||
borderWidth: 1,
|
||||
fontSize: 14,
|
||||
active: {
|
||||
borderColor: 'rgb(61, 57, 96)'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 12,
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(61, 57, 96)'
|
||||
}
|
||||
}
|
||||
})
|
||||
120
src/package/mind-map/src/utils/keyMap.js
Normal file
120
src/package/mind-map/src/utils/keyMap.js
Normal file
@@ -0,0 +1,120 @@
|
||||
const map = {
|
||||
'Backspace': 8,
|
||||
'Tab': 9,
|
||||
'Enter': 13,
|
||||
|
||||
'Shift': 16,
|
||||
'Control': 17,
|
||||
'Alt': 18,
|
||||
'CapsLock': 20,
|
||||
|
||||
'Esc': 27,
|
||||
|
||||
'Spacebar': 32,
|
||||
|
||||
'PageUp': 33,
|
||||
'PageDown': 34,
|
||||
'End': 35,
|
||||
'Home': 36,
|
||||
|
||||
'Insert': 45,
|
||||
|
||||
'Left': 37,
|
||||
'Up': 38,
|
||||
'Right': 39,
|
||||
'Down': 40,
|
||||
|
||||
'Del': 46,
|
||||
|
||||
'NumLock': 144,
|
||||
|
||||
'Cmd': 91,
|
||||
'CmdFF': 224,
|
||||
'F1': 112,
|
||||
'F2': 113,
|
||||
'F3': 114,
|
||||
'F4': 115,
|
||||
'F5': 116,
|
||||
'F6': 117,
|
||||
'F7': 118,
|
||||
'F8': 119,
|
||||
'F9': 120,
|
||||
'F10': 121,
|
||||
'F11': 122,
|
||||
'F12': 123,
|
||||
|
||||
'`': 192,
|
||||
'=': 187,
|
||||
'-': 189,
|
||||
|
||||
'/': 191,
|
||||
'.': 190,
|
||||
|
||||
'direction': {
|
||||
37: 1,
|
||||
38: 1,
|
||||
39: 1,
|
||||
40: 1
|
||||
},
|
||||
|
||||
controlKeys: {
|
||||
16: 1,
|
||||
17: 1,
|
||||
18: 1,
|
||||
20: 1,
|
||||
91: 1,
|
||||
224: 1
|
||||
},
|
||||
'notContentChange': {
|
||||
13: 1,
|
||||
9: 1,
|
||||
|
||||
33: 1,
|
||||
34: 1,
|
||||
35: 1,
|
||||
36: 1,
|
||||
|
||||
16: 1,
|
||||
17: 1,
|
||||
18: 1,
|
||||
20: 1,
|
||||
91: 1,
|
||||
|
||||
//上下左右
|
||||
37: 1,
|
||||
38: 1,
|
||||
39: 1,
|
||||
40: 1,
|
||||
|
||||
113: 1,
|
||||
114: 1,
|
||||
115: 1,
|
||||
144: 1,
|
||||
27: 1
|
||||
},
|
||||
'isSelectedNodeKey': {
|
||||
//上下左右
|
||||
37: 1,
|
||||
38: 1,
|
||||
39: 1,
|
||||
40: 1,
|
||||
13: 1,
|
||||
9: 1
|
||||
}
|
||||
}
|
||||
// 数字
|
||||
for (let i = 0; i <= 9; i++) {
|
||||
map[i] = i + 48
|
||||
}
|
||||
|
||||
// 字母
|
||||
'abcdefghijklmnopqrstuvwxyz'.split('').forEach((n, index) => {
|
||||
map[n] = index + 65
|
||||
})
|
||||
|
||||
export const keyMap = map
|
||||
|
||||
export const isKey = (e, key) => {
|
||||
let code = typeof e === 'object' ? e.keyCode : e
|
||||
return map[key] === code
|
||||
}
|
||||
44
src/pages/Edit/Index.vue
Normal file
44
src/pages/Edit/Index.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<template v-if="show">
|
||||
<Toolbar></Toolbar>
|
||||
<Edit></Edit>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Toolbar from "./components/Toolbar";
|
||||
import Edit from "./components/Edit";
|
||||
import { mapState, mapActions } from "vuex";
|
||||
|
||||
export default {
|
||||
name: "Index",
|
||||
components: {
|
||||
Toolbar,
|
||||
Edit,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
text: "正在加载,请稍后...",
|
||||
});
|
||||
await this.getUserMindMapData();
|
||||
this.show = true;
|
||||
loading.close();
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["getUserMindMapData"]),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
}
|
||||
</style>
|
||||
236
src/pages/Edit/components/BaseStyle.vue
Normal file
236
src/pages/Edit/components/BaseStyle.vue
Normal file
@@ -0,0 +1,236 @@
|
||||
<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>
|
||||
</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.lineColor }"
|
||||
></span>
|
||||
<el-popover ref="popover" placement="bottom" trigger="click">
|
||||
<Color
|
||||
:color="style.lineColor"
|
||||
@change="
|
||||
(color) => {
|
||||
update('lineColor', color);
|
||||
}
|
||||
"
|
||||
></Color>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="rowItem">
|
||||
<span class="name">粗细</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.lineWidth"
|
||||
placeholder=""
|
||||
@change="
|
||||
(value) => {
|
||||
update('lineWidth', 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">
|
||||
<div class="rowItem">
|
||||
<span class="name">水平</span>
|
||||
<el-slider
|
||||
style="width: 230px"
|
||||
v-model="style.paddingX"
|
||||
@change="
|
||||
(value) => {
|
||||
update('paddingX', value);
|
||||
}
|
||||
"
|
||||
></el-slider>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">垂直</span>
|
||||
<el-slider
|
||||
style="width: 230px"
|
||||
v-model="style.paddingY"
|
||||
@change="
|
||||
(value) => {
|
||||
update('paddingY', value);
|
||||
}
|
||||
"
|
||||
></el-slider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Sidebar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Sidebar from "./Sidebar";
|
||||
import Color from "./Color";
|
||||
import { lineWidthList } from "@/config";
|
||||
|
||||
export default {
|
||||
name: "BaseStyle",
|
||||
components: {
|
||||
Sidebar,
|
||||
Color,
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
type: [Object, null],
|
||||
default: null,
|
||||
},
|
||||
mindMap: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lineWidthList,
|
||||
style: {
|
||||
backgroundColor: "",
|
||||
lineColor: "",
|
||||
lineWidth: "",
|
||||
paddingX: 0,
|
||||
paddingY: 0,
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("showTheme", () => {
|
||||
this.$refs.sidebar.show = true;
|
||||
this.initStyle();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 14:02:12
|
||||
* @Desc: 初始样式
|
||||
*/
|
||||
initStyle() {
|
||||
[
|
||||
"backgroundColor",
|
||||
"lineWidth",
|
||||
"lineColor",
|
||||
"paddingX",
|
||||
"paddingY",
|
||||
].forEach((key) => {
|
||||
this.style[key] = this.mindMap.getThemeConfig(key);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 14:05:40
|
||||
* @Desc: 更新配置
|
||||
*/
|
||||
update(key, value) {
|
||||
this.style[key] = value;
|
||||
this.data.theme.config[key] = value;
|
||||
this.$emit("change");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.sidebarContent {
|
||||
padding: 20px;
|
||||
padding-top: 10px;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: rgba(26, 26, 26, 0.9);
|
||||
margin-bottom: 10px;
|
||||
margin-top: 20px;
|
||||
|
||||
&.noTop {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.btnGroup {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.rowItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.name {
|
||||
font-size: 12px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.styleBtn {
|
||||
position: relative;
|
||||
width: 50px;
|
||||
height: 30px;
|
||||
background: #fff;
|
||||
border: 1px solid #eee;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
|
||||
&.actived {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.colorShow {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
92
src/pages/Edit/components/Color.vue
Normal file
92
src/pages/Edit/components/Color.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="colorList">
|
||||
<span
|
||||
class="colorItem"
|
||||
v-for="item in colorList"
|
||||
:style="{ backgroundColor: item }"
|
||||
:key="item"
|
||||
@click="clickColorItem(item)"
|
||||
></span>
|
||||
</div>
|
||||
<div class="moreColor">
|
||||
<span>更多颜色</span>
|
||||
<el-color-picker
|
||||
size="mini"
|
||||
v-model="selectColor"
|
||||
@change="changeColor"
|
||||
></el-color-picker>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { colorList } from "@/config";
|
||||
|
||||
export default {
|
||||
name: "Color",
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
colorList,
|
||||
selectColor: "",
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
color() {
|
||||
this.selectColor = this.color;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.selectColor = this.color;
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 09:38:06
|
||||
* @Desc: 点击预设颜色
|
||||
*/
|
||||
clickColorItem(color) {
|
||||
this.$emit("change", color);
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 10:17:26
|
||||
* @Desc: 修改颜色
|
||||
*/
|
||||
changeColor() {
|
||||
this.$emit("change", this.selectColor);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.colorList {
|
||||
width: 240px;
|
||||
|
||||
.colorItem {
|
||||
display: inline-block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.moreColor {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
104
src/pages/Edit/components/Edit.vue
Normal file
104
src/pages/Edit/components/Edit.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<div class="editContainer">
|
||||
<div class="mindMapContainer" ref="mindMapContainer"></div>
|
||||
<Outline></Outline>
|
||||
<Style></Style>
|
||||
<BaseStyle :data="mindMapData" :mindMap="mindMap" @change="changeThemeConfig"></BaseStyle>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MindMap from "@/package/mind-map";
|
||||
import Outline from "./Outline";
|
||||
import Style from "./Style";
|
||||
import BaseStyle from "./BaseStyle";
|
||||
import exampleData from '@/package/mind-map/example/exampleData';
|
||||
|
||||
export default {
|
||||
name: "Edit",
|
||||
components: {
|
||||
Outline,
|
||||
Style,
|
||||
BaseStyle,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mindMap: null,
|
||||
mindMapData: exampleData
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
mounted() {
|
||||
this.init();
|
||||
this.$bus.$on("execCommand", this.execCommand);
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-10 15:01:01
|
||||
* @Desc: 初始化
|
||||
*/
|
||||
init() {
|
||||
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);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 13:49:25
|
||||
* @Desc: 修改主题配置
|
||||
*/
|
||||
changeThemeConfig() {
|
||||
this.mindMap.setThemeConfig(this.mindMapData.theme.config)
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 13:32:11
|
||||
* @Desc: 重新渲染
|
||||
*/
|
||||
reRender() {
|
||||
this.mindMap.render()
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:08:28
|
||||
* @Desc: 执行命令
|
||||
*/
|
||||
execCommand(...args) {
|
||||
this.mindMap.execCommand(...args);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.editContainer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 62px;
|
||||
bottom: 0;
|
||||
|
||||
.mindMapContainer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
0
src/pages/Edit/components/NodeIcon.vue
Normal file
0
src/pages/Edit/components/NodeIcon.vue
Normal file
51
src/pages/Edit/components/NodeImage.vue
Normal file
51
src/pages/Edit/components/NodeImage.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<el-dialog class="nodeImageDialog" title="图片" :visible.sync="dialogVisible" width="500">
|
||||
<ImgUpload ref="imgUpload"></ImgUpload>
|
||||
<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 ImgUpload from '@/components/ImgUpload';
|
||||
|
||||
export default {
|
||||
name: 'NodeImage',
|
||||
components: {
|
||||
ImgUpload
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
let activeNodes = args[1];
|
||||
this.activeNode = activeNodes[0];
|
||||
console.log(args);
|
||||
});
|
||||
this.$bus.$on("showNodeImage", () => {
|
||||
this.dialogVisible = true;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
cancel() {},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 22:28:20
|
||||
* @Desc: 确定
|
||||
*/
|
||||
confirm() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.nodeImageDialog {
|
||||
|
||||
}
|
||||
</style>
|
||||
37
src/pages/Edit/components/Outline.vue
Normal file
37
src/pages/Edit/components/Outline.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<Sidebar ref="sidebar" title="大纲">
|
||||
<el-tree :data="data" :props="defaultProps" default-expand-all></el-tree>
|
||||
</Sidebar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Sidebar from "./Sidebar";
|
||||
|
||||
export default {
|
||||
name: "Outline",
|
||||
components: {
|
||||
Sidebar,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
defaultProps: {
|
||||
label(data) {
|
||||
return data.data.text;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("data_change", (data) => {
|
||||
this.data = [data];
|
||||
});
|
||||
this.$bus.$on('showOutline', () => {
|
||||
this.$refs.sidebar.show = true
|
||||
})
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
</style>
|
||||
72
src/pages/Edit/components/Sidebar.vue
Normal file
72
src/pages/Edit/components/Sidebar.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<div class="sidebarContainer" :class="{show: show}">
|
||||
<span class="closeBtn el-icon-close" @click="show = false"></span>
|
||||
<div class="sidebarHeader" v-if="title">
|
||||
{{ title }}
|
||||
</div>
|
||||
<div class="sidebarContent">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Sidebar",
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.sidebarContainer {
|
||||
position: fixed;
|
||||
right: -300px;
|
||||
top: 62px;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
background-color: #fff;
|
||||
border-left: 1px solid #e8e8e8;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.show {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.closeBtn {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 12px;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sidebarHeader {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebarContent {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
441
src/pages/Edit/components/Style.vue
Normal file
441
src/pages/Edit/components/Style.vue
Normal file
@@ -0,0 +1,441 @@
|
||||
<template>
|
||||
<Sidebar ref="sidebar" title="节点样式">
|
||||
<div class="styleBox">
|
||||
<el-tabs class="tab" v-model="activeTab" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="常态" name="normal"></el-tab-pane>
|
||||
<el-tab-pane label="选中状态" name="active"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class="sidebarContent" v-if="activeNode">
|
||||
<div class="title noTop">文字</div>
|
||||
<div class="row">
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 160px"
|
||||
v-model="style.fontFamily"
|
||||
placeholder=""
|
||||
@change="update('fontFamily')"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in fontFamilyList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
:style="{ fontFamily: item.value }"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.fontSize"
|
||||
placeholder=""
|
||||
@change="update('fontSize')"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in fontSizeList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="btnGroup">
|
||||
<el-tooltip content="颜色" placement="bottom">
|
||||
<div class="styleBtn" v-popover:popover>
|
||||
A
|
||||
<span
|
||||
class="colorShow"
|
||||
:style="{ backgroundColor: style.color || '#eee' }"
|
||||
></span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="加粗" placement="bottom">
|
||||
<div
|
||||
class="styleBtn"
|
||||
:class="{ actived: style.fontWeight === 'bold' }"
|
||||
@click="toggleFontWeight"
|
||||
>
|
||||
B
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="斜体" placement="bottom">
|
||||
<div
|
||||
class="styleBtn i"
|
||||
:class="{ actived: style.fontStyle === 'italic' }"
|
||||
@click="toggleFontStyle"
|
||||
>
|
||||
I
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="划线" placement="bottom">
|
||||
<div
|
||||
class="styleBtn u"
|
||||
:style="{ textDecoration: style.textDecoration || 'none' }"
|
||||
v-popover:popover2
|
||||
>
|
||||
U
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-popover ref="popover" placement="bottom" trigger="click">
|
||||
<Color :color="style.color" @change="changeFontColor"></Color>
|
||||
</el-popover>
|
||||
<el-popover ref="popover2" placement="bottom" trigger="click">
|
||||
<el-radio-group
|
||||
size="mini"
|
||||
v-model="style.textDecoration"
|
||||
@change="update('textDecoration')"
|
||||
>
|
||||
<el-radio-button label="underline">下划线</el-radio-button>
|
||||
<el-radio-button label="line-through">中划线</el-radio-button>
|
||||
<el-radio-button label="overline">上划线</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="title">边框</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">颜色</span>
|
||||
<span
|
||||
class="block"
|
||||
v-popover:popover3
|
||||
:style="{ width: '80px', backgroundColor: style.borderColor }"
|
||||
></span>
|
||||
<el-popover ref="popover3" placement="bottom" trigger="click">
|
||||
<Color
|
||||
:color="style.borderColor"
|
||||
@change="changeBorderColor"
|
||||
></Color>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="rowItem">
|
||||
<span class="name" v-popover:popover5>样式</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.borderDasharray"
|
||||
placeholder=""
|
||||
@change="update('borderDasharray')"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in borderDasharrayList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">宽度</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.borderWidth"
|
||||
placeholder=""
|
||||
@change="update('borderWidth')"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in borderWidthList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="rowItem">
|
||||
<span class="name">圆角</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.borderRadius"
|
||||
placeholder=""
|
||||
@change="update('borderRadius')"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in borderRadiusList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title">背景</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">颜色</span>
|
||||
<span
|
||||
class="block"
|
||||
v-popover:popover4
|
||||
:style="{ backgroundColor: style.fillColor }"
|
||||
></span>
|
||||
<el-popover ref="popover4" placement="bottom" trigger="click">
|
||||
<Color :color="style.fillColor" @change="changeFillColor"></Color>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Sidebar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Sidebar from "./Sidebar";
|
||||
import Color from "./Color";
|
||||
import {
|
||||
fontFamilyList,
|
||||
fontSizeList,
|
||||
borderWidthList,
|
||||
borderDasharrayList,
|
||||
borderRadiusList,
|
||||
} from "@/config";
|
||||
|
||||
export default {
|
||||
name: "Style",
|
||||
components: {
|
||||
Sidebar,
|
||||
Color,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fontFamilyList,
|
||||
fontSizeList,
|
||||
borderWidthList,
|
||||
borderDasharrayList,
|
||||
borderRadiusList,
|
||||
activeNode: null,
|
||||
activeTab: "normal",
|
||||
style: {
|
||||
color: "",
|
||||
fontFamily: "",
|
||||
fontSize: "",
|
||||
textDecoration: "",
|
||||
fontWeight: "",
|
||||
fontStyle: "",
|
||||
borderWidth: "",
|
||||
borderColor: "",
|
||||
fillColor: "",
|
||||
borderDasharray: "",
|
||||
borderRadius: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
this.activeTab = 'normal'
|
||||
let activeNodes = args[1];
|
||||
this.activeNode = activeNodes[0];
|
||||
this.$refs.sidebar.show = activeNodes.length > 0;
|
||||
this.initNodeStyle();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 11:42:32
|
||||
* @Desc: tab切换
|
||||
*/
|
||||
handleTabClick() {
|
||||
this.initNodeStyle()
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 09:48:52
|
||||
* @Desc: 初始节点样式
|
||||
*/
|
||||
initNodeStyle() {
|
||||
if (!this.activeNode) {
|
||||
this.activeTab = 'normal'
|
||||
return;
|
||||
}
|
||||
[
|
||||
"color",
|
||||
"fontFamily",
|
||||
"fontSize",
|
||||
"textDecoration",
|
||||
"fontWeight",
|
||||
"fontStyle",
|
||||
"borderWidth",
|
||||
"borderColor",
|
||||
"fillColor",
|
||||
"borderDasharray",
|
||||
"borderRadius",
|
||||
].forEach((item) => {
|
||||
this.style[item] = this.activeNode.getStyle(item, false, this.activeTab === 'active');
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 22:08:16
|
||||
* @Desc: 修改样式
|
||||
*/
|
||||
update(prop) {
|
||||
this.activeNode.setStyle(prop, this.style[prop], this.activeTab === 'active');
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 09:41:34
|
||||
* @Desc: 切换加粗样式
|
||||
*/
|
||||
toggleFontWeight() {
|
||||
if (this.style.fontWeight === "bold") {
|
||||
this.style.fontWeight = "normal";
|
||||
} else {
|
||||
this.style.fontWeight = "bold";
|
||||
}
|
||||
this.update("fontWeight");
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 09:46:39
|
||||
* @Desc: 切换字体样式
|
||||
*/
|
||||
toggleFontStyle() {
|
||||
if (this.style.fontStyle === "italic") {
|
||||
this.style.fontStyle = "normal";
|
||||
} else {
|
||||
this.style.fontStyle = "italic";
|
||||
}
|
||||
this.update("fontStyle");
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 10:18:59
|
||||
* @Desc: 修改字体颜色
|
||||
*/
|
||||
changeFontColor(color) {
|
||||
this.style.color = color;
|
||||
this.update("color");
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 10:18:59
|
||||
* @Desc: 修改边框颜色
|
||||
*/
|
||||
changeBorderColor(color) {
|
||||
this.style.borderColor = color;
|
||||
this.update("borderColor");
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-05 10:18:59
|
||||
* @Desc: 修改背景颜色
|
||||
*/
|
||||
changeFillColor(color) {
|
||||
this.style.fillColor = color;
|
||||
this.update("fillColor");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.styleBox {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.tab {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
padding: 0 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebarContent {
|
||||
padding: 20px;
|
||||
padding-top: 10px;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: rgba(26, 26, 26, 0.9);
|
||||
margin-bottom: 10px;
|
||||
margin-top: 20px;
|
||||
|
||||
&.noTop {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.btnGroup {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.rowItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.name {
|
||||
font-size: 12px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.styleBtn {
|
||||
position: relative;
|
||||
width: 50px;
|
||||
height: 30px;
|
||||
background: #fff;
|
||||
border: 1px solid #eee;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
|
||||
&.actived {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
&.i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
&.u {
|
||||
}
|
||||
|
||||
.colorShow {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
155
src/pages/Edit/components/Toolbar.vue
Normal file
155
src/pages/Edit/components/Toolbar.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
<NodeImage></NodeImage>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NodeImage from "./NodeImage";
|
||||
|
||||
export default {
|
||||
name: "Toolbar",
|
||||
components: {
|
||||
NodeImage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeNodes: [],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
this.activeNodes = args[1];
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<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 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.toolbarBtn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
cursor: pointer;
|
||||
margin-right: 20px;
|
||||
|
||||
&:hover {
|
||||
&:not(.disabled) {
|
||||
.icon {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
color: #bcbcbc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
13
src/pages/Index/Index.vue
Normal file
13
src/pages/Index/Index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div class="container"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Index"
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style lang="less" scoped>
|
||||
</style>
|
||||
18
src/router.js
Normal file
18
src/router.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
|
||||
import IndexPage from '@/pages/Index/Index'
|
||||
import EditPage from '@/pages/Edit/Index'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const routes = [
|
||||
{ path: '/', name: 'Index', component: IndexPage },
|
||||
{ path: '/edit/:id', name: 'Edit', component: EditPage }
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
||||
68
src/store.js
Normal file
68
src/store.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import exampleData from './package/mind-map/example/exampleData';
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
state: {
|
||||
userInfo: null,// 用户信息
|
||||
mindMapData: null// 思维导图数据
|
||||
},
|
||||
mutations: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2020-11-28 15:32:32
|
||||
* @Desc: 设置用户信息
|
||||
*/
|
||||
setUserInfo(state, userInfo) {
|
||||
state.userInfo = userInfo
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-10 14:50:01
|
||||
* @Desc: 设置思维导图数据
|
||||
*/
|
||||
setMindMapData(state, data) {
|
||||
state.mindMapData = data
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2020-11-28 15:28:03
|
||||
* @Desc: 获取用户信息
|
||||
*/
|
||||
async getUserInfo(ctx) {
|
||||
try {
|
||||
let { data } = await api.getUserInfo()
|
||||
ctx.commit('setUserInfo', data.data)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-10 14:50:40
|
||||
* @Desc: 获取思维导图数据
|
||||
*/
|
||||
async getUserMindMapData(ctx) {
|
||||
try {
|
||||
let { data } = {
|
||||
data: {
|
||||
data: {
|
||||
mindMapData: exampleData
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.commit('setMindMapData', data.data)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default store
|
||||
0
src/utils/index.js
Normal file
0
src/utils/index.js
Normal file
13
vue.config.js
Normal file
13
vue.config.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
lintOnSave: false,
|
||||
productionSourceMap: false,
|
||||
configureWebpack: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './src/')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user