重新设计客户端架构

This commit is contained in:
wanglin2 2023-03-07 16:39:33 +08:00
parent 58f7be77ed
commit 78ed038012
28 changed files with 392 additions and 2956 deletions

View File

@ -1776,7 +1776,7 @@ eval("/*\n Yaku v0.16.7\n (c) 2015 Yad Smood. http://ysmood.org\n License MIT\n*
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var electron__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! electron */ \"electron\");\n/* harmony import */ var electron__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(electron__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var vue_cli_plugin_electron_builder_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue-cli-plugin-electron-builder/lib */ \"./node_modules/vue-cli-plugin-electron-builder/lib/index.js\");\n/* harmony import */ var electron_devtools_installer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! electron-devtools-installer */ \"./node_modules/electron-devtools-installer/dist/index.js\");\n/* harmony import */ var electron_devtools_installer__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(electron_devtools_installer__WEBPACK_IMPORTED_MODULE_2__);\n\n\n\n\n\nconst isDevelopment = \"development\" !== 'production'\n\n// Scheme must be registered before the app is ready\nelectron__WEBPACK_IMPORTED_MODULE_0__[\"protocol\"].registerSchemesAsPrivileged([\n { scheme: 'app', privileges: { secure: true, standard: true } }\n])\n\nasync function createWindow() {\n // Create the browser window.\n const win = new electron__WEBPACK_IMPORTED_MODULE_0__[\"BrowserWindow\"]({\n width: 1200,\n height: 800,\n frame: false,\n titleBarStyle: 'hiddenInset',\n webPreferences: {\n \n // Use pluginOptions.nodeIntegration, leave this alone\n // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info\n nodeIntegration: false,\n contextIsolation: !false\n }\n })\n\n if (true) {\n // Load the url of the dev server if in development mode\n await win.loadURL(\"http://localhost:8080\")\n if (!process.env.IS_TEST) win.webContents.openDevTools()\n } else {}\n}\n\n// Quit when all windows are closed.\nelectron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].on('window-all-closed', () => {\n // On macOS it is common for applications and their menu bar\n // to stay active until the user quits explicitly with Cmd + Q\n if (process.platform !== 'darwin') {\n electron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].quit()\n }\n})\n\nelectron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].on('activate', () => {\n // On macOS it's common to re-create a window in the app when the\n // dock icon is clicked and there are no other windows open.\n if (electron__WEBPACK_IMPORTED_MODULE_0__[\"BrowserWindow\"].getAllWindows().length === 0) createWindow()\n})\n\n// This method will be called when Electron has finished\n// initialization and is ready to create browser windows.\n// Some APIs can only be used after this event occurs.\nelectron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].on('ready', async () => {\n // if (isDevelopment && !process.env.IS_TEST) {\n // // Install Vue Devtools\n // try {\n // await installExtension(VUEJS_DEVTOOLS)\n // } catch (e) {\n // console.error('Vue Devtools failed to install:', e.toString())\n // }\n // }\n createWindow()\n})\n\n// Exit cleanly on request from parent process in development mode.\nif (isDevelopment) {\n if (process.platform === 'win32') {\n process.on('message', (data) => {\n if (data === 'graceful-exit') {\n electron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].quit()\n }\n })\n } else {\n process.on('SIGTERM', () => {\n electron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].quit()\n })\n }\n}\n\n\n//# sourceURL=webpack:///./src/background.js?");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var electron__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! electron */ \"electron\");\n/* harmony import */ var electron__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(electron__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var vue_cli_plugin_electron_builder_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue-cli-plugin-electron-builder/lib */ \"./node_modules/vue-cli-plugin-electron-builder/lib/index.js\");\n/* harmony import */ var electron_devtools_installer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! electron-devtools-installer */ \"./node_modules/electron-devtools-installer/dist/index.js\");\n/* harmony import */ var electron_devtools_installer__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(electron_devtools_installer__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! path */ \"path\");\n/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);\n\r\n\r\n\r\n\r\n\r\n\r\nconst isDevelopment = \"development\" !== 'production'\r\n\r\n// Scheme must be registered before the app is ready\r\nelectron__WEBPACK_IMPORTED_MODULE_0__[\"protocol\"].registerSchemesAsPrivileged([\r\n { scheme: 'app', privileges: { secure: true, standard: true } }\r\n])\r\n\r\nasync function createWindow() {\r\n // Create the browser window.\r\n const win = new electron__WEBPACK_IMPORTED_MODULE_0__[\"BrowserWindow\"]({\r\n width: 1200,\r\n height: 800,\r\n frame: false,\r\n titleBarStyle: 'hiddenInset',\r\n webPreferences: {\r\n webSecurity: false,\r\n nodeIntegration: true,\r\n enableRemoteModule: true,\r\n contextIsolation: true,\r\n preload: path__WEBPACK_IMPORTED_MODULE_3___default.a.join(__dirname, 'preload.js')\r\n }\r\n })\r\n\r\n // 新建编辑页面\r\n electron__WEBPACK_IMPORTED_MODULE_0__[\"ipcMain\"].on('createNewEditPage', async id => {\r\n const win = new electron__WEBPACK_IMPORTED_MODULE_0__[\"BrowserWindow\"]({\r\n width: 1200,\r\n height: 800,\r\n frame: false,\r\n titleBarStyle: 'hiddenInset',\r\n webPreferences: {\r\n webSecurity: false,\r\n nodeIntegration: true,\r\n enableRemoteModule: true,\r\n contextIsolation: true,\r\n preload: path__WEBPACK_IMPORTED_MODULE_3___default.a.join(__dirname, 'preload.js')\r\n }\r\n })\r\n if (true) {\r\n // Load the url of the dev server if in development mode\r\n win.loadURL(\r\n \"http://localhost:8080\" + '/#/workbenche/edit/' + id\r\n )\r\n // if (!process.env.IS_TEST) win.webContents.openDevTools()\r\n } else {}\r\n })\r\n ;['minimize', 'maximize', 'unmaximize', 'close'].forEach(item => {\r\n electron__WEBPACK_IMPORTED_MODULE_0__[\"ipcMain\"].on(item, event => {\r\n const webContents = event.sender\r\n const win = electron__WEBPACK_IMPORTED_MODULE_0__[\"BrowserWindow\"].fromWebContents(webContents)\r\n win[item]()\r\n })\r\n })\r\n\r\n if (true) {\r\n // Load the url of the dev server if in development mode\r\n await win.loadURL(\"http://localhost:8080\" + '/#/workbenche')\r\n if (!process.env.IS_TEST) win.webContents.openDevTools()\r\n } else {}\r\n}\r\n\r\n// Quit when all windows are closed.\r\nelectron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].on('window-all-closed', () => {\r\n // On macOS it is common for applications and their menu bar\r\n // to stay active until the user quits explicitly with Cmd + Q\r\n if (process.platform !== 'darwin') {\r\n electron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].quit()\r\n }\r\n})\r\n\r\nelectron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].on('activate', () => {\r\n // On macOS it's common to re-create a window in the app when the\r\n // dock icon is clicked and there are no other windows open.\r\n if (electron__WEBPACK_IMPORTED_MODULE_0__[\"BrowserWindow\"].getAllWindows().length === 0) createWindow()\r\n})\r\n\r\nelectron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].on('ready', async () => {\r\n createWindow()\r\n})\r\n\r\n// Exit cleanly on request from parent process in development mode.\r\nif (isDevelopment) {\r\n if (process.platform === 'win32') {\r\n process.on('message', data => {\r\n if (data === 'graceful-exit') {\r\n electron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].quit()\r\n }\r\n })\r\n } else {\r\n process.on('SIGTERM', () => {\r\n electron__WEBPACK_IMPORTED_MODULE_0__[\"app\"].quit()\r\n })\r\n }\r\n}\r\n\n\n//# sourceURL=webpack:///./src/background.js?");
/***/ }),
@ -1787,7 +1787,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var elec
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("module.exports = __webpack_require__(/*! /Users/lisa/wanglin/github/mind-map/web/src/background.js */\"./src/background.js\");\n\n\n//# sourceURL=webpack:///multi_./src/background.js?");
eval("module.exports = __webpack_require__(/*! E:\\wanglin\\mind-map\\web\\src\\background.js */\"./src/background.js\");\n\n\n//# sourceURL=webpack:///multi_./src/background.js?");
/***/ }),

