日常提交

This commit is contained in:
wanglin2 2023-03-14 09:40:09 +08:00
parent fba0ece8fd
commit d6e625efa6
21 changed files with 727 additions and 26 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules
.DS_Store
.DS_Store
dist_electron

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

File diff suppressed because one or more lines are too long

View File

@ -20,6 +20,7 @@
"@toast-ui/editor": "^3.1.5",
"core-js": "^3.6.5",
"element-ui": "^2.15.1",
"fs-extra": "^7.0.1",
"highlight.js": "^10.7.3",
"uuid": "^3.4.0",
"v-viewer": "^1.6.4",

View File

@ -93,7 +93,7 @@
/*! 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\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 createNewEditPage: (id) => ipcRenderer.send('createNewEditPage', id),\r\n activeEditPage: (id) => ipcRenderer.send('activeEditPage', id),\r\n})\n\n//# sourceURL=webpack:///./src/electron/preload.js?");
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 create: (id) => ipcRenderer.send('create', id),\r\n save: (id, data) => ipcRenderer.send('save', id, data),\r\n})\n\n//# sourceURL=webpack:///./src/electron/preload.js?");
/***/ }),

15
web/package-lock.json generated
View File

@ -12,6 +12,7 @@
"@toast-ui/editor": "^3.1.5",
"core-js": "^3.6.5",
"element-ui": "^2.15.1",
"fs-extra": "^7.0.1",
"highlight.js": "^10.7.3",
"uuid": "^3.4.0",
"v-viewer": "^1.6.4",
@ -9571,7 +9572,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
@ -9934,8 +9934,7 @@
"node_modules/graceful-fs": {
"version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
},
"node_modules/graceful-readlink": {
"version": "1.0.1",
@ -11786,7 +11785,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"dev": true,
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
@ -17910,7 +17908,6 @@
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"dev": true,
"engines": {
"node": ">= 4.0.0"
}
@ -27859,7 +27856,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
@ -28144,8 +28140,7 @@
"graceful-fs": {
"version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
},
"graceful-readlink": {
"version": "1.0.1",
@ -29541,7 +29536,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.6"
}
@ -34627,8 +34621,7 @@
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"dev": true
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
},
"unpipe": {
"version": "1.0.0",

View File

@ -20,6 +20,7 @@
"@toast-ui/editor": "^3.1.5",
"core-js": "^3.6.5",
"element-ui": "^2.15.1",
"fs-extra": "^7.0.1",
"highlight.js": "^10.7.3",
"uuid": "^3.4.0",
"v-viewer": "^1.6.4",

View File

@ -34,7 +34,17 @@ export const getData = () => {
return simpleDeepClone(exampleData)
} else {
try {
return JSON.parse(store)
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
}
} catch (error) {
return simpleDeepClone(exampleData)
}

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2479351 */
src: url('iconfont.woff2?t=1678168703777') format('woff2'),
url('iconfont.woff?t=1678168703777') format('woff'),
url('iconfont.ttf?t=1678168703777') format('truetype');
src: url('iconfont.woff2?t=1678265970945') format('woff2'),
url('iconfont.woff?t=1678265970945') format('woff'),
url('iconfont.ttf?t=1678265970945') format('truetype');
}
.iconfont {
@ -13,6 +13,22 @@
-moz-osx-font-smoothing: grayscale;
}
.iconbangzhu:before {
content: "\e620";
}
.iconshezhi:before {
content: "\e8b7";
}
.iconwushuju:before {
content: "\e643";
}
.iconzuijinliulan:before {
content: "\e62f";
}
.icon3zuidahua-3:before {
content: "\e692";
}

View File

