Demo:提供应用接管模式,方便对接自己的存储服务

This commit is contained in:
wanglin2 2023-08-01 09:49:44 +08:00
parent a4b7915196
commit b11bd5a7ef
11 changed files with 605 additions and 16 deletions

View File

@ -6,6 +6,10 @@
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
<link rel="icon" href="./dist/logo.ico">
<title>思绪思维导图</title>
<script>
// 接管应用
window.takeOverApp = false
</script>
</head>
<body>
<noscript>
@ -13,5 +17,73 @@
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script>
const getDataFromBackend = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
mindMapData: {
root:{
"data": {
"text": "根节点"
},
"children": []
},
theme:{
"template":"avocado",
"config":{}
},
layout:"logicalStructure",
config: {},
view: null,
},
lang: 'zh',
localConfig: null
})
}, 200)
})
}
const setTakeOverAppMethods = (data) => {
window.takeOverAppMethods = {}
// 获取思维导图数据的函数
window.takeOverAppMethods.getMindMapData = () => {
return data.mindMapData
}
// 保存思维导图数据的函数
window.takeOverAppMethods.saveMindMapData = (data) => {
console.log(data)
}
// 获取语言的函数
window.takeOverAppMethods.getLanguage = () => {
return data.lang
}
// 保存语言的函数
window.takeOverAppMethods.saveLanguage = (lang) => {
console.log(lang)
}
// 获取本地配置的函数
window.takeOverAppMethods.getLocalConfig = () => {
return data.localConfig
}
// 保存本地配置的函数
window.takeOverAppMethods.saveLocalConfig = (config) => {
console.log(config)
}
}
window.onload = async () => {
if (!window.takeOverApp) return
// 请求数据
const data = await getDataFromBackend()
// 设置全局的方法
setTakeOverAppMethods(data)
// 思维导图实例创建完成事件
window.$bus.$on('app_inited', (mindMap) => {
console.log(mindMap)
})
// 可以通过window.$bus.$on()来监听应用的一些事件
// 实例化页面
window.initApp()
}
</script>
</body>
</html>

View File