View File

@ -13,8 +13,7 @@
"electron:serve": "vue-cli-service electron:serve",
"format": "prettier --write src/* src/*/* src/*/*/* src/*/*/*/*",
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps",
"start": "electron ."
"postuninstall": "electron-builder install-app-deps"
},
"main": "background.js",
"dependencies": {

View File

@ -0,0 +1,122 @@
/******/ (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\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?");
/***/ }),
/***/ 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?");
/***/ })
/******/ });

20
web/package-lock.json generated
View File

@ -22380,7 +22380,6 @@
"integrity": "sha512-VCNRiAt2P/bLo09rYt3DLe6xXUMlhJwrvU18Ddd/lYJgC7s8+wvhgYs+MTx4OiAXdu58drGwSBO9SPx7C6J82Q==",
"dev": true,
"requires": {
"@babel/core": "^7.11.0",
"@babel/helper-compilation-targets": "^7.9.6",
"@babel/helper-module-imports": "^7.8.3",
"@babel/plugin-proposal-class-properties": "^7.8.3",
@ -22393,7 +22392,6 @@
"@vue/babel-plugin-jsx": "^1.0.3",
"@vue/babel-preset-jsx": "^1.2.4",
"babel-plugin-dynamic-import-node": "^2.3.3",
"core-js": "^3.6.5",
"core-js-compat": "^3.6.5",
"semver": "^6.1.0"
}
@ -22545,7 +22543,8 @@
"version": "4.5.19",
"resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.19.tgz",
"integrity": "sha512-DUmfdkG3pCdkP7Iznd87RfE9Qm42mgp2hcrNcYQYSru1W1gX2dG/JcW8bxmeGSa06lsxi9LEIc/QD1yPajSCZw==",
"dev": true
"dev": true,
"requires": {}
},
"@vue/cli-service": {
"version": "4.5.19",
@ -22703,7 +22702,8 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz",
"integrity": "sha512-LIZMuJk38pk9U9Ur4YzHjlIyMuxPlACdBIHH9/nGYVTsaGKOSnSuELiE8vS9wa+dJpIYspYUOqk+L1Q4pgHQHQ==",
"dev": true
"dev": true,
"requires": {}
},
"@vue/web-component-wrapper": {
"version": "1.3.0",
@ -22924,7 +22924,8 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true
"dev": true,
"requires": {}
},
"acorn-walk": {
"version": "7.2.0",
@ -22978,13 +22979,15 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
"integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
"dev": true
"dev": true,
"requires": {}
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"dev": true
"dev": true,
"requires": {}
},
"alphanum-sort": {
"version": "1.0.2",
@ -35603,7 +35606,8 @@
"vuex": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
"integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw=="
"integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==",
"requires": {}
},
"w3c-keyname": {
"version": "2.2.6",

View File

@ -1,539 +0,0 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2479351 */
src: url('iconfont.woff2?t=1677915953390') format('woff2'),
url('iconfont.woff?t=1677915953390') format('woff'),
url('iconfont.ttf?t=1677915953390') format('truetype');
src: url('iconfont.woff2?t=1678168703777') format('woff2'),
url('iconfont.woff?t=1678168703777') format('woff'),
url('iconfont.ttf?t=1678168703777') format('truetype');
}
.iconfont {
@ -13,6 +13,22 @@
-moz-osx-font-smoothing: grayscale;
}
.icon3zuidahua-3:before {
content: "\e692";
}
.iconzuixiaohua:before {
content: "\e650";
}
.iconzuidahua:before {
content: "\e651";
}
.iconguanbi:before {
content: "\e652";
}
.icondiannao:before {
content: "\eac0";
}

