Compare commits

..

15 Commits

Author SHA1 Message Date
街角小林
b04469649a Merge pull request #145 from clh021/main
add MIT LICENSE
2023-06-08 08:59:04 +08:00
chenlianghong
ee57dbdcc5 add MIT LICENSE 2023-06-07 17:40:47 +08:00
wanglin2
bca744f6fc 更新群二维码 2023-06-06 09:14:18 +08:00
wanglin2
442408dacf 更新群二维码 2023-05-30 08:54:11 +08:00
wanglin2
7297f0a082 更新群二维码 2023-05-23 14:24:29 +08:00
wanglin2
f0d90941fb 合并 2023-05-15 10:26:33 +08:00
wanglin2
830962c044 更新群二维码 2023-05-15 10:25:34 +08:00
wanglin2
eeec71dc65 更新群二维码 2023-05-05 21:48:58 +08:00
wanglin2
9bd87a22f3 更新群二维码 2023-05-05 21:39:43 +08:00
wanglin2
88c9f22a15 Merge branch 'feature' into main 2023-05-05 21:34:40 +08:00
wanglin2
7380fc60d5 打包 2023-05-05 21:34:26 +08:00
wanglin2
a178b99d73 更新群二维码 2023-05-05 16:10:31 +08:00
wanglin2
af9ee04aaf Merge branch 'feature' into main 2023-05-02 10:05:39 +08:00
wanglin2
c8d23cab40 更新README 2023-04-28 09:04:20 +08:00
wanglin2
244ced83bc 更新群二维码 2023-04-28 08:59:54 +08:00
53 changed files with 7680 additions and 14026 deletions

21
LICENSE Normal file
View 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.

View File

@@ -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
# 微信交流群
![](./qrcode.jpg)
<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

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

View File

@@ -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"
]
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

Binary file not shown.

View File

@@ -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)
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

View File

@@ -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()
})
}
}

View File

@@ -1,3 +0,0 @@
.noDrag {
-webkit-app-region: no-drag;
}

View File

@@ -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)
})
}

View 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)
})
}

View File

@@ -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)
})

View 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()
}
})
})
}

View File

@@ -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),

View File

@@ -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)
})

View File

@@ -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

View File

@@ -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 mapsupport 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 mapsupport 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>

View File

@@ -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

View File

@@ -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

View File

@@ -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: '客户端' }
]
},
{

View 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
```

View 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>

View File

@@ -3,6 +3,8 @@
`simple-mind-map`是一个简单&强大的Web思维导图库不依赖任何特定框架。可以帮助你快速开发思维导图产品。
> 如果你只是想使用思维导图你也完全可以把本项目的demo作为一个普通的在线思维导图工具使用。点击右上角的【在线示例】开始使用吧。
>
> 另外也提供了客户端可供下载,支持`Windows`、`Mac`及`Linux`[点此了解更多](/mind-map/#/doc/zh/client)。
## 特性

View File

@@ -4,22 +4,23 @@
<p><code>simple-mind-map</code>是一个简单&amp;强大的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>

View File

@@ -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

View File

@@ -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

View File

@@ -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
]

View File

@@ -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)
}
}
}

View File

@@ -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')
}
}
}

View File

@@ -506,7 +506,7 @@ export default {
this.activeTab = 'normal'
return
}
[
;[
'shape',
'paddingX',
'paddingY',

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,6 +0,0 @@
import { v4 as uuid } from 'uuid'
// 打开新的编辑窗口
export const create = () => {
window.electronAPI.create(uuid())
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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?`,

View File

@@ -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: {

View File

@@ -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
})
}
}
}
}
}