@ -6,6 +6,8 @@ const SIMPLE_MIND_MAP_DATA = 'SIMPLE_MIND_MAP_DATA'
const SIMPLE_MIND_MAP_LANG = 'SIMPLE_MIND_MAP_LANG'
const SIMPLE_MIND_MAP_LOCAL_CONFIG = 'SIMPLE_MIND_MAP_LOCAL_CONFIG'
let mindMapData = null
/**
* @Author: 王林
* @Date: 2021-08-02 22:36:48
@ -29,6 +31,10 @@ const copyMindMapTreeData = (tree, root) => {
* @Desc: 获取缓存的思维导图数据
*/
export const getData = () => {
if (window.takeOverApp) {
mindMapData = window.takeOverAppMethods.getMindMapData()
return mindMapData
}
let store = localStorage.getItem(SIMPLE_MIND_MAP_DATA)
if (store === null) {
return simpleDeepClone(exampleData)
@ -48,8 +54,18 @@ export const getData = () => {
*/
export const storeData = data => {
try {
let originData = getData()
let originData = null
if (window.takeOverApp) {
originData = mindMapData
} else {
originData = getData()
}
originData.root = copyMindMapTreeData({}, data)
if (window.takeOverApp) {
mindMapData = originData
window.takeOverAppMethods.saveMindMapData(originData)
return
}
Vue.prototype.$bus.$emit('write_local_file', originData)
let dataStr = JSON.stringify(originData)
localStorage.setItem(SIMPLE_MIND_MAP_DATA, dataStr)
@ -65,11 +81,21 @@ export const storeData = data => {
*/
export const storeConfig = config => {
try {
let originData = getData()
let originData = null
if (window.takeOverApp) {
originData = mindMapData
} else {
originData = getData()
}
originData = {
...originData,
...config
}
if (window.takeOverApp) {
mindMapData = originData
window.takeOverAppMethods.saveMindMapData(originData)
return
}
Vue.prototype.$bus.$emit('write_local_file', originData)
let dataStr = JSON.stringify(originData)
localStorage.setItem(SIMPLE_MIND_MAP_DATA, dataStr)
@ -85,6 +111,10 @@ export const storeConfig = config => {
* @Desc: 存储语言
*/
export const storeLang = lang => {
if (window.takeOverApp) {
window.takeOverAppMethods.saveLanguage(lang)
return
}
localStorage.setItem(SIMPLE_MIND_MAP_LANG, lang)
}
@ -95,6 +125,9 @@ export const storeLang = lang => {
* @Desc: 获取存储的语言
*/
export const getLang = () => {
if (window.takeOverApp) {
return window.takeOverAppMethods.getLanguage() || 'zh'
}
let lang = localStorage.getItem(SIMPLE_MIND_MAP_LANG)
if (lang) {
return lang
@ -110,6 +143,9 @@ export const getLang = () => {
* @Desc: 存储本地配置
*/
export const storeLocalConfig = config => {
if (window.takeOverApp) {
return window.takeOverAppMethods.saveLocalConfig(config)
}
localStorage.setItem(SIMPLE_MIND_MAP_LOCAL_CONFIG, JSON.stringify(config))
}
@ -120,6 +156,9 @@ export const storeLocalConfig = config => {
* @Desc: 获取本地配置
*/
export const getLocalConfig = () => {
if (window.takeOverApp) {
return window.takeOverAppMethods.getLocalConfig()
}
let config = localStorage.getItem(SIMPLE_MIND_MAP_LOCAL_CONFIG)
if (config) {
return JSON.parse(config)

View File

@ -1,12 +1,10 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import messages from './lang'
import { getLang } from '@/api'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale: getLang(),
messages
})

View File

@ -8,17 +8,31 @@ import '@/assets/icon-font/iconfont.css'
import 'viewerjs/dist/viewer.css'
import VueViewer from 'v-viewer'
import i18n from './i18n'
import { getLang } from '@/api'
// import VConsole from 'vconsole'
// const vConsole = new VConsole()
Vue.config.productionTip = false
Vue.prototype.$bus = new Vue()
const bus = new Vue()
Vue.prototype.$bus = bus
Vue.use(ElementUI)
Vue.use(VueViewer)
new Vue({
render: h => h(App),
router,
store,
i18n
}).$mount('#app')
const initApp = () => {
i18n.locale = getLang()
new Vue({
render: h => h(App),
router,
store,
i18n
}).$mount('#app')
}
// 是否处于接管应用模式
if (window.takeOverApp) {
window.initApp = initApp
window.$bus = bus
} else {
initApp()
}

View File

@ -63,4 +63,130 @@ However, this requires backend support, as our application is a single page clie
## Docker
In writing...
## Docker
> Thank you very much [水车](https://github.com/shuiche-it), This section is written by him, and the corresponding Docker package is also maintained by him.
Install directly from Docker Hub:
```
docker run -d -p 8081:8080 shuiche/mind-map:latest
```
Mindmap has activated port 8080 as the web service entry point in the container. When running the container through Docker, it is necessary to specify a local mapping port. In the above case, we mapped the local port 8081 to the container port 8080.
After the installation is completed, check the container's running status through 'Docker PS'.
Open 127.0.0.1:8081 in the browser to use the Web mind map function.
## Docking with one's own storage services
The application data is stored locally in the browser by default, and the local storage capacity of the browser is relatively small, so it is easy to trigger restrictions when inserting more images in the mind map. Therefore, a better choice is to dock with your own storage service, which usually has two ways:
### The first
Simply clone the warehouse code and modify the relevant methods in 'web/src/API/index.js' to obtain data from your database and store it in your data.
### The second
Many times, you may want to always use the latest code from this repository, so the first method is not very convenient because you need to manually merge the code, so the second method is provided.
Specific operating steps:
1. Copy the packaged resources of the web application
This includes the 'dist' directory and the 'index.html' file.
2. Modify the copied 'index.html' file
Firstly, insert the following code into the 'head' tag:
```js
<script>
window.takeOverApp = true
</script>
```
This line of code will prompt the application not to initialize the application 'i.e.: new Vue()', but to give control to you. Next, insert your own 'js' code at the end of the 'body', either inline or out of chain. The inline example is as follows:
```js
<script>
// Your own method of requesting data
const getDataFromBackend = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
// MindMap data
mindMapData: {
root: {
"data": {
"text": "根节点"
},
"children": []
},
theme: { "template":"avocado","config":{} },
layout: "logicalStructure",
config: {},
view: {}
},
// Page language, supporting Chinese (zh) and English (en)
lang: 'zh',
// Page Section Configuration
localConfig: null
})
}, 200)
})
}
// Register Global Method
const setTakeOverAppMethods = (data) => {
window.takeOverAppMethods = {}
// Function for obtaining mind map data
window.takeOverAppMethods.getMindMapData = () => {
return data.mindMapData
}
// Functions for Saving Mind Map Data
window.takeOverAppMethods.saveMindMapData = (data) => {
console.log(data)
// The trigger frequency of this function may be high, so you should do throttling or anti shaking measures
}
// Function to obtain language
window.takeOverAppMethods.getLanguage = () => {
return data.lang
}
// Functions for Saving Languages
window.takeOverAppMethods.saveLanguage = (lang) => {
console.log(lang)
}
// Get locally configured functions
window.takeOverAppMethods.getLocalConfig = () => {
return data.localConfig
}
// Save locally configured functions
window.takeOverAppMethods.saveLocalConfig = (config) => {
console.log(config)
}
}
window.onload = async () => {
if (!window.takeOverApp) return
// request data
const data = await getDataFromBackend()
// Method for setting global
setTakeOverAppMethods(data)
// Mind Map Instance Creation Completion Event
window.$bus.$on('app_inited', (mindMap) => {
console.log(mindMap)
})
// You can use window$ Bus$ On() to listen for some events in the application
// Instantiate Page
window.initApp()
}
</script>
```
As shown above, when you set the 'window.takeOverApp=true' flag, the application will no longer actively instantiate, but will expose the instantiated methods for you to call. You can first request the data of the mind map from the backend, and then register the relevant methods. The application will call internally at the appropriate time to achieve the purpose of echo and save.
The advantage of doing this is that whenever the code in this repository is updated, you can simply copy the packaged files to your own server. With a slight modification of the 'index. html' page, you can achieve synchronous updates and use your own storage service.
Of course, there are also certain limitations at present, as' Vue CLI 'does not support' webpack '`__ Webpack_ Public_ Path__` Variable, so it is not possible to meet the requirement of setting static resource paths at runtime. The default 'publicPath' is 'dist', so you should place the 'dist' directory and the 'index.html' file at the same level as the server.
If you want to modify the 'publicPath', such as placing static resources in the 'cdn', you can only 'clone' the code of this repository and modify the 'publicPath' configuration of 'web/vue.config.js'. After the code of this repository is updated, you need to pull it again, package it with the modified configuration, and then perform the modification operation of the ' index.html' file earlier. It is recommended to write a 'Node.js' script to complete this task.

View File

@ -39,7 +39,112 @@ npm link simple-mind-map
</code></pre>
<p>However, this requires backend support, as our application is a single page client application. If the backend is not properly configured, users will return 404 when accessing sub routes directly in the browser. Therefore, you need to add a candidate resource on the server that covers all situations: if the 'URL' cannot match any static resources, the same 'index. html' page should be returned.</p>
<h2>Docker</h2>
<p>In writing...</p>
<h2>Docker</h2>
<blockquote>
<p>Thank you very much <a href="https://github.com/shuiche-it">水车</a>, This section is written by him, and the corresponding Docker package is also maintained by him.</p>
</blockquote>
<p>Install directly from Docker Hub:</p>
<pre class="hljs"><code>docker run -d -p 8081:8080 shuiche/mind-map:latest
</code></pre>
<p>Mindmap has activated port 8080 as the web service entry point in the container. When running the container through Docker, it is necessary to specify a local mapping port. In the above case, we mapped the local port 8081 to the container port 8080.</p>
<p>After the installation is completed, check the container's running status through 'Docker PS'.</p>
<p>Open 127.0.0.1:8081 in the browser to use the Web mind map function.</p>
<h2>Docking with one's own storage services</h2>
<p>The application data is stored locally in the browser by default, and the local storage capacity of the browser is relatively small, so it is easy to trigger restrictions when inserting more images in the mind map. Therefore, a better choice is to dock with your own storage service, which usually has two ways:</p>
<h3>The first</h3>
<p>Simply clone the warehouse code and modify the relevant methods in 'web/src/API/index.js' to obtain data from your database and store it in your data.</p>
<h3>The second</h3>
<p>Many times, you may want to always use the latest code from this repository, so the first method is not very convenient because you need to manually merge the code, so the second method is provided.</p>
<p>Specific operating steps:</p>
<ol>
<li>Copy the packaged resources of the web application</li>
</ol>
<p>This includes the 'dist' directory and the 'index.html' file.</p>
<ol start="2">
<li>Modify the copied 'index.html' file</li>
</ol>
<p>Firstly, insert the following code into the 'head' tag:</p>
<pre class="hljs"><code>&lt;script&gt;
<span class="hljs-built_in">window</span>.takeOverApp = <span class="hljs-literal">true</span>
&lt;/script&gt;
</code></pre>
<p>This line of code will prompt the application not to initialize the application 'i.e.: new Vue()', but to give control to you. Next, insert your own 'js' code at the end of the 'body', either inline or out of chain. The inline example is as follows:</p>
<pre class="hljs"><code>&lt;script&gt;
<span class="hljs-comment">// Your own method of requesting data</span>
<span class="hljs-keyword">const</span> getDataFromBackend = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
resolve({
<span class="hljs-comment">// MindMap data</span>
<span class="hljs-attr">mindMapData</span>: {
<span class="hljs-attr">root</span>: {
<span class="hljs-string">&quot;data&quot;</span>: {
<span class="hljs-string">&quot;text&quot;</span>: <span class="hljs-string">&quot;根节点&quot;</span>
},
<span class="hljs-string">&quot;children&quot;</span>: []
},
<span class="hljs-attr">theme</span>: { <span class="hljs-string">&quot;template&quot;</span>:<span class="hljs-string">&quot;avocado&quot;</span>,<span class="hljs-string">&quot;config&quot;</span>:{} },
<span class="hljs-attr">layout</span>: <span class="hljs-string">&quot;logicalStructure&quot;</span>,
<span class="hljs-attr">config</span>: {},
<span class="hljs-attr">view</span>: {}
},
<span class="hljs-comment">// Page language, supporting Chinese (zh) and English (en)</span>
<span class="hljs-attr">lang</span>: <span class="hljs-string">&#x27;zh&#x27;</span>,
<span class="hljs-comment">// Page Section Configuration</span>
<span class="hljs-attr">localConfig</span>: <span class="hljs-literal">null</span>
})
}, <span class="hljs-number">200</span>)
})
}
<span class="hljs-comment">// Register Global Method</span>
<span class="hljs-keyword">const</span> setTakeOverAppMethods = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
<span class="hljs-built_in">window</span>.takeOverAppMethods = {}
<span class="hljs-comment">// Function for obtaining mind map data</span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.getMindMapData = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> data.mindMapData
}
<span class="hljs-comment">// Functions for Saving Mind Map Data</span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.saveMindMapData = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
<span class="hljs-built_in">console</span>.log(data)
<span class="hljs-comment">// The trigger frequency of this function may be high, so you should do throttling or anti shaking measures</span>
}
<span class="hljs-comment">// Function to obtain language</span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.getLanguage = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> data.lang
}
<span class="hljs-comment">// Functions for Saving Languages</span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.saveLanguage = <span class="hljs-function">(<span class="hljs-params">lang</span>) =&gt;</span> {
<span class="hljs-built_in">console</span>.log(lang)
}
<span class="hljs-comment">// Get locally configured functions</span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.getLocalConfig = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> data.localConfig
}
<span class="hljs-comment">// Save locally configured functions</span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.saveLocalConfig = <span class="hljs-function">(<span class="hljs-params">config</span>) =&gt;</span> {
<span class="hljs-built_in">console</span>.log(config)
}
}
<span class="hljs-built_in">window</span>.onload = <span class="hljs-keyword">async</span> () =&gt; {
<span class="hljs-keyword">if</span> (!<span class="hljs-built_in">window</span>.takeOverApp) <span class="hljs-keyword">return</span>
<span class="hljs-comment">// request data</span>
<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> getDataFromBackend()
<span class="hljs-comment">// Method for setting global</span>
setTakeOverAppMethods(data)
<span class="hljs-comment">// Mind Map Instance Creation Completion Event</span>
<span class="hljs-built_in">window</span>.$bus.$on(<span class="hljs-string">&#x27;app_inited&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">mindMap</span>) =&gt;</span> {
<span class="hljs-built_in">console</span>.log(mindMap)
})
<span class="hljs-comment">// You can use window$ Bus$ On() to listen for some events in the application</span>
<span class="hljs-comment">// Instantiate Page</span>
<span class="hljs-built_in">window</span>.initApp()
}
&lt;/script&gt;
</code></pre>
<p>As shown above, when you set the 'window.takeOverApp=true' flag, the application will no longer actively instantiate, but will expose the instantiated methods for you to call. You can first request the data of the mind map from the backend, and then register the relevant methods. The application will call internally at the appropriate time to achieve the purpose of echo and save.</p>
<p>The advantage of doing this is that whenever the code in this repository is updated, you can simply copy the packaged files to your own server. With a slight modification of the 'index. html' page, you can achieve synchronous updates and use your own storage service.</p>
<p>Of course, there are also certain limitations at present, as' Vue CLI 'does not support' webpack '<code>__ Webpack_ Public_ Path__</code> Variable, so it is not possible to meet the requirement of setting static resource paths at runtime. The default 'publicPath' is 'dist', so you should place the 'dist' directory and the 'index.html' file at the same level as the server.</p>
<p>If you want to modify the 'publicPath', such as placing static resources in the 'cdn', you can only 'clone' the code of this repository and modify the 'publicPath' configuration of 'web/vue.config.js'. After the code of this repository is updated, you need to pull it again, package it with the modified configuration, and then perform the modification operation of the ' index.html' file earlier. It is recommended to write a 'Node.js' script to complete this task.</p>
</div>
</template>

View File

@ -63,4 +63,128 @@ const router = new VueRouter({
## Docker
编写中。。。
> 非常感谢[水车](https://github.com/shuiche-it),本小节由他编写,对应的 Docker 包也由他维护。
直接从 Docker hup 中安装:
```
docker run -d -p 8081:8080 shuiche/mind-map:latest
```
mind-map在容器中启动了8080端口作为web服务入口通过docker运行容器时需要指定本地映射端口上面案例中我们通过本地的8081端口映射到容器端口8080。
安装完成后,通过 `docker ps` 查看容器运行状态。
浏览器打开 127.0.0.1:8081 即可使用Web 思维导图功能。
## 对接自己的存储服务
应用数据默认存储在浏览器本地,浏览器本地存储容量是比较小的,所以当在思维导图中插入更多图片后很容易触发限制,所以更好的选择是对接你自己的存储服务,这通常有两种方式:
### 第一种
直接clone本仓库代码然后修改`web/src/api/index.js`内的相关方法即可实现从你的数据库里获取数据,以及存储到你的数据中。
### 第二种
很多时候,你可能想始终使用本仓库的最新代码,那么第一种方式就不太方便,因为你要手动去合并代码,所以提供了第二种方式。
具体操作步骤:
1.复制web应用打包后的资源
包括:`dist`目录和`index.html`文件。
2.修改复制后的`index.html`文件
首先在`head`标签里插入如下代码:
```js
<script>
window.takeOverApp = true
</script>
```
这行代码会提示应用不要初始化应用`即new Vue()`,而是把控制权交给你,接下来再在`body`的最后插入你自己的`js`代码,内联或则外链都可以,内联示例如下:
```js
<script>
// 你自己的请求数据的方法
const getDataFromBackend = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
// 思维导图数据
mindMapData: {
root: {
"data": {
"text": "根节点"
},
"children": []
},
theme: { "template":"avocado","config":{} },
layout: "logicalStructure",
config: {},
view: {}
},
// 页面语言支持中文zh、英文en
lang: 'zh',
// 页面部分配置
localConfig: null
})
}, 200)
})
}
// 注册全局方法
const setTakeOverAppMethods = (data) => {
window.takeOverAppMethods = {}
// 获取思维导图数据的函数
window.takeOverAppMethods.getMindMapData = () => {
return data.mindMapData
}
// 保存思维导图数据的函数
window.takeOverAppMethods.saveMindMapData = (data) => {
console.log(data)
// 该函数触发频率可能会很高,所以你应该做一下节流或防抖
}
// 获取语言的函数
window.takeOverAppMethods.getLanguage = () => {
return data.lang
}
// 保存语言的函数
window.takeOverAppMethods.saveLanguage = (lang) => {
console.log(lang)
}
// 获取本地配置的函数
window.takeOverAppMethods.getLocalConfig = () => {
return data.localConfig
}
// 保存本地配置的函数
window.takeOverAppMethods.saveLocalConfig = (config) => {
console.log(config)
}
}
window.onload = async () => {
if (!window.takeOverApp) return
// 请求数据
const data = await getDataFromBackend()
// 设置全局的方法
setTakeOverAppMethods(data)
// 思维导图实例创建完成事件
window.$bus.$on('app_inited', (mindMap) => {
console.log(mindMap)
})
// 可以通过window.$bus.$on()来监听应用的一些事件
// 实例化页面
window.initApp()
}
</script>
```
如上所示,当你设置了`window.takeOverApp = true`标志,应用不再主动进行实例化,而是会将实例化的方法暴露出来由你调用,那么你可以先从后端请求思维导图的数据,然后再注册相关的方法,应用内部会在合适的时机进行调用,从而达到回显和保存的目的。
这样做的好处是,每当本仓库代码更新了,你可以简单的复制打包后的文件到你自己的服务器,只要稍微修改一下`index.html`页面即可达到同步更新且使用自己的存储服务的目的。
当然,目前也有一定限制,因为`Vue CLI`不支持`webpack`的`__webpack_public_path__`变量,所以无法实现运行时设置静态资源路径的需求,默认的`publicPath`为`dist`,所以你应该将`dist`目录和`index.html`文件放在服务器的同一层级。
如果你想修改`publicPath`,比如想把静态资源放到`cdn`,那么你只能`clone`本仓库的代码,然后修改一下`web/vue.config.js`的`publicPath`配置,后续当本仓库的代码更新后,你需要重新拉取,用你修改过的配置进行打包,再进行前面的`index.html`文件的修改操作,推荐写一个`Node.js`脚本来完成该任务。

View File

@ -39,7 +39,107 @@ npm link simple-mind-map
</code></pre>
<p>不过这需要后台支持因为我们的应用是个单页客户端应用如果后台没有正确的配置当用户在浏览器直接访问子路由时会返回404所以呢你要在服务端增加一个覆盖所有情况的候选资源如果<code>URL</code>匹配不到任何静态资源则应该返回同一个<code>index.html</code>页面</p>
<h2>Docker</h2>
<p>编写中</p>
<blockquote>
<p>非常感谢<a href="https://github.com/shuiche-it">水车</a>本小节由他编写对应的 Docker 包也由他维护</p>
</blockquote>
<p>直接从 Docker hup 中安装</p>
<pre class="hljs"><code>docker run -d -p 8081:8080 shuiche/mind-map:latest
</code></pre>
<p>mind-map在容器中启动了8080端口作为web服务入口通过docker运行容器时需要指定本地映射端口上面案例中我们通过本地的8081端口映射到容器端口8080</p>
<p>安装完成后通过 <code>docker ps</code> 查看容器运行状态</p>
<p>浏览器打开 127.0.0.1:8081 即可使用Web 思维导图功能</p>
<h2>对接自己的存储服务</h2>
<p>应用数据默认存储在浏览器本地浏览器本地存储容量是比较小的所以当在思维导图中插入更多图片后很容易触发限制所以更好的选择是对接你自己的存储服务这通常有两种方式</p>
<h3>第一种</h3>
<p>直接clone本仓库代码然后修改<code>web/src/api/index.js</code>内的相关方法即可实现从你的数据库里获取数据以及存储到你的数据中</p>
<h3>第二种</h3>
<p>很多时候你可能想始终使用本仓库的最新代码那么第一种方式就不太方便因为你要手动去合并代码所以提供了第二种方式</p>
<p>具体操作步骤</p>
<p>1.复制web应用打包后的资源</p>
<p>包括<code>dist</code>目录和<code>index.html</code>文件</p>
<p>2.修改复制后的<code>index.html</code>文件</p>
<p>首先在<code>head</code>标签里插入如下代码</p>
<pre class="hljs"><code>&lt;script&gt;
<span class="hljs-built_in">window</span>.takeOverApp = <span class="hljs-literal">true</span>
&lt;/script&gt;
</code></pre>
<p>这行代码会提示应用不要初始化应用<code>new Vue()</code>而是把控制权交给你接下来再在<code>body</code>的最后插入你自己的<code>js</code>代码内联或则外链都可以内联示例如下</p>
<pre class="hljs"><code>&lt;script&gt;
<span class="hljs-comment">// </span>
<span class="hljs-keyword">const</span> getDataFromBackend = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
resolve({
<span class="hljs-comment">// </span>
<span class="hljs-attr">mindMapData</span>: {
<span class="hljs-attr">root</span>: {
<span class="hljs-string">&quot;data&quot;</span>: {
<span class="hljs-string">&quot;text&quot;</span>: <span class="hljs-string">&quot;根节点&quot;</span>
},
<span class="hljs-string">&quot;children&quot;</span>: []
},
<span class="hljs-attr">theme</span>: { <span class="hljs-string">&quot;template&quot;</span>:<span class="hljs-string">&quot;avocado&quot;</span>,<span class="hljs-string">&quot;config&quot;</span>:{} },
<span class="hljs-attr">layout</span>: <span class="hljs-string">&quot;logicalStructure&quot;</span>,
<span class="hljs-attr">config</span>: {},
<span class="hljs-attr">view</span>: {}
},
<span class="hljs-comment">// zhen</span>
<span class="hljs-attr">lang</span>: <span class="hljs-string">&#x27;zh&#x27;</span>,
<span class="hljs-comment">// </span>
<span class="hljs-attr">localConfig</span>: <span class="hljs-literal">null</span>
})
}, <span class="hljs-number">200</span>)
})
}
<span class="hljs-comment">// </span>
<span class="hljs-keyword">const</span> setTakeOverAppMethods = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
<span class="hljs-built_in">window</span>.takeOverAppMethods = {}
<span class="hljs-comment">// </span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.getMindMapData = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> data.mindMapData
}
<span class="hljs-comment">// </span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.saveMindMapData = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
<span class="hljs-built_in">console</span>.log(data)
<span class="hljs-comment">// </span>
}
<span class="hljs-comment">// </span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.getLanguage = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> data.lang
}
<span class="hljs-comment">// </span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.saveLanguage = <span class="hljs-function">(<span class="hljs-params">lang</span>) =&gt;</span> {
<span class="hljs-built_in">console</span>.log(lang)
}
<span class="hljs-comment">// </span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.getLocalConfig = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> data.localConfig
}
<span class="hljs-comment">// </span>
<span class="hljs-built_in">window</span>.takeOverAppMethods.saveLocalConfig = <span class="hljs-function">(<span class="hljs-params">config</span>) =&gt;</span> {
<span class="hljs-built_in">console</span>.log(config)
}
}
<span class="hljs-built_in">window</span>.onload = <span class="hljs-keyword">async</span> () =&gt; {
<span class="hljs-keyword">if</span> (!<span class="hljs-built_in">window</span>.takeOverApp) <span class="hljs-keyword">return</span>
<span class="hljs-comment">// </span>
<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> getDataFromBackend()
<span class="hljs-comment">// </span>
setTakeOverAppMethods(data)
<span class="hljs-comment">// </span>
<span class="hljs-built_in">window</span>.$bus.$on(<span class="hljs-string">&#x27;app_inited&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">mindMap</span>) =&gt;</span> {
<span class="hljs-built_in">console</span>.log(mindMap)
})
<span class="hljs-comment">// window.$bus.$on()</span>
<span class="hljs-comment">// </span>
<span class="hljs-built_in">window</span>.initApp()
}
&lt;/script&gt;
</code></pre>
<p>如上所示当你设置了<code>window.takeOverApp = true</code>标志应用不再主动进行实例化而是会将实例化的方法暴露出来由你调用那么你可以先从后端请求思维导图的数据然后再注册相关的方法应用内部会在合适的时机进行调用从而达到回显和保存的目的</p>
<p>这样做的好处是每当本仓库代码更新了你可以简单的复制打包后的文件到你自己的服务器只要稍微修改一下<code>index.html</code>页面即可达到同步更新且使用自己的存储服务的目的</p>
<p>当然目前也有一定限制因为<code>Vue CLI</code>不支持<code>webpack</code><code>__webpack_public_path__</code>变量所以无法实现运行时设置静态资源路径的需求默认的<code>publicPath</code><code>dist</code>所以你应该将<code>dist</code>目录和<code>index.html</code>文件放在服务器的同一层级</p>
<p>如果你想修改<code>publicPath</code>比如想把静态资源放到<code>cdn</code>那么你只能<code>clone</code>本仓库的代码然后修改一下<code>web/vue.config.js</code><code>publicPath</code>配置后续当本仓库的代码更新后你需要重新拉取用你修改过的配置进行打包再进行前面的<code>index.html</code>文件的修改操作推荐写一个<code>Node.js</code>脚本来完成该任务</p>
</div>
</template>

View File

@ -384,6 +384,10 @@ export default {
//
// this.mindMap.execCommand('REMOVE_NODE', this.mindMap.renderer.root.children[0])
// }, 5000);
//
if (window.takeOverApp) {
this.$bus.$emit('app_inited', this.mindMap)
}
},
/**

View File

@ -108,7 +108,7 @@ export default {
data() {
return {
langList,
lang: getLang(),
lang: '',
isReadonly: false,
openMiniMap: false
}
@ -116,6 +116,9 @@ export default {
computed: {
...mapState(['isDark'])
},
created () {
this.lang = getLang()
},
methods: {
...mapMutations(['setIsDark']),

View File

@ -6,6 +6,10 @@ module.exports = {
outputDir: '../dist',
lintOnSave: false,
productionSourceMap: false,
chainWebpack: config => {
// 移除 prefetch 插件
config.plugins.delete('prefetch')
},
configureWebpack: {
resolve: {
alias: {