File diff suppressed because one or more lines are too long

View File

@ -1,415 +0,0 @@
{
"id": "2479351",
"name": "思绪",
"font_family": "iconfont",
"css_prefix_text": "icon",
"description": "思维导图",
"glyphs": [
{
"icon_id": "5387383",
"name": "电脑",
"font_class": "diannao",
"unicode": "eac0",
"unicode_decimal": 60096
},
{
"icon_id": "6940837",
"name": "主页",
"font_class": "zhuye",
"unicode": "e65c",
"unicode_decimal": 58972
},
{
"icon_id": "17859315",
"name": "本地@1x",
"font_class": "bendi1x",
"unicode": "e606",
"unicode_decimal": 58886
},
{
"icon_id": "1790495",
"name": "背景颜色",
"font_class": "beijingyanse",
"unicode": "e6f8",
"unicode_decimal": 59128
},
{
"icon_id": "11321310",
"name": "清除",
"font_class": "qingchu",
"unicode": "e605",
"unicode_decimal": 58885
},
{
"icon_id": "586787",
"name": "case",
"font_class": "case",
"unicode": "e6c6",
"unicode_decimal": 59078
},
{
"icon_id": "4354254",
"name": "形状-文字",
"font_class": "xingzhuang-wenzi",
"unicode": "eb99",
"unicode_decimal": 60313
},
{
"icon_id": "6337466",
"name": "字体加粗",
"font_class": "zitijiacu",
"unicode": "ec83",
"unicode_decimal": 60547
},
{
"icon_id": "6337470",
"name": "字体下划线",
"font_class": "zitixiahuaxian",
"unicode": "ec85",
"unicode_decimal": 60549
},
{
"icon_id": "6337471",
"name": "字体斜体",
"font_class": "zitixieti",
"unicode": "ec86",
"unicode_decimal": 60550
},
{
"icon_id": "11975179",
"name": "删除线",
"font_class": "shanchuxian",
"unicode": "e612",
"unicode_decimal": 58898
},
{
"icon_id": "34198316",
"name": "字体颜色",
"font_class": "zitiyanse",
"unicode": "e854",
"unicode_decimal": 59476
},
{
"icon_id": "8760187",
"name": "github",
"font_class": "github",
"unicode": "e64f",
"unicode_decimal": 58959
},
{
"icon_id": "1009019",
"name": "选择",
"font_class": "choose1",
"unicode": "e6c5",
"unicode_decimal": 59077
},
{
"icon_id": "493507",
"name": "主题",
"font_class": "zhuti",
"unicode": "e7aa",
"unicode_decimal": 59306
},
{
"icon_id": "1305460",
"name": "导出",
"font_class": "daochu1",
"unicode": "e63e",
"unicode_decimal": 58942
},
{
"icon_id": "4784101",
"name": "另存为",
"font_class": "lingcunwei",
"unicode": "e657",
"unicode_decimal": 58967
},
{
"icon_id": "9929033",
"name": "export",
"font_class": "export",
"unicode": "e642",
"unicode_decimal": 58946
},
{
"icon_id": "4570294",
"name": "打开",
"font_class": "dakai",
"unicode": "ebdf",
"unicode_decimal": 60383
},
{
"icon_id": "5086088",
"name": "新建",
"font_class": "xinjian",
"unicode": "e64e",
"unicode_decimal": 58958
},
{
"icon_id": "1117",
"name": "剪切",
"font_class": "jianqie",
"unicode": "e601",
"unicode_decimal": 58881
},
{
"icon_id": "1415523",
"name": "整理",
"font_class": "zhengli",
"unicode": "e83b",
"unicode_decimal": 59451
},
{
"icon_id": "2815710",
"name": "复制",
"font_class": "fuzhi",
"unicode": "e604",
"unicode_decimal": 58884
},
{
"icon_id": "11121506",
"name": "粘贴",
"font_class": "niantie",
"unicode": "e63f",
"unicode_decimal": 58943
},
{
"icon_id": "11383392",
"name": "上移",
"font_class": "shangyi",
"unicode": "e6be",
"unicode_decimal": 59070
},
{
"icon_id": "11383396",
"name": "下移",
"font_class": "xiayi",
"unicode": "e6bf",
"unicode_decimal": 59071
},
{
"icon_id": "14843439",
"name": "概括总览",
"font_class": "gaikuozonglan",
"unicode": "e609",
"unicode_decimal": 58889
},
{
"icon_id": "19738998",
"name": "全选",
"font_class": "quanxuan",
"unicode": "f199",
"unicode_decimal": 61849
},
{
"icon_id": "17606306",
"name": "导入",
"font_class": "daoru",
"unicode": "e6a3",
"unicode_decimal": 59043
},
{
"icon_id": "5110748",
"name": "后退-实",
"font_class": "houtui-shi",
"unicode": "e656",
"unicode_decimal": 58966
},
{
"icon_id": "14420971",
"name": "前进",
"font_class": "qianjin1",
"unicode": "e654",
"unicode_decimal": 58964
},
{
"icon_id": "1368553",
"name": "撤回",
"font_class": "withdraw",
"unicode": "e603",
"unicode_decimal": 58883
},
{
"icon_id": "15006636",
"name": "前进",
"font_class": "qianjin",
"unicode": "e600",
"unicode_decimal": 58880
},
{
"icon_id": "19980541",
"name": "恢复默认",
"font_class": "huifumoren",
"unicode": "e60e",
"unicode_decimal": 58894
},
{
"icon_id": "1616783",
"name": "换行",
"font_class": "huanhang",
"unicode": "e61e",
"unicode_decimal": 58910
},
{
"icon_id": "4777227",
"name": "缩小",
"font_class": "suoxiao",
"unicode": "ec13",
"unicode_decimal": 60435
},
{
"icon_id": "18811980",
"name": "编辑",
"font_class": "bianji",
"unicode": "e626",
"unicode_decimal": 58918
},
{
"icon_id": "21188137",
"name": "放大",
"font_class": "fangda",
"unicode": "e663",
"unicode_decimal": 58979
},
{
"icon_id": "21189639",
"name": "全屏",
"font_class": "quanping1",
"unicode": "e664",
"unicode_decimal": 58980
},
{
"icon_id": "397753",
"name": "定位",
"font_class": "dingwei",
"unicode": "e616",
"unicode_decimal": 58902
},
{
"icon_id": "2605158",
"name": "导航",
"font_class": "daohang",
"unicode": "e611",
"unicode_decimal": 58897
},
{
"icon_id": "6528451",
"name": "键盘",
"font_class": "jianpan",
"unicode": "e64d",
"unicode_decimal": 58957
},
{
"icon_id": "7556170",
"name": "全屏",
"font_class": "quanping",
"unicode": "e602",
"unicode_decimal": 58882
},
{
"icon_id": "788015",
"name": "导出",
"font_class": "daochu",
"unicode": "e63d",
"unicode_decimal": 58941
},
{
"icon_id": "2678575",
"name": "标签",
"font_class": "biaoqian",
"unicode": "e63c",
"unicode_decimal": 58940
},
{
"icon_id": "6265396",
"name": "流程-备注",
"font_class": "flow-Mark",
"unicode": "e65b",
"unicode_decimal": 58971
},
{
"icon_id": "1790486",
"name": "超链接",
"font_class": "chaolianjie",
"unicode": "e6f4",
"unicode_decimal": 59124
},
{
"icon_id": "4608986",
"name": "主题",
"font_class": "jingzi",
"unicode": "e610",
"unicode_decimal": 58896
},
{
"icon_id": "11903017",
"name": "笑脸",
"font_class": "xiaolian",
"unicode": "e60f",
"unicode_decimal": 58895
},
{
"icon_id": "19657962",
"name": "图 片",
"font_class": "image",
"unicode": "e629",
"unicode_decimal": 58921
},
{
"icon_id": "20784489",
"name": "结构",
"font_class": "jiegou",
"unicode": "e61d",
"unicode_decimal": 58909
},
{
"icon_id": "15969341",
"name": "样式",
"font_class": "yangshi",
"unicode": "e631",
"unicode_decimal": 58929
},
{
"icon_id": "2967176",
"name": "符号-大纲树",
"font_class": "fuhao-dagangshu",
"unicode": "e71f",
"unicode_decimal": 59167
},
{
"icon_id": "12316668",
"name": "添加子节点",
"font_class": "tianjiazijiedian",
"unicode": "e622",
"unicode_decimal": 58914
},
{
"icon_id": "14435368",
"name": "节点",
"font_class": "jiedian",
"unicode": "e655",
"unicode_decimal": 58965
},
{
"icon_id": "15765352",
"name": "删 除",
"font_class": "shanchu",
"unicode": "e696",
"unicode_decimal": 59030
},
{
"icon_id": "9592600",
"name": "HTSCIT_展开",
"font_class": "zhankai",
"unicode": "e64c",
"unicode_decimal": 58956
},
{
"icon_id": "9900009",
"name": "HTSCIT_展开2",
"font_class": "zhankai1",
"unicode": "e673",
"unicode_decimal": 58995
}
]
}

