mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-23 18:14:10 +08:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b04469649a | ||
|
|
ee57dbdcc5 | ||
|
|
bca744f6fc | ||
|
|
442408dacf | ||
|
|
7297f0a082 | ||
|
|
f0d90941fb | ||
|
|
830962c044 | ||
|
|
eeec71dc65 | ||
|
|
9bd87a22f3 | ||
|
|
88c9f22a15 | ||
|
|
7380fc60d5 | ||
|
|
a178b99d73 | ||
|
|
af9ee04aaf | ||
|
|
c8d23cab40 | ||
|
|
244ced83bc |
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021-2023 The MindMap Team
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
17
README.md
17
README.md
@@ -19,6 +19,12 @@
|
||||
|
||||
在线地址:[https://wanglin2.github.io/mind-map/](https://wanglin2.github.io/mind-map/)
|
||||
|
||||
另外也提供了客户端可供下载使用,支持`Windows`、`Mac`及`Linux`,下载地址:
|
||||
|
||||
Github:[releases](https://github.com/wanglin2/mind-map/releases)。
|
||||
|
||||
百度云盘:[地址](https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3)。
|
||||
|
||||
# 特性
|
||||
|
||||
- [x] 插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小打包体积
|
||||
@@ -84,4 +90,13 @@ MIT
|
||||
|
||||
# 微信交流群
|
||||
|
||||

|
||||
<img src="./qrcode.jpg" style="width: 300px" />
|
||||
|
||||
# 请作者喝杯咖啡
|
||||
|
||||
> 厚椰乳一盒 + 纯牛奶半盒 + 冰块 + 咖啡液 = 生椰拿铁 yyds
|
||||
|
||||
<p>
|
||||
<img src="./web/src/assets/img/alipay.jpg" style="width: 300px" />
|
||||
<img src="./web/src/assets/img/wechat.jpg" style="width: 300px" />
|
||||
</p>
|
||||
File diff suppressed because one or more lines are too long
BIN
qrcode.jpg
BIN
qrcode.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 60 KiB |
File diff suppressed because one or more lines are too long
@@ -1,84 +0,0 @@
|
||||
{
|
||||
"name": "thoughts",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "一个简洁的思维导图",
|
||||
"author": "街角小林<1013335014@qq.com>",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wanglin2/mind-map"
|
||||
},
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build && node ../copy.js",
|
||||
"lint": "vue-cli-service lint",
|
||||
"autoBuildDoc": "node ./scripts/autoBuildDoc.js",
|
||||
"buildDoc": "node ./scripts/buildDoc.js",
|
||||
"electron:build": "vue-cli-service electron:build",
|
||||
"electron:build-all": "vue-cli-service electron:build -p never -mwl",
|
||||
"electron:build-mac": "vue-cli-service electron:build -p never -m",
|
||||
"electron:build-win": "vue-cli-service electron:build -p never -w",
|
||||
"electron:build-linux": "vue-cli-service electron:build -p never -l",
|
||||
"electron:serve": "vue-cli-service electron:serve",
|
||||
"buildLibrary": "vue-cli-service build --target lib --name simpleMindMap ../simple-mind-map/full.js --dest ../simple-mind-map/dist && esbuild ../simple-mind-map/full.js --bundle --external:buffer --format=esm --outfile=../simple-mind-map/dist/simpleMindMap.esm.js",
|
||||
"format": "prettier --write src/* src/*/* src/*/*/* src/*/*/*/*",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"postuninstall": "electron-builder install-app-deps"
|
||||
},
|
||||
"main": "background.js",
|
||||
"dependencies": {
|
||||
"@toast-ui/editor": "^3.1.5",
|
||||
"core-js": "^3.6.5",
|
||||
"electron-json-storage": "^4.6.0",
|
||||
"element-ui": "^2.15.1",
|
||||
"fs-extra": "^7.0.1",
|
||||
"highlight.js": "^10.7.3",
|
||||
"open": "^6.4.0",
|
||||
"uuid": "^3.4.0",
|
||||
"v-viewer": "^1.6.4",
|
||||
"vue": "^2.6.11",
|
||||
"vue-i18n": "^8.27.2",
|
||||
"vue-router": "^3.5.1",
|
||||
"vuex": "^3.6.2",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"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",
|
||||
"chokidar": "^3.5.3",
|
||||
"electron": "^23.1.1",
|
||||
"electron-devtools-installer": "^3.1.0",
|
||||
"esbuild": "^0.17.15",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"less": "^3.12.2",
|
||||
"less-loader": "^7.1.0",
|
||||
"markdown-it": "^13.0.1",
|
||||
"markdown-it-checkbox": "^1.1.0",
|
||||
"prettier": "^1.19.1",
|
||||
"vue-cli-plugin-electron-builder": "~2.1.1",
|
||||
"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"
|
||||
]
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = function(exports) {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // create a fake namespace object
|
||||
/******/ // mode & 1: value is a module id, require it
|
||||
/******/ // mode & 2: merge all properties of value into the ns
|
||||
/******/ // mode & 4: return value when already ns object
|
||||
/******/ // mode & 8|1: behave like require
|
||||
/******/ __webpack_require__.t = function(value, mode) {
|
||||
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||
/******/ if(mode & 8) return value;
|
||||
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||
/******/ var ns = Object.create(null);
|
||||
/******/ __webpack_require__.r(ns);
|
||||
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||
/******/ return ns;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ "./src/electron/preload.js":
|
||||
/*!*********************************!*\
|
||||
!*** ./src/electron/preload.js ***!
|
||||
\*********************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
eval("const { contextBridge, ipcRenderer } = __webpack_require__(/*! electron */ \"electron\")\r\n\r\ncontextBridge.exposeInMainWorld('platform', process.platform)\r\ncontextBridge.exposeInMainWorld('IS_ELECTRON', true)\r\n\r\ncontextBridge.exposeInMainWorld('electronAPI', {\r\n minimize: () => ipcRenderer.send('minimize'),\r\n maximize: () => ipcRenderer.send('maximize'),\r\n unmaximize: () => ipcRenderer.send('unmaximize'),\r\n close: () => ipcRenderer.send('close'),\r\n destroy: () => ipcRenderer.send('destroy'),\r\n create: id => ipcRenderer.send('create', id),\r\n getFileContent: id => ipcRenderer.invoke('getFileContent', id),\r\n save: (id, data, fileName) => ipcRenderer.invoke('save', id, data, fileName),\r\n rename: (id, name) => ipcRenderer.invoke('rename', id, name),\r\n openUrl: url => ipcRenderer.send('openUrl', url),\r\n addRecentFileList: (fileList) => ipcRenderer.invoke('addRecentFileList', fileList),\r\n getRecentFileList: () => ipcRenderer.invoke('getRecentFileList'),\r\n clearRecentFileList: () => ipcRenderer.invoke('clearRecentFileList'),\r\n openFileInDir: file => ipcRenderer.send('openFileInDir', file),\r\n deleteFile: file => ipcRenderer.invoke('deleteFile', file),\r\n onRefreshRecentFileList: callback =>\r\n ipcRenderer.on('refreshRecentFileList', callback),\r\n openFile: file => ipcRenderer.send('openFile', file),\r\n selectOpenFile: () => ipcRenderer.send('selectOpenFile'),\r\n copyFile: file => ipcRenderer.invoke('copyFile', file)\r\n})\r\n\n\n//# sourceURL=webpack:///./src/electron/preload.js?");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 0:
|
||||
/*!***************************************!*\
|
||||
!*** multi ./src/electron/preload.js ***!
|
||||
\***************************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
eval("module.exports = __webpack_require__(/*! E:\\wanglin\\mind-map\\web\\src\\electron\\preload.js */\"./src/electron/preload.js\");\n\n\n//# sourceURL=webpack:///multi_./src/electron/preload.js?");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "electron":
|
||||
/*!***************************!*\
|
||||
!*** external "electron" ***!
|
||||
\***************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
eval("module.exports = require(\"electron\");\n\n//# sourceURL=webpack:///external_%22electron%22?");
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
17569
web/package-lock.json
generated
17569
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,39 +2,20 @@
|
||||
"name": "thoughts",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "一个简洁的思维导图",
|
||||
"author": "街角小林<1013335014@qq.com>",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wanglin2/mind-map"
|
||||
},
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build && node ../copy.js",
|
||||
"lint": "vue-cli-service lint",
|
||||
"autoBuildDoc": "node ./scripts/autoBuildDoc.js",
|
||||
"buildDoc": "node ./scripts/buildDoc.js",
|
||||
"electron:build": "vue-cli-service electron:build",
|
||||
"electron:build-all": "vue-cli-service electron:build -p never -mwl",
|
||||
"electron:build-mac": "vue-cli-service electron:build -p never -m",
|
||||
"electron:build-win": "vue-cli-service electron:build -p never -w",
|
||||
"electron:build-linux": "vue-cli-service electron:build -p never -l",
|
||||
"electron:serve": "vue-cli-service electron:serve",
|
||||
"buildLibrary": "vue-cli-service build --target lib --name simpleMindMap ../simple-mind-map/full.js --dest ../simple-mind-map/dist && esbuild ../simple-mind-map/full.js --bundle --external:buffer --format=esm --outfile=../simple-mind-map/dist/simpleMindMap.esm.js",
|
||||
"format": "prettier --write src/* src/*/* src/*/*/* src/*/*/*/*",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"postuninstall": "electron-builder install-app-deps"
|
||||
"buildDoc": "node ./scripts/buildDoc.js",
|
||||
"autoBuildDoc": "node ./scripts/autoBuildDoc.js"
|
||||
},
|
||||
"main": "background.js",
|
||||
"dependencies": {
|
||||
"@toast-ui/editor": "^3.1.5",
|
||||
"core-js": "^3.6.5",
|
||||
"electron-json-storage": "^4.6.0",
|
||||
"element-ui": "^2.15.1",
|
||||
"fs-extra": "^7.0.1",
|
||||
"highlight.js": "^10.7.3",
|
||||
"open": "^6.4.0",
|
||||
"uuid": "^3.4.0",
|
||||
"v-viewer": "^1.6.4",
|
||||
"vue": "^2.6.11",
|
||||
"vue-i18n": "^8.27.2",
|
||||
@@ -48,8 +29,6 @@
|
||||
"@vue/cli-service": "^4.5.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"electron": "^23.1.1",
|
||||
"electron-devtools-installer": "^3.1.0",
|
||||
"esbuild": "^0.17.15",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
@@ -58,7 +37,6 @@
|
||||
"markdown-it": "^13.0.1",
|
||||
"markdown-it-checkbox": "^1.1.0",
|
||||
"prettier": "^1.19.1",
|
||||
"vue-cli-plugin-electron-builder": "~2.1.1",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack": "^4.44.2"
|
||||
},
|
||||
|
||||
BIN
web/src/.DS_Store
vendored
BIN
web/src/.DS_Store
vendored
Binary file not shown.
@@ -34,17 +34,7 @@ export const getData = () => {
|
||||
return simpleDeepClone(exampleData)
|
||||
} else {
|
||||
try {
|
||||
let parsedData = JSON.parse(store)
|
||||
if (window.IS_ELECTRON) {
|
||||
return simpleDeepClone(exampleData)
|
||||
let { root, ...rest } = parsedData
|
||||
return {
|
||||
...rest,
|
||||
root: simpleDeepClone(exampleData).root
|
||||
}
|
||||
} else {
|
||||
return parsedData
|
||||
}
|
||||
return JSON.parse(store)
|
||||
} catch (error) {
|
||||
return simpleDeepClone(exampleData)
|
||||
}
|
||||
|
||||
BIN
web/src/assets/.DS_Store
vendored
BIN
web/src/assets/.DS_Store
vendored
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 60 KiB |
@@ -1,114 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
import { app, protocol, BrowserWindow } from 'electron'
|
||||
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
|
||||
import path from 'path'
|
||||
import { bindFileHandleEvent } from './electron/fileHandle'
|
||||
import { bindOtherHandleEvent } from './electron/otherHandle'
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
// 在应用程序准备就绪之前,必须注册方案
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{ scheme: 'app', privileges: { secure: true, standard: true } }
|
||||
])
|
||||
|
||||
// 创建主页面
|
||||
let mainWindow = null
|
||||
async function createMainWindow() {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
frame: false,
|
||||
titleBarStyle: 'hiddenInset',
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
nodeIntegration: true,
|
||||
enableRemoteModule: true,
|
||||
contextIsolation: true,
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||
// 如果处于开发模式,则加载开发服务器的url
|
||||
await mainWindow.loadURL(
|
||||
process.env.WEBPACK_DEV_SERVER_URL + '/#/workbenche'
|
||||
)
|
||||
// if (!process.env.IS_TEST) mainWindow.webContents.openDevTools()
|
||||
} else {
|
||||
createProtocol('app')
|
||||
// 非开发环境时加载index.html
|
||||
mainWindow.loadURL('app://./index.html/#/workbenche')
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定事件
|
||||
const bindEvent = () => {
|
||||
bindFileHandleEvent({ mainWindow, initOpenFileQueue })
|
||||
bindOtherHandleEvent()
|
||||
}
|
||||
|
||||
// 关闭所有窗口后退出
|
||||
app.on('window-all-closed', () => {
|
||||
// 在macOS上,应用程序及其菜单栏通常保持活动状态,直到用户使用Cmd+Q明确退出
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
// 在macOS上,当点击dock图标且没有其他窗口打开时,通常会在应用程序中重新创建一个窗口。
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createMainWindow()
|
||||
// bindEvent()
|
||||
}
|
||||
})
|
||||
|
||||
// Attempt to bind file opening #2
|
||||
// https://stackoverflow.com/questions/62420427/how-do-i-make-my-electron-app-the-default-for-opening-files
|
||||
// https://github.com/rchrd2/example-electron-file-association
|
||||
// https://www.jianshu.com/p/a32542277b83
|
||||
const initOpenFileQueue = []
|
||||
app.on('will-finish-launching', () => {
|
||||
// Event fired When someone drags files onto the icon while your app is running
|
||||
if (process.platform == 'win32') {
|
||||
const argv = process.argv
|
||||
if (argv) {
|
||||
argv.forEach(filePath => {
|
||||
if (filePath.indexOf('.smm') >= 0) {
|
||||
initOpenFileQueue.push(filePath)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
app.on('open-file', (event, file) => {
|
||||
if (app.isReady() === false) {
|
||||
initOpenFileQueue.push(file)
|
||||
} else {
|
||||
console.log(file)
|
||||
}
|
||||
event.preventDefault()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
app.on('ready', async () => {
|
||||
createMainWindow()
|
||||
bindEvent()
|
||||
})
|
||||
|
||||
// 在开发模式下,应父进程的请求干净地退出。
|
||||
if (isDevelopment) {
|
||||
if (process.platform === 'win32') {
|
||||
process.on('message', data => {
|
||||
if (data === 'graceful-exit') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
process.on('SIGTERM', () => {
|
||||
app.quit()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.noDrag {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
import { BrowserWindow, ipcMain, dialog, shell } from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import {
|
||||
saveToRecent,
|
||||
clearRecent,
|
||||
removeFileInRecent,
|
||||
replaceFileInRecent,
|
||||
getRecent,
|
||||
saveFileListToRecent
|
||||
} from './storage'
|
||||
import { v4 as uuid } from 'uuid'
|
||||
|
||||
export const bindFileHandleEvent = ({ mainWindow, initOpenFileQueue }) => {
|
||||
// 通知主页面刷新最近文件列表
|
||||
const notifyMainWindowRefreshRecentFileList = () => {
|
||||
mainWindow.webContents.send('refreshRecentFileList')
|
||||
}
|
||||
|
||||
// 新建编辑页面
|
||||
const openIds = []
|
||||
const createEditWindow = async (event, id) => {
|
||||
openIds.push(id)
|
||||
const win = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
frame: false,
|
||||
titleBarStyle: 'hiddenInset',
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
nodeIntegration: true,
|
||||
enableRemoteModule: true,
|
||||
contextIsolation: true,
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
win.on('closed', () => {
|
||||
// 从openIds数组中删除
|
||||
let index = openIds.find(item => {
|
||||
return item === id
|
||||
})
|
||||
if (index !== -1) {
|
||||
openIds.splice(index, 1)
|
||||
}
|
||||
// 从idToFilePath中删除
|
||||
delete idToFilePath[id]
|
||||
})
|
||||
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||
// Load the url of the dev server if in development mode
|
||||
win.loadURL(
|
||||
process.env.WEBPACK_DEV_SERVER_URL + '/#/workbenche/edit/' + id
|
||||
)
|
||||
// if (!process.env.IS_TEST) win.webContents.openDevTools()
|
||||
} else {
|
||||
// Load the index.html when not in development
|
||||
win.loadURL('app://./index.html/#/workbenche/edit/' + id)
|
||||
}
|
||||
}
|
||||
ipcMain.on('create', createEditWindow)
|
||||
|
||||
// 保存文件
|
||||
const idToFilePath = {}
|
||||
ipcMain.handle('save', async (event, id, data, fileName = '未命名') => {
|
||||
if (!idToFilePath[id]) {
|
||||
const webContents = event.sender
|
||||
const win = BrowserWindow.fromWebContents(webContents)
|
||||
const res = dialog.showSaveDialogSync(win, {
|
||||
title: '保存',
|
||||
defaultPath: fileName + '.smm',
|
||||
filters: [{ name: '思维导图', extensions: ['smm'] }]
|
||||
})
|
||||
if (res) {
|
||||
idToFilePath[id] = res
|
||||
fs.writeFile(res, data)
|
||||
saveToRecent(res).then(() => {
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
})
|
||||
return path.parse(idToFilePath[id]).name
|
||||
}
|
||||
} else {
|
||||
fs.writeFile(idToFilePath[id], data)
|
||||
}
|
||||
})
|
||||
|
||||
// 打开文件
|
||||
const openFile = (event, file) => {
|
||||
let id = uuid()
|
||||
idToFilePath[id] = file
|
||||
saveToRecent(file).then(() => {
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
})
|
||||
createEditWindow(null, id)
|
||||
}
|
||||
ipcMain.on('openFile', openFile)
|
||||
|
||||
// 选择打开本地文件
|
||||
ipcMain.on('selectOpenFile', event => {
|
||||
const res = dialog.showOpenDialogSync({
|
||||
title: '选择',
|
||||
filters: [{ name: '思维导图', extensions: ['smm'] }]
|
||||
})
|
||||
if (res && res[0]) {
|
||||
openFile(null, res[0])
|
||||
}
|
||||
})
|
||||
|
||||
// 获取文件内容
|
||||
ipcMain.handle('getFileContent', (event, id) => {
|
||||
return new Promise(resolve => {
|
||||
let file = idToFilePath[id]
|
||||
if (!file) {
|
||||
resolve(null)
|
||||
return
|
||||
}
|
||||
fs.readFile(file, { encoding: 'utf-8' }, (err, data) => {
|
||||
resolve({
|
||||
name: path.parse(file).name,
|
||||
content: JSON.parse(data)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// 重命名文件
|
||||
ipcMain.handle('rename', (event, id, name) => {
|
||||
return new Promise(resolve => {
|
||||
if (!idToFilePath[id]) {
|
||||
resolve('文件不存在')
|
||||
return
|
||||
}
|
||||
let oldPath = idToFilePath[id]
|
||||
let { base, ...oldPathData } = path.parse(oldPath)
|
||||
oldPathData.name = name
|
||||
let newPath = path.format(oldPathData)
|
||||
idToFilePath[id] = newPath
|
||||
fs.rename(oldPath, newPath, err => {
|
||||
if (err) {
|
||||
resolve('重命名失败')
|
||||
} else {
|
||||
replaceFileInRecent(oldPath, newPath).then(() => {
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// 获取最近文件列表
|
||||
ipcMain.handle('getRecentFileList', () => {
|
||||
return getRecent().map(item => {
|
||||
let data = path.parse(item)
|
||||
return {
|
||||
url: item,
|
||||
dir: data.dir,
|
||||
name: data.name
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 清空最近文件列表
|
||||
ipcMain.handle('clearRecentFileList', async () => {
|
||||
try {
|
||||
clearRecent()
|
||||
return ''
|
||||
} catch (error) {
|
||||
return '清空失败'
|
||||
}
|
||||
})
|
||||
|
||||
// 添加到最近文件列表
|
||||
ipcMain.handle('addRecentFileList', async (event, fileList) => {
|
||||
try {
|
||||
console.log(fileList);
|
||||
await saveFileListToRecent(fileList)
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
} catch (error) {
|
||||
return error
|
||||
}
|
||||
})
|
||||
|
||||
// 打开指定目录
|
||||
ipcMain.on('openFileInDir', (event, file) => {
|
||||
shell.showItemInFolder(file)
|
||||
})
|
||||
|
||||
// 删除指定文件
|
||||
ipcMain.handle('deleteFile', (event, file) => {
|
||||
let res = ''
|
||||
let id = Object.keys(idToFilePath).find(item => {
|
||||
return idToFilePath[item] === file
|
||||
})
|
||||
let index = -1
|
||||
if (id) {
|
||||
index = openIds.findIndex(item => {
|
||||
return item === id
|
||||
})
|
||||
}
|
||||
if (index === -1) {
|
||||
try {
|
||||
fs.rmSync(file)
|
||||
} catch (error) {}
|
||||
removeFileInRecent(file)
|
||||
} else {
|
||||
res = '该文件正在编辑,请关闭后再试'
|
||||
}
|
||||
return res
|
||||
})
|
||||
|
||||
// 复制文件
|
||||
ipcMain.handle('copyFile', async (event, file) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.pathExists(file, (err, exists) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
if (exists) {
|
||||
let { base, ...oldPathData } = path.parse(file)
|
||||
let newName = oldPathData.name + '-复制'
|
||||
let index = 1
|
||||
oldPathData.name = newName
|
||||
let newPath = path.format(oldPathData)
|
||||
// 检查新路径是否已存在
|
||||
while (fs.pathExistsSync(newPath)) {
|
||||
oldPathData.name = newName + index
|
||||
newPath = path.format(oldPathData)
|
||||
index++
|
||||
}
|
||||
fs.copy(file, newPath, err => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
saveToRecent(newPath).then(() => {
|
||||
notifyMainWindowRefreshRecentFileList()
|
||||
})
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
reject('文件不存在')
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// 直接双击文件打开应用时,需要直接打开该文件编辑
|
||||
initOpenFileQueue.forEach((file) => {
|
||||
openFile(null, file)
|
||||
})
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { BrowserWindow, ipcMain } from 'electron'
|
||||
import open from 'open'
|
||||
|
||||
export const bindOtherHandleEvent = () => {
|
||||
// 处理缩放事件
|
||||
;['minimize', 'maximize', 'unmaximize', 'close', 'destroy'].forEach(item => {
|
||||
ipcMain.on(item, event => {
|
||||
const webContents = event.sender
|
||||
const win = BrowserWindow.fromWebContents(webContents)
|
||||
win[item]()
|
||||
})
|
||||
})
|
||||
|
||||
// 使用默认浏览器打开指定url
|
||||
ipcMain.on('openUrl', (event, url) => {
|
||||
open(url)
|
||||
})
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('platform', process.platform)
|
||||
contextBridge.exposeInMainWorld('IS_ELECTRON', true)
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
minimize: () => ipcRenderer.send('minimize'),
|
||||
maximize: () => ipcRenderer.send('maximize'),
|
||||
unmaximize: () => ipcRenderer.send('unmaximize'),
|
||||
close: () => ipcRenderer.send('close'),
|
||||
destroy: () => ipcRenderer.send('destroy'),
|
||||
create: id => ipcRenderer.send('create', id),
|
||||
getFileContent: id => ipcRenderer.invoke('getFileContent', id),
|
||||
save: (id, data, fileName) => ipcRenderer.invoke('save', id, data, fileName),
|
||||
rename: (id, name) => ipcRenderer.invoke('rename', id, name),
|
||||
openUrl: url => ipcRenderer.send('openUrl', url),
|
||||
addRecentFileList: (fileList) => ipcRenderer.invoke('addRecentFileList', fileList),
|
||||
getRecentFileList: () => ipcRenderer.invoke('getRecentFileList'),
|
||||
clearRecentFileList: () => ipcRenderer.invoke('clearRecentFileList'),
|
||||
openFileInDir: file => ipcRenderer.send('openFileInDir', file),
|
||||
deleteFile: file => ipcRenderer.invoke('deleteFile', file),
|
||||
onRefreshRecentFileList: callback =>
|
||||
ipcRenderer.on('refreshRecentFileList', callback),
|
||||
openFile: file => ipcRenderer.send('openFile', file),
|
||||
selectOpenFile: () => ipcRenderer.send('selectOpenFile'),
|
||||
copyFile: file => ipcRenderer.invoke('copyFile', file)
|
||||
})
|
||||
@@ -1,109 +0,0 @@
|
||||
import storage from 'electron-json-storage'
|
||||
|
||||
export const RECENT_FILE_LIST = 'recentFileList'
|
||||
|
||||
// 保存到最近文件
|
||||
export const saveToRecent = file => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let list = getRecent()
|
||||
let index = list.findIndex(item => {
|
||||
return item === file
|
||||
})
|
||||
if (index !== -1) {
|
||||
list.splice(index, 1)
|
||||
}
|
||||
list.push(file)
|
||||
storage.set(RECENT_FILE_LIST, list, err => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 保存到最近文件
|
||||
export const saveFileListToRecent = fileList => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let list = getRecent()
|
||||
fileList.forEach(file => {
|
||||
let index = list.findIndex(item => {
|
||||
return item === file
|
||||
})
|
||||
if (index !== -1) {
|
||||
list.splice(index, 1)
|
||||
}
|
||||
list.push(file)
|
||||
})
|
||||
storage.set(RECENT_FILE_LIST, list, err => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 获取最近文件列表
|
||||
export const getRecent = () => {
|
||||
let res = storage.getSync(RECENT_FILE_LIST)
|
||||
return (Array.isArray(res) ? res : []).filter(item => {
|
||||
return !!item
|
||||
})
|
||||
}
|
||||
|
||||
// 清除最近文件列表
|
||||
export const clearRecent = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
storage.remove(RECENT_FILE_LIST, err => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 从最近文件列表中移除指定文件
|
||||
export const removeFileInRecent = file => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let list = getRecent()
|
||||
let index = list.findIndex(item => {
|
||||
return item === file
|
||||
})
|
||||
if (index !== -1) {
|
||||
list.splice(index, 1)
|
||||
}
|
||||
storage.set(RECENT_FILE_LIST, list, err => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 替换指定文件
|
||||
export const replaceFileInRecent = (oldFile, newFile) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let list = getRecent()
|
||||
let index = list.findIndex(item => {
|
||||
return item === oldFile
|
||||
})
|
||||
if (index !== -1) {
|
||||
list.splice(index, 1)
|
||||
}
|
||||
list.push(newFile)
|
||||
storage.set(RECENT_FILE_LIST, list, err => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -8,21 +8,11 @@ import '@/assets/icon-font/iconfont.css'
|
||||
import 'viewerjs/dist/viewer.css'
|
||||
import VueViewer from 'v-viewer'
|
||||
import i18n from './i18n'
|
||||
import './css/global.css'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.prototype.$bus = new Vue()
|
||||
Vue.use(ElementUI)
|
||||
Vue.use(VueViewer)
|
||||
Vue.mixin({
|
||||
data () {
|
||||
return {
|
||||
IS_ELECTRON: window.IS_ELECTRON,
|
||||
IS_MAC: window.platform === 'darwin',
|
||||
IS_WIN: window.platform === 'win32'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
new Vue({
|
||||
render: h => h(App),
|
||||
|
||||
@@ -10,7 +10,7 @@ let langList = [
|
||||
path: 'en'
|
||||
}
|
||||
]
|
||||
let StartList = ['introduction', 'start', 'deploy', 'translate', 'changelog']
|
||||
let StartList = ['introduction', 'start', 'deploy', 'client', 'translate', 'changelog']
|
||||
let CourseList = new Array(19).fill(0).map((_, index) => {
|
||||
return 'course' + (index + 1)
|
||||
})
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
`simple-mind-map` is a simple and powerful web mind map library, not dependent on any specific framework. Can help you quickly develop mind mapping products.
|
||||
|
||||
> If you just want to use mind mapping, you can also use the demo of this project as a regular online mind mapping tool. Click on the 【Online Demo】 in the upper right corner to start using it.
|
||||
>
|
||||
> Additionally, a client is provided for download, support `Windows`、`Mac` and `Linux`, [Click here to learn more](/mind-map/#/doc/zh/client)。
|
||||
|
||||
## Features
|
||||
|
||||
|
||||
@@ -4,24 +4,25 @@
|
||||
<p><code>simple-mind-map</code> is a simple and powerful web mind map library, not dependent on any specific framework. Can help you quickly develop mind mapping products.</p>
|
||||
<blockquote>
|
||||
<p>If you just want to use mind mapping, you can also use the demo of this project as a regular online mind mapping tool. Click on the 【Online Demo】 in the upper right corner to start using it.</p>
|
||||
<p>Additionally, a client is provided for download, support <code>Windows</code>、<code>Mac</code> and <code>Linux</code>, <a href="/mind-map/#/doc/zh/client">Click here to learn more</a>。</p>
|
||||
</blockquote>
|
||||
<h2>Features</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox216" checked="true" /><label for="checkbox216">Plugin architecture. In addition to core functions, other functions are provided as plugins, which can be used as needed to reduce the overall volume</label></li>
|
||||
<li><input type="checkbox" id="checkbox217" checked="true" /><label for="checkbox217">Supports six types of structures: logical structure diagrams, mind maps,</label>
|
||||
<li><input type="checkbox" id="checkbox90" checked="true" /><label for="checkbox90">Plugin architecture. In addition to core functions, other functions are provided as plugins, which can be used as needed to reduce the overall volume</label></li>
|
||||
<li><input type="checkbox" id="checkbox91" checked="true" /><label for="checkbox91">Supports six types of structures: logical structure diagrams, mind maps,</label>
|
||||
organizational structure diagrams, directory organization diagrams, timeline, and fishbone diagrams</li>
|
||||
<li><input type="checkbox" id="checkbox218" checked="true" /><label for="checkbox218">Built-in multiple themes and allows for highly customized styles, and support register new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox219" checked="true" /><label for="checkbox219">Supports shortcuts</label></li>
|
||||
<li><input type="checkbox" id="checkbox220" checked="true" /><label for="checkbox220">Node content supports images, icons, hyperlinks, notes, tags, and</label>
|
||||
<li><input type="checkbox" id="checkbox92" checked="true" /><label for="checkbox92">Built-in multiple themes and allows for highly customized styles, and support register new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox93" checked="true" /><label for="checkbox93">Supports shortcuts</label></li>
|
||||
<li><input type="checkbox" id="checkbox94" checked="true" /><label for="checkbox94">Node content supports images, icons, hyperlinks, notes, tags, and</label>
|
||||
summaries</li>
|
||||
<li><input type="checkbox" id="checkbox221" checked="true" /><label for="checkbox221">Supports forward and backward navigation</label></li>
|
||||
<li><input type="checkbox" id="checkbox222" checked="true" /><label for="checkbox222">Supports dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox223" checked="true" /><label for="checkbox223">Supports right-click and Ctrl + left-click to select multiple items</label></li>
|
||||
<li><input type="checkbox" id="checkbox224" checked="true" /><label for="checkbox224">Supports free dragging and dragging to adjust nodes</label></li>
|
||||
<li><input type="checkbox" id="checkbox225" checked="true" /><label for="checkbox225">Supports various node shapes</label></li>
|
||||
<li><input type="checkbox" id="checkbox226" checked="true" /><label for="checkbox226">Supports export to json, png, svg, pdf markdown, and import from json, xmind, markdown</label></li>
|
||||
<li><input type="checkbox" id="checkbox227" checked="true" /><label for="checkbox227">Supports mini map、support watermark</label></li>
|
||||
<li><input type="checkbox" id="checkbox228" checked="true" /><label for="checkbox228">Supports associative lines</label></li>
|
||||
<li><input type="checkbox" id="checkbox95" checked="true" /><label for="checkbox95">Supports forward and backward navigation</label></li>
|
||||
<li><input type="checkbox" id="checkbox96" checked="true" /><label for="checkbox96">Supports dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox97" checked="true" /><label for="checkbox97">Supports right-click and Ctrl + left-click to select multiple items</label></li>
|
||||
<li><input type="checkbox" id="checkbox98" checked="true" /><label for="checkbox98">Supports free dragging and dragging to adjust nodes</label></li>
|
||||
<li><input type="checkbox" id="checkbox99" checked="true" /><label for="checkbox99">Supports various node shapes</label></li>
|
||||
<li><input type="checkbox" id="checkbox100" checked="true" /><label for="checkbox100">Supports export to json, png, svg, pdf markdown, and import from json, xmind, markdown</label></li>
|
||||
<li><input type="checkbox" id="checkbox101" checked="true" /><label for="checkbox101">Supports mini map、support watermark</label></li>
|
||||
<li><input type="checkbox" id="checkbox102" checked="true" /><label for="checkbox102">Supports associative lines</label></li>
|
||||
</ul>
|
||||
<h2>Repository Catalog Introduction</h2>
|
||||
<p>1.<code>simple-mind-map</code></p>
|
||||
@@ -31,16 +32,16 @@ frameworks such as Vue and React, or without a framework.</p>
|
||||
<p>This is an online mind map built using the <code>simple-mind-map</code> library and based
|
||||
on <code>Vue2.x</code> and <code>ElementUI</code>. Features include:</p>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox229" checked="true" /><label for="checkbox229">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
<li><input type="checkbox" id="checkbox103" checked="true" /><label for="checkbox103">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
images, icons, hyperlinks, notes, tags, and summaries</li>
|
||||
<li><input type="checkbox" id="checkbox230" checked="true" /><label for="checkbox230">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
<li><input type="checkbox" id="checkbox104" checked="true" /><label for="checkbox104">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
outline, theme selection, and structure selection</li>
|
||||
<li><input type="checkbox" id="checkbox231" checked="true" /><label for="checkbox231">Import and export functionality; data is saved in the browser's local</label>
|
||||
<li><input type="checkbox" id="checkbox105" checked="true" /><label for="checkbox105">Import and export functionality; data is saved in the browser's local</label>
|
||||
storage by default, but it also supports creating, opening, and editing
|
||||
local files on the computer directly</li>
|
||||
<li><input type="checkbox" id="checkbox232" checked="true" /><label for="checkbox232">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
<li><input type="checkbox" id="checkbox106" checked="true" /><label for="checkbox106">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
and organizing layout</li>
|
||||
<li><input type="checkbox" id="checkbox233" checked="true" /><label for="checkbox233">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
<li><input type="checkbox" id="checkbox107" checked="true" /><label for="checkbox107">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
between edit and read-only modes, zooming in and out, and switching to
|
||||
full screen, support mini map</li>
|
||||
</ul>
|
||||
|
||||
@@ -91,6 +91,7 @@ If you only use library, you don't need to read this section.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/wanglin2/mind-map.git
|
||||
cd mind-map
|
||||
cd simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
|
||||
@@ -64,6 +64,7 @@ compile this dependency:</p>
|
||||
<p>If you only use library, you don't need to read this section.</p>
|
||||
<h3>Local Development</h3>
|
||||
<pre class="hljs"><code>git <span class="hljs-built_in">clone</span> https://github.com/wanglin2/mind-map.git
|
||||
<span class="hljs-built_in">cd</span> mind-map
|
||||
<span class="hljs-built_in">cd</span> simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
|
||||
@@ -43,7 +43,8 @@ export default [
|
||||
{ path: 'view', title: 'View实例' },
|
||||
{ path: 'watermark', title: 'Watermark插件' },
|
||||
{ path: 'xmind', title: 'XMind解析' },
|
||||
{ path: 'deploy', title: '部署' }
|
||||
{ path: 'deploy', title: '部署' },
|
||||
{ path: 'client', title: '客户端' }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
80
web/src/pages/Doc/zh/client/index.md
Normal file
80
web/src/pages/Doc/zh/client/index.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# 客户端
|
||||
|
||||
本项目也提供了客户端版本,使用[Electron](https://www.electronjs.org/)开发。支持`Windows`、`Mac`及`Linux`。
|
||||
|
||||
目前功能比较简单:
|
||||
|
||||
1.支持新建、打开文件进行编辑;
|
||||
|
||||
2.支持查看最近编辑文件列表;
|
||||
|
||||
3.支持文件的复制、删除、重命名;
|
||||
|
||||
## 下载
|
||||
|
||||
你可以直接下载对应的客户端安装使用,提供了两个下载地址:
|
||||
|
||||
Github:[releases](https://github.com/wanglin2/mind-map/releases)。
|
||||
|
||||
百度云盘:[地址](https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3)。
|
||||
|
||||
## 开发
|
||||
|
||||
如果有需要,你也可以进行二次开发。
|
||||
|
||||
### clone
|
||||
|
||||
```bash
|
||||
git clone https://github.com/wanglin2/mind-map.git
|
||||
cd mind-map
|
||||
git checkout electron
|
||||
```
|
||||
|
||||
### 启动服务
|
||||
|
||||
在项目根目录下执行:
|
||||
|
||||
```bash
|
||||
cd simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
cd ..
|
||||
cd web
|
||||
npm i
|
||||
npm link simple-mind-map
|
||||
npm run electron:serve
|
||||
```
|
||||
|
||||
### 打包客户端
|
||||
|
||||
你至少需要两台电脑,一台`Windows`和一台`Mac`。
|
||||
|
||||
打包`Windows`应用:
|
||||
|
||||
```bash
|
||||
npm run electron:build-win
|
||||
```
|
||||
|
||||
打包`Mac`应用:
|
||||
|
||||
```bash
|
||||
npm run electron:build-mac
|
||||
```
|
||||
|
||||
打包`Linux`应用:
|
||||
|
||||
```bash
|
||||
npm run electron:build-linux
|
||||
```
|
||||
|
||||
打包全部应用:
|
||||
|
||||
```bash
|
||||
npm run electron:build-all
|
||||
```
|
||||
|
||||
根据你的电脑系统自动打包:
|
||||
|
||||
```bash
|
||||
npm run electron:build
|
||||
```
|
||||
60
web/src/pages/Doc/zh/client/index.vue
Normal file
60
web/src/pages/Doc/zh/client/index.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>客户端</h1>
|
||||
<p>本项目也提供了客户端版本,使用<a href="https://www.electronjs.org/">Electron</a>开发。支持<code>Windows</code>、<code>Mac</code>及<code>Linux</code>。</p>
|
||||
<p>目前功能比较简单:</p>
|
||||
<p>1.支持新建、打开文件进行编辑;</p>
|
||||
<p>2.支持查看最近编辑文件列表;</p>
|
||||
<p>3.支持文件的复制、删除、重命名;</p>
|
||||
<h2>下载</h2>
|
||||
<p>你可以直接下载对应的客户端安装使用,提供了两个下载地址:</p>
|
||||
<p>Github:<a href="https://github.com/wanglin2/mind-map/releases">releases</a>。</p>
|
||||
<p>百度云盘:<a href="https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3">地址</a>。</p>
|
||||
<h2>开发</h2>
|
||||
<p>如果有需要,你也可以进行二次开发。</p>
|
||||
<h3>clone</h3>
|
||||
<pre class="hljs"><code>git <span class="hljs-built_in">clone</span> https://github.com/wanglin2/mind-map.git
|
||||
<span class="hljs-built_in">cd</span> mind-map
|
||||
git checkout electron
|
||||
</code></pre>
|
||||
<h3>启动服务</h3>
|
||||
<p>在项目根目录下执行:</p>
|
||||
<pre class="hljs"><code><span class="hljs-built_in">cd</span> simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
<span class="hljs-built_in">cd</span> ..
|
||||
<span class="hljs-built_in">cd</span> web
|
||||
npm i
|
||||
npm link simple-mind-map
|
||||
npm run electron:serve
|
||||
</code></pre>
|
||||
<h3>打包客户端</h3>
|
||||
<p>你至少需要两台电脑,一台<code>Windows</code>和一台<code>Mac</code>。</p>
|
||||
<p>打包<code>Windows</code>应用:</p>
|
||||
<pre class="hljs"><code>npm run electron:build-win
|
||||
</code></pre>
|
||||
<p>打包<code>Mac</code>应用:</p>
|
||||
<pre class="hljs"><code>npm run electron:build-mac
|
||||
</code></pre>
|
||||
<p>打包<code>Linux</code>应用:</p>
|
||||
<pre class="hljs"><code>npm run electron:build-linux
|
||||
</code></pre>
|
||||
<p>打包全部应用:</p>
|
||||
<pre class="hljs"><code>npm run electron:build-all
|
||||
</code></pre>
|
||||
<p>根据你的电脑系统自动打包:</p>
|
||||
<pre class="hljs"><code>npm run electron:build
|
||||
</code></pre>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -3,6 +3,8 @@
|
||||
`simple-mind-map`是一个简单&强大的Web思维导图库,不依赖任何特定框架。可以帮助你快速开发思维导图产品。
|
||||
|
||||
> 如果你只是想使用思维导图,你也完全可以把本项目的demo作为一个普通的在线思维导图工具使用。点击右上角的【在线示例】开始使用吧。
|
||||
>
|
||||
> 另外也提供了客户端可供下载,支持`Windows`、`Mac`及`Linux`,[点此了解更多](/mind-map/#/doc/zh/client)。
|
||||
|
||||
## 特性
|
||||
|
||||
|
||||
@@ -4,22 +4,23 @@
|
||||
<p><code>simple-mind-map</code>是一个简单&强大的Web思维导图库,不依赖任何特定框架。可以帮助你快速开发思维导图产品。</p>
|
||||
<blockquote>
|
||||
<p>如果你只是想使用思维导图,你也完全可以把本项目的demo作为一个普通的在线思维导图工具使用。点击右上角的【在线示例】开始使用吧。</p>
|
||||
<p>另外也提供了客户端可供下载,支持<code>Windows</code>、<code>Mac</code>及<code>Linux</code>,<a href="/mind-map/#/doc/zh/client">点此了解更多</a>。</p>
|
||||
</blockquote>
|
||||
<h2>特性</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox180" checked="true" /><label for="checkbox180">插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小整体体积</label></li>
|
||||
<li><input type="checkbox" id="checkbox181" checked="true" /><label for="checkbox181">支持逻辑结构图、思维导图、组织结构图、目录组织图、时间轴、鱼骨图六种结构</label></li>
|
||||
<li><input type="checkbox" id="checkbox182" checked="true" /><label for="checkbox182">内置多种主题,允许高度自定义样式,支持注册新主题</label></li>
|
||||
<li><input type="checkbox" id="checkbox183" checked="true" /><label for="checkbox183">支持快捷键</label></li>
|
||||
<li><input type="checkbox" id="checkbox184" checked="true" /><label for="checkbox184">节点内容支持图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox185" checked="true" /><label for="checkbox185">支持前进后退</label></li>
|
||||
<li><input type="checkbox" id="checkbox186" checked="true" /><label for="checkbox186">支持拖动、缩放</label></li>
|
||||
<li><input type="checkbox" id="checkbox187" checked="true" /><label for="checkbox187">支持右键和Ctrl+左键两种多选方式</label></li>
|
||||
<li><input type="checkbox" id="checkbox188" checked="true" /><label for="checkbox188">支持节点自由拖拽、拖拽调整</label></li>
|
||||
<li><input type="checkbox" id="checkbox189" checked="true" /><label for="checkbox189">支持多种节点形状</label></li>
|
||||
<li><input type="checkbox" id="checkbox190" checked="true" /><label for="checkbox190">支持导出为</label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>,支持从<code>json</code>、<code>xmind</code>、<code>markdown</code>导入</li>
|
||||
<li><input type="checkbox" id="checkbox191" checked="true" /><label for="checkbox191">支持小地图、支持水印</label></li>
|
||||
<li><input type="checkbox" id="checkbox192" checked="true" /><label for="checkbox192">支持关联线</label></li>
|
||||
<li><input type="checkbox" id="checkbox72" checked="true" /><label for="checkbox72">插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小整体体积</label></li>
|
||||
<li><input type="checkbox" id="checkbox73" checked="true" /><label for="checkbox73">支持逻辑结构图、思维导图、组织结构图、目录组织图、时间轴、鱼骨图六种结构</label></li>
|
||||
<li><input type="checkbox" id="checkbox74" checked="true" /><label for="checkbox74">内置多种主题,允许高度自定义样式,支持注册新主题</label></li>
|
||||
<li><input type="checkbox" id="checkbox75" checked="true" /><label for="checkbox75">支持快捷键</label></li>
|
||||
<li><input type="checkbox" id="checkbox76" checked="true" /><label for="checkbox76">节点内容支持图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox77" checked="true" /><label for="checkbox77">支持前进后退</label></li>
|
||||
<li><input type="checkbox" id="checkbox78" checked="true" /><label for="checkbox78">支持拖动、缩放</label></li>
|
||||
<li><input type="checkbox" id="checkbox79" checked="true" /><label for="checkbox79">支持右键和Ctrl+左键两种多选方式</label></li>
|
||||
<li><input type="checkbox" id="checkbox80" checked="true" /><label for="checkbox80">支持节点自由拖拽、拖拽调整</label></li>
|
||||
<li><input type="checkbox" id="checkbox81" checked="true" /><label for="checkbox81">支持多种节点形状</label></li>
|
||||
<li><input type="checkbox" id="checkbox82" checked="true" /><label for="checkbox82">支持导出为</label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>,支持从<code>json</code>、<code>xmind</code>、<code>markdown</code>导入</li>
|
||||
<li><input type="checkbox" id="checkbox83" checked="true" /><label for="checkbox83">支持小地图、支持水印</label></li>
|
||||
<li><input type="checkbox" id="checkbox84" checked="true" /><label for="checkbox84">支持关联线</label></li>
|
||||
</ul>
|
||||
<h2>仓库目录介绍</h2>
|
||||
<p>1.<code>simple-mind-map</code></p>
|
||||
@@ -27,11 +28,11 @@
|
||||
<p>2.<code>web</code></p>
|
||||
<p>使用<code>simple-mind-map</code>库,基于<code>vue2.x</code>、<code>ElementUI</code>搭建的在线思维导图。特性:</p>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox193" checked="true" /><label for="checkbox193">工具栏,支持插入节点、删除节点;编辑节点图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox194" checked="true" /><label for="checkbox194">侧边栏,基础样式设置面板、节点样式设置面板、大纲面板、主题选择面板、结构选择面板</label></li>
|
||||
<li><input type="checkbox" id="checkbox195" checked="true" /><label for="checkbox195">导入导出功能;数据默认保存在浏览器本地存储,也支持直接创建、打开、编辑电脑本地文件</label></li>
|
||||
<li><input type="checkbox" id="checkbox196" checked="true" /><label for="checkbox196">右键菜单,支持展开、收起、整理布局等操作</label></li>
|
||||
<li><input type="checkbox" id="checkbox197" checked="true" /><label for="checkbox197">底部栏,支持节点数量、字数统计;支持切换编辑和只读模式;支持放大缩小;支持全屏切换;支持小地图</label></li>
|
||||
<li><input type="checkbox" id="checkbox85" checked="true" /><label for="checkbox85">工具栏,支持插入节点、删除节点;编辑节点图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox86" checked="true" /><label for="checkbox86">侧边栏,基础样式设置面板、节点样式设置面板、大纲面板、主题选择面板、结构选择面板</label></li>
|
||||
<li><input type="checkbox" id="checkbox87" checked="true" /><label for="checkbox87">导入导出功能;数据默认保存在浏览器本地存储,也支持直接创建、打开、编辑电脑本地文件</label></li>
|
||||
<li><input type="checkbox" id="checkbox88" checked="true" /><label for="checkbox88">右键菜单,支持展开、收起、整理布局等操作</label></li>
|
||||
<li><input type="checkbox" id="checkbox89" checked="true" /><label for="checkbox89">底部栏,支持节点数量、字数统计;支持切换编辑和只读模式;支持放大缩小;支持全屏切换;支持小地图</label></li>
|
||||
</ul>
|
||||
<p>提供文档页面服务。</p>
|
||||
<p>3.<code>dist</code></p>
|
||||
|
||||
@@ -86,6 +86,7 @@ const mindMap = new MindMap({
|
||||
|
||||
```bash
|
||||
git clone https://github.com/wanglin2/mind-map.git
|
||||
cd mind-map
|
||||
cd simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
<p>如果你只是使用库的话可以不用阅读此小节。</p>
|
||||
<h3>本地开发</h3>
|
||||
<pre class="hljs"><code>git <span class="hljs-built_in">clone</span> https://github.com/wanglin2/mind-map.git
|
||||
<span class="hljs-built_in">cd</span> mind-map
|
||||
<span class="hljs-built_in">cd</span> simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
|
||||
@@ -730,7 +730,7 @@ export default {
|
||||
* @Desc: 初始样式
|
||||
*/
|
||||
initStyle() {
|
||||
[
|
||||
;[
|
||||
'backgroundColor',
|
||||
'lineWidth',
|
||||
'lineStyle',
|
||||
@@ -786,7 +786,7 @@ export default {
|
||||
* @Desc: margin初始值
|
||||
*/
|
||||
initMarginStyle() {
|
||||
['marginX', 'marginY'].forEach(key => {
|
||||
;['marginX', 'marginY'].forEach(key => {
|
||||
this.style[key] = this.mindMap.getThemeConfig()[this.marginActiveTab][
|
||||
key
|
||||
]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="editContainer" :style="{top: IS_ELECTRON ? '40px' : 0}">
|
||||
<div class="editContainer">
|
||||
<div class="mindMapContainer" ref="mindMapContainer"></div>
|
||||
<Count v-if="!isZenMode"></Count>
|
||||
<Navigator :mindMap="mindMap"></Navigator>
|
||||
@@ -46,7 +46,7 @@ import { getData, storeData, storeConfig } from '@/api'
|
||||
import Navigator from './Navigator.vue'
|
||||
import NodeImgPreview from './NodeImgPreview.vue'
|
||||
import SidebarTrigger from './SidebarTrigger.vue'
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
import { mapState } from 'vuex'
|
||||
import customThemeList from '@/customThemes'
|
||||
import icon from '@/config/icon'
|
||||
|
||||
@@ -93,13 +93,11 @@ export default {
|
||||
mindMap: null,
|
||||
mindMapData: null,
|
||||
prevImg: '',
|
||||
openTest: false,
|
||||
isFirst: true
|
||||
openTest: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
fileName: state => state.fileName,
|
||||
isZenMode: state => state.localConfig.isZenMode,
|
||||
openNodeRichText: state => state.localConfig.openNodeRichText,
|
||||
})
|
||||
@@ -113,9 +111,9 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
mounted() {
|
||||
// this.showNewFeatureInfo()
|
||||
await this.getData()
|
||||
this.getData()
|
||||
this.init()
|
||||
this.$bus.$on('execCommand', this.execCommand)
|
||||
this.$bus.$on('paddingChange', this.onPaddingChange)
|
||||
@@ -138,13 +136,8 @@ export default {
|
||||
this.test()
|
||||
}, 5000)
|
||||
}
|
||||
if (window.IS_ELECTRON) {
|
||||
this.mindMap.keyCommand.addShortcut('Control+s', this.saveToLocal)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setFileName', 'setIsUnSave']),
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-11-22 19:39:28
|
||||
@@ -234,16 +227,8 @@ export default {
|
||||
* @Date: 2021-07-03 22:11:37
|
||||
* @Desc: 获取思维导图数据,实际应该调接口获取
|
||||
*/
|
||||
async getData() {
|
||||
let data = await window.electronAPI.getFileContent(this.$route.params.id)
|
||||
let storeData = null
|
||||
if (data) {
|
||||
this.setFileName(data.name)
|
||||
storeData = data.content
|
||||
} else {
|
||||
this.setFileName('未命名')
|
||||
storeData = getData()
|
||||
}
|
||||
getData() {
|
||||
let storeData = getData()
|
||||
this.mindMapData = storeData
|
||||
},
|
||||
|
||||
@@ -257,15 +242,9 @@ export default {
|
||||
return
|
||||
}
|
||||
this.$bus.$on('data_change', data => {
|
||||
if (!this.isFirst) {
|
||||
this.setIsUnSave(true)
|
||||
} else {
|
||||
this.isFirst = false
|
||||
}
|
||||
storeData(data)
|
||||
})
|
||||
this.$bus.$on('view_data_change', data => {
|
||||
this.setIsUnSave(true)
|
||||
storeConfig({
|
||||
view: data
|
||||
})
|
||||
@@ -313,9 +292,9 @@ export default {
|
||||
iconList: icon
|
||||
})
|
||||
if (this.openNodeRichText) this.addRichTextPlugin()
|
||||
// this.mindMap.keyCommand.addShortcut('Control+s', () => {
|
||||
// this.manualSave()
|
||||
// })
|
||||
this.mindMap.keyCommand.addShortcut('Control+s', () => {
|
||||
this.manualSave()
|
||||
})
|
||||
// 转发事件
|
||||
;[
|
||||
'node_active',
|
||||
@@ -430,18 +409,6 @@ export default {
|
||||
// 移除节点富文本编辑插件
|
||||
removeRichTextPlugin() {
|
||||
this.mindMap.removePlugin(RichText)
|
||||
},
|
||||
|
||||
// 保存到本地文件
|
||||
async saveToLocal() {
|
||||
let id = this.$route.params.id
|
||||
let data = this.mindMap.getData(true)
|
||||
console.log('保存', id, data)
|
||||
let res = await window.electronAPI.save(id, JSON.stringify(data), this.fileName)
|
||||
if (res) {
|
||||
this.setFileName(res)
|
||||
}
|
||||
this.setIsUnSave(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
<Fullscreen :mindMap="mindMap"></Fullscreen>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="iconfont icongithub" @click="openGithub"></span>
|
||||
<a href="https://github.com/wanglin2/mind-map" target="_blank">
|
||||
<span class="iconfont icongithub"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -87,10 +89,6 @@ export default {
|
||||
onLangChange(lang) {
|
||||
i18n.locale = lang
|
||||
storeLang(lang)
|
||||
},
|
||||
|
||||
openGithub() {
|
||||
window.electronAPI.openUrl('https://github.com/wanglin2/mind-map')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ export default {
|
||||
this.activeTab = 'normal'
|
||||
return
|
||||
}
|
||||
[
|
||||
;[
|
||||
'shape',
|
||||
'paddingX',
|
||||
'paddingY',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="toolbarContainer">
|
||||
<div class="toolbar" :style="{top: IS_ELECTRON ? '40px' : 0}">
|
||||
<div class="toolbar">
|
||||
<!-- 节点操作 -->
|
||||
<div class="toolbarBlock">
|
||||
<div
|
||||
@@ -126,15 +126,15 @@
|
||||
</div>
|
||||
<!-- 导出 -->
|
||||
<div class="toolbarBlock">
|
||||
<div class="toolbarBtn" @click="createNewLocalFile" v-if="!IS_ELECTRON">
|
||||
<div class="toolbarBtn" @click="createNewLocalFile">
|
||||
<span class="icon iconfont iconxinjian"></span>
|
||||
<span class="text">{{ $t('toolbar.newFile') }}</span>
|
||||
</div>
|
||||
<div class="toolbarBtn" @click="openLocalFile" v-if="!IS_ELECTRON">
|
||||
<div class="toolbarBtn" @click="openLocalFile">
|
||||
<span class="icon iconfont icondakai"></span>
|
||||
<span class="text">{{ $t('toolbar.openFile') }}</span>
|
||||
</div>
|
||||
<div class="toolbarBtn" @click="saveLocalFile" v-if="!IS_ELECTRON">
|
||||
<div class="toolbarBtn" @click="saveLocalFile">
|
||||
<span class="icon iconfont iconlingcunwei"></span>
|
||||
<span class="text">{{ $t('toolbar.saveAs') }}</span>
|
||||
</div>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<template>
|
||||
<div class="workbencheContainer">
|
||||
<div class="workbencheContent">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Workbenche',
|
||||
created () {
|
||||
document.title = '思绪思维导图'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workbencheContainer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.workbencheContent {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,92 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="aboutDialog"
|
||||
title="关于"
|
||||
:visible.sync="dialogVisible"
|
||||
width="480px"
|
||||
@close="onClose"
|
||||
>
|
||||
<div class="aboutBox">
|
||||
<img src="../../../assets/img/icon.png" alt="" />
|
||||
<h2>思绪思维导图</h2>
|
||||
<p>版本:{{ version }}</p>
|
||||
<p>
|
||||
获取源码:<a href="https://github.com/wanglin2/mind-map/tree/electron"
|
||||
>mind-map</a
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
下载最新版本:<a href="https://github.com/wanglin2/mind-map/releases"
|
||||
>releases</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pkg from '../../../../package.json'
|
||||
|
||||
export default {
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change'
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
version: pkg.version
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val, oldVal) {
|
||||
this.dialogVisible = val
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClose() {
|
||||
this.$emit('change', false)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.aboutDialog {
|
||||
/deep/ .el-dialog__body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.aboutBox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-bottom: 30px;
|
||||
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,62 +0,0 @@
|
||||
<template>
|
||||
<div class="workbencheEmptyContainer">
|
||||
<div class="icon iconfont iconwushuju"></div>
|
||||
<div class="tip">暂时没有内容</div>
|
||||
<div class="desc">没有最近使用的文件记录</div>
|
||||
<div class="createBtn" @click="create">立即创建</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { create } from '../utils'
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
create
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workbencheEmptyContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.icon {
|
||||
font-size: 100px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.createBtn {
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #409eff;
|
||||
color: #409eff;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(64, 158, 255, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,165 +0,0 @@
|
||||
<template>
|
||||
<div class="workbencheFileListContainer">
|
||||
<div class="title">
|
||||
<span>最近</span>
|
||||
<span class="clearBtn" @click="clear">清空</span>
|
||||
</div>
|
||||
<div class="fileListBox">
|
||||
<Empty v-if="list.length <= 0"></Empty>
|
||||
<el-table v-else :data="list" style="width: 100%">
|
||||
<el-table-column prop="name" label="名称"> </el-table-column>
|
||||
<el-table-column prop="url" label="文件路径"> </el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
icon="el-icon-edit"
|
||||
circle
|
||||
size="mini"
|
||||
@click="openFile(scope.row.url)"
|
||||
></el-button>
|
||||
<el-button
|
||||
icon="el-icon-document-copy"
|
||||
circle
|
||||
size="mini"
|
||||
@click="copyFile(scope.row.url)"
|
||||
></el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
circle
|
||||
size="mini"
|
||||
@click="deleteFile(scope.row.url, scope.$index)"
|
||||
></el-button>
|
||||
<el-button
|
||||
icon="el-icon-folder-opened"
|
||||
circle
|
||||
size="mini"
|
||||
@click="openFileInDir(scope.row.url)"
|
||||
></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Empty from '../components/Empty.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Empty
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getRecentFileList()
|
||||
window.electronAPI.onRefreshRecentFileList(() => {
|
||||
this.getRecentFileList()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// 获取最近文件列表
|
||||
async getRecentFileList() {
|
||||
let list = await window.electronAPI.getRecentFileList()
|
||||
this.list = list.reverse()
|
||||
},
|
||||
|
||||
// 在文件夹里打开文件
|
||||
openFileInDir(file) {
|
||||
window.electronAPI.openFileInDir(file)
|
||||
},
|
||||
|
||||
// 删除文件
|
||||
deleteFile(file, index) {
|
||||
this.$confirm('确定删除该文件?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
let res = await window.electronAPI.deleteFile(file)
|
||||
if (res) {
|
||||
this.$message.error('删除失败')
|
||||
} else {
|
||||
this.list.splice(index, 1)
|
||||
this.$message.success('删除成功')
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
// 编辑文件
|
||||
openFile(file) {
|
||||
window.electronAPI.openFile(file)
|
||||
},
|
||||
|
||||
// 清空最近文件列表
|
||||
clear() {
|
||||
this.$confirm('确定清空最近文件?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
let res = await window.electronAPI.clearRecentFileList()
|
||||
if (res) {
|
||||
this.$message.error('清空失败')
|
||||
} else {
|
||||
this.list = []
|
||||
this.$message.success('清空成功')
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
// 复制文件
|
||||
async copyFile(file) {
|
||||
try {
|
||||
window.electronAPI.copyFile(file)
|
||||
this.$message.success('复制成功')
|
||||
} catch (error) {
|
||||
this.$message.error('复制失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workbencheFileListContainer {
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
padding-top: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
height: 65px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.clearBtn {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
.fileListBox {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,15 +0,0 @@
|
||||
<template>
|
||||
<div class="macControl" v-if="IS_MAC"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.macControl {
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<div class="workbencheSidebarContainer">
|
||||
<div class="createBtn" @click="create">开始新建</div>
|
||||
<div class="line"></div>
|
||||
<div class="btn" @click="openLocalFile">
|
||||
<span class="icon iconfont icondakai"></span>
|
||||
<span class="text">打开本地文件</span>
|
||||
</div>
|
||||
<div class="btn active">
|
||||
<span class="icon iconfont iconzuijinliulan"></span>
|
||||
<span class="text">最近文件</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { create } from '../utils'
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
create,
|
||||
|
||||
openLocalFile() {
|
||||
window.electronAPI.selectOpenFile()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workbencheSidebarContainer {
|
||||
flex-shrink: 0;
|
||||
width: 200px;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
margin-right: 20px;
|
||||
padding: 15px 20px;
|
||||
|
||||
.createBtn {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: #409eff;
|
||||
border-radius: 5px;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: #e4e7ed;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
color: #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
padding: 0 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
background-color: rgba(64, 158, 255, 0.3);
|
||||
color: rgba(64, 158, 255, 1);
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,68 +0,0 @@
|
||||
<template>
|
||||
<div class="winControl noDrag" v-if="IS_WIN">
|
||||
<div class="winControlBtn iconfont iconzuixiaohua" @click="minimize"></div>
|
||||
<div
|
||||
class="winControlBtn iconfont"
|
||||
:class="[isMaximize ? 'icon3zuidahua-3' : 'iconzuidahua']"
|
||||
@click="toggleMaximize"
|
||||
></div>
|
||||
<div class="winControlBtn iconfont iconguanbi" @click="close"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isMaximize: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
minimize() {
|
||||
window.electronAPI.minimize()
|
||||
},
|
||||
|
||||
toggleMaximize() {
|
||||
if (this.isMaximize) {
|
||||
this.isMaximize = false
|
||||
window.electronAPI.unmaximize()
|
||||
} else {
|
||||
this.isMaximize = true
|
||||
window.electronAPI.maximize()
|
||||
}
|
||||
},
|
||||
|
||||
close() {
|
||||
window.electronAPI.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.winControl {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
height: 100%;
|
||||
.winControlBtn {
|
||||
width: 40px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: #ccced1;
|
||||
}
|
||||
|
||||
&.iconguanbi {
|
||||
&:hover {
|
||||
background-color: #e81123;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +0,0 @@
|
||||
import { v4 as uuid } from 'uuid'
|
||||
|
||||
// 打开新的编辑窗口
|
||||
export const create = () => {
|
||||
window.electronAPI.create(uuid())
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
<template>
|
||||
<div class="workbencheEditContainer">
|
||||
<div class="workbencheEditHeader">
|
||||
<MacControl></MacControl>
|
||||
<WinControl></WinControl>
|
||||
<div class="inputBox">
|
||||
<el-input
|
||||
v-model="name"
|
||||
size="mini"
|
||||
placeholder=""
|
||||
@blur="rename"
|
||||
@keyup.enter="rename"
|
||||
></el-input>
|
||||
<div class="modifyDotBox">
|
||||
<div class="modifyDot" v-show="isUnSave"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Edit></Edit>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Edit from '../../Edit/Index.vue'
|
||||
import WinControl from '../components/WinControl.vue'
|
||||
import MacControl from '../components/MacControl.vue'
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Edit,
|
||||
MacControl,
|
||||
WinControl
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
name: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['fileName', 'isUnSave'])
|
||||
},
|
||||
watch: {
|
||||
fileName(val) {
|
||||
this.name = val
|
||||
document.title = val
|
||||
},
|
||||
name(val) {
|
||||
if (!val.trim()) return
|
||||
this.setFileName(val.trim())
|
||||
}
|
||||
},
|
||||
created() {
|
||||
window.onbeforeunload = async e => {
|
||||
e.returnValue = false
|
||||
// 没有未保存内容直接关闭
|
||||
if (!this.isUnSave) {
|
||||
window.electronAPI.destroy()
|
||||
} else {
|
||||
try {
|
||||
// 否则询问用户是否关闭
|
||||
await this.checkIsClose()
|
||||
window.electronAPI.destroy()
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setFileName']),
|
||||
|
||||
// 重命名文件
|
||||
rename() {
|
||||
let id = this.$route.params.id
|
||||
window.electronAPI.rename(id, this.name.trim())
|
||||
},
|
||||
|
||||
// 询问是否关闭页面
|
||||
checkIsClose() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.$confirm('有操作尚未保存,是否确认关闭?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
resolve()
|
||||
})
|
||||
.catch(() => {
|
||||
reject()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workbencheEditContainer {
|
||||
.workbencheEditHeader {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background-color: #ebeef1;
|
||||
-webkit-app-region: drag;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
.inputBox {
|
||||
-webkit-app-region: no-drag;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.modifyDotBox {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-left: 10px;
|
||||
|
||||
.modifyDot {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background-color: #409eff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,150 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
class="workbencheHomeContainer"
|
||||
@drop="onDrop"
|
||||
@dragenter="onDragenter"
|
||||
@dragover="onDragover"
|
||||
@dragleave="onDragleave"
|
||||
>
|
||||
<div class="workbencheHomeHeader">
|
||||
<MacControl></MacControl>
|
||||
<WinControl></WinControl>
|
||||
<div class="rightBar">
|
||||
<el-dropdown @command="handleCommand">
|
||||
<span class="settingBtn el-icon-setting"></span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="about">关于软件</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="workbencheHomeContent">
|
||||
<Sidebar></Sidebar>
|
||||
<FileList></FileList>
|
||||
</div>
|
||||
<AboutDialog v-model="showAboutDialog"></AboutDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WinControl from '../components/WinControl.vue'
|
||||
import MacControl from '../components/MacControl.vue'
|
||||
import Sidebar from '../components/Sidebar.vue'
|
||||
import FileList from '../components/FileList.vue'
|
||||
import AboutDialog from '../components/AboutDialog.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WinControl,
|
||||
MacControl,
|
||||
Sidebar,
|
||||
FileList,
|
||||
AboutDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAboutDialog: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCommand(command) {
|
||||
switch (command) {
|
||||
case 'about':
|
||||
this.showAboutDialog = true
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
},
|
||||
|
||||
onDrop(e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
let df = e.dataTransfer
|
||||
let dropFiles = []
|
||||
|
||||
if (df.items !== undefined) {
|
||||
for (let i = 0; i < df.items.length; i++) {
|
||||
let item = df.items[i]
|
||||
if (item.kind === 'file' && item.webkitGetAsEntry().isFile) {
|
||||
let file = item.getAsFile()
|
||||
if (/\.smm$/.test(file.name)) {
|
||||
dropFiles.push(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dropFiles.length === 1) {
|
||||
// 如果只有一个文件,直接打开编辑
|
||||
window.electronAPI.openFile(dropFiles[0].path)
|
||||
} else if (dropFiles.length > 1) {
|
||||
// 否则添加到最近文件列表
|
||||
window.electronAPI.addRecentFileList(
|
||||
dropFiles.map(file => {
|
||||
return file.path
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
onDragenter(e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
},
|
||||
|
||||
onDragover(e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
},
|
||||
|
||||
onDragleave(e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workbencheHomeContainer {
|
||||
background-color: #f6f8f9;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.workbencheHomeHeader {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background-color: #ebeef1;
|
||||
-webkit-app-region: drag;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
.rightBar {
|
||||
-webkit-app-region: no-drag;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.settingBtn {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.workbencheHomeContent {
|
||||
flex-grow: 1;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -3,9 +3,6 @@ import VueRouter from 'vue-router'
|
||||
import EditPage from '@/pages/Edit/Index'
|
||||
import DocPage from '@/pages/Doc/Index'
|
||||
import routerList from '@/pages/Doc/routerList'
|
||||
import WorkbenchePage from '@/pages/Workbenche/Index'
|
||||
import WorkbencheHomePage from '@/pages/Workbenche/views/Home'
|
||||
import WorkbencheEditPage from '@/pages/Workbenche/views/Edit'
|
||||
|
||||
// 处理没有翻译的章节路由
|
||||
const handleRouterList = () => {
|
||||
@@ -29,39 +26,21 @@ handleRouterList()
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Edit',
|
||||
component: EditPage
|
||||
},
|
||||
{
|
||||
path: '/workbenche',
|
||||
name: 'Workbenche',
|
||||
component: WorkbenchePage,
|
||||
redirect: '/workbenche/home',
|
||||
children: [
|
||||
{
|
||||
path: 'home',
|
||||
name: 'WorkbencheHome',
|
||||
component: WorkbencheHomePage,
|
||||
},
|
||||
{
|
||||
path: 'edit/:id',
|
||||
name: 'WorkbencheEdit',
|
||||
component: WorkbencheEditPage,
|
||||
}
|
||||
]
|
||||
{
|
||||
path: '/',
|
||||
name: 'Edit',
|
||||
component: EditPage
|
||||
},
|
||||
...routerList.map((item) => {
|
||||
return {
|
||||
path: `/doc/${item.lang}/`,
|
||||
return {
|
||||
path: `/doc/${item.lang}/`,
|
||||
redirect: `/doc/${item.lang}/introduction/`
|
||||
}
|
||||
}),
|
||||
...routerList.map((item) => {
|
||||
return {
|
||||
path: `/doc/${item.lang}/`,
|
||||
component: DocPage,
|
||||
return {
|
||||
path: `/doc/${item.lang}/`,
|
||||
component: DocPage,
|
||||
children: item.children.map((child) => {
|
||||
return {
|
||||
path: `${child.path}/:h?`,
|
||||
|
||||
@@ -7,8 +7,6 @@ Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
state: {
|
||||
fileName: '',// 本地的文件名
|
||||
isUnSave: false,// 当前操作是否未保存
|
||||
mindMapData: null, // 思维导图数据
|
||||
isHandleLocalFile: false, // 是否操作的是本地文件
|
||||
localConfig: {
|
||||
@@ -17,20 +15,9 @@ const store = new Vuex.Store({
|
||||
// 是否开启节点富文本
|
||||
openNodeRichText: true
|
||||
},
|
||||
activeSidebar: '', // 当前显示的侧边栏
|
||||
localEditList: []// 客户端中正在编辑的思维导图列表
|
||||
activeSidebar: '' // 当前显示的侧边栏
|
||||
},
|
||||
mutations: {
|
||||
// 设置本地文件名
|
||||
setFileName(state, data) {
|
||||
state.fileName = data
|
||||
},
|
||||
|
||||
// 设置当前操作是否未保存
|
||||
setIsUnSave(state, data) {
|
||||
state.isUnSave = data
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-10 14:50:01
|
||||
@@ -72,11 +59,6 @@ const store = new Vuex.Store({
|
||||
*/
|
||||
setActiveSidebar(state, data) {
|
||||
state.activeSidebar = data
|
||||
},
|
||||
|
||||
// 设置客户端中当前正在编辑的思维导图列表
|
||||
setLocalEditList(state, list) {
|
||||
state.localEditList = list
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
||||
@@ -1,119 +1,16 @@
|
||||
const path = require('path')
|
||||
const path = require('path');
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
module.exports = {
|
||||
publicPath: isDev ? '' : './dist',
|
||||
outputDir: '../dist',
|
||||
lintOnSave: false,
|
||||
productionSourceMap: false,
|
||||
configureWebpack: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './src/')
|
||||
}
|
||||
}
|
||||
},
|
||||
pluginOptions: {
|
||||
electronBuilder: {
|
||||
preload: 'src/electron/preload.js',
|
||||
builderOptions: {
|
||||
productName: '思绪思维导图',
|
||||
copyright: 'Copyright © 思绪思维导图',
|
||||
// compression: "maximum", // 机器好的可以打开,配置压缩,开启后会让 .AppImage 格式的客户端启动缓慢
|
||||
asar: true,
|
||||
fileAssociations: [
|
||||
{
|
||||
ext: 'smm',
|
||||
name: 'mind map file',
|
||||
role: 'Editor',
|
||||
icon: './build/icons/icon.ico'
|
||||
}
|
||||
],
|
||||
publish: [
|
||||
{
|
||||
provider: 'github',
|
||||
owner: 'wanglin2',
|
||||
repo: 'mind-map',
|
||||
vPrefixedTagName: true,
|
||||
releaseType: 'draft'
|
||||
}
|
||||
],
|
||||
directories: {
|
||||
output: 'dist_electron'
|
||||
},
|
||||
mac: {
|
||||
target: [
|
||||
{
|
||||
target: 'dmg',
|
||||
arch: ['x64', 'arm64', 'universal']
|
||||
publicPath: isDev ? '' : './dist',
|
||||
outputDir: '../dist',
|
||||
lintOnSave: false,
|
||||
productionSourceMap: false,
|
||||
configureWebpack: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './src/')
|
||||
}
|
||||
],
|
||||
artifactName: '${productName}-${os}-${version}-${arch}.${ext}',
|
||||
category: 'public.app-category.utilities',
|
||||
darkModeSupport: true
|
||||
},
|
||||
win: {
|
||||
target: [
|
||||
{
|
||||
target: 'portable',
|
||||
arch: ['x64']
|
||||
},
|
||||
{
|
||||
target: 'nsis',
|
||||
arch: ['x64']
|
||||
}
|
||||
],
|
||||
publisherName: '思绪思维导图',
|
||||
icon: 'build/icons/icon.ico',
|
||||
publish: ['github']
|
||||
},
|
||||
linux: {
|
||||
target: [
|
||||
{
|
||||
target: 'AppImage',
|
||||
arch: ['x64']
|
||||
},
|
||||
{
|
||||
target: 'tar.gz',
|
||||
arch: ['x64', 'arm64']
|
||||
},
|
||||
{
|
||||
target: 'deb',
|
||||
arch: ['x64', 'armv7l', 'arm64']
|
||||
},
|
||||
{
|
||||
target: 'rpm',
|
||||
arch: ['x64']
|
||||
},
|
||||
{
|
||||
target: 'snap',
|
||||
arch: ['x64']
|
||||
},
|
||||
{
|
||||
target: 'pacman',
|
||||
arch: ['x64']
|
||||
}
|
||||
],
|
||||
category: 'Utilities',
|
||||
icon: './build/icon.icns'
|
||||
},
|
||||
dmg: {
|
||||
icon: 'build/icons/icon.icns'
|
||||
},
|
||||
nsis: {
|
||||
oneClick: false,
|
||||
allowToChangeInstallationDirectory: true,
|
||||
perMachine: true,
|
||||
deleteAppDataOnUninstall: true
|
||||
}
|
||||
},
|
||||
// 渲染线程的配置文件
|
||||
chainWebpackRendererProcess: config => {
|
||||
config.plugin('define').tap(args => {
|
||||
args[0]['IS_ELECTRON'] = true
|
||||
return args
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user