@ -1,9 +1,10 @@
'use strict'
import { app, protocol, BrowserWindow, ipcMain, BrowserView } from 'electron'
import { app, protocol, BrowserWindow, ipcMain, BrowserView, dialog } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
import path from 'path'
const fs = require('fs-extra')
const isDevelopment = process.env.NODE_ENV !== 'production'
// Scheme must be registered before the app is ready
@ -28,7 +29,7 @@ async function createWindow() {
})
// 新建编辑页面
ipcMain.on('createNewEditPage', async id => {
ipcMain.on('create', async (event, id) => {
const win = new BrowserWindow({
width: 1200,
height: 800,
@ -53,6 +54,27 @@ async function createWindow() {
win.loadURL('app://./index.html/#/workbenche/edit/' + id)
}
})
// 保存
const idToFilePath = {}
ipcMain.on('save', async (event, id, data) => {
if (!idToFilePath[id]) {
const webContents = event.sender
const win = BrowserWindow.fromWebContents(webContents)
const res = dialog.showSaveDialogSync(win, {
title: '保存',
defaultPath: '未命名.smm',
filters: [
{ name: '思维导图', extensions: ['smm'] }
]
})
if (res) {
idToFilePath[id] = res
fs.writeFile(res, data)
}
return
}
fs.writeFile(idToFilePath[id], data)
})
;['minimize', 'maximize', 'unmaximize', 'close'].forEach(item => {
ipcMain.on(item, event => {
const webContents = event.sender
@ -64,7 +86,7 @@ async function createWindow() {
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '/#/workbenche')
if (!process.env.IS_TEST) win.webContents.openDevTools()
// if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development

View File

@ -1,12 +1,13 @@
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'),
createNewEditPage: (id) => ipcRenderer.send('createNewEditPage', id),
activeEditPage: (id) => ipcRenderer.send('activeEditPage', id),
create: (id) => ipcRenderer.send('create', id),
save: (id, data) => ipcRenderer.send('save', id, data),
})

View File

@ -17,7 +17,7 @@ Vue.use(VueViewer)
Vue.mixin({
data () {
return {
IS_ELECTRON: process.env.IS_ELECTRON,
IS_ELECTRON: window.IS_ELECTRON,
IS_MAC: window.platform === 'darwin',
IS_WIN: window.platform === 'win32'
}

View File

@ -126,6 +126,9 @@ export default {
this.test()
}, 5000)
}
if (window.IS_ELECTRON) {
this.mindMap.keyCommand.addShortcut('Control+s', this.saveToLocal)
}
},
methods: {
/**
@ -375,6 +378,13 @@ export default {
//
removeRichTextPlugin() {
this.mindMap.removePlugin(RichText)
},
saveToLocal() {
let id = this.$route.params.id
let data = this.mindMap.getData(true)
console.log('保存', id, data)
window.electronAPI.save(id, JSON.stringify(data))
}
}
}

View File

@ -0,0 +1,62 @@
<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

@ -0,0 +1,45 @@
<template>
<div class="workbencheFileListContainer">
<div class="title">最近</div>
<div class="fileListBox">
<Empty></Empty>
</div>
</div>
</template>
<script>
import Empty from '../components/Empty.vue'
export default {
components: {
Empty
}
}
</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;
line-height: 65px;
flex-shrink: 0;
}
.fileListBox {
flex-grow: 1;
overflow: hidden;
}
}
</style>

View File

@ -0,0 +1,86 @@
<template>
<div class="workbencheSidebarContainer">
<div class="createBtn" @click="create">开始新建</div>
<div class="line"></div>
<div class="btn">
<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
}
}
</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

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

View File

@ -4,18 +4,25 @@
<MacControl></MacControl>
<WinControl></WinControl>
</div>
<div class="workbencheHomeContent"></div>
<div class="workbencheHomeContent">
<Sidebar></Sidebar>
<FileList></FileList>
</div>
</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'
export default {
components: {
WinControl,
MacControl
MacControl,
Sidebar,
FileList
}
}
</script>
@ -41,6 +48,8 @@ export default {
.workbencheHomeContent {
flex-grow: 1;
padding: 20px;
display: flex;
overflow: hidden;
}
}
</style>