View File

@ -1,8 +1,9 @@
'use strict'
import { app, protocol, BrowserWindow } from 'electron'
import { app, protocol, BrowserWindow, ipcMain, BrowserView } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
import path from 'path'
const isDevelopment = process.env.NODE_ENV !== 'production'
// Scheme must be registered before the app is ready
@ -18,22 +19,56 @@ async function createWindow() {
frame: false,
titleBarStyle: 'hiddenInset',
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
webSecurity: false,
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
})
// 新建编辑页面
ipcMain.on('createNewEditPage', async 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')
}
})
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)
}
})
;['minimize', 'maximize', 'unmaximize', 'close'].forEach(item => {
ipcMain.on(item, event => {
const webContents = event.sender
const win = BrowserWindow.fromWebContents(webContents)
win[item]()
})
})
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)
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL + '/#/workbenche')
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
win.loadURL('app://./index.html/#/workbenche')
}
}
@ -52,25 +87,14 @@ app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
// if (isDevelopment && !process.env.IS_TEST) {
// // Install Vue Devtools
// try {
// await installExtension(VUEJS_DEVTOOLS)
// } catch (e) {
// console.error('Vue Devtools failed to install:', e.toString())
// }
// }
createWindow()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
process.on('message', data => {
if (data === 'graceful-exit') {
app.quit()
}

View File

@ -0,0 +1,12 @@
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('platform', process.platform)
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),
})

View File

@ -14,6 +14,15 @@ Vue.config.productionTip = false
Vue.prototype.$bus = new Vue()
Vue.use(ElementUI)
Vue.use(VueViewer)
Vue.mixin({
data () {
return {
IS_ELECTRON: process.env.IS_ELECTRON,
IS_MAC: window.platform === 'darwin',
IS_WIN: window.platform === 'win32'
}
}
})
new Vue({
render: h => h(App),

View File

@ -1,5 +1,5 @@
<template>
<div class="editContainer">
<div class="editContainer" :style="{top: IS_ELECTRON ? '40px' : 0}">
<div class="mindMapContainer" ref="mindMapContainer"></div>
<Count v-if="!isZenMode"></Count>
<Navigator :mindMap="mindMap"></Navigator>

View File

@ -1,6 +1,6 @@
<template>
<div class="toolbarContainer">
<div class="toolbar">
<div class="toolbar" :style="{top: IS_ELECTRON ? '40px' : 0}">
<!-- 节点操作 -->
<div class="toolbarBlock">
<div
@ -116,15 +116,15 @@
</div>
<!-- 导出 -->
<div class="toolbarBlock">
<div class="toolbarBtn" @click="createNewLocalFile">
<div class="toolbarBtn" @click="createNewLocalFile" v-if="!IS_ELECTRON">
<span class="icon iconfont iconxinjian"></span>
<span class="text">{{ $t('toolbar.newFile') }}</span>
</div>
<div class="toolbarBtn" @click="openLocalFile">
<div class="toolbarBtn" @click="openLocalFile" v-if="!IS_ELECTRON">
<span class="icon iconfont icondakai"></span>
<span class="text">{{ $t('toolbar.openFile') }}</span>
</div>
<div class="toolbarBtn" @click="saveLocalFile">
<div class="toolbarBtn" @click="saveLocalFile" v-if="!IS_ELECTRON">
<span class="icon iconfont iconlingcunwei"></span>
<span class="text">{{ $t('toolbar.saveAs') }}</span>
</div>

View File

@ -1,6 +1,5 @@
<template>
<div class="workbencheContainer">
<Header></Header>
<div class="workbencheContent">
<router-view></router-view>
</div>
@ -8,13 +7,8 @@
</template>
<script>
import Header from './components/Header.vue';
export default {
name: 'Workbenche',
components: {
Header
}
}
</script>

View File

@ -1,63 +0,0 @@
<template>
<div class="workbencheHeaderContainer">
<div class="placeholder"></div>
<div class="home noDrag" :class="{active: isInHome}">
<span class="icon iconfont iconzhuye"></span>
<span class="text">主页</span>
</div>
<ScrollTab></ScrollTab>
</div>
</template>
<script>
import ScrollTab from './ScrollTab.vue'
export default {
components: {
ScrollTab
},
computed: {
isInHome() {
return this.$route.path.includes('home')
}
}
}
</script>
<style lang="less" scoped>
.workbencheHeaderContainer {
width: 100%;
height: 40px;
background-color: #ebeef1;
-webkit-app-region: drag;
display: flex;
align-items: center;
flex-shrink: 0;
.placeholder {
width: 100px;
height: 100%;
flex-shrink: 0;
}
.home {
padding: 0 10px;
height: 100%;
display: flex;
align-items: center;
cursor: pointer;
user-select: none;
background-color: #e3e6e9;
flex-shrink: 0;
font-size: 14px;
&.active {
background-color: #fff;
}
.icon {
margin-right: 5px;
}
}
}
</style>

View File

@ -0,0 +1,15 @@
<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,227 +0,0 @@
<template>
<div class="workbencheScrollTabContainer" ref="container">
<div class="workbencheScrollTabBox noDrag">
<div class="workbencheScrollTabList" ref="list" :style="{ transform: `translateX(${listTranslateX}px)` }">
<div class="workbencheScrollTabItem" v-for="(item, index) in localEditList" :key="item.id"
:style="{ width: tabWidth + 'px' }" :class="{ active: $route.params.id === item.id }"
@click="openTab(item)">
<span class="icon iconfont icondiannao"></span>
<span class="text">{{ item.name }}</span>
<span class="mask"></span>
<span class="icon closeIcon el-icon-close" @click="deleteFile(index)"></span>
</div>
</div>
</div>
<div class="workbencheScrollTabControl noDrag" ref="control">
<div class="workbencheScrollTabBtn el-icon-plus" @click="addFile"></div>
<div class="workbencheScrollTabBtn el-icon-arrow-left" @click="scrollLeft"></div>
<div class="workbencheScrollTabBtn el-icon-arrow-right" @click="scrollRight"></div>
</div>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import { v4 as uuidv4 } from 'uuid';
const MIN_TAB_WIDTH = 100
const MAX_TAB_WIDTH = 220
export default {
data() {
return {
tabWidth: 0,
tabTotalWidth: 0,
listTranslateX: 0
}
},
computed: {
...mapState(['localEditList']),
},
mounted() {
this.computeTabWidth()
},
methods: {
...mapMutations(['setLocalEditList']),
addFile() {
let item = {
id: uuidv4(),
name: '新建文件',
path: ''
}
this.setLocalEditList([...this.localEditList, item])
this.$nextTick(() => {
this.openTab(item)
this.computeTabWidth()
this.scrollToEnd()
})
},
deleteFile(index) {
let arr = [...this.localEditList]
arr.splice(index, 1)
this.setLocalEditList(arr)
this.$nextTick(() => {
this.computeTabWidth()
})
},
computeTabWidth() {
let containerWidth = this.$refs.container.getBoundingClientRect().width
let controlWidth = this.$refs.control.getBoundingClientRect().width
this.tabTotalWidth = containerWidth - controlWidth
let length = this.localEditList.length
let tabWidth = Math.floor(this.tabTotalWidth / length)
if (tabWidth >= MAX_TAB_WIDTH) {
this.tabWidth = MAX_TAB_WIDTH
} else if (tabWidth <= MIN_TAB_WIDTH) {
this.tabWidth = MIN_TAB_WIDTH
} else {
this.tabWidth = tabWidth
}
},
scrollLeft() {
if (this.listTranslateX + this.tabWidth < 0) {
this.listTranslateX += this.tabWidth
} else {
this.listTranslateX = 0
}
},
scrollRight() {
let maxScroll = this.tabTotalWidth - this.localEditList.length * this.tabWidth
if (this.listTranslateX - this.tabWidth > maxScroll) {
this.listTranslateX -= this.tabWidth
} else {
this.listTranslateX = maxScroll
}
},
scrollToEnd() {
if (this.localEditList.length * this.tabWidth <= this.tabTotalWidth) {
return
}
this.listTranslateX = this.tabTotalWidth - this.localEditList.length * this.tabWidth
},
openTab(item) {
this.$router.push({
name: 'WorkbencheEdit',
params: {
id: item.id
}
})
}
}
}
</script>
<style lang="less" scoped>
.workbencheScrollTabContainer {
flex-grow: 1;
height: 100%;
display: flex;
align-items: center;
overflow: hidden;
.workbencheScrollTabBox {
overflow: hidden;
height: 100%;
.workbencheScrollTabList {
display: flex;
width: max-content;
height: 100%;
transition: all 0.3s;
.workbencheScrollTabItem {
flex-shrink: 0;
height: 100%;
font-size: 12px;
padding: 0 10px;
position: relative;
display: flex;
align-items: center;
cursor: pointer;
user-select: none;
.icon {
&.closeIcon {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
display: none;
}
}
.mask {
position: absolute;
right: 0;
top: 0;
width: 20px;
height: 100%;
background-color: #fff;
box-shadow: -10px 0 10px #fff;
display: none;
}
&:hover {
background-color: #fff;
.mask {
display: block;
}
.closeIcon {
display: block;
}
}
&::after {
content: '';
position: absolute;
width: 1px;
height: 10px;
background-color: #999;
top: 50%;
transform: translateY(-50%);
right: 0;
}
&.active {
background-color: #fff;
&::after {
display: none;
}
}
.text {}
}
}
}
.workbencheScrollTabControl {
flex-shrink: 0;
padding: 0 10px;
height: 100%;
display: flex;
.workbencheScrollTabBtn {
width: 20px;
height: 100%;
cursor: pointer;
font-size: 14px;
color: #000;
margin: 0 5px;
display: flex;
justify-content: center;
align-items: center;
}
}
}
</style>

View File

@ -1,75 +0,0 @@
<template>
<div class="workbencheHomeSidebarContainer">
<div class="workbencheMenuList">
<div class="workbencheMenuItem" v-for="item in menuList" :key="item.name"
:class="{ active: $route.name === item.routerName }" @click="toMenu(item.rou
)">
<span class="icon iconfont" :class="[item.icon]"></span>
<span class="text">{{ item.name }}</span>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
menuList: [
{
name: '本地',
icon: 'iconbendi1x',
routerName: 'WorkbencheHomeLocal'
}
]
}
},
methods: {
toMenu(routerName) {
this.$router.push(routerName)
}
}
}
</script>
<style lang="less" scoped>
.workbencheHomeSidebarContainer {
width: 80px;
background-color: #fff;
height: 100%;
flex-shrink: 0;
padding: 20px 0;
.workbencheMenuList {
display: flex;
flex-direction: column;
align-items: center;
.workbencheMenuItem {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #000;
width: 60px;
height: 60px;
border-radius: 5px;
cursor: pointer;
&.active {
background-color: #f3fbf4;
color: #56b74b;
}
.icon {
margin-bottom: 5px;
}
.text {
font-size: 14px;
}
}
}
}
</style>

View File

@ -0,0 +1,68 @@
<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,21 +1,37 @@
<template>
<div class="workbencheHeaderContainer">
<Edit :key="$route.params.id"></Edit>
<div class="workbencheEditContainer">
<div class="workbencheEditHeader">
<MacControl></MacControl>
<WinControl></WinControl>
</div>
<Edit></Edit>
</div>
</template>
<script>
import Edit from '../../Edit/Index.vue';
import Edit from '../../Edit/Index.vue'
import WinControl from '../components/WinControl.vue'
import MacControl from '../components/MacControl.vue'
export default {
components: {
Edit
}
components: {
Edit,
MacControl,
WinControl
},
}
</script>
<style lang="less" scoped>
.workbencheHeaderContainer {
.workbencheEditContainer {
.workbencheEditHeader {
width: 100%;
height: 40px;
background-color: #ebeef1;
-webkit-app-region: drag;
display: flex;
align-items: center;
flex-shrink: 0;
}
}
</style>
</style>

View File

@ -1,32 +1,46 @@
<template>
<div class="workbencheHomeContainer">
<Sidebar></Sidebar>
<div class="workbencheHomeContent">
<router-view></router-view>
</div>
<div class="workbencheHomeContainer">
<div class="workbencheHomeHeader">
<MacControl></MacControl>
<WinControl></WinControl>
</div>
<div class="workbencheHomeContent"></div>
</div>
</template>
<script>
import Sidebar from '../components/Sidebar.vue'
import WinControl from '../components/WinControl.vue'
import MacControl from '../components/MacControl.vue'
export default {
components: {
Sidebar
}
components: {
WinControl,
MacControl
}
}
</script>
<style lang="less" scoped>
.workbencheHomeContainer {
background-color: #f6f8f9;
width: 100%;
height: 100%;
display: flex;
background-color: #f6f8f9;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.workbencheHomeContent {
flex-grow: 1;
padding: 20px;
}
.workbencheHomeHeader {
width: 100%;
height: 40px;
background-color: #ebeef1;
-webkit-app-region: drag;
display: flex;
align-items: center;
flex-shrink: 0;
}
.workbencheHomeContent {
flex-grow: 1;
padding: 20px;
}
}
</style>
</style>

View File

@ -1,20 +0,0 @@
<template>
<div class="workbencheLocalContainer">
</div>
</template>
<script>
export default {
}
</script>
<style lang="less" scoped>
.workbencheLocalContainer {
width: 100%;
height: 100%;
border-radius: 5px;
background-color: #fff;
}
</style>

View File

@ -6,7 +6,6 @@ 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'
import WorkbencheHomeLocalPage from '@/pages/Workbenche/views/Local'
Vue.use(VueRouter)
@ -20,19 +19,12 @@ const routes = [
path: '/workbenche',
name: 'Workbenche',
component: WorkbenchePage,
redirect: '/workbenche/home/local',
redirect: '/workbenche/home',
children: [
{
path: 'home',
name: 'WorkbencheHome',
component: WorkbencheHomePage,
children: [
{
path: 'local',
name: 'WorkbencheHomeLocal',
component: WorkbencheHomeLocalPage,
}
]
},
{
path: 'edit/:id',

View File

@ -1,16 +1,29 @@
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/')
}
}
publicPath: isDev ? '' : './dist',
outputDir: '../dist',
lintOnSave: false,
productionSourceMap: false,
configureWebpack: {
resolve: {
alias: {
'@': path.resolve(__dirname, './src/')
}
}
}
},
pluginOptions: {
electronBuilder: {
preload: 'src/electron/preload.js',
builderOptions: {},
// 渲染线程的配置文件
chainWebpackRendererProcess: config => {
config.plugin('define').tap(args => {
args[0]['IS_ELECTRON'] = true
return args
})
}
}
}
}